www.pudn.com > datamode.zip > DATAMODE.C


// This code was designed as a simple example of TAPI.  By no means was 
// this designed to be an all inclusive example.  This code and example is  
// provided "AS IS" without warranty of any kind, either expressed or implied, 
// including but not limited to the implied warranties of merchantability  
// and/or fitness for a particular purpose. 
// 
// This was designed on Windows 95 with Microsoft MSVC 2.0 compiler. 
// This program will NOT run on WinNT and has not been tested on Win 3.1/3.11. 
// 
//	Files required to compile program : 
//		datamode.c 
//		tapi.h 
//		resource.h 
//		datamode.rc 
//		datamode.def 
//		tapi32.lib 
// 
//	Author 	: Mike Zercher 
//	Date	: 5/26/95 
// 
// This program and all related files are public domain and may be freely 
// distributed.  By using the program or any included part, the user assumes 
// full responsibility for it's proper use and may not hold the author liable 
// for any loss or damage.  If unable to accept this condition, the program 
// and all related parts may not be used and must be destroyed immediately. 
 
#include "windows.h" 
#include "tapi.h" 
#include "resource.h" 
 
LONG ConnectToData( HWND, LPTSTR ); 
void CALLBACK LineCallBackProc(DWORD hDevice,DWORD dwMessage,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2,DWORD dwParam3); 
BOOL WINAPI MainDialog(HWND hDlg, WORD msg, WORD wParam, LONG lParam); 
void SendStatus( HWND hWnd, LPTSTR OutputString ); 
void SetVariableProperties( HWND hWnd, DWORD hDevice ); 
 
#define tapiVersionCur                            (MAKELONG(4,1)) 
 
#define	TAPI_LINE_REPLY					5000 
#define TAPI_LINECALLSTATE_CONNECTED	5001 
#define TAPI_LINECALLSTATE_IDLE			5002 
#define TAPI_LINECALLSTATE_DISCONNECTED	5003 
#define TAPI_LINECALLSTATE_BUSY			5004 
#define TAPI_LINECALLSTATE_ACCEPTED		5005 
#define TAPI_LINECALLSTATE_PROCEEDING	5006 
#define TAPI_LINECALLSTATE_OFFERING		5007 
#define TAPI_LINECALLSTATE_DIALTONE		5008 
#define TAPI_LINECALLSTATE_DIALING		5009 
 
 
LINECALLPARAMS LineParams; 
DWORD lines; 
 
HINSTANCE hInst; 
HWND MainWin, ButtonWnd; 
HLINEAPP LineHandle = NULL; 
 
int PASCAL WinMain( HANDLE hInstance, HANDLE hPrev, LPSTR lpCmd, int nShow ) 
{ 
   	SetMessageQueue( 100 ); 
   	hInst = hInstance; 
	DialogBox( hInstance, MAKEINTRESOURCE( ID_MAIN_SCREEN ), NULL, MainDialog );  
   	return( FALSE ); 
} 
 
 
 
BOOL WINAPI MainDialog(HWND hDlg, WORD msg, WORD wParam, LONG lParam) 
{ 
 
	switch (msg) 
	{ 
		case WM_INITDIALOG: 
		{ 
			// Set the necessary properties to null 
			SetProp( hDlg, "HCALL", NULL ); 
			SetProp( hDlg, "HLINE", NULL ); 
			SetProp( hDlg, "HCOMM", NULL ); 
			break; 
		} 
 
		case WM_COMMAND: 
		{ 
 
			switch( wParam ) 
			{			 
				case IDOK:					// This is the exit routine. 
				{ 
					HCALL hCall; 
					HLINE hLine; 
					HANDLE hComm; 
 
					hCall = (HCALL)GetProp( hDlg, "HCALL" );	// Get the properties 
					hLine = (HLINE)GetProp( hDlg, "HLINE" ); 
					hComm = (HANDLE)GetProp( hDlg, "HCOMM" ); 
 
					if( hComm != NULL )							// is there a comm handle? 
					{ 
						CloseHandle( hComm );					// Yes, close it down. 
						SetProp( hDlg, "HCOMM", NULL );			// Set its value to NULL 
					} 
 
					if( hCall != NULL )							// is there a call present? 
					{ 
						lineDrop( hCall, NULL, 0 );				// Close down the line. 
						SetProp( hDlg, "HCALL", NULL );			// Set it's value to NULL 
					} 
 
					if( hLine != NULL )							// is the line open? 
					{ 
						lineClose( hLine );						// Yes, close it down 
						SetProp( hDlg, "HLINE", NULL );			// Set it to NULL 
					} 
 
					if( LineHandle != NULL )					//Was the line initialized? 
					{ 
						lineShutdown( LineHandle );				//Yes, shut it down 
						LineHandle = NULL;						// Set it to NULL 
					} 
					RemoveProp( hDlg, "HCALL" );				// Remove the properties 
					RemoveProp( hDlg, "HLINE" ); 
					RemoveProp( hDlg, "HCOMM" ); 
	   				EndDialog( hDlg, FALSE );					// Goodbye 
	   				break; 
   				} 
   				 
   				case ID_CALL: 
   				{ 
					// This is where the call will be called from. 
 
					char PhoneNumber[ 100 ]; 
					HCALL hCall; 
 
					// Check and see if there is anything left hanging open 
					hCall = (HCALL)GetProp( hDlg, "HCALL" ); 
					if( hCall != NULL  )						// Is there a current call? 
					{ 
					 	MessageBox( hDlg, "Please Disconnect before making another call!", " Tapi Error", MB_ICONSTOP ); 
						break; 
					} 
					// Get the Phone Number from the dialog 
					GetDlgItemText( hDlg, ID_PHONE, PhoneNumber, sizeof( PhoneNumber ) ); 
					if( ConnectToData( hDlg, PhoneNumber ) < 0 ) 
						SendStatus( hDlg, "Unable to start a TAPI Function" ); 
	   				break; 
	   			} 
 
				case ID_DISCONNECT:						// Time to Disconnect a call 
				{ 
					LONG retcode; 
					HCALL hCall; 
					HANDLE hComm; 
 
					hCall = (HCALL)GetProp( hDlg, "HCALL" );	// Get the properties 
					hComm = (HANDLE)GetProp( hDlg, "HCOMM" ); 
 
					if( hComm != NULL )						// Is there a comm handle? 
					{ 
						CloseHandle( hComm );				// Yes, close it 
						SetProp( hDlg, "HCALL", NULL ); 
					} 
					if( hCall != NULL )						// Is there a call? 
					{ 
						retcode = lineDrop( hCall, NULL, 0 );  // Drop the call 
						SendStatus( hDlg, "Call is Dropped" ); 
						SetProp( hDlg, "HCALL", NULL ); 
					} 
					break; 
				} 
 
				case TAPI_LINE_REPLY: 
				{ 
					SendStatus( hDlg, "Line Reply" );  
				 	break; 
				} 
 
				case TAPI_LINECALLSTATE_CONNECTED: 
				{ 
					SendStatus( hDlg, "Line Call State is Connected" );  
					break; 
				}						    
 
				case TAPI_LINECALLSTATE_IDLE: 
				{ 
					LONG retcode; 
					HLINE hLine; 
 
					// Since the call has been closed, you may now close down the line 
					hLine = (HLINE)GetProp( hDlg, "HLINE" );  
					if( hLine != NULL )			// Make sure there is a line open 
					{ 
						retcode = lineClose( hLine );  // Yes there was 
						SetProp( hDlg, "HLINE", (HANDLE)NULL ); 
					} 
					SendStatus( hDlg, "Line Call State is idle" ); 
					break; 
				} 
 
				// The rest of this switch is calls that are originated from my TAPI 
				// callback function.  This is just to show you how you can wait for 
				// certain functions to happen without using PeekMessage loops 
 
				case TAPI_LINECALLSTATE_DISCONNECTED: 
				{ 
					SendStatus( hDlg, "Line Call State is Disconnected" ); 
					break; 
				} 
 
				case TAPI_LINECALLSTATE_BUSY: 
				{ 
					SendStatus( hDlg, "Line Call State is Busy" ); 
					break; 
				} 
 
				case TAPI_LINECALLSTATE_ACCEPTED: 
				{ 
					SendStatus( hDlg, "Line Call State is Accepted" ); 
					break; 
				} 
 
				case TAPI_LINECALLSTATE_PROCEEDING: 
				{ 
					SendStatus( hDlg, "Line Call State is Proceeding" ); 
					break; 
				} 
 
				case TAPI_LINECALLSTATE_OFFERING: 
				{ 
					SendStatus( hDlg, "Line Call State is Offering" ); 
					break; 
				} 
 
				case TAPI_LINECALLSTATE_DIALTONE: 
				{ 
					SendStatus( hDlg, "Line Call State is DialTone" ); 
					break; 
				} 
 
				case TAPI_LINECALLSTATE_DIALING: 
				{ 
					SendStatus( hDlg, "Line Call State is Dialing" ); 
					break; 
				} 
 
				default: 
   					break; 
   			} 
			break; 
		} 
 
		default: 
			break; 
	} 
	return (FALSE); 
} 
 
 
 
LONG ConnectToData( HWND hWnd, LPTSTR PhoneNumber ) 
{ 
	// Here is the meat of the connection of a phone line.  This is not all inclusive 
	// and by no means have all the error checking present. 
 
	LONG	retcode; 
	DWORD	i; 
	DWORD	ApiVersion; 
	DWORD	RetApiVersion; 
	LINEEXTENSIONID	ExtensionID; 
	HLINE	hLine; 
	HCALL	hCall; 
 
	if( lstrlen( PhoneNumber ) < 1 ) //No Phone Number Provided 
		return( -1 );	 
 
	// Initialize the Line Handle 
	if( LineHandle == NULL ) 
		retcode = lineInitialize( &LineHandle, hInst, (LINECALLBACK)LineCallBackProc, "DataModem", &lines ); 
 
	if( retcode < 0 ) 
		return( retcode ); 
 
	hLine = (HLINE)GetProp( hWnd, "HLINE" ); 
	if( hLine == NULL ) 
	{ 
		for( i=0; i < lines; i++ ) 
		{ 
			// Negotiate the API Version 
			ApiVersion = tapiVersionCur; 
			retcode = lineNegotiateAPIVersion( LineHandle, i, ApiVersion, ApiVersion, &RetApiVersion, 
				&ExtensionID ); 
 
			retcode = lineOpen( LineHandle, i, &hLine, RetApiVersion, 0, (DWORD)hWnd, 
				LINECALLPRIVILEGE_OWNER | LINECALLPRIVILEGE_MONITOR, 
				LINEMEDIAMODE_DATAMODEM, NULL ); 
			if( retcode == 0 ) 
				break; 
		} 
		if( retcode != 0 ) 
			return( -1 ); 
	} 
 
	SetProp( hWnd, "HLINE",(HANDLE)(HLINE)hLine ); 
 
	// This will set up some line parameters for TAPI 
	memset( &LineParams, 0, sizeof( LINECALLPARAMS ) );	// Make sure you clear the memory first 
	LineParams.dwTotalSize = sizeof( LINECALLPARAMS ); 
	LineParams.dwMinRate = 9600;						//This is needed for me. You may leave 
	LineParams.dwMaxRate = 9600;						// these alone or put your own values in. 
	LineParams.dwMediaMode = LINEMEDIAMODE_DATAMODEM; 
 
	retcode = lineMakeCall( hLine, &hCall, PhoneNumber, 0, &LineParams ); 
	return( retcode ); 
} 
 
 
void CALLBACK LineCallBackProc(DWORD hDevice,DWORD dwMessage,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2,DWORD dwParam3) 
{    
	 
    switch (dwMessage)  
        {  
        case LINE_LINEDEVSTATE: 
            switch (dwParam1) 
            { 
            	case LINEDEVSTATE_REINIT: 
            		break; 
 
            	case LINEDEVSTATE_RINGING: 
            		break; 
            }  
            break; 
        /* process state transition */ 
        case LINE_CALLSTATE: 
            { 
				switch( dwParam1 ) 
				{ 
					case LINECALLSTATE_IDLE: 
					{ 
						LONG retcode; 
						LINECALLINFO LineCallInfo; 
 
						// This will get information about the call 
						memset( &LineCallInfo, 0, sizeof( LINECALLINFO ) ); 
						LineCallInfo.dwTotalSize = sizeof( LINECALLINFO ); 
						lineGetCallInfo( (HCALL)hDevice, &LineCallInfo ); 
 
						// OK, time to dealloc the line 
						retcode = lineDeallocateCall( (HCALL)hDevice ); 
						// Notify main window of idle state 
						PostMessage((HWND)dwInstance, WM_COMMAND, TAPI_LINECALLSTATE_IDLE, (LPARAM)(HLINE)LineCallInfo.hLine ); 
						break;	    
					}													      
					case LINECALLSTATE_ACCEPTED: 
					{ 
						SetVariableProperties( (HWND)dwInstance, hDevice ); 
						PostMessage( (HWND)dwInstance, WM_COMMAND, TAPI_LINECALLSTATE_ACCEPTED,(LPARAM)(HCALL)hDevice ); 
					 	break; 
					} 
 
					case LINECALLSTATE_PROCEEDING: 
					{ 
						SetVariableProperties( (HWND)dwInstance, hDevice ); 
						PostMessage( (HWND)dwInstance, WM_COMMAND, TAPI_LINECALLSTATE_PROCEEDING,(LPARAM)(HCALL)hDevice ); 
						break; 
					} 
 
					case LINECALLSTATE_CONNECTED: 
					{ 
						LPVARSTRING lpVarStringStruct = NULL; 
						size_t sizeofVarStringStruct = sizeof( VARSTRING ) + 1024; 
						HANDLE CommFile = NULL; 
						long lreturn; 
 
						// This is how to get the comm handle from TAPI. 
						// MAKE SURE YOU CLOSE THIS HANDLE. If you don't, TAPI keeps 
						// the resource locked and you will not be able to make other 
						// calls on the line.  The error result will be resource unavailable 
						lpVarStringStruct = LocalAlloc( 0, sizeofVarStringStruct ); 
						do 
						{ 
							memset( lpVarStringStruct, 0, sizeofVarStringStruct ); 
							lpVarStringStruct->dwTotalSize = (DWORD)sizeofVarStringStruct; 
							lreturn = lineGetID( 0, 0, (HCALL)hDevice, LINECALLSELECT_CALL, lpVarStringStruct, "comm/datamodem" ); 
						} while( lreturn != 0 ); 
 
						CommFile = *( (LPHANDLE )( ( LPBYTE )lpVarStringStruct + lpVarStringStruct->dwStringOffset ) ); 
						SetProp( (HWND)dwInstance, "HCOMM", CommFile ); 
						SetVariableProperties( (HWND)dwInstance, hDevice ); 
						// Notify the main window that you are now connected. 
						PostMessage( (HWND)dwInstance, WM_COMMAND, TAPI_LINECALLSTATE_CONNECTED, (LPARAM)(HANDLE)CommFile ); 
						LocalFree( lpVarStringStruct ); 
						break; 
					} 
 
					case LINECALLSTATE_OFFERING: 
					{ 
						SetVariableProperties( (HWND)dwInstance, hDevice ); 
						PostMessage( (HWND)dwInstance, WM_COMMAND, TAPI_LINECALLSTATE_OFFERING, (LPARAM)(HCALL)hDevice ); 
						break; 
					} 
 
					case LINECALLSTATE_DIALTONE: 
					{ 
						SetVariableProperties( (HWND)dwInstance, hDevice ); 
						PostMessage( (HWND)dwInstance, WM_COMMAND, TAPI_LINECALLSTATE_DIALTONE, (LPARAM)(HCALL)hDevice ); 
						break; 
					} 
 
					case LINECALLSTATE_DIALING: 
					{ 
						SetVariableProperties( (HWND)dwInstance, hDevice ); 
						PostMessage( (HWND)dwInstance, WM_COMMAND, TAPI_LINECALLSTATE_DIALING, (LPARAM)(HCALL)hDevice ); 
						break; 
					} 
 
					case LINECALLSTATE_BUSY: 
					{ 
						SetVariableProperties( (HWND)dwInstance, hDevice ); 
						PostMessage( (HWND)dwInstance, WM_COMMAND, TAPI_LINECALLSTATE_BUSY, 0 ); 
						break; 
					} 
 
					case LINECALLSTATE_DISCONNECTED: 
					{ 
						SetVariableProperties( (HWND)dwInstance, hDevice ); 
						PostMessage( (HWND)dwInstance, WM_COMMAND, TAPI_LINECALLSTATE_DISCONNECTED, (LPARAM)(HCALL)hDevice ); 
						break; 
					} 
				} 
            	break; 
            } 
        case LINE_CLOSE:  
            { 
            break;  
            } 
        /* handle the async completion of TAPI functions lineMakeCall/lineDropCall */ 
        case LINE_REPLY: 
		{ 
			PostMessage( (HWND)dwInstance, WM_COMMAND, TAPI_LINE_REPLY, 0 ); 
            break; 
		} 
 
        /* other messages that can be processed */ 
        case LINE_REQUEST: 
        case LINE_ADDRESSSTATE: 
            break; 
        case LINE_CALLINFO: 
            break; 
        case LINE_DEVSPECIFIC: 
            break; 
        case LINE_DEVSPECIFICFEATURE: 
            break; 
        case LINE_GATHERDIGITS: 
            break; 
        case LINE_GENERATE: 
            break; 
        case LINE_MONITORDIGITS: 
            break; 
        case LINE_MONITORMEDIA: 
            break; 
        case LINE_MONITORTONE: 
            break; 
        } /* switch */  
         
} /* LineCallBackProc */ 
 
 
void SendStatus( HWND hDlg, LPTSTR OutputString ) 
{ 
	DWORD dwIndex; 
	int i; 
 
	dwIndex = SendDlgItemMessage( hDlg, ID_STATUS_LIST, LB_ADDSTRING, 0, (LPARAM)(LPSTR)OutputString ); 
	if( dwIndex == LB_ERR )		// Oops no more room in listbox, delete the top 10 entries 
	{ 
		for( i = 0; i < 10; i++ ) 
			SendDlgItemMessage( hDlg, ID_STATUS_LIST, LB_DELETESTRING, 0, 0 ); 
		// Ok, There should be room now, resubmit it  
		dwIndex = SendDlgItemMessage( hDlg, ID_STATUS_LIST, LB_ADDSTRING, 0, (LPARAM)(LPSTR)OutputString ); 
	} 
	SendDlgItemMessage( hDlg, ID_STATUS_LIST, LB_SETCURSEL, (WPARAM)dwIndex, 0 ); 
	return; 
} 
 
 
void SetVariableProperties( HWND hWnd, DWORD hDevice ) 
{ 
	LINECALLINFO LineCallInfo; 
 
	memset( &LineCallInfo, 0, sizeof( LINECALLINFO ) ); 
	SetProp( hWnd, "HCALL", (HANDLE)(HCALL)hDevice ); 
	LineCallInfo.dwTotalSize = sizeof( LINECALLINFO ); 
	lineGetCallInfo( (HCALL)hDevice, &LineCallInfo ); 
 	SetProp( hWnd, "HLINE", (HANDLE)(HLINE)LineCallInfo.hLine ); 
	return; 
}