⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 misc.c

📁 See Hanoi.cpp for the implementation of this cla
💻 C
📖 第 1 页 / 共 3 页
字号:
/**************************************************************************/
/** 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
//
void
CompleteAsyncOp(
    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.
//
DWORD
SetAsyncID(
    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.
//
void
SetAsyncStatus(
    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)
//
void
SetAsyncOp(
    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")));
}   // SetAsyncOp


typedef struct _ASYNCCMD {
    DWORD dwRequestID;
    DWORD dwResult;
} ASYNCCMD, * PASYNCCMD;


DWORD
AsyncCompleteThread(
    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;
}   // AsyncCompleteThread


BOOL
StartCompleteAsyncOp(
    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
//
VOID
getDefaultDevConfig(
    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
//
PTLINEDEV
createLineDev(
    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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -