Author: tfaber Date: Thu Mar 26 09:53:23 2015 New Revision: 66900
URL: http://svn.reactos.org/svn/reactos?rev=66900&view=rev Log: [WINMM] - Apply Wine commit b1d9d43a (winmm: Don't mask out SND_ALIAS_ID or SND_FILENAME in sndPlaySound.) by Andrew Eikum. Fixes crash in winmm_winetest:wave - Import WINMM_CheckCallback from Wine and use it, various cleanups (commits cb77f9a2, 06d6dd3e, e6a501bb, a311dff7 by Jörg Höhle). In particular, accepting a NULL callback in DriverCallback fixes the crash in winmm_winetest:wave. CORE-9401 #resolve
Modified: trunk/reactos/dll/win32/winmm/driver.c trunk/reactos/dll/win32/winmm/playsound.c trunk/reactos/dll/win32/winmm/winemm.h trunk/reactos/dll/win32/winmm/winmm.c
Modified: trunk/reactos/dll/win32/winmm/driver.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winmm/driver.c?re... ============================================================================== --- trunk/reactos/dll/win32/winmm/driver.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/winmm/driver.c [iso-8859-1] Thu Mar 26 09:53:23 2015 @@ -569,36 +569,49 @@ }
/************************************************************************** + * DRIVER_getCallback [internal] + */ +static const char* DRIVER_getCallback(DWORD uFlags) +{ + switch(uFlags & DCB_TYPEMASK) { + case DCB_NULL: return "null"; + case DCB_WINDOW: return "window"; + case DCB_TASK: return "task"; + case DCB_EVENT: return "event"; + case DCB_FUNCTION: return "32bit function"; + default: return "UNKNOWN"; + } +} + +/************************************************************************** * DriverCallback [WINMM.@] */ BOOL WINAPI DriverCallback(DWORD_PTR dwCallBack, DWORD uFlags, HDRVR hDev, DWORD wMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { - TRACE("(%08lX, %04X, %p, %04X, %08lX, %08lX, %08lX)\n", - dwCallBack, uFlags, hDev, wMsg, dwUser, dwParam1, dwParam2); + BOOL ret = FALSE; + TRACE("(%08lX, %s %04X, %p, %04X, %08lX, %08lX, %08lX)\n", + dwCallBack, DRIVER_getCallback(uFlags), uFlags, hDev, wMsg, dwUser, dwParam1, dwParam2); + if (!dwCallBack) + return ret;
switch (uFlags & DCB_TYPEMASK) { case DCB_NULL: - TRACE("Null !\n"); - if (dwCallBack) - WARN("uFlags=%04X has null DCB value, but dwCallBack=%08lX is not null !\n", uFlags, dwCallBack); - break; + /* Native returns FALSE = no notification, not TRUE */ + return ret; case DCB_WINDOW: - TRACE("Window(%04lX) handle=%p!\n", dwCallBack, hDev); - PostMessageA((HWND)dwCallBack, wMsg, (WPARAM)hDev, dwParam1); + ret = PostMessageA((HWND)dwCallBack, wMsg, (WPARAM)hDev, dwParam1); break; case DCB_TASK: /* aka DCB_THREAD */ - TRACE("Task(%04lx) !\n", dwCallBack); - PostThreadMessageA(dwCallBack, wMsg, (WPARAM)hDev, dwParam1); + ret = PostThreadMessageA(dwCallBack, wMsg, (WPARAM)hDev, dwParam1); break; case DCB_FUNCTION: - TRACE("Function (32 bit) !\n"); ((LPDRVCALLBACK)dwCallBack)(hDev, wMsg, dwUser, dwParam1, dwParam2); + ret = TRUE; break; case DCB_EVENT: - TRACE("Event(%08lx) !\n", dwCallBack); - SetEvent((HANDLE)dwCallBack); + ret = SetEvent((HANDLE)dwCallBack); break; #if 0 /* FIXME: for now only usable in mmsystem.dll16 @@ -630,8 +643,11 @@ WARN("Unknown callback type %d\n", uFlags & DCB_TYPEMASK); return FALSE; } - TRACE("Done\n"); - return TRUE; + if (ret) + TRACE("Done\n"); + else + WARN("Notification failure\n"); + return ret; }
/******************************************************************
Modified: trunk/reactos/dll/win32/winmm/playsound.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winmm/playsound.c... ============================================================================== --- trunk/reactos/dll/win32/winmm/playsound.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/winmm/playsound.c [iso-8859-1] Thu Mar 26 09:53:23 2015 @@ -538,7 +538,7 @@ */ BOOL WINAPI sndPlaySoundA(LPCSTR pszSoundA, UINT uFlags) { - uFlags &= SND_ASYNC|SND_LOOP|SND_MEMORY|SND_NODEFAULT|SND_NOSTOP|SND_SYNC; + uFlags &= SND_ALIAS_ID|SND_FILENAME|SND_ASYNC|SND_LOOP|SND_MEMORY|SND_NODEFAULT|SND_NOSTOP|SND_SYNC; return MULTIMEDIA_PlaySound(pszSoundA, 0, uFlags, FALSE); }
@@ -547,7 +547,7 @@ */ BOOL WINAPI sndPlaySoundW(LPCWSTR pszSound, UINT uFlags) { - uFlags &= SND_ASYNC|SND_LOOP|SND_MEMORY|SND_NODEFAULT|SND_NOSTOP|SND_SYNC; + uFlags &= SND_ALIAS_ID|SND_FILENAME|SND_ASYNC|SND_LOOP|SND_MEMORY|SND_NODEFAULT|SND_NOSTOP|SND_SYNC; return MULTIMEDIA_PlaySound(pszSound, 0, uFlags, TRUE); }
Modified: trunk/reactos/dll/win32/winmm/winemm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winmm/winemm.h?re... ============================================================================== --- trunk/reactos/dll/win32/winmm/winemm.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/winmm/winemm.h [iso-8859-1] Thu Mar 26 09:53:23 2015 @@ -179,6 +179,8 @@
void TIME_MMTimeStop(void);
+MMRESULT WINMM_CheckCallback(DWORD_PTR dwCallback, DWORD fdwOpen, BOOL mixer) DECLSPEC_HIDDEN; + /* Global variables */ extern CRITICAL_SECTION WINMM_cs; extern HINSTANCE hWinMM32Instance;
Modified: trunk/reactos/dll/win32/winmm/winmm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winmm/winmm.c?rev... ============================================================================== --- trunk/reactos/dll/win32/winmm/winmm.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/winmm/winmm.c [iso-8859-1] Thu Mar 26 09:53:23 2015 @@ -140,6 +140,10 @@ ERR_TO_STR(WAVERR_STILLPLAYING); ERR_TO_STR(WAVERR_UNPREPARED); ERR_TO_STR(WAVERR_SYNC); + ERR_TO_STR(MIDIERR_INVALIDSETUP); + ERR_TO_STR(MIDIERR_NODEVICE); + ERR_TO_STR(MIDIERR_STILLPLAYING); + ERR_TO_STR(MIDIERR_UNPREPARED); } sprintf(unknown, "Unknown(0x%08x)", error); return unknown; @@ -184,6 +188,35 @@ break; } return TRUE; +} + +/************************************************************************** + * WINMM_CheckCallback [internal] + */ +MMRESULT WINMM_CheckCallback(DWORD_PTR dwCallback, DWORD fdwOpen, BOOL mixer) +{ + switch (fdwOpen & CALLBACK_TYPEMASK) { + case CALLBACK_NULL: /* dwCallback need not be NULL */ + break; + case CALLBACK_WINDOW: + if (dwCallback && !IsWindow((HWND)dwCallback)) + return MMSYSERR_INVALPARAM; + break; + + case CALLBACK_FUNCTION: + /* a NULL cb is acceptable since w2k, MMSYSERR_INVALPARAM earlier */ + if (mixer) + return MMSYSERR_INVALFLAG; /* since w2k, MMSYSERR_NOTSUPPORTED earlier */ + break; + case CALLBACK_THREAD: + case CALLBACK_EVENT: + if (mixer) /* FIXME: mixer supports THREAD+EVENT since w2k */ + return MMSYSERR_NOTSUPPORTED; /* w9X */ + break; + default: + WARN("Unknown callback type %d\n", HIWORD(fdwOpen)); + } + return MMSYSERR_NOERROR; }
/************************************************************************** @@ -311,35 +344,27 @@ { HANDLE hMix; LPWINE_MLD wmld; - DWORD dwRet = 0; + DWORD dwRet; MIXEROPENDESC mod;
TRACE("(%p, %d, %08lx, %08lx, %08x)\n", lphMix, uDeviceID, dwCallback, dwInstance, fdwOpen);
+ dwRet = WINMM_CheckCallback(dwCallback, fdwOpen, TRUE); + if(dwRet != MMSYSERR_NOERROR) + return dwRet; + mod.dwCallback = (DWORD_PTR)MIXER_WCallback; - mod.dwInstance = 0; - -/* If callback is a function, - * dwCallback contains function pointer - * dwInstance private data - * - * if callback is a window - * dwCallback contains a window handle - */ - switch (fdwOpen & CALLBACK_TYPEMASK) { - default: - return MMSYSERR_INVALFLAG; - - case CALLBACK_NULL: - break; - - case CALLBACK_WINDOW: + if ((fdwOpen & CALLBACK_TYPEMASK) == CALLBACK_WINDOW) mod.dwInstance = dwCallback; - if (dwCallback && !IsWindow((HWND)dwCallback)) - return MMSYSERR_INVALPARAM; - break; - } + else + mod.dwInstance = 0; + + /* We're remapping to CALLBACK_FUNCTION because that's what old winmm is + * documented to do when opening the mixer driver. + * FIXME: Native supports CALLBACK_EVENT + CALLBACK_THREAD flags since w2k. + * FIXME: The non ALSA drivers ignore callback requests - bug. + */
wmld = MMDRV_Alloc(sizeof(WINE_MIXER), MMDRV_MIXER, &hMix, &fdwOpen, &dwCallback, &dwInstance); @@ -897,8 +922,7 @@ lpwm = (LPWINE_MIDI)MMDRV_Alloc(size, MMDRV_MIDIOUT, &hMidiOut, lpdwFlags, lpdwCallback, lpdwInstance);
- if (lphMidiOut != NULL) - *lphMidiOut = hMidiOut; + *lphMidiOut = hMidiOut;
if (lpwm) { lpwm->mod.hMidi = hMidiOut; @@ -920,12 +944,16 @@ { HMIDIOUT hMidiOut; LPWINE_MIDI lpwm; - UINT dwRet = 0; + UINT dwRet;
TRACE("(%p, %d, %08lX, %08lX, %08X);\n", lphMidiOut, uDeviceID, dwCallback, dwInstance, dwFlags);
if (lphMidiOut != NULL) *lphMidiOut = 0; + + dwRet = WINMM_CheckCallback(dwCallback, dwFlags, FALSE); + if (dwRet != MMSYSERR_NOERROR) + return dwRet;
lpwm = MIDI_OutAlloc(&hMidiOut, &dwCallback, &dwInstance, &dwFlags, 0, NULL);
@@ -1211,12 +1239,16 @@ { HANDLE hMidiIn; LPWINE_MIDI lpwm; - DWORD dwRet = 0; + DWORD dwRet;
TRACE("(%p, %d, %08lX, %08lX, %08X);\n", lphMidiIn, uDeviceID, dwCallback, dwInstance, dwFlags);
if (lphMidiIn != NULL) *lphMidiIn = 0; + + dwRet = WINMM_CheckCallback(dwCallback, dwFlags, FALSE); + if (dwRet != MMSYSERR_NOERROR) + return dwRet;
lpwm = (LPWINE_MIDI)MMDRV_Alloc(sizeof(WINE_MIDI), MMDRV_MIDIIN, &hMidiIn, &dwFlags, &dwCallback, &dwInstance); @@ -1779,6 +1811,10 @@ if (cMidi != 1 || lphMidiStrm == NULL || lpuDeviceID == NULL) return MMSYSERR_INVALPARAM;
+ ret = WINMM_CheckCallback(dwCallback, fdwOpen, FALSE); + if (ret != MMSYSERR_NOERROR) + return ret; + lpMidiStrm = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_MIDIStream)); if (!lpMidiStrm) return MMSYSERR_NOMEM; @@ -1792,8 +1828,7 @@ mosm.wDeviceID = *lpuDeviceID; lpwm = MIDI_OutAlloc(&hMidiOut, &dwCallback, &dwInstance, &fdwOpen, 1, &mosm); lpMidiStrm->hDevice = hMidiOut; - if (lphMidiStrm) - *lphMidiStrm = (HMIDISTRM)hMidiOut; + *lphMidiStrm = (HMIDISTRM)hMidiOut;
lpwm->mld.uDeviceID = *lpuDeviceID;
@@ -1839,11 +1874,23 @@
TRACE("(%p, %p, %u)!\n", hMidiStrm, lpMidiHdr, cbMidiHdr);
+ if (cbMidiHdr < offsetof(MIDIHDR,dwOffset) || !lpMidiHdr || !lpMidiHdr->lpData + || lpMidiHdr->dwBufferLength < lpMidiHdr->dwBytesRecorded + || lpMidiHdr->dwBytesRecorded % 4 /* player expects DWORD padding */) + return MMSYSERR_INVALPARAM; + /* FIXME: Native additionally checks if the MIDIEVENTs in lpData + * exactly fit dwBytesRecorded. */ + + if (!(lpMidiHdr->dwFlags & MHDR_PREPARED)) + return MIDIERR_UNPREPARED; + + if (lpMidiHdr->dwFlags & MHDR_INQUEUE) + return MIDIERR_STILLPLAYING; + if (!MMSYSTEM_GetMidiStream(hMidiStrm, &lpMidiStrm, NULL)) { ret = MMSYSERR_INVALHANDLE; - } else if (!lpMidiHdr) { - ret = MMSYSERR_INVALPARAM; } else { + lpMidiHdr->dwFlags |= MHDR_ISSTRM; if (!PostThreadMessageA(lpMidiStrm->dwThreadID, WINE_MSM_HEADER, cbMidiHdr, (LPARAM)lpMidiHdr)) { @@ -2011,7 +2058,7 @@ { HANDLE handle; LPWINE_MLD wmld; - DWORD dwRet = MMSYSERR_NOERROR; + DWORD dwRet; WAVEOPENDESC wod;
TRACE("(%p, %d, %s, %p, %08lX, %08lX, %08X);\n", @@ -2020,6 +2067,10 @@
if (dwFlags & WAVE_FORMAT_QUERY) TRACE("WAVE_FORMAT_QUERY requested !\n"); + + dwRet = WINMM_CheckCallback(dwCallback, dwFlags, FALSE); + if (dwRet != MMSYSERR_NOERROR) + return dwRet;
if (lpFormat == NULL) { WARN("bad format\n"); @@ -2038,7 +2089,6 @@
if ((wmld = MMDRV_Alloc(sizeof(WINE_WAVE), uType, &handle, &dwFlags, &dwCallback, &dwInstance)) == NULL) { - WARN("no memory\n"); return MMSYSERR_NOMEM; }