📄 wavetsp.cpp
字号:
// WaveTsp.cpp
#include "pch.h"
#include "wavetsp.h"
#include "tspline.h"
#include "tspcall.h"
#include "resource.h"
HINSTANCE g_hinst = 0;
HPROVIDER g_hProvider = 0;
DWORD g_dwLineDeviceIDBase = 0;
DWORD g_dwPermanentProviderID = 0;
ASYNC_COMPLETION g_pfnCompletionProc = 0;
// { dwDialPause, dwDialSpeed, dwDigitDuration, dwWaitForDialtone }
LINEDIALPARAMS g_dpMin = { 100, 50, 100, 100 };
LINEDIALPARAMS g_dpDef = { 250, 50, 250, 500 };
LINEDIALPARAMS g_dpMax = { 1000, 50, 1000, 1000 };
BOOL WINAPI DllMain(
HINSTANCE hinst,
DWORD dwReason,
void* /*pReserved*/)
{
if( dwReason == DLL_PROCESS_ATTACH )
{
g_hinst = hinst;
}
return TRUE;
}
// TSPI_providerXxx functions /////////////////////////////////////////
LONG TSPIAPI TSPI_providerEnumDevices(
DWORD dwPermanentProviderID,
LPDWORD pdwNumLines,
LPDWORD pdwNumPhones,
HPROVIDER hProvider,
LINEEVENT pfnLineCreateProc,
PHONEEVENT pfnPhoneCreateProc)
{
BEGIN_PARAM_TABLE("TSPI_providerEnumDevices")
DWORD_IN_ENTRY(dwPermanentProviderID)
DWORD_OUT_ENTRY(pdwNumLines)
DWORD_OUT_ENTRY(pdwNumPhones)
DWORD_IN_ENTRY(hProvider)
DWORD_IN_ENTRY(pfnLineCreateProc)
DWORD_IN_ENTRY(pfnPhoneCreateProc)
END_PARAM_TABLE()
g_hProvider = hProvider;
*pdwNumLines = 1;
*pdwNumPhones = 0;
return EPILOG(0);
}
LONG TSPIAPI TSPI_providerInit(
DWORD dwTSPIVersion,
DWORD dwPermanentProviderID,
DWORD dwLineDeviceIDBase,
DWORD dwPhoneDeviceIDBase,
DWORD dwNumLines,
DWORD dwNumPhones,
ASYNC_COMPLETION pfnCompletionProc,
LPDWORD pdwTSPIOptions)
{
BEGIN_PARAM_TABLE("TSPI_providerInit")
DWORD_IN_ENTRY(dwTSPIVersion)
DWORD_IN_ENTRY(dwPermanentProviderID)
DWORD_IN_ENTRY(dwLineDeviceIDBase)
DWORD_IN_ENTRY(dwPhoneDeviceIDBase)
DWORD_IN_ENTRY(dwNumLines)
DWORD_IN_ENTRY(dwNumPhones)
DWORD_IN_ENTRY(pfnCompletionProc)
DWORD_OUT_ENTRY(pdwTSPIOptions)
END_PARAM_TABLE()
g_dwPermanentProviderID = dwPermanentProviderID;
g_dwLineDeviceIDBase = dwLineDeviceIDBase;
g_pfnCompletionProc = pfnCompletionProc;
*pdwTSPIOptions = LINETSPIOPTION_NONREENTRANT;
return EPILOG(0);
}
LONG TSPIAPI TSPI_providerShutdown(
DWORD dwTSPIVersion,
DWORD dwPermanentProviderID)
{
BEGIN_PARAM_TABLE("TSPI_providerShutdown")
DWORD_IN_ENTRY(dwTSPIVersion)
DWORD_IN_ENTRY(dwPermanentProviderID)
END_PARAM_TABLE()
return EPILOG(0);
}
LONG TSPIAPI TSPI_providerConfig(
HWND hwndOwner,
DWORD dwPermanentProviderID)
{
// Although this func is never called by TAPI v2.0, we export
// it so that the Telephony Control Panel Applet knows that it
// can configure this provider via lineConfigProvider(),
// otherwise Telephon.cpl will not consider it configurable
BEGIN_PARAM_TABLE("TSPI_providerConfig")
DWORD_IN_ENTRY(hwndOwner)
DWORD_IN_ENTRY(dwPermanentProviderID)
END_PARAM_TABLE()
return EPILOG(0);
}
LONG TSPIAPI TSPI_providerGenericDialogData(
DWORD dwObjectID,
DWORD dwObjectType,
LPVOID pParams,
DWORD dwSize)
{
BEGIN_PARAM_TABLE("TSPI_providerGenericDialogData")
DWORD_IN_ENTRY(dwObjectID)
DWORD_IN_ENTRY(dwObjectType)
DWORD_IN_ENTRY(pParams)
DWORD_IN_ENTRY(dwSize)
END_PARAM_TABLE()
if( dwObjectType == TUISPIDLL_OBJECT_DIALOGINSTANCE )
{
// Handle requests from the UI for dialog-related data
TSPUIDATA* pData = (TSPUIDATA*)pParams;
if( pData->dwRequestID )
{
// Complete asynch operation
g_pfnCompletionProc(pData->dwRequestID, pData->tr);
}
// Update call state
if( pData->tr == 0 )
{
pData->pCall->SetCallState(pData->nCallState);
}
}
return EPILOG(0);
}
LONG TSPIAPI TSPI_providerFreeDialogInstance(
HDRVDIALOGINSTANCE hdDlgInst)
{
BEGIN_PARAM_TABLE("TSPI_providerFreeDialogInstance")
DWORD_IN_ENTRY(hdDlgInst)
END_PARAM_TABLE()
// W/o this function, TAPISVR.EXE crashes
return EPILOG(0);
}
LONG TSPIAPI TSPI_providerInstall(
HWND hwndOwner,
DWORD dwPermanentProviderID)
{
// Although this func is never called by TAPI v2.0, we export
// it so that the Telephony Control Panel Applet knows that it
// can add this provider via lineAddProvider(), otherwise
// Telephon.cpl will not consider it installable
BEGIN_PARAM_TABLE("TSPI_providerInstall")
DWORD_IN_ENTRY(hwndOwner)
DWORD_IN_ENTRY(dwPermanentProviderID)
END_PARAM_TABLE()
return EPILOG(0);
}
LONG TSPIAPI TSPI_providerRemove(
HWND hwndOwner,
DWORD dwPermanentProviderID)
{
// Although this func is never called by TAPI v2.0, we export
// it so that the Telephony Control Panel Applet knows that it
// can remove this provider via lineRemoveProvider(), otherwise
// Telephon.cpl will not consider it removable
BEGIN_PARAM_TABLE("TSPI_providerRemove")
DWORD_IN_ENTRY(hwndOwner)
DWORD_IN_ENTRY(dwPermanentProviderID)
END_PARAM_TABLE()
return EPILOG(0);
}
LONG TSPIAPI TSPI_providerUIIdentify(
LPWSTR pszUIDLLName)
{
BEGIN_PARAM_TABLE("TSPI_providerUIIdentify")
STRING_OUT_ENTRY(pszUIDLLName)
END_PARAM_TABLE()
// Use the same DLL for both non-UI and UI functions
char szFileName[MAX_PATH+1];
GetModuleFileNameA(g_hinst, szFileName, MAX_PATH);
mbstowcs(pszUIDLLName, szFileName, strlen(szFileName) + 1);
return EPILOG(0);
}
// TSPI_lineXxx functions /////////////////////////////////////////////
#define MIN(a, b) (a < b ? a : b)
LONG TSPIAPI TSPI_lineNegotiateTSPIVersion(
DWORD dwDeviceID,
DWORD dwLowVersion,
DWORD dwHighVersion,
LPDWORD pdwTSPIVersion)
{
BEGIN_PARAM_TABLE("TSPI_lineNegotiateTSPIVersion")
DWORD_IN_ENTRY(dwDeviceID)
DWORD_IN_ENTRY(dwLowVersion)
DWORD_IN_ENTRY(dwHighVersion)
DWORD_OUT_ENTRY(pdwTSPIVersion)
END_PARAM_TABLE()
LONG tr = 0;
if( dwLowVersion <= TAPI_CURRENT_VERSION )
{
*pdwTSPIVersion = MIN(TAPI_CURRENT_VERSION, dwHighVersion);
}
else
{
tr = LINEERR_INCOMPATIBLEAPIVERSION;
}
return EPILOG(tr);
}
LONG TSPIAPI TSPI_lineGetDevCaps(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPLINEDEVCAPS pldc)
{
BEGIN_PARAM_TABLE("TSPI_lineGetDevCaps")
DWORD_IN_ENTRY(dwDeviceID)
DWORD_IN_ENTRY(dwTSPIVersion)
DWORD_IN_ENTRY(dwExtVersion)
DWORD_IN_ENTRY(pldc)
END_PARAM_TABLE()
LONG tr = 0;
const wchar_t szProviderInfo[] = L"WAVE Service Provider";
const wchar_t szLineName[] = L"WaveLine";
pldc->dwNeededSize = sizeof(LINEDEVCAPS) +
sizeof(szProviderInfo) +
sizeof(szLineName);
if( pldc->dwNeededSize <= pldc->dwTotalSize )
{
pldc->dwUsedSize = pldc->dwNeededSize;
pldc->dwProviderInfoSize = sizeof(szProviderInfo);
pldc->dwProviderInfoOffset = sizeof(LINEDEVCAPS) + 0;
wchar_t* pszProviderInfo = (wchar_t*)((BYTE*)pldc + pldc->dwProviderInfoOffset);
wcscpy(pszProviderInfo, szProviderInfo);
pldc->dwLineNameSize = sizeof(szLineName);
pldc->dwLineNameOffset = sizeof(LINEDEVCAPS) + sizeof(szProviderInfo);
wchar_t* pszLineName = (wchar_t*)((BYTE*)pldc + pldc->dwLineNameOffset);
wcscpy(pszLineName, szLineName);
}
else
{
pldc->dwUsedSize = sizeof(LINEDEVCAPS);
}
pldc->dwStringFormat = STRINGFORMAT_ASCII;
// Microsoft recommended algorithm for
// calculating the permanent line ID
#define MAKEPERMLINEID(dwPermProviderID, dwDeviceID) \
((LOWORD(dwPermProviderID) << 16) | dwDeviceID)
pldc->dwPermanentLineID = MAKEPERMLINEID(g_dwPermanentProviderID, dwDeviceID - g_dwLineDeviceIDBase);
pldc->dwAddressModes = LINEADDRESSMODE_ADDRESSID;
pldc->dwNumAddresses = 1;
pldc->dwBearerModes = LINEBEARERMODE_VOICE;
pldc->dwMediaModes = LINEMEDIAMODE_INTERACTIVEVOICE;
pldc->dwGenerateDigitModes= LINEDIGITMODE_DTMF;
pldc->dwDevCapFlags = LINEDEVCAPFLAGS_CLOSEDROP;
pldc->dwMaxNumActiveCalls = 1;
pldc->dwLineFeatures = LINEFEATURE_MAKECALL;
// DialParams
pldc->MinDialParams = g_dpMin;
pldc->MaxDialParams = g_dpMax;
pldc->DefaultDialParams = g_dpDef;
return EPILOG(tr);
}
LONG TSPIAPI TSPI_lineGetAddressCaps(
DWORD dwDeviceID,
DWORD dwAddressID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPLINEADDRESSCAPS pac)
{
BEGIN_PARAM_TABLE("TSPI_lineGetAddressCaps")
DWORD_IN_ENTRY(dwDeviceID)
DWORD_IN_ENTRY(dwAddressID)
DWORD_IN_ENTRY(dwTSPIVersion)
DWORD_IN_ENTRY(dwExtVersion)
END_PARAM_TABLE()
if( dwAddressID != 0 ) return EPILOG(LINEERR_INVALADDRESSID);
pac->dwNeededSize = sizeof(LINEADDRESSCAPS);
pac->dwUsedSize = sizeof(LINEADDRESSCAPS);
pac->dwLineDeviceID = dwDeviceID;
pac->dwAddressSharing = LINEADDRESSSHARING_PRIVATE;
pac->dwCallInfoStates = LINECALLINFOSTATE_MEDIAMODE |
LINECALLINFOSTATE_APPSPECIFIC;
pac->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
pac->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
pac->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
pac->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
pac->dwCallStates = LINECALLSTATE_IDLE |
LINECALLSTATE_DIALING |
LINECALLSTATE_CONNECTED;
pac->dwDialToneModes = LINEDIALTONEMODE_UNAVAIL;
pac->dwBusyModes = LINEBUSYMODE_UNAVAIL;
pac->dwSpecialInfo = LINESPECIALINFO_UNAVAIL;
pac->dwDisconnectModes = LINEDISCONNECTMODE_UNAVAIL;
pac->dwMaxNumActiveCalls = 1;
pac->dwAddrCapFlags = LINEADDRCAPFLAGS_DIALED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -