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.

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