https://git.reactos.org/?p=reactos.git;a=commitdiff;h=92231340ec071bd7a461d8a941b4cd82b865bc81

commit 92231340ec071bd7a461d8a941b4cd82b865bc81
Author:     Thamatip Chitpong <thamatip.chitp...@reactos.org>
AuthorDate: Sat Dec 7 09:15:11 2024 +0700
Commit:     GitHub <nore...@github.com>
CommitDate: Sat Dec 7 09:15:11 2024 +0700

    [WINMM] PlaySound: Fix user-specific environment variables handling (#7536)
    
    Correctly retrieve user-specific environment variables when impersonating.
    Addendum to commit f18111b64120806529e93404f21b6320f211ec39.
    CORE-13951
---
 dll/win32/winmm/CMakeLists.txt |  2 +-
 dll/win32/winmm/playsound.c    | 60 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/dll/win32/winmm/CMakeLists.txt b/dll/win32/winmm/CMakeLists.txt
index aca0942d4be..2566277f94d 100644
--- a/dll/win32/winmm/CMakeLists.txt
+++ b/dll/win32/winmm/CMakeLists.txt
@@ -30,7 +30,7 @@ endif()
 
 set_module_type(winmm win32dll)
 target_link_libraries(winmm wine ${PSEH_LIB} oldnames)
-add_importlibs(winmm advapi32 user32 msvcrt kernel32 ntdll)
+add_importlibs(winmm userenv advapi32 user32 msvcrt kernel32 ntdll)
 add_pch(winmm winemm.h SOURCE)
 add_cd_file(TARGET winmm DESTINATION reactos/system32 FOR all)
 
diff --git a/dll/win32/winmm/playsound.c b/dll/win32/winmm/playsound.c
index df532f05cfd..991299a0a7f 100644
--- a/dll/win32/winmm/playsound.c
+++ b/dll/win32/winmm/playsound.c
@@ -26,6 +26,7 @@
 #include "winemm.h"
 
 #include <winternl.h>
+#include <userenv.h>
 
 WINE_DEFAULT_DEBUG_CHANNEL(winmm);
 
@@ -39,6 +40,61 @@ typedef struct tagWINE_PLAYSOUND
 static WINE_PLAYSOUND *PlaySoundCurrent;
 static BOOL bPlaySoundStop;
 
+/* An impersonation-aware equivalent of ExpandEnvironmentStringsW */
+static DWORD PlaySound_ExpandEnvironmentStrings(LPCWSTR lpSrc, LPWSTR lpDst, 
DWORD nSize)
+{
+    HANDLE hToken;
+    DWORD dwError;
+    DWORD dwLength = 0;
+
+    if (!OpenThreadToken(GetCurrentThread(),
+                         TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
+                         TRUE,
+                         &hToken))
+    {
+        dwError = GetLastError();
+
+        if (dwError == ERROR_NO_TOKEN)
+        {
+            /* We are not impersonating, forward this to 
ExpandEnvironmentStrings */
+            return ExpandEnvironmentStringsW(lpSrc, lpDst, nSize);
+        }
+
+        ERR("OpenThreadToken failed (0x%x)\n", dwError);
+        return 0;
+    }
+
+    if (!ExpandEnvironmentStringsForUserW(hToken, lpSrc, lpDst, nSize))
+    {
+        dwError = GetLastError();
+
+        if (dwError == ERROR_INSUFFICIENT_BUFFER || nSize == 0)
+        {
+            /* The buffer is too small, find the required buffer size.
+             * NOTE: ExpandEnvironmentStringsForUser doesn't support 
retrieving buffer size. */
+            WCHAR szExpanded[1024];
+
+            if (ExpandEnvironmentStringsForUserW(hToken, lpSrc, szExpanded, 
ARRAY_SIZE(szExpanded)))
+            {
+                /* We success, return the required buffer size */
+                dwLength = lstrlenW(szExpanded) + 1;
+                goto Cleanup;
+            }
+        }
+
+        ERR("ExpandEnvironmentStringsForUser failed (0x%x)\n", dwError);
+    }
+    else
+    {
+        /* We success, return the size of the string */
+        dwLength = lstrlenW(lpDst) + 1;
+    }
+
+Cleanup:
+    CloseHandle(hToken);
+    return dwLength;
+}
+
 static HMMIO    get_mmioFromFile(LPCWSTR lpszName)
 {
     HMMIO       ret;
@@ -158,7 +214,7 @@ Next:
 
     if (type == REG_EXPAND_SZ)
     {
-        count = ExpandEnvironmentStringsW(str, NULL, 0);
+        count = PlaySound_ExpandEnvironmentStrings(str, NULL, 0);
         if (count == 0)
             goto None;
 
@@ -166,7 +222,7 @@ Next:
         if (!pszSnd)
             goto None;
 
-        if (ExpandEnvironmentStringsW(str, pszSnd, count) == 0)
+        if (PlaySound_ExpandEnvironmentStrings(str, pszSnd, count) == 0)
         {
             HeapFree(GetProcessHeap(), 0, pszSnd);
             goto None;

Reply via email to