Moved the NONAMELESSUNION/STRUCT macros to wine/test.h so that they
[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* 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                 mop32w->lpstrDeviceType  = MCI_strdupAtoW(MapSL(mop16->lpstrDeviceType));
2636                 mop32w->lpstrElementName = MCI_strdupAtoW(MapSL(mop16->lpstrElementName));
2637                 mop32w->lpstrAlias       = MCI_strdupAtoW(MapSL(mop16->lpstrAlias));
2638                 /* copy extended information if any...
2639                  * FIXME: this may seg fault if initial structure does not contain them and
2640                  * the reads after msip16 fail under LDT limits...
2641                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
2642                  * should not take care of extended parameters, and should be used by MCI_Open
2643                  * to fetch uDevType. When, this is known, the mapping for sending the
2644                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
2645                  */
2646                 memcpy(mop32w + 1, mop16 + 1, 2 * sizeof(DWORD));
2647             } else {
2648                 return WINMM_MAP_NOMEM;
2649             }
2650             *lParam = (DWORD)mop32w;
2651         }
2652         return WINMM_MAP_OKMEM;
2653     case MCI_SYSINFO:
2654         {
2655             LPMCI_SYSINFO_PARMSW        msip32w = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_SYSINFO_PARMSW));
2656             LPMCI_SYSINFO_PARMS16       msip16  = MapSL(*lParam);
2657
2658             if (msip32w) {
2659                 *(LPMCI_SYSINFO_PARMS16*)(msip32w) = msip16;
2660                 msip32w = (LPMCI_SYSINFO_PARMSW)((char*)msip32w + sizeof(LPMCI_OPEN_PARMS16));
2661                 msip32w->dwCallback       = msip16->dwCallback;
2662                 msip32w->lpstrReturn      = HeapAlloc(GetProcessHeap(), 0, msip16->dwRetSize * sizeof(WCHAR));
2663                 msip32w->dwRetSize        = msip16->dwRetSize;
2664                 msip32w->dwNumber         = msip16->dwNumber;
2665                 msip32w->wDeviceType      = msip16->wDeviceType;
2666             } else {
2667                 return WINMM_MAP_NOMEM;
2668             }
2669             *lParam = (DWORD)msip32w;
2670         }
2671         return WINMM_MAP_OKMEM;
2672     case MCI_SOUND:
2673         {
2674             LPMCI_SOUND_PARMSW          mbp32 = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_SOUND_PARMSW));
2675             LPMCI_SOUND_PARMS16         mbp16 = MapSL(*lParam);
2676
2677             if (mbp32) {
2678                 mbp32->dwCallback = mbp16->dwCallback;
2679                 mbp32->lpstrSoundName = MCI_strdupAtoW(MapSL(mbp16->lpstrSoundName));
2680             } else {
2681                 return WINMM_MAP_NOMEM;
2682             }
2683             *lParam = (DWORD)mbp32;
2684         }
2685         return WINMM_MAP_OKMEM;
2686     case DRV_LOAD:
2687     case DRV_ENABLE:
2688     case DRV_OPEN:
2689     case DRV_CLOSE:
2690     case DRV_DISABLE:
2691     case DRV_FREE:
2692     case DRV_CONFIGURE:
2693     case DRV_QUERYCONFIGURE:
2694     case DRV_INSTALL:
2695     case DRV_REMOVE:
2696     case DRV_EXITSESSION:
2697     case DRV_EXITAPPLICATION:
2698     case DRV_POWER:
2699         FIXME("This is a hack\n");
2700         return WINMM_MAP_OK;
2701     default:
2702         FIXME("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
2703     }
2704     return WINMM_MAP_MSGERROR;
2705 }
2706
2707 /**************************************************************************
2708  *                      MCI_UnMapMsg16To32W                     [internal]
2709  */
2710 static  WINMM_MapType   MCI_UnMapMsg16To32W(WORD uDevType, WORD wMsg, DWORD lParam)
2711 {
2712     switch (wMsg) {
2713         /* case MCI_CAPTURE */
2714     case MCI_CLOSE:
2715     case MCI_CLOSE_DRIVER:
2716     case MCI_CONFIGURE:
2717     case MCI_COPY:
2718     case MCI_CUE:
2719     case MCI_CUT:
2720     case MCI_DELETE:
2721     case MCI_FREEZE:
2722     case MCI_GETDEVCAPS:
2723         /* case MCI_INDEX: */
2724         /* case MCI_MARK: */
2725         /* case MCI_MONITOR: */
2726     case MCI_PASTE:
2727     case MCI_PAUSE:
2728     case MCI_PLAY:
2729     case MCI_PUT:
2730     case MCI_REALIZE:
2731     case MCI_RECORD:
2732     case MCI_RESUME:
2733     case MCI_SEEK:
2734     case MCI_SET:
2735         /* case MCI_SETTIMECODE:*/
2736         /* case MCI_SIGNAL:*/
2737     case MCI_SPIN:
2738     case MCI_STATUS:
2739     case MCI_STEP:
2740     case MCI_STOP:
2741         /* case MCI_UNDO: */
2742     case MCI_UNFREEZE:
2743     case MCI_UPDATE:
2744     case MCI_WHERE:
2745         return WINMM_MAP_OK;
2746
2747     case MCI_WINDOW:
2748         /* FIXME ?? see Map function */
2749         return WINMM_MAP_OK;
2750
2751     case MCI_BREAK:
2752         HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2753         return WINMM_MAP_OK;
2754     case MCI_ESCAPE:
2755         if (lParam) {
2756             LPMCI_VD_ESCAPE_PARMSW      mvep32W = (LPMCI_VD_ESCAPE_PARMSW)lParam;
2757             HeapFree(GetProcessHeap(), 0, (LPVOID)mvep32W->lpstrCommand);
2758             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2759         }
2760         return WINMM_MAP_OK;
2761     case MCI_INFO:
2762         if (lParam) {
2763             LPMCI_INFO_PARMSW           mip32w = (LPMCI_INFO_PARMSW)lParam;
2764             LPMCI_INFO_PARMS16          mip16  = *(LPMCI_INFO_PARMS16*)((char*)mip32w - sizeof(LPMCI_INFO_PARMS16));
2765
2766             WideCharToMultiByte(CP_ACP, 0,
2767                                 mip32w->lpstrReturn, mip32w->dwRetSize / sizeof(WCHAR),
2768                                 MapSL(mip16->lpstrReturn), mip16->dwRetSize,
2769                                 NULL, NULL);
2770             HeapFree(GetProcessHeap(), 0, (LPVOID)mip32w->lpstrReturn);
2771             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2772         }
2773         return WINMM_MAP_OK;
2774     case MCI_SYSINFO:
2775         if (lParam) {
2776             LPMCI_SYSINFO_PARMSW           msip32w = (LPMCI_SYSINFO_PARMSW)lParam;
2777             LPMCI_SYSINFO_PARMS16          msip16  = *(LPMCI_SYSINFO_PARMS16*)((char*)msip32w - sizeof(LPMCI_SYSINFO_PARMS16));
2778
2779             WideCharToMultiByte(CP_ACP, 0,
2780                                 msip32w->lpstrReturn, msip32w->dwRetSize,
2781                                 MapSL(msip16->lpstrReturn), msip16->dwRetSize,
2782                                 NULL, NULL);
2783             HeapFree(GetProcessHeap(), 0, (LPVOID)msip32w->lpstrReturn);
2784             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2785         }
2786         return WINMM_MAP_OK;
2787     case MCI_SOUND:
2788         if (lParam) {
2789             LPMCI_SOUND_PARMSW          msp32W = (LPMCI_SOUND_PARMSW)lParam;
2790             HeapFree(GetProcessHeap(), 0, (LPVOID)msp32W->lpstrSoundName);
2791             HeapFree(GetProcessHeap(), 0, (LPVOID)lParam);
2792         }
2793         return WINMM_MAP_OK;
2794     case MCI_OPEN:
2795     case MCI_OPEN_DRIVER:
2796         if (lParam) {
2797             LPMCI_OPEN_PARMSW   mop32w = (LPMCI_OPEN_PARMSW)lParam;
2798             LPMCI_OPEN_PARMS16  mop16  = *(LPMCI_OPEN_PARMS16*)((char*)mop32w - sizeof(LPMCI_OPEN_PARMS16));
2799
2800             mop16->wDeviceID = mop32w->wDeviceID;
2801             HeapFree(GetProcessHeap(), 0, mop32w->lpstrDeviceType);
2802             HeapFree(GetProcessHeap(), 0, mop32w->lpstrElementName);
2803             HeapFree(GetProcessHeap(), 0, mop32w->lpstrAlias);
2804             if (!HeapFree(GetProcessHeap(), 0, (LPVOID)(lParam - sizeof(LPMCI_OPEN_PARMS16))))
2805                 FIXME("bad free line=%d\n", __LINE__);
2806         }
2807         return WINMM_MAP_OK;
2808     case DRV_LOAD:
2809     case DRV_ENABLE:
2810     case DRV_OPEN:
2811     case DRV_CLOSE:
2812     case DRV_DISABLE:
2813     case DRV_FREE:
2814     case DRV_CONFIGURE:
2815     case DRV_QUERYCONFIGURE:
2816     case DRV_INSTALL:
2817     case DRV_REMOVE:
2818     case DRV_EXITSESSION:
2819     case DRV_EXITAPPLICATION:
2820     case DRV_POWER:
2821         FIXME("This is a hack\n");
2822         return WINMM_MAP_OK;
2823     default:
2824         FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
2825     }
2826     return WINMM_MAP_MSGERROR;
2827 }
2828
2829 /*
2830  * 0000 stop
2831  * 0001 squeeze   signed 4 bytes to 2 bytes     *( LPINT16)D = ( INT16)*( LPINT16)S; D += 2;     S += 4
2832  * 0010 squeeze unsigned 4 bytes to 2 bytes     *(LPUINT16)D = (UINT16)*(LPUINT16)S; D += 2;     S += 4
2833  * 0100
2834  * 0101
2835  * 0110 zero 4 bytes                            *(DWORD)D = 0                        D += 4;     S += 4
2836  * 0111 copy string                             *(LPSTR*)D = seg dup(*(LPSTR*)S)     D += 4;     S += 4
2837  * 1xxx copy xxx + 1 bytes                      memcpy(D, S, xxx + 1);               D += xxx+1; S += xxx+1
2838  */
2839
2840 /**************************************************************************
2841  *                      MCI_MsgMapper32WTo16_Create             [internal]
2842  *
2843  * Helper for MCI_MapMsg32WTo16.
2844  * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit
2845  * segmented pointer.
2846  * map contains a list of action to be performed for the mapping (see list
2847  * above)
2848  * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
2849  */
2850 static  WINMM_MapType   MCI_MsgMapper32WTo16_Create(void** ptr, int size16, DWORD map, BOOLEAN keep)
2851 {
2852     void*       lp = HeapAlloc( GetProcessHeap(), 0, (keep ? sizeof(void**) : 0) + size16 );
2853     LPBYTE      p16, p32;
2854
2855     if (!lp) {
2856         return WINMM_MAP_NOMEM;
2857     }
2858     p32 = (LPBYTE)(*ptr);
2859     if (keep) {
2860         *(void**)lp = *ptr;
2861         p16 = (LPBYTE)lp + sizeof(void**);
2862         *ptr = (char*)MapLS(lp) + sizeof(void**);
2863     } else {
2864         p16 = lp;
2865         *ptr = (void*)MapLS(lp);
2866     }
2867
2868     if (map == 0) {
2869         memcpy(p16, p32, size16);
2870     } else {
2871         unsigned        nibble;
2872         unsigned        sz;
2873
2874         while (map & 0xF) {
2875             nibble = map & 0xF;
2876             if (nibble & 0x8) {
2877                 sz = (nibble & 7) + 1;
2878                 memcpy(p16, p32, sz);
2879                 p16 += sz;
2880                 p32 += sz;
2881                 size16 -= sz;   /* DEBUG only */
2882             } else {
2883                 switch (nibble) {
2884                 case 0x1:
2885                     *(LPINT16)p16 = *(LPINT)p32;
2886                     p16 += sizeof(INT16);
2887                     p32 += sizeof(INT);
2888                     size16 -= sizeof(INT16);
2889                     break;
2890                 case 0x2:
2891                     *(LPUINT16)p16 = *(LPUINT)p32;
2892                     p16 += sizeof(UINT16);
2893                     p32 += sizeof(UINT);
2894                     size16 -= sizeof(UINT16);
2895                     break;
2896                 case 0x6:
2897                     *(LPDWORD)p16 = 0;
2898                     p16 += sizeof(DWORD);
2899                     p32 += sizeof(DWORD);
2900                     size16 -= sizeof(DWORD);
2901                     break;
2902                 case 0x7:
2903                     *(SEGPTR *)p16 = MapLS( MCI_strdupWtoA( *(LPCWSTR *)p32 ) );
2904                     p16 += sizeof(SEGPTR);
2905                     p32 += sizeof(LPSTR);
2906                     size16 -= sizeof(SEGPTR);
2907                     break;
2908                 default:
2909                     FIXME("Unknown nibble for mapping (%x)\n", nibble);
2910                 }
2911             }
2912             map >>= 4;
2913         }
2914         if (size16 != 0) /* DEBUG only */
2915             FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
2916     }
2917     return WINMM_MAP_OKMEM;
2918 }
2919
2920 /**************************************************************************
2921  *                      MCI_MsgMapper32WTo16_Destroy            [internal]
2922  *
2923  * Helper for MCI_UnMapMsg32WTo16.
2924  */
2925 static  WINMM_MapType   MCI_MsgMapper32WTo16_Destroy(void* ptr, int size16, DWORD map, BOOLEAN kept)
2926 {
2927     if (ptr) {
2928         void*           msg16 = MapSL((SEGPTR)ptr);
2929         void*           alloc;
2930         LPBYTE          p32, p16;
2931         unsigned        nibble;
2932
2933         UnMapLS( (SEGPTR)ptr );
2934         if (kept) {
2935             alloc = (char*)msg16 - sizeof(void**);
2936             p32 = *(void**)alloc;
2937             p16 = msg16;
2938
2939             if (map == 0) {
2940                 memcpy(p32, p16, size16);
2941             } else {
2942                 while (map & 0xF) {
2943                     nibble = map & 0xF;
2944                     if (nibble & 0x8) {
2945                         memcpy(p32, p16, (nibble & 7) + 1);
2946                         p16 += (nibble & 7) + 1;
2947                         p32 += (nibble & 7) + 1;
2948                         size16 -= (nibble & 7) + 1;
2949                     } else {
2950                         switch (nibble) {
2951                         case 0x1:
2952                             *(LPINT)p32 = *(LPINT16)p16;
2953                             p16 += sizeof(INT16);
2954                             p32 += sizeof(INT);
2955                             size16 -= sizeof(INT16);
2956                             break;
2957                         case 0x2:
2958                             *(LPUINT)p32 = *(LPUINT16)p16;
2959                             p16 += sizeof(UINT16);
2960                             p32 += sizeof(UINT);
2961                             size16 -= sizeof(UINT16);
2962                             break;
2963                         case 0x6:
2964                             p16 += sizeof(UINT);
2965                             p32 += sizeof(UINT);
2966                             size16 -= sizeof(UINT);
2967                             break;
2968                         case 0x7:
2969                             HeapFree(GetProcessHeap(), 0, MapSL(*(SEGPTR *)p16));
2970                             UnMapLS( *(SEGPTR *)p16 );
2971                             p16 += sizeof(SEGPTR);
2972                             p32 += sizeof(char*);
2973                             size16 -= sizeof(SEGPTR);
2974                             break;
2975                         default:
2976                             FIXME("Unknown nibble for mapping (%x)\n", nibble);
2977                         }
2978                     }
2979                     map >>= 4;
2980                 }
2981                 if (size16 != 0) /* DEBUG only */
2982                     FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
2983             }
2984         } else {
2985             alloc = msg16;
2986         }
2987
2988         HeapFree( GetProcessHeap(), 0, alloc );
2989     }
2990     return WINMM_MAP_OK;
2991 }
2992
2993 /**************************************************************************
2994  *                      MCI_MapMsg32WTo16                       [internal]
2995  *
2996  * Map a 32W bit MCI message to a 16 bit MCI message.
2997  */
2998 static  WINMM_MapType   MCI_MapMsg32WTo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
2999 {
3000     int         size;
3001     BOOLEAN     keep = FALSE;
3002     DWORD       map = 0;
3003
3004     if (*lParam == 0)
3005         return WINMM_MAP_OK;
3006
3007     /* FIXME: to add also (with seg/linear modifications to do):
3008      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
3009      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
3010      */
3011     switch (wMsg) {
3012     case MCI_BREAK:
3013         size = sizeof(MCI_BREAK_PARMS);
3014         break;
3015         /* case MCI_CAPTURE */
3016     case MCI_CLOSE:
3017     case MCI_CLOSE_DRIVER:
3018     case MCI_CONFIGURE:
3019         size = sizeof(MCI_GENERIC_PARMS);
3020         break;
3021         /* case MCI_COPY: */
3022     case MCI_CUE:
3023         switch (uDevType) {
3024         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_CUE_PARMS);       break;
3025         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_CUE_PARMS);     break;*/        FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3026         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3027         }
3028         break;
3029         /* case MCI_CUT:*/
3030     case MCI_DELETE:
3031         switch (uDevType) {
3032         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_DELETE_PARMS16);  map = 0x0F1111FB;       break;
3033         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_DELETE_PARMS);   break;
3034         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3035         }
3036         break;
3037         /* case MCI_ESCAPE: */
3038     case MCI_FREEZE:
3039         switch (uDevType) {
3040         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_FREEZE_PARMS);    map = 0x0001111B;       break;
3041         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
3042         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3043         }
3044         break;
3045     case MCI_GETDEVCAPS:
3046         keep = TRUE;
3047         size = sizeof(MCI_GETDEVCAPS_PARMS);
3048         break;
3049         /* case MCI_INDEX: */
3050     case MCI_INFO:
3051         {
3052             LPMCI_INFO_PARMSW   mip32w = (LPMCI_INFO_PARMSW)(*lParam);
3053             char*               ptr;
3054             LPMCI_INFO_PARMS16  mip16;
3055
3056             switch (uDevType) {
3057             case MCI_DEVTYPE_DIGITAL_VIDEO:     size = sizeof(MCI_DGV_INFO_PARMS16);    break;
3058             default:                            size = sizeof(MCI_INFO_PARMS16);        break;
3059             }
3060             ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMCI_INFO_PARMSW) + size);
3061             if (ptr)
3062             {
3063                 *(LPMCI_INFO_PARMSW*)ptr = mip32w;
3064                 mip16 = (LPMCI_INFO_PARMS16)(ptr + sizeof(LPMCI_INFO_PARMSW));
3065                 mip16->dwCallback  = mip32w->dwCallback;
3066                 mip16->lpstrReturn = MapLS( HeapAlloc(GetProcessHeap(), 0, mip32w->dwRetSize / sizeof(WCHAR)) );
3067                 mip16->dwRetSize   = mip32w->dwRetSize / sizeof(WCHAR);
3068                 if (uDevType == MCI_DEVTYPE_DIGITAL_VIDEO) {
3069                     ((LPMCI_DGV_INFO_PARMS16)mip16)->dwItem = ((LPMCI_DGV_INFO_PARMSW)mip32w)->dwItem;
3070                 }
3071             } else {
3072                 return WINMM_MAP_NOMEM;
3073             }
3074             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_INFO_PARMSW);
3075         }
3076         return WINMM_MAP_OKMEM;
3077         /* case MCI_MARK: */
3078         /* case MCI_MONITOR: */
3079     case MCI_OPEN:
3080     case MCI_OPEN_DRIVER:
3081         {
3082             LPMCI_OPEN_PARMSW   mop32w = (LPMCI_OPEN_PARMSW)(*lParam);
3083             char* ptr = HeapAlloc( GetProcessHeap(), 0,
3084                                    sizeof(LPMCI_OPEN_PARMSW) + sizeof(MCI_OPEN_PARMS16) + 2 * sizeof(DWORD));
3085             LPMCI_OPEN_PARMS16  mop16;
3086
3087
3088             if (ptr) {
3089                 *(LPMCI_OPEN_PARMSW*)(ptr) = mop32w;
3090                 mop16 = (LPMCI_OPEN_PARMS16)(ptr + sizeof(LPMCI_OPEN_PARMSW));
3091                 mop16->dwCallback       = mop32w->dwCallback;
3092                 mop16->wDeviceID        = mop32w->wDeviceID;
3093                 if (dwFlags & MCI_OPEN_TYPE) {
3094                     if (dwFlags & MCI_OPEN_TYPE_ID) {
3095                         /* dword "transparent" value */
3096                         mop16->lpstrDeviceType = (SEGPTR)mop32w->lpstrDeviceType;
3097                     } else {
3098                         /* string */
3099                         mop16->lpstrDeviceType = MapLS( MCI_strdupWtoA(mop32w->lpstrDeviceType) );
3100                     }
3101                 } else {
3102                     /* nuthin' */
3103                     mop16->lpstrDeviceType = 0;
3104                 }
3105                 if (dwFlags & MCI_OPEN_ELEMENT) {
3106                     if (dwFlags & MCI_OPEN_ELEMENT_ID) {
3107                         mop16->lpstrElementName = (SEGPTR)mop32w->lpstrElementName;
3108                     } else {
3109                         mop16->lpstrElementName = MapLS( MCI_strdupWtoA(mop32w->lpstrElementName) );
3110                     }
3111                 } else {
3112                     mop16->lpstrElementName = 0;
3113                 }
3114                 if (dwFlags & MCI_OPEN_ALIAS) {
3115                     mop16->lpstrAlias = MapLS( MCI_strdupWtoA(mop32w->lpstrAlias) );
3116                 } else {
3117                     mop16->lpstrAlias = 0;
3118                 }
3119                 /* copy extended information if any...
3120                  * FIXME: this may seg fault if initial structure does not contain them and
3121                  * the reads after msip16 fail under LDT limits...
3122                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
3123                  * should not take care of extended parameters, and should be used by MCI_Open
3124                  * to fetch uDevType. When, this is known, the mapping for sending the
3125                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
3126                  */
3127                 memcpy(mop16 + 1, mop32w + 1, 2 * sizeof(DWORD));
3128             } else {
3129                 return WINMM_MAP_NOMEM;
3130             }
3131             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_PARMSW);
3132         }
3133         return WINMM_MAP_OKMEM;
3134         /* case MCI_PASTE:*/
3135     case MCI_PAUSE:
3136         size = sizeof(MCI_GENERIC_PARMS);
3137         break;
3138     case MCI_PLAY:
3139         size = sizeof(MCI_PLAY_PARMS);
3140         break;
3141     case MCI_PUT:
3142         switch (uDevType) {
3143         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
3144         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     map = 0x0001111B;       break;
3145         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3146         }
3147         break;
3148     case MCI_REALIZE:
3149         size = sizeof(MCI_GENERIC_PARMS);
3150         break;
3151     case MCI_RECORD:
3152         switch (uDevType) {
3153         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECORD_PARMS16);  map = 0x0F1111FB;       break;
3154         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_RECORD_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3155         default:                        size = sizeof(MCI_RECORD_PARMS);        break;
3156         }
3157         break;
3158     case MCI_RESUME:
3159         size = sizeof(MCI_GENERIC_PARMS);
3160         break;
3161     case MCI_SEEK:
3162         switch (uDevType) {
3163         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SEEK_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3164         default:                        size = sizeof(MCI_SEEK_PARMS);          break;
3165         }
3166         break;
3167     case MCI_SET:
3168         switch (uDevType) {
3169         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SET_PARMS);       break;
3170         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SET_PARMS);     break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3171         case MCI_DEVTYPE_SEQUENCER:     size = sizeof(MCI_SEQ_SET_PARMS);       break;
3172         /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
3173          * so not doing anything should work...
3174          */
3175         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_SET_PARMS);      break;
3176         default:                        size = sizeof(MCI_SET_PARMS);           break;
3177         }
3178         break;
3179     case MCI_SETAUDIO:
3180         switch (uDevType) {
3181         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SETAUDIO_PARMS16);map = 0x0000077FF;      break;
3182         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3183         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3184         }
3185         break;
3186         /* case MCI_SETTIMECODE:*/
3187         /* case MCI_SIGNAL:*/
3188         /* case MCI_SOUND:*/
3189     case MCI_SPIN:
3190         size = sizeof(MCI_SET_PARMS);
3191         break;
3192     case MCI_STATUS:
3193         keep = TRUE;
3194         switch (uDevType) {
3195         /* FIXME:
3196          * don't know if buffer for value is the one passed through lpstrDevice
3197          * or is provided by MCI driver.
3198          * Assuming solution 2: provided by MCI driver, so zeroing on entry
3199          */
3200         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16);  map = 0x0B6FF;          break;
3201         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3202         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
3203         }
3204         break;
3205     case MCI_STEP:
3206         switch (uDevType) {
3207         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STEP_PARMS);      break;
3208         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STEP_PARMS);    break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3209         case MCI_DEVTYPE_VIDEODISC:     size = sizeof(MCI_VD_STEP_PARMS);       break;
3210         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3211         }
3212         break;
3213     case MCI_STOP:
3214         size = sizeof(MCI_SET_PARMS);
3215         break;
3216     case MCI_SYSINFO:
3217         {
3218             LPMCI_SYSINFO_PARMSW  msip32w = (LPMCI_SYSINFO_PARMSW)(*lParam);
3219             LPMCI_SYSINFO_PARMS16 msip16;
3220             char* ptr = HeapAlloc( GetProcessHeap(), 0,
3221                                    sizeof(LPMCI_SYSINFO_PARMSW) + sizeof(MCI_SYSINFO_PARMS16) );
3222
3223             if (ptr) {
3224                 *(LPMCI_SYSINFO_PARMSW*)(ptr) = msip32w;
3225                 msip16 = (LPMCI_SYSINFO_PARMS16)(ptr + sizeof(LPMCI_SYSINFO_PARMSW));
3226
3227                 msip16->dwCallback       = msip32w->dwCallback;
3228                 msip16->lpstrReturn      = MapLS( HeapAlloc(GetProcessHeap(), 0, msip32w->dwRetSize) );
3229                 msip16->dwRetSize        = msip32w->dwRetSize;
3230                 msip16->dwNumber         = msip32w->dwNumber;
3231                 msip16->wDeviceType      = msip32w->wDeviceType;
3232             } else {
3233                 return WINMM_MAP_NOMEM;
3234             }
3235             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_SYSINFO_PARMSW);
3236         }
3237         return WINMM_MAP_OKMEM;
3238         /* case MCI_UNDO: */
3239     case MCI_UNFREEZE:
3240         switch (uDevType) {
3241         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       break;
3242         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       break;
3243         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3244         }
3245         break;
3246     case MCI_UPDATE:
3247         switch (uDevType) {
3248         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_UPDATE_PARMS16);  map = 0x000B1111B;      break;
3249         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3250         }
3251         break;
3252     case MCI_WHERE:
3253         switch (uDevType) {
3254         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       keep = TRUE;    break;
3255         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       keep = TRUE;    break;
3256         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3257         }
3258         break;
3259     case MCI_WINDOW:
3260         switch (uDevType) {
3261         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7FB;        break;
3262         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7FB;        break;
3263         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
3264         }
3265         break;
3266     case DRV_OPEN:
3267         {
3268             LPMCI_OPEN_DRIVER_PARMSW  modp32w = (LPMCI_OPEN_DRIVER_PARMSW)(*lParam);
3269             LPMCI_OPEN_DRIVER_PARMS16 modp16;
3270             char *ptr = HeapAlloc( GetProcessHeap(), 0,
3271                                    sizeof(LPMCI_OPEN_DRIVER_PARMSW) + sizeof(MCI_OPEN_DRIVER_PARMS16));
3272
3273             if (ptr) {
3274                 *(LPMCI_OPEN_DRIVER_PARMSW*)(ptr) = modp32w;
3275                 modp16 = (LPMCI_OPEN_DRIVER_PARMS16)(ptr + sizeof(LPMCI_OPEN_DRIVER_PARMSW));
3276                 modp16->wDeviceID = modp32w->wDeviceID;
3277                 modp16->lpstrParams = MapLS( MCI_strdupWtoA(modp32w->lpstrParams) );
3278                 /* other fields are gonna be filled by the driver, don't copy them */
3279             } else {
3280                 return WINMM_MAP_NOMEM;
3281             }
3282             *lParam = (LPARAM)MapLS(ptr) + sizeof(LPMCI_OPEN_DRIVER_PARMSW);
3283         }
3284         return WINMM_MAP_OKMEM;
3285     case DRV_LOAD:
3286     case DRV_ENABLE:
3287     case DRV_CLOSE:
3288     case DRV_DISABLE:
3289     case DRV_FREE:
3290     case DRV_CONFIGURE:
3291     case DRV_QUERYCONFIGURE:
3292     case DRV_INSTALL:
3293     case DRV_REMOVE:
3294     case DRV_EXITSESSION:
3295     case DRV_EXITAPPLICATION:
3296     case DRV_POWER:
3297         return WINMM_MAP_OK;
3298
3299     default:
3300         FIXME("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
3301         return WINMM_MAP_MSGERROR;
3302     }
3303     return MCI_MsgMapper32WTo16_Create((void**)lParam, size, map, keep);
3304 }
3305
3306 /**************************************************************************
3307  *                      MCI_UnMapMsg32WTo16                     [internal]
3308  */
3309 static  WINMM_MapType   MCI_UnMapMsg32WTo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
3310 {
3311     int         size = 0;
3312     BOOLEAN     kept = FALSE;   /* there is no need to compute size when kept is FALSE */
3313     DWORD       map = 0;
3314
3315     switch (wMsg) {
3316     case MCI_BREAK:
3317         break;
3318         /* case MCI_CAPTURE */
3319     case MCI_CLOSE:
3320     case MCI_CLOSE_DRIVER:
3321     case MCI_CONFIGURE:
3322         break;
3323         /* case MCI_COPY: */
3324     case MCI_CUE:
3325         break;
3326         /* case MCI_CUT: */
3327     case MCI_DELETE:
3328         break;
3329         /* case MCI_ESCAPE: */
3330     case MCI_FREEZE:
3331         break;
3332     case MCI_GETDEVCAPS:
3333         kept = TRUE;
3334         size = sizeof(MCI_GETDEVCAPS_PARMS);
3335         break;
3336         /* case MCI_INDEX: */
3337     case MCI_INFO:
3338         if (lParam) {
3339             LPMCI_INFO_PARMS16  mip16  = (LPMCI_INFO_PARMS16)MapSL(lParam);
3340             LPMCI_INFO_PARMSW   mip32w = *(LPMCI_INFO_PARMSW*)((char*)mip16 - sizeof(LPMCI_INFO_PARMSW));
3341
3342             MultiByteToWideChar(CP_ACP, 0, MapSL(mip16->lpstrReturn), mip16->dwRetSize, 
3343                                 mip32w->lpstrReturn, mip32w->dwRetSize / sizeof(WCHAR));
3344             UnMapLS( lParam );
3345             UnMapLS( mip16->lpstrReturn );
3346             HeapFree( GetProcessHeap(), 0, (void*)MapSL(mip16->lpstrReturn) );
3347             HeapFree( GetProcessHeap(), 0, (char*)mip16 - sizeof(LPMCI_OPEN_PARMSW) );
3348         }
3349         return WINMM_MAP_OK;
3350         /* case MCI_MARK: */
3351         /* case MCI_MONITOR: */
3352     case MCI_OPEN:
3353     case MCI_OPEN_DRIVER:
3354         if (lParam) {
3355             LPMCI_OPEN_PARMS16  mop16  = (LPMCI_OPEN_PARMS16)MapSL(lParam);
3356             LPMCI_OPEN_PARMSW   mop32w = *(LPMCI_OPEN_PARMSW*)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSW));
3357             UnMapLS( lParam );
3358             mop32w->wDeviceID = mop16->wDeviceID;
3359             if ((dwFlags & MCI_OPEN_TYPE) && !(dwFlags & MCI_OPEN_TYPE_ID))
3360             {
3361                 HeapFree(GetProcessHeap(), 0, MapSL(mop16->lpstrDeviceType));
3362                 UnMapLS( mop16->lpstrDeviceType );
3363             }
3364             if ((dwFlags & MCI_OPEN_ELEMENT) && !(dwFlags & MCI_OPEN_ELEMENT_ID))
3365             {
3366                 HeapFree(GetProcessHeap(), 0, MapSL(mop16->lpstrElementName));
3367                 UnMapLS( mop16->lpstrElementName );
3368             }
3369             if (dwFlags & MCI_OPEN_ALIAS)
3370             {
3371                 HeapFree(GetProcessHeap(), 0, MapSL(mop16->lpstrAlias));
3372                 UnMapLS( mop16->lpstrAlias );
3373             }
3374             HeapFree( GetProcessHeap(), 0, (char*)mop16 - sizeof(LPMCI_OPEN_PARMSW) );
3375         }
3376         return WINMM_MAP_OK;
3377         /* case MCI_PASTE:*/
3378     case MCI_PAUSE:
3379         break;
3380     case MCI_PLAY:
3381         break;
3382     case MCI_PUT:
3383         break;
3384     case MCI_REALIZE:
3385         break;
3386     case MCI_RECORD:
3387         break;
3388     case MCI_RESUME:
3389         break;
3390     case MCI_SEEK:
3391         break;
3392     case MCI_SET:
3393         break;
3394     case MCI_SETAUDIO:
3395         switch (uDevType) {
3396         case MCI_DEVTYPE_DIGITAL_VIDEO: map = 0x0000077FF;      break;
3397         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SETAUDIO_PARMS);        break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3398         }
3399         break;
3400         /* case MCI_SETTIMECODE:*/
3401         /* case MCI_SIGNAL:*/
3402         /* case MCI_SOUND:*/
3403     case MCI_SPIN:
3404         break;
3405     case MCI_STATUS:
3406         kept = TRUE;
3407         switch (uDevType) {
3408         case MCI_DEVTYPE_DIGITAL_VIDEO:
3409         if (lParam) {
3410             LPMCI_DGV_STATUS_PARMS16    mdsp16  = (LPMCI_DGV_STATUS_PARMS16)MapSL(lParam);
3411             LPMCI_DGV_STATUS_PARMSA     mdsp32a = *(LPMCI_DGV_STATUS_PARMSA*)((char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA));
3412
3413             UnMapLS( lParam );
3414             if (mdsp16) {
3415                 mdsp32a->dwReturn = mdsp16->dwReturn;
3416                 if (dwFlags & MCI_DGV_STATUS_DISKSPACE) {
3417                     TRACE("MCI_STATUS (DGV) lpstrDrive=%08lx\n", mdsp16->lpstrDrive);
3418                     TRACE("MCI_STATUS (DGV) lpstrDrive=%s\n", (LPSTR)MapSL(mdsp16->lpstrDrive));
3419                     UnMapLS( mdsp16->lpstrDrive );
3420                 }
3421                 HeapFree( GetProcessHeap(), 0, (char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA) );
3422             } else {
3423                 return WINMM_MAP_NOMEM;
3424             }
3425         }
3426         return WINMM_MAP_OKMEM;
3427         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME("NIY vcr\n");     return WINMM_MAP_NOMEM;
3428         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
3429         }
3430         break;
3431     case MCI_STEP:
3432         break;
3433     case MCI_STOP:
3434         break;
3435     case MCI_SYSINFO:
3436         if (lParam) {
3437             LPMCI_SYSINFO_PARMS16       msip16  = (LPMCI_SYSINFO_PARMS16)MapSL(lParam);
3438             LPMCI_SYSINFO_PARMSW        msip32w = *(LPMCI_SYSINFO_PARMSW*)((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSW));
3439
3440             UnMapLS( lParam );
3441             if (msip16) {
3442                 MultiByteToWideChar(CP_ACP, 0, MapSL(msip16->lpstrReturn), msip16->dwRetSize, 
3443                                     msip32w->lpstrReturn, msip32w->dwRetSize);
3444                 UnMapLS( msip16->lpstrReturn );
3445                 HeapFree( GetProcessHeap(), 0, MapSL(msip16->lpstrReturn) );
3446                 HeapFree( GetProcessHeap(), 0, (char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSW) );
3447             } else {
3448                 return WINMM_MAP_NOMEM;
3449             }
3450         }
3451         return WINMM_MAP_OKMEM;
3452         /* case MCI_UNDO: */
3453     case MCI_UNFREEZE:
3454         break;
3455     case MCI_UPDATE:
3456         break;
3457     case MCI_WHERE:
3458         switch (uDevType) {
3459         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16);    map = 0x0001111B;       kept = TRUE;    break;
3460         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS16);   map = 0x0001111B;       kept = TRUE;    break;
3461         default:                        break;
3462         }
3463         break;
3464     case MCI_WINDOW:
3465         switch (uDevType) {
3466         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  if (dwFlags & MCI_DGV_WINDOW_TEXT)  map = 0x7666;       break;
3467         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7666;       break;
3468         default:                        break;
3469         }
3470         /* FIXME: see map function */
3471         break;
3472     case DRV_OPEN:
3473         if (lParam) {
3474             LPMCI_OPEN_DRIVER_PARMS16   modp16  = (LPMCI_OPEN_DRIVER_PARMS16)MapSL(lParam);
3475             LPMCI_OPEN_DRIVER_PARMSW    modp32w = *(LPMCI_OPEN_DRIVER_PARMSW*)((char*)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSW));
3476
3477             UnMapLS( lParam );
3478             modp32w->wCustomCommandTable = modp16->wCustomCommandTable;
3479             modp32w->wType = modp16->wType;
3480             HeapFree(GetProcessHeap(), 0, MapSL(modp16->lpstrParams));
3481             UnMapLS( modp16->lpstrParams );
3482             HeapFree( GetProcessHeap(), 0, (char *)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSW) );
3483         }
3484         return WINMM_MAP_OK;
3485     case DRV_LOAD:
3486     case DRV_ENABLE:
3487     case DRV_CLOSE:
3488     case DRV_DISABLE:
3489     case DRV_FREE:
3490     case DRV_CONFIGURE:
3491     case DRV_QUERYCONFIGURE:
3492     case DRV_INSTALL:
3493     case DRV_REMOVE:
3494     case DRV_EXITSESSION:
3495     case DRV_EXITAPPLICATION:
3496     case DRV_POWER:
3497         FIXME("This is a hack\n");
3498         return WINMM_MAP_OK;
3499
3500     default:
3501         FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
3502         return WINMM_MAP_MSGERROR;
3503     }
3504     return MCI_MsgMapper32WTo16_Destroy((void*)lParam, size, map, kept);
3505 }
3506
3507 void    MMDRV_Init16(void)
3508 {
3509 #define A(_x,_y) MMDRV_InstallMap(_x, \
3510 MMDRV_##_y##_Map16To32W, MMDRV_##_y##_UnMap16To32W, \
3511 MMDRV_##_y##_Map32WTo16, MMDRV_##_y##_UnMap32WTo16, \
3512 MMDRV_##_y##_Callback)
3513     A(MMDRV_AUX,        Aux);
3514     A(MMDRV_MIXER,      Mixer);
3515     A(MMDRV_MIDIIN,     MidiIn);
3516     A(MMDRV_MIDIOUT,    MidiOut);
3517     A(MMDRV_WAVEIN,     WaveIn);
3518     A(MMDRV_WAVEOUT,    WaveOut);
3519 #undef A
3520
3521     pFnCallMMDrvFunc16 = MMDRV_CallMMDrvFunc16;
3522     pFnLoadMMDrvFunc16 = MMDRV_LoadMMDrvFunc16;
3523
3524     pFnMciMapMsg16To32W   = MCI_MapMsg16To32W;
3525     pFnMciUnMapMsg16To32W = MCI_UnMapMsg16To32W;
3526     pFnMciMapMsg32WTo16   = MCI_MapMsg32WTo16;
3527     pFnMciUnMapMsg32WTo16 = MCI_UnMapMsg32WTo16;
3528 }