📄 win32_modem.cpp
字号:
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 Win32_Modem::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;
}
LPHCALL hCall;
do
{
if (bFirstDial)
lReturn = WaitForReply(
lineMakeCall(g_hLine, hCall, lpszDialableSubstring,
0, lpCallParams) );
else
lReturn = WaitForReply(
lineDial(*g_hCall, lpszDialableSubstring, 0) );
g_hCall = hCall;
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;
/* default:
char temp[30];
char temp2[50]="";
strcpy(temp2, "Returned from WaitForReply, hCall = ");
itoa((int )hCall,temp, 10);
strncat(temp2,temp, strlen(temp));
g_thCall=hCall;
OutputDebugString(temp2);
break;
*/
}
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)
LocalFree(lpDS);
if (lpCallParams)
LocalFree(lpCallParams);
if (lpAddressCaps)
LocalFree(lpAddressCaps);
return FALSE;
}
//
// FUNCTION: CreateCallParams(LPLINECALLPARAMS, LPCSTR)
//
// PURPOSE: Allocates and fills a LINECALLPARAMS structure
//
// PARAMETERS:
// lpCallParams -
// lpszDisplayableAddress -
//
// RETURN VALUE:
// Returns a LPLINECALLPARAMS ready to use for dialing DATAMODEM calls.
// Returns NULL if unable to allocate the structure.
//
// COMMENTS:
//
// If a non-NULL lpCallParams is passed in, it must have been allocated
// with LocalAlloc, and can potentially be freed and reallocated. It must
// also have the dwTotalSize field correctly set.
//
//
LPLINECALLPARAMS Win32_Modem::CreateCallParams (
LPLINECALLPARAMS lpCallParams, LPCSTR lpszDisplayableAddress)
{
size_t sizeDisplayableAddress;
if (lpszDisplayableAddress == NULL)
lpszDisplayableAddress = "";
sizeDisplayableAddress = strlen(lpszDisplayableAddress) + 1;
lpCallParams = (LPLINECALLPARAMS) CheckAndReAllocBuffer(
(LPVOID) lpCallParams,
sizeof(LINECALLPARAMS) + sizeDisplayableAddress,
"CreateCallParams: ");
if (lpCallParams == NULL)
return NULL;
// This is where we configure the line for DATAMODEM usage.
lpCallParams -> dwBearerMode = LINEBEARERMODE_VOICE;
lpCallParams -> dwMediaMode = LINEMEDIAMODE_DATAMODEM;
// This specifies that we want to use only IDLE calls and
// don't want to cut into a call that might not be IDLE (ie, in use).
lpCallParams -> dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
// if there are multiple addresses on line, use first anyway.
// It will take a more complex application than a simple tty app
// to use multiple addresses on a line anyway.
lpCallParams -> dwAddressMode = LINEADDRESSMODE_ADDRESSID;
lpCallParams -> dwAddressID = 0;
// Since we don't know where we originated, leave these blank.
lpCallParams -> dwOrigAddressSize = 0;
lpCallParams -> dwOrigAddressOffset = 0;
// Unimodem ignores these values.
(lpCallParams -> DialParams) . dwDialSpeed = 0;
(lpCallParams -> DialParams) . dwDigitDuration = 0;
(lpCallParams -> DialParams) . dwDialPause = 0;
(lpCallParams -> DialParams) . dwWaitForDialtone = 0;
// Address we are dialing.
lpCallParams -> dwDisplayableAddressOffset = sizeof(LINECALLPARAMS);
lpCallParams -> dwDisplayableAddressSize = sizeDisplayableAddress;
strcpy((LPSTR)lpCallParams + sizeof(LINECALLPARAMS),
lpszDisplayableAddress);
return lpCallParams;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -