1161 lines
27 KiB
C
1161 lines
27 KiB
C
//****************************************************************************
|
|
//
|
|
// Module: Unimdm
|
|
// File: devioctl.c
|
|
//
|
|
// Copyright (c) 1992-1995, Microsoft Corporation, all rights reserved
|
|
//
|
|
// Revision History
|
|
//
|
|
//
|
|
// 5/16/95 Viroon Touranachun Moved from mdmutil.c
|
|
//
|
|
//
|
|
// Description: Interface to kernel-mode unimodem
|
|
//
|
|
//****************************************************************************
|
|
|
|
#include "unimdm.h"
|
|
#include "umdmspi.h"
|
|
|
|
|
|
#ifdef WINNT
|
|
#ifndef USE_SERVICECONTROLLER
|
|
// # error "Unimplemented"
|
|
|
|
#define MODEM_SERVICE_NAME \
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\modem"
|
|
|
|
#endif // USE_SERVICECONTROLLER
|
|
|
|
|
|
// Global variable for the modem.sys service
|
|
BOOL bModemSysStarted = FALSE;
|
|
CRITICAL_SECTION ServiceControlerCriticalSection;
|
|
#endif // WINNT
|
|
|
|
|
|
LONG WINAPI
|
|
MCXSetModemSettings(
|
|
HANDLE hModem,
|
|
PMODEMSETTINGS lpMS
|
|
);
|
|
|
|
|
|
//****************************************************************************
|
|
// DWORD MapMcxResult (DWORD)
|
|
//
|
|
// Function: Maps internal error to a standard error code.
|
|
//
|
|
// Returns: standard error code
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD MapMcxResult (DWORD dwResult)
|
|
{
|
|
switch (dwResult)
|
|
{
|
|
case MDM_SUCCESS:
|
|
return ERROR_SUCCESS;
|
|
|
|
case MDM_PENDING:
|
|
return ERROR_IO_PENDING;
|
|
|
|
default:
|
|
return ERROR_IO_DEVICE;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef USE_SERVICECONTROLLER
|
|
|
|
LONG WINAPI
|
|
StartModemDriver(
|
|
VOID
|
|
)
|
|
|
|
{
|
|
|
|
LONG lResult=ERROR_SUCCESS; // Assume success
|
|
BOOL bResult;
|
|
|
|
SC_HANDLE schModemSys;
|
|
SC_HANDLE schSCManager;
|
|
SERVICE_STATUS ServiceStatus;
|
|
|
|
EnterCriticalSection(
|
|
&ServiceControlerCriticalSection
|
|
);
|
|
|
|
|
|
if (!bModemSysStarted) {
|
|
|
|
schSCManager=OpenSCManager(
|
|
NULL,
|
|
NULL,
|
|
SC_MANAGER_ALL_ACCESS
|
|
);
|
|
|
|
if (schSCManager != NULL) {
|
|
//
|
|
// now on service
|
|
//
|
|
schModemSys=OpenService(
|
|
schSCManager,
|
|
TEXT("modem"),
|
|
SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS
|
|
);
|
|
|
|
if (schModemSys == NULL) {
|
|
|
|
DPRINTF("OpenService() for modem.sys failed!");
|
|
CloseServiceHandle(schSCManager);
|
|
|
|
lResult=ERROR_IO_DEVICE;
|
|
|
|
goto Leave;
|
|
|
|
|
|
}
|
|
|
|
bResult=QueryServiceStatus(
|
|
schModemSys,
|
|
&ServiceStatus
|
|
);
|
|
|
|
if (bResult) {
|
|
|
|
if (ServiceStatus.dwCurrentState != SERVICE_RUNNING) {
|
|
|
|
bResult=StartService(
|
|
schModemSys,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if (bResult) {
|
|
|
|
DPRINTF("StartService() for modem.sys succeeded!");
|
|
|
|
bModemSysStarted=TRUE;
|
|
|
|
} else {
|
|
|
|
DPRINTF("StartService() for modem.sys FAILED!");
|
|
|
|
lResult = GetLastError();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bModemSysStarted=TRUE;
|
|
}
|
|
|
|
} else {
|
|
|
|
lResult = GetLastError();
|
|
|
|
DPRINTF1("QueryServiceStatus() for modem.sys failed (%d)!", lResult);
|
|
|
|
}
|
|
|
|
CloseServiceHandle(schModemSys);
|
|
|
|
CloseServiceHandle(schSCManager);
|
|
|
|
} else {
|
|
|
|
DPRINTF("OpenSCManager() failed!");
|
|
|
|
lResult=ERROR_IO_DEVICE;
|
|
|
|
} // if opened SC macanger
|
|
|
|
} else {
|
|
//
|
|
// already running
|
|
//
|
|
}
|
|
|
|
Leave:
|
|
|
|
LeaveCriticalSection(
|
|
&ServiceControlerCriticalSection
|
|
);
|
|
|
|
|
|
return lResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
LONG WINAPI
|
|
StopModemDriver(
|
|
VOID
|
|
)
|
|
|
|
{
|
|
|
|
LONG lResult;
|
|
BOOL bResult;
|
|
|
|
SC_HANDLE schModemSys;
|
|
SC_HANDLE schSCManager;
|
|
SERVICE_STATUS ServiceStatus;
|
|
|
|
EnterCriticalSection(
|
|
&ServiceControlerCriticalSection
|
|
);
|
|
|
|
|
|
if (bModemSysStarted) {
|
|
|
|
schSCManager=OpenSCManager(
|
|
NULL,
|
|
NULL,
|
|
SC_MANAGER_ALL_ACCESS
|
|
);
|
|
|
|
if (schSCManager != NULL) {
|
|
//
|
|
// now on service
|
|
//
|
|
schModemSys=OpenService(
|
|
schSCManager,
|
|
TEXT("modem"),
|
|
SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS
|
|
);
|
|
|
|
if (schModemSys != NULL) {
|
|
|
|
bResult=ControlService(
|
|
schModemSys,
|
|
SERVICE_CONTROL_STOP,
|
|
&ServiceStatus
|
|
);
|
|
|
|
if (bResult) {
|
|
|
|
bModemSysStarted=TRUE;
|
|
}
|
|
|
|
CloseServiceHandle(schModemSys);
|
|
|
|
}
|
|
|
|
CloseServiceHandle(schSCManager);
|
|
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(
|
|
&ServiceControlerCriticalSection
|
|
);
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
#else // !USE_SERVICECONTROLLER
|
|
|
|
|
|
BOOL WINAPI
|
|
ObtainLoadDriverPrivilege(
|
|
IN PBOOLEAN WasEnabled
|
|
) {
|
|
|
|
NTSTATUS Status;
|
|
|
|
DPRINTF("ObtainLoadDriverPrivilege");
|
|
|
|
|
|
//
|
|
// Obtain the process's access token for the current thread
|
|
//
|
|
|
|
Status = RtlImpersonateSelf(SecurityImpersonation);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DPRINTF1("RtlImpersonateSelf returned 0x%08x", Status);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// request "Load-Driver" privileges for this thread
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(
|
|
SE_LOAD_DRIVER_PRIVILEGE,
|
|
TRUE,
|
|
TRUE,
|
|
WasEnabled
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DPRINTF1("RtlAdjustPrivileges returned 0x%08x", Status);
|
|
RevertToSelf();
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID WINAPI
|
|
ReleaseLoadDriverPrivilege(
|
|
IN PBOOLEAN WasEnabled
|
|
) {
|
|
|
|
NTSTATUS Status;
|
|
|
|
DPRINTF("ReleaseLoadDriverPrivilege");
|
|
|
|
|
|
//
|
|
// See if we had to enable SE_LOAD_DRIVER_PRIVILEGE
|
|
//
|
|
|
|
if (!*WasEnabled) {
|
|
|
|
//
|
|
// relinquish "Load-Driver" privileges for this thread
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(
|
|
SE_LOAD_DRIVER_PRIVILEGE,
|
|
FALSE,
|
|
TRUE,
|
|
WasEnabled
|
|
);
|
|
}
|
|
|
|
|
|
//
|
|
// return the thread to its previous access token
|
|
//
|
|
|
|
RevertToSelf();
|
|
}
|
|
|
|
|
|
// # error "Unimplemented"
|
|
|
|
static WCHAR g_rgwchBuffer[] = MODEM_SERVICE_NAME;
|
|
static UNICODE_STRING g_usDriverName = {
|
|
sizeof(g_rgwchBuffer)-sizeof(WCHAR), //Length
|
|
sizeof(g_rgwchBuffer), //MaximumLength
|
|
g_rgwchBuffer //Buffer
|
|
};
|
|
|
|
|
|
LONG WINAPI
|
|
StartModemDriver(
|
|
VOID
|
|
)
|
|
|
|
{
|
|
|
|
LONG lResult=ERROR_SUCCESS;
|
|
|
|
EnterCriticalSection(
|
|
&ServiceControlerCriticalSection
|
|
);
|
|
|
|
while (!bModemSysStarted) { // breakout-construct
|
|
|
|
NTSTATUS nts;
|
|
BOOLEAN WasEnabled;
|
|
|
|
|
|
//
|
|
// Enable our load-driver privilege
|
|
//
|
|
|
|
if (!ObtainLoadDriverPrivilege(&WasEnabled)) {
|
|
lResult = ERROR_ACCESS_DENIED;
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Load modem.sys
|
|
//
|
|
|
|
nts = NtLoadDriver(&g_usDriverName);
|
|
if (NT_SUCCESS(nts) || nts==STATUS_IMAGE_ALREADY_LOADED)
|
|
{
|
|
DPRINTF1("NtLoadDriver returns %s",
|
|
(nts==STATUS_IMAGE_ALREADY_LOADED)
|
|
? TEXT("Already loaded")
|
|
: TEXT("Success"));
|
|
bModemSysStarted=TRUE;
|
|
}
|
|
else
|
|
{
|
|
DPRINTF1("ERROR: NtLoadDriver fails(0x%lx)", (DWORD) nts);
|
|
lResult=ERROR_IO_DEVICE;
|
|
}
|
|
|
|
|
|
//
|
|
// relinquish "Load-Driver" privileges for this thread
|
|
//
|
|
|
|
ReleaseLoadDriverPrivilege(&WasEnabled);
|
|
|
|
break;
|
|
}
|
|
|
|
LeaveCriticalSection(
|
|
&ServiceControlerCriticalSection
|
|
);
|
|
|
|
return lResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
LONG WINAPI
|
|
StopModemDriver(
|
|
VOID
|
|
)
|
|
|
|
{
|
|
|
|
LONG lResult=ERROR_SUCCESS;
|
|
|
|
EnterCriticalSection(
|
|
&ServiceControlerCriticalSection
|
|
);
|
|
|
|
while (bModemSysStarted) { // break-out construct
|
|
|
|
NTSTATUS nts;
|
|
BOOLEAN WasEnabled;
|
|
|
|
|
|
//
|
|
// Enable our load-driver privilege
|
|
//
|
|
|
|
if (!ObtainLoadDriverPrivilege(&WasEnabled)) {
|
|
lResult = ERROR_ACCESS_DENIED;
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Unload modem.sys
|
|
//
|
|
|
|
nts = NtUnloadDriver(&g_usDriverName);
|
|
|
|
if (NT_SUCCESS(nts))
|
|
{
|
|
DPRINTF("NtUnloadDriver succeeded");
|
|
bModemSysStarted=FALSE;
|
|
}
|
|
else
|
|
{
|
|
DPRINTF1("ERROR: NtUnloadDriver fails(0x%lx)", (DWORD) nts);
|
|
lResult=ERROR_IO_DEVICE;
|
|
}
|
|
|
|
|
|
//
|
|
// relinquish "Load-Driver" privileges for this thread
|
|
//
|
|
|
|
ReleaseLoadDriverPrivilege(&WasEnabled);
|
|
|
|
break;
|
|
}
|
|
|
|
LeaveCriticalSection(
|
|
&ServiceControlerCriticalSection
|
|
);
|
|
|
|
return lResult;
|
|
|
|
}
|
|
|
|
#endif // !USE_SERVICECONTROLLER
|
|
|
|
//****************************************************************************
|
|
// DWORD OpenModem (PLINEDEV)
|
|
//
|
|
// Function: Opens the modem device.
|
|
//
|
|
// Notes: This function never returns success synchrnously
|
|
//
|
|
// Returns: ERROR_IO_PENDING if the operation will complete asynchronously
|
|
// an error code for synchrnous failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD OpenModem(PLINEDEV pLineDev, LPBYTE lpComConfig, DWORD dwSize)
|
|
{
|
|
HANDLE hComm;
|
|
DCB dcb;
|
|
TCHAR szPort[MAXDEVICENAME+1];
|
|
DWORD dwRet;
|
|
SERVICE_STATUS ServiceStatus;
|
|
BOOL bResult;
|
|
|
|
|
|
TSPPRINTF("Open modem");
|
|
|
|
dwRet=StartModemDriver();
|
|
|
|
if (dwRet != ERROR_SUCCESS) {
|
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
|
|
// Initialize szPort to be "\\.\"
|
|
lstrcpy(szPort, cszDevicePrefix);
|
|
|
|
// Concatenate FriendlyName onto szPort to form "\\.\Modem Name"
|
|
lstrcat(szPort, pLineDev->szDeviceName);
|
|
|
|
TSPPRINTF1("Device Name = %s", szPort);
|
|
|
|
// Open the modem port
|
|
//
|
|
hComm = CreateFile(szPort,
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
|
|
|
if (hComm == INVALID_HANDLE_VALUE)
|
|
{
|
|
dwRet = GetLastError();
|
|
TSPPRINTF1("hComm CreateFile() failed! (%d)", dwRet);
|
|
return dwRet;
|
|
};
|
|
|
|
if (!PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR) ) {
|
|
|
|
dwRet = GetLastError();
|
|
CloseHandle(hComm);
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
|
|
ASSERT(ghCompletionPort != NULL);
|
|
|
|
if (CreateIoCompletionPort(hComm,
|
|
ghCompletionPort,
|
|
(DWORD)pLineDev,
|
|
0) == NULL)
|
|
{
|
|
dwRet = GetLastError();
|
|
CloseHandle(hComm);
|
|
return dwRet;
|
|
}
|
|
|
|
SetupComm (hComm, 4096, 4096);
|
|
|
|
// Open Mcx handle
|
|
//
|
|
if ((dwRet = MCXOpen(pLineDev->szDeviceName,
|
|
hComm,
|
|
pLineDev->szDriverKey,
|
|
&pLineDev->hModem,
|
|
pLineDev->dwID,
|
|
(DWORD)pLineDev))
|
|
== ERROR_SUCCESS)
|
|
{
|
|
pLineDev->hDevice = hComm;
|
|
|
|
// Set the modem configuration
|
|
//
|
|
UnimodemSetCommConfig(pLineDev, (LPCOMMCONFIG)lpComConfig, dwSize);
|
|
}
|
|
else
|
|
{
|
|
CloseHandle(hComm);
|
|
};
|
|
|
|
return (MapMcxResult(dwRet));
|
|
}
|
|
|
|
//****************************************************************************
|
|
// DWORD CloseModem (PLINEDEV)
|
|
//
|
|
// Function: Opens the modem device.
|
|
//
|
|
// Notes: This function never returns success synchrnously
|
|
//
|
|
// Returns: ERROR_IO_PENDING if the operation will complete asynchronously
|
|
// an error code for synchrnous failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD CloseModem (PLINEDEV pLineDev)
|
|
{
|
|
TSPPRINTF("Close modem");
|
|
|
|
//
|
|
// close comm handle as well
|
|
//
|
|
MCXClose(
|
|
pLineDev->hModem,
|
|
pLineDev->hDevice,
|
|
pLineDev->LineClosed
|
|
);
|
|
|
|
pLineDev->hModem = NULL;
|
|
pLineDev->hDevice = INVALID_DEVICE;
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemInit (PLINEDEV)
|
|
//
|
|
// Function: Initializes the modem device.
|
|
//
|
|
// Notes: This function never returns success synchrnously
|
|
//
|
|
// Returns: ERROR_IO_PENDING if the operation will complete asynchronously
|
|
// an error code for synchrnous failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD UnimodemInit (PLINEDEV pLineDev)
|
|
{
|
|
MCX_IN mcxi;
|
|
DWORD dwRet;
|
|
LPCOMMCONFIG lpCommConfig;
|
|
|
|
lpCommConfig = (LPCOMMCONFIG)&(pLineDev->pDevCfg->commconfig);
|
|
|
|
// set the new configuration
|
|
//
|
|
UnimodemSetCommConfig(pLineDev,
|
|
lpCommConfig, lpCommConfig->dwSize);
|
|
|
|
|
|
|
|
// Prepare the input/output information
|
|
//
|
|
pLineDev->dwVxdPendingID++;
|
|
|
|
mcxi.dwReqID = pLineDev->dwVxdPendingID;
|
|
mcxi.pMcxOut = &pLineDev->McxOut;
|
|
|
|
pLineDev->McxOut.dwReqID = mcxi.dwReqID;
|
|
pLineDev->McxOut.dwResult = MDM_FAILURE;
|
|
|
|
TSPPRINTF1("UnimodemInit id: %d", pLineDev->dwVxdPendingID);
|
|
|
|
pLineDev->InitStringsAreValid=TRUE;
|
|
|
|
dwRet = MCXInit(pLineDev->hModem, &mcxi);
|
|
dwRet = MapMcxResult(dwRet);
|
|
|
|
// If the MCX call returns success, converts it to async success
|
|
//
|
|
if (dwRet == ERROR_SUCCESS)
|
|
{
|
|
// The operation completes successfully synchronously
|
|
//
|
|
dwRet = ERROR_IO_PENDING;
|
|
pLineDev->McxOut.dwResult = MDM_SUCCESS;
|
|
PostQueuedCompletionStatus(ghCompletionPort,
|
|
CP_BYTES_WRITTEN(0),
|
|
(DWORD)pLineDev,
|
|
NULL);
|
|
};
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemDial (PLINEDEV, LPSTR)
|
|
//
|
|
// Function: dials the modem device with the provided dialable string. A dial-
|
|
// able string can be:
|
|
// "" - originate
|
|
// ";" - dialtone detection
|
|
// "5551212" - dial and originate
|
|
// "5551212;" - dial
|
|
//
|
|
// Notes: This function never returns success synchrnously
|
|
//
|
|
// Returns: ERROR_IO_PENDING if the operation will complete asynchronously
|
|
// an error code for synchrnous failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD
|
|
UnimodemDial(
|
|
PLINEDEV pLineDev,
|
|
LPSTR szAddress,
|
|
DWORD DialOptions
|
|
)
|
|
{
|
|
MCX_IN mcxi;
|
|
DWORD dwRet;
|
|
char szPhone[MAXADDRESSLEN+1];
|
|
|
|
// Prepare the input/output information
|
|
//
|
|
pLineDev->dwVxdPendingID++;
|
|
|
|
mcxi.dwReqID = pLineDev->dwVxdPendingID;
|
|
mcxi.pMcxOut = &pLineDev->McxOut;
|
|
|
|
pLineDev->McxOut.dwReqID = mcxi.dwReqID;
|
|
pLineDev->McxOut.dwResult = MDM_FAILURE;
|
|
|
|
lstrcpyA(szPhone, szAddress);
|
|
|
|
TSPPRINTF1("UnmodemDial id: %d", pLineDev->dwVxdPendingID);
|
|
|
|
dwRet = MCXDial(pLineDev->hModem, szPhone, &mcxi, DialOptions);
|
|
dwRet = MapMcxResult(dwRet);
|
|
|
|
// If the MCX call returns success, converts it to async success
|
|
//
|
|
if (dwRet == ERROR_SUCCESS)
|
|
{
|
|
// The operation completes successfully synchronously
|
|
//
|
|
dwRet = ERROR_IO_PENDING;
|
|
pLineDev->McxOut.dwResult = MDM_SUCCESS;
|
|
PostQueuedCompletionStatus(ghCompletionPort,
|
|
CP_BYTES_WRITTEN(0),
|
|
(DWORD)pLineDev,
|
|
NULL);
|
|
};
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemMonitor (PLINEDEV, DWORD)
|
|
//
|
|
// Function: Monitors the modem for an incoming call in two modes:
|
|
// MONITOR_NON_CONTINUOUS - Notify the first ring only
|
|
// MONITOR_CONTINUOUS - Notify each ring
|
|
//
|
|
// Notes: This function never returns success synchrnously
|
|
//
|
|
// Returns: ERROR_IO_PENDING if the operation will complete asynchronously
|
|
// an error code for synchrnous failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD UnimodemMonitor (PLINEDEV pLineDev, DWORD dwType)
|
|
{
|
|
MCX_IN mcxi;
|
|
DWORD dwRet;
|
|
|
|
// Prepare the input/output information
|
|
//
|
|
pLineDev->dwVxdPendingID++;
|
|
|
|
mcxi.dwReqID = pLineDev->dwVxdPendingID;
|
|
mcxi.pMcxOut = &pLineDev->McxOut;
|
|
|
|
pLineDev->McxOut.dwReqID = mcxi.dwReqID;
|
|
pLineDev->McxOut.dwResult = MDM_FAILURE;
|
|
|
|
TSPPRINTF1("UnmodemMonitor id: %d", pLineDev->dwVxdPendingID);
|
|
|
|
dwRet = MCXMonitor(pLineDev->hModem, dwType, &mcxi);
|
|
dwRet = MapMcxResult(dwRet);
|
|
|
|
// If the MCX call returns success, converts it to async success
|
|
//
|
|
if (dwRet == ERROR_SUCCESS)
|
|
{
|
|
// The operation completes successfully synchronously
|
|
//
|
|
dwRet = ERROR_IO_PENDING;
|
|
pLineDev->McxOut.dwResult = MDM_SUCCESS;
|
|
PostQueuedCompletionStatus(ghCompletionPort,
|
|
CP_BYTES_WRITTEN(0),
|
|
(DWORD)pLineDev,
|
|
NULL);
|
|
};
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemAnswer (PLINEDEV)
|
|
//
|
|
// Function: Answers the incoming call..
|
|
//
|
|
// Notes: This function never returns success synchrnously
|
|
//
|
|
// Returns: ERROR_IO_PENDING if the operation will complete asynchronously
|
|
// an error code for synchrnous failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD UnimodemAnswer (PLINEDEV pLineDev)
|
|
{
|
|
MCX_IN mcxi;
|
|
DWORD dwRet;
|
|
|
|
// Prepare the input/output information
|
|
//
|
|
pLineDev->dwVxdPendingID++;
|
|
|
|
mcxi.dwReqID = pLineDev->dwVxdPendingID;
|
|
mcxi.pMcxOut = &pLineDev->McxOut;
|
|
|
|
pLineDev->McxOut.dwReqID = mcxi.dwReqID;
|
|
pLineDev->McxOut.dwResult = MDM_FAILURE;
|
|
|
|
TSPPRINTF1("UnmodemAnswer id: %d", pLineDev->dwVxdPendingID);
|
|
|
|
dwRet = MCXAnswer(pLineDev->hModem, &mcxi);
|
|
dwRet = MapMcxResult(dwRet);
|
|
|
|
// If the MCX call returns success, converts it to async success
|
|
//
|
|
if (dwRet == ERROR_SUCCESS)
|
|
{
|
|
// The operation completes successfully synchronously
|
|
//
|
|
dwRet = ERROR_IO_PENDING;
|
|
pLineDev->McxOut.dwResult = MDM_SUCCESS;
|
|
PostQueuedCompletionStatus(ghCompletionPort,
|
|
CP_BYTES_WRITTEN(0),
|
|
(DWORD)pLineDev,
|
|
NULL);
|
|
};
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
VOID WINAPI
|
|
DisconnectHandler(
|
|
PLINEDEV pLineDev
|
|
)
|
|
|
|
{
|
|
TSPPRINTF("DisconnectHandle:");
|
|
|
|
NEW_CALLSTATE(pLineDev, LINECALLSTATE_DISCONNECTED, LINEDISCONNECTMODE_NORMAL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemMonitorDisconnect (PLINEDEV)
|
|
//
|
|
// Function: Monitors the remote disconnection. When the remote disconnection
|
|
// occurs, the function completes successfully in the async thread.
|
|
//
|
|
// Notes: This function never returns success synchrnously
|
|
//
|
|
// Returns: ERROR_IO_PENDING if the operation will complete asynchronously
|
|
// an error code for synchrnous failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD UnimodemMonitorDisconnect (PLINEDEV pLineDev)
|
|
{
|
|
|
|
DWORD Result;
|
|
|
|
Result=McxRegisterDisconectHandler(
|
|
pLineDev->hModem,
|
|
DisconnectHandler,
|
|
pLineDev
|
|
);
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemCancelMonitorDisconnect (PLINEDEV)
|
|
//
|
|
// Function: Cancel the pending monitoring remote disconnection request.
|
|
// The async thread always ignore the cancellation result.
|
|
//
|
|
// Notes: This function is synchronous.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// an error code for failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD UnimodemCancelMonitorDisconnect (PLINEDEV pLineDev)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
dwRet=McxDeregisterDisconnectHandler(
|
|
pLineDev->hModem
|
|
);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemHangup (PLINEDEV, BOOL)
|
|
//
|
|
// Function: Disconnect the modem locally. The caller can specifies whether
|
|
// the function should complete synchrnously or asynchronously.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success synchronously.
|
|
// ERROR_IO_PENDING if the operation will complete asynchronously
|
|
// an error code for failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD UnimodemHangup (PLINEDEV pLineDev, BOOL fSync)
|
|
{
|
|
MCX_IN mcxi;
|
|
DWORD dwRet;
|
|
|
|
if(!fSync)
|
|
{
|
|
// Asynchronous request, use the default event
|
|
//
|
|
pLineDev->dwVxdPendingID++;
|
|
|
|
TSPPRINTF1("UnmodemAsyncHangup id: %d", pLineDev->dwVxdPendingID);
|
|
}
|
|
else
|
|
{
|
|
// Synchronous request, create a local event so we can wait for it here
|
|
//
|
|
if ((pLineDev->hSynchronizeEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
|
|
{
|
|
return ERROR_OUTOFMEMORY;
|
|
};
|
|
|
|
TSPPRINTF("UnmodemSyncHangup");
|
|
};
|
|
|
|
// Prepare the input/output information
|
|
//
|
|
mcxi.dwReqID = pLineDev->dwVxdPendingID;
|
|
mcxi.pMcxOut = &pLineDev->McxOut;
|
|
|
|
pLineDev->McxOut.dwReqID = mcxi.dwReqID;
|
|
pLineDev->McxOut.dwResult = MDM_FAILURE;
|
|
|
|
// Hang up the line
|
|
//
|
|
dwRet = MCXHangup(pLineDev->hModem, &mcxi);
|
|
dwRet = MapMcxResult(dwRet);
|
|
|
|
switch(dwRet)
|
|
{
|
|
case ERROR_SUCCESS:
|
|
//
|
|
// The operation completes successfully synchronously
|
|
//
|
|
pLineDev->McxOut.dwResult = MDM_SUCCESS;
|
|
|
|
// If the operation is an async request, handles the result asynchronously
|
|
//
|
|
if (fSync)
|
|
{
|
|
TSPPRINTF("UnmodemSyncHangup completes");
|
|
CloseHandle(pLineDev->hSynchronizeEvent);
|
|
pLineDev->hSynchronizeEvent = NULL;
|
|
}
|
|
else
|
|
{
|
|
dwRet = ERROR_IO_PENDING;
|
|
PostQueuedCompletionStatus(ghCompletionPort,
|
|
CP_BYTES_WRITTEN(0),
|
|
(DWORD)pLineDev,
|
|
NULL);
|
|
};
|
|
break;
|
|
|
|
case ERROR_IO_PENDING:
|
|
//
|
|
// If it is synchronous request, need to wait until it is done
|
|
//
|
|
if (fSync)
|
|
{
|
|
RELEASE_LINEDEV(pLineDev);
|
|
WaitForSingleObject(pLineDev->hSynchronizeEvent, INFINITE);
|
|
CLAIM_LINEDEV(pLineDev);
|
|
CloseHandle(pLineDev->hSynchronizeEvent);
|
|
pLineDev->hSynchronizeEvent = NULL;
|
|
dwRet = ERROR_SUCCESS;
|
|
};
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
};
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemGetCommConfig (PLINEDEV, LPCOMMCONFIG, LPDWORD)
|
|
//
|
|
// Function: Gets the modem comm configuration
|
|
//
|
|
// Notes: This function is synchronous.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// an error code for failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD UnimodemGetCommConfig (PLINEDEV pLineDev, LPCOMMCONFIG lpCommConfig,
|
|
LPDWORD lpcb)
|
|
{
|
|
DWORD dwRet;
|
|
TSPPRINTF("UnimodemGetCommConfig.");
|
|
|
|
dwRet = MCXGetCommConfig(pLineDev->hModem, lpCommConfig, lpcb);
|
|
return (MapMcxResult(dwRet));
|
|
}
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemSetCommConfig (PLINEDEV, LPCOMMCONFIG, DWORD)
|
|
//
|
|
// Function: Sets the modem comm configuration
|
|
//
|
|
// Notes: This function is synchronous.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// an error code for failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD UnimodemSetCommConfig (PLINEDEV pLineDev, LPCOMMCONFIG lpCommConfig,
|
|
DWORD cb)
|
|
{
|
|
DWORD dwRet;
|
|
TSPPRINTF("UnimodemSetCommConfig.");
|
|
|
|
dwRet = MCXSetCommConfig(pLineDev->hModem, lpCommConfig, cb);
|
|
return (MapMcxResult(dwRet));
|
|
}
|
|
|
|
|
|
#if 0
|
|
//****************************************************************************
|
|
// DWORD UnimodemSetCommConfig (PLINEDEV, LPCOMMCONFIG, DWORD)
|
|
//
|
|
// Function: Sets the modem comm configuration
|
|
//
|
|
// Notes: This function is synchronous.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// an error code for failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD WINAPI
|
|
UnimodemSetModemSettings(
|
|
PLINEDEV pLineDev,
|
|
LPMODEMSETTINGS lpModemSettings
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
TSPPRINTF("UnimodemSetModemSettings.");
|
|
|
|
dwRet = MCXSetModemSettings(pLineDev->hModem, lpModemSettings);
|
|
|
|
return (MapMcxResult(dwRet));
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemSetPassthrough (PLINEDEV, DWORD)
|
|
//
|
|
// Function: Sets the modem passthrough mode to:
|
|
// PASSTHROUGH_ON
|
|
// PASSTHROUGH_OFF
|
|
// PASSTHROUGH_OFF_BUT_CONNECTED
|
|
//
|
|
// Notes: This function is synchronous.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// an error code for failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD UnimodemSetPassthrough (PLINEDEV pLineDev, DWORD dwMode)
|
|
{
|
|
DWORD dwRet;
|
|
TSPPRINTF1("UnimodemSetPassthrough mode: %d", dwMode);
|
|
|
|
dwRet = MCXSetPassthrough(pLineDev->hModem, dwMode);
|
|
return (MapMcxResult(dwRet));
|
|
}
|
|
|
|
//****************************************************************************
|
|
// DWORD UnimodemGetNegotiatedRate (PLINEDEV, LPDWORD)
|
|
//
|
|
// Function: Gets the modem connection speed
|
|
//
|
|
// Notes: This function is synchronous.
|
|
//
|
|
// Returns: ERROR_SUCCESS if success
|
|
// an error code for failure
|
|
//
|
|
// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont]
|
|
// created
|
|
//****************************************************************************
|
|
|
|
DWORD UnimodemGetNegotiatedRate (PLINEDEV pLineDev, LPDWORD lpdwRate)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
dwRet = MCXGetNegotiatedRate(pLineDev->hModem, lpdwRate);
|
|
return (MapMcxResult(dwRet));
|
|
}
|