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.

954 lines
28 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2001, Microsoft Corporation All rights reserved.
  4. //
  5. // Module Name:
  6. //
  7. // euroconv.c
  8. //
  9. // Abstract:
  10. //
  11. // This file contains the entry point of the euroconv.exe utility.
  12. //
  13. // NOTE: If you want to add exception for new locale, please add it to the
  14. // base list named gBaseEuroException. See the structure definition for more
  15. // information. Empty string represented by "\0" means that we don't need
  16. // to update the information. The chThousandSep member of gBaseEuroException
  17. // should always be different from "\0".
  18. //
  19. // Revision History:
  20. //
  21. // 2001-07-30 lguindon Created.
  22. //
  23. ///////////////////////////////////////////////////////////////////////////////
  24. ///////////////////////////////////////////////////////////////////////////////
  25. //
  26. // Includes Files.
  27. //
  28. ///////////////////////////////////////////////////////////////////////////////
  29. #include "euroconv.h"
  30. #include "util.h"
  31. #include "welcome.h"
  32. #include "confirm.h"
  33. ///////////////////////////////////////////////////////////////////////////////
  34. //
  35. // Global variable.
  36. //
  37. ///////////////////////////////////////////////////////////////////////////////
  38. EURO_EXCEPTION gBaseEuroException[] =
  39. {
  40. {0x00000403, "\0", "2", "."}, // Catalan - Spain
  41. {0x00000407, "\0", "\0", "."}, // German - Germany
  42. {0x00000c07, "\0", "\0", "."}, // German - Austria
  43. {0x00001007, "\0", "\0", "."}, // German - Luzembourg
  44. {0x00000408, "\0", "\0", "."}, // Greek - Greece
  45. {0x00001809, ".", "\0", ","}, // English - Ireland
  46. {0x0000040a, "\0", "2", "."}, // Spanish - Spain (traditional sort)
  47. {0x00000c0a, "\0", "2", "."}, // Spanish - Spain (international sort)
  48. {0x0000040b, "\0", "\0", " "}, // Finnish - Finland
  49. {0x0000040c, "\0", "\0", " "}, // French - France
  50. {0x0000080c, "\0", "\0", "."}, // French - Belgium
  51. {0x0000140c, "\0", "\0", " "}, // French - Luxembourg
  52. {0x0000180c, "\0", "\0", " "}, // French - Monaco
  53. {0x00000410, ",", "2", "."}, // Italian - Italy
  54. {0x00000413, "\0", "\0", "."}, // Dutch - Netherlands
  55. {0x00000813, "\0", "\0", "."}, // Dutch - Belgium
  56. {0x00000816, ",", "\0", "."}, // Portuguese - Portugal
  57. {0x0000081d, "\0", "\0", " "}, // Swedish - Finland
  58. {0x0000042d, "\0", "2", "."}, // Basque - Spain
  59. {0x00000456, "\0", "\0", "."} // Galician - Spain
  60. };
  61. UINT gNbBaseEuroException = sizeof(gBaseEuroException)/sizeof(EURO_EXCEPTION);
  62. UINT gNbOverrideEuroException = 0;
  63. PEURO_EXCEPTION gOverrideEuroException;
  64. HGLOBAL hOverrideEuroException = NULL;
  65. HINSTANCE ghInstance = NULL;
  66. BOOL gbSilence = FALSE;
  67. BOOL gbAll = TRUE;
  68. DWORD gdwVersion = (-1);
  69. #ifdef DEBUG
  70. BOOL gbPatchCheck = TRUE;
  71. #endif // DEBUG
  72. const CHAR c_szCPanelIntl[] = "Control Panel\\International";
  73. const CHAR c_szCPanelIntl_DefUser[] = ".DEFAULT\\Control Panel\\International";
  74. const CHAR c_szLocale[] = "Locale";
  75. const CHAR c_szCurrencySymbol[] = "sCurrency";
  76. const WCHAR c_wszCurrencySymbol[] = L"sCurrency";
  77. const CHAR c_szCurrencyDecimalSep[] = "sMonDecimalSep";
  78. const CHAR c_szCurrencyThousandSep[] = "sMonThousandSep";
  79. const CHAR c_szCurrencyDigits[] = "iCurrDigits";
  80. const CHAR c_szIntl[] = "intl";
  81. HINSTANCE hUserenvDLL = NULL;
  82. BOOL (*pfnGetProfilesDirectory)(LPSTR, LPDWORD) = NULL;
  83. HINSTANCE hUser32DLL = NULL;
  84. long (*pfnBroadcastSystemMessage)(DWORD, LPDWORD, UINT, WPARAM, LPARAM) = NULL;
  85. HINSTANCE hNtdllDLL = NULL;
  86. LONG (*pfnRtlAdjustPrivilege)(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN) = NULL;
  87. ///////////////////////////////////////////////////////////////////////////////
  88. //
  89. // Prototypes.
  90. //
  91. ///////////////////////////////////////////////////////////////////////////////
  92. BOOL ParseCmdLine(LPSTR argIndex);
  93. DWORD ApplyEuroSettings();
  94. DWORD ApplyEuroSettingsToRegistry();
  95. DWORD ApplyEuroSettingsToFile();
  96. BOOL UpdateFileLocaleInfo(LPCSTR szProfile, PEURO_EXCEPTION pInfo);
  97. BOOL UpdateRegLocaleInfo(HKEY hKey, PEURO_EXCEPTION pInfo);
  98. BOOL UpdateLocaleInfo(HKEY hKey, PEURO_EXCEPTION pInfo);
  99. void Usage();
  100. ///////////////////////////////////////////////////////////////////////////////
  101. //
  102. // Main entry point.
  103. //
  104. ///////////////////////////////////////////////////////////////////////////////
  105. INT APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
  106. {
  107. DWORD dwRecipients;
  108. DWORD nbChanged;
  109. //
  110. // Save instance.
  111. //
  112. ghInstance = hInstance;
  113. //
  114. // Set language.
  115. //
  116. // SetThreadLocale((LCID)0x00001809); // English - Ireland
  117. // SetThreadLocale((LCID)0x0000040c); // French - France
  118. // SetThreadLocale((LCID)0x0000080c); // French - Belgium
  119. // SetThreadLocale((LCID)0x0000140c); // French - Luxembourg
  120. // SetThreadLocale((LCID)0x0000180c); // French - Monaco
  121. // SetThreadLocale((LCID)0x00000410); // Italian - Italia
  122. // SetThreadLocale((LCID)0x0000040b); // Finnish - Finland
  123. // SetThreadLocale((LCID)0x00000408); // Greek - Greece
  124. // SetThreadLocale((LCID)0x00000816); // Portuguese - Portugal
  125. // SetThreadLocale((LCID)0x00000403); // Catalan - Spain
  126. // SetThreadLocale((LCID)0x0000040a); // Spanish - Spain (traditional sort)
  127. // SetThreadLocale((LCID)0x00000c0a); // Spanish - Spain (international sort)
  128. // SetThreadLocale((LCID)0x0000042d); // Basque - Spain
  129. // SetThreadLocale((LCID)0x00000456); // Galician - Spain
  130. // SetThreadLocale((LCID)0x00000407); // German - Germany
  131. // SetThreadLocale((LCID)0x00000c07); // German - Austria
  132. // SetThreadLocale((LCID)0x00001007); // German - Luzembourg
  133. // SetThreadLocale((LCID)0x0000081d); // Swedish - Finland
  134. // SetThreadLocale((LCID)0x00000413); // Dutch - Netherlands
  135. // SetThreadLocale((LCID)0x00000813); // Dutch - Belgium
  136. //
  137. // Parse command line arguments.
  138. //
  139. if (!ParseCmdLine(lpCmdLine))
  140. {
  141. return (-1);
  142. }
  143. //
  144. // Install the patch. The path for UI and Non-UI cases are seperated for
  145. // cleared understanding of both cases.
  146. //
  147. if (!gbSilence)
  148. {
  149. //
  150. // Verify administrative privileges.
  151. //
  152. if (gbAll && !IsAdmin())
  153. {
  154. if (ShowMsg(NULL, IDS_NOADMIN, IDS_TITLE, MB_YN_OOPS) == IDYES)
  155. {
  156. gbAll = FALSE;
  157. }
  158. else
  159. {
  160. CleanUp(hOverrideEuroException);
  161. return (0);
  162. }
  163. }
  164. //
  165. // Verify if Euro patch is there.
  166. //
  167. if (!IsEuroPatchInstalled())
  168. {
  169. ShowMsg(NULL, IDS_PATCH, IDS_TITLE, MB_OK_OOPS);
  170. CleanUp(hOverrideEuroException);
  171. return (-1);
  172. }
  173. //
  174. // Load needed library
  175. //
  176. if (!IsWindows9x() && gbAll)
  177. {
  178. if (!LoadLibraries())
  179. {
  180. ShowMsg(NULL, IDS_LIB_ERROR, IDS_TITLE, MB_OK_OOPS);
  181. CleanUp(hOverrideEuroException);
  182. return (-1);
  183. }
  184. }
  185. //
  186. // Show welcome screen.
  187. //
  188. if (!WelcomeDialog())
  189. {
  190. CleanUp(hOverrideEuroException);
  191. return (0);
  192. }
  193. //
  194. // Show Confirmation dialog.
  195. //
  196. if (!ConfirmDialog())
  197. {
  198. CleanUp(hOverrideEuroException);
  199. return (0);
  200. }
  201. //
  202. // Apply EURO changes.
  203. //
  204. if ((nbChanged = ApplyEuroSettings()) != 0)
  205. {
  206. //
  207. // Show success message.
  208. //
  209. if (IsWindows9x())
  210. {
  211. if (ShowMsg(NULL, IDS_SUCCESS, IDS_TITLE, MB_YESNO | MB_ICONQUESTION) == IDYES)
  212. {
  213. RebootTheSystem();
  214. }
  215. }
  216. else
  217. {
  218. if (ShowMsg(NULL, IDS_SUCCESS_DEF, IDS_TITLE, MB_YESNO | MB_ICONQUESTION) == IDYES)
  219. {
  220. if (gbAll)
  221. {
  222. RebootTheSystem();
  223. }
  224. }
  225. }
  226. }
  227. else
  228. {
  229. ShowMsg(NULL, IDS_NOTHING, IDS_TITLE, MB_OK_OOPS);
  230. }
  231. }
  232. else
  233. {
  234. //
  235. // Verify administrative privileges.
  236. //
  237. if (!IsAdmin())
  238. {
  239. gbAll = FALSE;
  240. }
  241. //
  242. // Load libraries.
  243. //
  244. if (!IsWindows9x() && gbAll)
  245. {
  246. LoadLibraries();
  247. }
  248. //
  249. // Verify if the patch is installed.
  250. //
  251. if (IsEuroPatchInstalled())
  252. {
  253. //
  254. // Apply Euro settings.
  255. //
  256. nbChanged = ApplyEuroSettings();
  257. }
  258. }
  259. //
  260. // Broadcast the message that the international settings in the
  261. // registry have changed.
  262. //
  263. if ((nbChanged != 0) &&
  264. pfnBroadcastSystemMessage)
  265. {
  266. dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
  267. (*pfnBroadcastSystemMessage)( BSF_FORCEIFHUNG | BSF_IGNORECURRENTTASK |
  268. BSF_NOHANG | BSF_NOTIMEOUTIFNOTHUNG,
  269. &dwRecipients,
  270. WM_WININICHANGE,
  271. 0,
  272. (LPARAM)c_szIntl );
  273. }
  274. //
  275. // Unload unneeded library
  276. //
  277. UnloadLibraries();
  278. CleanUp(hOverrideEuroException);
  279. // Make sure we return "failure" (non-zero) if no info was changed. This would
  280. // apply to both (a) permission problems and (b) being outside the Euro zone.
  281. return (((nbChanged != 0) ? 0 : -1));
  282. }
  283. ///////////////////////////////////////////////////////////////////////////////
  284. //
  285. // ParseCmdLine
  286. //
  287. // Parse the command line and search for supported argument.
  288. //
  289. ///////////////////////////////////////////////////////////////////////////////
  290. BOOL ParseCmdLine(LPSTR argIndex)
  291. {
  292. //
  293. // Parse the command line.
  294. //
  295. while (argIndex = NextCommandArg(argIndex))
  296. {
  297. switch(*argIndex)
  298. {
  299. case('s'): // Silent mode
  300. case('S'):
  301. {
  302. gbSilence = TRUE;
  303. break;
  304. }
  305. case('c'): // Current user only
  306. case('C'):
  307. {
  308. gbAll = FALSE;
  309. break;
  310. }
  311. case('a'): // Exception
  312. case('A'):
  313. {
  314. UINT nbException = 1;
  315. UINT idx = 0;
  316. LPSTR strPtrHead;
  317. LPSTR strPtrTail;
  318. BOOL bInsideQuote = FALSE;
  319. //
  320. // Change the separator used between each block in order to avoid
  321. // mistake with the data itself inside the double quote.
  322. //
  323. strPtrHead = argIndex + 2;
  324. while (*strPtrHead)
  325. {
  326. if (*strPtrHead == '"')
  327. {
  328. bInsideQuote = bInsideQuote ? FALSE : TRUE;
  329. }
  330. else if (*strPtrHead == ';')
  331. {
  332. if (!bInsideQuote)
  333. {
  334. *strPtrHead = '@';
  335. }
  336. }
  337. strPtrHead++;
  338. }
  339. //
  340. // Compute the number of exception override.
  341. //
  342. strPtrHead = argIndex + 2;
  343. while (strPtrHead = strchr(strPtrHead, '@'))
  344. {
  345. strPtrHead++;
  346. nbException++;
  347. }
  348. //
  349. // Allocation a structure for exception override.
  350. //
  351. if (!(hOverrideEuroException = GlobalAlloc(GHND, sizeof(EURO_EXCEPTION)*nbException)))
  352. {
  353. return (FALSE);
  354. }
  355. gOverrideEuroException = GlobalLock(hOverrideEuroException);
  356. gNbOverrideEuroException = nbException;
  357. //
  358. // Fill out the structure.
  359. //
  360. strPtrHead = argIndex + 2;
  361. while (idx < nbException)
  362. {
  363. CHAR buffer[128];
  364. UINT strLen;
  365. //
  366. // Extract the exception override information.
  367. //
  368. if (strPtrTail = strchr(strPtrHead, '@'))
  369. {
  370. strLen = (UINT)(strPtrTail - strPtrHead);
  371. }
  372. else
  373. {
  374. strLen = strlen(strPtrHead);
  375. }
  376. //
  377. // Copy the triplet.
  378. //
  379. strncpy(buffer, strPtrHead, strLen + 1);
  380. //
  381. // Add to the exception override list.
  382. //
  383. AddExceptionOverride(&gOverrideEuroException[idx], buffer);
  384. //
  385. // Next triplet.
  386. //
  387. if (strPtrTail)
  388. {
  389. strPtrHead = strPtrTail + 1;
  390. }
  391. idx++;
  392. }
  393. break;
  394. }
  395. #ifdef DEBUG
  396. case('z'): // private flag for disabling the patch detection.
  397. case('Z'):
  398. {
  399. gbPatchCheck = FALSE;
  400. break;
  401. }
  402. #endif // DEBUG
  403. case('h'): // Usage
  404. case('H'): // Usage
  405. case('?'):
  406. {
  407. Usage();
  408. return (FALSE);
  409. }
  410. default:
  411. {
  412. //
  413. // Usage.
  414. //
  415. if (!gbSilence)
  416. {
  417. Usage();
  418. }
  419. return (FALSE);
  420. }
  421. }
  422. }
  423. return (TRUE);
  424. }
  425. ///////////////////////////////////////////////////////////////////////////////
  426. //
  427. // ApplyEuroSettings
  428. //
  429. // Apply new Euro settings to the current user and/or to all user.
  430. //
  431. ///////////////////////////////////////////////////////////////////////////////
  432. DWORD ApplyEuroSettings()
  433. {
  434. HCURSOR hcurSave;
  435. DWORD nbChanged;
  436. //
  437. // Show hour glass
  438. //
  439. hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  440. //
  441. // Update available registry information.
  442. //
  443. nbChanged = ApplyEuroSettingsToRegistry();
  444. //
  445. // This is not complete because Windows NT security don't
  446. // allows to change other users because information in
  447. // registry is not available
  448. //
  449. if (!IsWindows9x())
  450. {
  451. //
  452. // Update all NTUSER.DAT file. This way we can update all users.
  453. //
  454. nbChanged += ApplyEuroSettingsToFile();
  455. }
  456. //
  457. // Revert cursor and return number changed.
  458. //
  459. SetCursor(hcurSave);
  460. return (nbChanged);
  461. }
  462. ///////////////////////////////////////////////////////////////////////////////
  463. //
  464. // ApplyEuroSettingsToFile
  465. //
  466. // Apply new Euro settings to the current user and/or to all user.
  467. //
  468. ///////////////////////////////////////////////////////////////////////////////
  469. DWORD ApplyEuroSettingsToFile()
  470. {
  471. LCID locale;
  472. PEURO_EXCEPTION pInfo;
  473. DWORD nbAffected = 0;
  474. //
  475. // Proceed with all users if requested.
  476. //
  477. if (gbAll)
  478. {
  479. CHAR docFolder[MAX_PATH] = {0};
  480. CHAR userFileData[MAX_PATH] = {0};
  481. CHAR searchPattern[MAX_PATH] = {0};
  482. WIN32_FIND_DATA fileData;
  483. HANDLE hList;
  484. //
  485. // Get Documents and Settings folder
  486. //
  487. if (!GetDocumentAndSettingsFolder(docFolder))
  488. {
  489. return (nbAffected);
  490. }
  491. //
  492. // Append a wildcard after the directory path to find
  493. // out all files/folders under it.
  494. //
  495. //strcpy(searchPattern, docFolder);
  496. //strcat(searchPattern, "\\*.*");
  497. StringCbCopy(searchPattern, MAX_PATH, docFolder);
  498. StringCbCatA(searchPattern, MAX_PATH, "\\*.*");
  499. //
  500. // List all files/folder under the profile directory
  501. //
  502. hList = FindFirstFile(searchPattern, &fileData);
  503. if (hList == INVALID_HANDLE_VALUE)
  504. {
  505. return (nbAffected);
  506. }
  507. //
  508. // Search through the Documents and settings folder for users.
  509. //
  510. do
  511. {
  512. //
  513. // Check if it's a directory
  514. //
  515. if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  516. {
  517. //
  518. // Build a full path for the User data file.
  519. //
  520. //strcpy(userFileData, docFolder);
  521. //strcat(userFileData, "\\");
  522. //strcat(userFileData, fileData.cFileName);
  523. //strcat(userFileData, "\\NTUSER.DAT");
  524. StringCbCopy(userFileData, MAX_PATH, docFolder);
  525. StringCbCatA(userFileData, MAX_PATH, "\\");
  526. StringCbCatA(userFileData, MAX_PATH, fileData.cFileName);
  527. StringCbCatA(userFileData, MAX_PATH, "\\NTUSER.DAT");
  528. //
  529. // Check if the file is associated to a valid user and
  530. // get user locale from the user data file.
  531. //
  532. if (IsValidUserDataFile(userFileData) &&
  533. (locale = GetLocaleFromFile(userFileData)))
  534. {
  535. //
  536. // Search for an exception.
  537. //
  538. if ((pInfo = GetLocaleOverrideInfo(locale)) != NULL)
  539. {
  540. if( UpdateFileLocaleInfo(userFileData, pInfo))
  541. {
  542. nbAffected++;
  543. }
  544. }
  545. }
  546. }
  547. }
  548. while (FindNextFile(hList, &fileData));
  549. //
  550. // Close handle.
  551. //
  552. FindClose(hList);
  553. }
  554. return (nbAffected);
  555. }
  556. ///////////////////////////////////////////////////////////////////////////////
  557. //
  558. // ApplyEuroSettingsToRegistry
  559. //
  560. // Apply new Euro settings to the current user and/or to all user.
  561. //
  562. ///////////////////////////////////////////////////////////////////////////////
  563. DWORD ApplyEuroSettingsToRegistry()
  564. {
  565. LCID locale;
  566. PEURO_EXCEPTION pInfo;
  567. DWORD nbAffected = 0;
  568. //
  569. // Proceed with all users if requested.
  570. //
  571. if (gbAll)
  572. {
  573. DWORD dwKeyLength, dwKeyIndex = 0;
  574. CHAR szKey[REGSTR_MAX_VALUE_LENGTH]; // this should be dynamic.
  575. HKEY hKey;
  576. DWORD lRet;
  577. LPSTR endPtr;
  578. //
  579. // Go through all users for registry settings.
  580. //
  581. for (;;)
  582. {
  583. dwKeyLength = REGSTR_MAX_VALUE_LENGTH;
  584. lRet = RegEnumKeyEx( HKEY_USERS,
  585. dwKeyIndex,
  586. szKey,
  587. &dwKeyLength,
  588. NULL,
  589. NULL,
  590. NULL,
  591. NULL );
  592. if (lRet == ERROR_NO_MORE_ITEMS)
  593. {
  594. lRet = ERROR_SUCCESS;
  595. break;
  596. }
  597. else if (lRet == ERROR_SUCCESS)
  598. {
  599. //
  600. // Open the registry
  601. //
  602. if (RegOpenKeyEx( HKEY_USERS,
  603. szKey,
  604. 0,
  605. KEY_READ,
  606. &hKey) == ERROR_SUCCESS)
  607. {
  608. //
  609. // Get user locale
  610. //
  611. if (locale = GetLocaleFromRegistry(hKey))
  612. {
  613. //
  614. // Search for an exception.
  615. //
  616. if ((pInfo = GetLocaleOverrideInfo(locale)) != NULL)
  617. {
  618. if (UpdateRegLocaleInfo(hKey, pInfo))
  619. {
  620. nbAffected++;
  621. }
  622. }
  623. }
  624. //
  625. // Close handle
  626. //
  627. RegCloseKey(hKey);
  628. }
  629. }
  630. else
  631. {
  632. break;
  633. }
  634. //
  635. // Next keys
  636. //
  637. ++dwKeyIndex;
  638. }
  639. }
  640. else
  641. {
  642. //
  643. // Update current user settings.
  644. //
  645. locale = GetUserDefaultLCID();
  646. if ((pInfo = GetLocaleOverrideInfo(locale)) != NULL)
  647. {
  648. if (UpdateRegLocaleInfo(HKEY_CURRENT_USER, pInfo))
  649. {
  650. nbAffected++;
  651. }
  652. }
  653. }
  654. return (nbAffected);
  655. }
  656. ///////////////////////////////////////////////////////////////////////////////
  657. //
  658. // GetLocaleOverrideInfo
  659. //
  660. // Search for locale information that need to be updated. First, search in
  661. // the default table. Second, search in the override table for more locales.
  662. //
  663. ///////////////////////////////////////////////////////////////////////////////
  664. PEURO_EXCEPTION GetLocaleOverrideInfo(LCID locale)
  665. {
  666. UINT idx;
  667. PEURO_EXCEPTION euroException = NULL;
  668. //
  669. // Search the base table. We still need to look in the second table even
  670. // if found something in the first table because information can be
  671. // overrided in the second table.
  672. //
  673. idx = 0;
  674. while (idx < gNbBaseEuroException)
  675. {
  676. if (LANGIDFROMLCID(locale) == LANGIDFROMLCID(gBaseEuroException[idx].dwLocale))
  677. {
  678. euroException = &gBaseEuroException[idx];
  679. break;
  680. }
  681. idx++;
  682. }
  683. //
  684. // Search the override table.
  685. //
  686. idx = 0;
  687. while (idx < gNbOverrideEuroException)
  688. {
  689. if (LANGIDFROMLCID(locale) == LANGIDFROMLCID(gOverrideEuroException[idx].dwLocale))
  690. {
  691. euroException = &gOverrideEuroException[idx];
  692. break;
  693. }
  694. idx++;
  695. }
  696. return (euroException);
  697. }
  698. ///////////////////////////////////////////////////////////////////////////////
  699. //
  700. // UpdateRegLocaleInfo
  701. //
  702. // Update the registry values sCurrency, sMonDecimalSep and iCurrDigits if
  703. // needed. Before applying the Decimal separator, we check is the Thousand
  704. // separator is the same to the value in our table. In the case, we need to
  705. // replacement also the the Thousand separator with our data.
  706. //
  707. ///////////////////////////////////////////////////////////////////////////////
  708. BOOL UpdateRegLocaleInfo(HKEY hKey, PEURO_EXCEPTION pInfo)
  709. {
  710. HKEY hIntlKey = NULL;
  711. BOOL bRet;
  712. //
  713. // Open the International registry key.
  714. //
  715. if(RegOpenKeyEx( hKey,
  716. c_szCPanelIntl,
  717. 0,
  718. KEY_ALL_ACCESS,
  719. &hIntlKey) != ERROR_SUCCESS)
  720. {
  721. return (FALSE);
  722. }
  723. //
  724. // Update specific registry entries
  725. //
  726. bRet = UpdateLocaleInfo(hIntlKey, pInfo);
  727. //
  728. // Clean Up
  729. //
  730. RegCloseKey(hIntlKey);
  731. return (bRet);
  732. }
  733. ///////////////////////////////////////////////////////////////////////////////
  734. //
  735. // UpdateFileLocaleInfo
  736. //
  737. // Update the registry values sCurrency, sMonDecimalSep and iCurrDigits if
  738. // needed. Before applying the Decimal separator, we check is the Thousand
  739. // separator is the same to the value in our table. In the case, we need to
  740. // replacement also the the Thousand separator with our data.
  741. //
  742. ///////////////////////////////////////////////////////////////////////////////
  743. BOOL UpdateFileLocaleInfo(LPCSTR szProfile, PEURO_EXCEPTION pInfo)
  744. {
  745. HKEY hIntlKey = NULL;
  746. BOOL bRet;
  747. BOOLEAN wasEnabled;
  748. //
  749. // Load hive.
  750. //
  751. if ((hIntlKey = LoadHive( szProfile,
  752. TEXT("TempKey"),
  753. c_szCPanelIntl,
  754. &wasEnabled )) == NULL)
  755. {
  756. return (FALSE);
  757. }
  758. //
  759. // Update specific registry entries
  760. //
  761. bRet = UpdateLocaleInfo(hIntlKey, pInfo);
  762. //
  763. // Unload hive
  764. //
  765. RegCloseKey(hIntlKey);
  766. UnloadHive(TEXT("TempKey"), &wasEnabled);
  767. return (bRet);
  768. }
  769. ///////////////////////////////////////////////////////////////////////////////
  770. //
  771. // UpdateLocaleInfo
  772. //
  773. ///////////////////////////////////////////////////////////////////////////////
  774. BOOL UpdateLocaleInfo(HKEY hIntlKey, PEURO_EXCEPTION pInfo)
  775. {
  776. //
  777. // Update the sCurrency value. We have to use the Unicode version for
  778. // Windows NTx because the euro character doesn't have the same ANSI
  779. // value depending of the System Locale and it's associated Code Page.
  780. // using the Unicode value fixes the problem.
  781. //
  782. if (IsWindows9x())
  783. {
  784. //
  785. // If the ACP code page is 1251, we need to store the proper value
  786. // for the euro symbol.
  787. //
  788. if (GetACP() == 1251)
  789. {
  790. RegSetValueExA( hIntlKey,
  791. c_szCurrencySymbol,
  792. 0L,
  793. REG_SZ,
  794. (CONST BYTE *)"\x88",
  795. strlen("\x88") + 1);
  796. }
  797. else
  798. {
  799. RegSetValueExA( hIntlKey,
  800. c_szCurrencySymbol,
  801. 0L,
  802. REG_SZ,
  803. (CONST BYTE *)"\x80",
  804. strlen("\x80") + 1);
  805. }
  806. }
  807. else
  808. {
  809. RegSetValueExW( hIntlKey,
  810. c_wszCurrencySymbol,
  811. 0L,
  812. REG_SZ,
  813. (CONST BYTE *)L"\x20AC",
  814. wcslen(L"\x20AC") + 1);
  815. }
  816. //
  817. // Update the sMonDecimalSep value.
  818. //
  819. if( pInfo->chDecimalSep[0] != '\0' )
  820. {
  821. RegSetValueEx( hIntlKey,
  822. c_szCurrencyDecimalSep,
  823. 0L,
  824. REG_SZ,
  825. (CONST BYTE *)pInfo->chDecimalSep,
  826. strlen(pInfo->chDecimalSep)+1);
  827. }
  828. //
  829. // Update the iCurrDigits value if needed.
  830. //
  831. if( pInfo->chDigits[0] != '\0' )
  832. {
  833. RegSetValueEx( hIntlKey,
  834. c_szCurrencyDigits,
  835. 0L,
  836. REG_SZ,
  837. (CONST BYTE *)pInfo->chDigits,
  838. strlen(pInfo->chDigits)+1);
  839. }
  840. //
  841. // Update the SMonThousandSep value.
  842. //
  843. if( pInfo->chThousandSep[0] != '\0' )
  844. {
  845. RegSetValueEx( hIntlKey,
  846. c_szCurrencyThousandSep,
  847. 0L,
  848. REG_SZ,
  849. (CONST BYTE *)pInfo->chThousandSep,
  850. strlen(pInfo->chThousandSep)+1);
  851. }
  852. return (TRUE);
  853. }
  854. ///////////////////////////////////////////////////////////////////////////////
  855. //
  856. // Usage
  857. //
  858. // Show command line Usage.
  859. //
  860. ///////////////////////////////////////////////////////////////////////////////
  861. void Usage()
  862. {
  863. TCHAR szMsg[MAX_PATH*8];
  864. if (LoadString(ghInstance, IDS_USAGE, szMsg, MAX_PATH*8))
  865. {
  866. ShowMsg(NULL, IDS_USAGE, IDS_TITLE, MB_OK);
  867. }
  868. }