Skip to content

Commit b254ea8

Browse files
committed
[MSGINA][WINLOGON] Perform thorough memory cleanup after user logging (reactos#8155)
- MSGINA: The `pMprNotifyInfo` and `pProfile` structures returned by `WlxLoggedOutSAS()`, as well as all of their pointer fields, are allocated by `LocalAlloc()`[^1][^2]. This is what Windows' Winlogon expects (and ours too, for interoperability with GINA dlls written for Windows), as it then frees them using `LocalFree()`. - WINLOGON: In `HandleLogon()`, free the cached `MprNotifyInfo` and `Profile` buffers (and all their members) obtained from a previous call to `WlxLoggedOutSAS()`. [^1]: https://learn.microsoft.com/en-us/windows/win32/api/winwlx/nf-winwlx-wlxloggedoutsas [^2]: 3rd-party GINAs rely on this as well. One example can be found at: https://www.codeproject.com/Articles/20656/Winlogon-using-Mobile-Disk
1 parent 64d1301 commit b254ea8

File tree

3 files changed

+83
-25
lines changed

3 files changed

+83
-25
lines changed

base/system/winlogon/sas.c

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,61 @@ RestoreAllConnections(PWLSESSION Session)
491491
RevertToSelf();
492492
}
493493

494+
/**
495+
* @brief
496+
* Frees the Profile information structure (WLX_PROFILE_V1_0
497+
* or WLX_PROFILE_V2_0) allocated by the GINA.
498+
**/
499+
static VOID
500+
FreeWlxProfileInfo(
501+
_Inout_ PVOID Profile)
502+
{
503+
PWLX_PROFILE_V2_0 pProfile = (PWLX_PROFILE_V2_0)Profile;
504+
505+
if (pProfile->dwType != WLX_PROFILE_TYPE_V1_0
506+
&& pProfile->dwType != WLX_PROFILE_TYPE_V2_0)
507+
{
508+
ERR("WL: Wrong profile info\n");
509+
return;
510+
}
511+
512+
if (pProfile->pszProfile)
513+
LocalFree(pProfile->pszProfile);
514+
if (pProfile->dwType >= WLX_PROFILE_TYPE_V2_0)
515+
{
516+
if (pProfile->pszPolicy)
517+
LocalFree(pProfile->pszPolicy);
518+
if (pProfile->pszNetworkDefaultUserProfile)
519+
LocalFree(pProfile->pszNetworkDefaultUserProfile);
520+
if (pProfile->pszServerName)
521+
LocalFree(pProfile->pszServerName);
522+
if (pProfile->pszEnvironment)
523+
LocalFree(pProfile->pszEnvironment);
524+
}
525+
}
526+
527+
/**
528+
* @brief
529+
* Frees the MPR information structure allocated by the GINA.
530+
*
531+
* @note
532+
* Currently used only in HandleLogon(), but will also be used
533+
* by WlxChangePasswordNotify(Ex) once implemented.
534+
**/
535+
static VOID
536+
FreeWlxMprInfo(
537+
_Inout_ PWLX_MPR_NOTIFY_INFO MprNotifyInfo)
538+
{
539+
if (MprNotifyInfo->pszUserName)
540+
LocalFree(MprNotifyInfo->pszUserName);
541+
if (MprNotifyInfo->pszDomain)
542+
LocalFree(MprNotifyInfo->pszDomain);
543+
if (MprNotifyInfo->pszPassword)
544+
LocalFree(MprNotifyInfo->pszPassword);
545+
if (MprNotifyInfo->pszOldPassword)
546+
LocalFree(MprNotifyInfo->pszOldPassword);
547+
}
548+
494549
static
495550
BOOL
496551
HandleLogon(
@@ -611,10 +666,13 @@ HandleLogon(
611666
cleanup:
612667
if (Session->Profile)
613668
{
614-
HeapFree(GetProcessHeap(), 0, Session->Profile->pszProfile);
615-
HeapFree(GetProcessHeap(), 0, Session->Profile);
669+
FreeWlxProfileInfo(Session->Profile);
670+
LocalFree(Session->Profile);
671+
Session->Profile = NULL;
616672
}
617-
Session->Profile = NULL;
673+
FreeWlxMprInfo(&Session->MprNotifyInfo);
674+
ZeroMemory(&Session->MprNotifyInfo, sizeof(Session->MprNotifyInfo));
675+
618676
if (!ret && ProfileInfo.hProfile != INVALID_HANDLE_VALUE)
619677
{
620678
UnloadUserProfile(Session->UserToken, ProfileInfo.hProfile);

base/system/winlogon/winlogon.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ typedef struct _WLSESSION
254254
/* Logon informations */
255255
DWORD Options;
256256
WLX_MPR_NOTIFY_INFO MprNotifyInfo;
257-
WLX_PROFILE_V2_0 *Profile;
257+
PWLX_PROFILE_V2_0 Profile;
258258
} WLSESSION, *PWLSESSION;
259259

260260
typedef enum _NOTIFICATION_TYPE

dll/win32/msgina/msgina.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -834,10 +834,10 @@ CreateProfile(
834834
IN PWSTR Domain,
835835
IN PWSTR Password)
836836
{
837-
LPWSTR ProfilePath = NULL;
838-
LPWSTR lpEnvironment = NULL;
839-
TOKEN_STATISTICS Stats;
840837
PWLX_PROFILE_V2_0 pProfile = NULL;
838+
PWSTR pProfilePath = NULL;
839+
PWSTR pEnvironment = NULL;
840+
TOKEN_STATISTICS Stats;
841841
DWORD cbStats, cbSize;
842842
DWORD dwLength;
843843
BOOL bResult;
@@ -862,13 +862,13 @@ CreateProfile(
862862
bResult = GetProfilesDirectoryW(NULL, &cbSize);
863863
if (!bResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
864864
{
865-
ProfilePath = HeapAlloc(GetProcessHeap(), 0, cbSize * sizeof(WCHAR));
866-
if (!ProfilePath)
865+
pProfilePath = LocalAlloc(LMEM_FIXED, cbSize * sizeof(WCHAR));
866+
if (!pProfilePath)
867867
{
868-
WARN("HeapAlloc() failed\n");
868+
WARN("LocalAlloc() failed\n");
869869
goto cleanup;
870870
}
871-
bResult = GetProfilesDirectoryW(ProfilePath, &cbSize);
871+
bResult = GetProfilesDirectoryW(pProfilePath, &cbSize);
872872
}
873873
if (!bResult)
874874
{
@@ -877,30 +877,30 @@ CreateProfile(
877877
}
878878

879879
/* Allocate memory for profile */
880-
pProfile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WLX_PROFILE_V2_0));
880+
pProfile = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(*pProfile));
881881
if (!pProfile)
882882
{
883883
WARN("HeapAlloc() failed\n");
884884
goto cleanup;
885885
}
886886
pProfile->dwType = WLX_PROFILE_TYPE_V2_0;
887-
pProfile->pszProfile = ProfilePath;
887+
pProfile->pszProfile = pProfilePath;
888888

889889
cbSize = sizeof(L"LOGONSERVER=\\\\") +
890890
wcslen(pgContext->DomainName) * sizeof(WCHAR) +
891891
sizeof(UNICODE_NULL);
892-
lpEnvironment = HeapAlloc(GetProcessHeap(), 0, cbSize);
893-
if (!lpEnvironment)
892+
pEnvironment = LocalAlloc(LMEM_FIXED, cbSize);
893+
if (!pEnvironment)
894894
{
895-
WARN("HeapAlloc() failed\n");
895+
WARN("LocalAlloc() failed\n");
896896
goto cleanup;
897897
}
898898

899-
StringCbPrintfW(lpEnvironment, cbSize, L"LOGONSERVER=\\\\%ls", pgContext->DomainName);
900-
ASSERT(wcslen(lpEnvironment) == cbSize / sizeof(WCHAR) - 2);
901-
lpEnvironment[cbSize / sizeof(WCHAR) - 1] = UNICODE_NULL;
899+
StringCbPrintfW(pEnvironment, cbSize, L"LOGONSERVER=\\\\%ls", pgContext->DomainName);
900+
ASSERT(wcslen(pEnvironment) == cbSize / sizeof(WCHAR) - 2);
901+
pEnvironment[cbSize / sizeof(WCHAR) - 1] = UNICODE_NULL;
902902

903-
pProfile->pszEnvironment = lpEnvironment;
903+
pProfile->pszEnvironment = pEnvironment;
904904

905905
if (!GetTokenInformation(pgContext->UserToken,
906906
TokenStatistics,
@@ -922,12 +922,12 @@ CreateProfile(
922922
return TRUE;
923923

924924
cleanup:
925+
if (pEnvironment)
926+
LocalFree(pEnvironment);
927+
if (pProfilePath)
928+
LocalFree(pProfilePath);
925929
if (pProfile)
926-
{
927-
HeapFree(GetProcessHeap(), 0, pProfile->pszEnvironment);
928-
}
929-
HeapFree(GetProcessHeap(), 0, pProfile);
930-
HeapFree(GetProcessHeap(), 0, ProfilePath);
930+
LocalFree(pProfile);
931931
return FALSE;
932932
}
933933

0 commit comments

Comments
 (0)