From eec8c9770838a2699ac76dcd2d9225d1303f39d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 14 May 2026 20:50:23 +0200 Subject: [PATCH] [USERINIT] In LiveCD/"MiniNT" mode, start the shell with a suitable environment block Using `userenv!CreateEnvironmentBlock()` when starting the shell ensures that, even if it's started as LocalSystem, its environment inherits the "dynamical" environment variables created by SMSS at runtime (stored in `HKLM\SYSTEM\CurrentControlSet\Session Manager\Environment`). In ReactOS/Windows PE "MiniNT" mode, the Winlogon environment doesn't contain these values, and doesn't start the Setup with this augmented environment. (This is compatible with what Windows does, on WinPE or during a clean installation.) Winlogon creates an augmented environment only when a user logs in and starts its shell (standard boot), which isn't the case in "MiniNT" mode. It is thus the responsibility of the module that starts the shell instead to do it: in ReactOS' case, userinit.exe in LiveCD mode. As a result, we get access to the `COMPUTERNAME`, `NUMBER_OF_PROCESSORS`, `OS`, and `PROCESSOR_*` environment variables, amongst others. --- base/system/userinit/CMakeLists.txt | 2 +- base/system/userinit/userinit.c | 36 +++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/base/system/userinit/CMakeLists.txt b/base/system/userinit/CMakeLists.txt index b168b4bd61c..d459cee4c2e 100644 --- a/base/system/userinit/CMakeLists.txt +++ b/base/system/userinit/CMakeLists.txt @@ -7,6 +7,6 @@ list(APPEND SOURCE add_executable(userinit ${SOURCE} userinit.rc) target_link_libraries(userinit wine) set_module_type(userinit win32gui UNICODE) -add_importlibs(userinit advapi32 gdi32 user32 msvcrt kernel32 ntdll) +add_importlibs(userinit advapi32 userenv gdi32 user32 msvcrt kernel32 ntdll) add_pch(userinit userinit.h SOURCE) add_cd_file(TARGET userinit DESTINATION reactos/system32 FOR all) diff --git a/base/system/userinit/userinit.c b/base/system/userinit/userinit.c index 91c99704d7c..b6a67c9409c 100644 --- a/base/system/userinit/userinit.c +++ b/base/system/userinit/userinit.c @@ -25,6 +25,7 @@ */ #include "userinit.h" +#include #define CMP_MAGIC 0x01234567 @@ -178,7 +179,8 @@ GetShell( static BOOL StartProcess( - IN LPCWSTR CommandLine) + _In_ PCWSTR CommandLine, + _In_opt_ PVOID pEnvironment) { STARTUPINFO si; PROCESS_INFORMATION pi; @@ -197,8 +199,8 @@ StartProcess( NULL, NULL, FALSE, - NORMAL_PRIORITY_CLASS, - NULL, + NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, + pEnvironment, NULL, &si, &pi)) @@ -213,7 +215,8 @@ StartProcess( } static BOOL -StartShell(VOID) +StartShell( + _In_opt_ PVOID pEnvironment) { DWORD Type, Size; DWORD Value = 0; @@ -257,7 +260,7 @@ StartShell(VOID) TRACE("Key located - %s\n", debugstr_w(Shell)); /* Try to run alternate shell */ - if (StartProcess(Shell)) + if (StartProcess(Shell, pEnvironment)) { TRACE("Alternate shell started (Safe Mode)\n"); return TRUE; @@ -284,14 +287,14 @@ StartShell(VOID) } /* Try to run shell in user key */ - if (GetShell(Shell, HKEY_CURRENT_USER) && StartProcess(Shell)) + if (GetShell(Shell, HKEY_CURRENT_USER) && StartProcess(Shell, pEnvironment)) { TRACE("Started shell from HKEY_CURRENT_USER\n"); return TRUE; } /* Try to run shell in local machine key */ - if (GetShell(Shell, HKEY_LOCAL_MACHINE) && StartProcess(Shell)) + if (GetShell(Shell, HKEY_LOCAL_MACHINE) && StartProcess(Shell, pEnvironment)) { TRACE("Started shell from HKEY_LOCAL_MACHINE\n"); return TRUE; @@ -313,7 +316,7 @@ StartShell(VOID) StringCchCatW(Shell, ARRAYSIZE(Shell), L"explorer.exe"); } - if (StartProcess(Shell)) + if (StartProcess(Shell, pEnvironment)) return TRUE; /* We failed, display an error message and quit */ @@ -613,7 +616,7 @@ StartInstaller(IN LPCWSTR lpInstallerName) if (ExpandInstallerPath(lpInstallerName, Installer, ARRAYSIZE(Installer))) { /* We have found the installer */ - if (StartProcess(Installer)) + if (StartProcess(Installer, NULL)) return TRUE; } @@ -688,10 +691,23 @@ Restart: switch (State.Run) { case SHELL: - Success = StartShell(); + { + /* In LiveCD mode, create a suitable environment block for the + * shell; otherwise, use the current one (built by WinLogon) */ + PVOID pEnvironment = NULL; + if (bIsLiveCD && /* In LiveCD mode we run under the LocalSystem account */ + !CreateEnvironmentBlock(&pEnvironment, NULL, TRUE)) + { + WARN("CreateEnvironmentBlock() failed, fall back to default (error %lu)\n", + GetLastError()); + } + Success = StartShell(pEnvironment); + if (pEnvironment) + DestroyEnvironmentBlock(pEnvironment); if (Success) NotifyLogon(); break; + } case INSTALLER: Success = StartInstaller(L"reactos.exe");