** WIP ** WINLOGON: Study check_setup handling

This commit is contained in:
Hermès Bélusca-Maïto 2024-03-25 15:35:22 +01:00
parent c5e918891b
commit afa515bfd0
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
4 changed files with 235 additions and 42 deletions

View file

@ -19,7 +19,6 @@
#include <mmsystem.h> #include <mmsystem.h>
#include <userenv.h> #include <userenv.h>
#include <ndk/setypes.h> #include <ndk/setypes.h>
#include <ndk/sefuncs.h>
/* GLOBALS ******************************************************************/ /* GLOBALS ******************************************************************/
@ -1313,18 +1312,17 @@ SASWindowProc(
} }
case WM_CREATE: case WM_CREATE:
{ {
/* Get the session pointer from the create data */ /* Get the session pointer from the create data and save it */
Session = (PWLSESSION)((LPCREATESTRUCT)lParam)->lpCreateParams; Session = (PWLSESSION)((LPCREATESTRUCT)lParam)->lpCreateParams;
/* Save the Session pointer */
SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)Session); SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)Session);
if (GetSetupType())
if (IsNonOOBESetup(g_setupType))
return TRUE; return TRUE;
return RegisterHotKeys(Session, hwndDlg); return RegisterHotKeys(Session, hwndDlg);
} }
case WM_DESTROY: case WM_DESTROY:
{ {
if (!GetSetupType()) if (!IsNonOOBESetup(g_setupType))
UnregisterHotKeys(Session, hwndDlg); UnregisterHotKeys(Session, hwndDlg);
return TRUE; return TRUE;
} }

View file

@ -9,31 +9,32 @@
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "winlogon.h" #include "winlogon.h"
#include <ndk/setypes.h>
SETUP_TYPE g_setupType = SetupType_None;
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
DWORD SETUP_TYPE
GetSetupType(VOID) GetSetupType(VOID)
{ {
DWORD dwError;
HKEY hKey; HKEY hKey;
DWORD dwError;
DWORD dwType; DWORD dwType;
DWORD dwSize; DWORD dwSize;
DWORD dwSetupType; DWORD dwSetupType;
TRACE("GetSetupType()\n");
/* Open key */ /* Open key */
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\Setup", L"SYSTEM\\Setup", // REGSTR_KEY_SYSTEM REGSTR_KEY_SETUP
0, 0,
KEY_QUERY_VALUE, KEY_QUERY_VALUE,
&hKey); &hKey);
if (dwError != ERROR_SUCCESS) if (dwError != ERROR_SUCCESS)
return 0; return 0;
/* Read key */ /* Read value */
dwSize = sizeof(DWORD); dwSize = sizeof(dwSetupType);
dwError = RegQueryValueExW(hKey, dwError = RegQueryValueExW(hKey,
L"SetupType", L"SetupType",
NULL, NULL,
@ -41,18 +42,108 @@ GetSetupType(VOID)
(LPBYTE)&dwSetupType, (LPBYTE)&dwSetupType,
&dwSize); &dwSize);
/* Close key, and check if returned values are correct */ /* Close key and check if returned values are correct */
RegCloseKey(hKey); RegCloseKey(hKey);
if (dwError != ERROR_SUCCESS || dwType != REG_DWORD || dwSize != sizeof(DWORD)) if (dwError != ERROR_SUCCESS || dwType != REG_DWORD || dwSize != sizeof(DWORD))
return 0; return 0;
TRACE("GetSetupType() returns %lu\n", dwSetupType); TRACE("GetSetupType() returns %lu\n", dwSetupType);
return dwSetupType; return (SETUP_TYPE)dwSetupType;
}
// Partially reverts commit c88c4b4ad (r28194)
static BOOL
SetSetupType(
_In_ DWORD dwSetupType)
{
HKEY hKey;
DWORD dwError;
/* Open key */
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\Setup",
0,
KEY_SET_VALUE,
&hKey);
if (dwError != ERROR_SUCCESS)
return FALSE;
/* Write value */
dwError = RegSetValueExW(hKey,
L"SetupType",
0,
REG_DWORD,
(LPBYTE)&dwSetupType,
sizeof(dwSetupType));
/* Close key and check for success */
RegCloseKey(hKey);
return (dwError == ERROR_SUCCESS);
}
static BOOL
IsSetupShutdownRequired(
_Out_ SHUTDOWN_ACTION* pShutdownAction)
{
HKEY hKey;
DWORD dwError;
DWORD dwType;
DWORD dwSize;
DWORD dwValue;
/* Open key */
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\Setup", // REGSTR_KEY_SYSTEM REGSTR_KEY_SETUP
0,
KEY_QUERY_VALUE | KEY_SET_VALUE,
&hKey);
if (dwError != ERROR_SUCCESS)
return FALSE;
/* Read value */
dwSize = sizeof(dwValue);
dwError = RegQueryValueExW(hKey,
L"SetupShutdownRequired",
NULL,
&dwType,
(LPBYTE)&dwValue,
&dwSize);
/* Close key and check if returned values are correct */
RegCloseKey(hKey);
if (dwError != ERROR_SUCCESS || dwType != REG_DWORD || dwSize != sizeof(DWORD))
return FALSE;
/* Delete the value */
RegDeleteValueW(hKey, L"SetupShutdownRequired");
TRACE("IsSetupShutdownRequired() returns %lu\n", dwValue);
*pShutdownAction = dwValue;
return TRUE;
}
// FIXME: Make the function generic -- see sas.c!HandleShutdown()
static VOID
DoSetupShutdown(
_In_ SHUTDOWN_ACTION Action)
{
BOOLEAN Old;
#if DBG
static const PCSTR s_pszShutdownAction[] =
{ "Shutting down", "Restarting", "Powering off"};
ERR("WL: %s NT...\n", s_pszShutdownAction[Action]);
#endif
RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
NtShutdownSystem(Action);
RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old);
ExitProcess(0);
} }
static static DWORD
DWORD
WINAPI WINAPI
RunSetupThreadProc( RunSetupThreadProc(
IN LPVOID lpParameter) IN LPVOID lpParameter)
@ -104,7 +195,7 @@ RunSetupThreadProc(
TRACE("Should run '%s' now\n", debugstr_w(CommandLine)); TRACE("Should run '%s' now\n", debugstr_w(CommandLine));
SwitchDesktop(WLSession->ApplicationDesktop); // SwitchDesktop(WLSession->ApplicationDesktop);
/* Start process */ /* Start process */
StartupInfo.cb = sizeof(StartupInfo); StartupInfo.cb = sizeof(StartupInfo);
@ -127,8 +218,8 @@ RunSetupThreadProc(
&ProcessInformation); &ProcessInformation);
if (!Result) if (!Result)
{ {
TRACE("Failed to run setup process\n"); ERR("Failed to run setup process '%s'\n", debugstr_w(CommandLine));
SwitchDesktop(WLSession->WinlogonDesktop); // SwitchDesktop(WLSession->WinlogonDesktop);
return FALSE; return FALSE;
} }
@ -141,29 +232,111 @@ RunSetupThreadProc(
CloseHandle(ProcessInformation.hThread); CloseHandle(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess); CloseHandle(ProcessInformation.hProcess);
// SwitchDesktop(WLSession->WinlogonDesktop); /* Reset the current setup type */
if (dwExitCode == 0)
SetSetupType(SetupType_None);
// // SwitchDesktop(WLSession->WinlogonDesktop);
TRACE("RunSetup() done\n"); TRACE("RunSetup() done\n");
return TRUE; return TRUE;
} }
static BOOL
BOOL
RunSetup(VOID) RunSetup(VOID)
{ {
HANDLE hThread; // HANDLE hThread;
SwitchDesktop(WLSession->ApplicationDesktop);
#if 0
hThread = CreateThread(NULL, hThread = CreateThread(NULL,
0, 0,
RunSetupThreadProc, RunSetupThreadProc,
NULL, NULL,
0, 0,
NULL); NULL);
if (hThread != NULL) if (hThread)
CloseHandle(hThread); #else
if (RunSetupThreadProc(NULL))
#endif
{
/* Message loop for the current thread */
/* Pump and dispatch any input events */
MSG msg;
// while (MsgWaitForMultipleObjects(1, &hThread, FALSE, INFINITE, QS_ALLINPUT))
// // if (dwRet == WAIT_OBJECT_0 + 1)
{
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
return hThread != NULL; // CloseHandle(hThread);
}
SwitchDesktop(WLSession->WinlogonDesktop);
// return (hThread != NULL);
return TRUE;
}
VOID
CheckForSetup(VOID)
{
TRACE("CheckForSetup() called\n");
/* Check for pending setup */
switch (g_setupType)
{
case SetupType_None:
/* Nothing to do */
break;
case SetupType_Full: case SetupType_Upgrade:
case SetupType_OOBE:
{
SHUTDOWN_ACTION shutdownAction = ShutdownReboot;
#if DBG
static const PCSTR pszSetupType[] =
{ "None", "", "OOBE", "Reserved", "Upgrade" };
TRACE("WL: %s%sSetup mode detected\n",
pszSetupType[g_setupType], pszSetupType[g_setupType][0] ? " " : "");
#endif
/*
* We currently support three types of setup actions:
*
* - Full setup or upgrade: run it and reboot when done
* or if the setup program crashed for whatever reason;
*
* - OOBE setup: run it, then check whether it requested
* a power action and initiate it if so, otherwise
* continue with regular logon.
*/
RunSetup();
/* Reboot only if needed */
if ((g_setupType == SetupType_Full) || (g_setupType == SetupType_Upgrade) ||
/*(g_setupType == SetupType_OOBE) &&*/IsSetupShutdownRequired(&shutdownAction))
{
DoSetupShutdown(shutdownAction);
}
break;
}
case SetupType_Reserved:
default:
/* Unknown setup type: ignore */
WARN("WL: Unknown Setup type %lu, ignored\n", g_setupType);
break;
}
} }
/* EOF */ /* EOF */

View file

@ -523,6 +523,11 @@ WinMain(
/* Init Notifications */ /* Init Notifications */
InitNotifications(); InitNotifications();
/* Check for pending setup: if so, run it and reboot when done */
__debugbreak();
g_setupType = GetSetupType();
// CheckForSetup();
/* Load and initialize gina */ /* Load and initialize gina */
if (!GinaInit(WLSession)) if (!GinaInit(WLSession))
{ {
@ -586,17 +591,20 @@ WinMain(
WLSession->LogonState = STATE_INIT; WLSession->LogonState = STATE_INIT;
RemoveStatusMessage(WLSession); RemoveStatusMessage(WLSession);
/* Check for pending setup */
if (GetSetupType() != 0) /* Check for pending setup: if so, run it and reboot when done */
{ __debugbreak();
/* Run setup and reboot when done */ // g_setupType = GetSetupType();
TRACE("WL: Setup mode detected\n"); /*****CheckForSetup();******/
RunSetup();
}
else /*
{ * Simulate an initial Ctrl-Alt-Del key press.
PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0); * FIXME: This should quite probably be done only if some registry
} * setting is set. However, since our current Ctrl-Alt-Del hotkey
* handling in Win32k is broken, we need to use this hack!
*/
// PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0);
(void)LoadLibraryW(L"sfc_os.dll"); (void)LoadLibraryW(L"sfc_os.dll");

View file

@ -361,11 +361,25 @@ AllowAccessOnSession(
_In_ PWLSESSION Session); _In_ PWLSESSION Session);
/* setup.c */ /* setup.c */
DWORD typedef enum _SETUP_TYPE
{
SetupType_None = 0,
SetupType_Full,
SetupType_OOBE,
SetupType_Reserved,
SetupType_Upgrade
} SETUP_TYPE, *PSETUP_TYPE;
extern SETUP_TYPE g_setupType;
#define IsNonOOBESetup(setupType) \
(((setupType) == SetupType_Full) || ((setupType) == SetupType_Upgrade))
SETUP_TYPE
GetSetupType(VOID); GetSetupType(VOID);
BOOL VOID
RunSetup(VOID); CheckForSetup(VOID);
/* shutdown.h */ /* shutdown.h */
DWORD DWORD