📄 tapiconn._cp
字号:
// Handle the line messages.
switch (dwMsg)
{
case LINE_CALLSTATE:
DoLineCallState(dwDevice, dwMsg, dwCallbackInstance, dwParam1, dwParam2,
dwParam3);
break;
case LINE_CLOSE:
DoLineClose(dwDevice, dwMsg, dwCallbackInstance,
dwParam1, dwParam2, dwParam3);
break;
/*
// Line has been shut down.
ASSERT(m_this);
m_this->m_hLine = NULL;
m_this->m_hCall = NULL;
m_this->HangupCall(); // all handles invalidated by this time
break;
*/
case LINE_LINEDEVSTATE:
DoLineDevState(dwDevice, dwMsg, dwCallbackInstance,
dwParam1, dwParam2, dwParam3);
break;
case LINE_REPLY:
DoLineReply(dwDevice, dwMsg, dwCallbackInstance,
dwParam1, dwParam2, dwParam3);
break;
/*
if ((long)dwParam2 != TAPISUCCESS)
TRACE0("LINE_REPLY error\n");
else
TRACE0("LINE_REPLY: successfully replied.\n");
break;*/
case LINE_CREATE:
DoLineCreate(dwDevice, dwMsg, dwCallbackInstance,
dwParam1, dwParam2, dwParam3);
break;
/*
ASSERT(m_this);
if (m_this->m_dwNumDevs <= dwParam1)
m_this->m_dwNumDevs = dwParam1+1;
break;
*/
default:
TRACE0("lineCallbackFunc message ignored\n");
break;
}
}
//
// FUNCTION: DoLineCallState(..)
//
// PURPOSE: Handle LINE_CALLSTATE asynchronous messages.
//
void CTapiConnection::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 != m_this->m_hCall)
{
TRACE0("LINE_CALLSTATE: Unknown device ID ");
// 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.
m_dwCallState = dwParam1;
m_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:
TRACE0("line given monitor privilege; closing\n");
// m_this->HangupCall();
return;
// close line if we are made owner. Shouldn't happen!
case LINECALLPRIVILEGE_OWNER:
TRACE0("line given owner privilege; closing\n");
// m_this->HangupCall();
break;
default: // Shouldn't happen! All cases handled.
TRACE0("Unknown LINECALLPRIVILEGE message: closing\n");
m_this->HangupCall();
return;
}
// dwParam1 is the specific CALLSTATE change that is occurring.
switch (dwParam1)
{
case LINECALLSTATE_DIALTONE:
TRACE0("Dial Tone\n");
break;
case LINECALLSTATE_DIALING:
TRACE0("Dialing\n");
break;
case LINECALLSTATE_PROCEEDING:
TRACE0("Proceeding\n");
break;
case LINECALLSTATE_RINGBACK:
TRACE0("RingBack\n");
break;
case LINECALLSTATE_BUSY:
TRACE0("Line busy, shutting down\n");
m_this->HangupCall();
break;
case LINECALLSTATE_IDLE:
TRACE0("Line idle\n");
m_this->HangupCall();
break;
case LINECALLSTATE_OFFERING:
// The call is being offered, signaling the arrival
// of a new call. check if we are the owner of the call, and if we are,
// then answer it.
if (dwParam3 == LINECALLPRIVILEGE_OWNER)
{
m_this->WaitForReply(::lineAnswer(m_this->m_hCall = (HCALL)dwDevice, NULL, 0));
} // end if (we own this call)
break;
case LINECALLSTATE_SPECIALINFO:
TRACE0("Special Info, probably couldn't dial number\n");
m_this->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;
}
TRACE0(pszReasonDisconnected);
TRACE0("\n");
m_this->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 (m_this->m_bConnected)
break;
m_this->m_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
{
// Allocate the VARSTRING structure
lpVarString = (LPVARSTRING)CheckAndReAllocBuffer((LPVOID)lpVarString,
dwSizeofVarString);
if (lpVarString == NULL)
goto LABEL_ERRORCONNECTING;
// Fill the VARSTRING structure
lReturn = ::lineGetID(0, 0, m_this->m_hCall, LINECALLSELECT_CALL,
lpVarString, "comm/datamodem");
if (m_this->HandleLineErr(lReturn))
; // Still need to check if structure was big enough.
else
{
OutputDebugLineError(lReturn,
"lineGetID unhandled error: ");
goto LABEL_ERRORCONNECTING;
}
// If the VARSTRING wasn't big enough, loop again.
if ((lpVarString->dwNeededSize) > (lpVarString->dwTotalSize))
{
dwSizeofVarString = lpVarString->dwNeededSize;
lReturn = -1; // Lets loop again.
}
}
while (lReturn != TAPISUCCESS);
TRACE0("Connected! Starting communications!\n");
// Again, the handle to the comm port is contained in a
// LPVARSTRING structure. Thus, the handle is the very first
// thing after the end of the structure. Note that the name of
// the comm port is right after the handle, but I don't want it.
hCommFile =
*((LPHANDLE)((LPBYTE)lpVarString +
lpVarString->dwStringOffset));
// Started communications!
if (m_this->StartComm(hCommFile))
{
// char szBuff[300];
// wsprintf(szBuff, "Connected to '%s'", g_szDisplayableAddress);
// UpdateStatusBar(szBuff, 1, 0);
::LocalFree(lpVarString);
break;
}
// Couldn't start communications. Clean up instead.
LABEL_ERRORCONNECTING:
// Its very important that we close all Win32 handles.
// The CommCode module is responsible for closing the hCommFile
// handle if it succeeds in starting communications.
if (hCommFile)
CloseHandle(hCommFile);
m_this->HangupCall();
{
// char szBuff[300];
// wsprintf(szBuff,"Failed to Connect to '%s'",
// g_szDisplayableAddress);
// UpdateStatusBar(szBuff, 1, 0);
}
if (lpVarString)
::LocalFree(lpVarString);
break;
}
default:
TRACE0("Unhandled LINECALLSTATE message\n");
break;
}
}
//
// FUNCTION: HandleLineErr(long)
//
// PURPOSE: Handle several of the standard LINEERR errors
//
BOOL CTapiConnection::HandleLineErr(long lLineErr)
{
BOOL bRet = FALSE;
// lLineErr is really an async request ID, not an error.
if (lLineErr > TAPISUCCESS)
return bRet;
// All we do is dispatch the correct error handler.
switch (lLineErr)
{
case TAPISUCCESS:
bRet = TRUE;
break;
case LINEERR_INVALCARD:
case LINEERR_INVALLOCATION:
case LINEERR_INIFILECORRUPT:
TRACE0("The values in the INI file are invalid.\n");
break;
case LINEERR_NODRIVER:
TRACE0("There is a problem with your Telephony device driver.\n");
break;
case LINEERR_REINIT:
ShutdownTAPI();
break;
case LINEERR_NOMULTIPLEINSTANCE:
TRACE0("Remove one of your copies of your Telephony driver.\n");
break;
case LINEERR_NOMEM:
TRACE0("Out of memory. Cancelling action.\n");
break;
case LINEERR_OPERATIONFAILED:
TRACE0("The TAPI operation failed.\n");
break;
case LINEERR_RESOURCEUNAVAIL:
TRACE0("A TAPI resource is unavailable at this time.\n");
break;
// Unhandled errors fail.
default:
break;
}
return bRet;
}
//
// FUNCTION: BOOL HangupCall()
//
// PURPOSE: Hangup the call in progress if it exists.
//
BOOL CTapiConnection::HangupCall()
{
LPLINECALLSTATUS pLineCallStatus = NULL;
long lReturn;
// Prevent HangupCall re-entrancy problems.
if (m_bStoppingCall)
return TRUE;
// If Tapi is not being used right now, then the call is hung up.
if (!m_bTapiInUse)
return TRUE;
m_bStoppingCall = TRUE;
TRACE0("Stopping Call in progress\n");
// If there is a call in progress, drop and deallocate it.
if (m_hCall)
{
pLineCallStatus = (LPLINECALLSTATUS)::malloc(sizeof(LINECALLSTATUS));
if (!pLineCallStatus)
{
ShutdownTAPI();
m_bStoppingCall = FALSE;
return FALSE;
}
lReturn = ::lineGetCallStatus(m_hCall, pLineCallStatus);
// Only drop the call when the line is not IDLE.
if (!((pLineCallStatus->dwCallState) & LINECALLSTATE_IDLE))
{
WaitForReply(::lineDrop(m_hCall, NULL, 0));
TRACE0("Call Dropped.\n");
}
// The call is now idle. Deallocate it!
do
{
lReturn = ::lineDeallocateCall(m_hCall);
if (HandleLineErr(lReturn))
continue;
else
{
TRACE0("lineDeallocateCall unhandled error\n");
break;
}
}
while (lReturn != TAPISUCCESS);
TRACE0("Call Deallocated.\n");
}
// if we have a line open, close it.
if (m_hLine)
{
lReturn = ::lineClose(m_hLine);
if (!HandleLineErr(lReturn))
TRACE0("lineClose unhandled error\n");
TRACE0("Line Closed.\n");
}
// Clean up.
m_hCall = NULL;
m_hLine = NULL;
m_bTapiInUse = FALSE;
m_bStoppingCall = FALSE; // allow HangupCall to be called again.
// Need to free buffer returned from lineGetCallStatus
if (pLineCallStatus)
::free(pLineCallStatus);
TRACE0("Call stopped\n");
return TRUE;
}
//
// FUNCTION: BOOL ShutdownTAPI()
//
// PURPOSE: Shuts down all use of TAPI
//
BOOL CTapiConnection::ShutdownTAPI()
{
long lReturn;
// If we aren't initialized, then Shutdown is unnecessary.
if (m_hLineApp == NULL)
return TRUE;
// Prevent ShutdownTAPI re-entrancy problems.
if (m_bShuttingDown)
return TRUE;
m_bShuttingDown = TRUE;
HangupCall();
do
{
lReturn = ::lineShutdown(m_hLineApp);
if (HandleLineErr(lReturn))
continue;
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -