[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

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