WaveTsp.cpp
上传用户:hcyyun520
上传日期:2019-05-14
资源大小:365k
文件大小:20k
源码类别:

TAPI编程

开发平台:

Visual C++

  1. // WaveTsp.cpp
  2. #include "pch.h"
  3. #include "wavetsp.h"
  4. #include "tspline.h"
  5. #include "tspcall.h"
  6. #include "resource.h"
  7. HINSTANCE           g_hinst = 0;
  8. HPROVIDER           g_hProvider = 0;
  9. DWORD               g_dwLineDeviceIDBase = 0;
  10. DWORD               g_dwPermanentProviderID = 0;
  11. ASYNC_COMPLETION    g_pfnCompletionProc = 0;
  12. // { dwDialPause, dwDialSpeed, dwDigitDuration, dwWaitForDialtone }
  13. LINEDIALPARAMS      g_dpMin = { 100,  50, 100,  100 };
  14. LINEDIALPARAMS      g_dpDef = { 250,  50, 250,  500 };
  15. LINEDIALPARAMS      g_dpMax = { 1000, 50, 1000, 1000 };
  16. BOOL WINAPI DllMain(
  17.     HINSTANCE   hinst,
  18.     DWORD       dwReason,
  19.     void*      /*pReserved*/)
  20. {
  21.     if( dwReason == DLL_PROCESS_ATTACH )
  22.     {
  23.         g_hinst = hinst;
  24.     }
  25.     
  26.     return TRUE;
  27. }
  28. // TSPI_providerXxx functions /////////////////////////////////////////
  29. LONG TSPIAPI TSPI_providerEnumDevices(
  30.     DWORD       dwPermanentProviderID,
  31.     LPDWORD     pdwNumLines,
  32.     LPDWORD     pdwNumPhones,
  33.     HPROVIDER   hProvider,
  34.     LINEEVENT   pfnLineCreateProc,
  35.     PHONEEVENT  pfnPhoneCreateProc)
  36. {
  37.     BEGIN_PARAM_TABLE("TSPI_providerEnumDevices")
  38.         DWORD_IN_ENTRY(dwPermanentProviderID)
  39.         DWORD_OUT_ENTRY(pdwNumLines)
  40.         DWORD_OUT_ENTRY(pdwNumPhones)
  41.         DWORD_IN_ENTRY(hProvider)
  42.         DWORD_IN_ENTRY(pfnLineCreateProc)
  43.         DWORD_IN_ENTRY(pfnPhoneCreateProc)
  44.     END_PARAM_TABLE()
  45.     g_hProvider = hProvider;
  46.     *pdwNumLines = 1;
  47.     *pdwNumPhones = 0;
  48.     return EPILOG(0);
  49. }
  50. LONG TSPIAPI TSPI_providerInit(
  51.     DWORD               dwTSPIVersion,
  52.     DWORD               dwPermanentProviderID,
  53.     DWORD               dwLineDeviceIDBase,
  54.     DWORD               dwPhoneDeviceIDBase,
  55.     DWORD               dwNumLines,
  56.     DWORD               dwNumPhones,
  57.     ASYNC_COMPLETION    pfnCompletionProc,
  58.     LPDWORD             pdwTSPIOptions)
  59. {
  60.     BEGIN_PARAM_TABLE("TSPI_providerInit")
  61.         DWORD_IN_ENTRY(dwTSPIVersion)
  62.         DWORD_IN_ENTRY(dwPermanentProviderID)
  63.         DWORD_IN_ENTRY(dwLineDeviceIDBase)
  64.         DWORD_IN_ENTRY(dwPhoneDeviceIDBase)
  65.         DWORD_IN_ENTRY(dwNumLines)
  66.         DWORD_IN_ENTRY(dwNumPhones)
  67.         DWORD_IN_ENTRY(pfnCompletionProc)
  68.         DWORD_OUT_ENTRY(pdwTSPIOptions)
  69.     END_PARAM_TABLE()
  70.     g_dwPermanentProviderID = dwPermanentProviderID;
  71.     g_dwLineDeviceIDBase = dwLineDeviceIDBase;
  72.     g_pfnCompletionProc  = pfnCompletionProc;
  73.     *pdwTSPIOptions = LINETSPIOPTION_NONREENTRANT;
  74.     return EPILOG(0);
  75. }
  76. LONG TSPIAPI TSPI_providerShutdown(
  77.     DWORD   dwTSPIVersion,
  78.     DWORD   dwPermanentProviderID)
  79. {
  80.     BEGIN_PARAM_TABLE("TSPI_providerShutdown")
  81.         DWORD_IN_ENTRY(dwTSPIVersion)
  82.         DWORD_IN_ENTRY(dwPermanentProviderID)
  83.     END_PARAM_TABLE()
  84.     return EPILOG(0);
  85. }
  86. LONG TSPIAPI TSPI_providerConfig(
  87.     HWND    hwndOwner,
  88.     DWORD   dwPermanentProviderID)
  89. {
  90.     // Although this func is never called by TAPI v2.0, we export
  91.     // it so that the Telephony Control Panel Applet knows that it
  92.     // can configure this provider via lineConfigProvider(),
  93.     // otherwise Telephon.cpl will not consider it configurable
  94.     BEGIN_PARAM_TABLE("TSPI_providerConfig")
  95.         DWORD_IN_ENTRY(hwndOwner)
  96.         DWORD_IN_ENTRY(dwPermanentProviderID)
  97.     END_PARAM_TABLE()
  98.     return EPILOG(0);
  99. }
  100. LONG TSPIAPI TSPI_providerGenericDialogData(
  101.     DWORD   dwObjectID,
  102.     DWORD   dwObjectType,
  103.     LPVOID  pParams,
  104.     DWORD   dwSize)
  105. {
  106.     BEGIN_PARAM_TABLE("TSPI_providerGenericDialogData")
  107.         DWORD_IN_ENTRY(dwObjectID)
  108.         DWORD_IN_ENTRY(dwObjectType)
  109.         DWORD_IN_ENTRY(pParams)
  110.         DWORD_IN_ENTRY(dwSize)
  111.     END_PARAM_TABLE()
  112.     if( dwObjectType == TUISPIDLL_OBJECT_DIALOGINSTANCE )
  113.     {
  114.         // Handle requests from the UI for dialog-related data
  115.         TSPUIDATA*  pData = (TSPUIDATA*)pParams;
  116.         if( pData->dwRequestID )
  117.         {
  118.             // Complete asynch operation
  119.             g_pfnCompletionProc(pData->dwRequestID, pData->tr);
  120.         }
  121.         // Update call state
  122.         if( pData->tr == 0 )
  123.         {
  124.             pData->pCall->SetCallState(pData->nCallState);
  125.         }
  126.     }
  127.     return EPILOG(0);
  128. }
  129. LONG TSPIAPI TSPI_providerFreeDialogInstance(
  130.     HDRVDIALOGINSTANCE hdDlgInst)
  131. {
  132.     BEGIN_PARAM_TABLE("TSPI_providerFreeDialogInstance")
  133.         DWORD_IN_ENTRY(hdDlgInst)
  134.     END_PARAM_TABLE()
  135.     // W/o this function, TAPISVR.EXE crashes
  136.     return EPILOG(0);
  137. }
  138. LONG TSPIAPI TSPI_providerInstall(
  139.     HWND    hwndOwner,
  140.     DWORD   dwPermanentProviderID)
  141. {
  142.     // Although this func is never called by TAPI v2.0, we export
  143.     // it so that the Telephony Control Panel Applet knows that it
  144.     // can add this provider via lineAddProvider(), otherwise
  145.     // Telephon.cpl will not consider it installable
  146.     BEGIN_PARAM_TABLE("TSPI_providerInstall")
  147.         DWORD_IN_ENTRY(hwndOwner)
  148.         DWORD_IN_ENTRY(dwPermanentProviderID)
  149.     END_PARAM_TABLE()
  150.     return EPILOG(0);
  151. }
  152. LONG TSPIAPI TSPI_providerRemove(
  153.     HWND    hwndOwner,
  154.     DWORD   dwPermanentProviderID)
  155. {
  156.     // Although this func is never called by TAPI v2.0, we export
  157.     // it so that the Telephony Control Panel Applet knows that it
  158.     // can remove this provider via lineRemoveProvider(), otherwise
  159.     // Telephon.cpl will not consider it removable
  160.     BEGIN_PARAM_TABLE("TSPI_providerRemove")
  161.         DWORD_IN_ENTRY(hwndOwner)
  162.         DWORD_IN_ENTRY(dwPermanentProviderID)
  163.     END_PARAM_TABLE()
  164.     return EPILOG(0);
  165. }
  166. LONG TSPIAPI TSPI_providerUIIdentify(
  167.     LPWSTR   pszUIDLLName)
  168. {
  169.     BEGIN_PARAM_TABLE("TSPI_providerUIIdentify")
  170.         STRING_OUT_ENTRY(pszUIDLLName)
  171.     END_PARAM_TABLE()
  172.     // Use the same DLL for both non-UI and UI functions
  173.     char    szFileName[MAX_PATH+1];
  174.     GetModuleFileNameA(g_hinst, szFileName, MAX_PATH);
  175.     mbstowcs(pszUIDLLName, szFileName, strlen(szFileName) + 1);
  176.     return EPILOG(0);
  177. }
  178. // TSPI_lineXxx functions /////////////////////////////////////////////
  179. #define MIN(a, b) (a < b ? a : b)
  180. LONG TSPIAPI TSPI_lineNegotiateTSPIVersion(
  181.     DWORD   dwDeviceID,
  182.     DWORD   dwLowVersion,
  183.     DWORD   dwHighVersion,
  184.     LPDWORD pdwTSPIVersion)
  185. {
  186.     BEGIN_PARAM_TABLE("TSPI_lineNegotiateTSPIVersion")
  187.         DWORD_IN_ENTRY(dwDeviceID)
  188.         DWORD_IN_ENTRY(dwLowVersion)
  189.         DWORD_IN_ENTRY(dwHighVersion)
  190.         DWORD_OUT_ENTRY(pdwTSPIVersion)
  191.     END_PARAM_TABLE()
  192.     LONG    tr = 0;
  193.     
  194.     if( dwLowVersion <= TAPI_CURRENT_VERSION )
  195.     {
  196.         *pdwTSPIVersion = MIN(TAPI_CURRENT_VERSION, dwHighVersion);
  197.     }
  198.     else
  199.     {
  200.         tr = LINEERR_INCOMPATIBLEAPIVERSION;
  201.     }
  202.     return EPILOG(tr);
  203. }
  204. LONG TSPIAPI TSPI_lineGetDevCaps(
  205.     DWORD           dwDeviceID,
  206.     DWORD           dwTSPIVersion,
  207.     DWORD           dwExtVersion,
  208.     LPLINEDEVCAPS   pldc)
  209. {
  210.     BEGIN_PARAM_TABLE("TSPI_lineGetDevCaps")
  211.         DWORD_IN_ENTRY(dwDeviceID)
  212.         DWORD_IN_ENTRY(dwTSPIVersion)
  213.         DWORD_IN_ENTRY(dwExtVersion)
  214.         DWORD_IN_ENTRY(pldc)
  215.     END_PARAM_TABLE()
  216.     LONG            tr = 0;
  217.     const wchar_t   szProviderInfo[] = L"WAVE Service Provider";
  218.     const wchar_t   szLineName[] = L"WaveLine";
  219.     pldc->dwNeededSize = sizeof(LINEDEVCAPS) +
  220.                          sizeof(szProviderInfo) +
  221.                          sizeof(szLineName);
  222.     
  223.     if( pldc->dwNeededSize <= pldc->dwTotalSize )
  224.     {
  225.         pldc->dwUsedSize = pldc->dwNeededSize;
  226.         pldc->dwProviderInfoSize    = sizeof(szProviderInfo);
  227.         pldc->dwProviderInfoOffset  = sizeof(LINEDEVCAPS) + 0;
  228.         wchar_t* pszProviderInfo = (wchar_t*)((BYTE*)pldc + pldc->dwProviderInfoOffset);
  229.         wcscpy(pszProviderInfo, szProviderInfo);
  230.         
  231.         pldc->dwLineNameSize        = sizeof(szLineName);
  232.         pldc->dwLineNameOffset      = sizeof(LINEDEVCAPS) + sizeof(szProviderInfo);
  233.         wchar_t* pszLineName = (wchar_t*)((BYTE*)pldc + pldc->dwLineNameOffset);
  234.         wcscpy(pszLineName, szLineName);
  235.     }
  236.     else
  237.     {
  238.         pldc->dwUsedSize = sizeof(LINEDEVCAPS);
  239.     }
  240.     
  241.     pldc->dwStringFormat      = STRINGFORMAT_ASCII;
  242. // Microsoft recommended algorithm for
  243. // calculating the permanent line ID
  244. #define MAKEPERMLINEID(dwPermProviderID, dwDeviceID) 
  245.     ((LOWORD(dwPermProviderID) << 16) | dwDeviceID)
  246.     pldc->dwPermanentLineID   = MAKEPERMLINEID(g_dwPermanentProviderID, dwDeviceID - g_dwLineDeviceIDBase);
  247.     pldc->dwAddressModes      = LINEADDRESSMODE_ADDRESSID;
  248.     pldc->dwNumAddresses      = 1;
  249.     pldc->dwBearerModes       = LINEBEARERMODE_VOICE;
  250.     pldc->dwMediaModes        = LINEMEDIAMODE_INTERACTIVEVOICE;
  251.     pldc->dwGenerateDigitModes= LINEDIGITMODE_DTMF;
  252.     pldc->dwDevCapFlags       = LINEDEVCAPFLAGS_CLOSEDROP;
  253.     pldc->dwMaxNumActiveCalls = 1;
  254.     pldc->dwLineFeatures      = LINEFEATURE_MAKECALL;
  255.     // DialParams
  256.     pldc->MinDialParams = g_dpMin;
  257.     pldc->MaxDialParams = g_dpMax;
  258.     pldc->DefaultDialParams = g_dpDef;
  259.     
  260.     return EPILOG(tr);
  261. }
  262. LONG TSPIAPI TSPI_lineGetAddressCaps(
  263.     DWORD              dwDeviceID,
  264.     DWORD              dwAddressID,
  265.     DWORD              dwTSPIVersion,
  266.     DWORD              dwExtVersion,
  267.     LPLINEADDRESSCAPS  pac)
  268. {
  269.     BEGIN_PARAM_TABLE("TSPI_lineGetAddressCaps")
  270.         DWORD_IN_ENTRY(dwDeviceID)
  271.         DWORD_IN_ENTRY(dwAddressID)
  272.         DWORD_IN_ENTRY(dwTSPIVersion)
  273.         DWORD_IN_ENTRY(dwExtVersion)
  274.     END_PARAM_TABLE()
  275.     if( dwAddressID != 0 ) return EPILOG(LINEERR_INVALADDRESSID);
  276.     pac->dwNeededSize           = sizeof(LINEADDRESSCAPS);
  277.     pac->dwUsedSize             = sizeof(LINEADDRESSCAPS);
  278.     pac->dwLineDeviceID         = dwDeviceID;
  279.     pac->dwAddressSharing       = LINEADDRESSSHARING_PRIVATE;
  280.     pac->dwCallInfoStates       = LINECALLINFOSTATE_MEDIAMODE |
  281.                                   LINECALLINFOSTATE_APPSPECIFIC;
  282.     pac->dwCallerIDFlags        = LINECALLPARTYID_UNAVAIL;
  283.     pac->dwCalledIDFlags        = LINECALLPARTYID_UNAVAIL;
  284.     pac->dwRedirectionIDFlags   = LINECALLPARTYID_UNAVAIL;
  285.     pac->dwRedirectingIDFlags   = LINECALLPARTYID_UNAVAIL;
  286.     pac->dwCallStates           = LINECALLSTATE_IDLE |
  287.                                   LINECALLSTATE_DIALING |
  288.                                   LINECALLSTATE_CONNECTED;
  289.     pac->dwDialToneModes        = LINEDIALTONEMODE_UNAVAIL;
  290.     pac->dwBusyModes            = LINEBUSYMODE_UNAVAIL;
  291.     pac->dwSpecialInfo          = LINESPECIALINFO_UNAVAIL;
  292.     pac->dwDisconnectModes      = LINEDISCONNECTMODE_UNAVAIL;
  293.     pac->dwMaxNumActiveCalls    = 1;
  294.     pac->dwAddrCapFlags         = LINEADDRCAPFLAGS_DIALED;
  295.     pac->dwCallFeatures         = LINECALLFEATURE_DIAL |
  296.                                   LINECALLFEATURE_DROP |
  297.                                   LINECALLFEATURE_GENERATEDIGITS;
  298.     pac->dwAddressFeatures      = LINEADDRFEATURE_MAKECALL;
  299.     
  300.     return EPILOG(0);
  301. }
  302. LONG TSPIAPI TSPI_lineGetID(
  303.     HDRVLINE    hdLine,
  304.     DWORD       dwAddressID,
  305.     HDRVCALL    hdCall,
  306.     DWORD       dwSelect,
  307.     LPVARSTRING pDeviceID,
  308.     LPCWSTR     pszDeviceClass,
  309.     HANDLE      hTargetProcess)
  310. {
  311.     BEGIN_PARAM_TABLE("TSPI_lineGetID")
  312.         DWORD_IN_ENTRY(hdLine)
  313.         DWORD_IN_ENTRY(dwAddressID)
  314.         DWORD_IN_ENTRY(hdCall)
  315.         DWORD_IN_ENTRY(dwSelect)
  316.         DWORD_IN_ENTRY(pDeviceID)
  317.         STRING_IN_ENTRY(pszDeviceClass)
  318.         DWORD_IN_ENTRY(hTargetProcess)
  319.     END_PARAM_TABLE()
  320.     
  321.     LONG    tr = LINEERR_NODEVICE;
  322.     /*
  323.     // TAPI handles "tapi/line" and "tapi/phone",
  324.     // so long as this function is present and returns LINEERR_NODEVICE
  325.     LONG        tr = 0;
  326.     CtspCall*   pCall = (dwSelect == LINECALLSELECT_CALL ? (CtspCall*)hdCall : 0);
  327.     CtspLine*   pLine = (dwSelect == LINECALLSELECT_LINE ? (CtspLine*)hdLine : (pCall ? pCall->GetLine() : 0));
  328.     if( lstrcmpiW(pszDeviceClass, L"tapi/line") == 0 )
  329.     {
  330.         pDeviceID->dwNeededSize = sizeof(VARSTRING) + sizeof(DWORD);
  331.         if( pDeviceID->dwNeededSize <= pDeviceID->dwTotalSize )
  332.         {
  333.             pDeviceID->dwUsedSize      = pDeviceID->dwNeededSize;
  334.             pDeviceID->dwStringFormat  = STRINGFORMAT_BINARY;
  335.             pDeviceID->dwStringSize    = sizeof(DWORD);
  336.             pDeviceID->dwStringOffset  = sizeof(VARSTRING);
  337.             
  338.             *((LPDWORD)(pDeviceID + 1)) = pLine->GetDeviceID();
  339.         }
  340.         else
  341.         {
  342.             pDeviceID->dwUsedSize = 3 * sizeof(DWORD);
  343.             tr = LINEERR_STRUCTURETOOSMALL;
  344.         }
  345.     }
  346.     else
  347.     {
  348.         tr = LINEERR_NODEVICE;
  349.     }
  350.     */
  351.     
  352.     return EPILOG(tr);
  353. }
  354. LONG TSPIAPI TSPI_lineOpen(
  355.     DWORD       dwDeviceID,
  356.     HTAPILINE   htLine,
  357.     LPHDRVLINE  phdLine,
  358.     DWORD       dwTSPIVersion,
  359.     LINEEVENT   pfnEventProc)
  360. {
  361.     BEGIN_PARAM_TABLE("TSPI_lineOpen")
  362.         DWORD_IN_ENTRY(dwDeviceID)
  363.         DWORD_IN_ENTRY(htLine)
  364.         DWORD_OUT_ENTRY(phdLine)
  365.         DWORD_IN_ENTRY(dwTSPIVersion)
  366.         DWORD_IN_ENTRY(pfnEventProc)
  367.     END_PARAM_TABLE()
  368.     
  369.     LONG        tr = LINEERR_NOMEM;
  370.     CtspLine*   pLine = new CtspLine(htLine, pfnEventProc, dwDeviceID);
  371.     if( pLine )
  372.     {
  373.         *phdLine = (HDRVLINE)pLine;
  374.         tr = 0;
  375.     }
  376.     
  377.     return EPILOG(tr);
  378. }
  379. LONG TSPIAPI TSPI_lineSetDefaultMediaDetection(
  380.     HDRVLINE    hdLine,
  381.     DWORD       dwMediaModes)
  382. {
  383.     BEGIN_PARAM_TABLE("TSPI_lineSetDefaultMediaDetection")
  384.         DWORD_IN_ENTRY(hdLine)
  385.         DWORD_IN_ENTRY(dwMediaModes)
  386.     END_PARAM_TABLE()
  387.     
  388.     // This function is required, or TAPISRV will crash
  389.     // if any application attempts to open this line
  390.     // for incoming calls (sigh)
  391.     return EPILOG(LINEERR_OPERATIONUNAVAIL);
  392. }
  393. LONG TSPIAPI TSPI_lineGetNumAddressIDs(
  394.     HDRVLINE    hdLine,
  395.     LPDWORD     pdwNumAddressIDs)
  396. {
  397.     BEGIN_PARAM_TABLE("TSPI_lineGetNumAddressIDs")
  398.         DWORD_IN_ENTRY(hdLine)
  399.         DWORD_OUT_ENTRY(pdwNumAddressIDs)
  400.     END_PARAM_TABLE()
  401.     
  402.     // We only support 1 address (id=0)
  403.     *pdwNumAddressIDs = 1;
  404.     return EPILOG(0);
  405. }
  406. LONG TSPIAPI TSPI_lineClose(
  407.     HDRVLINE    hdLine)
  408. {
  409.     BEGIN_PARAM_TABLE("TSPI_lineClose")
  410.         DWORD_IN_ENTRY(hdLine)
  411.     END_PARAM_TABLE()
  412.     delete (CtspLine*)hdLine;
  413.     return EPILOG(0);
  414. }
  415. LONG TSPIAPI TSPI_lineMakeCall(
  416.     DRV_REQUESTID       dwRequestID,
  417.     HDRVLINE            hdLine,
  418.     HTAPICALL           htCall,
  419.     LPHDRVCALL          phdCall,
  420.     LPCWSTR             pszDestAddress,
  421.     DWORD               dwCountryCode,
  422.     LPLINECALLPARAMS    const pCallParams)
  423. {
  424.     BEGIN_PARAM_TABLE("TSPI_lineMakeCall")
  425.         DWORD_IN_ENTRY(dwRequestID)
  426.         DWORD_IN_ENTRY(hdLine)
  427.         DWORD_IN_ENTRY(htCall)
  428.         DWORD_OUT_ENTRY(phdCall)
  429.         STRING_IN_ENTRY(pszDestAddress)
  430.         DWORD_IN_ENTRY(dwCountryCode)
  431.         DWORD_IN_ENTRY(pCallParams)
  432.     END_PARAM_TABLE()
  433.     LONG        tr;
  434.     CtspLine*   pLine = (CtspLine*)hdLine;
  435.     tr = pLine->MakeCall(dwRequestID, htCall, phdCall, pszDestAddress, dwCountryCode, pCallParams);
  436.     return EPILOG(tr);
  437. }
  438. LONG TSPIAPI TSPI_lineSetStatusMessages(
  439.     HDRVLINE    hdLine,
  440.     DWORD       dwLineStates,
  441.     DWORD       dwAddressStates)
  442. {
  443.     BEGIN_PARAM_TABLE("TSPI_lineSetStatusMessages")
  444.         DWORD_IN_ENTRY(hdLine)
  445.         DWORD_IN_ENTRY(dwLineStates)
  446.         DWORD_IN_ENTRY(dwAddressStates)
  447.     END_PARAM_TABLE()
  448.     // Since we don't ever send status messages of any kind
  449.     // we're happy at any limit. However, some apps require
  450.     // that this function return successfully before a call
  451.     // can be made, e.g. Outlook 98.
  452.     return EPILOG(0);
  453. }
  454. LONG TSPIAPI TSPI_lineDrop(
  455.     DRV_REQUESTID   dwRequestID,
  456.     HDRVCALL        hdCall,
  457.     LPCSTR          psUserUserInfo,
  458.     DWORD           dwSize)
  459. {
  460.     BEGIN_PARAM_TABLE("TSPI_lineDrop")
  461.         DWORD_IN_ENTRY(dwRequestID)
  462.         DWORD_IN_ENTRY(hdCall)
  463.         DWORD_IN_ENTRY(psUserUserInfo)
  464.         DWORD_IN_ENTRY(dwSize)
  465.     END_PARAM_TABLE()
  466.     CtspCall*   pCall = (CtspCall*)hdCall;
  467.     pCall->Drop();
  468.     g_pfnCompletionProc(dwRequestID, 0);
  469.     return EPILOG(dwRequestID);
  470. }
  471. LONG TSPIAPI TSPI_lineCloseCall(
  472.     HDRVCALL    hdCall)
  473. {
  474.     BEGIN_PARAM_TABLE("TSPI_lineCloseCall")
  475.         DWORD_IN_ENTRY(hdCall)
  476.     END_PARAM_TABLE()
  477.     // Note that in TAPI 2.0 TSPI_lineCloseCall can get called
  478.     // without TSPI_lineDrop ever being called, so we need to
  479.     // be prepared for either case.
  480.     CtspCall*   pCall = (CtspCall*)hdCall;
  481.     pCall->Drop();
  482.     delete pCall;
  483.     return EPILOG(0);
  484. }
  485. LONG TSPIAPI TSPI_lineGetAddressStatus(
  486.     HDRVLINE            hdLine,
  487.     DWORD               dwAddressID,
  488.     LPLINEADDRESSSTATUS pas)
  489. {
  490.     BEGIN_PARAM_TABLE("TSPI_lineGetAddressStatus")
  491.         DWORD_IN_ENTRY(hdLine)
  492.         DWORD_IN_ENTRY(dwAddressID)
  493.         DWORD_IN_ENTRY(pas)
  494.     END_PARAM_TABLE()
  495.     pas->dwNeededSize = sizeof(LINEADDRESSSTATUS);
  496.     pas->dwUsedSize   = sizeof(LINEADDRESSSTATUS);
  497.     pas->dwNumActiveCalls  = ((CtspLine*)hdLine)->GetNumActiveCalls();
  498.     pas->dwAddressFeatures = LINEADDRFEATURE_MAKECALL;
  499.     
  500.     return EPILOG(0);
  501. }
  502. LONG TSPIAPI TSPI_lineGetCallAddressID(
  503.     HDRVCALL    hdCall,
  504.     LPDWORD     pdwAddressID)
  505. {
  506.     BEGIN_PARAM_TABLE("TSPI_lineGetCallAddressID")
  507.         DWORD_IN_ENTRY(hdCall)
  508.         DWORD_OUT_ENTRY(pdwAddressID)
  509.     END_PARAM_TABLE()
  510.     // We only support 1 address (id=0)
  511.     *pdwAddressID = 0;
  512.     return EPILOG(0);
  513. }
  514. LONG TSPIAPI TSPI_lineGetCallInfo(
  515.     HDRVCALL        hdCall,
  516.     LPLINECALLINFO  pli)
  517. {
  518.     BEGIN_PARAM_TABLE("TSPI_lineGetCallInfo")
  519.         DWORD_IN_ENTRY(hdCall)
  520.         DWORD_IN_ENTRY(pli)
  521.     END_PARAM_TABLE()
  522.     pli->dwNeededSize           = sizeof(LINECALLINFO);
  523.     pli->dwUsedSize             = sizeof(LINECALLINFO);
  524.     
  525.     pli->dwBearerMode           = LINEBEARERMODE_VOICE;
  526.     pli->dwMediaMode            = LINEMEDIAMODE_INTERACTIVEVOICE;
  527.     pli->dwCallStates           = LINECALLSTATE_IDLE |
  528.                                   LINECALLSTATE_DIALING |
  529.                                   LINECALLSTATE_CONNECTED |
  530.                                   LINECALLSTATE_PROCEEDING |
  531.                                   LINECALLSTATE_UNKNOWN;
  532.     pli->dwOrigin               = LINECALLORIGIN_OUTBOUND;
  533.     pli->dwReason               = LINECALLREASON_DIRECT;
  534.     pli->dwCallerIDFlags        = LINECALLPARTYID_UNAVAIL;
  535.     pli->dwCalledIDFlags        = LINECALLPARTYID_UNAVAIL;
  536.     pli->dwConnectedIDFlags     = LINECALLPARTYID_UNAVAIL;
  537.     pli->dwRedirectionIDFlags   = LINECALLPARTYID_UNAVAIL;
  538.     pli->dwRedirectingIDFlags   = LINECALLPARTYID_UNAVAIL;
  539.     
  540.     return EPILOG(0);
  541. }
  542. LONG TSPIAPI TSPI_lineGetCallStatus(
  543.     HDRVCALL            hdCall,
  544.     LPLINECALLSTATUS    pls)
  545. {
  546.     BEGIN_PARAM_TABLE("TSPI_lineGetCallStatus")
  547.         DWORD_IN_ENTRY(hdCall)
  548.         DWORD_IN_ENTRY(pls)
  549.     END_PARAM_TABLE()
  550.     CtspCall*   pCall = (CtspCall*)hdCall;
  551.     pls->dwNeededSize = sizeof(LINECALLSTATUS);
  552.     pls->dwUsedSize   = sizeof(LINECALLSTATUS);
  553.     pls->dwCallState  = pCall->GetCallState();
  554.     
  555.     if( pls->dwCallState != LINECALLSTATE_IDLE )
  556.     {
  557.         pls->dwCallFeatures = LINECALLFEATURE_DROP;
  558.     }
  559.     
  560.     return EPILOG(0);
  561. }
  562. LONG TSPIAPI TSPI_lineGetLineDevStatus(
  563.     HDRVLINE        hdLine,
  564.     LPLINEDEVSTATUS plds)
  565. {
  566.     BEGIN_PARAM_TABLE("TSPI_lineGetLineDevStatus")
  567.         DWORD_IN_ENTRY(hdLine)
  568.         DWORD_IN_ENTRY(plds)
  569.     END_PARAM_TABLE()
  570.     plds->dwUsedSize        = sizeof(LINEDEVSTATUS);
  571.     plds->dwNeededSize      = sizeof(LINEDEVSTATUS);
  572.     
  573.     plds->dwNumActiveCalls  = ((CtspLine*)hdLine)->GetNumActiveCalls();
  574.     plds->dwDevStatusFlags  = LINEDEVSTATUSFLAGS_CONNECTED |
  575.                               LINEDEVSTATUSFLAGS_INSERVICE;
  576.     return EPILOG(0);
  577. }
  578. LONG TSPIAPI TSPI_lineGetIcon(
  579.     DWORD   dwDeviceID,
  580.     LPCWSTR lpszDeviceClass,  
  581.     LPHICON lphIcon)
  582. {
  583.     BEGIN_PARAM_TABLE("TSPI_lineGetIcon")
  584.         DWORD_IN_ENTRY(dwDeviceID)
  585.         STRING_IN_ENTRY(lpszDeviceClass)
  586.         DWORD_OUT_ENTRY(lphIcon)
  587.     END_PARAM_TABLE()
  588.     *lphIcon = LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_WAVETSP));
  589.     return EPILOG(0);
  590. }