⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tapiline.cpp

📁 TAPI编程应用
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	if(NULL == m_pActiveCall->GetStateSemHandle()) return -1L;	// failed to alloc mutex
	return 0L;	// why 0?....
}

// Remove active or any other call
void CTapiLine::RemoveCall(CTapiCall *pCall)
{
	// Protect this against async returns that may try to do something w/pCall!!! 
	// first claim the call list mutex
	HANDLE hStateSem;
	DWORD dwWS;

	TRACE("*** TALKER32 ***: RemoveCall entering wait for sem\n");
	DWORD dwrc = WaitForSingleObject(m_hCallSem, 15000);
	if(dwrc != WAIT_OBJECT_0) 
	{
		TRACE("*** TALKER32 ***: RemoveCall #%lx wait for sem failed rc=%lx\n", pCall, dwrc);
		return;
	}
	if(pCall == NULL) pCall = m_pActiveCall;
	if(pCall == NULL) goto FinishRemoveCall;		// nothing to do

	hStateSem = pCall->GetStateSemHandle();
	if(hStateSem)		// in case somebody else tries to call UpdateCallState...
	{
		WaitForSingleObject(hStateSem, 5000);
		CloseHandle(hStateSem);
 	}
	// cleanup async requests associated with this call here !!!
	dwWS = pCall->GetWaveStatus();
	if(dwWS != WAVE_IDLE) 	// Defer removing call ???...
		TRACE("*** TALKER32 ***: removing call while WAVE state=%d\n", dwWS);
	delete pCall;
	if(pCall == m_pActiveCall) m_pActiveCall = NULL;
FinishRemoveCall:
	TRACE("*** TALKER32 ***: RemoveCall %lx releasing mutex\n", pCall);
	ReleaseMutex(m_hCallSem);
	return;
}

// purge (all) calls on the line, no questions asked
void CTapiLine::ctlPurgeCalls()
{

	TRACE("*** TALKER32 ***: Enter PurgeCalls for line %d\n", m_dwLineID);
// for now only delete the active call. When the calls storage is impl, add logic
	if(NULL == m_pActiveCall) return;
// Do for all calls
	RemoveCall();
	TRACE("*** TALKER32 ***: Exit PurgeCalls for line %d\n", m_dwLineID);
}

// React to changes in call status; needs to be protected 
// Call NotifyFrontEnd after this function to update indicators
void CTapiLine::ctlUpdateCallStatus(WORD wFunction, DWORD dwStatus, CTapiCall *pCall)
{

	switch(wFunction)
	{
	 	case 0:			// status change is NOT a result of async return
			pCall->UpdateCallState((WORD) dwStatus);
		break;

		case FUNCTION_MAKECALL:
//		case FUNCTION_DIAL:
		if(dwStatus < 0) 
		{
			if(pCall) 	// do not try to drop; can only drop calls that were made 
			{
				pCall->UpdateCallState(IDLE, IDLE, LINECALLSTATE_UNKNOWN, MAKE_FAILED);
				ctlLineDeallocateCall(pCall);
			}	
		}	
		else pCall->UpdateCallState(PROGRESS);
		break;

		case FUNCTION_DROP:		// if failed, find out the reason
			if(m_pActiveCall==NULL || !IsBadReadPtr(pCall, 32))
			{
				TRACE("*** TALKER32 ***: Trying to update call state for invalid pCall, pCall=%lx, m_pActive=%lx\n",
					pCall, m_pActiveCall);
				break;	 
			}
			if(dwStatus < 0) 	// do NOT try to deallocate or change state
			{
				// mark it as tried to drop & failed
				pCall->UpdateCallState(0xffff, 0xffff, 0xffff, DROP_FAILED);
			}
			else pCall->UpdateCallState(DROPPING);
		break;	

		case FUNCTION_ANSWER:
		// does not mean we have an active connection yet
			if(dwStatus < 0) 	// don't know what to do, try to drop...
			{
				pCall->UpdateCallState(DROPPING, 0xffff, 0xffff, ANSWER_FAILED);
				ctlLineDrop(m_pActiveCall);
			}
		break;	

		case FUNCTION_DEVSPEC:
			if(dwStatus & 0x80000000)
				ctlUpdateDevSpecStatus(DEVSPEC_STARTFAILED);
			else ctlUpdateDevSpecStatus(dwStatus ? DEVSPEC_RESULTFAILED : DEVSPEC_IDLE);
			//ctlUpdateDevSpecStatus(DEVSPEC_PROGRESS);
				
		break;

		case FUNCTION_FORWARD:
			TRACE("TALKER32: lineForward reply status=%lx\n", dwStatus);
		break;

		default:
		break;	

		m_pApp->NotifyFrontEnd(m_dwLineID);		// always update front end
	} // end of switch(wFunction)

}

// Update call info based on HCALL
BOOL CTapiLine::ctlUpdateCallInfo(HCALL hCall, LPLINECALLINFO lpCallInfo)
{
	// find the call, delete the current CALLINFO if any, set new CALLINFO

	if(m_pActiveCall->m_hCall != hCall) return FALSE;	// for now
	// m_pActiveCall->UpdateCallInfo(lpCallInfo);	// must be protected
	return FALSE;	// always for now, so the caller deletes CALLINFO
}

//    get the id of the wave device corresponding to the line
//    COMMENTS: wave devices use an unsigned integer id.  we must allocate enough
//               space for this id to be returned from the driver.
void CTapiLine::ctlGetWaveDeviceID (WORD wType)
{
	LONG lrc;
	DWORD dwID; 
	VARSTRING *pvsVarStr = (VARSTRING *) new char[sizeof(VARSTRING) + 64];
// allocate 4 extra bytes for wave id. 
                 
	if(pvsVarStr == NULL) goto GetIDFail;                 
	pvsVarStr->dwTotalSize =  sizeof (VARSTRING) + 64;
	if ((lrc = lineGetID (m_hLine, 0, 0, LINECALLSELECT_LINE, 
		pvsVarStr, wType == WAVEIN ? "wave/in" : wType == WAVEOUT ? "wave/out" : "xxx")) < 0)
		goto GetIDFail;
	// if the returned id was not binary, something is wrong 
	if (!m_bRemote && pvsVarStr->dwStringFormat != STRINGFORMAT_BINARY) 
	{ 	
		#ifdef TAPI20
			if(pvsVarStr->dwStringFormat == STRINGFORMAT_ASCII || pvsVarStr->dwStringFormat == STRINGFORMAT_UNICODE)
			{
				m_bRemote = TRUE;		// the line is running remotely
				m_csName = ((BYTE *)pvsVarStr+sizeof(VARSTRING));
				m_csName += "\\";
			}
		#endif
		//goto GetIDFail;
	}
	dwID = (DWORD) *((BYTE *)pvsVarStr+sizeof(VARSTRING)); // get id 
	delete pvsVarStr;
	if(wType == WAVEIN) m_uiWaveInID = (UINT)(WORD) dwID; 
	else if(wType == WAVEOUT) m_uiWaveOutID = (UINT)(WORD) dwID; 
	return;
GetIDFail:
	if(pvsVarStr != NULL) delete pvsVarStr;
}

//call lineGetLineDevStatus here
LPLINEDEVSTATUS CTapiLine::ctlGetLineDevStatus()
{
    LPLINEDEVSTATUS lpDevStatus = NULL;
    LONG lrc = 0;
    DWORD dwSize = sizeof(LINEDEVSTATUS)+1000;
    DWORD i;
    
    // keep trying until buffer is big enough 
    for (i=0; i<2; i++)
	{
    	lpDevStatus = (LPLINEDEVSTATUS) new char[dwSize];
    	if (lpDevStatus == NULL)
        	return NULL;
	    lpDevStatus->dwTotalSize = dwSize;

        lrc = lineGetLineDevStatus(m_hLine,lpDevStatus);
		if(lrc < 0) goto FinishLineGetDevStatus;

        dwSize = lpDevStatus->dwNeededSize; 
		if(dwSize <= lpDevStatus->dwTotalSize) break;   // success
		         
		delete (char *) lpDevStatus;
	} 

    return lpDevStatus;

FinishLineGetDevStatus: 
    if (lpDevStatus != NULL)
        delete (LPBYTE) lpDevStatus;
    return NULL;
} 

// Configuration dialog
void CTapiLine::ctlConfigDialog(HWND hWnd, LPSTR lpClass)
{
	lineConfigDialog(m_dwLineID, hWnd, lpClass);
}

LONG CTapiLine::ctlLineDevSpecific(DWORD dwFunc, DWORD dwAddressID, HCALL hCall,
						 LPVOID lParams, DWORD dwSize)
{
	LONG lrc;
	TRACE("*** TALKER32: calling DevSpec dwSize=%d\n", dwSize);
	lrc = lineDevSpecific(m_hLine, dwAddressID, hCall, lParams, dwSize);
	if(lrc < 0) 
	{						// need to report an error
		TRACE("*** TALKER32: DevSpec failed on line %d\n", m_dwLineID);
		return lrc;
	}
	TRACE("*** TALKER32: DevSpec asyncID=%d\n",lrc);
	ctlUpdateDevSpecStatus(DEVSPEC_STARTING);
	// update the function in the beginning of execution ONLY
	ctlUpdateDevSpecFunction(dwFunc);
	m_pApp->SetAsyncID((DWORD) lrc, MAKING, FUNCTION_DEVSPEC, 
						(LPVOID) this, (LPVOID) m_pActiveCall); 
	return lrc;
}

LONG CTapiLine::ctlLineForward(LPSTR lpDest)
{
	if(!lpDest) return -1;
	LPLINEFORWARDLIST lpLFL = (LPLINEFORWARDLIST) new char[sizeof(LINEFORWARDLIST) + lstrlen(lpDest)+8];
	if(!lpLFL) return -1;
	BOOL bAllAddr = TRUE;
	DWORD dwAddrID = 0L;
	HCALL hCC;
	LONG lrc;

	lpLFL->dwNumEntries = 1;
	lpLFL->dwTotalSize = sizeof(LINEFORWARDLIST) + lstrlen(lpDest)+8;
	lpLFL->ForwardList[0].dwForwardMode = LINEFORWARDMODE_UNCOND;
	lpLFL->ForwardList[0].dwCallerAddressSize = 0;
	lpLFL->ForwardList[0].dwCallerAddressOffset = 0;
	lpLFL->ForwardList[0].dwDestCountryCode = 0;
	lpLFL->ForwardList[0].dwDestAddressSize = (DWORD)lstrlen(lpDest);
	lpLFL->ForwardList[0].dwDestAddressOffset = sizeof(LINEFORWARDLIST);
	memcpy((LPBYTE)lpLFL+sizeof(LINEFORWARDLIST), lpDest, lstrlen(lpDest)+1);

	lrc = lineForward(m_hLine, bAllAddr, dwAddrID, lpLFL, 4, &hCC, NULL);
	if(lrc < 0) 
		TRACE("*** TALKER32: lineForward failed on line %d rc=%lx\n", m_dwLineID, lrc);
	else m_pApp->SetAsyncID((DWORD) lrc, MAKING, FUNCTION_FORWARD, 
						(LPVOID) this, NULL); 
	delete (LPBYTE) lpLFL;
	return lrc;
}

// Determine if the line is running on the remote computer
// Since MS doesn't provide a standard way, use whatever mechanism is available for the SP
// Override this function to implement a better way
BOOL IsLineRemote(LPLINEDEVCAPS lpDC)
{
	int nInd;
	CString csTemp;

	if(!lpDC->dwLineNameOffset) return FALSE;
	csTemp.Format("%s", (LPSTR)((LPBYTE)lpDC + lpDC->dwLineNameOffset));
	csTemp.MakeUpper();
	if(-1 == csTemp.Find("DXXXB")) return FALSE;		// non-Dialogic TSP
	if(-1 == (nInd = csTemp.Find("\\"))) return FALSE;	// computer name not a part of board name
	csTemp = csTemp.Left(nInd);
	char szName[MAX_COMPUTERNAME_LENGTH+1];
	DWORD dwSize = MAX_COMPUTERNAME_LENGTH+1;
	if(!GetComputerName(szName, &dwSize)) return FALSE;	// Name unavailable for some reason
	if(!strcmpi(szName, (LPCTSTR)csTemp)) return FALSE;	// Same name
	return TRUE;					 // Finally, the names ARE different
}

/* call lineGetLineDevCaps here
LPLINEDEVSTATUS CTapiLine::ctlGetLineDevCaps()
{
    LPLINEDEVCAPS lpDevCaps = NULL;
    LONG lrc = 0;
    DWORD dwSize = sizeof(LINEDEVCAPS)+1000;
    DWORD i;
    
    // keep trying until buffer is big enough 
    for (i=0; i<2; i++)
	{
    	lpDevStatus = (LPLINEDEVSTATUS) new char[dwSize];
    	if (lpDevStatus == NULL)
        	return NULL;
	    lpDevStatus->dwTotalSize = dwSize;

        lrc = lineGetLineDevStatus(m_hLine,lpDevStatus);
		if(lrc < 0) goto FinishLineGetDevStatus;

        dwSize = lpDevStatus->dwNeededSize; 
		if(dwSize <= lpDevStatus->dwTotalSize) break;   // success
		         
		delete (char *) lpDevStatus;
	} 

    return lpDevStatus;

FinishLineGetDevStatus: 
    if (lpDevStatus != NULL)
        delete (LPBYTE) lpDevStatus;
    return NULL;
} */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -