|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
tapi.c
Abstract:
This file provides all access to tapi.
Environment:
WIN32 User Mode
Author:
Wesley Witt (wesw) 17-Feb-1996
--*/
#include "wizard.h"
#pragma hdrstop
#include <initguid.h>
#include <devguid.h>
DWORD TapiApiVersion; HLINEAPP hLineApp; HANDLE TapiEvent; DWORD TapiDevices; DWORD FaxDevices; PLINE_INFO LineInfo; DWORD CurrentLocationId; DWORD CurrentCountryId; LPTSTR CurrentAreaCode;
#include "modem.c"
LONG MyLineGetTransCaps( LPLINETRANSLATECAPS *LineTransCaps ) { DWORD LineTransCapsSize; LONG Rslt = ERROR_SUCCESS;
//
// allocate the initial linetranscaps structure
//
LineTransCapsSize = sizeof(LINETRANSLATECAPS) + 4096; *LineTransCaps = (LPLINETRANSLATECAPS) MemAlloc( LineTransCapsSize ); if (!*LineTransCaps) { DebugPrint(( TEXT("MemAlloc() failed, sz=0x%08x"), LineTransCapsSize )); Rslt = ERROR_NOT_ENOUGH_MEMORY; goto exit; }
(*LineTransCaps)->dwTotalSize = LineTransCapsSize;
Rslt = lineGetTranslateCaps( hLineApp, TapiApiVersion, *LineTransCaps );
if (Rslt != 0) { DebugPrint(( TEXT("lineGetTranslateCaps() failed, ec=0x%08x"), Rslt )); goto exit; }
if ((*LineTransCaps)->dwNeededSize > (*LineTransCaps)->dwTotalSize) {
//
// re-allocate the LineTransCaps structure
//
LineTransCapsSize = (*LineTransCaps)->dwNeededSize;
MemFree( *LineTransCaps );
*LineTransCaps = (LPLINETRANSLATECAPS) MemAlloc( LineTransCapsSize ); if (!*LineTransCaps) { DebugPrint(( TEXT("MemAlloc() failed, sz=0x%08x"), LineTransCapsSize )); Rslt = ERROR_NOT_ENOUGH_MEMORY; goto exit; }
(*LineTransCaps)->dwTotalSize = LineTransCapsSize;
Rslt = lineGetTranslateCaps( hLineApp, TapiApiVersion, *LineTransCaps );
if (Rslt != 0) { DebugPrint(( TEXT("lineGetTranslateCaps() failed, ec=0x%08x"), Rslt )); goto exit; }
}
exit: if (Rslt != ERROR_SUCCESS) { MemFree( *LineTransCaps ); *LineTransCaps = NULL; }
return Rslt; }
BOOL LookFor351Modems( VOID ) { TCHAR FileName[MAX_PATH*2]; TCHAR Ports[128];
if (!ExpandEnvironmentStrings( TEXT("%windir%\\system32\\ras\\serial.ini"), FileName, sizeof(FileName)/sizeof(TCHAR) )) { return FALSE; }
if (!GetPrivateProfileSectionNames( Ports, sizeof(Ports), FileName )) { return FALSE; }
return TRUE; }
DWORD DeviceInitThread( HWND hwnd ) { DWORD rVal = 0; LONG Rslt; LINEINITIALIZEEXPARAMS LineInitializeExParams; LINEEXTENSIONID lineExtensionID; DWORD LineDevCapsSize; LPLINEDEVCAPS LineDevCaps = NULL; LPTSTR DeviceClassList; BOOL UnimodemDevice; DWORD i; LPLINETRANSLATECAPS LineTransCaps = NULL; LPLINELOCATIONENTRY LineLocation = NULL; BOOL FirstTime = TRUE; BOOL NoClass1 = FALSE; LPTSTR p; DWORD Answer; DWORD LocalTapiApiVersion;
HKEY hKey; DWORD ValType; DWORD ValSize;
PMDM_DEVSPEC MdmDevSpec; LPSTR ModemKey = NULL; UINT Res; TCHAR AdaptiveFileName[MAX_PATH*2]; HANDLE AdaptiveFileHandle; BOOL AdaptiveFileExists = FALSE; TCHAR Drive[_MAX_DRIVE]; TCHAR Dir[_MAX_DIR];
#define AdaptiveFileMaxSize 20000
BYTE AdaptiveFileBuffer[AdaptiveFileMaxSize]; // temporary needed. Currently < 1K anyway.
DWORD BytesHaveRead;
#define RespKeyMaxSize 1000
BYTE RespKeyName[RespKeyMaxSize];
if (hLineApp) { return 0; }
LineInitializeExParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS); LineInitializeExParams.dwNeededSize = 0; LineInitializeExParams.dwUsedSize = 0; LineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT; LineInitializeExParams.Handles.hEvent = NULL; LineInitializeExParams.dwCompletionKey = 0;
LocalTapiApiVersion = TapiApiVersion = 0x00020000;
if (!Unattended) { SetDlgItemText( hwnd, IDC_DEVICE_PROGRESS_TEXT, GetString( IDS_INIT_TAPI ) ); }
if (LookFor351Modems()) { PopUpMsg( hwnd, IDS_351_MODEM, TRUE, 0 ); }
init_again: Rslt = lineInitializeEx( &hLineApp, FaxWizModuleHandle, NULL, TEXT("Fax Setup"), &TapiDevices, &LocalTapiApiVersion, &LineInitializeExParams );
if (Rslt != 0) { DebugPrint(( TEXT("lineInitializeEx() failed, ec=0x%08x"), Rslt )); hLineApp = NULL; goto exit; }
if (!FirstTime) { PopUpMsg( hwnd, IDS_NO_TAPI_DEVICES, TRUE, 0 ); ExitProcess(0); }
if (TapiDevices == 0) { if (NtGuiMode) { //
// if running in nt gui mode setup and there
// are no tapi devices then we do nothing,
// but do allow the setup to continue.
//
lineShutdown( hLineApp ); hLineApp = NULL; return 0; }
Answer = PopUpMsg( hwnd, IDS_NO_MODEM, FALSE, MB_YESNO ); if (Answer == IDYES) { if (!CallModemInstallWizard( hwnd )) { DebugPrint(( TEXT("CallModemInstallWizard() failed, ec=0x%08x"), GetLastError() )); } } else { DebugPrint(( TEXT("No tapi devices, user declined") )); } FirstTime = FALSE; lineShutdown( hLineApp ); hLineApp = NULL; goto init_again; }
//
// determine the current location information
//
Rslt = MyLineGetTransCaps( &LineTransCaps ); if (Rslt != ERROR_SUCCESS) { if (Rslt == LINEERR_INIFILECORRUPT) { //
// need to set the location information
//
if (!NtGuiMode) { Rslt = lineTranslateDialog( hLineApp, 0, LocalTapiApiVersion, hwnd, NULL ); if (Rslt == ERROR_SUCCESS) { Rslt = MyLineGetTransCaps( &LineTransCaps ); } } } if (Rslt != ERROR_SUCCESS) { DebugPrint(( TEXT("MyLineGetTransCaps() failed, ec=0x%08x"), Rslt )); goto exit; } }
LineLocation = (LPLINELOCATIONENTRY) ((LPBYTE)LineTransCaps + LineTransCaps->dwLocationListOffset); for (i=0; i<LineTransCaps->dwNumLocations; i++) { if (LineTransCaps->dwCurrentLocationID == LineLocation[i].dwPermanentLocationID) { break; } }
if (i == LineTransCaps->dwNumLocations) { DebugPrint(( TEXT("Could not determine the current location information") )); goto exit; }
CurrentLocationId = LineTransCaps->dwCurrentLocationID; CurrentCountryId = LineLocation->dwCountryID; CurrentAreaCode = StringDup( (LPTSTR) ((LPBYTE)LineTransCaps + LineLocation->dwCityCodeOffset) );
//
// allocate the lineinfo structure
//
TapiEvent = LineInitializeExParams.Handles.hEvent;
LineInfo = (PLINE_INFO) MemAlloc( TapiDevices * sizeof(LINE_INFO) ); if (!LineInfo) { goto exit; }
//
// allocate the initial linedevcaps structure
//
LineDevCapsSize = sizeof(LINEDEVCAPS) + 4096; LineDevCaps = (LPLINEDEVCAPS) MemAlloc( LineDevCapsSize ); if (!LineDevCaps) { goto exit; }
if (!Unattended) { SendMessage( hwnd, WM_MY_PROGRESS, 0xff, TapiDevices * 20 ); }
//
// open FaxAdapt.lst file to decide on enabling RX
// try executable directory first, then- system directory
//
if ( ! GetModuleFileName( FaxWizModuleHandle, AdaptiveFileName, sizeof(AdaptiveFileName) ) ) { DebugPrint(( TEXT("GetModuleFileName fails , ec=0x%08x "), GetLastError() )); goto l0; }
_tsplitpath( AdaptiveFileName, Drive, Dir, NULL, NULL ); _stprintf( AdaptiveFileName, TEXT("%s%s"), Drive, Dir );
if ( _tcslen(AdaptiveFileName) + _tcslen( TEXT("FAXADAPT.LST") ) >= MAX_PATH ) { DebugPrint(( TEXT("GetCurrentDirectory() too long , MAX_PATH = %d"), MAX_PATH )); goto l0; }
_tcscat (AdaptiveFileName, (TEXT ("FAXADAPT.LST")) );
if ( (AdaptiveFileHandle = CreateFile(AdaptiveFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL) ) == INVALID_HANDLE_VALUE ) {
DebugPrint(( TEXT("Could not open adaptive file %s ec=0x%08x"), AdaptiveFileName, GetLastError() )); goto l0; }
if (! ReadFile(AdaptiveFileHandle, AdaptiveFileBuffer, AdaptiveFileMaxSize, &BytesHaveRead, NULL ) ) { DebugPrint(( TEXT("Could not read adaptive file %s ec=0x%08x"), AdaptiveFileName, GetLastError() )); CloseHandle(AdaptiveFileHandle); goto l1; }
if (BytesHaveRead >= AdaptiveFileMaxSize) { DebugPrint(( TEXT("Adaptive file %s is too big - %d bytes"), AdaptiveFileName, BytesHaveRead )); CloseHandle(AdaptiveFileHandle); goto l1; }
CloseHandle(AdaptiveFileHandle);
AdaptiveFileBuffer[BytesHaveRead] = 0; // need a string
AdaptiveFileExists = TRUE;
goto l1;
//
// only if there is no file in the current directory.
//
l0:
Res = GetSystemDirectory( AdaptiveFileName, MAX_PATH); if (Res == 0) { DebugPrint(( TEXT("GetSystemDirectory() failed 0, ec=0x%08x"), GetLastError() )); goto l1; } else if (Res > MAX_PATH) { DebugPrint(( TEXT("GetSystemDirectory() failed > MAX_PATH = %d"), MAX_PATH )); goto l1; }
if (Res + _tcslen( TEXT("\\FAXADAPT.LST") ) >= MAX_PATH ) { DebugPrint(( TEXT("GetSystemDirectory() too long %d, MAX_PATH = %d"), Res, MAX_PATH )); goto l1; }
_tcscat (AdaptiveFileName, (TEXT ("\\FAXADAPT.LST")) );
if ( (AdaptiveFileHandle = CreateFile(AdaptiveFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL) ) == INVALID_HANDLE_VALUE ) {
DebugPrint(( TEXT("Could not open adaptive file %s ec=0x%08x"), AdaptiveFileName, GetLastError() )); goto l1; }
if (! ReadFile(AdaptiveFileHandle, AdaptiveFileBuffer, AdaptiveFileMaxSize, &BytesHaveRead, NULL ) ) { DebugPrint(( TEXT("Could not read adaptive file %s ec=0x%08x"), AdaptiveFileName, GetLastError() )); CloseHandle(AdaptiveFileHandle); goto l1; }
if (BytesHaveRead >= AdaptiveFileMaxSize) { DebugPrint(( TEXT("Adaptive file %s is too big - %d bytes"), AdaptiveFileName, BytesHaveRead )); CloseHandle(AdaptiveFileHandle); goto l1; }
CloseHandle(AdaptiveFileHandle);
AdaptiveFileBuffer[BytesHaveRead] = 0; // need a string
AdaptiveFileExists = TRUE;
l1: //
// enumerate all of the tapi devices
//
i = 0;
do {
Rslt = lineNegotiateAPIVersion( hLineApp, i, 0x00010003, TapiApiVersion, &LocalTapiApiVersion, &lineExtensionID ); if (Rslt != 0) { DebugPrint(( TEXT("lineNegotiateAPIVersion() failed, ec=0x%08x"), Rslt )); goto next_device; }
ZeroMemory( LineDevCaps, LineDevCapsSize ); LineDevCaps->dwTotalSize = LineDevCapsSize;
Rslt = lineGetDevCaps( hLineApp, i, LocalTapiApiVersion, 0, LineDevCaps );
if (Rslt != 0) { DebugPrint(( TEXT("lineGetDevCaps() failed, ec=0x%08x"), Rslt )); goto next_device; }
if (LineDevCaps->dwNeededSize > LineDevCaps->dwTotalSize) {
//
// re-allocate the linedevcaps structure
//
LineDevCapsSize = LineDevCaps->dwNeededSize;
MemFree( LineDevCaps );
LineDevCaps = (LPLINEDEVCAPS) MemAlloc( LineDevCapsSize ); if (!LineDevCaps) { rVal = ERROR_NOT_ENOUGH_MEMORY; goto exit; }
Rslt = lineGetDevCaps( hLineApp, i, TapiApiVersion, 0, LineDevCaps );
if (Rslt != 0) { DebugPrint(( TEXT("lineGetDevCaps() failed, ec=0x%08x"), Rslt )); goto next_device; }
}
if (!Unattended) { SendMessage( hwnd, WM_MY_PROGRESS, 10, 0 ); }
if (!Unattended) { SetDlgItemText( hwnd, IDC_DEVICE_PROGRESS_TEXT, (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwLineNameOffset) ); }
if (TapiApiVersion != 0x00020000) { DebugPrint(( TEXT("TAPI device is incompatible with the FAX server: %s"), (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwLineNameOffset) )); goto next_device; }
//
// save the line id
//
LineInfo[FaxDevices].PermanentLineID = LineDevCaps->dwPermanentLineID; LineInfo[FaxDevices].DeviceName = StringDup( (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwLineNameOffset) ); LineInfo[FaxDevices].ProviderName = StringDup( (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwProviderInfoOffset) ); LineInfo[FaxDevices].Rings = LineDevCaps->dwLineStates & LINEDEVSTATE_RINGING ? 2 : 0; LineInfo[FaxDevices].Flags = FPF_RECEIVE | FPF_SEND;
//
// filter out the commas because the spooler hates them
//
p = LineInfo[FaxDevices].DeviceName; while( p ) { p = _tcschr( p, TEXT(',') ); if (p) { *p = TEXT('_'); } }
//
// check for a modem device
//
UnimodemDevice = FALSE;
if (LineDevCaps->dwDeviceClassesSize && LineDevCaps->dwDeviceClassesOffset) { DeviceClassList = (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwDeviceClassesOffset); while (*DeviceClassList) { if (_tcscmp(DeviceClassList,TEXT("comm/datamodem")) == 0) { UnimodemDevice = TRUE; break; } DeviceClassList += (_tcslen(DeviceClassList) + 1); } }
if ((!(LineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE)) || (!(LineDevCaps->dwBearerModes & LINEBEARERMODE_PASSTHROUGH))) { //
// unacceptable modem device type
//
UnimodemDevice = FALSE; }
if (UnimodemDevice) {
LINECALLPARAMS LineCallParams; HCALL hCall = NULL; HLINE hLine = NULL; LINEMESSAGE LineMessage; DWORD RequestId;
LineInfo[FaxDevices].Flags = FPF_SEND; // Unimodem default
Rslt = lineOpen( hLineApp, i, &hLine, TapiApiVersion, 0, 0, LINECALLPRIVILEGE_OWNER, UnimodemDevice ? LINEMEDIAMODE_DATAMODEM : LINEMEDIAMODE_G3FAX, NULL ); if (Rslt != 0) { DebugPrint(( TEXT("lineOpen() failed, ec=0x%08x"), Rslt )); goto next_device; }
//
// Get Unimodem key to search Adaptive list.
//
if (! AdaptiveFileExists) { goto l2; }
if (! LineDevCaps->dwDevSpecificSize) { goto l2; }
MdmDevSpec = (PMDM_DEVSPEC) ((LPBYTE) LineDevCaps + LineDevCaps->dwDevSpecificOffset); if (MdmDevSpec->Contents == 1 && MdmDevSpec->KeyOffset == 8) { ModemKey = MdmDevSpec->String; } else { goto l2; }
if (!ModemKey) { DebugPrint(( TEXT("Can't get Unimodem key") )); goto l2; }
//
// Get ResponsesKeyName
//
Rslt = RegOpenKeyExA( HKEY_LOCAL_MACHINE, ModemKey, 0, KEY_READ, &hKey);
if (Rslt != ERROR_SUCCESS) { DebugPrint(( TEXT("Can't open Unimodem key") )); goto l2; }
ValSize = RespKeyMaxSize;
Rslt = RegQueryValueExA( hKey, "ResponsesKeyName", 0, &ValType, RespKeyName, &ValSize);
RegCloseKey(hKey);
if (Rslt != ERROR_SUCCESS) { DebugPrint(( TEXT("Can't get Unimodem ResponsesKeyName") )); goto l2; }
if ( (ValSize >= RespKeyMaxSize) || (ValSize == 0) ) { DebugPrint(( TEXT("Unimodem ResponsesKeyName key is invalid %d"), RespKeyMaxSize )); goto l2; }
if (!RespKeyName) { DebugPrint(( TEXT("Unimodem ResponsesKeyName key is NULL") )); goto l2; }
_strupr(RespKeyName);
//
// check to see if this modem is defined in Adaptive modem list
//
if ( strstr (AdaptiveFileBuffer, RespKeyName) ) {
// enable receive on this device: it is adaptive answer capable.
LineInfo[FaxDevices].Flags = FPF_RECEIVE | FPF_SEND; }
l2: ZeroMemory( &LineCallParams, sizeof(LineCallParams) ); LineCallParams.dwTotalSize = sizeof(LINECALLPARAMS); LineCallParams.dwBearerMode = LINEBEARERMODE_PASSTHROUGH; hCall = NULL;
Rslt = lineMakeCall( hLine, &hCall, NULL, 0, &LineCallParams ); if (Rslt > 0) {
#define IDVARSTRINGSIZE (sizeof(VARSTRING)+128)
PDEVICEID DeviceID = NULL; LPVARSTRING LineIdBuffer = MemAlloc( IDVARSTRINGSIZE ); LineIdBuffer->dwTotalSize = IDVARSTRINGSIZE; RequestId = (DWORD) Rslt;
//
// wait for the call to complete
//
while( TRUE ) { if (WaitForSingleObject( TapiEvent, 5 * 60 * 1000 ) == WAIT_TIMEOUT) { DebugPrint(( TEXT("Setup never received a tapi event") )); rVal = ERROR_INVALID_FUNCTION; goto exit; } Rslt = lineGetMessage( hLineApp, &LineMessage, 0 ); if (Rslt == 0) { if (LineMessage.dwMessageID == LINE_REPLY && LineMessage.dwParam1 == RequestId) { switch (LineMessage.dwParam2) { case 0: break;
case LINEERR_CALLUNAVAIL: DebugPrint(( TEXT("lineMakeCall() failed (LINE_REPLY), ec=0x%08x"), LineMessage.dwParam2 )); goto next_device;
default: DebugPrint(( TEXT("lineMakeCall() failed (LINE_REPLY), ec=0x%08x"), LineMessage.dwParam2 )); rVal = LineMessage.dwParam2; goto exit;
} break; } } }
//
// get the comm handle
//
Rslt = lineGetID( hLine, 0, hCall, LINECALLSELECT_CALL, LineIdBuffer, TEXT("comm/datamodem") ); if (Rslt == 0 && LineIdBuffer->dwStringFormat == STRINGFORMAT_BINARY && LineIdBuffer->dwUsedSize >= sizeof(DEVICEID)) {
DeviceID = (PDEVICEID) ((LPBYTE)(LineIdBuffer)+LineIdBuffer->dwStringOffset); if (GetModemClass( DeviceID->hComm ) != 1) {
Rslt = LINEERR_BADDEVICEID; NoClass1 = TRUE; DebugPrint(( TEXT("GetModemClass() failed, ec=0x%08x"), Rslt ));
} else {
FaxDevices += 1;
}
CloseHandle( DeviceID->hComm );
} else {
DebugPrint(( TEXT("lineGetID() failed, ec=0x%08x"), Rslt ));
}
MemFree( LineIdBuffer );
} else {
DebugPrint(( TEXT("lineMakeCall() failed, ec=0x%08x"), Rslt ));
}
if (hCall) { lineDeallocateCall( hCall ); }
if (hLine) { lineClose( hLine ); }
} else {
if (LineDevCaps->dwMediaModes & LINEMEDIAMODE_G3FAX) {
//
// save the line id
//
FaxDevices += 1; }
}
next_device: if (!Unattended) { SendMessage( hwnd, WM_MY_PROGRESS, 10, 0 ); Sleep( 1000 ); } i += 1;
} while ( i < TapiDevices );
exit:
MemFree( LineDevCaps ); MemFree( LineTransCaps );
lineShutdown( hLineApp );
if ((rVal != 0) || (FaxDevices == 0)) { if (NtGuiMode) { //
// if running in nt gui mode setup and there
// are no tapi devices then we do nothing,
// but do allow the setup to continue.
//
hLineApp = NULL; return 0; } PopUpMsg( hwnd, NoClass1 ? IDS_NO_CLASS1 : IDS_NO_TAPI_DEVICES, TRUE, 0 ); ExitProcess(0); }
if (!Unattended) { SetWindowLong( hwnd, DWL_MSGRESULT, 0 ); PropSheet_PressButton( GetParent(hwnd), PSBTN_NEXT ); }
return 0; }
BOOL CallModemInstallWizard( HWND hwnd )
/* call the Modem.Cpl install wizard to enable the user to install one or more modems
** ** Return TRUE if the wizard was successfully invoked, FALSE otherwise ** */ { HDEVINFO hdi; BOOL fReturn = FALSE; // Create a modem DeviceInfoSet
hdi = SetupDiCreateDeviceInfoList((LPGUID)&GUID_DEVCLASS_MODEM, hwnd); if (hdi) { SP_INSTALLWIZARD_DATA iwd;
// Initialize the InstallWizardData
ZeroMemory(&iwd, sizeof(iwd)); iwd.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); iwd.ClassInstallHeader.InstallFunction = DIF_INSTALLWIZARD; iwd.hwndWizardDlg = hwnd;
// Set the InstallWizardData as the ClassInstallParams
if (SetupDiSetClassInstallParams(hdi, NULL, (PSP_CLASSINSTALL_HEADER)&iwd, sizeof(iwd))) { // Call the class installer to invoke the installation
// wizard.
if (SetupDiCallClassInstaller(DIF_INSTALLWIZARD, hdi, NULL)) { // Success. The wizard was invoked and finished.
// Now cleanup.
fReturn = TRUE;
SetupDiCallClassInstaller(DIF_DESTROYWIZARDDATA, hdi, NULL); } }
// Clean up
SetupDiDestroyDeviceInfoList(hdi); } return fReturn; }
|