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