/*++ Copyright (c) 1997 Microsoft Corporation Module Name: tapi.cpp Abstract: This file implements the tapi dialing location page. Environment: WIN32 User Mode Author: Wesley Witt (wesw) 7-Aug-1997 --*/ #include "ntoc.h" #pragma hdrstop // // constants // #define MY_SET_FOCUS (WM_USER+1000) #define REGKEY_LOCATIONS L"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations" #define REGVAL_NUMENTRIES L"NumEntries" #define INTL_SECTION L"intl" #define INTL_COUNTRY L"iCountry" #define REGKEY_LOCATION L"Location1" #define REGVAL_CURRENT_ID L"CurrentID" #define REGVAL_NEXT_ID L"NextID" #define REGVAL_NUM_ENTRIES L"NumEntries" #define REGVAL_COUNTRY L"Country" #define REGVAL_FLAGS L"Flags" #define REGVAL_ID L"ID" #define REGVAL_AREA_CODE L"AreaCode" #define REGVAL_DISABLE_CALL_WAITING L"DisableCallWaiting" #define REGVAL_LONG_DISTANCE_ACCESS L"LongDistanceAccess" #define REGVAL_NAME L"Name" #define REGVAL_OUTSIDE_ACCESS L"OutsideAccess" #define REGKEY_PROVIDERS L"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Providers" #define REGVAL_NUMPROVIDERS L"NumProviders" #define REGVAL_NEXTPROVIDERID L"NextProviderID" #define REGVAL_PROVIDERFILENAME L"ProviderFileName" #define REGVAL_PROVIDERID L"ProviderID" #define TAPILOC_SECTION L"TapiLocation" #define TPILOC_COUNTRY_CODE L"CountryCode" #define TPILOC_DIALING L"Dialing" #define TPILOC_TONE L"Tone" #define TPILOC_AREA_CODE L"AreaCode" #define TPILOC_ACCESS L"LongDistanceAccess" #define LOCATION_USETONEDIALING 0x00000001 #define LOCATION_USECALLINGCARD 0x00000002 #define LOCATION_HASCALLWAITING 0x00000004 #define LOCATION_ALWAYSINCLUDEAREACODE 0x00000008 #define MAX_TAPI_STRING 32 #define PROVIDER_FILE_NAME_LEN 14 // Provider's file name has the DOS // form (8.3) // // structures // typedef struct _TAPI_LOCATION_INFO { BOOL Valid; DWORD Country; DWORD Flags; WCHAR AreaCode[MAX_TAPI_STRING+1]; WCHAR LongDistanceAccess[MAX_TAPI_STRING+1]; } TAPI_LOCATION_INFO, *PTAPI_LOCATION_INFO; typedef struct _TAPI_SERVICE_PROVIDER { DWORD dwProviderID; WCHAR szProviderName[PROVIDER_FILE_NAME_LEN]; }TAPI_SERVICE_PROVIDER, *PTAPI_SERVICE_PROVIDER; // // globals // TAPI_LOCATION_INFO TapiLoc; LPLINECOUNTRYLIST LineCountry; BOOL TapiBadUnattend; WCHAR DefaultLocationName[MAX_PATH]; BOOL IsDeviceModem( LPLINEDEVCAPS LineDevCaps ) { LPTSTR DeviceClassList; BOOL UnimodemDevice = FALSE; if (LineDevCaps->dwDeviceClassesSize && LineDevCaps->dwDeviceClassesOffset) { DeviceClassList = (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwDeviceClassesOffset); while (*DeviceClassList) { if (wcscmp(DeviceClassList,TEXT("comm/datamodem")) == 0) { UnimodemDevice = TRUE; break; } DeviceClassList += (wcslen(DeviceClassList) + 1); } } if ((!(LineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE)) || (!(LineDevCaps->dwBearerModes & LINEBEARERMODE_PASSTHROUGH))) { // // unacceptable modem device type // UnimodemDevice = FALSE; } return UnimodemDevice; } LPLINEDEVCAPS MyLineGetDevCaps( HLINEAPP hLineApp, DWORD TapiApiVersion, DWORD DeviceId ) { DWORD LineDevCapsSize; LPLINEDEVCAPS LineDevCaps = NULL; LONG Rslt = ERROR_SUCCESS; DWORD LocalTapiApiVersion; LINEEXTENSIONID lineExtensionID; Rslt = lineNegotiateAPIVersion( hLineApp, DeviceId, 0x00010003, TapiApiVersion, &LocalTapiApiVersion, &lineExtensionID ); // // allocate the initial linedevcaps structure // LineDevCapsSize = sizeof(LINEDEVCAPS) + 4096; LineDevCaps = (LPLINEDEVCAPS) LocalAlloc( LPTR, LineDevCapsSize ); if (!LineDevCaps) { return NULL; } LineDevCaps->dwTotalSize = LineDevCapsSize; Rslt = lineGetDevCaps( hLineApp, DeviceId, LocalTapiApiVersion, 0, LineDevCaps ); if (Rslt != 0) { // // lineGetDevCaps() can fail with error code 0x8000004b // if a device has been deleted and tapi has not been // cycled. this is caused by the fact that tapi leaves // a phantom device in it's device list. the error is // benign and the device can safely be ignored. // if (Rslt != LINEERR_INCOMPATIBLEAPIVERSION) { DebugPrint(( TEXT("lineGetDevCaps() failed, ec=0x%08x"), Rslt )); } goto exit; } if (LineDevCaps->dwNeededSize > LineDevCaps->dwTotalSize) { // // re-allocate the linedevcaps structure // LineDevCapsSize = LineDevCaps->dwNeededSize; LocalFree( LineDevCaps ); LineDevCaps = (LPLINEDEVCAPS) LocalAlloc( LPTR, LineDevCapsSize ); if (!LineDevCaps) { Rslt = ERROR_NOT_ENOUGH_MEMORY; goto exit; } Rslt = lineGetDevCaps( hLineApp, DeviceId, LocalTapiApiVersion, 0, LineDevCaps ); if (Rslt != 0) { DebugPrint(( TEXT("lineGetDevCaps() failed, ec=0x%08x"), Rslt )); goto exit; } } exit: if (Rslt != ERROR_SUCCESS) { LocalFree( LineDevCaps ); LineDevCaps = NULL; } return LineDevCaps; } LPLINECOUNTRYLIST MyLineGetCountry( void ) { #define DEFAULT_COUNTRY_SIZE 65536 LPLINECOUNTRYLIST LineCountry = (LPLINECOUNTRYLIST) LocalAlloc( LPTR, DEFAULT_COUNTRY_SIZE ); if (!LineCountry) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } LineCountry->dwTotalSize = DEFAULT_COUNTRY_SIZE; if (lineGetCountry( 0, 0x00020001, LineCountry ) != 0) { return NULL; } if (LineCountry->dwNeededSize > LineCountry->dwTotalSize) { DWORD Size = LineCountry->dwNeededSize; LocalFree( LineCountry ); LineCountry = (LPLINECOUNTRYLIST) LocalAlloc( LPTR, Size ); if (!LineCountry) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(NULL); } if (lineGetCountry( 0, 0x00020001, LineCountry ) != 0) { return NULL; } } return LineCountry; } static TAPI_SERVICE_PROVIDER DefaultProviders[] = {(DWORD)-1, L"unimdm.tsp", (DWORD)-1, L"kmddsp.tsp", (DWORD)-1, L"ndptsp.tsp", (DWORD)-1, L"ipconf.tsp", (DWORD)-1, L"h323.tsp", (DWORD)-1, L"hidphone.tsp"}; #define NUM_DEFAULT_PROVIDERS (sizeof(DefaultProviders)/sizeof(DefaultProviders[0])) void TapiInitializeProviders (void) { DWORD dwNextProviderID = 1; DWORD dwExistingProviders = 0; DWORD dwMaxProviderID = 0; DWORD dwNextProviderNr = 0; HKEY hKeyProviders = NULL; DWORD cbData, i, j; WCHAR szProviderFileName[24]; // Enough to hold "ProviderFileNameXXXXX\0" WCHAR szProviderID[16]; // Enough to hold "ProviderIDxxxxx\0" WCHAR szFileName[24]; // Enough to hold "ProviderFileNameXXXXX\0" WCHAR *pProviderFileNameNumber, *pProviderIDNumber; PTAPI_SERVICE_PROVIDER Providers = NULL, pProvider; // First, create / open the Providers key. if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_LOCAL_MACHINE, REGKEY_PROVIDERS, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyProviders, &cbData)) { return; } // Initialize value names and pointers lstrcpy (szProviderFileName, REGVAL_PROVIDERFILENAME); lstrcpy (szProviderID, REGVAL_PROVIDERID); pProviderFileNameNumber = szProviderFileName + lstrlen (szProviderFileName); pProviderIDNumber = szProviderID + lstrlen (szProviderID); if (REG_CREATED_NEW_KEY == cbData) { // This means that there are no providers // in the registry yet. Go and add all the // default ones. goto _AddDefaultProviders; } // Now compute how big a provider array we have to allocate, // by looking at how many values there are in the providers key; // we divide this number by 2, because each provider will have a file // name and an ID. if (ERROR_SUCCESS != RegQueryInfoKey (hKeyProviders, NULL, NULL, NULL, NULL, NULL, NULL, &dwExistingProviders, NULL, NULL, NULL, NULL)) { goto _CountProviders; } dwExistingProviders >>= 1; // divide by 2 if (0 == dwExistingProviders) { // This means that there are no providers // in the registry yet. Go and add all the // default ones. goto _AddDefaultProviders; } dwExistingProviders++; // just in case // Allocate a provider array with enough entries. Providers = (PTAPI_SERVICE_PROVIDER)LocalAlloc (LPTR, dwExistingProviders*sizeof(TAPI_SERVICE_PROVIDER)); if (NULL == Providers) { // we couldn't allocate memory, so skip // looking for providers and just go and // install the default ones. goto _AddDefaultProviders; } // Next, figure out the number of providers already // installed, and the next provider ID // Instead of reading NumProviders from the registry, // try to open each ProviderIDxxx and ProviderFileNameXXX. // Do this just in case the registry is not in a good state. // Also, store the provider (unless it's t1632tsp) in the // array. _CountProviders: pProvider = Providers; dwExistingProviders = 0; for (i = 0; TRUE; i++) { BOOL bFound; wsprintf (pProviderFileNameNumber, L"%d", i); lstrcpy (pProviderIDNumber, pProviderFileNameNumber); cbData = sizeof (szFileName); if (ERROR_SUCCESS != RegQueryValueEx (hKeyProviders, szProviderFileName, NULL, NULL, (PBYTE)szFileName, &cbData)) { break; } cbData = sizeof (dwNextProviderID); if (ERROR_SUCCESS != RegQueryValueEx (hKeyProviders, szProviderID, NULL, NULL, (PBYTE)&dwNextProviderID, &cbData)) { // We couldn't read this provider's ID. We must skip it. continue; } // Look for the current provider in the list // of default providers bFound = FALSE; for (j = 0; j < NUM_DEFAULT_PROVIDERS; j++) { if (0 == lstrcmpi (DefaultProviders[j].szProviderName, szFileName)) { DefaultProviders[j].dwProviderID = dwNextProviderID; bFound = TRUE; break; } } if (!bFound) { // We have a provider that was installed by the user on the previous NT installation. pProvider->dwProviderID = dwNextProviderID; pProvider->szProviderName[0] = 0; lstrcpyn (pProvider->szProviderName, szFileName, sizeof(pProvider->szProviderName)/sizeof(pProvider->szProviderName[0])); pProvider->szProviderName[sizeof(pProvider->szProviderName)/sizeof(pProvider->szProviderName[0])-1] = 0; pProvider++; dwExistingProviders++; } if (dwNextProviderID > dwMaxProviderID) { dwMaxProviderID = dwNextProviderID; } } dwNextProviderID = dwMaxProviderID + 1; // We got a list of all providers that were installed before. // Clean up the Providers key. for (i = 0; TRUE; i++) { cbData = sizeof(szFileName)/sizeof(WCHAR); if (ERROR_SUCCESS != RegEnumValue (hKeyProviders, i, szFileName, &cbData, NULL, NULL, NULL, NULL)) { break; } RegDeleteValue (hKeyProviders, szFileName); } _AddDefaultProviders: for (i = 0, pProvider = DefaultProviders; i < NUM_DEFAULT_PROVIDERS; i++, pProvider++) { // Found a provider that has to be added. // Compute it's value names. wsprintf (pProviderFileNameNumber, L"%d", dwNextProviderNr); lstrcpy (pProviderIDNumber, pProviderFileNameNumber); if (ERROR_SUCCESS == RegSetValueEx (hKeyProviders, szProviderFileName, 0, REG_SZ, (PBYTE)pProvider->szProviderName, (lstrlen(pProvider->szProviderName)+1)*sizeof(WCHAR))) { DWORD dwRet; if ((DWORD)-1 == pProvider->dwProviderID) { if (ERROR_SUCCESS == (dwRet = RegSetValueEx (hKeyProviders, szProviderID, 0, REG_DWORD, (PBYTE)&dwNextProviderID, sizeof(dwNextProviderID)))) { dwNextProviderID++; } } else { dwRet = RegSetValueEx (hKeyProviders, szProviderID, 0, REG_DWORD, (PBYTE)&pProvider->dwProviderID, sizeof(pProvider->dwProviderID)); } if (ERROR_SUCCESS == dwRet) { dwNextProviderNr++; } else { RegDeleteValue (hKeyProviders, szProviderFileName); } } } // Now, add all the providers again. We do this because the // IDs were REG_BINARY on win98 and have to be REG_DWORD on NT5. for (i = 0, pProvider = Providers; i < dwExistingProviders; i++, pProvider++) { // Found a provider that has to be added. // Compute it's value names. wsprintf (pProviderFileNameNumber, L"%d", dwNextProviderNr); lstrcpy (pProviderIDNumber, pProviderFileNameNumber); if (ERROR_SUCCESS == RegSetValueEx (hKeyProviders, szProviderFileName, 0, REG_SZ, (PBYTE)pProvider->szProviderName, (lstrlen(pProvider->szProviderName)+1)*sizeof(WCHAR))) { if (ERROR_SUCCESS == RegSetValueEx (hKeyProviders, szProviderID, 0, REG_DWORD, (PBYTE)&pProvider->dwProviderID, sizeof(pProvider->dwProviderID))) { dwNextProviderNr++; } else { RegDeleteValue (hKeyProviders, szProviderFileName); } } } // Finally, update NumProviders and NextProviderID. RegSetValueEx (hKeyProviders, REGVAL_NUMPROVIDERS, 0, REG_DWORD, (PBYTE)&dwNextProviderNr, sizeof(dwNextProviderNr)); RegSetValueEx (hKeyProviders, REGVAL_NEXTPROVIDERID, 0, REG_DWORD, (PBYTE)&dwNextProviderID, sizeof(dwNextProviderID)); RegCloseKey (hKeyProviders); if (NULL != Providers) { LocalFree (Providers); } } void CopyTsecFile ( void ) { TCHAR szWndDir[MAX_PATH]; TCHAR szSrc[MAX_PATH]; TCHAR szDest[MAX_PATH]; TCHAR szBuf[MAX_PATH]; HANDLE hFileIn = INVALID_HANDLE_VALUE; HANDLE hFileOut = INVALID_HANDLE_VALUE; const TCHAR szTsecSrc[] = TEXT("\\tsec.ini"); const TCHAR szTsecDest[] = TEXT("\\TAPI\\tsec.ini"); DWORD dwBytesRead, dwBytesWritten; BOOL bError = FALSE; if (GetWindowsDirectory (szWndDir, sizeof(szWndDir)/sizeof(TCHAR)) == 0 || lstrlen(szWndDir) + lstrlen(szTsecSrc) >= sizeof(szSrc)/sizeof(TCHAR) || lstrlen(szWndDir) + lstrlen(szTsecDest) >= sizeof(szDest)/sizeof(TCHAR)) { goto ExitHere; } lstrcpy (szSrc, szWndDir); lstrcat (szSrc, szTsecSrc); lstrcpy (szDest, szWndDir); lstrcat (szDest, szTsecDest); hFileIn = CreateFile ( szSrc, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); hFileOut = CreateFile ( szDest, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (hFileIn == INVALID_HANDLE_VALUE || hFileOut == INVALID_HANDLE_VALUE) { goto ExitHere; } do { if (!ReadFile ( hFileIn, (LPVOID) szBuf, sizeof(szBuf), &dwBytesRead, NULL) ) { bError = TRUE; dwBytesRead = 0; } if (dwBytesRead != 0) { if (!WriteFile ( hFileOut, (LPVOID) szBuf, dwBytesRead, &dwBytesWritten, NULL ) || dwBytesRead != dwBytesWritten) { bError = TRUE; } } } while (dwBytesRead != 0); // // Be extra careful not to loose any data, delete // old file only if we are sure no error happened // if (!bError) { CloseHandle (hFileIn); hFileIn = INVALID_HANDLE_VALUE; DeleteFile (szSrc); } ExitHere: if (hFileIn != INVALID_HANDLE_VALUE) { CloseHandle (hFileIn); } if (hFileOut != INVALID_HANDLE_VALUE) { CloseHandle (hFileOut); } } void TapiInit( void ) { if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_STANDALONE) { return; } CopyTsecFile(); TapiInitializeProviders (); LineCountry = MyLineGetCountry(); LoadString( hInstance, IDS_DEFAULT_LOCATION_NAME, DefaultLocationName, sizeof(DefaultLocationName)/sizeof(WCHAR) ); } void TapiCommitChanges( void ) { HKEY hKey, hKeyLoc; if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_STANDALONE) { return; } if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_NTUPGRADE) { return; } if (TapiLoc.Valid) { hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_LOCATIONS, TRUE, KEY_ALL_ACCESS ); if (hKey) { SetRegistryDword( hKey, REGVAL_CURRENT_ID, 1 ); SetRegistryDword( hKey, REGVAL_NEXT_ID, 2 ); // SetRegistryDword( hKey, REGVAL_NUM_ENTRIES, 1 ); hKeyLoc = OpenRegistryKey( hKey, REGKEY_LOCATION, TRUE, KEY_ALL_ACCESS ); if (hKeyLoc) { SetRegistryDword( hKeyLoc, REGVAL_COUNTRY, TapiLoc.Country ); SetRegistryDword( hKeyLoc, REGVAL_FLAGS, TapiLoc.Flags ); // SetRegistryDword( hKeyLoc, REGVAL_ID, 1 ); SetRegistryString( hKeyLoc, REGVAL_AREA_CODE, TapiLoc.AreaCode ); SetRegistryString( hKeyLoc, REGVAL_DISABLE_CALL_WAITING, L"" ); SetRegistryString( hKeyLoc, REGVAL_LONG_DISTANCE_ACCESS, TapiLoc.LongDistanceAccess ); SetRegistryString( hKeyLoc, REGVAL_NAME, DefaultLocationName ); SetRegistryString( hKeyLoc, REGVAL_OUTSIDE_ACCESS, TapiLoc.LongDistanceAccess ); RegCloseKey( hKeyLoc ); } RegCloseKey( hKey ); } } } INT IsCityCodeOptional( LPLINECOUNTRYENTRY pEntry ) { #define AREACODE_DONTNEED 0 #define AREACODE_REQUIRED 1 #define AREACODE_OPTIONAL 2 if (pEntry && pEntry->dwLongDistanceRuleSize && pEntry->dwLongDistanceRuleOffset ) { LPWSTR pLongDistanceRule; pLongDistanceRule = (LPTSTR)((PBYTE)LineCountry + pEntry->dwLongDistanceRuleOffset); if (wcschr(pLongDistanceRule, L'F') != NULL) return AREACODE_REQUIRED; if (wcschr(pLongDistanceRule, L'I') == NULL) return AREACODE_DONTNEED; } return AREACODE_OPTIONAL; } BOOL TapiOnInitDialog( IN HWND hwnd, IN HWND hwndFocus, IN LPARAM lParam ) { SendDlgItemMessage( hwnd, IDC_AREA_CODE, EM_LIMITTEXT, MAX_TAPI_STRING, 0 ); SendDlgItemMessage( hwnd, IDC_LONG_DISTANCE, EM_LIMITTEXT, MAX_TAPI_STRING, 0 ); CheckRadioButton( hwnd, IDC_TONE, IDC_PULSE, IDC_TONE ); if (LineCountry) { DWORD CurrCountryCode = GetProfileInt( INTL_SECTION, INTL_COUNTRY, 1 ); LPLINECOUNTRYENTRY LineCountryEntry = (LPLINECOUNTRYENTRY) ((LPBYTE)LineCountry + LineCountry->dwCountryListOffset); DWORD Selection = 0; DWORD Index; LPWSTR CountryName ; for (DWORD i=0; idwNumCountries; i++) { CountryName = (LPWSTR) ((LPBYTE)LineCountry + LineCountryEntry[i].dwCountryNameOffset); Index = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_ADDSTRING, 0, (LPARAM)CountryName ); SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_SETITEMDATA, Index, i ); if (LineCountryEntry[i].dwCountryID == CurrCountryCode) { Selection = i; } } CountryName = (LPWSTR) ((LPBYTE)LineCountry + LineCountryEntry[Selection].dwCountryNameOffset); Selection = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_FINDSTRING, 0, (LPARAM) CountryName ); SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_SETCURSEL, Selection, 0 ); } PostMessage( hwnd, MY_SET_FOCUS, 0, (LPARAM) GetDlgItem( hwnd, IDC_AREA_CODE ) ); return TRUE; } VOID ValidateAndSetWizardButtons( HWND hwnd ) { BOOL AreaCodeOk; { DWORD CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETCURSEL, 0, 0 ); LPLINECOUNTRYENTRY CntryFirstEntry = NULL; INT AreaCodeInfo = 0; WCHAR Buffer[MAX_TAPI_STRING+1]; GetDlgItemText( hwnd, IDC_AREA_CODE, Buffer, MAX_TAPI_STRING ); CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETITEMDATA, CurrCountry, 0 ); CntryFirstEntry = (LPLINECOUNTRYENTRY)((LPBYTE)LineCountry + LineCountry->dwCountryListOffset); AreaCodeInfo = IsCityCodeOptional( CntryFirstEntry + CurrCountry ); AreaCodeOk = TRUE; // // If the area code is required, then there must be a value in the Buffer. // // Otherwise, it's OK. // if ( ( AreaCodeInfo == AREACODE_REQUIRED ) && ( *Buffer == UNICODE_NULL ) ){ AreaCodeOk = FALSE; } } if ( TapiLoc.Valid ) AreaCodeOk = TRUE; PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_BACK | ( AreaCodeOk ? PSWIZB_NEXT : 0 ) ); } BOOL TapiOnCommand( IN HWND hwnd, IN DWORD NotifyCode, IN DWORD ControlId, IN HWND hwndControl ) { // If the area code changed, or the country code changed if ((NotifyCode == EN_CHANGE && ControlId == IDC_AREA_CODE) || (NotifyCode == CBN_SELCHANGE && ControlId == IDC_COUNTRY_LIST)) { ValidateAndSetWizardButtons(hwnd); } return TRUE; } BOOL TapiOnNotify( IN HWND hwnd, IN WPARAM ControlId, IN LPNMHDR pnmh ) { switch (pnmh->code ) { case PSN_SETACTIVE: { HKEY hKey; DWORD NumEntries, Size; WCHAR buf[MAX_TAPI_STRING+1]; BOOL OverrideMissingAreaCode = FALSE; if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_NTUPGRADE) { SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page return TRUE; } if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_LOCATIONS, &hKey ) == ERROR_SUCCESS) { Size = sizeof(DWORD); if (RegQueryValueEx( hKey, REGVAL_NUMENTRIES, NULL, NULL, (LPBYTE)&NumEntries, &Size ) == ERROR_SUCCESS) { if (NumEntries > 0 && !TapiLoc.Valid) { SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page return TRUE; } } RegCloseKey( hKey ); } // Look at the existing values on the page to see if everything // is OK to go to the next page ValidateAndSetWizardButtons(hwnd); TapiLoc.Valid = FALSE; HLINEAPP hLineApp; LINEINITIALIZEEXPARAMS LineInitializeExParams; DWORD TapiDevices = 0, ModemDevices = 0; DWORD LocalTapiApiVersion = 0x00020000; DWORD Rval; LineInitializeExParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS); LineInitializeExParams.dwNeededSize = 0; LineInitializeExParams.dwUsedSize = 0; LineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT; LineInitializeExParams.Handles.hEvent = NULL; LineInitializeExParams.dwCompletionKey = 0; Rval = lineInitializeEx( &hLineApp, hInstance, NULL, TEXT("Setup"), &TapiDevices, &LocalTapiApiVersion, &LineInitializeExParams ); if (Rval == 0) { for (DWORD i=0; i< TapiDevices; i++ ) { LPLINEDEVCAPS ldc = MyLineGetDevCaps( hLineApp, LocalTapiApiVersion, i ); if (ldc) { if (IsDeviceModem(ldc)) { ModemDevices++; } LocalFree( ldc ); } } lineShutdown( hLineApp ); } // If lineInitilaizeEx failed or there are no modem devices installed // then suppress this wizard page. if ( Rval != 0 || ModemDevices == 0 ) { SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page return TRUE; } } if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_BATCH) { // // unattended mode // WCHAR Buf[MAX_TAPI_STRING+1]; TapiLoc.Country = GetPrivateProfileInt( TAPILOC_SECTION, TPILOC_COUNTRY_CODE, 1, SetupInitComponent.SetupData.UnattendFile ); GetPrivateProfileString( TAPILOC_SECTION, TPILOC_DIALING, TPILOC_TONE, Buf, MAX_TAPI_STRING, SetupInitComponent.SetupData.UnattendFile ); if (_wcsicmp( Buf, TPILOC_TONE ) == 0) { TapiLoc.Flags = LOCATION_USETONEDIALING; } else { TapiLoc.Flags = 0; } GetPrivateProfileString( TAPILOC_SECTION, TPILOC_AREA_CODE, L"1", TapiLoc.AreaCode, MAX_TAPI_STRING, SetupInitComponent.SetupData.UnattendFile ); GetPrivateProfileString( TAPILOC_SECTION, TPILOC_ACCESS, L"", TapiLoc.LongDistanceAccess, MAX_TAPI_STRING, SetupInitComponent.SetupData.UnattendFile ); TapiLoc.Valid = TRUE; SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page return TRUE; } // If we get here the user needs has click next or back. // Make sure the wizard page is showing. // For Whistler GUI mode we try to hide wizard pages and show a background // billboard if there is only a progress bar. // SetupInitComponent.HelperRoutines.ShowHideWizardPage( SetupInitComponent.HelperRoutines.OcManagerContext, TRUE); PostMessage( hwnd, MY_SET_FOCUS, 0, (LPARAM) GetDlgItem( hwnd, IDC_AREA_CODE ) ); break; case PSN_WIZNEXT: { DWORD CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETCURSEL, 0, 0 ); CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETITEMDATA, CurrCountry, 0 ); LPLINECOUNTRYENTRY LineCountryEntry = (LPLINECOUNTRYENTRY) ((LPBYTE)LineCountry + LineCountry->dwCountryListOffset); TapiLoc.Country = LineCountryEntry[CurrCountry].dwCountryID; GetDlgItemText( hwnd, IDC_AREA_CODE, TapiLoc.AreaCode, MAX_TAPI_STRING ); GetDlgItemText( hwnd, IDC_LONG_DISTANCE, TapiLoc.LongDistanceAccess, MAX_TAPI_STRING ); if (IsDlgButtonChecked( hwnd, IDC_TONE )) { TapiLoc.Flags = LOCATION_USETONEDIALING; } else { TapiLoc.Flags = 0; } // // If an area code was not set but the areacode is required, then // fail to continue "going next." // if ((TapiLoc.AreaCode[0] == 0) && (IsCityCodeOptional(LineCountryEntry + CurrCountry) == AREACODE_REQUIRED)) { SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); return TRUE; } TapiLoc.Valid = TRUE; } break; } return FALSE; } INT_PTR CALLBACK TapiLocDlgProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { CommonWizardProc( hwnd, message, wParam, lParam, WizPageTapiLoc ); switch( message ) { case WM_INITDIALOG: return TapiOnInitDialog( hwnd, (HWND)wParam, lParam ); case WM_COMMAND: return TapiOnCommand( hwnd, HIWORD(wParam), LOWORD(wParam), (HWND)lParam ); case WM_NOTIFY: return TapiOnNotify( hwnd, wParam, (LPNMHDR) lParam ); case MY_SET_FOCUS: SetFocus( (HWND) lParam ); SendMessage( (HWND) lParam, EM_SETSEL, 0, MAKELPARAM( 0, -1 ) ); return FALSE; } return FALSE; }