diff --git a/dlls/winmm/message16.c b/dlls/winmm/message16.c index 98c97015e4..fe9e3b6272 100644 --- a/dlls/winmm/message16.c +++ b/dlls/winmm/message16.c @@ -2545,3 +2545,218 @@ MMDRV_##_y##_Callback) pFnMciMapMsg32WTo16 = MCI_MapMsg32WTo16; pFnMciUnMapMsg32WTo16 = MCI_UnMapMsg32WTo16; } + +/* ################################################### + * # DRIVER THUNKING # + * ################################################### + */ +typedef MMSYSTEM_MapType (*MMSYSTDRV_MAPMSG)(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2); +typedef MMSYSTEM_MapType (*MMSYSTDRV_UNMAPMSG)(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT ret); +typedef void (*MMSYSTDRV_MAPCB)(DWORD wMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2); + +#include +#define MMSYSTDRV_MAX_THUNKS 32 + +static struct mmsystdrv_thunk +{ + BYTE popl_eax; /* popl %eax (return address) */ + BYTE pushl_func; /* pushl $pfn16 (16bit callback function) */ + struct mmsystdrv_thunk* this; + BYTE pushl_eax; /* pushl %eax */ + BYTE jmp; /* ljmp MMDRV_Callback1632 */ + DWORD callback; + DWORD pfn16; + void* hMmdrv; /* Handle to 32bit mmdrv object */ + enum MMSYSTEM_DriverType kind; +} *MMSYSTDRV_Thunks; + +#include + +static struct MMSYSTDRV_Type +{ + MMSYSTDRV_MAPMSG mapmsg16to32W; + MMSYSTDRV_UNMAPMSG unmapmsg16to32W; + MMSYSTDRV_MAPCB mapcb; +} MMSYSTEM_DriversType[MMSYSTDRV_MAX] = +{ +}; + +/****************************************************************** + * MMSYSTDRV_Callback3216 + * + */ +static LRESULT CALLBACK MMSYSTDRV_Callback3216(struct mmsystdrv_thunk* thunk, DWORD uFlags, HDRVR hDev, + DWORD wMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1, + DWORD_PTR dwParam2) +{ + assert(thunk->kind < MMSYSTDRV_MAX); + assert(MMSYSTEM_DriversType[thunk->kind].mapcb); + + MMSYSTEM_DriversType[thunk->kind].mapcb(wMsg, &dwUser, &dwParam1, &dwParam2); + + if ((uFlags & DCB_TYPEMASK) == DCB_FUNCTION) + { + WORD args[8]; + /* 16 bit func, call it */ + TRACE("Function (16 bit) !\n"); + + args[7] = HDRVR_16(hDev); + args[6] = wMsg; + args[5] = HIWORD(dwUser); + args[4] = LOWORD(dwUser); + args[3] = HIWORD(dwParam1); + args[2] = LOWORD(dwParam1); + args[1] = HIWORD(dwParam2); + args[0] = LOWORD(dwParam2); + return WOWCallback16Ex(thunk->pfn16, WCB16_PASCAL, sizeof(args), args, NULL); + } + return DriverCallback(thunk->pfn16, uFlags, hDev, wMsg, dwUser, dwParam1, dwParam2); +} + +/****************************************************************** + * MMSYSTDRV_AddThunk + * + */ +struct mmsystdrv_thunk* MMSYSTDRV_AddThunk(DWORD pfn16, enum MMSYSTEM_DriverType kind) +{ + struct mmsystdrv_thunk* thunk; + + EnterCriticalSection(&mmdrv_cs); + if (!MMSYSTDRV_Thunks) + { + MMSYSTDRV_Thunks = VirtualAlloc(NULL, MMSYSTDRV_MAX_THUNKS * sizeof(*MMSYSTDRV_Thunks), + MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (!MMSYSTDRV_Thunks) + { + LeaveCriticalSection(&mmdrv_cs); + return NULL; + } + for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++) + { + thunk->popl_eax = 0x58; /* popl %eax */ + thunk->pushl_func = 0x68; /* pushl $pfn16 */ + thunk->this = thunk; + thunk->pushl_eax = 0x50; /* pushl %eax */ + thunk->jmp = 0xe9; /* jmp MMDRV_Callback3216 */ + thunk->callback = (char *)MMSYSTDRV_Callback3216 - (char *)(&thunk->callback + 1); + thunk->pfn16 = 0; + thunk->hMmdrv = NULL; + thunk->kind = MMSYSTDRV_MAX; + } + } + for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++) + { + if (thunk->pfn16 == 0 && thunk->hMmdrv == NULL) + { + thunk->pfn16 = pfn16; + thunk->hMmdrv = NULL; + thunk->kind = kind; + LeaveCriticalSection(&mmdrv_cs); + return thunk; + } + } + LeaveCriticalSection(&mmdrv_cs); + FIXME("Out of mmdrv-thunks. Bump MMDRV_MAX_THUNKS\n"); + return NULL; +} + +/****************************************************************** + * MMSYSTDRV_FindHandle + * + * Must be called with lock set + */ +static void* MMSYSTDRV_FindHandle(void* h) +{ + struct mmsystdrv_thunk* thunk; + + for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++) + { + if (thunk->hMmdrv == h) + { + if (thunk->kind >= MMSYSTDRV_MAX) FIXME("Kind isn't properly initialized %x\n", thunk->kind); + return thunk; + } + } + return NULL; +} + +/****************************************************************** + * MMSYSTDRV_SetHandle + * + */ +void MMSYSTDRV_SetHandle(struct mmsystdrv_thunk* thunk, void* h) +{ + if (MMSYSTDRV_FindHandle(h)) FIXME("Already has a thunk for this handle %p!!!\n", h); + thunk->hMmdrv = h; +} + +/****************************************************************** + * MMSYSTDRV_DeleteThunk + */ +void MMSYSTDRV_DeleteThunk(struct mmsystdrv_thunk* thunk) +{ + thunk->pfn16 = 0; + thunk->hMmdrv = NULL; + thunk->kind = MMSYSTDRV_MAX; +} + +/****************************************************************** + * MMSYSTDRV_CloseHandle + */ +void MMSYSTDRV_CloseHandle(void* h) +{ + struct mmsystdrv_thunk* thunk; + + EnterCriticalSection(&mmdrv_cs); + if ((thunk = MMSYSTDRV_FindHandle(h))) + { + MMSYSTDRV_DeleteThunk(thunk); + } + LeaveCriticalSection(&mmdrv_cs); +} + +/****************************************************************** + * MMSYSTDRV_Message + */ +DWORD MMSYSTDRV_Message(void* h, UINT msg, DWORD_PTR param1, DWORD_PTR param2) +{ + struct mmsystdrv_thunk* thunk = MMSYSTDRV_FindHandle(h); + struct MMSYSTDRV_Type* drvtype; + MMSYSTEM_MapType map; + DWORD ret; + + if (!thunk) return MMSYSERR_INVALHANDLE; + drvtype = &MMSYSTEM_DriversType[thunk->kind]; + + map = drvtype->mapmsg16to32W(msg, ¶m1, ¶m2); + switch (map) { + case MMSYSTEM_MAP_NOMEM: + ret = MMSYSERR_NOMEM; + break; + case MMSYSTEM_MAP_MSGERROR: + FIXME("NIY: no conversion yet 16->32 kind=%u msg=%u\n", thunk->kind, msg); + ret = MMSYSERR_ERROR; + break; + case MMSYSTEM_MAP_OK: + case MMSYSTEM_MAP_OKMEM: + TRACE("Calling message(msg=%u p1=0x%08lx p2=0x%08lx)\n", + msg, param1, param2); + switch (thunk->kind) + { + case MMSYSTDRV_MIXER: ret = mixerMessage (h, msg, param1, param2); break; + case MMSYSTDRV_MIDIIN: ret = midiInMessage (h, msg, param1, param2); break; + case MMSYSTDRV_MIDIOUT: ret = midiOutMessage(h, msg, param1, param2); break; + case MMSYSTDRV_WAVEIN: ret = waveInMessage (h, msg, param1, param2); break; + case MMSYSTDRV_WAVEOUT: ret = waveOutMessage(h, msg, param1, param2); break; + default: ret = MMSYSERR_INVALHANDLE; break; /* should never be reached */ + } + if (map == MMSYSTEM_MAP_OKMEM) + drvtype->unmapmsg16to32W(msg, ¶m1, ¶m2, ret); + break; + default: + FIXME("NIY\n"); + ret = MMSYSERR_NOTSUPPORTED; + break; + } + return ret; +} diff --git a/dlls/winmm/mmsystem.c b/dlls/winmm/mmsystem.c index d3214f7956..4007d46dc1 100644 --- a/dlls/winmm/mmsystem.c +++ b/dlls/winmm/mmsystem.c @@ -52,14 +52,13 @@ static LPWINE_DRIVER DRIVER_OpenDriver16(LPCWSTR, LPCWSTR, LPARAM); static LRESULT DRIVER_CloseDriver16(HDRVR16, LPARAM, LPARAM); static LRESULT DRIVER_SendMessage16(HDRVR16, UINT, LPARAM, LPARAM); -static CRITICAL_SECTION mmdrv_cs; static CRITICAL_SECTION_DEBUG mmdrv_critsect_debug = { 0, 0, &mmdrv_cs, { &mmdrv_critsect_debug.ProcessLocksList, &mmdrv_critsect_debug.ProcessLocksList }, 0, 0, { (DWORD_PTR)(__FILE__ ": mmsystem_mmdrv_cs") } }; -static CRITICAL_SECTION mmdrv_cs = { &mmdrv_critsect_debug, -1, 0, 0, 0, 0 }; +CRITICAL_SECTION mmdrv_cs = { &mmdrv_critsect_debug, -1, 0, 0, 0, 0 }; /* ################################################### * # LIBRARY # @@ -201,7 +200,6 @@ void WINAPI OutputDebugStr16(LPCSTR str) OutputDebugStringA( str ); } - /* ################################################### * # MIXER # * ################################################### diff --git a/dlls/winmm/winemm16.h b/dlls/winmm/winemm16.h index 38dbdeb3b4..97b03ef049 100644 --- a/dlls/winmm/winemm16.h +++ b/dlls/winmm/winemm16.h @@ -61,3 +61,21 @@ typedef enum { MMSYSTEM_MAP_OK, /* ok, no memory allocated. to be sent to the proc. */ MMSYSTEM_MAP_OKMEM, /* ok, some memory allocated, need to call UnMapMsg. to be sent to the proc. */ } MMSYSTEM_MapType; + +extern CRITICAL_SECTION mmdrv_cs; + +enum MMSYSTEM_DriverType +{ + MMSYSTDRV_MIXER, + MMSYSTDRV_MIDIIN, + MMSYSTDRV_MIDIOUT, + MMSYSTDRV_WAVEIN, + MMSYSTDRV_WAVEOUT, + MMSYSTDRV_MAX +}; + +extern struct mmsystdrv_thunk* MMSYSTDRV_AddThunk(DWORD pfn16, enum MMSYSTEM_DriverType kind); +extern void MMSYSTDRV_DeleteThunk(struct mmsystdrv_thunk* thunk); +extern void MMSYSTDRV_SetHandle(struct mmsystdrv_thunk* thunk, void* h); +extern void MMSYSTDRV_CloseHandle(void* h); +extern DWORD MMSYSTDRV_Message(void* h, UINT msg, DWORD_PTR param1, DWORD_PTR param2);