Commit c3774b66 authored by Jörg Höhle's avatar Jörg Höhle Committed by Alexandre Julliard

winmm: Check callback flags prior to opening a driver.

parent cb77f9a2
...@@ -1004,6 +1004,7 @@ static void mixer_testsW(void) ...@@ -1004,6 +1004,7 @@ static void mixer_testsW(void)
static void test_mixerOpen(void) static void test_mixerOpen(void)
{ {
HMIXER mix; HMIXER mix;
HANDLE event;
MMRESULT rc; MMRESULT rc;
UINT ndev, d; UINT ndev, d;
...@@ -1031,7 +1032,7 @@ static void test_mixerOpen(void) ...@@ -1031,7 +1032,7 @@ static void test_mixerOpen(void)
rc = mixerOpen(&mix, d, 0xdeadbeef, 0, CALLBACK_WINDOW); rc = mixerOpen(&mix, d, 0xdeadbeef, 0, CALLBACK_WINDOW);
ok(rc == MMSYSERR_INVALPARAM || ok(rc == MMSYSERR_INVALPARAM ||
rc == MMSYSERR_NOERROR, /* 98 */ broken(rc == MMSYSERR_NOERROR /* 98 */),
"mixerOpen: MMSYSERR_INVALPARAM expected, got %s\n", "mixerOpen: MMSYSERR_INVALPARAM expected, got %s\n",
mmsys_error(rc)); mmsys_error(rc));
if (rc == MMSYSERR_NOERROR) if (rc == MMSYSERR_NOERROR)
...@@ -1042,7 +1043,35 @@ static void test_mixerOpen(void) ...@@ -1042,7 +1043,35 @@ static void test_mixerOpen(void)
ok(rc == MMSYSERR_NOERROR, ok(rc == MMSYSERR_NOERROR,
"mixerOpen: MMSYSERR_NOERROR expected, got %s\n", "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
mmsys_error(rc)); 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) if (rc == MMSYSERR_NOERROR)
test_mixerClose(mix); test_mixerClose(mix);
...@@ -1054,6 +1083,10 @@ static void test_mixerOpen(void) ...@@ -1054,6 +1083,10 @@ static void test_mixerOpen(void)
if (rc == MMSYSERR_NOERROR) if (rc == MMSYSERR_NOERROR)
test_mixerClose(mix); test_mixerClose(mix);
rc = WaitForSingleObject(event, 0);
ok(rc == WAIT_TIMEOUT, "WaitEvent %d\n", rc);
CloseHandle(event);
} }
} }
......
...@@ -173,6 +173,35 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad) ...@@ -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 * Mixer devices. New to Win95
*/ */
...@@ -297,35 +326,27 @@ UINT WINAPI mixerOpen(LPHMIXER lphMix, UINT uDeviceID, DWORD_PTR dwCallback, ...@@ -297,35 +326,27 @@ UINT WINAPI mixerOpen(LPHMIXER lphMix, UINT uDeviceID, DWORD_PTR dwCallback,
{ {
HANDLE hMix; HANDLE hMix;
LPWINE_MLD wmld; LPWINE_MLD wmld;
DWORD dwRet = 0; DWORD dwRet;
MIXEROPENDESC mod; MIXEROPENDESC mod;
TRACE("(%p, %d, %08lx, %08lx, %08x)\n", TRACE("(%p, %d, %08lx, %08lx, %08x)\n",
lphMix, uDeviceID, dwCallback, dwInstance, fdwOpen); lphMix, uDeviceID, dwCallback, dwInstance, fdwOpen);
mod.dwCallback = (DWORD_PTR)MIXER_WCallback; dwRet = WINMM_CheckCallback(dwCallback, fdwOpen, TRUE);
mod.dwInstance = 0; if (dwRet != MMSYSERR_NOERROR)
return dwRet;
/* If callback is a function, mod.dwCallback = (DWORD_PTR)MIXER_WCallback;
* dwCallback contains function pointer if ((fdwOpen & CALLBACK_TYPEMASK) == CALLBACK_WINDOW)
* 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.dwInstance = dwCallback; mod.dwInstance = dwCallback;
if (dwCallback && !IsWindow((HWND)dwCallback)) else
return MMSYSERR_INVALPARAM; mod.dwInstance = 0;
break;
} /* 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, wmld = MMDRV_Alloc(sizeof(WINE_MIXER), MMDRV_MIXER, &hMix, &fdwOpen,
&dwCallback, &dwInstance); &dwCallback, &dwInstance);
...@@ -901,19 +922,16 @@ UINT WINAPI midiOutOpen(LPHMIDIOUT lphMidiOut, UINT uDeviceID, ...@@ -901,19 +922,16 @@ UINT WINAPI midiOutOpen(LPHMIDIOUT lphMidiOut, UINT uDeviceID,
{ {
HMIDIOUT hMidiOut; HMIDIOUT hMidiOut;
LPWINE_MIDI lpwm; LPWINE_MIDI lpwm;
UINT dwRet = 0; UINT dwRet;
TRACE("(%p, %d, %08lX, %08lX, %08X);\n", TRACE("(%p, %d, %08lX, %08lX, %08X);\n",
lphMidiOut, uDeviceID, dwCallback, dwInstance, dwFlags); lphMidiOut, uDeviceID, dwCallback, dwInstance, dwFlags);
if (lphMidiOut != NULL) *lphMidiOut = 0; if (lphMidiOut != NULL) *lphMidiOut = 0;
switch (dwFlags & CALLBACK_TYPEMASK) { dwRet = WINMM_CheckCallback(dwCallback, dwFlags, FALSE);
case CALLBACK_WINDOW: if (dwRet != MMSYSERR_NOERROR)
if (dwCallback && !IsWindow((HWND)dwCallback)) return dwRet;
return MMSYSERR_INVALPARAM;
break;
}
lpwm = MIDI_OutAlloc(&hMidiOut, &dwCallback, &dwInstance, &dwFlags, 0, NULL); lpwm = MIDI_OutAlloc(&hMidiOut, &dwCallback, &dwInstance, &dwFlags, 0, NULL);
...@@ -1200,13 +1218,17 @@ UINT WINAPI midiInOpen(HMIDIIN* lphMidiIn, UINT uDeviceID, ...@@ -1200,13 +1218,17 @@ UINT WINAPI midiInOpen(HMIDIIN* lphMidiIn, UINT uDeviceID,
{ {
HANDLE hMidiIn; HANDLE hMidiIn;
LPWINE_MIDI lpwm; LPWINE_MIDI lpwm;
DWORD dwRet = 0; DWORD dwRet;
TRACE("(%p, %d, %08lX, %08lX, %08X);\n", TRACE("(%p, %d, %08lX, %08lX, %08X);\n",
lphMidiIn, uDeviceID, dwCallback, dwInstance, dwFlags); lphMidiIn, uDeviceID, dwCallback, dwInstance, dwFlags);
if (lphMidiIn != NULL) *lphMidiIn = 0; 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, lpwm = (LPWINE_MIDI)MMDRV_Alloc(sizeof(WINE_MIDI), MMDRV_MIDIIN, &hMidiIn,
&dwFlags, &dwCallback, &dwInstance); &dwFlags, &dwCallback, &dwInstance);
...@@ -1758,12 +1780,9 @@ MMRESULT WINAPI midiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID, ...@@ -1758,12 +1780,9 @@ MMRESULT WINAPI midiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID,
if (cMidi != 1 || lphMidiStrm == NULL || lpuDeviceID == NULL) if (cMidi != 1 || lphMidiStrm == NULL || lpuDeviceID == NULL)
return MMSYSERR_INVALPARAM; return MMSYSERR_INVALPARAM;
switch (fdwOpen & CALLBACK_TYPEMASK) { ret = WINMM_CheckCallback(dwCallback, fdwOpen, FALSE);
case CALLBACK_WINDOW: if (ret != MMSYSERR_NOERROR)
if (dwCallback && !IsWindow((HWND)dwCallback)) return ret;
return MMSYSERR_INVALPARAM;
break;
}
lpMidiStrm = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_MIDIStream)); lpMidiStrm = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_MIDIStream));
if (!lpMidiStrm) if (!lpMidiStrm)
...@@ -2012,7 +2031,7 @@ static UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType, ...@@ -2012,7 +2031,7 @@ static UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType,
{ {
HANDLE handle; HANDLE handle;
LPWINE_MLD wmld; LPWINE_MLD wmld;
DWORD dwRet = MMSYSERR_NOERROR; DWORD dwRet;
WAVEOPENDESC wod; WAVEOPENDESC wod;
TRACE("(%p, %d, %s, %p, %08lX, %08lX, %08X);\n", TRACE("(%p, %d, %s, %p, %08lX, %08lX, %08X);\n",
...@@ -2022,6 +2041,10 @@ static UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType, ...@@ -2022,6 +2041,10 @@ static UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType,
if (dwFlags & WAVE_FORMAT_QUERY) if (dwFlags & WAVE_FORMAT_QUERY)
TRACE("WAVE_FORMAT_QUERY requested !\n"); TRACE("WAVE_FORMAT_QUERY requested !\n");
dwRet = WINMM_CheckCallback(dwCallback, dwFlags, FALSE);
if (dwRet != MMSYSERR_NOERROR)
return dwRet;
if (lpFormat == NULL) { if (lpFormat == NULL) {
WARN("bad format\n"); WARN("bad format\n");
return WAVERR_BADFORMAT; return WAVERR_BADFORMAT;
...@@ -2039,7 +2062,6 @@ static UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType, ...@@ -2039,7 +2062,6 @@ static UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType,
if ((wmld = MMDRV_Alloc(sizeof(WINE_WAVE), uType, &handle, if ((wmld = MMDRV_Alloc(sizeof(WINE_WAVE), uType, &handle,
&dwFlags, &dwCallback, &dwInstance)) == NULL) { &dwFlags, &dwCallback, &dwInstance)) == NULL) {
WARN("no memory\n");
return MMSYSERR_NOMEM; return MMSYSERR_NOMEM;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment