www.pudn.com > ppc_Cellcore.rar > ExTAPIAsync.cpp


// 
// Copyright (c) Microsoft Corporation.  All rights reserved. 
// 
// 
// Use of this source code is subject to the terms of the Microsoft end-user 
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT. 
// If you did not accept the terms of the EULA, you are not authorized to use 
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your 
// install media. 
// 
// 
 
// ExTAPIASync.CPP 
// 
// Sample that demonstrates some asynchronous functionality of ExTAPI 
// 
// NOTE: ExTAPI is a privileged API and any application using it must 
// be signed using a priviliged certificate. 
// 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include "newres.h" 
#include "resource.h" 
 
// some definitons 
#define ARRAY_LENGTH(x)			(sizeof(x)/sizeof((x)[0])) 
#define TAPI_API_LOW_VERSION	0x00020000 
#define TAPI_API_HIGH_VERSION	0x00020000 
#define EXT_API_LOW_VERSION		0x00010000 
#define EXT_API_HIGH_VERSION	0x00010000 
#define REASONABLE_BUFFER		1024 
#define EINITFAILED				(-1) 
 
// global variables 
HINSTANCE	g_hInstance; 
TCHAR		g_szAppName[80]; 
TCHAR		g_szTitle[80]; 
HLINEAPP	g_hLineApp; 
HLINE		g_hLine; 
HWND		g_hwndOpList; 
HWND		g_hDlg; 
 
// function declarations 
BOOL InitExTAPI(); 
BOOL GetCurrentOperator(HWND hDlg); 
BOOL GetAvailableOperators(HWND hDlg); 
DWORD GetTSPLineDeviceID(const HLINEAPP hLineApp, const DWORD dwNumberDevices,  
						 const DWORD dwAPIVersionLow, const DWORD dwAPIVersionHigh,  
						 const TCHAR* const psTSPLineName); 
BOOL CALLBACK MainDialogProc(const HWND hDlg, const UINT uiMessage,  
							 const WPARAM wParam, const LPARAM lParam); 
void CALLBACK TAPIProc(DWORD hDevice, DWORD dwMessage, DWORD dwInstance, 
					   DWORD dwParam1, DWORD dwParam2, DWORD dwParam3); 
BOOL InitDialog(const HWND hDlg, UINT nToolBarId); 
void RegisterNewOperator(); 
void CleanupLB(); 
 
// *************************************************************************** 
// Function Name: WinMain 
// 
// Purpose: Main entry point into the ExTAPIAsync program 
// 
// Arguments: Standard WinMain arguments 
// 
// Return Values: TRUE 
// 
// Description: 
//	Our WinMain function essentialy just pops up a Dialog box that displays 
//	the current operator and allows you to register with a new one 
 
int WINAPI WinMain (HINSTANCE hInstance, 
                    HINSTANCE hPreviousInstance, 
                    LPWSTR pszCommandLine, 
                    int nCommandShow) 
{ 
	int		iResult; 
 
	// Load strings 
	LoadString(hInstance, IDS_EXTAPIA_APPNAME, g_szAppName, ARRAY_LENGTH(g_szAppName)); 
	LoadString(hInstance, IDS_EXTAPIA_TITLE, g_szTitle, ARRAY_LENGTH(g_szTitle)); 
 
    // Use a globally named mutex to detect another instance of EXTAPIAsync 
    const HANDLE hMutex = CreateMutex(0, 0, TEXT("_EXTAPIA_EXE_MUTEX_")); 
 
    // check the result code 
	if(0 != hMutex) { 
        // First instance running?  Okay to proceed... 
		if(ERROR_ALREADY_EXISTS != GetLastError()) { 
			g_hInstance = hInstance; 
			InitCommonControls(); 
 
			// try to initialize ExTAPI 
			if (InitExTAPI()) { 
				iResult = DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_EXTAPIA_DLGMAIN), 
									0, (DLGPROC)MainDialogProc); 
				 
				if (iResult) { 
					MessageBox(NULL, TEXT("An error occurred while getting ExTAPI information"), 
							   TEXT("Error!!!"), MB_OK | MB_ICONERROR); 
				} 
				 
				// cleanup 
				lineClose(g_hLine); 
				lineShutdown(g_hLineApp); 
			} else { 
				MessageBox(NULL, TEXT("Unable to initialize ExTAPI"), 
						   TEXT("Error!!!"), MB_OK | MB_ICONERROR); 
			} 
		} 
        else { 
            // Already an instance running - attempt to switch to it and then exit 
            const HWND hWndExistingInstance = FindWindow(TEXT("Dialog"), g_szTitle); 
			VERIFY((0 == hWndExistingInstance) || SetForegroundWindow(hWndExistingInstance)); 
        } 
        VERIFY(CloseHandle(hMutex)); 
    } 
 
    return TRUE; 
} 
 
// *************************************************************************** 
// Function Name: InitExTAPI 
//  
// Purpose: Set up ExTAPI 
// 
// Arguments: none 
// 
// Return Values: 
//	TRUE if successful, FALSE otherwise 
// 
// Side Effects: 
//	Sets g_hLineApp and g_hLine 
//	Sets up TapiProc as a TAPI callback function 
//	 
// Description: 
//	This function initializes and opens lines for ExTAPI.  The HLINEAPP and HLINE 
//	will be used later to get and set operators. 
 
BOOL InitExTAPI() 
{ 
	DWORD dwNumDevs; 
	DWORD dwAPIVersion = TAPI_API_HIGH_VERSION; 
	LINEINITIALIZEEXPARAMS liep; 
	DWORD dwExtVersion; 
 
	// set the line init params 
	liep.dwTotalSize = sizeof(liep); 
	liep.dwOptions = LINEINITIALIZEEXOPTION_USEHIDDENWINDOW; 
	 
	if (lineInitializeEx(&g_hLineApp, g_hInstance, &TAPIProc, TEXT("EXTAPISAMPLE"),  
						 &dwNumDevs, &dwAPIVersion, &liep)) { 
		return FALSE; 
	} 
 
	// get the device ID 
	DWORD dwTAPILineDeviceID = GetTSPLineDeviceID(g_hLineApp, dwNumDevs,  
												  TAPI_API_LOW_VERSION,  
												  TAPI_API_HIGH_VERSION,  
												  CELLTSP_LINENAME_STRING); 
 
	// error getting the line device ID? 
	if (0xffffffff == dwTAPILineDeviceID) { 
		lineShutdown(g_hLineApp); 
		return FALSE; 
	} 
 
	// now try and open the line 
	const DWORD dwMediaMode = LINEMEDIAMODE_DATAMODEM | LINEMEDIAMODE_INTERACTIVEVOICE; 
 
	if(lineOpen(g_hLineApp, dwTAPILineDeviceID,  
				&g_hLine, dwAPIVersion, 0, 0,  
				LINECALLPRIVILEGE_OWNER, dwMediaMode, 0)) { 
		lineShutdown(g_hLineApp); 
		return FALSE; 
	} 
 
	// set up ExTAPI 
	if (lineNegotiateExtVersion(g_hLineApp, dwTAPILineDeviceID,  
								dwAPIVersion, EXT_API_LOW_VERSION,  
								EXT_API_HIGH_VERSION, &dwExtVersion)) { 
		lineClose(g_hLine); 
		lineShutdown(g_hLineApp); 
		return FALSE; 
	} 
 
	return TRUE; 
} 
 
// *************************************************************************** 
// Function Name: GetTSPLineDeviceID 
// 
// Purpose: To get a TSP Line Device ID 
// 
// Arguments: 
//	hLineApp = the HLINEAPP returned by lineInitializeEx 
//	dwNumberDevices = also returned by lineInitializeEx 
//	dwAPIVersionLow/High = min version of TAPI that we need 
//	psTSPLineName = "Cellular Line" 
// 
// Return Values: Current Device ID 
// 
// Description: 
//	This function returns the device ID of a named TAPI TSP.  The Device ID is  
//	used in the call to lineOpen 
 
DWORD GetTSPLineDeviceID(const HLINEAPP hLineApp,  
						 const DWORD dwNumberDevices,  
						 const DWORD dwAPIVersionLow,  
						 const DWORD dwAPIVersionHigh,  
						 const TCHAR* const psTSPLineName) 
{ 
	DWORD dwReturn = 0xffffffff; 
	for(DWORD dwCurrentDevID = 0 ; dwCurrentDevID < dwNumberDevices ; dwCurrentDevID++) 
	{ 
		DWORD dwAPIVersion; 
		LINEEXTENSIONID LineExtensionID; 
		if(0 == lineNegotiateAPIVersion(hLineApp, dwCurrentDevID,  
										dwAPIVersionLow, dwAPIVersionHigh,  
										&dwAPIVersion, &LineExtensionID)) { 
			LINEDEVCAPS LineDevCaps; 
			LineDevCaps.dwTotalSize = sizeof(LineDevCaps); 
			if(0 == lineGetDevCaps(hLineApp, dwCurrentDevID,  
								   dwAPIVersion, 0, &LineDevCaps)) { 
				BYTE* pLineDevCapsBytes = new BYTE[LineDevCaps.dwNeededSize]; 
				if(0 != pLineDevCapsBytes) { 
					LINEDEVCAPS* pLineDevCaps = (LINEDEVCAPS*)pLineDevCapsBytes; 
					pLineDevCaps->dwTotalSize = LineDevCaps.dwNeededSize; 
					if(0 == lineGetDevCaps(hLineApp, dwCurrentDevID,  
										   dwAPIVersion, 0, pLineDevCaps)) { 
						if(0 == _tcscmp((TCHAR*)((BYTE*)pLineDevCaps+pLineDevCaps->dwLineNameOffset), psTSPLineName)) { 
							dwReturn = dwCurrentDevID; 
						} 
					} 
					delete[]  pLineDevCapsBytes; 
				} 
			} 
		} 
	} 
	return dwReturn; 
} 
 
// *************************************************************************** 
// Function Name: MainDialogProc 
//  
// Purpose: Message Handler for ExTAPIAsync Dialog Box 
// 
// Arguments: Standard Dialog Procedure Arguments 
// 
// Return Values: 
//	EINITFAILED - One of the components in the dialog box could not be initialized 
//	0 - success 
// 
// Side Effects: 
//	Sets g_hDlg and g_hwndOpList 
//	 
// Description: 
//	Dialog Procedure for the main ExTAPIAsync Dialog.  Displays the current 
//	operator and a list of available operators.  Allows the user to try and register 
//	with a different operator. 
 
BOOL CALLBACK MainDialogProc(const HWND hDlg, const UINT uiMessage,  
							 const WPARAM wParam, const LPARAM lParam) 
{ 
	BOOL	bProcessedMsg = TRUE; 
 
	switch(uiMessage) 
	{ 
		case WM_INITDIALOG: 
			if (!InitDialog(hDlg, IDR_EXTAPIA_DLGMENU)) { 
				EndDialog(hDlg, EINITFAILED); 
				return TRUE; 
			} 
 
			// store the hDlg 
			g_hDlg = hDlg; 
			 
			// get current operator 
			if (!GetCurrentOperator(hDlg)) { 
				EndDialog(hDlg, EINITFAILED); 
				return TRUE; 
			} 
 
			// get a handle to the listbox 
			VERIFY(g_hwndOpList = GetDlgItem(hDlg, IDC_EXTAPIA_AVAILOP)); 
			 
			// get available operators 
			if (!GetAvailableOperators(hDlg)) { 
				CleanupLB(); 
				EndDialog(hDlg, EINITFAILED); 
				return TRUE; 
			} 
 
			// set the currently selected item 
			SendMessage(g_hwndOpList, LB_SETCURSEL, 0, 0); 
 
			break; 
 
		case WM_COMMAND: 
			switch (wParam) {			 
				case IDM_EXTAPIA_QUIT: 
					CleanupLB(); 
					EndDialog(hDlg, 0); 
					break; 
 
				case IDM_EXTAPIA_REG: 
					{ 
						RegisterNewOperator(); 
						break; 
					} 
 
				default: 
					bProcessedMsg = FALSE; 
					break; 
			} 
			break; 
		 
		default: 
			bProcessedMsg = FALSE; 
			break; 
	} 
 
	return bProcessedMsg; 
} 
 
// *************************************************************************** 
// Function Name: InitDialog 
//  
// Purpose: Sizes a dialog box to be full screen and adds the menus 
// 
// Arguments: 
//	hDlg = the HWND of the dialog box 
//	nToolBarId = the ID of the menu bar to add 
// 
// Return Values: 
//	TRUE if successful, FALSE otherwise 
// 
// Description: 
//	This function simply takes an HWND for a dialog, makes it full screen, adds 
//	a menu bar, and sets the title bar to be the title of the application. 
 
