1 /* 2 * PROJECT: input.dll 3 * FILE: dll/cpl/input/settings_page.c 4 * PURPOSE: input.dll 5 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org) 6 * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) 7 */ 8 9 #include "input.h" 10 #include "layout_list.h" 11 #include "locale_list.h" 12 #include "input_list.h" 13 14 static INT s_nAliveLeafCount = 0; 15 static INT s_nRootCount = 0; 16 static INT s_iKeyboardImage = -1; 17 static INT s_iDotImage = -1; 18 static BOOL s_bDefaultInputChanged = FALSE; 19 20 static HICON 21 CreateLayoutIcon(LANGID LangID) 22 { 23 WCHAR szBuf[4]; 24 HDC hdcScreen, hdc; 25 HBITMAP hbmColor, hbmMono, hBmpOld; 26 HFONT hFont, hFontOld; 27 LOGFONTW lf; 28 RECT rect; 29 ICONINFO IconInfo; 30 HICON hIcon; 31 INT cxIcon = GetSystemMetrics(SM_CXSMICON); 32 INT cyIcon = GetSystemMetrics(SM_CYSMICON); 33 34 /* Getting "EN", "FR", etc. from English, French, ... */ 35 if (GetLocaleInfoW(LangID, 36 LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE, 37 szBuf, 38 ARRAYSIZE(szBuf)) == 0) 39 { 40 szBuf[0] = szBuf[1] = L'?'; 41 } 42 szBuf[2] = UNICODE_NULL; /* Truncate the identifier to two characters: "ENG" --> "EN" etc. */ 43 44 /* Create hdc, hbmColor and hbmMono */ 45 hdcScreen = GetDC(NULL); 46 hdc = CreateCompatibleDC(hdcScreen); 47 hbmColor = CreateCompatibleBitmap(hdcScreen, cxIcon, cyIcon); 48 ReleaseDC(NULL, hdcScreen); 49 hbmMono = CreateBitmap(cxIcon, cyIcon, 1, 1, NULL); 50 51 /* Checking NULL */ 52 if (!hdc || !hbmColor || !hbmMono) 53 { 54 if (hbmMono) 55 DeleteObject(hbmMono); 56 if (hbmColor) 57 DeleteObject(hbmColor); 58 if (hdc) 59 DeleteDC(hdc); 60 return NULL; 61 } 62 63 /* Create a font */ 64 hFont = NULL; 65 if (SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0)) 66 { 67 /* Override the current size with something manageable */ 68 lf.lfHeight = -11; 69 lf.lfWidth = 0; 70 hFont = CreateFontIndirectW(&lf); 71 } 72 if (!hFont) 73 hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); 74 75 SetRect(&rect, 0, 0, cxIcon, cyIcon); 76 77 /* Draw hbmColor */ 78 hBmpOld = SelectObject(hdc, hbmColor); 79 SetDCBrushColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); 80 FillRect(hdc, &rect, (HBRUSH)GetStockObject(DC_BRUSH)); 81 hFontOld = SelectObject(hdc, hFont); 82 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); 83 SetBkMode(hdc, TRANSPARENT); 84 DrawTextW(hdc, szBuf, 2, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); 85 SelectObject(hdc, hFontOld); 86 87 /* Fill hbmMono with black */ 88 SelectObject(hdc, hbmMono); 89 PatBlt(hdc, 0, 0, cxIcon, cyIcon, BLACKNESS); 90 SelectObject(hdc, hBmpOld); 91 92 /* Create an icon from hbmColor and hbmMono */ 93 IconInfo.fIcon = TRUE; 94 IconInfo.xHotspot = IconInfo.yHotspot = 0; 95 IconInfo.hbmColor = hbmColor; 96 IconInfo.hbmMask = hbmMono; 97 hIcon = CreateIconIndirect(&IconInfo); 98 99 /* Clean up */ 100 DeleteObject(hFont); 101 DeleteObject(hbmMono); 102 DeleteObject(hbmColor); 103 DeleteDC(hdc); 104 105 return hIcon; 106 } 107 108 static VOID InitDefaultLangComboBox(HWND hwndCombo) 109 { 110 WCHAR szText[256]; 111 INPUT_LIST_NODE *pNode; 112 INT iIndex, nCount, iDefault = (INT)SendMessageW(hwndCombo, CB_GETCURSEL, 0, 0); 113 114 SendMessageW(hwndCombo, CB_RESETCONTENT, 0, 0); 115 116 for (pNode = InputList_GetFirst(); pNode != NULL; pNode = pNode->pNext) 117 { 118 if (pNode->wFlags & INPUT_LIST_NODE_FLAG_DELETED) 119 continue; 120 121 StringCchPrintfW(szText, _countof(szText), L"%s - %s", 122 pNode->pLocale->pszName, pNode->pLayout->pszName); 123 iIndex = (INT)SendMessageW(hwndCombo, CB_ADDSTRING, 0, (LPARAM)szText); 124 SendMessageW(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)pNode); 125 126 if (pNode->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT) 127 iDefault = iIndex; 128 } 129 130 nCount = (INT)SendMessageW(hwndCombo, CB_GETCOUNT, 0, 0); 131 if (iDefault >= nCount) 132 SendMessageW(hwndCombo, CB_SETCURSEL, nCount - 1, 0); 133 else 134 SendMessageW(hwndCombo, CB_SETCURSEL, iDefault, 0); 135 } 136 137 static VOID 138 SetControlsState(HWND hwndDlg) 139 { 140 HWND hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); 141 HWND hwndCombo = GetDlgItem(hwndDlg, IDC_DEFAULT_LANGUAGE); 142 BOOL bIsLeaf, bCanRemove, bCanProp; 143 HTREEITEM hSelected = TreeView_GetSelection(hwndList); 144 TV_ITEM item = { TVIF_PARAM | TVIF_HANDLE }; 145 item.hItem = hSelected; 146 147 bIsLeaf = (hSelected && TreeView_GetItem(hwndList, &item) && HIWORD(item.lParam)); 148 149 bCanRemove = (bIsLeaf && (s_nAliveLeafCount > 1)) || (s_nRootCount > 1); 150 bCanProp = bIsLeaf; 151 152 EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE_BUTTON), bCanRemove); 153 EnableWindow(GetDlgItem(hwndDlg, IDC_PROP_BUTTON), bCanProp); 154 155 InitDefaultLangComboBox(hwndCombo); 156 } 157 158 static BOOL CALLBACK 159 EnumResNameProc(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam) 160 { 161 HICON* phIconSm = (HICON*)lParam; 162 if (*phIconSm) 163 return FALSE; 164 165 *phIconSm = (HICON)LoadImageW(hModule, lpszName, IMAGE_ICON, 166 GetSystemMetrics(SM_CXSMICON), 167 GetSystemMetrics(SM_CYSMICON), 168 0); 169 return TRUE; 170 } 171 172 static HICON LoadIMEIcon(LPCTSTR pszImeFile) 173 { 174 WCHAR szSysDir[MAX_PATH], szPath[MAX_PATH]; 175 HINSTANCE hImeInst; 176 HICON hIconSm = NULL; 177 178 GetSystemDirectoryW(szSysDir, _countof(szSysDir)); 179 StringCchPrintfW(szPath, _countof(szPath), L"%s\\%s", szSysDir, pszImeFile); 180 181 hImeInst = LoadLibraryExW(szPath, NULL, DONT_RESOLVE_DLL_REFERENCES); 182 if (hImeInst == NULL) 183 return NULL; 184 185 EnumResourceNamesW(hImeInst, RT_GROUP_ICON, EnumResNameProc, (LPARAM)&hIconSm); 186 FreeLibrary(hImeInst); 187 188 return hIconSm; 189 } 190 191 static HTREEITEM FindLanguageInList(HWND hwndList, LPCTSTR pszLangName) 192 { 193 TV_ITEM item; 194 TCHAR szText[128]; 195 HTREEITEM hItem; 196 197 hItem = TreeView_GetRoot(hwndList); 198 while (hItem) 199 { 200 szText[0] = 0; 201 item.mask = TVIF_TEXT | TVIF_HANDLE; 202 item.pszText = szText; 203 item.cchTextMax = _countof(szText); 204 item.hItem = hItem; 205 TreeView_GetItem(hwndList, &item); 206 if (_wcsicmp(szText, pszLangName) == 0) 207 return hItem; 208 209 hItem = TreeView_GetNextSibling(hwndList, hItem); 210 } 211 212 return NULL; 213 } 214 215 static VOID 216 AddToInputListView(HWND hwndList, INPUT_LIST_NODE *pInputNode) 217 { 218 TV_ITEM item; 219 TV_INSERTSTRUCT insert; 220 HIMAGELIST hImageList = TreeView_GetImageList(hwndList, TVSIL_NORMAL); 221 WCHAR szKeyboard[64]; 222 HTREEITEM hItem; 223 BOOL bBold = !!(pInputNode->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT); 224 225 hItem = FindLanguageInList(hwndList, pInputNode->pLocale->pszName); 226 if (hItem == NULL) 227 { 228 // Language icon 229 INT LangImageIndex = -1; 230 HICON hLangIcon = CreateLayoutIcon(LOWORD(pInputNode->pLocale->dwId)); 231 if (hLangIcon) 232 { 233 LangImageIndex = ImageList_AddIcon(hImageList, hLangIcon); 234 DestroyIcon(hLangIcon); 235 } 236 237 // Language 238 ZeroMemory(&item, sizeof(item)); 239 item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE; 240 item.pszText = pInputNode->pLocale->pszName; 241 item.iImage = LangImageIndex; 242 item.iSelectedImage = LangImageIndex; 243 item.lParam = LOWORD(pInputNode->pLocale->dwId); // HIWORD(item.lParam) == 0 244 if (bBold) 245 { 246 item.state = item.stateMask = TVIS_BOLD; 247 } 248 insert.hParent = TVI_ROOT; 249 insert.hInsertAfter = TVI_LAST; 250 insert.item = item; 251 hItem = TreeView_InsertItem(hwndList, &insert); 252 253 // The type of input method (currently keyboard only) 254 LoadStringW(hApplet, IDS_KEYBOARD, szKeyboard, _countof(szKeyboard)); 255 ZeroMemory(&item, sizeof(item)); 256 item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE; 257 item.pszText = szKeyboard; 258 item.iImage = s_iKeyboardImage; 259 item.iSelectedImage = s_iKeyboardImage; 260 item.lParam = 0; // HIWORD(item.lParam) == 0 261 insert.hParent = hItem; 262 insert.hInsertAfter = TVI_LAST; 263 insert.item = item; 264 hItem = TreeView_InsertItem(hwndList, &insert); 265 } 266 else 267 { 268 // Language 269 ZeroMemory(&item, sizeof(item)); 270 item.mask = TVIF_STATE | TVIF_HANDLE; 271 item.hItem = hItem; 272 item.stateMask = TVIS_BOLD; 273 if (TreeView_GetItem(hwndList, &item) && bBold && !(item.state & TVIS_BOLD)) 274 { 275 // Make the item bold 276 item.mask = TVIF_STATE | TVIF_HANDLE; 277 item.hItem = hItem; 278 item.state = item.stateMask = TVIS_BOLD; 279 TreeView_SetItem(hwndList, &item); 280 } 281 282 // The type of input method (currently keyboard only) 283 hItem = TreeView_GetChild(hwndList, hItem); 284 } 285 286 // Input method 287 if (hItem) 288 { 289 INT ImeImageIndex = s_iDotImage; 290 if (IS_IME_HKL(pInputNode->hkl) && pInputNode->pLayout->pszImeFile) // IME? 291 { 292 HICON hImeIcon = LoadIMEIcon(pInputNode->pLayout->pszImeFile); 293 if (hImeIcon) 294 { 295 ImeImageIndex = ImageList_AddIcon(hImageList, hImeIcon); 296 DestroyIcon(hImeIcon); 297 } 298 } 299 300 ZeroMemory(&item, sizeof(item)); 301 item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE; 302 item.pszText = pInputNode->pLayout->pszName; 303 item.iImage = ImeImageIndex; 304 item.iSelectedImage = ImeImageIndex; 305 item.lParam = (LPARAM)pInputNode; // HIWORD(item.lParam) != 0 306 if (bBold) 307 { 308 item.state = item.stateMask = TVIS_BOLD; // Make the item bold 309 } 310 insert.hParent = hItem; 311 insert.hInsertAfter = TVI_LAST; 312 insert.item = item; 313 hItem = TreeView_InsertItem(hwndList, &insert); 314 } 315 } 316 317 static VOID ExpandTreeItem(HWND hwndTree, HTREEITEM hItem) 318 { 319 TreeView_Expand(hwndTree, hItem, TVE_EXPAND); 320 hItem = TreeView_GetChild(hwndTree, hItem); 321 while (hItem) 322 { 323 ExpandTreeItem(hwndTree, hItem); 324 hItem = TreeView_GetNextSibling(hwndTree, hItem); 325 } 326 } 327 328 static VOID 329 UpdateInputListView(HWND hwndList) 330 { 331 INPUT_LIST_NODE *pNode; 332 HIMAGELIST hImageList = TreeView_GetImageList(hwndList, TVSIL_NORMAL); 333 HTREEITEM hItem; 334 HICON hKeyboardIcon, hDotIcon; 335 336 ImageList_RemoveAll(hImageList); 337 TreeView_DeleteAllItems(hwndList); 338 339 // Add keyboard icon 340 s_iKeyboardImage = -1; 341 hKeyboardIcon = (HICON)LoadImageW(hApplet, MAKEINTRESOURCEW(IDI_KEYBOARD), IMAGE_ICON, 342 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 343 0); 344 if (hKeyboardIcon) 345 { 346 s_iKeyboardImage = ImageList_AddIcon(hImageList, hKeyboardIcon); 347 DestroyIcon(hKeyboardIcon); 348 } 349 350 // Add dot icon 351 s_iDotImage = -1; 352 hDotIcon = (HICON)LoadImageW(hApplet, MAKEINTRESOURCEW(IDI_DOT), IMAGE_ICON, 353 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 354 0); 355 if (hDotIcon) 356 { 357 s_iDotImage = ImageList_AddIcon(hImageList, hDotIcon); 358 DestroyIcon(hDotIcon); 359 } 360 361 InputList_Sort(); 362 363 s_nAliveLeafCount = InputList_GetAliveCount(); 364 365 // Add items to the list 366 for (pNode = InputList_GetFirst(); pNode; pNode = pNode->pNext) 367 { 368 if (pNode->wFlags & INPUT_LIST_NODE_FLAG_DELETED) 369 continue; 370 371 AddToInputListView(hwndList, pNode); 372 } 373 374 // Expand all (with counting s_nRootCount) 375 s_nRootCount = 0; 376 hItem = TreeView_GetRoot(hwndList); 377 while (hItem) 378 { 379 ++s_nRootCount; 380 ExpandTreeItem(hwndList, hItem); 381 hItem = TreeView_GetNextSibling(hwndList, hItem); 382 } 383 384 // Redraw 385 InvalidateRect(hwndList, NULL, TRUE); 386 } 387 388 static VOID 389 OnInitSettingsPage(HWND hwndDlg) 390 { 391 HWND hwndInputList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); 392 HIMAGELIST hLayoutImageList, hOldImageList; 393 394 LayoutList_Create(); 395 LocaleList_Create(); 396 InputList_Create(); 397 398 EnableWindow(GetDlgItem(hwndDlg, IDC_LANGUAGE_BAR), FALSE); 399 400 hLayoutImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), 401 GetSystemMetrics(SM_CYSMICON), 402 ILC_COLOR8 | ILC_MASK, 0, 0); 403 if (hLayoutImageList != NULL) 404 { 405 hOldImageList = TreeView_SetImageList(hwndInputList, hLayoutImageList, TVSIL_NORMAL); 406 ImageList_Destroy(hOldImageList); 407 } 408 409 UpdateInputListView(hwndInputList); 410 411 SetControlsState(hwndDlg); 412 } 413 414 415 static VOID 416 OnDestroySettingsPage(HWND hwndDlg) 417 { 418 LayoutList_Destroy(); 419 LocaleList_Destroy(); 420 InputList_Destroy(); 421 } 422 423 424 VOID 425 OnCommandSettingsPage(HWND hwndDlg, WPARAM wParam) 426 { 427 switch (LOWORD(wParam)) 428 { 429 case IDC_ADD_BUTTON: 430 { 431 if (DialogBoxW(hApplet, 432 MAKEINTRESOURCEW(IDD_ADD), 433 hwndDlg, 434 AddDialogProc) == IDOK) 435 { 436 UpdateInputListView(GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST)); 437 SetControlsState(hwndDlg); 438 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 439 } 440 } 441 break; 442 443 case IDC_REMOVE_BUTTON: 444 { 445 HWND hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); 446 if (hwndList) 447 { 448 HTREEITEM hItem = TreeView_GetSelection(hwndList); 449 TV_ITEM item = { TVIF_HANDLE | TVIF_PARAM }; 450 item.hItem = hItem; 451 452 if (hItem && TreeView_GetItem(hwndList, &item)) 453 { 454 if (item.lParam == 0) // Branch? (currently branch is keyboard only) 455 { 456 // Get root of branch 457 item.hItem = TreeView_GetParent(hwndList, hItem); 458 TreeView_GetItem(hwndList, &item); 459 } 460 461 if (HIWORD(item.lParam)) // Leaf? 462 { 463 if (InputList_Remove((INPUT_LIST_NODE*)item.lParam)) 464 s_bDefaultInputChanged = TRUE; 465 } 466 else // Root? 467 { 468 if (InputList_RemoveByLang(LOWORD(item.lParam))) 469 s_bDefaultInputChanged = TRUE; 470 } 471 472 UpdateInputListView(hwndList); 473 SetControlsState(hwndDlg); 474 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 475 } 476 } 477 } 478 break; 479 480 case IDC_PROP_BUTTON: 481 { 482 HWND hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); 483 if (hwndList) 484 { 485 HTREEITEM hItem = TreeView_GetSelection(hwndList); 486 TV_ITEM item = { TVIF_HANDLE | TVIF_PARAM }; 487 item.hItem = hItem; 488 489 if (hItem && TreeView_GetItem(hwndList, &item) && HIWORD(item.lParam)) 490 { 491 if (DialogBoxParamW(hApplet, 492 MAKEINTRESOURCEW(IDD_INPUT_LANG_PROP), 493 hwndDlg, 494 EditDialogProc, 495 item.lParam) == IDOK) 496 { 497 UpdateInputListView(hwndList); 498 SetControlsState(hwndDlg); 499 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 500 } 501 } 502 } 503 } 504 break; 505 506 case IDC_KEY_SET_BTN: 507 { 508 DialogBoxW(hApplet, 509 MAKEINTRESOURCEW(IDD_KEYSETTINGS), 510 hwndDlg, 511 KeySettingsDialogProc); 512 } 513 break; 514 515 case IDC_LANGUAGE_BAR: 516 { 517 // FIXME 518 break; 519 } 520 521 case IDC_DEFAULT_LANGUAGE: 522 { 523 if (HIWORD(wParam) == CBN_SELENDOK) 524 { 525 HWND hwndList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT_LIST); 526 HWND hwndCombo = GetDlgItem(hwndDlg, IDC_DEFAULT_LANGUAGE); 527 INT iSelected = (INT)SendMessageW(hwndCombo, CB_GETCURSEL, 0, 0); 528 if (iSelected != CB_ERR) 529 { 530 LPARAM lParam = SendMessageW(hwndCombo, CB_GETITEMDATA, iSelected, 0); 531 if (lParam) 532 { 533 INPUT_LIST_NODE* pNode = (INPUT_LIST_NODE*)lParam; 534 if (!(pNode->wFlags & INPUT_LIST_NODE_FLAG_DEFAULT)) 535 { 536 s_bDefaultInputChanged = TRUE; 537 InputList_SetDefault(pNode); 538 UpdateInputListView(hwndList); 539 SetControlsState(hwndDlg); 540 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 541 } 542 } 543 } 544 } 545 } 546 } 547 } 548 549 static BOOL IsRebootNeeded(VOID) 550 { 551 INPUT_LIST_NODE *pNode; 552 553 if (s_bDefaultInputChanged) 554 return TRUE; 555 556 for (pNode = InputList_GetFirst(); pNode != NULL; pNode = pNode->pNext) 557 { 558 if (IS_IME_HKL(pNode->hkl)) /* IME? */ 559 { 560 return TRUE; 561 } 562 } 563 564 return FALSE; 565 } 566 567 BOOL EnableProcessPrivileges(LPCWSTR lpPrivilegeName, BOOL bEnable) 568 { 569 HANDLE hToken; 570 LUID luid; 571 TOKEN_PRIVILEGES tokenPrivileges; 572 BOOL Ret; 573 574 Ret = OpenProcessToken(GetCurrentProcess(), 575 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 576 &hToken); 577 if (!Ret) 578 return Ret; // failure 579 580 Ret = LookupPrivilegeValueW(NULL, lpPrivilegeName, &luid); 581 if (Ret) 582 { 583 tokenPrivileges.PrivilegeCount = 1; 584 tokenPrivileges.Privileges[0].Luid = luid; 585 tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; 586 587 Ret = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, 0, 0); 588 } 589 590 CloseHandle(hToken); 591 return Ret; 592 } 593 594 static INT_PTR 595 OnNotifySettingsPage(HWND hwndDlg, LPARAM lParam) 596 { 597 LPNMHDR header = (LPNMHDR)lParam; 598 599 switch (header->code) 600 { 601 case TVN_SELCHANGED: 602 { 603 SetControlsState(hwndDlg); 604 break; 605 } 606 607 case TVN_ITEMEXPANDING: 608 { 609 // FIXME: Prevent collapse (COMCTL32 is buggy) 610 // https://bugs.winehq.org/show_bug.cgi?id=53727 611 NM_TREEVIEW* pTreeView = (NM_TREEVIEW*)lParam; 612 if ((pTreeView->action & TVE_TOGGLE) == TVE_COLLAPSE) 613 { 614 SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE); 615 return TRUE; 616 } 617 break; 618 } 619 620 case PSN_APPLY: 621 { 622 BOOL bRebootNeeded = IsRebootNeeded(); 623 624 /* Write Input Methods list to registry */ 625 if (InputList_Process() && bRebootNeeded) 626 { 627 /* Needs reboot */ 628 WCHAR szNeedsReboot[128], szLanguage[64]; 629 LoadStringW(hApplet, IDS_REBOOT_NOW, szNeedsReboot, _countof(szNeedsReboot)); 630 LoadStringW(hApplet, IDS_LANGUAGE, szLanguage, _countof(szLanguage)); 631 632 if (MessageBoxW(hwndDlg, szNeedsReboot, szLanguage, 633 MB_ICONINFORMATION | MB_YESNOCANCEL) == IDYES) 634 { 635 EnableProcessPrivileges(SE_SHUTDOWN_NAME, TRUE); 636 ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0); 637 } 638 } 639 break; 640 } 641 } 642 643 return 0; 644 } 645 646 INT_PTR CALLBACK 647 SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 648 { 649 switch (uMsg) 650 { 651 case WM_INITDIALOG: 652 OnInitSettingsPage(hwndDlg); 653 return TRUE; 654 655 case WM_DESTROY: 656 OnDestroySettingsPage(hwndDlg); 657 break; 658 659 case WM_COMMAND: 660 OnCommandSettingsPage(hwndDlg, wParam); 661 break; 662 663 case WM_NOTIFY: 664 return OnNotifySettingsPage(hwndDlg, lParam); 665 } 666 667 return FALSE; 668 } 669