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

📄 tapiline.cpp

📁 串口调试助手的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		// If the buffer was big enough, then succeed.
		if ((lpLineAddressCaps->dwNeededSize) <= 
			(lpLineAddressCaps->dwTotalSize))
		{
			return  lpLineAddressCaps;
		}
		else
		{
			// Buffer wasn't big enough.  Make it bigger and try again.
			nSizeLineAddressCaps = lpLineAddressCaps->dwNeededSize;
			delete  lpLineAddressCaps;
		}
	}
}

// Retrieve a LINECALLSTATUS structure for the specified line.
// This function is a wrapper around lineGetTranslateOutput to make it
// easy to handle the variable sized structure and any errors received.
LPLINETRANSLATEOUTPUT	CTAPILine::I_lineTranslateAddress(LPCTSTR  lpszDialAddress)
{
	int	nSizeLineTranslateOutput = sizeof(LINETRANSLATEOUTPUT) + 1024;
	long	lReturn;
    
	// Continue this loop until the structure is big enough.
	while (TRUE)
	{
		// Make sure the buffer exists, is valid and big enough.
		LPLINETRANSLATEOUTPUT	lpLineTranslateOutput = 
			(LPLINETRANSLATEOUTPUT)new  BYTE[nSizeLineTranslateOutput];
		if (lpLineTranslateOutput == NULL)
			return  NULL;

		lpLineTranslateOutput->dwTotalSize = nSizeLineTranslateOutput;

		// Make the call to fill the structure.
		do
		{
			// Note that CALLWAITING is disabled 
			// (assuming the service provider can disable it)
			lReturn = ::lineTranslateAddress(CTAPIConnection::m_hLineApp,
					m_dwDeviceID, m_dwAPIVersion,
					lpszDialAddress, 0, 
					LINETRANSLATEOPTION_CANCELCALLWAITING,
					lpLineTranslateOutput);

			// If the address isn't translatable, notify the user.
			if (lReturn == LINEERR_INVALADDRESS)
				::MessageBox(NULL, "Unable to translate phone number", "Warning", MB_OK);

			if (!CTAPIError::HandleLineErr(lReturn))
			{
				TRACE1("lineTranslateOutput unhandled error: %lx\n", lReturn);
				delete  lpLineTranslateOutput;
				return  NULL;
			}
		}
		while (lReturn != TAPISUCCESS);

		// If the buffer was big enough, then succeed.
		if ((lpLineTranslateOutput->dwNeededSize) <= 
			(lpLineTranslateOutput->dwTotalSize))
		{
			return  lpLineTranslateOutput;
		}
		else
		{
			// Buffer wasn't big enough.  Make it bigger and try again.
			nSizeLineTranslateOutput = lpLineTranslateOutput->dwNeededSize;
			delete  lpLineTranslateOutput;
		}
	}
}

// Get Comm File Handle to used by Comm API
HANDLE	CTAPILine::GetCommHandle(void)
{
	ASSERT(m_hCall != (HCALL)-1);

	LPVARSTRING	lpVarString = NULL;
	int	nSizeofVarString = sizeof(VARSTRING) + 1024;

	// Get the handle to the comm port from the driver so we can start
	// communicating. This is returned in a LPVARSTRING structure.
	long	lReturn;
	while (TRUE)
	{
		// Allocate the VARSTRING structure
		lpVarString = (LPVARSTRING)new  BYTE[nSizeofVarString];
		if (lpVarString == NULL)
		{
			TRACE0("Error alloc LPVARSTRING !\n");
			return  INVALID_HANDLE_VALUE;
		}
		lpVarString->dwTotalSize = nSizeofVarString;

		// Fill the VARSTRING structure
		lReturn = ::lineGetID(0, 0, m_hCall, LINECALLSELECT_CALL,
			lpVarString, "comm/datamodem");

		if (!CTAPIError::HandleLineErr(lReturn))
		{
			TRACE1("lineGetID unhandled error: %lu\n", lReturn);
			delete  lpVarString;
			return  INVALID_HANDLE_VALUE;
		}

		// If the VARSTRING wasn't big enough, loop again.
		if ((lpVarString->dwNeededSize) <= (lpVarString->dwTotalSize))
		{
			break;
		}
		else
		{
			nSizeofVarString = lpVarString->dwNeededSize;
			delete  lpVarString;
		}
	}

	// 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.
	HANDLE	hCommFile = *((LPHANDLE)((LPBYTE)lpVarString + lpVarString->dwStringOffset));
	if (lpVarString != NULL)
		delete  lpVarString;
	return  hCommFile;
}

// Hangup the call in progress if it exists.
// If HangupCall fails, then its likely either a problem
// with the service provider (and might require a system
// reboot to correct) or the application ran out of memory.
BOOL	CTAPILine::HangupCall(void)
{    
	LPLINECALLSTATUS	pLineCallStatus = NULL;
	long	lReturn;

	// If Tapi is not being used right now, then the call is hung up.
	if (m_WaitReplyType != REPLY_NONE)
		return  FALSE;

	TRACE0("Stopping Call in progress\n");
    
	// Stop any data communications on the comm port.
	if (m_pComm)
	{
		delete  m_pComm;
		m_pComm = NULL;
	}

	// If there is a call in progress, drop and deallocate it.
	if (m_hCall != (HCALL)-1)
	{
		if ((pLineCallStatus = I_lineGetCallStatus(m_hCall)) == NULL)
		{
//			ShutdownTAPI();
			return  FALSE;
		}

		// Only drop the call when the line is not IDLE.
		if (!((pLineCallStatus->dwCallState) & LINECALLSTATE_IDLE))
		{
			do
			{
				lReturn = ::lineDrop(m_hCall, NULL, 0);
				if (lReturn < 0)
				{
					if (!CTAPIError::HandleLineErr(lReturn))
					{
						TRACE1("lineDrop unhandled error: %lu\n", lReturn);
					}
				}
				else
				{
					// believe it or not, lineDrop is returning 0 syncronously with Unimodem!
					if (!lReturn)
					{
						// do what Unimodem should be doing
						CTAPIConnection::DoLineCallState((DWORD)m_hCall, LINE_CALLSTATE,
							0, LINECALLSTATE_IDLE, 0, 0);
					}

					m_dwAsyncID = lReturn;
					m_WaitReplyType = REPLY_DROPCALL;
					break;
				}
			}
			while (lReturn != TAPISUCCESS);

			// Wait for the dropped call to go IDLE before continuing.
			lReturn = CTAPIConnection::WaitForCallState(LINECALLSTATE_IDLE);
			switch (lReturn)
			{
			case WAITERR_WAITTIMEDOUT:
				TRACE0("Call timed out waiting for IDLE state.\n");
				break;

			case WAITERR_WAITABORTED:
				TRACE0("WAITERR_WAITABORTED while waiting for IDLE state.\n");
				break;
			}
			TRACE0("Call Dropped.\n");
		}

		// The call is now idle. Deallocate it!
		do
		{
			lReturn = ::lineDeallocateCall(m_hCall);
			if (!CTAPIError::HandleLineErr(lReturn))
			{
				TRACE1("lineDeallocateCall unhandled error: %lu\n", lReturn);
				break;
			}
		}
		while (lReturn != TAPISUCCESS);

		TRACE0("Call Deallocated.\n");
	}
	Close();

	m_hCall = (HCALL)-1;
	m_bConnected = FALSE;
	TRACE0("Call stopped\n");
	PostHangupCall();
	CTAPIConnection::m_dwAnswerCallWait=(DWORD)-1;
	// Send UI message
	// "Ready to make a call."

	// Need to free LocalAlloc()d buffer returned from I_lineGetCallStatus
	if (pLineCallStatus != NULL)
		delete  pLineCallStatus; 

	return  TRUE;
}

// Posts a message to the main TAPI thread to hangup the call.
// TAPI is thread specific, meaning that only the thread that does the
// lineInitialize can get asynchronous messages through the callback.
// Since the HangupCall can potentially go into a loop waiting for
// specific events, any other threads that call HangupCall can cause
// timing confusion. Best to just have other threads 'ask' the main thread
// to hangup the call.
void	CTAPILine::PostHangupCall()
{
	TRACE0("Post Hangup Call !\n");

	if (CTAPIConnection::m_pNotifyWnd != NULL)
	{
		CTAPIConnection::m_pNotifyWnd->PostMessage(WM_COMMAND,
			CTAPIConnection::m_dwCommBaseCommandID + IDM_HANGUPCALL,
			/*CTAPIConnection::m_dwAnswerCallWait*/0);
	}
	else
	{
		// avoid MainWnd is NULL
		if (::AfxGetApp()->m_pMainWnd != NULL)
		{
			::AfxGetApp()->m_pMainWnd->PostMessage(WM_COMMAND,
				CTAPIConnection::m_dwCommBaseCommandID + IDM_HANGUPCALL,
				/*CTAPIConnection::m_dwAnswerCallWait*/0);
		}
	}
}

// - There will only be one outgoing address per line.
BOOL	CTAPILine::DialCall(LPCTSTR  lpDialNumber, LPCTSTR  lpszDisplayableAddress)
{
	// If TAPI isn't initialized, its either because we couldn't initialize
	// at startup (and this might have been corrected by now), or because
	// a REINIT event was received.  In either case, try to init now.
	if (!CTAPIConnection::m_hLineApp)
	{
		if (!CTAPIConnection::Create(CTAPIConnection::m_pNotifyWnd,
			CTAPIConnection::m_dwAPILowVersion,
			CTAPIConnection::m_dwAPIHighVersion,
			CTAPIConnection::m_dwCommBaseCommandID,
			CTAPIConnection::m_pReadBuf,
			CTAPIConnection::m_nReadBufLen))
			return  FALSE;
	}

	if (m_bConnected || (m_WaitReplyType != REPLY_NONE && m_WaitReplyType != REPLY_DROPCALL))
	{
		TRACE0("---");
		return  FALSE;
	}

	// Send Message to UI, Enable

	// If there are no line devices installed on the machine, lets give
	// the user the opportunity to install one.
	if (CTAPIConnection::GetNumDevs() < 1)
	{
		if (!CTAPIError::HandleNoDevicesInstalled())
			return  FALSE;
	}

	// Need to check the DevCaps to make sure this line is usable.
	if (!IsSupportVoice())
	{
		::MessageBox(NULL,
			"Error on Requested line",
			"The selected line doesn't support VOICE capabilities",
			MB_OK);
		return  FALSE;
	}

	if (!IsSupportDataModem())
	{
		::MessageBox(NULL,
			"Error on Requested line",
			"The selected line doesn't support DATAMODEM capabilities",
			MB_OK);
		return  FALSE;
	}

	// Does this line have the capability to make calls?
	// It is possible that some lines can't make outbound calls.
	if (!IsSupportMakeCall())
	{
		::MessageBox(NULL,
			"Error on Requested line",
			"The selected line doesn't support MAKECALL capabilities",
			MB_OK);
		return  FALSE;
	}

	if (!Open())
	{
		TRACE0("Open fail !\n");
		return  FALSE;
	}

	// Get LineAddressStatus so we can make sure the line
	// isn't already in use by a TAPI application.
	LPLINEADDRESSSTATUS	lpLineAddressStatus = I_lineGetAddressStatus(0);   
	if (lpLineAddressStatus == NULL)
	{
		::MessageBox(NULL,
			"Error on Requested line",
			"Unable to Use Line",MB_OK);
		if (lpLineAddressStatus != NULL)
			delete  lpLineAddressStatus;
		return  FALSE;
	}

	// MAKECALL will be set if there are any available call appearances
	if (!((lpLineAddressStatus->dwAddressFeatures) & LINEADDRFEATURE_MAKECALL))
	{
		TRACE0("This line is not available to place a call.\n");
		::MessageBox(NULL,
			"Requested line is already in use",
			"Unable to Use Line", MB_OK);
		if (lpLineAddressStatus != NULL)
			delete  lpLineAddressStatus;
		return  FALSE;
	}

	// Start dialing the number
	if (DialCallInParts(lpDialNumber,
		lpszDisplayableAddress))
	{
		TRACE0("DialCallInParts succeeded.\n");
	}
	else
	{
		TRACE0("DialCallInParts failed.\n");
		if (lpLineAddressStatus != NULL)
			delete  lpLineAddressStatus;
		return  FALSE;
	}

	if (lpLineAddressStatus != NULL)
		delete  lpLineAddressStatus;

	// Send Message UI
	return  TRUE;
}

// Structures needed to handle special non-dialable characters.
struct	NONDIALTOKENS
{
	LONG	lError;
	DWORD	dwDevCapFlag;
	LPSTR	szToken;
	LPSTR	szMsg;
};

NONDIALTOKENS	g_sNonDialable[] = 
{
	{
		LINEERR_DIALBILLING,
		LINEDEVCAPFLAGS_DIALBILLING,
		"$", 
		"Wait for the credit card bong tone"
	},
	{
		LINEERR_DIALDIALTONE,
		LINEDEVCAPFLAGS_DIALDIALTONE,
		"W", 
		"Wait for the second dial tone"
	},
	{
		LINEERR_DIALDIALTONE,
		LINEDEVCAPFLAGS_DIALDIALTONE,
		"w", 
		"Wait for the second dial tone"
	},
	{
		LINEERR_DIALQUIET,
		LINEDEVCAPFLAGS_DIALQUIET,
		"@", 
		"Wait for the remote end to answer"
	},
	{
		LINEERR_DIALPROMPT,
		0,
		"?", 
		"Press OK when you are ready to continue dialing"
	},
};
const int	nSizeNonDialable = sizeof(g_sNonDialable) / sizeof(g_sNonDialable[0]);

// Dials the call, handling special characters.
// 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	CTAPILine::DialCallInParts(LPCSTR  lpszAddress,
	LPCSTR  lpszDisplayableAddress)
{
/*
	if (CTAPIConnection::m_dwMakeCallWait != (DWORD)-1)
	{
		TRACE1("line %d is Making call !", CTAPIConnection::m_dwMakeCallWait);
		return  FALSE;
	}*/

	if (m_WaitReplyType != REPLY_NONE)
	{
		TRACE0("Line is used !\n");
		return  FALSE;
	}
//	CTAPIConnection::m_dwMakeCallWait = m_dwDeviceID;
//	CTAPIConnection::m_dwAnswerCallWait = m_dwDeviceID;

	BOOL	bRetVal = TRUE;

	long	lReturn;
	char	szFilter[sizeof(g_sNonDialable) + 1] = "";
	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.
	LPLINEADDRESSCAPS	lpAddressCaps = I_lineGetAddressCaps(0);
	if (lpAddressCaps == NULL)
	{
		TRACE0("Get Address Caps fail !\n");
		return  FALSE;
	}

	// Setup our CallParams for DATAMODEM settings.
	LPLINECALLPARAMS	lpCallParams = CreateCallParams(lpszDisplayableAddress);
	if (lpCallParams == NULL)

⌨️ 快捷键说明

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