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