Jörg Höhle : winmm: MIDIHDR. dwOffset is set with MEVT_F_CALLBACK only.
Alexandre Julliard
julliard at winehq.org
Mon Feb 22 08:46:56 CST 2010
Module: wine
Branch: master
Commit: a8f1d2eb2f55f49fcbfe306946d37f3074eeab64
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a8f1d2eb2f55f49fcbfe306946d37f3074eeab64
Author: Jörg Höhle <hoehle at users.sourceforge.net>
Date: Tue Feb 16 10:31:05 2010 +0100
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 files changed, 33 insertions(+), 33 deletions(-)
diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c
index 1898e28..06aed09 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;
- }
-
- if (!lpData)
- lpData = (LPBYTE)lpMidiHdr->lpData;
+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;
+ }
- 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;
More information about the wine-cvs
mailing list