Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=40024 From: Michael Müller michael@fds-team.de Signed-off-by: Vijay Kiran Kamuju infyquest@gmail.com --- dlls/mmsystem.dll16/message16.c | 73 +++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 27 deletions(-)
diff --git a/dlls/mmsystem.dll16/message16.c b/dlls/mmsystem.dll16/message16.c index 28f20ba0b29..c2ffa0d3ab1 100644 --- a/dlls/mmsystem.dll16/message16.c +++ b/dlls/mmsystem.dll16/message16.c @@ -33,6 +33,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(winmm);
+struct mihdrWrap +{ + int ref; + SEGPTR mh16; + MIDIHDR hdr; +}; + /* ================================= * A U X M A P P E R S * ================================= */ @@ -117,13 +124,13 @@ static void MMSYSTDRV_MidiIn_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwPa case MIM_LONGDATA: case MIM_LONGERROR: { - LPMIDIHDR mh32 = (LPMIDIHDR)(*dwParam1); - SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)); + struct mihdrWrap *mh32 = CONTAINING_RECORD((MIDIHDR *)*dwParam1, struct mihdrWrap, hdr); + SEGPTR segmh16 = mh32->mh16; LPMIDIHDR16 mh16 = MapSL(segmh16);
*dwParam1 = (DWORD)segmh16; - mh16->dwFlags = mh32->dwFlags; - mh16->dwBytesRecorded = mh32->dwBytesRecorded; + mh16->dwFlags = mh32->hdr.dwFlags; + mh16->dwBytesRecorded = mh32->hdr.dwBytesRecorded; } break; default: @@ -175,17 +182,17 @@ static MMSYSTEM_MapType MMSYSTDRV_MidiOut_Map16To32W (UINT wMsg, DWORD_PTR* lpP break; case MODM_PREPARE: { - LPMIDIHDR mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR)); + struct mihdrWrap *mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(struct mihdrWrap)); LPMIDIHDR16 mh16 = MapSL(*lpParam1);
if (mh32) { - *(LPMIDIHDR*)mh32 = (LPMIDIHDR)*lpParam1; - mh32 = (LPMIDIHDR)((LPSTR)mh32 + sizeof(LPMIDIHDR)); - mh32->lpData = MapSL((SEGPTR)mh16->lpData); - mh32->dwBufferLength = mh16->dwBufferLength; - mh32->dwBytesRecorded = mh16->dwBytesRecorded; - mh32->dwUser = mh16->dwUser; - mh32->dwFlags = mh16->dwFlags; + mh32->ref = 2; + mh32->mh16 = (SEGPTR)*lpParam1; + mh32->hdr.lpData = MapSL((SEGPTR)mh16->lpData); + mh32->hdr.dwBufferLength = mh16->dwBufferLength; + mh32->hdr.dwBytesRecorded = mh16->dwBytesRecorded; + mh32->hdr.dwUser = mh16->dwUser; + mh32->hdr.dwFlags = mh16->dwFlags; mh16->lpNext = (MIDIHDR16*)mh32; /* for reuse in unprepare and write */ *lpParam1 = (DWORD)mh32; *lpParam2 = offsetof(MIDIHDR,dwOffset); /* old size, without dwOffset */ @@ -200,16 +207,17 @@ static MMSYSTEM_MapType MMSYSTDRV_MidiOut_Map16To32W (UINT wMsg, DWORD_PTR* lpP case MODM_LONGDATA: { LPMIDIHDR16 mh16 = MapSL(*lpParam1); - LPMIDIHDR mh32 = (MIDIHDR*)mh16->lpNext; + struct mihdrWrap *mh32 = (struct mihdrWrap*)mh16->lpNext;
- *lpParam1 = (DWORD)mh32; + mh32->ref++; + *lpParam1 = (DWORD)&mh32->hdr; *lpParam2 = offsetof(MIDIHDR,dwOffset); /* dwBufferLength can be reduced between prepare & write */ - if (wMsg == MODM_LONGDATA && mh32->dwBufferLength < mh16->dwBufferLength) { + if (wMsg == MODM_LONGDATA && mh32->hdr.dwBufferLength < mh16->dwBufferLength) { ERR("Size of buffer has been increased from %d to %d, keeping initial value\n", - mh32->dwBufferLength, mh16->dwBufferLength); + mh32->hdr.dwBufferLength, mh16->dwBufferLength); } else - mh32->dwBufferLength = mh16->dwBufferLength; + mh32->hdr.dwBufferLength = mh16->dwBufferLength; ret = MMSYSTEM_MAP_OKMEM; } break; @@ -267,16 +275,27 @@ static MMSYSTEM_MapType MMSYSTDRV_MidiOut_UnMap16To32W(UINT wMsg, DWORD_PTR* lpP case MODM_UNPREPARE: case MODM_LONGDATA: { - LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1); - LPMIDIHDR16 mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR))); + struct mihdrWrap *mh32 = CONTAINING_RECORD((MIDIHDR *)*lpParam1, struct mihdrWrap, hdr); + LPMIDIHDR16 mh16;
- assert((MIDIHDR*)mh16->lpNext == mh32); - mh16->dwFlags = mh32->dwFlags; + /* Prosound unprepares the buffer during a callback */ + if (mh32->mh16) + { + mh16 = MapSL(mh32->mh16); + assert((struct mihdrWrap *)mh16->lpNext == mh32); + mh16->dwFlags = mh32->hdr.dwFlags;
- if (wMsg == MODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) { - HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR)); - mh16->lpNext = 0; + if (wMsg == MODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) + { + mh32->mh16 = 0; + mh32->ref--; + mh16->lpNext = 0; + } } + + if (!--mh32->ref) + HeapFree(GetProcessHeap(), 0, mh32); + ret = MMSYSTEM_MAP_OK; } break; @@ -307,12 +326,12 @@ static void MMSYSTDRV_MidiOut_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwP case MOM_DONE: { /* initial map is: 16 => 32 */ - LPMIDIHDR mh32 = (LPMIDIHDR)(*dwParam1); - SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)); + struct mihdrWrap *mh32 = CONTAINING_RECORD((MIDIHDR *)*dwParam1, struct mihdrWrap, hdr); + SEGPTR segmh16 = mh32->mh16; LPMIDIHDR16 mh16 = MapSL(segmh16);
*dwParam1 = (DWORD)segmh16; - mh16->dwFlags = mh32->dwFlags; + mh16->dwFlags = mh32->hdr.dwFlags; } break; default: