Replaced PTR_SEG_TO_LIN macro by exported MapSL function.
[wine.git] / dlls / winmm / lolvldrv.c
blob3afe8abf1a98b6c05187ef6fff6590c8b2c8b5d5
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * MMSYTEM low level drivers handling functions
6 * Copyright 1999 Eric Pouech
7 */
9 #include <string.h>
10 #include <assert.h>
11 #include "wine/winbase16.h"
12 #include "heap.h"
13 #include "user.h" /* should be removed asap; used in MMDRV_(Get|Alloc|Free) */
14 #include "winver.h"
15 #include "winemm.h"
16 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(mmsys);
20 typedef DWORD CALLBACK (*WINEMM_msgFunc16)(UINT16, WORD, DWORD, DWORD, DWORD);
21 typedef DWORD CALLBACK (*WINEMM_msgFunc32)(UINT , UINT, DWORD, DWORD, DWORD);
23 /* for each loaded driver and each known type of driver, this structure contains
24 * the information needed to access it
26 typedef struct tagWINE_MM_DRIVER_PART {
27 int nIDMin; /* lower bound of global indexes for this type */
28 int nIDMax; /* hhigher bound of global indexes for this type */
29 union {
30 WINEMM_msgFunc32 fnMessage32; /* pointer to fonction */
31 WINEMM_msgFunc16 fnMessage16;
32 } u;
33 } WINE_MM_DRIVER_PART;
35 /* each low-level .drv will be associated with an instance of this structure */
36 typedef struct tagWINE_MM_DRIVER {
37 HDRVR hDriver;
38 LPSTR name; /* name of the driver */
39 BOOL bIs32 : 1, /* TRUE if 32 bit driver, FALSE for 16 */
40 bIsMapper : 1; /* TRUE if mapper */
41 WINE_MM_DRIVER_PART parts[MMDRV_MAX];/* Information for all known types */
42 } WINE_MM_DRIVER, *LPWINE_MM_DRIVER;
44 typedef enum {
45 MMDRV_MAP_NOMEM, /* ko, memory problem */
46 MMDRV_MAP_MSGERROR, /* ko, unknown message */
47 MMDRV_MAP_OK, /* ok, no memory allocated. to be sent to the proc. */
48 MMDRV_MAP_OKMEM, /* ok, some memory allocated, need to call UnMapMsg. to be sent to the proc. */
49 MMDRV_MAP_PASS /* not handled (no memory allocated) to be sent to the driver */
50 } MMDRV_MapType;
52 typedef MMDRV_MapType (*MMDRV_MAPFUNC)(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2);
54 /* each known type of driver has an instance of this structure */
55 typedef struct tagWINE_LLTYPE {
56 /* those attributes depend on the specification of the type */
57 LPSTR name; /* name (for debugging) */
58 BOOL bSupportMapper; /* if type is allowed to support mapper */
59 MMDRV_MAPFUNC Map16To32A; /* those are function pointers to handle */
60 MMDRV_MAPFUNC UnMap16To32A; /* the parameter conversion (16 vs 32 bit) */
61 MMDRV_MAPFUNC Map32ATo16; /* when hi-func (in mmsystem or winmm) and */
62 MMDRV_MAPFUNC UnMap32ATo16; /* low-func (in .drv) do not match */
63 LPDRVCALLBACK Callback; /* handles callback for a specified type */
64 /* those attributes reflect the loaded/current situation for the type */
65 UINT wMaxId; /* number of loaded devices (sum across all loaded drivers */
66 LPWINE_MLD lpMlds; /* "static" mlds to access the part though device IDs */
67 int nMapper; /* index to mapper */
68 } WINE_LLTYPE;
70 static WINE_MM_DRIVER MMDrvs[3];
72 /* ### start build ### */
73 extern WORD CALLBACK MMDRV_CallTo16_word_wwlll(FARPROC16,WORD,WORD,LONG,LONG,LONG);
74 /* ### stop build ### */
76 /**************************************************************************
77 * MMDRV_GetDescription16 [internal]
79 static BOOL MMDRV_GetDescription16(const char* fname, char* buf, int buflen)
81 OFSTRUCT ofs;
82 HFILE hFile;
83 WORD w;
84 DWORD dw;
85 BOOL ret = FALSE;
87 if ((hFile = OpenFile(fname, &ofs, OF_READ | OF_SHARE_DENY_WRITE)) == HFILE_ERROR) {
88 ERR("Can't open file %s\n", fname);
89 return FALSE;
92 #define E(_x) do {TRACE _x;goto theEnd;} while(0)
94 if (_lread(hFile, &w, 2) != 2) E(("Can't read sig\n"));
95 if (w != ('Z' * 256 + 'M')) E(("Bad sig %04x\n", w));
96 if (_llseek(hFile, 0x3C, SEEK_SET) < 0) E(("Can't seek to ext header offset\n"));
97 if (_lread(hFile, &dw, 4) != 4) E(("Can't read ext header offset\n"));
98 if (_llseek(hFile, dw + 0x2C, SEEK_SET) < 0) E(("Can't seek to ext header.nr table %lu\n", dw+0x2C));
99 if (_lread(hFile, &dw, 4) != 4) E(("Can't read nr table offset\n"));
100 if (_llseek(hFile, dw, SEEK_SET) < 0) E(("Can't seek to nr table %lu\n", dw));
101 if (_lread(hFile, buf, 1) != 1) E(("Can't read descr length\n"));
102 buflen = min((BYTE)buf[0], buflen - 1);
103 if (_lread(hFile, buf, buflen) != buflen) E(("Can't read descr (%d)\n", buflen));
104 buf[buflen] = '\0';
105 ret = TRUE;
106 TRACE("Got '%s' [%d]\n", buf, buflen);
107 theEnd:
108 CloseHandle(hFile);
109 return ret;
112 /**************************************************************************
113 * MMDRV_GetDescription32 [internal]
115 static BOOL MMDRV_GetDescription32(const char* fname, char* buf, int buflen)
117 OFSTRUCT ofs;
118 DWORD h;
119 LPVOID ptr = 0;
120 LPVOID val;
121 DWORD dw;
122 BOOL ret = FALSE;
123 UINT u;
124 FARPROC pGetFileVersionInfoSizeA;
125 FARPROC pGetFileVersionInfoA;
126 FARPROC pVerQueryValueA;
127 HMODULE hmodule = 0;
129 #define E(_x) do {TRACE _x;goto theEnd;} while(0)
131 if (OpenFile(fname, &ofs, OF_EXIST)==HFILE_ERROR) E(("Can't find file %s\n", fname));
133 if (!(hmodule = LoadLibraryA( "version.dll" ))) goto theEnd;
134 if (!(pGetFileVersionInfoSizeA = GetProcAddress( hmodule, "GetFileVersionInfoSizeA" )))
135 goto theEnd;
136 if (!(pGetFileVersionInfoA = GetProcAddress( hmodule, "GetFileVersionInfoA" )))
137 goto theEnd;
138 if (!(pVerQueryValueA = GetProcAddress( hmodule, "pVerQueryValueA" )))
139 goto theEnd;
141 if (!(dw = pGetFileVersionInfoSizeA(ofs.szPathName, &h))) E(("Can't get FVIS\n"));
142 if (!(ptr = HeapAlloc(GetProcessHeap(), 0, dw))) E(("OOM\n"));
143 if (!pGetFileVersionInfoA(ofs.szPathName, h, dw, ptr)) E(("Can't get FVI\n"));
145 #define A(_x) if (pVerQueryValueA(ptr, "\\StringFileInfo\\040904B0\\" #_x, &val, &u)) \
146 TRACE(#_x " => %s\n", (LPSTR)val); else TRACE(#_x " @\n")
148 A(CompanyName);
149 A(FileDescription);
150 A(FileVersion);
151 A(InternalName);
152 A(LegalCopyright);
153 A(OriginalFilename);
154 A(ProductName);
155 A(ProductVersion);
156 A(Comments);
157 A(LegalTrademarks);
158 A(PrivateBuild);
159 A(SpecialBuild);
160 #undef A
162 if (!pVerQueryValueA(ptr, "\\StringFileInfo\\040904B0\\ProductName", &val, &u)) E(("Can't get product name\n"));
163 lstrcpynA(buf, val, buflen);
165 #undef E
166 ret = TRUE;
167 theEnd:
168 HeapFree(GetProcessHeap(), 0, ptr);
169 if (hmodule) FreeLibrary( hmodule );
170 return ret;
173 /**************************************************************************
174 * MMDRV_Callback [internal]
176 static void MMDRV_Callback(LPWINE_MLD mld, HDRVR hDev, UINT uMsg, DWORD dwParam1, DWORD dwParam2)
178 TRACE("CB (*%08lx)(%08x %08x %08lx %08lx %08lx\n",
179 mld->dwCallback, hDev, uMsg, mld->dwClientInstance, dwParam1, dwParam2);
181 if (!mld->bFrom32 && (mld->dwFlags & DCB_TYPEMASK) == DCB_FUNCTION) {
182 /* 16 bit func, call it */
183 TRACE("Function (16 bit) !\n");
184 MMDRV_CallTo16_word_wwlll((FARPROC16)mld->dwCallback, hDev, uMsg,
185 mld->dwClientInstance, dwParam1, dwParam2);
186 } else {
187 DriverCallback(mld->dwCallback, mld->dwFlags, hDev, uMsg,
188 mld->dwClientInstance, dwParam1, dwParam2);
192 /* =================================
193 * A U X M A P P E R S
194 * ================================= */
196 /**************************************************************************
197 * MMDRV_Aux_Map16To32A [internal]
199 static MMDRV_MapType MMDRV_Aux_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
201 return MMDRV_MAP_MSGERROR;
204 /**************************************************************************
205 * MMDRV_Aux_UnMap16To32A [internal]
207 static MMDRV_MapType MMDRV_Aux_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
209 return MMDRV_MAP_MSGERROR;
212 /**************************************************************************
213 * MMDRV_Aux_Map32ATo16 [internal]
215 static MMDRV_MapType MMDRV_Aux_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
217 return MMDRV_MAP_MSGERROR;
220 /**************************************************************************
221 * MMDRV_Aux_UnMap32ATo16 [internal]
223 static MMDRV_MapType MMDRV_Aux_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
225 #if 0
226 case AUXDM_GETDEVCAPS:
227 lpCaps->wMid = ac16.wMid;
228 lpCaps->wPid = ac16.wPid;
229 lpCaps->vDriverVersion = ac16.vDriverVersion;
230 strcpy(lpCaps->szPname, ac16.szPname);
231 lpCaps->wTechnology = ac16.wTechnology;
232 lpCaps->dwSupport = ac16.dwSupport;
233 #endif
234 return MMDRV_MAP_MSGERROR;
237 /**************************************************************************
238 * MMDRV_Aux_Callback [internal]
240 static void CALLBACK MMDRV_Aux_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
242 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
244 FIXME("NIY\n");
245 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
248 /* =================================
249 * M I X E R M A P P E R S
250 * ================================= */
252 /**************************************************************************
253 * xMMDRV_Mixer_Map16To32A [internal]
255 static MMDRV_MapType MMDRV_Mixer_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
257 return MMDRV_MAP_MSGERROR;
260 /**************************************************************************
261 * MMDRV_Mixer_UnMap16To32A [internal]
263 static MMDRV_MapType MMDRV_Mixer_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
265 #if 0
266 MIXERCAPSA micA;
267 UINT ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
269 if (ret == MMSYSERR_NOERROR) {
270 mixcaps->wMid = micA.wMid;
271 mixcaps->wPid = micA.wPid;
272 mixcaps->vDriverVersion = micA.vDriverVersion;
273 strcpy(mixcaps->szPname, micA.szPname);
274 mixcaps->fdwSupport = micA.fdwSupport;
275 mixcaps->cDestinations = micA.cDestinations;
277 return ret;
278 #endif
279 return MMDRV_MAP_MSGERROR;
282 /**************************************************************************
283 * MMDRV_Mixer_Map32ATo16 [internal]
285 static MMDRV_MapType MMDRV_Mixer_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
287 return MMDRV_MAP_MSGERROR;
290 /**************************************************************************
291 * MMDRV_Mixer_UnMap32ATo16 [internal]
293 static MMDRV_MapType MMDRV_Mixer_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
295 return MMDRV_MAP_MSGERROR;
298 /**************************************************************************
299 * MMDRV_Mixer_Callback [internal]
301 static void CALLBACK MMDRV_Mixer_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
303 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
305 FIXME("NIY\n");
306 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
309 /* =================================
310 * M I D I I N M A P P E R S
311 * ================================= */
313 /**************************************************************************
314 * MMDRV_MidiIn_Map16To32A [internal]
316 static MMDRV_MapType MMDRV_MidiIn_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
318 return MMDRV_MAP_MSGERROR;
321 /**************************************************************************
322 * MMDRV_MidiIn_UnMap16To32A [internal]
324 static MMDRV_MapType MMDRV_MidiIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
326 return MMDRV_MAP_MSGERROR;
329 /**************************************************************************
330 * MMDRV_MidiIn_Map32ATo16 [internal]
332 static MMDRV_MapType MMDRV_MidiIn_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
334 return MMDRV_MAP_MSGERROR;
337 /**************************************************************************
338 * MMDRV_MidiIn_UnMap32ATo16 [internal]
340 static MMDRV_MapType MMDRV_MidiIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
342 return MMDRV_MAP_MSGERROR;
345 /**************************************************************************
346 * MMDRV_MidiIn_Callback [internal]
348 static void CALLBACK MMDRV_MidiIn_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
350 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
352 switch (uMsg) {
353 case MIM_OPEN:
354 case MIM_CLOSE:
355 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
357 case MIM_DATA:
358 case MIM_MOREDATA:
359 case MIM_ERROR:
360 /* dwParam1 & dwParam2 are are data, nothing to do */
361 break;
362 case MIM_LONGDATA:
363 case MIM_LONGERROR:
364 /* dwParam1 points to a MidiHdr, work to be done !!! */
365 if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
366 /* initial map is: 32 => 16 */
367 LPMIDIHDR mh16 = MapSL(dwParam1);
368 LPMIDIHDR mh32 = *(LPMIDIHDR*)((LPSTR)mh16 - sizeof(LPMIDIHDR));
370 dwParam1 = (DWORD)mh32;
371 mh32->dwFlags = mh16->dwFlags;
372 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
373 if (mh32->reserved >= sizeof(MIDIHDR))
374 mh32->dwOffset = mh16->dwOffset;
375 } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
376 /* initial map is: 16 => 32 */
377 LPMIDIHDR mh32 = (LPMIDIHDR)(dwParam1);
378 SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
379 LPMIDIHDR mh16 = MapSL(segmh16);
381 dwParam1 = (DWORD)segmh16;
382 mh16->dwFlags = mh32->dwFlags;
383 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
384 if (mh16->reserved >= sizeof(MIDIHDR))
385 mh16->dwOffset = mh32->dwOffset;
387 /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
388 break;
389 /* case MOM_POSITIONCB: */
390 default:
391 ERR("Unknown msg %u\n", uMsg);
394 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
397 /* =================================
398 * M I D I O U T M A P P E R S
399 * ================================= */
401 /**************************************************************************
402 * MMDRV_MidiOut_Map16To32A [internal]
404 static MMDRV_MapType MMDRV_MidiOut_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
406 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
408 switch (wMsg) {
409 case MODM_GETNUMDEVS:
410 case MODM_DATA:
411 case MODM_RESET:
412 case MODM_SETVOLUME:
413 ret = MMDRV_MAP_OK;
414 break;
416 case MODM_OPEN:
417 case MODM_CLOSE:
418 case MODM_GETVOLUME:
419 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
420 break;
422 case MODM_GETDEVCAPS:
424 LPMIDIOUTCAPSA moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSA));
425 LPMIDIOUTCAPS16 moc16 = MapSL(*lpParam1);
427 if (moc32) {
428 *(LPMIDIOUTCAPS16*)moc32 = moc16;
429 moc32 = (LPMIDIOUTCAPSA)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16));
430 *lpParam1 = (DWORD)moc32;
431 *lpParam2 = sizeof(MIDIOUTCAPSA);
433 ret = MMDRV_MAP_OKMEM;
434 } else {
435 ret = MMDRV_MAP_NOMEM;
438 break;
439 case MODM_PREPARE:
441 LPMIDIHDR mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR));
442 LPMIDIHDR mh16 = MapSL(*lpParam1);
444 if (mh32) {
445 *(LPMIDIHDR*)mh32 = (LPMIDIHDR)*lpParam1;
446 mh32 = (LPMIDIHDR)((LPSTR)mh32 + sizeof(LPMIDIHDR));
447 mh32->lpData = MapSL((SEGPTR)mh16->lpData);
448 mh32->dwBufferLength = mh16->dwBufferLength;
449 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
450 mh32->dwUser = mh16->dwUser;
451 mh32->dwFlags = mh16->dwFlags;
452 /* FIXME: nothing on mh32->lpNext */
453 /* could link the mh32->lpNext at this level for memory house keeping */
454 mh32->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? ((LPMIDIHDR)mh16)->dwOffset : 0;
455 mh16->lpNext = mh32; /* for reuse in unprepare and write */
456 /* store size of passed MIDIHDR?? structure to know if dwOffset is available or not */
457 mh16->reserved = *lpParam2;
458 *lpParam1 = (DWORD)mh32;
459 *lpParam2 = sizeof(MIDIHDR);
461 ret = MMDRV_MAP_OKMEM;
462 } else {
463 ret = MMDRV_MAP_NOMEM;
466 break;
467 case MODM_UNPREPARE:
468 case MODM_LONGDATA:
470 LPMIDIHDR mh16 = MapSL(*lpParam1);
471 LPMIDIHDR mh32 = (LPMIDIHDR)mh16->lpNext;
473 *lpParam1 = (DWORD)mh32;
474 *lpParam2 = sizeof(MIDIHDR);
475 /* dwBufferLength can be reduced between prepare & write */
476 if (mh32->dwBufferLength < mh16->dwBufferLength) {
477 ERR("Size of buffer has been increased (%ld, %ld)\n",
478 mh32->dwBufferLength, mh16->dwBufferLength);
479 return MMDRV_MAP_MSGERROR;
481 mh32->dwBufferLength = mh16->dwBufferLength;
482 ret = MMDRV_MAP_OKMEM;
484 break;
486 case MODM_CACHEPATCHES:
487 case MODM_CACHEDRUMPATCHES:
488 default:
489 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
490 break;
492 return ret;
495 /**************************************************************************
496 * MMDRV_MidiOut_UnMap16To32A [internal]
498 static MMDRV_MapType MMDRV_MidiOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
500 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
502 switch (wMsg) {
503 case MODM_GETNUMDEVS:
504 case MODM_DATA:
505 case MODM_RESET:
506 case MODM_SETVOLUME:
507 ret = MMDRV_MAP_OK;
508 break;
510 case MODM_OPEN:
511 case MODM_CLOSE:
512 case MODM_GETVOLUME:
513 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
514 break;
516 case MODM_GETDEVCAPS:
518 LPMIDIOUTCAPSA moc32 = (LPMIDIOUTCAPSA)(*lpParam1);
519 LPMIDIOUTCAPS16 moc16 = *(LPMIDIOUTCAPS16*)((LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
521 moc16->wMid = moc32->wMid;
522 moc16->wPid = moc32->wPid;
523 moc16->vDriverVersion = moc32->vDriverVersion;
524 strcpy(moc16->szPname, moc32->szPname);
525 moc16->wTechnology = moc32->wTechnology;
526 moc16->wVoices = moc32->wVoices;
527 moc16->wNotes = moc32->wNotes;
528 moc16->wChannelMask = moc32->wChannelMask;
529 moc16->dwSupport = moc32->dwSupport;
530 HeapFree(GetProcessHeap(), 0, (LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
531 ret = MMDRV_MAP_OK;
533 break;
534 case MODM_PREPARE:
535 case MODM_UNPREPARE:
536 case MODM_LONGDATA:
538 LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1);
539 LPMIDIHDR mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)));
541 assert(mh16->lpNext == mh32);
542 mh16->dwBufferLength = mh32->dwBufferLength;
543 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
544 mh16->dwUser = mh32->dwUser;
545 mh16->dwFlags = mh32->dwFlags;
546 if (mh16->reserved >= sizeof(MIDIHDR))
547 mh16->dwOffset = mh32->dwOffset;
549 if (wMsg == MODM_UNPREPARE) {
550 HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR));
551 mh16->lpNext = 0;
553 ret = MMDRV_MAP_OK;
555 break;
557 case MODM_CACHEPATCHES:
558 case MODM_CACHEDRUMPATCHES:
559 default:
560 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
561 break;
563 return ret;
566 /**************************************************************************
567 * MMDRV_MidiOut_Map32ATo16 [internal]
569 static MMDRV_MapType MMDRV_MidiOut_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
571 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
573 switch (wMsg) {
574 case MODM_CLOSE:
575 case MODM_GETNUMDEVS:
576 case MODM_DATA:
577 case MODM_RESET:
578 case MODM_SETVOLUME:
579 ret = MMDRV_MAP_OK;
580 break;
581 case MODM_GETDEVCAPS:
583 LPMIDIOUTCAPSA moc32 = (LPMIDIOUTCAPSA)*lpParam1;
584 LPSTR ptr = SEGPTR_ALLOC(sizeof(LPMIDIOUTCAPSA) + sizeof(MIDIOUTCAPS16));
586 if (ptr) {
587 *(LPMIDIOUTCAPSA*)ptr = moc32;
588 ret = MMDRV_MAP_OKMEM;
589 } else {
590 ret = MMDRV_MAP_NOMEM;
592 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMIDIOUTCAPSA);
593 *lpParam2 = sizeof(MIDIOUTCAPS16);
595 break;
596 case MODM_PREPARE:
598 LPMIDIHDR mh32 = (LPMIDIHDR)*lpParam1;
599 LPMIDIHDR mh16;
600 LPVOID ptr = SEGPTR_ALLOC(sizeof(LPMIDIHDR) + sizeof(MIDIHDR) + mh32->dwBufferLength);
602 if (ptr) {
603 *(LPMIDIHDR*)ptr = mh32;
604 mh16 = (LPMIDIHDR)((LPSTR)ptr + sizeof(LPMIDIHDR));
605 mh16->lpData = (LPSTR)SEGPTR_GET(ptr) + sizeof(LPMIDIHDR) + sizeof(MIDIHDR);
606 /* data will be copied on WODM_WRITE */
607 mh16->dwBufferLength = mh32->dwBufferLength;
608 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
609 mh16->dwUser = mh32->dwUser;
610 mh16->dwFlags = mh32->dwFlags;
611 /* FIXME: nothing on mh32->lpNext */
612 /* could link the mh32->lpNext at this level for memory house keeping */
613 mh16->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? mh32->dwOffset : 0;
615 mh32->lpNext = (LPMIDIHDR)mh16; /* for reuse in unprepare and write */
616 mh32->reserved = *lpParam2;
618 TRACE("mh16=%08lx mh16->lpData=%08lx mh32->buflen=%lu mh32->lpData=%08lx\n",
619 (DWORD)SEGPTR_GET(ptr) + sizeof(LPMIDIHDR), (DWORD)mh16->lpData,
620 mh32->dwBufferLength, (DWORD)mh32->lpData);
621 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMIDIHDR);
622 *lpParam2 = sizeof(MIDIHDR);
624 ret = MMDRV_MAP_OKMEM;
625 } else {
626 ret = MMDRV_MAP_NOMEM;
629 break;
630 case MODM_UNPREPARE:
631 case MODM_LONGDATA:
633 LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1);
634 LPMIDIHDR mh16 = (LPMIDIHDR)mh32->lpNext;
635 LPSTR ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
637 assert(*(LPMIDIHDR*)ptr == mh32);
639 TRACE("mh16=%08lx mh16->lpData=%08lx mh32->buflen=%lu mh32->lpData=%08lx\n",
640 (DWORD)SEGPTR_GET(ptr) + sizeof(LPMIDIHDR), (DWORD)mh16->lpData,
641 mh32->dwBufferLength, (DWORD)mh32->lpData);
643 if (wMsg == MODM_LONGDATA)
644 memcpy((LPSTR)mh16 + sizeof(MIDIHDR), mh32->lpData, mh32->dwBufferLength);
646 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMIDIHDR);
647 *lpParam2 = sizeof(MIDIHDR);
648 /* dwBufferLength can be reduced between prepare & write */
649 if (mh16->dwBufferLength < mh32->dwBufferLength) {
650 ERR("Size of buffer has been increased (%ld, %ld)\n",
651 mh16->dwBufferLength, mh32->dwBufferLength);
652 return MMDRV_MAP_MSGERROR;
654 mh16->dwBufferLength = mh32->dwBufferLength;
655 ret = MMDRV_MAP_OKMEM;
657 break;
658 case MODM_OPEN:
660 LPMIDIOPENDESC mod32 = (LPMIDIOPENDESC)*lpParam1;
661 LPVOID ptr;
662 LPMIDIOPENDESC16 mod16;
664 /* allocated data are mapped as follows:
665 LPMIDIOPENDESC ptr to orig lParam1
666 DWORD orig dwUser, which is a pointer to DWORD:driver dwInstance
667 DWORD dwUser passed to driver
668 MIDIOPENDESC16 mod16: openDesc passed to driver
669 MIDIOPENSTRMID cIds
671 ptr = SEGPTR_ALLOC(sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD) + sizeof(MIDIOPENDESC16) +
672 mod32->cIds ? (mod32->cIds - 1) * sizeof(MIDIOPENSTRMID) : 0);
674 if (ptr) {
675 *(LPMIDIOPENDESC*)ptr = mod32;
676 *(LPDWORD)(ptr + sizeof(LPMIDIOPENDESC)) = *lpdwUser;
677 mod16 = (LPMIDIOPENDESC16)((LPSTR)ptr + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD));
679 mod16->hMidi = mod32->hMidi;
680 mod16->dwCallback = mod32->dwCallback;
681 mod16->dwInstance = mod32->dwInstance;
682 mod16->dnDevNode = mod32->dnDevNode;
683 mod16->cIds = mod32->cIds;
684 memcpy(&mod16->rgIds, &mod32->rgIds, mod32->cIds * sizeof(MIDIOPENSTRMID));
686 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD);
687 *lpdwUser = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMIDIOPENDESC) + sizeof(DWORD);
689 ret = MMDRV_MAP_OKMEM;
690 } else {
691 ret = MMDRV_MAP_NOMEM;
694 break;
695 case MODM_GETVOLUME:
696 case MODM_CACHEPATCHES:
697 case MODM_CACHEDRUMPATCHES:
698 default:
699 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
700 break;
702 return ret;
705 /**************************************************************************
706 * MMDRV_MidiOut_UnMap32ATo16 [internal]
708 static MMDRV_MapType MMDRV_MidiOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
710 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
712 switch (wMsg) {
713 case MODM_CLOSE:
714 case MODM_GETNUMDEVS:
715 case MODM_DATA:
716 case MODM_RESET:
717 case MODM_SETVOLUME:
718 ret = MMDRV_MAP_OK;
719 break;
720 case MODM_GETDEVCAPS:
722 LPMIDIOUTCAPS16 moc16 = MapSL(*lpParam1);
723 LPSTR ptr = (LPSTR)moc16 - sizeof(LPMIDIOUTCAPSA);
724 LPMIDIOUTCAPSA moc32 = *(LPMIDIOUTCAPSA*)ptr;
726 moc32->wMid = moc16->wMid;
727 moc32->wPid = moc16->wPid;
728 moc32->vDriverVersion = moc16->vDriverVersion;
729 strcpy(moc32->szPname, moc16->szPname);
730 moc32->wTechnology = moc16->wTechnology;
731 moc32->wVoices = moc16->wVoices;
732 moc32->wNotes = moc16->wNotes;
733 moc32->wChannelMask = moc16->wChannelMask;
734 moc32->dwSupport = moc16->dwSupport;
736 if (!SEGPTR_FREE(ptr))
737 FIXME("bad free line=%d\n", __LINE__);
738 ret = MMDRV_MAP_OK;
740 break;
741 case MODM_PREPARE:
742 case MODM_UNPREPARE:
743 case MODM_LONGDATA:
745 LPMIDIHDR mh16 = MapSL(*lpParam1);
746 LPSTR ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
747 LPMIDIHDR mh32 = *(LPMIDIHDR*)ptr;
749 assert(mh32->lpNext == (LPMIDIHDR)mh16);
750 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
751 mh32->dwUser = mh16->dwUser;
752 mh32->dwFlags = mh16->dwFlags;
754 if (wMsg == MODM_UNPREPARE) {
755 if (!SEGPTR_FREE(ptr))
756 FIXME("bad free line=%d\n", __LINE__);
757 mh32->lpNext = 0;
759 ret = MMDRV_MAP_OK;
761 break;
762 case MODM_OPEN:
764 LPMIDIOPENDESC16 mod16 = MapSL(*lpParam1);
765 LPSTR ptr = (LPSTR)mod16 - sizeof(LPMIDIOPENDESC) - 2*sizeof(DWORD);
767 **(DWORD**)(ptr + sizeof(LPMIDIOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPMIDIOPENDESC) + sizeof(DWORD));
769 if (!SEGPTR_FREE(ptr))
770 FIXME("bad free line=%d\n", __LINE__);
772 ret = MMDRV_MAP_OK;
774 break;
775 case MODM_GETVOLUME:
776 case MODM_CACHEPATCHES:
777 case MODM_CACHEDRUMPATCHES:
778 default:
779 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
780 break;
782 return ret;
785 /**************************************************************************
786 * MMDRV_MidiOut_Callback [internal]
788 static void CALLBACK MMDRV_MidiOut_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
790 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
792 switch (uMsg) {
793 case MOM_OPEN:
794 case MOM_CLOSE:
795 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
796 break;
797 case MOM_DONE:
798 if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
799 /* initial map is: 32 => 16 */
800 LPMIDIHDR mh16 = MapSL(dwParam1);
801 LPMIDIHDR mh32 = *(LPMIDIHDR*)((LPSTR)mh16 - sizeof(LPMIDIHDR));
803 dwParam1 = (DWORD)mh32;
804 mh32->dwFlags = mh16->dwFlags;
805 mh32->dwOffset = mh16->dwOffset;
806 if (mh32->reserved >= sizeof(MIDIHDR))
807 mh32->dwOffset = mh16->dwOffset;
808 } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
809 /* initial map is: 16 => 32 */
810 LPMIDIHDR mh32 = (LPMIDIHDR)(dwParam1);
811 SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
812 LPMIDIHDR mh16 = MapSL(segmh16);
814 dwParam1 = (DWORD)segmh16;
815 mh16->dwFlags = mh32->dwFlags;
816 if (mh16->reserved >= sizeof(MIDIHDR))
817 mh16->dwOffset = mh32->dwOffset;
819 /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
820 break;
821 /* case MOM_POSITIONCB: */
822 default:
823 ERR("Unknown msg %u\n", uMsg);
826 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
829 /* =================================
830 * W A V E I N M A P P E R S
831 * ================================= */
833 /**************************************************************************
834 * MMDRV_WaveIn_Map16To32A [internal]
836 static MMDRV_MapType MMDRV_WaveIn_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
838 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
840 switch (wMsg) {
841 case WIDM_GETNUMDEVS:
842 case WIDM_RESET:
843 case WIDM_START:
844 case WIDM_STOP:
845 ret = MMDRV_MAP_OK;
846 break;
847 case WIDM_OPEN:
848 case WIDM_CLOSE:
849 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
850 break;
851 case WIDM_GETDEVCAPS:
853 LPWAVEINCAPSA wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSA));
854 LPWAVEINCAPS16 wic16 = MapSL(*lpParam1);
856 if (wic32) {
857 *(LPWAVEINCAPS16*)wic32 = wic16;
858 wic32 = (LPWAVEINCAPSA)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16));
859 *lpParam1 = (DWORD)wic32;
860 *lpParam2 = sizeof(WAVEINCAPSA);
862 ret = MMDRV_MAP_OKMEM;
863 } else {
864 ret = MMDRV_MAP_NOMEM;
867 break;
868 case WIDM_GETPOS:
870 LPMMTIME mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
871 LPMMTIME16 mmt16 = MapSL(*lpParam1);
873 if (mmt32) {
874 *(LPMMTIME16*)mmt32 = mmt16;
875 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
877 mmt32->wType = mmt16->wType;
878 *lpParam1 = (DWORD)mmt32;
879 *lpParam2 = sizeof(MMTIME);
881 ret = MMDRV_MAP_OKMEM;
882 } else {
883 ret = MMDRV_MAP_NOMEM;
886 break;
887 case WIDM_PREPARE:
889 LPWAVEHDR wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
890 LPWAVEHDR wh16 = MapSL(*lpParam1);
892 if (wh32) {
893 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
894 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
895 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
896 wh32->dwBufferLength = wh16->dwBufferLength;
897 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
898 wh32->dwUser = wh16->dwUser;
899 wh32->dwFlags = wh16->dwFlags;
900 wh32->dwLoops = wh16->dwLoops;
901 /* FIXME: nothing on wh32->lpNext */
902 /* could link the wh32->lpNext at this level for memory house keeping */
903 wh16->lpNext = wh32; /* for reuse in unprepare and write */
904 *lpParam1 = (DWORD)wh32;
905 *lpParam2 = sizeof(WAVEHDR);
907 ret = MMDRV_MAP_OKMEM;
908 } else {
909 ret = MMDRV_MAP_NOMEM;
912 break;
913 case WIDM_ADDBUFFER:
914 case WIDM_UNPREPARE:
916 LPWAVEHDR wh16 = MapSL(*lpParam1);
917 LPWAVEHDR wh32 = (LPWAVEHDR)wh16->lpNext;
919 *lpParam1 = (DWORD)wh32;
920 *lpParam2 = sizeof(WAVEHDR);
921 /* dwBufferLength can be reduced between prepare & write */
922 if (wh32->dwBufferLength < wh16->dwBufferLength) {
923 ERR("Size of buffer has been increased (%ld, %ld)\n",
924 wh32->dwBufferLength, wh16->dwBufferLength);
925 return MMDRV_MAP_MSGERROR;
927 wh32->dwBufferLength = wh16->dwBufferLength;
928 ret = MMDRV_MAP_OKMEM;
930 break;
931 default:
932 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
933 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
934 break;
936 return ret;
939 /**************************************************************************
940 * MMDRV_WaveIn_UnMap16To32A [internal]
942 static MMDRV_MapType MMDRV_WaveIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
944 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
946 switch (wMsg) {
947 case WIDM_GETNUMDEVS:
948 case WIDM_RESET:
949 case WIDM_START:
950 case WIDM_STOP:
951 ret = MMDRV_MAP_OK;
952 break;
953 case WIDM_OPEN:
954 case WIDM_CLOSE:
955 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
956 break;
957 case WIDM_GETDEVCAPS:
959 LPWAVEINCAPSA wic32 = (LPWAVEINCAPSA)(*lpParam1);
960 LPWAVEINCAPS16 wic16 = *(LPWAVEINCAPS16*)((LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
962 wic16->wMid = wic32->wMid;
963 wic16->wPid = wic32->wPid;
964 wic16->vDriverVersion = wic32->vDriverVersion;
965 strcpy(wic16->szPname, wic32->szPname);
966 wic16->dwFormats = wic32->dwFormats;
967 wic16->wChannels = wic32->wChannels;
968 HeapFree(GetProcessHeap(), 0, (LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
969 ret = MMDRV_MAP_OK;
971 break;
972 case WIDM_GETPOS:
974 LPMMTIME mmt32 = (LPMMTIME)(*lpParam1);
975 LPMMTIME16 mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
977 MMSYSTEM_MMTIME32to16(mmt16, mmt32);
978 HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
979 ret = MMDRV_MAP_OK;
981 break;
982 case WIDM_ADDBUFFER:
983 case WIDM_PREPARE:
984 case WIDM_UNPREPARE:
986 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
987 LPWAVEHDR wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
989 assert(wh16->lpNext == wh32);
990 wh16->dwBufferLength = wh32->dwBufferLength;
991 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
992 wh16->dwUser = wh32->dwUser;
993 wh16->dwFlags = wh32->dwFlags;
994 wh16->dwLoops = wh32->dwLoops;
996 if (wMsg == WIDM_UNPREPARE) {
997 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
998 wh16->lpNext = 0;
1000 ret = MMDRV_MAP_OK;
1002 break;
1003 default:
1004 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1005 break;
1007 return ret;
1010 /**************************************************************************
1011 * MMDRV_WaveIn_Map32ATo16 [internal]
1013 static MMDRV_MapType MMDRV_WaveIn_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1015 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
1017 switch (wMsg) {
1018 case WIDM_CLOSE:
1019 case WIDM_GETNUMDEVS:
1020 case WIDM_RESET:
1021 case WIDM_START:
1022 case WIDM_STOP:
1023 ret = MMDRV_MAP_OK;
1024 break;
1026 case WIDM_OPEN:
1028 LPWAVEOPENDESC wod32 = (LPWAVEOPENDESC)*lpParam1;
1029 int sz = sizeof(WAVEFORMATEX);
1030 LPVOID ptr;
1031 LPWAVEOPENDESC16 wod16;
1033 /* allocated data are mapped as follows:
1034 LPWAVEOPENDESC ptr to orig lParam1
1035 DWORD orig dwUser, which is a pointer to DWORD:driver dwInstance
1036 DWORD dwUser passed to driver
1037 WAVEOPENDESC16 wod16: openDesc passed to driver
1038 WAVEFORMATEX openDesc->lpFormat passed to driver
1039 xxx extra bytes to WAVEFORMATEX
1041 if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1042 TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag);
1043 sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize;
1046 ptr = SEGPTR_ALLOC(sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
1048 if (ptr) {
1049 *(LPWAVEOPENDESC*)ptr = wod32;
1050 *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
1051 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
1053 wod16->hWave = wod32->hWave;
1054 wod16->lpFormat = (LPWAVEFORMATEX)((DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16));
1055 memcpy(wod16 + 1, wod32->lpFormat, sz);
1057 wod16->dwCallback = wod32->dwCallback;
1058 wod16->dwInstance = wod32->dwInstance;
1059 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
1060 wod16->dnDevNode = wod32->dnDevNode;
1062 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
1063 *lpdwUser = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
1065 ret = MMDRV_MAP_OKMEM;
1066 } else {
1067 ret = MMDRV_MAP_NOMEM;
1070 break;
1071 case WIDM_PREPARE:
1073 LPWAVEHDR wh32 = (LPWAVEHDR)*lpParam1;
1074 LPWAVEHDR wh16;
1075 LPVOID ptr = SEGPTR_ALLOC(sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
1077 if (ptr) {
1078 *(LPWAVEHDR*)ptr = wh32;
1079 wh16 = (LPWAVEHDR)((LPSTR)ptr + sizeof(LPWAVEHDR));
1080 wh16->lpData = (LPSTR)SEGPTR_GET(ptr) + sizeof(LPWAVEHDR) + sizeof(WAVEHDR);
1081 /* data will be copied on WODM_WRITE */
1082 wh16->dwBufferLength = wh32->dwBufferLength;
1083 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1084 wh16->dwUser = wh32->dwUser;
1085 wh16->dwFlags = wh32->dwFlags;
1086 wh16->dwLoops = wh32->dwLoops;
1087 /* FIXME: nothing on wh32->lpNext */
1088 /* could link the wh32->lpNext at this level for memory house keeping */
1089 wh32->lpNext = wh16; /* for reuse in unprepare and write */
1090 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1091 (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1092 wh32->dwBufferLength, (DWORD)wh32->lpData);
1093 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEHDR);
1094 *lpParam2 = sizeof(WAVEHDR);
1096 ret = MMDRV_MAP_OKMEM;
1097 } else {
1098 ret = MMDRV_MAP_NOMEM;
1101 break;
1102 case WIDM_ADDBUFFER:
1103 case WIDM_UNPREPARE:
1105 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
1106 LPWAVEHDR wh16 = wh32->lpNext;
1107 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1109 assert(*(LPWAVEHDR*)ptr == wh32);
1111 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1112 (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1113 wh32->dwBufferLength, (DWORD)wh32->lpData);
1115 if (wMsg == WIDM_ADDBUFFER)
1116 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
1118 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEHDR);
1119 *lpParam2 = sizeof(WAVEHDR);
1120 /* dwBufferLength can be reduced between prepare & write */
1121 if (wh32->dwBufferLength < wh16->dwBufferLength) {
1122 ERR("Size of buffer has been increased (%ld, %ld)\n",
1123 wh32->dwBufferLength, wh16->dwBufferLength);
1124 return MMDRV_MAP_MSGERROR;
1126 wh32->dwBufferLength = wh16->dwBufferLength;
1127 ret = MMDRV_MAP_OKMEM;
1129 break;
1130 case WIDM_GETDEVCAPS:
1132 LPWAVEINCAPSA wic32 = (LPWAVEINCAPSA)*lpParam1;
1133 LPSTR ptr = SEGPTR_ALLOC(sizeof(LPWAVEINCAPSA) + sizeof(WAVEINCAPS16));
1135 if (ptr) {
1136 *(LPWAVEINCAPSA*)ptr = wic32;
1137 ret = MMDRV_MAP_OKMEM;
1138 } else {
1139 ret = MMDRV_MAP_NOMEM;
1141 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEINCAPSA);
1142 *lpParam2 = sizeof(WAVEINCAPS16);
1144 break;
1145 case WIDM_GETPOS:
1147 LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1148 LPSTR ptr = SEGPTR_ALLOC(sizeof(LPMMTIME) + sizeof(MMTIME16));
1149 LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1151 if (ptr) {
1152 *(LPMMTIME*)ptr = mmt32;
1153 mmt16->wType = mmt32->wType;
1154 ret = MMDRV_MAP_OKMEM;
1155 } else {
1156 ret = MMDRV_MAP_NOMEM;
1158 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMMTIME);
1159 *lpParam2 = sizeof(MMTIME16);
1161 break;
1162 default:
1163 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1164 break;
1166 return ret;
1169 /**************************************************************************
1170 * MMDRV_WaveIn_UnMap32ATo16 [internal]
1172 static MMDRV_MapType MMDRV_WaveIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1174 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
1176 switch (wMsg) {
1177 case WIDM_CLOSE:
1178 case WIDM_GETNUMDEVS:
1179 case WIDM_RESET:
1180 case WIDM_START:
1181 case WIDM_STOP:
1182 ret = MMDRV_MAP_OK;
1183 break;
1185 case WIDM_OPEN:
1187 LPWAVEOPENDESC16 wod16 = MapSL(*lpParam1);
1188 LPSTR ptr = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1189 LPWAVEOPENDESC wod32 = *(LPWAVEOPENDESC*)ptr;
1191 wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1192 **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1194 if (!SEGPTR_FREE(ptr))
1195 FIXME("bad free line=%d\n", __LINE__);
1197 ret = MMDRV_MAP_OK;
1199 break;
1201 case WIDM_ADDBUFFER:
1202 case WIDM_PREPARE:
1203 case WIDM_UNPREPARE:
1205 LPWAVEHDR wh16 = MapSL(*lpParam1);
1206 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1207 LPWAVEHDR wh32 = *(LPWAVEHDR*)ptr;
1209 assert(wh32->lpNext == wh16);
1210 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1211 wh32->dwUser = wh16->dwUser;
1212 wh32->dwFlags = wh16->dwFlags;
1213 wh32->dwLoops = wh16->dwLoops;
1215 if (wMsg == WIDM_UNPREPARE) {
1216 if (!SEGPTR_FREE(ptr))
1217 FIXME("bad free line=%d\n", __LINE__);
1218 wh32->lpNext = 0;
1220 ret = MMDRV_MAP_OK;
1222 break;
1223 case WIDM_GETDEVCAPS:
1225 LPWAVEINCAPS16 wic16 = MapSL(*lpParam1);
1226 LPSTR ptr = (LPSTR)wic16 - sizeof(LPWAVEINCAPSA);
1227 LPWAVEINCAPSA wic32 = *(LPWAVEINCAPSA*)ptr;
1229 wic32->wMid = wic16->wMid;
1230 wic32->wPid = wic16->wPid;
1231 wic32->vDriverVersion = wic16->vDriverVersion;
1232 strcpy(wic32->szPname, wic16->szPname);
1233 wic32->dwFormats = wic16->dwFormats;
1234 wic32->wChannels = wic16->wChannels;
1235 if (!SEGPTR_FREE(ptr))
1236 FIXME("bad free line=%d\n", __LINE__);
1237 ret = MMDRV_MAP_OK;
1239 break;
1240 case WIDM_GETPOS:
1242 LPMMTIME16 mmt16 = MapSL(*lpParam1);
1243 LPSTR ptr = (LPSTR)mmt16 - sizeof(LPMMTIME);
1244 LPMMTIME mmt32 = *(LPMMTIME*)ptr;
1246 MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1248 if (!SEGPTR_FREE(ptr))
1249 FIXME("bad free line=%d\n", __LINE__);
1251 ret = MMDRV_MAP_OK;
1253 break;
1254 default:
1255 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1256 break;
1258 return ret;
1261 /**************************************************************************
1262 * MMDRV_WaveIn_Callback [internal]
1264 static void CALLBACK MMDRV_WaveIn_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1266 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
1268 switch (uMsg) {
1269 case WIM_OPEN:
1270 case WIM_CLOSE:
1271 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1272 break;
1273 case WIM_DATA:
1274 if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
1275 /* initial map is: 32 => 16 */
1276 LPWAVEHDR wh16 = MapSL(dwParam1);
1277 LPWAVEHDR wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1279 dwParam1 = (DWORD)wh32;
1280 wh32->dwFlags = wh16->dwFlags;
1281 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1282 } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
1283 /* initial map is: 16 => 32 */
1284 LPWAVEHDR wh32 = (LPWAVEHDR)(dwParam1);
1285 SEGPTR segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1286 LPWAVEHDR wh16 = MapSL(segwh16);
1288 dwParam1 = (DWORD)segwh16;
1289 wh16->dwFlags = wh32->dwFlags;
1290 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1292 /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1293 break;
1294 default:
1295 ERR("Unknown msg %u\n", uMsg);
1298 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1301 /* =================================
1302 * W A V E O U T M A P P E R S
1303 * ================================= */
1305 /**************************************************************************
1306 * MMDRV_WaveOut_Map16To32A [internal]
1308 static MMDRV_MapType MMDRV_WaveOut_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1310 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
1312 switch (wMsg) {
1313 /* nothing to do */
1314 case WODM_BREAKLOOP:
1315 case WODM_CLOSE:
1316 case WODM_GETNUMDEVS:
1317 case WODM_PAUSE:
1318 case WODM_RESET:
1319 case WODM_RESTART:
1320 case WODM_SETPITCH:
1321 case WODM_SETPLAYBACKRATE:
1322 case WODM_SETVOLUME:
1323 ret = MMDRV_MAP_OK;
1324 break;
1326 case WODM_GETPITCH:
1327 case WODM_GETPLAYBACKRATE:
1328 case WODM_GETVOLUME:
1329 case WODM_OPEN:
1330 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
1331 break;
1333 case WODM_GETDEVCAPS:
1335 LPWAVEOUTCAPSA woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSA));
1336 LPWAVEOUTCAPS16 woc16 = MapSL(*lpParam1);
1338 if (woc32) {
1339 *(LPWAVEOUTCAPS16*)woc32 = woc16;
1340 woc32 = (LPWAVEOUTCAPSA)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16));
1341 *lpParam1 = (DWORD)woc32;
1342 *lpParam2 = sizeof(WAVEOUTCAPSA);
1344 ret = MMDRV_MAP_OKMEM;
1345 } else {
1346 ret = MMDRV_MAP_NOMEM;
1349 break;
1350 case WODM_GETPOS:
1352 LPMMTIME mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
1353 LPMMTIME16 mmt16 = MapSL(*lpParam1);
1355 if (mmt32) {
1356 *(LPMMTIME16*)mmt32 = mmt16;
1357 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
1359 mmt32->wType = mmt16->wType;
1360 *lpParam1 = (DWORD)mmt32;
1361 *lpParam2 = sizeof(MMTIME);
1363 ret = MMDRV_MAP_OKMEM;
1364 } else {
1365 ret = MMDRV_MAP_NOMEM;
1368 break;
1369 case WODM_PREPARE:
1371 LPWAVEHDR wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
1372 LPWAVEHDR wh16 = MapSL(*lpParam1);
1374 if (wh32) {
1375 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
1376 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
1377 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
1378 wh32->dwBufferLength = wh16->dwBufferLength;
1379 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1380 wh32->dwUser = wh16->dwUser;
1381 wh32->dwFlags = wh16->dwFlags;
1382 wh32->dwLoops = wh16->dwLoops;
1383 /* FIXME: nothing on wh32->lpNext */
1384 /* could link the wh32->lpNext at this level for memory house keeping */
1385 wh16->lpNext = wh32; /* for reuse in unprepare and write */
1386 *lpParam1 = (DWORD)wh32;
1387 *lpParam2 = sizeof(WAVEHDR);
1389 ret = MMDRV_MAP_OKMEM;
1390 } else {
1391 ret = MMDRV_MAP_NOMEM;
1394 break;
1395 case WODM_UNPREPARE:
1396 case WODM_WRITE:
1398 LPWAVEHDR wh16 = MapSL(*lpParam1);
1399 LPWAVEHDR wh32 = (LPWAVEHDR)wh16->lpNext;
1401 *lpParam1 = (DWORD)wh32;
1402 *lpParam2 = sizeof(WAVEHDR);
1403 /* dwBufferLength can be reduced between prepare & write */
1404 if (wh32->dwBufferLength < wh16->dwBufferLength) {
1405 ERR("Size of buffer has been increased (%ld, %ld)\n",
1406 wh32->dwBufferLength, wh16->dwBufferLength);
1407 return MMDRV_MAP_MSGERROR;
1409 wh32->dwBufferLength = wh16->dwBufferLength;
1410 ret = MMDRV_MAP_OKMEM;
1412 break;
1413 default:
1414 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1415 break;
1417 return ret;
1420 /**************************************************************************
1421 * MMDRV_WaveOut_UnMap16To32A [internal]
1423 static MMDRV_MapType MMDRV_WaveOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1425 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
1427 switch (wMsg) {
1428 /* nothing to do */
1429 case WODM_BREAKLOOP:
1430 case WODM_CLOSE:
1431 case WODM_GETNUMDEVS:
1432 case WODM_PAUSE:
1433 case WODM_RESET:
1434 case WODM_RESTART:
1435 case WODM_SETPITCH:
1436 case WODM_SETPLAYBACKRATE:
1437 case WODM_SETVOLUME:
1438 ret = MMDRV_MAP_OK;
1439 break;
1441 case WODM_GETPITCH:
1442 case WODM_GETPLAYBACKRATE:
1443 case WODM_GETVOLUME:
1444 case WODM_OPEN:
1445 FIXME("Shouldn't be used: those 16 bit functions use the 32 bit interface\n");
1446 break;
1448 case WODM_GETDEVCAPS:
1450 LPWAVEOUTCAPSA woc32 = (LPWAVEOUTCAPSA)(*lpParam1);
1451 LPWAVEOUTCAPS16 woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1453 woc16->wMid = woc32->wMid;
1454 woc16->wPid = woc32->wPid;
1455 woc16->vDriverVersion = woc32->vDriverVersion;
1456 strcpy(woc16->szPname, woc32->szPname);
1457 woc16->dwFormats = woc32->dwFormats;
1458 woc16->wChannels = woc32->wChannels;
1459 woc16->dwSupport = woc32->dwSupport;
1460 HeapFree(GetProcessHeap(), 0, (LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1461 ret = MMDRV_MAP_OK;
1463 break;
1464 case WODM_GETPOS:
1466 LPMMTIME mmt32 = (LPMMTIME)(*lpParam1);
1467 LPMMTIME16 mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
1469 MMSYSTEM_MMTIME32to16(mmt16, mmt32);
1470 HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
1471 ret = MMDRV_MAP_OK;
1473 break;
1474 case WODM_PREPARE:
1475 case WODM_UNPREPARE:
1476 case WODM_WRITE:
1478 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
1479 LPWAVEHDR wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
1481 assert(wh16->lpNext == wh32);
1482 wh16->dwBufferLength = wh32->dwBufferLength;
1483 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1484 wh16->dwUser = wh32->dwUser;
1485 wh16->dwFlags = wh32->dwFlags;
1486 wh16->dwLoops = wh32->dwLoops;
1488 if (wMsg == WODM_UNPREPARE) {
1489 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
1490 wh16->lpNext = 0;
1492 ret = MMDRV_MAP_OK;
1494 break;
1495 default:
1496 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1497 break;
1499 return ret;
1502 /**************************************************************************
1503 * MMDRV_WaveOut_Map32ATo16 [internal]
1505 static MMDRV_MapType MMDRV_WaveOut_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1507 MMDRV_MapType ret;
1509 switch (wMsg) {
1510 /* nothing to do */
1511 case WODM_BREAKLOOP:
1512 case WODM_CLOSE:
1513 case WODM_GETNUMDEVS:
1514 case WODM_PAUSE:
1515 case WODM_RESET:
1516 case WODM_RESTART:
1517 case WODM_SETPITCH:
1518 case WODM_SETPLAYBACKRATE:
1519 case WODM_SETVOLUME:
1520 ret = MMDRV_MAP_OK;
1521 break;
1523 case WODM_GETDEVCAPS:
1525 LPWAVEOUTCAPSA woc32 = (LPWAVEOUTCAPSA)*lpParam1;
1526 LPSTR ptr = SEGPTR_ALLOC(sizeof(LPWAVEOUTCAPSA) + sizeof(WAVEOUTCAPS16));
1528 if (ptr) {
1529 *(LPWAVEOUTCAPSA*)ptr = woc32;
1530 ret = MMDRV_MAP_OKMEM;
1531 } else {
1532 ret = MMDRV_MAP_NOMEM;
1534 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOUTCAPSA);
1535 *lpParam2 = sizeof(WAVEOUTCAPS16);
1537 break;
1538 case WODM_GETPITCH:
1539 FIXME("NIY: no conversion yet\n");
1540 ret = MMDRV_MAP_MSGERROR;
1541 break;
1542 case WODM_GETPLAYBACKRATE:
1543 FIXME("NIY: no conversion yet\n");
1544 ret = MMDRV_MAP_MSGERROR;
1545 break;
1546 case WODM_GETPOS:
1548 LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1549 LPSTR ptr = SEGPTR_ALLOC(sizeof(LPMMTIME) + sizeof(MMTIME16));
1550 LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1552 if (ptr) {
1553 *(LPMMTIME*)ptr = mmt32;
1554 mmt16->wType = mmt32->wType;
1555 ret = MMDRV_MAP_OKMEM;
1556 } else {
1557 ret = MMDRV_MAP_NOMEM;
1559 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMMTIME);
1560 *lpParam2 = sizeof(MMTIME16);
1562 break;
1563 case WODM_GETVOLUME:
1564 FIXME("NIY: no conversion yet\n");
1565 ret = MMDRV_MAP_MSGERROR;
1566 break;
1567 case WODM_OPEN:
1569 LPWAVEOPENDESC wod32 = (LPWAVEOPENDESC)*lpParam1;
1570 int sz = sizeof(WAVEFORMATEX);
1571 LPVOID ptr;
1572 LPWAVEOPENDESC16 wod16;
1574 /* allocated data are mapped as follows:
1575 LPWAVEOPENDESC ptr to orig lParam1
1576 DWORD orig dwUser, which is a pointer to DWORD:driver dwInstance
1577 DWORD dwUser passed to driver
1578 WAVEOPENDESC16 wod16: openDesc passed to driver
1579 WAVEFORMATEX openDesc->lpFormat passed to driver
1580 xxx extra bytes to WAVEFORMATEX
1582 if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1583 TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag);
1584 sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize;
1587 ptr = SEGPTR_ALLOC(sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
1589 if (ptr) {
1590 *(LPWAVEOPENDESC*)ptr = wod32;
1591 *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
1592 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
1594 wod16->hWave = wod32->hWave;
1595 wod16->lpFormat = (LPWAVEFORMATEX)((DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16));
1596 memcpy(wod16 + 1, wod32->lpFormat, sz);
1598 wod16->dwCallback = wod32->dwCallback;
1599 wod16->dwInstance = wod32->dwInstance;
1600 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
1601 wod16->dnDevNode = wod32->dnDevNode;
1603 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
1604 *lpdwUser = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
1606 ret = MMDRV_MAP_OKMEM;
1607 } else {
1608 ret = MMDRV_MAP_NOMEM;
1611 break;
1612 case WODM_PREPARE:
1614 LPWAVEHDR wh32 = (LPWAVEHDR)*lpParam1;
1615 LPWAVEHDR wh16;
1616 LPVOID ptr = SEGPTR_ALLOC(sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
1618 if (ptr) {
1619 *(LPWAVEHDR*)ptr = wh32;
1620 wh16 = (LPWAVEHDR)((LPSTR)ptr + sizeof(LPWAVEHDR));
1621 wh16->lpData = (LPSTR)SEGPTR_GET(ptr) + sizeof(LPWAVEHDR) + sizeof(WAVEHDR);
1622 /* data will be copied on WODM_WRITE */
1623 wh16->dwBufferLength = wh32->dwBufferLength;
1624 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1625 wh16->dwUser = wh32->dwUser;
1626 wh16->dwFlags = wh32->dwFlags;
1627 wh16->dwLoops = wh32->dwLoops;
1628 /* FIXME: nothing on wh32->lpNext */
1629 /* could link the wh32->lpNext at this level for memory house keeping */
1630 wh32->lpNext = wh16; /* for reuse in unprepare and write */
1631 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1632 (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1633 wh32->dwBufferLength, (DWORD)wh32->lpData);
1634 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEHDR);
1635 *lpParam2 = sizeof(WAVEHDR);
1637 ret = MMDRV_MAP_OKMEM;
1638 } else {
1639 ret = MMDRV_MAP_NOMEM;
1642 break;
1643 case WODM_UNPREPARE:
1644 case WODM_WRITE:
1646 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
1647 LPWAVEHDR wh16 = wh32->lpNext;
1648 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1650 assert(*(LPWAVEHDR*)ptr == wh32);
1652 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1653 (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1654 wh32->dwBufferLength, (DWORD)wh32->lpData);
1656 if (wMsg == WODM_WRITE)
1657 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
1659 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEHDR);
1660 *lpParam2 = sizeof(WAVEHDR);
1661 /* dwBufferLength can be reduced between prepare & write */
1662 if (wh16->dwBufferLength < wh32->dwBufferLength) {
1663 ERR("Size of buffer has been increased (%ld, %ld)\n",
1664 wh16->dwBufferLength, wh32->dwBufferLength);
1665 return MMDRV_MAP_MSGERROR;
1667 wh16->dwBufferLength = wh32->dwBufferLength;
1668 ret = MMDRV_MAP_OKMEM;
1670 break;
1671 default:
1672 FIXME("NIY: no conversion yet\n");
1673 ret = MMDRV_MAP_MSGERROR;
1674 break;
1676 return ret;
1679 /**************************************************************************
1680 * MMDRV_WaveOut_UnMap32ATo16 [internal]
1682 static MMDRV_MapType MMDRV_WaveOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1684 MMDRV_MapType ret;
1686 switch (wMsg) {
1687 /* nothing to do */
1688 case WODM_BREAKLOOP:
1689 case WODM_CLOSE:
1690 case WODM_GETNUMDEVS:
1691 case WODM_PAUSE:
1692 case WODM_RESET:
1693 case WODM_RESTART:
1694 case WODM_SETPITCH:
1695 case WODM_SETPLAYBACKRATE:
1696 case WODM_SETVOLUME:
1697 ret = MMDRV_MAP_OK;
1698 break;
1700 case WODM_GETDEVCAPS:
1702 LPWAVEOUTCAPS16 woc16 = MapSL(*lpParam1);
1703 LPSTR ptr = (LPSTR)woc16 - sizeof(LPWAVEOUTCAPSA);
1704 LPWAVEOUTCAPSA woc32 = *(LPWAVEOUTCAPSA*)ptr;
1706 woc32->wMid = woc16->wMid;
1707 woc32->wPid = woc16->wPid;
1708 woc32->vDriverVersion = woc16->vDriverVersion;
1709 strcpy(woc32->szPname, woc16->szPname);
1710 woc32->dwFormats = woc16->dwFormats;
1711 woc32->wChannels = woc16->wChannels;
1712 woc32->dwSupport = woc16->dwSupport;
1713 if (!SEGPTR_FREE(ptr))
1714 FIXME("bad free line=%d\n", __LINE__);
1715 ret = MMDRV_MAP_OK;
1717 break;
1718 case WODM_GETPITCH:
1719 FIXME("NIY: no conversion yet\n");
1720 ret = MMDRV_MAP_MSGERROR;
1721 break;
1722 case WODM_GETPLAYBACKRATE:
1723 FIXME("NIY: no conversion yet\n");
1724 ret = MMDRV_MAP_MSGERROR;
1725 break;
1726 case WODM_GETPOS:
1728 LPMMTIME16 mmt16 = MapSL(*lpParam1);
1729 LPSTR ptr = (LPSTR)mmt16 - sizeof(LPMMTIME);
1730 LPMMTIME mmt32 = *(LPMMTIME*)ptr;
1732 MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1734 if (!SEGPTR_FREE(ptr))
1735 FIXME("bad free line=%d\n", __LINE__);
1737 ret = MMDRV_MAP_OK;
1739 break;
1740 case WODM_OPEN:
1742 LPWAVEOPENDESC16 wod16 = MapSL(*lpParam1);
1743 LPSTR ptr = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1744 LPWAVEOPENDESC wod32 = *(LPWAVEOPENDESC*)ptr;
1746 wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1747 **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1749 if (!SEGPTR_FREE(ptr))
1750 FIXME("bad free line=%d\n", __LINE__);
1752 ret = MMDRV_MAP_OK;
1754 break;
1755 case WODM_PREPARE:
1756 case WODM_UNPREPARE:
1757 case WODM_WRITE:
1759 LPWAVEHDR wh16 = MapSL(*lpParam1);
1760 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1761 LPWAVEHDR wh32 = *(LPWAVEHDR*)ptr;
1763 assert(wh32->lpNext == wh16);
1764 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1765 wh32->dwUser = wh16->dwUser;
1766 wh32->dwFlags = wh16->dwFlags;
1767 wh32->dwLoops = wh16->dwLoops;
1769 if (wMsg == WODM_UNPREPARE) {
1770 if (!SEGPTR_FREE(ptr))
1771 FIXME("bad free line=%d\n", __LINE__);
1772 wh32->lpNext = 0;
1774 ret = MMDRV_MAP_OK;
1776 break;
1777 case WODM_GETVOLUME:
1778 FIXME("NIY: no conversion yet\n");
1779 ret = MMDRV_MAP_MSGERROR;
1780 break;
1781 default:
1782 FIXME("NIY: no conversion yet\n");
1783 ret = MMDRV_MAP_MSGERROR;
1784 break;
1786 return ret;
1789 /**************************************************************************
1790 * MMDRV_WaveOut_Callback [internal]
1792 static void CALLBACK MMDRV_WaveOut_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1794 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
1796 switch (uMsg) {
1797 case WOM_OPEN:
1798 case WOM_CLOSE:
1799 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1800 break;
1801 case WOM_DONE:
1802 if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
1803 /* initial map is: 32 => 16 */
1804 LPWAVEHDR wh16 = MapSL(dwParam1);
1805 LPWAVEHDR wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1807 dwParam1 = (DWORD)wh32;
1808 wh32->dwFlags = wh16->dwFlags;
1809 } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
1810 /* initial map is: 16 => 32 */
1811 LPWAVEHDR wh32 = (LPWAVEHDR)(dwParam1);
1812 SEGPTR segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1813 LPWAVEHDR wh16 = MapSL(segwh16);
1815 dwParam1 = (DWORD)segwh16;
1816 wh16->dwFlags = wh32->dwFlags;
1818 /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1819 break;
1820 default:
1821 ERR("Unknown msg %u\n", uMsg);
1824 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1827 #define A(_x,_y) {#_y, _x, \
1828 MMDRV_##_y##_Map16To32A, MMDRV_##_y##_UnMap16To32A, \
1829 MMDRV_##_y##_Map32ATo16, MMDRV_##_y##_UnMap32ATo16, \
1830 MMDRV_##_y##_Callback, 0, NULL, -1}
1832 /* Note: the indices of this array must match the definitions
1833 * of the MMDRV_???? manifest constants
1835 static WINE_LLTYPE llTypes[MMDRV_MAX] = {
1836 A(TRUE, Aux),
1837 A(FALSE, Mixer),
1838 A(TRUE, MidiIn),
1839 A(TRUE, MidiOut),
1840 A(TRUE, WaveIn),
1841 A(TRUE, WaveOut),
1843 #undef A
1845 /**************************************************************************
1846 * MMDRV_GetNum [internal]
1848 UINT MMDRV_GetNum(UINT type)
1850 assert(type < MMDRV_MAX);
1851 return llTypes[type].wMaxId;
1854 /**************************************************************************
1855 * WINE_Message [internal]
1857 DWORD MMDRV_Message(LPWINE_MLD mld, WORD wMsg, DWORD dwParam1,
1858 DWORD dwParam2, BOOL bFrom32)
1860 LPWINE_MM_DRIVER lpDrv;
1861 DWORD ret;
1862 WINE_MM_DRIVER_PART* part;
1863 WINE_LLTYPE* llType = &llTypes[mld->type];
1864 MMDRV_MapType map;
1865 int devID;
1867 TRACE("(%s %u %u 0x%08lx 0x%08lx 0x%08lx %c)!\n",
1868 llTypes[mld->type].name, mld->uDeviceID, wMsg,
1869 mld->dwDriverInstance, dwParam1, dwParam2, bFrom32?'Y':'N');
1871 if (mld->uDeviceID == (UINT16)-1) {
1872 if (!llType->bSupportMapper) {
1873 WARN("uDev=-1 requested on non-mappable ll type %s\n",
1874 llTypes[mld->type].name);
1875 return MMSYSERR_BADDEVICEID;
1877 devID = -1;
1878 } else {
1879 if (mld->uDeviceID >= llType->wMaxId) {
1880 WARN("uDev(%u) requested >= max (%d)\n", mld->uDeviceID, llType->wMaxId);
1881 return MMSYSERR_BADDEVICEID;
1883 devID = mld->uDeviceID;
1886 lpDrv = &MMDrvs[mld->mmdIndex];
1887 part = &lpDrv->parts[mld->type];
1889 #if 0
1890 /* some sanity checks */
1891 if (!(part->nIDMin <= devID))
1892 ERR("!(part->nIDMin(%d) <= devID(%d))\n", part->nIDMin, devID);
1893 if (!(devID < part->nIDMax))
1894 ERR("!(devID(%d) < part->nIDMax(%d))\n", devID, part->nIDMax);
1895 #endif
1897 if (lpDrv->bIs32) {
1898 assert(part->u.fnMessage32);
1900 if (bFrom32) {
1901 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
1902 mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1903 ret = part->u.fnMessage32(mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1904 TRACE("=> %lu\n", ret);
1905 } else {
1906 map = llType->Map16To32A(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
1907 switch (map) {
1908 case MMDRV_MAP_NOMEM:
1909 ret = MMSYSERR_NOMEM;
1910 break;
1911 case MMDRV_MAP_MSGERROR:
1912 FIXME("NIY: no conversion yet 16->32 (%u)\n", wMsg);
1913 ret = MMSYSERR_ERROR;
1914 break;
1915 case MMDRV_MAP_OK:
1916 case MMDRV_MAP_OKMEM:
1917 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
1918 mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1919 ret = part->u.fnMessage32(mld->uDeviceID, wMsg, mld->dwDriverInstance,
1920 dwParam1, dwParam2);
1921 TRACE("=> %lu\n", ret);
1922 if (map == MMDRV_MAP_OKMEM)
1923 llType->UnMap16To32A(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
1924 break;
1925 default:
1926 case MMDRV_MAP_PASS:
1927 FIXME("NIY: pass used ?\n");
1928 ret = MMSYSERR_NOTSUPPORTED;
1929 break;
1932 } else {
1933 assert(part->u.fnMessage16);
1935 if (bFrom32) {
1936 map = llType->Map32ATo16(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
1937 switch (map) {
1938 case MMDRV_MAP_NOMEM:
1939 ret = MMSYSERR_NOMEM;
1940 break;
1941 case MMDRV_MAP_MSGERROR:
1942 FIXME("NIY: no conversion yet 32->16 (%u)\n", wMsg);
1943 ret = MMSYSERR_ERROR;
1944 break;
1945 case MMDRV_MAP_OK:
1946 case MMDRV_MAP_OKMEM:
1947 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
1948 mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1949 ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16, mld->uDeviceID,
1950 wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1951 TRACE("=> %lu\n", ret);
1952 if (map == MMDRV_MAP_OKMEM)
1953 llType->UnMap32ATo16(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
1954 break;
1955 default:
1956 case MMDRV_MAP_PASS:
1957 FIXME("NIY: pass used ?\n");
1958 ret = MMSYSERR_NOTSUPPORTED;
1959 break;
1961 } else {
1962 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
1963 mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1964 ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16, mld->uDeviceID,
1965 wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1966 TRACE("=> %lu\n", ret);
1969 return ret;
1972 /**************************************************************************
1973 * MMDRV_Alloc [internal]
1975 LPWINE_MLD MMDRV_Alloc(UINT size, UINT type, LPHANDLE hndl, DWORD* dwFlags,
1976 DWORD* dwCallback, DWORD* dwInstance, BOOL bFrom32)
1978 LPWINE_MLD mld;
1980 if ((*hndl = USER_HEAP_ALLOC(size)) == 0)
1981 return NULL;
1983 mld = (LPWINE_MLD) USER_HEAP_LIN_ADDR(*hndl);
1984 if (!mld) return NULL;
1985 mld->type = type;
1986 if ((UINT)*hndl < MMDRV_GetNum(type) || HIWORD(*hndl) != 0) {
1987 /* FIXME: those conditions must be fulfilled so that:
1988 * - we can distinguish between device IDs and handles
1989 * - we can use handles as 16 or 32 bit entities
1991 ERR("Shouldn't happen. Bad allocation scheme\n");
1994 mld->bFrom32 = bFrom32;
1995 mld->dwFlags = HIWORD(*dwFlags);
1996 mld->dwCallback = *dwCallback;
1997 mld->dwClientInstance = *dwInstance;
1999 *dwFlags = LOWORD(*dwFlags) | CALLBACK_FUNCTION;
2000 *dwCallback = (DWORD)llTypes[type].Callback;
2001 *dwInstance = (DWORD)mld; /* FIXME: wouldn't some 16 bit drivers only use the loword ? */
2003 return mld;
2006 /**************************************************************************
2007 * MMDRV_Free [internal]
2009 void MMDRV_Free(HANDLE hndl, LPWINE_MLD mld)
2011 USER_HEAP_FREE(hndl);
2014 /**************************************************************************
2015 * MMDRV_Open [internal]
2017 DWORD MMDRV_Open(LPWINE_MLD mld, UINT wMsg, DWORD dwParam1, DWORD dwFlags)
2019 DWORD dwRet = MMSYSERR_BADDEVICEID;
2020 DWORD dwInstance;
2021 WINE_LLTYPE* llType = &llTypes[mld->type];
2023 mld->dwDriverInstance = (DWORD)&dwInstance;
2025 if (mld->uDeviceID == (UINT)-1 || mld->uDeviceID == (UINT16)-1) {
2026 TRACE("MAPPER mode requested !\n");
2027 /* check if mapper is supported by type */
2028 if (llType->bSupportMapper) {
2029 if (llType->nMapper == -1) {
2030 /* no driver for mapper has been loaded, try a dumb implementation */
2031 TRACE("No mapper loaded, doing it by hand\n");
2032 for (mld->uDeviceID = 0; mld->uDeviceID < llType->wMaxId; mld->uDeviceID++) {
2033 if ((dwRet = MMDRV_Open(mld, wMsg, dwParam1, dwFlags)) == MMSYSERR_NOERROR) {
2034 /* to share this function epilog */
2035 dwInstance = mld->dwDriverInstance;
2036 break;
2039 } else {
2040 mld->uDeviceID = (UINT16)-1;
2041 mld->mmdIndex = llType->lpMlds[-1].mmdIndex;
2042 TRACE("Setting mmdIndex to %u\n", mld->mmdIndex);
2043 dwRet = MMDRV_Message(mld, wMsg, dwParam1, dwFlags, TRUE);
2046 } else {
2047 if (mld->uDeviceID < llType->wMaxId) {
2048 mld->mmdIndex = llType->lpMlds[mld->uDeviceID].mmdIndex;
2049 TRACE("Setting mmdIndex to %u\n", mld->mmdIndex);
2050 dwRet = MMDRV_Message(mld, wMsg, dwParam1, dwFlags, TRUE);
2053 if (dwRet == MMSYSERR_NOERROR)
2054 mld->dwDriverInstance = dwInstance;
2055 return dwRet;
2058 /**************************************************************************
2059 * MMDRV_Close [internal]
2061 DWORD MMDRV_Close(LPWINE_MLD mld, UINT wMsg)
2063 return MMDRV_Message(mld, wMsg, 0L, 0L, TRUE);
2066 /**************************************************************************
2067 * MMDRV_GetByID [internal]
2069 LPWINE_MLD MMDRV_GetByID(UINT uDevID, UINT type)
2071 if (uDevID < llTypes[type].wMaxId)
2072 return &llTypes[type].lpMlds[uDevID];
2073 if ((uDevID == (UINT16)-1 || uDevID == (UINT)-1) && llTypes[type].nMapper != -1)
2074 return &llTypes[type].lpMlds[-1];
2075 return NULL;
2078 /**************************************************************************
2079 * MMDRV_Get [internal]
2081 LPWINE_MLD MMDRV_Get(HANDLE hndl, UINT type, BOOL bCanBeID)
2083 LPWINE_MLD mld = NULL;
2085 assert(type < MMDRV_MAX);
2087 if ((UINT)hndl >= llTypes[type].wMaxId) {
2088 mld = (LPWINE_MLD)USER_HEAP_LIN_ADDR(hndl);
2090 if (!IsBadWritePtr(mld, sizeof(*mld)) && mld->type != type) mld = NULL;
2092 if (mld == NULL && bCanBeID) {
2093 mld = MMDRV_GetByID((UINT)hndl, type);
2095 return mld;
2098 /**************************************************************************
2099 * MMDRV_GetRelated [internal]
2101 LPWINE_MLD MMDRV_GetRelated(HANDLE hndl, UINT srcType,
2102 BOOL bSrcCanBeID, UINT dstType)
2104 LPWINE_MLD mld;
2106 if ((mld = MMDRV_Get(hndl, srcType, bSrcCanBeID)) != NULL) {
2107 WINE_MM_DRIVER_PART* part = &MMDrvs[mld->mmdIndex].parts[dstType];
2108 if (part->nIDMin < part->nIDMax)
2109 return MMDRV_GetByID(part->nIDMin, dstType);
2111 return NULL;
2114 /**************************************************************************
2115 * MMDRV_PhysicalFeatures [internal]
2117 UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD dwParam1,
2118 DWORD dwParam2)
2120 WINE_MM_DRIVER* lpDrv = &MMDrvs[mld->mmdIndex];
2122 TRACE("(%p, %04x, %08lx, %08lx)\n", mld, uMsg, dwParam1, dwParam2);
2124 /* all those function calls are undocumented */
2125 switch (uMsg) {
2126 case 0x801: /* DRV_QUERYDRVENTRY */
2127 lstrcpynA((LPSTR)dwParam1, lpDrv->name, LOWORD(dwParam2));
2128 break;
2129 case 0x802: /* DRV_QUERYDEVNODE */
2130 *(LPDWORD)dwParam1 = 0L; /* should be DevNode */
2131 break;
2132 case 0x803: /* DRV_QUERYNAME */
2133 WARN("NIY 0x803\n");
2134 break;
2135 case 0x804: /* DRV_QUERYDRIVERIDS */
2136 WARN("NIY call VxD\n");
2137 /* should call VxD MMDEVLDR with (DevNode, dwParam1 and dwParam2) as pmts
2138 * dwParam1 is buffer and dwParam2 is sizeof buffer
2139 * I don't know where the result is stored though
2141 break;
2142 case 0x805: /* DRV_QUERYMAPPABLE */
2143 return (lpDrv->bIsMapper) ? 2 : 0;
2145 case 0x810: /* Wine-specific: Retrieve DirectSound interface */
2146 return MMDRV_Message(mld, uMsg, dwParam1, dwParam2, TRUE);
2148 default:
2149 WARN("Unknown call %04x\n", uMsg);
2150 return MMSYSERR_INVALPARAM;
2152 return 0L;
2155 /**************************************************************************
2156 * MMDRV_InitPerType [internal]
2158 static BOOL MMDRV_InitPerType(LPWINE_MM_DRIVER lpDrv, UINT num,
2159 UINT type, UINT wMsg)
2161 WINE_MM_DRIVER_PART* part = &lpDrv->parts[type];
2162 DWORD ret;
2163 UINT count = 0;
2164 int i, k;
2166 part->nIDMin = part->nIDMax = 0;
2168 /* for DRVM_INIT and DRVM_ENABLE, dwParam2 should be PnP node */
2169 /* the DRVM_ENABLE is only required when the PnP node is non zero */
2171 if (lpDrv->bIs32 && part->u.fnMessage32) {
2172 ret = part->u.fnMessage32(0, DRVM_INIT, 0L, 0L, 0L);
2173 TRACE("DRVM_INIT => %08lx\n", ret);
2174 #if 0
2175 ret = part->u.fnMessage32(0, DRVM_ENABLE, 0L, 0L, 0L);
2176 TRACE("DRVM_ENABLE => %08lx\n", ret);
2177 #endif
2178 count = part->u.fnMessage32(0, wMsg, 0L, 0L, 0L);
2181 if (!lpDrv->bIs32 && part->u.fnMessage16) {
2182 ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16,
2183 0, DRVM_INIT, 0L, 0L, 0L);
2184 TRACE("DRVM_INIT => %08lx\n", ret);
2185 #if 0
2186 ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16,
2187 0, DRVM_ENABLE, 0L, 0L, 0L);
2188 TRACE("DRVM_ENABLE => %08lx\n", ret);
2189 #endif
2190 count = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16,
2191 0, wMsg, 0L, 0L, 0L);
2194 TRACE("Got %u dev for (%s:%s)\n", count, lpDrv->name, llTypes[type].name);
2195 if (count == 0)
2196 return FALSE;
2198 /* got some drivers */
2199 if (lpDrv->bIsMapper) {
2200 if (llTypes[type].nMapper != -1)
2201 ERR("Two mappers for type %s (%d, %s)\n",
2202 llTypes[type].name, llTypes[type].nMapper, lpDrv->name);
2203 if (count > 1)
2204 ERR("Strange: mapper with %d > 1 devices\n", count);
2205 llTypes[type].nMapper = num;
2206 } else {
2207 part->nIDMin = llTypes[type].wMaxId;
2208 llTypes[type].wMaxId += count;
2209 part->nIDMax = llTypes[type].wMaxId;
2211 TRACE("Setting min=%d max=%d (ttop=%d) for (%s:%s)\n",
2212 part->nIDMin, part->nIDMax, llTypes[type].wMaxId,
2213 lpDrv->name, llTypes[type].name);
2214 /* realloc translation table */
2215 llTypes[type].lpMlds = (LPWINE_MLD)
2216 HeapReAlloc(GetProcessHeap(), 0, (llTypes[type].lpMlds) ? llTypes[type].lpMlds - 1 : NULL,
2217 sizeof(WINE_MLD) * (llTypes[type].wMaxId + 1)) + 1;
2218 /* re-build the translation table */
2219 if (llTypes[type].nMapper != -1) {
2220 TRACE("%s:Trans[%d] -> %s\n", llTypes[type].name, -1, MMDrvs[llTypes[type].nMapper].name);
2221 llTypes[type].lpMlds[-1].uDeviceID = (UINT16)-1;
2222 llTypes[type].lpMlds[-1].type = type;
2223 llTypes[type].lpMlds[-1].mmdIndex = llTypes[type].nMapper;
2224 llTypes[type].lpMlds[-1].dwDriverInstance = 0;
2226 for (i = k = 0; i <= num; i++) {
2227 while (MMDrvs[i].parts[type].nIDMin <= k && k < MMDrvs[i].parts[type].nIDMax) {
2228 TRACE("%s:Trans[%d] -> %s\n", llTypes[type].name, k, MMDrvs[i].name);
2229 llTypes[type].lpMlds[k].uDeviceID = k;
2230 llTypes[type].lpMlds[k].type = type;
2231 llTypes[type].lpMlds[k].mmdIndex = i;
2232 llTypes[type].lpMlds[k].dwDriverInstance = 0;
2233 k++;
2236 return TRUE;
2239 /**************************************************************************
2240 * MMDRV_Install [internal]
2242 static BOOL MMDRV_Install(LPCSTR name, int num, BOOL bIsMapper)
2244 int count = 0;
2245 char buffer[128];
2246 LPWINE_MM_DRIVER lpDrv = &MMDrvs[num];
2247 LPWINE_DRIVER d;
2249 TRACE("('%s');\n", name);
2251 memset(lpDrv, 0, sizeof(*lpDrv));
2253 if (!(lpDrv->hDriver = OpenDriverA(name, 0, 0))) {
2254 WARN("Couldn't open driver '%s'\n", name);
2255 return FALSE;
2258 d = DRIVER_FindFromHDrvr(lpDrv->hDriver);
2259 lpDrv->bIs32 = (d->dwFlags & WINE_GDF_16BIT) ? FALSE : TRUE;
2261 /* Then look for xxxMessage functions */
2262 #define AA(_h,_w,_x,_y,_z) \
2263 func = (WINEMM_msgFunc##_y) _z ((_h), #_x); \
2264 if (func != NULL) \
2265 { lpDrv->parts[_w].u.fnMessage##_y = func; count++; \
2266 TRACE("Got %d bit func '%s'\n", _y, #_x); }
2268 if (lpDrv->bIs32) {
2269 WINEMM_msgFunc32 func;
2271 if (d->d.d32.hModule) {
2272 #define A(_x,_y) AA(d->d.d32.hModule,_x,_y,32,GetProcAddress)
2273 A(MMDRV_AUX, auxMessage);
2274 A(MMDRV_MIXER, mixMessage);
2275 A(MMDRV_MIDIIN, midMessage);
2276 A(MMDRV_MIDIOUT, modMessage);
2277 A(MMDRV_WAVEIN, widMessage);
2278 A(MMDRV_WAVEOUT, wodMessage);
2279 #undef A
2281 } else {
2282 WINEMM_msgFunc16 func;
2285 * DESCRIPTION 'wave,aux,mixer:Creative Labs Sound Blaster 16 Driver'
2286 * The beginning of the module description indicates the driver supports
2287 * waveform, auxiliary, and mixer devices. Use one of the following
2288 * device-type names, followed by a colon (:) to indicate the type of
2289 * device your driver supports. If the driver supports more than one
2290 * type of device, separate each device-type name with a comma (,).
2292 * wave for waveform audio devices
2293 * wavemapper for wave mappers
2294 * midi for MIDI audio devices
2295 * midimapper for midi mappers
2296 * aux for auxiliary audio devices
2297 * mixer for mixer devices
2300 if (d->d.d16.hDriver16) {
2301 #define A(_x,_y) AA(d->d.d16.hDriver16,_x,_y,16,GetProcAddress16)
2302 A(MMDRV_AUX, auxMessage);
2303 A(MMDRV_MIXER, mixMessage);
2304 A(MMDRV_MIDIIN, midMessage);
2305 A(MMDRV_MIDIOUT, modMessage);
2306 A(MMDRV_WAVEIN, widMessage);
2307 A(MMDRV_WAVEOUT, wodMessage);
2308 #undef A
2311 #undef AA
2313 if (TRACE_ON(mmsys)) {
2314 if ((lpDrv->bIs32) ? MMDRV_GetDescription32(name, buffer, sizeof(buffer)) :
2315 MMDRV_GetDescription16(name, buffer, sizeof(buffer)))
2316 TRACE("%s => %s\n", name, buffer);
2317 else
2318 TRACE("%s => No description\n", name);
2321 if (!count) {
2322 CloseDriver(lpDrv->hDriver, 0, 0);
2323 WARN("No message functions found\n");
2324 return FALSE;
2327 /* FIXME: being a mapper or not should be known by another way */
2328 /* it's known for NE drvs (the description is of the form '*mapper: *'
2329 * I don't have any clue for PE drvs
2330 * on Win 9x, the value is gotten from the key mappable under
2331 * HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\MediaResources\
2333 lpDrv->bIsMapper = bIsMapper;
2334 lpDrv->name = HEAP_strdupA(GetProcessHeap(), 0, name);
2336 /* Finish init and get the count of the devices */
2337 MMDRV_InitPerType(lpDrv, num, MMDRV_AUX, AUXDM_GETNUMDEVS);
2338 MMDRV_InitPerType(lpDrv, num, MMDRV_MIXER, MXDM_GETNUMDEVS);
2339 MMDRV_InitPerType(lpDrv, num, MMDRV_MIDIIN, MIDM_GETNUMDEVS);
2340 MMDRV_InitPerType(lpDrv, num, MMDRV_MIDIOUT, MODM_GETNUMDEVS);
2341 MMDRV_InitPerType(lpDrv, num, MMDRV_WAVEIN, WIDM_GETNUMDEVS);
2342 MMDRV_InitPerType(lpDrv, num, MMDRV_WAVEOUT, WODM_GETNUMDEVS);
2343 /* FIXME: if all those func calls return FALSE, then the driver must be unloaded */
2344 return TRUE;
2347 /**************************************************************************
2348 * MMDRV_Init [internal]
2350 BOOL MMDRV_Init(void)
2352 int num = 0;
2354 /* FIXME: this should be moved to init files;
2355 * - either .winerc/wine.conf
2356 * - or made of registry keys
2357 * this is a temporary hack, shall be removed anytime now
2359 /* first load hardware drivers */
2360 if (MMDRV_Install("wineoss.drv", num, FALSE)) num++;
2362 /* finish with mappers */
2363 if (MMDRV_Install("msacm.drv", num, TRUE )) num++;
2364 if (MMDRV_Install("midimap.drv", num, TRUE )) num++;
2366 /* be sure that size of MMDrvs matches the max number of loadable drivers !!
2367 * if not just increase size of MMDrvs */
2368 assert(num <= sizeof(MMDrvs)/sizeof(MMDrvs[0]));
2370 return TRUE;