Added parser template and made AVISplitter use it.
[wine] / dlls / winmm / message16.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  * MMSYSTEM MCI and low level mapping functions
5  *
6  * Copyright 1999 Eric Pouech
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <string.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <assert.h>
27 #include "wine/winbase16.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "winver.h"
32 #include "wownt32.h"
33 #include "winemm16.h"
34 #include "digitalv.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(winmm);
38
39 /**************************************************************************
40  *                              MMDRV_Callback                  [internal]
41  */
42 static  void    MMDRV_Callback(LPWINE_MLD mld, HDRVR hDev, UINT uMsg, DWORD dwParam1, DWORD dwParam2)
43 {
44     TRACE("CB (*%08lx)(%p %08x %08lx %08lx %08lx\n",
45           mld->dwCallback, hDev, uMsg, mld->dwClientInstance, dwParam1, dwParam2);
46
47     if (!mld->bFrom32 && (mld->dwFlags & DCB_TYPEMASK) == DCB_FUNCTION)
48     {
49         WORD args[8];
50         /* 16 bit func, call it */
51         TRACE("Function (16 bit) !\n");
52
53         args[7] = HDRVR_16(hDev);
54         args[6] = uMsg;
55         args[5] = HIWORD(mld->dwClientInstance);
56         args[4] = LOWORD(mld->dwClientInstance);
57         args[3] = HIWORD(dwParam1);
58         args[2] = LOWORD(dwParam1);
59         args[1] = HIWORD(dwParam2);
60         args[0] = LOWORD(dwParam2);
61         WOWCallback16Ex( mld->dwCallback, WCB16_PASCAL, sizeof(args), args, NULL );
62     } else {
63         DriverCallback(mld->dwCallback, mld->dwFlags, hDev, uMsg,
64                        mld->dwClientInstance, dwParam1, dwParam2);
65     }
66 }
67
68 /* =================================
69  *       A U X    M A P P E R S
70  * ================================= */
71
72 /**************************************************************************
73  *                              MMDRV_Aux_Map16To32A            [internal]
74  */
75 static  WINMM_MapType   MMDRV_Aux_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
76 {
77     return WINMM_MAP_MSGERROR;
78 }
79
80 /**************************************************************************
81  *                              MMDRV_Aux_UnMap16To32A          [internal]
82  */
83 static  WINMM_MapType   MMDRV_Aux_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
84 {
85     return WINMM_MAP_MSGERROR;
86 }
87
88 /**************************************************************************
89  *                              MMDRV_Aux_Map32ATo16            [internal]
90  */
91 static  WINMM_MapType   MMDRV_Aux_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
92 {
93     return WINMM_MAP_MSGERROR;
94 }
95
96 /**************************************************************************
97  *                              MMDRV_Aux_UnMap32ATo16          [internal]
98  */
99 static  WINMM_MapType   MMDRV_Aux_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
100 {
101 #if 0
102  case AUXDM_GETDEVCAPS:
103     lpCaps->wMid = ac16.wMid;
104     lpCaps->wPid = ac16.wPid;
105     lpCaps->vDriverVersion = ac16.vDriverVersion;
106     strcpy(lpCaps->szPname, ac16.szPname);
107     lpCaps->wTechnology = ac16.wTechnology;
108     lpCaps->dwSupport = ac16.dwSupport;
109 #endif
110     return WINMM_MAP_MSGERROR;
111 }
112
113 /**************************************************************************
114  *                              MMDRV_Aux_Callback              [internal]
115  */
116 static  void    CALLBACK MMDRV_Aux_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
117 {
118     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
119
120     FIXME("NIY\n");
121     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
122 }
123
124 /* =================================
125  *     M I X E R  M A P P E R S
126  * ================================= */
127
128 /**************************************************************************
129  *                              xMMDRV_Mixer_Map16To32A         [internal]
130  */
131 static  WINMM_MapType   MMDRV_Mixer_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
132 {
133     return WINMM_MAP_MSGERROR;
134 }
135
136 /**************************************************************************
137  *                              MMDRV_Mixer_UnMap16To32A        [internal]
138  */
139 static  WINMM_MapType   MMDRV_Mixer_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
140 {
141 #if 0
142     MIXERCAPSA  micA;
143     UINT        ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
144
145     if (ret == MMSYSERR_NOERROR) {
146         mixcaps->wMid           = micA.wMid;
147         mixcaps->wPid           = micA.wPid;
148         mixcaps->vDriverVersion = micA.vDriverVersion;
149         strcpy(mixcaps->szPname, micA.szPname);
150         mixcaps->fdwSupport     = micA.fdwSupport;
151         mixcaps->cDestinations  = micA.cDestinations;
152     }
153     return ret;
154 #endif
155     return WINMM_MAP_MSGERROR;
156 }
157
158 /**************************************************************************
159  *                              MMDRV_Mixer_Map32ATo16          [internal]
160  */
161 static  WINMM_MapType   MMDRV_Mixer_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
162 {
163     return WINMM_MAP_MSGERROR;
164 }
165
166 /**************************************************************************
167  *                              MMDRV_Mixer_UnMap32ATo16        [internal]
168  */
169 static  WINMM_MapType   MMDRV_Mixer_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
170 {
171     return WINMM_MAP_MSGERROR;
172 }
173
174 /**************************************************************************
175  *                              MMDRV_Mixer_Callback            [internal]
176  */
177 static  void    CALLBACK MMDRV_Mixer_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
178 {
179     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
180
181     FIXME("NIY\n");
182     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
183 }
184
185 /* =================================
186  *   M I D I  I N    M A P P E R S
187  * ================================= */
188
189 /**************************************************************************
190  *                              MMDRV_MidiIn_Map16To32A         [internal]
191  */
192 static  WINMM_MapType   MMDRV_MidiIn_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
193 {
194     return WINMM_MAP_MSGERROR;
195 }
196
197 /**************************************************************************
198  *                              MMDRV_MidiIn_UnMap16To32A       [internal]
199  */
200 static  WINMM_MapType   MMDRV_MidiIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
201 {
202     return WINMM_MAP_MSGERROR;
203 }
204
205 /**************************************************************************
206  *                              MMDRV_MidiIn_Map32ATo16         [internal]
207  */
208 static  WINMM_MapType   MMDRV_MidiIn_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
209 {
210     return WINMM_MAP_MSGERROR;
211 }
212
213 /**************************************************************************
214  *                              MMDRV_MidiIn_UnMap32ATo16       [internal]
215  */
216 static  WINMM_MapType   MMDRV_MidiIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
217 {
218     return WINMM_MAP_MSGERROR;
219 }
220
221 /**************************************************************************
222  *                              MMDRV_MidiIn_Callback           [internal]
223  */
224 static  void    CALLBACK MMDRV_MidiIn_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
225 {
226     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
227
228     switch (uMsg) {
229     case MIM_OPEN:
230     case MIM_CLOSE:
231         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
232
233     case MIM_DATA:
234     case MIM_MOREDATA:
235     case MIM_ERROR:
236         /* dwParam1 & dwParam2 are are data, nothing to do */
237         break;
238     case MIM_LONGDATA:
239     case MIM_LONGERROR:
240         /* dwParam1 points to a MidiHdr, work to be done !!! */
241         if (mld->bFrom32 && !MMDRV_Is32(mld->mmdIndex)) {
242             /* initial map is: 32 => 16 */
243             LPMIDIHDR           mh16 = MapSL(dwParam1);
244             LPMIDIHDR           mh32 = *(LPMIDIHDR*)((LPSTR)mh16 - sizeof(LPMIDIHDR));
245
246             dwParam1 = (DWORD)mh32;
247             mh32->dwFlags = mh16->dwFlags;
248             mh32->dwBytesRecorded = mh16->dwBytesRecorded;
249             if (mh32->reserved >= sizeof(MIDIHDR))
250                 mh32->dwOffset = mh16->dwOffset;
251         } else if (!mld->bFrom32 && MMDRV_Is32(mld->mmdIndex)) {
252             /* initial map is: 16 => 32 */
253             LPMIDIHDR           mh32 = (LPMIDIHDR)(dwParam1);
254             SEGPTR              segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
255             LPMIDIHDR           mh16 = MapSL(segmh16);
256
257             dwParam1 = (DWORD)segmh16;
258             mh16->dwFlags = mh32->dwFlags;
259             mh16->dwBytesRecorded = mh32->dwBytesRecorded;
260             if (mh16->reserved >= sizeof(MIDIHDR))
261                 mh16->dwOffset = mh32->dwOffset;
262         }
263         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
264         break;
265     /* case MOM_POSITIONCB: */
266     default:
267         ERR("Unknown msg %u\n", uMsg);
268     }
269
270     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
271 }
272
273 /* =================================
274  *   M I D I  O U T  M A P P E R S
275  * ================================= */
276
277 /**************************************************************************
278  *                              MMDRV_MidiOut_Map16To32A        [internal]
279  */
280 static  WINMM_MapType   MMDRV_MidiOut_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
281 {
282     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
283
284     switch (wMsg) {
285     case MODM_GETNUMDEVS:
286     case MODM_DATA:
287     case MODM_RESET:
288     case MODM_SETVOLUME:
289         ret = WINMM_MAP_OK;
290         break;
291
292     case MODM_OPEN:
293     case MODM_CLOSE:
294     case MODM_GETVOLUME:
295         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
296         break;
297
298     case MODM_GETDEVCAPS:
299         {
300             LPMIDIOUTCAPSW      moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSW));
301             LPMIDIOUTCAPS16     moc16 = MapSL(*lpParam1);
302
303             if (moc32) {
304                 *(LPMIDIOUTCAPS16*)moc32 = moc16;
305                 moc32 = (LPMIDIOUTCAPSW)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16));
306                 *lpParam1 = (DWORD)moc32;
307                 *lpParam2 = sizeof(MIDIOUTCAPSW);
308
309                 ret = WINMM_MAP_OKMEM;
310             } else {
311                 ret = WINMM_MAP_NOMEM;
312             }
313         }
314         break;
315     case MODM_PREPARE:
316         {
317             LPMIDIHDR           mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR));
318             LPMIDIHDR           mh16 = MapSL(*lpParam1);
319
320             if (mh32) {
321                 *(LPMIDIHDR*)mh32 = (LPMIDIHDR)*lpParam1;
322                 mh32 = (LPMIDIHDR)((LPSTR)mh32 + sizeof(LPMIDIHDR));
323                 mh32->lpData = MapSL((SEGPTR)mh16->lpData);
324                 mh32->dwBufferLength = mh16->dwBufferLength;
325                 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
326                 mh32->dwUser = mh16->dwUser;
327                 mh32->dwFlags = mh16->dwFlags;
328                 /* FIXME: nothing on mh32->lpNext */
329                 /* could link the mh32->lpNext at this level for memory house keeping */
330                 mh32->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? ((LPMIDIHDR)mh16)->dwOffset : 0;
331                 mh16->lpNext = mh32; /* for reuse in unprepare and write */
332                 /* store size of passed MIDIHDR?? structure to know if dwOffset is available or not */
333                 mh16->reserved = *lpParam2;
334                 *lpParam1 = (DWORD)mh32;
335                 *lpParam2 = sizeof(MIDIHDR);
336
337                 ret = WINMM_MAP_OKMEM;
338             } else {
339                 ret = WINMM_MAP_NOMEM;
340             }
341         }
342         break;
343     case MODM_UNPREPARE:
344     case MODM_LONGDATA:
345         {
346             LPMIDIHDR           mh16 = MapSL(*lpParam1);
347             LPMIDIHDR           mh32 = (LPMIDIHDR)mh16->lpNext;
348
349             *lpParam1 = (DWORD)mh32;
350             *lpParam2 = sizeof(MIDIHDR);
351             /* dwBufferLength can be reduced between prepare & write */
352             if (wMsg == MODM_LONGDATA && mh32->dwBufferLength < mh16->dwBufferLength) {
353                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
354                     mh32->dwBufferLength, mh16->dwBufferLength);
355             } else
356                 mh32->dwBufferLength = mh16->dwBufferLength;
357             ret = WINMM_MAP_OKMEM;
358         }
359         break;
360
361     case MODM_CACHEPATCHES:
362     case MODM_CACHEDRUMPATCHES:
363     default:
364         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
365         break;
366     }
367     return ret;
368 }
369
370 /**************************************************************************
371  *                              MMDRV_MidiOut_UnMap16To32A      [internal]
372  */
373 static  WINMM_MapType   MMDRV_MidiOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
374 {
375     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
376
377     switch (wMsg) {
378     case MODM_GETNUMDEVS:
379     case MODM_DATA:
380     case MODM_RESET:
381     case MODM_SETVOLUME:
382         ret = WINMM_MAP_OK;
383         break;
384
385     case MODM_OPEN:
386     case MODM_CLOSE:
387     case MODM_GETVOLUME:
388         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
389         break;
390
391     case MODM_GETDEVCAPS:
392         {
393             LPMIDIOUTCAPSW              moc32 = (LPMIDIOUTCAPSW)(*lpParam1);
394             LPMIDIOUTCAPS16             moc16 = *(LPMIDIOUTCAPS16*)((LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
395
396             moc16->wMid                 = moc32->wMid;
397             moc16->wPid                 = moc32->wPid;
398             moc16->vDriverVersion       = moc32->vDriverVersion;
399             WideCharToMultiByte( CP_ACP, 0, moc32->szPname, -1, moc16->szPname,
400                                  sizeof(moc16->szPname), NULL, NULL );
401             moc16->wTechnology          = moc32->wTechnology;
402             moc16->wVoices              = moc32->wVoices;
403             moc16->wNotes               = moc32->wNotes;
404             moc16->wChannelMask         = moc32->wChannelMask;
405             moc16->dwSupport            = moc32->dwSupport;
406             HeapFree(GetProcessHeap(), 0, (LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
407             ret = WINMM_MAP_OK;
408         }
409         break;
410     case MODM_PREPARE:
411     case MODM_UNPREPARE:
412     case MODM_LONGDATA:
413         {
414             LPMIDIHDR           mh32 = (LPMIDIHDR)(*lpParam1);
415             LPMIDIHDR           mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)));
416
417             assert(mh16->lpNext == mh32);
418             mh16->dwBufferLength = mh32->dwBufferLength;
419             mh16->dwBytesRecorded = mh32->dwBytesRecorded;
420             mh16->dwUser = mh32->dwUser;
421             mh16->dwFlags = mh32->dwFlags;
422             if (mh16->reserved >= sizeof(MIDIHDR))
423                 mh16->dwOffset = mh32->dwOffset;
424
425             if (wMsg == MODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
426                 HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR));
427                 mh16->lpNext = 0;
428             }
429             ret = WINMM_MAP_OK;
430         }
431         break;
432
433     case MODM_CACHEPATCHES:
434     case MODM_CACHEDRUMPATCHES:
435     default:
436         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
437         break;
438     }
439     return ret;
440 }
441
442 /**************************************************************************
443  *                              MMDRV_MidiOut_Map32ATo16        [internal]
444  */
445 static  WINMM_MapType   MMDRV_MidiOut_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
446 {
447     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
448
449     switch (wMsg) {
450     case MODM_CLOSE:
451     case MODM_GETNUMDEVS:
452     case MODM_DATA:
453     case MODM_RESET:
454     case MODM_SETVOLUME:
455         ret = WINMM_MAP_OK;
456         break;
457     case MODM_GETDEVCAPS:
458         {
459             LPMIDIOUTCAPSW moc32 = (LPMIDIOUTCAPSW)*lpParam1;
460             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPSW)+sizeof(MIDIOUTCAPS16));
461
462             if (ptr) {
463                 *(LPMIDIOUTCAPSW*)ptr = moc32;
464                 ret = WINMM_MAP_OKMEM;
465             } else {
466                 ret = WINMM_MAP_NOMEM;
467             }
468             *lpParam1 = (DWORD)MapLS(ptr) + sizeof(LPMIDIOUTCAPSW);
469             *lpParam2 = sizeof(MIDIOUTCAPS16);
470         }
471         break;
472     case MODM_PREPARE:
473         {
474             LPMIDIHDR           mh32 = (LPMIDIHDR)*lpParam1;
475             LPMIDIHDR           mh16;
476             LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
477                                     sizeof(LPMIDIHDR) + sizeof(MIDIHDR) + mh32->dwBufferLength);
478
479             if (ptr) {
480                 *(LPMIDIHDR*)ptr = mh32;
481                 mh16 = (LPMIDIHDR)((LPSTR)ptr + sizeof(LPMIDIHDR));
482                 *lpParam1 = MapLS(mh16);
483                 mh16->lpData = (LPSTR)*lpParam1 + sizeof(MIDIHDR);
484                 /* data will be copied on WODM_WRITE */
485                 mh16->dwBufferLength = mh32->dwBufferLength;
486                 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
487                 mh16->dwUser = mh32->dwUser;
488                 mh16->dwFlags = mh32->dwFlags;
489                 /* FIXME: nothing on mh32->lpNext */
490                 /* could link the mh32->lpNext at this level for memory house keeping */
491                 mh16->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? mh32->dwOffset : 0;
492
493                 mh32->lpNext = (LPMIDIHDR)mh16; /* for reuse in unprepare and write */
494                 mh32->reserved = *lpParam2;
495
496                 TRACE("mh16=%08lx mh16->lpData=%08lx mh32->buflen=%lu mh32->lpData=%08lx\n",
497                       *lpParam1, (DWORD)mh16->lpData,
498                       mh32->dwBufferLength, (DWORD)mh32->lpData);
499                 *lpParam2 = sizeof(MIDIHDR);
500
501                 ret = WINMM_MAP_OKMEM;
502             } else {
503                 ret = WINMM_MAP_NOMEM;
504             }
505         }
506         break;
507     case MODM_UNPREPARE:
508     case MODM_LONGDATA:
509         {
510             LPMIDIHDR           mh32 = (LPMIDIHDR)(*lpParam1);
511             LPMIDIHDR           mh16 = (LPMIDIHDR)mh32->lpNext;
512             LPSTR               ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
513
514             assert(*(LPMIDIHDR*)ptr == mh32);
515
516             if (wMsg == MODM_LONGDATA)
517                 memcpy((LPSTR)mh16 + sizeof(MIDIHDR), mh32->lpData, mh32->dwBufferLength);
518
519             *lpParam1 = MapLS(mh16);
520             *lpParam2 = sizeof(MIDIHDR);
521             TRACE("mh16=%08lx mh16->lpData=%08lx mh32->buflen=%lu mh32->lpData=%08lx\n",
522                   *lpParam1, (DWORD)mh16->lpData, mh32->dwBufferLength, (DWORD)mh32->lpData);
523
524             /* dwBufferLength can be reduced between prepare & write */
525             if (wMsg == MODM_LONGDATA && mh16->dwBufferLength < mh32->dwBufferLength) {
526                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
527                     mh16->dwBufferLength, mh32->dwBufferLength);
528             } else
529                 mh16->dwBufferLength = mh32->dwBufferLength;
530             ret = WINMM_MAP_OKMEM;
531         }
532         break;
533     case MODM_OPEN:
534         {
535             LPMIDIOPENDESC              mod32 = (LPMIDIOPENDESC)*lpParam1;
536             LPVOID                      ptr;
537             LPMIDIOPENDESC16            mod16;
538
539             /* allocated data are mapped as follows:
540                LPMIDIOPENDESC   ptr to orig lParam1
541                DWORD            orig dwUser, which is a pointer to DWORD:driver dwInstance
542                DWORD            dwUser passed to driver
543                MIDIOPENDESC16   mod16: openDesc passed to driver
544                MIDIOPENSTRMID   cIds
545             */
546             ptr = HeapAlloc( GetProcessHeap(), 0,
547                              sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD) + sizeof(MIDIOPENDESC16) +
548                              mod32->cIds ? (mod32->cIds - 1) * sizeof(MIDIOPENSTRMID) : 0);
549
550             if (ptr) {
551                 SEGPTR segptr = MapLS(ptr);
552                 *(LPMIDIOPENDESC*)ptr = mod32;
553                 *(LPDWORD)((char*)ptr + sizeof(LPMIDIOPENDESC)) = *lpdwUser;
554                 mod16 = (LPMIDIOPENDESC16)((LPSTR)ptr + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD));
555
556                 mod16->hMidi = HMIDI_16(mod32->hMidi);
557                 mod16->dwCallback = mod32->dwCallback;
558                 mod16->dwInstance = mod32->dwInstance;
559                 mod16->dnDevNode = mod32->dnDevNode;
560                 mod16->cIds = mod32->cIds;
561                 memcpy(&mod16->rgIds, &mod32->rgIds, mod32->cIds * sizeof(MIDIOPENSTRMID));
562
563                 *lpParam1 = (DWORD)segptr + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD);
564                 *lpdwUser = (DWORD)segptr + sizeof(LPMIDIOPENDESC) + sizeof(DWORD);
565
566                 ret = WINMM_MAP_OKMEM;
567             } else {
568                 ret = WINMM_MAP_NOMEM;
569             }
570         }
571         break;
572     case MODM_GETVOLUME:
573     case MODM_CACHEPATCHES:
574     case MODM_CACHEDRUMPATCHES:
575     default:
576         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
577         break;
578     }
579     return ret;
580 }
581
582 /**************************************************************************
583  *                              MMDRV_MidiOut_UnMap32ATo16      [internal]
584  */
585 static  WINMM_MapType   MMDRV_MidiOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
586 {
587     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
588
589     switch (wMsg) {
590     case MODM_CLOSE:
591     case MODM_GETNUMDEVS:
592     case MODM_DATA:
593     case MODM_RESET:
594     case MODM_SETVOLUME:
595         ret = WINMM_MAP_OK;
596         break;
597     case MODM_GETDEVCAPS:
598         {
599             LPMIDIOUTCAPS16             moc16 = MapSL(*lpParam1);
600             LPSTR                       ptr   = (LPSTR)moc16 - sizeof(LPMIDIOUTCAPSW);
601             LPMIDIOUTCAPSW              moc32 = *(LPMIDIOUTCAPSW*)ptr;
602
603             moc32->wMid                 = moc16->wMid;
604             moc32->wPid                 = moc16->wPid;
605             moc32->vDriverVersion       = moc16->vDriverVersion;
606             WideCharToMultiByte( CP_ACP, 0, moc32->szPname, -1, moc16->szPname,
607                                  sizeof(moc16->szPname), NULL, NULL );
608             moc32->wTechnology          = moc16->wTechnology;
609             moc32->wVoices              = moc16->wVoices;
610             moc32->wNotes               = moc16->wNotes;
611             moc32->wChannelMask         = moc16->wChannelMask;
612             moc32->dwSupport            = moc16->dwSupport;
613             UnMapLS( *lpParam1 );
614             HeapFree( GetProcessHeap(), 0, ptr );
615             ret = WINMM_MAP_OK;
616         }
617         break;
618     case MODM_PREPARE:
619     case MODM_UNPREPARE:
620     case MODM_LONGDATA:
621         {
622             LPMIDIHDR           mh16 = MapSL(*lpParam1);
623             LPSTR               ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
624             LPMIDIHDR           mh32 = *(LPMIDIHDR*)ptr;
625
626             assert(mh32->lpNext == (LPMIDIHDR)mh16);
627             UnMapLS( *lpParam1 );
628             mh32->dwBytesRecorded = mh16->dwBytesRecorded;
629             mh32->dwUser = mh16->dwUser;
630             mh32->dwFlags = mh16->dwFlags;
631
632             if (wMsg == MODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
633                 HeapFree( GetProcessHeap(), 0, ptr );
634                 mh32->lpNext = 0;
635             }
636             ret = WINMM_MAP_OK;
637         }
638         break;
639     case MODM_OPEN:
640         {
641             LPMIDIOPENDESC16            mod16 = MapSL(*lpParam1);
642             LPSTR                       ptr   = (LPSTR)mod16 - sizeof(LPMIDIOPENDESC) - 2*sizeof(DWORD);
643             UnMapLS( *lpParam1 );
644             **(DWORD**)(ptr + sizeof(LPMIDIOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPMIDIOPENDESC) + sizeof(DWORD));
645
646             HeapFree( GetProcessHeap(), 0, ptr );
647             ret = WINMM_MAP_OK;
648         }
649         break;
650     case MODM_GETVOLUME:
651     case MODM_CACHEPATCHES:
652     case MODM_CACHEDRUMPATCHES:
653     default:
654         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
655         break;
656     }
657     return ret;
658 }
659
660 /**************************************************************************
661  *                              MMDRV_MidiOut_Callback          [internal]
662  */
663 static  void    CALLBACK MMDRV_MidiOut_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
664 {
665     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
666
667     switch (uMsg) {
668     case MOM_OPEN:
669     case MOM_CLOSE:
670         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
671         break;
672     case MOM_DONE:
673         if (mld->bFrom32 && !MMDRV_Is32(mld->mmdIndex)) {
674             /* initial map is: 32 => 16 */
675             LPMIDIHDR           mh16 = MapSL(dwParam1);
676             LPMIDIHDR           mh32 = *(LPMIDIHDR*)((LPSTR)mh16 - sizeof(LPMIDIHDR));
677
678             dwParam1 = (DWORD)mh32;
679             mh32->dwFlags = mh16->dwFlags;
680             mh32->dwOffset = mh16->dwOffset;
681             if (mh32->reserved >= sizeof(MIDIHDR))
682                 mh32->dwOffset = mh16->dwOffset;
683         } else if (!mld->bFrom32 && MMDRV_Is32(mld->mmdIndex)) {
684             /* initial map is: 16 => 32 */
685             LPMIDIHDR           mh32 = (LPMIDIHDR)(dwParam1);
686             SEGPTR              segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
687             LPMIDIHDR           mh16 = MapSL(segmh16);
688
689             dwParam1 = (DWORD)segmh16;
690             mh16->dwFlags = mh32->dwFlags;
691             if (mh16->reserved >= sizeof(MIDIHDR))
692                 mh16->dwOffset = mh32->dwOffset;
693         }
694         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
695         break;
696     /* case MOM_POSITIONCB: */
697     default:
698         ERR("Unknown msg %u\n", uMsg);
699     }
700
701     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
702 }
703
704 /* =================================
705  *   W A V E  I N    M A P P E R S
706  * ================================= */
707
708 /**************************************************************************
709  *                              MMDRV_WaveIn_Map16To32A         [internal]
710  */
711 static  WINMM_MapType   MMDRV_WaveIn_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
712 {
713     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
714
715     switch (wMsg) {
716     case WIDM_GETNUMDEVS:
717     case WIDM_RESET:
718     case WIDM_START:
719     case WIDM_STOP:
720         ret = WINMM_MAP_OK;
721         break;
722     case WIDM_OPEN:
723     case WIDM_CLOSE:
724         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
725         break;
726     case WIDM_GETDEVCAPS:
727         {
728             LPWAVEINCAPSW       wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSW));
729             LPWAVEINCAPS16      wic16 = MapSL(*lpParam1);
730
731             if (wic32) {
732                 *(LPWAVEINCAPS16*)wic32 = wic16;
733                 wic32 = (LPWAVEINCAPSW)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16));
734                 *lpParam1 = (DWORD)wic32;
735                 *lpParam2 = sizeof(WAVEINCAPSW);
736
737                 ret = WINMM_MAP_OKMEM;
738             } else {
739                 ret = WINMM_MAP_NOMEM;
740             }
741         }
742         break;
743     case WIDM_GETPOS:
744         {
745             LPMMTIME            mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
746             LPMMTIME16          mmt16 = MapSL(*lpParam1);
747
748             if (mmt32) {
749                 *(LPMMTIME16*)mmt32 = mmt16;
750                 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
751
752                 mmt32->wType = mmt16->wType;
753                 *lpParam1 = (DWORD)mmt32;
754                 *lpParam2 = sizeof(MMTIME);
755
756                 ret = WINMM_MAP_OKMEM;
757             } else {
758                 ret = WINMM_MAP_NOMEM;
759             }
760         }
761         break;
762     case WIDM_PREPARE:
763         {
764             LPWAVEHDR           wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
765             LPWAVEHDR           wh16 = MapSL(*lpParam1);
766
767             if (wh32) {
768                 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
769                 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
770                 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
771                 wh32->dwBufferLength = wh16->dwBufferLength;
772                 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
773                 wh32->dwUser = wh16->dwUser;
774                 wh32->dwFlags = wh16->dwFlags;
775                 wh32->dwLoops = wh16->dwLoops;
776                 /* FIXME: nothing on wh32->lpNext */
777                 /* could link the wh32->lpNext at this level for memory house keeping */
778                 wh16->lpNext = wh32; /* for reuse in unprepare and write */
779                 *lpParam1 = (DWORD)wh32;
780                 *lpParam2 = sizeof(WAVEHDR);
781
782                 ret = WINMM_MAP_OKMEM;
783             } else {
784                 ret = WINMM_MAP_NOMEM;
785             }
786         }
787         break;
788     case WIDM_ADDBUFFER:
789     case WIDM_UNPREPARE:
790         {
791             LPWAVEHDR           wh16 = MapSL(*lpParam1);
792             LPWAVEHDR           wh32 = (LPWAVEHDR)wh16->lpNext;
793
794             *lpParam1 = (DWORD)wh32;
795             *lpParam2 = sizeof(WAVEHDR);
796             /* dwBufferLength can be reduced between prepare & write */
797             if (wMsg == WIDM_ADDBUFFER && wh32->dwBufferLength < wh16->dwBufferLength) {
798                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
799                     wh32->dwBufferLength, wh16->dwBufferLength);
800             } else
801                 wh32->dwBufferLength = wh16->dwBufferLength;
802             ret = WINMM_MAP_OKMEM;
803         }
804         break;
805     case WIDM_MAPPER_STATUS:
806         /* just a single DWORD */
807         *lpParam2 = (DWORD)MapSL(*lpParam2);
808         ret = WINMM_MAP_OK;
809         break;
810     default:
811         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
812         break;
813     }
814     return ret;
815 }
816
817 /**************************************************************************
818  *                              MMDRV_WaveIn_UnMap16To32A       [internal]
819  */
820 static  WINMM_MapType   MMDRV_WaveIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
821 {
822     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
823
824     switch (wMsg) {
825     case WIDM_GETNUMDEVS:
826     case WIDM_RESET:
827     case WIDM_START:
828     case WIDM_STOP:
829     case WIDM_MAPPER_STATUS:
830         ret = WINMM_MAP_OK;
831         break;
832     case WIDM_OPEN:
833     case WIDM_CLOSE:
834         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
835         break;
836     case WIDM_GETDEVCAPS:
837         {
838             LPWAVEINCAPSW               wic32 = (LPWAVEINCAPSW)(*lpParam1);
839             LPWAVEINCAPS16              wic16 = *(LPWAVEINCAPS16*)((LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
840
841             wic16->wMid = wic32->wMid;
842             wic16->wPid = wic32->wPid;
843             wic16->vDriverVersion = wic32->vDriverVersion;
844             WideCharToMultiByte( CP_ACP, 0, wic32->szPname, -1, wic16->szPname,
845                                  sizeof(wic16->szPname), NULL, NULL );
846             wic16->dwFormats = wic32->dwFormats;
847             wic16->wChannels = wic32->wChannels;
848             HeapFree(GetProcessHeap(), 0, (LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
849             ret = WINMM_MAP_OK;
850         }
851         break;
852     case WIDM_GETPOS:
853         {
854             LPMMTIME            mmt32 = (LPMMTIME)(*lpParam1);
855             LPMMTIME16          mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
856
857             MMSYSTEM_MMTIME32to16(mmt16, mmt32);
858             HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
859             ret = WINMM_MAP_OK;
860         }
861         break;
862     case WIDM_ADDBUFFER:
863     case WIDM_PREPARE:
864     case WIDM_UNPREPARE:
865         {
866             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
867             LPWAVEHDR           wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
868
869             assert(wh16->lpNext == wh32);
870             wh16->dwBufferLength = wh32->dwBufferLength;
871             wh16->dwBytesRecorded = wh32->dwBytesRecorded;
872             wh16->dwUser = wh32->dwUser;
873             wh16->dwFlags = wh32->dwFlags;
874             wh16->dwLoops = wh32->dwLoops;
875
876             if (wMsg == WIDM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
877                 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
878                 wh16->lpNext = 0;
879             }
880             ret = WINMM_MAP_OK;
881         }
882         break;
883     default:
884         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
885         break;
886     }
887     return ret;
888 }
889
890 /**************************************************************************
891  *                              MMDRV_WaveIn_Map32ATo16         [internal]
892  */
893 static  WINMM_MapType   MMDRV_WaveIn_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
894 {
895     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
896
897     switch (wMsg) {
898     case WIDM_CLOSE:
899     case WIDM_GETNUMDEVS:
900     case WIDM_RESET:
901     case WIDM_START:
902     case WIDM_STOP:
903         ret = WINMM_MAP_OK;
904         break;
905
906     case WIDM_OPEN:
907         {
908             LPWAVEOPENDESC              wod32 = (LPWAVEOPENDESC)*lpParam1;
909             int                         sz = sizeof(WAVEFORMATEX);
910             LPVOID                      ptr;
911             LPWAVEOPENDESC16            wod16;
912
913             /* allocated data are mapped as follows:
914                LPWAVEOPENDESC   ptr to orig lParam1
915                DWORD            orig dwUser, which is a pointer to DWORD:driver dwInstance
916                DWORD            dwUser passed to driver
917                WAVEOPENDESC16   wod16: openDesc passed to driver
918                WAVEFORMATEX     openDesc->lpFormat passed to driver
919                xxx              extra bytes to WAVEFORMATEX
920             */
921             if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
922                 TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag);
923                 sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize;
924             }
925
926             ptr = HeapAlloc( GetProcessHeap(), 0,
927                              sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
928
929             if (ptr) {
930                 SEGPTR seg_ptr = MapLS( ptr );
931                 *(LPWAVEOPENDESC*)ptr = wod32;
932                 *(LPDWORD)((char*)ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
933                 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
934
935                 wod16->hWave = HWAVE_16(wod32->hWave);
936                 wod16->lpFormat = (LPWAVEFORMATEX)(seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16));
937                 memcpy(wod16 + 1, wod32->lpFormat, sz);
938
939                 wod16->dwCallback = wod32->dwCallback;
940                 wod16->dwInstance = wod32->dwInstance;
941                 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
942                 wod16->dnDevNode = wod32->dnDevNode;
943
944                 *lpParam1 = seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
945                 *lpdwUser = seg_ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
946
947                 ret = WINMM_MAP_OKMEM;
948             } else {
949                 ret = WINMM_MAP_NOMEM;
950             }
951         }
952         break;
953     case WIDM_PREPARE:
954         {
955             LPWAVEHDR           wh32 = (LPWAVEHDR)*lpParam1;
956             LPWAVEHDR           wh16;
957             LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
958                                     sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
959
960             if (ptr) {
961                 SEGPTR seg_ptr = MapLS( ptr );
962                 *(LPWAVEHDR*)ptr = wh32;
963                 wh16 = (LPWAVEHDR)((LPSTR)ptr + sizeof(LPWAVEHDR));
964                 wh16->lpData = (LPSTR)seg_ptr + sizeof(LPWAVEHDR) + sizeof(WAVEHDR);
965                 /* data will be copied on WODM_WRITE */
966                 wh16->dwBufferLength = wh32->dwBufferLength;
967                 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
968                 wh16->dwUser = wh32->dwUser;
969                 wh16->dwFlags = wh32->dwFlags;
970                 wh16->dwLoops = wh32->dwLoops;
971                 /* FIXME: nothing on wh32->lpNext */
972                 /* could link the wh32->lpNext at this level for memory house keeping */
973                 wh32->lpNext = wh16; /* for reuse in unprepare and write */
974                 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
975                       seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
976                       wh32->dwBufferLength, (DWORD)wh32->lpData);
977                 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
978                 *lpParam2 = sizeof(WAVEHDR);
979
980                 ret = WINMM_MAP_OKMEM;
981             } else {
982                 ret = WINMM_MAP_NOMEM;
983             }
984         }
985         break;
986     case WIDM_ADDBUFFER:
987     case WIDM_UNPREPARE:
988         {
989             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
990             LPWAVEHDR           wh16 = wh32->lpNext;
991             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
992             SEGPTR seg_ptr = MapLS( ptr );
993
994             assert(*(LPWAVEHDR*)ptr == wh32);
995
996             TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
997                   seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
998                   wh32->dwBufferLength, (DWORD)wh32->lpData);
999
1000             if (wMsg == WIDM_ADDBUFFER)
1001                 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
1002
1003             *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1004             *lpParam2 = sizeof(WAVEHDR);
1005             /* dwBufferLength can be reduced between prepare & write */
1006             if (wMsg == WIDM_ADDBUFFER && wh16->dwBufferLength < wh32->dwBufferLength) {
1007                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
1008                     wh16->dwBufferLength, wh32->dwBufferLength);
1009             } else
1010                 wh16->dwBufferLength = wh32->dwBufferLength;
1011             ret = WINMM_MAP_OKMEM;
1012         }
1013         break;
1014    case WIDM_GETDEVCAPS:
1015         {
1016             LPWAVEINCAPSW wic32 = (LPWAVEINCAPSW)*lpParam1;
1017             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0 ,sizeof(LPWAVEINCAPSW) + sizeof(WAVEINCAPS16));
1018
1019             if (ptr) {
1020                 *(LPWAVEINCAPSW*)ptr = wic32;
1021                 ret = WINMM_MAP_OKMEM;
1022             } else {
1023                 ret = WINMM_MAP_NOMEM;
1024             }
1025             *lpParam1 = MapLS(ptr) + sizeof(LPWAVEINCAPSW);
1026             *lpParam2 = sizeof(WAVEINCAPS16);
1027         }
1028         break;
1029     case WIDM_GETPOS:
1030         {
1031             LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1032             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMMTIME) + sizeof(MMTIME16));
1033             LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1034
1035             if (ptr) {
1036                 *(LPMMTIME*)ptr = mmt32;
1037                 mmt16->wType = mmt32->wType;
1038                 ret = WINMM_MAP_OKMEM;
1039             } else {
1040                 ret = WINMM_MAP_NOMEM;
1041             }
1042             *lpParam1 = MapLS(ptr) + sizeof(LPMMTIME);
1043             *lpParam2 = sizeof(MMTIME16);
1044         }
1045         break;
1046     case DRVM_MAPPER_STATUS:
1047         {
1048             LPDWORD p32 = (LPDWORD)*lpParam2;
1049             *lpParam2 = MapLS(p32);
1050             ret = WINMM_MAP_OKMEM;
1051         }
1052         break;
1053     default:
1054         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1055         break;
1056     }
1057     return ret;
1058 }
1059
1060 /**************************************************************************
1061  *                              MMDRV_WaveIn_UnMap32ATo16       [internal]
1062  */
1063 static  WINMM_MapType   MMDRV_WaveIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
1064 {
1065     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
1066
1067     switch (wMsg) {
1068     case WIDM_CLOSE:
1069     case WIDM_GETNUMDEVS:
1070     case WIDM_RESET:
1071     case WIDM_START:
1072     case WIDM_STOP:
1073         ret = WINMM_MAP_OK;
1074         break;
1075
1076     case WIDM_OPEN:
1077         {
1078             LPWAVEOPENDESC16            wod16 = MapSL(*lpParam1);
1079             LPSTR                       ptr   = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1080             LPWAVEOPENDESC              wod32 = *(LPWAVEOPENDESC*)ptr;
1081
1082             UnMapLS( *lpParam1 );
1083             wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1084             **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1085             HeapFree( GetProcessHeap(), 0, ptr );
1086             ret = WINMM_MAP_OK;
1087         }
1088         break;
1089
1090     case WIDM_ADDBUFFER:
1091     case WIDM_PREPARE:
1092     case WIDM_UNPREPARE:
1093         {
1094             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1095             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1096             LPWAVEHDR           wh32 = *(LPWAVEHDR*)ptr;
1097
1098             assert(wh32->lpNext == wh16);
1099             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1100             wh32->dwUser = wh16->dwUser;
1101             wh32->dwFlags = wh16->dwFlags;
1102             wh32->dwLoops = wh16->dwLoops;
1103             UnMapLS( *lpParam1 );
1104
1105             if (wMsg == WIDM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
1106                 HeapFree( GetProcessHeap(), 0, ptr );
1107                 wh32->lpNext = 0;
1108             }
1109             ret = WINMM_MAP_OK;
1110         }
1111         break;
1112      case WIDM_GETDEVCAPS:
1113         {
1114             LPWAVEINCAPS16              wic16 = MapSL(*lpParam1);
1115             LPSTR                       ptr   = (LPSTR)wic16 - sizeof(LPWAVEINCAPSW);
1116             LPWAVEINCAPSW               wic32 = *(LPWAVEINCAPSW*)ptr;
1117
1118             wic32->wMid = wic16->wMid;
1119             wic32->wPid = wic16->wPid;
1120             wic32->vDriverVersion = wic16->vDriverVersion;
1121             WideCharToMultiByte( CP_ACP, 0, wic32->szPname, -1, wic16->szPname,
1122                                  sizeof(wic16->szPname), NULL, NULL );
1123             wic32->dwFormats = wic16->dwFormats;
1124             wic32->wChannels = wic16->wChannels;
1125             UnMapLS( *lpParam1 );
1126             HeapFree( GetProcessHeap(), 0, ptr );
1127             ret = WINMM_MAP_OK;
1128         }
1129         break;
1130     case WIDM_GETPOS:
1131         {
1132             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1133             LPSTR               ptr   = (LPSTR)mmt16 - sizeof(LPMMTIME);
1134             LPMMTIME            mmt32 = *(LPMMTIME*)ptr;
1135
1136             MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1137             UnMapLS( *lpParam1 );
1138             HeapFree( GetProcessHeap(), 0, ptr );
1139             ret = WINMM_MAP_OK;
1140         }
1141         break;
1142     case DRVM_MAPPER_STATUS:
1143         {
1144             UnMapLS( *lpParam2 );
1145             ret = WINMM_MAP_OK;
1146         }
1147         break;
1148     default:
1149         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1150         break;
1151     }
1152     return ret;
1153 }
1154
1155 /**************************************************************************
1156  *                              MMDRV_WaveIn_Callback           [internal]
1157  */
1158 static  void    CALLBACK MMDRV_WaveIn_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1159 {
1160     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
1161
1162     switch (uMsg) {
1163     case WIM_OPEN:
1164     case WIM_CLOSE:
1165         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1166         break;
1167     case WIM_DATA:
1168         if (mld->bFrom32 && !MMDRV_Is32(mld->mmdIndex)) {
1169             /* initial map is: 32 => 16 */
1170             LPWAVEHDR           wh16 = MapSL(dwParam1);
1171             LPWAVEHDR           wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1172
1173             dwParam1 = (DWORD)wh32;
1174             wh32->dwFlags = wh16->dwFlags;
1175             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1176         } else if (!mld->bFrom32 && MMDRV_Is32(mld->mmdIndex)) {
1177             /* initial map is: 16 => 32 */
1178             LPWAVEHDR           wh32 = (LPWAVEHDR)(dwParam1);
1179             SEGPTR              segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1180             LPWAVEHDR           wh16 = MapSL(segwh16);
1181
1182             dwParam1 = (DWORD)segwh16;
1183             wh16->dwFlags = wh32->dwFlags;
1184             wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1185         }
1186         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1187         break;
1188     default:
1189         ERR("Unknown msg %u\n", uMsg);
1190     }
1191
1192     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1193 }
1194
1195 /* =================================
1196  *   W A V E  O U T  M A P P E R S
1197  * ================================= */
1198
1199 /**************************************************************************
1200  *                              MMDRV_WaveOut_Map16To32A        [internal]
1201  */
1202 static  WINMM_MapType   MMDRV_WaveOut_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1203 {
1204     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
1205
1206     switch (wMsg) {
1207     /* nothing to do */
1208     case WODM_BREAKLOOP:
1209     case WODM_CLOSE:
1210     case WODM_GETNUMDEVS:
1211     case WODM_PAUSE:
1212     case WODM_RESET:
1213     case WODM_RESTART:
1214     case WODM_SETPITCH:
1215     case WODM_SETPLAYBACKRATE:
1216     case WODM_SETVOLUME:
1217         ret = WINMM_MAP_OK;
1218         break;
1219
1220     case WODM_GETPITCH:
1221     case WODM_GETPLAYBACKRATE:
1222     case WODM_GETVOLUME:
1223     case WODM_OPEN:
1224         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
1225         break;
1226
1227     case WODM_GETDEVCAPS:
1228         {
1229             LPWAVEOUTCAPSW              woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSW));
1230             LPWAVEOUTCAPS16             woc16 = MapSL(*lpParam1);
1231
1232             if (woc32) {
1233                 *(LPWAVEOUTCAPS16*)woc32 = woc16;
1234                 woc32 = (LPWAVEOUTCAPSW)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16));
1235                 *lpParam1 = (DWORD)woc32;
1236                 *lpParam2 = sizeof(WAVEOUTCAPSW);
1237
1238                 ret = WINMM_MAP_OKMEM;
1239             } else {
1240                 ret = WINMM_MAP_NOMEM;
1241             }
1242         }
1243         break;
1244     case WODM_GETPOS:
1245         {
1246             LPMMTIME            mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
1247             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1248
1249             if (mmt32) {
1250                 *(LPMMTIME16*)mmt32 = mmt16;
1251                 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
1252
1253                 mmt32->wType = mmt16->wType;
1254                 *lpParam1 = (DWORD)mmt32;
1255                 *lpParam2 = sizeof(MMTIME);
1256
1257                 ret = WINMM_MAP_OKMEM;
1258             } else {
1259                 ret = WINMM_MAP_NOMEM;
1260             }
1261         }
1262         break;
1263     case WODM_PREPARE:
1264         {
1265             LPWAVEHDR           wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
1266             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1267
1268             if (wh32) {
1269                 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
1270                 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
1271                 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
1272                 wh32->dwBufferLength = wh16->dwBufferLength;
1273                 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1274                 wh32->dwUser = wh16->dwUser;
1275                 wh32->dwFlags = wh16->dwFlags;
1276                 wh32->dwLoops = wh16->dwLoops;
1277                 /* FIXME: nothing on wh32->lpNext */
1278                 /* could link the wh32->lpNext at this level for memory house keeping */
1279                 wh16->lpNext = wh32; /* for reuse in unprepare and write */
1280                 *lpParam1 = (DWORD)wh32;
1281                 *lpParam2 = sizeof(WAVEHDR);
1282
1283                 ret = WINMM_MAP_OKMEM;
1284             } else {
1285                 ret = WINMM_MAP_NOMEM;
1286             }
1287         }
1288         break;
1289     case WODM_UNPREPARE:
1290     case WODM_WRITE:
1291         {
1292             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1293             LPWAVEHDR           wh32 = (LPWAVEHDR)wh16->lpNext;
1294
1295             *lpParam1 = (DWORD)wh32;
1296             *lpParam2 = sizeof(WAVEHDR);
1297             /* dwBufferLength can be reduced between prepare & write */
1298             if (wMsg == WODM_WRITE && wh32->dwBufferLength < wh16->dwBufferLength) {
1299                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
1300                     wh32->dwBufferLength, wh16->dwBufferLength);
1301             } else
1302                 wh32->dwBufferLength = wh16->dwBufferLength;
1303             ret = WINMM_MAP_OKMEM;
1304         }
1305         break;
1306     case WODM_MAPPER_STATUS:
1307         *lpParam2 = (DWORD)MapSL(*lpParam2);
1308         ret = WINMM_MAP_OK;
1309         break;
1310     default:
1311         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1312         break;
1313     }
1314     return ret;
1315 }
1316
1317 /**************************************************************************
1318  *                              MMDRV_WaveOut_UnMap16To32A      [internal]
1319  */
1320 static  WINMM_MapType   MMDRV_WaveOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
1321 {
1322     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
1323
1324     switch (wMsg) {
1325     /* nothing to do */
1326     case WODM_BREAKLOOP:
1327     case WODM_CLOSE:
1328     case WODM_GETNUMDEVS:
1329     case WODM_PAUSE:
1330     case WODM_RESET:
1331     case WODM_RESTART:
1332     case WODM_SETPITCH:
1333     case WODM_SETPLAYBACKRATE:
1334     case WODM_SETVOLUME:
1335     case WODM_MAPPER_STATUS:
1336         ret = WINMM_MAP_OK;
1337         break;
1338
1339     case WODM_GETPITCH:
1340     case WODM_GETPLAYBACKRATE:
1341     case WODM_GETVOLUME:
1342     case WODM_OPEN:
1343         FIXME("Shouldn't be used: those 16 bit functions use the 32 bit interface\n");
1344         break;
1345
1346     case WODM_GETDEVCAPS:
1347         {
1348             LPWAVEOUTCAPSW              woc32 = (LPWAVEOUTCAPSW)(*lpParam1);
1349             LPWAVEOUTCAPS16             woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1350
1351             woc16->wMid = woc32->wMid;
1352             woc16->wPid = woc32->wPid;
1353             woc16->vDriverVersion = woc32->vDriverVersion;
1354             WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname,
1355                                  sizeof(woc16->szPname), NULL, NULL );
1356             woc16->dwFormats = woc32->dwFormats;
1357             woc16->wChannels = woc32->wChannels;
1358             woc16->dwSupport = woc32->dwSupport;
1359             HeapFree(GetProcessHeap(), 0, (LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1360             ret = WINMM_MAP_OK;
1361         }
1362         break;
1363     case WODM_GETPOS:
1364         {
1365             LPMMTIME            mmt32 = (LPMMTIME)(*lpParam1);
1366             LPMMTIME16          mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
1367
1368             MMSYSTEM_MMTIME32to16(mmt16, mmt32);
1369             HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
1370             ret = WINMM_MAP_OK;
1371         }
1372         break;
1373     case WODM_PREPARE:
1374     case WODM_UNPREPARE:
1375     case WODM_WRITE:
1376         {
1377             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
1378             LPWAVEHDR           wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
1379
1380             assert(wh16->lpNext == wh32);
1381             wh16->dwBufferLength = wh32->dwBufferLength;
1382             wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1383             wh16->dwUser = wh32->dwUser;
1384             wh16->dwFlags = wh32->dwFlags;
1385             wh16->dwLoops = wh32->dwLoops;
1386
1387             if (wMsg == WODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
1388                 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
1389                 wh16->lpNext = 0;
1390             }
1391             ret = WINMM_MAP_OK;
1392         }
1393         break;
1394     default:
1395         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1396         break;
1397     }
1398     return ret;
1399 }
1400
1401 /**************************************************************************
1402  *                              MMDRV_WaveOut_Map32ATo16        [internal]
1403  */
1404 static  WINMM_MapType   MMDRV_WaveOut_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1405 {
1406     WINMM_MapType       ret;
1407
1408     switch (wMsg) {
1409         /* nothing to do */
1410     case WODM_BREAKLOOP:
1411     case WODM_CLOSE:
1412     case WODM_GETNUMDEVS:
1413     case WODM_PAUSE:
1414     case WODM_RESET:
1415     case WODM_RESTART:
1416     case WODM_SETPITCH:
1417     case WODM_SETPLAYBACKRATE:
1418     case WODM_SETVOLUME:
1419         ret = WINMM_MAP_OK;
1420         break;
1421
1422     case WODM_GETDEVCAPS:
1423         {
1424             LPWAVEOUTCAPSW woc32 = (LPWAVEOUTCAPSW)*lpParam1;
1425             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0,
1426                                    sizeof(LPWAVEOUTCAPSW) + sizeof(WAVEOUTCAPS16));
1427
1428             if (ptr) {
1429                 *(LPWAVEOUTCAPSW*)ptr = woc32;
1430                 ret = WINMM_MAP_OKMEM;
1431             } else {
1432                 ret = WINMM_MAP_NOMEM;
1433             }
1434             *lpParam1 = MapLS(ptr) + sizeof(LPWAVEOUTCAPSW);
1435             *lpParam2 = sizeof(WAVEOUTCAPS16);
1436         }
1437         break;
1438     case WODM_GETPITCH:
1439         FIXME("NIY: no conversion yet\n");
1440         ret = WINMM_MAP_MSGERROR;
1441         break;
1442     case WODM_GETPLAYBACKRATE:
1443         FIXME("NIY: no conversion yet\n");
1444         ret = WINMM_MAP_MSGERROR;
1445         break;
1446     case WODM_GETPOS:
1447         {
1448             LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1449             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMMTIME) + sizeof(MMTIME16));
1450             LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1451
1452             if (ptr) {
1453                 *(LPMMTIME*)ptr = mmt32;
1454                 mmt16->wType = mmt32->wType;
1455                 ret = WINMM_MAP_OKMEM;
1456             } else {
1457                 ret = WINMM_MAP_NOMEM;
1458             }
1459             *lpParam1 = MapLS(ptr) + sizeof(LPMMTIME);
1460             *lpParam2 = sizeof(MMTIME16);
1461         }
1462         break;
1463     case WODM_GETVOLUME:
1464         FIXME("NIY: no conversion yet\n");
1465         ret = WINMM_MAP_MSGERROR;
1466         break;
1467     case WODM_OPEN:
1468         {
1469             LPWAVEOPENDESC              wod32 = (LPWAVEOPENDESC)*lpParam1;
1470             int                         sz = sizeof(WAVEFORMATEX);
1471             LPVOID                      ptr;
1472             LPWAVEOPENDESC16            wod16;
1473
1474             /* allocated data are mapped as follows:
1475                LPWAVEOPENDESC   ptr to orig lParam1
1476                DWORD            orig dwUser, which is a pointer to DWORD:driver dwInstance
1477                DWORD            dwUser passed to driver
1478                WAVEOPENDESC16   wod16: openDesc passed to driver
1479                WAVEFORMATEX     openDesc->lpFormat passed to driver
1480                xxx              extra bytes to WAVEFORMATEX
1481             */
1482             if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1483                 TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag);
1484                 sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize;
1485             }
1486
1487             ptr = HeapAlloc( GetProcessHeap(), 0,
1488                              sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
1489
1490             if (ptr) {
1491                 SEGPTR seg_ptr = MapLS( ptr );
1492                 *(LPWAVEOPENDESC*)ptr = wod32;
1493                 *(LPDWORD)((char*)ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
1494                 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
1495
1496                 wod16->hWave = HWAVE_16(wod32->hWave);
1497                 wod16->lpFormat = (LPWAVEFORMATEX)(seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16));
1498                 memcpy(wod16 + 1, wod32->lpFormat, sz);
1499
1500                 wod16->dwCallback = wod32->dwCallback;
1501                 wod16->dwInstance = wod32->dwInstance;
1502                 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
1503                 wod16->dnDevNode = wod32->dnDevNode;
1504
1505                 *lpParam1 = seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
1506                 *lpdwUser = seg_ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
1507
1508                 ret = WINMM_MAP_OKMEM;
1509             } else {
1510                 ret = WINMM_MAP_NOMEM;
1511             }
1512         }
1513         break;
1514     case WODM_PREPARE:
1515         {
1516             LPWAVEHDR           wh32 = (LPWAVEHDR)*lpParam1;
1517             LPWAVEHDR           wh16;
1518             LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
1519                                     sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
1520
1521             if (ptr) {
1522                 SEGPTR seg_ptr = MapLS( ptr );
1523                 *(LPWAVEHDR*)ptr = wh32;
1524                 wh16 = (LPWAVEHDR)((LPSTR)ptr + sizeof(LPWAVEHDR));
1525                 wh16->lpData = (LPSTR)seg_ptr + sizeof(LPWAVEHDR) + sizeof(WAVEHDR);
1526                 /* data will be copied on WODM_WRITE */
1527                 wh16->dwBufferLength = wh32->dwBufferLength;
1528                 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1529                 wh16->dwUser = wh32->dwUser;
1530                 wh16->dwFlags = wh32->dwFlags;
1531                 wh16->dwLoops = wh32->dwLoops;
1532                 /* FIXME: nothing on wh32->lpNext */
1533                 /* could link the wh32->lpNext at this level for memory house keeping */
1534                 wh32->lpNext = wh16; /* for reuse in unprepare and write */
1535                 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1536                       seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1537                       wh32->dwBufferLength, (DWORD)wh32->lpData);
1538                 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1539                 *lpParam2 = sizeof(WAVEHDR);
1540
1541                 ret = WINMM_MAP_OKMEM;
1542             } else {
1543                 ret = WINMM_MAP_NOMEM;
1544             }
1545         }
1546         break;
1547     case WODM_UNPREPARE:
1548     case WODM_WRITE:
1549         {
1550             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
1551             LPWAVEHDR           wh16 = wh32->lpNext;
1552             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1553             SEGPTR seg_ptr = MapLS( ptr );
1554
1555             assert(*(LPWAVEHDR*)ptr == wh32);
1556
1557             TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1558                   seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1559                   wh32->dwBufferLength, (DWORD)wh32->lpData);
1560
1561             if (wMsg == WODM_WRITE)
1562                 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
1563
1564             *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1565             *lpParam2 = sizeof(WAVEHDR);
1566             /* dwBufferLength can be reduced between prepare & write */
1567             if (wMsg == WODM_WRITE && wh16->dwBufferLength < wh32->dwBufferLength) {
1568                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
1569                     wh16->dwBufferLength, wh32->dwBufferLength);
1570             } else
1571                 wh16->dwBufferLength = wh32->dwBufferLength;
1572             ret = WINMM_MAP_OKMEM;
1573         }
1574         break;
1575     case DRVM_MAPPER_STATUS:
1576         {
1577             LPDWORD p32 = (LPDWORD)*lpParam2;
1578             *lpParam2 = MapLS(p32);
1579             ret = WINMM_MAP_OKMEM;
1580         }
1581         break;
1582     default:
1583         FIXME("NIY: no conversion yet\n");
1584         ret = WINMM_MAP_MSGERROR;
1585         break;
1586     }
1587     return ret;
1588 }
1589
1590 /**************************************************************************
1591  *                              MMDRV_WaveOut_UnMap32ATo16      [internal]
1592  */
1593 static  WINMM_MapType   MMDRV_WaveOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2, MMRESULT fn_ret)
1594 {
1595     WINMM_MapType       ret;
1596
1597     switch (wMsg) {
1598         /* nothing to do */
1599     case WODM_BREAKLOOP:
1600     case WODM_CLOSE:
1601     case WODM_GETNUMDEVS:
1602     case WODM_PAUSE:
1603     case WODM_RESET:
1604     case WODM_RESTART:
1605     case WODM_SETPITCH:
1606     case WODM_SETPLAYBACKRATE:
1607     case WODM_SETVOLUME:
1608         ret = WINMM_MAP_OK;
1609         break;
1610
1611     case WODM_GETDEVCAPS:
1612         {
1613             LPWAVEOUTCAPS16             woc16 = MapSL(*lpParam1);
1614             LPSTR                       ptr   = (LPSTR)woc16 - sizeof(LPWAVEOUTCAPSW);
1615             LPWAVEOUTCAPSW              woc32 = *(LPWAVEOUTCAPSW*)ptr;
1616
1617             woc32->wMid = woc16->wMid;
1618             woc32->wPid = woc16->wPid;
1619             woc32->vDriverVersion = woc16->vDriverVersion;
1620             WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname,
1621                                  sizeof(woc16->szPname), NULL, NULL );
1622             woc32->dwFormats = woc16->dwFormats;
1623             woc32->wChannels = woc16->wChannels;
1624             woc32->dwSupport = woc16->dwSupport;
1625             UnMapLS( *lpParam1 );
1626             HeapFree( GetProcessHeap(), 0, ptr );
1627             ret = WINMM_MAP_OK;
1628         }
1629         break;
1630     case WODM_GETPITCH:
1631         FIXME("NIY: no conversion yet\n");
1632         ret = WINMM_MAP_MSGERROR;
1633         break;
1634     case WODM_GETPLAYBACKRATE:
1635         FIXME("NIY: no conversion yet\n");
1636         ret = WINMM_MAP_MSGERROR;
1637         break;
1638     case WODM_GETPOS:
1639         {
1640             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1641             LPSTR               ptr   = (LPSTR)mmt16 - sizeof(LPMMTIME);
1642             LPMMTIME            mmt32 = *(LPMMTIME*)ptr;
1643
1644             MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1645             UnMapLS( *lpParam1 );
1646             HeapFree( GetProcessHeap(), 0, ptr );
1647             ret = WINMM_MAP_OK;
1648         }
1649         break;
1650     case WODM_OPEN:
1651         {
1652             LPWAVEOPENDESC16            wod16 = MapSL(*lpParam1);
1653             LPSTR                       ptr   = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1654             LPWAVEOPENDESC              wod32 = *(LPWAVEOPENDESC*)ptr;
1655
1656             wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1657             **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1658             UnMapLS( *lpParam1 );
1659             HeapFree( GetProcessHeap(), 0, ptr );
1660             ret = WINMM_MAP_OK;
1661         }
1662         break;
1663     case WODM_PREPARE:
1664     case WODM_UNPREPARE:
1665     case WODM_WRITE:
1666         {
1667             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1668             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1669             LPWAVEHDR           wh32 = *(LPWAVEHDR*)ptr;
1670
1671             assert(wh32->lpNext == wh16);
1672             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1673             wh32->dwUser = wh16->dwUser;
1674             wh32->dwFlags = wh16->dwFlags;
1675             wh32->dwLoops = wh16->dwLoops;
1676
1677             UnMapLS( *lpParam1 );
1678             if (wMsg == WODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
1679                 HeapFree( GetProcessHeap(), 0, ptr );
1680                 wh32->lpNext = 0;
1681             }
1682             ret = WINMM_MAP_OK;
1683         }
1684         break;
1685     case WODM_GETVOLUME:
1686         FIXME("NIY: no conversion yet\n");
1687         ret = WINMM_MAP_MSGERROR;
1688         break;
1689     case DRVM_MAPPER_STATUS:
1690         {
1691             UnMapLS( *lpParam2 );
1692             ret = WINMM_MAP_OK;
1693         }
1694         break;
1695     default:
1696         FIXME("NIY: no conversion yet\n");
1697         ret = WINMM_MAP_MSGERROR;
1698         break;
1699     }
1700     return ret;
1701 }
1702
1703 /**************************************************************************
1704  *                              MMDRV_WaveOut_Callback          [internal]
1705  */
1706 static  void    CALLBACK MMDRV_WaveOut_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1707 {
1708     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
1709
1710     switch (uMsg) {
1711     case WOM_OPEN:
1712     case WOM_CLOSE:
1713         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1714         break;
1715     case WOM_DONE:
1716         if (mld->bFrom32 && !MMDRV_Is32(mld->mmdIndex)) {
1717             /* initial map is: 32 => 16 */
1718             LPWAVEHDR           wh16 = MapSL(dwParam1);
1719             LPWAVEHDR           wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1720
1721             dwParam1 = (DWORD)wh32;
1722             wh32->dwFlags = wh16->dwFlags;
1723         } else if (!mld->bFrom32 && MMDRV_Is32(mld->mmdIndex)) {
1724             /* initial map is: 16 => 32 */
1725             LPWAVEHDR           wh32 = (LPWAVEHDR)(dwParam1);
1726             SEGPTR              segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1727             LPWAVEHDR           wh16 = MapSL(segwh16);
1728
1729             dwParam1 = (DWORD)segwh16;
1730             wh16->dwFlags = wh32->dwFlags;
1731         }
1732         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1733         break;
1734     default:
1735         ERR("Unknown msg %u\n", uMsg);
1736     }
1737
1738     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1739 }
1740
1741 /* =================================
1742  *  M A P P E R S   H A N D L I N G
1743  * ================================= */
1744
1745 static  LRESULT    MMDRV_CallMMDrvFunc16(DWORD fp16, WORD dev, WORD msg, LONG instance,
1746                                          LONG lp1, LONG lp2)
1747 {
1748     WORD args[8];
1749     DWORD ret;
1750
1751     args[7] = dev;
1752     args[6] = msg;
1753     args[5] = HIWORD(instance);
1754     args[4] = LOWORD(instance);
1755     args[3] = HIWORD(lp1);
1756     args[2] = LOWORD(lp1);
1757     args[1] = HIWORD(lp2);
1758     args[0] = LOWORD(lp2);
1759     WOWCallback16Ex( fp16, WCB16_PASCAL, sizeof(args), args, &ret );
1760     return LOWORD(ret);
1761 }
1762
1763 /**************************************************************************
1764  *                              MMDRV_GetDescription16          [internal]
1765  */
1766 static  BOOL    MMDRV_GetDescription16(const char* fname, char* buf, int buflen)
1767 {
1768     OFSTRUCT    ofs;
1769     HFILE       hFile;
1770     WORD        w;
1771     DWORD       dw;
1772     BOOL        ret = FALSE;
1773
1774     if ((hFile = OpenFile(fname, &ofs, OF_READ | OF_SHARE_DENY_WRITE)) == HFILE_ERROR) {
1775         ERR("Can't open file %s (builtin driver ?)\n", fname);
1776         return FALSE;
1777     }
1778
1779 #define E(_x)   do {TRACE _x;goto theEnd;} while(0)
1780
1781     if (_lread(hFile, &w, 2) != 2)                      E(("Can't read sig\n"));
1782     if (w != ('Z' * 256 + 'M'))                         E(("Bad sig %04x\n", w));
1783     if (_llseek(hFile, 0x3C, SEEK_SET) < 0)             E(("Can't seek to ext header offset\n"));
1784     if (_lread(hFile, &dw, 4) != 4)                     E(("Can't read ext header offset\n"));
1785     if (_llseek(hFile, dw + 0x2C, SEEK_SET) < 0)        E(("Can't seek to ext header.nr table %lu\n", dw+0x2C));
1786     if (_lread(hFile, &dw, 4) != 4)                     E(("Can't read nr table offset\n"));
1787     if (_llseek(hFile, dw, SEEK_SET) < 0)               E(("Can't seek to nr table %lu\n", dw));
1788     if (_lread(hFile, buf, 1) != 1)                     E(("Can't read descr length\n"));
1789     buflen = min((int)(unsigned)(BYTE)buf[0], buflen - 1);
1790     if (_lread(hFile, buf, buflen) != buflen)           E(("Can't read descr (%d)\n", buflen));
1791     buf[buflen] = '\0';
1792     ret = TRUE;
1793     TRACE("Got '%s' [%d]\n", buf, buflen);
1794 theEnd:
1795     _lclose(hFile);
1796     return ret;
1797 }
1798
1799 /******************************************************************
1800  *              MMDRV_LoadMMDrvFunc16
1801  *
1802  */
1803 unsigned   MMDRV_LoadMMDrvFunc16(LPCSTR drvName, LPWINE_DRIVER d, 
1804                                  LPWINE_MM_DRIVER lpDrv)
1805 {        
1806     WINEMM_msgFunc16    func;
1807     unsigned            count = 0;
1808     char                buffer[128];
1809     /*
1810      * DESCRIPTION 'wave,aux,mixer:Creative Labs Sound Blaster 16 Driver'
1811      * The beginning of the module description indicates the driver supports
1812      * waveform, auxiliary, and mixer devices. Use one of the following
1813      * device-type names, followed by a colon (:) to indicate the type of
1814      * device your driver supports. If the driver supports more than one
1815      * type of device, separate each device-type name with a comma (,).
1816      *
1817      * wave for waveform audio devices
1818      * wavemapper for wave mappers
1819      * midi for MIDI audio devices
1820      * midimapper for midi mappers
1821      * aux for auxiliary audio devices
1822      * mixer for mixer devices
1823      */
1824
1825     if (d->d.d16.hDriver16) {
1826         HMODULE16       hMod16 = GetDriverModuleHandle16(d->d.d16.hDriver16);
1827
1828 #define AA(_h,_w,_x,_y,_z)                                      \
1829     func = (WINEMM_msgFunc##_y) _z ((_h), #_x);                 \
1830     if (func != NULL)                                           \
1831         { lpDrv->parts[_w].u.fnMessage##_y = func; count++;     \
1832           TRACE("Got %d bit func '%s'\n", _y, #_x);         }
1833
1834 #define A(_x,_y)        AA(hMod16,_x,_y,16,GetProcAddress16)
1835         A(MMDRV_AUX,    auxMessage);
1836         A(MMDRV_MIXER,  mxdMessage);
1837         A(MMDRV_MIDIIN, midMessage);
1838         A(MMDRV_MIDIOUT,modMessage);
1839         A(MMDRV_WAVEIN, widMessage);
1840         A(MMDRV_WAVEOUT,wodMessage);
1841 #undef A
1842 #undef AA
1843     }
1844     if (TRACE_ON(winmm)) {
1845         if (MMDRV_GetDescription16(drvName, buffer, sizeof(buffer)))
1846             TRACE("%s => %s\n", drvName, buffer);
1847         else
1848             TRACE("%s => No description\n", drvName);
1849     }
1850
1851     return count;
1852 }
1853
1854 /* =================================
1855  *              M C I
1856  * ================================= */
1857
1858 /**************************************************************************
1859  *                      MCI_MapMsg16To32A                       [internal]
1860  */
1861 static WINMM_MapType    MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
1862 {
1863     if (*lParam == 0)
1864         return WINMM_MAP_OK;
1865     /* FIXME: to add also (with seg/linear modifications to do):
1866      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
1867      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
1868      */
1869     switch (wMsg) {
1870         /* case MCI_CAPTURE */
1871     case MCI_CLOSE:
1872     case MCI_CLOSE_DRIVER:
1873     case MCI_CONFIGURE:
1874     case MCI_COPY:
1875     case MCI_CUE:
1876     case MCI_CUT:
1877     case MCI_DELETE:
1878     case MCI_FREEZE:
1879     case MCI_GETDEVCAPS:
1880         /* case MCI_INDEX: */
1881         /* case MCI_MARK: */
1882         /* case MCI_MONITOR: */
1883     case MCI_PASTE:
1884     case MCI_PAUSE:
1885     case MCI_PLAY:
1886     case MCI_PUT:
1887     case MCI_REALIZE:
1888     case MCI_RECORD:
1889     case MCI_RESUME:
1890     case MCI_SEEK:
1891     case MCI_SET:
1892         /* case MCI_SETTIMECODE:*/
1893         /* case MCI_SIGNAL:*/
1894     case MCI_SPIN:
1895     case MCI_STATUS:            /* FIXME: is wrong for digital video */
1896     case MCI_STEP:
1897     case MCI_STOP:
1898         /* case MCI_UNDO: */
1899     case MCI_UNFREEZE:
1900     case MCI_UPDATE:
1901     case MCI_WHERE:
1902         *lParam = (DWORD)MapSL(*lParam);
1903         return WINMM_MAP_OK;
1904     case MCI_WINDOW:
1905         /* in fact, I would also need the dwFlags... to see
1906          * which members of lParam are effectively used
1907          */
1908         *lParam = (DWORD)MapSL(*lParam);
1909         FIXME("Current mapping may be wrong\n");
1910         break;
1911     case MCI_BREAK:
1912         {
1913             LPMCI_BREAK_PARMS           mbp32 = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_BREAK_PARMS));
1914             LPMCI_BREAK_PARMS16         mbp16 = MapSL(*lParam);
1915
1916             if (mbp32) {
1917                 mbp32->dwCallback = mbp16->dwCallback;
1918                 mbp32->nVirtKey = mbp16->nVirtKey;
1919                 mbp32->hwndBreak = HWND_32(mbp16->hwndBreak);
1920             } else {
1921                 return WINMM_MAP_NOMEM;
1922             }
1923             *lParam = (DWORD)mbp32;
1924         }
1925         return WINMM_MAP_OKMEM;
1926     case MCI_ESCAPE:
1927         {
1928             LPMCI_VD_ESCAPE_PARMSA      mvep32a = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_VD_ESCAPE_PARMSA));
1929             LPMCI_VD_ESCAPE_PARMS16     mvep16  = MapSL(*lParam);
1930
1931             if (mvep32a) {
1932                 mvep32a->dwCallback       = mvep16->dwCallback;
1933                 mvep32a->lpstrCommand     = MapSL(mvep16->lpstrCommand);
1934             } else {
1935                 return WINMM_MAP_NOMEM;
1936             }
1937             *lParam = (DWORD)mvep32a;
1938         }
1939         return WINMM_MAP_OKMEM;
1940     case MCI_INFO:
1941         {
1942             LPMCI_INFO_PARMSA   mip32a = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_INFO_PARMSA));
1943             LPMCI_INFO_PARMS16  mip16  = MapSL(*lParam);
1944
1945             /* FIXME this is wrong if device is of type
1946              * MCI_DEVTYPE_DIGITAL_VIDEO, some members are not mapped
1947              */
1948             if (mip32a) {
1949                 mip32a->dwCallback  = mip16->dwCallback;
1950                 mip32a->lpstrReturn = MapSL(mip16->lpstrReturn);
1951                 mip32a->dwRetSize   = mip16->dwRetSize;
1952             } else {
1953                 return WINMM_MAP_NOMEM;
1954             }
1955             *lParam = (DWORD)mip32a;
1956         }
1957         return WINMM_MAP_OKMEM;
1958     case MCI_OPEN:
1959     case MCI_OPEN_DRIVER:
1960         {
1961             LPMCI_OPEN_PARMSA   mop32a = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_OPEN_PARMSA) + 2 * sizeof(DWORD));
1962             LPMCI_OPEN_PARMS16  mop16  = MapSL(*lParam);
1963
1964             if (mop32a) {
1965                 *(LPMCI_OPEN_PARMS16*)(mop32a) = mop16;
1966                 mop32a = (LPMCI_OPEN_PARMSA)((char*)mop32a + sizeof(LPMCI_OPEN_PARMS16));
1967                 mop32a->dwCallback       = mop16->dwCallback;
1968                 mop32a->wDeviceID        = mop16->wDeviceID;
1969                 mop32a->lpstrDeviceType  = MapSL(mop16->lpstrDeviceType);
1970                 mop32a->lpstrElementName = MapSL(mop16->lpstrElementName);
1971                 mop32a->lpstrAlias       = MapSL(mop16->lpstrAlias);
1972                 /* copy extended information if any...
1973                  * FIXME: this may seg fault if initial structure does not contain them and
1974                  * the reads after msip16 fail under LDT limits...
1975                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
1976                  * should not take care of extended parameters, and should be used by MCI_Open
1977                  * to fetch uDevType. When, this is known, the mapping for sending the
1978                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
1979                  */
1980                 memcpy(mop32a + 1, mop16 + 1, 2 * sizeof(DWORD));
1981             } else {
1982                 return WINMM_MAP_NOMEM;
1983             }
1984             *lParam = (DWORD)mop32a;
1985         }
1986         return WINMM_MAP_OKMEM;
1987     case MCI_SYSINFO:
1988         {
1989             LPMCI_SYSINFO_PARMSA        msip32a = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_SYSINFO_PARMSA));
1990             LPMCI_SYSINFO_PARMS16       msip16  = MapSL(*lParam);
1991
1992             if (msip32a) {
1993                 msip32a->dwCallback       = msip16->dwCallback;
1994                 msip32a->lpstrReturn      = MapSL(msip16->lpstrReturn);
1995                 msip32a->dwRetSize        = msip16->dwRetSize;
1996                 msip32a->dwNumber         = msip16->dwNumber;
1997                 msip32a->wDeviceType      = msip16->wDeviceType;
1998             } else {
1999                 return WINMM_MAP_NOMEM;
2000             }
2001             *lParam = (DWORD)msip32a;
2002         }
2003         return WINMM_MAP_OKMEM;
2004     case MCI_SOUND:
2005         {
2006             LPMCI_SOUND_PARMS           mbp32 = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_SOUND_PARMS));
2007             LPMCI_SOUND_PARMS16         mbp16 = MapSL(*lParam);
2008
2009             if (mbp32) {
2010                 mbp32->dwCallback = mbp16->dwCallback;
2011                 mbp32->lpstrSoundName = MapSL(mbp16->lpstrSoundName);
2012             } else {
2013                 return WINMM_MAP_NOMEM;
2014             }
2015             *lParam = (DWORD)mbp32;
2016         }
2017         return WINMM_MAP_OKMEM;
2018     case DRV_LOAD:
2019     case DRV_ENABLE:
2020     case DRV_OPEN:
2021     case DRV_CLOSE:
2022     case DRV_DISABLE:
2023     case DRV_FREE:
2024     case DRV_CONFIGURE:
2025     case DRV_QUERYCONFIGURE:
2026     case DRV_INSTALL:
2027     case DRV_REMOVE:
2028     case DRV_EXITSESSION:
2029     case DRV_EXITAPPLICATION:
2030     case DRV_POWER:
2031         FIXME("This is a hack\n");
2032         return WINMM_MAP_OK;
2033
2034     default:
2035         WARN("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
2036     }
2037     return WINMM_MAP_MSGERROR;
2038 }
2039
2040 /**************************************************************************
2041  *                      MCI_UnMapMsg16To32A                     [internal]
2042  */
2043 static  WINMM_MapType   MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
2044 {
2045     switch (wMsg) {
2046         /* case MCI_CAPTURE */
2047     case MCI_CLOSE:
2048     case MCI_CLOSE_DRIVER:
2049     case MCI_CONFIGURE:
2050     case MCI_COPY:
2051     case MCI_CUE:
2052     case MCI_CUT:
2053     case MCI_DELETE:
2054     case MCI_FREEZE:
2055     case MCI_GETDEVCAPS:
2056         /* case MCI_INDEX: */
2057         /* case MCI_MARK: */
2058         /* case MCI_MONITOR: */
2059     case MCI_PASTE:
2060     case MCI_PAUSE:
2061     case MCI_PLAY:
2062     case MCI_PUT:
2063     case MCI_REALIZE:
2064     case MCI_RECORD:
2065     case MCI_RESUME:
2066     case MCI_SEEK:
2067     case MCI_SET:
2068         /* case MCI_SETTIMECODE:*/
2069         /* case MCI_SIGNAL:*/
2070     case MCI_SPIN:
2071     case MCI_STATUS:
2072     case MCI_STEP:
2073     case MCI_STOP:
2074         /* case MCI_UNDO: */
2075     case MCI_UNFREEZE:
2076     case MCI_UPDATE:
2077     case MCI_WHERE:
2078         return WINMM_MAP_OK;
2079
2080     case MCI_WINDOW:
2081         /* FIXME ?? see Map function */
2082         return WINMM_MAP_OK;
2083
2084     case MCI_BREAK:
2085     case MCI_ESCAPE:
2086     case MCI_INFO:
2087     case MCI_SYSINFO:
2088     case MCI_SOUND:
2089         HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2090         return WINMM_MAP_OK;
2091     case MCI_OPEN:
2092     case MCI_OPEN_DRIVER:
2093         if (lParam) {
2094             LPMCI_OPEN_PARMSA   mop32a = (LPMCI_OPEN_PARMSA)lParam;
2095             LPMCI_OPEN_PARMS16  mop16  = *(LPMCI_OPEN_PARMS16*)((char*)mop32a - sizeof(LPMCI_OPEN_PARMS16));
2096
2097             mop16->wDeviceID = mop32a->wDeviceID;
2098             if (!HeapFree(GetProcessHeap(), 0, (LPVOID)(lParam - sizeof(LPMCI_OPEN_PARMS16))))
2099                 FIXME("bad free line=%d\n", __LINE__);
2100         }
2101         return WINMM_MAP_OK;
2102     case DRV_LOAD:
2103     case DRV_ENABLE:
2104     case DRV_OPEN:
2105     case DRV_CLOSE:
2106     case DRV_DISABLE:
2107     case DRV_FREE:
2108     case DRV_CONFIGURE:
2109     case DRV_QUERYCONFIGURE:
2110     case DRV_INSTALL:
2111     case DRV_REMOVE:
2112     case DRV_EXITSESSION:
2113     case DRV_EXITAPPLICATION:
2114     case DRV_POWER:
2115         FIXME("This is a hack\n");
2116         return WINMM_MAP_OK;
2117     default:
2118         FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
2119     }
2120     return WINMM_MAP_MSGERROR;
2121 }
2122
2123 /*
2124  * 0000 stop
2125  * 0001 squeeze   signed 4 bytes to 2 bytes     *( LPINT16)D = ( INT16)*( LPINT16)S; D += 2;     S += 4
2126  * 0010 squeeze unsigned 4 bytes to 2 bytes     *(LPUINT16)D = (UINT16)*(LPUINT16)S; D += 2;     S += 4
2127  * 0100
2128  * 0101
2129  * 0110 zero 4 bytes                            *(DWORD)D = 0                        D += 4;     S += 4
2130  * 0111 copy string                             *(LPSTR*)D = seg dup(*(LPSTR*)S)     D += 4;     S += 4
2131  * 1xxx copy xxx + 1 bytes                      memcpy(D, S, xxx + 1);               D += xxx+1; S += xxx+1
2132  */
2133
2134 /**************************************************************************
2135  *                      MCI_MsgMapper32To16_Create              [internal]
2136  *
2137  * Helper for MCI_MapMsg32ATo16.
2138  * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit
2139  * segmented pointer.
2140  * map contains a list of action to be performed for the mapping (see list
2141  * above)
2142  * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
2143  */
2144 static  WINMM_MapType   MCI_MsgMapper32To16_Create(void** ptr, int size16, DWORD map, BOOLEAN keep)
2145 {
2146     void*       lp = HeapAlloc( GetProcessHeap(), 0, (keep ? sizeof(void**) : 0) + size16 );
2147     LPBYTE      p16, p32;
2148
2149     if (!lp) {
2150         return WINMM_MAP_NOMEM;
2151     }
2152     p32 = (LPBYTE)(*ptr);
2153     if (keep) {
2154         *(void**)lp = *ptr;
2155         p16 = (LPBYTE)lp + sizeof(void**);
2156         *ptr = (char*)MapLS(lp) + sizeof(void**);
2157     } else {
2158         p16 = lp;
2159         *ptr = (void*)MapLS(lp);
2160     }
2161
2162     if (map == 0) {
2163         memcpy(p16, p32, size16);
2164     } else {
2165         unsigned        nibble;
2166         unsigned        sz;
2167
2168         while (map & 0xF) {
2169             nibble = map & 0xF;
2170             if (nibble & 0x8) {
2171                 sz = (nibble & 7) + 1;
2172                 memcpy(p16, p32, sz);
2173                 p16 += sz;
2174                 p32 += sz;
2175                 size16 -= sz;   /* DEBUG only */
2176             } else {
2177                 switch (nibble) {
2178                 case 0x1:
2179                     *(LPINT16)p16 = *(LPINT)p32;
2180                     p16 += sizeof(INT16);
2181                     p32 += sizeof(INT);
2182                     size16 -= sizeof(INT16);
2183                     break;
2184                 case 0x2:
2185                     *(LPUINT16)p16 = *(LPUINT)p32;
2186                     p16 += sizeof(UINT16);
2187                     p32 += sizeof(UINT);
2188                     size16 -= sizeof(UINT16);
2189                     break;
2190                 case 0x6:
2191                     *(LPDWORD)p16 = 0;
2192                     p16 += sizeof(DWORD);
2193                     p32 += sizeof(DWORD);
2194                     size16 -= sizeof(DWORD);
2195                     break;
2196                 case 0x7:
2197                     *(SEGPTR *)p16 = MapLS( *(LPSTR *)p32 );
2198                     p16 += sizeof(SEGPTR);
2199                     p32 += sizeof(LPSTR);
2200                     size16 -= sizeof(SEGPTR);
2201                     break;
2202                 default:
2203                     FIXME("Unknown nibble for mapping (%x)\n", nibble);
2204                 }
2205             }
2206             map >>= 4;
2207         }
2208         if (size16 != 0) /* DEBUG only */
2209             FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
2210     }
2211     return WINMM_MAP_OKMEM;
2212 }
2213
2214 /**************************************************************************
2215  *                      MCI_MsgMapper32To16_Destroy             [internal]
2216  *
2217  * Helper for MCI_UnMapMsg32ATo16.
2218  */
2219 static  WINMM_MapType   MCI_MsgMapper32To16_Destroy(void* ptr, int size16, DWORD map, BOOLEAN kept)
2220 {
2221     if (ptr) {
2222         void*           msg16 = MapSL((SEGPTR)ptr);
2223         void*           alloc;
2224         LPBYTE          p32, p16;
2225         unsigned        nibble;
2226
2227         UnMapLS( (SEGPTR)ptr );
2228         if (kept) {
2229             alloc = (char*)msg16 - sizeof(void**);
2230             p32 = *(void**)alloc;
2231             p16 = msg16;
2232
2233             if (map == 0) {
2234                 memcpy(p32, p16, size16);
2235             } else {
2236                 while (map & 0xF) {
2237                     nibble = map & 0xF;
2238                     if (nibble & 0x8) {
2239                         memcpy(p32, p16, (nibble & 7) + 1);
2240                         p16 += (nibble & 7) + 1;
2241                         p32 += (nibble & 7) + 1;
2242                         size16 -= (nibble & 7) + 1;
2243                     } else {
2244                         switch (nibble) {
2245                         case 0x1:
2246                             *(LPINT)p32 = *(LPINT16)p16;
2247                             p16 += sizeof(INT16);
2248                             p32 += sizeof(INT);
2249                             size16 -= sizeof(INT16);
2250                             break;
2251                         case 0x2:
2252                             *(LPUINT)p32 = *(LPUINT16)p16;
2253                             p16 += sizeof(UINT16);
2254                             p32 += sizeof(UINT);
2255                             size16 -= sizeof(UINT16);
2256                             break;
2257                         case 0x6:
2258                             p16 += sizeof(UINT);
2259                             p32 += sizeof(UINT);
2260                             size16 -= sizeof(UINT);
2261                             break;
2262                         case 0x7:
2263                             UnMapLS( *(SEGPTR *)p16 );
2264                             p16 += sizeof(SEGPTR);
2265                             p32 += sizeof(char*);
2266                             size16 -= sizeof(SEGPTR);
2267                             break;
2268                         default:
2269                             FIXME("Unknown nibble for mapping (%x)\n", nibble);
2270                         }
2271                     }
2272                     map >>= 4;
2273                 }
2274                 if (size16 != 0) /* DEBUG only */
2275                     FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
2276             }
2277         } else {
2278             alloc = msg16;
2279         }
2280
2281         HeapFree( GetProcessHeap(), 0, alloc );
2282     }
2283     return WINMM_MAP_OK;
2284 }
2285
2286 /**************************************************************************
2287  *                      MCI_MapMsg32ATo16                       [internal]
2288  *
2289  * Map a 32-A bit MCI message to a 16 bit MCI message.
2290  */
2291 static  WINMM_MapType   MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
2292 {
2293     int         size;
2294     BOOLEAN     keep = FALSE;
2295     DWORD       map = 0;
2296
2297     if (*lParam == 0)
2298         return WINMM_MAP_OK;
2299
2300     /* FIXME: to add also (with seg/linear modifications to do):
2301      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
2302      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
2303      */
2304     switch (wMsg) {
2305     case MCI_BREAK:
2306         size = sizeof(MCI_BREAK_PARMS);
2307         break;
2308         /* case MCI_CAPTURE */
2309     case MCI_CLOSE:
2310     case MCI_CLOSE_DRIVER:
2311     case MCI_CONFIGURE:
2312         size = sizeof(MCI_GENERIC_PARMS);
2313         break;
2314         /* case MCI_COPY: */
2315     case MCI_CUE:
2316         switch (uDevType) {
2317         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_CUE_PARMS);       break;
2318         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_CUE_PARMS);     break;*/        FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2319         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2320         }
2321         break;
2322         /* case MCI_CUT:*/
2323     case MCI_DELETE:
2324         switch (uDevType) {
2325         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_DELETE_PARMS16);  map = 0x0F1111FB;       break;
2326         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_DELETE_PARMS);   break;
2327         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2328         }
2329         break;
2330         /* case MCI_ESCAPE: */
2331     case MCI_FREEZE:
2332         switch (uDevType) {
2333         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_FREEZE_PARMS);    map = 0x0001111B;       break;
2334         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
2335         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2336         }
2337         break;
2338     case MCI_GETDEVCAPS:
2339         keep = TRUE;
2340         size = sizeof(MCI_GETDEVCAPS_PARMS);
2341         break;
2342         /* case MCI_INDEX: */
2343     case MCI_INFO:
2344         {
2345             LPMCI_INFO_PARMSA   mip32a = (LPMCI_INFO_PARMSA)(*lParam);
2346             LPMCI_INFO_PARMS16  mip16;
2347
2348             switch (uDevType) {
2349             case MCI_DEVTYPE_DIGITAL_VIDEO:     size = sizeof(MCI_DGV_INFO_PARMS16);    break;
2350             default:                            size = sizeof(MCI_INFO_PARMS16);        break;
2351             }
2352             mip16 = HeapAlloc( GetProcessHeap(), 0, size);
2353             if (mip16)
2354             {
2355                 mip16->dwCallback  = mip32a->dwCallback;
2356                 mip16->lpstrReturn = MapLS( mip32a->lpstrReturn );
2357                 mip16->dwRetSize   = mip32a->dwRetSize;
2358                 if (uDevType == MCI_DEVTYPE_DIGITAL_VIDEO) {
2359                     ((LPMCI_DGV_INFO_PARMS16)mip16)->dwItem = ((LPMCI_DGV_INFO_PARMSA)mip32a)->dwItem;
2360                 }
2361             } else {
2362                 return WINMM_MAP_NOMEM;
2363             }
2364             *lParam = MapLS(mip16);
2365         }
2366         return WINMM_MAP_OKMEM;
2367         /* case MCI_MARK: */
2368         /* case MCI_MONITOR: */
2369     case MCI_OPEN:
2370     case MCI_OPEN_DRIVER:
2371         {
2372             LPMCI_OPEN_PARMSA   mop32a = (LPMCI_OPEN_PARMSA)(*lParam);
2373             char* ptr = HeapAlloc( GetProcessHeap(), 0,
2374                                    sizeof(LPMCI_OPEN_PARMSA) + sizeof(MCI_OPEN_PARMS16) + 2 * sizeof(DWORD));
2375             LPMCI_OPEN_PARMS16  mop16;
2376
2377
2378             if (ptr) {
2379                 *(LPMCI_OPEN_PARMSA*)(ptr) = mop32a;
2380                 mop16 = (LPMCI_OPEN_PARMS16)(ptr + sizeof(LPMCI_OPEN_PARMSA));
2381                 mop16->dwCallback       = mop32a->dwCallback;
2382                 mop16->wDeviceID        = mop32a->wDeviceID;
2383                 if (dwFlags & MCI_OPEN_TYPE) {
2384                     if (dwFlags & MCI_OPEN_TYPE_ID) {
2385                         /* dword "transparent" value */
2386                         mop16->lpstrDeviceType = (SEGPTR)mop32a->lpstrDeviceType;
2387                     } else {
2388                         /* string */
2389                         mop16->lpstrDeviceType = MapLS( mop32a->lpstrDeviceType );
2390                     }
2391                 } else {
2392                     /* nuthin' */
2393                     mop16->lpstrDeviceType = 0;
2394                 }
2395                 if (dwFlags & MCI_OPEN_ELEMENT) {
2396                     if (dwFlags & MCI_OPEN_ELEMENT_ID) {
2397                         mop16->lpstrElementName = (SEGPTR)mop32a->lpstrElementName;
2398                     } else {
2399                         mop16->lpstrElementName = MapLS( mop32a->lpstrElementName );
2400                     }
2401                 } else {
2402                     mop16->lpstrElementName = 0;
2403                 }
2404                 if (dwFlags & MCI_OPEN_ALIAS) {
2405                     mop16->lpstrAlias = MapLS( mop32a->lpstrAlias );
2406                 } else {
2407                     mop16->lpstrAlias = 0;
2408                 }
2409                 /* copy extended information if any...
2410                  * FIXME: this may seg fault if initial structure does not contain them and
2411                  * the reads after msip16 fail under LDT limits...
2412                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
2413                  * should not take care of extended parameters, and should be used by MCI_Open
2414                  * to fetch uDevType. When, this is known, the mapping for sending the
2415                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
2416                  */
2417                 memcpy(mop16 + 1, mop32a + 1, 2 * sizeof(DWORD));
2418             } else {
2419                 return WINMM_MAP_NOMEM;
2420             }
2421             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_PARMSA);
2422         }
2423         return WINMM_MAP_OKMEM;
2424         /* case MCI_PASTE:*/
2425     case MCI_PAUSE:
2426         size = sizeof(MCI_GENERIC_PARMS);
2427         break;
2428     case MCI_PLAY:
2429         size = sizeof(MCI_PLAY_PARMS);
2430         break;
2431     case MCI_PUT:
2432         switch (uDevType) {
2433         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
2434         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
2435         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2436         }
2437         break;
2438     case MCI_REALIZE:
2439         size = sizeof(MCI_GENERIC_PARMS);
2440         break;
2441     case MCI_RECORD:
2442         switch (uDevType) {
2443         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECORD_PARMS16);  map = 0x0F1111FB;       break;
2444         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_RECORD_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2445         default:                        size = sizeof(MCI_RECORD_PARMS);        break;
2446         }
2447         break;
2448     case MCI_RESUME:
2449         size = sizeof(MCI_GENERIC_PARMS);
2450         break;
2451     case MCI_SEEK:
2452         switch (uDevType) {
2453         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SEEK_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2454         default:                        size = sizeof(MCI_SEEK_PARMS);          break;
2455         }
2456         break;
2457     case MCI_SET:
2458         switch (uDevType) {
2459         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SET_PARMS);       break;
2460         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SET_PARMS);     break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2461         case MCI_DEVTYPE_SEQUENCER:     size = sizeof(MCI_SEQ_SET_PARMS);       break;
2462         /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
2463          * so not doing anything should work...
2464          */
2465         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_SET_PARMS);      break;
2466         default:                        size = sizeof(MCI_SET_PARMS);           break;
2467         }
2468         break;
2469     case MCI_SETAUDIO:
2470         switch (uDevType) {
2471         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SETAUDIO_PARMS16);map = 0x0000077FF;      break;
2472         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2473         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2474         }
2475         break;
2476         /* case MCI_SETTIMECODE:*/
2477         /* case MCI_SIGNAL:*/
2478         /* case MCI_SOUND:*/
2479     case MCI_SPIN:
2480         size = sizeof(MCI_SET_PARMS);
2481         break;
2482     case MCI_STATUS:
2483         keep = TRUE;
2484         switch (uDevType) {
2485         /* FIXME:
2486          * don't know if buffer for value is the one passed through lpstrDevice
2487          * or is provided by MCI driver.
2488          * Assuming solution 2: provided by MCI driver, so zeroing on entry
2489          */
2490         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16);  map = 0x0B6FF;          break;
2491         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2492         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
2493         }
2494         break;
2495     case MCI_STEP:
2496         switch (uDevType) {
2497         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STEP_PARMS);      break;
2498         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STEP_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2499         case MCI_DEVTYPE_VIDEODISC:     size = sizeof(MCI_VD_STEP_PARMS);       break;
2500         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2501         }
2502         break;
2503     case MCI_STOP:
2504         size = sizeof(MCI_SET_PARMS);
2505         break;
2506     case MCI_SYSINFO:
2507         {
2508             LPMCI_SYSINFO_PARMSA  msip32a = (LPMCI_SYSINFO_PARMSA)(*lParam);
2509             LPMCI_SYSINFO_PARMS16 msip16;
2510             char* ptr = HeapAlloc( GetProcessHeap(), 0,
2511                                    sizeof(LPMCI_SYSINFO_PARMSA) + sizeof(MCI_SYSINFO_PARMS16) );
2512
2513             if (ptr) {
2514                 *(LPMCI_SYSINFO_PARMSA*)(ptr) = msip32a;
2515                 msip16 = (LPMCI_SYSINFO_PARMS16)(ptr + sizeof(LPMCI_SYSINFO_PARMSA));
2516
2517                 msip16->dwCallback       = msip32a->dwCallback;
2518                 msip16->lpstrReturn      = MapLS( msip32a->lpstrReturn );
2519                 msip16->dwRetSize        = msip32a->dwRetSize;
2520                 msip16->dwNumber         = msip32a->dwNumber;
2521                 msip16->wDeviceType      = msip32a->wDeviceType;
2522             } else {
2523                 return WINMM_MAP_NOMEM;
2524             }
2525             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_SYSINFO_PARMSA);
2526         }
2527         return WINMM_MAP_OKMEM;
2528         /* case MCI_UNDO: */
2529     case MCI_UNFREEZE:
2530         switch (uDevType) {
2531         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
2532         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       break;
2533         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2534         }
2535         break;
2536     case MCI_UPDATE:
2537         switch (uDevType) {
2538         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_UPDATE_PARMS16);  map = 0x000B1111B;      break;
2539         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2540         }
2541         break;
2542     case MCI_WHERE:
2543         switch (uDevType) {
2544         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       keep = TRUE;    break;
2545         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       keep = TRUE;    break;
2546         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2547         }
2548         break;
2549     case MCI_WINDOW:
2550         switch (uDevType) {
2551         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7FB;        break;
2552         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7FB;        break;
2553         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2554         }
2555         break;
2556     case DRV_OPEN:
2557         {
2558             LPMCI_OPEN_DRIVER_PARMSA  modp32a = (LPMCI_OPEN_DRIVER_PARMSA)(*lParam);
2559             LPMCI_OPEN_DRIVER_PARMS16 modp16;
2560             char *ptr = HeapAlloc( GetProcessHeap(), 0,
2561                                   sizeof(LPMCI_OPEN_DRIVER_PARMSA) + sizeof(MCI_OPEN_DRIVER_PARMS16));
2562
2563             if (ptr) {
2564                 *(LPMCI_OPEN_DRIVER_PARMSA*)(ptr) = modp32a;
2565                 modp16 = (LPMCI_OPEN_DRIVER_PARMS16)(ptr + sizeof(LPMCI_OPEN_DRIVER_PARMSA));
2566                 modp16->wDeviceID = modp32a->wDeviceID;
2567                 modp16->lpstrParams = MapLS( modp32a->lpstrParams );
2568                 /* other fields are gonna be filled by the driver, don't copy them */
2569             } else {
2570                 return WINMM_MAP_NOMEM;
2571             }
2572             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_DRIVER_PARMSA);
2573         }
2574         return WINMM_MAP_OKMEM;
2575     case DRV_LOAD:
2576     case DRV_ENABLE:
2577     case DRV_CLOSE:
2578     case DRV_DISABLE:
2579     case DRV_FREE:
2580     case DRV_CONFIGURE:
2581     case DRV_QUERYCONFIGURE:
2582     case DRV_INSTALL:
2583     case DRV_REMOVE:
2584     case DRV_EXITSESSION:
2585     case DRV_EXITAPPLICATION:
2586     case DRV_POWER:
2587         return WINMM_MAP_OK;
2588
2589     default:
2590         WARN("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
2591         return WINMM_MAP_MSGERROR;
2592     }
2593     return MCI_MsgMapper32To16_Create((void**)lParam, size, map, keep);
2594 }
2595
2596 /**************************************************************************
2597  *                      MCI_UnMapMsg32ATo16                     [internal]
2598  */
2599 static  WINMM_MapType   MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
2600 {
2601     int         size = 0;
2602     BOOLEAN     kept = FALSE;   /* there is no need to compute size when kept is FALSE */
2603     DWORD       map = 0;
2604
2605     switch (wMsg) {
2606     case MCI_BREAK:
2607         break;
2608         /* case MCI_CAPTURE */
2609     case MCI_CLOSE:
2610     case MCI_CLOSE_DRIVER:
2611     case MCI_CONFIGURE:
2612         break;
2613         /* case MCI_COPY: */
2614     case MCI_CUE:
2615         break;
2616         /* case MCI_CUT: */
2617     case MCI_DELETE:
2618         break;
2619         /* case MCI_ESCAPE: */
2620     case MCI_FREEZE:
2621         break;
2622     case MCI_GETDEVCAPS:
2623         kept = TRUE;
2624         size = sizeof(MCI_GETDEVCAPS_PARMS);
2625         break;
2626         /* case MCI_INDEX: */
2627     case MCI_INFO:
2628         {
2629             LPMCI_INFO_PARMS16 mip16  = (LPMCI_INFO_PARMS16)MapSL(lParam);
2630             UnMapLS( lParam );
2631             UnMapLS( mip16->lpstrReturn );
2632             HeapFree( GetProcessHeap(), 0, mip16 );
2633         }
2634         return WINMM_MAP_OK;
2635         /* case MCI_MARK: */
2636         /* case MCI_MONITOR: */
2637     case MCI_OPEN:
2638     case MCI_OPEN_DRIVER:
2639         if (lParam) {
2640             LPMCI_OPEN_PARMS16  mop16  = (LPMCI_OPEN_PARMS16)MapSL(lParam);
2641             LPMCI_OPEN_PARMSA   mop32a = *(LPMCI_OPEN_PARMSA*)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSA));
2642             UnMapLS( lParam );
2643             mop32a->wDeviceID = mop16->wDeviceID;
2644             if ((dwFlags & MCI_OPEN_TYPE) && !(dwFlags & MCI_OPEN_TYPE_ID))
2645                 UnMapLS( mop16->lpstrDeviceType );
2646             if ((dwFlags & MCI_OPEN_ELEMENT) && !(dwFlags & MCI_OPEN_ELEMENT_ID))
2647                 UnMapLS( mop16->lpstrElementName );
2648             if (dwFlags & MCI_OPEN_ALIAS)
2649                 UnMapLS( mop16->lpstrAlias );
2650             HeapFree( GetProcessHeap(), 0, (char*)mop16 - sizeof(LPMCI_OPEN_PARMSA) );
2651         }
2652         return WINMM_MAP_OK;
2653         /* case MCI_PASTE:*/
2654     case MCI_PAUSE:
2655         break;
2656     case MCI_PLAY:
2657         break;
2658     case MCI_PUT:
2659         break;
2660     case MCI_REALIZE:
2661         break;
2662     case MCI_RECORD:
2663         break;
2664     case MCI_RESUME:
2665         break;
2666     case MCI_SEEK:
2667         break;
2668     case MCI_SET:
2669         break;
2670     case MCI_SETAUDIO:
2671         switch (uDevType) {
2672         case MCI_DEVTYPE_DIGITAL_VIDEO: map = 0x0000077FF;      break;
2673         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2674         }
2675         break;
2676         /* case MCI_SETTIMECODE:*/
2677         /* case MCI_SIGNAL:*/
2678         /* case MCI_SOUND:*/
2679     case MCI_SPIN:
2680         break;
2681     case MCI_STATUS:
2682         kept = TRUE;
2683         switch (uDevType) {
2684         case MCI_DEVTYPE_DIGITAL_VIDEO:
2685         if (lParam) {
2686             LPMCI_DGV_STATUS_PARMS16    mdsp16  = (LPMCI_DGV_STATUS_PARMS16)MapSL(lParam);
2687             LPMCI_DGV_STATUS_PARMSA     mdsp32a = *(LPMCI_DGV_STATUS_PARMSA*)((char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA));
2688
2689             UnMapLS( lParam );
2690             if (mdsp16) {
2691                 mdsp32a->dwReturn = mdsp16->dwReturn;
2692                 if (dwFlags & MCI_DGV_STATUS_DISKSPACE) {
2693                     TRACE("MCI_STATUS (DGV) lpstrDrive=%08lx\n", mdsp16->lpstrDrive);
2694                     TRACE("MCI_STATUS (DGV) lpstrDrive=%s\n", (LPSTR)MapSL(mdsp16->lpstrDrive));
2695                     UnMapLS( mdsp16->lpstrDrive );
2696                 }
2697                 HeapFree( GetProcessHeap(), 0, (char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA) );
2698             } else {
2699                 return WINMM_MAP_NOMEM;
2700             }
2701         }
2702         return WINMM_MAP_OKMEM;
2703         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2704         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
2705         }
2706         break;
2707     case MCI_STEP:
2708         break;
2709     case MCI_STOP:
2710         break;
2711     case MCI_SYSINFO:
2712         if (lParam) {
2713             LPMCI_SYSINFO_PARMS16       msip16  = (LPMCI_SYSINFO_PARMS16)MapSL(lParam);
2714             LPMCI_SYSINFO_PARMSA        msip32a = *(LPMCI_SYSINFO_PARMSA*)((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA));
2715
2716             UnMapLS( lParam );
2717             if (msip16) {
2718                 msip16->dwCallback = msip32a->dwCallback;
2719                 UnMapLS( msip16->lpstrReturn );
2720                 HeapFree( GetProcessHeap(), 0, (char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA) );
2721             } else {
2722                 return WINMM_MAP_NOMEM;
2723             }
2724         }
2725         return WINMM_MAP_OKMEM;
2726         /* case MCI_UNDO: */
2727     case MCI_UNFREEZE:
2728         break;
2729     case MCI_UPDATE:
2730         break;
2731     case MCI_WHERE:
2732         switch (uDevType) {
2733         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       kept = TRUE;    break;
2734         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       kept = TRUE;    break;
2735         default:                        break;
2736         }
2737         break;
2738     case MCI_WINDOW:
2739         switch (uDevType) {
2740         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7666;       break;
2741         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7666;       break;
2742         default:                        break;
2743         }
2744         /* FIXME: see map function */
2745         break;
2746
2747     case DRV_OPEN:
2748         if (lParam) {
2749             LPMCI_OPEN_DRIVER_PARMS16   modp16  = (LPMCI_OPEN_DRIVER_PARMS16)MapSL(lParam);
2750             LPMCI_OPEN_DRIVER_PARMSA    modp32a = *(LPMCI_OPEN_DRIVER_PARMSA*)((char*)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSA));
2751
2752             UnMapLS( lParam );
2753             modp32a->wCustomCommandTable = modp16->wCustomCommandTable;
2754             modp32a->wType = modp16->wType;
2755             UnMapLS( modp16->lpstrParams );
2756             HeapFree( GetProcessHeap(), 0, (char *)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSA) );
2757         }
2758         return WINMM_MAP_OK;
2759     case DRV_LOAD:
2760     case DRV_ENABLE:
2761     case DRV_CLOSE:
2762     case DRV_DISABLE:
2763     case DRV_FREE:
2764     case DRV_CONFIGURE:
2765     case DRV_QUERYCONFIGURE:
2766     case DRV_INSTALL:
2767     case DRV_REMOVE:
2768     case DRV_EXITSESSION:
2769     case DRV_EXITAPPLICATION:
2770     case DRV_POWER:
2771         FIXME("This is a hack\n");
2772         return WINMM_MAP_OK;
2773     default:
2774         FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
2775         return WINMM_MAP_MSGERROR;
2776     }
2777     return MCI_MsgMapper32To16_Destroy((void*)lParam, size, map, kept);
2778 }
2779
2780 void    MMDRV_Init16(void)
2781 {
2782 #define A(_x,_y) MMDRV_InstallMap(_x, \
2783 MMDRV_##_y##_Map16To32A, MMDRV_##_y##_UnMap16To32A, \
2784 MMDRV_##_y##_Map32ATo16, MMDRV_##_y##_UnMap32ATo16, \
2785 MMDRV_##_y##_Callback)
2786     A(MMDRV_AUX,        Aux);
2787     A(MMDRV_MIXER,      Mixer);
2788     A(MMDRV_MIDIIN,     MidiIn);
2789     A(MMDRV_MIDIOUT,    MidiOut);
2790     A(MMDRV_WAVEIN,     WaveIn);
2791     A(MMDRV_WAVEOUT,    WaveOut);
2792 #undef A
2793
2794     pFnCallMMDrvFunc16 = MMDRV_CallMMDrvFunc16;
2795     pFnLoadMMDrvFunc16 = MMDRV_LoadMMDrvFunc16;
2796
2797     pFnMciMapMsg16To32A   = MCI_MapMsg16To32A;
2798     pFnMciUnMapMsg16To32A = MCI_UnMapMsg16To32A;
2799     pFnMciMapMsg32ATo16   = MCI_MapMsg32ATo16;
2800     pFnMciUnMapMsg32ATo16 = MCI_UnMapMsg32ATo16;
2801 }