📄 simpletapi.c
字号:
//
// MODULE: SimpleTAPI.c
//
// PURPOSE: Demonstrates basic TAPI programming model
//
#include <stdio.h>
#include <windows.h>
#include <winbase.h>
#define TAPI_CURRENT_VERSION 0x00020000
#include <tapi.h>
#include "TapiInfo.h"
HLINEAPP g_hLineApp;
// Buffers used for pretty printing stuff...
CHAR strAddress[512];
CHAR strText[512], strText2[512];
// Various flags...
BOOL g_bIncoming; // Waits for Incoming Calls
BOOL g_bTranslate; // Perform Address Translation
BOOL g_bTranslateDialog; // Display Translation Dialog
BOOL g_bForce; // Force specified device
BOOL g_bQuit; // Session terminating.
DWORD g_dwMediaMode; // MediaMode for calls.
BOOL g_bTerminate; // Flag to tell message thread to terminate
DWORD g_dwDevId; // TAPI device used.
// Handles and Messages
HANDLE g_hTAPIEvent; // Created by TAPI
HANDLE g_hEvReply; // Used for Asynch Reply
HLINE g_hLine; // Line handle
HCALL g_hCall; // Call handle
DWORD g_dwTAPIMsg; // TAPI Message
DWORD g_dwNumDevs; // Total number of TAPI devices
DWORD g_dwTAPIVer; // TAPI Version
HANDLE hEventThread; // TAPI Event monitoring thread.
// Stuff defined somewhere else
extern DWORD WINAPI CallProc(LPVOID lpThreadParam);
extern DWORD WINAPI zTapiEventThread (LPVOID lpThreadParam);
extern BOOL ParseCommandLine(int ac, char * av[]);
// Stuff defined here...
BOOL WINAPI zControlHandlerRoutine (DWORD dwCtrlType);
DWORD SelectLine(HLINEAPP hLineApp, DWORD dwTAPIVersion, DWORD dwNumDevs, DWORD dwMediaMode);
void EndSession();
int main (int argc, char * argv[])
{
LINEINITIALIZEEXPARAMS lineInitializeExParams;
LONG lRes;
LINETRANSLATEOUTPUT *lpTranslateOutput;
g_dwTAPIVer = 0x00020000;
g_bIncoming = FALSE;
g_hCall = NULL;
g_bQuit = FALSE;
ParseCommandLine(argc, argv);
SetConsoleCtrlHandler(zControlHandlerRoutine, TRUE);
g_hEvReply = CreateEvent(NULL, FALSE, FALSE, NULL);
// Clear the structure before using...
memset(&lineInitializeExParams, 0, sizeof(LINEINITIALIZEEXPARAMS));
// Populate the options...
lineInitializeExParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
lineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
// Initialize TAPI.
lRes = lineInitializeEx(&g_hLineApp, NULL, NULL,
"CallTest", &g_dwNumDevs, &g_dwTAPIVer, &lineInitializeExParams);
if(lRes != 0) //Oops!
{
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineInitializeEx.\r\n", strText);
CloseHandle(g_hEvReply);
return -1;
}
// Got the event handle...
g_hTAPIEvent = lineInitializeExParams.Handles.hEvent;
// Start event monitoring...
hEventThread = CreateThread(NULL, 0, zTapiEventThread, NULL, 0, 0);
if(hEventThread == NULL) // Bummer...
{
printf("Win32 Error %d on CreateThread (event thread).\r\n", GetLastError());
g_bTerminate = TRUE;
WaitForSingleObject(hEventThread, INFINITE);
CloseHandle(hEventThread);
CloseHandle(g_hEvReply);
lineShutdown(g_hLineApp);
return -1;
}
if(! g_bForce) // Select the device that supports specified media modes.
g_dwDevId = SelectLine(g_hLineApp, g_dwTAPIVer, g_dwNumDevs, g_dwMediaMode);
if(g_dwDevId == 0xffffffff)
{
printf("No suitable line found.\r\n");
g_bTerminate = TRUE;
WaitForSingleObject(hEventThread, INFINITE);
CloseHandle(hEventThread);
CloseHandle(g_hEvReply);
lineShutdown(g_hLineApp);
ExitProcess(0);
}
// Open the line...
lRes = lineOpen(g_hLineApp, g_dwDevId, &g_hLine, 0x00020000, 0x00000000, 1,
LINECALLPRIVILEGE_OWNER, g_dwMediaMode, NULL);
if(lRes != 0)
{ // Doh!
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineOpen.\r\n", strText);
g_bTerminate = TRUE;
WaitForSingleObject(hEventThread, INFINITE);
CloseHandle(hEventThread);
CloseHandle(g_hEvReply);
return -1;
}
// We want to be notified for everything
lRes = lineSetStatusMessages(g_hLine, 0x1ffffff, 0);
if(lRes != 0)
{
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineOpen.\r\n", strText);
}
if(g_bIncoming)
{
printf("Waiting for incoming call.\r\n");
while (1)
{
// Now we wait for notification...
WaitForSingleObject(g_hEvReply, INFINITE);
if(g_dwTAPIMsg == LINECALLSTATE_OFFERING)
{
printf("Answering.\r\n");
lRes = lineAnswer(g_hCall, NULL, 0);
if(lRes != 0)
{ // Doh!
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineMakeCall.\r\n", strText);
EndSession();
}
break;
}
}
}
else
{
if(g_bTranslateDialog)
{
lRes = lineTranslateDialog(g_hLineApp, g_dwDevId, g_dwTAPIVer, NULL, strAddress);
if(lRes != 0)
{
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineTranslateDialog.\r\n", strText);
}
}
if(g_bTranslate)
{
printf("Performing translation\r\nSource: %s\r\n", strAddress);
lpTranslateOutput = (LINETRANSLATEOUTPUT *)malloc(sizeof(LINETRANSLATEOUTPUT)+1000);
lpTranslateOutput->dwTotalSize = sizeof(LINETRANSLATEOUTPUT)+1000;
while (1)
{
lRes = lineTranslateAddress(g_hLineApp, g_dwDevId, g_dwTAPIVer, strAddress, 0, 0, lpTranslateOutput);
if(lRes != 0)
{
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineTranslateAddress.\r\n", strText);
}
if(lpTranslateOutput->dwTotalSize < lpTranslateOutput->dwNeededSize)
lpTranslateOutput = (LINETRANSLATEOUTPUT *)realloc(lpTranslateOutput, lpTranslateOutput->dwNeededSize);
else break;
}
strcpy(strAddress, (LPSTR)((DWORD)lpTranslateOutput+(DWORD)lpTranslateOutput->dwDialableStringOffset));
printf("Results: %s\r\n",(LPSTR)((DWORD)lpTranslateOutput+(DWORD)lpTranslateOutput->dwDisplayableStringOffset));
}
printf("Calling %s\r\n", strAddress);
lRes = lineMakeCall(g_hLine, &g_hCall, strAddress, 0, NULL);
if(lRes != 0)
{ // Doh!
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineMakeCall.\r\n", strText);
}
}
// All done. Wait for the event thread to finish.
WaitForSingleObject(hEventThread, INFINITE);
CloseHandle(hEventThread);
if(!g_bQuit)
{
EndSession();
}
}
BOOL WINAPI zControlHandlerRoutine (DWORD dwCtrlType)
{
// Got an control handler event
switch (dwCtrlType)
{
case CTRL_C_EVENT: // Handle any event that will cause
case CTRL_BREAK_EVENT: // a termination of our program
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
{
g_bQuit = TRUE;
EndSession();
break;
}
default:
break;
}
return(FALSE);
} // End of zControlHandlerRoutine
// SelectLine function returns the ID of last line device that supports requested MediaMode
// If not found, It will return 0xFFFFFFFF
DWORD SelectLine(
HLINEAPP hLineApp, // Valid LineApp Handle
DWORD dwTAPIVersion, // TAPI Version to be used.
DWORD dwNumDevs, // Number of line devices
DWORD dwMediaMode) // MediaMode to look for.
{
DWORD dwResult = 0xFFFFFFFF;
DWORD dwAPIVersion;
LINEEXTENSIONID ExtentionId;
LINEDEVCAPS *lpDevCaps;
DWORD i;
LONG lRes;
BOOL bDone;
for(i = 0 ; i < dwNumDevs ; i++)
{
lRes = lineNegotiateAPIVersion(hLineApp, i, dwTAPIVersion, dwTAPIVersion,
&dwAPIVersion, &ExtentionId);
if(lRes != 0) //Oops!
{
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineNegotiateAPIVersion.\r\n", strText);
}
else
{
lpDevCaps = (LINEDEVCAPS *)malloc(sizeof(LINEDEVCAPS)+1000); // Allocate a little extra memory...
if(lpDevCaps == NULL) return dwResult; // No luck allocating memory...
memset(lpDevCaps, 0, sizeof(LINEDEVCAPS)+1000);
lpDevCaps->dwTotalSize = sizeof(LINEDEVCAPS)+1000;
bDone = FALSE;
do // Go around and keep trying until there's enough memory
{
lRes = lineGetDevCaps(hLineApp, i, dwAPIVersion, 0, lpDevCaps);
if(lRes != 0) //Oops!
{
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineGetDevCaps.\r\n", strText);
free(lpDevCaps);
break;
}
if(lpDevCaps->dwNeededSize > lpDevCaps->dwTotalSize)
// Reallocate for dwNeededSize
lpDevCaps = (LINEDEVCAPS *)realloc(lpDevCaps, lpDevCaps->dwNeededSize);
else bDone = TRUE;
}
while (!bDone);
printf("Line %d is %s.\r\n", i, (LPBYTE)((DWORD)lpDevCaps+(DWORD)lpDevCaps->dwLineNameOffset));
if(lpDevCaps->dwMediaModes & dwMediaMode)
{
dwResult = i;
printf("Line device %d selected.\r\n", i);
}
else printf("Line device %d rejected.\r\n", i);
free(lpDevCaps);
}
}
return dwResult;
}
void EndSession()
{
LINECALLSTATUS CallStatus;
LONG lRes;
if(g_hCall != NULL) // Call might be in progress...
{
memset(&CallStatus, 0, sizeof(LINECALLSTATUS));
lRes = lineGetCallStatus(g_hCall, &CallStatus);
// Technically, lineGetCallStatus returns more info than
// there is in the structure. Since we don't care about it,
// We just go on our merry way...
if(lRes == 0) // If it didn't fail, there's at least a call that needs
// to be droped.
{
printf("Call is still in progress. Droping it.\r\n");
lineDrop(g_hCall, NULL, 0);
}
}
printf("Closing line. (Ctrl Handler)\r\n");
lRes = lineClose(g_hLine);
if(lRes != 0)
{
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineClose.\r\n", strText);
}
g_bTerminate = TRUE; // Tell the event thread that it's time to go...
WaitForSingleObject(hEventThread, INFINITE); // Wait for it to comit suicide..
CloseHandle(hEventThread);
printf("Shutting down TAPI.\r\n");
lRes = lineShutdown(g_hLineApp);
if(lRes != 0)
{
FormatLineError(lRes, strText);
printf("TAPI Error: %s on lineShutdown.\r\n", strText);
}
ExitProcess(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -