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

📄 tapicode.c

📁 一份有用的TAPI编程源码
💻 C
📖 第 1 页 / 共 5 页
字号:
        LocalFree(lpDS);
    if (lpCallParams)
        LocalFree(lpCallParams);
    if (lpAddressCaps)
        LocalFree(lpAddressCaps);

    return FALSE;
}   


//
//  FUNCTION: CreateCallParams(LPLINECALLPARAMS, LPCSTR)
//
//  PURPOSE: Allocates and fills a LINECALLPARAMS structure
//
//  PARAMETERS:
//    lpCallParams - 
//    lpszDisplayableAddress - 
//
//  RETURN VALUE:
//    Returns a LPLINECALLPARAMS ready to use for dialing DATAMODEM calls.
//    Returns NULL if unable to allocate the structure.
//
//  COMMENTS:
//
//    If a non-NULL lpCallParams is passed in, it must have been allocated
//    with LocalAlloc, and can potentially be freed and reallocated.  It must
//    also have the dwTotalSize field correctly set.
//
//

LPLINECALLPARAMS CreateCallParams (
    LPLINECALLPARAMS lpCallParams, LPCSTR lpszDisplayableAddress)
{
    size_t sizeDisplayableAddress;

    if (lpszDisplayableAddress == NULL)
        lpszDisplayableAddress = "";
        
    sizeDisplayableAddress = strlen(lpszDisplayableAddress) + 1;
                          
    lpCallParams = (LPLINECALLPARAMS) CheckAndReAllocBuffer(
        (LPVOID) lpCallParams, 
        sizeof(LINECALLPARAMS) + sizeDisplayableAddress,
        "CreateCallParams: ");

    if (lpCallParams == NULL)
        return NULL;
    
    // This is where we configure the line for DATAMODEM usage.
    lpCallParams -> dwBearerMode = LINEBEARERMODE_VOICE;
    lpCallParams -> dwMediaMode  = LINEMEDIAMODE_DATAMODEM;

    // This specifies that we want to use only IDLE calls and
    // don't want to cut into a call that might not be IDLE (ie, in use).
    lpCallParams -> dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
                                    
    // if there are multiple addresses on line, use first anyway.
    // It will take a more complex application than a simple tty app
    // to use multiple addresses on a line anyway.
    lpCallParams -> dwAddressMode = LINEADDRESSMODE_ADDRESSID;
    lpCallParams -> dwAddressID = 0;

    // Since we don't know where we originated, leave these blank.
    lpCallParams -> dwOrigAddressSize = 0;
    lpCallParams -> dwOrigAddressOffset = 0;
    
    // Unimodem ignores these values.
    (lpCallParams -> DialParams) . dwDialSpeed = 0;
    (lpCallParams -> DialParams) . dwDigitDuration = 0;
    (lpCallParams -> DialParams) . dwDialPause = 0;
    (lpCallParams -> DialParams) . dwWaitForDialtone = 0;
    
    // Address we are dialing.
    lpCallParams -> dwDisplayableAddressOffset = sizeof(LINECALLPARAMS);
    lpCallParams -> dwDisplayableAddressSize = sizeDisplayableAddress;
    strcpy((LPSTR)lpCallParams + sizeof(LINECALLPARAMS),
           lpszDisplayableAddress);

    return lpCallParams;
}


//
//  FUNCTION: long WaitForReply(long)
//
//  PURPOSE: Resynchronize by waiting for a LINE_REPLY 
//
//  PARAMETERS:
//    lRequestID - The asynchronous request ID that we're
//                 on a LINE_REPLY for.
//
//  RETURN VALUE:
//    - 0 if LINE_REPLY responded with a success.
//    - LINEERR constant if LINE_REPLY responded with a LINEERR
//    - 1 if the line was shut down before LINE_REPLY is received.
//
//  COMMENTS:
//
//    This function allows us to resynchronize an asynchronous
//    TAPI line call by waiting for the LINE_REPLY message.  It
//    waits until a LINE_REPLY is received or the line is shut down.
//
//    Note that this could cause re-entrancy problems as
//    well as mess with any message preprocessing that might
//    occur on this thread (such as TranslateAccelerator).
//
//    This function should to be called from the thread that did
//    lineInitialize, or the PeekMessage is on the wrong thread
//    and the synchronization is not guaranteed to work.  Also note
//    that if another PeekMessage loop is entered while waiting,
//    this could also cause synchronization problems.
//
//    One more note.  This function can potentially be re-entered
//    if the call is dropped for any reason while waiting.  If this
//    happens, just drop out and assume the wait has been canceled.  
//    This is signaled by setting bReentered to FALSE when the function 
//    is entered and TRUE when it is left.  If bReentered is ever TRUE 
//    during the function, then the function was re-entered.
//
//    This function times out and returns WAITERR_WAITTIMEDOUT
//    after WAITTIMEOUT milliseconds have elapsed.
//
//


