?? tapicode.c
字號:
if (!(lpLineDevCaps->dwLineFeatures & LINEFEATURE_MAKECALL))
{
HangupCall();
MessageBox(g_hDlgParentWindow,
"Error on Requested line",
"The selected line doesn't support MAKECALL capabilities",
MB_OK);
goto DeleteBuffers;
}
// Open the Line for an outgoing DATAMODEM call.
do
{
lReturn = lineOpen(g_hLineApp, g_dwDeviceID, &g_hLine,
g_dwAPIVersion, 0, 0,
LINECALLPRIVILEGE_NONE, LINEMEDIAMODE_DATAMODEM,
0);
if(lReturn == LINEERR_ALLOCATED)
{
HangupCall();
MessageBox(g_hDlgParentWindow,
"Line is already in use by a non-TAPI application "
"or by another TAPI Service Provider.",
"Unable to Use Line",MB_OK);
goto DeleteBuffers;
}
if (HandleLineErr(lReturn))
continue;
else
{
OutputDebugLineError(lReturn, "lineOpen unhandled error: ");
MessageBox(g_hDlgParentWindow,
"Error on Requested line",
"Unable to Use Line",MB_OK);
HangupCall();
goto DeleteBuffers;
}
}
while(lReturn != SUCCESS);
// Tell the service provider that we want all notifications that
// have anything to do with this line.
do
{
// Set the messages we are interested in.
// Note that while most applications aren't really interested
// in dealing with all of the possible messages, its interesting
// to see which come through the callback for testing purposes.
lReturn = lineSetStatusMessages(g_hLine,
LINEDEVSTATE_OTHER |
LINEDEVSTATE_RINGING |
LINEDEVSTATE_CONNECTED | // Important state!
LINEDEVSTATE_DISCONNECTED | // Important state!
LINEDEVSTATE_MSGWAITON |
LINEDEVSTATE_MSGWAITOFF |
LINEDEVSTATE_INSERVICE |
LINEDEVSTATE_OUTOFSERVICE | // Important state!
LINEDEVSTATE_MAINTENANCE | // Important state!
LINEDEVSTATE_OPEN |
LINEDEVSTATE_CLOSE |
LINEDEVSTATE_NUMCALLS |
LINEDEVSTATE_NUMCOMPLETIONS |
LINEDEVSTATE_TERMINALS |
LINEDEVSTATE_ROAMMODE |
LINEDEVSTATE_BATTERY |
LINEDEVSTATE_SIGNAL |
LINEDEVSTATE_DEVSPECIFIC |
LINEDEVSTATE_REINIT | // Not allowed to disable this.
LINEDEVSTATE_LOCK |
LINEDEVSTATE_CAPSCHANGE |
LINEDEVSTATE_CONFIGCHANGE |
LINEDEVSTATE_COMPLCANCEL ,
LINEADDRESSSTATE_OTHER |
LINEADDRESSSTATE_DEVSPECIFIC|
LINEADDRESSSTATE_INUSEZERO |
LINEADDRESSSTATE_INUSEONE |
LINEADDRESSSTATE_INUSEMANY |
LINEADDRESSSTATE_NUMCALLS |
LINEADDRESSSTATE_FORWARD |
LINEADDRESSSTATE_TERMINALS |
LINEADDRESSSTATE_CAPSCHANGE);
if (HandleLineErr(lReturn))
continue;
else
{
// If we do get an unhandled problem, we don't care.
// We just won't get notifications.
OutputDebugLineError(lReturn,
"lineSetStatusMessages unhandled error: ");
break;
}
}
while(lReturn != SUCCESS);
// Get LineAddressStatus so we can make sure the line
// isn't already in use by a TAPI application.
lpLineAddressStatus =
I_lineGetAddressStatus(lpLineAddressStatus, g_hLine, 0);
if (lpLineAddressStatus == NULL)
{
HangupCall();
MessageBox(g_hDlgParentWindow,
"Error on Requested line",
"Unable to Use Line",MB_OK);
goto DeleteBuffers;
}
// MAKECALL will be set if there are any available call appearances
if ( ! ((lpLineAddressStatus -> dwAddressFeatures) &
LINEADDRFEATURE_MAKECALL) )
{
OutputDebugString("This line is not available to place a call.\n");
HangupCall();
MessageBox(g_hDlgParentWindow,
"Requested line is already in use",
"Unable to Use Line",MB_OK);
goto DeleteBuffers;
}
// If the line was configured in the 'Dial' dialog, then
// we need to actually complete the configuration.
if (g_lpDeviceConfig)
lineSetDevConfig(g_dwDeviceID, g_lpDeviceConfig,
g_dwSizeDeviceConfig, "comm/datamodem");
// Start dialing the number
if (DialCallInParts(lpLineDevCaps, g_szDialableAddress,
g_szDisplayableAddress))
{
OutputDebugString("DialCallInParts succeeded.\n");
}
else
{
OutputDebugString("DialCallInParts failed.\n");
HangupCall();
goto DeleteBuffers;
}
DeleteBuffers:
if (lpLineAddressStatus)
LocalFree(lpLineAddressStatus);
if (lpLineDevCaps)
LocalFree(lpLineDevCaps);
if (g_bTapiInUse)
EnableHangupCall(g_hWndMainWindow, TRUE);
return g_bTapiInUse;
}
//**************************************************
// These APIs are specific to this module
//**************************************************
//
// FUNCTION: DialCallInParts(LPLINEDEVCAPS, LPCSTR, LPCSTR)
//
// PURPOSE: Dials the call, handling special characters.
//
// PARAMETERS:
// lpLineDevCaps - LINEDEVCAPS for the line to be used.
// lpszAddress - Address to Dial.
// lpszDisplayableAddress - Displayable Address.
//
// RETURN VALUE:
// Returns TRUE if we successfully Dial.
//
// COMMENTS:
//
// This function dials the Address and handles any
// special characters in the address that the service provider
// can't handle. It requires input from the user to handle
// these characters; this can cause problems for fully automated
// dialing.
//
// Note that we can return TRUE, even if we don't reach a
// CONNECTED state. DIalCallInParts returns as soon as the
// Address is fully dialed or when an error occurs.
//
//
BOOL DialCallInParts(LPLINEDEVCAPS lpLineDevCaps,
LPCSTR lpszAddress, LPCSTR lpszDisplayableAddress)
{
LPLINECALLPARAMS lpCallParams = NULL;
LPLINEADDRESSCAPS lpAddressCaps = NULL;
LPLINECALLSTATUS lpLineCallStatus = NULL;
long lReturn;
int i;
DWORD dwDevCapFlags;
char szFilter[1+sizeof(g_sNonDialable)] = "";
BOOL bFirstDial = TRUE;
// Variables to handle Dialable Substring dialing.
LPSTR lpDS; // This is just so we can free lpszDialableSubstring later.
LPSTR lpszDialableSubstring;
int nAddressLength = 0;
int nCurrentAddress = 0;
char chUnhandledCharacter;
// Get the capabilities for the line device we're going to use.
lpAddressCaps = I_lineGetAddressCaps(lpAddressCaps,
g_dwDeviceID, 0, g_dwAPIVersion, 0);
if (lpAddressCaps == NULL)
return FALSE;
// Setup our CallParams for DATAMODEM settings.
lpCallParams = CreateCallParams (lpCallParams, lpszDisplayableAddress);
if (lpCallParams == NULL)
return FALSE;
// Determine which special characters the service provider
// does *not* handle so we can handle them manually.
// Keep list of unhandled characters in szFilter.
dwDevCapFlags = lpLineDevCaps -> dwDevCapFlags; // SP handled characters.
for (i = 0; i < g_sizeofNonDialable ; i++)
{
if ((dwDevCapFlags & g_sNonDialable[i].dwDevCapFlag) == 0)
{
strcat(szFilter, g_sNonDialable[i].szToken);
}
}
// szFilter now contains the set of tokens which delimit dialable substrings
// Setup the strings for substring dialing.
nAddressLength = strlen(lpszAddress);
lpDS = lpszDialableSubstring = (LPSTR) LocalAlloc(LPTR, nAddressLength + 1);
if (lpszDialableSubstring == NULL)
{
OutputDebugLastError(GetLastError(), "LocalAlloc failed: ");
HandleNoMem();
goto errExit;
}
// Lets start dialing substrings!
while (nCurrentAddress < nAddressLength)
{
retryAfterError:
// Find the next undialable character
i = strcspn(&lpszAddress[nCurrentAddress], szFilter);
// Was there one before the end of the Address string?
if (i + nCurrentAddress < nAddressLength)
{
// Make sure this device can handle partial dial.
if (! (lpAddressCaps -> dwAddrCapFlags &
LINEADDRCAPFLAGS_PARTIALDIAL))
{
MessageBox(g_hDlgParentWindow,
"This line doesn't support partial dialing.\n",
"Warning",MB_OK);
goto errExit;
}
// Remember what the unhandled character is so we can handle it.
chUnhandledCharacter = lpszAddress[nCurrentAddress+i];
// Copy the dialable string to the Substring.
memcpy(lpszDialableSubstring, &lpszAddress[nCurrentAddress], i);
// Terminate the substring with a ';' to signify the partial dial.
lpszDialableSubstring[i] = ';';
lpszDialableSubstring[i+1] = '\0';
// Increment the address for next iteration.
nCurrentAddress += i + 1;
}
else // No more partial dials. Dial the rest of the Address.
{
lpszDialableSubstring = (LPSTR) &lpszAddress[nCurrentAddress];
chUnhandledCharacter = 0;
nCurrentAddress = nAddressLength;
}
do
{
if (bFirstDial)
lReturn = WaitForReply(
lineMakeCall(g_hLine, &g_hCall, lpszDialableSubstring,
0, lpCallParams) );
else
lReturn = WaitForReply(
lineDial(g_hCall, lpszDialableSubstring, 0) );
switch(lReturn)
{
// We should not have received these errors because of the
// prefiltering strategy, but there may be some ill-behaved
// service providers which do not correctly set their
// devcapflags. Add the character corresponding to the error
// to the filter set and retry dialing.
//
case LINEERR_DIALBILLING:
case LINEERR_DIALDIALTONE:
case LINEERR_DIALQUIET:
case LINEERR_DIALPROMPT:
{
OutputDebugString("Service Provider incorrectly sets dwDevCapFlags\n");
for (i = 0; i < g_sizeofNonDialable; i++)
if (lReturn == g_sNonDialable[i].lError)
{
strcat(szFilter, g_sNonDialable[i].szToken);
}
goto retryAfterError;
}
case WAITERR_WAITABORTED:
OutputDebugString("While Dialing, WaitForReply aborted.\n");
goto errExit;
}
if (HandleLineErr(lReturn))
continue;
else
{
if (bFirstDial)
OutputDebugLineError(lReturn, "lineMakeCall unhandled error: ");
else
OutputDebugLineError(lReturn, "lineDial unhandled error: ");
goto errExit;
}
}
while (lReturn != SUCCESS);
bFirstDial = FALSE;
// The dial was successful; now handle characters the service
// provider didn't (if any).
if (chUnhandledCharacter)
{
LPSTR lpMsg = "";
// First, wait until we know we can continue dialing. While the
// last string is still pending to be dialed, we can't dial another.
while(TRUE)
{
lpLineCallStatus = I_lineGetCallStatus(lpLineCallStatus, g_hCall);
if (lpLineCallStatus == NULL)
goto errExit;
// Does CallStatus say we can dial now?
if ((lpLineCallStatus->dwCallFeatures) & LINECALLFEATURE_DIAL)
{
OutputDebugString("Ok to continue dialing.\n");
break;
}
// We can't dial yet, so wait for a CALLSTATE message
OutputDebugString("Waiting for dialing to be enabled.\n");
if (WaitForCallState(I_LINECALLSTATE_ANY) != SUCCESS)
goto errExit;
}
for (i = 0; i < g_sizeofNonDialable; i++)
if (chUnhandledCharacter == g_sNonDialable[i].szToken[0])
lpMsg = g_sNonDialable[i].szMsg;
MessageBox(g_hDlgParentWindow, lpMsg, "Dialing Paused", MB_OK);
}
} // continue dialing until we dial all Dialable Substrings.
LocalFree(lpCallParams);
LocalFree(lpDS);
LocalFree(lpAddressCaps);
if (lpLineCallStatus)
LocalFree(lpLineCallStatus);
return TRUE;
errExit:
// if lineMakeCall has already been successfully called, there's a call in progress.
// let the invoking routine shut down the call.
// if the invoker did not clean up the call, it should be done here.
if (lpLineCallStatus)
LocalFree(lpLineCallStatus);
if (lpDS)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -