📄 tapicode.c
字号:
//
// FUNCTION: DoLineClose(..)
//
// PURPOSE: Handle LINE_CLOSE asynchronous messages.
//
// PARAMETERS:
// dwDevice - Line Handle that was closed.
// dwMsg - Should always be LINE_CLOSE.
// dwCallbackInstance - Unused by this sample.
// dwParam1 - Unused.
// dwParam2 - Unused.
// dwParam3 - Unused.
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
// This message is sent when something outside our app shuts
// down a line in use.
//
// The hLine (and any hCall on this line) are no longer valid.
//
//
void DoLineClose(
DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
// Line has been shut down. Clean up our internal variables.
g_hLine = (HLINE)((ULONG_PTR)NULL);
g_hCall = (HCALL)((ULONG_PTR)NULL);
UpdateStatusBar("Call was shut down.",1,0);
MessageBox(g_hDlgParentWindow,
"Call was shut down.","Warning",MB_OK);
HangupCall();
}
//
// FUNCTION: DoLineDevState(..)
//
// PURPOSE: Handle LINE_LINEDEVSTATE asynchronous messages.
//
// PARAMETERS:
// dwDevice - Line Handle that was closed.
// dwMsg - Should always be LINE_LINEDEVSTATE.
// dwCallbackInstance - Unused by this sample.
// dwParam1 - LINEDEVSTATE constant.
// dwParam2 - Depends on dwParam1.
// dwParam3 - Depends on dwParam1.
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
// The LINE_LINEDEVSTATE message is received if the state of the line
// changes. Examples are RINGING, MAINTENANCE, MSGWAITON. Very few of
// these are relevant to this sample.
//
// Assuming that any LINEDEVSTATE that removes the line from use by TAPI
// will also send a LINE_CLOSE message.
//
//
void DoLineDevState(
DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
switch(dwParam1)
{
case LINEDEVSTATE_RINGING:
UpdateStatusBar("Line Ringing",1,0);
OutputDebugString("Line Ringing.\n");
break;
case LINEDEVSTATE_REINIT:
// This is an important case! Usually means that a service provider
// has changed in such a way that requires TAPI to REINIT.
// Note that there are both 'soft' REINITs and 'hard' REINITs.
// Soft REINITs don't actually require a full shutdown but is instead
// just an informational change that historically required a REINIT
// to force the application to deal with. TAPI API Version 1.3 apps
// will still need to do a full REINIT for both hard and soft REINITs.
switch(dwParam2)
{
// This is the hard REINIT. No reason given, just REINIT.
// TAPI is waiting for everyone to shutdown.
// Our response is to immediately shutdown any calls,
// shutdown our use of TAPI and notify the user.
case 0:
ShutdownTAPI();
WarningBox("Tapi line configuration has changed.");
break;
case LINE_CREATE:
OutputDebugString("Soft REINIT: LINE_CREATE.\n");
DoLineCreate(dwDevice, dwParam2, dwCallbackInstance,
dwParam3, 0, 0);
break;
case LINE_LINEDEVSTATE:
OutputDebugString("Soft REINIT: LINE_LINEDEVSTATE.\n");
DoLineDevState(dwDevice, dwParam2, dwCallbackInstance,
dwParam3, 0, 0);
break;
// There might be other reasons to send a soft reinit.
// No need to to shutdown for these.
default:
OutputDebugString("Ignoring soft REINIT\n");
break;
}
break;
case LINEDEVSTATE_OUTOFSERVICE:
WarningBox("Line selected is now Out of Service.");
HangupCall();
break;
case LINEDEVSTATE_DISCONNECTED:
WarningBox("Line selected is now disconnected.");
HangupCall();
break;
case LINEDEVSTATE_MAINTENANCE:
WarningBox("Line selected is now out for maintenance.");
HangupCall();
break;
case LINEDEVSTATE_TRANSLATECHANGE:
if (g_hDialog)
PostMessage(g_hDialog, WM_COMMAND, IDC_CONFIGURATIONCHANGED, 0);
break;
case LINEDEVSTATE_REMOVED:
OutputDebugString("A Line device has been removed;"
" no action taken.\n");
break;
default:
OutputDebugString("Unhandled LINEDEVSTATE message\n");
}
}
//
// FUNCTION: DoLineCreate(..)
//
// PURPOSE: Handle LINE_LINECREATE asynchronous messages.
//
// PARAMETERS:
// dwDevice - Unused.
// dwMsg - Should always be LINE_CREATE.
// dwCallbackInstance - Unused.
// dwParam1 - dwDeviceID of new Line created.
// dwParam2 - Unused.
// dwParam3 - Unused.
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
// This message is new for Windows 95. It is sent when a new line is
// added to the system. This allows us to handle new lines without having
// to REINIT. This allows for much more graceful Plug and Play.
//
// This sample just changes the number of devices available and can use
// it next time a call is made. It also tells the "Dial" dialog.
//
//
void DoLineCreate(
DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
// dwParam1 is the Device ID of the new line.
// Add one to get the number of total devices.
if (g_dwNumDevs <= dwParam1)
g_dwNumDevs = dwParam1+1;
if (g_hDialog)
PostMessage(g_hDialog, WM_COMMAND, IDC_LINECREATE, 0);
}
//
// FUNCTION: DoLineCallState(..)
//
// PURPOSE: Handle LINE_CALLSTATE asynchronous messages.
//
// PARAMETERS:
// dwDevice - Handle to Call who's state is changing.
// dwMsg - Should always be LINE_CALLSTATE.
// dwCallbackInstance - Unused by this sample.
// dwParam1 - LINECALLSTATE constant specifying state change.
// dwParam2 - Specific to dwParam1.
// dwParam3 - LINECALLPRIVILEGE change, if any.
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
// This message is received whenever a call changes state. Lots of
// things we do, ranging from notifying the user to closing the line
// to actually connecting to the target of our phone call.
//
// What we do is usually obvious based on the call state change.
//
void DoLineCallState(
DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
// Error if this CALLSTATE doesn't apply to our call in progress.
if ((HCALL) dwDevice != g_hCall)
{
OutputDebugPrintf("LINE_CALLSTATE: Unknown device ID '0x%lx'.",
dwDevice);
return;
}
// This sets the global g_dwCallState variable so if we are waiting
// for a specific call state change, we will know when it happens.
g_dwCallState = dwParam1;
g_bCallStateReceived = TRUE;
// dwParam3 contains changes to LINECALLPRIVILEGE, if there are any.
switch (dwParam3)
{
case 0:
break; // no change to call state
// close line if we are made monitor. Shouldn't happen!
case LINECALLPRIVILEGE_MONITOR:
OutputDebugString("line given monitor privilege; closing\n");
HangupCall();
return;
// close line if we are made owner. Shouldn't happen!
case LINECALLPRIVILEGE_OWNER:
OutputDebugString("line given owner privilege; closing\n");
HangupCall();
break;
default: // Shouldn't happen! All cases handled.
OutputDebugString("Unknown LINECALLPRIVILEGE message: closing\n");
HangupCall();
return;
}
// dwParam1 is the specific CALLSTATE change that is occurring.
switch (dwParam1)
{
case LINECALLSTATE_DIALTONE:
UpdateStatusBar("Dial Tone",1,0);
OutputDebugString("Dial Tone\n");
break;
case LINECALLSTATE_DIALING:
UpdateStatusBar("Dialing Call",1,0);
OutputDebugString("Dialing\n");
break;
case LINECALLSTATE_PROCEEDING:
UpdateStatusBar("Call is Proceeding",1,0);
OutputDebugString("Proceeding\n");
break;
case LINECALLSTATE_RINGBACK:
UpdateStatusBar("RingBack",1,0);
OutputDebugString("RingBack\n");
break;
case LINECALLSTATE_BUSY:
UpdateStatusBar("Line is busy",1,0);
OutputDebugString("Line busy, shutting down\n");
HangupCall();
break;
case LINECALLSTATE_IDLE:
UpdateStatusBar("Line is idle",1,0);
OutputDebugString("Line idle\n");
HangupCall();
break;
case LINECALLSTATE_SPECIALINFO:
UpdateStatusBar(
"Special Info, probably couldn't dial number",1,0);
OutputDebugString(
"Special Info, probably couldn't dial number\n");
HangupCall();
break;
case LINECALLSTATE_DISCONNECTED:
{
LPSTR pszReasonDisconnected;
switch (dwParam2)
{
case LINEDISCONNECTMODE_NORMAL:
pszReasonDisconnected = "Remote Party Disconnected";
break;
case LINEDISCONNECTMODE_UNKNOWN:
pszReasonDisconnected = "Disconnected: Unknown reason";
break;
case LINEDISCONNECTMODE_REJECT:
pszReasonDisconnected = "Remote Party rejected call";
break;
case LINEDISCONNECTMODE_PICKUP:
pszReasonDisconnected =
"Disconnected: Local phone picked up";
break;
case LINEDISCONNECTMODE_FORWARDED:
pszReasonDisconnected = "Disconnected: Forwarded";
break;
case LINEDISCONNECTMODE_BUSY:
pszReasonDisconnected = "Disconnected: Busy";
break;
case LINEDISCONNECTMODE_NOANSWER:
pszReasonDisconnected = "Disconnected: No Answer";
break;
case LINEDISCONNECTMODE_BADADDRESS:
pszReasonDisconnected = "Disconnected: Bad Address";
break;
case LINEDISCONNECTMODE_UNREACHABLE:
pszReasonDisconnected = "Disconnected: Unreachable";
break;
case LINEDISCONNECTMODE_CONGESTION:
pszReasonDisconnected = "Disconnected: Congestion";
break;
case LINEDISCONNECTMODE_INCOMPATIBLE:
pszReasonDisconnected = "Disconnected: Incompatible";
break;
case LINEDISCONNECTMODE_UNAVAIL:
pszReasonDisconnected = "Disconnected: Unavail";
break;
case LINEDISCONNECTMODE_NODIALTONE:
pszReasonDisconnected = "Disconnected: No Dial Tone";
break;
default:
pszReasonDisconnected =
"Disconnected: LINECALLSTATE; Bad Reason";
break;
}
UpdateStatusBar(pszReasonDisconnected,1,0);
OutputDebugString(pszReasonDisconnected);
OutputDebugString("\n");
HangupCall();
break;
}
case LINECALLSTATE_CONNECTED: // CONNECTED!!!
{
LPVARSTRING lpVarString = NULL;
DWORD dwSizeofVarString = sizeof(VARSTRING) + 1024;
HANDLE hCommFile = NULL;
long lReturn;
// Very first, make sure this isn't a duplicated message.
// A CALLSTATE message can be sent whenever there is a
// change to the capabilities of a line, meaning that it is
// possible to receive multiple CONNECTED messages per call.
// The CONNECTED CALLSTATE message is the only one in TapiComm
// where it would cause problems if it where sent more
// than once.
if (g_bConnected)
break;
g_bConnected = TRUE;
// Get the handle to the comm port from the driver so we can start
// communicating. This is returned in a LPVARSTRING structure.
do
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -