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