[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
This commit is contained in:
Arnav Bhatt 2023-07-14 12:02:40 +00:00 committed by GitHub
parent 22ab8c812a
commit 79e4efe04e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 212 additions and 333 deletions

View file

@ -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

View file

@ -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

View file

@ -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<IUnknown> 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;
}