https://git.reactos.org/?p=reactos.git;a=commitdiff;h=05886b83e978542ab19d2…
commit 05886b83e978542ab19d29a177d13d7b6d100445
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Fri Mar 15 20:54:03 2019 +0100
Commit: Eric Kohl <eric.kohl(a)reactos.org>
CommitDate: Fri Mar 15 21:20:14 2019 +0100
[USERENV] Use a mutex to serialize profile loading and unloading.
---
dll/win32/userenv/profile.c | 110 ++++++++++++++++++++++++++++++++++++++++----
1 file changed, 102 insertions(+), 8 deletions(-)
diff --git a/dll/win32/userenv/profile.c b/dll/win32/userenv/profile.c
index c250d8846d..6b4635ba06 100644
--- a/dll/win32/userenv/profile.c
+++ b/dll/win32/userenv/profile.c
@@ -143,6 +143,60 @@ CheckForLoadedProfile(HANDLE hToken)
}
+static
+HANDLE
+CreateProfileMutex(
+ _In_ PWSTR pszSidString)
+{
+ SECURITY_DESCRIPTOR SecurityDescriptor;
+ SECURITY_ATTRIBUTES SecurityAttributes;
+ PWSTR pszMutexName = NULL;
+ HANDLE hMutex = NULL;
+
+ pszMutexName = HeapAlloc(GetProcessHeap(),
+ 0,
+ (wcslen(L"Global\\userenv: User Profile Mutex for
") + wcslen(pszSidString) + 1) * sizeof(WCHAR));
+ if (pszMutexName == NULL)
+ {
+ DPRINT("Failed to allocate the mutex name buffer!\n");
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
+ /* Build the profile mutex name */
+ wcscpy(pszMutexName, L"Global\\userenv: User Profile Mutex for ");
+ wcscat(pszMutexName, pszSidString);
+
+ /* Initialize the security descriptor */
+ InitializeSecurityDescriptor(&SecurityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION);
+
+ /* Set a NULL-DACL (everyone has access) */
+ SetSecurityDescriptorDacl(&SecurityDescriptor,
+ TRUE,
+ NULL,
+ FALSE);
+
+ /* Initialize the security attributes */
+ SecurityAttributes.nLength = sizeof(SecurityAttributes);
+ SecurityAttributes.lpSecurityDescriptor = &SecurityDescriptor;
+ SecurityAttributes.bInheritHandle = FALSE;
+
+ /* Create the profile mutex */
+ hMutex = CreateMutexW(&SecurityAttributes,
+ FALSE,
+ pszMutexName);
+ if (hMutex == NULL)
+ {
+ DPRINT1("Failed to create the profile mutex (Error %lu)\n",
GetLastError());
+ }
+
+ HeapFree(GetProcessHeap(), 0, pszMutexName);
+
+ return hMutex;
+}
+
+
/* PUBLIC FUNCTIONS ********************************************************/
BOOL
@@ -1420,6 +1474,7 @@ LoadUserProfileW(
WCHAR szUserHivePath[MAX_PATH];
PTOKEN_USER UserSid = NULL;
UNICODE_STRING SidString = { 0, 0, NULL };
+ HANDLE hProfileMutex = NULL;
LONG Error;
BOOL ret = FALSE;
DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]);
@@ -1445,6 +1500,17 @@ LoadUserProfileW(
}
ret = FALSE;
+ /* Create the profile mutex */
+ hProfileMutex = CreateProfileMutex(SidString.Buffer);
+ if (hProfileMutex == NULL)
+ {
+ DPRINT1("Failed to create the profile mutex\n");
+ goto cleanup;
+ }
+
+ /* Wait for the profile mutex */
+ WaitForSingleObject(hProfileMutex, INFINITE);
+
/* Don't load a profile twice */
if (CheckForLoadedProfile(hToken))
{
@@ -1552,6 +1618,13 @@ LoadUserProfileW(
cleanup:
if (UserSid != NULL)
HeapFree(GetProcessHeap(), 0, UserSid);
+
+ if (hProfileMutex != NULL)
+ {
+ ReleaseMutex(hProfileMutex);
+ CloseHandle(hProfileMutex);
+ }
+
RtlFreeUnicodeString(&SidString);
DPRINT("LoadUserProfileW() done\n");
@@ -1565,8 +1638,10 @@ UnloadUserProfile(
_In_ HANDLE hToken,
_In_ HANDLE hProfile)
{
- UNICODE_STRING SidString;
+ UNICODE_STRING SidString = {0, 0, NULL};
+ HANDLE hProfileMutex = NULL;
LONG Error;
+ BOOL bRet = FALSE;
DPRINT("UnloadUserProfile() called\n");
@@ -1577,8 +1652,6 @@ UnloadUserProfile(
return FALSE;
}
- RegCloseKey(hProfile);
-
/* Get the user SID string */
if (!GetUserSidStringFromToken(hToken, &SidString))
{
@@ -1588,12 +1661,25 @@ UnloadUserProfile(
DPRINT("SidString: '%wZ'\n", &SidString);
+ /* Create the profile mutex */
+ hProfileMutex = CreateProfileMutex(SidString.Buffer);
+ if (hProfileMutex == NULL)
+ {
+ DPRINT1("Failed to create the profile mutex\n");
+ goto cleanup;
+ }
+
+ /* Wait for the profile mutex */
+ WaitForSingleObject(hProfileMutex, INFINITE);
+
+ /* Close the profile handle */
+ RegCloseKey(hProfile);
+
/* Acquire restore privilege */
if (!AcquireRemoveRestorePrivilege(TRUE))
{
DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n",
GetLastError());
- RtlFreeUnicodeString(&SidString);
- return FALSE;
+ goto cleanup;
}
/* HACK */
@@ -1625,16 +1711,24 @@ UnloadUserProfile(
if (Error != ERROR_SUCCESS)
{
DPRINT1("RegUnLoadKeyW() failed (Error %ld)\n", Error);
- RtlFreeUnicodeString(&SidString);
SetLastError((DWORD)Error);
- return FALSE;
+ goto cleanup;
+ }
+
+ bRet = TRUE;
+
+cleanup:
+ if (hProfileMutex != NULL)
+ {
+ ReleaseMutex(hProfileMutex);
+ CloseHandle(hProfileMutex);
}
RtlFreeUnicodeString(&SidString);
DPRINT("UnloadUserProfile() done\n");
- return TRUE;
+ return bRet;
}
/* EOF */