https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f18111b64120806529e93…
commit f18111b64120806529e93404f21b6320f211ec39
Author: Thamatip Chitpong <tangaming123456(a)outlook.com>
AuthorDate: Fri May 5 19:19:34 2023 +0700
Commit: GitHub <noreply(a)github.com>
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);
}
/**************************************************************************