Skip to content

Commit aa67222

Browse files
committed
[MSGINA] CreateProfile(): Fix initialization of some WLX_PROFILE_V2_0 members (reactos#8321)
The following members of the returned `WLX_PROFILE_V2_0` structure: `pszProfile`, `pszPolicy`, `pszNetworkDefaultUserProfile`, and `pszServerName`, have a specific meaning and are used when logging to (NT4, Active Directory...) domains. See the added code comments for details. In particular, `pszProfile` specifies the path to a *roaming* user profile[^1] on a domain server, if any. It **DOES NOT** specify the local `"C:\Documents and Settings"` path (got via `GetProfilesDirectoryW()`). Since we don't really support user login on domains, set these pointers to NULL. ---- Enabling UserEnv debug logging[^2] on Windows 2003, one can observe such following traces, for a `TestUser` roaming user profile: ``` USERENV(148.14c) 20:24:59:821 LoadUserProfile: Entering, hToken = <0x8bc>, lpProfileInfo = 0x6e5d8 USERENV(148.14c) 20:24:59:875 LoadUserProfile: lpProfileInfo->dwFlags = <0x0> USERENV(148.14c) 20:24:59:912 LoadUserProfile: lpProfileInfo->lpUserName = <TestUser> USERENV(148.14c) 20:24:59:966 LoadUserProfile: lpProfileInfo->lpProfilePath = <C:\Documents and Settings\TestUser_Roaming> USERENV(148.14c) 20:25:00:021 LoadUserProfile: lpProfileInfo->lpDefaultPath = <\\PC-H\netlogon\Default User> USERENV(148.14c) 20:25:00:075 LoadUserProfile: NULL server name ... USERENV(148.14c) 20:25:06:177 CopyProfileDirectoryEx: Found hive file NTUSER.DAT USERENV(148.14c) 20:25:06:395 ReconcileFile: C:\Documents and Settings\TestUser_Roaming\NTUSER.DAT ==> C:\Documents and Settings\TestUser\NTUSER.DAT [OK] ... ``` The `lpProfilePath` specifies a roaming profile directory (`"TestUser_Roaming"`) for a user named named `TestUser`, and UserEnv proceeds to image the roaming profile into the directory (`"TestUser"`) in the local computer. However, when the user has a local profile, the `lpProfilePath` is set to NULL in this case, and one observes instead: ``` USERENV(148.14c) 20:21:22:644 LoadUserProfile: NULL central profile path ``` ---- [^1]: The following links explain this, also demonstrating UserEnv debug logging: - https://web.archive.org/web/20130319204738/http://blogs.technet.com/b/askds/archive/2008/11/11/understanding-how-to-read-a-userenv-log-part-2.aspx - https://web.archive.org/web/20150405040409/http://blogs.technet.com/b/ad/archive/2007/08/20/tracking-user-environment-creation.aspx [^2]: For more details, see: https://www.betaarchive.com/wiki/index.php?title=Microsoft_KB_Archive/221833 (archived from: http://support.microsoft.com/kb/221833) UserEnv debug logging is achieved by adding a `REG_DWORD` value named `UserEnvDebugLevel` in the following registry sub-key: `HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon` with a non-zero value. To view the output in a debugger (e.g. WinDbg when kernel-debugging Windows), set the value to `0x00020002`.
1 parent 96249c1 commit aa67222

File tree

1 file changed

+71
-27
lines changed

1 file changed

+71
-27
lines changed

dll/win32/msgina/msgina.c

Lines changed: 71 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -835,19 +835,21 @@ CreateProfile(
835835
IN PWSTR Password)
836836
{
837837
PWLX_PROFILE_V2_0 pProfile = NULL;
838-
PWSTR pProfilePath = NULL;
839838
PWSTR pEnvironment = NULL;
840839
TOKEN_STATISTICS Stats;
841840
DWORD cbStats, cbSize;
842841
DWORD dwLength;
843-
BOOL bResult;
842+
#if 0
843+
BOOL bIsDomainLogon;
844+
WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH+1];
845+
#endif
844846

845847
/* Store the logon time in the context */
846848
GetLocalTime(&pgContext->LogonTime);
847849

848850
/* Store user and domain in the context */
849851
wcscpy(pgContext->UserName, UserName);
850-
if (Domain == NULL || wcslen(Domain) == 0)
852+
if (Domain == NULL || !Domain[0])
851853
{
852854
dwLength = _countof(pgContext->DomainName);
853855
GetComputerNameW(pgContext->DomainName, &dwLength);
@@ -856,25 +858,17 @@ CreateProfile(
856858
{
857859
wcscpy(pgContext->DomainName, Domain);
858860
}
861+
/* From now on we use in UserName and Domain the captured values from pgContext */
862+
UserName = pgContext->UserName;
863+
Domain = pgContext->DomainName;
859864

860-
/* Get profile path */
861-
cbSize = 0;
862-
bResult = GetProfilesDirectoryW(NULL, &cbSize);
863-
if (!bResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
864-
{
865-
pProfilePath = LocalAlloc(LMEM_FIXED, cbSize * sizeof(WCHAR));
866-
if (!pProfilePath)
867-
{
868-
WARN("LocalAlloc() failed\n");
869-
goto cleanup;
870-
}
871-
bResult = GetProfilesDirectoryW(pProfilePath, &cbSize);
872-
}
873-
if (!bResult)
874-
{
875-
WARN("GetUserProfileDirectoryW() failed\n");
876-
goto cleanup;
877-
}
865+
#if 0
866+
/* Determine whether this is really a domain logon, by verifying
867+
* that the specified domain is different from the local computer */
868+
dwLength = _countof(ComputerName);
869+
GetComputerNameW(ComputerName, &dwLength);
870+
bIsDomainLogon = (_wcsicmp(ComputerName, Domain) != 0);
871+
#endif
878872

879873
/* Allocate memory for profile */
880874
pProfile = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(*pProfile));
@@ -884,10 +878,61 @@ CreateProfile(
884878
goto cleanup;
885879
}
886880
pProfile->dwType = WLX_PROFILE_TYPE_V2_0;
887-
pProfile->pszProfile = pProfilePath;
888881

882+
/*
883+
* TODO: For domain logon support:
884+
*
885+
* - pszProfile: Specifies the path to a *roaming* user profile on a
886+
* domain server, if any. It is then used to create a local image
887+
* (copy) of the profile on the local computer.
888+
* ** This data should be retrieved from the LsaLogonUser() call
889+
* made by MyLogonUser()! **
890+
*
891+
* - pszPolicy (for domain logon): Path to a policy file.
892+
* Windows' msgina.dll hardcodes it as:
893+
* "\\<domain_controller>\netlogon\ntconfig.pol"
894+
*
895+
* - pszNetworkDefaultUserProfile (for domain logon): Path to the
896+
* default user profile. Windows' msgina.dll hardcodes it as:
897+
* "\\<domain_controller>\netlogon\Default User"
898+
*
899+
* - pszServerName (for domain logon): Name ("domain_controller") of
900+
* the server (local computer; Active Directory domain controller...)
901+
* that validated the logon.
902+
* ** This data should be retrieved from the LsaLogonUser() call
903+
* made by MyLogonUser()! **
904+
*
905+
* NOTES:
906+
* - The paths use the domain controllers' "netlogon" share.
907+
* - These strings are LocalAlloc'd here, and LocalFree'd by Winlogon.
908+
*/
909+
pProfile->pszProfile = NULL;
910+
pProfile->pszPolicy = NULL;
911+
pProfile->pszNetworkDefaultUserProfile = NULL;
912+
pProfile->pszServerName = NULL;
913+
#if 0
914+
if (bIsDomainLogon)
915+
{
916+
PWSTR pServerName;
917+
cbSize = sizeof(L"\\\\") + wcslen(Domain) * sizeof(WCHAR);
918+
pServerName = LocalAlloc(LMEM_FIXED, cbSize);
919+
if (!pServerName)
920+
WARN("HeapAlloc() failed\n"); // Consider this optional, so no failure.
921+
else
922+
StringCbPrintfW(pServerName, cbSize, L"\\\\%ws", Domain); // See LogonServer below.
923+
pProfile->pszServerName = pServerName;
924+
}
925+
#endif
926+
927+
/* Build the minimal environment string block */
928+
// FIXME: LogonServer is the name of the server that processed the logon
929+
// request ("domain_controller"). It can be different from the selected
930+
// user's logon domain.
931+
// See e.g.:
932+
// - https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-msv1_0_interactive_profile
933+
// - https://learn.microsoft.com/en-us/windows/win32/api/winwlx/ns-winwlx-wlx_consoleswitch_credentials_info_v1_0
889934
cbSize = sizeof(L"LOGONSERVER=\\\\") +
890-
wcslen(pgContext->DomainName) * sizeof(WCHAR) +
935+
wcslen(Domain) * sizeof(WCHAR) +
891936
sizeof(UNICODE_NULL);
892937
pEnvironment = LocalAlloc(LMEM_FIXED, cbSize);
893938
if (!pEnvironment)
@@ -896,19 +941,20 @@ CreateProfile(
896941
goto cleanup;
897942
}
898943

899-
StringCbPrintfW(pEnvironment, cbSize, L"LOGONSERVER=\\\\%ls", pgContext->DomainName);
944+
StringCbPrintfW(pEnvironment, cbSize, L"LOGONSERVER=\\\\%ws", Domain);
900945
ASSERT(wcslen(pEnvironment) == cbSize / sizeof(WCHAR) - 2);
901946
pEnvironment[cbSize / sizeof(WCHAR) - 1] = UNICODE_NULL;
902947

903948
pProfile->pszEnvironment = pEnvironment;
904949

950+
/* Return the other info */
905951
if (!GetTokenInformation(pgContext->UserToken,
906952
TokenStatistics,
907953
&Stats,
908954
sizeof(Stats),
909955
&cbStats))
910956
{
911-
WARN("Couldn't get Authentication id from user token!\n");
957+
WARN("Couldn't get Authentication Id from user token!\n");
912958
goto cleanup;
913959
}
914960

@@ -924,8 +970,6 @@ CreateProfile(
924970
cleanup:
925971
if (pEnvironment)
926972
LocalFree(pEnvironment);
927-
if (pProfilePath)
928-
LocalFree(pProfilePath);
929973
if (pProfile)
930974
LocalFree(pProfile);
931975
return FALSE;

0 commit comments

Comments
 (0)