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