[MSGINA] Revisit WlxActivateUserShell(), add support for "Logon User Name" (#8370)

- Add SAL annotations;
- Avoid using hardcoded buffer sizes in function calls.

- If the start-application (Userinit) launched successfully, store
  in the logged-in user's Explorer key, value `"Logon User Name"`,
  the user name that was entered verbatim in the "Log On" dialog
  to log into the system. This value is used as a "convenience" to
  display the `"Log Off <username>"` item in the explorer's Start menu
  (see `explorer!util.cpp:GetCurrentLoggedOnUserName()`), and the
  corresponding item in the "Shut Down" dialog.

- utils.c: Introduce the `RegOpenLoggedOnHKCU()` helper, for opening
  the current logged-in user HKCU key.

  NOTE: Regarding the `.Default` registry key, see:
  https://devblogs.microsoft.com/oldnewthing/20070302-00/?p=27783
This commit is contained in:
Hermès Bélusca-Maïto
2025-08-29 18:34:07 +02:00
parent 55ed59c379
commit b306f46e5b
3 changed files with 114 additions and 27 deletions

View File

@@ -499,46 +499,46 @@ WlxStartApplication(
/*
* @implemented
*/
BOOL WINAPI
BOOL
WINAPI
WlxActivateUserShell(
PVOID pWlxContext,
PWSTR pszDesktopName,
PWSTR pszMprLogonScript,
PVOID pEnvironment)
_In_ PVOID pWlxContext,
_In_ PWSTR pszDesktopName,
_In_ PWSTR pszMprLogonScript,
_In_ PVOID pEnvironment)
{
HKEY hKey;
PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
HKEY hKey, hKeyCurrentUser;
DWORD BufSize, ValueType;
WCHAR pszUserInitApp[MAX_PATH + 1];
WCHAR pszExpUserInitApp[MAX_PATH];
DWORD len;
LONG rc;
BOOL ret;
WCHAR pszUserInitApp[MAX_PATH + 1];
WCHAR pszExpUserInitApp[MAX_PATH];
TRACE("WlxActivateUserShell()\n");
UNREFERENCED_PARAMETER(pszMprLogonScript);
/* Get the path of userinit */
rc = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
0,
KEY_QUERY_VALUE,
&hKey);
/* Get the path of Userinit */
rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
0,
KEY_QUERY_VALUE,
&hKey);
if (rc != ERROR_SUCCESS)
{
WARN("RegOpenKeyExW() failed with error %lu\n", rc);
return FALSE;
}
/* Query userinit application */
BufSize = sizeof(pszUserInitApp) - sizeof(UNICODE_NULL);
rc = RegQueryValueExW(
hKey,
L"Userinit",
NULL,
&ValueType,
(LPBYTE)pszUserInitApp,
&BufSize);
rc = RegQueryValueExW(hKey,
L"Userinit",
NULL,
&ValueType,
(PBYTE)pszUserInitApp,
&BufSize);
RegCloseKey(hKey);
if (rc != ERROR_SUCCESS || (ValueType != REG_SZ && ValueType != REG_EXPAND_SZ))
{
@@ -547,15 +547,52 @@ WlxActivateUserShell(
}
pszUserInitApp[MAX_PATH] = UNICODE_NULL;
len = ExpandEnvironmentStringsW(pszUserInitApp, pszExpUserInitApp, MAX_PATH);
if (len > MAX_PATH)
len = ExpandEnvironmentStringsW(pszUserInitApp, pszExpUserInitApp, _countof(pszExpUserInitApp));
if (len > _countof(pszExpUserInitApp))
{
WARN("ExpandEnvironmentStringsW() failed. Required size %lu\n", len);
return FALSE;
}
/* Start userinit app */
return WlxStartApplication(pWlxContext, pszDesktopName, pEnvironment, pszExpUserInitApp);
/* Start the Userinit application */
ret = WlxStartApplication(pWlxContext, pszDesktopName, pEnvironment, pszExpUserInitApp);
if (!ret)
return ret;
/* For convenience, store in the logged-in user's Explorer key, the user name
* that was entered verbatim in the "Log On" dialog to log into the system.
* This name may differ from the resulting user name used during authentication. */
/* Open the per-user registry key */
rc = RegOpenLoggedOnHKCU(pgContext->UserToken,
KEY_SET_VALUE,
&hKeyCurrentUser);
if (rc != ERROR_SUCCESS)
{
ERR("RegOpenLoggedOnHKCU() failed with error %ld\n", rc);
return ret;
}
/* Open the subkey and write the value */
rc = RegOpenKeyExW(hKeyCurrentUser,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
0,
KEY_SET_VALUE,
&hKey);
if (rc == ERROR_SUCCESS)
{
len = wcslen(pgContext->UserName) + 1;
RegSetValueExW(hKey,
L"Logon User Name",
0,
REG_SZ,
(PBYTE)pgContext->UserName,
len * sizeof(WCHAR));
RegCloseKey(hKey);
}
RegCloseKey(hKeyCurrentUser);
return ret;
}
/*

View File

@@ -146,6 +146,12 @@ ShutdownDialog(
/* utils.c */
LONG
RegOpenLoggedOnHKCU(
_In_opt_ HANDLE hUserToken,
_In_ REGSAM samDesired,
_Out_ PHKEY phkResult);
LONG
ReadRegSzValue(
_In_ HKEY hKey,

View File

@@ -9,6 +9,50 @@
#include "msgina.h"
/**
* @brief
* Opens and retrieves a handle to the HKEY_CURRENT_USER
* corresponding to the specified logged-on user.
*
* @param[in] hUserToken
* Optional handle to a primary or impersonation access token that represents
* a logged-on user. See @b ImpersonateLoggedOnUser() for more information.
* If NULL, opens the SYSTEM's HKEY_USERS\.Default (i.e. HKEY_USERS\S-1-5-18).
*
* @param[in] samDesired
* A mask (type: REGSAM or ACCESS_MASK) that specifies the desired access
* rights to the key. See @b RegOpenCurrentUser() for more information.
*
* @param[out] phkResult
* A pointer to a variable that receives a handle to the opened key.
* When the handle is no longer needed, close it with @b RegCloseKey().
**/
LONG
RegOpenLoggedOnHKCU(
_In_opt_ HANDLE hUserToken,
_In_ REGSAM samDesired,
_Out_ PHKEY phkResult)
{
LONG rc;
/* Impersonate the logged-on user if necessary */
if (hUserToken && !ImpersonateLoggedOnUser(hUserToken))
{
rc = GetLastError();
ERR("ImpersonateLoggedOnUser() failed with error %ld\n", rc);
return rc;
}
/* Open the logged-on user HKCU key */
rc = RegOpenCurrentUser(samDesired, phkResult);
/* Revert the impersonation */
if (hUserToken)
RevertToSelf();
return rc;
}
LONG
ReadRegSzValue(
_In_ HKEY hKey,