gdi32: Don't store the metaclip region, recompute it as needed.
[wine/multimedia.git] / dlls / mmsystem.dll16 / message16.c
blob0935ca0a47c3fbeef3adb7dc2052d7daf05c3fe4
1 /*
2 * MMSYSTEM MCI and low level mapping functions
4 * Copyright 1999 Eric Pouech
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <string.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <assert.h>
25 #include "wine/winbase16.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "wownt32.h"
30 #include "winemm16.h"
31 #include "digitalv.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(winmm);
36 /* =================================
37 * A U X M A P P E R S
38 * ================================= */
40 /* =================================
41 * M I X E R M A P P E R S
42 * ================================= */
44 /**************************************************************************
45 * MMSYSTDRV_Mixer_Map16To32W [internal]
47 static MMSYSTEM_MapType MMSYSTDRV_Mixer_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
49 return MMSYSTEM_MAP_MSGERROR;
52 /**************************************************************************
53 * MMSYSTDRV_Mixer_UnMap16To32W [internal]
55 static MMSYSTEM_MapType MMSYSTDRV_Mixer_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
57 #if 0
58 MIXERCAPSA micA;
59 UINT ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
61 if (ret == MMSYSERR_NOERROR) {
62 mixcaps->wMid = micA.wMid;
63 mixcaps->wPid = micA.wPid;
64 mixcaps->vDriverVersion = micA.vDriverVersion;
65 strcpy(mixcaps->szPname, micA.szPname);
66 mixcaps->fdwSupport = micA.fdwSupport;
67 mixcaps->cDestinations = micA.cDestinations;
69 return ret;
70 #endif
71 return MMSYSTEM_MAP_MSGERROR;
74 /**************************************************************************
75 * MMSYSTDRV_Mixer_MapCB
77 static void MMSYSTDRV_Mixer_MapCB(DWORD uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2)
79 FIXME("NIY\n");
82 /* =================================
83 * M I D I I N M A P P E R S
84 * ================================= */
86 /**************************************************************************
87 * MMSYSTDRV_MidiIn_Map16To32W [internal]
89 static MMSYSTEM_MapType MMSYSTDRV_MidiIn_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
91 return MMSYSTEM_MAP_MSGERROR;
94 /**************************************************************************
95 * MMSYSTDRV_MidiIn_UnMap16To32W [internal]
97 static MMSYSTEM_MapType MMSYSTDRV_MidiIn_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
99 return MMSYSTEM_MAP_MSGERROR;
102 /**************************************************************************
103 * MMSYSTDRV_MidiIn_MapCB [internal]
105 static void MMSYSTDRV_MidiIn_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2)
107 switch (uMsg) {
108 case MIM_OPEN:
109 case MIM_CLOSE:
110 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
112 case MIM_DATA:
113 case MIM_MOREDATA:
114 case MIM_ERROR:
115 /* dwParam1 & dwParam2 are data, nothing to do */
116 break;
117 case MIM_LONGDATA:
118 case MIM_LONGERROR:
120 LPMIDIHDR mh32 = (LPMIDIHDR)(*dwParam1);
121 SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
122 LPMIDIHDR mh16 = MapSL(segmh16);
124 *dwParam1 = (DWORD)segmh16;
125 mh16->dwFlags = mh32->dwFlags;
126 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
127 if (mh16->reserved >= sizeof(MIDIHDR))
128 mh16->dwOffset = mh32->dwOffset;
130 break;
131 default:
132 ERR("Unknown msg %u\n", uMsg);
136 /* =================================
137 * M I D I O U T M A P P E R S
138 * ================================= */
140 /**************************************************************************
141 * MMSYSTDRV_MidiOut_Map16To32W [internal]
143 static MMSYSTEM_MapType MMSYSTDRV_MidiOut_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
145 MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR;
147 switch (wMsg) {
148 case MODM_GETNUMDEVS:
149 case MODM_DATA:
150 case MODM_RESET:
151 case MODM_SETVOLUME:
152 ret = MMSYSTEM_MAP_OK;
153 break;
155 case MODM_OPEN:
156 case MODM_CLOSE:
157 case MODM_GETVOLUME:
158 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
159 break;
161 case MODM_GETDEVCAPS:
163 LPMIDIOUTCAPSW moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSW));
164 LPMIDIOUTCAPS16 moc16 = MapSL(*lpParam1);
166 if (moc32) {
167 *(LPMIDIOUTCAPS16*)moc32 = moc16;
168 moc32 = (LPMIDIOUTCAPSW)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16));
169 *lpParam1 = (DWORD)moc32;
170 *lpParam2 = sizeof(MIDIOUTCAPSW);
172 ret = MMSYSTEM_MAP_OKMEM;
173 } else {
174 ret = MMSYSTEM_MAP_NOMEM;
177 break;
178 case MODM_PREPARE:
180 LPMIDIHDR mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR));
181 LPMIDIHDR mh16 = MapSL(*lpParam1);
183 if (mh32) {
184 *(LPMIDIHDR*)mh32 = (LPMIDIHDR)*lpParam1;
185 mh32 = (LPMIDIHDR)((LPSTR)mh32 + sizeof(LPMIDIHDR));
186 mh32->lpData = MapSL((SEGPTR)mh16->lpData);
187 mh32->dwBufferLength = mh16->dwBufferLength;
188 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
189 mh32->dwUser = mh16->dwUser;
190 mh32->dwFlags = mh16->dwFlags;
191 /* FIXME: nothing on mh32->lpNext */
192 /* could link the mh32->lpNext at this level for memory house keeping */
193 mh32->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? mh16->dwOffset : 0;
194 mh16->lpNext = mh32; /* for reuse in unprepare and write */
195 /* store size of passed MIDIHDR?? structure to know if dwOffset is available or not */
196 mh16->reserved = *lpParam2;
197 *lpParam1 = (DWORD)mh32;
198 *lpParam2 = sizeof(MIDIHDR);
200 ret = MMSYSTEM_MAP_OKMEM;
201 } else {
202 ret = MMSYSTEM_MAP_NOMEM;
205 break;
206 case MODM_UNPREPARE:
207 case MODM_LONGDATA:
209 LPMIDIHDR mh16 = MapSL(*lpParam1);
210 LPMIDIHDR mh32 = mh16->lpNext;
212 *lpParam1 = (DWORD)mh32;
213 *lpParam2 = sizeof(MIDIHDR);
214 /* dwBufferLength can be reduced between prepare & write */
215 if (wMsg == MODM_LONGDATA && mh32->dwBufferLength < mh16->dwBufferLength) {
216 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
217 mh32->dwBufferLength, mh16->dwBufferLength);
218 } else
219 mh32->dwBufferLength = mh16->dwBufferLength;
220 ret = MMSYSTEM_MAP_OKMEM;
222 break;
224 case MODM_CACHEPATCHES:
225 case MODM_CACHEDRUMPATCHES:
226 default:
227 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
228 break;
230 return ret;
233 /**************************************************************************
234 * MMSYSTDRV_MidiOut_UnMap16To32W [internal]
236 static MMSYSTEM_MapType MMSYSTDRV_MidiOut_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
238 MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR;
240 switch (wMsg) {
241 case MODM_GETNUMDEVS:
242 case MODM_DATA:
243 case MODM_RESET:
244 case MODM_SETVOLUME:
245 ret = MMSYSTEM_MAP_OK;
246 break;
248 case MODM_OPEN:
249 case MODM_CLOSE:
250 case MODM_GETVOLUME:
251 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
252 break;
254 case MODM_GETDEVCAPS:
256 LPMIDIOUTCAPSW moc32 = (LPMIDIOUTCAPSW)(*lpParam1);
257 LPMIDIOUTCAPS16 moc16 = *(LPMIDIOUTCAPS16*)((LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
259 moc16->wMid = moc32->wMid;
260 moc16->wPid = moc32->wPid;
261 moc16->vDriverVersion = moc32->vDriverVersion;
262 WideCharToMultiByte( CP_ACP, 0, moc32->szPname, -1, moc16->szPname,
263 sizeof(moc16->szPname), NULL, NULL );
264 moc16->wTechnology = moc32->wTechnology;
265 moc16->wVoices = moc32->wVoices;
266 moc16->wNotes = moc32->wNotes;
267 moc16->wChannelMask = moc32->wChannelMask;
268 moc16->dwSupport = moc32->dwSupport;
269 HeapFree(GetProcessHeap(), 0, (LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
270 ret = MMSYSTEM_MAP_OK;
272 break;
273 case MODM_PREPARE:
274 case MODM_UNPREPARE:
275 case MODM_LONGDATA:
277 LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1);
278 LPMIDIHDR mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)));
280 assert(mh16->lpNext == mh32);
281 mh16->dwBufferLength = mh32->dwBufferLength;
282 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
283 mh16->dwUser = mh32->dwUser;
284 mh16->dwFlags = mh32->dwFlags;
285 if (mh16->reserved >= sizeof(MIDIHDR))
286 mh16->dwOffset = mh32->dwOffset;
288 if (wMsg == MODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
289 HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR));
290 mh16->lpNext = 0;
292 ret = MMSYSTEM_MAP_OK;
294 break;
296 case MODM_CACHEPATCHES:
297 case MODM_CACHEDRUMPATCHES:
298 default:
299 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
300 break;
302 return ret;
305 /******************************************************************
306 * MMSYSTDRV_MidiOut_MapCB
308 static void MMSYSTDRV_MidiOut_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2)
310 switch (uMsg) {
311 case MOM_OPEN:
312 case MOM_CLOSE:
313 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
314 break;
315 case MOM_DONE:
317 /* initial map is: 16 => 32 */
318 LPMIDIHDR mh32 = (LPMIDIHDR)(*dwParam1);
319 SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
320 LPMIDIHDR mh16 = MapSL(segmh16);
322 *dwParam1 = (DWORD)segmh16;
323 mh16->dwFlags = mh32->dwFlags;
324 if (mh16->reserved >= sizeof(MIDIHDR))
325 mh16->dwOffset = mh32->dwOffset;
327 break;
328 case MOM_POSITIONCB:
329 FIXME("NIY\n");
330 /* FIXME: would require to recreate a 16bit MIDIHDR here */
331 *dwParam1 = *dwParam2 = 0;
332 break;
333 default:
334 ERR("Unknown msg %u\n", uMsg);
338 /* =================================
339 * W A V E I N M A P P E R S
340 * ================================= */
342 /**************************************************************************
343 * MMSYSTDRV_WaveIn_Map16To32W [internal]
345 static MMSYSTEM_MapType MMSYSTDRV_WaveIn_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
347 MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR;
349 switch (wMsg) {
350 case WIDM_GETNUMDEVS:
351 case WIDM_RESET:
352 case WIDM_START:
353 case WIDM_STOP:
354 ret = MMSYSTEM_MAP_OK;
355 break;
356 case WIDM_OPEN:
357 case WIDM_CLOSE:
358 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
359 break;
360 case WIDM_GETDEVCAPS:
362 LPWAVEINCAPSW wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSW));
363 LPWAVEINCAPS16 wic16 = MapSL(*lpParam1);
365 if (wic32) {
366 *(LPWAVEINCAPS16*)wic32 = wic16;
367 wic32 = (LPWAVEINCAPSW)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16));
368 *lpParam1 = (DWORD)wic32;
369 *lpParam2 = sizeof(WAVEINCAPSW);
371 ret = MMSYSTEM_MAP_OKMEM;
372 } else {
373 ret = MMSYSTEM_MAP_NOMEM;
376 break;
377 case WIDM_GETPOS:
379 LPMMTIME mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
380 LPMMTIME16 mmt16 = MapSL(*lpParam1);
382 if (mmt32) {
383 *(LPMMTIME16*)mmt32 = mmt16;
384 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
386 mmt32->wType = mmt16->wType;
387 *lpParam1 = (DWORD)mmt32;
388 *lpParam2 = sizeof(MMTIME);
390 ret = MMSYSTEM_MAP_OKMEM;
391 } else {
392 ret = MMSYSTEM_MAP_NOMEM;
395 break;
396 case WIDM_PREPARE:
398 LPWAVEHDR wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
399 LPWAVEHDR wh16 = MapSL(*lpParam1);
401 if (wh32) {
402 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
403 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
404 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
405 wh32->dwBufferLength = wh16->dwBufferLength;
406 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
407 wh32->dwUser = wh16->dwUser;
408 wh32->dwFlags = wh16->dwFlags;
409 wh32->dwLoops = wh16->dwLoops;
410 /* FIXME: nothing on wh32->lpNext */
411 /* could link the wh32->lpNext at this level for memory house keeping */
412 wh16->lpNext = wh32; /* for reuse in unprepare and write */
413 *lpParam1 = (DWORD)wh32;
414 *lpParam2 = sizeof(WAVEHDR);
416 ret = MMSYSTEM_MAP_OKMEM;
417 } else {
418 ret = MMSYSTEM_MAP_NOMEM;
421 break;
422 case WIDM_ADDBUFFER:
423 case WIDM_UNPREPARE:
425 LPWAVEHDR wh16 = MapSL(*lpParam1);
426 LPWAVEHDR wh32 = wh16->lpNext;
428 *lpParam1 = (DWORD)wh32;
429 *lpParam2 = sizeof(WAVEHDR);
430 /* dwBufferLength can be reduced between prepare & write */
431 if (wMsg == WIDM_ADDBUFFER && wh32->dwBufferLength < wh16->dwBufferLength) {
432 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
433 wh32->dwBufferLength, wh16->dwBufferLength);
434 } else
435 wh32->dwBufferLength = wh16->dwBufferLength;
436 ret = MMSYSTEM_MAP_OKMEM;
438 break;
439 case WIDM_MAPPER_STATUS:
440 /* just a single DWORD */
441 *lpParam2 = (DWORD)MapSL(*lpParam2);
442 ret = MMSYSTEM_MAP_OK;
443 break;
444 default:
445 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
446 break;
448 return ret;
451 /**************************************************************************
452 * MMSYSTDRV_WaveIn_UnMap16To32W [internal]
454 static MMSYSTEM_MapType MMSYSTDRV_WaveIn_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
456 MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR;
458 switch (wMsg) {
459 case WIDM_GETNUMDEVS:
460 case WIDM_RESET:
461 case WIDM_START:
462 case WIDM_STOP:
463 case WIDM_MAPPER_STATUS:
464 ret = MMSYSTEM_MAP_OK;
465 break;
466 case WIDM_OPEN:
467 case WIDM_CLOSE:
468 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
469 break;
470 case WIDM_GETDEVCAPS:
472 LPWAVEINCAPSW wic32 = (LPWAVEINCAPSW)(*lpParam1);
473 LPWAVEINCAPS16 wic16 = *(LPWAVEINCAPS16*)((LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
475 wic16->wMid = wic32->wMid;
476 wic16->wPid = wic32->wPid;
477 wic16->vDriverVersion = wic32->vDriverVersion;
478 WideCharToMultiByte( CP_ACP, 0, wic32->szPname, -1, wic16->szPname,
479 sizeof(wic16->szPname), NULL, NULL );
480 wic16->dwFormats = wic32->dwFormats;
481 wic16->wChannels = wic32->wChannels;
482 HeapFree(GetProcessHeap(), 0, (LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
483 ret = MMSYSTEM_MAP_OK;
485 break;
486 case WIDM_GETPOS:
488 LPMMTIME mmt32 = (LPMMTIME)(*lpParam1);
489 LPMMTIME16 mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
491 MMSYSTEM_MMTIME32to16(mmt16, mmt32);
492 HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
493 ret = MMSYSTEM_MAP_OK;
495 break;
496 case WIDM_ADDBUFFER:
497 case WIDM_PREPARE:
498 case WIDM_UNPREPARE:
500 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
501 LPWAVEHDR wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
503 assert(wh16->lpNext == wh32);
504 wh16->dwBufferLength = wh32->dwBufferLength;
505 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
506 wh16->dwUser = wh32->dwUser;
507 wh16->dwFlags = wh32->dwFlags;
508 wh16->dwLoops = wh32->dwLoops;
510 if (wMsg == WIDM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
511 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
512 wh16->lpNext = 0;
514 ret = MMSYSTEM_MAP_OK;
516 break;
517 default:
518 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
519 break;
521 return ret;
524 /**************************************************************************
525 * MMSYSTDRV_WaveIn_MapCB [internal]
527 static void MMSYSTDRV_WaveIn_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2)
529 switch (uMsg) {
530 case WIM_OPEN:
531 case WIM_CLOSE:
532 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
533 break;
534 case WIM_DATA:
536 /* initial map is: 16 => 32 */
537 LPWAVEHDR wh32 = (LPWAVEHDR)(*dwParam1);
538 SEGPTR segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
539 LPWAVEHDR wh16 = MapSL(segwh16);
541 *dwParam1 = (DWORD)segwh16;
542 wh16->dwFlags = wh32->dwFlags;
543 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
545 break;
546 default:
547 ERR("Unknown msg %u\n", uMsg);
551 /* =================================
552 * W A V E O U T M A P P E R S
553 * ================================= */
555 /**************************************************************************
556 * MMSYSTDRV_WaveOut_Map16To32W [internal]
558 static MMSYSTEM_MapType MMSYSTDRV_WaveOut_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
560 MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR;
562 switch (wMsg) {
563 /* nothing to do */
564 case WODM_BREAKLOOP:
565 case WODM_CLOSE:
566 case WODM_GETNUMDEVS:
567 case WODM_PAUSE:
568 case WODM_RESET:
569 case WODM_RESTART:
570 case WODM_SETPITCH:
571 case WODM_SETPLAYBACKRATE:
572 case WODM_SETVOLUME:
573 ret = MMSYSTEM_MAP_OK;
574 break;
576 case WODM_GETPITCH:
577 case WODM_GETPLAYBACKRATE:
578 case WODM_GETVOLUME:
579 case WODM_OPEN:
580 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
581 break;
583 case WODM_GETDEVCAPS:
585 LPWAVEOUTCAPSW woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSW));
586 LPWAVEOUTCAPS16 woc16 = MapSL(*lpParam1);
588 if (woc32) {
589 *(LPWAVEOUTCAPS16*)woc32 = woc16;
590 woc32 = (LPWAVEOUTCAPSW)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16));
591 *lpParam1 = (DWORD)woc32;
592 *lpParam2 = sizeof(WAVEOUTCAPSW);
594 ret = MMSYSTEM_MAP_OKMEM;
595 } else {
596 ret = MMSYSTEM_MAP_NOMEM;
599 break;
600 case WODM_GETPOS:
602 LPMMTIME mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
603 LPMMTIME16 mmt16 = MapSL(*lpParam1);
605 if (mmt32) {
606 *(LPMMTIME16*)mmt32 = mmt16;
607 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
609 mmt32->wType = mmt16->wType;
610 *lpParam1 = (DWORD)mmt32;
611 *lpParam2 = sizeof(MMTIME);
613 ret = MMSYSTEM_MAP_OKMEM;
614 } else {
615 ret = MMSYSTEM_MAP_NOMEM;
618 break;
619 case WODM_PREPARE:
621 LPWAVEHDR wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
622 LPWAVEHDR wh16 = MapSL(*lpParam1);
624 if (wh32) {
625 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
626 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
627 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
628 wh32->dwBufferLength = wh16->dwBufferLength;
629 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
630 wh32->dwUser = wh16->dwUser;
631 wh32->dwFlags = wh16->dwFlags;
632 wh32->dwLoops = wh16->dwLoops;
633 /* FIXME: nothing on wh32->lpNext */
634 /* could link the wh32->lpNext at this level for memory house keeping */
635 wh16->lpNext = wh32; /* for reuse in unprepare and write */
636 *lpParam1 = (DWORD)wh32;
637 *lpParam2 = sizeof(WAVEHDR);
639 ret = MMSYSTEM_MAP_OKMEM;
640 } else {
641 ret = MMSYSTEM_MAP_NOMEM;
644 break;
645 case WODM_UNPREPARE:
646 case WODM_WRITE:
648 LPWAVEHDR wh16 = MapSL(*lpParam1);
649 LPWAVEHDR wh32 = wh16->lpNext;
651 *lpParam1 = (DWORD)wh32;
652 *lpParam2 = sizeof(WAVEHDR);
653 /* dwBufferLength can be reduced between prepare & write */
654 if (wMsg == WODM_WRITE && wh32->dwBufferLength < wh16->dwBufferLength) {
655 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
656 wh32->dwBufferLength, wh16->dwBufferLength);
657 } else
658 wh32->dwBufferLength = wh16->dwBufferLength;
659 ret = MMSYSTEM_MAP_OKMEM;
661 break;
662 case WODM_MAPPER_STATUS:
663 *lpParam2 = (DWORD)MapSL(*lpParam2);
664 ret = MMSYSTEM_MAP_OK;
665 break;
666 default:
667 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
668 break;
670 return ret;
673 /**************************************************************************
674 * MMSYSTDRV_WaveOut_UnMap16To32W [internal]
676 static MMSYSTEM_MapType MMSYSTDRV_WaveOut_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
678 MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR;
680 switch (wMsg) {
681 /* nothing to do */
682 case WODM_BREAKLOOP:
683 case WODM_CLOSE:
684 case WODM_GETNUMDEVS:
685 case WODM_PAUSE:
686 case WODM_RESET:
687 case WODM_RESTART:
688 case WODM_SETPITCH:
689 case WODM_SETPLAYBACKRATE:
690 case WODM_SETVOLUME:
691 case WODM_MAPPER_STATUS:
692 ret = MMSYSTEM_MAP_OK;
693 break;
695 case WODM_GETPITCH:
696 case WODM_GETPLAYBACKRATE:
697 case WODM_GETVOLUME:
698 case WODM_OPEN:
699 FIXME("Shouldn't be used: those 16 bit functions use the 32 bit interface\n");
700 break;
702 case WODM_GETDEVCAPS:
704 LPWAVEOUTCAPSW woc32 = (LPWAVEOUTCAPSW)(*lpParam1);
705 LPWAVEOUTCAPS16 woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
707 woc16->wMid = woc32->wMid;
708 woc16->wPid = woc32->wPid;
709 woc16->vDriverVersion = woc32->vDriverVersion;
710 WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname,
711 sizeof(woc16->szPname), NULL, NULL );
712 woc16->dwFormats = woc32->dwFormats;
713 woc16->wChannels = woc32->wChannels;
714 woc16->dwSupport = woc32->dwSupport;
715 HeapFree(GetProcessHeap(), 0, (LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
716 ret = MMSYSTEM_MAP_OK;
718 break;
719 case WODM_GETPOS:
721 LPMMTIME mmt32 = (LPMMTIME)(*lpParam1);
722 LPMMTIME16 mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
724 MMSYSTEM_MMTIME32to16(mmt16, mmt32);
725 HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
726 ret = MMSYSTEM_MAP_OK;
728 break;
729 case WODM_PREPARE:
730 case WODM_UNPREPARE:
731 case WODM_WRITE:
733 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
734 LPWAVEHDR wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
736 assert(wh16->lpNext == wh32);
737 wh16->dwBufferLength = wh32->dwBufferLength;
738 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
739 wh16->dwUser = wh32->dwUser;
740 wh16->dwFlags = wh32->dwFlags;
741 wh16->dwLoops = wh32->dwLoops;
743 if (wMsg == WODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
744 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
745 wh16->lpNext = 0;
747 ret = MMSYSTEM_MAP_OK;
749 break;
750 default:
751 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
752 break;
754 return ret;
757 /**************************************************************************
758 * MMDRV_WaveOut_Callback [internal]
760 static void MMSYSTDRV_WaveOut_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2)
762 switch (uMsg) {
763 case WOM_OPEN:
764 case WOM_CLOSE:
765 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
766 break;
767 case WOM_DONE:
769 /* initial map is: 16 => 32 */
770 LPWAVEHDR wh32 = (LPWAVEHDR)(*dwParam1);
771 SEGPTR segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
772 LPWAVEHDR wh16 = MapSL(segwh16);
774 *dwParam1 = (DWORD)segwh16;
775 wh16->dwFlags = wh32->dwFlags;
777 break;
778 default:
779 ERR("Unknown msg %u\n", uMsg);
783 /* ###################################################
784 * # DRIVER THUNKING #
785 * ###################################################
787 typedef MMSYSTEM_MapType (*MMSYSTDRV_MAPMSG)(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2);
788 typedef MMSYSTEM_MapType (*MMSYSTDRV_UNMAPMSG)(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT ret);
789 typedef void (*MMSYSTDRV_MAPCB)(DWORD wMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2);
791 #include <pshpack1.h>
792 #define MMSYSTDRV_MAX_THUNKS 32
794 static struct mmsystdrv_thunk
796 BYTE popl_eax; /* popl %eax (return address) */
797 BYTE pushl_this; /* pushl this (this very thunk) */
798 struct mmsystdrv_thunk* this;
799 BYTE pushl_eax; /* pushl %eax */
800 BYTE jmp; /* ljmp MMDRV_Callback3216 */
801 DWORD callback3216;
802 DWORD callback; /* callback value (function, window, event...) */
803 DWORD flags; /* flags to control callback value (CALLBACK_???) */
804 void* hMmdrv; /* Handle to 32bit mmdrv object */
805 enum MMSYSTEM_DriverType kind;
806 } *MMSYSTDRV_Thunks;
808 #include <poppack.h>
810 static struct MMSYSTDRV_Type
812 MMSYSTDRV_MAPMSG mapmsg16to32W;
813 MMSYSTDRV_UNMAPMSG unmapmsg16to32W;
814 MMSYSTDRV_MAPCB mapcb;
815 } MMSYSTEM_DriversType[MMSYSTDRV_MAX] =
817 {MMSYSTDRV_Mixer_Map16To32W, MMSYSTDRV_Mixer_UnMap16To32W, MMSYSTDRV_Mixer_MapCB},
818 {MMSYSTDRV_MidiIn_Map16To32W, MMSYSTDRV_MidiIn_UnMap16To32W, MMSYSTDRV_MidiIn_MapCB},
819 {MMSYSTDRV_MidiOut_Map16To32W, MMSYSTDRV_MidiOut_UnMap16To32W, MMSYSTDRV_MidiOut_MapCB},
820 {MMSYSTDRV_WaveIn_Map16To32W, MMSYSTDRV_WaveIn_UnMap16To32W, MMSYSTDRV_WaveIn_MapCB},
821 {MMSYSTDRV_WaveOut_Map16To32W, MMSYSTDRV_WaveOut_UnMap16To32W, MMSYSTDRV_WaveOut_MapCB},
824 /******************************************************************
825 * MMSYSTDRV_Callback3216
828 static LRESULT CALLBACK MMSYSTDRV_Callback3216(struct mmsystdrv_thunk* thunk, HDRVR hDev,
829 DWORD wMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1,
830 DWORD_PTR dwParam2)
832 WORD args[8];
834 assert(thunk->kind < MMSYSTDRV_MAX);
835 assert(MMSYSTEM_DriversType[thunk->kind].mapcb);
837 MMSYSTEM_DriversType[thunk->kind].mapcb(wMsg, &dwUser, &dwParam1, &dwParam2);
839 switch (thunk->flags & CALLBACK_TYPEMASK) {
840 case CALLBACK_NULL:
841 TRACE("Null !\n");
842 break;
843 case CALLBACK_WINDOW:
844 TRACE("Window(%04X) handle=%p!\n", thunk->callback, hDev);
845 PostMessageA((HWND)thunk->callback, wMsg, (WPARAM)hDev, dwParam1);
846 break;
847 case CALLBACK_TASK: /* aka CALLBACK_THREAD */
848 TRACE("Task(%04x) !\n", thunk->callback);
849 PostThreadMessageA(thunk->callback, wMsg, (WPARAM)hDev, dwParam1);
850 break;
851 case CALLBACK_FUNCTION:
852 /* 16 bit func, call it */
853 TRACE("Function (16 bit) %x!\n", thunk->callback);
855 args[7] = HDRVR_16(hDev);
856 args[6] = wMsg;
857 args[5] = HIWORD(dwUser);
858 args[4] = LOWORD(dwUser);
859 args[3] = HIWORD(dwParam1);
860 args[2] = LOWORD(dwParam1);
861 args[1] = HIWORD(dwParam2);
862 args[0] = LOWORD(dwParam2);
863 return WOWCallback16Ex(thunk->callback, WCB16_PASCAL, sizeof(args), args, NULL);
864 case CALLBACK_EVENT:
865 TRACE("Event(%08x) !\n", thunk->callback);
866 SetEvent((HANDLE)thunk->callback);
867 break;
868 default:
869 WARN("Unknown callback type %x\n", thunk->flags & CALLBACK_TYPEMASK);
870 return FALSE;
872 TRACE("Done\n");
873 return TRUE;
876 /******************************************************************
877 * MMSYSTDRV_AddThunk
880 struct mmsystdrv_thunk* MMSYSTDRV_AddThunk(DWORD callback, DWORD flags, enum MMSYSTEM_DriverType kind)
882 struct mmsystdrv_thunk* thunk;
884 EnterCriticalSection(&mmdrv_cs);
885 if (!MMSYSTDRV_Thunks)
887 MMSYSTDRV_Thunks = VirtualAlloc(NULL, MMSYSTDRV_MAX_THUNKS * sizeof(*MMSYSTDRV_Thunks),
888 MEM_COMMIT, PAGE_EXECUTE_READWRITE);
889 if (!MMSYSTDRV_Thunks)
891 LeaveCriticalSection(&mmdrv_cs);
892 return NULL;
894 for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++)
896 thunk->popl_eax = 0x58; /* popl %eax */
897 thunk->pushl_this = 0x68; /* pushl this */
898 thunk->this = thunk;
899 thunk->pushl_eax = 0x50; /* pushl %eax */
900 thunk->jmp = 0xe9; /* jmp MMDRV_Callback3216 */
901 thunk->callback3216 = (char *)MMSYSTDRV_Callback3216 - (char *)(&thunk->callback3216 + 1);
902 thunk->callback = 0;
903 thunk->flags = CALLBACK_NULL;
904 thunk->hMmdrv = NULL;
905 thunk->kind = MMSYSTDRV_MAX;
908 for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++)
910 if (thunk->callback == 0 && thunk->hMmdrv == NULL)
912 thunk->callback = callback;
913 thunk->flags = flags;
914 thunk->hMmdrv = NULL;
915 thunk->kind = kind;
916 LeaveCriticalSection(&mmdrv_cs);
917 return thunk;
920 LeaveCriticalSection(&mmdrv_cs);
921 FIXME("Out of mmdrv-thunks. Bump MMDRV_MAX_THUNKS\n");
922 return NULL;
925 /******************************************************************
926 * MMSYSTDRV_FindHandle
928 * Must be called with lock set
930 static void* MMSYSTDRV_FindHandle(void* h)
932 struct mmsystdrv_thunk* thunk;
934 for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++)
936 if (thunk->hMmdrv == h)
938 if (thunk->kind >= MMSYSTDRV_MAX) FIXME("Kind isn't properly initialized %x\n", thunk->kind);
939 return thunk;
942 return NULL;
945 /******************************************************************
946 * MMSYSTDRV_SetHandle
949 void MMSYSTDRV_SetHandle(struct mmsystdrv_thunk* thunk, void* h)
951 if (MMSYSTDRV_FindHandle(h)) FIXME("Already has a thunk for this handle %p!!!\n", h);
952 thunk->hMmdrv = h;
955 /******************************************************************
956 * MMSYSTDRV_DeleteThunk
958 void MMSYSTDRV_DeleteThunk(struct mmsystdrv_thunk* thunk)
960 thunk->callback = 0;
961 thunk->flags = CALLBACK_NULL;
962 thunk->hMmdrv = NULL;
963 thunk->kind = MMSYSTDRV_MAX;
966 /******************************************************************
967 * MMSYSTDRV_CloseHandle
969 void MMSYSTDRV_CloseHandle(void* h)
971 struct mmsystdrv_thunk* thunk;
973 EnterCriticalSection(&mmdrv_cs);
974 if ((thunk = MMSYSTDRV_FindHandle(h)))
976 MMSYSTDRV_DeleteThunk(thunk);
978 LeaveCriticalSection(&mmdrv_cs);
981 /******************************************************************
982 * MMSYSTDRV_Message
984 DWORD MMSYSTDRV_Message(void* h, UINT msg, DWORD_PTR param1, DWORD_PTR param2)
986 struct mmsystdrv_thunk* thunk = MMSYSTDRV_FindHandle(h);
987 struct MMSYSTDRV_Type* drvtype;
988 MMSYSTEM_MapType map;
989 DWORD ret;
991 if (!thunk) return MMSYSERR_INVALHANDLE;
992 drvtype = &MMSYSTEM_DriversType[thunk->kind];
994 map = drvtype->mapmsg16to32W(msg, &param1, &param2);
995 switch (map) {
996 case MMSYSTEM_MAP_NOMEM:
997 ret = MMSYSERR_NOMEM;
998 break;
999 case MMSYSTEM_MAP_MSGERROR:
1000 FIXME("NIY: no conversion yet 16->32 kind=%u msg=%u\n", thunk->kind, msg);
1001 ret = MMSYSERR_ERROR;
1002 break;
1003 case MMSYSTEM_MAP_OK:
1004 case MMSYSTEM_MAP_OKMEM:
1005 TRACE("Calling message(msg=%u p1=0x%08lx p2=0x%08lx)\n",
1006 msg, param1, param2);
1007 switch (thunk->kind)
1009 case MMSYSTDRV_MIXER: ret = mixerMessage (h, msg, param1, param2); break;
1010 case MMSYSTDRV_MIDIIN:
1011 switch (msg)
1013 case MIDM_ADDBUFFER: ret = midiInAddBuffer(h, (LPMIDIHDR)param1, param2); break;
1014 case MIDM_PREPARE: ret = midiInPrepareHeader(h, (LPMIDIHDR)param1, param2); break;
1015 case MIDM_UNPREPARE: ret = midiInUnprepareHeader(h, (LPMIDIHDR)param1, param2); break;
1016 default: ret = midiInMessage(h, msg, param1, param2); break;
1018 break;
1019 case MMSYSTDRV_MIDIOUT:
1020 switch (msg)
1022 case MODM_PREPARE: ret = midiOutPrepareHeader(h, (LPMIDIHDR)param1, param2); break;
1023 case MODM_UNPREPARE: ret = midiOutUnprepareHeader(h, (LPMIDIHDR)param1, param2); break;
1024 case MODM_LONGDATA: ret = midiOutLongMsg(h, (LPMIDIHDR)param1, param2); break;
1025 default: ret = midiOutMessage(h, msg, param1, param2); break;
1027 break;
1028 case MMSYSTDRV_WAVEIN:
1029 switch (msg)
1031 case WIDM_ADDBUFFER: ret = waveInAddBuffer(h, (LPWAVEHDR)param1, param2); break;
1032 case WIDM_PREPARE: ret = waveInPrepareHeader(h, (LPWAVEHDR)param1, param2); break;
1033 case WIDM_UNPREPARE: ret = waveInUnprepareHeader(h, (LPWAVEHDR)param1, param2); break;
1034 default: ret = waveInMessage(h, msg, param1, param2); break;
1036 break;
1037 case MMSYSTDRV_WAVEOUT:
1038 switch (msg)
1040 case WODM_PREPARE: ret = waveOutPrepareHeader(h, (LPWAVEHDR)param1, param2); break;
1041 case WODM_UNPREPARE: ret = waveOutUnprepareHeader(h, (LPWAVEHDR)param1, param2); break;
1042 case WODM_WRITE: ret = waveOutWrite(h, (LPWAVEHDR)param1, param2); break;
1043 default: ret = waveOutMessage(h, msg, param1, param2); break;
1045 break;
1046 default: ret = MMSYSERR_INVALHANDLE; break; /* should never be reached */
1048 if (map == MMSYSTEM_MAP_OKMEM)
1049 drvtype->unmapmsg16to32W(msg, &param1, &param2, ret);
1050 break;
1051 default:
1052 FIXME("NIY\n");
1053 ret = MMSYSERR_NOTSUPPORTED;
1054 break;
1056 return ret;