Fixed loading of 16 bit drivers.
[wine.git] / dlls / winmm / lolvldrv.c
blobb13917ec211da06593aa79dcb0bf98ec0e3022fb
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 "winver.h"
14 #include "winemm.h"
15 #include "debugtools.h"
17 DEFAULT_DEBUG_CHANNEL(mmsys);
19 typedef DWORD CALLBACK (*WINEMM_msgFunc16)(UINT16, WORD, DWORD, DWORD, DWORD);
20 typedef DWORD CALLBACK (*WINEMM_msgFunc32)(UINT , UINT, DWORD, DWORD, DWORD);
22 /* for each loaded driver and each known type of driver, this structure contains
23 * the information needed to access it
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;
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;
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;
51 typedef MMDRV_MapType (*MMDRV_MAPFUNC)(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2);
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;
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]))
73 /* ### start build ### */
74 extern WORD CALLBACK MMDRV_CallTo16_word_wwlll(FARPROC16,WORD,WORD,LONG,LONG,LONG);
75 /* ### stop build ### */
77 /**************************************************************************
78 * MMDRV_GetDescription16 [internal]
80 static BOOL MMDRV_GetDescription16(const char* fname, char* buf, int buflen)
82 OFSTRUCT ofs;
83 HFILE hFile;
84 WORD w;
85 DWORD dw;
86 BOOL ret = FALSE;
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;
93 #define E(_x) do {TRACE _x;goto theEnd;} while(0)
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;
113 /**************************************************************************
114 * MMDRV_GetDescription32 [internal]
116 static BOOL MMDRV_GetDescription32(const char* fname, char* buf, int buflen)
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;
130 #define E(_x) do {TRACE _x;goto theEnd;} while(0)
132 if (OpenFile(fname, &ofs, OF_EXIST)==HFILE_ERROR) E(("Can't find file %s\n", fname));
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;
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"));
146 #define A(_x) if (pVerQueryValueA(ptr, "\\StringFileInfo\\040904B0\\" #_x, &val, &u)) \
147 TRACE(#_x " => %s\n", (LPSTR)val); else TRACE(#_x " @\n")
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
163 if (!pVerQueryValueA(ptr, "\\StringFileInfo\\040904B0\\ProductName", &val, &u)) E(("Can't get product name\n"));
164 lstrcpynA(buf, val, buflen);
166 #undef E
167 ret = TRUE;
168 theEnd:
169 HeapFree(GetProcessHeap(), 0, ptr);
170 if (hmodule) FreeLibrary( hmodule );
171 return ret;
174 /**************************************************************************
175 * MMDRV_Callback [internal]
177 static void MMDRV_Callback(LPWINE_MLD mld, HDRVR hDev, UINT uMsg, DWORD dwParam1, DWORD dwParam2)
179 TRACE("CB (*%08lx)(%08x %08x %08lx %08lx %08lx\n",
180 mld->dwCallback, hDev, uMsg, mld->dwClientInstance, dwParam1, dwParam2);
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);
193 /* =================================
194 * A U X M A P P E R S
195 * ================================= */
197 /**************************************************************************
198 * MMDRV_Aux_Map16To32A [internal]
200 static MMDRV_MapType MMDRV_Aux_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
202 return MMDRV_MAP_MSGERROR;
205 /**************************************************************************
206 * MMDRV_Aux_UnMap16To32A [internal]
208 static MMDRV_MapType MMDRV_Aux_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
210 return MMDRV_MAP_MSGERROR;
213 /**************************************************************************
214 * MMDRV_Aux_Map32ATo16 [internal]
216 static MMDRV_MapType MMDRV_Aux_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
218 return MMDRV_MAP_MSGERROR;
221 /**************************************************************************
222 * MMDRV_Aux_UnMap32ATo16 [internal]
224 static MMDRV_MapType MMDRV_Aux_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
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;
238 /**************************************************************************
239 * MMDRV_Aux_Callback [internal]
241 static void CALLBACK MMDRV_Aux_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
243 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
245 FIXME("NIY\n");
246 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
249 /* =================================
250 * M I X E R M A P P E R S
251 * ================================= */
253 /**************************************************************************
254 * xMMDRV_Mixer_Map16To32A [internal]
256 static MMDRV_MapType MMDRV_Mixer_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
258 return MMDRV_MAP_MSGERROR;
261 /**************************************************************************
262 * MMDRV_Mixer_UnMap16To32A [internal]
264 static MMDRV_MapType MMDRV_Mixer_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
266 #if 0
267 MIXERCAPSA micA;
268 UINT ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
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;
278 return ret;
279 #endif
280 return MMDRV_MAP_MSGERROR;
283 /**************************************************************************
284 * MMDRV_Mixer_Map32ATo16 [internal]
286 static MMDRV_MapType MMDRV_Mixer_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
288 return MMDRV_MAP_MSGERROR;
291 /**************************************************************************
292 * MMDRV_Mixer_UnMap32ATo16 [internal]
294 static MMDRV_MapType MMDRV_Mixer_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
296 return MMDRV_MAP_MSGERROR;
299 /**************************************************************************
300 * MMDRV_Mixer_Callback [internal]
302 static void CALLBACK MMDRV_Mixer_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
304 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
306 FIXME("NIY\n");
307 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
310 /* =================================
311 * M I D I I N M A P P E R S
312 * ================================= */
314 /**************************************************************************
315 * MMDRV_MidiIn_Map16To32A [internal]
317 static MMDRV_MapType MMDRV_MidiIn_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
319 return MMDRV_MAP_MSGERROR;
322 /**************************************************************************
323 * MMDRV_MidiIn_UnMap16To32A [internal]
325 static MMDRV_MapType MMDRV_MidiIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
327 return MMDRV_MAP_MSGERROR;
330 /**************************************************************************
331 * MMDRV_MidiIn_Map32ATo16 [internal]
333 static MMDRV_MapType MMDRV_MidiIn_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
335 return MMDRV_MAP_MSGERROR;
338 /**************************************************************************
339 * MMDRV_MidiIn_UnMap32ATo16 [internal]
341 static MMDRV_MapType MMDRV_MidiIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
343 return MMDRV_MAP_MSGERROR;
346 /**************************************************************************
347 * MMDRV_MidiIn_Callback [internal]
349 static void CALLBACK MMDRV_MidiIn_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
351 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
353 switch (uMsg) {
354 case MIM_OPEN:
355 case MIM_CLOSE:
356 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
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));
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);
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;
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);
395 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
398 /* =================================
399 * M I D I O U T M A P P E R S
400 * ================================= */
402 /**************************************************************************
403 * MMDRV_MidiOut_Map16To32A [internal]
405 static MMDRV_MapType MMDRV_MidiOut_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
407 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
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;
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;
423 case MODM_GETDEVCAPS:
425 LPMIDIOUTCAPSA moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSA));
426 LPMIDIOUTCAPS16 moc16 = MapSL(*lpParam1);
428 if (moc32) {
429 *(LPMIDIOUTCAPS16*)moc32 = moc16;
430 moc32 = (LPMIDIOUTCAPSA)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16));
431 *lpParam1 = (DWORD)moc32;
432 *lpParam2 = sizeof(MIDIOUTCAPSA);
434 ret = MMDRV_MAP_OKMEM;
435 } else {
436 ret = MMDRV_MAP_NOMEM;
439 break;
440 case MODM_PREPARE:
442 LPMIDIHDR mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR));
443 LPMIDIHDR mh16 = MapSL(*lpParam1);
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);
462 ret = MMDRV_MAP_OKMEM;
463 } else {
464 ret = MMDRV_MAP_NOMEM;
467 break;
468 case MODM_UNPREPARE:
469 case MODM_LONGDATA:
471 LPMIDIHDR mh16 = MapSL(*lpParam1);
472 LPMIDIHDR mh32 = (LPMIDIHDR)mh16->lpNext;
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;
482 mh32->dwBufferLength = mh16->dwBufferLength;
483 ret = MMDRV_MAP_OKMEM;
485 break;
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;
493 return ret;
496 /**************************************************************************
497 * MMDRV_MidiOut_UnMap16To32A [internal]
499 static MMDRV_MapType MMDRV_MidiOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
501 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
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;
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;
517 case MODM_GETDEVCAPS:
519 LPMIDIOUTCAPSA moc32 = (LPMIDIOUTCAPSA)(*lpParam1);
520 LPMIDIOUTCAPS16 moc16 = *(LPMIDIOUTCAPS16*)((LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
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;
534 break;
535 case MODM_PREPARE:
536 case MODM_UNPREPARE:
537 case MODM_LONGDATA:
539 LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1);
540 LPMIDIHDR mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)));
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;
550 if (wMsg == MODM_UNPREPARE) {
551 HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR));
552 mh16->lpNext = 0;
554 ret = MMDRV_MAP_OK;
556 break;
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;
564 return ret;
567 /**************************************************************************
568 * MMDRV_MidiOut_Map32ATo16 [internal]
570 static MMDRV_MapType MMDRV_MidiOut_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
572 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
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:
584 LPMIDIOUTCAPSA moc32 = (LPMIDIOUTCAPSA)*lpParam1;
585 LPSTR ptr = SEGPTR_ALLOC(sizeof(LPMIDIOUTCAPSA) + sizeof(MIDIOUTCAPS16));
587 if (ptr) {
588 *(LPMIDIOUTCAPSA*)ptr = moc32;
589 ret = MMDRV_MAP_OKMEM;
590 } else {
591 ret = MMDRV_MAP_NOMEM;
593 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMIDIOUTCAPSA);
594 *lpParam2 = sizeof(MIDIOUTCAPS16);
596 break;
597 case MODM_PREPARE:
599 LPMIDIHDR mh32 = (LPMIDIHDR)*lpParam1;
600 LPMIDIHDR mh16;
601 LPVOID ptr = SEGPTR_ALLOC(sizeof(LPMIDIHDR) + sizeof(MIDIHDR) + mh32->dwBufferLength);
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;
616 mh32->lpNext = (LPMIDIHDR)mh16; /* for reuse in unprepare and write */
617 mh32->reserved = *lpParam2;
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);
625 ret = MMDRV_MAP_OKMEM;
626 } else {
627 ret = MMDRV_MAP_NOMEM;
630 break;
631 case MODM_UNPREPARE:
632 case MODM_LONGDATA:
634 LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1);
635 LPMIDIHDR mh16 = (LPMIDIHDR)mh32->lpNext;
636 LPSTR ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
638 assert(*(LPMIDIHDR*)ptr == mh32);
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);
644 if (wMsg == MODM_LONGDATA)
645 memcpy((LPSTR)mh16 + sizeof(MIDIHDR), mh32->lpData, mh32->dwBufferLength);
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;
655 mh16->dwBufferLength = mh32->dwBufferLength;
656 ret = MMDRV_MAP_OKMEM;
658 break;
659 case MODM_OPEN:
661 LPMIDIOPENDESC mod32 = (LPMIDIOPENDESC)*lpParam1;
662 LPVOID ptr;
663 LPMIDIOPENDESC16 mod16;
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
672 ptr = SEGPTR_ALLOC(sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD) + sizeof(MIDIOPENDESC16) +
673 mod32->cIds ? (mod32->cIds - 1) * sizeof(MIDIOPENSTRMID) : 0);
675 if (ptr) {
676 *(LPMIDIOPENDESC*)ptr = mod32;
677 *(LPDWORD)(ptr + sizeof(LPMIDIOPENDESC)) = *lpdwUser;
678 mod16 = (LPMIDIOPENDESC16)((LPSTR)ptr + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD));
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));
687 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD);
688 *lpdwUser = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMIDIOPENDESC) + sizeof(DWORD);
690 ret = MMDRV_MAP_OKMEM;
691 } else {
692 ret = MMDRV_MAP_NOMEM;
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;
703 return ret;
706 /**************************************************************************
707 * MMDRV_MidiOut_UnMap32ATo16 [internal]
709 static MMDRV_MapType MMDRV_MidiOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
711 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
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:
723 LPMIDIOUTCAPS16 moc16 = MapSL(*lpParam1);
724 LPSTR ptr = (LPSTR)moc16 - sizeof(LPMIDIOUTCAPSA);
725 LPMIDIOUTCAPSA moc32 = *(LPMIDIOUTCAPSA*)ptr;
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;
737 if (!SEGPTR_FREE(ptr))
738 FIXME("bad free line=%d\n", __LINE__);
739 ret = MMDRV_MAP_OK;
741 break;
742 case MODM_PREPARE:
743 case MODM_UNPREPARE:
744 case MODM_LONGDATA:
746 LPMIDIHDR mh16 = MapSL(*lpParam1);
747 LPSTR ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
748 LPMIDIHDR mh32 = *(LPMIDIHDR*)ptr;
750 assert(mh32->lpNext == (LPMIDIHDR)mh16);
751 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
752 mh32->dwUser = mh16->dwUser;
753 mh32->dwFlags = mh16->dwFlags;
755 if (wMsg == MODM_UNPREPARE) {
756 if (!SEGPTR_FREE(ptr))
757 FIXME("bad free line=%d\n", __LINE__);
758 mh32->lpNext = 0;
760 ret = MMDRV_MAP_OK;
762 break;
763 case MODM_OPEN:
765 LPMIDIOPENDESC16 mod16 = MapSL(*lpParam1);
766 LPSTR ptr = (LPSTR)mod16 - sizeof(LPMIDIOPENDESC) - 2*sizeof(DWORD);
768 **(DWORD**)(ptr + sizeof(LPMIDIOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPMIDIOPENDESC) + sizeof(DWORD));
770 if (!SEGPTR_FREE(ptr))
771 FIXME("bad free line=%d\n", __LINE__);
773 ret = MMDRV_MAP_OK;
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;
783 return ret;
786 /**************************************************************************
787 * MMDRV_MidiOut_Callback [internal]
789 static void CALLBACK MMDRV_MidiOut_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
791 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
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));
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);
815 dwParam1 = (DWORD)segmh16;
816 mh16->dwFlags = mh32->dwFlags;
817 if (mh16->reserved >= sizeof(MIDIHDR))
818 mh16->dwOffset = mh32->dwOffset;
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);
827 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
830 /* =================================
831 * W A V E I N M A P P E R S
832 * ================================= */
834 /**************************************************************************
835 * MMDRV_WaveIn_Map16To32A [internal]
837 static MMDRV_MapType MMDRV_WaveIn_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
839 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
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:
854 LPWAVEINCAPSA wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSA));
855 LPWAVEINCAPS16 wic16 = MapSL(*lpParam1);
857 if (wic32) {
858 *(LPWAVEINCAPS16*)wic32 = wic16;
859 wic32 = (LPWAVEINCAPSA)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16));
860 *lpParam1 = (DWORD)wic32;
861 *lpParam2 = sizeof(WAVEINCAPSA);
863 ret = MMDRV_MAP_OKMEM;
864 } else {
865 ret = MMDRV_MAP_NOMEM;
868 break;
869 case WIDM_GETPOS:
871 LPMMTIME mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
872 LPMMTIME16 mmt16 = MapSL(*lpParam1);
874 if (mmt32) {
875 *(LPMMTIME16*)mmt32 = mmt16;
876 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
878 mmt32->wType = mmt16->wType;
879 *lpParam1 = (DWORD)mmt32;
880 *lpParam2 = sizeof(MMTIME);
882 ret = MMDRV_MAP_OKMEM;
883 } else {
884 ret = MMDRV_MAP_NOMEM;
887 break;
888 case WIDM_PREPARE:
890 LPWAVEHDR wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
891 LPWAVEHDR wh16 = MapSL(*lpParam1);
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);
908 ret = MMDRV_MAP_OKMEM;
909 } else {
910 ret = MMDRV_MAP_NOMEM;
913 break;
914 case WIDM_ADDBUFFER:
915 case WIDM_UNPREPARE:
917 LPWAVEHDR wh16 = MapSL(*lpParam1);
918 LPWAVEHDR wh32 = (LPWAVEHDR)wh16->lpNext;
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;
928 wh32->dwBufferLength = wh16->dwBufferLength;
929 ret = MMDRV_MAP_OKMEM;
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;
941 return ret;
944 /**************************************************************************
945 * MMDRV_WaveIn_UnMap16To32A [internal]
947 static MMDRV_MapType MMDRV_WaveIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
949 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
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:
965 LPWAVEINCAPSA wic32 = (LPWAVEINCAPSA)(*lpParam1);
966 LPWAVEINCAPS16 wic16 = *(LPWAVEINCAPS16*)((LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
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;
977 break;
978 case WIDM_GETPOS:
980 LPMMTIME mmt32 = (LPMMTIME)(*lpParam1);
981 LPMMTIME16 mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
983 MMSYSTEM_MMTIME32to16(mmt16, mmt32);
984 HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
985 ret = MMDRV_MAP_OK;
987 break;
988 case WIDM_ADDBUFFER:
989 case WIDM_PREPARE:
990 case WIDM_UNPREPARE:
992 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
993 LPWAVEHDR wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
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;
1002 if (wMsg == WIDM_UNPREPARE) {
1003 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
1004 wh16->lpNext = 0;
1006 ret = MMDRV_MAP_OK;
1008 break;
1009 default:
1010 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1011 break;
1013 return ret;
1016 /**************************************************************************
1017 * MMDRV_WaveIn_Map32ATo16 [internal]
1019 static MMDRV_MapType MMDRV_WaveIn_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1021 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
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;
1032 case WIDM_OPEN:
1034 LPWAVEOPENDESC wod32 = (LPWAVEOPENDESC)*lpParam1;
1035 int sz = sizeof(WAVEFORMATEX);
1036 LPVOID ptr;
1037 LPWAVEOPENDESC16 wod16;
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
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;
1052 ptr = SEGPTR_ALLOC(sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
1054 if (ptr) {
1055 *(LPWAVEOPENDESC*)ptr = wod32;
1056 *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
1057 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
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);
1063 wod16->dwCallback = wod32->dwCallback;
1064 wod16->dwInstance = wod32->dwInstance;
1065 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
1066 wod16->dnDevNode = wod32->dnDevNode;
1068 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
1069 *lpdwUser = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
1071 ret = MMDRV_MAP_OKMEM;
1072 } else {
1073 ret = MMDRV_MAP_NOMEM;
1076 break;
1077 case WIDM_PREPARE:
1079 LPWAVEHDR wh32 = (LPWAVEHDR)*lpParam1;
1080 LPWAVEHDR wh16;
1081 LPVOID ptr = SEGPTR_ALLOC(sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
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);
1102 ret = MMDRV_MAP_OKMEM;
1103 } else {
1104 ret = MMDRV_MAP_NOMEM;
1107 break;
1108 case WIDM_ADDBUFFER:
1109 case WIDM_UNPREPARE:
1111 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
1112 LPWAVEHDR wh16 = wh32->lpNext;
1113 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1115 assert(*(LPWAVEHDR*)ptr == wh32);
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);
1121 if (wMsg == WIDM_ADDBUFFER)
1122 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
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;
1132 wh32->dwBufferLength = wh16->dwBufferLength;
1133 ret = MMDRV_MAP_OKMEM;
1135 break;
1136 case WIDM_GETDEVCAPS:
1138 LPWAVEINCAPSA wic32 = (LPWAVEINCAPSA)*lpParam1;
1139 LPSTR ptr = SEGPTR_ALLOC(sizeof(LPWAVEINCAPSA) + sizeof(WAVEINCAPS16));
1141 if (ptr) {
1142 *(LPWAVEINCAPSA*)ptr = wic32;
1143 ret = MMDRV_MAP_OKMEM;
1144 } else {
1145 ret = MMDRV_MAP_NOMEM;
1147 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEINCAPSA);
1148 *lpParam2 = sizeof(WAVEINCAPS16);
1150 break;
1151 case WIDM_GETPOS:
1153 LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1154 LPSTR ptr = SEGPTR_ALLOC(sizeof(LPMMTIME) + sizeof(MMTIME16));
1155 LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1157 if (ptr) {
1158 *(LPMMTIME*)ptr = mmt32;
1159 mmt16->wType = mmt32->wType;
1160 ret = MMDRV_MAP_OKMEM;
1161 } else {
1162 ret = MMDRV_MAP_NOMEM;
1164 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMMTIME);
1165 *lpParam2 = sizeof(MMTIME16);
1167 break;
1168 case DRVM_MAPPER_STATUS:
1170 LPDWORD p32 = (LPDWORD)*lpParam2;
1171 int sz;
1172 LPSTR ptr;
1173 LPDWORD p16;
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;
1183 ptr = SEGPTR_ALLOC(sizeof(LPDWORD) + sz);
1184 p16 = (LPDWORD)(ptr + sizeof(LPDWORD));
1186 if (ptr) {
1187 *(LPDWORD*)ptr = p32;
1188 ret = MMDRV_MAP_OKMEM;
1189 } else {
1190 ret = MMDRV_MAP_NOMEM;
1192 *lpParam2 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPDWORD);
1194 break;
1195 default:
1196 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1197 break;
1199 return ret;
1202 /**************************************************************************
1203 * MMDRV_WaveIn_UnMap32ATo16 [internal]
1205 static MMDRV_MapType MMDRV_WaveIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1207 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
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;
1218 case WIDM_OPEN:
1220 LPWAVEOPENDESC16 wod16 = MapSL(*lpParam1);
1221 LPSTR ptr = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1222 LPWAVEOPENDESC wod32 = *(LPWAVEOPENDESC*)ptr;
1224 wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1225 **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1227 if (!SEGPTR_FREE(ptr))
1228 FIXME("bad free line=%d\n", __LINE__);
1230 ret = MMDRV_MAP_OK;
1232 break;
1234 case WIDM_ADDBUFFER:
1235 case WIDM_PREPARE:
1236 case WIDM_UNPREPARE:
1238 LPWAVEHDR wh16 = MapSL(*lpParam1);
1239 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1240 LPWAVEHDR wh32 = *(LPWAVEHDR*)ptr;
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;
1248 if (wMsg == WIDM_UNPREPARE) {
1249 if (!SEGPTR_FREE(ptr))
1250 FIXME("bad free line=%d\n", __LINE__);
1251 wh32->lpNext = 0;
1253 ret = MMDRV_MAP_OK;
1255 break;
1256 case WIDM_GETDEVCAPS:
1258 LPWAVEINCAPS16 wic16 = MapSL(*lpParam1);
1259 LPSTR ptr = (LPSTR)wic16 - sizeof(LPWAVEINCAPSA);
1260 LPWAVEINCAPSA wic32 = *(LPWAVEINCAPSA*)ptr;
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;
1272 break;
1273 case WIDM_GETPOS:
1275 LPMMTIME16 mmt16 = MapSL(*lpParam1);
1276 LPSTR ptr = (LPSTR)mmt16 - sizeof(LPMMTIME);
1277 LPMMTIME mmt32 = *(LPMMTIME*)ptr;
1279 MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1281 if (!SEGPTR_FREE(ptr))
1282 FIXME("bad free line=%d\n", __LINE__);
1284 ret = MMDRV_MAP_OK;
1286 break;
1287 case DRVM_MAPPER_STATUS:
1289 LPDWORD p16 = MapSL(*lpParam2);
1290 LPSTR ptr = (LPSTR)p16 - sizeof(LPDWORD);
1291 LPDWORD p32 = *(LPDWORD*)ptr;
1292 int sz;
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;
1303 memcpy(p32, p16, sz);
1304 if (!SEGPTR_FREE(ptr))
1305 FIXME("bad free line=%d\n", __LINE__);
1307 ret = MMDRV_MAP_OK;
1309 break;
1310 default:
1311 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1312 break;
1314 return ret;
1317 /**************************************************************************
1318 * MMDRV_WaveIn_Callback [internal]
1320 static void CALLBACK MMDRV_WaveIn_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1322 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
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));
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);
1344 dwParam1 = (DWORD)segwh16;
1345 wh16->dwFlags = wh32->dwFlags;
1346 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
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);
1354 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1357 /* =================================
1358 * W A V E O U T M A P P E R S
1359 * ================================= */
1361 /**************************************************************************
1362 * MMDRV_WaveOut_Map16To32A [internal]
1364 static MMDRV_MapType MMDRV_WaveOut_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1366 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
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;
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;
1389 case WODM_GETDEVCAPS:
1391 LPWAVEOUTCAPSA woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSA));
1392 LPWAVEOUTCAPS16 woc16 = MapSL(*lpParam1);
1394 if (woc32) {
1395 *(LPWAVEOUTCAPS16*)woc32 = woc16;
1396 woc32 = (LPWAVEOUTCAPSA)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16));
1397 *lpParam1 = (DWORD)woc32;
1398 *lpParam2 = sizeof(WAVEOUTCAPSA);
1400 ret = MMDRV_MAP_OKMEM;
1401 } else {
1402 ret = MMDRV_MAP_NOMEM;
1405 break;
1406 case WODM_GETPOS:
1408 LPMMTIME mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
1409 LPMMTIME16 mmt16 = MapSL(*lpParam1);
1411 if (mmt32) {
1412 *(LPMMTIME16*)mmt32 = mmt16;
1413 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
1415 mmt32->wType = mmt16->wType;
1416 *lpParam1 = (DWORD)mmt32;
1417 *lpParam2 = sizeof(MMTIME);
1419 ret = MMDRV_MAP_OKMEM;
1420 } else {
1421 ret = MMDRV_MAP_NOMEM;
1424 break;
1425 case WODM_PREPARE:
1427 LPWAVEHDR wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
1428 LPWAVEHDR wh16 = MapSL(*lpParam1);
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);
1445 ret = MMDRV_MAP_OKMEM;
1446 } else {
1447 ret = MMDRV_MAP_NOMEM;
1450 break;
1451 case WODM_UNPREPARE:
1452 case WODM_WRITE:
1454 LPWAVEHDR wh16 = MapSL(*lpParam1);
1455 LPWAVEHDR wh32 = (LPWAVEHDR)wh16->lpNext;
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;
1465 wh32->dwBufferLength = wh16->dwBufferLength;
1466 ret = MMDRV_MAP_OKMEM;
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;
1477 return ret;
1480 /**************************************************************************
1481 * MMDRV_WaveOut_UnMap16To32A [internal]
1483 static MMDRV_MapType MMDRV_WaveOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1485 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
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;
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;
1509 case WODM_GETDEVCAPS:
1511 LPWAVEOUTCAPSA woc32 = (LPWAVEOUTCAPSA)(*lpParam1);
1512 LPWAVEOUTCAPS16 woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
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;
1524 break;
1525 case WODM_GETPOS:
1527 LPMMTIME mmt32 = (LPMMTIME)(*lpParam1);
1528 LPMMTIME16 mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
1530 MMSYSTEM_MMTIME32to16(mmt16, mmt32);
1531 HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
1532 ret = MMDRV_MAP_OK;
1534 break;
1535 case WODM_PREPARE:
1536 case WODM_UNPREPARE:
1537 case WODM_WRITE:
1539 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
1540 LPWAVEHDR wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
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;
1549 if (wMsg == WODM_UNPREPARE) {
1550 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
1551 wh16->lpNext = 0;
1553 ret = MMDRV_MAP_OK;
1555 break;
1556 default:
1557 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1558 break;
1560 return ret;
1563 /**************************************************************************
1564 * MMDRV_WaveOut_Map32ATo16 [internal]
1566 static MMDRV_MapType MMDRV_WaveOut_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1568 MMDRV_MapType ret;
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;
1584 case WODM_GETDEVCAPS:
1586 LPWAVEOUTCAPSA woc32 = (LPWAVEOUTCAPSA)*lpParam1;
1587 LPSTR ptr = SEGPTR_ALLOC(sizeof(LPWAVEOUTCAPSA) + sizeof(WAVEOUTCAPS16));
1589 if (ptr) {
1590 *(LPWAVEOUTCAPSA*)ptr = woc32;
1591 ret = MMDRV_MAP_OKMEM;
1592 } else {
1593 ret = MMDRV_MAP_NOMEM;
1595 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOUTCAPSA);
1596 *lpParam2 = sizeof(WAVEOUTCAPS16);
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:
1609 LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1610 LPSTR ptr = SEGPTR_ALLOC(sizeof(LPMMTIME) + sizeof(MMTIME16));
1611 LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1613 if (ptr) {
1614 *(LPMMTIME*)ptr = mmt32;
1615 mmt16->wType = mmt32->wType;
1616 ret = MMDRV_MAP_OKMEM;
1617 } else {
1618 ret = MMDRV_MAP_NOMEM;
1620 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPMMTIME);
1621 *lpParam2 = sizeof(MMTIME16);
1623 break;
1624 case WODM_GETVOLUME:
1625 FIXME("NIY: no conversion yet\n");
1626 ret = MMDRV_MAP_MSGERROR;
1627 break;
1628 case WODM_OPEN:
1630 LPWAVEOPENDESC wod32 = (LPWAVEOPENDESC)*lpParam1;
1631 int sz = sizeof(WAVEFORMATEX);
1632 LPVOID ptr;
1633 LPWAVEOPENDESC16 wod16;
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
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;
1648 ptr = SEGPTR_ALLOC(sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
1650 if (ptr) {
1651 *(LPWAVEOPENDESC*)ptr = wod32;
1652 *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
1653 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
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);
1659 wod16->dwCallback = wod32->dwCallback;
1660 wod16->dwInstance = wod32->dwInstance;
1661 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
1662 wod16->dnDevNode = wod32->dnDevNode;
1664 *lpParam1 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
1665 *lpdwUser = (DWORD)SEGPTR_GET(ptr) + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
1667 ret = MMDRV_MAP_OKMEM;
1668 } else {
1669 ret = MMDRV_MAP_NOMEM;
1672 break;
1673 case WODM_PREPARE:
1675 LPWAVEHDR wh32 = (LPWAVEHDR)*lpParam1;
1676 LPWAVEHDR wh16;
1677 LPVOID ptr = SEGPTR_ALLOC(sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
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);
1698 ret = MMDRV_MAP_OKMEM;
1699 } else {
1700 ret = MMDRV_MAP_NOMEM;
1703 break;
1704 case WODM_UNPREPARE:
1705 case WODM_WRITE:
1707 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
1708 LPWAVEHDR wh16 = wh32->lpNext;
1709 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1711 assert(*(LPWAVEHDR*)ptr == wh32);
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);
1717 if (wMsg == WODM_WRITE)
1718 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
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;
1728 wh16->dwBufferLength = wh32->dwBufferLength;
1729 ret = MMDRV_MAP_OKMEM;
1731 break;
1732 case DRVM_MAPPER_STATUS:
1734 LPDWORD p32 = (LPDWORD)*lpParam2;
1735 int sz;
1736 LPSTR ptr;
1737 LPDWORD p16;
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;
1747 ptr = SEGPTR_ALLOC(sizeof(LPDWORD) + sz);
1748 p16 = (LPDWORD)(ptr + sizeof(LPDWORD));
1750 if (ptr) {
1751 *(LPDWORD*)ptr = p32;
1752 memcpy(p16, p32, sz);
1753 ret = MMDRV_MAP_OKMEM;
1754 } else {
1755 ret = MMDRV_MAP_NOMEM;
1757 *lpParam2 = (DWORD)SEGPTR_GET(ptr) + sizeof(LPDWORD);
1759 break;
1760 default:
1761 FIXME("NIY: no conversion yet\n");
1762 ret = MMDRV_MAP_MSGERROR;
1763 break;
1765 return ret;
1768 /**************************************************************************
1769 * MMDRV_WaveOut_UnMap32ATo16 [internal]
1771 static MMDRV_MapType MMDRV_WaveOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1773 MMDRV_MapType ret;
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;
1789 case WODM_GETDEVCAPS:
1791 LPWAVEOUTCAPS16 woc16 = MapSL(*lpParam1);
1792 LPSTR ptr = (LPSTR)woc16 - sizeof(LPWAVEOUTCAPSA);
1793 LPWAVEOUTCAPSA woc32 = *(LPWAVEOUTCAPSA*)ptr;
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;
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:
1817 LPMMTIME16 mmt16 = MapSL(*lpParam1);
1818 LPSTR ptr = (LPSTR)mmt16 - sizeof(LPMMTIME);
1819 LPMMTIME mmt32 = *(LPMMTIME*)ptr;
1821 MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1823 if (!SEGPTR_FREE(ptr))
1824 FIXME("bad free line=%d\n", __LINE__);
1826 ret = MMDRV_MAP_OK;
1828 break;
1829 case WODM_OPEN:
1831 LPWAVEOPENDESC16 wod16 = MapSL(*lpParam1);
1832 LPSTR ptr = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1833 LPWAVEOPENDESC wod32 = *(LPWAVEOPENDESC*)ptr;
1835 wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1836 **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1838 if (!SEGPTR_FREE(ptr))
1839 FIXME("bad free line=%d\n", __LINE__);
1841 ret = MMDRV_MAP_OK;
1843 break;
1844 case WODM_PREPARE:
1845 case WODM_UNPREPARE:
1846 case WODM_WRITE:
1848 LPWAVEHDR wh16 = MapSL(*lpParam1);
1849 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1850 LPWAVEHDR wh32 = *(LPWAVEHDR*)ptr;
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;
1858 if (wMsg == WODM_UNPREPARE) {
1859 if (!SEGPTR_FREE(ptr))
1860 FIXME("bad free line=%d\n", __LINE__);
1861 wh32->lpNext = 0;
1863 ret = MMDRV_MAP_OK;
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:
1872 LPDWORD p16 = MapSL(*lpParam2);
1873 LPSTR ptr = (LPSTR)p16 - sizeof(LPDWORD);
1874 LPDWORD p32 = *(LPDWORD*)ptr;
1875 int sz;
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;
1886 memcpy(p32, p16, sz);
1887 if (!SEGPTR_FREE(ptr))
1888 FIXME("bad free line=%d\n", __LINE__);
1890 ret = MMDRV_MAP_OK;
1892 break;
1893 default:
1894 FIXME("NIY: no conversion yet\n");
1895 ret = MMDRV_MAP_MSGERROR;
1896 break;
1898 return ret;
1901 /**************************************************************************
1902 * MMDRV_WaveOut_Callback [internal]
1904 static void CALLBACK MMDRV_WaveOut_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1906 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
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));
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);
1927 dwParam1 = (DWORD)segwh16;
1928 wh16->dwFlags = wh32->dwFlags;
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);
1936 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
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}
1944 /* Note: the indices of this array must match the definitions
1945 * of the MMDRV_???? manifest constants
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),
1955 #undef A
1957 /**************************************************************************
1958 * MMDRV_GetNum [internal]
1960 UINT MMDRV_GetNum(UINT type)
1962 assert(type < MMDRV_MAX);
1963 return llTypes[type].wMaxId;
1966 /**************************************************************************
1967 * WINE_Message [internal]
1969 DWORD MMDRV_Message(LPWINE_MLD mld, WORD wMsg, DWORD dwParam1,
1970 DWORD dwParam2, BOOL bFrom32)
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;
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');
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;
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;
1995 devID = mld->uDeviceID;
1998 lpDrv = &MMDrvs[mld->mmdIndex];
1999 part = &lpDrv->parts[mld->type];
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
2009 if (lpDrv->bIs32) {
2010 assert(part->u.fnMessage32);
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;
2044 } else {
2045 assert(part->u.fnMessage16);
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;
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);
2081 return ret;
2084 /**************************************************************************
2085 * MMDRV_Alloc [internal]
2087 LPWINE_MLD MMDRV_Alloc(UINT size, UINT type, LPHANDLE hndl, DWORD* dwFlags,
2088 DWORD* dwCallback, DWORD* dwInstance, BOOL bFrom32)
2090 LPWINE_MLD mld;
2092 mld = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2093 if (!mld) return NULL;
2095 /* find an empty slot in MM_MLDrvs table */
2096 for (*hndl = 0; *hndl < MAX_MM_MLDRVS; (*hndl)++) {
2097 if (!MM_MLDrvs[*hndl]) break;
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;
2104 MM_MLDrvs[*hndl] = mld;
2105 *hndl |= 0x8000;
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
2113 ERR("Shouldn't happen. Bad allocation scheme\n");
2116 mld->bFrom32 = bFrom32;
2117 mld->dwFlags = HIWORD(*dwFlags);
2118 mld->dwCallback = *dwCallback;
2119 mld->dwClientInstance = *dwInstance;
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 ? */
2125 return mld;
2128 /**************************************************************************
2129 * MMDRV_Free [internal]
2131 void MMDRV_Free(HANDLE hndl, LPWINE_MLD mld)
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;
2141 ERR("Bad Handle %08x at %p (not freed)\n", hndl, mld);
2144 /**************************************************************************
2145 * MMDRV_Open [internal]
2147 DWORD MMDRV_Open(LPWINE_MLD mld, UINT wMsg, DWORD dwParam1, DWORD dwFlags)
2149 DWORD dwRet = MMSYSERR_BADDEVICEID;
2150 DWORD dwInstance;
2151 WINE_LLTYPE* llType = &llTypes[mld->type];
2153 mld->dwDriverInstance = (DWORD)&dwInstance;
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;
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);
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);
2183 if (dwRet == MMSYSERR_NOERROR)
2184 mld->dwDriverInstance = dwInstance;
2185 return dwRet;
2188 /**************************************************************************
2189 * MMDRV_Close [internal]
2191 DWORD MMDRV_Close(LPWINE_MLD mld, UINT wMsg)
2193 return MMDRV_Message(mld, wMsg, 0L, 0L, TRUE);
2196 /**************************************************************************
2197 * MMDRV_GetByID [internal]
2199 LPWINE_MLD MMDRV_GetByID(UINT uDevID, UINT type)
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;
2208 /**************************************************************************
2209 * MMDRV_Get [internal]
2211 LPWINE_MLD MMDRV_Get(HANDLE hndl, UINT type, BOOL bCanBeID)
2213 LPWINE_MLD mld = NULL;
2215 assert(type < MMDRV_MAX);
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;
2227 if (mld == NULL && bCanBeID) {
2228 mld = MMDRV_GetByID((UINT)hndl, type);
2230 return mld;
2233 /**************************************************************************
2234 * MMDRV_GetRelated [internal]
2236 LPWINE_MLD MMDRV_GetRelated(HANDLE hndl, UINT srcType,
2237 BOOL bSrcCanBeID, UINT dstType)
2239 LPWINE_MLD mld;
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);
2246 return NULL;
2249 /**************************************************************************
2250 * MMDRV_PhysicalFeatures [internal]
2252 UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD dwParam1,
2253 DWORD dwParam2)
2255 WINE_MM_DRIVER* lpDrv = &MMDrvs[mld->mmdIndex];
2257 TRACE("(%p, %04x, %08lx, %08lx)\n", mld, uMsg, dwParam1, dwParam2);
2259 /* all those function calls are undocumented */
2260 switch (uMsg) {
2261 case 0x801: /* DRV_QUERYDRVENTRY */
2262 lstrcpynA((LPSTR)dwParam1, lpDrv->name, LOWORD(dwParam2));
2263 break;
2264 case 0x802: /* DRV_QUERYDEVNODE */
2265 *(LPDWORD)dwParam1 = 0L; /* should be DevNode */
2266 break;
2267 case 0x803: /* DRV_QUERYNAME */
2268 WARN("NIY 0x803\n");
2269 break;
2270 case 0x804: /* 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
2276 break;
2277 case 0x805: /* DRV_QUERYMAPPABLE */
2278 return (lpDrv->bIsMapper) ? 2 : 0;
2280 case 0x810: /* Wine-specific: Retrieve DirectSound interface */
2281 return MMDRV_Message(mld, uMsg, dwParam1, dwParam2, TRUE);
2283 default:
2284 WARN("Unknown call %04x\n", uMsg);
2285 return MMSYSERR_INVALPARAM;
2287 return 0L;
2290 /**************************************************************************
2291 * MMDRV_InitPerType [internal]
2293 static BOOL MMDRV_InitPerType(LPWINE_MM_DRIVER lpDrv, UINT num,
2294 UINT type, UINT wMsg)
2296 WINE_MM_DRIVER_PART* part = &lpDrv->parts[type];
2297 DWORD ret;
2298 UINT count = 0;
2299 int i, k;
2301 part->nIDMin = part->nIDMax = 0;
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 */
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;
2329 TRACE("Got %u dev for (%s:%s)\n", count, lpDrv->name, llTypes[type].name);
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;
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;
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++;
2372 return TRUE;
2375 /**************************************************************************
2376 * MMDRV_Install [internal]
2378 static BOOL MMDRV_Install(LPCSTR name, int num, BOOL bIsMapper)
2380 int count = 0;
2381 char buffer[128];
2382 LPWINE_MM_DRIVER lpDrv = &MMDrvs[num];
2383 LPWINE_DRIVER d;
2385 TRACE("('%s');\n", name);
2387 memset(lpDrv, 0, sizeof(*lpDrv));
2389 if (!(lpDrv->hDriver = OpenDriverA(name, 0, 0))) {
2390 WARN("Couldn't open driver '%s'\n", name);
2391 return FALSE;
2394 d = DRIVER_FindFromHDrvr(lpDrv->hDriver);
2395 lpDrv->bIs32 = (d->dwFlags & WINE_GDF_16BIT) ? FALSE : TRUE;
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); }
2404 if (lpDrv->bIs32) {
2405 WINEMM_msgFunc32 func;
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
2417 } else {
2418 WINEMM_msgFunc16 func;
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 (,).
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
2436 if (d->d.d16.hDriver16) {
2437 HMODULE16 hMod16 = GetDriverModuleHandle16(d->d.d16.hDriver16);
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
2449 #undef AA
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);
2459 if (!count) {
2460 CloseDriver(lpDrv->hDriver, 0, 0);
2461 WARN("No message functions found\n");
2462 return FALSE;
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\
2471 lpDrv->bIsMapper = bIsMapper;
2472 lpDrv->name = HEAP_strdupA(GetProcessHeap(), 0, name);
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;
2485 /**************************************************************************
2486 * MMDRV_Init [internal]
2488 BOOL MMDRV_Init(void)
2490 int num = 0;
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
2497 /* first load hardware drivers */
2498 if (MMDRV_Install("wineoss.drv", num, FALSE)) num++;
2500 /* finish with mappers */
2501 if (MMDRV_Install("msacm.drv", num, TRUE )) num++;
2502 if (MMDRV_Install("midimap.drv", num, TRUE )) num++;
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]));
2508 return TRUE;