📄 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 Settingsstatic const CHAR szDefaultAnswerCmd[] = "ATA\r\n";static const WCHAR szMonitor[] = TEXT("Monitor"); // Registry value name under Settingsstatic 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 priorityextern DWORD g_dwUnimodemThreadPriority;extern HANDLE g_hCoreDLL;#ifdef DEBUGLPWSTRGetPendingName( 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//voidOpenModemLog( 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.// voidWriteModemLog( 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")));} // WriteModemLogvoidSetDCBfromDevMiniCfg( 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; }} // SetDCBfromDevMiniCfgvoidSetDialerTimeouts( 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);} // SetDialerTimeoutsDWORDOpenModem ( 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.//// ****************************************************************************LONGDevlineOpen ( 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.////****************************************************************************LONGDevlineClose ( 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//LONGToggleCommMask( 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;} // ToggleCommMasktypedef LRESULT (WINAPI * PFN_SENDMESSAGE)(HWND,UINT,WPARAM,LPARAM);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -