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

📄 tapiconn._cp

📁 串口调试助手的源代码
💻 _CP
📖 第 1 页 / 共 5 页
字号:
// Modify by FangHong, 1997

#include "stdafx.h"
#include "tapiconn.h"

//BOOL	bAnswerCallInProgress;

//DWORD	m_dwAsyncID;	// id of pending async operation

DWORD	m_dwCallState = 0;
char  m_szDisplayableAddress[1024] = "";
//char  m_szDialableAddress[1024] = "";
BOOL  m_bCallStateReceived;

LPVOID	g_lpDeviceConfig = NULL;

// Possible return error for resynchronization functions.
#define WAITERR_WAITABORTED  1

// Constant used in WaitForCallState when any new
// callstate message is acceptable.
#define I_LINECALLSTATE_ANY 0

// Wait up to 30 seconds for an async completion.
#define WAITTIMEOUT 30000

// Possible return error for resynchronization functions.
#define WAITERR_WAITABORTED  1
#define WAITERR_WAITTIMEDOUT 2

// Structures needed to handle special non-dialable characters.
#define g_sizeofNonDialable (sizeof(g_sNonDialable)/sizeof(g_sNonDialable[0]))

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"
	},
};

// A pointer to my class because TAPI needs a callback
BOOL	CTapiConnection::m_bTapiInUse = FALSE;
DWORD	CTapiConnection::m_dwRequestedID;
LONG	CTapiConnection::m_lAsyncReply;
BOOL	CTapiConnection::m_bReplyRecieved;
CTapiConnection*	CTapiConnection::m_this = NULL;

// 
// Constructor
//
CTapiConnection::CTapiConnection()
{
	m_bShuttingDown = FALSE;
	m_bStoppingCall = FALSE;
	m_bInitializing = FALSE;
	m_dwNumDevs = 0;
	m_hCall = NULL;
	m_hLine = NULL;
	m_dwDeviceID = 0;
	m_hLineApp = NULL;

	// Comm Ctrls 
	m_bConnected = FALSE;

	m_pNotifyWnd = NULL;
	m_hCommFile = NULL;
	m_dwReadThreadID  = 0;
	m_dwWriteThreadID = 0;
	m_hReadThread = NULL;
	m_hWriteThread = NULL;
	m_hCloseEvent = NULL;

	m_this = this;
};

//
// Destructor
//
CTapiConnection::~CTapiConnection()
{
	m_bInitialized = FALSE;
	ShutdownTAPI();
};

//
//  FUNCTION: BOOL Create()
//
//  PURPOSE: Initializes TAPI
//
BOOL	CTapiConnection::Create(LPCTSTR  szPhoneNumber)
{
	long	lReturn;
	BOOL	bTryReInit = TRUE;

	// If we're already initialized, then initialization succeeds.
	if (m_hLineApp)
		return  TRUE;

	// If we're in the middle of initializing, then fail, we're not done.
	if (m_bInitializing)
		return FALSE;

	m_bInitializing = TRUE;

	// Initialize TAPI
	do
	{
		lReturn = ::lineInitialize(&m_hLineApp,
			::AfxGetInstanceHandle(),
			lineCallbackFunc,
			::AfxGetAppName(),
			&m_dwNumDevs);

		// If we get this error, its because some other app has yet
		// to respond to the REINIT message.  Wait 5 seconds and try
		// again.  If it still doesn't respond, tell the user.
		if (lReturn == LINEERR_REINIT)
		{
			if (bTryReInit)
			{
				MSG	msg; 
				DWORD	dwTimeStarted;

				dwTimeStarted = GetTickCount();
				while (GetTickCount() - dwTimeStarted < 5000)
				{
					if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
					{
						::TranslateMessage(&msg);
						::DispatchMessage(&msg);
					}
				}            
				bTryReInit = FALSE;
				continue;
			}
			else
			{
				MessageBox(NULL,
					"A change to the system configuration requires that "
					"all Telephony applications relinquish their use of "
					"Telephony before any can progress.  "
					"Some have not yet done so.", "Warning", MB_OK);
				m_bInitializing = FALSE;
				return  FALSE;
			}
		}

		if (lReturn == LINEERR_NODEVICE)
		{
			if (HandleNoDevicesInstalled())
				continue;
			else
			{
				TRACE0("No devices installed.\n");
				m_bInitializing = FALSE;
				return  FALSE;
			}
		}

		if (m_dwNumDevs == 0)
		{
			::AfxMessageBox("There are no telephony devices installed.");
			m_bInitializing = FALSE;
			return  FALSE;
		}

		if (HandleLineErr(lReturn))
			continue;
		else
		{
			TRACE0("lineInitialize unhandled error\n");
			m_bInitializing = FALSE;
			return  FALSE;
		}
	}
	while(lReturn != TAPISUCCESS);

	TRACE0("Tapi initialized.\n");

	// If the user furnished a phone number copy it over.
	if (szPhoneNumber)
		::strcpy(m_szPhoneNumber, szPhoneNumber);

	m_bInitializing = FALSE;
	return  TRUE;
}

//
//  FUNCTION: DialCall()
//
//  PURPOSE: Get a number from the user and dial it.
//
BOOL	CTapiConnection::DialCall(LPCTSTR  szPhoneNumber)
{
	// if already connected or in a pending state, do nothing
//	if (m_bConnected || m_dwAsyncID)
//		return  FALSE;

	long	lReturn;
	LPLINEADDRESSSTATUS	lpLineAddressStatus = NULL;
	LPLINEDEVCAPS	lpLineDevCaps = NULL;

	if (m_bTapiInUse)
	{
		::AfxMessageBox("A call is already being handled.");
		return  FALSE;
	}

	// Make sure TAPI is initialized properly
	if (!m_hLineApp)
	{
		if (!Create(NULL))
			return  FALSE;
	}

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

	// We now have a call active. Prevent future calls.
	m_bTapiInUse = TRUE;

	// Get a phone number from the user.
	if (szPhoneNumber == NULL)
	{
		if (m_szPhoneNumber == NULL)
		{
			HangupCall();
			goto  LABEL_DELETEBUFFERS;
		}
	}
	else 
		strcpy(m_szPhoneNumber, szPhoneNumber);

	// Negotiate the API version to use for this device.
	m_dwAPIVersion = I_lineNegotiateAPIVersion(m_dwDeviceID);
	if (m_dwAPIVersion == 0)
	{
		MessageBox(NULL,
			"Line Version unsupported by this Sample",
			"Unable to Use Line",MB_OK);
		HangupCall();
		goto  LABEL_DELETEBUFFERS;
	}


	// Need to check the DevCaps to make sure this line is usable.
	// The 'Dial' dialog checks also, but better safe than sorry.
	lpLineDevCaps = I_lineGetDevCaps(lpLineDevCaps,
		m_dwDeviceID, m_dwAPIVersion);

	// Get the line to use
// 	lpLineDevCaps = GetDeviceLine(&m_dwAPIVersion, lpLineDevCaps);

	// Need to check the DevCaps to make sure this line is usable.
	if (lpLineDevCaps == NULL)
	{
		HangupCall();

		MessageBox(NULL,
            "Error on Requested line",
            "Unable to Use Line",MB_OK);
		goto  LABEL_DELETEBUFFERS;
	}

	if (!(lpLineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE))
	{
		HangupCall();
		::AfxMessageBox("The selected line doesn't support VOICE capabilities");
		goto  LABEL_DELETEBUFFERS;
	}

    if (!(lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM))
    {
        HangupCall();
        MessageBox(NULL,
            "Error on Requested line",
            "The selected line doesn't support DATAMODEM capabilities",
            MB_OK);
        goto LABEL_DELETEBUFFERS;
    }

	// Does this line have the capability to make calls?
	if (!(lpLineDevCaps->dwLineFeatures & LINEFEATURE_MAKECALL))
	{
        HangupCall();
		::AfxMessageBox("The selected line doesn't support MAKECALL capabilities");
		goto  LABEL_DELETEBUFFERS;
	}

	// Open the Line for an outgoing call.
	do
	{
		lReturn = ::lineOpen(m_hLineApp, m_dwDeviceID, &m_hLine,
			m_dwAPIVersion, 0, 0,
//			LINECALLPRIVILEGE_NONE, 0, 0);
			LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_DATAMODEM, NULL);

		if ((lReturn == LINEERR_ALLOCATED) || (lReturn == LINEERR_RESOURCEUNAVAIL))
		{
			HangupCall();
			TRACE0("Line is already in use by a non-TAPI application "
				"or by another TAPI Service Provider.\n");
			goto  LABEL_DELETEBUFFERS;
		}

		if (HandleLineErr(lReturn))
			continue;
		else
		{
			TRACE0("Unable to Use Line\n");
			HangupCall();
			goto  LABEL_DELETEBUFFERS;
		}
	}
	while (lReturn != TAPISUCCESS);

	// Tell the service provider that we want all notifications that
	// have anything to do with this line.
	do
	{
		// Set the messages we are interested in.
		// Note that while most applications aren't really interested
		// in dealing with all of the possible messages, its interesting
		// to see which come through the callback for testing purposes.

		lReturn = ::lineSetStatusMessages(m_hLine,
			LINEDEVSTATE_OTHER	|
			LINEDEVSTATE_RINGING	|
			LINEDEVSTATE_CONNECTED	|	// Important state!
			LINEDEVSTATE_DISCONNECTED	|	// Important state!
			LINEDEVSTATE_MSGWAITON	|
			LINEDEVSTATE_MSGWAITOFF	|
			LINEDEVSTATE_INSERVICE	|
			LINEDEVSTATE_OUTOFSERVICE	|	// Important state!
			LINEDEVSTATE_MAINTENANCE	|	// Important state!
			LINEDEVSTATE_OPEN	|
			LINEDEVSTATE_CLOSE	|
			LINEDEVSTATE_NUMCALLS	|
			LINEDEVSTATE_NUMCOMPLETIONS	|
			LINEDEVSTATE_TERMINALS	|
			LINEDEVSTATE_ROAMMODE	|
			LINEDEVSTATE_BATTERY	|
			LINEDEVSTATE_SIGNAL	|
			LINEDEVSTATE_DEVSPECIFIC	|
			LINEDEVSTATE_REINIT	|	// Not allowed to disable this.
			LINEDEVSTATE_LOCK	|
			LINEDEVSTATE_CAPSCHANGE	|
			LINEDEVSTATE_CONFIGCHANGE	|
			LINEDEVSTATE_COMPLCANCEL,

			LINEADDRESSSTATE_OTHER	|
			LINEADDRESSSTATE_DEVSPECIFIC	|
			LINEADDRESSSTATE_INUSEZERO	|
			LINEADDRESSSTATE_INUSEONE	|
			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 != TAPISUCCESS);

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

	// 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");
		HangupCall();
		MessageBox(NULL,
			"Requested line is already in use",
			"Unable to Use Line",MB_OK);
		goto  LABEL_DELETEBUFFERS;
	}

	// If the line was configured in the 'Dial' dialog, then
	// we need to actually complete the configuration.
	if (g_lpDeviceConfig)
		::lineSetDevConfig(m_dwDeviceID, g_lpDeviceConfig,
			m_dwSizeDeviceConfig, "comm/datamodem");
/*
	// Start dialing the number
	if (MakeTheCall(lpLineDevCaps, m_szPhoneNumber))
		TRACE0("lineMakeCall succeeded.\n");
	else
	{
		TRACE0("lineMakeCall failed.\n");
		HangupCall();
	}
*/

    // Start dialing the number
    if (DialCallInParts(lpLineDevCaps, m_szPhoneNumber,//m_szDialableAddress,
            /*m_szDisplayableAddress*/m_szPhoneNumber + 1))
    {
        TRACE0("DialCallInParts succeeded.\n");
    }
    else
    {
        TRACE0("DialCallInParts failed.\n");
        HangupCall();
        goto  LABEL_DELETEBUFFERS;
    }

LABEL_DELETEBUFFERS:
    if (lpLineAddressStatus)
        LocalFree(lpLineAddressStatus);

	if (lpLineDevCaps)
		::LocalFree(lpLineDevCaps);

	return  m_bTapiInUse;
}

//
//  FUNCTION: void GetDeviceLine()
//
//  PURPOSE: Gets the first available line device.
//

⌨️ 快捷键说明

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