dmcompos: Replaced && 0xff by & 0xff.
[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                 TRACE("wh16=%08x wh16->lpData=%p wh32->buflen=%u wh32->lpData=%p\n",
972                       seg_ptr + sizeof(LPWAVEHDR), wh16->lpData,
973                       wh32->dwBufferLength, wh32->lpData);
974                 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
975                 *lpParam2 = sizeof(WAVEHDR);
976
977                 ret = WINMM_MAP_OKMEM;
978             } else {
979                 ret = WINMM_MAP_NOMEM;
980             }
981         }
982         break;
983     case WIDM_ADDBUFFER:
984     case WIDM_UNPREPARE:
985         {
986             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
987             LPWAVEHDR           wh16 = wh32->lpNext;
988             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
989             SEGPTR seg_ptr = MapLS( ptr );
990
991             assert(*(LPWAVEHDR*)ptr == wh32);
992
993             TRACE("wh16=%08x wh16->lpData=%p wh32->buflen=%u wh32->lpData=%p\n",
994                   seg_ptr + sizeof(LPWAVEHDR), wh16->lpData, wh32->dwBufferLength, wh32->lpData);
995
996             if (wMsg == WIDM_ADDBUFFER)
997                 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
998
999             *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1000             *lpParam2 = sizeof(WAVEHDR);
1001             /* dwBufferLength can be reduced between prepare & write */
1002             if (wMsg == WIDM_ADDBUFFER && wh16->dwBufferLength < wh32->dwBufferLength) {
1003                 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
1004                     wh16->dwBufferLength, wh32->dwBufferLength);
1005             } else
1006                 wh16->dwBufferLength = wh32->dwBufferLength;
1007             ret = WINMM_MAP_OKMEM;
1008         }
1009         break;
1010    case WIDM_GETDEVCAPS:
1011         {
1012             LPWAVEINCAPSW wic32 = (LPWAVEINCAPSW)*lpParam1;
1013             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0 ,sizeof(LPWAVEINCAPSW) + sizeof(WAVEINCAPS16));
1014
1015             if (ptr) {
1016                 *(LPWAVEINCAPSW*)ptr = wic32;
1017                 ret = WINMM_MAP_OKMEM;
1018             } else {
1019                 ret = WINMM_MAP_NOMEM;
1020             }
1021             *lpParam1 = MapLS(ptr) + sizeof(LPWAVEINCAPSW);
1022             *lpParam2 = sizeof(WAVEINCAPS16);
1023         }
1024         break;
1025     case WIDM_GETPOS:
1026         {
1027             LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1028             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMMTIME) + sizeof(MMTIME16));
1029             LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1030
1031             if (ptr) {
1032                 *(LPMMTIME*)ptr = mmt32;
1033                 mmt16->wType = mmt32->wType;
1034                 ret = WINMM_MAP_OKMEM;
1035             } else {
1036                 ret = WINMM_MAP_NOMEM;
1037             }
1038             *lpParam1 = MapLS(ptr) + sizeof(LPMMTIME);
1039             *lpParam2 = sizeof(MMTIME16);
1040         }
1041         break;
1042     case DRVM_MAPPER_STATUS:
1043         {
1044             LPDWORD p32 = (LPDWORD)*lpParam2;
1045             *lpParam2 = MapLS(p32);
1046             ret = WINMM_MAP_OKMEM;
1047         }
1048         break;
1049     default:
1050         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1051         break;
1052     }
1053     return ret;
1054 }
1055
1056 /**************************************************************************
1057  *                              MMDRV_WaveIn_UnMap32WTo16       [internal]
1058  */
1059 static  WINMM_MapType   MMDRV_WaveIn_UnMap32WTo16(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
1060 {
1061     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
1062
1063     switch (wMsg) {
1064     case WIDM_CLOSE:
1065     case WIDM_GETNUMDEVS:
1066     case WIDM_RESET:
1067     case WIDM_START:
1068     case WIDM_STOP:
1069         ret = WINMM_MAP_OK;
1070         break;
1071
1072     case WIDM_OPEN:
1073         {
1074             LPWAVEOPENDESC16            wod16 = MapSL(*lpParam1);
1075             LPSTR                       ptr   = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1076             LPWAVEOPENDESC              wod32 = *(LPWAVEOPENDESC*)ptr;
1077
1078             UnMapLS( *lpParam1 );
1079             wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1080             **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1081             HeapFree( GetProcessHeap(), 0, ptr );
1082             ret = WINMM_MAP_OK;
1083         }
1084         break;
1085
1086     case WIDM_ADDBUFFER:
1087     case WIDM_PREPARE:
1088     case WIDM_UNPREPARE:
1089         {
1090             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1091             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1092             LPWAVEHDR           wh32 = *(LPWAVEHDR*)ptr;
1093
1094             assert(wh32->lpNext == wh16);
1095             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1096             wh32->dwUser = wh16->dwUser;
1097             wh32->dwFlags = wh16->dwFlags;
1098             wh32->dwLoops = wh16->dwLoops;
1099             UnMapLS( *lpParam1 );
1100
1101             if (wMsg == WIDM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
1102                 HeapFree( GetProcessHeap(), 0, ptr );
1103                 wh32->lpNext = 0;
1104             }
1105             ret = WINMM_MAP_OK;
1106         }
1107         break;
1108      case WIDM_GETDEVCAPS:
1109         {
1110             LPWAVEINCAPS16              wic16 = MapSL(*lpParam1);
1111             LPSTR                       ptr   = (LPSTR)wic16 - sizeof(LPWAVEINCAPSW);
1112             LPWAVEINCAPSW               wic32 = *(LPWAVEINCAPSW*)ptr;
1113
1114             wic32->wMid = wic16->wMid;
1115             wic32->wPid = wic16->wPid;
1116             wic32->vDriverVersion = wic16->vDriverVersion;
1117             WideCharToMultiByte( CP_ACP, 0, wic32->szPname, -1, wic16->szPname,
1118                                  sizeof(wic16->szPname), NULL, NULL );
1119             wic32->dwFormats = wic16->dwFormats;
1120             wic32->wChannels = wic16->wChannels;
1121             UnMapLS( *lpParam1 );
1122             HeapFree( GetProcessHeap(), 0, ptr );
1123             ret = WINMM_MAP_OK;
1124         }
1125         break;
1126     case WIDM_GETPOS:
1127         {
1128             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1129             LPSTR               ptr   = (LPSTR)mmt16 - sizeof(LPMMTIME);
1130             LPMMTIME            mmt32 = *(LPMMTIME*)ptr;
1131
1132             MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1133             UnMapLS( *lpParam1 );
1134             HeapFree( GetProcessHeap(), 0, ptr );
1135             ret = WINMM_MAP_OK;
1136         }
1137         break;
1138     case DRVM_MAPPER_STATUS:
1139         {
1140             UnMapLS( *lpParam2 );
1141             ret = WINMM_MAP_OK;
1142         }
1143         break;
1144     default:
1145         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1146         break;
1147     }
1148     return ret;
1149 }
1150
1151 /**************************************************************************
1152  *                              MMDRV_WaveIn_Callback           [internal]
1153  */
1154 static  void    CALLBACK MMDRV_WaveIn_Callback(HDRVR hDev, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
1155 {
1156     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
1157
1158     switch (uMsg) {
1159     case WIM_OPEN:
1160     case WIM_CLOSE:
1161         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1162         break;
1163     case WIM_DATA:
1164         if (mld->bFrom32 && !MMDRV_Is32(mld->mmdIndex)) {
1165             /* initial map is: 32 => 16 */
1166             LPWAVEHDR           wh16 = MapSL(dwParam1);
1167             LPWAVEHDR           wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1168
1169             dwParam1 = (DWORD)wh32;
1170             wh32->dwFlags = wh16->dwFlags;
1171             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1172         } else if (!mld->bFrom32 && MMDRV_Is32(mld->mmdIndex)) {
1173             /* initial map is: 16 => 32 */
1174             LPWAVEHDR           wh32 = (LPWAVEHDR)(dwParam1);
1175             SEGPTR              segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1176             LPWAVEHDR           wh16 = MapSL(segwh16);
1177
1178             dwParam1 = (DWORD)segwh16;
1179             wh16->dwFlags = wh32->dwFlags;
1180             wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1181         }
1182         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1183         break;
1184     default:
1185         ERR("Unknown msg %u\n", uMsg);
1186     }
1187
1188     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1189 }
1190
1191 /* =================================
1192  *   W A V E  O U T  M A P P E R S
1193  * ================================= */
1194
1195 /**************************************************************************
1196  *                              MMDRV_WaveOut_Map16To32W        [internal]
1197  */
1198 static  WINMM_MapType   MMDRV_WaveOut_Map16To32W  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
1199 {
1200     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
1201
1202     switch (wMsg) {
1203     /* nothing to do */
1204     case WODM_BREAKLOOP:
1205     case WODM_CLOSE:
1206     case WODM_GETNUMDEVS:
1207     case WODM_PAUSE:
1208     case WODM_RESET:
1209     case WODM_RESTART:
1210     case WODM_SETPITCH:
1211     case WODM_SETPLAYBACKRATE:
1212     case WODM_SETVOLUME:
1213         ret = WINMM_MAP_OK;
1214         break;
1215
1216     case WODM_GETPITCH:
1217     case WODM_GETPLAYBACKRATE:
1218     case WODM_GETVOLUME:
1219     case WODM_OPEN:
1220         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
1221         break;
1222
1223     case WODM_GETDEVCAPS:
1224         {
1225             LPWAVEOUTCAPSW              woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSW));
1226             LPWAVEOUTCAPS16             woc16 = MapSL(*lpParam1);
1227
1228             if (woc32) {
1229                 *(LPWAVEOUTCAPS16*)woc32 = woc16;
1230                 woc32 = (LPWAVEOUTCAPSW)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16));
1231                 *lpParam1 = (DWORD)woc32;
1232                 *lpParam2 = sizeof(WAVEOUTCAPSW);
1233
1234                 ret = WINMM_MAP_OKMEM;
1235             } else {
1236                 ret = WINMM_MAP_NOMEM;
1237             }
1238         }
1239         break;
1240     case WODM_GETPOS:
1241         {
1242             LPMMTIME            mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
1243             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1244
1245             if (mmt32) {
1246                 *(LPMMTIME16*)mmt32 = mmt16;
1247                 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
1248
1249                 mmt32->wType = mmt16->wType;
1250                 *lpParam1 = (DWORD)mmt32;
1251                 *lpParam2 = sizeof(MMTIME);
1252
1253                 ret = WINMM_MAP_OKMEM;
1254             } else {
1255                 ret = WINMM_MAP_NOMEM;
1256             }
1257         }
1258         break;
1259     case WODM_PREPARE:
1260         {
1261             LPWAVEHDR           wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
1262             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1263
1264             if (wh32) {
1265                 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
1266                 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
1267                 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
1268                 wh32->dwBufferLength = wh16->dwBufferLength;
1269                 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1270                 wh32->dwUser = wh16->dwUser;
1271                 wh32->dwFlags = wh16->dwFlags;
1272                 wh32->dwLoops = wh16->dwLoops;
1273                 /* FIXME: nothing on wh32->lpNext */
1274                 /* could link the wh32->lpNext at this level for memory house keeping */
1275                 wh16->lpNext = wh32; /* for reuse in unprepare and write */
1276                 *lpParam1 = (DWORD)wh32;
1277                 *lpParam2 = sizeof(WAVEHDR);
1278
1279                 ret = WINMM_MAP_OKMEM;
1280             } else {
1281                 ret = WINMM_MAP_NOMEM;
1282             }
1283         }
1284         break;
1285     case WODM_UNPREPARE:
1286     case WODM_WRITE:
1287         {
1288             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1289             LPWAVEHDR           wh32 = (LPWAVEHDR)wh16->lpNext;
1290
1291             *lpParam1 = (DWORD)wh32;
1292             *lpParam2 = sizeof(WAVEHDR);
1293             /* dwBufferLength can be reduced between prepare & write */
1294             if (wMsg == WODM_WRITE && wh32->dwBufferLength < wh16->dwBufferLength) {
1295                 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
1296                     wh32->dwBufferLength, wh16->dwBufferLength);
1297             } else
1298                 wh32->dwBufferLength = wh16->dwBufferLength;
1299             ret = WINMM_MAP_OKMEM;
1300         }
1301         break;
1302     case WODM_MAPPER_STATUS:
1303         *lpParam2 = (DWORD)MapSL(*lpParam2);
1304         ret = WINMM_MAP_OK;
1305         break;
1306     default:
1307         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1308         break;
1309     }
1310     return ret;
1311 }
1312
1313 /**************************************************************************
1314  *                              MMDRV_WaveOut_UnMap16To32W      [internal]
1315  */
1316 static  WINMM_MapType   MMDRV_WaveOut_UnMap16To32W(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
1317 {
1318     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
1319
1320     switch (wMsg) {
1321     /* nothing to do */
1322     case WODM_BREAKLOOP:
1323     case WODM_CLOSE:
1324     case WODM_GETNUMDEVS:
1325     case WODM_PAUSE:
1326     case WODM_RESET:
1327     case WODM_RESTART:
1328     case WODM_SETPITCH:
1329     case WODM_SETPLAYBACKRATE:
1330     case WODM_SETVOLUME:
1331     case WODM_MAPPER_STATUS:
1332         ret = WINMM_MAP_OK;
1333         break;
1334
1335     case WODM_GETPITCH:
1336     case WODM_GETPLAYBACKRATE:
1337     case WODM_GETVOLUME:
1338     case WODM_OPEN:
1339         FIXME("Shouldn't be used: those 16 bit functions use the 32 bit interface\n");
1340         break;
1341
1342     case WODM_GETDEVCAPS:
1343         {
1344             LPWAVEOUTCAPSW              woc32 = (LPWAVEOUTCAPSW)(*lpParam1);
1345             LPWAVEOUTCAPS16             woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1346
1347             woc16->wMid = woc32->wMid;
1348             woc16->wPid = woc32->wPid;
1349             woc16->vDriverVersion = woc32->vDriverVersion;
1350             WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname,
1351                                  sizeof(woc16->szPname), NULL, NULL );
1352             woc16->dwFormats = woc32->dwFormats;
1353             woc16->wChannels = woc32->wChannels;
1354             woc16->dwSupport = woc32->dwSupport;
1355             HeapFree(GetProcessHeap(), 0, (LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1356             ret = WINMM_MAP_OK;
1357         }
1358         break;
1359     case WODM_GETPOS:
1360         {
1361             LPMMTIME            mmt32 = (LPMMTIME)(*lpParam1);
1362             LPMMTIME16          mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
1363
1364             MMSYSTEM_MMTIME32to16(mmt16, mmt32);
1365             HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
1366             ret = WINMM_MAP_OK;
1367         }
1368         break;
1369     case WODM_PREPARE:
1370     case WODM_UNPREPARE:
1371     case WODM_WRITE:
1372         {
1373             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
1374             LPWAVEHDR           wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
1375
1376             assert(wh16->lpNext == wh32);
1377             wh16->dwBufferLength = wh32->dwBufferLength;
1378             wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1379             wh16->dwUser = wh32->dwUser;
1380             wh16->dwFlags = wh32->dwFlags;
1381             wh16->dwLoops = wh32->dwLoops;
1382
1383             if (wMsg == WODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
1384                 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
1385                 wh16->lpNext = 0;
1386             }
1387             ret = WINMM_MAP_OK;
1388         }
1389         break;
1390     default:
1391         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1392         break;
1393     }
1394     return ret;
1395 }
1396
1397 /**************************************************************************
1398  *                              MMDRV_WaveOut_Map32WTo16        [internal]
1399  */
1400 static  WINMM_MapType   MMDRV_WaveOut_Map32WTo16  (UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
1401 {
1402     WINMM_MapType       ret;
1403
1404     switch (wMsg) {
1405         /* nothing to do */
1406     case WODM_BREAKLOOP:
1407     case WODM_CLOSE:
1408     case WODM_GETNUMDEVS:
1409     case WODM_PAUSE:
1410     case WODM_RESET:
1411     case WODM_RESTART:
1412     case WODM_SETPITCH:
1413     case WODM_SETPLAYBACKRATE:
1414     case WODM_SETVOLUME:
1415         ret = WINMM_MAP_OK;
1416         break;
1417
1418     case WODM_GETDEVCAPS:
1419         {
1420             LPWAVEOUTCAPSW woc32 = (LPWAVEOUTCAPSW)*lpParam1;
1421             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0,
1422                                    sizeof(LPWAVEOUTCAPSW) + sizeof(WAVEOUTCAPS16));
1423
1424             if (ptr) {
1425                 *(LPWAVEOUTCAPSW*)ptr = woc32;
1426                 ret = WINMM_MAP_OKMEM;
1427             } else {
1428                 ret = WINMM_MAP_NOMEM;
1429             }
1430             *lpParam1 = MapLS(ptr) + sizeof(LPWAVEOUTCAPSW);
1431             *lpParam2 = sizeof(WAVEOUTCAPS16);
1432         }
1433         break;
1434     case WODM_GETPITCH:
1435         FIXME("NIY: no conversion yet\n");
1436         ret = WINMM_MAP_MSGERROR;
1437         break;
1438     case WODM_GETPLAYBACKRATE:
1439         FIXME("NIY: no conversion yet\n");
1440         ret = WINMM_MAP_MSGERROR;
1441         break;
1442     case WODM_GETPOS:
1443         {
1444             LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1445             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMMTIME) + sizeof(MMTIME16));
1446             LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1447
1448             if (ptr) {
1449                 *(LPMMTIME*)ptr = mmt32;
1450                 mmt16->wType = mmt32->wType;
1451                 ret = WINMM_MAP_OKMEM;
1452             } else {
1453                 ret = WINMM_MAP_NOMEM;
1454             }
1455             *lpParam1 = MapLS(ptr) + sizeof(LPMMTIME);
1456             *lpParam2 = sizeof(MMTIME16);
1457         }
1458         break;
1459     case WODM_GETVOLUME:
1460         FIXME("NIY: no conversion yet\n");
1461         ret = WINMM_MAP_MSGERROR;
1462         break;
1463     case WODM_OPEN:
1464         {
1465             LPWAVEOPENDESC              wod32 = (LPWAVEOPENDESC)*lpParam1;
1466             int                         sz = sizeof(WAVEFORMATEX);
1467             LPVOID                      ptr;
1468             LPWAVEOPENDESC16            wod16;
1469
1470             /* allocated data are mapped as follows:
1471                LPWAVEOPENDESC   ptr to orig lParam1
1472                DWORD            orig dwUser, which is a pointer to DWORD:driver dwInstance
1473                DWORD            dwUser passed to driver
1474                WAVEOPENDESC16   wod16: openDesc passed to driver
1475                WAVEFORMATEX     openDesc->lpFormat passed to driver
1476                xxx              extra bytes to WAVEFORMATEX
1477             */
1478             if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1479                 TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag);
1480                 sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize;
1481             }
1482
1483             ptr = HeapAlloc( GetProcessHeap(), 0,
1484                              sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
1485
1486             if (ptr) {
1487                 SEGPTR seg_ptr = MapLS( ptr );
1488                 *(LPWAVEOPENDESC*)ptr = wod32;
1489                 *(LPDWORD)((char*)ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
1490                 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
1491
1492                 wod16->hWave = HWAVE_16(wod32->hWave);
1493                 wod16->lpFormat = (LPWAVEFORMATEX)(seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16));
1494                 memcpy(wod16 + 1, wod32->lpFormat, sz);
1495
1496                 wod16->dwCallback = wod32->dwCallback;
1497                 wod16->dwInstance = wod32->dwInstance;
1498                 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
1499                 wod16->dnDevNode = wod32->dnDevNode;
1500
1501                 *lpParam1 = seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
1502                 *lpdwUser = seg_ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
1503
1504                 ret = WINMM_MAP_OKMEM;
1505             } else {
1506                 ret = WINMM_MAP_NOMEM;
1507             }
1508         }
1509         break;
1510     case WODM_PREPARE:
1511         {
1512             LPWAVEHDR           wh32 = (LPWAVEHDR)*lpParam1;
1513             LPWAVEHDR           wh16;
1514             LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
1515                                     sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
1516
1517             if (ptr) {
1518                 SEGPTR seg_ptr = MapLS( ptr );
1519                 *(LPWAVEHDR*)ptr = wh32;
1520                 wh16 = (LPWAVEHDR)((LPSTR)ptr + sizeof(LPWAVEHDR));
1521                 wh16->lpData = (LPSTR)seg_ptr + sizeof(LPWAVEHDR) + sizeof(WAVEHDR);
1522                 /* data will be copied on WODM_WRITE */
1523                 wh16->dwBufferLength = wh32->dwBufferLength;
1524                 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1525                 wh16->dwUser = wh32->dwUser;
1526                 wh16->dwFlags = wh32->dwFlags;
1527                 wh16->dwLoops = wh32->dwLoops;
1528                 /* FIXME: nothing on wh32->lpNext */
1529                 /* could link the wh32->lpNext at this level for memory house keeping */
1530                 wh32->lpNext = wh16; /* for reuse in unprepare and write */
1531                 TRACE("wh16=%08x wh16->lpData=%p wh32->buflen=%u wh32->lpData=%p\n",
1532                       seg_ptr + sizeof(LPWAVEHDR), wh16->lpData,
1533                       wh32->dwBufferLength, wh32->lpData);
1534                 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1535                 *lpParam2 = sizeof(WAVEHDR);
1536
1537                 ret = WINMM_MAP_OKMEM;
1538             } else {
1539                 ret = WINMM_MAP_NOMEM;
1540             }
1541         }
1542         break;
1543     case WODM_UNPREPARE:
1544     case WODM_WRITE:
1545         {
1546             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
1547             LPWAVEHDR           wh16 = wh32->lpNext;
1548             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1549             SEGPTR seg_ptr = MapLS( ptr );
1550
1551             assert(*(LPWAVEHDR*)ptr == wh32);
1552
1553             TRACE("wh16=%08x wh16->lpData=%p wh32->buflen=%u wh32->lpData=%p\n",
1554                   seg_ptr + sizeof(LPWAVEHDR), wh16->lpData,
1555                   wh32->dwBufferLength, wh32->lpData);
1556
1557             if (wMsg == WODM_WRITE)
1558                 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
1559
1560             *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1561             *lpParam2 = sizeof(WAVEHDR);
1562             /* dwBufferLength can be reduced between prepare & write */
1563             if (wMsg == WODM_WRITE && wh16->dwBufferLength < wh32->dwBufferLength) {
1564                 ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
1565                     wh16->dwBufferLength, wh32->dwBufferLength);
1566             } else
1567                 wh16->dwBufferLength = wh32->dwBufferLength;
1568             ret = WINMM_MAP_OKMEM;
1569         }
1570         break;
1571     case DRVM_MAPPER_STATUS:
1572         {
1573             LPDWORD p32 = (LPDWORD)*lpParam2;
1574             *lpParam2 = MapLS(p32);
1575             ret = WINMM_MAP_OKMEM;
1576         }
1577         break;
1578     default:
1579         FIXME("NIY: no conversion yet\n");
1580         ret = WINMM_MAP_MSGERROR;
1581         break;
1582     }
1583     return ret;
1584 }
1585
1586 /**************************************************************************
1587  *                              MMDRV_WaveOut_UnMap32WTo16      [internal]
1588  */
1589 static  WINMM_MapType   MMDRV_WaveOut_UnMap32WTo16(UINT wMsg, LPDWORD lpdwUser, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
1590 {
1591     WINMM_MapType       ret;
1592
1593     switch (wMsg) {
1594         /* nothing to do */
1595     case WODM_BREAKLOOP:
1596     case WODM_CLOSE:
1597     case WODM_GETNUMDEVS:
1598     case WODM_PAUSE:
1599     case WODM_RESET:
1600     case WODM_RESTART:
1601     case WODM_SETPITCH:
1602     case WODM_SETPLAYBACKRATE:
1603     case WODM_SETVOLUME:
1604         ret = WINMM_MAP_OK;
1605         break;
1606
1607     case WODM_GETDEVCAPS:
1608         {
1609             LPWAVEOUTCAPS16             woc16 = MapSL(*lpParam1);
1610             LPSTR                       ptr   = (LPSTR)woc16 - sizeof(LPWAVEOUTCAPSW);
1611             LPWAVEOUTCAPSW              woc32 = *(LPWAVEOUTCAPSW*)ptr;
1612
1613             woc32->wMid = woc16->wMid;
1614             woc32->wPid = woc16->wPid;
1615             woc32->vDriverVersion = woc16->vDriverVersion;
1616             WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname,
1617                                  sizeof(woc16->szPname), NULL, NULL );
1618             woc32->dwFormats = woc16->dwFormats;
1619             woc32->wChannels = woc16->wChannels;
1620             woc32->dwSupport = woc16->dwSupport;
1621             UnMapLS( *lpParam1 );
1622             HeapFree( GetProcessHeap(), 0, ptr );
1623             ret = WINMM_MAP_OK;
1624         }
1625         break;
1626     case WODM_GETPITCH:
1627         FIXME("NIY: no conversion yet\n");
1628         ret = WINMM_MAP_MSGERROR;
1629         break;
1630     case WODM_GETPLAYBACKRATE:
1631         FIXME("NIY: no conversion yet\n");
1632         ret = WINMM_MAP_MSGERROR;
1633         break;
1634     case WODM_GETPOS:
1635         {
1636             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1637             LPSTR               ptr   = (LPSTR)mmt16 - sizeof(LPMMTIME);
1638             LPMMTIME            mmt32 = *(LPMMTIME*)ptr;
1639
1640             MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1641             UnMapLS( *lpParam1 );
1642             HeapFree( GetProcessHeap(), 0, ptr );
1643             ret = WINMM_MAP_OK;
1644         }
1645         break;
1646     case WODM_OPEN:
1647         {
1648             LPWAVEOPENDESC16            wod16 = MapSL(*lpParam1);
1649             LPSTR                       ptr   = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1650             LPWAVEOPENDESC              wod32 = *(LPWAVEOPENDESC*)ptr;
1651
1652             wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1653             **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1654             UnMapLS( *lpParam1 );
1655             HeapFree( GetProcessHeap(), 0, ptr );
1656             ret = WINMM_MAP_OK;
1657         }
1658         break;
1659     case WODM_PREPARE:
1660     case WODM_UNPREPARE:
1661     case WODM_WRITE:
1662         {
1663             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1664             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1665             LPWAVEHDR           wh32 = *(LPWAVEHDR*)ptr;
1666
1667             assert(wh32->lpNext == wh16);
1668             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1669             wh32->dwUser = wh16->dwUser;
1670             wh32->dwFlags = wh16->dwFlags;
1671             wh32->dwLoops = wh16->dwLoops;
1672
1673             UnMapLS( *lpParam1 );
1674             if (wMsg == WODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
1675                 HeapFree( GetProcessHeap(), 0, ptr );
1676                 wh32->lpNext = 0;
1677             }
1678             ret = WINMM_MAP_OK;
1679         }
1680         break;
1681     case WODM_GETVOLUME:
1682         FIXME("NIY: no conversion yet\n");
1683         ret = WINMM_MAP_MSGERROR;
1684         break;
1685     case DRVM_MAPPER_STATUS:
1686         {
1687             UnMapLS( *lpParam2 );
1688             ret = WINMM_MAP_OK;
1689         }
1690         break;
1691     default:
1692         FIXME("NIY: no conversion yet\n");
1693         ret = WINMM_MAP_MSGERROR;
1694         break;
1695     }
1696     return ret;
1697 }
1698
1699 /**************************************************************************
1700  *                              MMDRV_WaveOut_Callback          [internal]
1701  */
1702 static  void    CALLBACK MMDRV_WaveOut_Callback(HDRVR hDev, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
1703 {
1704     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
1705
1706     switch (uMsg) {
1707     case WOM_OPEN:
1708     case WOM_CLOSE:
1709         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1710         break;
1711     case WOM_DONE:
1712         if (mld->bFrom32 && !MMDRV_Is32(mld->mmdIndex)) {
1713             /* initial map is: 32 => 16 */
1714             LPWAVEHDR           wh16 = MapSL(dwParam1);
1715             LPWAVEHDR           wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1716
1717             dwParam1 = (DWORD)wh32;
1718             wh32->dwFlags = wh16->dwFlags;
1719         } else if (!mld->bFrom32 && MMDRV_Is32(mld->mmdIndex)) {
1720             /* initial map is: 16 => 32 */
1721             LPWAVEHDR           wh32 = (LPWAVEHDR)(dwParam1);
1722             SEGPTR              segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1723             LPWAVEHDR           wh16 = MapSL(segwh16);
1724
1725             dwParam1 = (DWORD)segwh16;
1726             wh16->dwFlags = wh32->dwFlags;
1727         }
1728         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1729         break;
1730     default:
1731         ERR("Unknown msg %u\n", uMsg);
1732     }
1733
1734     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1735 }
1736
1737 /* =================================
1738  *  M A P P E R S   H A N D L I N G
1739  * ================================= */
1740
1741 static  LRESULT    MMDRV_CallMMDrvFunc16(DWORD fp16, WORD dev, WORD msg, LONG instance,
1742                                          LONG lp1, LONG lp2)
1743 {
1744     WORD args[8];
1745     DWORD ret;
1746
1747     args[7] = dev;
1748     args[6] = msg;
1749     args[5] = HIWORD(instance);
1750     args[4] = LOWORD(instance);
1751     args[3] = HIWORD(lp1);
1752     args[2] = LOWORD(lp1);
1753     args[1] = HIWORD(lp2);
1754     args[0] = LOWORD(lp2);
1755     WOWCallback16Ex( fp16, WCB16_PASCAL, sizeof(args), args, &ret );
1756     return LOWORD(ret);
1757 }
1758
1759 /**************************************************************************
1760  *                              MMDRV_GetDescription16          [internal]
1761  */
1762 static  BOOL    MMDRV_GetDescription16(const char* fname, char* buf, int buflen)
1763 {
1764     OFSTRUCT    ofs;
1765     HFILE       hFile;
1766     WORD        w;
1767     DWORD       dw;
1768     BOOL        ret = FALSE;
1769
1770     if ((hFile = OpenFile(fname, &ofs, OF_READ | OF_SHARE_DENY_WRITE)) == HFILE_ERROR) {
1771         ERR("Can't open file %s (builtin driver ?)\n", fname);
1772         return FALSE;
1773     }
1774
1775 #define E(_x)   do {TRACE _x;goto theEnd;} while(0)
1776
1777     if (_lread(hFile, &w, 2) != 2)                      E(("Can't read sig\n"));
1778     if (w != ('Z' * 256 + 'M'))                         E(("Bad sig %04x\n", w));
1779     if (_llseek(hFile, 0x3C, SEEK_SET) < 0)             E(("Can't seek to ext header offset\n"));
1780     if (_lread(hFile, &dw, 4) != 4)                     E(("Can't read ext header offset\n"));
1781     if (_llseek(hFile, dw + 0x2C, SEEK_SET) < 0)        E(("Can't seek to ext header.nr table %u\n", dw+0x2C));
1782     if (_lread(hFile, &dw, 4) != 4)                     E(("Can't read nr table offset\n"));
1783     if (_llseek(hFile, dw, SEEK_SET) < 0)               E(("Can't seek to nr table %u\n", dw));
1784     if (_lread(hFile, buf, 1) != 1)                     E(("Can't read descr length\n"));
1785     buflen = min((int)(unsigned)(BYTE)buf[0], buflen - 1);
1786     if (_lread(hFile, buf, buflen) != buflen)           E(("Can't read descr (%d)\n", buflen));
1787     buf[buflen] = '\0';
1788     ret = TRUE;
1789     TRACE("Got '%s' [%d]\n", buf, buflen);
1790 theEnd:
1791     _lclose(hFile);
1792     return ret;
1793 }
1794
1795 /******************************************************************
1796  *              MMDRV_LoadMMDrvFunc16
1797  *
1798  */
1799 unsigned   MMDRV_LoadMMDrvFunc16(LPCSTR drvName, LPWINE_DRIVER d, 
1800                                  LPWINE_MM_DRIVER lpDrv)
1801 {        
1802     WINEMM_msgFunc16    func;
1803     unsigned            count = 0;
1804     char                buffer[128];
1805     /*
1806      * DESCRIPTION 'wave,aux,mixer:Creative Labs Sound Blaster 16 Driver'
1807      * The beginning of the module description indicates the driver supports
1808      * waveform, auxiliary, and mixer devices. Use one of the following
1809      * device-type names, followed by a colon (:) to indicate the type of
1810      * device your driver supports. If the driver supports more than one
1811      * type of device, separate each device-type name with a comma (,).
1812      *
1813      * wave for waveform audio devices
1814      * wavemapper for wave mappers
1815      * midi for MIDI audio devices
1816      * midimapper for midi mappers
1817      * aux for auxiliary audio devices
1818      * mixer for mixer devices
1819      */
1820
1821     if (d->d.d16.hDriver16) {
1822         HMODULE16       hMod16 = GetDriverModuleHandle16(d->d.d16.hDriver16);
1823
1824 #define AA(_h,_w,_x,_y,_z)                                      \
1825     func = (WINEMM_msgFunc##_y) _z ((_h), #_x);                 \
1826     if (func != NULL)                                           \
1827         { lpDrv->parts[_w].u.fnMessage##_y = func; count++;     \
1828           TRACE("Got %d bit func '%s'\n", _y, #_x);         }
1829
1830 #define A(_x,_y)        AA(hMod16,_x,_y,16,GetProcAddress16)
1831         A(MMDRV_AUX,    auxMessage);
1832         A(MMDRV_MIXER,  mxdMessage);
1833         A(MMDRV_MIDIIN, midMessage);
1834         A(MMDRV_MIDIOUT,modMessage);
1835         A(MMDRV_WAVEIN, widMessage);
1836         A(MMDRV_WAVEOUT,wodMessage);
1837 #undef A
1838 #undef AA
1839     }
1840     if (TRACE_ON(winmm)) {
1841         if (MMDRV_GetDescription16(drvName, buffer, sizeof(buffer)))
1842             TRACE("%s => %s\n", drvName, buffer);
1843         else
1844             TRACE("%s => No description\n", drvName);
1845     }
1846
1847     return count;
1848 }
1849
1850 /* =================================
1851  *              M C I
1852  * ================================= */
1853
1854 #if 0
1855 /* FIXME: this code is kept for not yet implemented optimisation for an application
1856  * using the 32A MCI interface and calling a 16 bit driver.
1857  * For now, we're doing two conversions:
1858  * - 32A => 32W (in 32 bit MCI code)
1859  * - 32W => 16  in this file
1860  */
1861
1862 /*
1863  * 0000 stop
1864  * 0001 squeeze   signed 4 bytes to 2 bytes     *( LPINT16)D = ( INT16)*( LPINT16)S; D += 2;     S += 4
1865  * 0010 squeeze unsigned 4 bytes to 2 bytes     *(LPUINT16)D = (UINT16)*(LPUINT16)S; D += 2;     S += 4
1866  * 0100
1867  * 0101
1868  * 0110 zero 4 bytes                            *(DWORD)D = 0                        D += 4;     S += 4
1869  * 0111 copy string                             *(LPSTR*)D = seg dup(*(LPSTR*)S)     D += 4;     S += 4
1870  * 1xxx copy xxx + 1 bytes                      memcpy(D, S, xxx + 1);               D += xxx+1; S += xxx+1
1871  */
1872
1873 /**************************************************************************
1874  *                      MCI_MsgMapper32ATo16_Create             [internal]
1875  *
1876  * Helper for MCI_MapMsg32ATo16.
1877  * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit
1878  * segmented pointer.
1879  * map contains a list of action to be performed for the mapping (see list
1880  * above)
1881  * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
1882  */
1883 static  WINMM_MapType   MCI_MsgMapper32ATo16_Create(void** ptr, int size16, DWORD map, BOOLEAN keep)
1884 {
1885     void*       lp = HeapAlloc( GetProcessHeap(), 0, (keep ? sizeof(void**) : 0) + size16 );
1886     LPBYTE      p16, p32;
1887
1888     if (!lp) {
1889         return WINMM_MAP_NOMEM;
1890     }
1891     p32 = (LPBYTE)(*ptr);
1892     if (keep) {
1893         *(void**)lp = *ptr;
1894         p16 = (LPBYTE)lp + sizeof(void**);
1895         *ptr = (char*)MapLS(lp) + sizeof(void**);
1896     } else {
1897         p16 = lp;
1898         *ptr = (void*)MapLS(lp);
1899     }
1900
1901     if (map == 0) {
1902         memcpy(p16, p32, size16);
1903     } else {
1904         unsigned        nibble;
1905         unsigned        sz;
1906
1907         while (map & 0xF) {
1908             nibble = map & 0xF;
1909             if (nibble & 0x8) {
1910                 sz = (nibble & 7) + 1;
1911                 memcpy(p16, p32, sz);
1912                 p16 += sz;
1913                 p32 += sz;
1914                 size16 -= sz;   /* DEBUG only */
1915             } else {
1916                 switch (nibble) {
1917                 case 0x1:
1918                     *(LPINT16)p16 = *(LPINT)p32;
1919                     p16 += sizeof(INT16);
1920                     p32 += sizeof(INT);
1921                     size16 -= sizeof(INT16);
1922                     break;
1923                 case 0x2:
1924                     *(LPUINT16)p16 = *(LPUINT)p32;
1925                     p16 += sizeof(UINT16);
1926                     p32 += sizeof(UINT);
1927                     size16 -= sizeof(UINT16);
1928                     break;
1929                 case 0x6:
1930                     *(LPDWORD)p16 = 0;
1931                     p16 += sizeof(DWORD);
1932                     p32 += sizeof(DWORD);
1933                     size16 -= sizeof(DWORD);
1934                     break;
1935                 case 0x7:
1936                     *(SEGPTR *)p16 = MapLS( *(LPSTR *)p32 );
1937                     p16 += sizeof(SEGPTR);
1938                     p32 += sizeof(LPSTR);
1939                     size16 -= sizeof(SEGPTR);
1940                     break;
1941                 default:
1942                     FIXME("Unknown nibble for mapping (%x)\n", nibble);
1943                 }
1944             }
1945             map >>= 4;
1946         }
1947         if (size16 != 0) /* DEBUG only */
1948             FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
1949     }
1950     return WINMM_MAP_OKMEM;
1951 }
1952
1953 /**************************************************************************
1954  *                      MCI_MsgMapper32ATo16_Destroy            [internal]
1955  *
1956  * Helper for MCI_UnMapMsg32ATo16.
1957  */
1958 static  WINMM_MapType   MCI_MsgMapper32ATo16_Destroy(void* ptr, int size16, DWORD map, BOOLEAN kept)
1959 {
1960     if (ptr) {
1961         void*           msg16 = MapSL((SEGPTR)ptr);
1962         void*           alloc;
1963         LPBYTE          p32, p16;
1964         unsigned        nibble;
1965
1966         UnMapLS( (SEGPTR)ptr );
1967         if (kept) {
1968             alloc = (char*)msg16 - sizeof(void**);
1969             p32 = *(void**)alloc;
1970             p16 = msg16;
1971
1972             if (map == 0) {
1973                 memcpy(p32, p16, size16);
1974             } else {
1975                 while (map & 0xF) {
1976                     nibble = map & 0xF;
1977                     if (nibble & 0x8) {
1978                         memcpy(p32, p16, (nibble & 7) + 1);
1979                         p16 += (nibble & 7) + 1;
1980                         p32 += (nibble & 7) + 1;
1981                         size16 -= (nibble & 7) + 1;
1982                     } else {
1983                         switch (nibble) {
1984                         case 0x1:
1985                             *(LPINT)p32 = *(LPINT16)p16;
1986                             p16 += sizeof(INT16);
1987                             p32 += sizeof(INT);
1988                             size16 -= sizeof(INT16);
1989                             break;
1990                         case 0x2:
1991                             *(LPUINT)p32 = *(LPUINT16)p16;
1992                             p16 += sizeof(UINT16);
1993                             p32 += sizeof(UINT);
1994                             size16 -= sizeof(UINT16);
1995                             break;
1996                         case 0x6:
1997                             p16 += sizeof(UINT);
1998                             p32 += sizeof(UINT);
1999                             size16 -= sizeof(UINT);
2000                             break;
2001                         case 0x7:
2002                             UnMapLS( *(SEGPTR *)p16 );
2003                             p16 += sizeof(SEGPTR);
2004                             p32 += sizeof(char*);
2005                             size16 -= sizeof(SEGPTR);
2006                             break;
2007                         default:
2008                             FIXME("Unknown nibble for mapping (%x)\n", nibble);
2009                         }
2010                     }
2011                     map >>= 4;
2012                 }
2013                 if (size16 != 0) /* DEBUG only */
2014                     FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
2015             }
2016         } else {
2017             alloc = msg16;
2018         }
2019
2020         HeapFree( GetProcessHeap(), 0, alloc );
2021     }
2022     return WINMM_MAP_OK;
2023 }
2024
2025 /**************************************************************************
2026  *                      MCI_MapMsg32ATo16                       [internal]
2027  *
2028  * Map a 32-A bit MCI message to a 16 bit MCI message.
2029  */
2030 static  WINMM_MapType   MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
2031 {
2032     int         size;
2033     BOOLEAN     keep = FALSE;
2034     DWORD       map = 0;
2035
2036     if (*lParam == 0)
2037         return WINMM_MAP_OK;
2038
2039     /* FIXME: to add also (with seg/linear modifications to do):
2040      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
2041      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
2042      */
2043     switch (wMsg) {
2044     case MCI_BREAK:
2045         size = sizeof(MCI_BREAK_PARMS);
2046         break;
2047         /* case MCI_CAPTURE */
2048     case MCI_CLOSE:
2049     case MCI_CLOSE_DRIVER:
2050     case MCI_CONFIGURE:
2051         size = sizeof(MCI_GENERIC_PARMS);
2052         break;
2053         /* case MCI_COPY: */
2054     case MCI_CUE:
2055         switch (uDevType) {
2056         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_CUE_PARMS);       break;
2057         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_CUE_PARMS);     break;*/        FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2058         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2059         }
2060         break;
2061         /* case MCI_CUT:*/
2062     case MCI_DELETE:
2063         switch (uDevType) {
2064         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_DELETE_PARMS16);  map = 0x0F1111FB;       break;
2065         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_DELETE_PARMS);   break;
2066         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2067         }
2068         break;
2069         /* case MCI_ESCAPE: */
2070     case MCI_FREEZE:
2071         switch (uDevType) {
2072         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_FREEZE_PARMS);    map = 0x0001111B;       break;
2073         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
2074         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2075         }
2076         break;
2077     case MCI_GETDEVCAPS:
2078         keep = TRUE;
2079         size = sizeof(MCI_GETDEVCAPS_PARMS);
2080         break;
2081         /* case MCI_INDEX: */
2082     case MCI_INFO:
2083         {
2084             LPMCI_INFO_PARMSA   mip32a = (LPMCI_INFO_PARMSA)(*lParam);
2085             LPMCI_INFO_PARMS16  mip16;
2086
2087             switch (uDevType) {
2088             case MCI_DEVTYPE_DIGITAL_VIDEO:     size = sizeof(MCI_DGV_INFO_PARMS16);    break;
2089             default:                            size = sizeof(MCI_INFO_PARMS16);        break;
2090             }
2091             mip16 = HeapAlloc( GetProcessHeap(), 0, size);
2092             if (mip16)
2093             {
2094                 mip16->dwCallback  = mip32a->dwCallback;
2095                 mip16->lpstrReturn = MapLS( mip32a->lpstrReturn );
2096                 mip16->dwRetSize   = mip32a->dwRetSize;
2097                 if (uDevType == MCI_DEVTYPE_DIGITAL_VIDEO) {
2098                     ((LPMCI_DGV_INFO_PARMS16)mip16)->dwItem = ((LPMCI_DGV_INFO_PARMSA)mip32a)->dwItem;
2099                 }
2100             } else {
2101                 return WINMM_MAP_NOMEM;
2102             }
2103             *lParam = MapLS(mip16);
2104         }
2105         return WINMM_MAP_OKMEM;
2106         /* case MCI_MARK: */
2107         /* case MCI_MONITOR: */
2108     case MCI_OPEN:
2109     case MCI_OPEN_DRIVER:
2110         {
2111             LPMCI_OPEN_PARMSA   mop32a = (LPMCI_OPEN_PARMSA)(*lParam);
2112             char* ptr = HeapAlloc( GetProcessHeap(), 0,
2113                                    sizeof(LPMCI_OPEN_PARMSA) + sizeof(MCI_OPEN_PARMS16) + 2 * sizeof(DWORD));
2114             LPMCI_OPEN_PARMS16  mop16;
2115
2116
2117             if (ptr) {
2118                 *(LPMCI_OPEN_PARMSA*)(ptr) = mop32a;
2119                 mop16 = (LPMCI_OPEN_PARMS16)(ptr + sizeof(LPMCI_OPEN_PARMSA));
2120                 mop16->dwCallback       = mop32a->dwCallback;
2121                 mop16->wDeviceID        = mop32a->wDeviceID;
2122                 if (dwFlags & MCI_OPEN_TYPE) {
2123                     if (dwFlags & MCI_OPEN_TYPE_ID) {
2124                         /* dword "transparent" value */
2125                         mop16->lpstrDeviceType = (SEGPTR)mop32a->lpstrDeviceType;
2126                     } else {
2127                         /* string */
2128                         mop16->lpstrDeviceType = MapLS( mop32a->lpstrDeviceType );
2129                     }
2130                 } else {
2131                     /* nuthin' */
2132                     mop16->lpstrDeviceType = 0;
2133                 }
2134                 if (dwFlags & MCI_OPEN_ELEMENT) {
2135                     if (dwFlags & MCI_OPEN_ELEMENT_ID) {
2136                         mop16->lpstrElementName = (SEGPTR)mop32a->lpstrElementName;
2137                     } else {
2138                         mop16->lpstrElementName = MapLS( mop32a->lpstrElementName );
2139                     }
2140                 } else {
2141                     mop16->lpstrElementName = 0;
2142                 }
2143                 if (dwFlags & MCI_OPEN_ALIAS) {
2144                     mop16->lpstrAlias = MapLS( mop32a->lpstrAlias );
2145                 } else {
2146                     mop16->lpstrAlias = 0;
2147                 }
2148                 /* copy extended information if any...
2149                  * FIXME: this may seg fault if initial structure does not contain them and
2150                  * the reads after msip16 fail under LDT limits...
2151                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
2152                  * should not take care of extended parameters, and should be used by MCI_Open
2153                  * to fetch uDevType. When, this is known, the mapping for sending the
2154                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
2155                  */
2156                 memcpy(mop16 + 1, mop32a + 1, 2 * sizeof(DWORD));
2157             } else {
2158                 return WINMM_MAP_NOMEM;
2159             }
2160             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_PARMSA);
2161         }
2162         return WINMM_MAP_OKMEM;
2163         /* case MCI_PASTE:*/
2164     case MCI_PAUSE:
2165         size = sizeof(MCI_GENERIC_PARMS);
2166         break;
2167     case MCI_PLAY:
2168         size = sizeof(MCI_PLAY_PARMS);
2169         break;
2170     case MCI_PUT:
2171         switch (uDevType) {
2172         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
2173         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
2174         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2175         }
2176         break;
2177     case MCI_REALIZE:
2178         size = sizeof(MCI_GENERIC_PARMS);
2179         break;
2180     case MCI_RECORD:
2181         switch (uDevType) {
2182         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECORD_PARMS16);  map = 0x0F1111FB;       break;
2183         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_RECORD_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2184         default:                        size = sizeof(MCI_RECORD_PARMS);        break;
2185         }
2186         break;
2187     case MCI_RESUME:
2188         size = sizeof(MCI_GENERIC_PARMS);
2189         break;
2190     case MCI_SEEK:
2191         switch (uDevType) {
2192         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SEEK_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2193         default:                        size = sizeof(MCI_SEEK_PARMS);          break;
2194         }
2195         break;
2196     case MCI_SET:
2197         switch (uDevType) {
2198         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SET_PARMS);       break;
2199         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SET_PARMS);     break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2200         case MCI_DEVTYPE_SEQUENCER:     size = sizeof(MCI_SEQ_SET_PARMS);       break;
2201         /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
2202          * so not doing anything should work...
2203          */
2204         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_SET_PARMS);      break;
2205         default:                        size = sizeof(MCI_SET_PARMS);           break;
2206         }
2207         break;
2208     case MCI_SETAUDIO:
2209         switch (uDevType) {
2210         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SETAUDIO_PARMS16);map = 0x0000077FF;      break;
2211         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2212         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2213         }
2214         break;
2215         /* case MCI_SETTIMECODE:*/
2216         /* case MCI_SIGNAL:*/
2217         /* case MCI_SOUND:*/
2218     case MCI_SPIN:
2219         size = sizeof(MCI_SET_PARMS);
2220         break;
2221     case MCI_STATUS:
2222         keep = TRUE;
2223         switch (uDevType) {
2224         /* FIXME:
2225          * don't know if buffer for value is the one passed through lpstrDevice
2226          * or is provided by MCI driver.
2227          * Assuming solution 2: provided by MCI driver, so zeroing on entry
2228          */
2229         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16);  map = 0x0B6FF;          break;
2230         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2231         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
2232         }
2233         break;
2234     case MCI_STEP:
2235         switch (uDevType) {
2236         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STEP_PARMS);      break;
2237         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STEP_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2238         case MCI_DEVTYPE_VIDEODISC:     size = sizeof(MCI_VD_STEP_PARMS);       break;
2239         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2240         }
2241         break;
2242     case MCI_STOP:
2243         size = sizeof(MCI_SET_PARMS);
2244         break;
2245     case MCI_SYSINFO:
2246         {
2247             LPMCI_SYSINFO_PARMSA  msip32a = (LPMCI_SYSINFO_PARMSA)(*lParam);
2248             LPMCI_SYSINFO_PARMS16 msip16;
2249             char* ptr = HeapAlloc( GetProcessHeap(), 0,
2250                                    sizeof(LPMCI_SYSINFO_PARMSA) + sizeof(MCI_SYSINFO_PARMS16) );
2251
2252             if (ptr) {
2253                 *(LPMCI_SYSINFO_PARMSA*)(ptr) = msip32a;
2254                 msip16 = (LPMCI_SYSINFO_PARMS16)(ptr + sizeof(LPMCI_SYSINFO_PARMSA));
2255
2256                 msip16->dwCallback       = msip32a->dwCallback;
2257                 msip16->lpstrReturn      = MapLS( msip32a->lpstrReturn );
2258                 msip16->dwRetSize        = msip32a->dwRetSize;
2259                 msip16->dwNumber         = msip32a->dwNumber;
2260                 msip16->wDeviceType      = msip32a->wDeviceType;
2261             } else {
2262                 return WINMM_MAP_NOMEM;
2263             }
2264             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_SYSINFO_PARMSA);
2265         }
2266         return WINMM_MAP_OKMEM;
2267         /* case MCI_UNDO: */
2268     case MCI_UNFREEZE:
2269         switch (uDevType) {
2270         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
2271         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       break;
2272         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2273         }
2274         break;
2275     case MCI_UPDATE:
2276         switch (uDevType) {
2277         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_UPDATE_PARMS16);  map = 0x000B1111B;      break;
2278         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2279         }
2280         break;
2281     case MCI_WHERE:
2282         switch (uDevType) {
2283         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       keep = TRUE;    break;
2284         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       keep = TRUE;    break;
2285         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2286         }
2287         break;
2288     case MCI_WINDOW:
2289         switch (uDevType) {
2290         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7FB;        break;
2291         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7FB;        break;
2292         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
2293         }
2294         break;
2295     case DRV_OPEN:
2296         {
2297             LPMCI_OPEN_DRIVER_PARMSA  modp32a = (LPMCI_OPEN_DRIVER_PARMSA)(*lParam);
2298             LPMCI_OPEN_DRIVER_PARMS16 modp16;
2299             char *ptr = HeapAlloc( GetProcessHeap(), 0,
2300                                    sizeof(LPMCI_OPEN_DRIVER_PARMSA) + sizeof(MCI_OPEN_DRIVER_PARMS16));
2301
2302             if (ptr) {
2303                 *(LPMCI_OPEN_DRIVER_PARMSA*)(ptr) = modp32a;
2304                 modp16 = (LPMCI_OPEN_DRIVER_PARMS16)(ptr + sizeof(LPMCI_OPEN_DRIVER_PARMSA));
2305                 modp16->wDeviceID = modp32a->wDeviceID;
2306                 modp16->lpstrParams = MapLS( modp32a->lpstrParams );
2307                 /* other fields are gonna be filled by the driver, don't copy them */
2308             } else {
2309                 return WINMM_MAP_NOMEM;
2310             }
2311             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_DRIVER_PARMSA);
2312         }
2313         return WINMM_MAP_OKMEM;
2314     case DRV_LOAD:
2315     case DRV_ENABLE:
2316     case DRV_CLOSE:
2317     case DRV_DISABLE:
2318     case DRV_FREE:
2319     case DRV_CONFIGURE:
2320     case DRV_QUERYCONFIGURE:
2321     case DRV_INSTALL:
2322     case DRV_REMOVE:
2323     case DRV_EXITSESSION:
2324     case DRV_EXITAPPLICATION:
2325     case DRV_POWER:
2326         return WINMM_MAP_OK;
2327
2328     default:
2329         FIXME("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
2330         return WINMM_MAP_MSGERROR;
2331     }
2332     return MCI_MsgMapper32ATo16_Create((void**)lParam, size, map, keep);
2333 }
2334
2335 /**************************************************************************
2336  *                      MCI_UnMapMsg32ATo16                     [internal]
2337  */
2338 static  WINMM_MapType   MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
2339 {
2340     int         size = 0;
2341     BOOLEAN     kept = FALSE;   /* there is no need to compute size when kept is FALSE */
2342     DWORD       map = 0;
2343
2344     switch (wMsg) {
2345     case MCI_BREAK:
2346         break;
2347         /* case MCI_CAPTURE */
2348     case MCI_CLOSE:
2349     case MCI_CLOSE_DRIVER:
2350     case MCI_CONFIGURE:
2351         break;
2352         /* case MCI_COPY: */
2353     case MCI_CUE:
2354         break;
2355         /* case MCI_CUT: */
2356     case MCI_DELETE:
2357         break;
2358         /* case MCI_ESCAPE: */
2359     case MCI_FREEZE:
2360         break;
2361     case MCI_GETDEVCAPS:
2362         kept = TRUE;
2363         size = sizeof(MCI_GETDEVCAPS_PARMS);
2364         break;
2365         /* case MCI_INDEX: */
2366     case MCI_INFO:
2367         {
2368             LPMCI_INFO_PARMS16 mip16  = (LPMCI_INFO_PARMS16)MapSL(lParam);
2369             UnMapLS( lParam );
2370             UnMapLS( mip16->lpstrReturn );
2371             HeapFree( GetProcessHeap(), 0, mip16 );
2372         }
2373         return WINMM_MAP_OK;
2374         /* case MCI_MARK: */
2375         /* case MCI_MONITOR: */
2376     case MCI_OPEN:
2377     case MCI_OPEN_DRIVER:
2378         if (lParam) {
2379             LPMCI_OPEN_PARMS16  mop16  = (LPMCI_OPEN_PARMS16)MapSL(lParam);
2380             LPMCI_OPEN_PARMSA   mop32a = *(LPMCI_OPEN_PARMSA*)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSA));
2381             UnMapLS( lParam );
2382             mop32a->wDeviceID = mop16->wDeviceID;
2383             if ((dwFlags & MCI_OPEN_TYPE) && !(dwFlags & MCI_OPEN_TYPE_ID))
2384                 UnMapLS( mop16->lpstrDeviceType );
2385             if ((dwFlags & MCI_OPEN_ELEMENT) && !(dwFlags & MCI_OPEN_ELEMENT_ID))
2386                 UnMapLS( mop16->lpstrElementName );
2387             if (dwFlags & MCI_OPEN_ALIAS)
2388                 UnMapLS( mop16->lpstrAlias );
2389             HeapFree( GetProcessHeap(), 0, (char*)mop16 - sizeof(LPMCI_OPEN_PARMSA) );
2390         }
2391         return WINMM_MAP_OK;
2392         /* case MCI_PASTE:*/
2393     case MCI_PAUSE:
2394         break;
2395     case MCI_PLAY:
2396         break;
2397     case MCI_PUT:
2398         break;
2399     case MCI_REALIZE:
2400         break;
2401     case MCI_RECORD:
2402         break;
2403     case MCI_RESUME:
2404         break;
2405     case MCI_SEEK:
2406         break;
2407     case MCI_SET:
2408         break;
2409     case MCI_SETAUDIO:
2410         switch (uDevType) {
2411         case MCI_DEVTYPE_DIGITAL_VIDEO: map = 0x0000077FF;      break;
2412         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2413         }
2414         break;
2415         /* case MCI_SETTIMECODE:*/
2416         /* case MCI_SIGNAL:*/
2417         /* case MCI_SOUND:*/
2418     case MCI_SPIN:
2419         break;
2420     case MCI_STATUS:
2421         kept = TRUE;
2422         switch (uDevType) {
2423         case MCI_DEVTYPE_DIGITAL_VIDEO:
2424         if (lParam) {
2425             LPMCI_DGV_STATUS_PARMS16    mdsp16  = (LPMCI_DGV_STATUS_PARMS16)MapSL(lParam);
2426             LPMCI_DGV_STATUS_PARMSA     mdsp32a = *(LPMCI_DGV_STATUS_PARMSA*)((char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA));
2427
2428             UnMapLS( lParam );
2429             if (mdsp16) {
2430                 mdsp32a->dwReturn = mdsp16->dwReturn;
2431                 if (dwFlags & MCI_DGV_STATUS_DISKSPACE) {
2432                     TRACE("MCI_STATUS (DGV) lpstrDrive=%08lx\n", mdsp16->lpstrDrive);
2433                     TRACE("MCI_STATUS (DGV) lpstrDrive=%s\n", (LPSTR)MapSL(mdsp16->lpstrDrive));
2434                     UnMapLS( mdsp16->lpstrDrive );
2435                 }
2436                 HeapFree( GetProcessHeap(), 0, (char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA) );
2437             } else {
2438                 return WINMM_MAP_NOMEM;
2439             }
2440         }
2441         return WINMM_MAP_OKMEM;
2442         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
2443         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
2444         }
2445         break;
2446     case MCI_STEP:
2447         break;
2448     case MCI_STOP:
2449         break;
2450     case MCI_SYSINFO:
2451         if (lParam) {
2452             LPMCI_SYSINFO_PARMS16       msip16  = (LPMCI_SYSINFO_PARMS16)MapSL(lParam);
2453             LPMCI_SYSINFO_PARMSA        msip32a = *(LPMCI_SYSINFO_PARMSA*)((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA));
2454
2455             UnMapLS( lParam );
2456             if (msip16) {
2457                 msip16->dwCallback = msip32a->dwCallback;
2458                 UnMapLS( msip16->lpstrReturn );
2459                 HeapFree( GetProcessHeap(), 0, (char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA) );
2460             } else {
2461                 return WINMM_MAP_NOMEM;
2462             }
2463         }
2464         return WINMM_MAP_OKMEM;
2465         /* case MCI_UNDO: */
2466     case MCI_UNFREEZE:
2467         break;
2468     case MCI_UPDATE:
2469         break;
2470     case MCI_WHERE:
2471         switch (uDevType) {
2472         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       kept = TRUE;    break;
2473         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       kept = TRUE;    break;
2474         default:                        break;
2475         }
2476         break;
2477     case MCI_WINDOW:
2478         switch (uDevType) {
2479         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7666;       break;
2480         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7666;       break;
2481         default:                        break;
2482         }
2483         /* FIXME: see map function */
2484         break;
2485
2486     case DRV_OPEN:
2487         if (lParam) {
2488             LPMCI_OPEN_DRIVER_PARMS16   modp16  = (LPMCI_OPEN_DRIVER_PARMS16)MapSL(lParam);
2489             LPMCI_OPEN_DRIVER_PARMSA    modp32a = *(LPMCI_OPEN_DRIVER_PARMSA*)((char*)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSA));
2490
2491             UnMapLS( lParam );
2492             modp32a->wCustomCommandTable = modp16->wCustomCommandTable;
2493             modp32a->wType = modp16->wType;
2494             UnMapLS( modp16->lpstrParams );
2495             HeapFree( GetProcessHeap(), 0, (char *)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSA) );
2496         }
2497         return WINMM_MAP_OK;
2498     case DRV_LOAD:
2499     case DRV_ENABLE:
2500     case DRV_CLOSE:
2501     case DRV_DISABLE:
2502     case DRV_FREE:
2503     case DRV_CONFIGURE:
2504     case DRV_QUERYCONFIGURE:
2505     case DRV_INSTALL:
2506     case DRV_REMOVE:
2507     case DRV_EXITSESSION:
2508     case DRV_EXITAPPLICATION:
2509     case DRV_POWER:
2510         FIXME("This is a hack\n");
2511         return WINMM_MAP_OK;
2512     default:
2513         FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
2514         return WINMM_MAP_MSGERROR;
2515     }
2516     return MCI_MsgMapper32ATo16_Destroy((void*)lParam, size, map, kept);
2517 }
2518 #endif
2519
2520 /**************************************************************************
2521  *                      MCI_MapMsg16To32W                       [internal]
2522  */
2523 static WINMM_MapType    MCI_MapMsg16To32W(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD_PTR* lParam)
2524 {
2525     if (*lParam == 0)
2526         return WINMM_MAP_OK;
2527     /* FIXME: to add also (with seg/linear modifications to do):
2528      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
2529      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
2530      */
2531     switch (wMsg) {
2532         /* case MCI_CAPTURE */
2533     case MCI_CLOSE:
2534     case MCI_CLOSE_DRIVER:
2535     case MCI_CONFIGURE:
2536     case MCI_COPY:
2537     case MCI_CUE:
2538     case MCI_CUT:
2539     case MCI_DELETE:
2540     case MCI_FREEZE:
2541     case MCI_GETDEVCAPS:
2542         /* case MCI_INDEX: */
2543         /* case MCI_MARK: */
2544         /* case MCI_MONITOR: */
2545     case MCI_PASTE:
2546     case MCI_PAUSE:
2547     case MCI_PLAY:
2548     case MCI_PUT:
2549     case MCI_REALIZE:
2550     case MCI_RECORD:
2551     case MCI_RESUME:
2552     case MCI_SEEK:
2553     case MCI_SET:
2554         /* case MCI_SETTIMECODE:*/
2555         /* case MCI_SIGNAL:*/
2556     case MCI_SPIN:
2557     case MCI_STATUS:            /* FIXME: is wrong for digital video */
2558     case MCI_STEP:
2559     case MCI_STOP:
2560         /* case MCI_UNDO: */
2561     case MCI_UNFREEZE:
2562     case MCI_UPDATE:
2563     case MCI_WHERE:
2564         *lParam = (DWORD)MapSL(*lParam);
2565         return WINMM_MAP_OK;
2566     case MCI_WINDOW:
2567         /* in fact, I would also need the dwFlags... to see
2568          * which members of lParam are effectively used
2569          */
2570         *lParam = (DWORD)MapSL(*lParam);
2571         FIXME("Current mapping may be wrong\n");
2572         break;
2573     case MCI_BREAK:
2574         {
2575             LPMCI_BREAK_PARMS           mbp32 = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_BREAK_PARMS));
2576             LPMCI_BREAK_PARMS16         mbp16 = MapSL(*lParam);
2577
2578             if (mbp32) {
2579                 mbp32->dwCallback = mbp16->dwCallback;
2580                 mbp32->nVirtKey = mbp16->nVirtKey;
2581                 mbp32->hwndBreak = HWND_32(mbp16->hwndBreak);
2582             } else {
2583                 return WINMM_MAP_NOMEM;
2584             }
2585             *lParam = (DWORD)mbp32;
2586         }
2587         return WINMM_MAP_OKMEM;
2588     case MCI_ESCAPE:
2589         {
2590             LPMCI_VD_ESCAPE_PARMSW      mvep32w = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_VD_ESCAPE_PARMSW));
2591             LPMCI_VD_ESCAPE_PARMS16     mvep16  = MapSL(*lParam);
2592
2593             if (mvep32w) {
2594                 mvep32w->dwCallback       = mvep16->dwCallback;
2595                 mvep32w->lpstrCommand     = MCI_strdupAtoW(MapSL(mvep16->lpstrCommand));
2596             } else {
2597                 return WINMM_MAP_NOMEM;
2598             }
2599             *lParam = (DWORD)mvep32w;
2600         }
2601         return WINMM_MAP_OKMEM;
2602     case MCI_INFO:
2603         {
2604             LPMCI_INFO_PARMSW   mip32w = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_INFO_PARMSW));
2605             LPMCI_INFO_PARMS16  mip16  = MapSL(*lParam);
2606
2607             /* FIXME this is wrong if device is of type
2608              * MCI_DEVTYPE_DIGITAL_VIDEO, some members are not mapped
2609              */
2610             if (mip32w) {
2611                 *(LPMCI_INFO_PARMS16*)(mip32w) = mip16;
2612                 mip32w = (LPMCI_INFO_PARMSW)((char*)mip32w + sizeof(LPMCI_INFO_PARMS16));
2613                 mip32w->dwCallback  = mip16->dwCallback;
2614                 mip32w->lpstrReturn = HeapAlloc(GetProcessHeap(), 0, mip16->dwRetSize * sizeof(WCHAR));
2615                 mip32w->dwRetSize   = mip16->dwRetSize * sizeof(WCHAR);
2616             } else {
2617                 return WINMM_MAP_NOMEM;
2618             }
2619             *lParam = (DWORD)mip32w;
2620         }
2621         return WINMM_MAP_OKMEM;
2622     case MCI_OPEN:
2623     case MCI_OPEN_DRIVER:
2624         {
2625             LPMCI_OPEN_PARMSW   mop32w = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_OPEN_PARMSW) + 2 * sizeof(DWORD));
2626             LPMCI_OPEN_PARMS16  mop16  = MapSL(*lParam);
2627
2628             if (mop32w) {
2629                 *(LPMCI_OPEN_PARMS16*)(mop32w) = mop16;
2630                 mop32w = (LPMCI_OPEN_PARMSW)((char*)mop32w + sizeof(LPMCI_OPEN_PARMS16));
2631                 mop32w->dwCallback       = mop16->dwCallback;
2632                 mop32w->wDeviceID        = mop16->wDeviceID;
2633                 if( ( dwFlags & ( MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID)) == MCI_OPEN_TYPE)
2634                     mop32w->lpstrDeviceType  = MCI_strdupAtoW(MapSL(mop16->lpstrDeviceType));
2635                 else
2636                     mop32w->lpstrDeviceType  = (LPWSTR) mop16->lpstrDeviceType;
2637                 if( ( dwFlags & ( MCI_OPEN_ELEMENT | MCI_OPEN_ELEMENT_ID)) == MCI_OPEN_ELEMENT)
2638                     mop32w->lpstrElementName = MCI_strdupAtoW(MapSL(mop16->lpstrElementName));
2639                 else
2640                     mop32w->lpstrElementName = (LPWSTR) mop16->lpstrElementName;
2641                 if( ( dwFlags &  MCI_OPEN_ALIAS))
2642                     mop32w->lpstrAlias = MCI_strdupAtoW(MapSL(mop16->lpstrAlias));
2643                 else
2644                     mop32w->lpstrAlias = (LPWSTR) mop16->lpstrAlias;
2645                 /* copy extended information if any...
2646                  * FIXME: this may seg fault if initial structure does not contain them and
2647                  * the reads after msip16 fail under LDT limits...
2648                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
2649                  * should not take care of extended parameters, and should be used by MCI_Open
2650                  * to fetch uDevType. When, this is known, the mapping for sending the
2651                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
2652                  */
2653                 memcpy(mop32w + 1, mop16 + 1, 2 * sizeof(DWORD));
2654             } else {
2655                 return WINMM_MAP_NOMEM;
2656             }
2657             *lParam = (DWORD)mop32w;
2658         }
2659         return WINMM_MAP_OKMEM;
2660     case MCI_SYSINFO:
2661         {
2662             LPMCI_SYSINFO_PARMSW        msip32w = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_SYSINFO_PARMSW));
2663             LPMCI_SYSINFO_PARMS16       msip16  = MapSL(*lParam);
2664
2665             if (msip32w) {
2666                 *(LPMCI_SYSINFO_PARMS16*)(msip32w) = msip16;
2667                 msip32w = (LPMCI_SYSINFO_PARMSW)((char*)msip32w + sizeof(LPMCI_OPEN_PARMS16));
2668                 msip32w->dwCallback       = msip16->dwCallback;
2669                 msip32w->lpstrReturn      = HeapAlloc(GetProcessHeap(), 0, msip16->dwRetSize * sizeof(WCHAR));
2670                 msip32w->dwRetSize        = msip16->dwRetSize;
2671                 msip32w->dwNumber         = msip16->dwNumber;
2672                 msip32w->wDeviceType      = msip16->wDeviceType;
2673             } else {
2674                 return WINMM_MAP_NOMEM;
2675             }
2676             *lParam = (DWORD)msip32w;
2677         }
2678         return WINMM_MAP_OKMEM;
2679     case MCI_SOUND:
2680         {
2681             LPMCI_SOUND_PARMSW          mbp32 = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_SOUND_PARMSW));
2682             LPMCI_SOUND_PARMS16         mbp16 = MapSL(*lParam);
2683
2684             if (mbp32) {
2685                 mbp32->dwCallback = mbp16->dwCallback;
2686                 mbp32->lpstrSoundName = MCI_strdupAtoW(MapSL(mbp16->lpstrSoundName));
2687             } else {
2688                 return WINMM_MAP_NOMEM;
2689             }
2690             *lParam = (DWORD)mbp32;
2691         }
2692         return WINMM_MAP_OKMEM;
2693     case DRV_LOAD:
2694     case DRV_ENABLE:
2695     case DRV_OPEN:
2696     case DRV_CLOSE:
2697     case DRV_DISABLE:
2698     case DRV_FREE:
2699     case DRV_CONFIGURE:
2700     case DRV_QUERYCONFIGURE:
2701     case DRV_INSTALL:
2702     case DRV_REMOVE:
2703     case DRV_EXITSESSION:
2704     case DRV_EXITAPPLICATION:
2705     case DRV_POWER:
2706         FIXME("This is a hack\n");
2707         return WINMM_MAP_OK;
2708     default:
2709         FIXME("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
2710     }
2711     return WINMM_MAP_MSGERROR;
2712 }
2713
2714 /**************************************************************************
2715  *                      MCI_UnMapMsg16To32W                     [internal]
2716  */
2717 static  WINMM_MapType   MCI_UnMapMsg16To32W(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD_PTR lParam)
2718 {
2719     switch (wMsg) {
2720         /* case MCI_CAPTURE */
2721     case MCI_CLOSE:
2722     case MCI_CLOSE_DRIVER:
2723     case MCI_CONFIGURE:
2724     case MCI_COPY:
2725     case MCI_CUE:
2726     case MCI_CUT:
2727     case MCI_DELETE:
2728     case MCI_FREEZE:
2729     case MCI_GETDEVCAPS:
2730         /* case MCI_INDEX: */
2731         /* case MCI_MARK: */
2732         /* case MCI_MONITOR: */
2733     case MCI_PASTE:
2734     case MCI_PAUSE:
2735     case MCI_PLAY:
2736     case MCI_PUT:
2737     case MCI_REALIZE:
2738     case MCI_RECORD:
2739     case MCI_RESUME:
2740     case MCI_SEEK:
2741     case MCI_SET:
2742         /* case MCI_SETTIMECODE:*/
2743         /* case MCI_SIGNAL:*/
2744     case MCI_SPIN:
2745     case MCI_STATUS:
2746     case MCI_STEP:
2747     case MCI_STOP:
2748         /* case MCI_UNDO: */
2749     case MCI_UNFREEZE:
2750     case MCI_UPDATE:
2751     case MCI_WHERE:
2752         return WINMM_MAP_OK;
2753
2754     case MCI_WINDOW:
2755         /* FIXME ?? see Map function */
2756         return WINMM_MAP_OK;
2757
2758     case MCI_BREAK:
2759         HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2760         return WINMM_MAP_OK;
2761     case MCI_ESCAPE:
2762         if (lParam) {
2763             LPMCI_VD_ESCAPE_PARMSW      mvep32W = (LPMCI_VD_ESCAPE_PARMSW)lParam;
2764             HeapFree(GetProcessHeap(), 0, (LPVOID)mvep32W->lpstrCommand);
2765             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2766         }
2767         return WINMM_MAP_OK;
2768     case MCI_INFO:
2769         if (lParam) {
2770             LPMCI_INFO_PARMSW           mip32w = (LPMCI_INFO_PARMSW)lParam;
2771             LPMCI_INFO_PARMS16          mip16  = *(LPMCI_INFO_PARMS16*)((char*)mip32w - sizeof(LPMCI_INFO_PARMS16));
2772
2773             WideCharToMultiByte(CP_ACP, 0,
2774                                 mip32w->lpstrReturn, mip32w->dwRetSize / sizeof(WCHAR),
2775                                 MapSL(mip16->lpstrReturn), mip16->dwRetSize,
2776                                 NULL, NULL);
2777             HeapFree(GetProcessHeap(), 0, (LPVOID)mip32w->lpstrReturn);
2778             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2779         }
2780         return WINMM_MAP_OK;
2781     case MCI_SYSINFO:
2782         if (lParam) {
2783             LPMCI_SYSINFO_PARMSW           msip32w = (LPMCI_SYSINFO_PARMSW)lParam;
2784             LPMCI_SYSINFO_PARMS16          msip16  = *(LPMCI_SYSINFO_PARMS16*)((char*)msip32w - sizeof(LPMCI_SYSINFO_PARMS16));
2785
2786             WideCharToMultiByte(CP_ACP, 0,
2787                                 msip32w->lpstrReturn, msip32w->dwRetSize,
2788                                 MapSL(msip16->lpstrReturn), msip16->dwRetSize,
2789                                 NULL, NULL);
2790             HeapFree(GetProcessHeap(), 0, (LPVOID)msip32w->lpstrReturn);
2791             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2792         }
2793         return WINMM_MAP_OK;
2794     case MCI_SOUND:
2795         if (lParam) {
2796             LPMCI_SOUND_PARMSW          msp32W = (LPMCI_SOUND_PARMSW)lParam;
2797             HeapFree(GetProcessHeap(), 0, (LPVOID)msp32W->lpstrSoundName);
2798             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2799         }
2800         return WINMM_MAP_OK;
2801     case MCI_OPEN:
2802     case MCI_OPEN_DRIVER:
2803         if (lParam) {
2804             LPMCI_OPEN_PARMSW   mop32w = (LPMCI_OPEN_PARMSW)lParam;
2805             LPMCI_OPEN_PARMS16  mop16  = *(LPMCI_OPEN_PARMS16*)((char*)mop32w - sizeof(LPMCI_OPEN_PARMS16));
2806
2807             mop16->wDeviceID = mop32w->wDeviceID;
2808             if( ( dwFlags & ( MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID)) == MCI_OPEN_TYPE)
2809                 HeapFree(GetProcessHeap(), 0, (LPWSTR)mop32w->lpstrDeviceType);
2810             if( ( dwFlags & ( MCI_OPEN_ELEMENT | MCI_OPEN_ELEMENT_ID)) == MCI_OPEN_ELEMENT)
2811                 HeapFree(GetProcessHeap(), 0, (LPWSTR)mop32w->lpstrElementName);
2812             if( ( dwFlags &  MCI_OPEN_ALIAS))
2813                 HeapFree(GetProcessHeap(), 0, (LPWSTR)mop32w->lpstrAlias);
2814             if (!HeapFree(GetProcessHeap(), 0, (LPVOID)(lParam - sizeof(LPMCI_OPEN_PARMS16))))
2815                 FIXME("bad free line=%d\n", __LINE__);
2816         }
2817         return WINMM_MAP_OK;
2818     case DRV_LOAD:
2819     case DRV_ENABLE:
2820     case DRV_OPEN:
2821     case DRV_CLOSE:
2822     case DRV_DISABLE:
2823     case DRV_FREE:
2824     case DRV_CONFIGURE:
2825     case DRV_QUERYCONFIGURE:
2826     case DRV_INSTALL:
2827     case DRV_REMOVE:
2828     case DRV_EXITSESSION:
2829     case DRV_EXITAPPLICATION:
2830     case DRV_POWER:
2831         FIXME("This is a hack\n");
2832         return WINMM_MAP_OK;
2833     default:
2834         FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
2835     }
2836     return WINMM_MAP_MSGERROR;
2837 }
2838
2839 /*
2840  * 0000 stop
2841  * 0001 squeeze   signed 4 bytes to 2 bytes     *( LPINT16)D = ( INT16)*( LPINT16)S; D += 2;     S += 4
2842  * 0010 squeeze unsigned 4 bytes to 2 bytes     *(LPUINT16)D = (UINT16)*(LPUINT16)S; D += 2;     S += 4
2843  * 0100
2844  * 0101
2845  * 0110 zero 4 bytes                            *(DWORD)D = 0                        D += 4;     S += 4
2846  * 0111 copy string                             *(LPSTR*)D = seg dup(*(LPSTR*)S)     D += 4;     S += 4
2847  * 1xxx copy xxx + 1 bytes                      memcpy(D, S, xxx + 1);               D += xxx+1; S += xxx+1
2848  */
2849
2850 /**************************************************************************
2851  *                      MCI_MsgMapper32WTo16_Create             [internal]
2852  *
2853  * Helper for MCI_MapMsg32WTo16.
2854  * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit
2855  * segmented pointer.
2856  * map contains a list of action to be performed for the mapping (see list
2857  * above)
2858  * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
2859  */
2860 static  WINMM_MapType   MCI_MsgMapper32WTo16_Create(void** ptr, int size16, DWORD map, BOOLEAN keep)
2861 {
2862     void*       lp = HeapAlloc( GetProcessHeap(), 0, (keep ? sizeof(void**) : 0) + size16 );
2863     LPBYTE      p16, p32;
2864
2865     if (!lp) {
2866         return WINMM_MAP_NOMEM;
2867     }
2868     p32 = (LPBYTE)(*ptr);
2869     if (keep) {
2870         *(void**)lp = *ptr;
2871         p16 = (LPBYTE)lp + sizeof(void**);
2872         *ptr = (char*)MapLS(lp) + sizeof(void**);
2873     } else {
2874         p16 = lp;
2875         *ptr = (void*)MapLS(lp);
2876     }
2877
2878     if (map == 0) {
2879         memcpy(p16, p32, size16);
2880     } else {
2881         unsigned        nibble;
2882         unsigned        sz;
2883
2884         while (map & 0xF) {
2885             nibble = map & 0xF;
2886             if (nibble & 0x8) {
2887                 sz = (nibble & 7) + 1;
2888                 memcpy(p16, p32, sz);
2889                 p16 += sz;
2890                 p32 += sz;
2891                 size16 -= sz;   /* DEBUG only */
2892             } else {
2893                 switch (nibble) {
2894                 case 0x1:
2895                     *(LPINT16)p16 = *(LPINT)p32;
2896                     p16 += sizeof(INT16);
2897                     p32 += sizeof(INT);
2898                     size16 -= sizeof(INT16);
2899                     break;
2900                 case 0x2:
2901                     *(LPUINT16)p16 = *(LPUINT)p32;
2902                     p16 += sizeof(UINT16);
2903                     p32 += sizeof(UINT);
2904                     size16 -= sizeof(UINT16);
2905                     break;
2906                 case 0x6:
2907                     *(LPDWORD)p16 = 0;
2908                     p16 += sizeof(DWORD);
2909                     p32 += sizeof(DWORD);
2910                     size16 -= sizeof(DWORD);
2911                     break;
2912                 case 0x7:
2913                     *(SEGPTR *)p16 = MapLS( MCI_strdupWtoA( *(LPCWSTR *)p32 ) );
2914                     p16 += sizeof(SEGPTR);
2915                     p32 += sizeof(LPSTR);
2916                     size16 -= sizeof(SEGPTR);
2917                     break;
2918                 default:
2919                     FIXME("Unknown nibble for mapping (%x)\n", nibble);
2920                 }
2921             }
2922             map >>= 4;
2923         }
2924         if (size16 != 0) /* DEBUG only */
2925             FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
2926     }
2927     return WINMM_MAP_OKMEM;
2928 }
2929
2930 /**************************************************************************
2931  *                      MCI_MsgMapper32WTo16_Destroy            [internal]
2932  *
2933  * Helper for MCI_UnMapMsg32WTo16.
2934  */
2935 static  WINMM_MapType   MCI_MsgMapper32WTo16_Destroy(void* ptr, int size16, DWORD map, BOOLEAN kept)
2936 {
2937     if (ptr) {
2938         void*           msg16 = MapSL((SEGPTR)ptr);
2939         void*           alloc;
2940         LPBYTE          p32, p16;
2941         unsigned        nibble;
2942
2943         UnMapLS( (SEGPTR)ptr );
2944         if (kept) {
2945             alloc = (char*)msg16 - sizeof(void**);
2946             p32 = *(void**)alloc;
2947             p16 = msg16;
2948
2949             if (map == 0) {
2950                 memcpy(p32, p16, size16);
2951             } else {
2952                 while (map & 0xF) {
2953                     nibble = map & 0xF;
2954                     if (nibble & 0x8) {
2955                         memcpy(p32, p16, (nibble & 7) + 1);
2956                         p16 += (nibble & 7) + 1;
2957                         p32 += (nibble & 7) + 1;
2958                         size16 -= (nibble & 7) + 1;
2959                     } else {
2960                         switch (nibble) {
2961                         case 0x1:
2962                             *(LPINT)p32 = *(LPINT16)p16;
2963                             p16 += sizeof(INT16);
2964                             p32 += sizeof(INT);
2965                             size16 -= sizeof(INT16);
2966                             break;
2967                         case 0x2:
2968                             *(LPUINT)p32 = *(LPUINT16)p16;
2969                             p16 += sizeof(UINT16);
2970                             p32 += sizeof(UINT);
2971                             size16 -= sizeof(UINT16);
2972                             break;
2973                         case 0x6:
2974                             p16 += sizeof(UINT);
2975                             p32 += sizeof(UINT);
2976                             size16 -= sizeof(UINT);
2977                             break;
2978                         case 0x7:
2979                             HeapFree(GetProcessHeap(), 0, MapSL(*(SEGPTR *)p16));
2980                             UnMapLS( *(SEGPTR *)p16 );
2981                             p16 += sizeof(SEGPTR);
2982                             p32 += sizeof(char*);
2983                             size16 -= sizeof(SEGPTR);
2984                             break;
2985                         default:
2986                             FIXME("Unknown nibble for mapping (%x)\n", nibble);
2987                         }
2988                     }
2989                     map >>= 4;
2990                 }
2991                 if (size16 != 0) /* DEBUG only */
2992                     FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
2993             }
2994         } else {
2995             alloc = msg16;
2996         }
2997
2998         HeapFree( GetProcessHeap(), 0, alloc );
2999     }
3000     return WINMM_MAP_OK;
3001 }
3002
3003 /**************************************************************************
3004  *                      MCI_MapMsg32WTo16                       [internal]
3005  *
3006  * Map a 32W bit MCI message to a 16 bit MCI message.
3007  */
3008 static  WINMM_MapType   MCI_MapMsg32WTo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD_PTR* lParam)
3009 {
3010     int         size;
3011     BOOLEAN     keep = FALSE;
3012     DWORD       map = 0;
3013
3014     if (*lParam == 0)
3015         return WINMM_MAP_OK;
3016
3017     /* FIXME: to add also (with seg/linear modifications to do):
3018      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
3019      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
3020      */
3021     switch (wMsg) {
3022     case MCI_BREAK:
3023         size = sizeof(MCI_BREAK_PARMS);
3024         break;
3025         /* case MCI_CAPTURE */
3026     case MCI_CLOSE:
3027     case MCI_CLOSE_DRIVER:
3028     case MCI_CONFIGURE:
3029         size = sizeof(MCI_GENERIC_PARMS);
3030         break;
3031         /* case MCI_COPY: */
3032     case MCI_CUE:
3033         switch (uDevType) {
3034         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_CUE_PARMS);       break;
3035         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_CUE_PARMS);     break;*/        FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3036         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3037         }
3038         break;
3039         /* case MCI_CUT:*/
3040     case MCI_DELETE:
3041         switch (uDevType) {
3042         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_DELETE_PARMS16);  map = 0x0F1111FB;       break;
3043         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_DELETE_PARMS);   break;
3044         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3045         }
3046         break;
3047         /* case MCI_ESCAPE: */
3048     case MCI_FREEZE:
3049         switch (uDevType) {
3050         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_FREEZE_PARMS);    map = 0x0001111B;       break;
3051         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
3052         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3053         }
3054         break;
3055     case MCI_GETDEVCAPS:
3056         keep = TRUE;
3057         size = sizeof(MCI_GETDEVCAPS_PARMS);
3058         break;
3059         /* case MCI_INDEX: */
3060     case MCI_INFO:
3061         {
3062             LPMCI_INFO_PARMSW   mip32w = (LPMCI_INFO_PARMSW)(*lParam);
3063             char*               ptr;
3064             LPMCI_INFO_PARMS16  mip16;
3065
3066             switch (uDevType) {
3067             case MCI_DEVTYPE_DIGITAL_VIDEO:     size = sizeof(MCI_DGV_INFO_PARMS16);    break;
3068             default:                            size = sizeof(MCI_INFO_PARMS16);        break;
3069             }
3070             ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMCI_INFO_PARMSW) + size);
3071             if (ptr)
3072             {
3073                 *(LPMCI_INFO_PARMSW*)ptr = mip32w;
3074                 mip16 = (LPMCI_INFO_PARMS16)(ptr + sizeof(LPMCI_INFO_PARMSW));
3075                 mip16->dwCallback  = mip32w->dwCallback;
3076                 mip16->lpstrReturn = MapLS( HeapAlloc(GetProcessHeap(), 0, mip32w->dwRetSize / sizeof(WCHAR)) );
3077                 mip16->dwRetSize   = mip32w->dwRetSize / sizeof(WCHAR);
3078                 if (uDevType == MCI_DEVTYPE_DIGITAL_VIDEO) {
3079                     ((LPMCI_DGV_INFO_PARMS16)mip16)->dwItem = ((LPMCI_DGV_INFO_PARMSW)mip32w)->dwItem;
3080                 }
3081             } else {
3082                 return WINMM_MAP_NOMEM;
3083             }
3084             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_INFO_PARMSW);
3085         }
3086         return WINMM_MAP_OKMEM;
3087         /* case MCI_MARK: */
3088         /* case MCI_MONITOR: */
3089     case MCI_OPEN:
3090     case MCI_OPEN_DRIVER:
3091         {
3092             LPMCI_OPEN_PARMSW   mop32w = (LPMCI_OPEN_PARMSW)(*lParam);
3093             char* ptr = HeapAlloc( GetProcessHeap(), 0,
3094                                    sizeof(LPMCI_OPEN_PARMSW) + sizeof(MCI_OPEN_PARMS16) + 2 * sizeof(DWORD));
3095             LPMCI_OPEN_PARMS16  mop16;
3096
3097
3098             if (ptr) {
3099                 *(LPMCI_OPEN_PARMSW*)(ptr) = mop32w;
3100                 mop16 = (LPMCI_OPEN_PARMS16)(ptr + sizeof(LPMCI_OPEN_PARMSW));
3101                 mop16->dwCallback       = mop32w->dwCallback;
3102                 mop16->wDeviceID        = mop32w->wDeviceID;
3103                 if (dwFlags & MCI_OPEN_TYPE) {
3104                     if (dwFlags & MCI_OPEN_TYPE_ID) {
3105                         /* dword "transparent" value */
3106                         mop16->lpstrDeviceType = (SEGPTR)mop32w->lpstrDeviceType;
3107                     } else {
3108                         /* string */
3109                         mop16->lpstrDeviceType = MapLS( MCI_strdupWtoA(mop32w->lpstrDeviceType) );
3110                     }
3111                 } else {
3112                     /* nuthin' */
3113                     mop16->lpstrDeviceType = 0;
3114                 }
3115                 if (dwFlags & MCI_OPEN_ELEMENT) {
3116                     if (dwFlags & MCI_OPEN_ELEMENT_ID) {
3117                         mop16->lpstrElementName = (SEGPTR)mop32w->lpstrElementName;
3118                     } else {
3119                         mop16->lpstrElementName = MapLS( MCI_strdupWtoA(mop32w->lpstrElementName) );
3120                     }
3121                 } else {
3122                     mop16->lpstrElementName = 0;
3123                 }
3124                 if (dwFlags & MCI_OPEN_ALIAS) {
3125                     mop16->lpstrAlias = MapLS( MCI_strdupWtoA(mop32w->lpstrAlias) );
3126                 } else {
3127                     mop16->lpstrAlias = 0;
3128                 }
3129                 /* copy extended information if any...
3130                  * FIXME: this may seg fault if initial structure does not contain them and
3131                  * the reads after msip16 fail under LDT limits...
3132                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
3133                  * should not take care of extended parameters, and should be used by MCI_Open
3134                  * to fetch uDevType. When, this is known, the mapping for sending the
3135                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
3136                  */
3137                 memcpy(mop16 + 1, mop32w + 1, 2 * sizeof(DWORD));
3138             } else {
3139                 return WINMM_MAP_NOMEM;
3140             }
3141             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_PARMSW);
3142         }
3143         return WINMM_MAP_OKMEM;
3144         /* case MCI_PASTE:*/
3145     case MCI_PAUSE:
3146         size = sizeof(MCI_GENERIC_PARMS);
3147         break;
3148     case MCI_PLAY:
3149         size = sizeof(MCI_PLAY_PARMS);
3150         break;
3151     case MCI_PUT:
3152         switch (uDevType) {
3153         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
3154         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
3155         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3156         }
3157         break;
3158     case MCI_REALIZE:
3159         size = sizeof(MCI_GENERIC_PARMS);
3160         break;
3161     case MCI_RECORD:
3162         switch (uDevType) {
3163         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECORD_PARMS16);  map = 0x0F1111FB;       break;
3164         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_RECORD_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3165         default:                        size = sizeof(MCI_RECORD_PARMS);        break;
3166         }
3167         break;
3168     case MCI_RESUME:
3169         size = sizeof(MCI_GENERIC_PARMS);
3170         break;
3171     case MCI_SEEK:
3172         switch (uDevType) {
3173         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SEEK_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3174         default:                        size = sizeof(MCI_SEEK_PARMS);          break;
3175         }
3176         break;
3177     case MCI_SET:
3178         switch (uDevType) {
3179         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SET_PARMS);       break;
3180         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SET_PARMS);     break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3181         case MCI_DEVTYPE_SEQUENCER:     size = sizeof(MCI_SEQ_SET_PARMS);       break;
3182         /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
3183          * so not doing anything should work...
3184          */
3185         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_SET_PARMS);      break;
3186         default:                        size = sizeof(MCI_SET_PARMS);           break;
3187         }
3188         break;
3189     case MCI_SETAUDIO:
3190         switch (uDevType) {
3191         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SETAUDIO_PARMS16);map = 0x0000077FF;      break;
3192         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3193         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3194         }
3195         break;
3196         /* case MCI_SETTIMECODE:*/
3197         /* case MCI_SIGNAL:*/
3198         /* case MCI_SOUND:*/
3199     case MCI_SPIN:
3200         size = sizeof(MCI_SET_PARMS);
3201         break;
3202     case MCI_STATUS:
3203         keep = TRUE;
3204         switch (uDevType) {
3205         /* FIXME:
3206          * don't know if buffer for value is the one passed through lpstrDevice
3207          * or is provided by MCI driver.
3208          * Assuming solution 2: provided by MCI driver, so zeroing on entry
3209          */
3210         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16);  map = 0x0B6FF;          break;
3211         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3212         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
3213         }
3214         break;
3215     case MCI_STEP:
3216         switch (uDevType) {
3217         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STEP_PARMS);      break;
3218         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STEP_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3219         case MCI_DEVTYPE_VIDEODISC:     size = sizeof(MCI_VD_STEP_PARMS);       break;
3220         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3221         }
3222         break;
3223     case MCI_STOP:
3224         size = sizeof(MCI_SET_PARMS);
3225         break;
3226     case MCI_SYSINFO:
3227         {
3228             LPMCI_SYSINFO_PARMSW  msip32w = (LPMCI_SYSINFO_PARMSW)(*lParam);
3229             LPMCI_SYSINFO_PARMS16 msip16;
3230             char* ptr = HeapAlloc( GetProcessHeap(), 0,
3231                                    sizeof(LPMCI_SYSINFO_PARMSW) + sizeof(MCI_SYSINFO_PARMS16) );
3232
3233             if (ptr) {
3234                 *(LPMCI_SYSINFO_PARMSW*)(ptr) = msip32w;
3235                 msip16 = (LPMCI_SYSINFO_PARMS16)(ptr + sizeof(LPMCI_SYSINFO_PARMSW));
3236
3237                 msip16->dwCallback       = msip32w->dwCallback;
3238                 msip16->lpstrReturn      = MapLS( HeapAlloc(GetProcessHeap(), 0, msip32w->dwRetSize) );
3239                 msip16->dwRetSize        = msip32w->dwRetSize;
3240                 msip16->dwNumber         = msip32w->dwNumber;
3241                 msip16->wDeviceType      = msip32w->wDeviceType;
3242             } else {
3243                 return WINMM_MAP_NOMEM;
3244             }
3245             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_SYSINFO_PARMSW);
3246         }
3247         return WINMM_MAP_OKMEM;
3248         /* case MCI_UNDO: */
3249     case MCI_UNFREEZE:
3250         switch (uDevType) {
3251         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
3252         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       break;
3253         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3254         }
3255         break;
3256     case MCI_UPDATE:
3257         switch (uDevType) {
3258         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_UPDATE_PARMS16);  map = 0x000B1111B;      break;
3259         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3260         }
3261         break;
3262     case MCI_WHERE:
3263         switch (uDevType) {
3264         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       keep = TRUE;    break;
3265         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       keep = TRUE;    break;
3266         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3267         }
3268         break;
3269     case MCI_WINDOW:
3270         switch (uDevType) {
3271         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7FB;        break;
3272         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7FB;        break;
3273         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3274         }
3275         break;
3276     case DRV_OPEN:
3277         {
3278             LPMCI_OPEN_DRIVER_PARMSW  modp32w = (LPMCI_OPEN_DRIVER_PARMSW)(*lParam);
3279             LPMCI_OPEN_DRIVER_PARMS16 modp16;
3280             char *ptr = HeapAlloc( GetProcessHeap(), 0,
3281                                    sizeof(LPMCI_OPEN_DRIVER_PARMSW) + sizeof(MCI_OPEN_DRIVER_PARMS16));
3282
3283             if (ptr) {
3284                 *(LPMCI_OPEN_DRIVER_PARMSW*)(ptr) = modp32w;
3285                 modp16 = (LPMCI_OPEN_DRIVER_PARMS16)(ptr + sizeof(LPMCI_OPEN_DRIVER_PARMSW));
3286                 modp16->wDeviceID = modp32w->wDeviceID;
3287                 modp16->lpstrParams = MapLS( MCI_strdupWtoA(modp32w->lpstrParams) );
3288                 /* other fields are gonna be filled by the driver, don't copy them */
3289             } else {
3290                 return WINMM_MAP_NOMEM;
3291             }
3292             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_DRIVER_PARMSW);
3293         }
3294         return WINMM_MAP_OKMEM;
3295     case DRV_LOAD:
3296     case DRV_ENABLE:
3297     case DRV_CLOSE:
3298     case DRV_DISABLE:
3299     case DRV_FREE:
3300     case DRV_CONFIGURE:
3301     case DRV_QUERYCONFIGURE:
3302     case DRV_INSTALL:
3303     case DRV_REMOVE:
3304     case DRV_EXITSESSION:
3305     case DRV_EXITAPPLICATION:
3306     case DRV_POWER:
3307         return WINMM_MAP_OK;
3308
3309     default:
3310         FIXME("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
3311         return WINMM_MAP_MSGERROR;
3312     }
3313     return MCI_MsgMapper32WTo16_Create((void**)lParam, size, map, keep);
3314 }
3315
3316 /**************************************************************************
3317  *                      MCI_UnMapMsg32WTo16                     [internal]
3318  */
3319 static  WINMM_MapType   MCI_UnMapMsg32WTo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD_PTR lParam)
3320 {
3321     int         size = 0;
3322     BOOLEAN     kept = FALSE;   /* there is no need to compute size when kept is FALSE */
3323     DWORD       map = 0;
3324
3325     switch (wMsg) {
3326     case MCI_BREAK:
3327         break;
3328         /* case MCI_CAPTURE */
3329     case MCI_CLOSE:
3330     case MCI_CLOSE_DRIVER:
3331     case MCI_CONFIGURE:
3332         break;
3333         /* case MCI_COPY: */
3334     case MCI_CUE:
3335         break;
3336         /* case MCI_CUT: */
3337     case MCI_DELETE:
3338         break;
3339         /* case MCI_ESCAPE: */
3340     case MCI_FREEZE:
3341         break;
3342     case MCI_GETDEVCAPS:
3343         kept = TRUE;
3344         size = sizeof(MCI_GETDEVCAPS_PARMS);
3345         break;
3346         /* case MCI_INDEX: */
3347     case MCI_INFO:
3348         if (lParam) {
3349             LPMCI_INFO_PARMS16  mip16  = (LPMCI_INFO_PARMS16)MapSL(lParam);
3350             LPMCI_INFO_PARMSW   mip32w = *(LPMCI_INFO_PARMSW*)((char*)mip16 - sizeof(LPMCI_INFO_PARMSW));
3351
3352             MultiByteToWideChar(CP_ACP, 0, MapSL(mip16->lpstrReturn), mip16->dwRetSize, 
3353                                 mip32w->lpstrReturn, mip32w->dwRetSize / sizeof(WCHAR));
3354             UnMapLS( lParam );
3355             UnMapLS( mip16->lpstrReturn );
3356             HeapFree( GetProcessHeap(), 0, (void*)MapSL(mip16->lpstrReturn) );
3357             HeapFree( GetProcessHeap(), 0, (char*)mip16 - sizeof(LPMCI_OPEN_PARMSW) );
3358         }
3359         return WINMM_MAP_OK;
3360         /* case MCI_MARK: */
3361         /* case MCI_MONITOR: */
3362     case MCI_OPEN:
3363     case MCI_OPEN_DRIVER:
3364         if (lParam) {
3365             LPMCI_OPEN_PARMS16  mop16  = (LPMCI_OPEN_PARMS16)MapSL(lParam);
3366             LPMCI_OPEN_PARMSW   mop32w = *(LPMCI_OPEN_PARMSW*)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSW));
3367             UnMapLS( lParam );
3368             mop32w->wDeviceID = mop16->wDeviceID;
3369             if ((dwFlags & MCI_OPEN_TYPE) && !(dwFlags & MCI_OPEN_TYPE_ID))
3370             {
3371                 HeapFree(GetProcessHeap(), 0, MapSL(mop16->lpstrDeviceType));
3372                 UnMapLS( mop16->lpstrDeviceType );
3373             }
3374             if ((dwFlags & MCI_OPEN_ELEMENT) && !(dwFlags & MCI_OPEN_ELEMENT_ID))
3375             {
3376                 HeapFree(GetProcessHeap(), 0, MapSL(mop16->lpstrElementName));
3377                 UnMapLS( mop16->lpstrElementName );
3378             }
3379             if (dwFlags & MCI_OPEN_ALIAS)
3380             {
3381                 HeapFree(GetProcessHeap(), 0, MapSL(mop16->lpstrAlias));
3382                 UnMapLS( mop16->lpstrAlias );
3383             }
3384             HeapFree( GetProcessHeap(), 0, (char*)mop16 - sizeof(LPMCI_OPEN_PARMSW) );
3385         }
3386         return WINMM_MAP_OK;
3387         /* case MCI_PASTE:*/
3388     case MCI_PAUSE:
3389         break;
3390     case MCI_PLAY:
3391         break;
3392     case MCI_PUT:
3393         break;
3394     case MCI_REALIZE:
3395         break;
3396     case MCI_RECORD:
3397         break;
3398     case MCI_RESUME:
3399         break;
3400     case MCI_SEEK:
3401         break;
3402     case MCI_SET:
3403         break;
3404     case MCI_SETAUDIO:
3405         switch (uDevType) {
3406         case MCI_DEVTYPE_DIGITAL_VIDEO: map = 0x0000077FF;      break;
3407         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3408         }
3409         break;
3410         /* case MCI_SETTIMECODE:*/
3411         /* case MCI_SIGNAL:*/
3412         /* case MCI_SOUND:*/
3413     case MCI_SPIN:
3414         break;
3415     case MCI_STATUS:
3416         kept = TRUE;
3417         switch (uDevType) {
3418         case MCI_DEVTYPE_DIGITAL_VIDEO:
3419         if (lParam) {
3420             LPMCI_DGV_STATUS_PARMS16    mdsp16  = (LPMCI_DGV_STATUS_PARMS16)MapSL(lParam);
3421             LPMCI_DGV_STATUS_PARMSA     mdsp32a = *(LPMCI_DGV_STATUS_PARMSA*)((char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA));
3422
3423             UnMapLS( lParam );
3424             if (mdsp16) {
3425                 mdsp32a->dwReturn = mdsp16->dwReturn;
3426                 if (dwFlags & MCI_DGV_STATUS_DISKSPACE) {
3427                     TRACE("MCI_STATUS (DGV) lpstrDrive=%08x\n", mdsp16->lpstrDrive);
3428                     TRACE("MCI_STATUS (DGV) lpstrDrive=%s\n", (LPSTR)MapSL(mdsp16->lpstrDrive));
3429                     UnMapLS( mdsp16->lpstrDrive );
3430                 }
3431                 HeapFree( GetProcessHeap(), 0, (char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA) );
3432             } else {
3433                 return WINMM_MAP_NOMEM;
3434             }
3435         }
3436         return WINMM_MAP_OKMEM;
3437         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3438         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
3439         }
3440         break;
3441     case MCI_STEP:
3442         break;
3443     case MCI_STOP:
3444         break;
3445     case MCI_SYSINFO:
3446         if (lParam) {
3447             LPMCI_SYSINFO_PARMS16       msip16  = (LPMCI_SYSINFO_PARMS16)MapSL(lParam);
3448             LPMCI_SYSINFO_PARMSW        msip32w = *(LPMCI_SYSINFO_PARMSW*)((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSW));
3449
3450             UnMapLS( lParam );
3451             if (msip16) {
3452                 MultiByteToWideChar(CP_ACP, 0, MapSL(msip16->lpstrReturn), msip16->dwRetSize, 
3453                                     msip32w->lpstrReturn, msip32w->dwRetSize/sizeof(WCHAR));
3454                 UnMapLS( msip16->lpstrReturn );
3455                 HeapFree( GetProcessHeap(), 0, MapSL(msip16->lpstrReturn) );
3456                 HeapFree( GetProcessHeap(), 0, (char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSW) );
3457             } else {
3458                 return WINMM_MAP_NOMEM;
3459             }
3460         }
3461         return WINMM_MAP_OKMEM;
3462         /* case MCI_UNDO: */
3463     case MCI_UNFREEZE:
3464         break;
3465     case MCI_UPDATE:
3466         break;
3467     case MCI_WHERE:
3468         switch (uDevType) {
3469         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       kept = TRUE;    break;
3470         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       kept = TRUE;    break;
3471         default:                        break;
3472         }
3473         break;
3474     case MCI_WINDOW:
3475         switch (uDevType) {
3476         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7666;       break;
3477         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7666;       break;
3478         default:                        break;
3479         }
3480         /* FIXME: see map function */
3481         break;
3482     case DRV_OPEN:
3483         if (lParam) {
3484             LPMCI_OPEN_DRIVER_PARMS16   modp16  = (LPMCI_OPEN_DRIVER_PARMS16)MapSL(lParam);
3485             LPMCI_OPEN_DRIVER_PARMSW    modp32w = *(LPMCI_OPEN_DRIVER_PARMSW*)((char*)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSW));
3486
3487             UnMapLS( lParam );
3488             modp32w->wCustomCommandTable = modp16->wCustomCommandTable;
3489             modp32w->wType = modp16->wType;
3490             HeapFree(GetProcessHeap(), 0, MapSL(modp16->lpstrParams));
3491             UnMapLS( modp16->lpstrParams );
3492             HeapFree( GetProcessHeap(), 0, (char *)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSW) );
3493         }
3494         return WINMM_MAP_OK;
3495     case DRV_LOAD:
3496     case DRV_ENABLE:
3497     case DRV_CLOSE:
3498     case DRV_DISABLE:
3499     case DRV_FREE:
3500     case DRV_CONFIGURE:
3501     case DRV_QUERYCONFIGURE:
3502     case DRV_INSTALL:
3503     case DRV_REMOVE:
3504     case DRV_EXITSESSION:
3505     case DRV_EXITAPPLICATION:
3506     case DRV_POWER:
3507         FIXME("This is a hack\n");
3508         return WINMM_MAP_OK;
3509
3510     default:
3511         FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
3512         return WINMM_MAP_MSGERROR;
3513     }
3514     return MCI_MsgMapper32WTo16_Destroy((void*)lParam, size, map, kept);
3515 }
3516
3517 void    MMDRV_Init16(void)
3518 {
3519 #define A(_x,_y) MMDRV_InstallMap(_x, \
3520 MMDRV_##_y##_Map16To32W, MMDRV_##_y##_UnMap16To32W, \
3521 MMDRV_##_y##_Map32WTo16, MMDRV_##_y##_UnMap32WTo16, \
3522 MMDRV_##_y##_Callback)
3523     A(MMDRV_AUX,        Aux);
3524     A(MMDRV_MIXER,      Mixer);
3525     A(MMDRV_MIDIIN,     MidiIn);
3526     A(MMDRV_MIDIOUT,    MidiOut);
3527     A(MMDRV_WAVEIN,     WaveIn);
3528     A(MMDRV_WAVEOUT,    WaveOut);
3529 #undef A
3530
3531     pFnCallMMDrvFunc16 = MMDRV_CallMMDrvFunc16;
3532     pFnLoadMMDrvFunc16 = MMDRV_LoadMMDrvFunc16;
3533
3534     pFnMciMapMsg16To32W   = MCI_MapMsg16To32W;
3535     pFnMciUnMapMsg16To32W = MCI_UnMapMsg16To32W;
3536     pFnMciMapMsg32WTo16   = MCI_MapMsg32WTo16;
3537     pFnMciUnMapMsg32WTo16 = MCI_UnMapMsg32WTo16;
3538 }