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

commit f18111b64120806529e93404f21b6320f211ec39
Author:     Thamatip Chitpong <[email protected]>
AuthorDate: Fri May 5 19:19:34 2023 +0700
Commit:     GitHub <[email protected]>
CommitDate: Fri May 5 14:19:34 2023 +0200

    [WINMM] Winmm fixes for system sound (#4635)
    
    CORE-13951
    
    MIDIMAP_LoadSettings and PlaySound:
    Use RegOpenCurrentUser to access the appropriate HKEY_CURRENT_USER key.
    This allows functions that use HKEY_CURRENT_USER to be called from system
    processes while impersonating, for example: winlogon.
    
    PlaySound:
    - Open the correct registry key.
    - Expand environment strings if registry value type is REG_EXPAND_SZ.
    - Handle "SystemDefault" event and improve flags handling.
    - Don't use proc_PlaySound as thread proc.
    - Fix SND_ASYNC flag for system processes.
      Move get_mmio* code out of proc_PlaySound to fix impersonation problem.
---
 dll/win32/winmm/midimap/midimap.c |  15 +-
 dll/win32/winmm/playsound.c       | 515 +++++++++++++++++++++++---------------
 2 files changed, 322 insertions(+), 208 deletions(-)

diff --git a/dll/win32/winmm/midimap/midimap.c 
b/dll/win32/winmm/midimap/midimap.c
index 8eefac33d14..a214b64a15a 100644
--- a/dll/win32/winmm/midimap/midimap.c
+++ b/dll/win32/winmm/midimap/midimap.c
@@ -202,11 +202,20 @@ static BOOL       MIDIMAP_LoadSettingsScheme(MIDIMAPDATA* 
mom, const WCHAR* scheme)
 
 static BOOL    MIDIMAP_LoadSettings(MIDIMAPDATA* mom)
 {
-    HKEY       hKey;
+    HKEY       hUserKey, hKey;
+    DWORD   err;
     BOOL       ret;
 
-    if (RegOpenKeyA(HKEY_CURRENT_USER,
-                   
"Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap", &hKey))
+    err = RegOpenCurrentUser(KEY_READ, &hUserKey);
+    if (err == ERROR_SUCCESS)
+    {
+        err = RegOpenKeyW(hUserKey,
+                          
L"Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap",
+                          &hKey);
+        RegCloseKey(hUserKey);
+    }
+
+    if (err != ERROR_SUCCESS)
     {
        ret = MIDIMAP_LoadSettingsDefault(mom, NULL);
     }
diff --git a/dll/win32/winmm/playsound.c b/dll/win32/winmm/playsound.c
index a6fdbd7ed19..f0b2fe086f9 100644
--- a/dll/win32/winmm/playsound.c
+++ b/dll/win32/winmm/playsound.c
@@ -29,12 +29,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(winmm);
 
 typedef struct tagWINE_PLAYSOUND
 {
-    unsigned                    bLoop : 1,
-                                bAlloc : 1;
-    LPCWSTR                     pszSound;
-    HMODULE                     hMod;
-    DWORD                       fdwSound;
-    HANDLE                      hThread;
+    unsigned                    bLoop : 1;
+    HMMIO                       hmmio;
     HWAVEOUT                    hWave;
     struct tagWINE_PLAYSOUND*   lpNext;
 } WINE_PLAYSOUND;
@@ -50,7 +46,7 @@ static HMMIO  get_mmioFromFile(LPCWSTR lpszName)
     ret = mmioOpenW((LPWSTR)lpszName, NULL,
                     MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
     if (ret != 0) return ret;
-    if (SearchPathW(NULL, lpszName, NULL, sizeof(buf)/sizeof(buf[0]), buf, 
&dummy))
+    if (SearchPathW(NULL, lpszName, NULL, ARRAY_SIZE(buf), buf, &dummy))
     {
         return mmioOpenW(buf, NULL,
                          MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
@@ -58,55 +54,67 @@ static HMMIO        get_mmioFromFile(LPCWSTR lpszName)
     return 0;
 }
 
-static HMMIO   get_mmioFromProfile(UINT uFlags, LPCWSTR lpszName)
+static HMMIO get_mmioFromProfile(UINT uFlags, LPCWSTR lpszName)
 {
-    WCHAR      str[128];
-    LPWSTR     ptr;
-    HMMIO      hmmio;
-    HKEY        hRegSnd, hRegApp, hScheme, hSnd;
-    DWORD       err, type, count;
-
-    static const WCHAR  wszSounds[] = {'S','o','u','n','d','s',0};
-    static const WCHAR  wszDefault[] = {'D','e','f','a','u','l','t',0};
-    static const WCHAR  wszKey[] = {'A','p','p','E','v','e','n','t','s','\\',
-                                    'S','c','h','e','m','e','s','\\',
-                                    'A','p','p','s',0};
-    static const WCHAR  wszDotDefault[] = {'.','D','e','f','a','u','l','t',0};
-    static const WCHAR  wszDotCurrent[] = {'.','C','u','r','r','e','n','t',0};
-    static const WCHAR  wszNull[] = {0};
+    WCHAR str[128];
+    LPWSTR ptr, pszSnd;
+    HMMIO hmmio;
+    HKEY hUserKey, hRegSnd, hRegApp, hScheme, hSnd;
+    DWORD err, type, count;
+    BOOL bIsDefault;
 
     TRACE("searching in SystemSound list for %s\n", debugstr_w(lpszName));
-    GetProfileStringW(wszSounds, lpszName, wszNull, str, 
sizeof(str)/sizeof(str[0]));
+
+    bIsDefault = (_wcsicmp(lpszName, L"SystemDefault") == 0);
+
+    GetProfileStringW(L"Sounds",
+                      bIsDefault ? L"Default" : lpszName,
+                      L"",
+                      str,
+                      ARRAY_SIZE(str));
     if (lstrlenW(str) == 0)
-    {
-       if (uFlags & SND_NODEFAULT) goto next;
-       GetProfileStringW(wszSounds, wszDefault, wszNull, str, 
sizeof(str)/sizeof(str[0]));
-       if (lstrlenW(str) == 0) goto next;
-    }
-    for (ptr = str; *ptr && *ptr != ','; ptr++);
-    if (*ptr) *ptr = 0;
+        goto Next;
+
+    for (ptr = str; *ptr && *ptr != L','; ptr++);
+
+    if (*ptr)
+        *ptr = UNICODE_NULL;
+
     hmmio = mmioOpenW(str, NULL, MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
-    if (hmmio != 0) return hmmio;
- next:
+    if (hmmio)
+        return hmmio;
+
+Next:
     /* we look up the registry under
      *      HKCU\AppEvents\Schemes\Apps\.Default
      *      HKCU\AppEvents\Schemes\Apps\<AppName>
      */
-    if (RegOpenKeyW(HKEY_CURRENT_USER, wszKey, &hRegSnd) != 0) goto none;
+    err = RegOpenCurrentUser(KEY_READ, &hUserKey);
+    if (err == ERROR_SUCCESS)
+    {
+        err = RegOpenKeyW(hUserKey, L"AppEvents\\Schemes\\Apps", &hRegSnd);
+        RegCloseKey(hUserKey);
+    }
+
+    if (err != ERROR_SUCCESS)
+        goto None;
+
     if (uFlags & SND_APPLICATION)
     {
         DWORD len;
 
-        err = 1; /* error */
-        len = GetModuleFileNameW(0, str, sizeof(str)/sizeof(str[0]));
-        if (len > 0 && len < sizeof(str)/sizeof(str[0]))
+        err = ERROR_FILE_NOT_FOUND; /* error */
+        len = GetModuleFileNameW(NULL, str, ARRAY_SIZE(str));
+        if (len > 0 && len < ARRAY_SIZE(str))
         {
             for (ptr = str + lstrlenW(str) - 1; ptr >= str; ptr--)
             {
-                if (*ptr == '.') *ptr = 0;
-                if (*ptr == '\\')
+                if (*ptr == L'.')
+                    *ptr = UNICODE_NULL;
+
+                if (*ptr == L'\\')
                 {
-                    err = RegOpenKeyW(hRegSnd, ptr+1, &hRegApp);
+                    err = RegOpenKeyW(hRegSnd, ptr + 1, &hRegApp);
                     break;
                 }
             }
@@ -114,31 +122,188 @@ static HMMIO     get_mmioFromProfile(UINT uFlags, 
LPCWSTR lpszName)
     }
     else
     {
-        err = RegOpenKeyW(hRegSnd, wszDotDefault, &hRegApp);
+        err = RegOpenKeyW(hRegSnd, L".Default", &hRegApp);
     }
+
     RegCloseKey(hRegSnd);
-    if (err != 0) goto none;
-    err = RegOpenKeyW(hRegApp, lpszName, &hScheme);
+
+    if (err != ERROR_SUCCESS)
+        goto None;
+
+    err = RegOpenKeyW(hRegApp,
+                      bIsDefault ? L".Default" : lpszName,
+                      &hScheme);
+
     RegCloseKey(hRegApp);
-    if (err != 0) goto none;
-    /* what's the difference between .Current and .Default ? */
-    err = RegOpenKeyW(hScheme, wszDotDefault, &hSnd);
-    if (err != 0)
-    {
-        err = RegOpenKeyW(hScheme, wszDotCurrent, &hSnd);
-        RegCloseKey(hScheme);
-        if (err != 0)
-            goto none;
-    }
+
+    if (err != ERROR_SUCCESS)
+        goto None;
+    
+    err = RegOpenKeyW(hScheme, L".Current", &hSnd);
+
+    RegCloseKey(hScheme);
+
+    if (err != ERROR_SUCCESS)
+        goto None;
+
     count = sizeof(str);
     err = RegQueryValueExW(hSnd, NULL, 0, &type, (LPBYTE)str, &count);
+
     RegCloseKey(hSnd);
-    if (err != 0 || !*str) goto none;
-    hmmio = mmioOpenW(str, NULL, MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
-    if (hmmio) return hmmio;
- none:
+
+    if (err != ERROR_SUCCESS || !*str)
+        goto None;
+
+    if (type == REG_EXPAND_SZ)
+    {
+        count = ExpandEnvironmentStringsW(str, NULL, 0);
+        if (count == 0)
+            goto None;
+
+        pszSnd = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
+        if (!pszSnd)
+            goto None;
+
+        if (ExpandEnvironmentStringsW(str, pszSnd, count) == 0)
+        {
+            HeapFree(GetProcessHeap(), 0, pszSnd);
+            goto None;
+        }
+    }
+    else if (type == REG_SZ)
+    {
+        /* The type is REG_SZ, no need to expand */
+        pszSnd = str;
+    }
+    else
+    {
+        /* Invalid type */
+        goto None;
+    }
+
+    hmmio = mmioOpenW(pszSnd, NULL, MMIO_ALLOCBUF | MMIO_READ | 
MMIO_DENYWRITE);
+
+    if (type == REG_EXPAND_SZ)
+        HeapFree(GetProcessHeap(), 0, pszSnd);
+
+    if (hmmio)
+        return hmmio;
+
+None:
     WARN("can't find SystemSound=%s !\n", debugstr_w(lpszName));
-    return 0;
+    return NULL;
+}
+
+static HMMIO PlaySound_GetMMIO(LPCWSTR pszSound, HMODULE hMod, DWORD fdwSound)
+{
+    BOOL bIsDefault = FALSE;
+    HMMIO hmmio = NULL;
+
+    TRACE("SoundName=%s !\n", debugstr_w(pszSound));
+
+    if (fdwSound & SND_MEMORY)
+    {
+        PVOID data;
+        MMIOINFO mminfo;
+
+        /* NOTE: SND_RESOURCE has the SND_MEMORY bit set */
+        if ((fdwSound & SND_RESOURCE) == SND_RESOURCE)
+        {
+            HRSRC hRes;
+            HGLOBAL hGlob;
+
+            hRes = FindResourceW(hMod, pszSound, L"WAVE");
+            hGlob = LoadResource(hMod, hRes);
+            if (!hRes || !hGlob)
+                goto Quit;
+
+            data = LockResource(hGlob);
+            FreeResource(hGlob);
+            if (!data)
+                goto Quit;
+        }
+        else
+        {
+            data = (PVOID)pszSound;
+        }
+        
+        ZeroMemory(&mminfo, sizeof(mminfo));
+        mminfo.fccIOProc = FOURCC_MEM;
+        mminfo.pchBuffer = data;
+        mminfo.cchBuffer = -1; /* FIXME: when a resource, could grab real size 
*/
+
+        TRACE("Memory sound %p\n", data);
+
+        hmmio = mmioOpenW(NULL, &mminfo, MMIO_READ);
+    }
+    else if (fdwSound & SND_ALIAS)
+    {
+        LPCWSTR pszName;
+
+        /* NOTE: SND_ALIAS_ID has the SND_ALIAS bit set */
+        if ((fdwSound & SND_ALIAS_ID) == SND_ALIAS_ID)
+        {
+            if (pszSound == (LPCWSTR)SND_ALIAS_SYSTEMASTERISK)
+                pszName = L"SystemAsterisk";
+            else if (pszSound == (LPCWSTR)SND_ALIAS_SYSTEMDEFAULT)
+                pszName = L"SystemDefault";
+            else if (pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXCLAMATION)
+                pszName = L"SystemExclamation";
+            else if (pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXIT)
+                pszName = L"SystemExit";
+            else if (pszSound == (LPCWSTR)SND_ALIAS_SYSTEMHAND)
+                pszName = L"SystemHand";
+            else if (pszSound == (LPCWSTR)SND_ALIAS_SYSTEMQUESTION)
+                pszName = L"SystemQuestion";
+            else if (pszSound == (LPCWSTR)SND_ALIAS_SYSTEMSTART)
+                pszName = L"SystemStart";
+            else if (pszSound == (LPCWSTR)SND_ALIAS_SYSTEMWELCOME)
+                pszName = L"SystemWelcome";
+            else
+                goto Quit;
+        }
+        else
+        {
+            pszName = pszSound;
+        }
+
+        bIsDefault = (_wcsicmp(pszName, L"SystemDefault") == 0);
+        hmmio = get_mmioFromProfile(fdwSound, pszName);
+    }
+    else if (fdwSound & SND_FILENAME)
+    {
+        hmmio = get_mmioFromFile(pszSound);
+    }
+    else
+    {
+        hmmio = get_mmioFromProfile(fdwSound, pszSound);
+        if (!hmmio)
+            hmmio = get_mmioFromFile(pszSound);
+    }
+
+Quit:
+    if (!hmmio && !(fdwSound & SND_NODEFAULT))
+    {
+        if (fdwSound & SND_APPLICATION)
+        {
+            if (!bIsDefault)
+            {
+                /* Find application-defined default sound */
+                hmmio = get_mmioFromProfile(fdwSound, L"SystemDefault");
+                if (hmmio)
+                    return hmmio;
+            }
+
+            /* Find system default sound */
+            hmmio = get_mmioFromProfile(fdwSound & ~SND_APPLICATION, 
L"SystemDefault");
+        }
+        else if (!bIsDefault)
+        {
+            hmmio = get_mmioFromProfile(fdwSound, L"SystemDefault");
+        }
+    }
+
+    return hmmio;
 }
 
 struct playsound_data
@@ -183,15 +348,23 @@ static BOOL PlaySound_IsString(DWORD fdwSound, const 
void* psz)
     /* SND_RESOURCE is 0x40004 while
      * SND_MEMORY is 0x00004
      */
-    switch (fdwSound & (SND_RESOURCE|SND_ALIAS_ID|SND_FILENAME))
+    switch (fdwSound & (SND_RESOURCE | SND_ALIAS_ID | SND_FILENAME))
     {
-    case SND_RESOURCE:  return HIWORD(psz) != 0; /* by name or by ID ? */
-    case SND_ALIAS_ID:
-    case SND_MEMORY:    return FALSE;
-    case SND_ALIAS:
-    case SND_FILENAME:
-    case 0:             return TRUE;
-    default:            FIXME("WTF\n"); return FALSE;
+        case SND_RESOURCE:
+            return HIWORD(psz) != 0; /* by name or by ID ? */
+
+        case SND_ALIAS_ID:
+        case SND_MEMORY:
+            return FALSE;
+
+        case SND_ALIAS:
+        case SND_FILENAME:
+        case 0:
+            return TRUE;
+
+        default:
+            FIXME("WTF\n");
+            return FALSE;
     }
 }
 
@@ -204,151 +377,64 @@ static void     PlaySound_Free(WINE_PLAYSOUND* wps)
     if (*p) *p = (*p)->lpNext;
     if (PlaySoundList == NULL) SetEvent(psLastEvent);
     LeaveCriticalSection(&WINMM_cs);
-    if (wps->bAlloc) HeapFree(GetProcessHeap(), 0, (void*)wps->pszSound);
-    if (wps->hThread) CloseHandle(wps->hThread);
+    if (wps->hmmio) mmioClose(wps->hmmio, 0);
     HeapFree(GetProcessHeap(), 0, wps);
 }
 
-static WINE_PLAYSOUND*  PlaySound_Alloc(const void* pszSound, HMODULE hmod,
-                                        DWORD fdwSound, BOOL bUnicode)
+static WINE_PLAYSOUND* PlaySound_AllocAndGetMMIO(const void* pszSound, HMODULE 
hmod,
+                                                 DWORD fdwSound, BOOL bUnicode)
 {
+    BOOL bIsString;
+    LPCWSTR pszSoundW;
+    UNICODE_STRING usBuffer;
     WINE_PLAYSOUND* wps;
 
-    wps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wps));
-    if (!wps) return NULL;
+    bIsString = PlaySound_IsString(fdwSound, pszSound);
 
-    wps->hMod = hmod;
-    wps->fdwSound = fdwSound;
-    if (PlaySound_IsString(fdwSound, pszSound))
+    if (bIsString && !bUnicode)
     {
-        if (bUnicode)
-        {
-            if (fdwSound & SND_ASYNC)
-            {
-                LPWSTR sound = HeapAlloc(GetProcessHeap(), 0,
-                                         (lstrlenW(pszSound)+1) * 
sizeof(WCHAR));
-                if (!sound) goto oom_error;
-                wps->pszSound = lstrcpyW(sound, pszSound);
-                wps->bAlloc = TRUE;
-            }
-            else
-                wps->pszSound = pszSound;
-        }
-        else
+        RtlCreateUnicodeStringFromAsciiz(&usBuffer, pszSound);
+        if (!usBuffer.Buffer)
+            return NULL;
+
+        pszSoundW = usBuffer.Buffer;
+    }
+    else
+    {
+        pszSoundW = pszSound;
+    }
+
+    wps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wps));
+    if (wps)
+    {
+        /* construct an MMIO stream (either in memory, or from a file) */
+        wps->hmmio = PlaySound_GetMMIO(pszSoundW, hmod, fdwSound);
+        if (!wps->hmmio)
         {
-            UNICODE_STRING usBuffer;
-            RtlCreateUnicodeStringFromAsciiz(&usBuffer, pszSound);
-            wps->pszSound = usBuffer.Buffer;
-            if (!wps->pszSound) goto oom_error;
-            wps->bAlloc = TRUE;
+            PlaySound_Free(wps);
+            wps = NULL;
         }
     }
-    else
-        wps->pszSound = pszSound;
+
+    if (bIsString && !bUnicode)
+        RtlFreeUnicodeString(&usBuffer);
 
     return wps;
- oom_error:
-    PlaySound_Free(wps);
-    return NULL;
 }
 
-static DWORD WINAPI proc_PlaySound(LPVOID arg)
+static BOOL proc_PlaySound(WINE_PLAYSOUND *wps)
 {
-    WINE_PLAYSOUND*     wps = arg;
     BOOL               bRet = FALSE;
-    HMMIO              hmmio = 0;
     MMCKINFO           ckMainRIFF;
     MMCKINFO           mmckInfo;
     LPWAVEFORMATEX      lpWaveFormat = NULL;
     LPWAVEHDR          waveHdr = NULL;
     INT                        count, bufsize, left, index;
     struct playsound_data      s;
-    void*               data;
 
     s.hEvent = 0;
 
-    TRACE("SoundName=%s !\n", debugstr_w(wps->pszSound));
-
-    /* if resource, grab it */
-    if ((wps->fdwSound & SND_RESOURCE) == SND_RESOURCE) {
-        static const WCHAR wszWave[] = {'W','A','V','E',0};
-        HRSRC  hRes;
-        HGLOBAL        hGlob;
-
-        if ((hRes = FindResourceW(wps->hMod, wps->pszSound, wszWave)) == 0 ||
-            (hGlob = LoadResource(wps->hMod, hRes)) == 0)
-            goto errCleanUp;
-        if ((data = LockResource(hGlob)) == NULL) {
-            FreeResource(hGlob);
-            goto errCleanUp;
-        }
-        FreeResource(hGlob);
-    } else
-        data = (void*)wps->pszSound;
-
-    /* construct an MMIO stream (either in memory, or from a file */
-    if (wps->fdwSound & SND_MEMORY)
-    { /* NOTE: SND_RESOURCE has the SND_MEMORY bit set */
-       MMIOINFO        mminfo;
-
-       memset(&mminfo, 0, sizeof(mminfo));
-       mminfo.fccIOProc = FOURCC_MEM;
-       mminfo.pchBuffer = data;
-       mminfo.cchBuffer = -1; /* FIXME: when a resource, could grab real size 
*/
-       TRACE("Memory sound %p\n", data);
-       hmmio = mmioOpenW(NULL, &mminfo, MMIO_READ);
-    }
-    else if (wps->fdwSound & SND_ALIAS)
-    {
-        if ((wps->fdwSound & SND_ALIAS_ID) == SND_ALIAS_ID)
-        {
-            static const WCHAR  wszSystemAsterisk[] = 
{'S','y','s','t','e','m','A','s','t','e','r','i','s','k',0};
-            static const WCHAR  wszSystemDefault[] = 
{'S','y','s','t','e','m','D','e','f','a','u','l','t',0};
-            static const WCHAR  wszSystemExclamation[] = 
{'S','y','s','t','e','m','E','x','c','l','a','m','a','t','i','o','n',0};
-            static const WCHAR  wszSystemExit[] = 
{'S','y','s','t','e','m','E','x','i','t',0};
-            static const WCHAR  wszSystemHand[] = 
{'S','y','s','t','e','m','H','a','n','d',0};
-            static const WCHAR  wszSystemQuestion[] = 
{'S','y','s','t','e','m','Q','u','e','s','t','i','o','n',0};
-            static const WCHAR  wszSystemStart[] = 
{'S','y','s','t','e','m','S','t','a','r','t',0};
-            static const WCHAR  wszSystemWelcome[] = 
{'S','y','s','t','e','m','W','e','l','c','o','m','e',0};
-
-            wps->fdwSound &= ~(SND_ALIAS_ID ^ SND_ALIAS);
-            if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMASTERISK)
-                wps->pszSound = wszSystemAsterisk;
-            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMDEFAULT)
-                wps->pszSound = wszSystemDefault;
-            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXCLAMATION)
-                wps->pszSound = wszSystemExclamation;
-            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXIT)
-                wps->pszSound = wszSystemExit;
-            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMHAND)
-                wps->pszSound = wszSystemHand;
-            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMQUESTION)
-                wps->pszSound = wszSystemQuestion;
-            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMSTART)
-                wps->pszSound = wszSystemStart;
-            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMWELCOME)
-                wps->pszSound = wszSystemWelcome;
-            else goto errCleanUp;
-        }
-        hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound);
-    }
-    else if (wps->fdwSound & SND_FILENAME)
-    {
-        hmmio = get_mmioFromFile(wps->pszSound);
-    }
-    else
-    {
-        if ((hmmio = get_mmioFromProfile(wps->fdwSound | SND_NODEFAULT, 
wps->pszSound)) == 0)
-        {
-            if ((hmmio = get_mmioFromFile(wps->pszSound)) == 0)
-            {
-                hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound);
-            }
-        }
-    }
-    if (hmmio == 0) goto errCleanUp;
-
-    if (mmioDescend(hmmio, &ckMainRIFF, NULL, 0))
+    if (mmioDescend(wps->hmmio, &ckMainRIFF, NULL, 0))
        goto errCleanUp;
 
     TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08X\n",
@@ -359,14 +445,14 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg)
        goto errCleanUp;
 
     mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
-    if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK))
+    if (mmioDescend(wps->hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK))
        goto errCleanUp;
 
     TRACE("Chunk Found ckid=%.4s fccType=%08x cksize=%08X\n",
          (LPSTR)&mmckInfo.ckid, mmckInfo.fccType, mmckInfo.cksize);
 
     lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
-    if (mmioRead(hmmio, (HPSTR)lpWaveFormat, mmckInfo.cksize) < 
sizeof(PCMWAVEFORMAT))
+    if (mmioRead(wps->hmmio, (HPSTR)lpWaveFormat, mmckInfo.cksize) < 
sizeof(PCMWAVEFORMAT))
        goto errCleanUp;
 
     TRACE("wFormatTag=%04X !\n",       lpWaveFormat->wFormatTag);
@@ -377,10 +463,10 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg)
     TRACE("wBitsPerSample=%u !\n",     lpWaveFormat->wBitsPerSample);
 
     /* move to end of 'fmt ' chunk */
-    mmioAscend(hmmio, &mmckInfo, 0);
+    mmioAscend(wps->hmmio, &mmckInfo, 0);
 
     mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
-    if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK))
+    if (mmioDescend(wps->hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK))
        goto errCleanUp;
 
     TRACE("Chunk Found ckid=%.4s fccType=%08x cksize=%08X\n",
@@ -413,7 +499,7 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg)
     do {
        left = mmckInfo.cksize;
 
-       mmioSeek(hmmio, mmckInfo.dwDataOffset, SEEK_SET);
+       mmioSeek(wps->hmmio, mmckInfo.dwDataOffset, SEEK_SET);
        while (left)
         {
            if (WaitForSingleObject(psStopEvent, 0) == WAIT_OBJECT_0)
@@ -421,7 +507,7 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg)
                wps->bLoop = FALSE;
                break;
            }
-           count = mmioRead(hmmio, waveHdr[index].lpData, min(bufsize, left));
+           count = mmioRead(wps->hmmio, waveHdr[index].lpData, min(bufsize, 
left));
            if (count < 1) break;
            left -= count;
            waveHdr[index].dwBufferLength = count;
@@ -442,18 +528,45 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg)
     waveOutUnprepareHeader(wps->hWave, &waveHdr[1], sizeof(WAVEHDR));
 
 errCleanUp:
-    TRACE("Done playing=%s => %s!\n", debugstr_w(wps->pszSound), bRet ? "ok" : 
"ko");
+    TRACE("Done playing sound => %s!\n", bRet ? "ok" : "ko");
     CloseHandle(s.hEvent);
     HeapFree(GetProcessHeap(), 0, waveHdr);
     HeapFree(GetProcessHeap(), 0, lpWaveFormat);
     if (wps->hWave)    while (waveOutClose(wps->hWave) == WAVERR_STILLPLAYING) 
Sleep(100);
-    if (hmmio)                 mmioClose(hmmio, 0);
 
     PlaySound_Free(wps);
 
     return bRet;
 }
 
+static DWORD WINAPI PlaySoundAsyncThreadProc(LPVOID lpParameter)
+{
+    WINE_PLAYSOUND *wps = (WINE_PLAYSOUND*)lpParameter;
+
+    /* Play the sound */
+    proc_PlaySound(wps);
+
+    return 0;
+}
+
+static BOOL proc_PlaySoundAsync(WINE_PLAYSOUND *wps)
+{
+    HANDLE hThread;
+
+    /* Create a thread to play the sound asynchronously */
+    hThread = CreateThread(NULL, 0, PlaySoundAsyncThreadProc, wps, 0, NULL);
+    if (hThread)
+    {
+        SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
+        CloseHandle(hThread);
+        return TRUE;
+    }
+
+    /* Error cases */
+    PlaySound_Free(wps);
+    return FALSE;
+}
+
 static BOOL MULTIMEDIA_PlaySound(const void* pszSound, HMODULE hmod, DWORD 
fdwSound, BOOL bUnicode)
 {
     WINE_PLAYSOUND*     wps = NULL;
@@ -470,7 +583,7 @@ static BOOL MULTIMEDIA_PlaySound(const void* pszSound, 
HMODULE hmod, DWORD fdwSo
     /* alloc internal structure, if we need to play something */
     if (pszSound && !(fdwSound & SND_PURGE))
     {
-        if (!(wps = PlaySound_Alloc(pszSound, hmod, fdwSound, bUnicode)))
+        if (!(wps = PlaySound_AllocAndGetMMIO(pszSound, hmod, fdwSound, 
bUnicode)))
             return FALSE;
     }
 
@@ -501,20 +614,12 @@ static BOOL MULTIMEDIA_PlaySound(const void* pszSound, 
HMODULE hmod, DWORD fdwSo
 
     if (fdwSound & SND_ASYNC)
     {
-        DWORD       id;
-        HANDLE      handle;
         wps->bLoop = (fdwSound & SND_LOOP) ? TRUE : FALSE;
-        if ((handle = CreateThread(NULL, 0, proc_PlaySound, wps, 0, &id)) != 
0) {
-            wps->hThread = handle;
-            SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL);
-            return TRUE;
-        }
+        
+        return proc_PlaySoundAsync(wps);
     }
-    else return proc_PlaySound(wps);
-
-    /* error cases */
-    PlaySound_Free(wps);
-    return FALSE;
+    
+    return proc_PlaySound(wps);
 }
 
 /**************************************************************************

Reply via email to