misc.c
来自「wince下的源代码集合打包」· C语言 代码 · 共 1,256 行 · 第 1/3 页
C
1,256 行
/**************************************************************************//** Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved. **//**************************************************************************///// misc.c Support files for Telephony Service Provider Interface//// @doc EX_TSPI//// @topic TSPI |//// Tspi utilities////#include "windows.h"#include "types.h"#include "memory.h"#include "mcx.h"#include "tspi.h"#include "tspip.h"#include "linklist.h"extern const WCHAR szSettings[];extern const WCHAR szDialSuffix[];const WCHAR szDefaultsName[] = TEXT("Drivers\\Unimodem");// Unimodem thread priority#define DEFAULT_THREAD_PRIORITY 150#define REGISTRY_PRIORITY_VALUE TEXT("Priority256")DWORD g_dwUnimodemThreadPriority;const DEVMINICFG DefaultDevCfg ={ DEVMINCFG_VERSION, // Version 0x00, // WaitBong 90, // CallSetupFail 0, // ModemOptions 19200, // Baud Rate 0, // Options 8, // Byte Size 0, // Stop Bits 0 // Parity};extern HANDLE g_hCoreDLL;//// Function to complete an outstanding async operation// (unimodem can only handle one outstanding async operation per linedev)//// NOTE: Must be called holding the OpenCS//voidCompleteAsyncOp( PTLINEDEV pLineDev ){ DWORD dwID; DWORD dwStatus; DEBUGMSG(ZONE_FUNC|ZONE_ASYNC, (TEXT("UNIMODEM:+CompleteAsyncOp\n"))); dwID = pLineDev->dwPendingID; dwStatus = pLineDev->dwPendingStatus; switch (pLineDev->dwPendingType) { case PENDING_LINEACCEPT: case PENDING_LINEANSWER: case PENDING_LINEDEVSPECIFIC: case PENDING_LINEDIAL: case PENDING_LINEDROP: case PENDING_LINEMAKECALL: LeaveCriticalSection(&pLineDev->OpenCS); DEBUGMSG(ZONE_ASYNC, (TEXT("UNIMODEM:CompleteAsyncOp completing Op %s(0x%x)\n"), GetPendingName(pLineDev->dwPendingType), dwID)); TspiGlobals.fnCompletionCallback(dwID, dwStatus); EnterCriticalSection(&pLineDev->OpenCS); break; } pLineDev->dwPendingID = INVALID_PENDINGID; pLineDev->dwPendingType = INVALID_PENDINGOP; pLineDev->dwPendingStatus = 0; DEBUGMSG(ZONE_FUNC|ZONE_ASYNC, (TEXT("UNIMODEM:-CompleteAsyncOp\n")));} // CompleteAsyncOp//// NOTE on async operations:// The function that invokes an async operation (TSPI_lineMakeCall, TSPI_lineAnswer, etc)// first calls ControlThreadCmd which calls SetAsyncOp. Just before returning it calls// SetAsyncID in order to avoid calling the TAPI completion callback before the user// knows the async ID. The UnimodemControlThread will call SetAsyncStatus when the// async operation has completed. If the ID has been set, then SetAsyncStatus will perform// the callback.////// Set the async ID for a pending operation. This signals that the function which// invoked the async operation has completed so any subsequent SetAsyncStatus call// will cause a completion callback to TAPI. If the invoked async operation has// already completed (SetAsyncStatus already called), then we need to kick off a// thread to make the callback for this completed async operation.//// Return LINEERR_OPERATIONFAILED if this async operation has been aborted, else// return async ID.//DWORDSetAsyncID( PTLINEDEV pLineDev, DWORD dwID ){ DWORD dwRet = LINEERR_OPERATIONFAILED; DEBUGMSG(ZONE_FUNC|ZONE_ASYNC, (TEXT("UNIMODEM:+SetAsyncID\n"))); EnterCriticalSection(&pLineDev->OpenCS); if (pLineDev->dwPendingID != INVALID_PENDINGID) { LeaveCriticalSection(&pLineDev->OpenCS); } else { pLineDev->dwPendingID = dwID; dwRet = dwID; // // If the operation has completed then we need to do the callback on another thread // if (pLineDev->dwPendingStatus != LINEERR_ALLOCATED) { LeaveCriticalSection(&pLineDev->OpenCS); if (!StartCompleteAsyncOp(pLineDev)) { dwRet = LINEERR_OPERATIONFAILED; } } else { LeaveCriticalSection(&pLineDev->OpenCS); } } DEBUGMSG(ZONE_FUNC|ZONE_ASYNC, (TEXT("UNIMODEM:-SetAsyncID 0x%x\n"), dwRet)); return dwRet;} // SetAsyncID//// Set the status for a pending async operation and complete it if possible.//voidSetAsyncStatus( PTLINEDEV pLineDev, DWORD dwNewStatus ){ DEBUGMSG(ZONE_FUNC|ZONE_ASYNC, (TEXT("UNIMODEM:+SetAsyncStatus\n"))); EnterCriticalSection(&pLineDev->OpenCS); // // Is there a pending operation to complete? // if (pLineDev->dwPendingType != INVALID_PENDINGOP) { pLineDev->dwPendingStatus = dwNewStatus; if (pLineDev->dwPendingID != INVALID_PENDINGID) { CompleteAsyncOp(pLineDev); } } LeaveCriticalSection(&pLineDev->OpenCS); DEBUGMSG(ZONE_FUNC|ZONE_ASYNC, (TEXT("UNIMODEM:-SetAsyncStatus\n")));} // SetAsyncStatus//// Abort any previously pending operation and record new pending operation// (called by async TSPI_line* functions)//voidSetAsyncOp( PTLINEDEV pLineDev, DWORD dwNewOp ){ DEBUGMSG(ZONE_FUNC|ZONE_ASYNC, (TEXT("UNIMODEM:+SetAsyncOp\n"))); EnterCriticalSection(&pLineDev->OpenCS); // // Is there a pending operation that we need to abort? // if (pLineDev->dwPendingType != INVALID_PENDINGOP) { LeaveCriticalSection(&pLineDev->OpenCS); SetAsyncStatus(pLineDev, LINEERR_OPERATIONFAILED); EnterCriticalSection(&pLineDev->OpenCS); } pLineDev->dwPendingType = dwNewOp; pLineDev->dwPendingStatus = LINEERR_ALLOCATED; pLineDev->dwPendingID = INVALID_PENDINGID; LeaveCriticalSection(&pLineDev->OpenCS); DEBUGMSG(ZONE_FUNC|ZONE_ASYNC, (TEXT("UNIMODEM:-SetAsyncOp\n")));} // SetAsyncOptypedef struct _ASYNCCMD { DWORD dwRequestID; DWORD dwResult;} ASYNCCMD, * PASYNCCMD;DWORDAsyncCompleteThread( PVOID lpvIn ){ PASYNCCMD pCmd = (PASYNCCMD)lpvIn; DEBUGMSG(ZONE_ASYNC, (TEXT("UNIMODEM:AsyncCompleteThread completing ID(0x%x) result 0x%x\n"), pCmd->dwRequestID, pCmd->dwResult)); TspiGlobals.fnCompletionCallback(pCmd->dwRequestID, pCmd->dwResult); TSPIFree(pCmd); return 0;} // AsyncCompleteThreadBOOLStartCompleteAsyncOp( PTLINEDEV pLineDev ){ HANDLE hThd; PASYNCCMD pCmd; if (NULL == (pCmd = TSPIAlloc(sizeof(ASYNCCMD)))) { DEBUGMSG(1, (TEXT("UNIMODEM:StartCompleteAsyncOp Unable to allocate ASYNCCMD!!!\n"))); return FALSE; } EnterCriticalSection(&pLineDev->OpenCS); pCmd->dwRequestID = pLineDev->dwPendingID; pCmd->dwResult = pLineDev->dwPendingStatus; pLineDev->dwPendingID = INVALID_PENDINGID; pLineDev->dwPendingType = INVALID_PENDINGOP; pLineDev->dwPendingStatus = 0; LeaveCriticalSection(&pLineDev->OpenCS); hThd = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)AsyncCompleteThread, pCmd, 0, NULL ); if (!hThd) { DEBUGMSG(1, (TEXT("UNIMODEM:StartCompleteAsyncOp Unable to Create AsyncCompleteThread!!!\n"))); TSPIFree(pCmd); return FALSE; } CloseHandle(hThd); return TRUE;} // StartCompleteAsyncOp//// Read the default devconfig for this device from the registry//VOIDgetDefaultDevConfig( PTLINEDEV ptLineDev, PDEVMINICFG pDevMiniCfg ){ static const WCHAR szDevConfig[] = TEXT("DevConfig"); DWORD dwSize, dwRetCode; DEBUGMSG(ZONE_FUNC | ZONE_INIT, (TEXT("UNIMODEM:+getDefaultDevConfig\r\n"))); // Get the default device config from the registry dwSize = sizeof( DEVMINICFG ); dwRetCode = MdmRegGetValue(ptLineDev, NULL, szDevConfig, REG_BINARY, (LPBYTE)pDevMiniCfg, &dwSize); if( (dwRetCode != ERROR_SUCCESS) || (pDevMiniCfg->wVersion != DEVMINCFG_VERSION) || (dwSize < (sizeof(DEVMINICFG) - (DIAL_MODIFIER_LEN*sizeof(WCHAR)) ))) { DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("UNIMODEM:Device Config error, retcode x%X, version x%X (x%X), Size x%X (x%X)\r\n"), dwRetCode, pDevMiniCfg->wVersion, DEVMINCFG_VERSION, dwSize, (sizeof(DEVMINICFG) - (DIAL_MODIFIER_LEN*sizeof(WCHAR)) )) ); // Either the registry value is missing, or it is invalid. // We need some default, use the one in ROM *pDevMiniCfg = DefaultDevCfg; } pDevMiniCfg->szDialModifier[DIAL_MODIFIER_LEN] = 0; // make sure it is null terminated DEBUGMSG(ZONE_INIT, (TEXT("UNIMODEM:Done reading Device Config, retcode x%X\r\n"), dwRetCode)); DEBUGMSG(ZONE_INIT, (TEXT("UNIMODEM:Version x%X\tWait Bong x%X\tCall Setup Fail x%X\r\n"), ptLineDev->DevMiniCfg.wVersion, ptLineDev->DevMiniCfg.wWaitBong, ptLineDev->DevMiniCfg.dwCallSetupFailTimer)); DEBUGMSG(ZONE_INIT, (TEXT("UNIMODEM:Baud %d\tByte Size %d\tStop Bits %d\tParity %d\r\n"), ptLineDev->DevMiniCfg.dwBaudRate, ptLineDev->DevMiniCfg.ByteSize, ptLineDev->DevMiniCfg.StopBits, ptLineDev->DevMiniCfg.Parity)); DEBUGMSG(ZONE_FUNC | ZONE_INIT, (TEXT("UNIMODEM:-getDefaultDevConfig\r\n")));}//// Create a LineDev//PTLINEDEVcreateLineDev( HKEY hActiveKey, LPCWSTR lpszDevPath, LPCWSTR lpszDeviceName ){ PTLINEDEV ptLineDev; PTLINEDEV ptExistingDev; static const WCHAR szDeviceType[] = TEXT("DeviceType"); static const WCHAR szPortName[] = TEXT("Port"); static const WCHAR szFriendlyName[] = TEXT("FriendlyName"); static const WCHAR szPnpIdName[] = TEXT("PnpId"); static const WCHAR szMaxCmd[] = TEXT("MaxCmd"); static const WCHAR szDialBilling[] = TEXT("DialBilling"); DWORD dwSize, dwRetCode, dwTemp; WCHAR szContinuation[16]; DEBUGMSG(ZONE_FUNC|ZONE_INIT, (TEXT("UNIMODEM:+createLineDev\r\n"))); // We are being asked to create a new linedev - do it if (!(ptLineDev = (PTLINEDEV) TSPIAlloc(sizeof(TLINEDEV)) )) { return NULL; } // Initialize all of the fields ptLineDev->dwPendingID = INVALID_PENDINGID; ptLineDev->dwDefaultMediaModes = LINEMEDIAMODE_DATAMODEM; // Do this early, NullifyLine uses it ptLineDev->bControlThreadRunning = FALSE; NullifyLineDevice( ptLineDev, TRUE ); // also calls getDefaultDevConfig // Get the device registry handle for later use. dwRetCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, lpszDevPath, 0, KEY_READ, &ptLineDev->hSettingsKey); if (ERROR_SUCCESS != dwRetCode) { // We can't very well continue if the registry values aren't there. DEBUGMSG(ZONE_ERROR|ZONE_INIT, (TEXT("UNIMODEM:createLineDev - RegOpenKeyEx %s returned %d.\r\n"), lpszDevPath, dwRetCode)); goto abort_buffer_allocated; } else { DEBUGMSG(ZONE_MISC|ZONE_INIT, (TEXT("UNIMODEM:createLineDev - RegOpenKeyEx %s handle x%X.\r\n"), lpszDevPath, ptLineDev->hSettingsKey)); } // Record the port name, or read it ourselves if NULL if( NULL == lpszDeviceName ) { // Get the port name from registry dwSize = MAXDEVICENAME; dwRetCode = MdmRegGetValue(ptLineDev, NULL, szPortName, REG_SZ, (LPBYTE)ptLineDev->szDeviceName, &dwSize); if( dwRetCode != ERROR_SUCCESS ) { // We can't do much without a port, abort now. goto abort_registry_opened; } } else { wcscpy( ptLineDev->szDeviceName, lpszDeviceName ); } // Get the device type from registry dwSize = sizeof( DWORD ); dwRetCode = MdmRegGetValue(ptLineDev, NULL, szDeviceType, REG_DWORD, (LPBYTE)&dwTemp, &dwSize); if( dwRetCode == ERROR_SUCCESS ) { DEBUGMSG(ZONE_MISC|ZONE_INIT, (TEXT("UNIMODEM:createLineDev - Device type x%X.\r\n"), dwTemp)); ptLineDev->wDeviceType = (WORD)dwTemp; } else { DEBUGMSG(ZONE_MISC|ZONE_INIT, (TEXT("UNIMODEM:createLineDev - Device type defaulting to NULL_MODEM.\r\n"))); ptLineDev->wDeviceType = DT_NULL_MODEM; // default type is null } // Get the maximum command length from registry dwSize = sizeof( DWORD ); dwRetCode = MdmRegGetValue(ptLineDev, szSettings, szMaxCmd, REG_DWORD, (LPBYTE)&dwTemp, &dwSize); if( dwRetCode == ERROR_SUCCESS ) { DEBUGMSG(ZONE_MISC|ZONE_INIT, (TEXT("UNIMODEM:createLineDev - Max command length x%X.\r\n"), dwTemp)); ptLineDev->dwMaxCmd = (WORD)dwTemp; } else { DEBUGMSG(ZONE_MISC|ZONE_INIT, (TEXT("UNIMODEM:createLineDev - Max command length defaulting to x%X.\r\n"), MAX_CMD_LENGTH)); ptLineDev->dwMaxCmd = MAX_CMD_LENGTH; } // Get modem command continuation character - assume it is the first character of the dial suffix dwSize = sizeof( szContinuation ); if (ERROR_SUCCESS != MdmRegGetValue(ptLineDev, szSettings, szDialSuffix, REG_SZ, (PUCHAR)szContinuation, &dwSize) ) { ptLineDev->chContinuation = ';'; } else { ptLineDev->chContinuation = szContinuation[0]; } // // Get modem dial capabilities // ptLineDev->dwDevCapFlags = LINEDEVCAPFLAGS_DIALQUIET | LINEDEVCAPFLAGS_DIALDIALTONE |
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?