long WaitForReply (long lRequestID)
{
    static BOOL bReentered;
    bReentered = FALSE;

    if (lRequestID > SUCCESS)
    {
        MSG msg; 
        DWORD dwTimeStarted;

        g_bReplyRecieved = FALSE;
        g_dwRequestedID = (DWORD) lRequestID;

        // Initializing this just in case there is a bug
        // that sets g_bReplyRecieved without setting the reply value.
        g_lAsyncReply = LINEERR_OPERATIONFAILED;

        dwTimeStarted = GetTickCount();

        while(!g_bReplyRecieved)
        {
            if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }

            // This should only occur if the line is shut down while waiting.
            if (!g_bTapiInUse || bReentered)
            {
                bReentered = TRUE;
                return WAITERR_WAITABORTED;
            }

            // Its a really bad idea to timeout a wait for a LINE_REPLY.
            // If we are execting a LINE_REPLY, we should wait till we get
            // it; it might take a long time to dial (for example).

            // If 5 seconds go by without a reply, it might be a good idea
            // to display a dialog box to tell the user that a
            // wait is in progress and to give the user the capability to
            // abort the wait.
        }

        bReentered = TRUE;
        return g_lAsyncReply;
    }

    bReentered = TRUE;
    return lRequestID;
}


//
//  FUNCTION: long WaitForCallState(DWORD)
//
//  PURPOSE: Wait for the line to reach a specific CallState.
//
//  PARAMETERS:
//    dwDesiredCallState - specific CallState to wait for.
//
//  RETURN VALUE:
//    Returns 0 (SUCCESS) when we reach the Desired CallState.
//    Returns WAITERR_WAITTIMEDOUT if timed out.
//    Returns WAITERR_WAITABORTED if call was closed while waiting.
//
//  COMMENTS:
//
//    This function allows us to synchronously wait for a line
//    to reach a specific LINESTATE or until the line is shut down.
//
//    Note that this could cause re-entrancy problems as
//    well as mess with any message preprocessing that might
//    occur on this thread (such as TranslateAccelerator).
//
//    One more note.  This function can potentially be re-entered
//    if the call is dropped for any reason while waiting.  If this
//    happens, just drop out and assume the wait has been canceled.  
//    This is signaled by setting bReentered to FALSE when the function 
//    is entered and TRUE when it is left.  If bReentered is ever TRUE 
//    during the function, then the function was re-entered.
//
//    This function should to be called from the thread that did
//    lineInitialize, or the PeekMessage is on the wrong thread
//    and the synchronization is not guaranteed to work.  Also note
//    that if another PeekMessage loop is entered while waiting,
//    this could also cause synchronization problems.
//
//    If the constant value I_LINECALLSTATE_ANY is used for the 
//    dwDesiredCallState, then WaitForCallState will return SUCCESS
//    upon receiving any CALLSTATE messages.
//    
//
//

long WaitForCallState(DWORD dwDesiredCallState)
{
    MSG msg;
    DWORD dwTimeStarted;
    static BOOL bReentered;

    bReentered = FALSE;

    dwTimeStarted = GetTickCount();

    g_bCallStateReceived = FALSE;

    while ((dwDesiredCallState == I_LINECALLSTATE_ANY) || 
           (g_dwCallState != dwDesiredCallState))
    {
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        // If we are waiting for any call state and get one, succeed.
        if ((dwDesiredCallState == I_LINECALLSTATE_ANY) && 
            g_bCallStateReceived)
        {
            break;
        }

        // This should only occur if the line is shut down while waiting.
        if (!g_bTapiInUse || bReentered)
        {
            bReentered = TRUE;
            OutputDebugString("WAITABORTED\n");
            return WAITERR_WAITABORTED;
        }

        // If we don't get the reply in a reasonable time, we time out.
        if (GetTickCount() - dwTimeStarted > WAITTIMEOUT)
        {
            bReentered = TRUE;
            OutputDebugString("WAITTIMEDOUT\n");
            return WAITERR_WAITTIMEDOUT;
        }

    }

    bReentered = TRUE;
    return SUCCESS;
}

