Leaked source code of windows server 2003
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.

997 lines
32 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. pProvider->szProviderName[0] = 0;
  323. lstrcpyn (pProvider->szProviderName, szFileName, sizeof(pProvider->szProviderName)/sizeof(pProvider->szProviderName[0]));
  324. pProvider->szProviderName[sizeof(pProvider->szProviderName)/sizeof(pProvider->szProviderName[0])-1] = 0;
  325. pProvider++;
  326. dwExistingProviders++;
  327. }
  328. if (dwNextProviderID > dwMaxProviderID)
  329. {
  330. dwMaxProviderID = dwNextProviderID;
  331. }
  332. }
  333. dwNextProviderID = dwMaxProviderID + 1;
  334. // We got a list of all providers that were installed before.
  335. // Clean up the Providers key.
  336. for (i = 0; TRUE; i++)
  337. {
  338. cbData = sizeof(szFileName)/sizeof(WCHAR);
  339. if (ERROR_SUCCESS !=
  340. RegEnumValue (hKeyProviders, i, szFileName, &cbData, NULL, NULL, NULL, NULL))
  341. {
  342. break;
  343. }
  344. RegDeleteValue (hKeyProviders, szFileName);
  345. }
  346. _AddDefaultProviders:
  347. for (i = 0, pProvider = DefaultProviders;
  348. i < NUM_DEFAULT_PROVIDERS;
  349. i++, pProvider++)
  350. {
  351. // Found a provider that has to be added.
  352. // Compute it's value names.
  353. wsprintf (pProviderFileNameNumber, L"%d", dwNextProviderNr);
  354. lstrcpy (pProviderIDNumber, pProviderFileNameNumber);
  355. if (ERROR_SUCCESS ==
  356. RegSetValueEx (hKeyProviders, szProviderFileName, 0, REG_SZ, (PBYTE)pProvider->szProviderName,
  357. (lstrlen(pProvider->szProviderName)+1)*sizeof(WCHAR)))
  358. {
  359. DWORD dwRet;
  360. if ((DWORD)-1 == pProvider->dwProviderID)
  361. {
  362. if (ERROR_SUCCESS == (dwRet =
  363. RegSetValueEx (hKeyProviders, szProviderID, 0, REG_DWORD,
  364. (PBYTE)&dwNextProviderID, sizeof(dwNextProviderID))))
  365. {
  366. dwNextProviderID++;
  367. }
  368. }
  369. else
  370. {
  371. dwRet = RegSetValueEx (hKeyProviders, szProviderID, 0, REG_DWORD,
  372. (PBYTE)&pProvider->dwProviderID, sizeof(pProvider->dwProviderID));
  373. }
  374. if (ERROR_SUCCESS == dwRet)
  375. {
  376. dwNextProviderNr++;
  377. }
  378. else
  379. {
  380. RegDeleteValue (hKeyProviders, szProviderFileName);
  381. }
  382. }
  383. }
  384. // Now, add all the providers again. We do this because the
  385. // IDs were REG_BINARY on win98 and have to be REG_DWORD on NT5.
  386. for (i = 0, pProvider = Providers;
  387. i < dwExistingProviders;
  388. i++, pProvider++)
  389. {
  390. // Found a provider that has to be added.
  391. // Compute it's value names.
  392. wsprintf (pProviderFileNameNumber, L"%d", dwNextProviderNr);
  393. lstrcpy (pProviderIDNumber, pProviderFileNameNumber);
  394. if (ERROR_SUCCESS ==
  395. RegSetValueEx (hKeyProviders, szProviderFileName, 0, REG_SZ,
  396. (PBYTE)pProvider->szProviderName,
  397. (lstrlen(pProvider->szProviderName)+1)*sizeof(WCHAR)))
  398. {
  399. if (ERROR_SUCCESS ==
  400. RegSetValueEx (hKeyProviders, szProviderID, 0, REG_DWORD,
  401. (PBYTE)&pProvider->dwProviderID,
  402. sizeof(pProvider->dwProviderID)))
  403. {
  404. dwNextProviderNr++;
  405. }
  406. else
  407. {
  408. RegDeleteValue (hKeyProviders, szProviderFileName);
  409. }
  410. }
  411. }
  412. // Finally, update NumProviders and NextProviderID.
  413. RegSetValueEx (hKeyProviders, REGVAL_NUMPROVIDERS, 0, REG_DWORD,
  414. (PBYTE)&dwNextProviderNr, sizeof(dwNextProviderNr));
  415. RegSetValueEx (hKeyProviders, REGVAL_NEXTPROVIDERID, 0, REG_DWORD,
  416. (PBYTE)&dwNextProviderID, sizeof(dwNextProviderID));
  417. RegCloseKey (hKeyProviders);
  418. if (NULL != Providers)
  419. {
  420. LocalFree (Providers);
  421. }
  422. }
  423. void
  424. CopyTsecFile (
  425. void
  426. )
  427. {
  428. TCHAR szWndDir[MAX_PATH];
  429. TCHAR szSrc[MAX_PATH];
  430. TCHAR szDest[MAX_PATH];
  431. TCHAR szBuf[MAX_PATH];
  432. HANDLE hFileIn = INVALID_HANDLE_VALUE;
  433. HANDLE hFileOut = INVALID_HANDLE_VALUE;
  434. const TCHAR szTsecSrc[] = TEXT("\\tsec.ini");
  435. const TCHAR szTsecDest[] = TEXT("\\TAPI\\tsec.ini");
  436. DWORD dwBytesRead, dwBytesWritten;
  437. BOOL bError = FALSE;
  438. if (GetWindowsDirectory (szWndDir, sizeof(szWndDir)/sizeof(TCHAR)) == 0 ||
  439. lstrlen(szWndDir) + lstrlen(szTsecSrc) >= sizeof(szSrc)/sizeof(TCHAR) ||
  440. lstrlen(szWndDir) + lstrlen(szTsecDest) >= sizeof(szDest)/sizeof(TCHAR))
  441. {
  442. goto ExitHere;
  443. }
  444. lstrcpy (szSrc, szWndDir);
  445. lstrcat (szSrc, szTsecSrc);
  446. lstrcpy (szDest, szWndDir);
  447. lstrcat (szDest, szTsecDest);
  448. hFileIn = CreateFile (
  449. szSrc,
  450. GENERIC_READ,
  451. FILE_SHARE_READ,
  452. NULL,
  453. OPEN_EXISTING,
  454. FILE_ATTRIBUTE_NORMAL,
  455. NULL
  456. );
  457. hFileOut = CreateFile (
  458. szDest,
  459. GENERIC_WRITE,
  460. FILE_SHARE_READ,
  461. NULL,
  462. CREATE_NEW,
  463. FILE_ATTRIBUTE_NORMAL,
  464. NULL);
  465. if (hFileIn == INVALID_HANDLE_VALUE || hFileOut == INVALID_HANDLE_VALUE)
  466. {
  467. goto ExitHere;
  468. }
  469. do
  470. {
  471. if (!ReadFile (
  472. hFileIn,
  473. (LPVOID) szBuf,
  474. sizeof(szBuf),
  475. &dwBytesRead,
  476. NULL)
  477. )
  478. {
  479. bError = TRUE;
  480. dwBytesRead = 0;
  481. }
  482. if (dwBytesRead != 0)
  483. {
  484. if (!WriteFile (
  485. hFileOut,
  486. (LPVOID) szBuf,
  487. dwBytesRead,
  488. &dwBytesWritten,
  489. NULL
  490. ) ||
  491. dwBytesRead != dwBytesWritten)
  492. {
  493. bError = TRUE;
  494. }
  495. }
  496. } while (dwBytesRead != 0);
  497. //
  498. // Be extra careful not to loose any data, delete
  499. // old file only if we are sure no error happened
  500. //
  501. if (!bError)
  502. {
  503. CloseHandle (hFileIn);
  504. hFileIn = INVALID_HANDLE_VALUE;
  505. DeleteFile (szSrc);
  506. }
  507. ExitHere:
  508. if (hFileIn != INVALID_HANDLE_VALUE)
  509. {
  510. CloseHandle (hFileIn);
  511. }
  512. if (hFileOut != INVALID_HANDLE_VALUE)
  513. {
  514. CloseHandle (hFileOut);
  515. }
  516. }
  517. void
  518. TapiInit(
  519. void
  520. )
  521. {
  522. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_STANDALONE) {
  523. return;
  524. }
  525. CopyTsecFile();
  526. TapiInitializeProviders ();
  527. LineCountry = MyLineGetCountry();
  528. LoadString( hInstance, IDS_DEFAULT_LOCATION_NAME, DefaultLocationName, sizeof(DefaultLocationName)/sizeof(WCHAR) );
  529. }
  530. void
  531. TapiCommitChanges(
  532. void
  533. )
  534. {
  535. HKEY hKey, hKeyLoc;
  536. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_STANDALONE) {
  537. return;
  538. }
  539. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_NTUPGRADE) {
  540. return;
  541. }
  542. if (TapiLoc.Valid) {
  543. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_LOCATIONS, TRUE, KEY_ALL_ACCESS );
  544. if (hKey) {
  545. SetRegistryDword( hKey, REGVAL_CURRENT_ID, 1 );
  546. SetRegistryDword( hKey, REGVAL_NEXT_ID, 2 );
  547. // SetRegistryDword( hKey, REGVAL_NUM_ENTRIES, 1 );
  548. hKeyLoc = OpenRegistryKey( hKey, REGKEY_LOCATION, TRUE, KEY_ALL_ACCESS );
  549. if (hKeyLoc) {
  550. SetRegistryDword( hKeyLoc, REGVAL_COUNTRY, TapiLoc.Country );
  551. SetRegistryDword( hKeyLoc, REGVAL_FLAGS, TapiLoc.Flags );
  552. // SetRegistryDword( hKeyLoc, REGVAL_ID, 1 );
  553. SetRegistryString( hKeyLoc, REGVAL_AREA_CODE, TapiLoc.AreaCode );
  554. SetRegistryString( hKeyLoc, REGVAL_DISABLE_CALL_WAITING, L"" );
  555. SetRegistryString( hKeyLoc, REGVAL_LONG_DISTANCE_ACCESS, TapiLoc.LongDistanceAccess );
  556. SetRegistryString( hKeyLoc, REGVAL_NAME, DefaultLocationName );
  557. SetRegistryString( hKeyLoc, REGVAL_OUTSIDE_ACCESS, TapiLoc.LongDistanceAccess );
  558. RegCloseKey( hKeyLoc );
  559. }
  560. RegCloseKey( hKey );
  561. }
  562. }
  563. }
  564. INT
  565. IsCityCodeOptional(
  566. LPLINECOUNTRYENTRY pEntry
  567. )
  568. {
  569. #define AREACODE_DONTNEED 0
  570. #define AREACODE_REQUIRED 1
  571. #define AREACODE_OPTIONAL 2
  572. if (pEntry && pEntry->dwLongDistanceRuleSize && pEntry->dwLongDistanceRuleOffset )
  573. {
  574. LPWSTR pLongDistanceRule;
  575. pLongDistanceRule = (LPTSTR)((PBYTE)LineCountry + pEntry->dwLongDistanceRuleOffset);
  576. if (wcschr(pLongDistanceRule, L'F') != NULL) return AREACODE_REQUIRED;
  577. if (wcschr(pLongDistanceRule, L'I') == NULL) return AREACODE_DONTNEED;
  578. }
  579. return AREACODE_OPTIONAL;
  580. }
  581. BOOL
  582. TapiOnInitDialog(
  583. IN HWND hwnd,
  584. IN HWND hwndFocus,
  585. IN LPARAM lParam
  586. )
  587. {
  588. SendDlgItemMessage( hwnd, IDC_AREA_CODE, EM_LIMITTEXT, MAX_TAPI_STRING, 0 );
  589. SendDlgItemMessage( hwnd, IDC_LONG_DISTANCE, EM_LIMITTEXT, MAX_TAPI_STRING, 0 );
  590. CheckRadioButton( hwnd, IDC_TONE, IDC_PULSE, IDC_TONE );
  591. if (LineCountry) {
  592. DWORD CurrCountryCode = GetProfileInt( INTL_SECTION, INTL_COUNTRY, 1 );
  593. LPLINECOUNTRYENTRY LineCountryEntry = (LPLINECOUNTRYENTRY) ((LPBYTE)LineCountry + LineCountry->dwCountryListOffset);
  594. DWORD Selection = 0;
  595. DWORD Index;
  596. LPWSTR CountryName ;
  597. for (DWORD i=0; i<LineCountry->dwNumCountries; i++) {
  598. CountryName = (LPWSTR) ((LPBYTE)LineCountry + LineCountryEntry[i].dwCountryNameOffset);
  599. Index = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_ADDSTRING, 0, (LPARAM)CountryName );
  600. SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_SETITEMDATA, Index, i );
  601. if (LineCountryEntry[i].dwCountryID == CurrCountryCode) {
  602. Selection = i;
  603. }
  604. }
  605. CountryName = (LPWSTR) ((LPBYTE)LineCountry + LineCountryEntry[Selection].dwCountryNameOffset);
  606. Selection = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_FINDSTRING, 0, (LPARAM) CountryName );
  607. SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_SETCURSEL, Selection, 0 );
  608. }
  609. PostMessage( hwnd, MY_SET_FOCUS, 0, (LPARAM) GetDlgItem( hwnd, IDC_AREA_CODE ) );
  610. return TRUE;
  611. }
  612. VOID
  613. ValidateAndSetWizardButtons( HWND hwnd )
  614. {
  615. BOOL AreaCodeOk;
  616. {
  617. DWORD CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETCURSEL, 0, 0 );
  618. LPLINECOUNTRYENTRY CntryFirstEntry = NULL;
  619. INT AreaCodeInfo = 0;
  620. WCHAR Buffer[MAX_TAPI_STRING+1];
  621. GetDlgItemText( hwnd, IDC_AREA_CODE, Buffer, MAX_TAPI_STRING );
  622. CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETITEMDATA, CurrCountry, 0 );
  623. CntryFirstEntry = (LPLINECOUNTRYENTRY)((LPBYTE)LineCountry + LineCountry->dwCountryListOffset);
  624. AreaCodeInfo = IsCityCodeOptional( CntryFirstEntry + CurrCountry );
  625. AreaCodeOk = TRUE;
  626. //
  627. // If the area code is required, then there must be a value in the Buffer.
  628. //
  629. // Otherwise, it's OK.
  630. //
  631. if ( ( AreaCodeInfo == AREACODE_REQUIRED ) && ( *Buffer == UNICODE_NULL ) ){
  632. AreaCodeOk = FALSE;
  633. }
  634. }
  635. if ( TapiLoc.Valid )
  636. AreaCodeOk = TRUE;
  637. PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_BACK | ( AreaCodeOk ? PSWIZB_NEXT : 0 ) );
  638. }
  639. BOOL
  640. TapiOnCommand(
  641. IN HWND hwnd,
  642. IN DWORD NotifyCode,
  643. IN DWORD ControlId,
  644. IN HWND hwndControl
  645. )
  646. {
  647. // If the area code changed, or the country code changed
  648. if ((NotifyCode == EN_CHANGE && ControlId == IDC_AREA_CODE) ||
  649. (NotifyCode == CBN_SELCHANGE && ControlId == IDC_COUNTRY_LIST)) {
  650. ValidateAndSetWizardButtons(hwnd);
  651. }
  652. return TRUE;
  653. }
  654. BOOL
  655. TapiOnNotify(
  656. IN HWND hwnd,
  657. IN WPARAM ControlId,
  658. IN LPNMHDR pnmh
  659. )
  660. {
  661. switch (pnmh->code ) {
  662. case PSN_SETACTIVE:
  663. {
  664. HKEY hKey;
  665. DWORD NumEntries, Size;
  666. WCHAR buf[MAX_TAPI_STRING+1];
  667. BOOL OverrideMissingAreaCode = FALSE;
  668. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_NTUPGRADE) {
  669. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page
  670. return TRUE;
  671. }
  672. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_LOCATIONS, &hKey ) == ERROR_SUCCESS) {
  673. Size = sizeof(DWORD);
  674. if (RegQueryValueEx( hKey, REGVAL_NUMENTRIES, NULL, NULL, (LPBYTE)&NumEntries, &Size ) == ERROR_SUCCESS) {
  675. if (NumEntries > 0 && !TapiLoc.Valid) {
  676. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page
  677. return TRUE;
  678. }
  679. }
  680. RegCloseKey( hKey );
  681. }
  682. // Look at the existing values on the page to see if everything
  683. // is OK to go to the next page
  684. ValidateAndSetWizardButtons(hwnd);
  685. TapiLoc.Valid = FALSE;
  686. HLINEAPP hLineApp;
  687. LINEINITIALIZEEXPARAMS LineInitializeExParams;
  688. DWORD TapiDevices = 0, ModemDevices = 0;
  689. DWORD LocalTapiApiVersion = 0x00020000;
  690. DWORD Rval;
  691. LineInitializeExParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
  692. LineInitializeExParams.dwNeededSize = 0;
  693. LineInitializeExParams.dwUsedSize = 0;
  694. LineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
  695. LineInitializeExParams.Handles.hEvent = NULL;
  696. LineInitializeExParams.dwCompletionKey = 0;
  697. Rval = lineInitializeEx(
  698. &hLineApp,
  699. hInstance,
  700. NULL,
  701. TEXT("Setup"),
  702. &TapiDevices,
  703. &LocalTapiApiVersion,
  704. &LineInitializeExParams
  705. );
  706. if (Rval == 0) {
  707. for (DWORD i=0; i< TapiDevices; i++ ) {
  708. LPLINEDEVCAPS ldc = MyLineGetDevCaps( hLineApp, LocalTapiApiVersion, i );
  709. if (ldc) {
  710. if (IsDeviceModem(ldc)) {
  711. ModemDevices++;
  712. }
  713. LocalFree( ldc );
  714. }
  715. }
  716. lineShutdown( hLineApp );
  717. }
  718. // If lineInitilaizeEx failed or there are no modem devices installed
  719. // then suppress this wizard page.
  720. if ( Rval != 0 || ModemDevices == 0 )
  721. {
  722. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page
  723. return TRUE;
  724. }
  725. }
  726. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_BATCH) {
  727. //
  728. // unattended mode
  729. //
  730. WCHAR Buf[MAX_TAPI_STRING+1];
  731. TapiLoc.Country = GetPrivateProfileInt(
  732. TAPILOC_SECTION,
  733. TPILOC_COUNTRY_CODE,
  734. 1,
  735. SetupInitComponent.SetupData.UnattendFile
  736. );
  737. GetPrivateProfileString(
  738. TAPILOC_SECTION,
  739. TPILOC_DIALING,
  740. TPILOC_TONE,
  741. Buf,
  742. MAX_TAPI_STRING,
  743. SetupInitComponent.SetupData.UnattendFile
  744. );
  745. if (_wcsicmp( Buf, TPILOC_TONE ) == 0) {
  746. TapiLoc.Flags = LOCATION_USETONEDIALING;
  747. } else {
  748. TapiLoc.Flags = 0;
  749. }
  750. GetPrivateProfileString(
  751. TAPILOC_SECTION,
  752. TPILOC_AREA_CODE,
  753. L"1",
  754. TapiLoc.AreaCode,
  755. MAX_TAPI_STRING,
  756. SetupInitComponent.SetupData.UnattendFile
  757. );
  758. GetPrivateProfileString(
  759. TAPILOC_SECTION,
  760. TPILOC_ACCESS,
  761. L"",
  762. TapiLoc.LongDistanceAccess,
  763. MAX_TAPI_STRING,
  764. SetupInitComponent.SetupData.UnattendFile
  765. );
  766. TapiLoc.Valid = TRUE;
  767. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 ); // don't activate this page
  768. return TRUE;
  769. }
  770. // If we get here the user needs has click next or back.
  771. // Make sure the wizard page is showing.
  772. // For Whistler GUI mode we try to hide wizard pages and show a background
  773. // billboard if there is only a progress bar.
  774. //
  775. SetupInitComponent.HelperRoutines.ShowHideWizardPage(
  776. SetupInitComponent.HelperRoutines.OcManagerContext,
  777. TRUE);
  778. PostMessage( hwnd, MY_SET_FOCUS, 0, (LPARAM) GetDlgItem( hwnd, IDC_AREA_CODE ) );
  779. break;
  780. case PSN_WIZNEXT:
  781. {
  782. DWORD CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETCURSEL, 0, 0 );
  783. CurrCountry = (DWORD)SendDlgItemMessage( hwnd, IDC_COUNTRY_LIST, CB_GETITEMDATA, CurrCountry, 0 );
  784. LPLINECOUNTRYENTRY LineCountryEntry = (LPLINECOUNTRYENTRY) ((LPBYTE)LineCountry + LineCountry->dwCountryListOffset);
  785. TapiLoc.Country = LineCountryEntry[CurrCountry].dwCountryID;
  786. GetDlgItemText( hwnd, IDC_AREA_CODE, TapiLoc.AreaCode, MAX_TAPI_STRING );
  787. GetDlgItemText( hwnd, IDC_LONG_DISTANCE, TapiLoc.LongDistanceAccess, MAX_TAPI_STRING );
  788. if (IsDlgButtonChecked( hwnd, IDC_TONE )) {
  789. TapiLoc.Flags = LOCATION_USETONEDIALING;
  790. } else {
  791. TapiLoc.Flags = 0;
  792. }
  793. //
  794. // If an area code was not set but the areacode is required, then
  795. // fail to continue "going next."
  796. //
  797. if ((TapiLoc.AreaCode[0] == 0) &&
  798. (IsCityCodeOptional(LineCountryEntry + CurrCountry) == AREACODE_REQUIRED)) {
  799. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 );
  800. return TRUE;
  801. }
  802. TapiLoc.Valid = TRUE;
  803. }
  804. break;
  805. }
  806. return FALSE;
  807. }
  808. INT_PTR CALLBACK
  809. TapiLocDlgProc(
  810. HWND hwnd,
  811. UINT message,
  812. WPARAM wParam,
  813. LPARAM lParam
  814. )
  815. {
  816. CommonWizardProc( hwnd, message, wParam, lParam, WizPageTapiLoc );
  817. switch( message ) {
  818. case WM_INITDIALOG:
  819. return TapiOnInitDialog( hwnd, (HWND)wParam, lParam );
  820. case WM_COMMAND:
  821. return TapiOnCommand( hwnd, HIWORD(wParam), LOWORD(wParam), (HWND)lParam );
  822. case WM_NOTIFY:
  823. return TapiOnNotify( hwnd, wParam, (LPNMHDR) lParam );
  824. case MY_SET_FOCUS:
  825. SetFocus( (HWND) lParam );
  826. SendMessage( (HWND) lParam, EM_SETSEL, 0, MAKELPARAM( 0, -1 ) );
  827. return FALSE;
  828. }
  829. return FALSE;
  830. }