ole32: Return an error in CoMarshalInterface if pStream is NULL.
[wine] / dlls / winmm / message16.c
1 /*
2  * MMSYSTEM MCI and low level mapping functions
3  *
4  * Copyright 1999 Eric Pouech
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <string.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <assert.h>
25 #include "wine/winbase16.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winver.h"
30 #include "wownt32.h"
31 #include "winemm16.h"
32 #include "digitalv.h"
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(winmm);
36
37 /**************************************************************************
38  *                              MMDRV_Callback                  [internal]
39  */
40 static  void    MMDRV_Callback(LPWINE_MLD mld, HDRVR hDev, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
41 {
42     TRACE("CB (*%08lx)(%p %08x %08lx %08lx %08lx\n",
43           mld->dwCallback, hDev, uMsg, mld->dwClientInstance, dwParam1, dwParam2);
44
45     if (!mld->bFrom32 && (mld->dwFlags & DCB_TYPEMASK) == DCB_FUNCTION)
46     {
47         WORD args[8];
48         /* 16 bit func, call it */
49         TRACE("Function (16 bit) !\n");
50
51         args[7] = HDRVR_16(hDev);
52         args[6] = uMsg;
53         args[5] = HIWORD(mld->dwClientInstance);
54         args[4] = LOWORD(mld->dwClientInstance);
55         args[3] = HIWORD(dwParam1);
56         args[2] = LOWORD(dwParam1);
57         args[1] = HIWORD(dwParam2);
58         args[0] = LOWORD(dwParam2);
59         WOWCallback16Ex( mld->dwCallback, WCB16_PASCAL, sizeof(args), args, NULL );
60     } else {
61         DriverCallback(mld->dwCallback, mld->dwFlags, hDev, uMsg,
62                        mld->dwClientInstance, dwParam1, dwParam2);
63     }
64 }
65
66 /* =================================
67  *       A U X    M A P P E R S
68  * ================================= */
69
70 /**************************************************************************
71  *                              MMDRV_Aux_Map16To32W            [internal]
72  */
73 static  WINMM_MapType   MMDRV_Aux_Map16To32W  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
74 {
75     return WINMM_MAP_MSGERROR;
76 }
77
78 /**************************************************************************
79  *                              MMDRV_Aux_UnMap16To32W          [internal]
80  */
81 static  WINMM_MapType   MMDRV_Aux_UnMap16To32W(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
82 {
83     return WINMM_MAP_MSGERROR;
84 }
85
86 /**************************************************************************
87  *                              MMDRV_Aux_Map32WTo16            [internal]
88  */
89 static  WINMM_MapType   MMDRV_Aux_Map32WTo16  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
90 {
91     return WINMM_MAP_MSGERROR;
92 }
93
94 /**************************************************************************
95  *                              MMDRV_Aux_UnMap32WTo16          [internal]
96  */
97 static  WINMM_MapType   MMDRV_Aux_UnMap32WTo16(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
98 {
99 #if 0
100  case AUXDM_GETDEVCAPS:
101     lpCaps->wMid = ac16.wMid;
102     lpCaps->wPid = ac16.wPid;
103     lpCaps->vDriverVersion = ac16.vDriverVersion;
104     strcpy(lpCaps->szPname, ac16.szPname);
105     lpCaps->wTechnology = ac16.wTechnology;
106     lpCaps->dwSupport = ac16.dwSupport;
107 #endif
108     return WINMM_MAP_MSGERROR;
109 }
110
111 /**************************************************************************
112  *                              MMDRV_Aux_Callback              [internal]
113  */
114 static  void    CALLBACK MMDRV_Aux_Callback(HDRVR hDev, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
115 {
116     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
117
118     FIXME("NIY\n");
119     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
120 }
121
122 /* =================================
123  *     M I X E R  M A P P E R S
124  * ================================= */
125
126 /**************************************************************************
127  *                              xMMDRV_Mixer_Map16To32W         [internal]
128  */
129 static  WINMM_MapType   MMDRV_Mixer_Map16To32W  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
130 {
131     return WINMM_MAP_MSGERROR;
132 }
133
134 /**************************************************************************
135  *                              MMDRV_Mixer_UnMap16To32W        [internal]
136  */
137 static  WINMM_MapType   MMDRV_Mixer_UnMap16To32W(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
138 {
139 #if 0
140     MIXERCAPSA  micA;
141     UINT        ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
142
143     if (ret == MMSYSERR_NOERROR) {
144         mixcaps->wMid           = micA.wMid;
145         mixcaps->wPid           = micA.wPid;
146         mixcaps->vDriverVersion = micA.vDriverVersion;
147         strcpy(mixcaps->szPname, micA.szPname);
148         mixcaps->fdwSupport     = micA.fdwSupport;
149         mixcaps->cDestinations  = micA.cDestinations;
150     }
151     return ret;
152 #endif
153     return WINMM_MAP_MSGERROR;
154 }
155
156 /**************************************************************************
157  *                              MMDRV_Mixer_Map32WTo16          [internal]
158  */
159 static  WINMM_MapType   MMDRV_Mixer_Map32WTo16  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
160 {
161     return WINMM_MAP_MSGERROR;
162 }
163
164 /**************************************************************************
165  *                              MMDRV_Mixer_UnMap32WTo16        [internal]
166  */
167 static  WINMM_MapType   MMDRV_Mixer_UnMap32WTo16(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
168 {
169     return WINMM_MAP_MSGERROR;
170 }
171
172 /**************************************************************************
173  *                              MMDRV_Mixer_Callback            [internal]
174  */
175 static  void    CALLBACK MMDRV_Mixer_Callback(HDRVR hDev, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
176 {
177     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
178
179     FIXME("NIY\n");
180     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
181 }
182
183 /* =================================
184  *   M I D I  I N    M A P P E R S
185  * ================================= */
186
187 /**************************************************************************
188  *                              MMDRV_MidiIn_Map16To32W         [internal]
189  */
190 static  WINMM_MapType   MMDRV_MidiIn_Map16To32W  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
191 {
192     return WINMM_MAP_MSGERROR;
193 }
194
195 /**************************************************************************
196  *                              MMDRV_MidiIn_UnMap16To32W       [internal]
197  */
198 static  WINMM_MapType   MMDRV_MidiIn_UnMap16To32W(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
199 {
200     return WINMM_MAP_MSGERROR;
201 }
202
203 /**************************************************************************
204  *                              MMDRV_MidiIn_Map32WTo16         [internal]
205  */
206 static  WINMM_MapType   MMDRV_MidiIn_Map32WTo16  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
207 {
208     return WINMM_MAP_MSGERROR;
209 }
210
211 /**************************************************************************
212  *                              MMDRV_MidiIn_UnMap32WTo16       [internal]
213  */
214 static  WINMM_MapType   MMDRV_MidiIn_UnMap32WTo16(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
215 {
216     return WINMM_MAP_MSGERROR;
217 }
218
219 /**************************************************************************
220  *                              MMDRV_MidiIn_Callback           [internal]
221  */
222 static  void    CALLBACK MMDRV_MidiIn_Callback(HDRVR hDev, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
223 {
224     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
225
226     switch (uMsg) {
227     case MIM_OPEN:
228     case MIM_CLOSE:
229         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
230
231     case MIM_DATA:
232     case MIM_MOREDATA:
233     case MIM_ERROR:
234         /* dwParam1 & dwParam2 are data, nothing to do */
235         break;
236     case MIM_LONGDATA:
237     case MIM_LONGERROR:
238         /* dwParam1 points to a MidiHdr, work to be done !!! */
239         if (mld->bFrom32 && !MMDRV_Is32(mld->mmdIndex)) {
240             /* initial map is: 32 => 16 */
241             LPMIDIHDR           mh16 = MapSL(dwParam1);
242             LPMIDIHDR           mh32 = *(LPMIDIHDR*)((LPSTR)mh16 - sizeof(LPMIDIHDR));
243
244             dwParam1 = (DWORD)mh32;
245             mh32->dwFlags = mh16->dwFlags;
246             mh32->dwBytesRecorded = mh16->dwBytesRecorded;
247             if (mh32->reserved >= sizeof(MIDIHDR))
248                 mh32->dwOffset = mh16->dwOffset;
249         } else if (!mld->bFrom32 && MMDRV_Is32(mld->mmdIndex)) {
250             /* initial map is: 16 => 32 */
251             LPMIDIHDR           mh32 = (LPMIDIHDR)(dwParam1);
252             SEGPTR              segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
253             LPMIDIHDR           mh16 = MapSL(segmh16);
254
255             dwParam1 = (DWORD)segmh16;
256             mh16->dwFlags = mh32->dwFlags;
257             mh16->dwBytesRecorded = mh32->dwBytesRecorded;
258             if (mh16->reserved >= sizeof(MIDIHDR))
259                 mh16->dwOffset = mh32->dwOffset;
260         }
261         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
262         break;
263     /* case MOM_POSITIONCB: */
264     default:
265         ERR("Unknown msg %u\n", uMsg);
266     }
267
268     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
269 }
270
271 /* =================================
272  *   M I D I  O U T  M A P P E R S
273  * ================================= */
274
275 /**************************************************************************
276  *                              MMDRV_MidiOut_Map16To32W        [internal]
277  */
278 static  WINMM_MapType   MMDRV_MidiOut_Map16To32W  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
279 {
280     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
281
282     switch (wMsg) {
283     case MODM_GETNUMDEVS:
284     case MODM_DATA:
285     case MODM_RESET:
286     case MODM_SETVOLUME:
287         ret = WINMM_MAP_OK;
288         break;
289
290     case MODM_OPEN:
291     case MODM_CLOSE:
292     case MODM_GETVOLUME:
293         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
294         break;
295
296     case MODM_GETDEVCAPS:
297         {
298             LPMIDIOUTCAPSW      moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSW));
299             LPMIDIOUTCAPS16     moc16 = MapSL(*lpParam1);
300
301             if (moc32) {
302                 *(LPMIDIOUTCAPS16*)moc32 = moc16;
303                 moc32 = (LPMIDIOUTCAPSW)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16));
304                 *lpParam1 = (DWORD)moc32;
305                 *lpParam2 = sizeof(MIDIOUTCAPSW);
306
307                 ret = WINMM_MAP_OKMEM;
308             } else {
309                 ret = WINMM_MAP_NOMEM;
310             }
311         }
312         break;
313     case MODM_PREPARE:
314         {
315             LPMIDIHDR           mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR));
316             LPMIDIHDR           mh16 = MapSL(*lpParam1);
317
318             if (mh32) {
319                 *(LPMIDIHDR*)mh32 = (LPMIDIHDR)*lpParam1;
320                 mh32 = (LPMIDIHDR)((LPSTR)mh32 + sizeof(LPMIDIHDR));
321                 mh32->lpData = MapSL((SEGPTR)mh16->lpData);
322                 mh32->dwBufferLength = mh16->dwBufferLength;
323                 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
324                 mh32->dwUser = mh16->dwUser;
325                 mh32->dwFlags = mh16->dwFlags;
326                 /* FIXME: nothing on mh32->lpNext */
327                 /* could link the mh32->lpNext at this level for memory house keeping */
328                 mh32->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? ((LPMIDIHDR)mh16)->dwOffset : 0;
329                 mh16->lpNext = mh32; /* for reuse in unprepare and write */
330                 /* store size of passed MIDIHDR?? structure to know if dwOffset is available or not */
331                 mh16->reserved = *lpParam2;
332                 *lpParam1 = (DWORD)mh32;
333                 *lpParam2 = sizeof(MIDIHDR);
334
335                 ret = WINMM_MAP_OKMEM;
336             } else {
337                 ret = WINMM_MAP_NOMEM;
338             }
339         }
340         break;
341     case MODM_UNPREPARE:
342     case MODM_LONGDATA:
343         {
344             LPMIDIHDR           mh16 = MapSL(*lpParam1);
345             LPMIDIHDR           mh32 = (LPMIDIHDR)mh16->lpNext;
346
347             *lpParam1 = (DWORD)mh32;
348             *lpParam2 = sizeof(MIDIHDR);
349             /* dwBufferLength can be reduced between prepare & write */
350             if (wMsg == MODM_LONGDATA && mh32->dwBufferLength < mh16->dwBufferLength) {
351                 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
352                     mh32->dwBufferLength, mh16->dwBufferLength);
353             } else
354                 mh32->dwBufferLength = mh16->dwBufferLength;
355             ret = WINMM_MAP_OKMEM;
356         }
357         break;
358
359     case MODM_CACHEPATCHES:
360     case MODM_CACHEDRUMPATCHES:
361     default:
362         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
363         break;
364     }
365     return ret;
366 }
367
368 /**************************************************************************
369  *                              MMDRV_MidiOut_UnMap16To32W      [internal]
370  */
371 static  WINMM_MapType   MMDRV_MidiOut_UnMap16To32W(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
372 {
373     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
374
375     switch (wMsg) {
376     case MODM_GETNUMDEVS:
377     case MODM_DATA:
378     case MODM_RESET:
379     case MODM_SETVOLUME:
380         ret = WINMM_MAP_OK;
381         break;
382
383     case MODM_OPEN:
384     case MODM_CLOSE:
385     case MODM_GETVOLUME:
386         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
387         break;
388
389     case MODM_GETDEVCAPS:
390         {
391             LPMIDIOUTCAPSW              moc32 = (LPMIDIOUTCAPSW)(*lpParam1);
392             LPMIDIOUTCAPS16             moc16 = *(LPMIDIOUTCAPS16*)((LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
393
394             moc16->wMid                 = moc32->wMid;
395             moc16->wPid                 = moc32->wPid;
396             moc16->vDriverVersion       = moc32->vDriverVersion;
397             WideCharToMultiByte( CP_ACP, 0, moc32->szPname, -1, moc16->szPname,
398                                  sizeof(moc16->szPname), NULL, NULL );
399             moc16->wTechnology          = moc32->wTechnology;
400             moc16->wVoices              = moc32->wVoices;
401             moc16->wNotes               = moc32->wNotes;
402             moc16->wChannelMask         = moc32->wChannelMask;
403             moc16->dwSupport            = moc32->dwSupport;
404             HeapFree(GetProcessHeap(), 0, (LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
405             ret = WINMM_MAP_OK;
406         }
407         break;
408     case MODM_PREPARE:
409     case MODM_UNPREPARE:
410     case MODM_LONGDATA:
411         {
412             LPMIDIHDR           mh32 = (LPMIDIHDR)(*lpParam1);
413             LPMIDIHDR           mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)));
414
415             assert(mh16->lpNext == mh32);
416             mh16->dwBufferLength = mh32->dwBufferLength;
417             mh16->dwBytesRecorded = mh32->dwBytesRecorded;
418             mh16->dwUser = mh32->dwUser;
419             mh16->dwFlags = mh32->dwFlags;
420             if (mh16->reserved >= sizeof(MIDIHDR))
421                 mh16->dwOffset = mh32->dwOffset;
422
423             if (wMsg == MODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
424                 HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR));
425                 mh16->lpNext = 0;
426             }
427             ret = WINMM_MAP_OK;
428         }
429         break;
430
431     case MODM_CACHEPATCHES:
432     case MODM_CACHEDRUMPATCHES:
433     default:
434         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
435         break;
436     }
437     return ret;
438 }
439
440 /**************************************************************************
441  *                              MMDRV_MidiOut_Map32WTo16        [internal]
442  */
443 static  WINMM_MapType   MMDRV_MidiOut_Map32WTo16  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
444 {
445     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
446
447     switch (wMsg) {
448     case MODM_CLOSE:
449     case MODM_GETNUMDEVS:
450     case MODM_DATA:
451     case MODM_RESET:
452     case MODM_SETVOLUME:
453         ret = WINMM_MAP_OK;
454         break;
455     case MODM_GETDEVCAPS:
456         {
457             LPMIDIOUTCAPSW moc32 = (LPMIDIOUTCAPSW)*lpParam1;
458             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPSW)+sizeof(MIDIOUTCAPS16));
459
460             if (ptr) {
461                 *(LPMIDIOUTCAPSW*)ptr = moc32;
462                 ret = WINMM_MAP_OKMEM;
463             } else {
464                 ret = WINMM_MAP_NOMEM;
465             }
466             *lpParam1 = (DWORD)MapLS(ptr) + sizeof(LPMIDIOUTCAPSW);
467             *lpParam2 = sizeof(MIDIOUTCAPS16);
468         }
469         break;
470     case MODM_PREPARE:
471         {
472             LPMIDIHDR           mh32 = (LPMIDIHDR)*lpParam1;
473             LPMIDIHDR           mh16;
474             LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
475                                     sizeof(LPMIDIHDR) + sizeof(MIDIHDR) + mh32->dwBufferLength);
476
477             if (ptr) {
478                 *(LPMIDIHDR*)ptr = mh32;
479                 mh16 = (LPMIDIHDR)((LPSTR)ptr + sizeof(LPMIDIHDR));
480                 *lpParam1 = MapLS(mh16);
481                 mh16->lpData = (LPSTR)*lpParam1 + sizeof(MIDIHDR);
482                 /* data will be copied on WODM_WRITE */
483                 mh16->dwBufferLength = mh32->dwBufferLength;
484                 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
485                 mh16->dwUser = mh32->dwUser;
486                 mh16->dwFlags = mh32->dwFlags;
487                 /* FIXME: nothing on mh32->lpNext */
488                 /* could link the mh32->lpNext at this level for memory house keeping */
489                 mh16->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? mh32->dwOffset : 0;
490
491                 mh32->lpNext = (LPMIDIHDR)mh16; /* for reuse in unprepare and write */
492                 mh32->reserved = *lpParam2;
493
494                 TRACE("mh16=%08lx mh16->lpData=%p mh32->buflen=%u mh32->lpData=%p\n",
495                       *lpParam1, mh16->lpData, mh32->dwBufferLength, mh32->lpData);
496                 *lpParam2 = sizeof(MIDIHDR);
497
498                 ret = WINMM_MAP_OKMEM;
499             } else {
500                 ret = WINMM_MAP_NOMEM;
501             }
502         }
503         break;
504     case MODM_UNPREPARE:
505     case MODM_LONGDATA:
506         {
507             LPMIDIHDR           mh32 = (LPMIDIHDR)(*lpParam1);
508             LPMIDIHDR           mh16 = (LPMIDIHDR)mh32->lpNext;
509             LPSTR               ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
510
511             assert(*(LPMIDIHDR*)ptr == mh32);
512
513             if (wMsg == MODM_LONGDATA)
514                 memcpy((LPSTR)mh16 + sizeof(MIDIHDR), mh32->lpData, mh32->dwBufferLength);
515
516             *lpParam1 = MapLS(mh16);
517             *lpParam2 = sizeof(MIDIHDR);
518             TRACE("mh16=%08lx mh16->lpData=%p mh32->buflen=%u mh32->lpData=%p\n",
519                   *lpParam1, mh16->lpData, mh32->dwBufferLength, mh32->lpData);
520
521             /* dwBufferLength can be reduced between prepare & write */
522             if (wMsg == MODM_LONGDATA && mh16->dwBufferLength < mh32->dwBufferLength) {
523                 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
524                     mh16->dwBufferLength, mh32->dwBufferLength);
525             } else
526                 mh16->dwBufferLength = mh32->dwBufferLength;
527             ret = WINMM_MAP_OKMEM;
528         }
529         break;
530     case MODM_OPEN:
531         {
532             LPMIDIOPENDESC              mod32 = (LPMIDIOPENDESC)*lpParam1;
533             LPVOID                      ptr;
534             LPMIDIOPENDESC16            mod16;
535
536             /* allocated data are mapped as follows:
537                LPMIDIOPENDESC   ptr to orig lParam1
538                DWORD            orig dwUser, which is a pointer to DWORD:driver dwInstance
539                DWORD            dwUser passed to driver
540                MIDIOPENDESC16   mod16: openDesc passed to driver
541                MIDIOPENSTRMID   cIds
542             */
543             ptr = HeapAlloc( GetProcessHeap(), 0,
544                              sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD) + sizeof(MIDIOPENDESC16) +
545                              mod32->cIds ? (mod32->cIds - 1) * sizeof(MIDIOPENSTRMID) : 0);
546
547             if (ptr) {
548                 SEGPTR segptr = MapLS(ptr);
549                 *(LPMIDIOPENDESC*)ptr = mod32;
550                 *(LPDWORD)((char*)ptr + sizeof(LPMIDIOPENDESC)) = *lpdwUser;
551                 mod16 = (LPMIDIOPENDESC16)((LPSTR)ptr + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD));
552
553                 mod16->hMidi = HMIDI_16(mod32->hMidi);
554                 mod16->dwCallback = mod32->dwCallback;
555                 mod16->dwInstance = mod32->dwInstance;
556                 mod16->dnDevNode = mod32->dnDevNode;
557                 mod16->cIds = mod32->cIds;
558                 memcpy(&mod16->rgIds, &mod32->rgIds, mod32->cIds * sizeof(MIDIOPENSTRMID));
559
560                 *lpParam1 = (DWORD)segptr + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD);
561                 *lpdwUser = (DWORD)segptr + sizeof(LPMIDIOPENDESC) + sizeof(DWORD);
562
563                 ret = WINMM_MAP_OKMEM;
564             } else {
565                 ret = WINMM_MAP_NOMEM;
566             }
567         }
568         break;
569     case MODM_GETVOLUME:
570     case MODM_CACHEPATCHES:
571     case MODM_CACHEDRUMPATCHES:
572     default:
573         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
574         break;
575     }
576     return ret;
577 }
578
579 /**************************************************************************
580  *                              MMDRV_MidiOut_UnMap32WTo16      [internal]
581  */
582 static  WINMM_MapType   MMDRV_MidiOut_UnMap32WTo16(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
583 {
584     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
585
586     switch (wMsg) {
587     case MODM_CLOSE:
588     case MODM_GETNUMDEVS:
589     case MODM_DATA:
590     case MODM_RESET:
591     case MODM_SETVOLUME:
592         ret = WINMM_MAP_OK;
593         break;
594     case MODM_GETDEVCAPS:
595         {
596             LPMIDIOUTCAPS16             moc16 = MapSL(*lpParam1);
597             LPSTR                       ptr   = (LPSTR)moc16 - sizeof(LPMIDIOUTCAPSW);
598             LPMIDIOUTCAPSW              moc32 = *(LPMIDIOUTCAPSW*)ptr;
599
600             moc32->wMid                 = moc16->wMid;
601             moc32->wPid                 = moc16->wPid;
602             moc32->vDriverVersion       = moc16->vDriverVersion;
603             WideCharToMultiByte( CP_ACP, 0, moc32->szPname, -1, moc16->szPname,
604                                  sizeof(moc16->szPname), NULL, NULL );
605             moc32->wTechnology          = moc16->wTechnology;
606             moc32->wVoices              = moc16->wVoices;
607             moc32->wNotes               = moc16->wNotes;
608             moc32->wChannelMask         = moc16->wChannelMask;
609             moc32->dwSupport            = moc16->dwSupport;
610             UnMapLS( *lpParam1 );
611             HeapFree( GetProcessHeap(), 0, ptr );
612             ret = WINMM_MAP_OK;
613         }
614         break;
615     case MODM_PREPARE:
616     case MODM_UNPREPARE:
617     case MODM_LONGDATA:
618         {
619             LPMIDIHDR           mh16 = MapSL(*lpParam1);
620             LPSTR               ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
621             LPMIDIHDR           mh32 = *(LPMIDIHDR*)ptr;
622
623             assert(mh32->lpNext == (LPMIDIHDR)mh16);
624             UnMapLS( *lpParam1 );
625             mh32->dwBytesRecorded = mh16->dwBytesRecorded;
626             mh32->dwUser = mh16->dwUser;
627             mh32->dwFlags = mh16->dwFlags;
628
629             if (wMsg == MODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
630                 HeapFree( GetProcessHeap(), 0, ptr );
631                 mh32->lpNext = 0;
632             }
633             ret = WINMM_MAP_OK;
634         }
635         break;
636     case MODM_OPEN:
637         {
638             LPMIDIOPENDESC16            mod16 = MapSL(*lpParam1);
639             LPSTR                       ptr   = (LPSTR)mod16 - sizeof(LPMIDIOPENDESC) - 2*sizeof(DWORD);
640             UnMapLS( *lpParam1 );
641             **(DWORD**)(ptr + sizeof(LPMIDIOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPMIDIOPENDESC) + sizeof(DWORD));
642
643             HeapFree( GetProcessHeap(), 0, ptr );
644             ret = WINMM_MAP_OK;
645         }
646         break;
647     case MODM_GETVOLUME:
648     case MODM_CACHEPATCHES:
649     case MODM_CACHEDRUMPATCHES:
650     default:
651         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
652         break;
653     }
654     return ret;
655 }
656
657 /**************************************************************************
658  *                              MMDRV_MidiOut_Callback          [internal]
659  */
660 static  void    CALLBACK MMDRV_MidiOut_Callback(HDRVR hDev, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
661 {
662     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
663
664     switch (uMsg) {
665     case MOM_OPEN:
666     case MOM_CLOSE:
667         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
668         break;
669     case MOM_DONE:
670         if (mld->bFrom32 && !MMDRV_Is32(mld->mmdIndex)) {
671             /* initial map is: 32 => 16 */
672             LPMIDIHDR           mh16 = MapSL(dwParam1);
673             LPMIDIHDR           mh32 = *(LPMIDIHDR*)((LPSTR)mh16 - sizeof(LPMIDIHDR));
674
675             dwParam1 = (DWORD)mh32;
676             mh32->dwFlags = mh16->dwFlags;
677             mh32->dwOffset = mh16->dwOffset;
678             if (mh32->reserved >= sizeof(MIDIHDR))
679                 mh32->dwOffset = mh16->dwOffset;
680         } else if (!mld->bFrom32 && MMDRV_Is32(mld->mmdIndex)) {
681             /* initial map is: 16 => 32 */
682             LPMIDIHDR           mh32 = (LPMIDIHDR)(dwParam1);
683             SEGPTR              segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
684             LPMIDIHDR           mh16 = MapSL(segmh16);
685
686             dwParam1 = (DWORD)segmh16;
687             mh16->dwFlags = mh32->dwFlags;
688             if (mh16->reserved >= sizeof(MIDIHDR))
689                 mh16->dwOffset = mh32->dwOffset;
690         }
691         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
692         break;
693     /* case MOM_POSITIONCB: */
694     default:
695         ERR("Unknown msg %u\n", uMsg);
696     }
697
698     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
699 }
700
701 /* =================================
702  *   W A V E  I N    M A P P E R S
703  * ================================= */
704
705 /**************************************************************************
706  *                              MMDRV_WaveIn_Map16To32W         [internal]
707  */
708 static  WINMM_MapType   MMDRV_WaveIn_Map16To32W  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
709 {
710     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
711
712     switch (wMsg) {
713     case WIDM_GETNUMDEVS:
714     case WIDM_RESET:
715     case WIDM_START:
716     case WIDM_STOP:
717         ret = WINMM_MAP_OK;
718         break;
719     case WIDM_OPEN:
720     case WIDM_CLOSE:
721         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
722         break;
723     case WIDM_GETDEVCAPS:
724         {
725             LPWAVEINCAPSW       wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSW));
726             LPWAVEINCAPS16      wic16 = MapSL(*lpParam1);
727
728             if (wic32) {
729                 *(LPWAVEINCAPS16*)wic32 = wic16;
730                 wic32 = (LPWAVEINCAPSW)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16));
731                 *lpParam1 = (DWORD)wic32;
732                 *lpParam2 = sizeof(WAVEINCAPSW);
733
734                 ret = WINMM_MAP_OKMEM;
735             } else {
736                 ret = WINMM_MAP_NOMEM;
737             }
738         }
739         break;
740     case WIDM_GETPOS:
741         {
742             LPMMTIME            mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
743             LPMMTIME16          mmt16 = MapSL(*lpParam1);
744
745             if (mmt32) {
746                 *(LPMMTIME16*)mmt32 = mmt16;
747                 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
748
749                 mmt32->wType = mmt16->wType;
750                 *lpParam1 = (DWORD)mmt32;
751                 *lpParam2 = sizeof(MMTIME);
752
753                 ret = WINMM_MAP_OKMEM;
754             } else {
755                 ret = WINMM_MAP_NOMEM;
756             }
757         }
758         break;
759     case WIDM_PREPARE:
760         {
761             LPWAVEHDR           wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
762             LPWAVEHDR           wh16 = MapSL(*lpParam1);
763
764             if (wh32) {
765                 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
766                 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
767                 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
768                 wh32->dwBufferLength = wh16->dwBufferLength;
769                 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
770                 wh32->dwUser = wh16->dwUser;
771                 wh32->dwFlags = wh16->dwFlags;
772                 wh32->dwLoops = wh16->dwLoops;
773                 /* FIXME: nothing on wh32->lpNext */
774                 /* could link the wh32->lpNext at this level for memory house keeping */
775                 wh16->lpNext = wh32; /* for reuse in unprepare and write */
776                 *lpParam1 = (DWORD)wh32;
777                 *lpParam2 = sizeof(WAVEHDR);
778
779                 ret = WINMM_MAP_OKMEM;
780             } else {
781                 ret = WINMM_MAP_NOMEM;
782             }
783         }
784         break;
785     case WIDM_ADDBUFFER:
786     case WIDM_UNPREPARE:
787         {
788             LPWAVEHDR           wh16 = MapSL(*lpParam1);
789             LPWAVEHDR           wh32 = (LPWAVEHDR)wh16->lpNext;
790
791             *lpParam1 = (DWORD)wh32;
792             *lpParam2 = sizeof(WAVEHDR);
793             /* dwBufferLength can be reduced between prepare & write */
794             if (wMsg == WIDM_ADDBUFFER && wh32->dwBufferLength < wh16->dwBufferLength) {
795                 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
796                     wh32->dwBufferLength, wh16->dwBufferLength);
797             } else
798                 wh32->dwBufferLength = wh16->dwBufferLength;
799             ret = WINMM_MAP_OKMEM;
800         }
801         break;
802     case WIDM_MAPPER_STATUS:
803         /* just a single DWORD */
804         *lpParam2 = (DWORD)MapSL(*lpParam2);
805         ret = WINMM_MAP_OK;
806         break;
807     default:
808         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
809         break;
810     }
811     return ret;
812 }
813
814 /**************************************************************************
815  *                              MMDRV_WaveIn_UnMap16To32W       [internal]
816  */
817 static  WINMM_MapType   MMDRV_WaveIn_UnMap16To32W(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
818 {
819     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
820
821     switch (wMsg) {
822     case WIDM_GETNUMDEVS:
823     case WIDM_RESET:
824     case WIDM_START:
825     case WIDM_STOP:
826     case WIDM_MAPPER_STATUS:
827         ret = WINMM_MAP_OK;
828         break;
829     case WIDM_OPEN:
830     case WIDM_CLOSE:
831         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
832         break;
833     case WIDM_GETDEVCAPS:
834         {
835             LPWAVEINCAPSW               wic32 = (LPWAVEINCAPSW)(*lpParam1);
836             LPWAVEINCAPS16              wic16 = *(LPWAVEINCAPS16*)((LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
837
838             wic16->wMid = wic32->wMid;
839             wic16->wPid = wic32->wPid;
840             wic16->vDriverVersion = wic32->vDriverVersion;
841             WideCharToMultiByte( CP_ACP, 0, wic32->szPname, -1, wic16->szPname,
842                                  sizeof(wic16->szPname), NULL, NULL );
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_Map32WTo16         [internal]
889  */
890 static  WINMM_MapType   MMDRV_WaveIn_Map32WTo16  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* 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                 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
972                 *lpParam2 = sizeof(WAVEHDR);
973                 TRACE("wh16=%08lx wh16->lpData=%p wh32->buflen=%u wh32->lpData=%p\n",
974                       *lpParam1, wh16->lpData, wh32->dwBufferLength, wh32->lpData);
975
976                 ret = WINMM_MAP_OKMEM;
977             } else {
978                 ret = WINMM_MAP_NOMEM;
979             }
980         }
981         break;
982     case WIDM_ADDBUFFER:
983     case WIDM_UNPREPARE:
984         {
985             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
986             LPWAVEHDR           wh16 = wh32->lpNext;
987             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
988             SEGPTR seg_ptr = MapLS( ptr );
989
990             assert(*(LPWAVEHDR*)ptr == wh32);
991
992             if (wMsg == WIDM_ADDBUFFER)
993                 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
994
995             *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
996             *lpParam2 = sizeof(WAVEHDR);
997             TRACE("wh16=%08lx wh16->lpData=%p wh32->buflen=%u wh32->lpData=%p\n",
998                   *lpParam1, wh16->lpData, wh32->dwBufferLength, wh32->lpData);
999
1000             /* dwBufferLength can be reduced between prepare & write */
1001             if (wMsg == WIDM_ADDBUFFER && wh16->dwBufferLength < wh32->dwBufferLength) {
1002                 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
1003                     wh16->dwBufferLength, wh32->dwBufferLength);
1004             } else
1005                 wh16->dwBufferLength = wh32->dwBufferLength;
1006             ret = WINMM_MAP_OKMEM;
1007         }
1008         break;
1009    case WIDM_GETDEVCAPS:
1010         {
1011             LPWAVEINCAPSW wic32 = (LPWAVEINCAPSW)*lpParam1;
1012             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0 ,sizeof(LPWAVEINCAPSW) + sizeof(WAVEINCAPS16));
1013
1014             if (ptr) {
1015                 *(LPWAVEINCAPSW*)ptr = wic32;
1016                 ret = WINMM_MAP_OKMEM;
1017             } else {
1018                 ret = WINMM_MAP_NOMEM;
1019             }
1020             *lpParam1 = MapLS(ptr) + sizeof(LPWAVEINCAPSW);
1021             *lpParam2 = sizeof(WAVEINCAPS16);
1022         }
1023         break;
1024     case WIDM_GETPOS:
1025         {
1026             LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1027             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMMTIME) + sizeof(MMTIME16));
1028             LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1029
1030             if (ptr) {
1031                 *(LPMMTIME*)ptr = mmt32;
1032                 mmt16->wType = mmt32->wType;
1033                 ret = WINMM_MAP_OKMEM;
1034             } else {
1035                 ret = WINMM_MAP_NOMEM;
1036             }
1037             *lpParam1 = MapLS(ptr) + sizeof(LPMMTIME);
1038             *lpParam2 = sizeof(MMTIME16);
1039         }
1040         break;
1041     case DRVM_MAPPER_STATUS:
1042         {
1043             LPDWORD p32 = (LPDWORD)*lpParam2;
1044             *lpParam2 = MapLS(p32);
1045             ret = WINMM_MAP_OKMEM;
1046         }
1047         break;
1048     default:
1049         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1050         break;
1051     }
1052     return ret;
1053 }
1054
1055 /**************************************************************************
1056  *                              MMDRV_WaveIn_UnMap32WTo16       [internal]
1057  */
1058 static  WINMM_MapType   MMDRV_WaveIn_UnMap32WTo16(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
1059 {
1060     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
1061
1062     switch (wMsg) {
1063     case WIDM_CLOSE:
1064     case WIDM_GETNUMDEVS:
1065     case WIDM_RESET:
1066     case WIDM_START:
1067     case WIDM_STOP:
1068         ret = WINMM_MAP_OK;
1069         break;
1070
1071     case WIDM_OPEN:
1072         {
1073             LPWAVEOPENDESC16            wod16 = MapSL(*lpParam1);
1074             LPSTR                       ptr   = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1075             LPWAVEOPENDESC              wod32 = *(LPWAVEOPENDESC*)ptr;
1076
1077             UnMapLS( *lpParam1 );
1078             wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1079             **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1080             HeapFree( GetProcessHeap(), 0, ptr );
1081             ret = WINMM_MAP_OK;
1082         }
1083         break;
1084
1085     case WIDM_ADDBUFFER:
1086     case WIDM_PREPARE:
1087     case WIDM_UNPREPARE:
1088         {
1089             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1090             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1091             LPWAVEHDR           wh32 = *(LPWAVEHDR*)ptr;
1092
1093             assert(wh32->lpNext == wh16);
1094             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1095             wh32->dwUser = wh16->dwUser;
1096             wh32->dwFlags = wh16->dwFlags;
1097             wh32->dwLoops = wh16->dwLoops;
1098             UnMapLS( *lpParam1 );
1099
1100             if (wMsg == WIDM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
1101                 HeapFree( GetProcessHeap(), 0, ptr );
1102                 wh32->lpNext = 0;
1103             }
1104             ret = WINMM_MAP_OK;
1105         }
1106         break;
1107      case WIDM_GETDEVCAPS:
1108         {
1109             LPWAVEINCAPS16              wic16 = MapSL(*lpParam1);
1110             LPSTR                       ptr   = (LPSTR)wic16 - sizeof(LPWAVEINCAPSW);
1111             LPWAVEINCAPSW               wic32 = *(LPWAVEINCAPSW*)ptr;
1112
1113             wic32->wMid = wic16->wMid;
1114             wic32->wPid = wic16->wPid;
1115             wic32->vDriverVersion = wic16->vDriverVersion;
1116             WideCharToMultiByte( CP_ACP, 0, wic32->szPname, -1, wic16->szPname,
1117                                  sizeof(wic16->szPname), NULL, NULL );
1118             wic32->dwFormats = wic16->dwFormats;
1119             wic32->wChannels = wic16->wChannels;
1120             UnMapLS( *lpParam1 );
1121             HeapFree( GetProcessHeap(), 0, ptr );
1122             ret = WINMM_MAP_OK;
1123         }
1124         break;
1125     case WIDM_GETPOS:
1126         {
1127             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1128             LPSTR               ptr   = (LPSTR)mmt16 - sizeof(LPMMTIME);
1129             LPMMTIME            mmt32 = *(LPMMTIME*)ptr;
1130
1131             MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1132             UnMapLS( *lpParam1 );
1133             HeapFree( GetProcessHeap(), 0, ptr );
1134             ret = WINMM_MAP_OK;
1135         }
1136         break;
1137     case DRVM_MAPPER_STATUS:
1138         {
1139             UnMapLS( *lpParam2 );
1140             ret = WINMM_MAP_OK;
1141         }
1142         break;
1143     default:
1144         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1145         break;
1146     }
1147     return ret;
1148 }
1149
1150 /**************************************************************************
1151  *                              MMDRV_WaveIn_Callback           [internal]
1152  */
1153 static  void    CALLBACK MMDRV_WaveIn_Callback(HDRVR hDev, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
1154 {
1155     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
1156
1157     switch (uMsg) {
1158     case WIM_OPEN:
1159     case WIM_CLOSE:
1160         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1161         break;
1162     case WIM_DATA:
1163         if (mld->bFrom32 && !MMDRV_Is32(mld->mmdIndex)) {
1164             /* initial map is: 32 => 16 */
1165             LPWAVEHDR           wh16 = MapSL(dwParam1);
1166             LPWAVEHDR           wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1167
1168             dwParam1 = (DWORD)wh32;
1169             wh32->dwFlags = wh16->dwFlags;
1170             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1171         } else if (!mld->bFrom32 && MMDRV_Is32(mld->mmdIndex)) {
1172             /* initial map is: 16 => 32 */
1173             LPWAVEHDR           wh32 = (LPWAVEHDR)(dwParam1);
1174             SEGPTR              segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1175             LPWAVEHDR           wh16 = MapSL(segwh16);
1176
1177             dwParam1 = (DWORD)segwh16;
1178             wh16->dwFlags = wh32->dwFlags;
1179             wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1180         }
1181         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1182         break;
1183     default:
1184         ERR("Unknown msg %u\n", uMsg);
1185     }
1186
1187     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1188 }
1189
1190 /* =================================
1191  *   W A V E  O U T  M A P P E R S
1192  * ================================= */
1193
1194 /**************************************************************************
1195  *                              MMDRV_WaveOut_Map16To32W        [internal]
1196  */
1197 static  WINMM_MapType   MMDRV_WaveOut_Map16To32W  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
1198 {
1199     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
1200
1201     switch (wMsg) {
1202     /* nothing to do */
1203     case WODM_BREAKLOOP:
1204     case WODM_CLOSE:
1205     case WODM_GETNUMDEVS:
1206     case WODM_PAUSE:
1207     case WODM_RESET:
1208     case WODM_RESTART:
1209     case WODM_SETPITCH:
1210     case WODM_SETPLAYBACKRATE:
1211     case WODM_SETVOLUME:
1212         ret = WINMM_MAP_OK;
1213         break;
1214
1215     case WODM_GETPITCH:
1216     case WODM_GETPLAYBACKRATE:
1217     case WODM_GETVOLUME:
1218     case WODM_OPEN:
1219         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
1220         break;
1221
1222     case WODM_GETDEVCAPS:
1223         {
1224             LPWAVEOUTCAPSW              woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSW));
1225             LPWAVEOUTCAPS16             woc16 = MapSL(*lpParam1);
1226
1227             if (woc32) {
1228                 *(LPWAVEOUTCAPS16*)woc32 = woc16;
1229                 woc32 = (LPWAVEOUTCAPSW)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16));
1230                 *lpParam1 = (DWORD)woc32;
1231                 *lpParam2 = sizeof(WAVEOUTCAPSW);
1232
1233                 ret = WINMM_MAP_OKMEM;
1234             } else {
1235                 ret = WINMM_MAP_NOMEM;
1236             }
1237         }
1238         break;
1239     case WODM_GETPOS:
1240         {
1241             LPMMTIME            mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
1242             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1243
1244             if (mmt32) {
1245                 *(LPMMTIME16*)mmt32 = mmt16;
1246                 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
1247
1248                 mmt32->wType = mmt16->wType;
1249                 *lpParam1 = (DWORD)mmt32;
1250                 *lpParam2 = sizeof(MMTIME);
1251
1252                 ret = WINMM_MAP_OKMEM;
1253             } else {
1254                 ret = WINMM_MAP_NOMEM;
1255             }
1256         }
1257         break;
1258     case WODM_PREPARE:
1259         {
1260             LPWAVEHDR           wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
1261             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1262
1263             if (wh32) {
1264                 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
1265                 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
1266                 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
1267                 wh32->dwBufferLength = wh16->dwBufferLength;
1268                 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1269                 wh32->dwUser = wh16->dwUser;
1270                 wh32->dwFlags = wh16->dwFlags;
1271                 wh32->dwLoops = wh16->dwLoops;
1272                 /* FIXME: nothing on wh32->lpNext */
1273                 /* could link the wh32->lpNext at this level for memory house keeping */
1274                 wh16->lpNext = wh32; /* for reuse in unprepare and write */
1275                 *lpParam1 = (DWORD)wh32;
1276                 *lpParam2 = sizeof(WAVEHDR);
1277
1278                 ret = WINMM_MAP_OKMEM;
1279             } else {
1280                 ret = WINMM_MAP_NOMEM;
1281             }
1282         }
1283         break;
1284     case WODM_UNPREPARE:
1285     case WODM_WRITE:
1286         {
1287             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1288             LPWAVEHDR           wh32 = (LPWAVEHDR)wh16->lpNext;
1289
1290             *lpParam1 = (DWORD)wh32;
1291             *lpParam2 = sizeof(WAVEHDR);
1292             /* dwBufferLength can be reduced between prepare & write */
1293             if (wMsg == WODM_WRITE && wh32->dwBufferLength < wh16->dwBufferLength) {
1294                 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
1295                     wh32->dwBufferLength, wh16->dwBufferLength);
1296             } else
1297                 wh32->dwBufferLength = wh16->dwBufferLength;
1298             ret = WINMM_MAP_OKMEM;
1299         }
1300         break;
1301     case WODM_MAPPER_STATUS:
1302         *lpParam2 = (DWORD)MapSL(*lpParam2);
1303         ret = WINMM_MAP_OK;
1304         break;
1305     default:
1306         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1307         break;
1308     }
1309     return ret;
1310 }
1311
1312 /**************************************************************************
1313  *                              MMDRV_WaveOut_UnMap16To32W      [internal]
1314  */
1315 static  WINMM_MapType   MMDRV_WaveOut_UnMap16To32W(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
1316 {
1317     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
1318
1319     switch (wMsg) {
1320     /* nothing to do */
1321     case WODM_BREAKLOOP:
1322     case WODM_CLOSE:
1323     case WODM_GETNUMDEVS:
1324     case WODM_PAUSE:
1325     case WODM_RESET:
1326     case WODM_RESTART:
1327     case WODM_SETPITCH:
1328     case WODM_SETPLAYBACKRATE:
1329     case WODM_SETVOLUME:
1330     case WODM_MAPPER_STATUS:
1331         ret = WINMM_MAP_OK;
1332         break;
1333
1334     case WODM_GETPITCH:
1335     case WODM_GETPLAYBACKRATE:
1336     case WODM_GETVOLUME:
1337     case WODM_OPEN:
1338         FIXME("Shouldn't be used: those 16 bit functions use the 32 bit interface\n");
1339         break;
1340
1341     case WODM_GETDEVCAPS:
1342         {
1343             LPWAVEOUTCAPSW              woc32 = (LPWAVEOUTCAPSW)(*lpParam1);
1344             LPWAVEOUTCAPS16             woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1345
1346             woc16->wMid = woc32->wMid;
1347             woc16->wPid = woc32->wPid;
1348             woc16->vDriverVersion = woc32->vDriverVersion;
1349             WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname,
1350                                  sizeof(woc16->szPname), NULL, NULL );
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_Map32WTo16        [internal]
1398  */
1399 static  WINMM_MapType   MMDRV_WaveOut_Map32WTo16  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* 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             LPWAVEOUTCAPSW woc32 = (LPWAVEOUTCAPSW)*lpParam1;
1420             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0,
1421                                    sizeof(LPWAVEOUTCAPSW) + sizeof(WAVEOUTCAPS16));
1422
1423             if (ptr) {
1424                 *(LPWAVEOUTCAPSW*)ptr = woc32;
1425                 ret = WINMM_MAP_OKMEM;
1426             } else {
1427                 ret = WINMM_MAP_NOMEM;
1428             }
1429             *lpParam1 = MapLS(ptr) + sizeof(LPWAVEOUTCAPSW);
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                 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1531                 *lpParam2 = sizeof(WAVEHDR);
1532                 TRACE("wh16=%08lx wh16->lpData=%p wh32->buflen=%u wh32->lpData=%p\n",
1533                       *lpParam1, wh16->lpData, wh32->dwBufferLength, wh32->lpData);
1534
1535                 ret = WINMM_MAP_OKMEM;
1536             } else {
1537                 ret = WINMM_MAP_NOMEM;
1538             }
1539         }
1540         break;
1541     case WODM_UNPREPARE:
1542     case WODM_WRITE:
1543         {
1544             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
1545             LPWAVEHDR           wh16 = wh32->lpNext;
1546             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1547             SEGPTR seg_ptr = MapLS( ptr );
1548
1549             assert(*(LPWAVEHDR*)ptr == wh32);
1550
1551             if (wMsg == WODM_WRITE)
1552                 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
1553
1554             *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1555             *lpParam2 = sizeof(WAVEHDR);
1556             TRACE("wh16=%08lx wh16->lpData=%p wh32->buflen=%u wh32->lpData=%p\n",
1557                   *lpParam1, wh16->lpData, wh32->dwBufferLength, wh32->lpData);
1558
1559             /* dwBufferLength can be reduced between prepare & write */
1560             if (wMsg == WODM_WRITE && wh16->dwBufferLength < wh32->dwBufferLength) {
1561                 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
1562                     wh16->dwBufferLength, wh32->dwBufferLength);
1563             } else
1564                 wh16->dwBufferLength = wh32->dwBufferLength;
1565             ret = WINMM_MAP_OKMEM;
1566         }
1567         break;
1568     case DRVM_MAPPER_STATUS:
1569         {
1570             LPDWORD p32 = (LPDWORD)*lpParam2;
1571             *lpParam2 = MapLS(p32);
1572             ret = WINMM_MAP_OKMEM;
1573         }
1574         break;
1575     default:
1576         FIXME("NIY: no conversion yet\n");
1577         ret = WINMM_MAP_MSGERROR;
1578         break;
1579     }
1580     return ret;
1581 }
1582
1583 /**************************************************************************
1584  *                              MMDRV_WaveOut_UnMap32WTo16      [internal]
1585  */
1586 static  WINMM_MapType   MMDRV_WaveOut_UnMap32WTo16(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
1587 {
1588     WINMM_MapType       ret;
1589
1590     switch (wMsg) {
1591         /* nothing to do */
1592     case WODM_BREAKLOOP:
1593     case WODM_CLOSE:
1594     case WODM_GETNUMDEVS:
1595     case WODM_PAUSE:
1596     case WODM_RESET:
1597     case WODM_RESTART:
1598     case WODM_SETPITCH:
1599     case WODM_SETPLAYBACKRATE:
1600     case WODM_SETVOLUME:
1601         ret = WINMM_MAP_OK;
1602         break;
1603
1604     case WODM_GETDEVCAPS:
1605         {
1606             LPWAVEOUTCAPS16             woc16 = MapSL(*lpParam1);
1607             LPSTR                       ptr   = (LPSTR)woc16 - sizeof(LPWAVEOUTCAPSW);
1608             LPWAVEOUTCAPSW              woc32 = *(LPWAVEOUTCAPSW*)ptr;
1609
1610             woc32->wMid = woc16->wMid;
1611             woc32->wPid = woc16->wPid;
1612             woc32->vDriverVersion = woc16->vDriverVersion;
1613             WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname,
1614                                  sizeof(woc16->szPname), NULL, NULL );
1615             woc32->dwFormats = woc16->dwFormats;
1616             woc32->wChannels = woc16->wChannels;
1617             woc32->dwSupport = woc16->dwSupport;
1618             UnMapLS( *lpParam1 );
1619             HeapFree( GetProcessHeap(), 0, ptr );
1620             ret = WINMM_MAP_OK;
1621         }
1622         break;
1623     case WODM_GETPITCH:
1624         FIXME("NIY: no conversion yet\n");
1625         ret = WINMM_MAP_MSGERROR;
1626         break;
1627     case WODM_GETPLAYBACKRATE:
1628         FIXME("NIY: no conversion yet\n");
1629         ret = WINMM_MAP_MSGERROR;
1630         break;
1631     case WODM_GETPOS:
1632         {
1633             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1634             LPSTR               ptr   = (LPSTR)mmt16 - sizeof(LPMMTIME);
1635             LPMMTIME            mmt32 = *(LPMMTIME*)ptr;
1636
1637             MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1638             UnMapLS( *lpParam1 );
1639             HeapFree( GetProcessHeap(), 0, ptr );
1640             ret = WINMM_MAP_OK;
1641         }
1642         break;
1643     case WODM_OPEN:
1644         {
1645             LPWAVEOPENDESC16            wod16 = MapSL(*lpParam1);
1646             LPSTR                       ptr   = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1647             LPWAVEOPENDESC              wod32 = *(LPWAVEOPENDESC*)ptr;
1648
1649             wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1650             **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1651             UnMapLS( *lpParam1 );
1652             HeapFree( GetProcessHeap(), 0, ptr );
1653             ret = WINMM_MAP_OK;
1654         }
1655         break;
1656     case WODM_PREPARE:
1657     case WODM_UNPREPARE:
1658     case WODM_WRITE:
1659         {
1660             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1661             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1662             LPWAVEHDR           wh32 = *(LPWAVEHDR*)ptr;
1663
1664             assert(wh32->lpNext == wh16);
1665             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1666             wh32->dwUser = wh16->dwUser;
1667             wh32->dwFlags = wh16->dwFlags;
1668             wh32->dwLoops = wh16->dwLoops;
1669
1670             UnMapLS( *lpParam1 );
1671             if (wMsg == WODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
1672                 HeapFree( GetProcessHeap(), 0, ptr );
1673                 wh32->lpNext = 0;
1674             }
1675             ret = WINMM_MAP_OK;
1676         }
1677         break;
1678     case WODM_GETVOLUME:
1679         FIXME("NIY: no conversion yet\n");
1680         ret = WINMM_MAP_MSGERROR;
1681         break;
1682     case DRVM_MAPPER_STATUS:
1683         {
1684             UnMapLS( *lpParam2 );
1685             ret = WINMM_MAP_OK;
1686         }
1687         break;
1688     default:
1689         FIXME("NIY: no conversion yet\n");
1690         ret = WINMM_MAP_MSGERROR;
1691         break;
1692     }
1693     return ret;
1694 }
1695
1696 /**************************************************************************
1697  *                              MMDRV_WaveOut_Callback          [internal]
1698  */
1699 static  void    CALLBACK MMDRV_WaveOut_Callback(HDRVR hDev, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
1700 {
1701     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
1702
1703     switch (uMsg) {
1704     case WOM_OPEN:
1705     case WOM_CLOSE:
1706         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1707         break;
1708     case WOM_DONE:
1709         if (mld->bFrom32 && !MMDRV_Is32(mld->mmdIndex)) {
1710             /* initial map is: 32 => 16 */
1711             LPWAVEHDR           wh16 = MapSL(dwParam1);
1712             LPWAVEHDR           wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1713
1714             dwParam1 = (DWORD)wh32;
1715             wh32->dwFlags = wh16->dwFlags;
1716         } else if (!mld->bFrom32 && MMDRV_Is32(mld->mmdIndex)) {
1717             /* initial map is: 16 => 32 */
1718             LPWAVEHDR           wh32 = (LPWAVEHDR)(dwParam1);
1719             SEGPTR              segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1720             LPWAVEHDR           wh16 = MapSL(segwh16);
1721
1722             dwParam1 = (DWORD)segwh16;
1723             wh16->dwFlags = wh32->dwFlags;
1724         }
1725         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1726         break;
1727     default:
1728         ERR("Unknown msg %u\n", uMsg);
1729     }
1730
1731     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1732 }
1733
1734 /* =================================
1735  *  M A P P E R S   H A N D L I N G
1736  * ================================= */
1737
1738 static  LRESULT    MMDRV_CallMMDrvFunc16(DWORD fp16, WORD dev, WORD msg, LONG instance,
1739                                          LONG lp1, LONG lp2)
1740 {
1741     WORD args[8];
1742     DWORD ret;
1743
1744     args[7] = dev;
1745     args[6] = msg;
1746     args[5] = HIWORD(instance);
1747     args[4] = LOWORD(instance);
1748     args[3] = HIWORD(lp1);
1749     args[2] = LOWORD(lp1);
1750     args[1] = HIWORD(lp2);
1751     args[0] = LOWORD(lp2);
1752     WOWCallback16Ex( fp16, WCB16_PASCAL, sizeof(args), args, &ret );
1753     return LOWORD(ret);
1754 }
1755
1756 /**************************************************************************
1757  *                              MMDRV_GetDescription16          [internal]
1758  */
1759 static  BOOL    MMDRV_GetDescription16(const char* fname, char* buf, int buflen)
1760 {
1761     OFSTRUCT    ofs;
1762     HFILE       hFile;
1763     WORD        w;
1764     DWORD       dw;
1765     BOOL        ret = FALSE;
1766
1767     if ((hFile = OpenFile(fname, &ofs, OF_READ | OF_SHARE_DENY_WRITE)) == HFILE_ERROR) {
1768         ERR("Can't open file %s (builtin driver ?)\n", fname);
1769         return FALSE;
1770     }
1771
1772 #define E(_x)   do {TRACE _x;goto theEnd;} while(0)
1773
1774     if (_lread(hFile, &w, 2) != 2)                      E(("Can't read sig\n"));
1775     if (w != ('Z' * 256 + 'M'))                         E(("Bad sig %04x\n", w));
1776     if (_llseek(hFile, 0x3C, SEEK_SET) < 0)             E(("Can't seek to ext header offset\n"));
1777     if (_lread(hFile, &dw, 4) != 4)                     E(("Can't read ext header offset\n"));
1778     if (_llseek(hFile, dw + 0x2C, SEEK_SET) < 0)        E(("Can't seek to ext header.nr table %u\n", dw+0x2C));
1779     if (_lread(hFile, &dw, 4) != 4)                     E(("Can't read nr table offset\n"));
1780     if (_llseek(hFile, dw, SEEK_SET) < 0)               E(("Can't seek to nr table %u\n", dw));
1781     if (_lread(hFile, buf, 1) != 1)                     E(("Can't read descr length\n"));
1782     buflen = min((int)(unsigned)(BYTE)buf[0], buflen - 1);
1783     if (_lread(hFile, buf, buflen) != buflen)           E(("Can't read descr (%d)\n", buflen));
1784     buf[buflen] = '\0';
1785     ret = TRUE;
1786     TRACE("Got '%s' [%d]\n", buf, buflen);
1787 theEnd:
1788     _lclose(hFile);
1789     return ret;
1790 }
1791
1792 /******************************************************************
1793  *              MMDRV_LoadMMDrvFunc16
1794  *
1795  */
1796 unsigned   MMDRV_LoadMMDrvFunc16(LPCSTR drvName, LPWINE_DRIVER d, 
1797                                  LPWINE_MM_DRIVER lpDrv)
1798 {        
1799     WINEMM_msgFunc16    func;
1800     unsigned            count = 0;
1801     char                buffer[128];
1802     /*
1803      * DESCRIPTION 'wave,aux,mixer:Creative Labs Sound Blaster 16 Driver'
1804      * The beginning of the module description indicates the driver supports
1805      * waveform, auxiliary, and mixer devices. Use one of the following
1806      * device-type names, followed by a colon (:) to indicate the type of
1807      * device your driver supports. If the driver supports more than one
1808      * type of device, separate each device-type name with a comma (,).
1809      *
1810      * wave for waveform audio devices
1811      * wavemapper for wave mappers
1812      * midi for MIDI audio devices
1813      * midimapper for midi mappers
1814      * aux for auxiliary audio devices
1815      * mixer for mixer devices
1816      */
1817
1818     if (d->d.d16.hDriver16) {
1819         HMODULE16       hMod16 = GetDriverModuleHandle16(d->d.d16.hDriver16);
1820
1821 #define AA(_h,_w,_x,_y,_z)                                      \
1822     func = (WINEMM_msgFunc##_y) _z ((_h), #_x);                 \
1823     if (func != NULL)                                           \
1824         { lpDrv->parts[_w].u.fnMessage##_y = func; count++;     \
1825           TRACE("Got %d bit func '%s'\n", _y, #_x);         }
1826
1827 #define A(_x,_y)        AA(hMod16,_x,_y,16,GetProcAddress16)
1828         A(MMDRV_AUX,    auxMessage);
1829         A(MMDRV_MIXER,  mxdMessage);
1830         A(MMDRV_MIDIIN, midMessage);
1831         A(MMDRV_MIDIOUT,modMessage);
1832         A(MMDRV_WAVEIN, widMessage);
1833         A(MMDRV_WAVEOUT,wodMessage);
1834 #undef A
1835 #undef AA
1836     }
1837     if (TRACE_ON(winmm)) {
1838         if (MMDRV_GetDescription16(drvName, buffer, sizeof(buffer)))
1839             TRACE("%s => %s\n", drvName, buffer);
1840         else
1841             TRACE("%s => No description\n", drvName);
1842     }
1843
1844     return count;
1845 }
1846
1847 /* =================================
1848  *              M C I
1849  * ================================= */
1850
1851 #if 0
1852 /* FIXME: this code is kept for not yet implemented optimisation for an application
1853  * using the 32A MCI interface and calling a 16 bit driver.
1854  * For now, we're doing two conversions:
1855  * - 32A => 32W (in 32 bit MCI code)
1856  * - 32W => 16  in this file
1857  */
1858
1859 /*
1860  * 0000 stop
1861  * 0001 squeeze   signed 4 bytes to 2 bytes     *( LPINT16)D = ( INT16)*( LPINT16)S; D += 2;     S += 4
1862  * 0010 squeeze unsigned 4 bytes to 2 bytes     *(LPUINT16)D = (UINT16)*(LPUINT16)S; D += 2;     S += 4
1863  * 0100
1864  * 0101
1865  * 0110 zero 4 bytes                            *(DWORD)D = 0                        D += 4;     S += 4
1866  * 0111 copy string                             *(LPSTR*)D = seg dup(*(LPSTR*)S)     D += 4;     S += 4
1867  * 1xxx copy xxx + 1 bytes                      memcpy(D, S, xxx + 1);               D += xxx+1; S += xxx+1
1868  */
1869
1870 /**************************************************************************
1871  *                      MCI_MsgMapper32ATo16_Create             [internal]
1872  *
1873  * Helper for MCI_MapMsg32ATo16.
1874  * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit
1875  * segmented pointer.
1876  * map contains a list of action to be performed for the mapping (see list
1877  * above)
1878  * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
1879  */
1880 static  WINMM_MapType   MCI_MsgMapper32ATo16_Create(void** ptr, int size16, DWORD map, BOOLEAN keep)
1881 {
1882     void*       lp = HeapAlloc( GetProcessHeap(), 0, (keep ? sizeof(void**) : 0) + size16 );
1883     LPBYTE      p16, p32;
1884
1885     if (!lp) {
1886         return WINMM_MAP_NOMEM;
1887     }
1888     p32 = (LPBYTE)(*ptr);
1889     if (keep) {
1890         *(void**)lp = *ptr;
1891         p16 = (LPBYTE)lp + sizeof(void**);
1892         *ptr = (char*)MapLS(lp) + sizeof(void**);
1893     } else {
1894         p16 = lp;
1895         *ptr = (void*)MapLS(lp);
1896     }
1897
1898     if (map == 0) {
1899         memcpy(p16, p32, size16);
1900     } else {
1901         unsigned        nibble;
1902         unsigned        sz;
1903
1904         while (map & 0xF) {
1905             nibble = map & 0xF;
1906             if (nibble & 0x8) {
1907                 sz = (nibble & 7) + 1;
1908                 memcpy(p16, p32, sz);
1909                 p16 += sz;
1910                 p32 += sz;
1911                 size16 -= sz;   /* DEBUG only */
1912             } else {
1913                 switch (nibble) {
1914                 case 0x1:
1915                     *(LPINT16)p16 = *(LPINT)p32;
1916                     p16 += sizeof(INT16);
1917                     p32 += sizeof(INT);
1918                     size16 -= sizeof(INT16);
1919                     break;
1920                 case 0x2:
1921                     *(LPUINT16)p16 = *(LPUINT)p32;
1922                     p16 += sizeof(UINT16);
1923                     p32 += sizeof(UINT);
1924                     size16 -= sizeof(UINT16);
1925                     break;
1926                 case 0x6:
1927                     *(LPDWORD)p16 = 0;
1928                     p16 += sizeof(DWORD);
1929                     p32 += sizeof(DWORD);
1930                     size16 -= sizeof(DWORD);
1931                     break;
1932                 case 0x7:
1933                     *(SEGPTR *)p16 = MapLS( *(LPSTR *)p32 );
1934                     p16 += sizeof(SEGPTR);
1935                     p32 += sizeof(LPSTR);
1936                     size16 -= sizeof(SEGPTR);
1937                     break;
1938                 default:
1939                     FIXME("Unknown nibble for mapping (%x)\n", nibble);
1940                 }
1941             }
1942             map >>= 4;
1943         }
1944         if (size16 != 0) /* DEBUG only */
1945             FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
1946     }
1947     return WINMM_MAP_OKMEM;
1948 }
1949
1950 /**************************************************************************
1951  *                      MCI_MsgMapper32ATo16_Destroy            [internal]
1952  *
1953  * Helper for MCI_UnMapMsg32ATo16.
1954  */
1955 static  WINMM_MapType   MCI_MsgMapper32ATo16_Destroy(void* ptr, int size16, DWORD map, BOOLEAN kept)
1956 {
1957     if (ptr) {
1958         void*           msg16 = MapSL((SEGPTR)ptr);
1959         void*           alloc;
1960         LPBYTE          p32, p16;
1961         unsigned        nibble;
1962
1963         UnMapLS( (SEGPTR)ptr );
1964         if (kept) {
1965             alloc = (char*)msg16 - sizeof(void**);
1966             p32 = *(void**)alloc;
1967             p16 = msg16;
1968
1969             if (map == 0) {
1970                 memcpy(p32, p16, size16);
1971             } else {
1972                 while (map & 0xF) {
1973                     nibble = map & 0xF;
1974                     if (nibble & 0x8) {
1975                         memcpy(p32, p16, (nibble & 7) + 1);
1976                         p16 += (nibble & 7) + 1;
1977                         p32 += (nibble & 7) + 1;
1978                         size16 -= (nibble & 7) + 1;
1979                     } else {
1980                         switch (nibble) {
1981                         case 0x1:
1982                             *(LPINT)p32 = *(LPINT16)p16;
1983                             p16 += sizeof(INT16);
1984                             p32 += sizeof(INT);
1985                             size16 -= sizeof(INT16);
1986                             break;
1987                         case 0x2:
1988                             *(LPUINT)p32 = *(LPUINT16)p16;
1989                             p16 += sizeof(UINT16);
1990                             p32 += sizeof(UINT);
1991                             size16 -= sizeof(UINT16);
1992                             break;
1993                         case 0x6:
1994                             p16 += sizeof(UINT);
1995                             p32 += sizeof(UINT);
1996                             size16 -= sizeof(UINT);
1997                             break;
1998                         case 0x7:
1999                             UnMapLS( *(SEGPTR *)p16 );
2000                             p16 += sizeof(SEGPTR);
2001                             p32 += sizeof(char*);
2002                             size16 -= sizeof(SEGPTR);
2003                             break;
2004                         default:
2005                             FIXME("Unknown nibble for mapping (%x)\n", nibble);
2006                         }
2007                     }
2008                     map >>= 4;
2009                 }
2010                 if (size16 != 0) /* DEBUG only */
2011                     FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
2012             }
2013         } else {
2014             alloc = msg16;
2015         }
2016
2017         HeapFree( GetProcessHeap(), 0, alloc );
2018     }
2019     return WINMM_MAP_OK;
2020 }
2021
2022 /**************************************************************************
2023  *                      MCI_MapMsg32ATo16                       [internal]
2024  *
2025  * Map a 32-A bit MCI message to a 16 bit MCI message.
2026  */
2027 static  WINMM_MapType   MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
2028 {
2029     int         size;
2030     BOOLEAN     keep = FALSE;
2031     DWORD       map = 0;
2032
2033     if (*lParam == 0)
2034         return WINMM_MAP_OK;
2035
2036     /* FIXME: to add also (with seg/linear modifications to do):
2037      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
2038      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
2039      */
2040     switch (wMsg) {
2041     case MCI_BREAK:
2042         size = sizeof(MCI_BREAK_PARMS);
2043         break;
2044         /* case MCI_CAPTURE */
2045     case MCI_CLOSE:
2046     case MCI_CLOSE_DRIVER:
2047     case MCI_CONFIGURE:
2048         size = sizeof(MCI_GENERIC_PARMS);
2049         break;
2050         /* case MCI_COPY: */
2051     case MCI_CUE:
2052         switch (uDevType) {
2053         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_CUE_PARMS);       break;
2054         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_CUE_PARMS);     break;*/        FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2055         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2056         }
2057         break;
2058         /* case MCI_CUT:*/
2059     case MCI_DELETE:
2060         switch (uDevType) {
2061         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_DELETE_PARMS16);  map = 0x0F1111FB;       break;
2062         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_DELETE_PARMS);   break;
2063         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2064         }
2065         break;
2066         /* case MCI_ESCAPE: */
2067     case MCI_FREEZE:
2068         switch (uDevType) {
2069         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_FREEZE_PARMS);    map = 0x0001111B;       break;
2070         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
2071         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2072         }
2073         break;
2074     case MCI_GETDEVCAPS:
2075         keep = TRUE;
2076         size = sizeof(MCI_GETDEVCAPS_PARMS);
2077         break;
2078         /* case MCI_INDEX: */
2079     case MCI_INFO:
2080         {
2081             LPMCI_INFO_PARMSA   mip32a = (LPMCI_INFO_PARMSA)(*lParam);
2082             LPMCI_INFO_PARMS16  mip16;
2083
2084             switch (uDevType) {
2085             case MCI_DEVTYPE_DIGITAL_VIDEO:     size = sizeof(MCI_DGV_INFO_PARMS16);    break;
2086             default:                            size = sizeof(MCI_INFO_PARMS16);        break;
2087             }
2088             mip16 = HeapAlloc( GetProcessHeap(), 0, size);
2089             if (mip16)
2090             {
2091                 mip16->dwCallback  = mip32a->dwCallback;
2092                 mip16->lpstrReturn = MapLS( mip32a->lpstrReturn );
2093                 mip16->dwRetSize   = mip32a->dwRetSize;
2094                 if (uDevType == MCI_DEVTYPE_DIGITAL_VIDEO) {
2095                     ((LPMCI_DGV_INFO_PARMS16)mip16)->dwItem = ((LPMCI_DGV_INFO_PARMSA)mip32a)->dwItem;
2096                 }
2097             } else {
2098                 return WINMM_MAP_NOMEM;
2099             }
2100             *lParam = MapLS(mip16);
2101         }
2102         return WINMM_MAP_OKMEM;
2103         /* case MCI_MARK: */
2104         /* case MCI_MONITOR: */
2105     case MCI_OPEN:
2106     case MCI_OPEN_DRIVER:
2107         {
2108             LPMCI_OPEN_PARMSA   mop32a = (LPMCI_OPEN_PARMSA)(*lParam);
2109             char* ptr = HeapAlloc( GetProcessHeap(), 0,
2110                                    sizeof(LPMCI_OPEN_PARMSA) + sizeof(MCI_OPEN_PARMS16) + 2 * sizeof(DWORD));
2111             LPMCI_OPEN_PARMS16  mop16;
2112
2113
2114             if (ptr) {
2115                 *(LPMCI_OPEN_PARMSA*)(ptr) = mop32a;
2116                 mop16 = (LPMCI_OPEN_PARMS16)(ptr + sizeof(LPMCI_OPEN_PARMSA));
2117                 mop16->dwCallback       = mop32a->dwCallback;
2118                 mop16->wDeviceID        = mop32a->wDeviceID;
2119                 if (dwFlags & MCI_OPEN_TYPE) {
2120                     if (dwFlags & MCI_OPEN_TYPE_ID) {
2121                         /* dword "transparent" value */
2122                         mop16->lpstrDeviceType = (SEGPTR)mop32a->lpstrDeviceType;
2123                     } else {
2124                         /* string */
2125                         mop16->lpstrDeviceType = MapLS( mop32a->lpstrDeviceType );
2126                     }
2127                 } else {
2128                     /* nuthin' */
2129                     mop16->lpstrDeviceType = 0;
2130                 }
2131                 if (dwFlags & MCI_OPEN_ELEMENT) {
2132                     if (dwFlags & MCI_OPEN_ELEMENT_ID) {
2133                         mop16->lpstrElementName = (SEGPTR)mop32a->lpstrElementName;
2134                     } else {
2135                         mop16->lpstrElementName = MapLS( mop32a->lpstrElementName );
2136                     }
2137                 } else {
2138                     mop16->lpstrElementName = 0;
2139                 }
2140                 if (dwFlags & MCI_OPEN_ALIAS) {
2141                     mop16->lpstrAlias = MapLS( mop32a->lpstrAlias );
2142                 } else {
2143                     mop16->lpstrAlias = 0;
2144                 }
2145                 /* copy extended information if any...
2146                  * FIXME: this may seg fault if initial structure does not contain them and
2147                  * the reads after msip16 fail under LDT limits...
2148                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
2149                  * should not take care of extended parameters, and should be used by MCI_Open
2150                  * to fetch uDevType. When, this is known, the mapping for sending the
2151                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
2152                  */
2153                 memcpy(mop16 + 1, mop32a + 1, 2 * sizeof(DWORD));
2154             } else {
2155                 return WINMM_MAP_NOMEM;
2156             }
2157             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_PARMSA);
2158         }
2159         return WINMM_MAP_OKMEM;
2160         /* case MCI_PASTE:*/
2161     case MCI_PAUSE:
2162         size = sizeof(MCI_GENERIC_PARMS);
2163         break;
2164     case MCI_PLAY:
2165         size = sizeof(MCI_PLAY_PARMS);
2166         break;
2167     case MCI_PUT:
2168         switch (uDevType) {
2169         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
2170         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
2171         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2172         }
2173         break;
2174     case MCI_REALIZE:
2175         size = sizeof(MCI_GENERIC_PARMS);
2176         break;
2177     case MCI_RECORD:
2178         switch (uDevType) {
2179         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECORD_PARMS16);  map = 0x0F1111FB;       break;
2180         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_RECORD_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2181         default:                        size = sizeof(MCI_RECORD_PARMS);        break;
2182         }
2183         break;
2184     case MCI_RESUME:
2185         size = sizeof(MCI_GENERIC_PARMS);
2186         break;
2187     case MCI_SEEK:
2188         switch (uDevType) {
2189         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SEEK_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2190         default:                        size = sizeof(MCI_SEEK_PARMS);          break;
2191         }
2192         break;
2193     case MCI_SET:
2194         switch (uDevType) {
2195         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SET_PARMS);       break;
2196         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SET_PARMS);     break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2197         case MCI_DEVTYPE_SEQUENCER:     size = sizeof(MCI_SEQ_SET_PARMS);       break;
2198         /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
2199          * so not doing anything should work...
2200          */
2201         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_SET_PARMS);      break;
2202         default:                        size = sizeof(MCI_SET_PARMS);           break;
2203         }
2204         break;
2205     case MCI_SETAUDIO:
2206         switch (uDevType) {
2207         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SETAUDIO_PARMS16);map = 0x0000077FF;      break;
2208         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2209         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2210         }
2211         break;
2212         /* case MCI_SETTIMECODE:*/
2213         /* case MCI_SIGNAL:*/
2214         /* case MCI_SOUND:*/
2215     case MCI_SPIN:
2216         size = sizeof(MCI_SET_PARMS);
2217         break;
2218     case MCI_STATUS:
2219         keep = TRUE;
2220         switch (uDevType) {
2221         /* FIXME:
2222          * don't know if buffer for value is the one passed through lpstrDevice
2223          * or is provided by MCI driver.
2224          * Assuming solution 2: provided by MCI driver, so zeroing on entry
2225          */
2226         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16);  map = 0x0B6FF;          break;
2227         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2228         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
2229         }
2230         break;
2231     case MCI_STEP:
2232         switch (uDevType) {
2233         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STEP_PARMS);      break;
2234         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STEP_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2235         case MCI_DEVTYPE_VIDEODISC:     size = sizeof(MCI_VD_STEP_PARMS);       break;
2236         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2237         }
2238         break;
2239     case MCI_STOP:
2240         size = sizeof(MCI_SET_PARMS);
2241         break;
2242     case MCI_SYSINFO:
2243         {
2244             LPMCI_SYSINFO_PARMSA  msip32a = (LPMCI_SYSINFO_PARMSA)(*lParam);
2245             LPMCI_SYSINFO_PARMS16 msip16;
2246             char* ptr = HeapAlloc( GetProcessHeap(), 0,
2247                                    sizeof(LPMCI_SYSINFO_PARMSA) + sizeof(MCI_SYSINFO_PARMS16) );
2248
2249             if (ptr) {
2250                 *(LPMCI_SYSINFO_PARMSA*)(ptr) = msip32a;
2251                 msip16 = (LPMCI_SYSINFO_PARMS16)(ptr + sizeof(LPMCI_SYSINFO_PARMSA));
2252
2253                 msip16->dwCallback       = msip32a->dwCallback;
2254                 msip16->lpstrReturn      = MapLS( msip32a->lpstrReturn );
2255                 msip16->dwRetSize        = msip32a->dwRetSize;
2256                 msip16->dwNumber         = msip32a->dwNumber;
2257                 msip16->wDeviceType      = msip32a->wDeviceType;
2258             } else {
2259                 return WINMM_MAP_NOMEM;
2260             }
2261             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_SYSINFO_PARMSA);
2262         }
2263         return WINMM_MAP_OKMEM;
2264         /* case MCI_UNDO: */
2265     case MCI_UNFREEZE:
2266         switch (uDevType) {
2267         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
2268         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       break;
2269         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2270         }
2271         break;
2272     case MCI_UPDATE:
2273         switch (uDevType) {
2274         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_UPDATE_PARMS16);  map = 0x000B1111B;      break;
2275         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2276         }
2277         break;
2278     case MCI_WHERE:
2279         switch (uDevType) {
2280         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       keep = TRUE;    break;
2281         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       keep = TRUE;    break;
2282         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2283         }
2284         break;
2285     case MCI_WINDOW:
2286         switch (uDevType) {
2287         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7FB;        break;
2288         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7FB;        break;
2289         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2290         }
2291         break;
2292     case DRV_OPEN:
2293         {
2294             LPMCI_OPEN_DRIVER_PARMSA  modp32a = (LPMCI_OPEN_DRIVER_PARMSA)(*lParam);
2295             LPMCI_OPEN_DRIVER_PARMS16 modp16;
2296             char *ptr = HeapAlloc( GetProcessHeap(), 0,
2297                                    sizeof(LPMCI_OPEN_DRIVER_PARMSA) + sizeof(MCI_OPEN_DRIVER_PARMS16));
2298
2299             if (ptr) {
2300                 *(LPMCI_OPEN_DRIVER_PARMSA*)(ptr) = modp32a;
2301                 modp16 = (LPMCI_OPEN_DRIVER_PARMS16)(ptr + sizeof(LPMCI_OPEN_DRIVER_PARMSA));
2302                 modp16->wDeviceID = modp32a->wDeviceID;
2303                 modp16->lpstrParams = MapLS( modp32a->lpstrParams );
2304                 /* other fields are gonna be filled by the driver, don't copy them */
2305             } else {
2306                 return WINMM_MAP_NOMEM;
2307             }
2308             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_DRIVER_PARMSA);
2309         }
2310         return WINMM_MAP_OKMEM;
2311     case DRV_LOAD:
2312     case DRV_ENABLE:
2313     case DRV_CLOSE:
2314     case DRV_DISABLE:
2315     case DRV_FREE:
2316     case DRV_CONFIGURE:
2317     case DRV_QUERYCONFIGURE:
2318     case DRV_INSTALL:
2319     case DRV_REMOVE:
2320     case DRV_EXITSESSION:
2321     case DRV_EXITAPPLICATION:
2322     case DRV_POWER:
2323         return WINMM_MAP_OK;
2324
2325     default:
2326         FIXME("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
2327         return WINMM_MAP_MSGERROR;
2328     }
2329     return MCI_MsgMapper32ATo16_Create((void**)lParam, size, map, keep);
2330 }
2331
2332 /**************************************************************************
2333  *                      MCI_UnMapMsg32ATo16                     [internal]
2334  */
2335 static  WINMM_MapType   MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
2336 {
2337     int         size = 0;
2338     BOOLEAN     kept = FALSE;   /* there is no need to compute size when kept is FALSE */
2339     DWORD       map = 0;
2340
2341     switch (wMsg) {
2342     case MCI_BREAK:
2343         break;
2344         /* case MCI_CAPTURE */
2345     case MCI_CLOSE:
2346     case MCI_CLOSE_DRIVER:
2347     case MCI_CONFIGURE:
2348         break;
2349         /* case MCI_COPY: */
2350     case MCI_CUE:
2351         break;
2352         /* case MCI_CUT: */
2353     case MCI_DELETE:
2354         break;
2355         /* case MCI_ESCAPE: */
2356     case MCI_FREEZE:
2357         break;
2358     case MCI_GETDEVCAPS:
2359         kept = TRUE;
2360         size = sizeof(MCI_GETDEVCAPS_PARMS);
2361         break;
2362         /* case MCI_INDEX: */
2363     case MCI_INFO:
2364         {
2365             LPMCI_INFO_PARMS16 mip16  = (LPMCI_INFO_PARMS16)MapSL(lParam);
2366             UnMapLS( lParam );
2367             UnMapLS( mip16->lpstrReturn );
2368             HeapFree( GetProcessHeap(), 0, mip16 );
2369         }
2370         return WINMM_MAP_OK;
2371         /* case MCI_MARK: */
2372         /* case MCI_MONITOR: */
2373     case MCI_OPEN:
2374     case MCI_OPEN_DRIVER:
2375         if (lParam) {
2376             LPMCI_OPEN_PARMS16  mop16  = (LPMCI_OPEN_PARMS16)MapSL(lParam);
2377             LPMCI_OPEN_PARMSA   mop32a = *(LPMCI_OPEN_PARMSA*)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSA));
2378             UnMapLS( lParam );
2379             mop32a->wDeviceID = mop16->wDeviceID;
2380             if ((dwFlags & MCI_OPEN_TYPE) && !(dwFlags & MCI_OPEN_TYPE_ID))
2381                 UnMapLS( mop16->lpstrDeviceType );
2382             if ((dwFlags & MCI_OPEN_ELEMENT) && !(dwFlags & MCI_OPEN_ELEMENT_ID))
2383                 UnMapLS( mop16->lpstrElementName );
2384             if (dwFlags & MCI_OPEN_ALIAS)
2385                 UnMapLS( mop16->lpstrAlias );
2386             HeapFree( GetProcessHeap(), 0, (char*)mop16 - sizeof(LPMCI_OPEN_PARMSA) );
2387         }
2388         return WINMM_MAP_OK;
2389         /* case MCI_PASTE:*/
2390     case MCI_PAUSE:
2391         break;
2392     case MCI_PLAY:
2393         break;
2394     case MCI_PUT:
2395         break;
2396     case MCI_REALIZE:
2397         break;
2398     case MCI_RECORD:
2399         break;
2400     case MCI_RESUME:
2401         break;
2402     case MCI_SEEK:
2403         break;
2404     case MCI_SET:
2405         break;
2406     case MCI_SETAUDIO:
2407         switch (uDevType) {
2408         case MCI_DEVTYPE_DIGITAL_VIDEO: map = 0x0000077FF;      break;
2409         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2410         }
2411         break;
2412         /* case MCI_SETTIMECODE:*/
2413         /* case MCI_SIGNAL:*/
2414         /* case MCI_SOUND:*/
2415     case MCI_SPIN:
2416         break;
2417     case MCI_STATUS:
2418         kept = TRUE;
2419         switch (uDevType) {
2420         case MCI_DEVTYPE_DIGITAL_VIDEO:
2421         if (lParam) {
2422             LPMCI_DGV_STATUS_PARMS16    mdsp16  = (LPMCI_DGV_STATUS_PARMS16)MapSL(lParam);
2423             LPMCI_DGV_STATUS_PARMSA     mdsp32a = *(LPMCI_DGV_STATUS_PARMSA*)((char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA));
2424
2425             UnMapLS( lParam );
2426             if (mdsp16) {
2427                 mdsp32a->dwReturn = mdsp16->dwReturn;
2428                 if (dwFlags & MCI_DGV_STATUS_DISKSPACE) {
2429                     TRACE("MCI_STATUS (DGV) lpstrDrive=%08lx\n", mdsp16->lpstrDrive);
2430                     TRACE("MCI_STATUS (DGV) lpstrDrive=%s\n", (LPSTR)MapSL(mdsp16->lpstrDrive));
2431                     UnMapLS( mdsp16->lpstrDrive );
2432                 }
2433                 HeapFree( GetProcessHeap(), 0, (char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA) );
2434             } else {
2435                 return WINMM_MAP_NOMEM;
2436             }
2437         }
2438         return WINMM_MAP_OKMEM;
2439         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2440         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
2441         }
2442         break;
2443     case MCI_STEP:
2444         break;
2445     case MCI_STOP:
2446         break;
2447     case MCI_SYSINFO:
2448         if (lParam) {
2449             LPMCI_SYSINFO_PARMS16       msip16  = (LPMCI_SYSINFO_PARMS16)MapSL(lParam);
2450             LPMCI_SYSINFO_PARMSA        msip32a = *(LPMCI_SYSINFO_PARMSA*)((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA));
2451
2452             UnMapLS( lParam );
2453             if (msip16) {
2454                 msip16->dwCallback = msip32a->dwCallback;
2455                 UnMapLS( msip16->lpstrReturn );
2456                 HeapFree( GetProcessHeap(), 0, (char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA) );
2457             } else {
2458                 return WINMM_MAP_NOMEM;
2459             }
2460         }
2461         return WINMM_MAP_OKMEM;
2462         /* case MCI_UNDO: */
2463     case MCI_UNFREEZE:
2464         break;
2465     case MCI_UPDATE:
2466         break;
2467     case MCI_WHERE:
2468         switch (uDevType) {
2469         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       kept = TRUE;    break;
2470         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       kept = TRUE;    break;
2471         default:                        break;
2472         }
2473         break;
2474     case MCI_WINDOW:
2475         switch (uDevType) {
2476         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7666;       break;
2477         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7666;       break;
2478         default:                        break;
2479         }
2480         /* FIXME: see map function */
2481         break;
2482
2483     case DRV_OPEN:
2484         if (lParam) {
2485             LPMCI_OPEN_DRIVER_PARMS16   modp16  = (LPMCI_OPEN_DRIVER_PARMS16)MapSL(lParam);
2486             LPMCI_OPEN_DRIVER_PARMSA    modp32a = *(LPMCI_OPEN_DRIVER_PARMSA*)((char*)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSA));
2487
2488             UnMapLS( lParam );
2489             modp32a->wCustomCommandTable = modp16->wCustomCommandTable;
2490             modp32a->wType = modp16->wType;
2491             UnMapLS( modp16->lpstrParams );
2492             HeapFree( GetProcessHeap(), 0, (char *)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSA) );
2493         }
2494         return WINMM_MAP_OK;
2495     case DRV_LOAD:
2496     case DRV_ENABLE:
2497     case DRV_CLOSE:
2498     case DRV_DISABLE:
2499     case DRV_FREE:
2500     case DRV_CONFIGURE:
2501     case DRV_QUERYCONFIGURE:
2502     case DRV_INSTALL:
2503     case DRV_REMOVE:
2504     case DRV_EXITSESSION:
2505     case DRV_EXITAPPLICATION:
2506     case DRV_POWER:
2507         FIXME("This is a hack\n");
2508         return WINMM_MAP_OK;
2509     default:
2510         FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
2511         return WINMM_MAP_MSGERROR;
2512     }
2513     return MCI_MsgMapper32ATo16_Destroy((void*)lParam, size, map, kept);
2514 }
2515 #endif
2516
2517 /**************************************************************************
2518  *                      MCI_MapMsg16To32W                       [internal]
2519  */
2520 static WINMM_MapType    MCI_MapMsg16To32W(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD_PTR* lParam)
2521 {
2522     if (*lParam == 0)
2523         return WINMM_MAP_OK;
2524     /* FIXME: to add also (with seg/linear modifications to do):
2525      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
2526      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
2527      */
2528     switch (wMsg) {
2529         /* case MCI_CAPTURE */
2530     case MCI_CLOSE:
2531     case MCI_CLOSE_DRIVER:
2532     case MCI_CONFIGURE:
2533     case MCI_COPY:
2534     case MCI_CUE:
2535     case MCI_CUT:
2536     case MCI_DELETE:
2537     case MCI_FREEZE:
2538     case MCI_GETDEVCAPS:
2539         /* case MCI_INDEX: */
2540         /* case MCI_MARK: */
2541         /* case MCI_MONITOR: */
2542     case MCI_PASTE:
2543     case MCI_PAUSE:
2544     case MCI_PLAY:
2545     case MCI_PUT:
2546     case MCI_REALIZE:
2547     case MCI_RECORD:
2548     case MCI_RESUME:
2549     case MCI_SEEK:
2550     case MCI_SET:
2551         /* case MCI_SETTIMECODE:*/
2552         /* case MCI_SIGNAL:*/
2553     case MCI_SPIN:
2554     case MCI_STATUS:            /* FIXME: is wrong for digital video */
2555     case MCI_STEP:
2556     case MCI_STOP:
2557         /* case MCI_UNDO: */
2558     case MCI_UNFREEZE:
2559     case MCI_UPDATE:
2560     case MCI_WHERE:
2561         *lParam = (DWORD)MapSL(*lParam);
2562         return WINMM_MAP_OK;
2563     case MCI_WINDOW:
2564         /* in fact, I would also need the dwFlags... to see
2565          * which members of lParam are effectively used
2566          */
2567         *lParam = (DWORD)MapSL(*lParam);
2568         FIXME("Current mapping may be wrong\n");
2569         break;
2570     case MCI_BREAK:
2571         {
2572             LPMCI_BREAK_PARMS           mbp32 = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_BREAK_PARMS));
2573             LPMCI_BREAK_PARMS16         mbp16 = MapSL(*lParam);
2574
2575             if (mbp32) {
2576                 mbp32->dwCallback = mbp16->dwCallback;
2577                 mbp32->nVirtKey = mbp16->nVirtKey;
2578                 mbp32->hwndBreak = HWND_32(mbp16->hwndBreak);
2579             } else {
2580                 return WINMM_MAP_NOMEM;
2581             }
2582             *lParam = (DWORD)mbp32;
2583         }
2584         return WINMM_MAP_OKMEM;
2585     case MCI_ESCAPE:
2586         {
2587             LPMCI_VD_ESCAPE_PARMSW      mvep32w = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_VD_ESCAPE_PARMSW));
2588             LPMCI_VD_ESCAPE_PARMS16     mvep16  = MapSL(*lParam);
2589
2590             if (mvep32w) {
2591                 mvep32w->dwCallback       = mvep16->dwCallback;
2592                 mvep32w->lpstrCommand     = MCI_strdupAtoW(MapSL(mvep16->lpstrCommand));
2593             } else {
2594                 return WINMM_MAP_NOMEM;
2595             }
2596             *lParam = (DWORD)mvep32w;
2597         }
2598         return WINMM_MAP_OKMEM;
2599     case MCI_INFO:
2600         {
2601             LPMCI_INFO_PARMSW   mip32w = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_INFO_PARMSW));
2602             LPMCI_INFO_PARMS16  mip16  = MapSL(*lParam);
2603
2604             /* FIXME this is wrong if device is of type
2605              * MCI_DEVTYPE_DIGITAL_VIDEO, some members are not mapped
2606              */
2607             if (mip32w) {
2608                 *(LPMCI_INFO_PARMS16*)(mip32w) = mip16;
2609                 mip32w = (LPMCI_INFO_PARMSW)((char*)mip32w + sizeof(LPMCI_INFO_PARMS16));
2610                 mip32w->dwCallback  = mip16->dwCallback;
2611                 mip32w->lpstrReturn = HeapAlloc(GetProcessHeap(), 0, mip16->dwRetSize * sizeof(WCHAR));
2612                 mip32w->dwRetSize   = mip16->dwRetSize * sizeof(WCHAR);
2613             } else {
2614                 return WINMM_MAP_NOMEM;
2615             }
2616             *lParam = (DWORD)mip32w;
2617         }
2618         return WINMM_MAP_OKMEM;
2619     case MCI_OPEN:
2620     case MCI_OPEN_DRIVER:
2621         {
2622             LPMCI_OPEN_PARMSW   mop32w = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_OPEN_PARMSW) + 2 * sizeof(DWORD));
2623             LPMCI_OPEN_PARMS16  mop16  = MapSL(*lParam);
2624
2625             if (mop32w) {
2626                 *(LPMCI_OPEN_PARMS16*)(mop32w) = mop16;
2627                 mop32w = (LPMCI_OPEN_PARMSW)((char*)mop32w + sizeof(LPMCI_OPEN_PARMS16));
2628                 mop32w->dwCallback       = mop16->dwCallback;
2629                 mop32w->wDeviceID        = mop16->wDeviceID;
2630                 if( ( dwFlags & ( MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID)) == MCI_OPEN_TYPE)
2631                     mop32w->lpstrDeviceType  = MCI_strdupAtoW(MapSL(mop16->lpstrDeviceType));
2632                 else
2633                     mop32w->lpstrDeviceType  = (LPWSTR) mop16->lpstrDeviceType;
2634                 if( ( dwFlags & ( MCI_OPEN_ELEMENT | MCI_OPEN_ELEMENT_ID)) == MCI_OPEN_ELEMENT)
2635                     mop32w->lpstrElementName = MCI_strdupAtoW(MapSL(mop16->lpstrElementName));
2636                 else
2637                     mop32w->lpstrElementName = (LPWSTR) mop16->lpstrElementName;
2638                 if( ( dwFlags &  MCI_OPEN_ALIAS))
2639                     mop32w->lpstrAlias = MCI_strdupAtoW(MapSL(mop16->lpstrAlias));
2640                 else
2641                     mop32w->lpstrAlias = (LPWSTR) mop16->lpstrAlias;
2642                 /* copy extended information if any...
2643                  * FIXME: this may seg fault if initial structure does not contain them and
2644                  * the reads after msip16 fail under LDT limits...
2645                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
2646                  * should not take care of extended parameters, and should be used by MCI_Open
2647                  * to fetch uDevType. When, this is known, the mapping for sending the
2648                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
2649                  */
2650                 memcpy(mop32w + 1, mop16 + 1, 2 * sizeof(DWORD));
2651             } else {
2652                 return WINMM_MAP_NOMEM;
2653             }
2654             *lParam = (DWORD)mop32w;
2655         }
2656         return WINMM_MAP_OKMEM;
2657     case MCI_SYSINFO:
2658         {
2659             LPMCI_SYSINFO_PARMSW        msip32w = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_SYSINFO_PARMSW));
2660             LPMCI_SYSINFO_PARMS16       msip16  = MapSL(*lParam);
2661
2662             if (msip32w) {
2663                 *(LPMCI_SYSINFO_PARMS16*)(msip32w) = msip16;
2664                 msip32w = (LPMCI_SYSINFO_PARMSW)((char*)msip32w + sizeof(LPMCI_OPEN_PARMS16));
2665                 msip32w->dwCallback       = msip16->dwCallback;
2666                 msip32w->lpstrReturn      = HeapAlloc(GetProcessHeap(), 0, msip16->dwRetSize * sizeof(WCHAR));
2667                 msip32w->dwRetSize        = msip16->dwRetSize;
2668                 msip32w->dwNumber         = msip16->dwNumber;
2669                 msip32w->wDeviceType      = msip16->wDeviceType;
2670             } else {
2671                 return WINMM_MAP_NOMEM;
2672             }
2673             *lParam = (DWORD)msip32w;
2674         }
2675         return WINMM_MAP_OKMEM;
2676     case MCI_SOUND:
2677         {
2678             LPMCI_SOUND_PARMSW          mbp32 = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_SOUND_PARMSW));
2679             LPMCI_SOUND_PARMS16         mbp16 = MapSL(*lParam);
2680
2681             if (mbp32) {
2682                 mbp32->dwCallback = mbp16->dwCallback;
2683                 mbp32->lpstrSoundName = MCI_strdupAtoW(MapSL(mbp16->lpstrSoundName));
2684             } else {
2685                 return WINMM_MAP_NOMEM;
2686             }
2687             *lParam = (DWORD)mbp32;
2688         }
2689         return WINMM_MAP_OKMEM;
2690     case DRV_LOAD:
2691     case DRV_ENABLE:
2692     case DRV_OPEN:
2693     case DRV_CLOSE:
2694     case DRV_DISABLE:
2695     case DRV_FREE:
2696     case DRV_CONFIGURE:
2697     case DRV_QUERYCONFIGURE:
2698     case DRV_INSTALL:
2699     case DRV_REMOVE:
2700     case DRV_EXITSESSION:
2701     case DRV_EXITAPPLICATION:
2702     case DRV_POWER:
2703         FIXME("This is a hack\n");
2704         return WINMM_MAP_OK;
2705     default:
2706         FIXME("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
2707     }
2708     return WINMM_MAP_MSGERROR;
2709 }
2710
2711 /**************************************************************************
2712  *                      MCI_UnMapMsg16To32W                     [internal]
2713  */
2714 static  WINMM_MapType   MCI_UnMapMsg16To32W(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD_PTR lParam)
2715 {
2716     switch (wMsg) {
2717         /* case MCI_CAPTURE */
2718     case MCI_CLOSE:
2719     case MCI_CLOSE_DRIVER:
2720     case MCI_CONFIGURE:
2721     case MCI_COPY:
2722     case MCI_CUE:
2723     case MCI_CUT:
2724     case MCI_DELETE:
2725     case MCI_FREEZE:
2726     case MCI_GETDEVCAPS:
2727         /* case MCI_INDEX: */
2728         /* case MCI_MARK: */
2729         /* case MCI_MONITOR: */
2730     case MCI_PASTE:
2731     case MCI_PAUSE:
2732     case MCI_PLAY:
2733     case MCI_PUT:
2734     case MCI_REALIZE:
2735     case MCI_RECORD:
2736     case MCI_RESUME:
2737     case MCI_SEEK:
2738     case MCI_SET:
2739         /* case MCI_SETTIMECODE:*/
2740         /* case MCI_SIGNAL:*/
2741     case MCI_SPIN:
2742     case MCI_STATUS:
2743     case MCI_STEP:
2744     case MCI_STOP:
2745         /* case MCI_UNDO: */
2746     case MCI_UNFREEZE:
2747     case MCI_UPDATE:
2748     case MCI_WHERE:
2749         return WINMM_MAP_OK;
2750
2751     case MCI_WINDOW:
2752         /* FIXME ?? see Map function */
2753         return WINMM_MAP_OK;
2754
2755     case MCI_BREAK:
2756         HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2757         return WINMM_MAP_OK;
2758     case MCI_ESCAPE:
2759         if (lParam) {
2760             LPMCI_VD_ESCAPE_PARMSW      mvep32W = (LPMCI_VD_ESCAPE_PARMSW)lParam;
2761             HeapFree(GetProcessHeap(), 0, (LPVOID)mvep32W->lpstrCommand);
2762             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2763         }
2764         return WINMM_MAP_OK;
2765     case MCI_INFO:
2766         if (lParam) {
2767             LPMCI_INFO_PARMSW           mip32w = (LPMCI_INFO_PARMSW)lParam;
2768             LPMCI_INFO_PARMS16          mip16  = *(LPMCI_INFO_PARMS16*)((char*)mip32w - sizeof(LPMCI_INFO_PARMS16));
2769
2770             WideCharToMultiByte(CP_ACP, 0,
2771                                 mip32w->lpstrReturn, mip32w->dwRetSize / sizeof(WCHAR),
2772                                 MapSL(mip16->lpstrReturn), mip16->dwRetSize,
2773                                 NULL, NULL);
2774             HeapFree(GetProcessHeap(), 0, (LPVOID)mip32w->lpstrReturn);
2775             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2776         }
2777         return WINMM_MAP_OK;
2778     case MCI_SYSINFO:
2779         if (lParam) {
2780             LPMCI_SYSINFO_PARMSW           msip32w = (LPMCI_SYSINFO_PARMSW)lParam;
2781             LPMCI_SYSINFO_PARMS16          msip16  = *(LPMCI_SYSINFO_PARMS16*)((char*)msip32w - sizeof(LPMCI_SYSINFO_PARMS16));
2782
2783             WideCharToMultiByte(CP_ACP, 0,
2784                                 msip32w->lpstrReturn, msip32w->dwRetSize,
2785                                 MapSL(msip16->lpstrReturn), msip16->dwRetSize,
2786                                 NULL, NULL);
2787             HeapFree(GetProcessHeap(), 0, (LPVOID)msip32w->lpstrReturn);
2788             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2789         }
2790         return WINMM_MAP_OK;
2791     case MCI_SOUND:
2792         if (lParam) {
2793             LPMCI_SOUND_PARMSW          msp32W = (LPMCI_SOUND_PARMSW)lParam;
2794             HeapFree(GetProcessHeap(), 0, (LPVOID)msp32W->lpstrSoundName);
2795             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2796         }
2797         return WINMM_MAP_OK;
2798     case MCI_OPEN:
2799     case MCI_OPEN_DRIVER:
2800         if (lParam) {
2801             LPMCI_OPEN_PARMSW   mop32w = (LPMCI_OPEN_PARMSW)lParam;
2802             LPMCI_OPEN_PARMS16  mop16  = *(LPMCI_OPEN_PARMS16*)((char*)mop32w - sizeof(LPMCI_OPEN_PARMS16));
2803
2804             mop16->wDeviceID = mop32w->wDeviceID;
2805             if( ( dwFlags & ( MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID)) == MCI_OPEN_TYPE)
2806                 HeapFree(GetProcessHeap(), 0, (LPWSTR)mop32w->lpstrDeviceType);
2807             if( ( dwFlags & ( MCI_OPEN_ELEMENT | MCI_OPEN_ELEMENT_ID)) == MCI_OPEN_ELEMENT)
2808                 HeapFree(GetProcessHeap(), 0, (LPWSTR)mop32w->lpstrElementName);
2809             if( ( dwFlags &  MCI_OPEN_ALIAS))
2810                 HeapFree(GetProcessHeap(), 0, (LPWSTR)mop32w->lpstrAlias);
2811             if (!HeapFree(GetProcessHeap(), 0, (LPVOID)(lParam - sizeof(LPMCI_OPEN_PARMS16))))
2812                 FIXME("bad free line=%d\n", __LINE__);
2813         }
2814         return WINMM_MAP_OK;
2815     case DRV_LOAD:
2816     case DRV_ENABLE:
2817     case DRV_OPEN:
2818     case DRV_CLOSE:
2819     case DRV_DISABLE:
2820     case DRV_FREE:
2821     case DRV_CONFIGURE:
2822     case DRV_QUERYCONFIGURE:
2823     case DRV_INSTALL:
2824     case DRV_REMOVE:
2825     case DRV_EXITSESSION:
2826     case DRV_EXITAPPLICATION:
2827     case DRV_POWER:
2828         FIXME("This is a hack\n");
2829         return WINMM_MAP_OK;
2830     default:
2831         FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
2832     }
2833     return WINMM_MAP_MSGERROR;
2834 }
2835
2836 /*
2837  * 0000 stop
2838  * 0001 squeeze   signed 4 bytes to 2 bytes     *( LPINT16)D = ( INT16)*( LPINT16)S; D += 2;     S += 4
2839  * 0010 squeeze unsigned 4 bytes to 2 bytes     *(LPUINT16)D = (UINT16)*(LPUINT16)S; D += 2;     S += 4
2840  * 0100
2841  * 0101
2842  * 0110 zero 4 bytes                            *(DWORD)D = 0                        D += 4;     S += 4
2843  * 0111 copy string                             *(LPSTR*)D = seg dup(*(LPSTR*)S)     D += 4;     S += 4
2844  * 1xxx copy xxx + 1 bytes                      memcpy(D, S, xxx + 1);               D += xxx+1; S += xxx+1
2845  */
2846
2847 /**************************************************************************
2848  *                      MCI_MsgMapper32WTo16_Create             [internal]
2849  *
2850  * Helper for MCI_MapMsg32WTo16.
2851  * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit
2852  * segmented pointer.
2853  * map contains a list of action to be performed for the mapping (see list
2854  * above)
2855  * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
2856  */
2857 static  WINMM_MapType   MCI_MsgMapper32WTo16_Create(void** ptr, int size16, DWORD map, BOOLEAN keep)
2858 {
2859     void*       lp = HeapAlloc( GetProcessHeap(), 0, (keep ? sizeof(void**) : 0) + size16 );
2860     LPBYTE      p16, p32;
2861
2862     if (!lp) {
2863         return WINMM_MAP_NOMEM;
2864     }
2865     p32 = (LPBYTE)(*ptr);
2866     if (keep) {
2867         *(void**)lp = *ptr;
2868         p16 = (LPBYTE)lp + sizeof(void**);
2869         *ptr = (char*)MapLS(lp) + sizeof(void**);
2870     } else {
2871         p16 = lp;
2872         *ptr = (void*)MapLS(lp);
2873     }
2874
2875     if (map == 0) {
2876         memcpy(p16, p32, size16);
2877     } else {
2878         unsigned        nibble;
2879         unsigned        sz;
2880
2881         while (map & 0xF) {
2882             nibble = map & 0xF;
2883             if (nibble & 0x8) {
2884                 sz = (nibble & 7) + 1;
2885                 memcpy(p16, p32, sz);
2886                 p16 += sz;
2887                 p32 += sz;
2888                 size16 -= sz;   /* DEBUG only */
2889             } else {
2890                 switch (nibble) {
2891                 case 0x1:
2892                     *(LPINT16)p16 = *(LPINT)p32;
2893                     p16 += sizeof(INT16);
2894                     p32 += sizeof(INT);
2895                     size16 -= sizeof(INT16);
2896                     break;
2897                 case 0x2:
2898                     *(LPUINT16)p16 = *(LPUINT)p32;
2899                     p16 += sizeof(UINT16);
2900                     p32 += sizeof(UINT);
2901                     size16 -= sizeof(UINT16);
2902                     break;
2903                 case 0x6:
2904                     *(LPDWORD)p16 = 0;
2905                     p16 += sizeof(DWORD);
2906                     p32 += sizeof(DWORD);
2907                     size16 -= sizeof(DWORD);
2908                     break;
2909                 case 0x7:
2910                     *(SEGPTR *)p16 = MapLS( MCI_strdupWtoA( *(LPCWSTR *)p32 ) );
2911                     p16 += sizeof(SEGPTR);
2912                     p32 += sizeof(LPSTR);
2913                     size16 -= sizeof(SEGPTR);
2914                     break;
2915                 default:
2916                     FIXME("Unknown nibble for mapping (%x)\n", nibble);
2917                 }
2918             }
2919             map >>= 4;
2920         }
2921         if (size16 != 0) /* DEBUG only */
2922             FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
2923     }
2924     return WINMM_MAP_OKMEM;
2925 }
2926
2927 /**************************************************************************
2928  *                      MCI_MsgMapper32WTo16_Destroy            [internal]
2929  *
2930  * Helper for MCI_UnMapMsg32WTo16.
2931  */
2932 static  WINMM_MapType   MCI_MsgMapper32WTo16_Destroy(void* ptr, int size16, DWORD map, BOOLEAN kept)
2933 {
2934     if (ptr) {
2935         void*           msg16 = MapSL((SEGPTR)ptr);
2936         void*           alloc;
2937         LPBYTE          p32, p16;
2938         unsigned        nibble;
2939
2940         UnMapLS( (SEGPTR)ptr );
2941         if (kept) {
2942             alloc = (char*)msg16 - sizeof(void**);
2943             p32 = *(void**)alloc;
2944             p16 = msg16;
2945
2946             if (map == 0) {
2947                 memcpy(p32, p16, size16);
2948             } else {
2949                 while (map & 0xF) {
2950                     nibble = map & 0xF;
2951                     if (nibble & 0x8) {
2952                         memcpy(p32, p16, (nibble & 7) + 1);
2953                         p16 += (nibble & 7) + 1;
2954                         p32 += (nibble & 7) + 1;
2955                         size16 -= (nibble & 7) + 1;
2956                     } else {
2957                         switch (nibble) {
2958                         case 0x1:
2959                             *(LPINT)p32 = *(LPINT16)p16;
2960                             p16 += sizeof(INT16);
2961                             p32 += sizeof(INT);
2962                             size16 -= sizeof(INT16);
2963                             break;
2964                         case 0x2:
2965                             *(LPUINT)p32 = *(LPUINT16)p16;
2966                             p16 += sizeof(UINT16);
2967                             p32 += sizeof(UINT);
2968                             size16 -= sizeof(UINT16);
2969                             break;
2970                         case 0x6:
2971                             p16 += sizeof(UINT);
2972                             p32 += sizeof(UINT);
2973                             size16 -= sizeof(UINT);
2974                             break;
2975                         case 0x7:
2976                             HeapFree(GetProcessHeap(), 0, MapSL(*(SEGPTR *)p16));
2977                             UnMapLS( *(SEGPTR *)p16 );
2978                             p16 += sizeof(SEGPTR);
2979                             p32 += sizeof(char*);
2980                             size16 -= sizeof(SEGPTR);
2981                             break;
2982                         default:
2983                             FIXME("Unknown nibble for mapping (%x)\n", nibble);
2984                         }
2985                     }
2986                     map >>= 4;
2987                 }
2988                 if (size16 != 0) /* DEBUG only */
2989                     FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
2990             }
2991         } else {
2992             alloc = msg16;
2993         }
2994
2995         HeapFree( GetProcessHeap(), 0, alloc );
2996     }
2997     return WINMM_MAP_OK;
2998 }
2999
3000 /**************************************************************************
3001  *                      MCI_MapMsg32WTo16                       [internal]
3002  *
3003  * Map a 32W bit MCI message to a 16 bit MCI message.
3004  */
3005 static  WINMM_MapType   MCI_MapMsg32WTo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD_PTR* lParam)
3006 {
3007     int         size;
3008     BOOLEAN     keep = FALSE;
3009     DWORD       map = 0;
3010
3011     if (*lParam == 0)
3012         return WINMM_MAP_OK;
3013
3014     /* FIXME: to add also (with seg/linear modifications to do):
3015      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
3016      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
3017      */
3018     switch (wMsg) {
3019     case MCI_BREAK:
3020         size = sizeof(MCI_BREAK_PARMS);
3021         break;
3022         /* case MCI_CAPTURE */
3023     case MCI_CLOSE:
3024     case MCI_CLOSE_DRIVER:
3025     case MCI_CONFIGURE:
3026         size = sizeof(MCI_GENERIC_PARMS);
3027         break;
3028         /* case MCI_COPY: */
3029     case MCI_CUE:
3030         switch (uDevType) {
3031         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_CUE_PARMS);       break;
3032         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_CUE_PARMS);     break;*/        FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3033         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3034         }
3035         break;
3036         /* case MCI_CUT:*/
3037     case MCI_DELETE:
3038         switch (uDevType) {
3039         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_DELETE_PARMS16);  map = 0x0F1111FB;       break;
3040         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_DELETE_PARMS);   break;
3041         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3042         }
3043         break;
3044         /* case MCI_ESCAPE: */
3045     case MCI_FREEZE:
3046         switch (uDevType) {
3047         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_FREEZE_PARMS);    map = 0x0001111B;       break;
3048         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
3049         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3050         }
3051         break;
3052     case MCI_GETDEVCAPS:
3053         keep = TRUE;
3054         size = sizeof(MCI_GETDEVCAPS_PARMS);
3055         break;
3056         /* case MCI_INDEX: */
3057     case MCI_INFO:
3058         {
3059             LPMCI_INFO_PARMSW   mip32w = (LPMCI_INFO_PARMSW)(*lParam);
3060             char*               ptr;
3061             LPMCI_INFO_PARMS16  mip16;
3062
3063             switch (uDevType) {
3064             case MCI_DEVTYPE_DIGITAL_VIDEO:     size = sizeof(MCI_DGV_INFO_PARMS16);    break;
3065             default:                            size = sizeof(MCI_INFO_PARMS16);        break;
3066             }
3067             ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMCI_INFO_PARMSW) + size);
3068             if (ptr)
3069             {
3070                 *(LPMCI_INFO_PARMSW*)ptr = mip32w;
3071                 mip16 = (LPMCI_INFO_PARMS16)(ptr + sizeof(LPMCI_INFO_PARMSW));
3072                 mip16->dwCallback  = mip32w->dwCallback;
3073                 mip16->lpstrReturn = MapLS( HeapAlloc(GetProcessHeap(), 0, mip32w->dwRetSize / sizeof(WCHAR)) );
3074                 mip16->dwRetSize   = mip32w->dwRetSize / sizeof(WCHAR);
3075                 if (uDevType == MCI_DEVTYPE_DIGITAL_VIDEO) {
3076                     ((LPMCI_DGV_INFO_PARMS16)mip16)->dwItem = ((LPMCI_DGV_INFO_PARMSW)mip32w)->dwItem;
3077                 }
3078             } else {
3079                 return WINMM_MAP_NOMEM;
3080             }
3081             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_INFO_PARMSW);
3082         }
3083         return WINMM_MAP_OKMEM;
3084         /* case MCI_MARK: */
3085         /* case MCI_MONITOR: */
3086     case MCI_OPEN:
3087     case MCI_OPEN_DRIVER:
3088         {
3089             LPMCI_OPEN_PARMSW   mop32w = (LPMCI_OPEN_PARMSW)(*lParam);
3090             char* ptr = HeapAlloc( GetProcessHeap(), 0,
3091                                    sizeof(LPMCI_OPEN_PARMSW) + sizeof(MCI_OPEN_PARMS16) + 2 * sizeof(DWORD));
3092             LPMCI_OPEN_PARMS16  mop16;
3093
3094
3095             if (ptr) {
3096                 *(LPMCI_OPEN_PARMSW*)(ptr) = mop32w;
3097                 mop16 = (LPMCI_OPEN_PARMS16)(ptr + sizeof(LPMCI_OPEN_PARMSW));
3098                 mop16->dwCallback       = mop32w->dwCallback;
3099                 mop16->wDeviceID        = mop32w->wDeviceID;
3100                 if (dwFlags & MCI_OPEN_TYPE) {
3101                     if (dwFlags & MCI_OPEN_TYPE_ID) {
3102                         /* dword "transparent" value */
3103                         mop16->lpstrDeviceType = (SEGPTR)mop32w->lpstrDeviceType;
3104                     } else {
3105                         /* string */
3106                         mop16->lpstrDeviceType = MapLS( MCI_strdupWtoA(mop32w->lpstrDeviceType) );
3107                     }
3108                 } else {
3109                     /* nuthin' */
3110                     mop16->lpstrDeviceType = 0;
3111                 }
3112                 if (dwFlags & MCI_OPEN_ELEMENT) {
3113                     if (dwFlags & MCI_OPEN_ELEMENT_ID) {
3114                         mop16->lpstrElementName = (SEGPTR)mop32w->lpstrElementName;
3115                     } else {
3116                         mop16->lpstrElementName = MapLS( MCI_strdupWtoA(mop32w->lpstrElementName) );
3117                     }
3118                 } else {
3119                     mop16->lpstrElementName = 0;
3120                 }
3121                 if (dwFlags & MCI_OPEN_ALIAS) {
3122                     mop16->lpstrAlias = MapLS( MCI_strdupWtoA(mop32w->lpstrAlias) );
3123                 } else {
3124                     mop16->lpstrAlias = 0;
3125                 }
3126                 /* copy extended information if any...
3127                  * FIXME: this may seg fault if initial structure does not contain them and
3128                  * the reads after msip16 fail under LDT limits...
3129                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
3130                  * should not take care of extended parameters, and should be used by MCI_Open
3131                  * to fetch uDevType. When, this is known, the mapping for sending the
3132                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
3133                  */
3134                 memcpy(mop16 + 1, mop32w + 1, 2 * sizeof(DWORD));
3135             } else {
3136                 return WINMM_MAP_NOMEM;
3137             }
3138             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_PARMSW);
3139         }
3140         return WINMM_MAP_OKMEM;
3141         /* case MCI_PASTE:*/
3142     case MCI_PAUSE:
3143         size = sizeof(MCI_GENERIC_PARMS);
3144         break;
3145     case MCI_PLAY:
3146         size = sizeof(MCI_PLAY_PARMS);
3147         break;
3148     case MCI_PUT:
3149         switch (uDevType) {
3150         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
3151         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
3152         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3153         }
3154         break;
3155     case MCI_REALIZE:
3156         size = sizeof(MCI_GENERIC_PARMS);
3157         break;
3158     case MCI_RECORD:
3159         switch (uDevType) {
3160         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECORD_PARMS16);  map = 0x0F1111FB;       break;
3161         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_RECORD_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3162         default:                        size = sizeof(MCI_RECORD_PARMS);        break;
3163         }
3164         break;
3165     case MCI_RESUME:
3166         size = sizeof(MCI_GENERIC_PARMS);
3167         break;
3168     case MCI_SEEK:
3169         switch (uDevType) {
3170         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SEEK_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3171         default:                        size = sizeof(MCI_SEEK_PARMS);          break;
3172         }
3173         break;
3174     case MCI_SET:
3175         switch (uDevType) {
3176         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SET_PARMS);       break;
3177         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SET_PARMS);     break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3178         case MCI_DEVTYPE_SEQUENCER:     size = sizeof(MCI_SEQ_SET_PARMS);       break;
3179         /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
3180          * so not doing anything should work...
3181          */
3182         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_SET_PARMS);      break;
3183         default:                        size = sizeof(MCI_SET_PARMS);           break;
3184         }
3185         break;
3186     case MCI_SETAUDIO:
3187         switch (uDevType) {
3188         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SETAUDIO_PARMS16);map = 0x0000077FF;      break;
3189         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3190         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3191         }
3192         break;
3193         /* case MCI_SETTIMECODE:*/
3194         /* case MCI_SIGNAL:*/
3195         /* case MCI_SOUND:*/
3196     case MCI_SPIN:
3197         size = sizeof(MCI_SET_PARMS);
3198         break;
3199     case MCI_STATUS:
3200         keep = TRUE;
3201         switch (uDevType) {
3202         /* FIXME:
3203          * don't know if buffer for value is the one passed through lpstrDevice
3204          * or is provided by MCI driver.
3205          * Assuming solution 2: provided by MCI driver, so zeroing on entry
3206          */
3207         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16);  map = 0x0B6FF;          break;
3208         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3209         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
3210         }
3211         break;
3212     case MCI_STEP:
3213         switch (uDevType) {
3214         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STEP_PARMS);      break;
3215         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STEP_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3216         case MCI_DEVTYPE_VIDEODISC:     size = sizeof(MCI_VD_STEP_PARMS);       break;
3217         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3218         }
3219         break;
3220     case MCI_STOP:
3221         size = sizeof(MCI_SET_PARMS);
3222         break;
3223     case MCI_SYSINFO:
3224         {
3225             LPMCI_SYSINFO_PARMSW  msip32w = (LPMCI_SYSINFO_PARMSW)(*lParam);
3226             LPMCI_SYSINFO_PARMS16 msip16;
3227             char* ptr = HeapAlloc( GetProcessHeap(), 0,
3228                                    sizeof(LPMCI_SYSINFO_PARMSW) + sizeof(MCI_SYSINFO_PARMS16) );
3229
3230             if (ptr) {
3231                 *(LPMCI_SYSINFO_PARMSW*)(ptr) = msip32w;
3232                 msip16 = (LPMCI_SYSINFO_PARMS16)(ptr + sizeof(LPMCI_SYSINFO_PARMSW));
3233
3234                 msip16->dwCallback       = msip32w->dwCallback;
3235                 msip16->lpstrReturn      = MapLS( HeapAlloc(GetProcessHeap(), 0, msip32w->dwRetSize) );
3236                 msip16->dwRetSize        = msip32w->dwRetSize;
3237                 msip16->dwNumber         = msip32w->dwNumber;
3238                 msip16->wDeviceType      = msip32w->wDeviceType;
3239             } else {
3240                 return WINMM_MAP_NOMEM;
3241             }
3242             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_SYSINFO_PARMSW);
3243         }
3244         return WINMM_MAP_OKMEM;
3245         /* case MCI_UNDO: */
3246     case MCI_UNFREEZE:
3247         switch (uDevType) {
3248         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
3249         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       break;
3250         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3251         }
3252         break;
3253     case MCI_UPDATE:
3254         switch (uDevType) {
3255         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_UPDATE_PARMS16);  map = 0x000B1111B;      break;
3256         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3257         }
3258         break;
3259     case MCI_WHERE:
3260         switch (uDevType) {
3261         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       keep = TRUE;    break;
3262         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       keep = TRUE;    break;
3263         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3264         }
3265         break;
3266     case MCI_WINDOW:
3267         switch (uDevType) {
3268         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7FB;        break;
3269         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7FB;        break;
3270         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3271         }
3272         break;
3273     case DRV_OPEN:
3274         {
3275             LPMCI_OPEN_DRIVER_PARMSW  modp32w = (LPMCI_OPEN_DRIVER_PARMSW)(*lParam);
3276             LPMCI_OPEN_DRIVER_PARMS16 modp16;
3277             char *ptr = HeapAlloc( GetProcessHeap(), 0,
3278                                    sizeof(LPMCI_OPEN_DRIVER_PARMSW) + sizeof(MCI_OPEN_DRIVER_PARMS16));
3279
3280             if (ptr) {
3281                 *(LPMCI_OPEN_DRIVER_PARMSW*)(ptr) = modp32w;
3282                 modp16 = (LPMCI_OPEN_DRIVER_PARMS16)(ptr + sizeof(LPMCI_OPEN_DRIVER_PARMSW));
3283                 modp16->wDeviceID = modp32w->wDeviceID;
3284                 modp16->lpstrParams = MapLS( MCI_strdupWtoA(modp32w->lpstrParams) );
3285                 /* other fields are gonna be filled by the driver, don't copy them */
3286             } else {
3287                 return WINMM_MAP_NOMEM;
3288             }
3289             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_DRIVER_PARMSW);
3290         }
3291         return WINMM_MAP_OKMEM;
3292     case DRV_LOAD:
3293     case DRV_ENABLE:
3294     case DRV_CLOSE:
3295     case DRV_DISABLE:
3296     case DRV_FREE:
3297     case DRV_CONFIGURE:
3298     case DRV_QUERYCONFIGURE:
3299     case DRV_INSTALL:
3300     case DRV_REMOVE:
3301     case DRV_EXITSESSION:
3302     case DRV_EXITAPPLICATION:
3303     case DRV_POWER:
3304         return WINMM_MAP_OK;
3305
3306     default:
3307         FIXME("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
3308         return WINMM_MAP_MSGERROR;
3309     }
3310     return MCI_MsgMapper32WTo16_Create((void**)lParam, size, map, keep);
3311 }
3312
3313 /**************************************************************************
3314  *                      MCI_UnMapMsg32WTo16                     [internal]
3315  */
3316 static  WINMM_MapType   MCI_UnMapMsg32WTo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD_PTR lParam)
3317 {
3318     int         size = 0;
3319     BOOLEAN     kept = FALSE;   /* there is no need to compute size when kept is FALSE */
3320     DWORD       map = 0;
3321
3322     switch (wMsg) {
3323     case MCI_BREAK:
3324         break;
3325         /* case MCI_CAPTURE */
3326     case MCI_CLOSE:
3327     case MCI_CLOSE_DRIVER:
3328     case MCI_CONFIGURE:
3329         break;
3330         /* case MCI_COPY: */
3331     case MCI_CUE:
3332         break;
3333         /* case MCI_CUT: */
3334     case MCI_DELETE:
3335         break;
3336         /* case MCI_ESCAPE: */
3337     case MCI_FREEZE:
3338         break;
3339     case MCI_GETDEVCAPS:
3340         kept = TRUE;
3341         size = sizeof(MCI_GETDEVCAPS_PARMS);
3342         break;
3343         /* case MCI_INDEX: */
3344     case MCI_INFO:
3345         if (lParam) {
3346             LPMCI_INFO_PARMS16  mip16  = (LPMCI_INFO_PARMS16)MapSL(lParam);
3347             LPMCI_INFO_PARMSW   mip32w = *(LPMCI_INFO_PARMSW*)((char*)mip16 - sizeof(LPMCI_INFO_PARMSW));
3348
3349             MultiByteToWideChar(CP_ACP, 0, MapSL(mip16->lpstrReturn), mip16->dwRetSize, 
3350                                 mip32w->lpstrReturn, mip32w->dwRetSize / sizeof(WCHAR));
3351             UnMapLS( lParam );
3352             UnMapLS( mip16->lpstrReturn );
3353             HeapFree( GetProcessHeap(), 0, (void*)MapSL(mip16->lpstrReturn) );
3354             HeapFree( GetProcessHeap(), 0, (char*)mip16 - sizeof(LPMCI_OPEN_PARMSW) );
3355         }
3356         return WINMM_MAP_OK;
3357         /* case MCI_MARK: */
3358         /* case MCI_MONITOR: */
3359     case MCI_OPEN:
3360     case MCI_OPEN_DRIVER:
3361         if (lParam) {
3362             LPMCI_OPEN_PARMS16  mop16  = (LPMCI_OPEN_PARMS16)MapSL(lParam);
3363             LPMCI_OPEN_PARMSW   mop32w = *(LPMCI_OPEN_PARMSW*)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSW));
3364             UnMapLS( lParam );
3365             mop32w->wDeviceID = mop16->wDeviceID;
3366             if ((dwFlags & MCI_OPEN_TYPE) && !(dwFlags & MCI_OPEN_TYPE_ID))
3367             {
3368                 HeapFree(GetProcessHeap(), 0, MapSL(mop16->lpstrDeviceType));
3369                 UnMapLS( mop16->lpstrDeviceType );
3370             }
3371             if ((dwFlags & MCI_OPEN_ELEMENT) && !(dwFlags & MCI_OPEN_ELEMENT_ID))
3372             {
3373                 HeapFree(GetProcessHeap(), 0, MapSL(mop16->lpstrElementName));
3374                 UnMapLS( mop16->lpstrElementName );
3375             }
3376             if (dwFlags & MCI_OPEN_ALIAS)
3377             {
3378                 HeapFree(GetProcessHeap(), 0, MapSL(mop16->lpstrAlias));
3379                 UnMapLS( mop16->lpstrAlias );
3380             }
3381             HeapFree( GetProcessHeap(), 0, (char*)mop16 - sizeof(LPMCI_OPEN_PARMSW) );
3382         }
3383         return WINMM_MAP_OK;
3384         /* case MCI_PASTE:*/
3385     case MCI_PAUSE:
3386         break;
3387     case MCI_PLAY:
3388         break;
3389     case MCI_PUT:
3390         break;
3391     case MCI_REALIZE:
3392         break;
3393     case MCI_RECORD:
3394         break;
3395     case MCI_RESUME:
3396         break;
3397     case MCI_SEEK:
3398         break;
3399     case MCI_SET:
3400         break;
3401     case MCI_SETAUDIO:
3402         switch (uDevType) {
3403         case MCI_DEVTYPE_DIGITAL_VIDEO: map = 0x0000077FF;      break;
3404         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3405         }
3406         break;
3407         /* case MCI_SETTIMECODE:*/
3408         /* case MCI_SIGNAL:*/
3409         /* case MCI_SOUND:*/
3410     case MCI_SPIN:
3411         break;
3412     case MCI_STATUS:
3413         kept = TRUE;
3414         switch (uDevType) {
3415         case MCI_DEVTYPE_DIGITAL_VIDEO:
3416         if (lParam) {
3417             LPMCI_DGV_STATUS_PARMS16    mdsp16  = (LPMCI_DGV_STATUS_PARMS16)MapSL(lParam);
3418             LPMCI_DGV_STATUS_PARMSA     mdsp32a = *(LPMCI_DGV_STATUS_PARMSA*)((char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA));
3419
3420             UnMapLS( lParam );
3421             if (mdsp16) {
3422                 mdsp32a->dwReturn = mdsp16->dwReturn;
3423                 if (dwFlags & MCI_DGV_STATUS_DISKSPACE) {
3424                     TRACE("MCI_STATUS (DGV) lpstrDrive=%08x\n", mdsp16->lpstrDrive);
3425                     TRACE("MCI_STATUS (DGV) lpstrDrive=%s\n", (LPSTR)MapSL(mdsp16->lpstrDrive));
3426                     UnMapLS( mdsp16->lpstrDrive );
3427                 }
3428                 HeapFree( GetProcessHeap(), 0, (char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA) );
3429             } else {
3430                 return WINMM_MAP_NOMEM;
3431             }
3432         }
3433         return WINMM_MAP_OKMEM;
3434         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3435         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
3436         }
3437         break;
3438     case MCI_STEP:
3439         break;
3440     case MCI_STOP:
3441         break;
3442     case MCI_SYSINFO:
3443         if (lParam) {
3444             LPMCI_SYSINFO_PARMS16       msip16  = (LPMCI_SYSINFO_PARMS16)MapSL(lParam);
3445             LPMCI_SYSINFO_PARMSW        msip32w = *(LPMCI_SYSINFO_PARMSW*)((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSW));
3446
3447             UnMapLS( lParam );
3448             if (msip16) {
3449                 MultiByteToWideChar(CP_ACP, 0, MapSL(msip16->lpstrReturn), msip16->dwRetSize, 
3450                                     msip32w->lpstrReturn, msip32w->dwRetSize/sizeof(WCHAR));
3451                 UnMapLS( msip16->lpstrReturn );
3452                 HeapFree( GetProcessHeap(), 0, MapSL(msip16->lpstrReturn) );
3453                 HeapFree( GetProcessHeap(), 0, (char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSW) );
3454             } else {
3455                 return WINMM_MAP_NOMEM;
3456             }
3457         }
3458         return WINMM_MAP_OKMEM;
3459         /* case MCI_UNDO: */
3460     case MCI_UNFREEZE:
3461         break;
3462     case MCI_UPDATE:
3463         break;
3464     case MCI_WHERE:
3465         switch (uDevType) {
3466         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       kept = TRUE;    break;
3467         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       kept = TRUE;    break;
3468         default:                        break;
3469         }
3470         break;
3471     case MCI_WINDOW:
3472         switch (uDevType) {
3473         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7666;       break;
3474         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7666;       break;
3475         default:                        break;
3476         }
3477         /* FIXME: see map function */
3478         break;
3479     case DRV_OPEN:
3480         if (lParam) {
3481             LPMCI_OPEN_DRIVER_PARMS16   modp16  = (LPMCI_OPEN_DRIVER_PARMS16)MapSL(lParam);
3482             LPMCI_OPEN_DRIVER_PARMSW    modp32w = *(LPMCI_OPEN_DRIVER_PARMSW*)((char*)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSW));
3483
3484             UnMapLS( lParam );
3485             modp32w->wCustomCommandTable = modp16->wCustomCommandTable;
3486             modp32w->wType = modp16->wType;
3487             HeapFree(GetProcessHeap(), 0, MapSL(modp16->lpstrParams));
3488             UnMapLS( modp16->lpstrParams );
3489             HeapFree( GetProcessHeap(), 0, (char *)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSW) );
3490         }
3491         return WINMM_MAP_OK;
3492     case DRV_LOAD:
3493     case DRV_ENABLE:
3494     case DRV_CLOSE:
3495     case DRV_DISABLE:
3496     case DRV_FREE:
3497     case DRV_CONFIGURE:
3498     case DRV_QUERYCONFIGURE:
3499     case DRV_INSTALL:
3500     case DRV_REMOVE:
3501     case DRV_EXITSESSION:
3502     case DRV_EXITAPPLICATION:
3503     case DRV_POWER:
3504         FIXME("This is a hack\n");
3505         return WINMM_MAP_OK;
3506
3507     default:
3508         FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
3509         return WINMM_MAP_MSGERROR;
3510     }
3511     return MCI_MsgMapper32WTo16_Destroy((void*)lParam, size, map, kept);
3512 }
3513
3514 void    MMDRV_Init16(void)
3515 {
3516 #define A(_x,_y) MMDRV_InstallMap(_x, \
3517 MMDRV_##_y##_Map16To32W, MMDRV_##_y##_UnMap16To32W, \
3518 MMDRV_##_y##_Map32WTo16, MMDRV_##_y##_UnMap32WTo16, \
3519 MMDRV_##_y##_Callback)
3520     A(MMDRV_AUX,        Aux);
3521     A(MMDRV_MIXER,      Mixer);
3522     A(MMDRV_MIDIIN,     MidiIn);
3523     A(MMDRV_MIDIOUT,    MidiOut);
3524     A(MMDRV_WAVEIN,     WaveIn);
3525     A(MMDRV_WAVEOUT,    WaveOut);
3526 #undef A
3527
3528     pFnCallMMDrvFunc16 = MMDRV_CallMMDrvFunc16;
3529     pFnLoadMMDrvFunc16 = MMDRV_LoadMMDrvFunc16;
3530
3531     pFnMciMapMsg16To32W   = MCI_MapMsg16To32W;
3532     pFnMciUnMapMsg16To32W = MCI_UnMapMsg16To32W;
3533     pFnMciMapMsg32WTo16   = MCI_MapMsg32WTo16;
3534     pFnMciUnMapMsg32WTo16 = MCI_UnMapMsg32WTo16;
3535 }