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

📄 tapiline.cpp

📁 串口调试助手的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	{
		TRACE0("Create Call Params fail !\n");
		return  FALSE;
	}

	// Determine which special characters the service provider
	// does *not* handle so we can handle them manually.
	// Keep list of unhandled characters in szFilter.
	DWORD	dwDevCapFlags = GetDevCapFlags();	// SP handled characters.
	for (int  i = 0; i < nSizeNonDialable; ++ i)
	{
		if ((dwDevCapFlags & g_sNonDialable[i].dwDevCapFlag) == 0)
		{
			strcat(szFilter, g_sNonDialable[i].szToken);
		}
	}

	// szFilter now contains the set of tokens which delimit dialable substrings
	// Setup the strings for substring dialing.                      
	nAddressLength = strlen(lpszAddress);
	lpDS = lpszDialableSubstring = (LPSTR)new  TCHAR[nAddressLength + 1];
	if (lpszDialableSubstring == NULL)
	{
		TRACE1("LocalAlloc failed: %lu\n", ::GetLastError());
		CTAPIError::HandleNoMem();
		bRetVal = FALSE;
		goto  LABEL_ERREXIT;
	}

	// Lets start dialing substrings!
	while (nCurrentAddress < nAddressLength)
	{
//	LABEL_RETRYAFTERERROR:
		// Find the next undialable character
		i = strcspn(&lpszAddress[nCurrentAddress], szFilter);

		// Was there one before the end of the Address string?
		if (i + nCurrentAddress < nAddressLength)
		{
			// Make sure this device can handle partial dial.
			if (! (lpAddressCaps->dwAddrCapFlags & LINEADDRCAPFLAGS_PARTIALDIAL))
			{
				::MessageBox(NULL,
					"This line doesn't support partial dialing.\n",
					"Warning",MB_OK);
				bRetVal = FALSE;
				goto  LABEL_ERREXIT;
			}
			// Remember what the unhandled character is so we can handle it.
			chUnhandledCharacter = lpszAddress[nCurrentAddress+i];
            
			// Copy the dialable string to the Substring.
			memcpy(lpszDialableSubstring, &lpszAddress[nCurrentAddress], i);

			// Terminate the substring with a ';' to signify the partial dial.
			lpszDialableSubstring[i] = ';';
			lpszDialableSubstring[i + 1] = '\0';
            
			// Increment the address for next iteration.
			nCurrentAddress += i + 1;
		}
		else	// No more partial dials. Dial the rest of the Address.
		{
			lpszDialableSubstring = (LPSTR)&lpszAddress[nCurrentAddress];
			chUnhandledCharacter = 0;
			nCurrentAddress = nAddressLength;
		}
        
//		do
//		{                   
			if (bFirstDial)
			{
//				HCALL	hCall;
				TRACE0("..make call !\n");

				lReturn = ::lineMakeCall(m_hLine,
					&m_hCall, lpszDialableSubstring,
					0, lpCallParams);
				TRACE0("make call **OK** !\n");

//				ASSERT(hCall == m_hCall);
//				ASSERT(lReturn == m_dwAsyncID);
			}
			else
			{
				lReturn = ::lineDial(m_hCall,
					lpszDialableSubstring, 0);
			}

/*				lReturn = WaitForReply( 
					::lineMakeCall(m_hLine,
						&m_hCall, lpszDialableSubstring,
						0, lpCallParams));
			else
				lReturn = WaitForReply(
					::lineDial(m_hCall,
						lpszDialableSubstring, 0));

			switch (lReturn)
			{
			// We should not have received these errors because of the
			// prefiltering strategy, but there may be some ill-behaved
			// service providers which do not correctly set their
			// devcapflags.  Add the character corresponding to the error
			// to the filter set and retry dialing.
			case LINEERR_DIALBILLING:
			case LINEERR_DIALDIALTONE:
			case LINEERR_DIALQUIET:
			case LINEERR_DIALPROMPT:
				TRACE0("Service Provider incorrectly sets dwDevCapFlags\n");

				for (i = 0; i < nSizeNonDialable; ++ i)
                        if (lReturn == g_sNonDialable[i].lError)
                        {
                            strcat(szFilter, g_sNonDialable[i].szToken);
                        }
                    goto  LABEL_RETRYAFTERERROR;
//				break;

			case WAITERR_WAITABORTED:
                    TRACE0("While Dialing, WaitForReply aborted.\n");
				bRetVal = FALSE;
                    goto  LABEL_ERREXIT;
//				break;
			}*/
			if (lReturn < 0)
			{
				if (!CTAPIError::HandleLineErr(lReturn))
				{
					if (bFirstDial)
						TRACE1("lineMakeCall unhandled error: %lx\n", lReturn);
					else
						TRACE1("lineDial unhandled error: %lx\n", lReturn);
					bRetVal = FALSE;
					goto  LABEL_ERREXIT;
				}
			}
			else
			{
				TRACE0("REPLY_MAKECALL\n");
				m_dwAsyncID = lReturn;
				m_WaitReplyType = REPLY_MAKECALL;
			}
//		}
//		while (lReturn != TAPISUCCESS);
        
		bFirstDial = FALSE;
                                
		// The dial was successful; now handle characters the service
		// provider didn't (if any).
		if (chUnhandledCharacter)
		{
			LPTSTR	lpMsg = _T("");

			// First, wait until we know we can continue dialing.  While the
			// last string is still pending to be dialed, we can't dial another.
			while (TRUE)
			{
				LPLINECALLSTATUS	lpLineCallStatus = I_lineGetCallStatus(m_hCall);
				if (lpLineCallStatus == NULL)
				{
					bRetVal = FALSE;	
					goto  LABEL_ERREXIT;
				}

				DWORD	dwCallFeatures = lpLineCallStatus->dwCallFeatures;
				delete  lpLineCallStatus;

				// Does CallStatus say we can dial now?
				if (dwCallFeatures & LINECALLFEATURE_DIAL)
				{
					TRACE0("Ok to continue dialing.\n");
					break;
				}                
				// We can't dial yet, so wait for a CALLSTATE message
				TRACE0("Waiting for dialing to be enabled.\n");

				if (CTAPIConnection::WaitForCallState(I_LINECALLSTATE_ANY) != TAPISUCCESS)
				{
					bRetVal = FALSE;
					goto  LABEL_ERREXIT;
				}
			}

			for (i = 0; i < nSizeNonDialable; ++ i)
				if (chUnhandledCharacter == g_sNonDialable[i].szToken[0])
					lpMsg = g_sNonDialable[i].szMsg;
                    
			::MessageBox(NULL, lpMsg, "Dialing Paused", MB_OK);
		}
	}	// continue dialing until we dial all Dialable Substrings.

LABEL_ERREXIT:
	if (lpDS)
		delete  lpDS;
	if (lpCallParams != NULL)
		delete  lpCallParams;
	if (lpAddressCaps != NULL)
		delete  lpAddressCaps;

	return  bRetVal;
}

// - There will only be one outgoing address per line.
BOOL	CTAPILine::WaitCall(void)
{
	if (CTAPIConnection::m_dwAnswerCallWait != (DWORD)-1)
	{
		TRACE1("line %d is waiting call !", CTAPIConnection::m_dwAnswerCallWait);
		return  FALSE;
	}

	if (m_WaitReplyType != REPLY_NONE)
	{
		TRACE0("Line is used !\n");
		return  FALSE;
	}
	// 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)
	{
		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;
	}
	CTAPIConnection::m_dwAnswerCallWait = m_dwDeviceID;

	//------
	delete  lpLineAddressStatus;
	//------
	return  TRUE;
}

LPCTSTR	CTAPILine::GetLineName(void)
{
	LPCTSTR	szLineUnnamed = _T("线路无名");
	LPCTSTR	szLineNameEmpty = _T("线路名为空");
	DWORD	dwDefaultDevice = MAXDWORD;
        
	LPCTSTR	lpszLineName = _T("");
	if ((m_lpLineDevCaps->dwLineNameSize) &&
		(m_lpLineDevCaps->dwLineNameOffset) &&
		(m_lpLineDevCaps->dwStringFormat == STRINGFORMAT_ASCII))
	{
		// This is the name of the device.
		lpszLineName = ((LPTSTR)m_lpLineDevCaps) +
			m_lpLineDevCaps->dwLineNameOffset;

		if (lpszLineName[0] != '\0')
		{
			// Reverse indented to make this fit
			// Make sure the device name is null terminated.
			if (lpszLineName[m_lpLineDevCaps->dwLineNameSize - 1] != '\0')
			{
				// If the device name is not null terminated, null
				// terminate it.  Yes, this looses the end character.
				// Its a bug in the service provider.
				*((LPTSTR)lpszLineName + m_lpLineDevCaps->dwLineNameSize - 1) = '\0';
				TRACE1("Device name for device 0x%lx is not null terminated.\n",
					m_dwDeviceID);
			}
		}
		else	// Line name started with a NULL.
			lpszLineName = szLineNameEmpty;
	}
	else	// DevCaps doesn't have a valid line name.  Unnamed.
		lpszLineName = szLineUnnamed;

	return  lpszLineName;
}

LPVOID	CTAPILine::CallConfigDialogEdit(HWND  hMainWnd, DWORD&  dwSizeDeviceConfig)
{
	long	lReturn;
	LPVARSTRING	lpVarString;
	int	nSizeofVarString = sizeof(VARSTRING);
	while (TRUE)
	{
		// Allocate the VARSTRING structure
		lpVarString = (LPVARSTRING)new  BYTE[nSizeofVarString];
		if (lpVarString == NULL)
			return  NULL;

		lpVarString->dwTotalSize = nSizeofVarString;
		lReturn = ::lineGetDevConfig(m_dwDeviceID, lpVarString, 
			"comm/datamodem");

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

		if ((lpVarString->dwNeededSize) <= (lpVarString->dwTotalSize))
		{
			break;
		}
		else
		{
			nSizeofVarString = lpVarString->dwNeededSize;
			delete  lpVarString;
		}
	}
	dwSizeDeviceConfig = lpVarString->dwStringSize;

	// The extra byte allocated is in case dwStringSize is 0.
	LPVOID	lpDeviceConfig = (LPVOID)new  BYTE[dwSizeDeviceConfig + 1];
	if (lpDeviceConfig == NULL)
	{
		delete  lpVarString;
		return  NULL;
	}
	else
	{
		::memcpy(lpDeviceConfig,
			((LPBYTE)lpVarString + lpVarString->dwStringOffset),
			dwSizeDeviceConfig);
	}
	delete  lpVarString;
	lpVarString = NULL;

	// Next make the lineConfigDialogEdit call.

	// Note that we determine the initial size of the VARSTRING
	// structure based on the known size of the existing configuration
	// information.  I make the assumption that this configuration
	// information is very unlikely to grow by more than 5K or by
	// more than 5 times.  This is a *very* conservative number.
	// We do *not* want lineConfigDialogEdit to fail just because there 
	// wasn't enough room to stored the data.  This would require the user
	// to go through configuration again and that would be annoying.
	nSizeofVarString = 5 * dwSizeDeviceConfig + 5000;
	while (TRUE)
	{
		// Allocate the VARSTRING structure
		lpVarString = (LPVARSTRING)new  BYTE[nSizeofVarString];
		if (lpVarString == NULL)
			return  NULL;

		lpVarString->dwTotalSize = nSizeofVarString;
		lReturn = ::lineConfigDialogEdit(m_dwDeviceID, hMainWnd, "comm/datamodem",
			lpDeviceConfig, dwSizeDeviceConfig, lpVarString);

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

		if ((lpVarString->dwNeededSize) <= (lpVarString->dwTotalSize))
		{
			break;
		}
		else
		{
			// We had been conservative about making sure the structure was 
			// big enough.  Unfortunately, not conservative enough.  Hopefully, 
			// this will not happen a second time because we are *DOUBLING* 
			// the NeededSize.
			::MessageBox(NULL,
				"Internal Error: Unable to set line configuration.\n"
				"Please try again.",
				"Oops", MB_OK);
			nSizeofVarString = (lpVarString->dwNeededSize) * 2;
		}
	}
	delete  lpDeviceConfig;
	lpDeviceConfig = NULL;

	// Store the configuration information into a global structure
	// so it can be set at a later time.
	dwSizeDeviceConfig = lpVarString->dwStringSize;

	lpDeviceConfig = (LPVOID)new  BYTE[dwSizeDeviceConfig + 1];
	if (lpDeviceConfig == NULL)
	{
		delete  lpVarString;
		return  NULL;
	}
	else
	{
		::memcpy(lpDeviceConfig,
			((LPBYTE)lpVarString + lpVarString->dwStringOffset),
			dwSizeDeviceConfig);
	}
	delete  lpVarString;
	return  lpDeviceConfig;
}

⌨️ 快捷键说明

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