📄 tapiconn._cp
字号:
//
LPLINEDEVCAPS CTapiConnection::GetDeviceLine(DWORD* pdwAPIVersion, LPLINEDEVCAPS lpLineDevCaps)
{
LPCTSTR szLineUnavail = _T("Line Unavailable");
LPCTSTR szLineUnnamed = _T("Line Unnamed");
LPCTSTR szLineNameEmpty = _T("Line Name is Empty");
LPCTSTR lpszLineName;
LINEEXTENSIONID lineExtID;
long lReturn;
BOOL bDone = FALSE;
for (DWORD dwDeviceID = 0; (dwDeviceID < m_dwNumDevs) && !bDone; ++ dwDeviceID)
{
*pdwAPIVersion = I_lineNegotiateLegacyAPIVersion(dwDeviceID);
if (*pdwAPIVersion)
{
lpLineDevCaps = I_lineGetDevCaps(lpLineDevCaps, dwDeviceID, *pdwAPIVersion);
if ((lpLineDevCaps->dwLineNameSize) &&
(lpLineDevCaps->dwLineNameOffset) &&
(lpLineDevCaps->dwStringFormat == STRINGFORMAT_ASCII))
{
// This is the name of the device.
lpszLineName = ((char*)lpLineDevCaps) +
lpLineDevCaps->dwLineNameOffset;
TRACE1("Name of device is: %s\n", lpszLineName);
}
else // DevCaps doesn't have a valid line name. Unnamed.
lpszLineName = szLineUnnamed;
}
else // Couldn't NegotiateAPIVersion. Line is unavail.
lpszLineName = szLineUnavail;
// If this line is usable and we don't have a default initial
// line yet, make this the initial line.
if ((lpszLineName != szLineUnavail) && (lReturn == TAPISUCCESS))
{
m_dwDeviceID = dwDeviceID;
bDone = TRUE;
}
else
m_dwDeviceID = MAXDWORD;
}
return lpLineDevCaps;
}
//
// FUNCTION: I_lineGetDevCaps(LPLINEDEVCAPS, DWORD , DWORD)
//
// PURPOSE: Gets a LINEDEVCAPS structure for the specified line.
//
// COMMENTS:
//
// This function is a wrapper around lineGetDevCaps to make it easy
// to handle the variable sized structure and any errors received.
//
// The returned structure has been allocated with LocalAlloc,
// so LocalFree has to be called on it when you're finished with it,
// or there will be a memory leak.
//
// Similarly, if a lpLineDevCaps structure is passed in, it *must*
// have been allocated with LocalAlloc and it could potentially be
// LocalFree()d.
//
// If lpLineDevCaps == NULL, then a new structure is allocated. It is
// normal to pass in NULL for this parameter unless you want to use a
// I_lineGetDevCaps that has been returned by a previous MylineGetDevCaps
// call.
//
//
LPLINEDEVCAPS CTapiConnection::I_lineGetDevCaps(
LPLINEDEVCAPS lpLineDevCaps,
DWORD dwDeviceID, DWORD dwAPIVersion)
{
// Allocate enough space for the structure plus 1024.
size_t sizeofLineDevCaps = sizeof(LINEDEVCAPS) + 1024;
long lReturn;
// Continue this loop until the structure is big enough.
while (TRUE)
{
// Make sure the buffer exists, is valid and big enough.
lpLineDevCaps =
(LPLINEDEVCAPS)CheckAndReAllocBuffer(
(LPVOID)lpLineDevCaps, // Pointer to existing buffer, if any
sizeofLineDevCaps); // Minimum size the buffer should be
if (lpLineDevCaps == NULL)
return NULL;
// Make the call to fill the structure.
do
{
lReturn =
::lineGetDevCaps(m_hLineApp,
dwDeviceID, dwAPIVersion, 0, lpLineDevCaps);
if (HandleLineErr(lReturn))
continue;
else
{
TRACE0("lineGetDevCaps unhandled error/n");
::LocalFree(lpLineDevCaps);
return NULL;
}
}
while (lReturn != TAPISUCCESS);
// If the buffer was big enough, then succeed.
if ((lpLineDevCaps->dwNeededSize) <= (lpLineDevCaps->dwTotalSize))
return lpLineDevCaps;
// Buffer wasn't big enough. Make it bigger and try again.
sizeofLineDevCaps = lpLineDevCaps->dwNeededSize;
}
}
//
// FUNCTION: LPVOID CheckAndReAllocBuffer(LPVOID, size_t, LPCSTR)
//
// PURPOSE: Checks and ReAllocates a buffer if necessary.
//
LPVOID CTapiConnection::CheckAndReAllocBuffer(LPVOID lpBuffer, size_t sizeBufferMinimum)
{
size_t sizeBuffer;
if (lpBuffer == NULL) // Allocate the buffer if necessary.
{
sizeBuffer = sizeBufferMinimum;
lpBuffer = (LPVOID)::LocalAlloc(LPTR, sizeBuffer);
if (lpBuffer == NULL)
{
TRACE0("LocalAlloc failed in CheckAndReAllocBuffer./n");
return NULL;
}
}
else // If the structure already exists, make sure its good.
{
sizeBuffer = ::LocalSize((HLOCAL)lpBuffer);
if (sizeBuffer == 0) // Bad pointer?
{
TRACE0("LocalSize returned 0 in CheckAndReAllocBuffer/n");
return NULL;
}
// Was the buffer big enough for the structure?
if (sizeBuffer < sizeBufferMinimum)
{
TRACE0("Reallocating structure\n");
::LocalFree(lpBuffer);
return CheckAndReAllocBuffer(NULL, sizeBufferMinimum);
}
}
((LPVARSTRING)lpBuffer)->dwTotalSize = (DWORD)sizeBuffer;
return lpBuffer;
}
//
// FUNCTION: I_lineGetAddressCaps(LPLINEADDRESSCAPS, ..)
//
// PURPOSE: Retrieve a LINEADDRESSCAPS structure for the specified line.
//
// PARAMETERS:
// lpLineAddressCaps - Pointer to a LINEADDRESSCAPS, or NULL.
// dwDeviceID - Device to get the address caps for.
// dwAddressID - This sample always assumes the first address.
// dwAPIVersion - API version negotiated for the device.
// dwExtVersion - Always 0 for this sample.
//
// RETURN VALUE:
// Returns a pointer to a LINEADDRESSCAPS structure if successful.
// Returns NULL if unsuccessful.
//
// COMMENTS:
//
// This function is a wrapper around lineGetAddressCaps to make it easy
// to handle the variable sized structure and any errors received.
//
// The returned structure has been allocated with LocalAlloc,
// so LocalFree has to be called on it when you're finished with it,
// or there will be a memory leak.
//
// Similarly, if a lpLineAddressCaps structure is passed in, it *must*
// have been allocated with LocalAlloc and it could potentially be
// LocalFree()d. It also *must* have the dwTotalSize field set.
//
// If lpLineAddressCaps == NULL, then a new structure is allocated. It
// is normal to pass in NULL for this parameter unless you want to use a
// lpLineCallStatus that has been returned by previous I_lineGetAddressCaps
// call.
//
//
LPLINEADDRESSCAPS CTapiConnection::I_lineGetAddressCaps(
LPLINEADDRESSCAPS lpLineAddressCaps,
DWORD dwDeviceID, DWORD dwAddressID,
DWORD dwAPIVersion, DWORD dwExtVersion)
{
size_t sizeofLineAddressCaps = sizeof(LINEADDRESSCAPS) + 1024;
long lReturn;
// Continue this loop until the structure is big enough.
while (TRUE)
{
// Make sure the buffer exists, is valid and big enough.
lpLineAddressCaps =
(LPLINEADDRESSCAPS)CheckAndReAllocBuffer(
(LPVOID)lpLineAddressCaps,
sizeofLineAddressCaps);
if (lpLineAddressCaps == NULL)
return NULL;
// Make the call to fill the structure.
do
{
lReturn =
::lineGetAddressCaps(m_hLineApp,
dwDeviceID, dwAddressID, dwAPIVersion, dwExtVersion,
lpLineAddressCaps);
if (HandleLineErr(lReturn))
continue;
else
{
TRACE0("lineGetAddressCaps unhandled error\n");
::LocalFree(lpLineAddressCaps);
return NULL;
}
}
while (lReturn != TAPISUCCESS);
// If the buffer was big enough, then succeed.
if ((lpLineAddressCaps->dwNeededSize) <=
(lpLineAddressCaps->dwTotalSize))
{
return lpLineAddressCaps;
}
// Buffer wasn't big enough. Make it bigger and try again.
sizeofLineAddressCaps = lpLineAddressCaps->dwNeededSize;
}
}
/*
//
// FUNCTION: MakeTheCall(LPLINEDEVCAPS, LPCSTR)
//
// PURPOSE: Dials the call
//
BOOL CTapiConnection::MakeTheCall(LPLINEDEVCAPS lpLineDevCaps, LPCTSTR lpszAddress)
{
LPLINECALLPARAMS lpCallParams = NULL;
LPLINEADDRESSCAPS lpAddressCaps = NULL;
long lReturn;
BOOL bFirstDial = TRUE;
// Get the capabilities for the line device we're going to use.
lpAddressCaps = I_lineGetAddressCaps(lpAddressCaps,
m_dwDeviceID, 0, m_dwAPIVersion, 0);
if (lpAddressCaps == NULL)
return FALSE;
// Setup our CallParams.
lpCallParams = CreateCallParams (lpCallParams, lpszAddress);
if (lpCallParams == NULL)
return FALSE;
do
{
if (bFirstDial)
lReturn = WaitForReply(::lineMakeCall(m_hLine, &m_hCall, lpszAddress,
0, lpCallParams));
else
lReturn = WaitForReply(::lineDial(m_hCall, lpszAddress, 0));
if (lReturn == WAITERR_WAITABORTED)
{
TRACE0("While Dialing, WaitForReply aborted.\n");
goto LABEL_ERREXIT;
}
if (HandleLineErr(lReturn))
continue;
else
{
if (bFirstDial)
TRACE0("lineMakeCall unhandled error\n");
else
TRACE0("lineDial unhandled error\n");
goto LABEL_ERREXIT;
}
}
while (lReturn != TAPISUCCESS);
bFirstDial = FALSE;
if (lpCallParams)
::LocalFree(lpCallParams);
if (lpAddressCaps)
::LocalFree(lpAddressCaps);
return TRUE;
LABEL_ERREXIT:
if (lpCallParams)
::LocalFree(lpCallParams);
if (lpAddressCaps)
::LocalFree(lpAddressCaps);
::AfxMessageBox("Dial failed.");
return FALSE;
}
*/
//
// FUNCTION: CreateCallParams(LPLINECALLPARAMS, LPCSTR)
//
// PURPOSE: Allocates and fills a LINECALLPARAMS structure
//
//
LPLINECALLPARAMS CTapiConnection::CreateCallParams(
LPLINECALLPARAMS lpCallParams, LPCSTR lpszDisplayableAddress)
{
size_t sizeDisplayableAddress;
if (lpszDisplayableAddress == NULL)
lpszDisplayableAddress = _T("");
sizeDisplayableAddress = strlen(lpszDisplayableAddress) + 1;
lpCallParams = (LPLINECALLPARAMS)CheckAndReAllocBuffer(
(LPVOID)lpCallParams,
sizeof(LINECALLPARAMS) + sizeDisplayableAddress);
// "CreateCallParams: ");
if (lpCallParams == NULL)
return NULL;
// set everything to 0
// memset(lpCallParams, 0, sizeof(lpCallParams));
// This is where we configure the line for DATAMODEM usage.
lpCallParams->dwBearerMode = LINEBEARERMODE_VOICE;
lpCallParams->dwMediaMode = LINEMEDIAMODE_DATAMODEM;//LINEMEDIAMODE_INTERACTIVEVOICE;
// 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;
}
//
// FUNCTION: long WaitForReply(long)
//
// PURPOSE: Resynchronize by waiting for a LINE_REPLY
//
// PARAMETERS:
// lRequestID - The asynchronous request ID that we're
// on a LINE_REPLY for.
//
// RETURN VALUE:
// - 0 if LINE_REPLY responded with a success.
// - LINEERR constant if LINE_REPLY responded with a LINEERR
// - 1 if the line was shut down before LINE_REPLY is received.
//
// COMMENTS:
//
// This function allows us to resynchronize an asynchronous
// TAPI line call by waiting for the LINE_REPLY message. It
// waits until a LINE_REPLY is received or the line is shut down.
//
// Note that this could cause re-entrancy problems as
// well as mess with any message preprocessing that might
// occur on this thread (such as TranslateAccelerator).
//
// This function should to be called from the thread that did
// lineInitialize, or the PeekMessage is on the wrong thread
// and the synchronization is not guaranteed to work. Also note
// that if another PeekMessage loop is entered while waiting,
// this could also cause synchronization problems.
//
// One more note. This function can potentially be re-entered
// if the call is dropped for any reason while waiting. If this
// happens, just drop out and assume the wait has been canceled.
// This is signaled by setting bReentered to FALSE when the function
// is entered and TRUE when it is left. If bReentered is ever TRUE
// during the function, then the function was re-entered.
//
// This function times out and returns WAITERR_WAITTIMEDOUT
// after WAITTIMEOUT milliseconds have elapsed.
//
//
long CTapiConnection::WaitForReply(long lRequestID)
{
static BOOL bReentered;
bReentered = FALSE;
if (lRequestID > TAPISUCCESS)
{
MSG msg;
DWORD dwTimeStarted;
m_bReplyRecieved = FALSE;
m_dwRequestedID = (DWORD)lRequestID;
// Initializing this just in case there is a bug
// that sets m_bReplyRecieved without setting the reply value.
m_lAsyncReply = LINEERR_OPERATIONFAILED;
dwTimeStarted = GetTickCount();
while (!m_bReplyRecieved)
{
if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
// This should only occur if the line is shut down while waiting.
if ((m_hCall != NULL) &&(!m_bTapiInUse || bReentered))
{
bReentered = TRUE;
return WAITERR_WAITABORTED;
}
// Its a really bad idea to timeout a wait for a LINE_REPLY.
// If we are execting a LINE_REPLY, we should wait till we get
// it; it might take a long time to dial (for example).
// If 5 seconds go by without a reply, it might be a good idea
// to display a dialog box to tell the user that a
// wait is in progress and to give the user the capability to
// abort the wait.
}
bReentered = TRUE;
return m_lAsyncReply;
}
bReentered = TRUE;
return lRequestID;
}
//
// FUNCTION: lineCallbackFunc(..)
//
// PURPOSE: Receive asynchronous TAPI events
//
void CALLBACK CTapiConnection::lineCallbackFunc(
DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
OutputDebugLineCallback(dwDevice, dwMsg, dwCallbackInstance,
dwParam1, dwParam2, dwParam3);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -