From 79e4efe04e2b00ae6fbae09657264a2ff23c3655 Mon Sep 17 00:00:00 2001 From: Arnav Bhatt Date: Fri, 14 Jul 2023 12:02:40 +0000 Subject: [PATCH] [MSGINA] Convert shutdown/logoff boxes back to modal dialog boxes (#5114) - Convert all modeless dialog boxes back to modal dialog boxes. - Use WM_TIMER to detect SHIFT key press instead, as you can't directly intercept messages on modal dialog boxes. - Remove some unused functions. Fixes explorer crash on shutdown cancel. CORE-17749 --- dll/win32/msgina/resource.h | 16 +- dll/win32/msgina/shutdown.c | 395 +++++++++----------------- dll/win32/shell32/dialogs/dialogs.cpp | 134 +++++---- 3 files changed, 212 insertions(+), 333 deletions(-) diff --git a/dll/win32/msgina/resource.h b/dll/win32/msgina/resource.h index 7116ab5cbac..5020c6dfb7d 100644 --- a/dll/win32/msgina/resource.h +++ b/dll/win32/msgina/resource.h @@ -58,10 +58,10 @@ #define IDC_SHUTDOWN_STATIC 3004 #define IDC_RESTART_STATIC 3005 -#define IDC_BUTTON_HIBERNATE 1901 -#define IDC_BUTTON_SLEEP 1902 -#define IDC_BUTTON_SHUTDOWN 1903 -#define IDC_BUTTON_REBOOT 1904 +#define IDC_BUTTON_SHUTDOWN 1901 +#define IDC_BUTTON_REBOOT 1902 +#define IDC_BUTTON_SLEEP 1903 +#define IDC_BUTTON_HIBERNATE 1904 #define IDD_LEGALNOTICE 2100 #define IDC_LEGALNOTICE_TEXT 2101 @@ -111,14 +111,14 @@ #define IDS_INVALIDWORKSTATION 40023 #define IDS_ACCOUNTRESTRICTION 40024 -#define IDS_SHUTDOWN_SHUTDOWN 50000 -#define IDS_SHUTDOWN_LOGOFF 50001 +#define IDS_SHUTDOWN_LOGOFF 50000 +#define IDS_SHUTDOWN_SHUTDOWN 50001 #define IDS_SHUTDOWN_RESTART 50002 #define IDS_SHUTDOWN_SLEEP 50003 #define IDS_SHUTDOWN_HIBERNATE 50004 /* Shut down descriptions */ -#define IDS_SHUTDOWN_SHUTDOWN_DESC 50005 -#define IDS_SHUTDOWN_LOGOFF_DESC 50006 +#define IDS_SHUTDOWN_LOGOFF_DESC 50005 +#define IDS_SHUTDOWN_SHUTDOWN_DESC 50006 #define IDS_SHUTDOWN_RESTART_DESC 50007 #define IDS_SHUTDOWN_SLEEP_DESC 50008 #define IDS_SHUTDOWN_HIBERNATE_DESC 50009 diff --git a/dll/win32/msgina/shutdown.c b/dll/win32/msgina/shutdown.c index 559b6c5b243..f2f5f3c2a01 100644 --- a/dll/win32/msgina/shutdown.c +++ b/dll/win32/msgina/shutdown.c @@ -48,11 +48,18 @@ #define BUTTON_SLEEP_FOCUSED (CY_BITMAP + BUTTON_SLEEP_PRESSED) #define BUTTON_SLEEP_DISABLED (CY_BITMAP + BUTTON_SLEEP_FOCUSED) +/* For bIsButtonHot */ +#define SHUTDOWN_BUTTON_HOT 0 +#define REBOOT_BUTTON_HOT 1 +#define SLEEP_BUTTON_HOT 2 +#define HIBERNATE_BUTTON_HOT 3 + typedef struct _SHUTDOWN_DLG_CONTEXT { PGINA_CONTEXT pgContext; HBITMAP hBitmap; HBITMAP hImageStrip; + DWORD ShutdownDialogId; DWORD ShutdownOptions; HBRUSH hBrush; HFONT hfFont; @@ -61,7 +68,8 @@ typedef struct _SHUTDOWN_DLG_CONTEXT BOOL bReasonUI; BOOL bFriendlyUI; BOOL bIsButtonHot[NUMBER_OF_BUTTONS]; - BOOL bIsDialogModal; + BOOL bTimer; + UINT_PTR iTimer; WNDPROC OldButtonProc; } SHUTDOWN_DLG_CONTEXT, *PSHUTDOWN_DLG_CONTEXT; @@ -333,7 +341,7 @@ DrawIconOnOwnerDrawnButtons( { y = BUTTON_SHUTDOWN_PRESSED; } - else if (pContext->bIsButtonHot[0] || (pdis->itemState & ODS_FOCUS)) + else if (pContext->bIsButtonHot[SHUTDOWN_BUTTON_HOT] || (pdis->itemState & ODS_FOCUS)) { y = BUTTON_SHUTDOWN_FOCUSED; } @@ -356,7 +364,7 @@ DrawIconOnOwnerDrawnButtons( { y = BUTTON_REBOOT_PRESSED; } - else if (pContext->bIsButtonHot[1] || (pdis->itemState & ODS_FOCUS)) + else if (pContext->bIsButtonHot[REBOOT_BUTTON_HOT] || (pdis->itemState & ODS_FOCUS)) { y = BUTTON_REBOOT_FOCUSED; } @@ -384,8 +392,8 @@ DrawIconOnOwnerDrawnButtons( { y = BUTTON_SLEEP_PRESSED; } - else if ((pdis->CtlID == IDC_BUTTON_SLEEP && pContext->bIsButtonHot[2]) || - (pdis->CtlID == IDC_BUTTON_HIBERNATE && pContext->bIsButtonHot[3]) || + else if ((pdis->CtlID == IDC_BUTTON_SLEEP && pContext->bIsButtonHot[SLEEP_BUTTON_HOT]) || + (pdis->CtlID == IDC_BUTTON_HIBERNATE && pContext->bIsButtonHot[HIBERNATE_BUTTON_HOT]) || (pdis->itemState & ODS_FOCUS)) { y = BUTTON_SLEEP_FOCUSED; @@ -504,8 +512,7 @@ OwnerDrawButtonSubclass( LPARAM lParam) { PSHUTDOWN_DLG_CONTEXT pContext; - pContext = (PSHUTDOWN_DLG_CONTEXT)GetWindowLongPtrW(hButton, GWLP_USERDATA); - + pContext = (PSHUTDOWN_DLG_CONTEXT)GetWindowLongPtrW(GetParent(hButton), GWLP_USERDATA); int buttonID = GetDlgCtrlID(hButton); switch (uMsg) @@ -520,19 +527,19 @@ OwnerDrawButtonSubclass( SetCapture(hButton); if (buttonID == IDC_BUTTON_SHUTDOWN) { - pContext->bIsButtonHot[0] = TRUE; + pContext->bIsButtonHot[SHUTDOWN_BUTTON_HOT] = TRUE; } else if (buttonID == IDC_BUTTON_REBOOT) { - pContext->bIsButtonHot[1] = TRUE; + pContext->bIsButtonHot[REBOOT_BUTTON_HOT] = TRUE; } else if (buttonID == IDC_BUTTON_SLEEP) { - pContext->bIsButtonHot[2] = TRUE; + pContext->bIsButtonHot[SLEEP_BUTTON_HOT] = TRUE; } else if (buttonID == IDC_BUTTON_HIBERNATE) { - pContext->bIsButtonHot[3] = TRUE; + pContext->bIsButtonHot[HIBERNATE_BUTTON_HOT] = TRUE; } SetCursor(LoadCursorW(NULL, MAKEINTRESOURCEW(IDC_HAND))); } @@ -545,19 +552,19 @@ OwnerDrawButtonSubclass( ReleaseCapture(); if (buttonID == IDC_BUTTON_SHUTDOWN) { - pContext->bIsButtonHot[0] = FALSE; + pContext->bIsButtonHot[SHUTDOWN_BUTTON_HOT] = FALSE; } else if (buttonID == IDC_BUTTON_REBOOT) { - pContext->bIsButtonHot[1] = FALSE; + pContext->bIsButtonHot[REBOOT_BUTTON_HOT] = FALSE; } else if (buttonID == IDC_BUTTON_SLEEP) { - pContext->bIsButtonHot[2] = FALSE; + pContext->bIsButtonHot[SLEEP_BUTTON_HOT] = FALSE; } else if (buttonID == IDC_BUTTON_HIBERNATE) { - pContext->bIsButtonHot[3] = FALSE; + pContext->bIsButtonHot[HIBERNATE_BUTTON_HOT] = FALSE; } } InvalidateRect(hButton, NULL, FALSE); @@ -581,26 +588,6 @@ OwnerDrawButtonSubclass( return CallWindowProcW(pContext->OldButtonProc, hButton, uMsg, wParam, lParam); } -VOID -AddPrefixToStaticTexts( - HWND hDlg, - BOOL bIsSleepButtonReplaced) -{ - WCHAR szBuffer[30]; - - for (int i = 0; i < NUMBER_OF_BUTTONS; i++) - { - GetDlgItemTextW(hDlg, IDC_BUTTON_HIBERNATE + i, szBuffer, _countof(szBuffer)); - SetDlgItemTextW(hDlg, IDC_HIBERNATE_STATIC + i, szBuffer); - } - - if (bIsSleepButtonReplaced) - { - GetDlgItemTextW(hDlg, IDC_BUTTON_HIBERNATE, szBuffer, _countof(szBuffer)); - SetDlgItemTextW(hDlg, IDC_SLEEP_STATIC, szBuffer); - } -} - VOID CreateToolTipForButtons( int controlID, @@ -637,11 +624,33 @@ CreateToolTipForButtons( } VOID -ReplaceRequiredButton( +EndFriendlyDialog( HWND hDlg, - HINSTANCE hInstance, - BOOL bIsAltKeyPressed, - BOOL bIsSleepButtonReplaced) + PSHUTDOWN_DLG_CONTEXT pContext) +{ + if (pContext->bTimer) + { + KillTimer(hDlg, pContext->iTimer); + } + + DeleteObject(pContext->hBitmap); + DeleteObject(pContext->hBrush); + DeleteObject(pContext->hImageStrip); + DeleteObject(pContext->hfFont); + + /* Remove the subclass from the buttons */ + for (int i = 0; i < NUMBER_OF_BUTTONS; i++) + { + SetWindowLongPtrW(GetDlgItem(hDlg, IDC_BUTTON_SHUTDOWN + i), + GWLP_WNDPROC, + (LONG_PTR)pContext->OldButtonProc); + } +} + +VOID +ChangeRequiredButton( + HWND hDlg, + PSHUTDOWN_DLG_CONTEXT pContext) { int destID = IDC_BUTTON_SLEEP; int targetedID = IDC_BUTTON_HIBERNATE; @@ -650,7 +659,7 @@ ReplaceRequiredButton( WCHAR szBuffer[30]; /* If the sleep button has been already replaced earlier, bring sleep button back to its original position */ - if (bIsSleepButtonReplaced) + if (pContext->bIsSleepButtonReplaced) { destID = IDC_BUTTON_HIBERNATE; targetedID = IDC_BUTTON_SLEEP; @@ -678,31 +687,35 @@ ReplaceRequiredButton( ShowWindow(hwndTarget, SW_SHOW); SetFocus(hwndTarget); - if (bIsAltKeyPressed) + if (!pContext->bIsSleepButtonReplaced) { - if (!bIsSleepButtonReplaced) - { - GetDlgItemTextW(hDlg, IDC_BUTTON_HIBERNATE, szBuffer, _countof(szBuffer)); - SetDlgItemTextW(hDlg, IDC_SLEEP_STATIC, szBuffer); - } - else - { - GetDlgItemTextW(hDlg, IDC_BUTTON_SLEEP, szBuffer, _countof(szBuffer)); - SetDlgItemTextW(hDlg, IDC_SLEEP_STATIC, szBuffer); - } + LoadStringW(pContext->pgContext->hDllInstance, IDS_SHUTDOWN_HIBERNATE, szBuffer, _countof(szBuffer)); + SetDlgItemTextW(hDlg, IDC_SLEEP_STATIC, szBuffer); } else { - if (!bIsSleepButtonReplaced) - { - LoadStringW(hInstance, IDS_SHUTDOWN_HIBERNATE, szBuffer, _countof(szBuffer)); - SetDlgItemTextW(hDlg, IDC_SLEEP_STATIC, szBuffer); - } - else - { - LoadStringW(hInstance, IDS_SHUTDOWN_SLEEP, szBuffer, _countof(szBuffer)); - SetDlgItemTextW(hDlg, IDC_SLEEP_STATIC, szBuffer); - } + LoadStringW(pContext->pgContext->hDllInstance, IDS_SHUTDOWN_SLEEP, szBuffer, _countof(szBuffer)); + SetDlgItemTextW(hDlg, IDC_SLEEP_STATIC, szBuffer); + } + + InvalidateRect(hDlg, NULL, FALSE); +} + +VOID OnTimer( + HWND hDlg, + PSHUTDOWN_DLG_CONTEXT pContext) +{ + BOOL ReplaceButton = !!(GetKeyState(VK_SHIFT) & 0x8000); + + if (ReplaceButton && !pContext->bIsSleepButtonReplaced) + { + ChangeRequiredButton(hDlg, pContext); + pContext->bIsSleepButtonReplaced = TRUE; + } + else if (!ReplaceButton && pContext->bIsSleepButtonReplaced) + { + ChangeRequiredButton(hDlg, pContext); + pContext->bIsSleepButtonReplaced = FALSE; } } @@ -836,15 +849,11 @@ UpdateShutdownDesc( } static VOID -ShutdownOnInit( +ShutdownOnFriendlyInit( IN HWND hDlg, IN PSHUTDOWN_DLG_CONTEXT pContext) { PGINA_CONTEXT pgContext = pContext->pgContext; - HWND hwndList; - INT idx, count, i; - WCHAR szBuffer[256]; - WCHAR szBuffer2[256]; HDC hdc; LONG lfHeight; @@ -858,21 +867,61 @@ ShutdownOnInit( /* Create a brush for static controls for fancy shut down dialog */ pContext->hBrush = CreateSolidBrush(DARK_GREY_COLOR); + /* Gather image strip */ pContext->hImageStrip = LoadBitmapW(pgContext->hDllInstance, MAKEINTRESOURCEW(IDB_IMAGE_STRIP)); + /* Set the boolean flags to false */ + pContext->bIsSleepButtonReplaced = FALSE; + pContext->bTimer = FALSE; + + EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_HIBERNATE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_SLEEP), IsPwrSuspendAllowed()); + + /* Gather old button func */ + pContext->OldButtonProc = (WNDPROC)GetWindowLongPtrW(GetDlgItem(hDlg, IDC_BUTTON_HIBERNATE), GWLP_WNDPROC); + + /* Set bIsButtonHot to false, create tooltips for each buttons, make buttons to remember pContext and subclass the buttons */ + for (int i = 0; i < NUMBER_OF_BUTTONS; i++) + { + pContext->bIsButtonHot[i] = FALSE; + SetWindowLongPtrW(GetDlgItem(hDlg, IDC_BUTTON_SHUTDOWN + i), + GWLP_WNDPROC, + (LONG_PTR)OwnerDrawButtonSubclass); + CreateToolTipForButtons(IDC_BUTTON_SHUTDOWN + i, + IDS_SHUTDOWN_SHUTDOWN_DESC + i, + hDlg, IDS_SHUTDOWN_SHUTDOWN + i, + pContext->pgContext->hDllInstance); + } + + if (pContext->ShutdownDialogId == IDD_SHUTDOWN_FANCY && IsPwrSuspendAllowed()) + { + pContext->iTimer = SetTimer(hDlg, 0, 50, NULL); + pContext->bTimer = TRUE; + } +} + +static VOID +ShutdownOnInit( + IN HWND hDlg, + IN PSHUTDOWN_DLG_CONTEXT pContext) +{ + PGINA_CONTEXT pgContext = pContext->pgContext; + HWND hwndList; + INT idx, count, i; + WCHAR szBuffer[256]; + WCHAR szBuffer2[256]; + + if (pContext->bFriendlyUI) + { + ShutdownOnFriendlyInit(hDlg, pContext); + return; + } + hwndList = GetDlgItem(hDlg, IDC_SHUTDOWN_ACTION); /* Clear the content before it's used */ SendMessageW(hwndList, CB_RESETCONTENT, 0, 0); - /* Set the boolean flags to false */ - pContext->bIsSleepButtonReplaced = FALSE; - - for (int i = 0; i < NUMBER_OF_BUTTONS; i++) - { - pContext->bIsButtonHot[i] = FALSE; - } - /* Log off */ if (pContext->ShutdownOptions & WLX_SHUTDOWN_STATE_LOGOFF) { @@ -891,10 +940,6 @@ ShutdownOnInit( if (idx != CB_ERR) SendMessageW(hwndList, CB_SETITEMDATA, idx, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF); } - else if (pContext->bFriendlyUI) - { - EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_SHUTDOWN), FALSE); - } /* Restart */ if (pContext->ShutdownOptions & WLX_SHUTDOWN_STATE_REBOOT) @@ -904,10 +949,6 @@ ShutdownOnInit( if (idx != CB_ERR) SendMessageW(hwndList, CB_SETITEMDATA, idx, WLX_SAS_ACTION_SHUTDOWN_REBOOT); } - else if (pContext->bFriendlyUI) - { - EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_REBOOT), FALSE); - } // if (pContext->ShutdownOptions & 0x08) {} @@ -919,10 +960,6 @@ ShutdownOnInit( if (idx != CB_ERR) SendMessageW(hwndList, CB_SETITEMDATA, idx, WLX_SAS_ACTION_SHUTDOWN_SLEEP); } - else if (pContext->bFriendlyUI) - { - EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_SLEEP), IsPwrSuspendAllowed()); - } // if (pContext->ShutdownOptions & 0x20) {} @@ -934,10 +971,6 @@ ShutdownOnInit( if (idx != CB_ERR) SendMessageW(hwndList, CB_SETITEMDATA, idx, WLX_SAS_ACTION_SHUTDOWN_HIBERNATE); } - else if (pContext->bFriendlyUI) - { - EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_HIBERNATE), FALSE); - } // if (pContext->ShutdownOptions & 0x80) {} @@ -952,34 +985,6 @@ ShutdownOnInit( } } - /* Create tool tips for the buttons of fancy log off dialog */ - CreateToolTipForButtons(IDC_BUTTON_HIBERNATE, - IDS_SHUTDOWN_HIBERNATE_DESC, - hDlg, IDS_SHUTDOWN_HIBERNATE, - pContext->pgContext->hDllInstance); - CreateToolTipForButtons(IDC_BUTTON_SHUTDOWN, - IDS_SHUTDOWN_SHUTDOWN_DESC, - hDlg, IDS_SHUTDOWN_SHUTDOWN, - pContext->pgContext->hDllInstance); - CreateToolTipForButtons(IDC_BUTTON_REBOOT, - IDS_SHUTDOWN_RESTART_DESC, - hDlg, IDS_SHUTDOWN_RESTART, - pContext->pgContext->hDllInstance); - CreateToolTipForButtons(IDC_BUTTON_SLEEP, - IDS_SHUTDOWN_SLEEP_DESC, - hDlg, IDS_SHUTDOWN_SLEEP, - pContext->pgContext->hDllInstance); - - /* Gather old button func */ - pContext->OldButtonProc = (WNDPROC)GetWindowLongPtrW(GetDlgItem(hDlg, IDC_BUTTON_HIBERNATE), GWLP_WNDPROC); - - /* Make buttons to remember pContext and subclass the buttons */ - for (int i = 0; i < NUMBER_OF_BUTTONS; i++) - { - SetWindowLongPtrW(GetDlgItem(hDlg, IDC_BUTTON_HIBERNATE + i), GWLP_USERDATA, (LONG_PTR)pContext); - SetWindowLongPtrW(GetDlgItem(hDlg, IDC_BUTTON_HIBERNATE + i), GWLP_WNDPROC, (LONG_PTR)OwnerDrawButtonSubclass); - } - /* Update the choice description based on the current selection */ UpdateShutdownDesc(hDlg, pContext); } @@ -1027,23 +1032,13 @@ ShutdownDialogProc( SetWindowLongPtrW(hDlg, GWLP_USERDATA, (LONG_PTR)pContext); ShutdownOnInit(hDlg, pContext); - - /* Draw the logo bitmap */ - pContext->hBitmap = - LoadImageW(pContext->pgContext->hDllInstance, MAKEINTRESOURCEW(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); return TRUE; } case WM_DESTROY: - DeleteObject(pContext->hBitmap); - DeleteObject(pContext->hBrush); - DeleteObject(pContext->hImageStrip); - DeleteObject(pContext->hfFont); - - /* Remove the subclass from the buttons */ - for (int i = 0; i < NUMBER_OF_BUTTONS; i++) + if (pContext->bFriendlyUI) { - SetWindowLongPtrW(GetDlgItem(hDlg, IDC_BUTTON_HIBERNATE + i), GWLP_WNDPROC, (LONG_PTR)pContext->OldButtonProc); + EndFriendlyDialog(hDlg, pContext); } return TRUE; @@ -1059,45 +1054,15 @@ ShutdownDialogProc( if (!pContext->bCloseDlg) { pContext->bCloseDlg = TRUE; - - if (pContext->bIsDialogModal) - { - EndDialog(hDlg, 0); - } - else - { - DestroyWindow(hDlg); - PostQuitMessage(0); - } + EndDialog(hDlg, IDCANCEL); } } return FALSE; } - case WM_PAINT: - { - PAINTSTRUCT ps; - if (pContext->hBitmap) - { - BeginPaint(hDlg, &ps); - DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP); - EndPaint(hDlg, &ps); - } - return TRUE; - } - case WM_CLOSE: pContext->bCloseDlg = TRUE; - - if (pContext->bIsDialogModal) - { - EndDialog(hDlg, IDCANCEL); - } - else - { - DestroyWindow(hDlg); - PostQuitMessage(IDCANCEL); - } + EndDialog(hDlg, IDCANCEL); break; case WM_COMMAND: @@ -1122,16 +1087,7 @@ ShutdownDialogProc( case IDCANCEL: case IDHELP: pContext->bCloseDlg = TRUE; - - if (pContext->bIsDialogModal) - { - EndDialog(hDlg, LOWORD(wParam)); - } - else - { - DestroyWindow(hDlg); - PostQuitMessage(LOWORD(wParam)); - } + EndDialog(hDlg, LOWORD(wParam)); break; case IDC_SHUTDOWN_ACTION: @@ -1179,6 +1135,10 @@ ShutdownDialogProc( break; } + case WM_TIMER: + OnTimer(hDlg, pContext); + return TRUE; + default: return FALSE; } @@ -1193,10 +1153,6 @@ ShutdownDialog( { INT_PTR ret; SHUTDOWN_DLG_CONTEXT Context; - BOOL bIsAltKeyPressed = FALSE; - DWORD ShutdownDialogId = IDD_SHUTDOWN; - MSG Msg; - HWND hDlg; #if 0 DWORD ShutdownOptions; @@ -1208,13 +1164,13 @@ ShutdownDialog( Context.pgContext = pgContext; Context.ShutdownOptions = ShutdownOptions; + Context.ShutdownDialogId = IDD_SHUTDOWN; Context.bCloseDlg = FALSE; Context.bReasonUI = GetShutdownReasonUI(); Context.bFriendlyUI = ShellIsFriendlyUIActive(); if (pgContext->hWlx && pgContext->pWlxFuncs && !Context.bFriendlyUI) { - Context.bIsDialogModal = TRUE; ret = pgContext->pWlxFuncs->WlxDialogBoxParam(pgContext->hWlx, pgContext->hDllInstance, MAKEINTRESOURCEW(Context.bReasonUI ? IDD_SHUTDOWN_REASON : IDD_SHUTDOWN), @@ -1228,90 +1184,19 @@ ShutdownDialog( { if (IsShowHibernateButtonActive()) { - ShutdownDialogId = IDD_SHUTDOWN_FANCY_LONG; + Context.ShutdownDialogId = IDD_SHUTDOWN_FANCY_LONG; } else { - ShutdownDialogId = IDD_SHUTDOWN_FANCY; + Context.ShutdownDialogId = IDD_SHUTDOWN_FANCY; } } - Context.bIsDialogModal = FALSE; - hDlg = CreateDialogParamW(pgContext->hDllInstance, - MAKEINTRESOURCEW(Context.bReasonUI ? IDD_SHUTDOWN_REASON : ShutdownDialogId), - hwndDlg, - ShutdownDialogProc, - (LPARAM)&Context); - - ShowWindow(hDlg, SW_SHOW); - - /* Detect either Alt or Shift key have been pressed or released */ - while (GetMessageW(&Msg, NULL, 0, 0)) - { - if (!IsDialogMessageW(hDlg, &Msg)) - { - TranslateMessage(&Msg); - DispatchMessageW(&Msg); - } - - switch (Msg.message) - { - case WM_SYSKEYDOWN: - { - /* If the Alt key has been pressed once, add prefix to static controls */ - if (Msg.wParam == VK_MENU && !bIsAltKeyPressed) - { - AddPrefixToStaticTexts(hDlg, Context.bIsSleepButtonReplaced); - bIsAltKeyPressed = TRUE; - } - } - break; - - case WM_KEYDOWN: - { - /* - * If the Shift key has been pressed once, and both hibernate button and sleep button are enabled - * replace the sleep button with hibernate button - */ - if (Msg.wParam == VK_SHIFT) - { - if (ShutdownDialogId == IDD_SHUTDOWN_FANCY && !Context.bIsSleepButtonReplaced) - { - if (IsPwrHibernateAllowed() && IsPwrSuspendAllowed()) - { - ReplaceRequiredButton(hDlg, - pgContext->hDllInstance, - bIsAltKeyPressed, - Context.bIsSleepButtonReplaced); - Context.bIsSleepButtonReplaced = TRUE; - } - } - } - } - break; - - case WM_KEYUP: - { - /* If the Shift key has been released after being pressed, replace the hibernate button with sleep button again */ - if (Msg.wParam == VK_SHIFT) - { - if (ShutdownDialogId == IDD_SHUTDOWN_FANCY && Context.bIsSleepButtonReplaced) - { - if (IsPwrHibernateAllowed() && IsPwrSuspendAllowed()) - { - ReplaceRequiredButton(hDlg, - pgContext->hDllInstance, - bIsAltKeyPressed, - Context.bIsSleepButtonReplaced); - Context.bIsSleepButtonReplaced = FALSE; - } - } - } - } - break; - } - } - ret = Msg.wParam; + ret = DialogBoxParamW(pgContext->hDllInstance, + MAKEINTRESOURCEW(Context.bReasonUI ? IDD_SHUTDOWN_REASON : Context.ShutdownDialogId), + hwndDlg, + ShutdownDialogProc, + (LPARAM)&Context); } #if 0 diff --git a/dll/win32/shell32/dialogs/dialogs.cpp b/dll/win32/shell32/dialogs/dialogs.cpp index 4b05a92ef31..f2ee6aa2278 100644 --- a/dll/win32/shell32/dialogs/dialogs.cpp +++ b/dll/win32/shell32/dialogs/dialogs.cpp @@ -1124,6 +1124,10 @@ int WINAPI RestartDialogEx(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, D #define BUTTON_LOG_OFF_FOCUSED (CY_BITMAP + BUTTON_LOG_OFF_PRESSED) #define BUTTON_SWITCH_USER_DISABLED (CY_BITMAP + BUTTON_LOG_OFF_FOCUSED) // Temporary +/* For bIsButtonHot */ +#define LOG_OFF_BUTTON_HOT 0 +#define SWITCH_USER_BUTTON_HOT 1 + BOOL DrawIconOnOwnerDrawnButtons(DRAWITEMSTRUCT* pdis, PLOGOFF_DLG_CONTEXT pContext) { BOOL bRet = FALSE; @@ -1152,7 +1156,7 @@ BOOL DrawIconOnOwnerDrawnButtons(DRAWITEMSTRUCT* pdis, PLOGOFF_DLG_CONTEXT pCont { y = BUTTON_LOG_OFF_PRESSED; } - else if (pContext->bIsButtonHot[0] || (pdis->itemState & ODS_FOCUS)) + else if (pContext->bIsButtonHot[LOG_OFF_BUTTON_HOT] || (pdis->itemState & ODS_FOCUS)) { y = BUTTON_LOG_OFF_FOCUSED; } @@ -1175,7 +1179,7 @@ BOOL DrawIconOnOwnerDrawnButtons(DRAWITEMSTRUCT* pdis, PLOGOFF_DLG_CONTEXT pCont { y = BUTTON_SWITCH_USER_PRESSED; } - else if (pContext->bIsButtonHot[1] || (pdis->itemState & ODS_FOCUS)) + else if (pContext->bIsButtonHot[SWITCH_USER_BUTTON_HOT] || (pdis->itemState & ODS_FOCUS)) { y = BUTTON_SWITCH_USER_FOCUSED; } @@ -1210,7 +1214,7 @@ BOOL DrawIconOnOwnerDrawnButtons(DRAWITEMSTRUCT* pdis, PLOGOFF_DLG_CONTEXT pCont INT_PTR CALLBACK OwnerDrawButtonSubclass(HWND hButton, UINT uMsg, WPARAM wParam, LPARAM lParam) { PLOGOFF_DLG_CONTEXT pContext; - pContext = (PLOGOFF_DLG_CONTEXT)GetWindowLongPtrW(hButton, GWLP_USERDATA); + pContext = (PLOGOFF_DLG_CONTEXT)GetWindowLongPtrW(GetParent(hButton), GWLP_USERDATA); int buttonID = GetDlgCtrlID(hButton); @@ -1224,13 +1228,19 @@ INT_PTR CALLBACK OwnerDrawButtonSubclass(HWND hButton, UINT uMsg, WPARAM wParam, if (GetCapture() != hButton) { SetCapture(hButton); - if (buttonID == IDC_LOG_OFF_BUTTON) + + switch (buttonID) { - pContext->bIsButtonHot[0] = TRUE; - } - else if (buttonID == IDC_SWITCH_USER_BUTTON) - { - pContext->bIsButtonHot[1] = TRUE; + case IDC_LOG_OFF_BUTTON: + { + pContext->bIsButtonHot[LOG_OFF_BUTTON_HOT] = TRUE; + break; + } + case IDC_SWITCH_USER_BUTTON: + { + pContext->bIsButtonHot[SWITCH_USER_BUTTON_HOT] = TRUE; + break; + } } SetCursor(LoadCursorW(NULL, MAKEINTRESOURCEW(IDC_HAND))); } @@ -1241,13 +1251,19 @@ INT_PTR CALLBACK OwnerDrawButtonSubclass(HWND hButton, UINT uMsg, WPARAM wParam, if (hwndTarget != hButton) { ReleaseCapture(); - if (buttonID == IDC_LOG_OFF_BUTTON) + + switch (buttonID) { - pContext->bIsButtonHot[0] = FALSE; - } - else if (buttonID == IDC_SWITCH_USER_BUTTON) - { - pContext->bIsButtonHot[1] = FALSE; + case IDC_LOG_OFF_BUTTON: + { + pContext->bIsButtonHot[LOG_OFF_BUTTON_HOT] = FALSE; + break; + } + case IDC_SWITCH_USER_BUTTON: + { + pContext->bIsButtonHot[SWITCH_USER_BUTTON_HOT] = FALSE; + break; + } } } InvalidateRect(hButton, NULL, FALSE); @@ -1300,6 +1316,21 @@ VOID CreateToolTipForButtons(int controlID, int detailID, HWND hDlg, int titleID SendMessageW(hwndTip, TTM_SETMAXTIPWIDTH, 0, 250); } +VOID EndFriendlyDialog(HWND hwnd, PLOGOFF_DLG_CONTEXT pContext) +{ + DeleteObject(pContext->hBrush); + DeleteObject(pContext->hImageStrip); + DeleteObject(pContext->hfFont); + + /* Remove the subclass from the buttons */ + for (int i = 0; i < NUMBER_OF_BUTTONS; i++) + { + SetWindowLongPtrW(GetDlgItem(hwnd, IDC_LOG_OFF_BUTTON + i), + GWLP_WNDPROC, + (LONG_PTR)pContext->OldButtonProc); + } +} + static BOOL IsFriendlyUIActive(VOID) { DWORD dwType = 0, dwValue = 0, dwSize = 0; @@ -1389,18 +1420,20 @@ static VOID FancyLogoffOnInit(HWND hwnd, PLOGOFF_DLG_CONTEXT pContext) pContext->hImageStrip = LoadBitmapW(shell32_hInstance, MAKEINTRESOURCEW(IDB_IMAGE_STRIP)); - CreateToolTipForButtons(IDC_LOG_OFF_BUTTON, IDS_LOG_OFF_DESC, hwnd, IDS_LOG_OFF_TITLE); - CreateToolTipForButtons(IDC_SWITCH_USER_BUTTON, IDS_SWITCH_USER_DESC, hwnd, IDS_SWITCH_USER_TITLE); - /* Gather old button func */ pContext->OldButtonProc = (WNDPROC)GetWindowLongPtrW(GetDlgItem(hwnd, IDC_LOG_OFF_BUTTON), GWLP_WNDPROC); - /* Make buttons to remember pContext and subclass the buttons as well as set bIsButtonHot boolean flags to false */ + /* Set bIsButtonHot to false, create tooltips for each buttons and subclass the buttons */ for (int i = 0; i < NUMBER_OF_BUTTONS; i++) { pContext->bIsButtonHot[i] = FALSE; - SetWindowLongPtrW(GetDlgItem(hwnd, IDC_LOG_OFF_BUTTON + i), GWLP_USERDATA, (LONG_PTR)pContext); - SetWindowLongPtrW(GetDlgItem(hwnd, IDC_LOG_OFF_BUTTON + i), GWLP_WNDPROC, (LONG_PTR)OwnerDrawButtonSubclass); + SetWindowLongPtrW(GetDlgItem(hwnd, IDC_LOG_OFF_BUTTON + i), + GWLP_WNDPROC, + (LONG_PTR)OwnerDrawButtonSubclass); + CreateToolTipForButtons(IDC_LOG_OFF_BUTTON + i, + IDS_LOG_OFF_DESC + i, + hwnd, + IDS_LOG_OFF_TITLE + i); } } @@ -1428,8 +1461,7 @@ INT_PTR CALLBACK LogOffDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP } case WM_CLOSE: - DestroyWindow(hwnd); - PostQuitMessage(IDCANCEL); + EndDialog(hwnd, IDCANCEL); break; /* @@ -1441,8 +1473,7 @@ INT_PTR CALLBACK LogOffDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP { if (LOWORD(wParam) == WA_INACTIVE) { - DestroyWindow(hwnd); - PostQuitMessage(0); + EndDialog(hwnd, IDCANCEL); } return FALSE; } @@ -1456,22 +1487,14 @@ INT_PTR CALLBACK LogOffDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP break; case IDCANCEL: - DestroyWindow(hwnd); - PostQuitMessage(IDCANCEL); + EndDialog(hwnd, IDCANCEL); break; } break; case WM_DESTROY: - DeleteObject(pContext->hBrush); - DeleteObject(pContext->hImageStrip); - DeleteObject(pContext->hfFont); - - /* Remove the subclass from the buttons */ - for (int i = 0; i < NUMBER_OF_BUTTONS; i++) - { - SetWindowLongPtrW(GetDlgItem(hwnd, IDC_LOG_OFF_BUTTON + i), GWLP_WNDPROC, (LONG_PTR)pContext->OldButtonProc); - } + if (pContext->bFriendlyUI) + EndFriendlyDialog(hwnd, pContext); return TRUE; case WM_CTLCOLORSTATIC: @@ -1522,11 +1545,7 @@ INT_PTR CALLBACK LogOffDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP EXTERN_C int WINAPI LogoffWindowsDialog(HWND hWndOwner) { CComPtr fadeHandler; - BOOL bIsAltKeyPressed = FALSE; - MSG Msg; HWND parent = NULL; - HWND hWndChild = NULL; - WCHAR szBuffer[30]; DWORD LogoffDialogID = IDD_LOG_OFF; LOGOFF_DLG_CONTEXT Context; @@ -1539,36 +1558,11 @@ EXTERN_C int WINAPI LogoffWindowsDialog(HWND hWndOwner) LogoffDialogID = IDD_LOG_OFF_FANCY; } - hWndChild = CreateDialogParamW(shell32_hInstance, MAKEINTRESOURCEW(LogoffDialogID), parent, LogOffDialogProc, (LPARAM)&Context); - ShowWindow(hWndChild, SW_SHOWNORMAL); - - /* Detect either Alt key has been pressed */ - while (GetMessageW(&Msg, NULL, 0, 0)) - { - if(!IsDialogMessageW(hWndChild, &Msg)) - { - TranslateMessage(&Msg); - DispatchMessageW(&Msg); - } - - switch (Msg.message) - { - case WM_SYSKEYDOWN: - { - /* If the Alt key has been pressed once, add prefix to static controls */ - if (Msg.wParam == VK_MENU && !bIsAltKeyPressed && Context.bFriendlyUI) - { - for (int i = 0; i < NUMBER_OF_BUTTONS; i++) - { - GetDlgItemTextW(hWndChild, IDC_LOG_OFF_BUTTON + i, szBuffer, _countof(szBuffer)); - SetDlgItemTextW(hWndChild, IDC_LOG_OFF_STATIC + i, szBuffer); - } - bIsAltKeyPressed = TRUE; - } - } - break; - } - } + DialogBoxParamW(shell32_hInstance, + MAKEINTRESOURCEW(LogoffDialogID), + parent, + LogOffDialogProc, + (LPARAM)&Context); return 0; }