BOOL InitDialog(const HWND hDlg, UINT nToolBarId) 
{ 
	// Specify that the dialog box should stretch full screen 
	SHINITDLGINFO shidi; 
	ZeroMemory(&shidi, sizeof(shidi)); 
	shidi.dwMask = SHIDIM_FLAGS; 
	shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN; 
	shidi.hDlg = hDlg; 
 
	// set up Soft Keys menu 
	SHMENUBARINFO mbi; 
	ZeroMemory(&mbi, sizeof(SHMENUBARINFO)); 
	mbi.cbSize = sizeof(SHMENUBARINFO); 
	mbi.hwndParent = hDlg; 
	mbi.nToolBarId = nToolBarId; 
	mbi.hInstRes = g_hInstance; 
 
	// If we could not initialize the dialog box, return an error 
	if (!(SHInitDialog(&shidi) && SHCreateMenuBar(&mbi))) { 
		return FALSE; 
	} 
 
	// set the title bar 
	VERIFY(SetWindowText(hDlg, g_szTitle)); 
 
	// In order to make Back work properly, it's necessary to  
	// override it and then call the appropriate SH API 
	(void)SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK,  
					  MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY,  
								 SHMBOF_NODEFAULT | SHMBOF_NOTIFY)); 
 
	return TRUE; 
} 
 
// *************************************************************************** 
// Function Name: TAPIProc 
//  
// Purpose: Callback function for asynchronous TAPI calls 
// 
// Arguments: Standard TAPI callback arguments 
// 
// Return Values: None 
// 
// Description: 
//	Normally, this function would respond to any messages created by calls to 
//	asynchronous TAPI functions.  One would definitely want to keep track of the 
//	request numbers so they could be matched to their replies.  However, since this  
//	program only has one asynchronous call, we just assume that anything that passes 
//	through here was a reply to that call. 
 
void CALLBACK TAPIProc(DWORD hDevice, DWORD dwMessage, DWORD dwInstance, 
					   DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) 
{ 
	// since we only made one asynch request, we just want to see if it was 
	// successful or not.  A dwParam2 of 0 indicates success. 
	if (dwMessage == LINE_REPLY) { 
		if (!dwParam2) { 
			MessageBox(g_hDlg, TEXT("LINE_REPLY: Success!"),  
					   g_szTitle, MB_OK | MB_ICONINFORMATION); 
		} else { 
			MessageBox(g_hDlg, TEXT("LINE_REPLY: Failure"),  
					   g_szTitle, MB_OK | MB_ICONERROR); 
		} 
		// Update the Current Operator text box 
		GetCurrentOperator(g_hDlg); 
	} 
} 
 
// *************************************************************************** 
// Function Name: GetCurrentOperator 
//  
// Purpose: Get the current operator and update the dialog display 
// 
// Arguments: 
//	hDlg - the dialog containing the IDC_EXTAPIA_CUROP control 
// 
// Return Values: 
//	TRUE if successful, FALSE otherwise 
// 
// Side Effects: 
//	Updates the text for control IDC_EXTAPIA_CUROP 
// 
// Description: 
//	This function simply calls the lineGetCurrentOperator function and updates 
//	the display with the results. 
 
BOOL GetCurrentOperator(HWND hDlg) 
{ 
	LINEOPERATOR CurrentOperator; 
	if (lineGetCurrentOperator(g_hLine, &CurrentOperator)) { 
		return FALSE; 
	} 
	SetDlgItemText(hDlg, IDC_EXTAPIA_CUROP, CurrentOperator.lpszLongName); 
 
	return TRUE; 
} 
 
// *************************************************************************** 
// Function Name: GetAvailableOperators 
//  
// Purpose: Get the available operators and update the dialog display 
// 
// Arguments: 
//	hDlg - the dialog containing the IDC_EXTAPIA_CUROP control 
// 
// Return Values: 
//	TRUE if successful, FALSE otherwise 
// 
// Side Effects: 
//	Updates the text in the listbox with HWND g_hwndOpList 
//	Allocates memory to copy the operator strings 
// 
// Description: 
//	This function simply calls the lineGetOperatorStatus function and updates 
//	the display with the results.  If there are more operators than can fit in pbInit 
//	it also temporarily allocates memory. 
 
BOOL GetAvailableOperators(HWND hDlg) 
{ 
	// set up the initial mega data structure 
	BYTE pbInit[REASONABLE_BUFFER]; 
	LPLINEOPERATORSTATUS plosOperatorStatus = (LPLINEOPERATORSTATUS)pbInit; 
	LPBYTE pLineOperatorStatusBytes = NULL; 
	LPTSTR lpszItemData; 
	DWORD dwNeededSize; 
	int iResult; 
 
	plosOperatorStatus->dwTotalSize = REASONABLE_BUFFER; 
	if (lineGetOperatorStatus(g_hLine, plosOperatorStatus)) { 
		return FALSE; 
	} 
 
	// check to see if our buffer was large enough 
	if (plosOperatorStatus->dwNeededSize >= plosOperatorStatus->dwTotalSize) { 
		// allocate a byte array and cast it to a LPLINEOPERATORSTATUS 
		dwNeededSize = plosOperatorStatus->dwNeededSize; 
		pLineOperatorStatusBytes = new BYTE[dwNeededSize]; 
		if (!pLineOperatorStatusBytes) { 
			return FALSE; 
		} 
		plosOperatorStatus = (LPLINEOPERATORSTATUS)pLineOperatorStatusBytes; 
		 
		// call lGOS again to fill the new structure 
		plosOperatorStatus->dwTotalSize = dwNeededSize; 
		if (lineGetOperatorStatus(g_hLine, plosOperatorStatus)) { 
			delete[] pLineOperatorStatusBytes; 
			return FALSE; 
		} 
	} 
 
	// set the pointer to the first available operator and iterate 
	LPLINEOPERATOR ploOperator; 
	DWORD dwOperatorNumber; 
	ploOperator = (LPLINEOPERATOR)((LPBYTE)plosOperatorStatus+(plosOperatorStatus->dwAvailableOffset)); 
	for(dwOperatorNumber = 0;  
		dwOperatorNumber < plosOperatorStatus->dwAvailableCount;  
		dwOperatorNumber++) { 
		// add the element to the listbox 
		iResult = SendMessage(g_hwndOpList, LB_ADDSTRING, 0, (LPARAM) ploOperator->lpszLongName); 
 
		// copy the lpszNumName and store the pointer as ItemData 
		if (iResult >= LB_OKAY) { 
			lpszItemData = _tcsdup(ploOperator->lpszNumName); 
			if (!lpszItemData) { 
				delete[] pLineOperatorStatusBytes; 
				return FALSE; 
			} 
			SendMessage(g_hwndOpList, LB_SETITEMDATA, iResult, (LPARAM) lpszItemData); 
		} else { 
			delete[] pLineOperatorStatusBytes; 
			return FALSE; 
		} 
 
		// increment the pointer 
		ploOperator++; 
	} 
 
	// cleanup 
	delete[] pLineOperatorStatusBytes; 
	return TRUE; 
} 
 
// *************************************************************************** 
// Function Name: RegisterNewOperator 
//  
// Purpose: call lineRegister on the currently selected operator 
// 
// Arguments: none 
// 
// Return Values: none 
// 
// Description: 
//	This function simply takes the currently selected member of g_hwndOpList and 
//	tries to register it as a new operator.  lineRegister is asynchronous, so the 
//	result of this call is posted to TAPIProc. 
 
void RegisterNewOperator() 
{ 
	LPTSTR lpszNumName; 
	int iCurSel, iResult; 
 
	iCurSel = SendMessage(g_hwndOpList, LB_GETCURSEL, 0, 0); 
	if (iCurSel != LB_ERR) { 
		// get the provider name 
		lpszNumName = (LPTSTR) SendMessage(g_hwndOpList, LB_GETITEMDATA,  
										   (WPARAM) iCurSel, (LPARAM) 0); 
 
		// now try to set the current provider 
		// normally we would store this ID and verify it in TAPIProc, but since we are 
		// only making one asynchronous request, we ignore this value... 
		iResult = lineRegister(g_hLine, LINEREGMODE_MANUAL,  
							   lpszNumName, LINEOPFORMAT_NUMERIC); 
	} else { 
		MessageBox(NULL, TEXT("Unable to get current selection"), 
				   TEXT("Error!!!"), MB_OK | MB_ICONERROR); 
	} 
 
} 
 
// *************************************************************************** 
// Function Name: CleanupLB 
//  
// Purpose: free the strings pointed to by a listbox's itemdata 
// 
// Arguments: none 
// 
// Return Values: none 
// 
// Description: 
//	This function simply iterates through the members of a listbox, gets their 
//	item data values, which should be pointers to strings, and frees them. 
 
void CleanupLB() 
{ 
	int iResult; 
	LPTSTR lpszNumName; 
	 
	// get the number of items in the listbox 
	iResult = SendMessage(g_hwndOpList, LB_GETCOUNT, 0, 0); 
	if (iResult != LB_ERR) { 
		for (int i = 0; i < iResult; i++) { 
			lpszNumName = (LPTSTR) SendMessage(g_hwndOpList, LB_GETITEMDATA, (WPARAM) i, (LPARAM) 0); 
			free(lpszNumName); 
		} 
	} 
}