//**************************************************
// lineCallback Function and Handlers.
//**************************************************


//
//  FUNCTION: lineCallbackFunc(..)
//
//  PURPOSE: Receive asynchronous TAPI events
//
//  PARAMETERS:
//    dwDevice  - Device associated with the event, if any
//    dwMsg     - TAPI event that occurred.
//    dwCallbackInstance - User defined data supplied when opening the line.
//    dwParam1  - dwMsg specific information
//    dwParam2  - dwMsg specific information
//    dwParam3  - dwMsg specific information
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
//    This is the function where all asynchronous events will come.
//    Almost all events will be specific to an open line, but a few
//    will be general TAPI events (such as LINE_REINIT).
//
//    Its important to note that this callback will *ALWAYS* be
//    called in the context of the thread that does the lineInitialize.
//    Even if another thread (such as the COMM threads) calls the API
//    that would result in the callback being called, it will be called
//    in the context of the main thread (since in this sample, the main
//    thread does the lineInitialize).
//
//


void CALLBACK lineCallbackFunc(
    DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance, 
    DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{

    OutputDebugLineCallback(
        dwDevice, dwMsg, dwCallbackInstance, 
        dwParam1, dwParam2, dwParam3);

    // All we do is dispatch the dwMsg to the correct handler.
    switch(dwMsg)
    {
        case LINE_CALLSTATE:
            DoLineCallState(dwDevice, dwMsg, dwCallbackInstance,
                dwParam1, dwParam2, dwParam3);
            break;

        case LINE_CLOSE:
            DoLineClose(dwDevice, dwMsg, dwCallbackInstance,
                dwParam1, dwParam2, dwParam3);
            break;

        case LINE_LINEDEVSTATE:
            DoLineDevState(dwDevice, dwMsg, dwCallbackInstance,
                dwParam1, dwParam2, dwParam3);
            break;

        case LINE_REPLY:
            DoLineReply(dwDevice, dwMsg, dwCallbackInstance,
                dwParam1, dwParam2, dwParam3);
            break;

        case LINE_CREATE:
            DoLineCreate(dwDevice, dwMsg, dwCallbackInstance,
                dwParam1, dwParam2, dwParam3);
            break;

        default:
            OutputDebugString("lineCallbackFunc message ignored\n");
            break;

    }

    return;

}


//
//  FUNCTION: DoLineReply(..)
//
//  PURPOSE: Handle LINE_REPLY asynchronous messages.
//
//  PARAMETERS:
//    dwDevice  - Line Handle associated with this LINE_REPLY.
//    dwMsg     - Should always be LINE_REPLY.
//    dwCallbackInstance - Unused by this sample.
//    dwParam1  - Asynchronous request ID.
//    dwParam2  - success or LINEERR error value.
//    dwParam3  - Unused.
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
//
//    All line API calls that return an asynchronous request ID
//    will eventually cause a LINE_REPLY message.  Handle it.
//
//    This sample assumes only one call at time, and that we wait
//    for a LINE_REPLY before making any other line API calls.
//
//    The only exception to the above is that we might shut down
//    the line before receiving a LINE_REPLY.
//
//

void DoLineReply(
    DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
    DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
    if ((long) dwParam2 != SUCCESS)
        OutputDebugLineError((long) dwParam2, "LINE_REPLY error: ");
    else
        OutputDebugString("LINE_REPLY: successfully replied.\n");

    // If we are currently waiting for this async Request ID
    // then set the global variables to acknowledge it.
    if (g_dwRequestedID == dwParam1)
    {
        g_bReplyRecieved = TRUE;
        g_lAsyncReply = (long) dwParam2;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -