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.

1467 lines
41 KiB

  1. /*++
  2. Copyright (c) 1994-2000, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. advdlg.c
  5. Abstract:
  6. This module implements the advanced property sheet for the Regional
  7. Options applet.
  8. Revision History:
  9. --*/
  10. //
  11. // Include Files.
  12. //
  13. #include "intl.h"
  14. #include <windowsx.h>
  15. #include <setupapi.h>
  16. #include <syssetup.h>
  17. #include "intlhlp.h"
  18. #include "maxvals.h"
  19. //
  20. // Context Help Ids.
  21. //
  22. static int aAdvancedHelpIds[] =
  23. {
  24. IDC_GROUPBOX1, IDH_COMM_GROUPBOX,
  25. IDC_GROUPBOX2, IDH_COMM_GROUPBOX,
  26. IDC_GROUPBOX3, IDH_COMM_GROUPBOX,
  27. IDC_CODEPAGES, IDH_INTL_ADV_CODEPAGES,
  28. IDC_SYSTEM_LOCALE, IDH_INTL_ADV_SYSTEM_LOCALE,
  29. IDC_SYSTEM_LOCALE_TEXT1, IDH_INTL_ADV_SYSTEM_LOCALE,
  30. IDC_SYSTEM_LOCALE_TEXT2, IDH_INTL_ADV_SYSTEM_LOCALE,
  31. IDC_DEFAULT_USER, IDH_INTL_ADV_CHANGE,
  32. 0, 0
  33. };
  34. ////////////////////////////////////////////////////////////////////////////
  35. //
  36. // Advanced_ListViewCustomDraw
  37. //
  38. // Processing for a list view NM_CUSTOMDRAW notification message.
  39. //
  40. ////////////////////////////////////////////////////////////////////////////
  41. void Advanced_ListViewCustomDraw(
  42. HWND hDlg,
  43. LPNMLVCUSTOMDRAW pDraw)
  44. {
  45. LPCODEPAGE pNode;
  46. //
  47. // Tell the list view to notify me of item draws.
  48. //
  49. if (pDraw->nmcd.dwDrawStage == CDDS_PREPAINT)
  50. {
  51. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW);
  52. return;
  53. }
  54. //
  55. // Handle the Item Prepaint.
  56. //
  57. pNode = (LPCODEPAGE)(pDraw->nmcd.lItemlParam);
  58. if ((pDraw->nmcd.dwDrawStage & CDDS_ITEMPREPAINT) &&
  59. (pNode) && (pNode != (LPCODEPAGE)(LB_ERR)))
  60. {
  61. if (pNode->wStatus & (ML_PERMANENT | ML_DISABLE))
  62. {
  63. pDraw->clrText = (pDraw->nmcd.uItemState & CDIS_SELECTED)
  64. ? ((GetSysColor(COLOR_HIGHLIGHT) ==
  65. GetSysColor(COLOR_GRAYTEXT))
  66. ? GetSysColor(COLOR_HIGHLIGHTTEXT)
  67. : GetSysColor(COLOR_GRAYTEXT))
  68. : GetSysColor(COLOR_GRAYTEXT);
  69. }
  70. }
  71. //
  72. // Do the default action.
  73. //
  74. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, CDRF_DODEFAULT);
  75. }
  76. ////////////////////////////////////////////////////////////////////////////
  77. //
  78. // Advanced_ListViewChanging
  79. //
  80. ////////////////////////////////////////////////////////////////////////////
  81. BOOL Advanced_ListViewChanging(
  82. HWND hDlg,
  83. NM_LISTVIEW *pLV)
  84. {
  85. LPCODEPAGE pNode;
  86. //
  87. // Make sure it's a state change message.
  88. //
  89. if ((((*pLV).hdr).idFrom != IDC_CODEPAGES) ||
  90. (!(pLV->uChanged & LVIF_STATE)) ||
  91. ((pLV->uNewState & 0x3000) == 0))
  92. {
  93. return (FALSE);
  94. }
  95. //
  96. // Get the item data for the currently selected item.
  97. //
  98. pNode = (LPCODEPAGE)(pLV->lParam);
  99. //
  100. // Make sure we're not trying to change a permanent or disabled
  101. // code page. If so, return TRUE to prevent the change.
  102. //
  103. if ((pNode) && (pNode->wStatus & (ML_PERMANENT | ML_DISABLE)))
  104. {
  105. return (TRUE);
  106. }
  107. //
  108. // Return FALSE to allow the change.
  109. //
  110. return (FALSE);
  111. }
  112. ////////////////////////////////////////////////////////////////////////////
  113. //
  114. // Advanced_ListViewChanged
  115. //
  116. ////////////////////////////////////////////////////////////////////////////
  117. BOOL Advanced_ListViewChanged(
  118. HWND hDlg,
  119. int iID,
  120. NM_LISTVIEW *pLV)
  121. {
  122. HWND hwndLV = GetDlgItem(hDlg, iID);
  123. LPCODEPAGE pNode;
  124. BOOL bChecked;
  125. int iCount;
  126. //
  127. // Make sure it's a state change message.
  128. //
  129. if ((((*pLV).hdr).idFrom != IDC_CODEPAGES) ||
  130. (!(pLV->uChanged & LVIF_STATE)) ||
  131. ((pLV->uNewState & 0x3000) == 0))
  132. {
  133. return (FALSE);
  134. }
  135. //
  136. // Get the state of the check box for the currently selected item.
  137. //
  138. bChecked = ListView_GetCheckState(hwndLV, pLV->iItem) ? TRUE : FALSE;
  139. //
  140. // Get the item data for the currently selected item.
  141. //
  142. pNode = (LPCODEPAGE)(pLV->lParam);
  143. //
  144. // Make sure we're not trying to change a permanent or disabled
  145. // code page. If so, set the check box to its appropriate state.
  146. //
  147. if (pNode->wStatus & (ML_PERMANENT | ML_DISABLE))
  148. {
  149. if (pNode->wStatus & ML_PERMANENT)
  150. {
  151. if (bChecked == FALSE)
  152. {
  153. ListView_SetCheckState(hwndLV, pLV->iItem, TRUE);
  154. }
  155. }
  156. else // ML_DISABLE only
  157. {
  158. if ((bChecked == FALSE) && (pNode->wStatus & ML_ORIG_INSTALLED))
  159. {
  160. ListView_SetCheckState(hwndLV, pLV->iItem, TRUE);
  161. }
  162. else if ((bChecked == TRUE) && (!(pNode->wStatus & ML_ORIG_INSTALLED)))
  163. {
  164. ListView_SetCheckState(hwndLV, pLV->iItem, FALSE);
  165. }
  166. }
  167. return (FALSE);
  168. }
  169. //
  170. // Store the proper info in the code page structure.
  171. //
  172. pNode->wStatus &= (ML_ORIG_INSTALLED | ML_STATIC);
  173. pNode->wStatus |= ((bChecked) ? ML_INSTALL : ML_REMOVE);
  174. //
  175. // Deselect all items.
  176. //
  177. iCount = ListView_GetItemCount(hwndLV);
  178. while (iCount > 0)
  179. {
  180. ListView_SetItemState( hwndLV,
  181. iCount - 1,
  182. 0,
  183. LVIS_FOCUSED | LVIS_SELECTED );
  184. iCount--;
  185. }
  186. //
  187. // Make sure this item is selected.
  188. //
  189. ListView_SetItemState( hwndLV,
  190. pLV->iItem,
  191. LVIS_FOCUSED | LVIS_SELECTED,
  192. LVIS_FOCUSED | LVIS_SELECTED );
  193. //
  194. // Return success.
  195. //
  196. return (TRUE);
  197. }
  198. ////////////////////////////////////////////////////////////////////////////
  199. //
  200. // Advanced_ListViewClick
  201. //
  202. ////////////////////////////////////////////////////////////////////////////
  203. BOOL Advanced_ListViewClick(
  204. HWND hDlg,
  205. LPNMHDR lpNmHdr)
  206. {
  207. LV_HITTESTINFO ht;
  208. HWND hwndList = GetDlgItem(hDlg, IDC_CODEPAGES);
  209. //
  210. // Remove unnecessary processing.
  211. //
  212. if (lpNmHdr->idFrom != IDC_CODEPAGES)
  213. {
  214. return (FALSE);
  215. }
  216. //
  217. // Get where we were hit and then translate it to our
  218. // window.
  219. //
  220. GetCursorPos(&ht.pt);
  221. ScreenToClient(hwndList, &ht.pt);
  222. ListView_HitTest(hwndList, &ht);
  223. if ((ht.iItem >= 0) && ((ht.flags & LVHT_ONITEM) == LVHT_ONITEMLABEL))
  224. {
  225. UINT state;
  226. //
  227. // The user clicked on the item label. Simulate a
  228. // state change so we can process it.
  229. //
  230. state = ListView_GetItemState( hwndList,
  231. ht.iItem,
  232. LVIS_STATEIMAGEMASK );
  233. state ^= INDEXTOSTATEIMAGEMASK(LVIS_SELECTED | LVIS_FOCUSED);
  234. //
  235. // The state is either selected or focused. Flip the
  236. // bits. The SetItemState causes the system to bounce
  237. // back a notification for LVN_ITEMCHANGED and the
  238. // code then does the right thing. Note -- we MUST
  239. // check for LVHT_ONITEMLABEL. If we do this code for
  240. // LVHT_ONITEMSTATEICON, the code will get 2
  241. // ITEMCHANGED notifications, and the state will stay
  242. // where it is, which is not good. If we want this
  243. // to also fire if the guy clicks in the empty space
  244. // right of the label text, we need to look for
  245. // LVHT_ONITEM as well as LVHT_ONITEMLABEL.
  246. //
  247. ListView_SetItemState( hwndList,
  248. ht.iItem,
  249. state,
  250. LVIS_STATEIMAGEMASK );
  251. }
  252. return (TRUE);
  253. }
  254. ////////////////////////////////////////////////////////////////////////////
  255. //
  256. // Advanced_GetSupportedCodePages
  257. //
  258. ////////////////////////////////////////////////////////////////////////////
  259. BOOL Advanced_GetSupportedCodePages()
  260. {
  261. UINT CodePage;
  262. HANDLE hCodePage;
  263. LPCODEPAGE pCP;
  264. INFCONTEXT Context;
  265. TCHAR szSection[MAX_PATH];
  266. int LineCount, LineNum;
  267. CPINFOEX Info;
  268. //
  269. // Get the number of supported code pages from the inf file.
  270. //
  271. LineCount = (UINT)SetupGetLineCount(g_hIntlInf, TEXT("CodePages"));
  272. if (LineCount <= 0)
  273. {
  274. return (FALSE);
  275. }
  276. //
  277. // Go through all supported code pages in the inf file.
  278. //
  279. for (LineNum = 0; LineNum < LineCount; LineNum++)
  280. {
  281. if (SetupGetLineByIndex(g_hIntlInf, TEXT("CodePages"), LineNum, &Context) &&
  282. SetupGetIntField(&Context, 0, &CodePage))
  283. {
  284. //
  285. // Create the new node.
  286. //
  287. if (!(hCodePage = GlobalAlloc(GHND, sizeof(CODEPAGE))))
  288. {
  289. return (FALSE);
  290. }
  291. pCP = GlobalLock(hCodePage);
  292. //
  293. // Fill in the new node with the appropriate info.
  294. //
  295. pCP->wStatus = 0;
  296. pCP->CodePage = CodePage;
  297. pCP->hCodePage = hCodePage;
  298. (pCP->pszName)[0] = 0;
  299. //
  300. // Get the appropriate display string.
  301. //
  302. if (GetCPInfoEx(CodePage, 0, &Info))
  303. {
  304. lstrcpy(pCP->pszName, Info.CodePageName);
  305. }
  306. else if (!SetupGetStringField(&Context, 1, pCP->pszName, MAX_PATH, NULL))
  307. {
  308. GlobalUnlock(hCodePage);
  309. GlobalFree(hCodePage);
  310. continue;
  311. }
  312. //
  313. // See if this code page can be removed.
  314. //
  315. wsprintf(szSection, TEXT("%ws%d"), szCPRemovePrefix, CodePage);
  316. if ((CodePage == GetACP()) ||
  317. (CodePage == GetOEMCP()) ||
  318. (!SetupFindFirstLine( g_hIntlInf,
  319. szSection,
  320. TEXT("AddReg"),
  321. &Context )))
  322. {
  323. //
  324. // Mark it as permanent.
  325. // Also mark it as originally installed to avoid problems.
  326. //
  327. pCP->wStatus |= (ML_ORIG_INSTALLED | ML_PERMANENT);
  328. }
  329. //
  330. // Add the code page to the front of the linked list.
  331. //
  332. pCP->pNext = pCodePages;
  333. pCodePages = pCP;
  334. }
  335. }
  336. //
  337. // Return success.
  338. //
  339. return (TRUE);
  340. }
  341. ////////////////////////////////////////////////////////////////////////////
  342. //
  343. // Advanced_InitSystemLocales
  344. //
  345. ////////////////////////////////////////////////////////////////////////////
  346. BOOL Advanced_InitSystemLocales(
  347. HWND hDlg)
  348. {
  349. TCHAR szSystemBuf[SIZE_128];
  350. TCHAR szDefaultSystemBuf[SIZE_128];
  351. TCHAR szBuf[SIZE_128];
  352. DWORD dwIndex;
  353. HWND hSystemLocale = GetDlgItem(hDlg, IDC_SYSTEM_LOCALE);
  354. //
  355. // Get the list of locales and fill in the system locale
  356. // combo box.
  357. //
  358. Intl_EnumLocales(hDlg, hSystemLocale, TRUE);
  359. //
  360. // Get the string for the system default setting.
  361. // Special case Spanish.
  362. //
  363. if ((SysLocaleID == LCID_SPANISH_TRADITIONAL) ||
  364. (SysLocaleID == LCID_SPANISH_INTL))
  365. {
  366. LoadString(hInstance, IDS_SPANISH_NAME, szSystemBuf, SIZE_128);
  367. }
  368. else
  369. {
  370. GetLocaleInfo(SysLocaleID, LOCALE_SLANGUAGE, szSystemBuf, SIZE_128);
  371. }
  372. //
  373. // Select the current system default locale id in the list.
  374. //
  375. dwIndex = ComboBox_FindStringExact(hSystemLocale, -1, szSystemBuf);
  376. if (dwIndex == CB_ERR)
  377. {
  378. dwIndex = ComboBox_FindStringExact(hSystemLocale, -1, szDefaultSystemBuf);
  379. if (dwIndex == CB_ERR)
  380. {
  381. GetLocaleInfo(US_LOCALE, LOCALE_SLANGUAGE, szBuf, SIZE_128);
  382. dwIndex = ComboBox_FindStringExact(hSystemLocale, -1, szBuf);
  383. if (dwIndex == CB_ERR)
  384. {
  385. dwIndex = 0;
  386. }
  387. }
  388. }
  389. ComboBox_SetCurSel(hSystemLocale, dwIndex);
  390. //
  391. // Return success.
  392. //
  393. return (TRUE);
  394. }
  395. ////////////////////////////////////////////////////////////////////////////
  396. //
  397. // Advanced_SetSystemLocale
  398. //
  399. ////////////////////////////////////////////////////////////////////////////
  400. BOOL Advanced_SetSystemLocale(
  401. HWND hDlg)
  402. {
  403. HWND hSystemLocale = GetDlgItem(hDlg, IDC_SYSTEM_LOCALE);
  404. DWORD dwLocale;
  405. LCID NewLocale;
  406. HCURSOR hcurSave;
  407. //
  408. // Put up the hour glass.
  409. //
  410. hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  411. //
  412. // Get the current selection.
  413. //
  414. dwLocale = ComboBox_GetCurSel(hSystemLocale);
  415. //
  416. // Get the locale id for the current selection and save it.
  417. //
  418. NewLocale = (LCID)ComboBox_GetItemData(hSystemLocale, dwLocale);
  419. if (IsValidLocale(NewLocale, LCID_SUPPORTED))
  420. {
  421. SysLocaleID = NewLocale;
  422. }
  423. else
  424. {
  425. //
  426. // This shouldn't happen, since the values in the combo box
  427. // should already be installed via the language groups.
  428. // Put up an error message just in case.
  429. //
  430. SetCursor(hcurSave);
  431. ShowMsg( NULL,
  432. IDS_SETUP_STRING,
  433. IDS_TITLE_STRING,
  434. MB_OK_OOPS,
  435. NULL );
  436. return (FALSE);
  437. }
  438. //
  439. // Turn off the hour glass.
  440. //
  441. SetCursor(hcurSave);
  442. //
  443. // Return success.
  444. //
  445. return (TRUE);
  446. }
  447. ////////////////////////////////////////////////////////////////////////////
  448. //
  449. // Advanced_InitCodePages
  450. //
  451. ////////////////////////////////////////////////////////////////////////////
  452. BOOL Advanced_InitCodePages(
  453. HWND hDlg,
  454. BOOL bInitTime)
  455. {
  456. HWND hwndCP = GetDlgItem(hDlg, IDC_CODEPAGES);
  457. LPCODEPAGE pCP;
  458. DWORD dwExStyle;
  459. RECT Rect;
  460. LV_COLUMN Column;
  461. LV_ITEM Item;
  462. int iIndex;
  463. //
  464. // Open the Inf file.
  465. //
  466. g_hIntlInf = SetupOpenInfFile(szIntlInf, NULL, INF_STYLE_WIN4, NULL);
  467. if (g_hIntlInf == INVALID_HANDLE_VALUE)
  468. {
  469. return (FALSE);
  470. }
  471. if (!SetupOpenAppendInfFile(NULL, g_hIntlInf, NULL))
  472. {
  473. SetupCloseInfFile(g_hIntlInf);
  474. g_hIntlInf = NULL;
  475. return (FALSE);
  476. }
  477. //
  478. // Get all supported code pages from the inf file.
  479. //
  480. if (Advanced_GetSupportedCodePages() == FALSE)
  481. {
  482. return (FALSE);
  483. }
  484. //
  485. // Close the inf file.
  486. //
  487. SetupCloseInfFile(g_hIntlInf);
  488. g_hIntlInf = NULL;
  489. //
  490. // Enumerate all installed code pages.
  491. //
  492. if (EnumSystemCodePages(Intl_EnumInstalledCPProc, CP_INSTALLED) == FALSE)
  493. {
  494. return (FALSE);
  495. }
  496. //
  497. // We only want to do this the first time we setup the list view.
  498. // Otherwise, we get multiple columns created.
  499. //
  500. if (bInitTime)
  501. {
  502. //
  503. // Create a column for the list view.
  504. //
  505. GetClientRect(hwndCP, &Rect);
  506. Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
  507. Column.fmt = LVCFMT_LEFT;
  508. Column.cx = Rect.right - GetSystemMetrics(SM_CYHSCROLL);
  509. Column.pszText = NULL;
  510. Column.cchTextMax = 0;
  511. Column.iSubItem = 0;
  512. ListView_InsertColumn(hwndCP, 0, &Column);
  513. //
  514. // Set extended list view style to use the check boxes.
  515. //
  516. dwExStyle = ListView_GetExtendedListViewStyle(hwndCP);
  517. ListView_SetExtendedListViewStyle( hwndCP,
  518. dwExStyle |
  519. LVS_EX_CHECKBOXES |
  520. LVS_EX_FULLROWSELECT );
  521. }
  522. //
  523. // Go through the list of code pages and add each one to the
  524. // list view and set the appropriate state.
  525. //
  526. pCP = pCodePages;
  527. while (pCP)
  528. {
  529. //
  530. // Insert the item into the list view.
  531. //
  532. Item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  533. Item.iItem = 0;
  534. Item.iSubItem = 0;
  535. Item.state = 0;
  536. Item.stateMask = LVIS_STATEIMAGEMASK;
  537. Item.pszText = pCP->pszName;
  538. Item.cchTextMax = 0;
  539. Item.iImage = 0;
  540. Item.lParam = (LPARAM)pCP;
  541. iIndex = ListView_InsertItem(hwndCP, &Item);
  542. //
  543. // Set the checked state.
  544. //
  545. // There's a bug in the list view code such that the check mark
  546. // isn't displayed when you set the state through InsertItem, so
  547. // we have to set it explicitly using SetItemState.
  548. //
  549. if (iIndex >= 0)
  550. {
  551. ListView_SetItemState( hwndCP,
  552. iIndex,
  553. (pCP->wStatus & ML_ORIG_INSTALLED)
  554. ? INDEXTOSTATEIMAGEMASK(LVIS_SELECTED)
  555. : INDEXTOSTATEIMAGEMASK(LVIS_FOCUSED),
  556. LVIS_STATEIMAGEMASK );
  557. }
  558. //
  559. // Advance to the next code page.
  560. //
  561. pCP = pCP->pNext;
  562. }
  563. //
  564. // Deselect all items.
  565. //
  566. iIndex = ListView_GetItemCount(hwndCP);
  567. while (iIndex > 0)
  568. {
  569. ListView_SetItemState( hwndCP,
  570. iIndex - 1,
  571. 0,
  572. LVIS_FOCUSED | LVIS_SELECTED );
  573. iIndex--;
  574. }
  575. //
  576. // Select the first one in the list.
  577. //
  578. ListView_SetItemState( hwndCP,
  579. 0,
  580. LVIS_FOCUSED | LVIS_SELECTED,
  581. LVIS_FOCUSED | LVIS_SELECTED );
  582. //
  583. // Return success.
  584. //
  585. return (TRUE);
  586. }
  587. ////////////////////////////////////////////////////////////////////////////
  588. //
  589. // Region_FreeGlobalInfo
  590. //
  591. // Processing for a WM_DESTROY message.
  592. //
  593. ////////////////////////////////////////////////////////////////////////////
  594. void Advanced_FreeGlobalInfo()
  595. {
  596. LPCODEPAGE pPreCP, pCurCP;
  597. HANDLE hAlloc;
  598. //
  599. // Remove Code Page info.
  600. //
  601. pCurCP = pCodePages;
  602. pCodePages = NULL;
  603. while (pCurCP)
  604. {
  605. pPreCP = pCurCP;
  606. pCurCP = pPreCP->pNext;
  607. hAlloc = pPreCP->hCodePage;
  608. GlobalUnlock(hAlloc);
  609. GlobalFree(hAlloc);
  610. }
  611. }
  612. ////////////////////////////////////////////////////////////////////////////
  613. //
  614. // Advanced_ClearValues
  615. //
  616. // Reset each of the list boxes in the advanced property sheet page.
  617. //
  618. ////////////////////////////////////////////////////////////////////////////
  619. void Advanced_ClearValues(
  620. HWND hDlg)
  621. {
  622. //
  623. // Clear the system locale
  624. //
  625. ComboBox_ResetContent(GetDlgItem(hDlg, IDC_SYSTEM_LOCALE));
  626. //
  627. // Clear the Code Page list
  628. //
  629. ListView_DeleteAllItems(GetDlgItem(hDlg, IDC_CODEPAGES));
  630. Advanced_FreeGlobalInfo();
  631. }
  632. ////////////////////////////////////////////////////////////////////////////
  633. //
  634. // Advanced_SetValues
  635. //
  636. // Initialize all of the controls in the advanced property sheet page.
  637. //
  638. ////////////////////////////////////////////////////////////////////////////
  639. void Advanced_SetValues(
  640. HWND hDlg,
  641. BOOL bInitTime)
  642. {
  643. //
  644. // Init system locale list.
  645. //
  646. Advanced_InitSystemLocales(hDlg);
  647. //
  648. // Init code page list view.
  649. //
  650. Advanced_InitCodePages(hDlg, bInitTime);
  651. }
  652. ////////////////////////////////////////////////////////////////////////////
  653. //
  654. // Advanced_ApplySettings
  655. //
  656. // For every control that has changed (that affects the Locale settings),
  657. // call Set_Locale_Values to update the user locale information. Notify
  658. // the parent of changes and reset the change flag stored in the property
  659. // sheet page structure appropriately. Redisplay the time sample if
  660. // bRedisplay is TRUE.
  661. //
  662. ////////////////////////////////////////////////////////////////////////////
  663. BOOL Advanced_ApplySettings(
  664. HWND hDlg)
  665. {
  666. LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  667. LPARAM Changes = lpPropSheet->lParam;
  668. HWND hSystemLocale = GetDlgItem(hDlg, IDC_SYSTEM_LOCALE);
  669. DWORD dwLocale;
  670. LCID NewLocale;
  671. HCURSOR hcurSave;
  672. BOOL InvokeSysocmgr = FALSE;
  673. BOOL bReboot = FALSE;
  674. //
  675. // Put up the hour glass.
  676. //
  677. hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  678. //
  679. // See if there are any changes to the codepage conversions.
  680. //
  681. if (Changes & AD_CodePages)
  682. {
  683. LPCODEPAGE pCP;
  684. HINF hIntlInf;
  685. HSPFILEQ FileQueue;
  686. PVOID QueueContext;
  687. BOOL bInitInf = FALSE;
  688. BOOL fAdd;
  689. BOOL bRet = TRUE;
  690. TCHAR szSection[MAX_PATH];
  691. //
  692. // Go through each code page node to see if anything needs to
  693. // be done.
  694. //
  695. pCP = pCodePages;
  696. while (pCP)
  697. {
  698. //
  699. // See if any changes are necessary for this code page.
  700. //
  701. if ((pCP->wStatus == ML_INSTALL) ||
  702. (pCP->wStatus == (ML_ORIG_INSTALLED | ML_REMOVE)))
  703. {
  704. //
  705. // See if we're installing or removing.
  706. //
  707. fAdd = (pCP->wStatus == ML_INSTALL);
  708. //
  709. // Initialize Inf stuff.
  710. //
  711. if ((!bInitInf) &&
  712. (!Intl_InitInf(hDlg, &hIntlInf, szIntlInf, &FileQueue, &QueueContext)))
  713. {
  714. SetCursor(hcurSave);
  715. return (FALSE);
  716. }
  717. bInitInf = TRUE;
  718. //
  719. // Get the inf section name.
  720. //
  721. wsprintf( szSection,
  722. TEXT("%ws%d"),
  723. fAdd ? szCPInstallPrefix : szCPRemovePrefix,
  724. pCP->CodePage );
  725. //
  726. // Enqueue the code page files so that they may be
  727. // copied. This only handles the CopyFiles entries in the
  728. // inf file.
  729. //
  730. if (!SetupInstallFilesFromInfSection( hIntlInf,
  731. NULL,
  732. FileQueue,
  733. szSection,
  734. pSetupSourcePath,
  735. SP_COPY_NEWER ))
  736. {
  737. //
  738. // Setup failed to find the code page.
  739. // This shouldn't happen - the inf file is messed up.
  740. //
  741. ShowMsg( hDlg,
  742. IDS_ML_COPY_FAILED,
  743. 0,
  744. MB_OK_OOPS,
  745. pCP->pszName );
  746. pCP->wStatus = 0;
  747. }
  748. }
  749. //
  750. // Go to the next code page node.
  751. //
  752. pCP = pCP->pNext;
  753. }
  754. if (bInitInf)
  755. {
  756. DWORD d;
  757. //
  758. // See if we need to install any files.
  759. //
  760. // d = 0: User wants new files or some files were missing;
  761. // Must commit queue.
  762. //
  763. // d = 1: User wants to use existing files and queue is empty;
  764. // Can skip committing queue.
  765. //
  766. // d = 2: User wants to use existing files, but del/ren queues
  767. // not empty. Must commit queue. The copy queue will
  768. // have been emptied, so only del/ren functions will be
  769. // performed.
  770. //
  771. if ((SetupScanFileQueue( FileQueue,
  772. SPQ_SCAN_PRUNE_COPY_QUEUE |
  773. SPQ_SCAN_FILE_VALIDITY,
  774. GetParent(hDlg),
  775. NULL,
  776. NULL,
  777. &d )) && (d != 1))
  778. {
  779. //
  780. // Copy the files in the queue.
  781. //
  782. if (!SetupCommitFileQueue( GetParent(hDlg),
  783. FileQueue,
  784. SetupDefaultQueueCallback,
  785. QueueContext ))
  786. {
  787. //
  788. // This can happen if the user hits Cancel from within
  789. // the setup dialog.
  790. //
  791. ShowMsg( hDlg,
  792. IDS_ML_SETUP_FAILED,
  793. 0,
  794. MB_OK_OOPS,
  795. NULL );
  796. bRet = FALSE;
  797. goto Advanced_CodepageConverionsSetupError;
  798. }
  799. }
  800. //
  801. // Execute all of the other code page entries in the inf file.
  802. //
  803. pCP = pCodePages;
  804. while (pCP)
  805. {
  806. //
  807. // See if any changes are necessary for this code page.
  808. //
  809. if ((pCP->wStatus == ML_INSTALL) ||
  810. (pCP->wStatus == (ML_ORIG_INSTALLED | ML_REMOVE)))
  811. {
  812. fAdd = (pCP->wStatus == ML_INSTALL);
  813. //
  814. // Get the inf section name.
  815. //
  816. wsprintf( szSection,
  817. TEXT("%ws%d"),
  818. fAdd ? szCPInstallPrefix : szCPRemovePrefix,
  819. pCP->CodePage );
  820. //
  821. // Call setup to install other inf info for this
  822. // code page.
  823. //
  824. if (!SetupInstallFromInfSection( GetParent(hDlg),
  825. hIntlInf,
  826. szSection,
  827. SPINST_ALL & ~SPINST_FILES,
  828. NULL,
  829. pSetupSourcePath,
  830. 0,
  831. NULL,
  832. NULL,
  833. NULL,
  834. NULL ))
  835. {
  836. //
  837. // Setup failed.
  838. //
  839. // Already copied the code page file, so no need to
  840. // change the status of the code page info here.
  841. //
  842. // This shouldn't happen - the inf file is messed up.
  843. //
  844. ShowMsg( hDlg,
  845. IDS_ML_INSTALL_FAILED,
  846. 0,
  847. MB_OK_OOPS,
  848. pCP->pszName );
  849. }
  850. //
  851. // Reset the status to show the new state of this
  852. // code page.
  853. //
  854. pCP->wStatus &= (ML_STATIC);
  855. if (fAdd)
  856. {
  857. pCP->wStatus |= ML_ORIG_INSTALLED;
  858. }
  859. }
  860. //
  861. // Clear out wStatus and go to the next code page node.
  862. //
  863. pCP->wStatus &= (ML_ORIG_INSTALLED | ML_STATIC);
  864. pCP = pCP->pNext;
  865. }
  866. Advanced_CodepageConverionsSetupError:
  867. //
  868. // Close Inf stuff.
  869. //
  870. Intl_CloseInf(hIntlInf, FileQueue, QueueContext);
  871. }
  872. //
  873. // Check if we need a reboot
  874. //
  875. if (RegionalChgState & AD_SystemLocale)
  876. {
  877. bReboot = TRUE;
  878. }
  879. }
  880. //
  881. // See if there are any changes to the system locale.
  882. //
  883. if (Changes & AD_SystemLocale)
  884. {
  885. //
  886. // Get the current selection.
  887. //
  888. dwLocale = ComboBox_GetCurSel(hSystemLocale);
  889. //
  890. // Get the locale id for the current selection and save it.
  891. //
  892. NewLocale = (LCID)ComboBox_GetItemData(hSystemLocale, dwLocale);
  893. if (IsValidLocale(NewLocale, LCID_SUPPORTED))
  894. {
  895. SysLocaleID = NewLocale;
  896. }
  897. else
  898. {
  899. //
  900. // This shouldn't happen, since the values in the combo box
  901. // should already be installed via the language groups.
  902. // Put up an error message just in case.
  903. //
  904. SetCursor(hcurSave);
  905. ShowMsg( NULL,
  906. IDS_SETUP_STRING,
  907. IDS_TITLE_STRING,
  908. MB_OK_OOPS,
  909. NULL );
  910. return (FALSE);
  911. }
  912. //
  913. // See if the current selection is different from the original
  914. // selection.
  915. //
  916. if (RegSysLocaleID != SysLocaleID)
  917. {
  918. //
  919. // Call setup to install the option.
  920. //
  921. if (SetupChangeLocaleEx( hDlg,
  922. SysLocaleID,
  923. pSetupSourcePath,
  924. (g_bSetupCase)
  925. ? SP_INSTALL_FILES_QUIETLY
  926. : 0,
  927. NULL,
  928. 0 ))
  929. {
  930. //
  931. // If Setup fails, put up a message.
  932. //
  933. SetCursor(hcurSave);
  934. ShowMsg( NULL,
  935. IDS_SETUP_STRING,
  936. IDS_TITLE_STRING,
  937. MB_OK_OOPS,
  938. NULL );
  939. SysLocaleID = GetSystemDefaultLCID();
  940. return (FALSE);
  941. }
  942. //
  943. // Check if we need to proceed with the Font Substitution
  944. //
  945. if (Intl_IsUIFontSubstitute() &&
  946. ((LANGID)LANGIDFROMLCID(SysLocaleID) == Intl_GetDotDefaultUILanguage()))
  947. {
  948. Intl_ApplyFontSubstitute(SysLocaleID);
  949. }
  950. //
  951. // Reset the registry system locale value.
  952. //
  953. RegSysLocaleID = SysLocaleID;
  954. //
  955. // Need to make sure the proper keyboard layout is installed.
  956. //
  957. Intl_InstallKeyboardLayout(hDlg, SysLocaleID, 0, FALSE, FALSE, TRUE);
  958. //
  959. // See if we need to reboot.
  960. //
  961. if (SysLocaleID != GetSystemDefaultLCID())
  962. {
  963. bReboot = TRUE;
  964. }
  965. InvokeSysocmgr = TRUE;
  966. }
  967. }
  968. //
  969. // If the system locale changed and we're not running
  970. // in gui setup, then let's invoke sysocmgr.exe.
  971. //
  972. if (!g_bSetupCase && InvokeSysocmgr)
  973. {
  974. //
  975. // Run any necessary apps (for FSVGA/FSNEC installation).
  976. //
  977. Intl_RunRegApps(c_szSysocmgr);
  978. }
  979. //
  980. // Reset the property page settings.
  981. //
  982. PropSheet_UnChanged(GetParent(hDlg), hDlg);
  983. Changes = AD_EverChg;
  984. //
  985. // Turn off the hour glass.
  986. //
  987. SetCursor(hcurSave);
  988. //
  989. // See if we need to display the reboot message.
  990. //
  991. if ((!g_bSetupCase) && (bReboot))
  992. {
  993. if(RegionalChgState & Process_Languages )
  994. {
  995. RegionalChgState &= ~(AD_CodePages | AD_SystemLocale);
  996. }
  997. else
  998. {
  999. if (ShowMsg( hDlg,
  1000. IDS_REBOOT_STRING,
  1001. IDS_TITLE_STRING,
  1002. MB_YESNO | MB_ICONQUESTION,
  1003. NULL ) == IDYES)
  1004. {
  1005. Intl_RebootTheSystem();
  1006. }
  1007. }
  1008. }
  1009. //
  1010. // Return success.
  1011. //
  1012. return (TRUE);
  1013. }
  1014. ////////////////////////////////////////////////////////////////////////////
  1015. //
  1016. // Advanced_ValidatePPS
  1017. //
  1018. // Validate each of the combo boxes whose values are constrained.
  1019. // If any of the input fails, notify the user and then return FALSE
  1020. // to indicate validation failure.
  1021. //
  1022. ////////////////////////////////////////////////////////////////////////////
  1023. BOOL Advanced_ValidatePPS(
  1024. HWND hDlg,
  1025. LPARAM Changes)
  1026. {
  1027. //
  1028. // If nothing has changed, return TRUE immediately.
  1029. //
  1030. if (Changes <= AD_EverChg)
  1031. {
  1032. return (TRUE);
  1033. }
  1034. //
  1035. // See if the system locale has changed.
  1036. //
  1037. if (Changes & AD_SystemLocale)
  1038. {
  1039. HWND hSystemLocale = GetDlgItem(hDlg, IDC_SYSTEM_LOCALE);
  1040. DWORD dwLocale = ComboBox_GetCurSel(hSystemLocale);
  1041. LCID NewLocale;
  1042. //
  1043. // Get the locale id for the current selection and save it.
  1044. //
  1045. NewLocale = (LCID)ComboBox_GetItemData(hSystemLocale, dwLocale);
  1046. if (IsValidLocale(NewLocale, LCID_SUPPORTED))
  1047. {
  1048. SysLocaleID = NewLocale;
  1049. }
  1050. else
  1051. {
  1052. //
  1053. // This shouldn't happen, since the values in the combo box
  1054. // should already be installed via the language groups.
  1055. // Put up an error message just in case.
  1056. //
  1057. ShowMsg( NULL,
  1058. IDS_SETUP_STRING,
  1059. IDS_TITLE_STRING,
  1060. MB_OK_OOPS,
  1061. NULL );
  1062. return (FALSE);
  1063. }
  1064. }
  1065. return (TRUE);
  1066. }
  1067. ////////////////////////////////////////////////////////////////////////////
  1068. //
  1069. // Advanced_InitPropSheet
  1070. //
  1071. // The extra long value for the property sheet page is used as a set of
  1072. // state or change flags for each of the list boxes in the property sheet.
  1073. // Initialize this value to 0. Call Advanced_SetValues with the property
  1074. // sheet handle to initialize all of the property sheet controls. Limit
  1075. // the length of the text in some of the ComboBoxes.
  1076. //
  1077. ////////////////////////////////////////////////////////////////////////////
  1078. void Advanced_InitPropSheet(
  1079. HWND hDlg,
  1080. LPARAM lParam)
  1081. {
  1082. //
  1083. // The lParam holds a pointer to the property sheet page. Save it
  1084. // for later reference.
  1085. //
  1086. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  1087. //
  1088. // Set values.
  1089. //
  1090. if (pLanguageGroups == NULL)
  1091. {
  1092. Intl_LoadLanguageGroups(hDlg);
  1093. }
  1094. Advanced_SetValues(hDlg, TRUE);
  1095. //
  1096. // If we are in setup mode, we need to disable the Default User
  1097. // Account UI.
  1098. //
  1099. if (g_bSetupCase)
  1100. {
  1101. HWND hUIDefUserBox = GetDlgItem(hDlg, IDC_GROUPBOX3);
  1102. HWND hUIDefUser = GetDlgItem(hDlg, IDC_DEFAULT_USER);
  1103. EnableWindow(hUIDefUserBox, FALSE);
  1104. EnableWindow(hUIDefUser, FALSE);
  1105. ShowWindow(hUIDefUserBox, SW_HIDE);
  1106. ShowWindow(hUIDefUser, SW_HIDE);
  1107. }
  1108. }
  1109. ////////////////////////////////////////////////////////////////////////////
  1110. //
  1111. // AdvancedDlgProc
  1112. //
  1113. ////////////////////////////////////////////////////////////////////////////
  1114. INT_PTR CALLBACK AdvancedDlgProc(
  1115. HWND hDlg,
  1116. UINT message,
  1117. WPARAM wParam,
  1118. LPARAM lParam)
  1119. {
  1120. LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  1121. switch (message)
  1122. {
  1123. case ( WM_NOTIFY ) :
  1124. {
  1125. LPNMHDR lpnm = (NMHDR *)lParam;
  1126. switch (lpnm->code)
  1127. {
  1128. case ( PSN_SETACTIVE ) :
  1129. {
  1130. //
  1131. // If there has been a change in the regional Locale
  1132. // setting, clear all of the current info in the
  1133. // property sheet, get the new values, and update the
  1134. // appropriate registry values.
  1135. //
  1136. if (Verified_Regional_Chg & Process_Advanced)
  1137. {
  1138. Verified_Regional_Chg &= ~Process_Advanced;
  1139. Advanced_ClearValues(hDlg);
  1140. Advanced_SetValues(hDlg, FALSE);
  1141. lpPropSheet->lParam = 0;
  1142. }
  1143. break;
  1144. }
  1145. case ( PSN_KILLACTIVE ) :
  1146. {
  1147. //
  1148. // Validate the entries on the property page.
  1149. //
  1150. SetWindowLongPtr( hDlg,
  1151. DWLP_MSGRESULT,
  1152. !Advanced_ValidatePPS(hDlg, lpPropSheet->lParam) );
  1153. break;
  1154. }
  1155. case ( PSN_APPLY ) :
  1156. {
  1157. //
  1158. // Apply the settings.
  1159. //
  1160. if (Advanced_ApplySettings(hDlg))
  1161. {
  1162. SetWindowLongPtr( hDlg,
  1163. DWLP_MSGRESULT,
  1164. PSNRET_NOERROR );
  1165. //
  1166. // Zero out the AD_EverChg bit.
  1167. //
  1168. lpPropSheet->lParam = 0;
  1169. }
  1170. else
  1171. {
  1172. SetWindowLongPtr( hDlg,
  1173. DWLP_MSGRESULT,
  1174. PSNRET_INVALID_NOCHANGEPAGE );
  1175. }
  1176. break;
  1177. }
  1178. case ( NM_CUSTOMDRAW ) :
  1179. {
  1180. Advanced_ListViewCustomDraw(hDlg, (LPNMLVCUSTOMDRAW)lParam);
  1181. return (TRUE);
  1182. }
  1183. case ( LVN_ITEMCHANGING ) :
  1184. {
  1185. Advanced_ListViewChanging(hDlg, (NM_LISTVIEW *)lParam);
  1186. break;
  1187. }
  1188. case ( LVN_ITEMCHANGED ) :
  1189. {
  1190. //
  1191. // Save the change to the code pages.
  1192. //
  1193. if (Advanced_ListViewChanged( hDlg,
  1194. IDC_CODEPAGES,
  1195. (NM_LISTVIEW *)lParam ))
  1196. {
  1197. //
  1198. // Note that the code pages have changed and
  1199. // enable the apply button.
  1200. //
  1201. lpPropSheet->lParam |= AD_CodePages;
  1202. PropSheet_Changed(GetParent(hDlg), hDlg);
  1203. RegionalChgState |= AD_CodePages;
  1204. }
  1205. break;
  1206. }
  1207. case ( NM_CLICK ) :
  1208. case ( NM_DBLCLK ) :
  1209. {
  1210. Advanced_ListViewClick(hDlg, (NMHDR*)lParam);
  1211. }
  1212. default :
  1213. {
  1214. return (FALSE);
  1215. }
  1216. }
  1217. break;
  1218. }
  1219. case ( WM_INITDIALOG ) :
  1220. {
  1221. Advanced_InitPropSheet(hDlg, lParam);
  1222. break;
  1223. }
  1224. case ( WM_DESTROY ) :
  1225. {
  1226. Advanced_FreeGlobalInfo();
  1227. break;
  1228. }
  1229. case ( WM_HELP ) :
  1230. {
  1231. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  1232. szHelpFile,
  1233. HELP_WM_HELP,
  1234. (DWORD_PTR)(LPTSTR)aAdvancedHelpIds );
  1235. break;
  1236. }
  1237. case ( WM_CONTEXTMENU ) : // right mouse click
  1238. {
  1239. WinHelp( (HWND)wParam,
  1240. szHelpFile,
  1241. HELP_CONTEXTMENU,
  1242. (DWORD_PTR)(LPTSTR)aAdvancedHelpIds );
  1243. break;
  1244. }
  1245. case ( WM_COMMAND ) :
  1246. {
  1247. switch (LOWORD(wParam))
  1248. {
  1249. case ( IDC_SYSTEM_LOCALE ) :
  1250. {
  1251. if (HIWORD(wParam) == CBN_SELCHANGE)
  1252. {
  1253. //
  1254. // Set the AD_SystemLocale change flag.
  1255. //
  1256. lpPropSheet->lParam |= AD_SystemLocale;
  1257. PropSheet_Changed(GetParent(hDlg), hDlg);
  1258. RegionalChgState |= AD_SystemLocale;
  1259. }
  1260. break;
  1261. }
  1262. case ( IDC_DEFAULT_USER ) :
  1263. {
  1264. BOOL curState;
  1265. //
  1266. // Verify the check box state.
  1267. //
  1268. if (IsDlgButtonChecked(hDlg, IDC_DEFAULT_USER))
  1269. {
  1270. ShowMsg( hDlg,
  1271. IDS_DEF_USER_CONF,
  1272. IDS_DEF_USER_CONF_TITLE,
  1273. MB_OK_OOPS,
  1274. NULL);
  1275. g_bDefaultUser = TRUE;
  1276. }
  1277. else
  1278. {
  1279. g_bDefaultUser = FALSE;
  1280. }
  1281. //
  1282. // Set the AD_DefaultUser change flag.
  1283. //
  1284. if (g_bDefaultUser)
  1285. {
  1286. lpPropSheet->lParam |= AD_DefaultUser;
  1287. PropSheet_Changed(GetParent(hDlg), hDlg);
  1288. }
  1289. else
  1290. {
  1291. lpPropSheet->lParam &= ~AD_DefaultUser;
  1292. }
  1293. break;
  1294. }
  1295. }
  1296. break;
  1297. }
  1298. default :
  1299. {
  1300. return (FALSE);
  1301. }
  1302. }
  1303. return (TRUE);
  1304. }