From f18111b64120806529e93404f21b6320f211ec39 Mon Sep 17 00:00:00 2001 From: Thamatip Chitpong Date: Fri, 5 May 2023 19:19:34 +0700 Subject: [PATCH] [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 | 517 ++++++++++++++++++------------ 2 files changed, 323 insertions(+), 209 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\ */ - 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 - { - UNICODE_STRING usBuffer; - RtlCreateUnicodeStringFromAsciiz(&usBuffer, pszSound); - wps->pszSound = usBuffer.Buffer; - if (!wps->pszSound) goto oom_error; - wps->bAlloc = TRUE; - } + RtlCreateUnicodeStringFromAsciiz(&usBuffer, pszSound); + if (!usBuffer.Buffer) + return NULL; + + pszSoundW = usBuffer.Buffer; } else - wps->pszSound = pszSound; + { + 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) + { + PlaySound_Free(wps); + wps = NULL; + } + } + + 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); } /**************************************************************************