Jörg Höhle : winmm: Check callback flags prior to opening a driver.
Alexandre Julliard
julliard at winehq.org
Mon Apr 4 10:10:57 CDT 2011
Module: wine
Branch: master
Commit: c3774b664ad3cfd3b53eae19999489bc16904ff8
URL: http://source.winehq.org/git/wine.git/?a=commit;h=c3774b664ad3cfd3b53eae19999489bc16904ff8
Author: Jörg Höhle <hoehle at 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;
}
More information about the wine-cvs
mailing list