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 +#include 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;