Fix large item label calculation when not focused.
[wine] / dlls / winmm / lolvldrv.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  * MMSYTEM low level drivers handling functions
5  *
6  * Copyright 1999 Eric Pouech
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <string.h>
24 #include <stdio.h>
25 #include <assert.h>
26 #include "wine/winbase16.h"
27 #include "winreg.h"
28 #include "winver.h"
29 #include "winemm.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
33
34 typedef DWORD   (CALLBACK *WINEMM_msgFunc16)(UINT16, WORD, DWORD, DWORD, DWORD);
35 typedef DWORD   (CALLBACK *WINEMM_msgFunc32)(UINT  , UINT, DWORD, DWORD, DWORD);
36
37 /* for each loaded driver and each known type of driver, this structure contains
38  * the information needed to access it
39  */
40 typedef struct tagWINE_MM_DRIVER_PART {
41     int                         nIDMin;         /* lower bound of global indexes for this type */
42     int                         nIDMax;         /* hhigher bound of global indexes for this type */
43     union {
44         WINEMM_msgFunc32        fnMessage32;    /* pointer to fonction */
45         WINEMM_msgFunc16        fnMessage16;
46     } u;
47 } WINE_MM_DRIVER_PART;
48
49 /* each low-level .drv will be associated with an instance of this structure */
50 typedef struct tagWINE_MM_DRIVER {
51     HDRVR                       hDriver;
52     LPSTR                       drvname;        /* name of the driver */
53     BOOL                        bIs32 : 1,      /* TRUE if 32 bit driver, FALSE for 16 */
54                                 bIsMapper : 1;  /* TRUE if mapper */
55     WINE_MM_DRIVER_PART         parts[MMDRV_MAX];/* Information for all known types */
56 } WINE_MM_DRIVER, *LPWINE_MM_DRIVER;
57
58 typedef enum {
59     MMDRV_MAP_NOMEM,    /* ko, memory problem */
60     MMDRV_MAP_MSGERROR, /* ko, unknown message */
61     MMDRV_MAP_OK,       /* ok, no memory allocated. to be sent to the proc. */
62     MMDRV_MAP_OKMEM,    /* ok, some memory allocated, need to call UnMapMsg. to be sent to the proc. */
63     MMDRV_MAP_PASS      /* not handled (no memory allocated) to be sent to the driver */
64 } MMDRV_MapType;
65
66 typedef MMDRV_MapType   (*MMDRV_MAPFUNC)(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2);
67
68 /* each known type of driver has an instance of this structure */
69 typedef struct tagWINE_LLTYPE {
70     /* those attributes depend on the specification of the type */
71     LPSTR               typestr;        /* name (for debugging) */
72     BOOL                bSupportMapper; /* if type is allowed to support mapper */
73     MMDRV_MAPFUNC       Map16To32A;     /* those are function pointers to handle */
74     MMDRV_MAPFUNC       UnMap16To32A;   /*   the parameter conversion (16 vs 32 bit) */
75     MMDRV_MAPFUNC       Map32ATo16;     /*   when hi-func (in mmsystem or winmm) and */
76     MMDRV_MAPFUNC       UnMap32ATo16;   /*   low-func (in .drv) do not match */
77     LPDRVCALLBACK       Callback;       /* handles callback for a specified type */
78     /* those attributes reflect the loaded/current situation for the type */
79     UINT                wMaxId;         /* number of loaded devices (sum across all loaded drivers */
80     LPWINE_MLD          lpMlds;         /* "static" mlds to access the part though device IDs */
81     int                 nMapper;        /* index to mapper */
82 } WINE_LLTYPE;
83
84 static int              MMDrvsHi /* = 0 */;
85 static WINE_MM_DRIVER   MMDrvs[3];
86 static LPWINE_MLD       MM_MLDrvs[40];
87 #define MAX_MM_MLDRVS   (sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0]))
88
89 /* ### start build ### */
90 extern WORD CALLBACK MMDRV_CallTo16_word_wwlll(FARPROC16,WORD,WORD,LONG,LONG,LONG);
91 /* ### stop build ### */
92
93 /**************************************************************************
94  *                              MMDRV_GetDescription16          [internal]
95  */
96 static  BOOL    MMDRV_GetDescription16(const char* fname, char* buf, int buflen)
97 {
98     OFSTRUCT    ofs;
99     HFILE       hFile;
100     WORD        w;
101     DWORD       dw;
102     BOOL        ret = FALSE;
103
104     if ((hFile = OpenFile(fname, &ofs, OF_READ | OF_SHARE_DENY_WRITE)) == HFILE_ERROR) {
105         ERR("Can't open file %s (builtin driver ?)\n", fname);
106         return FALSE;
107     }
108
109 #define E(_x)   do {TRACE _x;goto theEnd;} while(0)
110
111     if (_lread(hFile, &w, 2) != 2)                      E(("Can't read sig\n"));
112     if (w != ('Z' * 256 + 'M'))                         E(("Bad sig %04x\n", w));
113     if (_llseek(hFile, 0x3C, SEEK_SET) < 0)             E(("Can't seek to ext header offset\n"));
114     if (_lread(hFile, &dw, 4) != 4)                     E(("Can't read ext header offset\n"));
115     if (_llseek(hFile, dw + 0x2C, SEEK_SET) < 0)        E(("Can't seek to ext header.nr table %lu\n", dw+0x2C));
116     if (_lread(hFile, &dw, 4) != 4)                     E(("Can't read nr table offset\n"));
117     if (_llseek(hFile, dw, SEEK_SET) < 0)               E(("Can't seek to nr table %lu\n", dw));
118     if (_lread(hFile, buf, 1) != 1)                     E(("Can't read descr length\n"));
119     buflen = min((int)(unsigned)(BYTE)buf[0], buflen - 1);
120     if (_lread(hFile, buf, buflen) != buflen)           E(("Can't read descr (%d)\n", buflen));
121     buf[buflen] = '\0';
122     ret = TRUE;
123     TRACE("Got '%s' [%d]\n", buf, buflen);
124 theEnd:
125     CloseHandle(hFile);
126     return ret;
127 }
128
129 /**************************************************************************
130  *                              MMDRV_GetDescription32          [internal]
131  */
132 static  BOOL    MMDRV_GetDescription32(const char* fname, char* buf, int buflen)
133 {
134     OFSTRUCT    ofs;
135     DWORD       h;
136     LPVOID      ptr = 0;
137     LPVOID      val;
138     DWORD       dw;
139     BOOL        ret = FALSE;
140     UINT        u;
141     FARPROC pGetFileVersionInfoSizeA;
142     FARPROC pGetFileVersionInfoA;
143     FARPROC pVerQueryValueA;
144     HMODULE hmodule = 0;
145
146 #define E(_x)   do {TRACE _x;goto theEnd;} while(0)
147
148     if (OpenFile(fname, &ofs, OF_EXIST)==HFILE_ERROR)           E(("Can't find file %s\n", fname));
149
150     if (!(hmodule = LoadLibraryA( "version.dll" ))) goto theEnd;
151     if (!(pGetFileVersionInfoSizeA = GetProcAddress( hmodule, "GetFileVersionInfoSizeA" )))
152         goto theEnd;
153     if (!(pGetFileVersionInfoA = GetProcAddress( hmodule, "GetFileVersionInfoA" )))
154         goto theEnd;
155     if (!(pVerQueryValueA = GetProcAddress( hmodule, "pVerQueryValueA" )))
156         goto theEnd;
157
158     if (!(dw = pGetFileVersionInfoSizeA(ofs.szPathName, &h)))   E(("Can't get FVIS\n"));
159     if (!(ptr = HeapAlloc(GetProcessHeap(), 0, dw)))            E(("OOM\n"));
160     if (!pGetFileVersionInfoA(ofs.szPathName, h, dw, ptr))      E(("Can't get FVI\n"));
161
162 #define A(_x) if (pVerQueryValueA(ptr, "\\StringFileInfo\\040904B0\\" #_x, &val, &u)) \
163                   TRACE(#_x " => %s\n", (LPSTR)val); else TRACE(#_x " @\n")
164
165     A(CompanyName);
166     A(FileDescription);
167     A(FileVersion);
168     A(InternalName);
169     A(LegalCopyright);
170     A(OriginalFilename);
171     A(ProductName);
172     A(ProductVersion);
173     A(Comments);
174     A(LegalTrademarks);
175     A(PrivateBuild);
176     A(SpecialBuild);
177 #undef A
178
179     if (!pVerQueryValueA(ptr, "\\StringFileInfo\\040904B0\\ProductName", &val, &u)) E(("Can't get product name\n"));
180     lstrcpynA(buf, val, buflen);
181
182 #undef E
183     ret = TRUE;
184 theEnd:
185     HeapFree(GetProcessHeap(), 0, ptr);
186     if (hmodule) FreeLibrary( hmodule );
187     return ret;
188 }
189
190 /**************************************************************************
191  *                              MMDRV_Callback                  [internal]
192  */
193 static void     MMDRV_Callback(LPWINE_MLD mld, HDRVR hDev, UINT uMsg, DWORD dwParam1, DWORD dwParam2)
194 {
195     TRACE("CB (*%08lx)(%08x %08x %08lx %08lx %08lx\n",
196           mld->dwCallback, hDev, uMsg, mld->dwClientInstance, dwParam1, dwParam2);
197
198     if (!mld->bFrom32 && (mld->dwFlags & DCB_TYPEMASK) == DCB_FUNCTION) {
199         /* 16 bit func, call it */
200         TRACE("Function (16 bit) !\n");
201         MMDRV_CallTo16_word_wwlll((FARPROC16)mld->dwCallback, HDRVR_16(hDev), uMsg,
202                                   mld->dwClientInstance, dwParam1, dwParam2);
203     } else {
204         DriverCallback(mld->dwCallback, mld->dwFlags, hDev, uMsg,
205                        mld->dwClientInstance, dwParam1, dwParam2);
206     }
207 }
208
209 /* =================================
210  *       A U X    M A P P E R S
211  * ================================= */
212
213 /**************************************************************************
214  *                              MMDRV_Aux_Map16To32A            [internal]
215  */
216 static  MMDRV_MapType   MMDRV_Aux_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
217 {
218     return MMDRV_MAP_MSGERROR;
219 }
220
221 /**************************************************************************
222  *                              MMDRV_Aux_UnMap16To32A          [internal]
223  */
224 static  MMDRV_MapType   MMDRV_Aux_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
225 {
226     return MMDRV_MAP_MSGERROR;
227 }
228
229 /**************************************************************************
230  *                              MMDRV_Aux_Map32ATo16            [internal]
231  */
232 static  MMDRV_MapType   MMDRV_Aux_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
233 {
234     return MMDRV_MAP_MSGERROR;
235 }
236
237 /**************************************************************************
238  *                              MMDRV_Aux_UnMap32ATo16          [internal]
239  */
240 static  MMDRV_MapType   MMDRV_Aux_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
241 {
242 #if 0
243  case AUXDM_GETDEVCAPS:
244     lpCaps->wMid = ac16.wMid;
245     lpCaps->wPid = ac16.wPid;
246     lpCaps->vDriverVersion = ac16.vDriverVersion;
247     strcpy(lpCaps->szPname, ac16.szPname);
248     lpCaps->wTechnology = ac16.wTechnology;
249     lpCaps->dwSupport = ac16.dwSupport;
250 #endif
251     return MMDRV_MAP_MSGERROR;
252 }
253
254 /**************************************************************************
255  *                              MMDRV_Aux_Callback              [internal]
256  */
257 static void     CALLBACK MMDRV_Aux_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
258 {
259     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
260
261     FIXME("NIY\n");
262     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
263 }
264
265 /* =================================
266  *     M I X E R  M A P P E R S
267  * ================================= */
268
269 /**************************************************************************
270  *                              xMMDRV_Mixer_Map16To32A         [internal]
271  */
272 static  MMDRV_MapType   MMDRV_Mixer_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
273 {
274     return MMDRV_MAP_MSGERROR;
275 }
276
277 /**************************************************************************
278  *                              MMDRV_Mixer_UnMap16To32A        [internal]
279  */
280 static  MMDRV_MapType   MMDRV_Mixer_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
281 {
282 #if 0
283     MIXERCAPSA  micA;
284     UINT        ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
285
286     if (ret == MMSYSERR_NOERROR) {
287         mixcaps->wMid           = micA.wMid;
288         mixcaps->wPid           = micA.wPid;
289         mixcaps->vDriverVersion = micA.vDriverVersion;
290         strcpy(mixcaps->szPname, micA.szPname);
291         mixcaps->fdwSupport     = micA.fdwSupport;
292         mixcaps->cDestinations  = micA.cDestinations;
293     }
294     return ret;
295 #endif
296     return MMDRV_MAP_MSGERROR;
297 }
298
299 /**************************************************************************
300  *                              MMDRV_Mixer_Map32ATo16          [internal]
301  */
302 static  MMDRV_MapType   MMDRV_Mixer_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
303 {
304     return MMDRV_MAP_MSGERROR;
305 }
306
307 /**************************************************************************
308  *                              MMDRV_Mixer_UnMap32ATo16        [internal]
309  */
310 static  MMDRV_MapType   MMDRV_Mixer_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
311 {
312     return MMDRV_MAP_MSGERROR;
313 }
314
315 /**************************************************************************
316  *                              MMDRV_Mixer_Callback            [internal]
317  */
318 static void     CALLBACK MMDRV_Mixer_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
319 {
320     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
321
322     FIXME("NIY\n");
323     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
324 }
325
326 /* =================================
327  *   M I D I  I N    M A P P E R S
328  * ================================= */
329
330 /**************************************************************************
331  *                              MMDRV_MidiIn_Map16To32A         [internal]
332  */
333 static  MMDRV_MapType   MMDRV_MidiIn_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
334 {
335     return MMDRV_MAP_MSGERROR;
336 }
337
338 /**************************************************************************
339  *                              MMDRV_MidiIn_UnMap16To32A       [internal]
340  */
341 static  MMDRV_MapType   MMDRV_MidiIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
342 {
343     return MMDRV_MAP_MSGERROR;
344 }
345
346 /**************************************************************************
347  *                              MMDRV_MidiIn_Map32ATo16         [internal]
348  */
349 static  MMDRV_MapType   MMDRV_MidiIn_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
350 {
351     return MMDRV_MAP_MSGERROR;
352 }
353
354 /**************************************************************************
355  *                              MMDRV_MidiIn_UnMap32ATo16       [internal]
356  */
357 static  MMDRV_MapType   MMDRV_MidiIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
358 {
359     return MMDRV_MAP_MSGERROR;
360 }
361
362 /**************************************************************************
363  *                              MMDRV_MidiIn_Callback           [internal]
364  */
365 static void     CALLBACK MMDRV_MidiIn_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
366 {
367     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
368
369     switch (uMsg) {
370     case MIM_OPEN:
371     case MIM_CLOSE:
372         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
373
374     case MIM_DATA:
375     case MIM_MOREDATA:
376     case MIM_ERROR:
377         /* dwParam1 & dwParam2 are are data, nothing to do */
378         break;
379     case MIM_LONGDATA:
380     case MIM_LONGERROR:
381         /* dwParam1 points to a MidiHdr, work to be done !!! */
382         if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
383             /* initial map is: 32 => 16 */
384             LPMIDIHDR           mh16 = MapSL(dwParam1);
385             LPMIDIHDR           mh32 = *(LPMIDIHDR*)((LPSTR)mh16 - sizeof(LPMIDIHDR));
386
387             dwParam1 = (DWORD)mh32;
388             mh32->dwFlags = mh16->dwFlags;
389             mh32->dwBytesRecorded = mh16->dwBytesRecorded;
390             if (mh32->reserved >= sizeof(MIDIHDR))
391                 mh32->dwOffset = mh16->dwOffset;
392         } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
393             /* initial map is: 16 => 32 */
394             LPMIDIHDR           mh32 = (LPMIDIHDR)(dwParam1);
395             SEGPTR              segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
396             LPMIDIHDR           mh16 = MapSL(segmh16);
397
398             dwParam1 = (DWORD)segmh16;
399             mh16->dwFlags = mh32->dwFlags;
400             mh16->dwBytesRecorded = mh32->dwBytesRecorded;
401             if (mh16->reserved >= sizeof(MIDIHDR))
402                 mh16->dwOffset = mh32->dwOffset;
403         }
404         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
405         break;
406     /* case MOM_POSITIONCB: */
407     default:
408         ERR("Unknown msg %u\n", uMsg);
409     }
410
411     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
412 }
413
414 /* =================================
415  *   M I D I  O U T  M A P P E R S
416  * ================================= */
417
418 /**************************************************************************
419  *                              MMDRV_MidiOut_Map16To32A        [internal]
420  */
421 static  MMDRV_MapType   MMDRV_MidiOut_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
422 {
423     MMDRV_MapType       ret = MMDRV_MAP_MSGERROR;
424
425     switch (wMsg) {
426     case MODM_GETNUMDEVS:
427     case MODM_DATA:
428     case MODM_RESET:
429     case MODM_SETVOLUME:
430         ret = MMDRV_MAP_OK;
431         break;
432
433     case MODM_OPEN:
434     case MODM_CLOSE:
435     case MODM_GETVOLUME:
436         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
437         break;
438
439     case MODM_GETDEVCAPS:
440         {
441             LPMIDIOUTCAPSA      moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSA));
442             LPMIDIOUTCAPS16     moc16 = MapSL(*lpParam1);
443
444             if (moc32) {
445                 *(LPMIDIOUTCAPS16*)moc32 = moc16;
446                 moc32 = (LPMIDIOUTCAPSA)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16));
447                 *lpParam1 = (DWORD)moc32;
448                 *lpParam2 = sizeof(MIDIOUTCAPSA);
449
450                 ret = MMDRV_MAP_OKMEM;
451             } else {
452                 ret = MMDRV_MAP_NOMEM;
453             }
454         }
455         break;
456     case MODM_PREPARE:
457         {
458             LPMIDIHDR           mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR));
459             LPMIDIHDR           mh16 = MapSL(*lpParam1);
460
461             if (mh32) {
462                 *(LPMIDIHDR*)mh32 = (LPMIDIHDR)*lpParam1;
463                 mh32 = (LPMIDIHDR)((LPSTR)mh32 + sizeof(LPMIDIHDR));
464                 mh32->lpData = MapSL((SEGPTR)mh16->lpData);
465                 mh32->dwBufferLength = mh16->dwBufferLength;
466                 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
467                 mh32->dwUser = mh16->dwUser;
468                 mh32->dwFlags = mh16->dwFlags;
469                 /* FIXME: nothing on mh32->lpNext */
470                 /* could link the mh32->lpNext at this level for memory house keeping */
471                 mh32->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? ((LPMIDIHDR)mh16)->dwOffset : 0;
472                 mh16->lpNext = mh32; /* for reuse in unprepare and write */
473                 /* store size of passed MIDIHDR?? structure to know if dwOffset is available or not */
474                 mh16->reserved = *lpParam2;
475                 *lpParam1 = (DWORD)mh32;
476                 *lpParam2 = sizeof(MIDIHDR);
477
478                 ret = MMDRV_MAP_OKMEM;
479             } else {
480                 ret = MMDRV_MAP_NOMEM;
481             }
482         }
483         break;
484     case MODM_UNPREPARE:
485     case MODM_LONGDATA:
486         {
487             LPMIDIHDR           mh16 = MapSL(*lpParam1);
488             LPMIDIHDR           mh32 = (LPMIDIHDR)mh16->lpNext;
489
490             *lpParam1 = (DWORD)mh32;
491             *lpParam2 = sizeof(MIDIHDR);
492             /* dwBufferLength can be reduced between prepare & write */
493             if (wMsg == MODM_LONGDATA && mh32->dwBufferLength < mh16->dwBufferLength) {
494                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
495                     mh32->dwBufferLength, mh16->dwBufferLength);
496             } else
497                 mh32->dwBufferLength = mh16->dwBufferLength;
498             ret = MMDRV_MAP_OKMEM;
499         }
500         break;
501
502     case MODM_CACHEPATCHES:
503     case MODM_CACHEDRUMPATCHES:
504     default:
505         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
506         break;
507     }
508     return ret;
509 }
510
511 /**************************************************************************
512  *                              MMDRV_MidiOut_UnMap16To32A      [internal]
513  */
514 static  MMDRV_MapType   MMDRV_MidiOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
515 {
516     MMDRV_MapType       ret = MMDRV_MAP_MSGERROR;
517
518     switch (wMsg) {
519     case MODM_GETNUMDEVS:
520     case MODM_DATA:
521     case MODM_RESET:
522     case MODM_SETVOLUME:
523         ret = MMDRV_MAP_OK;
524         break;
525
526     case MODM_OPEN:
527     case MODM_CLOSE:
528     case MODM_GETVOLUME:
529         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
530         break;
531
532     case MODM_GETDEVCAPS:
533         {
534             LPMIDIOUTCAPSA              moc32 = (LPMIDIOUTCAPSA)(*lpParam1);
535             LPMIDIOUTCAPS16             moc16 = *(LPMIDIOUTCAPS16*)((LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
536
537             moc16->wMid                 = moc32->wMid;
538             moc16->wPid                 = moc32->wPid;
539             moc16->vDriverVersion       = moc32->vDriverVersion;
540             strcpy(moc16->szPname, moc32->szPname);
541             moc16->wTechnology          = moc32->wTechnology;
542             moc16->wVoices              = moc32->wVoices;
543             moc16->wNotes               = moc32->wNotes;
544             moc16->wChannelMask         = moc32->wChannelMask;
545             moc16->dwSupport            = moc32->dwSupport;
546             HeapFree(GetProcessHeap(), 0, (LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
547             ret = MMDRV_MAP_OK;
548         }
549         break;
550     case MODM_PREPARE:
551     case MODM_UNPREPARE:
552     case MODM_LONGDATA:
553         {
554             LPMIDIHDR           mh32 = (LPMIDIHDR)(*lpParam1);
555             LPMIDIHDR           mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)));
556
557             assert(mh16->lpNext == mh32);
558             mh16->dwBufferLength = mh32->dwBufferLength;
559             mh16->dwBytesRecorded = mh32->dwBytesRecorded;
560             mh16->dwUser = mh32->dwUser;
561             mh16->dwFlags = mh32->dwFlags;
562             if (mh16->reserved >= sizeof(MIDIHDR))
563                 mh16->dwOffset = mh32->dwOffset;
564
565             if (wMsg == MODM_UNPREPARE) {
566                 HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR));
567                 mh16->lpNext = 0;
568             }
569             ret = MMDRV_MAP_OK;
570         }
571         break;
572
573     case MODM_CACHEPATCHES:
574     case MODM_CACHEDRUMPATCHES:
575     default:
576         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
577         break;
578     }
579     return ret;
580 }
581
582 /**************************************************************************
583  *                              MMDRV_MidiOut_Map32ATo16        [internal]
584  */
585 static  MMDRV_MapType   MMDRV_MidiOut_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
586 {
587     MMDRV_MapType       ret = MMDRV_MAP_MSGERROR;
588
589     switch (wMsg) {
590     case MODM_CLOSE:
591     case MODM_GETNUMDEVS:
592     case MODM_DATA:
593     case MODM_RESET:
594     case MODM_SETVOLUME:
595         ret = MMDRV_MAP_OK;
596         break;
597     case MODM_GETDEVCAPS:
598         {
599             LPMIDIOUTCAPSA moc32 = (LPMIDIOUTCAPSA)*lpParam1;
600             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPSA)+sizeof(MIDIOUTCAPS16));
601
602             if (ptr) {
603                 *(LPMIDIOUTCAPSA*)ptr = moc32;
604                 ret = MMDRV_MAP_OKMEM;
605             } else {
606                 ret = MMDRV_MAP_NOMEM;
607             }
608             *lpParam1 = (DWORD)MapLS(ptr) + sizeof(LPMIDIOUTCAPSA);
609             *lpParam2 = sizeof(MIDIOUTCAPS16);
610         }
611         break;
612     case MODM_PREPARE:
613         {
614             LPMIDIHDR           mh32 = (LPMIDIHDR)*lpParam1;
615             LPMIDIHDR           mh16;
616             LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
617                                     sizeof(LPMIDIHDR) + sizeof(MIDIHDR) + mh32->dwBufferLength);
618
619             if (ptr) {
620                 *(LPMIDIHDR*)ptr = mh32;
621                 mh16 = (LPMIDIHDR)((LPSTR)ptr + sizeof(LPMIDIHDR));
622                 *lpParam1 = MapLS(mh16);
623                 mh16->lpData = (LPSTR)*lpParam1 + sizeof(MIDIHDR);
624                 /* data will be copied on WODM_WRITE */
625                 mh16->dwBufferLength = mh32->dwBufferLength;
626                 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
627                 mh16->dwUser = mh32->dwUser;
628                 mh16->dwFlags = mh32->dwFlags;
629                 /* FIXME: nothing on mh32->lpNext */
630                 /* could link the mh32->lpNext at this level for memory house keeping */
631                 mh16->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? mh32->dwOffset : 0;
632
633                 mh32->lpNext = (LPMIDIHDR)mh16; /* for reuse in unprepare and write */
634                 mh32->reserved = *lpParam2;
635
636                 TRACE("mh16=%08lx mh16->lpData=%08lx mh32->buflen=%lu mh32->lpData=%08lx\n",
637                       *lpParam1, (DWORD)mh16->lpData,
638                       mh32->dwBufferLength, (DWORD)mh32->lpData);
639                 *lpParam2 = sizeof(MIDIHDR);
640
641                 ret = MMDRV_MAP_OKMEM;
642             } else {
643                 ret = MMDRV_MAP_NOMEM;
644             }
645         }
646         break;
647     case MODM_UNPREPARE:
648     case MODM_LONGDATA:
649         {
650             LPMIDIHDR           mh32 = (LPMIDIHDR)(*lpParam1);
651             LPMIDIHDR           mh16 = (LPMIDIHDR)mh32->lpNext;
652             LPSTR               ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
653
654             assert(*(LPMIDIHDR*)ptr == mh32);
655
656             if (wMsg == MODM_LONGDATA)
657                 memcpy((LPSTR)mh16 + sizeof(MIDIHDR), mh32->lpData, mh32->dwBufferLength);
658
659             *lpParam1 = MapLS(mh16);
660             *lpParam2 = sizeof(MIDIHDR);
661             TRACE("mh16=%08lx mh16->lpData=%08lx mh32->buflen=%lu mh32->lpData=%08lx\n",
662                   *lpParam1, (DWORD)mh16->lpData, mh32->dwBufferLength, (DWORD)mh32->lpData);
663
664             /* dwBufferLength can be reduced between prepare & write */
665             if (wMsg == MODM_LONGDATA && mh16->dwBufferLength < mh32->dwBufferLength) {
666                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
667                     mh16->dwBufferLength, mh32->dwBufferLength);
668             } else
669                 mh16->dwBufferLength = mh32->dwBufferLength;
670             ret = MMDRV_MAP_OKMEM;
671         }
672         break;
673     case MODM_OPEN:
674         {
675             LPMIDIOPENDESC              mod32 = (LPMIDIOPENDESC)*lpParam1;
676             LPVOID                      ptr;
677             LPMIDIOPENDESC16            mod16;
678
679             /* allocated data are mapped as follows:
680                LPMIDIOPENDESC   ptr to orig lParam1
681                DWORD            orig dwUser, which is a pointer to DWORD:driver dwInstance
682                DWORD            dwUser passed to driver
683                MIDIOPENDESC16   mod16: openDesc passed to driver
684                MIDIOPENSTRMID   cIds
685             */
686             ptr = HeapAlloc( GetProcessHeap(), 0,
687                              sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD) + sizeof(MIDIOPENDESC16) +
688                              mod32->cIds ? (mod32->cIds - 1) * sizeof(MIDIOPENSTRMID) : 0);
689
690             if (ptr) {
691                 SEGPTR segptr = MapLS(ptr);
692                 *(LPMIDIOPENDESC*)ptr = mod32;
693                 *(LPDWORD)((char*)ptr + sizeof(LPMIDIOPENDESC)) = *lpdwUser;
694                 mod16 = (LPMIDIOPENDESC16)((LPSTR)ptr + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD));
695
696                 mod16->hMidi = HMIDI_16(mod32->hMidi);
697                 mod16->dwCallback = mod32->dwCallback;
698                 mod16->dwInstance = mod32->dwInstance;
699                 mod16->dnDevNode = mod32->dnDevNode;
700                 mod16->cIds = mod32->cIds;
701                 memcpy(&mod16->rgIds, &mod32->rgIds, mod32->cIds * sizeof(MIDIOPENSTRMID));
702
703                 *lpParam1 = (DWORD)segptr + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD);
704                 *lpdwUser = (DWORD)segptr + sizeof(LPMIDIOPENDESC) + sizeof(DWORD);
705
706                 ret = MMDRV_MAP_OKMEM;
707             } else {
708                 ret = MMDRV_MAP_NOMEM;
709             }
710         }
711         break;
712     case MODM_GETVOLUME:
713     case MODM_CACHEPATCHES:
714     case MODM_CACHEDRUMPATCHES:
715     default:
716         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
717         break;
718     }
719     return ret;
720 }
721
722 /**************************************************************************
723  *                              MMDRV_MidiOut_UnMap32ATo16      [internal]
724  */
725 static  MMDRV_MapType   MMDRV_MidiOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
726 {
727     MMDRV_MapType       ret = MMDRV_MAP_MSGERROR;
728
729     switch (wMsg) {
730     case MODM_CLOSE:
731     case MODM_GETNUMDEVS:
732     case MODM_DATA:
733     case MODM_RESET:
734     case MODM_SETVOLUME:
735         ret = MMDRV_MAP_OK;
736         break;
737     case MODM_GETDEVCAPS:
738         {
739             LPMIDIOUTCAPS16             moc16 = MapSL(*lpParam1);
740             LPSTR                       ptr   = (LPSTR)moc16 - sizeof(LPMIDIOUTCAPSA);
741             LPMIDIOUTCAPSA              moc32 = *(LPMIDIOUTCAPSA*)ptr;
742
743             moc32->wMid                 = moc16->wMid;
744             moc32->wPid                 = moc16->wPid;
745             moc32->vDriverVersion       = moc16->vDriverVersion;
746             strcpy(moc32->szPname, moc16->szPname);
747             moc32->wTechnology          = moc16->wTechnology;
748             moc32->wVoices              = moc16->wVoices;
749             moc32->wNotes               = moc16->wNotes;
750             moc32->wChannelMask         = moc16->wChannelMask;
751             moc32->dwSupport            = moc16->dwSupport;
752             UnMapLS( *lpParam1 );
753             HeapFree( GetProcessHeap(), 0, ptr );
754             ret = MMDRV_MAP_OK;
755         }
756         break;
757     case MODM_PREPARE:
758     case MODM_UNPREPARE:
759     case MODM_LONGDATA:
760         {
761             LPMIDIHDR           mh16 = MapSL(*lpParam1);
762             LPSTR               ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
763             LPMIDIHDR           mh32 = *(LPMIDIHDR*)ptr;
764
765             assert(mh32->lpNext == (LPMIDIHDR)mh16);
766             UnMapLS( *lpParam1 );
767             mh32->dwBytesRecorded = mh16->dwBytesRecorded;
768             mh32->dwUser = mh16->dwUser;
769             mh32->dwFlags = mh16->dwFlags;
770
771             if (wMsg == MODM_UNPREPARE) {
772                 HeapFree( GetProcessHeap(), 0, ptr );
773                 mh32->lpNext = 0;
774             }
775             ret = MMDRV_MAP_OK;
776         }
777         break;
778     case MODM_OPEN:
779         {
780             LPMIDIOPENDESC16            mod16 = MapSL(*lpParam1);
781             LPSTR                       ptr   = (LPSTR)mod16 - sizeof(LPMIDIOPENDESC) - 2*sizeof(DWORD);
782             UnMapLS( *lpParam1 );
783             **(DWORD**)(ptr + sizeof(LPMIDIOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPMIDIOPENDESC) + sizeof(DWORD));
784
785             HeapFree( GetProcessHeap(), 0, ptr );
786             ret = MMDRV_MAP_OK;
787         }
788         break;
789     case MODM_GETVOLUME:
790     case MODM_CACHEPATCHES:
791     case MODM_CACHEDRUMPATCHES:
792     default:
793         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
794         break;
795     }
796     return ret;
797 }
798
799 /**************************************************************************
800  *                              MMDRV_MidiOut_Callback          [internal]
801  */
802 static void     CALLBACK MMDRV_MidiOut_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
803 {
804     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
805
806     switch (uMsg) {
807     case MOM_OPEN:
808     case MOM_CLOSE:
809         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
810         break;
811     case MOM_DONE:
812         if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
813             /* initial map is: 32 => 16 */
814             LPMIDIHDR           mh16 = MapSL(dwParam1);
815             LPMIDIHDR           mh32 = *(LPMIDIHDR*)((LPSTR)mh16 - sizeof(LPMIDIHDR));
816
817             dwParam1 = (DWORD)mh32;
818             mh32->dwFlags = mh16->dwFlags;
819             mh32->dwOffset = mh16->dwOffset;
820             if (mh32->reserved >= sizeof(MIDIHDR))
821                 mh32->dwOffset = mh16->dwOffset;
822         } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
823             /* initial map is: 16 => 32 */
824             LPMIDIHDR           mh32 = (LPMIDIHDR)(dwParam1);
825             SEGPTR              segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
826             LPMIDIHDR           mh16 = MapSL(segmh16);
827
828             dwParam1 = (DWORD)segmh16;
829             mh16->dwFlags = mh32->dwFlags;
830             if (mh16->reserved >= sizeof(MIDIHDR))
831                 mh16->dwOffset = mh32->dwOffset;
832         }
833         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
834         break;
835     /* case MOM_POSITIONCB: */
836     default:
837         ERR("Unknown msg %u\n", uMsg);
838     }
839
840     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
841 }
842
843 /* =================================
844  *   W A V E  I N    M A P P E R S
845  * ================================= */
846
847 /**************************************************************************
848  *                              MMDRV_WaveIn_Map16To32A         [internal]
849  */
850 static  MMDRV_MapType   MMDRV_WaveIn_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
851 {
852     MMDRV_MapType       ret = MMDRV_MAP_MSGERROR;
853
854     switch (wMsg) {
855     case WIDM_GETNUMDEVS:
856     case WIDM_RESET:
857     case WIDM_START:
858     case WIDM_STOP:
859         ret = MMDRV_MAP_OK;
860         break;
861     case WIDM_OPEN:
862     case WIDM_CLOSE:
863         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
864         break;
865     case WIDM_GETDEVCAPS:
866         {
867             LPWAVEINCAPSA       wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSA));
868             LPWAVEINCAPS16      wic16 = MapSL(*lpParam1);
869
870             if (wic32) {
871                 *(LPWAVEINCAPS16*)wic32 = wic16;
872                 wic32 = (LPWAVEINCAPSA)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16));
873                 *lpParam1 = (DWORD)wic32;
874                 *lpParam2 = sizeof(WAVEINCAPSA);
875
876                 ret = MMDRV_MAP_OKMEM;
877             } else {
878                 ret = MMDRV_MAP_NOMEM;
879             }
880         }
881         break;
882     case WIDM_GETPOS:
883         {
884             LPMMTIME            mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
885             LPMMTIME16          mmt16 = MapSL(*lpParam1);
886
887             if (mmt32) {
888                 *(LPMMTIME16*)mmt32 = mmt16;
889                 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
890
891                 mmt32->wType = mmt16->wType;
892                 *lpParam1 = (DWORD)mmt32;
893                 *lpParam2 = sizeof(MMTIME);
894
895                 ret = MMDRV_MAP_OKMEM;
896             } else {
897                 ret = MMDRV_MAP_NOMEM;
898             }
899         }
900         break;
901     case WIDM_PREPARE:
902         {
903             LPWAVEHDR           wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
904             LPWAVEHDR           wh16 = MapSL(*lpParam1);
905
906             if (wh32) {
907                 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
908                 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
909                 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
910                 wh32->dwBufferLength = wh16->dwBufferLength;
911                 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
912                 wh32->dwUser = wh16->dwUser;
913                 wh32->dwFlags = wh16->dwFlags;
914                 wh32->dwLoops = wh16->dwLoops;
915                 /* FIXME: nothing on wh32->lpNext */
916                 /* could link the wh32->lpNext at this level for memory house keeping */
917                 wh16->lpNext = wh32; /* for reuse in unprepare and write */
918                 *lpParam1 = (DWORD)wh32;
919                 *lpParam2 = sizeof(WAVEHDR);
920
921                 ret = MMDRV_MAP_OKMEM;
922             } else {
923                 ret = MMDRV_MAP_NOMEM;
924             }
925         }
926         break;
927     case WIDM_ADDBUFFER:
928     case WIDM_UNPREPARE:
929         {
930             LPWAVEHDR           wh16 = MapSL(*lpParam1);
931             LPWAVEHDR           wh32 = (LPWAVEHDR)wh16->lpNext;
932
933             *lpParam1 = (DWORD)wh32;
934             *lpParam2 = sizeof(WAVEHDR);
935             /* dwBufferLength can be reduced between prepare & write */
936             if (wMsg == WIDM_ADDBUFFER && wh32->dwBufferLength < wh16->dwBufferLength) {
937                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
938                     wh32->dwBufferLength, wh16->dwBufferLength);
939             } else
940                 wh32->dwBufferLength = wh16->dwBufferLength;
941             ret = MMDRV_MAP_OKMEM;
942         }
943         break;
944     case WIDM_MAPPER_STATUS:
945         /* just a single DWORD */
946         *lpParam2 = (DWORD)MapSL(*lpParam2);
947         ret = MMDRV_MAP_OK;
948         break;
949     default:
950         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
951         break;
952     }
953     return ret;
954 }
955
956 /**************************************************************************
957  *                              MMDRV_WaveIn_UnMap16To32A       [internal]
958  */
959 static  MMDRV_MapType   MMDRV_WaveIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
960 {
961     MMDRV_MapType       ret = MMDRV_MAP_MSGERROR;
962
963     switch (wMsg) {
964     case WIDM_GETNUMDEVS:
965     case WIDM_RESET:
966     case WIDM_START:
967     case WIDM_STOP:
968     case WIDM_MAPPER_STATUS:
969         ret = MMDRV_MAP_OK;
970         break;
971     case WIDM_OPEN:
972     case WIDM_CLOSE:
973         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
974         break;
975     case WIDM_GETDEVCAPS:
976         {
977             LPWAVEINCAPSA               wic32 = (LPWAVEINCAPSA)(*lpParam1);
978             LPWAVEINCAPS16              wic16 = *(LPWAVEINCAPS16*)((LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
979
980             wic16->wMid = wic32->wMid;
981             wic16->wPid = wic32->wPid;
982             wic16->vDriverVersion = wic32->vDriverVersion;
983             strcpy(wic16->szPname, wic32->szPname);
984             wic16->dwFormats = wic32->dwFormats;
985             wic16->wChannels = wic32->wChannels;
986             HeapFree(GetProcessHeap(), 0, (LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
987             ret = MMDRV_MAP_OK;
988         }
989         break;
990     case WIDM_GETPOS:
991         {
992             LPMMTIME            mmt32 = (LPMMTIME)(*lpParam1);
993             LPMMTIME16          mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
994
995             MMSYSTEM_MMTIME32to16(mmt16, mmt32);
996             HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
997             ret = MMDRV_MAP_OK;
998         }
999         break;
1000     case WIDM_ADDBUFFER:
1001     case WIDM_PREPARE:
1002     case WIDM_UNPREPARE:
1003         {
1004             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
1005             LPWAVEHDR           wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
1006
1007             assert(wh16->lpNext == wh32);
1008             wh16->dwBufferLength = wh32->dwBufferLength;
1009             wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1010             wh16->dwUser = wh32->dwUser;
1011             wh16->dwFlags = wh32->dwFlags;
1012             wh16->dwLoops = wh32->dwLoops;
1013
1014             if (wMsg == WIDM_UNPREPARE) {
1015                 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
1016                 wh16->lpNext = 0;
1017             }
1018             ret = MMDRV_MAP_OK;
1019         }
1020         break;
1021     default:
1022         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1023         break;
1024     }
1025     return ret;
1026 }
1027
1028 /**************************************************************************
1029  *                              MMDRV_WaveIn_Map32ATo16         [internal]
1030  */
1031 static  MMDRV_MapType   MMDRV_WaveIn_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1032 {
1033     MMDRV_MapType       ret = MMDRV_MAP_MSGERROR;
1034
1035     switch (wMsg) {
1036     case WIDM_CLOSE:
1037     case WIDM_GETNUMDEVS:
1038     case WIDM_RESET:
1039     case WIDM_START:
1040     case WIDM_STOP:
1041         ret = MMDRV_MAP_OK;
1042         break;
1043
1044     case WIDM_OPEN:
1045         {
1046             LPWAVEOPENDESC              wod32 = (LPWAVEOPENDESC)*lpParam1;
1047             int                         sz = sizeof(WAVEFORMATEX);
1048             LPVOID                      ptr;
1049             LPWAVEOPENDESC16            wod16;
1050
1051             /* allocated data are mapped as follows:
1052                LPWAVEOPENDESC   ptr to orig lParam1
1053                DWORD            orig dwUser, which is a pointer to DWORD:driver dwInstance
1054                DWORD            dwUser passed to driver
1055                WAVEOPENDESC16   wod16: openDesc passed to driver
1056                WAVEFORMATEX     openDesc->lpFormat passed to driver
1057                xxx              extra bytes to WAVEFORMATEX
1058             */
1059             if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1060                 TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag);
1061                 sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize;
1062             }
1063
1064             ptr = HeapAlloc( GetProcessHeap(), 0,
1065                              sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
1066
1067             if (ptr) {
1068                 SEGPTR seg_ptr = MapLS( ptr );
1069                 *(LPWAVEOPENDESC*)ptr = wod32;
1070                 *(LPDWORD)((char*)ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
1071                 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
1072
1073                 wod16->hWave = HWAVE_16(wod32->hWave);
1074                 wod16->lpFormat = (LPWAVEFORMATEX)(seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16));
1075                 memcpy(wod16 + 1, wod32->lpFormat, sz);
1076
1077                 wod16->dwCallback = wod32->dwCallback;
1078                 wod16->dwInstance = wod32->dwInstance;
1079                 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
1080                 wod16->dnDevNode = wod32->dnDevNode;
1081
1082                 *lpParam1 = seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
1083                 *lpdwUser = seg_ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
1084
1085                 ret = MMDRV_MAP_OKMEM;
1086             } else {
1087                 ret = MMDRV_MAP_NOMEM;
1088             }
1089         }
1090         break;
1091     case WIDM_PREPARE:
1092         {
1093             LPWAVEHDR           wh32 = (LPWAVEHDR)*lpParam1;
1094             LPWAVEHDR           wh16;
1095             LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
1096                                     sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
1097
1098             if (ptr) {
1099                 SEGPTR seg_ptr = MapLS( ptr );
1100                 *(LPWAVEHDR*)ptr = wh32;
1101                 wh16 = (LPWAVEHDR)((LPSTR)ptr + sizeof(LPWAVEHDR));
1102                 wh16->lpData = (LPSTR)seg_ptr + sizeof(LPWAVEHDR) + sizeof(WAVEHDR);
1103                 /* data will be copied on WODM_WRITE */
1104                 wh16->dwBufferLength = wh32->dwBufferLength;
1105                 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1106                 wh16->dwUser = wh32->dwUser;
1107                 wh16->dwFlags = wh32->dwFlags;
1108                 wh16->dwLoops = wh32->dwLoops;
1109                 /* FIXME: nothing on wh32->lpNext */
1110                 /* could link the wh32->lpNext at this level for memory house keeping */
1111                 wh32->lpNext = wh16; /* for reuse in unprepare and write */
1112                 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1113                       seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1114                       wh32->dwBufferLength, (DWORD)wh32->lpData);
1115                 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1116                 *lpParam2 = sizeof(WAVEHDR);
1117
1118                 ret = MMDRV_MAP_OKMEM;
1119             } else {
1120                 ret = MMDRV_MAP_NOMEM;
1121             }
1122         }
1123         break;
1124     case WIDM_ADDBUFFER:
1125     case WIDM_UNPREPARE:
1126         {
1127             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
1128             LPWAVEHDR           wh16 = wh32->lpNext;
1129             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1130             SEGPTR seg_ptr = MapLS( ptr );
1131
1132             assert(*(LPWAVEHDR*)ptr == wh32);
1133
1134             TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1135                   seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1136                   wh32->dwBufferLength, (DWORD)wh32->lpData);
1137
1138             if (wMsg == WIDM_ADDBUFFER)
1139                 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
1140
1141             *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1142             *lpParam2 = sizeof(WAVEHDR);
1143             /* dwBufferLength can be reduced between prepare & write */
1144             if (wMsg == WIDM_ADDBUFFER && wh16->dwBufferLength < wh32->dwBufferLength) {
1145                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
1146                     wh16->dwBufferLength, wh32->dwBufferLength);
1147             } else
1148                 wh16->dwBufferLength = wh32->dwBufferLength;
1149             ret = MMDRV_MAP_OKMEM;
1150         }
1151         break;
1152    case WIDM_GETDEVCAPS:
1153         {
1154             LPWAVEINCAPSA wic32 = (LPWAVEINCAPSA)*lpParam1;
1155             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0 ,sizeof(LPWAVEINCAPSA) + sizeof(WAVEINCAPS16));
1156
1157             if (ptr) {
1158                 *(LPWAVEINCAPSA*)ptr = wic32;
1159                 ret = MMDRV_MAP_OKMEM;
1160             } else {
1161                 ret = MMDRV_MAP_NOMEM;
1162             }
1163             *lpParam1 = MapLS(ptr) + sizeof(LPWAVEINCAPSA);
1164             *lpParam2 = sizeof(WAVEINCAPS16);
1165         }
1166         break;
1167     case WIDM_GETPOS:
1168         {
1169             LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1170             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMMTIME) + sizeof(MMTIME16));
1171             LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1172
1173             if (ptr) {
1174                 *(LPMMTIME*)ptr = mmt32;
1175                 mmt16->wType = mmt32->wType;
1176                 ret = MMDRV_MAP_OKMEM;
1177             } else {
1178                 ret = MMDRV_MAP_NOMEM;
1179             }
1180             *lpParam1 = MapLS(ptr) + sizeof(LPMMTIME);
1181             *lpParam2 = sizeof(MMTIME16);
1182         }
1183         break;
1184     case DRVM_MAPPER_STATUS:
1185         {
1186             LPDWORD p32 = (LPDWORD)*lpParam2;
1187             *lpParam2 = MapLS(p32);
1188             ret = MMDRV_MAP_OKMEM;
1189         }
1190         break;
1191     default:
1192         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1193         break;
1194     }
1195     return ret;
1196 }
1197
1198 /**************************************************************************
1199  *                              MMDRV_WaveIn_UnMap32ATo16       [internal]
1200  */
1201 static  MMDRV_MapType   MMDRV_WaveIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1202 {
1203     MMDRV_MapType       ret = MMDRV_MAP_MSGERROR;
1204
1205     switch (wMsg) {
1206     case WIDM_CLOSE:
1207     case WIDM_GETNUMDEVS:
1208     case WIDM_RESET:
1209     case WIDM_START:
1210     case WIDM_STOP:
1211         ret = MMDRV_MAP_OK;
1212         break;
1213
1214     case WIDM_OPEN:
1215         {
1216             LPWAVEOPENDESC16            wod16 = MapSL(*lpParam1);
1217             LPSTR                       ptr   = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1218             LPWAVEOPENDESC              wod32 = *(LPWAVEOPENDESC*)ptr;
1219
1220             UnMapLS( *lpParam1 );
1221             wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1222             **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1223             HeapFree( GetProcessHeap(), 0, ptr );
1224             ret = MMDRV_MAP_OK;
1225         }
1226         break;
1227
1228     case WIDM_ADDBUFFER:
1229     case WIDM_PREPARE:
1230     case WIDM_UNPREPARE:
1231         {
1232             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1233             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1234             LPWAVEHDR           wh32 = *(LPWAVEHDR*)ptr;
1235
1236             assert(wh32->lpNext == wh16);
1237             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1238             wh32->dwUser = wh16->dwUser;
1239             wh32->dwFlags = wh16->dwFlags;
1240             wh32->dwLoops = wh16->dwLoops;
1241             UnMapLS( *lpParam1 );
1242
1243             if (wMsg == WIDM_UNPREPARE) {
1244                 HeapFree( GetProcessHeap(), 0, ptr );
1245                 wh32->lpNext = 0;
1246             }
1247             ret = MMDRV_MAP_OK;
1248         }
1249         break;
1250      case WIDM_GETDEVCAPS:
1251         {
1252             LPWAVEINCAPS16              wic16 = MapSL(*lpParam1);
1253             LPSTR                       ptr   = (LPSTR)wic16 - sizeof(LPWAVEINCAPSA);
1254             LPWAVEINCAPSA               wic32 = *(LPWAVEINCAPSA*)ptr;
1255
1256             wic32->wMid = wic16->wMid;
1257             wic32->wPid = wic16->wPid;
1258             wic32->vDriverVersion = wic16->vDriverVersion;
1259             strcpy(wic32->szPname, wic16->szPname);
1260             wic32->dwFormats = wic16->dwFormats;
1261             wic32->wChannels = wic16->wChannels;
1262             UnMapLS( *lpParam1 );
1263             HeapFree( GetProcessHeap(), 0, ptr );
1264             ret = MMDRV_MAP_OK;
1265         }
1266         break;
1267     case WIDM_GETPOS:
1268         {
1269             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1270             LPSTR               ptr   = (LPSTR)mmt16 - sizeof(LPMMTIME);
1271             LPMMTIME            mmt32 = *(LPMMTIME*)ptr;
1272
1273             MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1274             UnMapLS( *lpParam1 );
1275             HeapFree( GetProcessHeap(), 0, ptr );
1276             ret = MMDRV_MAP_OK;
1277         }
1278         break;
1279     case DRVM_MAPPER_STATUS:
1280         {
1281             UnMapLS( *lpParam2 );
1282             ret = MMDRV_MAP_OK;
1283         }
1284         break;
1285     default:
1286         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1287         break;
1288     }
1289     return ret;
1290 }
1291
1292 /**************************************************************************
1293  *                              MMDRV_WaveIn_Callback           [internal]
1294  */
1295 static void     CALLBACK MMDRV_WaveIn_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1296 {
1297     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
1298
1299     switch (uMsg) {
1300     case WIM_OPEN:
1301     case WIM_CLOSE:
1302         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1303         break;
1304     case WIM_DATA:
1305         if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
1306             /* initial map is: 32 => 16 */
1307             LPWAVEHDR           wh16 = MapSL(dwParam1);
1308             LPWAVEHDR           wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1309
1310             dwParam1 = (DWORD)wh32;
1311             wh32->dwFlags = wh16->dwFlags;
1312             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1313         } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
1314             /* initial map is: 16 => 32 */
1315             LPWAVEHDR           wh32 = (LPWAVEHDR)(dwParam1);
1316             SEGPTR              segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1317             LPWAVEHDR           wh16 = MapSL(segwh16);
1318
1319             dwParam1 = (DWORD)segwh16;
1320             wh16->dwFlags = wh32->dwFlags;
1321             wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1322         }
1323         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1324         break;
1325     default:
1326         ERR("Unknown msg %u\n", uMsg);
1327     }
1328
1329     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1330 }
1331
1332 /* =================================
1333  *   W A V E  O U T  M A P P E R S
1334  * ================================= */
1335
1336 /**************************************************************************
1337  *                              MMDRV_WaveOut_Map16To32A        [internal]
1338  */
1339 static  MMDRV_MapType   MMDRV_WaveOut_Map16To32A  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1340 {
1341     MMDRV_MapType       ret = MMDRV_MAP_MSGERROR;
1342
1343     switch (wMsg) {
1344     /* nothing to do */
1345     case WODM_BREAKLOOP:
1346     case WODM_CLOSE:
1347     case WODM_GETNUMDEVS:
1348     case WODM_PAUSE:
1349     case WODM_RESET:
1350     case WODM_RESTART:
1351     case WODM_SETPITCH:
1352     case WODM_SETPLAYBACKRATE:
1353     case WODM_SETVOLUME:
1354         ret = MMDRV_MAP_OK;
1355         break;
1356
1357     case WODM_GETPITCH:
1358     case WODM_GETPLAYBACKRATE:
1359     case WODM_GETVOLUME:
1360     case WODM_OPEN:
1361         FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
1362         break;
1363
1364     case WODM_GETDEVCAPS:
1365         {
1366             LPWAVEOUTCAPSA              woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSA));
1367             LPWAVEOUTCAPS16             woc16 = MapSL(*lpParam1);
1368
1369             if (woc32) {
1370                 *(LPWAVEOUTCAPS16*)woc32 = woc16;
1371                 woc32 = (LPWAVEOUTCAPSA)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16));
1372                 *lpParam1 = (DWORD)woc32;
1373                 *lpParam2 = sizeof(WAVEOUTCAPSA);
1374
1375                 ret = MMDRV_MAP_OKMEM;
1376             } else {
1377                 ret = MMDRV_MAP_NOMEM;
1378             }
1379         }
1380         break;
1381     case WODM_GETPOS:
1382         {
1383             LPMMTIME            mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
1384             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1385
1386             if (mmt32) {
1387                 *(LPMMTIME16*)mmt32 = mmt16;
1388                 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
1389
1390                 mmt32->wType = mmt16->wType;
1391                 *lpParam1 = (DWORD)mmt32;
1392                 *lpParam2 = sizeof(MMTIME);
1393
1394                 ret = MMDRV_MAP_OKMEM;
1395             } else {
1396                 ret = MMDRV_MAP_NOMEM;
1397             }
1398         }
1399         break;
1400     case WODM_PREPARE:
1401         {
1402             LPWAVEHDR           wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
1403             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1404
1405             if (wh32) {
1406                 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
1407                 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
1408                 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
1409                 wh32->dwBufferLength = wh16->dwBufferLength;
1410                 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1411                 wh32->dwUser = wh16->dwUser;
1412                 wh32->dwFlags = wh16->dwFlags;
1413                 wh32->dwLoops = wh16->dwLoops;
1414                 /* FIXME: nothing on wh32->lpNext */
1415                 /* could link the wh32->lpNext at this level for memory house keeping */
1416                 wh16->lpNext = wh32; /* for reuse in unprepare and write */
1417                 *lpParam1 = (DWORD)wh32;
1418                 *lpParam2 = sizeof(WAVEHDR);
1419
1420                 ret = MMDRV_MAP_OKMEM;
1421             } else {
1422                 ret = MMDRV_MAP_NOMEM;
1423             }
1424         }
1425         break;
1426     case WODM_UNPREPARE:
1427     case WODM_WRITE:
1428         {
1429             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1430             LPWAVEHDR           wh32 = (LPWAVEHDR)wh16->lpNext;
1431
1432             *lpParam1 = (DWORD)wh32;
1433             *lpParam2 = sizeof(WAVEHDR);
1434             /* dwBufferLength can be reduced between prepare & write */
1435             if (wMsg == WODM_WRITE && wh32->dwBufferLength < wh16->dwBufferLength) {
1436                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
1437                     wh32->dwBufferLength, wh16->dwBufferLength);
1438             } else
1439                 wh32->dwBufferLength = wh16->dwBufferLength;
1440             ret = MMDRV_MAP_OKMEM;
1441         }
1442         break;
1443     case WODM_MAPPER_STATUS:
1444         *lpParam2 = (DWORD)MapSL(*lpParam2);
1445         ret = MMDRV_MAP_OK;
1446         break;
1447     default:
1448         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1449         break;
1450     }
1451     return ret;
1452 }
1453
1454 /**************************************************************************
1455  *                              MMDRV_WaveOut_UnMap16To32A      [internal]
1456  */
1457 static  MMDRV_MapType   MMDRV_WaveOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1458 {
1459     MMDRV_MapType       ret = MMDRV_MAP_MSGERROR;
1460
1461     switch (wMsg) {
1462     /* nothing to do */
1463     case WODM_BREAKLOOP:
1464     case WODM_CLOSE:
1465     case WODM_GETNUMDEVS:
1466     case WODM_PAUSE:
1467     case WODM_RESET:
1468     case WODM_RESTART:
1469     case WODM_SETPITCH:
1470     case WODM_SETPLAYBACKRATE:
1471     case WODM_SETVOLUME:
1472     case WODM_MAPPER_STATUS:
1473         ret = MMDRV_MAP_OK;
1474         break;
1475
1476     case WODM_GETPITCH:
1477     case WODM_GETPLAYBACKRATE:
1478     case WODM_GETVOLUME:
1479     case WODM_OPEN:
1480         FIXME("Shouldn't be used: those 16 bit functions use the 32 bit interface\n");
1481         break;
1482
1483     case WODM_GETDEVCAPS:
1484         {
1485             LPWAVEOUTCAPSA              woc32 = (LPWAVEOUTCAPSA)(*lpParam1);
1486             LPWAVEOUTCAPS16             woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1487
1488             woc16->wMid = woc32->wMid;
1489             woc16->wPid = woc32->wPid;
1490             woc16->vDriverVersion = woc32->vDriverVersion;
1491             strcpy(woc16->szPname, woc32->szPname);
1492             woc16->dwFormats = woc32->dwFormats;
1493             woc16->wChannels = woc32->wChannels;
1494             woc16->dwSupport = woc32->dwSupport;
1495             HeapFree(GetProcessHeap(), 0, (LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1496             ret = MMDRV_MAP_OK;
1497         }
1498         break;
1499     case WODM_GETPOS:
1500         {
1501             LPMMTIME            mmt32 = (LPMMTIME)(*lpParam1);
1502             LPMMTIME16          mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
1503
1504             MMSYSTEM_MMTIME32to16(mmt16, mmt32);
1505             HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
1506             ret = MMDRV_MAP_OK;
1507         }
1508         break;
1509     case WODM_PREPARE:
1510     case WODM_UNPREPARE:
1511     case WODM_WRITE:
1512         {
1513             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
1514             LPWAVEHDR           wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
1515
1516             assert(wh16->lpNext == wh32);
1517             wh16->dwBufferLength = wh32->dwBufferLength;
1518             wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1519             wh16->dwUser = wh32->dwUser;
1520             wh16->dwFlags = wh32->dwFlags;
1521             wh16->dwLoops = wh32->dwLoops;
1522
1523             if (wMsg == WODM_UNPREPARE) {
1524                 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
1525                 wh16->lpNext = 0;
1526             }
1527             ret = MMDRV_MAP_OK;
1528         }
1529         break;
1530     default:
1531         FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1532         break;
1533     }
1534     return ret;
1535 }
1536
1537 /**************************************************************************
1538  *                              MMDRV_WaveOut_Map32ATo16        [internal]
1539  */
1540 static  MMDRV_MapType   MMDRV_WaveOut_Map32ATo16  (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1541 {
1542     MMDRV_MapType       ret;
1543
1544     switch (wMsg) {
1545         /* nothing to do */
1546     case WODM_BREAKLOOP:
1547     case WODM_CLOSE:
1548     case WODM_GETNUMDEVS:
1549     case WODM_PAUSE:
1550     case WODM_RESET:
1551     case WODM_RESTART:
1552     case WODM_SETPITCH:
1553     case WODM_SETPLAYBACKRATE:
1554     case WODM_SETVOLUME:
1555         ret = MMDRV_MAP_OK;
1556         break;
1557
1558     case WODM_GETDEVCAPS:
1559         {
1560             LPWAVEOUTCAPSA woc32 = (LPWAVEOUTCAPSA)*lpParam1;
1561             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0,
1562                                    sizeof(LPWAVEOUTCAPSA) + sizeof(WAVEOUTCAPS16));
1563
1564             if (ptr) {
1565                 *(LPWAVEOUTCAPSA*)ptr = woc32;
1566                 ret = MMDRV_MAP_OKMEM;
1567             } else {
1568                 ret = MMDRV_MAP_NOMEM;
1569             }
1570             *lpParam1 = MapLS(ptr) + sizeof(LPWAVEOUTCAPSA);
1571             *lpParam2 = sizeof(WAVEOUTCAPS16);
1572         }
1573         break;
1574     case WODM_GETPITCH:
1575         FIXME("NIY: no conversion yet\n");
1576         ret = MMDRV_MAP_MSGERROR;
1577         break;
1578     case WODM_GETPLAYBACKRATE:
1579         FIXME("NIY: no conversion yet\n");
1580         ret = MMDRV_MAP_MSGERROR;
1581         break;
1582     case WODM_GETPOS:
1583         {
1584             LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1585             LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMMTIME) + sizeof(MMTIME16));
1586             LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1587
1588             if (ptr) {
1589                 *(LPMMTIME*)ptr = mmt32;
1590                 mmt16->wType = mmt32->wType;
1591                 ret = MMDRV_MAP_OKMEM;
1592             } else {
1593                 ret = MMDRV_MAP_NOMEM;
1594             }
1595             *lpParam1 = MapLS(ptr) + sizeof(LPMMTIME);
1596             *lpParam2 = sizeof(MMTIME16);
1597         }
1598         break;
1599     case WODM_GETVOLUME:
1600         FIXME("NIY: no conversion yet\n");
1601         ret = MMDRV_MAP_MSGERROR;
1602         break;
1603     case WODM_OPEN:
1604         {
1605             LPWAVEOPENDESC              wod32 = (LPWAVEOPENDESC)*lpParam1;
1606             int                         sz = sizeof(WAVEFORMATEX);
1607             LPVOID                      ptr;
1608             LPWAVEOPENDESC16            wod16;
1609
1610             /* allocated data are mapped as follows:
1611                LPWAVEOPENDESC   ptr to orig lParam1
1612                DWORD            orig dwUser, which is a pointer to DWORD:driver dwInstance
1613                DWORD            dwUser passed to driver
1614                WAVEOPENDESC16   wod16: openDesc passed to driver
1615                WAVEFORMATEX     openDesc->lpFormat passed to driver
1616                xxx              extra bytes to WAVEFORMATEX
1617             */
1618             if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1619                 TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag);
1620                 sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize;
1621             }
1622
1623             ptr = HeapAlloc( GetProcessHeap(), 0,
1624                              sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
1625
1626             if (ptr) {
1627                 SEGPTR seg_ptr = MapLS( ptr );
1628                 *(LPWAVEOPENDESC*)ptr = wod32;
1629                 *(LPDWORD)((char*)ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
1630                 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
1631
1632                 wod16->hWave = HWAVE_16(wod32->hWave);
1633                 wod16->lpFormat = (LPWAVEFORMATEX)(seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16));
1634                 memcpy(wod16 + 1, wod32->lpFormat, sz);
1635
1636                 wod16->dwCallback = wod32->dwCallback;
1637                 wod16->dwInstance = wod32->dwInstance;
1638                 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
1639                 wod16->dnDevNode = wod32->dnDevNode;
1640
1641                 *lpParam1 = seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
1642                 *lpdwUser = seg_ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
1643
1644                 ret = MMDRV_MAP_OKMEM;
1645             } else {
1646                 ret = MMDRV_MAP_NOMEM;
1647             }
1648         }
1649         break;
1650     case WODM_PREPARE:
1651         {
1652             LPWAVEHDR           wh32 = (LPWAVEHDR)*lpParam1;
1653             LPWAVEHDR           wh16;
1654             LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
1655                                     sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
1656
1657             if (ptr) {
1658                 SEGPTR seg_ptr = MapLS( ptr );
1659                 *(LPWAVEHDR*)ptr = wh32;
1660                 wh16 = (LPWAVEHDR)((LPSTR)ptr + sizeof(LPWAVEHDR));
1661                 wh16->lpData = (LPSTR)seg_ptr + sizeof(LPWAVEHDR) + sizeof(WAVEHDR);
1662                 /* data will be copied on WODM_WRITE */
1663                 wh16->dwBufferLength = wh32->dwBufferLength;
1664                 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1665                 wh16->dwUser = wh32->dwUser;
1666                 wh16->dwFlags = wh32->dwFlags;
1667                 wh16->dwLoops = wh32->dwLoops;
1668                 /* FIXME: nothing on wh32->lpNext */
1669                 /* could link the wh32->lpNext at this level for memory house keeping */
1670                 wh32->lpNext = wh16; /* for reuse in unprepare and write */
1671                 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1672                       seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1673                       wh32->dwBufferLength, (DWORD)wh32->lpData);
1674                 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1675                 *lpParam2 = sizeof(WAVEHDR);
1676
1677                 ret = MMDRV_MAP_OKMEM;
1678             } else {
1679                 ret = MMDRV_MAP_NOMEM;
1680             }
1681         }
1682         break;
1683     case WODM_UNPREPARE:
1684     case WODM_WRITE:
1685         {
1686             LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
1687             LPWAVEHDR           wh16 = wh32->lpNext;
1688             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1689             SEGPTR seg_ptr = MapLS( ptr );
1690
1691             assert(*(LPWAVEHDR*)ptr == wh32);
1692
1693             TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1694                   seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1695                   wh32->dwBufferLength, (DWORD)wh32->lpData);
1696
1697             if (wMsg == WODM_WRITE)
1698                 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
1699
1700             *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1701             *lpParam2 = sizeof(WAVEHDR);
1702             /* dwBufferLength can be reduced between prepare & write */
1703             if (wMsg == WODM_WRITE && wh16->dwBufferLength < wh32->dwBufferLength) {
1704                 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
1705                     wh16->dwBufferLength, wh32->dwBufferLength);
1706             } else
1707                 wh16->dwBufferLength = wh32->dwBufferLength;
1708             ret = MMDRV_MAP_OKMEM;
1709         }
1710         break;
1711     case DRVM_MAPPER_STATUS:
1712         {
1713             LPDWORD p32 = (LPDWORD)*lpParam2;
1714             *lpParam2 = MapLS(p32);
1715             ret = MMDRV_MAP_OKMEM;
1716         }
1717         break;
1718     default:
1719         FIXME("NIY: no conversion yet\n");
1720         ret = MMDRV_MAP_MSGERROR;
1721         break;
1722     }
1723     return ret;
1724 }
1725
1726 /**************************************************************************
1727  *                              MMDRV_WaveOut_UnMap32ATo16      [internal]
1728  */
1729 static  MMDRV_MapType   MMDRV_WaveOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1730 {
1731     MMDRV_MapType       ret;
1732
1733     switch (wMsg) {
1734         /* nothing to do */
1735     case WODM_BREAKLOOP:
1736     case WODM_CLOSE:
1737     case WODM_GETNUMDEVS:
1738     case WODM_PAUSE:
1739     case WODM_RESET:
1740     case WODM_RESTART:
1741     case WODM_SETPITCH:
1742     case WODM_SETPLAYBACKRATE:
1743     case WODM_SETVOLUME:
1744         ret = MMDRV_MAP_OK;
1745         break;
1746
1747     case WODM_GETDEVCAPS:
1748         {
1749             LPWAVEOUTCAPS16             woc16 = MapSL(*lpParam1);
1750             LPSTR                       ptr   = (LPSTR)woc16 - sizeof(LPWAVEOUTCAPSA);
1751             LPWAVEOUTCAPSA              woc32 = *(LPWAVEOUTCAPSA*)ptr;
1752
1753             woc32->wMid = woc16->wMid;
1754             woc32->wPid = woc16->wPid;
1755             woc32->vDriverVersion = woc16->vDriverVersion;
1756             strcpy(woc32->szPname, woc16->szPname);
1757             woc32->dwFormats = woc16->dwFormats;
1758             woc32->wChannels = woc16->wChannels;
1759             woc32->dwSupport = woc16->dwSupport;
1760             UnMapLS( *lpParam1 );
1761             HeapFree( GetProcessHeap(), 0, ptr );
1762             ret = MMDRV_MAP_OK;
1763         }
1764         break;
1765     case WODM_GETPITCH:
1766         FIXME("NIY: no conversion yet\n");
1767         ret = MMDRV_MAP_MSGERROR;
1768         break;
1769     case WODM_GETPLAYBACKRATE:
1770         FIXME("NIY: no conversion yet\n");
1771         ret = MMDRV_MAP_MSGERROR;
1772         break;
1773     case WODM_GETPOS:
1774         {
1775             LPMMTIME16          mmt16 = MapSL(*lpParam1);
1776             LPSTR               ptr   = (LPSTR)mmt16 - sizeof(LPMMTIME);
1777             LPMMTIME            mmt32 = *(LPMMTIME*)ptr;
1778
1779             MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1780             UnMapLS( *lpParam1 );
1781             HeapFree( GetProcessHeap(), 0, ptr );
1782             ret = MMDRV_MAP_OK;
1783         }
1784         break;
1785     case WODM_OPEN:
1786         {
1787             LPWAVEOPENDESC16            wod16 = MapSL(*lpParam1);
1788             LPSTR                       ptr   = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1789             LPWAVEOPENDESC              wod32 = *(LPWAVEOPENDESC*)ptr;
1790
1791             wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1792             **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1793             UnMapLS( *lpParam1 );
1794             HeapFree( GetProcessHeap(), 0, ptr );
1795             ret = MMDRV_MAP_OK;
1796         }
1797         break;
1798     case WODM_PREPARE:
1799     case WODM_UNPREPARE:
1800     case WODM_WRITE:
1801         {
1802             LPWAVEHDR           wh16 = MapSL(*lpParam1);
1803             LPSTR               ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1804             LPWAVEHDR           wh32 = *(LPWAVEHDR*)ptr;
1805
1806             assert(wh32->lpNext == wh16);
1807             wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1808             wh32->dwUser = wh16->dwUser;
1809             wh32->dwFlags = wh16->dwFlags;
1810             wh32->dwLoops = wh16->dwLoops;
1811
1812             UnMapLS( *lpParam1 );
1813             if (wMsg == WODM_UNPREPARE) {
1814                 HeapFree( GetProcessHeap(), 0, ptr );
1815                 wh32->lpNext = 0;
1816             }
1817             ret = MMDRV_MAP_OK;
1818         }
1819         break;
1820     case WODM_GETVOLUME:
1821         FIXME("NIY: no conversion yet\n");
1822         ret = MMDRV_MAP_MSGERROR;
1823         break;
1824     case DRVM_MAPPER_STATUS:
1825         {
1826             UnMapLS( *lpParam2 );
1827             ret = MMDRV_MAP_OK;
1828         }
1829         break;
1830     default:
1831         FIXME("NIY: no conversion yet\n");
1832         ret = MMDRV_MAP_MSGERROR;
1833         break;
1834     }
1835     return ret;
1836 }
1837
1838 /**************************************************************************
1839  *                              MMDRV_WaveOut_Callback          [internal]
1840  */
1841 static void     CALLBACK MMDRV_WaveOut_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1842 {
1843     LPWINE_MLD  mld = (LPWINE_MLD)dwInstance;
1844
1845     switch (uMsg) {
1846     case WOM_OPEN:
1847     case WOM_CLOSE:
1848         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1849         break;
1850     case WOM_DONE:
1851         if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
1852             /* initial map is: 32 => 16 */
1853             LPWAVEHDR           wh16 = MapSL(dwParam1);
1854             LPWAVEHDR           wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1855
1856             dwParam1 = (DWORD)wh32;
1857             wh32->dwFlags = wh16->dwFlags;
1858         } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
1859             /* initial map is: 16 => 32 */
1860             LPWAVEHDR           wh32 = (LPWAVEHDR)(dwParam1);
1861             SEGPTR              segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1862             LPWAVEHDR           wh16 = MapSL(segwh16);
1863
1864             dwParam1 = (DWORD)segwh16;
1865             wh16->dwFlags = wh32->dwFlags;
1866         }
1867         /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1868         break;
1869     default:
1870         ERR("Unknown msg %u\n", uMsg);
1871     }
1872
1873     MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1874 }
1875
1876 #define A(_x,_y) {#_y, _x, \
1877 MMDRV_##_y##_Map16To32A, MMDRV_##_y##_UnMap16To32A, \
1878 MMDRV_##_y##_Map32ATo16, MMDRV_##_y##_UnMap32ATo16, \
1879 MMDRV_##_y##_Callback, 0, NULL, -1}
1880
1881 /* Note: the indices of this array must match the definitions
1882  *       of the MMDRV_???? manifest constants
1883  */
1884 static WINE_LLTYPE      llTypes[MMDRV_MAX] = {
1885     A(TRUE,  Aux),
1886     A(FALSE, Mixer),
1887     A(TRUE,  MidiIn),
1888     A(TRUE,  MidiOut),
1889     A(TRUE,  WaveIn),
1890     A(TRUE,  WaveOut),
1891 };
1892 #undef A
1893
1894 /**************************************************************************
1895  *                      MMDRV_GetNum                            [internal]
1896  */
1897 UINT    MMDRV_GetNum(UINT type)
1898 {
1899     assert(type < MMDRV_MAX);
1900     return llTypes[type].wMaxId;
1901 }
1902
1903 /**************************************************************************
1904  *                              WINE_Message                    [internal]
1905  */
1906 DWORD   MMDRV_Message(LPWINE_MLD mld, WORD wMsg, DWORD dwParam1,
1907                       DWORD dwParam2, BOOL bFrom32)
1908 {
1909     LPWINE_MM_DRIVER            lpDrv;
1910     DWORD                       ret;
1911     WINE_MM_DRIVER_PART*        part;
1912     WINE_LLTYPE*                llType = &llTypes[mld->type];
1913     MMDRV_MapType               map;
1914     int                         devID;
1915
1916     TRACE("(%s %u %u 0x%08lx 0x%08lx 0x%08lx %c)!\n",
1917           llTypes[mld->type].typestr, mld->uDeviceID, wMsg,
1918           mld->dwDriverInstance, dwParam1, dwParam2, bFrom32?'Y':'N');
1919
1920     if (mld->uDeviceID == (UINT16)-1) {
1921         if (!llType->bSupportMapper) {
1922             WARN("uDev=-1 requested on non-mappable ll type %s\n",
1923                  llTypes[mld->type].typestr);
1924             return MMSYSERR_BADDEVICEID;
1925         }
1926         devID = -1;
1927     } else {
1928         if (mld->uDeviceID >= llType->wMaxId) {
1929             WARN("uDev(%u) requested >= max (%d)\n", mld->uDeviceID, llType->wMaxId);
1930             return MMSYSERR_BADDEVICEID;
1931         }
1932         devID = mld->uDeviceID;
1933     }
1934
1935     lpDrv = &MMDrvs[mld->mmdIndex];
1936     part = &lpDrv->parts[mld->type];
1937
1938 #if 0
1939     /* some sanity checks */
1940     if (!(part->nIDMin <= devID))
1941         ERR("!(part->nIDMin(%d) <= devID(%d))\n", part->nIDMin, devID);
1942     if (!(devID < part->nIDMax))
1943         ERR("!(devID(%d) < part->nIDMax(%d))\n", devID, part->nIDMax);
1944 #endif
1945
1946     if (lpDrv->bIs32) {
1947         assert(part->u.fnMessage32);
1948
1949         if (bFrom32) {
1950             TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
1951                   mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1952             ret = part->u.fnMessage32(mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1953             TRACE("=> %lu\n", ret);
1954         } else {
1955             map = llType->Map16To32A(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
1956             switch (map) {
1957             case MMDRV_MAP_NOMEM:
1958                 ret = MMSYSERR_NOMEM;
1959                 break;
1960             case MMDRV_MAP_MSGERROR:
1961                 FIXME("NIY: no conversion yet 16->32 (%u)\n", wMsg);
1962                 ret = MMSYSERR_ERROR;
1963                 break;
1964             case MMDRV_MAP_OK:
1965             case MMDRV_MAP_OKMEM:
1966                 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
1967                       mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1968                 ret = part->u.fnMessage32(mld->uDeviceID, wMsg, mld->dwDriverInstance,
1969                                           dwParam1, dwParam2);
1970                 TRACE("=> %lu\n", ret);
1971                 if (map == MMDRV_MAP_OKMEM)
1972                     llType->UnMap16To32A(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
1973                 break;
1974             default:
1975             case MMDRV_MAP_PASS:
1976                 FIXME("NIY: pass used ?\n");
1977                 ret = MMSYSERR_NOTSUPPORTED;
1978                 break;
1979             }
1980         }
1981     } else {
1982         assert(part->u.fnMessage16);
1983
1984         if (bFrom32) {
1985             map = llType->Map32ATo16(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
1986             switch (map) {
1987             case MMDRV_MAP_NOMEM:
1988                 ret = MMSYSERR_NOMEM;
1989                 break;
1990             case MMDRV_MAP_MSGERROR:
1991                 FIXME("NIY: no conversion yet 32->16 (%u)\n", wMsg);
1992                 ret = MMSYSERR_ERROR;
1993                 break;
1994             case MMDRV_MAP_OK:
1995             case MMDRV_MAP_OKMEM:
1996                 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
1997                       mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1998                 ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16, mld->uDeviceID,
1999                                                 wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
2000                 TRACE("=> %lu\n", ret);
2001                 if (map == MMDRV_MAP_OKMEM)
2002                     llType->UnMap32ATo16(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
2003                 break;
2004             default:
2005             case MMDRV_MAP_PASS:
2006                 FIXME("NIY: pass used ?\n");
2007                 ret = MMSYSERR_NOTSUPPORTED;
2008                 break;
2009             }
2010         } else {
2011             TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
2012                   mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
2013             ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16, mld->uDeviceID,
2014                                             wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
2015             TRACE("=> %lu\n", ret);
2016         }
2017     }
2018     return ret;
2019 }
2020
2021 /**************************************************************************
2022  *                              MMDRV_Alloc                     [internal]
2023  */
2024 LPWINE_MLD      MMDRV_Alloc(UINT size, UINT type, LPHANDLE hndl, DWORD* dwFlags,
2025                             DWORD* dwCallback, DWORD* dwInstance, BOOL bFrom32)
2026 {
2027     LPWINE_MLD  mld;
2028
2029     mld = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2030     if (!mld)   return NULL;
2031
2032     /* find an empty slot in MM_MLDrvs table */
2033     for (*hndl = 0; *hndl < MAX_MM_MLDRVS; (*hndl)++) {
2034         if (!MM_MLDrvs[*hndl]) break;
2035     }
2036     if (*hndl == MAX_MM_MLDRVS) {
2037         /* the MM_MLDrvs table could be made growable in the future if needed */
2038         ERR("Too many open drivers\n");
2039         return NULL;
2040     }
2041     MM_MLDrvs[*hndl] = mld;
2042     *hndl |= 0x8000;
2043
2044     mld->type = type;
2045     if ((UINT)*hndl < MMDRV_GetNum(type) || HIWORD(*hndl) != 0) {
2046         /* FIXME: those conditions must be fulfilled so that:
2047          * - we can distinguish between device IDs and handles
2048          * - we can use handles as 16 or 32 bit entities
2049          */
2050         ERR("Shouldn't happen. Bad allocation scheme\n");
2051     }
2052
2053     mld->bFrom32 = bFrom32;
2054     mld->dwFlags = HIWORD(*dwFlags);
2055     mld->dwCallback = *dwCallback;
2056     mld->dwClientInstance = *dwInstance;
2057
2058     *dwFlags = LOWORD(*dwFlags) | CALLBACK_FUNCTION;
2059     *dwCallback = (DWORD)llTypes[type].Callback;
2060     *dwInstance = (DWORD)mld; /* FIXME: wouldn't some 16 bit drivers only use the loword ? */
2061
2062     return mld;
2063 }
2064
2065 /**************************************************************************
2066  *                              MMDRV_Free                      [internal]
2067  */
2068 void    MMDRV_Free(HANDLE hndl, LPWINE_MLD mld)
2069 {
2070     if (hndl & 0x8000) {
2071         unsigned idx = hndl & ~0x8000;
2072         if (idx < sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0])) {
2073             MM_MLDrvs[idx] = NULL;
2074             HeapFree(GetProcessHeap(), 0, mld);
2075             return;
2076         }
2077     }
2078     ERR("Bad Handle %08x at %p (not freed)\n", hndl, mld);
2079 }
2080
2081 /**************************************************************************
2082  *                              MMDRV_Open                      [internal]
2083  */
2084 DWORD   MMDRV_Open(LPWINE_MLD mld, UINT wMsg, DWORD dwParam1, DWORD dwFlags)
2085 {
2086     DWORD               dwRet = MMSYSERR_BADDEVICEID;
2087     DWORD               dwInstance;
2088     WINE_LLTYPE*        llType = &llTypes[mld->type];
2089
2090     mld->dwDriverInstance = (DWORD)&dwInstance;
2091
2092     if (mld->uDeviceID == (UINT)-1 || mld->uDeviceID == (UINT16)-1) {
2093         TRACE("MAPPER mode requested !\n");
2094         /* check if mapper is supported by type */
2095         if (llType->bSupportMapper) {
2096             if (llType->nMapper == -1) {
2097                 /* no driver for mapper has been loaded, try a dumb implementation */
2098                 TRACE("No mapper loaded, doing it by hand\n");
2099                 for (mld->uDeviceID = 0; mld->uDeviceID < llType->wMaxId; mld->uDeviceID++) {
2100                     if ((dwRet = MMDRV_Open(mld, wMsg, dwParam1, dwFlags)) == MMSYSERR_NOERROR) {
2101                         /* to share this function epilog */
2102                         dwInstance = mld->dwDriverInstance;
2103                         break;
2104                     }
2105                 }
2106             } else {
2107                 mld->uDeviceID = (UINT16)-1;
2108                 mld->mmdIndex = llType->lpMlds[-1].mmdIndex;
2109                 TRACE("Setting mmdIndex to %u\n", mld->mmdIndex);
2110                 dwRet = MMDRV_Message(mld, wMsg, dwParam1, dwFlags, TRUE);
2111             }
2112         }
2113     } else {
2114         if (mld->uDeviceID < llType->wMaxId) {
2115             mld->mmdIndex = llType->lpMlds[mld->uDeviceID].mmdIndex;
2116             TRACE("Setting mmdIndex to %u\n", mld->mmdIndex);
2117             dwRet = MMDRV_Message(mld, wMsg, dwParam1, dwFlags, TRUE);
2118         }
2119     }
2120     if (dwRet == MMSYSERR_NOERROR)
2121         mld->dwDriverInstance = dwInstance;
2122     return dwRet;
2123 }
2124
2125 /**************************************************************************
2126  *                              MMDRV_Close                     [internal]
2127  */
2128 DWORD   MMDRV_Close(LPWINE_MLD mld, UINT wMsg)
2129 {
2130     return MMDRV_Message(mld, wMsg, 0L, 0L, TRUE);
2131 }
2132
2133 /**************************************************************************
2134  *                              MMDRV_GetByID                   [internal]
2135  */
2136 LPWINE_MLD      MMDRV_GetByID(UINT uDevID, UINT type)
2137 {
2138     if (uDevID < llTypes[type].wMaxId)
2139         return &llTypes[type].lpMlds[uDevID];
2140     if ((uDevID == (UINT16)-1 || uDevID == (UINT)-1) && llTypes[type].nMapper != -1)
2141         return &llTypes[type].lpMlds[-1];
2142     return NULL;
2143 }
2144
2145 /**************************************************************************
2146  *                              MMDRV_Get                       [internal]
2147  */
2148 LPWINE_MLD      MMDRV_Get(HANDLE hndl, UINT type, BOOL bCanBeID)
2149 {
2150     LPWINE_MLD  mld = NULL;
2151
2152     assert(type < MMDRV_MAX);
2153
2154     if ((UINT)hndl >= llTypes[type].wMaxId &&
2155         hndl != (UINT16)-1 && hndl != (UINT)-1) {
2156         if (hndl & 0x8000) {
2157             hndl &= ~0x8000;
2158             if (hndl < sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0])) {
2159                 mld = MM_MLDrvs[hndl];
2160                 if (!mld || !HeapValidate(GetProcessHeap(), 0, mld) || mld->type != type)
2161                     mld = NULL;
2162             }
2163             hndl |= 0x8000;
2164         }
2165     }
2166     if (mld == NULL && bCanBeID) {
2167         mld = MMDRV_GetByID((UINT)hndl, type);
2168     }
2169     return mld;
2170 }
2171
2172 /**************************************************************************
2173  *                              MMDRV_GetRelated                [internal]
2174  */
2175 LPWINE_MLD      MMDRV_GetRelated(HANDLE hndl, UINT srcType,
2176                                  BOOL bSrcCanBeID, UINT dstType)
2177 {
2178     LPWINE_MLD          mld;
2179
2180     if ((mld = MMDRV_Get(hndl, srcType, bSrcCanBeID)) != NULL) {
2181         WINE_MM_DRIVER_PART*    part = &MMDrvs[mld->mmdIndex].parts[dstType];
2182         if (part->nIDMin < part->nIDMax)
2183             return MMDRV_GetByID(part->nIDMin, dstType);
2184     }
2185     return NULL;
2186 }
2187
2188 /**************************************************************************
2189  *                              MMDRV_PhysicalFeatures          [internal]
2190  */
2191 UINT    MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD dwParam1,
2192                                DWORD dwParam2)
2193 {
2194     WINE_MM_DRIVER*     lpDrv = &MMDrvs[mld->mmdIndex];
2195
2196     TRACE("(%p, %04x, %08lx, %08lx)\n", mld, uMsg, dwParam1, dwParam2);
2197
2198     /* all those function calls are undocumented */
2199     switch (uMsg) {
2200     case DRV_QUERYDRVENTRY:
2201         lstrcpynA((LPSTR)dwParam1, lpDrv->drvname, LOWORD(dwParam2));
2202         break;
2203     case DRV_QUERYDEVNODE:
2204         *(LPDWORD)dwParam1 = 0L; /* should be DevNode */
2205         break;
2206     case DRV_QUERYNAME:
2207         WARN("NIY QueryName\n");
2208         break;
2209     case DRV_QUERYDRIVERIDS:
2210         WARN("NIY call VxD\n");
2211         /* should call VxD MMDEVLDR with (DevNode, dwParam1 and dwParam2) as pmts
2212          * dwParam1 is buffer and dwParam2 is sizeof buffer
2213          * I don't know where the result is stored though
2214          */
2215         break;
2216     case DRV_QUERYMAPPABLE:
2217         return (lpDrv->bIsMapper) ? 2 : 0;
2218
2219     case DRV_QUERYDSOUNDIFACE: /* Wine-specific: Retrieve DirectSound interface */
2220         return MMDRV_Message(mld, uMsg, dwParam1, dwParam2, TRUE);
2221
2222     default:
2223         WARN("Unknown call %04x\n", uMsg);
2224         return MMSYSERR_INVALPARAM;
2225     }
2226     return 0L;
2227 }
2228
2229 /**************************************************************************
2230  *                              MMDRV_InitPerType               [internal]
2231  */
2232 static  BOOL    MMDRV_InitPerType(LPWINE_MM_DRIVER lpDrv, UINT type, UINT wMsg)
2233 {
2234     WINE_MM_DRIVER_PART*        part = &lpDrv->parts[type];
2235     DWORD                       ret;
2236     UINT                        count = 0;
2237     int                         i, k;
2238
2239     part->nIDMin = part->nIDMax = 0;
2240
2241     /* for DRVM_INIT and DRVM_ENABLE, dwParam2 should be PnP node */
2242     /* the DRVM_ENABLE is only required when the PnP node is non zero */
2243
2244     if (lpDrv->bIs32 && part->u.fnMessage32) {
2245         ret = part->u.fnMessage32(0, DRVM_INIT, 0L, 0L, 0L);
2246         TRACE("DRVM_INIT => %08lx\n", ret);
2247 #if 0
2248         ret = part->u.fnMessage32(0, DRVM_ENABLE, 0L, 0L, 0L);
2249         TRACE("DRVM_ENABLE => %08lx\n", ret);
2250 #endif
2251         count = part->u.fnMessage32(0, wMsg, 0L, 0L, 0L);
2252     } else if (!lpDrv->bIs32 && part->u.fnMessage16) {
2253         ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16,
2254                                         0, DRVM_INIT, 0L, 0L, 0L);
2255         TRACE("DRVM_INIT => %08lx\n", ret);
2256 #if 0
2257         ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16,
2258                                         0, DRVM_ENABLE, 0L, 0L, 0L);
2259         TRACE("DRVM_ENABLE => %08lx\n", ret);
2260 #endif
2261         count = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16,
2262                                           0, wMsg, 0L, 0L, 0L);
2263     } else {
2264         return FALSE;
2265     }
2266
2267     TRACE("Got %u dev for (%s:%s)\n", count, lpDrv->drvname, llTypes[type].typestr);
2268
2269     /* got some drivers */
2270     if (lpDrv->bIsMapper) {
2271         /* it seems native mappers return 0 devices :-( */
2272         if (llTypes[type].nMapper != -1)
2273             ERR("Two mappers for type %s (%d, %s)\n",
2274                 llTypes[type].typestr, llTypes[type].nMapper, lpDrv->drvname);
2275         if (count > 1)
2276             ERR("Strange: mapper with %d > 1 devices\n", count);
2277         llTypes[type].nMapper = MMDrvsHi;
2278     } else {
2279         if (count == 0)
2280             return FALSE;
2281         part->nIDMin = llTypes[type].wMaxId;
2282         llTypes[type].wMaxId += count;
2283         part->nIDMax = llTypes[type].wMaxId;
2284     }
2285     TRACE("Setting min=%d max=%d (ttop=%d) for (%s:%s)\n",
2286           part->nIDMin, part->nIDMax, llTypes[type].wMaxId,
2287           lpDrv->drvname, llTypes[type].typestr);
2288     /* realloc translation table */
2289     llTypes[type].lpMlds = (LPWINE_MLD)
2290         HeapReAlloc(GetProcessHeap(), 0, (llTypes[type].lpMlds) ? llTypes[type].lpMlds - 1 : NULL,
2291                     sizeof(WINE_MLD) * (llTypes[type].wMaxId + 1)) + 1;
2292     /* re-build the translation table */
2293     if (llTypes[type].nMapper != -1) {
2294         TRACE("%s:Trans[%d] -> %s\n", llTypes[type].typestr, -1, MMDrvs[llTypes[type].nMapper].drvname);
2295         llTypes[type].lpMlds[-1].uDeviceID = (UINT16)-1;
2296         llTypes[type].lpMlds[-1].type = type;
2297         llTypes[type].lpMlds[-1].mmdIndex = llTypes[type].nMapper;
2298         llTypes[type].lpMlds[-1].dwDriverInstance = 0;
2299     }
2300     for (i = k = 0; i <= MMDrvsHi; i++) {
2301         while (MMDrvs[i].parts[type].nIDMin <= k && k < MMDrvs[i].parts[type].nIDMax) {
2302             TRACE("%s:Trans[%d] -> %s\n", llTypes[type].typestr, k, MMDrvs[i].drvname);
2303             llTypes[type].lpMlds[k].uDeviceID = k;
2304             llTypes[type].lpMlds[k].type = type;
2305             llTypes[type].lpMlds[k].mmdIndex = i;
2306             llTypes[type].lpMlds[k].dwDriverInstance = 0;
2307             k++;
2308         }
2309     }
2310     return TRUE;
2311 }
2312
2313 /**************************************************************************
2314  *                              MMDRV_Install                   [internal]
2315  */
2316 static  BOOL    MMDRV_Install(LPCSTR drvRegName, LPCSTR drvFileName, BOOL bIsMapper)
2317 {
2318     int                 i, count = 0;
2319     char                buffer[128];
2320     LPWINE_MM_DRIVER    lpDrv = &MMDrvs[MMDrvsHi];
2321     LPWINE_DRIVER       d;
2322
2323     TRACE("('%s', '%s', mapper=%c);\n", drvRegName, drvFileName, bIsMapper ? 'Y' : 'N');
2324
2325     /* be sure that size of MMDrvs matches the max number of loadable drivers !!
2326      * if not just increase size of MMDrvs */
2327     assert(MMDrvsHi <= sizeof(MMDrvs)/sizeof(MMDrvs[0]));
2328
2329     for (i = 0; i < MMDrvsHi; i++) {
2330         if (!strcmp(drvRegName, MMDrvs[i].drvname)) return FALSE;
2331     }
2332
2333     memset(lpDrv, 0, sizeof(*lpDrv));
2334
2335     if (!(lpDrv->hDriver = OpenDriverA(drvFileName, 0, 0))) {
2336         WARN("Couldn't open driver '%s'\n", drvFileName);
2337         return FALSE;
2338     }
2339
2340     d = DRIVER_FindFromHDrvr(lpDrv->hDriver);
2341     lpDrv->bIs32 = (d->dwFlags & WINE_GDF_16BIT) ? FALSE : TRUE;
2342
2343     /* Then look for xxxMessage functions */
2344 #define AA(_h,_w,_x,_y,_z)                                      \
2345     func = (WINEMM_msgFunc##_y) _z ((_h), #_x);                 \
2346     if (func != NULL)                                           \
2347         { lpDrv->parts[_w].u.fnMessage##_y = func; count++;     \
2348           TRACE("Got %d bit func '%s'\n", _y, #_x);         }
2349
2350     if (lpDrv->bIs32) {
2351         WINEMM_msgFunc32        func;
2352
2353         if (d->d.d32.hModule) {
2354 #define A(_x,_y)        AA(d->d.d32.hModule,_x,_y,32,GetProcAddress)
2355             A(MMDRV_AUX,        auxMessage);
2356             A(MMDRV_MIXER,      mixMessage);
2357             A(MMDRV_MIDIIN,     midMessage);
2358             A(MMDRV_MIDIOUT,    modMessage);
2359             A(MMDRV_WAVEIN,     widMessage);
2360             A(MMDRV_WAVEOUT,    wodMessage);
2361 #undef A
2362         }
2363     } else {
2364         WINEMM_msgFunc16        func;
2365
2366         /*
2367          * DESCRIPTION 'wave,aux,mixer:Creative Labs Sound Blaster 16 Driver'
2368          * The beginning of the module description indicates the driver supports
2369          * waveform, auxiliary, and mixer devices. Use one of the following
2370          * device-type names, followed by a colon (:) to indicate the type of
2371          * device your driver supports. If the driver supports more than one
2372          * type of device, separate each device-type name with a comma (,).
2373          *
2374          * wave for waveform audio devices
2375          * wavemapper for wave mappers
2376          * midi for MIDI audio devices
2377          * midimapper for midi mappers
2378          * aux for auxiliary audio devices
2379          * mixer for mixer devices
2380          */
2381
2382         if (d->d.d16.hDriver16) {
2383             HMODULE16   hMod16 = GetDriverModuleHandle16(d->d.d16.hDriver16);
2384
2385 #define A(_x,_y)        AA(hMod16,_x,_y,16,GetProcAddress16)
2386             A(MMDRV_AUX,        auxMessage);
2387             A(MMDRV_MIXER,      mixMessage);
2388             A(MMDRV_MIDIIN,     midMessage);
2389             A(MMDRV_MIDIOUT,    modMessage);
2390             A(MMDRV_WAVEIN,     widMessage);
2391             A(MMDRV_WAVEOUT,    wodMessage);
2392 #undef A
2393         }
2394     }
2395 #undef AA
2396
2397     if (TRACE_ON(mmsys)) {
2398         if ((lpDrv->bIs32) ? MMDRV_GetDescription32(drvFileName, buffer, sizeof(buffer)) :
2399                              MMDRV_GetDescription16(drvFileName, buffer, sizeof(buffer)))
2400             TRACE("%s => %s\n", drvFileName, buffer);
2401         else
2402             TRACE("%s => No description\n", drvFileName);
2403     }
2404
2405     if (!count) {
2406         CloseDriver(lpDrv->hDriver, 0, 0);
2407         WARN("No message functions found\n");
2408         return FALSE;
2409     }
2410
2411     /* FIXME: being a mapper or not should be known by another way */
2412     /* it's known for NE drvs (the description is of the form '*mapper: *'
2413      * I don't have any clue for PE drvs
2414      */
2415     lpDrv->bIsMapper = bIsMapper;
2416     lpDrv->drvname = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(drvRegName) + 1), drvRegName);
2417
2418     /* Finish init and get the count of the devices */
2419     MMDRV_InitPerType(lpDrv, MMDRV_AUX,         AUXDM_GETNUMDEVS);
2420     MMDRV_InitPerType(lpDrv, MMDRV_MIXER,       MXDM_GETNUMDEVS);
2421     MMDRV_InitPerType(lpDrv, MMDRV_MIDIIN,      MIDM_GETNUMDEVS);
2422     MMDRV_InitPerType(lpDrv, MMDRV_MIDIOUT,     MODM_GETNUMDEVS);
2423     MMDRV_InitPerType(lpDrv, MMDRV_WAVEIN,      WIDM_GETNUMDEVS);
2424     MMDRV_InitPerType(lpDrv, MMDRV_WAVEOUT,     WODM_GETNUMDEVS);
2425     /* FIXME: if all those func calls return FALSE,
2426      * then the driver must be unloaded
2427      */
2428
2429     MMDrvsHi++;
2430
2431     return TRUE;
2432 }
2433
2434 /**************************************************************************
2435  *                              MMDRV_InitFromRegistry          [internal]
2436  */
2437 static BOOL     MMDRV_InitFromRegistry(void)
2438 {
2439     HKEY        hKey;
2440     char        buffer[256];
2441     char*       p1;
2442     char*       p2;
2443     DWORD       type, size;
2444     BOOL        ret = FALSE;
2445
2446     if (RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\WinMM", &hKey)) {
2447         TRACE("Cannot open WinMM config key\n");
2448         return FALSE;
2449     }
2450
2451     size = sizeof(buffer);
2452     if (!RegQueryValueExA(hKey, "Drivers", 0, &type, (LPVOID)buffer, &size)) {
2453         p1 = buffer;
2454         while (p1) {
2455             p2 = strchr(p1, ';');
2456             if (p2) *p2++ = '\0';
2457             ret |= MMDRV_Install(p1, p1, FALSE);
2458             p1 = p2;
2459         }
2460     }
2461
2462     /* finish with mappers */
2463     size = sizeof(buffer);
2464     if (!RegQueryValueExA(hKey, "WaveMapper", 0, &type, (LPVOID)buffer, &size))
2465         ret |= MMDRV_Install("wavemapper", buffer, TRUE);
2466     size = sizeof(buffer);
2467     if (!RegQueryValueExA(hKey, "MidiMapper", 0, &type, (LPVOID)buffer, &size))
2468         ret |= MMDRV_Install("midimapper", buffer, TRUE);
2469
2470     RegCloseKey(hKey);
2471
2472     return ret;
2473 }
2474
2475 /**************************************************************************
2476  *                              MMDRV_InitHardcoded             [internal]
2477  */
2478 static BOOL     MMDRV_InitHardcoded(void)
2479 {
2480     /* first load hardware drivers */
2481     MMDRV_Install("wineoss.drv",        "wineoss.drv",  FALSE);
2482
2483     /* finish with mappers */
2484     MMDRV_Install("wavemapper",         "msacm.drv",    TRUE);
2485     MMDRV_Install("midimapper",         "midimap.drv",  TRUE);
2486
2487     return TRUE;
2488 }
2489
2490 /**************************************************************************
2491  *                              MMDRV_Init                      [internal]
2492  */
2493 BOOL    MMDRV_Init(void)
2494 {
2495     /* FIXME: MMDRV_InitFromRegistry shall be MMDRV_Init in a near future */
2496     return MMDRV_InitFromRegistry() || MMDRV_InitHardcoded();
2497 }