1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS msgina.dll 4 * FILE: lib/msgina/shutdown.c 5 * PURPOSE: Shutdown Dialog Box (GUI only) 6 * PROGRAMMERS: Lee Schroeder (spaceseel at gmail dot com) 7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr) 8 */ 9 10 #include "msgina.h" 11 #include <powrprof.h> 12 #include <wingdi.h> 13 14 /* Shutdown state flags */ 15 #define WLX_SHUTDOWN_STATE_LOGOFF 0x01 16 #define WLX_SHUTDOWN_STATE_POWER_OFF 0x02 17 #define WLX_SHUTDOWN_STATE_REBOOT 0x04 18 // 0x08 19 #define WLX_SHUTDOWN_STATE_SLEEP 0x10 20 // 0x20 21 #define WLX_SHUTDOWN_STATE_HIBERNATE 0x40 22 // 0x80 23 24 typedef struct _SHUTDOWN_DLG_CONTEXT 25 { 26 PGINA_CONTEXT pgContext; 27 HBITMAP hBitmap; 28 DWORD ShutdownOptions; 29 BOOL bCloseDlg; 30 BOOL bReasonUI; 31 BOOL bFriendlyUI; 32 } SHUTDOWN_DLG_CONTEXT, *PSHUTDOWN_DLG_CONTEXT; 33 34 35 static 36 BOOL 37 GetShutdownReasonUI(VOID) 38 { 39 OSVERSIONINFOEX VersionInfo; 40 DWORD dwValue, dwSize; 41 HKEY hKey; 42 LONG lRet; 43 44 /* Query the policy value */ 45 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 46 L"Software\\Policies\\Microsoft\\Windows NT\\Reliability", 47 0, 48 KEY_QUERY_VALUE, 49 &hKey); 50 if (lRet == ERROR_SUCCESS) 51 { 52 dwValue = 0; 53 dwSize = sizeof(dwValue); 54 RegQueryValueExW(hKey, 55 L"ShutdownReasonUI", 56 NULL, 57 NULL, 58 (LPBYTE)&dwValue, 59 &dwSize); 60 RegCloseKey(hKey); 61 62 return (dwValue != 0) ? TRUE : FALSE; 63 } 64 65 /* Query the machine value */ 66 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 67 L"Software\\Microsoft\\Windows\\CurrentVersion\\Reliability", 68 0, 69 KEY_QUERY_VALUE, 70 &hKey); 71 if (lRet == ERROR_SUCCESS) 72 { 73 dwValue = 0; 74 dwSize = sizeof(dwValue); 75 RegQueryValueExW(hKey, 76 L"ShutdownReasonUI", 77 NULL, 78 NULL, 79 (LPBYTE)&dwValue, 80 &dwSize); 81 RegCloseKey(hKey); 82 83 return (dwValue != 0) ? TRUE : FALSE; 84 } 85 86 /* Return the default value */ 87 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo); 88 if (!GetVersionEx((POSVERSIONINFO)&VersionInfo)) 89 return FALSE; 90 91 return FALSE; 92 // return (VersionInfo.wProductType == VER_NT_WORKSTATION) ? FALSE : TRUE; 93 } 94 95 static 96 BOOL 97 IsFriendlyUIActive(VOID) 98 { 99 DWORD dwType, dwValue, dwSize; 100 HKEY hKey; 101 LONG lRet; 102 103 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 104 L"SYSTEM\\CurrentControlSet\\Control\\Windows", 105 0, 106 KEY_QUERY_VALUE, 107 &hKey); 108 if (lRet != ERROR_SUCCESS) 109 return FALSE; 110 111 /* CORE-17282 First check an optional ReactOS specific override, that Windows does not check. 112 We use this to allow users pairing 'Server'-configuration with FriendlyShutdown. 113 Otherwise users would have to change CSDVersion or LogonType (side-effects AppCompat) */ 114 dwValue = 0; 115 dwSize = sizeof(dwValue); 116 lRet = RegQueryValueExW(hKey, 117 L"EnforceFriendlyShutdown", 118 NULL, 119 &dwType, 120 (LPBYTE)&dwValue, 121 &dwSize); 122 123 if (lRet == ERROR_SUCCESS && dwType == REG_DWORD && dwValue == 0x1) 124 { 125 RegCloseKey(hKey); 126 return TRUE; 127 } 128 129 /* Check product version number */ 130 dwValue = 0; 131 dwSize = sizeof(dwValue); 132 lRet = RegQueryValueExW(hKey, 133 L"CSDVersion", 134 NULL, 135 &dwType, 136 (LPBYTE)&dwValue, 137 &dwSize); 138 RegCloseKey(hKey); 139 140 if (lRet != ERROR_SUCCESS || dwType != REG_DWORD || dwValue != 0x300) 141 { 142 /* Allow Friendly UI only on Workstation */ 143 return FALSE; 144 } 145 146 /* Check LogonType value */ 147 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 148 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 149 0, 150 KEY_QUERY_VALUE, 151 &hKey); 152 if (lRet != ERROR_SUCCESS) 153 return FALSE; 154 155 dwValue = 0; 156 dwSize = sizeof(dwValue); 157 lRet = RegQueryValueExW(hKey, 158 L"LogonType", 159 NULL, 160 &dwType, 161 (LPBYTE)&dwValue, 162 &dwSize); 163 RegCloseKey(hKey); 164 165 if (lRet != ERROR_SUCCESS || dwType != REG_DWORD) 166 return FALSE; 167 168 return (dwValue != 0); 169 } 170 171 static 172 BOOL 173 IsDomainMember(VOID) 174 { 175 UNIMPLEMENTED; 176 return FALSE; 177 } 178 179 static 180 BOOL 181 IsNetwareActive(VOID) 182 { 183 UNIMPLEMENTED; 184 return FALSE; 185 } 186 187 static 188 BOOL 189 ForceFriendlyUI(VOID) 190 { 191 DWORD dwType, dwValue, dwSize; 192 HKEY hKey; 193 LONG lRet; 194 195 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 196 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 197 0, 198 KEY_QUERY_VALUE, 199 &hKey); 200 if (lRet == ERROR_SUCCESS) 201 { 202 dwValue = 0; 203 dwSize = sizeof(dwValue); 204 lRet = RegQueryValueExW(hKey, 205 L"ForceFriendlyUI", 206 NULL, 207 &dwType, 208 (LPBYTE)&dwValue, 209 &dwSize); 210 RegCloseKey(hKey); 211 212 if (lRet == ERROR_SUCCESS && dwType == REG_DWORD) 213 return (dwValue != 0); 214 } 215 216 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 217 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 218 0, 219 KEY_QUERY_VALUE, 220 &hKey); 221 if (lRet == ERROR_SUCCESS) 222 { 223 dwValue = 0; 224 dwSize = sizeof(dwValue); 225 lRet = RegQueryValueExW(hKey, 226 L"ForceFriendlyUI", 227 NULL, 228 &dwType, 229 (LPBYTE)&dwValue, 230 &dwSize); 231 232 RegCloseKey(hKey); 233 234 if (lRet == ERROR_SUCCESS && dwType == REG_DWORD) 235 return (dwValue != 0); 236 } 237 238 return FALSE; 239 } 240 241 BOOL 242 WINAPI 243 ShellIsFriendlyUIActive(VOID) 244 { 245 BOOL bActive; 246 247 bActive = IsFriendlyUIActive(); 248 249 if ((IsDomainMember() || IsNetwareActive()) && !ForceFriendlyUI()) 250 return FALSE; 251 252 return bActive; 253 } 254 255 DWORD 256 GetDefaultShutdownSelState(VOID) 257 { 258 return WLX_SAS_ACTION_SHUTDOWN_POWER_OFF; 259 } 260 261 DWORD 262 LoadShutdownSelState(VOID) 263 { 264 LONG lRet; 265 HKEY hKeyCurrentUser, hKey; 266 DWORD dwValue, dwTemp, dwSize; 267 268 /* Default to shutdown */ 269 dwValue = WLX_SAS_ACTION_SHUTDOWN_POWER_OFF; 270 271 /* Open the current user HKCU key */ 272 lRet = RegOpenCurrentUser(MAXIMUM_ALLOWED, &hKeyCurrentUser); 273 if (lRet == ERROR_SUCCESS) 274 { 275 /* Open the subkey */ 276 lRet = RegOpenKeyExW(hKeyCurrentUser, 277 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer", 278 0, KEY_QUERY_VALUE, &hKey); 279 RegCloseKey(hKeyCurrentUser); 280 } 281 if (lRet != ERROR_SUCCESS) 282 return dwValue; 283 284 /* Read the value */ 285 dwSize = sizeof(dwTemp); 286 lRet = RegQueryValueExW(hKey, 287 L"Shutdown Setting", 288 NULL, NULL, 289 (LPBYTE)&dwTemp, &dwSize); 290 RegCloseKey(hKey); 291 292 if (lRet == ERROR_SUCCESS) 293 { 294 switch (dwTemp) 295 { 296 case WLX_SHUTDOWN_STATE_LOGOFF: 297 dwValue = WLX_SAS_ACTION_LOGOFF; 298 break; 299 300 case WLX_SHUTDOWN_STATE_POWER_OFF: 301 dwValue = WLX_SAS_ACTION_SHUTDOWN_POWER_OFF; 302 break; 303 304 case WLX_SHUTDOWN_STATE_REBOOT: 305 dwValue = WLX_SAS_ACTION_SHUTDOWN_REBOOT; 306 break; 307 308 // 0x08 309 310 case WLX_SHUTDOWN_STATE_SLEEP: 311 dwValue = WLX_SAS_ACTION_SHUTDOWN_SLEEP; 312 break; 313 314 // 0x20 315 316 case WLX_SHUTDOWN_STATE_HIBERNATE: 317 dwValue = WLX_SAS_ACTION_SHUTDOWN_HIBERNATE; 318 break; 319 320 // 0x80 321 } 322 } 323 324 return dwValue; 325 } 326 327 VOID 328 SaveShutdownSelState( 329 IN DWORD ShutdownCode) 330 { 331 LONG lRet; 332 HKEY hKeyCurrentUser, hKey; 333 DWORD dwValue = 0; 334 335 /* Open the current user HKCU key */ 336 lRet = RegOpenCurrentUser(MAXIMUM_ALLOWED, &hKeyCurrentUser); 337 if (lRet == ERROR_SUCCESS) 338 { 339 /* Create the subkey */ 340 lRet = RegCreateKeyExW(hKeyCurrentUser, 341 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer", 342 0, NULL, 343 REG_OPTION_NON_VOLATILE, 344 KEY_SET_VALUE, 345 NULL, &hKey, NULL); 346 RegCloseKey(hKeyCurrentUser); 347 } 348 if (lRet != ERROR_SUCCESS) 349 return; 350 351 switch (ShutdownCode) 352 { 353 case WLX_SAS_ACTION_LOGOFF: 354 dwValue = WLX_SHUTDOWN_STATE_LOGOFF; 355 break; 356 357 case WLX_SAS_ACTION_SHUTDOWN_POWER_OFF: 358 dwValue = WLX_SHUTDOWN_STATE_POWER_OFF; 359 break; 360 361 case WLX_SAS_ACTION_SHUTDOWN_REBOOT: 362 dwValue = WLX_SHUTDOWN_STATE_REBOOT; 363 break; 364 365 case WLX_SAS_ACTION_SHUTDOWN_SLEEP: 366 dwValue = WLX_SHUTDOWN_STATE_SLEEP; 367 break; 368 369 case WLX_SAS_ACTION_SHUTDOWN_HIBERNATE: 370 dwValue = WLX_SHUTDOWN_STATE_HIBERNATE; 371 break; 372 } 373 374 RegSetValueExW(hKey, 375 L"Shutdown Setting", 376 0, REG_DWORD, 377 (LPBYTE)&dwValue, sizeof(dwValue)); 378 RegCloseKey(hKey); 379 } 380 381 DWORD 382 GetDefaultShutdownOptions(VOID) 383 { 384 return WLX_SHUTDOWN_STATE_POWER_OFF | WLX_SHUTDOWN_STATE_REBOOT; 385 } 386 387 DWORD 388 GetAllowedShutdownOptions(VOID) 389 { 390 DWORD Options = 0; 391 392 // FIXME: Compute those options accordings to current user's rights! 393 Options |= WLX_SHUTDOWN_STATE_LOGOFF | WLX_SHUTDOWN_STATE_POWER_OFF | WLX_SHUTDOWN_STATE_REBOOT; 394 395 if (IsPwrSuspendAllowed()) 396 Options |= WLX_SHUTDOWN_STATE_SLEEP; 397 398 if (IsPwrHibernateAllowed()) 399 Options |= WLX_SHUTDOWN_STATE_HIBERNATE; 400 401 return Options; 402 } 403 404 static VOID 405 UpdateShutdownDesc( 406 IN HWND hDlg, 407 IN PSHUTDOWN_DLG_CONTEXT pContext) // HINSTANCE hInstance 408 { 409 UINT DescId = 0; 410 DWORD ShutdownCode; 411 WCHAR szBuffer[256]; 412 413 ShutdownCode = SendDlgItemMessageW(hDlg, IDC_SHUTDOWN_ACTION, CB_GETCURSEL, 0, 0); 414 if (ShutdownCode == CB_ERR) // Invalid selection 415 return; 416 417 ShutdownCode = SendDlgItemMessageW(hDlg, IDC_SHUTDOWN_ACTION, CB_GETITEMDATA, ShutdownCode, 0); 418 419 switch (ShutdownCode) 420 { 421 case WLX_SAS_ACTION_LOGOFF: 422 DescId = IDS_SHUTDOWN_LOGOFF_DESC; 423 break; 424 425 case WLX_SAS_ACTION_SHUTDOWN_POWER_OFF: 426 DescId = IDS_SHUTDOWN_SHUTDOWN_DESC; 427 break; 428 429 case WLX_SAS_ACTION_SHUTDOWN_REBOOT: 430 DescId = IDS_SHUTDOWN_RESTART_DESC; 431 break; 432 433 case WLX_SAS_ACTION_SHUTDOWN_SLEEP: 434 DescId = IDS_SHUTDOWN_SLEEP_DESC; 435 break; 436 437 case WLX_SAS_ACTION_SHUTDOWN_HIBERNATE: 438 DescId = IDS_SHUTDOWN_HIBERNATE_DESC; 439 break; 440 441 default: 442 break; 443 } 444 445 LoadStringW(pContext->pgContext->hDllInstance, DescId, szBuffer, _countof(szBuffer)); 446 SetDlgItemTextW(hDlg, IDC_SHUTDOWN_DESCRIPTION, szBuffer); 447 448 if (pContext->bReasonUI) 449 { 450 EnableWindow(GetDlgItem(hDlg, IDC_REASON_PLANNED), (ShutdownCode != WLX_SAS_ACTION_LOGOFF)); 451 EnableWindow(GetDlgItem(hDlg, IDC_REASON_LIST), (ShutdownCode != WLX_SAS_ACTION_LOGOFF)); 452 EnableWindow(GetDlgItem(hDlg, IDC_REASON_COMMENT), (ShutdownCode != WLX_SAS_ACTION_LOGOFF)); 453 } 454 } 455 456 static VOID 457 ShutdownOnInit( 458 IN HWND hDlg, 459 IN PSHUTDOWN_DLG_CONTEXT pContext) 460 { 461 PGINA_CONTEXT pgContext = pContext->pgContext; 462 HWND hwndList; 463 INT idx, count, i; 464 WCHAR szBuffer[256]; 465 WCHAR szBuffer2[256]; 466 467 hwndList = GetDlgItem(hDlg, IDC_SHUTDOWN_ACTION); 468 469 /* Clear the content before it's used */ 470 SendMessageW(hwndList, CB_RESETCONTENT, 0, 0); 471 472 /* Log off */ 473 if (pContext->ShutdownOptions & WLX_SHUTDOWN_STATE_LOGOFF) 474 { 475 LoadStringW(pgContext->hDllInstance, IDS_SHUTDOWN_LOGOFF, szBuffer, _countof(szBuffer)); 476 StringCchPrintfW(szBuffer2, _countof(szBuffer2), szBuffer, pgContext->UserName); 477 idx = SendMessageW(hwndList, CB_ADDSTRING, 0, (LPARAM)szBuffer2); 478 if (idx != CB_ERR) 479 SendMessageW(hwndList, CB_SETITEMDATA, idx, WLX_SAS_ACTION_LOGOFF); 480 } 481 482 /* Shut down - DEFAULT */ 483 if (pContext->ShutdownOptions & WLX_SHUTDOWN_STATE_POWER_OFF) 484 { 485 LoadStringW(pgContext->hDllInstance, IDS_SHUTDOWN_SHUTDOWN, szBuffer, _countof(szBuffer)); 486 idx = SendMessageW(hwndList, CB_ADDSTRING, 0, (LPARAM)szBuffer); 487 if (idx != CB_ERR) 488 SendMessageW(hwndList, CB_SETITEMDATA, idx, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF); 489 } 490 else if (pContext->bFriendlyUI) 491 { 492 EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_SHUTDOWN), FALSE); 493 } 494 495 /* Restart */ 496 if (pContext->ShutdownOptions & WLX_SHUTDOWN_STATE_REBOOT) 497 { 498 LoadStringW(pgContext->hDllInstance, IDS_SHUTDOWN_RESTART, szBuffer, _countof(szBuffer)); 499 idx = SendMessageW(hwndList, CB_ADDSTRING, 0, (LPARAM)szBuffer); 500 if (idx != CB_ERR) 501 SendMessageW(hwndList, CB_SETITEMDATA, idx, WLX_SAS_ACTION_SHUTDOWN_REBOOT); 502 } 503 else if (pContext->bFriendlyUI) 504 { 505 EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_REBOOT), FALSE); 506 } 507 508 // if (pContext->ShutdownOptions & 0x08) {} 509 510 /* Sleep */ 511 if (pContext->ShutdownOptions & WLX_SHUTDOWN_STATE_SLEEP) 512 { 513 LoadStringW(pgContext->hDllInstance, IDS_SHUTDOWN_SLEEP, szBuffer, _countof(szBuffer)); 514 idx = SendMessageW(hwndList, CB_ADDSTRING, 0, (LPARAM)szBuffer); 515 if (idx != CB_ERR) 516 SendMessageW(hwndList, CB_SETITEMDATA, idx, WLX_SAS_ACTION_SHUTDOWN_SLEEP); 517 } 518 else if (pContext->bFriendlyUI) 519 { 520 EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_SLEEP), FALSE); 521 } 522 523 // if (pContext->ShutdownOptions & 0x20) {} 524 525 /* Hibernate */ 526 if (pContext->ShutdownOptions & WLX_SHUTDOWN_STATE_HIBERNATE) 527 { 528 LoadStringW(pgContext->hDllInstance, IDS_SHUTDOWN_HIBERNATE, szBuffer, _countof(szBuffer)); 529 idx = SendMessageW(hwndList, CB_ADDSTRING, 0, (LPARAM)szBuffer); 530 if (idx != CB_ERR) 531 SendMessageW(hwndList, CB_SETITEMDATA, idx, WLX_SAS_ACTION_SHUTDOWN_HIBERNATE); 532 } 533 534 // if (pContext->ShutdownOptions & 0x80) {} 535 536 /* Set the default shut down selection */ 537 count = SendMessageW(hwndList, CB_GETCOUNT, 0, 0); 538 for (i = 0; i < count; i++) 539 { 540 if (SendMessageW(hwndList, CB_GETITEMDATA, i, 0) == pgContext->nShutdownAction) 541 { 542 SendMessageW(hwndList, CB_SETCURSEL, i, 0); 543 break; 544 } 545 } 546 547 /* Update the choice description based on the current selection */ 548 UpdateShutdownDesc(hDlg, pContext); 549 } 550 551 static VOID 552 ShutdownOnOk( 553 IN HWND hDlg, 554 IN PGINA_CONTEXT pgContext) 555 { 556 INT idx; 557 558 idx = SendDlgItemMessageW(hDlg, 559 IDC_SHUTDOWN_ACTION, 560 CB_GETCURSEL, 561 0, 562 0); 563 if (idx != CB_ERR) 564 { 565 pgContext->nShutdownAction = 566 SendDlgItemMessageW(hDlg, 567 IDC_SHUTDOWN_ACTION, 568 CB_GETITEMDATA, 569 idx, 570 0); 571 } 572 } 573 574 static INT_PTR 575 CALLBACK 576 ShutdownDialogProc( 577 HWND hDlg, 578 UINT uMsg, 579 WPARAM wParam, 580 LPARAM lParam) 581 { 582 PSHUTDOWN_DLG_CONTEXT pContext; 583 584 pContext = (PSHUTDOWN_DLG_CONTEXT)GetWindowLongPtrW(hDlg, GWLP_USERDATA); 585 586 switch (uMsg) 587 { 588 case WM_INITDIALOG: 589 { 590 pContext = (PSHUTDOWN_DLG_CONTEXT)lParam; 591 SetWindowLongPtrW(hDlg, GWLP_USERDATA, (LONG_PTR)pContext); 592 593 ShutdownOnInit(hDlg, pContext); 594 595 /* Draw the logo bitmap */ 596 pContext->hBitmap = 597 LoadImageW(pContext->pgContext->hDllInstance, MAKEINTRESOURCEW(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); 598 return TRUE; 599 } 600 601 case WM_DESTROY: 602 DeleteObject(pContext->hBitmap); 603 return TRUE; 604 605 case WM_ACTIVATE: 606 { 607 /* 608 * If the user deactivates the shutdown dialog (it loses its focus 609 * while the dialog is not being closed), then destroy the dialog 610 * and cancel shutdown. 611 */ 612 if (LOWORD(wParam) == WA_INACTIVE) 613 { 614 if (!pContext->bCloseDlg) 615 { 616 pContext->bCloseDlg = TRUE; 617 EndDialog(hDlg, 0); 618 } 619 } 620 return FALSE; 621 } 622 623 case WM_PAINT: 624 { 625 PAINTSTRUCT ps; 626 if (pContext->hBitmap) 627 { 628 BeginPaint(hDlg, &ps); 629 DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP); 630 EndPaint(hDlg, &ps); 631 } 632 return TRUE; 633 } 634 635 case WM_CLOSE: 636 pContext->bCloseDlg = TRUE; 637 EndDialog(hDlg, IDCANCEL); 638 break; 639 640 case WM_COMMAND: 641 switch (LOWORD(wParam)) 642 { 643 case IDC_BUTTON_SHUTDOWN: 644 ExitWindowsEx(EWX_SHUTDOWN, SHTDN_REASON_MAJOR_OTHER); 645 break; 646 647 case IDC_BUTTON_REBOOT: 648 ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_MAJOR_OTHER); 649 break; 650 651 case IDC_BUTTON_SLEEP: 652 SetSuspendState(TRUE, TRUE, TRUE); 653 break; 654 655 case IDOK: 656 ShutdownOnOk(hDlg, pContext->pgContext); 657 658 /* Fall back */ 659 case IDCANCEL: 660 case IDHELP: 661 pContext->bCloseDlg = TRUE; 662 EndDialog(hDlg, LOWORD(wParam)); 663 break; 664 665 case IDC_SHUTDOWN_ACTION: 666 UpdateShutdownDesc(hDlg, pContext); 667 break; 668 } 669 break; 670 671 default: 672 return FALSE; 673 } 674 return TRUE; 675 } 676 677 INT_PTR 678 ShutdownDialog( 679 IN HWND hwndDlg, 680 IN DWORD ShutdownOptions, 681 IN PGINA_CONTEXT pgContext) 682 { 683 INT_PTR ret; 684 SHUTDOWN_DLG_CONTEXT Context; 685 DWORD ShutdownDialogId = IDD_SHUTDOWN; 686 687 #if 0 688 DWORD ShutdownOptions; 689 690 // FIXME: User impersonation!! 691 pgContext->nShutdownAction = LoadShutdownSelState(); 692 ShutdownOptions = GetAllowedShutdownOptions(); 693 #endif 694 695 Context.pgContext = pgContext; 696 Context.ShutdownOptions = ShutdownOptions; 697 Context.bCloseDlg = FALSE; 698 Context.bReasonUI = GetShutdownReasonUI(); 699 Context.bFriendlyUI = ShellIsFriendlyUIActive(); 700 701 if (pgContext->hWlx && pgContext->pWlxFuncs && !Context.bFriendlyUI) 702 { 703 ret = pgContext->pWlxFuncs->WlxDialogBoxParam(pgContext->hWlx, 704 pgContext->hDllInstance, 705 MAKEINTRESOURCEW(Context.bReasonUI ? IDD_SHUTDOWN_REASON : IDD_SHUTDOWN), 706 hwndDlg, 707 ShutdownDialogProc, 708 (LPARAM)&Context); 709 } 710 else 711 { 712 if (Context.bFriendlyUI) 713 { 714 ShutdownDialogId = IDD_SHUTDOWN_FANCY; 715 } 716 717 ret = DialogBoxParamW(pgContext->hDllInstance, 718 MAKEINTRESOURCEW(Context.bReasonUI ? IDD_SHUTDOWN_REASON : ShutdownDialogId), 719 hwndDlg, 720 ShutdownDialogProc, 721 (LPARAM)&Context); 722 } 723 724 #if 0 725 // FIXME: User impersonation!! 726 if (ret == IDOK) 727 SaveShutdownSelState(pgContext->nShutdownAction); 728 #endif 729 730 return ret; 731 } 732 733 734 /* 735 * NOTES: 736 * - Based upon observations on the ShellShutdownDialog() function, the function doesn't actually 737 * do anything except show a dialog box and returning a value based upon the value chosen. That 738 * means that any code that calls the function has to execute the chosen action (shut down, 739 * restart, etc.). 740 * - When this function is called in Windows XP, it shows the classic dialog box regardless if 741 * SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\LogonType is enabled or not. 742 * - When the Help button is pushed, it sends the same return value as IDCANCEL (0x00), but 743 * at the same time, it calls the help file directly from the dialog box. 744 * - When the dialog is created, it doesn't disable all other input from the other windows. 745 * This is done elsewhere. When running the function ShellShutdownDialog() from XP/2K3, if the user clicks 746 * out of the window, it automatically closes itself. 747 * - The parameter, lpUsername never seems to be used when calling the function from Windows XP. Either 748 * it was a parameter that was never used in the final version before release, or it has a use that 749 * is currently not known. 750 */ 751 DWORD WINAPI 752 ShellShutdownDialog( 753 HWND hParent, 754 LPWSTR lpUsername, 755 BOOL bHideLogoff) 756 { 757 INT_PTR dlgValue; 758 DWORD ShutdownOptions; 759 760 /* 761 * As we are called by the shell itself, don't use 762 * the cached GINA context but use a local copy here. 763 */ 764 GINA_CONTEXT gContext = { 0 }; 765 DWORD BufferSize; 766 767 UNREFERENCED_PARAMETER(lpUsername); 768 769 ShutdownOptions = GetAllowedShutdownOptions(); 770 if (bHideLogoff) 771 ShutdownOptions &= ~WLX_SHUTDOWN_STATE_LOGOFF; 772 773 /* Initialize our local GINA context */ 774 gContext.hDllInstance = hDllInstance; 775 BufferSize = _countof(gContext.UserName); 776 // NOTE: Only when this function is called, Win checks inside 777 // HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer", 778 // value "Logon User Name", and determines whether it will display 779 // the user name. 780 GetUserNameW(gContext.UserName, &BufferSize); 781 gContext.nShutdownAction = LoadShutdownSelState(); 782 783 /* Load the shutdown dialog box */ 784 dlgValue = ShutdownDialog(hParent, ShutdownOptions, &gContext); 785 786 /* Determine what to do based on user selection */ 787 if (dlgValue == IDOK) 788 { 789 SaveShutdownSelState(gContext.nShutdownAction); 790 791 switch (gContext.nShutdownAction) 792 { 793 case WLX_SAS_ACTION_LOGOFF: 794 return WLX_SHUTDOWN_STATE_LOGOFF; 795 796 case WLX_SAS_ACTION_SHUTDOWN_POWER_OFF: 797 return WLX_SHUTDOWN_STATE_POWER_OFF; 798 799 case WLX_SAS_ACTION_SHUTDOWN_REBOOT: 800 return WLX_SHUTDOWN_STATE_REBOOT; 801 802 // 0x08 803 804 case WLX_SAS_ACTION_SHUTDOWN_SLEEP: 805 return WLX_SHUTDOWN_STATE_SLEEP; 806 807 // 0x20 808 809 case WLX_SAS_ACTION_SHUTDOWN_HIBERNATE: 810 return WLX_SHUTDOWN_STATE_HIBERNATE; 811 812 // 0x80 813 } 814 } 815 /* Help file is called directly here */ 816 else if (dlgValue == IDHELP) 817 { 818 FIXME("Help is not implemented yet."); 819 MessageBoxW(hParent, L"Help is not implemented yet.", L"Message", MB_OK | MB_ICONEXCLAMATION); 820 } 821 else if (dlgValue == -1) 822 { 823 ERR("Failed to create dialog\n"); 824 } 825 826 return 0; 827 } 828