diff --git a/patches/mmsystem.dll16-MIDIHDR_Refcount/0001-mmsystem.dll16-Refcount-midihdr-to-work-around-buggy.patch b/patches/mmsystem.dll16-MIDIHDR_Refcount/0001-mmsystem.dll16-Refcount-midihdr-to-work-around-buggy.patch new file mode 100644 index 00000000..bc1ba617 --- /dev/null +++ b/patches/mmsystem.dll16-MIDIHDR_Refcount/0001-mmsystem.dll16-Refcount-midihdr-to-work-around-buggy.patch @@ -0,0 +1,184 @@ +From 777db4a5e0c6058253b471640c9ae6dbf0e159da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +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 + diff --git a/patches/mmsystem.dll16-MIDIHDR_Refcount/0002-mmsystem.dll16-Translate-MidiIn-messages.patch b/patches/mmsystem.dll16-MIDIHDR_Refcount/0002-mmsystem.dll16-Translate-MidiIn-messages.patch new file mode 100644 index 00000000..79fd73d1 --- /dev/null +++ b/patches/mmsystem.dll16-MIDIHDR_Refcount/0002-mmsystem.dll16-Translate-MidiIn-messages.patch @@ -0,0 +1,158 @@ +From 23a789f7364648c706fc14a5558de028016f7b42 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +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 + diff --git a/patches/mmsystem.dll16-MIDIHDR_Refcount/definition b/patches/mmsystem.dll16-MIDIHDR_Refcount/definition new file mode 100644 index 00000000..2d86a77c --- /dev/null +++ b/patches/mmsystem.dll16-MIDIHDR_Refcount/definition @@ -0,0 +1 @@ +Fixes: [40024] Fix multiple issues in mmsystem.dll16 when translating MIDI messages diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 1e25e156..f00207c9 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -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: