Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

995 lines
30 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. tapi.cpp
  5. Abstract:
  6. This file implements the tapi dialing location page.
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Wesley Witt (wesw) 7-Aug-1997
  11. --*/
  12. #include "ntoc.h"
  13. #pragma hdrstop
  14. //
  15. // constants
  16. //
  17. #define MY_SET_FOCUS (WM_USER+1000)
  18. #define REGKEY_LOCATIONS L"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations"
  19. #define REGVAL_NUMENTRIES L"NumEntries"
  20. #define INTL_SECTION L"intl"
  21. #define INTL_COUNTRY L"iCountry"
  22. #define REGKEY_LOCATION L"Location1"
  23. #define REGVAL_CURRENT_ID L"CurrentID"
  24. #define REGVAL_NEXT_ID L"NextID"
  25. #define REGVAL_NUM_ENTRIES L"NumEntries"
  26. #define REGVAL_COUNTRY L"Country"
  27. #define REGVAL_FLAGS L"Flags"
  28. #define REGVAL_ID L"ID"
  29. #define REGVAL_AREA_CODE L"AreaCode"
  30. #define REGVAL_DISABLE_CALL_WAITING L"DisableCallWaiting"
  31. #define REGVAL_LONG_DISTANCE_ACCESS L"LongDistanceAccess"
  32. #define REGVAL_NAME L"Name"
  33. #define REGVAL_OUTSIDE_ACCESS L"OutsideAccess"
  34. #define REGKEY_PROVIDERS L"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Providers"
  35. #define REGVAL_NUMPROVIDERS L"NumProviders"
  36. #define REGVAL_NEXTPROVIDERID L"NextProviderID"
  37. #define REGVAL_PROVIDERFILENAME L"ProviderFileName"
  38. #define REGVAL_PROVIDERID L"ProviderID"
  39. #define TAPILOC_SECTION L"TapiLocation"
  40. #define TPILOC_COUNTRY_CODE L"CountryCode"
  41. #define TPILOC_DIALING L"Dialing"
  42. #define TPILOC_TONE L"Tone"
  43. #define TPILOC_AREA_CODE L"AreaCode"
  44. #define TPILOC_ACCESS L"LongDistanceAccess"
  45. #define LOCATION_USETONEDIALING 0x00000001
  46. #define LOCATION_USECALLINGCARD 0x00000002
  47. #define LOCATION_HASCALLWAITING 0x00000004
  48. #define LOCATION_ALWAYSINCLUDEAREACODE 0x00000008
  49. #define MAX_TAPI_STRING 32
  50. #define PROVIDER_FILE_NAME_LEN 14 // Provider's file name has the DOS
  51. // form (8.3)
  52. //
  53. // structures
  54. //
  55. typedef struct _TAPI_LOCATION_INFO {
  56. BOOL Valid;
  57. DWORD Country;
  58. DWORD Flags;
  59. WCHAR AreaCode[MAX_TAPI_STRING+1];
  60. WCHAR LongDistanceAccess[MAX_TAPI_STRING+1];
  61. } TAPI_LOCATION_INFO, *PTAPI_LOCATION_INFO;
  62. typedef struct _TAPI_SERVICE_PROVIDER
  63. {
  64. DWORD dwProviderID;
  65. WCHAR szProviderName[PROVIDER_FILE_NAME_LEN];
  66. }TAPI_SERVICE_PROVIDER, *PTAPI_SERVICE_PROVIDER;
  67. //
  68. // globals
  69. //
  70. TAPI_LOCATION_INFO TapiLoc;
  71. LPLINECOUNTRYLIST LineCountry;
  72. BOOL TapiBadUnattend;
  73. WCHAR DefaultLocationName[MAX_PATH];
  74. BOOL
  75. IsDeviceModem(
  76. LPLINEDEVCAPS LineDevCaps
  77. )
  78. {
  79. LPTSTR DeviceClassList;
  80. BOOL UnimodemDevice = FALSE;
  81. if (LineDevCaps->dwDeviceClassesSize && LineDevCaps->dwDeviceClassesOffset) {
  82. DeviceClassList = (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwDeviceClassesOffset);
  83. while (*DeviceClassList) {
  84. if (wcscmp(DeviceClassList,TEXT("comm/datamodem")) == 0) {
  85. UnimodemDevice = TRUE;
  86. break;
  87. }
  88. DeviceClassList += (wcslen(DeviceClassList) + 1);
  89. }
  90. }
  91. if ((!(LineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE)) ||
  92. (!(LineDevCaps->dwBearerModes & LINEBEARERMODE_PASSTHROUGH))) {
  93. //
  94. // unacceptable modem device type
  95. //
  96. UnimodemDevice = FALSE;
  97. }
  98. return UnimodemDevice;
  99. }
  100. LPLINEDEVCAPS
  101. MyLineGetDevCaps(
  102. HLINEAPP hLineApp,
  103. DWORD TapiApiVersion,
  104. DWORD DeviceId
  105. )
  106. {
  107. DWORD LineDevCapsSize;
  108. LPLINEDEVCAPS LineDevCaps = NULL;
  109. LONG Rslt = ERROR_SUCCESS;
  110. DWORD LocalTapiApiVersion;
  111. LINEEXTENSIONID lineExtensionID;
  112. Rslt = lineNegotiateAPIVersion(
  113. hLineApp,
  114. DeviceId,
  115. 0x00010003,
  116. TapiApiVersion,
  117. &LocalTapiApiVersion,
  118. &lineExtensionID
  119. );
  120. //
  121. // allocate the initial linedevcaps structure
  122. //
  123. LineDevCapsSize = sizeof(LINEDEVCAPS) + 4096;
  124. LineDevCaps = (LPLINEDEVCAPS) LocalAlloc( LPTR, LineDevCapsSize );
  125. if (!LineDevCaps) {
  126. return NULL;
  127. }
  128. LineDevCaps->dwTotalSize = LineDevCapsSize;
  129. Rslt = lineGetDevCaps(
  130. hLineApp,
  131. DeviceId,
  132. LocalTapiApiVersion,
  133. 0,
  134. LineDevCaps
  135. );
  136. if (Rslt != 0) {
  137. //
  138. // lineGetDevCaps() can fail with error code 0x8000004b
  139. // if a device has been deleted and tapi has not been
  140. // cycled. this is caused by the fact that tapi leaves
  141. // a phantom device in it's device list. the error is
  142. // benign and the device can safely be ignored.
  143. //
  144. if (Rslt != LINEERR_INCOMPATIBLEAPIVERSION) {
  145. DebugPrint(( TEXT("lineGetDevCaps() failed, ec=0x%08x"), Rslt ));
  146. }
  147. goto exit;
  148. }
  149. if (LineDevCaps->dwNeededSize > LineDevCaps->dwTotalSize) {
  150. //
  151. // re-allocate the linedevcaps structure
  152. //
  153. LineDevCapsSize = LineDevCaps->dwNeededSize;
  154. LocalFree( LineDevCaps );
  155. LineDevCaps = (LPLINEDEVCAPS) LocalAlloc( LPTR, LineDevCapsSize );
  156. if (!LineDevCaps) {
  157. Rslt = ERROR_NOT_ENOUGH_MEMORY;
  158. goto exit;
  159. }
  160. Rslt = lineGetDevCaps(
  161. hLineApp,
  162. DeviceId,
  163. LocalTapiApiVersion,
  164. 0,
  165. LineDevCaps
  166. );
  167. if (Rslt != 0) {
  168. DebugPrint(( TEXT("lineGetDevCaps() failed, ec=0x%08x"), Rslt ));
  169. goto exit;
  170. }
  171. }
  172. exit:
  173. if (Rslt != ERROR_SUCCESS) {
  174. LocalFree( LineDevCaps );
  175. LineDevCaps = NULL;
  176. }
  177. return LineDevCaps;
  178. }
  179. LPLINECOUNTRYLIST
  180. MyLineGetCountry(
  181. void
  182. )
  183. {
  184. #define DEFAULT_COUNTRY_SIZE 65536
  185. LPLINECOUNTRYLIST LineCountry = (LPLINECOUNTRYLIST) LocalAlloc( LPTR, DEFAULT_COUNTRY_SIZE );
  186. if (!LineCountry) {
  187. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  188. return NULL;
  189. }
  190. LineCountry->dwTotalSize = DEFAULT_COUNTRY_SIZE;
  191. if (lineGetCountry( 0, 0x00020001, LineCountry ) != 0) {
  192. return NULL;
  193. }
  194. if (LineCountry->dwNeededSize > LineCountry->dwTotalSize) {
  195. DWORD Size = LineCountry->dwNeededSize;
  196. LocalFree( LineCountry );
  197. LineCountry = (LPLINECOUNTRYLIST) LocalAlloc( LPTR, Size );
  198. if (!LineCountry) {
  199. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  200. return(NULL);
  201. }
  202. if (lineGetCountry( 0, 0x00020001, LineCountry ) != 0) {
  203. return NULL;
  204. }
  205. }
  206. return LineCountry;
  207. }
  208. static TAPI_SERVICE_PROVIDER DefaultProviders[] = {(DWORD)-1, L"unimdm.tsp",
  209. (DWORD)-1, L"kmddsp.tsp",
  210. (DWORD)-1, L"ndptsp.tsp",
  211. (DWORD)-1, L"ipconf.tsp",
  212. (DWORD)-1, L"h323.tsp",
  213. (DWORD)-1, L"hidphone.tsp"};
  214. #define NUM_DEFAULT_PROVIDERS (sizeof(DefaultProviders)/sizeof(DefaultProviders[0]))
  215. void
  216. TapiInitializeProviders (void)
  217. {
  218. DWORD dwNextProviderID = 1;
  219. DWORD dwExistingProviders = 0;
  220. DWORD dwMaxProviderID = 0;
  221. DWORD dwNextProviderNr = 0;
  222. HKEY hKeyProviders = NULL;
  223. DWORD cbData, i, j;
  224. WCHAR szProviderFileName[24]; // Enough to hold "ProviderFileNameXXXXX\0"
  225. WCHAR szProviderID[16]; // Enough to hold "ProviderIDxxxxx\0"
  226. WCHAR szFileName[24]; // Enough to hold "ProviderFileNameXXXXX\0"
  227. WCHAR *pProviderFileNameNumber, *pProviderIDNumber;
  228. PTAPI_SERVICE_PROVIDER Providers = NULL, pProvider;
  229. // First, create / open the Providers key.
  230. if (ERROR_SUCCESS !=
  231. RegCreateKeyEx (HKEY_LOCAL_MACHINE, REGKEY_PROVIDERS, 0, NULL, REG_OPTION_NON_VOLATILE,
  232. KEY_ALL_ACCESS, NULL, &hKeyProviders, &cbData))
  233. {
  234. return;
  235. }
  236. // Initialize value names and pointers
  237. lstrcpy (szProviderFileName, REGVAL_PROVIDERFILENAME);
  238. lstrcpy (szProviderID, REGVAL_PROVIDERID);
  239. pProviderFileNameNumber = szProviderFileName + lstrlen (szProviderFileName);
  240. pProviderIDNumber = szProviderID + lstrlen (szProviderID);
  241. if (REG_CREATED_NEW_KEY == cbData)
  242. {
  243. // This means that there are no providers
  244. // in the registry yet. Go and add all the
  245. // default ones.
  246. goto _AddDefaultProviders;
  247. }
  248. // Now compute how big a provider array we have to allocate,
  249. // by looking at how many values there are in the providers key;
  250. // we divide this number by 2, because each provider will have a file
  251. // name and an ID.
  252. if (ERROR_SUCCESS !=
  253. RegQueryInfoKey (hKeyProviders,
  254. NULL, NULL, NULL, NULL, NULL, NULL,
  255. &dwExistingProviders,
  256. NULL, NULL, NULL, NULL))
  257. {
  258. goto _CountProviders;
  259. }
  260. dwExistingProviders >>= 1; // divide by 2
  261. if (0 == dwExistingProviders)
  262. {
  263. // This means that there are no providers
  264. // in the registry yet. Go and add all the
  265. // default ones.
  266. goto _AddDefaultProviders;
  267. }
  268. dwExistingProviders++; // just in case
  269. // Allocate a provider array with enough entries.
  270. Providers = (PTAPI_SERVICE_PROVIDER)LocalAlloc (LPTR, dwExistingProviders*sizeof(TAPI_SERVICE_PROVIDER));
  271. if (NULL == Providers)
  272. {
  273. // we couldn't allocate memory, so skip
  274. // looking for providers and just go and
  275. // install the default ones.
  276. goto _AddDefaultProviders;
  277. }
  278. // Next, figure out the number of providers already
  279. // installed, and the next provider ID
  280. // Instead of reading NumProviders from the registry,
  281. // try to open each ProviderIDxxx and ProviderFileNameXXX.
  282. // Do this just in case the registry is not in a good state.
  283. // Also, store the provider (unless it's t1632tsp) in the
  284. // array.
  285. _CountProviders:
  286. pProvider = Providers;
  287. dwExistingProviders = 0;
  288. for (i = 0; TRUE; i++)
  289. {
  290. BOOL bFound;
  291. wsprintf (pProviderFileNameNumber, L"%d", i);
  292. lstrcpy (pProviderIDNumber, pProviderFileNameNumber);
  293. cbData = sizeof (szFileName);
  294. if (ERROR_SUCCESS !=
  295. RegQueryValueEx (hKeyProviders, szProviderFileName, NULL, NULL, (PBYTE)szFileName, &cbData))
  296. {
  297. break;
  298. }
  299. cbData = sizeof (dwNextProviderID);
  300. if (ERROR_SUCCESS !=
  301. RegQueryValueEx (hKeyProviders, szProviderID, NULL, NULL, (PBYTE)&dwNextProviderID, &cbData))
  302. {
  303. // We couldn't read this provider's ID. We must skip it.
  304. continue;
  305. }
  306. // Look for the current provider in the list
  307. // of default providers
  308. bFound = FALSE;
  309. for (j = 0; j < NUM_DEFAULT_PROVIDERS; j++)
  310. {
  311. if (0 == lstrcmpi (DefaultProviders[j].szProviderName, szFileName))
  312. {
  313. DefaultProviders[j].dwProviderID = dwNextProviderID;
  314. bFound = TRUE;
  315. break;
  316. }
  317. }
  318. if (!bFound)
  319. {
  320. // We have a provider that was installed by the user on the previous NT installation.
  321. pProvider->dwProviderID = dwNextProviderID;
  322. lstrcpy (pProvider->szProviderName, szFileName);
  323. pProvider++;
  324. dwExistingProviders++;
  325. }
  326. if (dwNextProviderID > dwMaxProviderID)
  327. {
  328. dwMaxProviderID = dwNextProviderID;
  329. }
  330. }
  331. dwNextProviderID = dwMaxProviderID + 1;
  332. // We got a list of all providers that were installed before.
  333. // Clean up the Providers key.
  334. for (i = 0; TRUE; i++)
  335. {
  336. cbData = sizeof(szFileName)/sizeof(WCHAR);
  337. if (ERROR_SUCCESS !=
  338. RegEnumValue (hKeyProviders, i, szFileName, &cbData, NULL, NULL, NULL, NULL))
  339. {
  340. break;
  341. }
  342. RegDeleteValue (hKeyProviders, szFileName);
  343. }
  344. _AddDefaultProviders:
  345. for (i = 0, pProvider = DefaultProviders;
  346. i < NUM_DEFAULT_PROVIDERS;
  347. i++, pProvider++)
  348. {
  349. // Found a provider that has to be added.
  350. // Compute it's value names.
  351. wsprintf (pProviderFileNameNumber, L"%d", dwNextProviderNr);
  352. lstrcpy (pProviderIDNumber, pProviderFileNameNumber);
  353. if (ERROR_SUCCESS ==
  354. RegSetValueEx (hKeyProviders, szProviderFileName, 0, REG_SZ, (PBYTE)pProvider->szProviderName,
  355. (lstrlen(pProvider->szProviderName)+1)*sizeof(WCHAR)))
  356. {
  357. DWORD dwRet;
  358. if ((DWORD)-1 == pProvider->dwProviderID)
  359. {
  360. if (ERROR_SUCCESS == (dwRet =
  361. RegSetValueEx (hKeyProviders, szProviderID, 0, REG_DWORD,
  362. (PBYTE)&dwNextProviderID, sizeof(dwNextProviderID))))
  363. {
  364. dwNextProviderID++;
  365. }
  366. }
  367. else
  368. {
  369. dwRet = RegSetValueEx (hKeyProviders, szProviderID, 0, REG_DWORD,
  370. (PBYTE)&pProvider->dwProviderID, sizeof(pProvider->dwProviderID));
  371. }
  372. if (ERROR_SUCCESS == dwRet)
  373. {
  374. dwNextProviderNr++;
  375. }
  376. else
  377. {
  378. RegDeleteValue (hKeyProviders, szProviderFileName);
  379. }
  380. }
  381. }
  382. // Now, add all the providers again. We do this because the
  383. // IDs were REG_BINARY on win98 and have to be REG_DWORD on NT5.
  384. for (i = 0, pProvider = Providers;
  385. i < dwExistingProviders;
  386. i++, pProvider++)
  387. {
  388. // Found a provider that has to be added.
  389. // Compute it's value names.
  390. wsprintf (pProviderFileNameNumber, L"%d", dwNextProviderNr);
  391. lstrcpy (pProviderIDNumber, pProviderFileNameNumber);
  392. if (ERROR_SUCCESS ==
  393. RegSetValueEx (hKeyProviders, szProviderFileName, 0, REG_SZ,
  394. (PBYTE)pProvider->szProviderName,
  395. (lstrlen(pProvider->szProviderName)+1)*sizeof(WCHAR)))
  396. {
  397. if (ERROR_SUCCESS ==
  398. RegSetValueEx (hKeyProviders, szProviderID, 0, REG_DWORD,
  399. (PBYTE)&pProvider->dwProviderID,
  400. sizeof(pProvider->dwProviderID)))
  401. {
  402. dwNextProviderNr++;
  403. }
  404. else
  405. {
  406. RegDeleteValue (hKeyProviders, szProviderFileName);
  407. }
  408. }
  409. }
  410. // Finally, update NumProviders and NextProviderID.
  411. RegSetValueEx (hKeyProviders, REGVAL_NUMPROVIDERS, 0, REG_DWORD,
  412. (PBYTE)&dwNextProviderNr, sizeof(dwNextProviderNr));
  413. RegSetValueEx (hKeyProviders, REGVAL_NEXTPROVIDERID, 0, REG_DWORD,
  414. (PBYTE)&dwNextProviderID, sizeof(dwNextProviderID));
  415. RegCloseKey (hKeyProviders);
  416. if (NULL != Providers)
  417. {
  418. LocalFree (Providers);
  419. }
  420. }
  421. void
  422. CopyTsecFile (
  423. void
  424. )
  425. {
  426. TCHAR szWndDir[MAX_PATH];
  427. TCHAR szSrc[MAX_PATH];
  428. TCHAR szDest[MAX_PATH];
  429. TCHAR szBuf[MAX_PATH];
  430. HANDLE hFileIn = INVALID_HANDLE_VALUE;
  431. HANDLE hFileOut = INVALID_HANDLE_VALUE;
  432. const TCHAR szTsecSrc[] = TEXT("\\tsec.ini");
  433. const TCHAR szTsecDest[] = TEXT("\\TAPI\\tsec.ini");
  434. DWORD dwBytesRead, dwBytesWritten;
  435. BOOL bError = FALSE;
  436. if (GetWindowsDirectory (szWndDir, sizeof(szWndDir)/sizeof(TCHAR)) == 0 ||
  437. lstrlen(szWndDir) + lstrlen(szTsecSrc) >= sizeof(szSrc)/sizeof(TCHAR) ||
  438. lstrlen(szWndDir) + lstrlen(szTsecDest) >= sizeof(szDest)/sizeof(TCHAR))
  439. {
  440. goto ExitHere;
  441. }
  442. lstrcpy (szSrc, szWndDir);
  443. lstrcat (szSrc, szTsecSrc);
  444. lstrcpy (szDest, szWndDir);
  445. lstrcat (szDest, szTsecDest);
  446. hFileIn = CreateFile (
  447. szSrc,
  448. GENERIC_READ,
  449. FILE_SHARE_READ,
  450. NULL,
  451. OPEN_EXISTING,
  452. FILE_ATTRIBUTE_NORMAL,
  453. NULL
  454. );
  455. hFileOut = CreateFile (
  456. szDest,
  457. GENERIC_WRITE,
  458. FILE_SHARE_READ,
  459. NULL,
  460. CREATE_NEW,
  461. FILE_ATTRIBUTE_NORMAL,
  462. NULL);
  463. if (hFileIn == INVALID_HANDLE_VALUE || hFileOut == INVALID_HANDLE_VALUE)
  464. {
  465. goto ExitHere;
  466. }
  467. do
  468. {
  469. if (!ReadFile (
  470. hFileIn,
  471. (LPVOID) szBuf,
  472. sizeof(szBuf),
  473. &dwBytesRead,
  474. NULL)
  475. )
  476. {
  477. bError = TRUE;
  478. dwBytesRead = 0;
  479. }
  480. if (dwBytesRead != 0)
  481. {
  482. if (!WriteFile (
  483. hFileOut,
  484. (LPVOID) szBuf,
  485. dwBytesRead,
  486. &dwBytesWritten,
  487. NULL
  488. ) ||
  489. dwBytesRead != dwBytesWritten)
  490. {
  491. bError = TRUE;
  492. }
  493. }
  494. } while (dwBytesRead != 0);
  495. //
  496. // Be extra careful not to loose any data, delete
  497. // old file only if we are sure no error happened
  498. //
  499. if (!bError)
  500. {
  501. CloseHandle (hFileIn);
  502. hFileIn = INVALID_HANDLE_VALUE;
  503. DeleteFile (szSrc);
  504. }
  505. ExitHere:
  506. if (hFileIn != INVALID_HANDLE_VALUE)
  507. {
  508. CloseHandle (hFileIn);
  509. }
  510. if (hFileOut != INVALID_HANDLE_VALUE)
  511. {
  512. CloseHandle (hFileOut);
  513. }
  514. }
  515. void
  516. TapiInit(
  517. void
  518. )
  519. {
  520. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_STANDALONE) {
  521. return;
  522. }
  523. CopyTsecFile();
  524. TapiInitializeProviders ();
  525. LineCountry = MyLineGetCountry();
  526. LoadString( hInstance, IDS_DEFAULT_LOCATION_NAME, DefaultLocationName, sizeof(DefaultLocationName)/sizeof(WCHAR) );
  527. }
  528. void
  529. TapiCommitChanges(
  530. void
  531. )
  532. {
  533. HKEY hKey, hKeyLoc;
  534. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_STANDALONE) {
  535. return;
  536. }
  537. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_NTUPGRADE) {
  538. return;
  539. }
  540. if (TapiLoc.Valid) {
  541. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_LOCATIONS, TRUE, KEY_ALL_ACCESS );
  542. if (hKey) {
  543. SetRegistryDword( hKey, REGVAL_CURRENT_ID, 1 );
  544. SetRegistryDword( hKey, REGVAL_NEXT_ID, 2 );
  545. // SetRegistryDword( hKey, REGVAL_NUM_ENTRIES, 1 );
  546. hKeyLoc = OpenRegistryKey( hKey, REGKEY_LOCATION, TRUE, KEY_ALL_ACCESS );
  547. if (hKeyLoc) {
  548. SetRegistryDword( hKeyLoc, REGVAL_COUNTRY, TapiLoc.Country );
  549. SetRegistryDword( hKeyLoc, REGVAL_FLAGS, TapiLoc.Flags );
  550. // SetRegistryDword( hKeyLoc, REGVAL_ID, 1 );
  551. SetRegistryString( hKeyLoc, REGVAL_AREA_CODE, TapiLoc.AreaCode );
  552. SetRegistryString( hKeyLoc, REGVAL_DISABLE_CALL_WAITING, L"" );
  553. SetRegistryString( hKeyLoc, REGVAL_LONG_DISTANCE_ACCESS, TapiLoc.LongDistanceAccess );
  554. SetRegistryString( hKeyLoc, REGVAL_NAME, DefaultLocationName );
  555. SetRegistryString( hKeyLoc, REGVAL_OUTSIDE_ACCESS, TapiLoc.LongDistanceAccess );
  556. RegCloseKey( hKeyLoc );
  557. }
  558. RegCloseKey( hKey );
  559. }
  560. }
  561. }
  562. INT
  563. IsCityCodeOptional(
  564. LPLINECOUNTRYENTRY pEntry
  565. )
  566. {
  567. #define AREACODE_DONTNEED 0
  568. #define AREACODE_REQUIRED 1
  569. #define AREACODE_OPTIONAL 2
  570. if (pEntry && pEntry->dwLongDistanceRuleSize && pEntry->dwLongDistanceRuleOffset )
  571. {
  572. LPWSTR pLongDistanceRule;
  573. pLongDistanceRule = (LPTSTR)((PBYTE)LineCountry + pEntry->dwLongDistanceRuleOffset);
  574. if (wcschr(pLongDistanceRule, L'F') != NULL) return AREACODE_REQUIRED;
  575. if (wcschr(pLongDistanceRule, L'I') == NULL) return AREACODE_DONTNEED;
  576. }
  577. return AREACODE_OPTIONAL;
  578. }
  579. BOOL
  580. TapiOnInitDialog(
  581. IN HWND hwnd,
  582. IN HWND hwndFocus,
  583. IN LPARAM lParam
  584. )
  585. {
  586. SendDlgItemMessage( hwnd, IDC_AREA_CODE, EM_LIMITTEXT, MAX_TAPI_STRING, 0 );
  587. SendDlgItemMessage( hwnd, IDC_LONG_DISTANCE, EM_LIMITTEXT, MAX_TAPI_STRING, 0 );
  588. CheckRadioButton( hwnd, IDC_TONE, IDC_PULSE, IDC_TONE );
  589. if (LineCountry) {
  590. DWORD CurrCountryCode = GetProfileInt( INTL_SECTION, INTL_COUNTRY, 1 );
  591. LPLINECOUNTRYENTRY LineCountryEntry = (LPLINECOUNTRYENTRY) ((LPBYTE)LineCountry + LineCountry->dwCountryListOffset);
  592. DWORD Selection = 0;
  593. DWORD Index;
  594. LPWSTR CountryName ;
  595. for (DWORD i=0; i<LineCountry->dwNumCountries; i++) {
  596. CountryName = (LPWSTR) ((LPBYTE)LineCountry + LineCountryEntry[i].dwCountryNameOffset);
  597. Index = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_ADDSTRING, 0, (LPARAM)CountryName );
  598. SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_SETITEMDATA, Index, i );
  599. if (LineCountryEntry[i].dwCountryID == CurrCountryCode) {
  600. Selection = i;
  601. }
  602. }
  603. CountryName = (LPWSTR) ((LPBYTE)LineCountry + LineCountryEntry[Selection].dwCountryNameOffset);
  604. Selection = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_FINDSTRING, 0, (LPARAM) CountryName );
  605. SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_SETCURSEL, Selection, 0 );
  606. }
  607. PostMessage( hwnd, MY_SET_FOCUS, 0, (LPARAM) GetDlgItem( hwnd, IDC_AREA_CODE ) );
  608. return TRUE;
  609. }
  610. VOID
  611. ValidateAndSetWizardButtons( HWND hwnd )
  612. {
  613. BOOL AreaCodeOk;
  614. {
  615. DWORD CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETCURSEL, 0, 0 );
  616. LPLINECOUNTRYENTRY CntryFirstEntry = NULL;
  617. INT AreaCodeInfo = 0;
  618. WCHAR Buffer[MAX_TAPI_STRING+1];
  619. GetDlgItemText( hwnd, IDC_AREA_CODE, Buffer, MAX_TAPI_STRING );
  620. CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETITEMDATA, CurrCountry, 0 );
  621. CntryFirstEntry = (LPLINECOUNTRYENTRY)((LPBYTE)LineCountry + LineCountry->dwCountryListOffset);
  622. AreaCodeInfo = IsCityCodeOptional( CntryFirstEntry + CurrCountry );
  623. AreaCodeOk = TRUE;
  624. //
  625. // If the area code is required, then there must be a value in the Buffer.
  626. //
  627. // Otherwise, it's OK.
  628. //
  629. if ( ( AreaCodeInfo == AREACODE_REQUIRED ) && ( *Buffer == UNICODE_NULL ) ){
  630. AreaCodeOk = FALSE;
  631. }
  632. }
  633. if ( TapiLoc.Valid )
  634. AreaCodeOk = TRUE;
  635. PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_BACK | ( AreaCodeOk ? PSWIZB_NEXT : 0 ) );
  636. }
  637. BOOL
  638. TapiOnCommand(
  639. IN HWND hwnd,
  640. IN DWORD NotifyCode,
  641. IN DWORD ControlId,
  642. IN HWND hwndControl
  643. )
  644. {
  645. // If the area code changed, or the country code changed
  646. if ((NotifyCode == EN_CHANGE && ControlId == IDC_AREA_CODE) ||
  647. (NotifyCode == CBN_SELCHANGE && ControlId == IDC_COUNTRY_LIST)) {
  648. ValidateAndSetWizardButtons(hwnd);
  649. }
  650. return TRUE;
  651. }
  652. BOOL
  653. TapiOnNotify(
  654. IN HWND hwnd,
  655. IN WPARAM ControlId,
  656. IN LPNMHDR pnmh
  657. )
  658. {
  659. switch (pnmh->code ) {
  660. case PSN_SETACTIVE:
  661. {
  662. HKEY hKey;
  663. DWORD NumEntries, Size;
  664. WCHAR buf[MAX_TAPI_STRING+1];
  665. BOOL OverrideMissingAreaCode = FALSE;
  666. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_NTUPGRADE) {
  667. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page
  668. return TRUE;
  669. }
  670. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_LOCATIONS, &hKey ) == ERROR_SUCCESS) {
  671. Size = sizeof(DWORD);
  672. if (RegQueryValueEx( hKey, REGVAL_NUMENTRIES, NULL, NULL, (LPBYTE)&NumEntries, &Size ) == ERROR_SUCCESS) {
  673. if (NumEntries > 0 && !TapiLoc.Valid) {
  674. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page
  675. return TRUE;
  676. }
  677. }
  678. RegCloseKey( hKey );
  679. }
  680. // Look at the existing values on the page to see if everything
  681. // is OK to go to the next page
  682. ValidateAndSetWizardButtons(hwnd);
  683. TapiLoc.Valid = FALSE;
  684. HLINEAPP hLineApp;
  685. LINEINITIALIZEEXPARAMS LineInitializeExParams;
  686. DWORD TapiDevices = 0, ModemDevices = 0;
  687. DWORD LocalTapiApiVersion = 0x00020000;
  688. DWORD Rval;
  689. LineInitializeExParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
  690. LineInitializeExParams.dwNeededSize = 0;
  691. LineInitializeExParams.dwUsedSize = 0;
  692. LineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
  693. LineInitializeExParams.Handles.hEvent = NULL;
  694. LineInitializeExParams.dwCompletionKey = 0;
  695. Rval = lineInitializeEx(
  696. &hLineApp,
  697. hInstance,
  698. NULL,
  699. TEXT("Setup"),
  700. &TapiDevices,
  701. &LocalTapiApiVersion,
  702. &LineInitializeExParams
  703. );
  704. if (Rval == 0) {
  705. for (DWORD i=0; i< TapiDevices; i++ ) {
  706. LPLINEDEVCAPS ldc = MyLineGetDevCaps( hLineApp, LocalTapiApiVersion, i );
  707. if (ldc) {
  708. if (IsDeviceModem(ldc)) {
  709. ModemDevices++;
  710. }
  711. LocalFree( ldc );
  712. }
  713. }
  714. lineShutdown( hLineApp );
  715. }
  716. // If lineInitilaizeEx failed or there are no modem devices installed
  717. // then suppress this wizard page.
  718. if ( Rval != 0 || ModemDevices == 0 )
  719. {
  720. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page
  721. return TRUE;
  722. }
  723. }
  724. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_BATCH) {
  725. //
  726. // unattended mode
  727. //
  728. WCHAR Buf[MAX_TAPI_STRING+1];
  729. TapiLoc.Country = GetPrivateProfileInt(
  730. TAPILOC_SECTION,
  731. TPILOC_COUNTRY_CODE,
  732. 1,
  733. SetupInitComponent.SetupData.UnattendFile
  734. );
  735. GetPrivateProfileString(
  736. TAPILOC_SECTION,
  737. TPILOC_DIALING,
  738. TPILOC_TONE,
  739. Buf,
  740. MAX_TAPI_STRING,
  741. SetupInitComponent.SetupData.UnattendFile
  742. );
  743. if (_wcsicmp( Buf, TPILOC_TONE ) == 0) {
  744. TapiLoc.Flags = LOCATION_USETONEDIALING;
  745. } else {
  746. TapiLoc.Flags = 0;
  747. }
  748. GetPrivateProfileString(
  749. TAPILOC_SECTION,
  750. TPILOC_AREA_CODE,
  751. L"1",
  752. TapiLoc.AreaCode,
  753. MAX_TAPI_STRING,
  754. SetupInitComponent.SetupData.UnattendFile
  755. );
  756. GetPrivateProfileString(
  757. TAPILOC_SECTION,
  758. TPILOC_ACCESS,
  759. L"",
  760. TapiLoc.LongDistanceAccess,
  761. MAX_TAPI_STRING,
  762. SetupInitComponent.SetupData.UnattendFile
  763. );
  764. TapiLoc.Valid = TRUE;
  765. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page
  766. return TRUE;
  767. }
  768. // If we get here the user needs has click next or back.
  769. // Make sure the wizard page is showing.
  770. // For Whistler GUI mode we try to hide wizard pages and show a background
  771. // billboard if there is only a progress bar.
  772. //
  773. SetupInitComponent.HelperRoutines.ShowHideWizardPage(
  774. SetupInitComponent.HelperRoutines.OcManagerContext,
  775. TRUE);
  776. PostMessage( hwnd, MY_SET_FOCUS, 0, (LPARAM) GetDlgItem( hwnd, IDC_AREA_CODE ) );
  777. break;
  778. case PSN_WIZNEXT:
  779. {
  780. DWORD CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETCURSEL, 0, 0 );
  781. CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETITEMDATA, CurrCountry, 0 );
  782. LPLINECOUNTRYENTRY LineCountryEntry = (LPLINECOUNTRYENTRY) ((LPBYTE)LineCountry + LineCountry->dwCountryListOffset);
  783. TapiLoc.Country = LineCountryEntry[CurrCountry].dwCountryID;
  784. GetDlgItemText( hwnd, IDC_AREA_CODE, TapiLoc.AreaCode, MAX_TAPI_STRING );
  785. GetDlgItemText( hwnd, IDC_LONG_DISTANCE, TapiLoc.LongDistanceAccess, MAX_TAPI_STRING );
  786. if (IsDlgButtonChecked( hwnd, IDC_TONE )) {
  787. TapiLoc.Flags = LOCATION_USETONEDIALING;
  788. } else {
  789. TapiLoc.Flags = 0;
  790. }
  791. //
  792. // If an area code was not set but the areacode is required, then
  793. // fail to continue "going next."
  794. //
  795. if ((TapiLoc.AreaCode[0] == 0) &&
  796. (IsCityCodeOptional(LineCountryEntry + CurrCountry) == AREACODE_REQUIRED)) {
  797. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 );
  798. return TRUE;
  799. }
  800. TapiLoc.Valid = TRUE;
  801. }
  802. break;
  803. }
  804. return FALSE;
  805. }
  806. LRESULT
  807. TapiLocDlgProc(
  808. HWND hwnd,
  809. UINT message,
  810. WPARAM wParam,
  811. LPARAM lParam
  812. )
  813. {
  814. CommonWizardProc( hwnd, message, wParam, lParam, WizPageTapiLoc );
  815. switch( message ) {
  816. case WM_INITDIALOG:
  817. return TapiOnInitDialog( hwnd, (HWND)wParam, lParam );
  818. case WM_COMMAND:
  819. return TapiOnCommand( hwnd, HIWORD(wParam), LOWORD(wParam), (HWND)lParam );
  820. case WM_NOTIFY:
  821. return TapiOnNotify( hwnd, wParam, (LPNMHDR) lParam );
  822. case MY_SET_FOCUS:
  823. SetFocus( (HWND) lParam );
  824. SendMessage( (HWND) lParam, EM_SETSEL, 0, MAKELPARAM( 0, -1 ) );
  825. return FALSE;
  826. }
  827. return FALSE;
  828. }