?? modem.c
字號:
// ****************************************************************************
//
// Module: Unimdm
// File: modem.c
//
// Copyright (c) 1992-2000 Microsoft Corporation. All rights reserved.
//
// Revision History
//
// Description: Intermediate modem SPI layer
//
// ****************************************************************************
#include "windows.h"
#include "types.h"
#include "memory.h"
#include "tspi.h"
#include "linklist.h"
#include "tspip.h"
#include "tapicomn.h"
#include "mcx.h"
#include "dial.h"
static const WCHAR szAnswer[] = TEXT("Answer"); // Registry value name under Settings
static const CHAR szDefaultAnswerCmd[] = "ATA\r\n";
static const WCHAR szMonitor[] = TEXT("Monitor"); // Registry value name under Settings
static const CHAR szDefaultMonitorCmd[] = "ATS0=0\r\n";
static const WCHAR szMdmLogBase[] = TEXT("mdmlog");
static const WCHAR szMdmLogExt[] = TEXT(".txt");
extern const WCHAR szSettings[];
extern DWORD SetWatchdog(PTLINEDEV pLineDev,DWORD dwTimeout);
// Unimodem thread priority
extern DWORD g_dwUnimodemThreadPriority;
extern HANDLE g_hCoreDLL;
#ifdef DEBUG
LPWSTR
GetPendingName(
DWORD dwPendingType
)
{
LPWSTR lpszType;
switch (dwPendingType) {
case PENDING_LINEACCEPT: lpszType = TEXT("LINEACCEPT"); break;
case PENDING_LINEANSWER: lpszType = TEXT("LINEANSWER"); break;
case PENDING_LINEDEVSPECIFIC: lpszType = TEXT("LINEDEVSPECIFIC"); break;
case PENDING_LINEDIAL: lpszType = TEXT("LINEDIAL"); break;
case PENDING_LINEDROP: lpszType = TEXT("LINEDROP"); break;
case PENDING_LINEMAKECALL: lpszType = TEXT("LINEMAKECALL"); break;
case PENDING_LISTEN: lpszType = TEXT("LISTEN"); break;
case PENDING_EXIT: lpszType = TEXT("EXIT"); break;
case INVALID_PENDINGOP: lpszType = TEXT("INVALIDOP"); break;
default: lpszType = TEXT("UNKNOWN!!!"); break;
}
return lpszType;
}
#endif
//
// Function to open the modem command log file for the specified line device
//
void
OpenModemLog(
PTLINEDEV pLineDev
)
{
WCHAR FileName[16];
LPWSTR lpwsz;
HANDLE hFile;
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+OpenModemLog\n")));
if (pLineDev->hMdmLog != (HANDLE)INVALID_DEVICE) {
CloseHandle(pLineDev->hMdmLog);
}
//
// Format modem log file name "mdmlog<dwDeviceID>.txt"
//
wcscpy(FileName, szMdmLogBase);
lpwsz = FileName + wcslen(FileName);
wsprintf(lpwsz, TEXT("%d"), pLineDev->dwDeviceID);
wcscat(FileName, szMdmLogExt);
hFile = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
DEBUGMSG(ZONE_CALLS|ZONE_FUNC|ZONE_ERROR,
(TEXT("UNIMODEM:OpenModemLog CreateFile(%s) failed %d\n"), FileName, GetLastError()));
pLineDev->hMdmLog = (HANDLE)INVALID_DEVICE;
} else {
DEBUGMSG(ZONE_CALLS|ZONE_FUNC, (TEXT("UNIMODEM:OpenModemLog CreateFile(%s) succeeded\n"), FileName));
pLineDev->hMdmLog = hFile;
}
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-OpenModemLog\n")));
} // OpenModemLog
//
// Function to write modem commands to the line device's command history file.
//
void
WriteModemLog(
PTLINEDEV pLineDev,
UCHAR * szCommand,
DWORD dwOp
)
{
CHAR Buf[MAXSTRINGLENGTH];
LPSTR lpsz;
DWORD dwLen;
DWORD dwIO;
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+WriteModemLog %a\n"), szCommand));
switch (dwOp) {
case MDMLOG_COMMAND_OK:
lpsz = "Modem Command: ";
break;
case MDMLOG_COMMAND_FAIL:
lpsz = "Failed Command: ";
break;
case MDMLOG_RESPONSE:
lpsz = "Modem Response: ";
break;
default:
lpsz = " ";
break;
}
Buf[MAXSTRINGLENGTH-2] = 0;
strcpy(Buf, lpsz);
dwLen = strlen(Buf);
strncat(Buf, szCommand, MAXSTRINGLENGTH - dwLen - 2);
dwLen += strlen(szCommand);
if (dwLen > (MAXSTRINGLENGTH - 2)) {
dwLen = MAXSTRINGLENGTH - 2;
}
Buf[dwLen] = '\n';
dwLen++;
Buf[dwLen] = '\0';
DEBUGMSG(ZONE_CALLS|ZONE_FUNC, (TEXT("UNIMODEM:WriteModemLog(%a) %d bytes\n"), Buf, dwLen));
if (!WriteFile(pLineDev->hMdmLog, (PUCHAR)Buf, dwLen, &dwIO, NULL)) {
DEBUGMSG(ZONE_CALLS|ZONE_FUNC, (TEXT("UNIMODEM:WriteModemLog WriteFile() failed %d\n"), GetLastError()));
}
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-WriteModemLog\n")));
} // WriteModemLog
void
SetDCBfromDevMiniCfg(
DCB * pDCB,
PDEVMINICFG lpDevMiniCfg
)
{
pDCB->BaudRate = lpDevMiniCfg->dwBaudRate;
pDCB->ByteSize = lpDevMiniCfg->ByteSize;
pDCB->StopBits = lpDevMiniCfg->StopBits;
pDCB->fParity = (NOPARITY == lpDevMiniCfg->Parity) ? FALSE : TRUE;
pDCB->Parity = lpDevMiniCfg->Parity;
pDCB->fDsrSensitivity = FALSE;
pDCB->fDtrControl = DTR_CONTROL_ENABLE;
if( MDM_FLOWCONTROL_HARD & lpDevMiniCfg->dwModemOptions ) {
// Enable RTS/CTS Flow Control
pDCB->fRtsControl = RTS_CONTROL_HANDSHAKE;
pDCB->fOutxCtsFlow = 1;
pDCB->fOutX = 0;
pDCB->fInX = 0;
} else if( MDM_FLOWCONTROL_SOFT & lpDevMiniCfg->dwModemOptions ) {
// Enable XON/XOFF Flow Control
pDCB->fRtsControl = RTS_CONTROL_ENABLE;
pDCB->fOutxCtsFlow = 0;
pDCB->fOutX = 1;
pDCB->fInX = 1;
} else {
pDCB->fRtsControl = RTS_CONTROL_ENABLE;
pDCB->fOutxCtsFlow = 0;
pDCB->fOutX = 0;
pDCB->fInX = 0;
}
} // SetDCBfromDevMiniCfg
void
SetDialerTimeouts(
HANDLE hComDev
)
{
COMMTIMEOUTS commTimeouts;
GetCommTimeouts (hComDev, &commTimeouts);
commTimeouts.ReadIntervalTimeout = 50;
commTimeouts.ReadTotalTimeoutMultiplier = 0;
commTimeouts.ReadTotalTimeoutConstant = 50;
commTimeouts.WriteTotalTimeoutMultiplier = 5;
commTimeouts.WriteTotalTimeoutConstant = 500;
SetCommTimeouts (hComDev, &commTimeouts);
} // SetDialerTimeouts
DWORD
OpenModem (
LPCWSTR lpszPortName,
LPDWORD lpR3handle,
LPDWORD lpR0handle,
PDEVMINICFG lpDevMiniCfg )
{
HANDLE hComDev;
HANDLE hComDev0;
WCHAR szDeviceName[16];
DEBUGMSG(ZONE_FUNC|ZONE_CALLS, (TEXT("UNIMODEM:+OpenModem('%s')\r\n"), lpszPortName));
// Compose the device name from the portname
wcscpy(szDeviceName, lpszPortName);
// Open the device
//
if ((hComDev = CreateFile(szDeviceName, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, 0, 0))
== INVALID_HANDLE_VALUE) {
goto om_fail;
}
if ((hComDev0 = CreateFile(szDeviceName, 0, 0,
NULL, OPEN_EXISTING, 0, 0))
!= INVALID_HANDLE_VALUE) {
DCB commDCB;
DEBUGMSG(ZONE_MISC|ZONE_CALLS,
(TEXT("UNIMODEM:OpenModem - createfile OK, handle x%X\n"),
hComDev));
// ********************************************************
// Set the device configuration based on DEVMINICFG
//
GetCommState( hComDev, &commDCB );
SetDCBfromDevMiniCfg(&commDCB, lpDevMiniCfg);
DEBUGMSG(ZONE_FUNCTION|ZONE_CALLS,
(TEXT("UNIMODEM:OpenModem Setting port configuration :\n")));
DEBUGMSG(ZONE_FUNCTION|ZONE_CALLS,
(TEXT("UNIMODEM:OpenModem Baud %d, Byte Size %d, Stop bits %d, Parity %d\n"),
commDCB.BaudRate, commDCB.ByteSize, commDCB.StopBits, commDCB.Parity));
DEBUGMSG(ZONE_FUNCTION|ZONE_CALLS,
(TEXT("UNIMODEM:OpenModem RTS Control %d, CTS Out Flow %d, XON/XOFF out/in %d/%d\n"),
commDCB.fRtsControl, commDCB.fOutxCtsFlow, commDCB.fOutX, commDCB.fInX));
SetCommState( hComDev, &commDCB );
// Adjust the read/write timeouts as required by dialer thread
SetDialerTimeouts(hComDev);
*lpR3handle = (DWORD)hComDev;
*lpR0handle = (DWORD)hComDev0;
DEBUGMSG(ZONE_FUNCTION, (TEXT("UNIMODEM:-OpenModem\n")));
return ERROR_SUCCESS;
} else {
CloseHandle(hComDev);
}
om_fail:
DEBUGMSG(ZONE_FUNCTION,
(TEXT("UNIMODEM:-OpenModem : Unable to open %s, hComdev x%X\n"),
szDeviceName, hComDev));
return ERROR_OPEN_FAILED;
}
// ****************************************************************************
// lineOpen()
//
// Function: Emulate the TAPI lineOpen call.
//
// ****************************************************************************
LONG
DevlineOpen (
PTLINEDEV pLineDev
)
{
DWORD idMdm;
DWORD idMdm0;
DWORD dwRet;
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+DevlineOpen\r\n")));
EnterCriticalSection(&pLineDev->OpenCS);
// The line must be closed
if (pLineDev->hDevice != (HANDLE)INVALID_DEVICE) {
DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:DevlineOpen - device already open\r\n")));
dwRet = LINEERR_ALLOCATED;
goto exit_Point;
}
if (0 == pLineDev->wDeviceAvail) {
DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:DevlineOpen - device has been removed\r\n")));
dwRet = LINEERR_NODEVICE;
goto exit_Point;
}
// Open the modem port
DEBUGMSG(ZONE_MISC, (TEXT("UNIMODEM:DevlineOpen - calling openmodem\r\n")));
dwRet = OpenModem(pLineDev->szDeviceName,
&idMdm, &idMdm0,
&pLineDev->DevMiniCfg);
if (dwRet == SUCCESS) {
// we successfully opened the modem
// Convert modem handle to ring 0 handle
pLineDev->hDevice = (HANDLE)idMdm;
pLineDev->hDevice_r0 = (HANDLE)idMdm0;
pLineDev->DevState = DEVST_DISCONNECTED;
OpenModemLog(pLineDev);
} else {
dwRet = LINEERR_RESOURCEUNAVAIL;
};
exit_Point:
LeaveCriticalSection(&pLineDev->OpenCS);
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-DevlineOpen x%X\r\n"), dwRet));
return dwRet;
}
//****************************************************************************
// lineClose()
//
// Function: Emulate the TAPI lineClose call.
//
// NOTE : The fDoDrop flag is used to indicate that we should
// make sure the line gets dropped before we close it.
//
//****************************************************************************
LONG
DevlineClose (
PTLINEDEV pLineDev,
BOOL fDoDrop
)
{
DWORD dwPrevCallState;
HTAPICALL hPrevCall;
DWORD dwPrevProcPerms;
DEBUGMSG(ZONE_FUNC|ZONE_CALLS,
(TEXT("UNIMODEM:+DevlineClose, handle x%X, callstate x%X\r\n"),
pLineDev->hDevice, pLineDev->dwCallState));
// Grab a critical section to ensure the app doesn't call in and
// cause a line close while we are in the middle of doing a close
// ourselves.
EnterCriticalSection(&pLineDev->OpenCS);
dwPrevCallState = pLineDev->dwCallState;
hPrevCall = pLineDev->htCall;
if( (HANDLE)INVALID_DEVICE != pLineDev->hDevice )
{
try
{
//
// We (device.exe PSL) were the current process when the device
// was opened, so we need to be the owner for DevlineDrop and
// the CloseHandle() to work as expected.
//
dwPrevProcPerms = SetProcPermissions(-1);
SetHandleOwner((HANDLE) pLineDev->hDevice, GetCurrentProcess());
SetProcPermissions(dwPrevProcPerms);
// If a call is in progress, terminate it
if (fDoDrop && LINECALLSTATE_CONNECTED == pLineDev->dwCallState) {
DEBUGMSG(ZONE_CALLS, (L"UNIMODEM:DevlineClose - Callstate x%X, dropping call\r\n",
pLineDev->dwCallState));
DevlineDrop(pLineDev);
}
CloseHandle( pLineDev->hDevice );
CloseHandle( pLineDev->hDevice_r0);
CloseHandle( pLineDev->hMdmLog);
NullifyLineDevice(pLineDev, FALSE); // Reinit the line device
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Oops, we must have hit a bad handle. Fall thru & release the CS.
}
}
pLineDev->dwPendingID = INVALID_PENDINGID;
LeaveCriticalSection(&pLineDev->OpenCS);
if (dwPrevCallState != LINECALLSTATE_IDLE) {
pLineDev->htCall = hPrevCall;
NewCallState(pLineDev, LINECALLSTATE_IDLE, 0L);
pLineDev->htCall = NULL;
}
DEBUGMSG(ZONE_FUNC|ZONE_CALLS, (TEXT("UNIMODEM:-DevlineClose\r\n")));
return SUCCESS;
}
//
// Function to signal any threads stuck in WaitCommEvent
//
LONG
ToggleCommMask(
PTLINEDEV pLineDev
)
{
LONG rc = 0;
if ((HANDLE)INVALID_DEVICE != pLineDev->hDevice) {
try {
if (!SetCommMask( pLineDev->hDevice, 0)) {
DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:ToggleCommMask SetCommMask(0) failed %d\n"), GetLastError()));
rc = LINEERR_OPERATIONFAILED;
}
if (!SetCommMask( pLineDev->hDevice_r0, 0)) {
DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:ToggleCommMask SetCommMask(r0,0) failed %d\n"), GetLastError()));
rc = LINEERR_OPERATIONFAILED;
}
if (!SetCommMask( pLineDev->hDevice, EV_DEFAULT)) {
DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:ToggleCommMask SetCommMask() failed %d\n"), GetLastError()));
rc = LINEERR_OPERATIONFAILED;
}
if (!SetCommMask( pLineDev->hDevice_r0, EV_RLSD)) {
DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:ToggleCommMask SetCommMask(r0) failed %d\n"), GetLastError()));
rc = LINEERR_OPERATIONFAILED;
}
} except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Exception means bad handle, so we can't do anything to cancel call
rc = LINEERR_OPERATIONFAILED;
}
}
return rc;
} // ToggleCommMask
typedef LRESULT (WINAPI * PFN_SENDMESSAGE)(HWND,UINT,WPARAM,LPARAM);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -