Module: wine Branch: master Commit: c3774b664ad3cfd3b53eae19999489bc16904ff8 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c3774b664ad3cfd3b53eae1999...
Author: Jörg Höhle hoehle@users.sourceforge.net Date: Tue Mar 15 23:00:04 2011 +0100
winmm: Check callback flags prior to opening a driver.
---
dlls/winmm/tests/mixer.c | 35 ++++++++++++++++- dlls/winmm/winmm.c | 98 ++++++++++++++++++++++++++++------------------ 2 files changed, 94 insertions(+), 39 deletions(-)
diff --git a/dlls/winmm/tests/mixer.c b/dlls/winmm/tests/mixer.c index 59627a7..da27b16 100644 --- a/dlls/winmm/tests/mixer.c +++ b/dlls/winmm/tests/mixer.c @@ -1004,6 +1004,7 @@ static void mixer_testsW(void) static void test_mixerOpen(void) { HMIXER mix; + HANDLE event; MMRESULT rc; UINT ndev, d;
@@ -1031,7 +1032,7 @@ static void test_mixerOpen(void)
rc = mixerOpen(&mix, d, 0xdeadbeef, 0, CALLBACK_WINDOW); ok(rc == MMSYSERR_INVALPARAM || - rc == MMSYSERR_NOERROR, /* 98 */ + broken(rc == MMSYSERR_NOERROR /* 98 */), "mixerOpen: MMSYSERR_INVALPARAM expected, got %s\n", mmsys_error(rc)); if (rc == MMSYSERR_NOERROR) @@ -1042,7 +1043,35 @@ static void test_mixerOpen(void) ok(rc == MMSYSERR_NOERROR, "mixerOpen: MMSYSERR_NOERROR expected, got %s\n", mmsys_error(rc)); + if (rc == MMSYSERR_NOERROR) + test_mixerClose(mix); + + rc = mixerOpen(&mix, d, 0, 0, CALLBACK_THREAD); + ok(rc == MMSYSERR_NOERROR /* since w2k */ || + rc == MMSYSERR_NOTSUPPORTED, /* 98 */ + "mixerOpen: MMSYSERR_NOERROR expected, got %s\n", + mmsys_error(rc)); + if (rc == MMSYSERR_NOERROR) + test_mixerClose(mix); + + rc = mixerOpen(&mix, d, 0, 0, CALLBACK_EVENT); + ok(rc == MMSYSERR_NOERROR /* since w2k */ || + rc == MMSYSERR_NOTSUPPORTED, /* 98 */ + "mixerOpen: MMSYSERR_NOERROR expected, got %s\n", + mmsys_error(rc)); + if (rc == MMSYSERR_NOERROR) + test_mixerClose(mix);
+ event = CreateEvent(NULL, FALSE, FALSE, NULL); + ok(event != NULL, "CreateEvent(): error=%d\n", GetLastError()); + + /* NOTSUPPORTED is not broken, but it enables the todo_wine marker. */ + rc = mixerOpen(&mix, d, (DWORD_PTR)event, 0, CALLBACK_EVENT); + todo_wine + ok(rc == MMSYSERR_NOERROR /* since w2k */ || + broken(rc == MMSYSERR_NOTSUPPORTED), /* 98 */ + "mixerOpen: MMSYSERR_NOERROR expected, got %s\n", + mmsys_error(rc)); if (rc == MMSYSERR_NOERROR) test_mixerClose(mix);
@@ -1054,6 +1083,10 @@ static void test_mixerOpen(void)
if (rc == MMSYSERR_NOERROR) test_mixerClose(mix); + + rc = WaitForSingleObject(event, 0); + ok(rc == WAIT_TIMEOUT, "WaitEvent %d\n", rc); + CloseHandle(event); } }
diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c index 6d5950b..29f068b 100644 --- a/dlls/winmm/winmm.c +++ b/dlls/winmm/winmm.c @@ -173,6 +173,35 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad) }
/************************************************************************** + * WINMM_CheckCallback [internal] + */ +static 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; +} + +/************************************************************************** * Mixer devices. New to Win95 */
@@ -297,35 +326,27 @@ UINT WINAPI mixerOpen(LPHMIXER lphMix, UINT uDeviceID, DWORD_PTR dwCallback, { HANDLE hMix; LPWINE_MLD wmld; - DWORD dwRet = 0; + DWORD dwRet; MIXEROPENDESC mod;
TRACE("(%p, %d, %08lx, %08lx, %08x)\n", lphMix, uDeviceID, dwCallback, dwInstance, fdwOpen);
- mod.dwCallback = (DWORD_PTR)MIXER_WCallback; - mod.dwInstance = 0; + dwRet = WINMM_CheckCallback(dwCallback, fdwOpen, TRUE); + if (dwRet != MMSYSERR_NOERROR) + return dwRet;
-/* 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: + mod.dwCallback = (DWORD_PTR)MIXER_WCallback; + 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); @@ -901,19 +922,16 @@ UINT WINAPI midiOutOpen(LPHMIDIOUT lphMidiOut, UINT uDeviceID, { 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;
- switch (dwFlags & CALLBACK_TYPEMASK) { - case CALLBACK_WINDOW: - if (dwCallback && !IsWindow((HWND)dwCallback)) - return MMSYSERR_INVALPARAM; - break; - } + dwRet = WINMM_CheckCallback(dwCallback, dwFlags, FALSE); + if (dwRet != MMSYSERR_NOERROR) + return dwRet;
lpwm = MIDI_OutAlloc(&hMidiOut, &dwCallback, &dwInstance, &dwFlags, 0, NULL);
@@ -1200,13 +1218,17 @@ UINT WINAPI midiInOpen(HMIDIIN* lphMidiIn, UINT uDeviceID, { 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);
@@ -1758,12 +1780,9 @@ MMRESULT WINAPI midiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID, if (cMidi != 1 || lphMidiStrm == NULL || lpuDeviceID == NULL) return MMSYSERR_INVALPARAM;
- switch (fdwOpen & CALLBACK_TYPEMASK) { - case CALLBACK_WINDOW: - if (dwCallback && !IsWindow((HWND)dwCallback)) - return MMSYSERR_INVALPARAM; - break; - } + ret = WINMM_CheckCallback(dwCallback, fdwOpen, FALSE); + if (ret != MMSYSERR_NOERROR) + return ret;
lpMidiStrm = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_MIDIStream)); if (!lpMidiStrm) @@ -2012,7 +2031,7 @@ static UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType, { HANDLE handle; LPWINE_MLD wmld; - DWORD dwRet = MMSYSERR_NOERROR; + DWORD dwRet; WAVEOPENDESC wod;
TRACE("(%p, %d, %s, %p, %08lX, %08lX, %08X);\n", @@ -2022,6 +2041,10 @@ static UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType, 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"); return WAVERR_BADFORMAT; @@ -2039,7 +2062,6 @@ static UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType,
if ((wmld = MMDRV_Alloc(sizeof(WINE_WAVE), uType, &handle, &dwFlags, &dwCallback, &dwInstance)) == NULL) { - WARN("no memory\n"); return MMSYSERR_NOMEM; }