Hello, this patch is aimed to fix crashes in the old 16-bit game, which calls waveOutUnprepareHeader16 for busy headers. MMDRV_Message in that case returns WAVERR_STILLPLAYING, but it's not stopping MMDRV_WaveOut_UnMap16To32A() from freeing the header. Slightly later game calls waveOutReset16() which crashes. In that case the duty of freeing the header should be moved to a higher level. I have generalized this approach to all similar cases. Changelog: Do not free the header while unmapping the xxxx_UNPREPARE messages, do it at the higher level API. diff -u cvs/cw/crossover/office/wine/dlls/winmm/message16.c wine/dlls/winmm/message16.c --- cvs/cw/crossover/office/wine/dlls/winmm/message16.c Sat Nov 9 08:12:50 2002 +++ wine/dlls/winmm/message16.c Wed Dec 25 23:14:34 2002 @@ -411,10 +411,6 @@ if (mh16->reserved >= sizeof(MIDIHDR)) mh16->dwOffset = mh32->dwOffset; - if (wMsg == MODM_UNPREPARE) { - HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR)); - mh16->lpNext = 0; - } ret = WINMM_MAP_OK; } break; @@ -617,10 +613,6 @@ mh32->dwUser = mh16->dwUser; mh32->dwFlags = mh16->dwFlags; - if (wMsg == MODM_UNPREPARE) { - HeapFree( GetProcessHeap(), 0, ptr ); - mh32->lpNext = 0; - } ret = WINMM_MAP_OK; } break; @@ -860,10 +852,6 @@ wh16->dwFlags = wh32->dwFlags; wh16->dwLoops = wh32->dwLoops; - if (wMsg == WIDM_UNPREPARE) { - HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR)); - wh16->lpNext = 0; - } ret = WINMM_MAP_OK; } break; @@ -1089,10 +1077,6 @@ wh32->dwLoops = wh16->dwLoops; UnMapLS( *lpParam1 ); - if (wMsg == WIDM_UNPREPARE) { - HeapFree( GetProcessHeap(), 0, ptr ); - wh32->lpNext = 0; - } ret = WINMM_MAP_OK; } break; @@ -1369,10 +1353,6 @@ wh16->dwFlags = wh32->dwFlags; wh16->dwLoops = wh32->dwLoops; - if (wMsg == WODM_UNPREPARE) { - HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR)); - wh16->lpNext = 0; - } ret = WINMM_MAP_OK; } break; @@ -1659,10 +1639,7 @@ wh32->dwLoops = wh16->dwLoops; UnMapLS( *lpParam1 ); - if (wMsg == WODM_UNPREPARE) { - HeapFree( GetProcessHeap(), 0, ptr ); - wh32->lpNext = 0; - } + ret = WINMM_MAP_OK; } break; diff -u cvs/cw/crossover/office/wine/dlls/winmm/mmsystem.c wine/dlls/winmm/mmsystem.c --- cvs/cw/crossover/office/wine/dlls/winmm/mmsystem.c Sat Dec 21 14:03:30 2002 +++ wine/dlls/winmm/mmsystem.c Wed Dec 25 23:29:58 2002 @@ -755,6 +755,7 @@ SEGPTR lpsegMidiOutHdr, /* [???] */ UINT16 uSize) /* [in] */ { + UINT16 ret; LPWINE_MLD wmld; LPMIDIHDR16 lpMidiOutHdr = MapSL(lpsegMidiOutHdr); @@ -767,7 +768,14 @@ if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL) return MMSYSERR_INVALHANDLE; - return MMDRV_Message(wmld, MODM_UNPREPARE, (DWORD)lpsegMidiOutHdr, uSize, FALSE); + ret = MMDRV_Message(wmld, MODM_UNPREPARE, (DWORD)lpsegMidiOutHdr, uSize, FALSE); + + if (ret == MMSYSERR_NOERROR) + { + HeapFree(GetProcessHeap(), 0, (LPSTR)lpMidiOutHdr - sizeof(LPMIDIHDR)); + lpMidiOutHdr->lpNext = 0; + } + return ret; } /************************************************************************** @@ -970,6 +978,7 @@ SEGPTR lpsegMidiInHdr, /* [???] */ UINT16 uSize) /* [in] */ { + UINT16 ret; LPWINE_MLD wmld; LPMIDIHDR16 lpMidiInHdr = MapSL(lpsegMidiInHdr); @@ -982,7 +991,14 @@ if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL) return MMSYSERR_INVALHANDLE; - return MMDRV_Message(wmld, MIDM_UNPREPARE, (DWORD)lpsegMidiInHdr, uSize, FALSE); + ret = MMDRV_Message(wmld, MIDM_UNPREPARE, (DWORD)lpsegMidiInHdr, uSize, FALSE); + + if (ret == MMSYSERR_NOERROR) + { + HeapFree(GetProcessHeap(), 0, (LPSTR)lpMidiInHdr - sizeof(LPMIDIHDR)); + lpMidiInHdr->lpNext = 0; + } + return ret; } /************************************************************************** @@ -1273,6 +1289,7 @@ SEGPTR lpsegWaveOutHdr, /* [???] */ UINT16 uSize) /* [in] */ { + UINT16 ret; LPWINE_MLD wmld; LPWAVEHDR lpWaveOutHdr = MapSL(lpsegWaveOutHdr); @@ -1285,7 +1302,14 @@ if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL) return MMSYSERR_INVALHANDLE; - return MMDRV_Message(wmld, WODM_UNPREPARE, (DWORD)lpsegWaveOutHdr, uSize, FALSE); + ret = MMDRV_Message(wmld, WODM_UNPREPARE, (DWORD)lpsegWaveOutHdr, uSize, FALSE); + + if (ret == MMSYSERR_NOERROR) + { + HeapFree(GetProcessHeap(), 0, (LPSTR)lpWaveOutHdr - sizeof(LPWAVEHDR)); + lpWaveOutHdr->lpNext = 0; + } + return ret; } /************************************************************************** @@ -1570,6 +1594,7 @@ SEGPTR lpsegWaveInHdr, /* [???] */ UINT16 uSize) /* [in] */ { + UINT16 ret; LPWINE_MLD wmld; LPWAVEHDR lpWaveInHdr = MapSL(lpsegWaveInHdr); @@ -1584,7 +1609,14 @@ if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL) return MMSYSERR_INVALHANDLE; - return MMDRV_Message(wmld, WIDM_UNPREPARE, (DWORD)lpsegWaveInHdr, uSize, FALSE); + ret = MMDRV_Message(wmld, WIDM_UNPREPARE, (DWORD)lpsegWaveInHdr, uSize, FALSE); + + if (ret == MMSYSERR_NOERROR) + { + HeapFree(GetProcessHeap(), 0, (LPSTR)lpWaveInHdr - sizeof(LPWAVEHDR)); + lpWaveInHdr->lpNext = 0; + } + return ret; } /************************************************************************** diff -u cvs/cw/crossover/office/wine/dlls/winmm/winmm.c wine/dlls/winmm/winmm.c --- cvs/cw/crossover/office/wine/dlls/winmm/winmm.c Sat Dec 21 14:03:30 2002 +++ wine/dlls/winmm/winmm.c Wed Dec 25 23:30:35 2002 @@ -1119,6 +1119,7 @@ UINT WINAPI midiOutUnprepareHeader(HMIDIOUT hMidiOut, MIDIHDR* lpMidiOutHdr, UINT uSize) { + UINT ret; LPWINE_MLD wmld; TRACE("(%p, %p, %d)\n", hMidiOut, lpMidiOutHdr, uSize); @@ -1130,7 +1131,14 @@ if ((wmld = MMDRV_Get(hMidiOut, MMDRV_MIDIOUT, FALSE)) == NULL) return MMSYSERR_INVALHANDLE; - return MMDRV_Message(wmld, MODM_UNPREPARE, (DWORD)lpMidiOutHdr, uSize, TRUE); + ret = MMDRV_Message(wmld, MODM_UNPREPARE, (DWORD)lpMidiOutHdr, uSize, TRUE); + + if (ret == MMSYSERR_NOERROR) + { + HeapFree(GetProcessHeap(), 0, (LPSTR)lpMidiOutHdr - sizeof(LPMIDIHDR)); + lpMidiOutHdr->lpNext = 0; + } + return ret; } /************************************************************************** @@ -1425,6 +1433,7 @@ UINT WINAPI midiInUnprepareHeader(HMIDIIN hMidiIn, MIDIHDR* lpMidiInHdr, UINT uSize) { + UINT ret; LPWINE_MLD wmld; TRACE("(%p, %p, %d)\n", hMidiIn, lpMidiInHdr, uSize); @@ -1436,7 +1445,14 @@ if ((wmld = MMDRV_Get(hMidiIn, MMDRV_MIDIIN, FALSE)) == NULL) return MMSYSERR_INVALHANDLE; - return MMDRV_Message(wmld, MIDM_UNPREPARE, (DWORD)lpMidiInHdr, uSize, TRUE); + ret = MMDRV_Message(wmld, MIDM_UNPREPARE, (DWORD)lpMidiInHdr, uSize, TRUE); + + if (ret == MMSYSERR_NOERROR) + { + HeapFree(GetProcessHeap(), 0, (LPSTR)lpMidiInHdr - sizeof(LPMIDIHDR)); + lpMidiInHdr->lpNext = 0; + } + return ret; } /************************************************************************** @@ -2358,6 +2374,7 @@ UINT WINAPI waveOutUnprepareHeader(HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr, UINT uSize) { + UINT ret; LPWINE_MLD wmld; TRACE("(%p, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize); @@ -2369,7 +2386,14 @@ if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL) return MMSYSERR_INVALHANDLE; - return MMDRV_Message(wmld, WODM_UNPREPARE, (DWORD)lpWaveOutHdr, uSize, TRUE); + ret = MMDRV_Message(wmld, WODM_UNPREPARE, (DWORD)lpWaveOutHdr, uSize, TRUE); + + if (ret == MMSYSERR_NOERROR) + { + HeapFree(GetProcessHeap(), 0, (LPSTR)lpWaveOutHdr - sizeof(LPWAVEHDR)); + lpWaveOutHdr->lpNext = 0; + } + return ret; } /************************************************************************** @@ -2707,6 +2731,7 @@ UINT WINAPI waveInUnprepareHeader(HWAVEIN hWaveIn, WAVEHDR* lpWaveInHdr, UINT uSize) { + UINT ret; LPWINE_MLD wmld; TRACE("(%p, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize); @@ -2719,7 +2744,14 @@ if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL) return MMSYSERR_INVALHANDLE; - return MMDRV_Message(wmld, WIDM_UNPREPARE, (DWORD)lpWaveInHdr, uSize, TRUE); + ret = MMDRV_Message(wmld, WIDM_UNPREPARE, (DWORD)lpWaveInHdr, uSize, TRUE); + + if (ret == MMSYSERR_NOERROR) + { + HeapFree(GetProcessHeap(), 0, (LPSTR)lpWaveInHdr - sizeof(LPWAVEHDR)); + lpWaveInHdr->lpNext = 0; + } + return ret; } /**************************************************************************