From a8f1d2eb2f55f49fcbfe306946d37f3074eeab64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20H=C3=B6hle?= Date: Tue, 16 Feb 2010 10:31:05 +0100 Subject: [PATCH] winmm: MIDIHDR.dwOffset is set with MEVT_F_CALLBACK only. At the same time, the change to the player loop prevents a buffer overshoot and a (perhaps unlikely) program trace where a sequence Suspend; Stop; midiStreamOut could send MOM_DONE twice and access memory possibly released within a MOM_DONE DCB_FUNCTION callback. --- dlls/winmm/winmm.c | 66 +++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c index 1898e285240..06aed09587f 100644 --- a/dlls/winmm/winmm.c +++ b/dlls/winmm/winmm.c @@ -1577,7 +1577,6 @@ static BOOL MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream* lpMidiStrm, LPWI lpMidiHdr->lpNext = 0; lpMidiHdr->dwFlags |= MHDR_INQUEUE; lpMidiHdr->dwFlags &= ~MHDR_DONE; - lpMidiHdr->dwOffset = 0; break; default: @@ -1598,8 +1597,7 @@ static DWORD CALLBACK MMSYSTEM_MidiStream_Player(LPVOID pmt) DWORD dwToGo; DWORD dwCurrTC; LPMIDIHDR lpMidiHdr; - LPMIDIEVENT me; - LPBYTE lpData = 0; + DWORD dwOffset; TRACE("(%p)!\n", lpMidiStrm); @@ -1618,23 +1616,21 @@ static DWORD CALLBACK MMSYSTEM_MidiStream_Player(LPVOID pmt) /* midiStreamOpen is waiting for ack */ SetEvent(lpMidiStrm->hEvent); - for (;;) { - lpMidiHdr = lpMidiStrm->lpMidiHdr; - if (!lpMidiHdr) { - /* for first message, block until one arrives, then process all that are available */ - GetMessageA(&msg, 0, 0, 0); - do { - if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm, lpwm, &msg)) - goto the_end; - } while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)); - lpData = 0; - continue; - } +start_header: + lpMidiHdr = lpMidiStrm->lpMidiHdr; + if (!lpMidiHdr) { + /* for first message, block until one arrives, then process all that are available */ + GetMessageA(&msg, 0, 0, 0); + do { + if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm, lpwm, &msg)) + goto the_end; + } while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)); + goto start_header; + } - if (!lpData) - lpData = (LPBYTE)lpMidiHdr->lpData; - - me = (LPMIDIEVENT)(lpData + lpMidiHdr->dwOffset); + dwOffset = 0; + while (dwOffset + offsetof(MIDIEVENT,dwParms) <= lpMidiHdr->dwBytesRecorded) { + LPMIDIEVENT me = (LPMIDIEVENT)(lpMidiHdr->lpData+dwOffset); /* do we have to wait ? */ if (me->dwDeltaTime) { @@ -1650,8 +1646,11 @@ static DWORD CALLBACK MMSYSTEM_MidiStream_Player(LPVOID pmt) while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm, lpwm, &msg)) goto the_end; + /* is lpMidiHdr still current? */ + if (lpMidiHdr != lpMidiStrm->lpMidiHdr) { + goto start_header; + } } - lpData = 0; } else { /* timeout, so me->dwDeltaTime is elapsed, can break the while loop */ break; @@ -1681,25 +1680,26 @@ static DWORD CALLBACK MMSYSTEM_MidiStream_Player(LPVOID pmt) break; } if (me->dwEvent & MEVT_F_CALLBACK) { + /* native fills dwOffset regardless of the cbMidiHdr size argument to midiStreamOut */ + lpMidiHdr->dwOffset = dwOffset; DriverCallback(lpwm->mod.dwCallback, lpMidiStrm->wFlags, (HDRVR)lpMidiStrm->hDevice, MM_MOM_POSITIONCB, lpwm->mod.dwInstance, (LPARAM)lpMidiHdr, 0L); } - lpMidiHdr->dwOffset += sizeof(MIDIEVENT) - sizeof(me->dwParms); + dwOffset += offsetof(MIDIEVENT,dwParms); if (me->dwEvent & MEVT_F_LONG) - lpMidiHdr->dwOffset += (MEVT_EVENTPARM(me->dwEvent) + 3) & ~3; - if (lpMidiHdr->dwOffset >= lpMidiHdr->dwBytesRecorded) { - /* done with this header */ - lpMidiHdr->dwFlags |= MHDR_DONE; - lpMidiHdr->dwFlags &= ~MHDR_INQUEUE; - - lpMidiStrm->lpMidiHdr = lpMidiHdr->lpNext; - DriverCallback(lpwm->mod.dwCallback, lpMidiStrm->wFlags, - (HDRVR)lpMidiStrm->hDevice, MM_MOM_DONE, - lpwm->mod.dwInstance, (DWORD_PTR)lpMidiHdr, 0); - lpData = 0; - } + dwOffset += (MEVT_EVENTPARM(me->dwEvent) + 3) & ~3; } + /* done with this header */ + lpMidiStrm->lpMidiHdr = lpMidiHdr->lpNext; + lpMidiHdr->dwFlags |= MHDR_DONE; + lpMidiHdr->dwFlags &= ~MHDR_INQUEUE; + + DriverCallback(lpwm->mod.dwCallback, lpMidiStrm->wFlags, + (HDRVR)lpMidiStrm->hDevice, MM_MOM_DONE, + lpwm->mod.dwInstance, (DWORD_PTR)lpMidiHdr, 0); + goto start_header; + the_end: TRACE("End of thread\n"); return 0;