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