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