Added patches to fix multiple issues in mmsystem.dll16 when translating MIDI messages.

This commit is contained in:
Sebastian Lackner 2016-02-27 01:11:58 +01:00
parent bfebdf34eb
commit 177b54d90f
4 changed files with 364 additions and 0 deletions

View File

@ -0,0 +1,184 @@
From 777db4a5e0c6058253b471640c9ae6dbf0e159da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Fri, 26 Feb 2016 03:54:28 +0100
Subject: mmsystem.dll16: Refcount midihdr to work around buggy application
which unprepares buffer during a callback.
---
dlls/mmsystem.dll16/message16.c | 121 ++++++++++++++++++++++++----------------
1 file changed, 73 insertions(+), 48 deletions(-)
diff --git a/dlls/mmsystem.dll16/message16.c b/dlls/mmsystem.dll16/message16.c
index 012d3dc..e0df741 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, DW
case MIM_LONGDATA:
case MIM_LONGERROR:
{
- LPMIDIHDR mh32 = (LPMIDIHDR)(*dwParam1);
- SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
- LPMIDIHDR16 mh16 = MapSL(segmh16);
+ struct mihdrWrap *mh32 = CONTAINING_RECORD(*dwParam1, struct mihdrWrap, hdr);
+ SEGPTR segmh16 = mh32->mh16;
+ LPMIDIHDR16 mh16 = MapSL(segmh16);
- *dwParam1 = (DWORD)segmh16;
- mh16->dwFlags = mh32->dwFlags;
- mh16->dwBytesRecorded = mh32->dwBytesRecorded;
+ *dwParam1 = (DWORD)segmh16;
+ mh16->dwFlags = mh32->hdr.dwFlags;
+ mh16->dwBytesRecorded = mh32->hdr.dwBytesRecorded;
}
break;
default:
@@ -175,41 +182,48 @@ static MMSYSTEM_MapType MMSYSTDRV_MidiOut_Map16To32W (UINT wMsg, DWORD_PTR* lpP
break;
case MODM_PREPARE:
{
- LPMIDIHDR mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR));
- 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;
- mh16->lpNext = (MIDIHDR16*)mh32; /* for reuse in unprepare and write */
- *lpParam1 = (DWORD)mh32;
- *lpParam2 = offsetof(MIDIHDR,dwOffset); /* old size, without dwOffset */
+ struct mihdrWrap *mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(struct mihdrWrap));
+ LPMIDIHDR16 mh16 = MapSL(*lpParam1);
- ret = MMSYSTEM_MAP_OKMEM;
- } else {
- ret = MMSYSTEM_MAP_NOMEM;
- }
+ if (mh32)
+ {
+ 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->hdr;
+ *lpParam2 = offsetof(MIDIHDR,dwOffset); /* old size, without dwOffset */
+
+ ret = MMSYSTEM_MAP_OKMEM;
+ }
+ else
+ ret = MMSYSTEM_MAP_NOMEM;
}
break;
case MODM_UNPREPARE:
case MODM_LONGDATA:
{
- LPMIDIHDR16 mh16 = MapSL(*lpParam1);
- LPMIDIHDR mh32 = (MIDIHDR*)mh16->lpNext;
+ LPMIDIHDR16 mh16 = MapSL(*lpParam1);
+ struct mihdrWrap *mh32 = (struct mihdrWrap*)mh16->lpNext;
+
+ mh32->ref++;
+
+ *lpParam1 = (DWORD)&mh32->hdr;
+ *lpParam2 = offsetof(MIDIHDR,dwOffset);
+
+ /* dwBufferLength can be reduced between prepare & write */
+ 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->hdr.dwBufferLength, mh16->dwBufferLength);
+ }
+ else
+ mh32->hdr.dwBufferLength = mh16->dwBufferLength;
- *lpParam1 = (DWORD)mh32;
- *lpParam2 = offsetof(MIDIHDR,dwOffset);
- /* dwBufferLength can be reduced between prepare & write */
- if (wMsg == MODM_LONGDATA && mh32->dwBufferLength < mh16->dwBufferLength) {
- ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
- mh32->dwBufferLength, mh16->dwBufferLength);
- } else
- mh32->dwBufferLength = mh16->dwBufferLength;
ret = MMSYSTEM_MAP_OKMEM;
}
break;
@@ -267,17 +281,28 @@ static MMSYSTEM_MapType MMSYSTDRV_MidiOut_UnMap16To32W(UINT wMsg, DWORD_PTR* lp
case MODM_UNPREPARE:
case MODM_LONGDATA:
{
- LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1);
- LPMIDIHDR16 mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)));
+ struct mihdrWrap *mh32 = CONTAINING_RECORD(*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;
- }
- ret = MMSYSTEM_MAP_OK;
+ 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 +332,12 @@ static void MMSYSTDRV_MidiOut_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dw
case MOM_DONE:
{
/* initial map is: 16 => 32 */
- LPMIDIHDR mh32 = (LPMIDIHDR)(*dwParam1);
- SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
- LPMIDIHDR16 mh16 = MapSL(segmh16);
+ struct mihdrWrap *mh32 = CONTAINING_RECORD(*dwParam1, struct mihdrWrap, hdr);
+ SEGPTR segmh16 = mh32->mh16;
+ LPMIDIHDR16 mh16 = MapSL(segmh16);
- *dwParam1 = (DWORD)segmh16;
- mh16->dwFlags = mh32->dwFlags;
+ *dwParam1 = (DWORD)segmh16;
+ mh16->dwFlags = mh32->hdr.dwFlags;
}
break;
default:
--
2.7.1

View File

@ -0,0 +1,158 @@
From 23a789f7364648c706fc14a5558de028016f7b42 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Fri, 26 Feb 2016 04:04:12 +0100
Subject: mmsystem.dll16: Translate MidiIn messages.
---
dlls/mmsystem.dll16/message16.c | 128 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 126 insertions(+), 2 deletions(-)
diff --git a/dlls/mmsystem.dll16/message16.c b/dlls/mmsystem.dll16/message16.c
index e0df741..f7125da 100644
--- a/dlls/mmsystem.dll16/message16.c
+++ b/dlls/mmsystem.dll16/message16.c
@@ -95,7 +95,78 @@ static void MMSYSTDRV_Mixer_MapCB(DWORD uMsg, DWORD_PTR* dwUser
*/
static MMSYSTEM_MapType MMSYSTDRV_MidiIn_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
{
- return MMSYSTEM_MAP_MSGERROR;
+ MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR;
+
+ switch (wMsg)
+ {
+ case MIDM_GETNUMDEVS:
+ case MIDM_RESET:
+ ret = MMSYSTEM_MAP_OK;
+ break;
+
+ case MIDM_GETDEVCAPS:
+ {
+ LPMIDIINCAPSW mic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIINCAPS16) + sizeof(MIDIINCAPSW));
+ LPMIDIINCAPS16 mic16 = MapSL(*lpParam1);
+
+ if (mic32)
+ {
+ *(LPMIDIINCAPS16 *)mic32 = mic16;
+ mic32 = (LPMIDIINCAPSW)((LPSTR)mic32 + sizeof(LPMIDIINCAPS16));
+ *lpParam1 = (DWORD)mic32;
+ *lpParam2 = sizeof(LPMIDIINCAPSW);
+
+ ret = MMSYSTEM_MAP_OKMEM;
+ }
+ else
+ ret = MMSYSTEM_MAP_NOMEM;
+ }
+ break;
+
+ case MIDM_ADDBUFFER:
+ case MIDM_PREPARE:
+ {
+ struct mihdrWrap *mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(struct mihdrWrap));
+ LPMIDIHDR16 mh16 = MapSL(*lpParam1);
+
+ if (mh32)
+ {
+ 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;
+ *lpParam1 = (DWORD)&mh32->hdr;
+ *lpParam2 = offsetof(MIDIHDR,dwOffset);
+
+ ret = MMSYSTEM_MAP_OKMEM;
+ }
+ else
+ ret = MMSYSTEM_MAP_NOMEM;
+ }
+ break;
+
+ case MIDM_UNPREPARE:
+ {
+ LPMIDIHDR16 mh16 = MapSL(*lpParam1);
+ struct mihdrWrap *mh32 = (struct mihdrWrap *)mh16->lpNext;
+
+ mh32->ref++;
+
+ *lpParam1 = (DWORD)&mh32->hdr;
+ *lpParam2 = offsetof(MIDIHDR,dwOffset);
+
+ mh32->hdr.dwBufferLength = mh16->dwBufferLength;
+
+ ret = MMSYSTEM_MAP_OKMEM;
+ }
+ break;
+ }
+
+ return ret;
}
/**************************************************************************
@@ -103,7 +174,60 @@ static MMSYSTEM_MapType MMSYSTDRV_MidiIn_Map16To32W (UINT wMsg, DWORD_PTR* lpP
*/
static MMSYSTEM_MapType MMSYSTDRV_MidiIn_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
{
- return MMSYSTEM_MAP_MSGERROR;
+ MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR;
+
+ switch (wMsg)
+ {
+ case MIDM_GETNUMDEVS:
+ case MIDM_RESET:
+ ret = MMSYSTEM_MAP_OK;
+ break;
+
+ case MIDM_GETDEVCAPS:
+ {
+ LPMIDIINCAPSW mic32 = (LPMIDIINCAPSW)(*lpParam1);
+ LPMIDIINCAPS16 mic16 = *(LPMIDIINCAPS16*)((LPSTR)mic32 - sizeof(LPMIDIINCAPS16));
+
+ mic16->wMid = mic32->wMid;
+ mic16->wPid = mic32->wPid;
+ mic16->vDriverVersion = mic32->vDriverVersion;
+ WideCharToMultiByte( CP_ACP, 0, mic32->szPname, -1, mic16->szPname,
+ sizeof(mic16->szPname), NULL, NULL );
+ mic16->dwSupport = mic32->dwSupport;
+ HeapFree(GetProcessHeap(), 0, (LPSTR)mic32 - sizeof(LPMIDIINCAPS16));
+ ret = MMSYSTEM_MAP_OK;
+ }
+ break;
+
+ case MIDM_PREPARE:
+ case MIDM_UNPREPARE:
+ {
+ struct mihdrWrap *mh32 = CONTAINING_RECORD(*lpParam1, struct mihdrWrap, hdr);
+ LPMIDIHDR16 mh16;
+
+ 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)
+ {
+ mh32->mh16 = 0;
+ mh32->ref--;
+ mh16->lpNext = 0;
+ }
+ }
+
+ if (!--mh32->ref)
+ HeapFree(GetProcessHeap(), 0, mh32);
+
+ ret = MMSYSTEM_MAP_OK;
+ }
+ break;
+
+ }
+ return ret;
}
/**************************************************************************
--
2.7.1

View File

@ -0,0 +1 @@
Fixes: [40024] Fix multiple issues in mmsystem.dll16 when translating MIDI messages

View File

@ -182,6 +182,7 @@ patch_enable_all ()
enable_makedep_PARENTSPEC="$1"
enable_mfplat_MFTRegister="$1"
enable_mmdevapi_AEV_Stubs="$1"
enable_mmsystem_dll16_MIDIHDR_Refcount="$1"
enable_mountmgr_DosDevices="$1"
enable_mpr_WNetGetUniversalNameW="$1"
enable_mscoree_CorValidateImage="$1"
@ -693,6 +694,9 @@ patch_enable ()
mmdevapi-AEV_Stubs)
enable_mmdevapi_AEV_Stubs="$2"
;;
mmsystem.dll16-MIDIHDR_Refcount)
enable_mmsystem_dll16_MIDIHDR_Refcount="$2"
;;
mountmgr-DosDevices)
enable_mountmgr_DosDevices="$2"
;;
@ -4297,6 +4301,23 @@ if test "$enable_mmdevapi_AEV_Stubs" -eq 1; then
) >> "$patchlist"
fi
# Patchset mmsystem.dll16-MIDIHDR_Refcount
# |
# | This patchset fixes the following Wine bugs:
# | * [#40024] Fix multiple issues in mmsystem.dll16 when translating MIDI messages
# |
# | Modified files:
# | * dlls/mmsystem.dll16/message16.c
# |
if test "$enable_mmsystem_dll16_MIDIHDR_Refcount" -eq 1; then
patch_apply mmsystem.dll16-MIDIHDR_Refcount/0001-mmsystem.dll16-Refcount-midihdr-to-work-around-buggy.patch
patch_apply mmsystem.dll16-MIDIHDR_Refcount/0002-mmsystem.dll16-Translate-MidiIn-messages.patch
(
echo '+ { "Michael Müller", "mmsystem.dll16: Refcount midihdr to work around buggy application which unprepares buffer during a callback.", 1 },';
echo '+ { "Michael Müller", "mmsystem.dll16: Translate MidiIn messages.", 1 },';
) >> "$patchlist"
fi
# Patchset mountmgr-DosDevices
# |
# | This patchset fixes the following Wine bugs: