Compile fix when all handles are converted to a void*.
[wine/multimedia.git] / dlls / winmm / lolvldrv.c
blob6eac372e7d56e280445a31e41663c481faaf2a44
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * MMSYTEM low level drivers handling functions
6 * Copyright 1999 Eric Pouech
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <string.h>
24 #include <stdio.h>
25 #include <assert.h>
26 #include "wine/winbase16.h"
27 #include "winreg.h"
28 #include "winver.h"
29 #include "winemm.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
34 typedef DWORD (CALLBACK *WINEMM_msgFunc16)(UINT16, WORD, DWORD, DWORD, DWORD);
35 typedef DWORD (CALLBACK *WINEMM_msgFunc32)(UINT , UINT, DWORD, DWORD, DWORD);
37 /* for each loaded driver and each known type of driver, this structure contains
38 * the information needed to access it
40 typedef struct tagWINE_MM_DRIVER_PART {
41 int nIDMin; /* lower bound of global indexes for this type */
42 int nIDMax; /* hhigher bound of global indexes for this type */
43 union {
44 WINEMM_msgFunc32 fnMessage32; /* pointer to fonction */
45 WINEMM_msgFunc16 fnMessage16;
46 } u;
47 } WINE_MM_DRIVER_PART;
49 /* each low-level .drv will be associated with an instance of this structure */
50 typedef struct tagWINE_MM_DRIVER {
51 HDRVR hDriver;
52 LPSTR drvname; /* name of the driver */
53 BOOL bIs32 : 1, /* TRUE if 32 bit driver, FALSE for 16 */
54 bIsMapper : 1; /* TRUE if mapper */
55 WINE_MM_DRIVER_PART parts[MMDRV_MAX];/* Information for all known types */
56 } WINE_MM_DRIVER, *LPWINE_MM_DRIVER;
58 typedef enum {
59 MMDRV_MAP_NOMEM, /* ko, memory problem */
60 MMDRV_MAP_MSGERROR, /* ko, unknown message */
61 MMDRV_MAP_OK, /* ok, no memory allocated. to be sent to the proc. */
62 MMDRV_MAP_OKMEM, /* ok, some memory allocated, need to call UnMapMsg. to be sent to the proc. */
63 MMDRV_MAP_PASS /* not handled (no memory allocated) to be sent to the driver */
64 } MMDRV_MapType;
66 typedef MMDRV_MapType (*MMDRV_MAPFUNC)(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2);
68 /* each known type of driver has an instance of this structure */
69 typedef struct tagWINE_LLTYPE {
70 /* those attributes depend on the specification of the type */
71 LPSTR typestr; /* name (for debugging) */
72 BOOL bSupportMapper; /* if type is allowed to support mapper */
73 MMDRV_MAPFUNC Map16To32A; /* those are function pointers to handle */
74 MMDRV_MAPFUNC UnMap16To32A; /* the parameter conversion (16 vs 32 bit) */
75 MMDRV_MAPFUNC Map32ATo16; /* when hi-func (in mmsystem or winmm) and */
76 MMDRV_MAPFUNC UnMap32ATo16; /* low-func (in .drv) do not match */
77 LPDRVCALLBACK Callback; /* handles callback for a specified type */
78 /* those attributes reflect the loaded/current situation for the type */
79 UINT wMaxId; /* number of loaded devices (sum across all loaded drivers */
80 LPWINE_MLD lpMlds; /* "static" mlds to access the part though device IDs */
81 int nMapper; /* index to mapper */
82 } WINE_LLTYPE;
84 static int MMDrvsHi /* = 0 */;
85 static WINE_MM_DRIVER MMDrvs[3];
86 static LPWINE_MLD MM_MLDrvs[40];
87 #define MAX_MM_MLDRVS (sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0]))
89 /* ### start build ### */
90 extern WORD CALLBACK MMDRV_CallTo16_word_wwlll(FARPROC16,WORD,WORD,LONG,LONG,LONG);
91 /* ### stop build ### */
93 /**************************************************************************
94 * MMDRV_GetDescription16 [internal]
96 static BOOL MMDRV_GetDescription16(const char* fname, char* buf, int buflen)
98 OFSTRUCT ofs;
99 HFILE hFile;
100 WORD w;
101 DWORD dw;
102 BOOL ret = FALSE;
104 if ((hFile = OpenFile(fname, &ofs, OF_READ | OF_SHARE_DENY_WRITE)) == HFILE_ERROR) {
105 ERR("Can't open file %s (builtin driver ?)\n", fname);
106 return FALSE;
109 #define E(_x) do {TRACE _x;goto theEnd;} while(0)
111 if (_lread(hFile, &w, 2) != 2) E(("Can't read sig\n"));
112 if (w != ('Z' * 256 + 'M')) E(("Bad sig %04x\n", w));
113 if (_llseek(hFile, 0x3C, SEEK_SET) < 0) E(("Can't seek to ext header offset\n"));
114 if (_lread(hFile, &dw, 4) != 4) E(("Can't read ext header offset\n"));
115 if (_llseek(hFile, dw + 0x2C, SEEK_SET) < 0) E(("Can't seek to ext header.nr table %lu\n", dw+0x2C));
116 if (_lread(hFile, &dw, 4) != 4) E(("Can't read nr table offset\n"));
117 if (_llseek(hFile, dw, SEEK_SET) < 0) E(("Can't seek to nr table %lu\n", dw));
118 if (_lread(hFile, buf, 1) != 1) E(("Can't read descr length\n"));
119 buflen = min((int)(unsigned)(BYTE)buf[0], buflen - 1);
120 if (_lread(hFile, buf, buflen) != buflen) E(("Can't read descr (%d)\n", buflen));
121 buf[buflen] = '\0';
122 ret = TRUE;
123 TRACE("Got '%s' [%d]\n", buf, buflen);
124 theEnd:
125 CloseHandle(hFile);
126 return ret;
129 /**************************************************************************
130 * MMDRV_GetDescription32 [internal]
132 static BOOL MMDRV_GetDescription32(const char* fname, char* buf, int buflen)
134 OFSTRUCT ofs;
135 DWORD h;
136 LPVOID ptr = 0;
137 LPVOID val;
138 DWORD dw;
139 BOOL ret = FALSE;
140 UINT u;
141 FARPROC pGetFileVersionInfoSizeA;
142 FARPROC pGetFileVersionInfoA;
143 FARPROC pVerQueryValueA;
144 HMODULE hmodule = 0;
146 #define E(_x) do {TRACE _x;goto theEnd;} while(0)
148 if (OpenFile(fname, &ofs, OF_EXIST)==HFILE_ERROR) E(("Can't find file %s\n", fname));
150 if (!(hmodule = LoadLibraryA( "version.dll" ))) goto theEnd;
151 if (!(pGetFileVersionInfoSizeA = GetProcAddress( hmodule, "GetFileVersionInfoSizeA" )))
152 goto theEnd;
153 if (!(pGetFileVersionInfoA = GetProcAddress( hmodule, "GetFileVersionInfoA" )))
154 goto theEnd;
155 if (!(pVerQueryValueA = GetProcAddress( hmodule, "pVerQueryValueA" )))
156 goto theEnd;
158 if (!(dw = pGetFileVersionInfoSizeA(ofs.szPathName, &h))) E(("Can't get FVIS\n"));
159 if (!(ptr = HeapAlloc(GetProcessHeap(), 0, dw))) E(("OOM\n"));
160 if (!pGetFileVersionInfoA(ofs.szPathName, h, dw, ptr)) E(("Can't get FVI\n"));
162 #define A(_x) if (pVerQueryValueA(ptr, "\\StringFileInfo\\040904B0\\" #_x, &val, &u)) \
163 TRACE(#_x " => %s\n", (LPSTR)val); else TRACE(#_x " @\n")
165 A(CompanyName);
166 A(FileDescription);
167 A(FileVersion);
168 A(InternalName);
169 A(LegalCopyright);
170 A(OriginalFilename);
171 A(ProductName);
172 A(ProductVersion);
173 A(Comments);
174 A(LegalTrademarks);
175 A(PrivateBuild);
176 A(SpecialBuild);
177 #undef A
179 if (!pVerQueryValueA(ptr, "\\StringFileInfo\\040904B0\\ProductName", &val, &u)) E(("Can't get product name\n"));
180 lstrcpynA(buf, val, buflen);
182 #undef E
183 ret = TRUE;
184 theEnd:
185 HeapFree(GetProcessHeap(), 0, ptr);
186 if (hmodule) FreeLibrary( hmodule );
187 return ret;
190 /**************************************************************************
191 * MMDRV_Callback [internal]
193 static void MMDRV_Callback(LPWINE_MLD mld, HDRVR hDev, UINT uMsg, DWORD dwParam1, DWORD dwParam2)
195 TRACE("CB (*%08lx)(%08x %08x %08lx %08lx %08lx\n",
196 mld->dwCallback, hDev, uMsg, mld->dwClientInstance, dwParam1, dwParam2);
198 if (!mld->bFrom32 && (mld->dwFlags & DCB_TYPEMASK) == DCB_FUNCTION) {
199 /* 16 bit func, call it */
200 TRACE("Function (16 bit) !\n");
201 MMDRV_CallTo16_word_wwlll((FARPROC16)mld->dwCallback, HDRVR_16(hDev), uMsg,
202 mld->dwClientInstance, dwParam1, dwParam2);
203 } else {
204 DriverCallback(mld->dwCallback, mld->dwFlags, hDev, uMsg,
205 mld->dwClientInstance, dwParam1, dwParam2);
209 /* =================================
210 * A U X M A P P E R S
211 * ================================= */
213 /**************************************************************************
214 * MMDRV_Aux_Map16To32A [internal]
216 static MMDRV_MapType MMDRV_Aux_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
218 return MMDRV_MAP_MSGERROR;
221 /**************************************************************************
222 * MMDRV_Aux_UnMap16To32A [internal]
224 static MMDRV_MapType MMDRV_Aux_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
226 return MMDRV_MAP_MSGERROR;
229 /**************************************************************************
230 * MMDRV_Aux_Map32ATo16 [internal]
232 static MMDRV_MapType MMDRV_Aux_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
234 return MMDRV_MAP_MSGERROR;
237 /**************************************************************************
238 * MMDRV_Aux_UnMap32ATo16 [internal]
240 static MMDRV_MapType MMDRV_Aux_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
242 #if 0
243 case AUXDM_GETDEVCAPS:
244 lpCaps->wMid = ac16.wMid;
245 lpCaps->wPid = ac16.wPid;
246 lpCaps->vDriverVersion = ac16.vDriverVersion;
247 strcpy(lpCaps->szPname, ac16.szPname);
248 lpCaps->wTechnology = ac16.wTechnology;
249 lpCaps->dwSupport = ac16.dwSupport;
250 #endif
251 return MMDRV_MAP_MSGERROR;
254 /**************************************************************************
255 * MMDRV_Aux_Callback [internal]
257 static void CALLBACK MMDRV_Aux_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
259 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
261 FIXME("NIY\n");
262 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
265 /* =================================
266 * M I X E R M A P P E R S
267 * ================================= */
269 /**************************************************************************
270 * xMMDRV_Mixer_Map16To32A [internal]
272 static MMDRV_MapType MMDRV_Mixer_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
274 return MMDRV_MAP_MSGERROR;
277 /**************************************************************************
278 * MMDRV_Mixer_UnMap16To32A [internal]
280 static MMDRV_MapType MMDRV_Mixer_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
282 #if 0
283 MIXERCAPSA micA;
284 UINT ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
286 if (ret == MMSYSERR_NOERROR) {
287 mixcaps->wMid = micA.wMid;
288 mixcaps->wPid = micA.wPid;
289 mixcaps->vDriverVersion = micA.vDriverVersion;
290 strcpy(mixcaps->szPname, micA.szPname);
291 mixcaps->fdwSupport = micA.fdwSupport;
292 mixcaps->cDestinations = micA.cDestinations;
294 return ret;
295 #endif
296 return MMDRV_MAP_MSGERROR;
299 /**************************************************************************
300 * MMDRV_Mixer_Map32ATo16 [internal]
302 static MMDRV_MapType MMDRV_Mixer_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
304 return MMDRV_MAP_MSGERROR;
307 /**************************************************************************
308 * MMDRV_Mixer_UnMap32ATo16 [internal]
310 static MMDRV_MapType MMDRV_Mixer_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
312 return MMDRV_MAP_MSGERROR;
315 /**************************************************************************
316 * MMDRV_Mixer_Callback [internal]
318 static void CALLBACK MMDRV_Mixer_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
320 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
322 FIXME("NIY\n");
323 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
326 /* =================================
327 * M I D I I N M A P P E R S
328 * ================================= */
330 /**************************************************************************
331 * MMDRV_MidiIn_Map16To32A [internal]
333 static MMDRV_MapType MMDRV_MidiIn_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
335 return MMDRV_MAP_MSGERROR;
338 /**************************************************************************
339 * MMDRV_MidiIn_UnMap16To32A [internal]
341 static MMDRV_MapType MMDRV_MidiIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
343 return MMDRV_MAP_MSGERROR;
346 /**************************************************************************
347 * MMDRV_MidiIn_Map32ATo16 [internal]
349 static MMDRV_MapType MMDRV_MidiIn_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
351 return MMDRV_MAP_MSGERROR;
354 /**************************************************************************
355 * MMDRV_MidiIn_UnMap32ATo16 [internal]
357 static MMDRV_MapType MMDRV_MidiIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
359 return MMDRV_MAP_MSGERROR;
362 /**************************************************************************
363 * MMDRV_MidiIn_Callback [internal]
365 static void CALLBACK MMDRV_MidiIn_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
367 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
369 switch (uMsg) {
370 case MIM_OPEN:
371 case MIM_CLOSE:
372 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
374 case MIM_DATA:
375 case MIM_MOREDATA:
376 case MIM_ERROR:
377 /* dwParam1 & dwParam2 are are data, nothing to do */
378 break;
379 case MIM_LONGDATA:
380 case MIM_LONGERROR:
381 /* dwParam1 points to a MidiHdr, work to be done !!! */
382 if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
383 /* initial map is: 32 => 16 */
384 LPMIDIHDR mh16 = MapSL(dwParam1);
385 LPMIDIHDR mh32 = *(LPMIDIHDR*)((LPSTR)mh16 - sizeof(LPMIDIHDR));
387 dwParam1 = (DWORD)mh32;
388 mh32->dwFlags = mh16->dwFlags;
389 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
390 if (mh32->reserved >= sizeof(MIDIHDR))
391 mh32->dwOffset = mh16->dwOffset;
392 } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
393 /* initial map is: 16 => 32 */
394 LPMIDIHDR mh32 = (LPMIDIHDR)(dwParam1);
395 SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
396 LPMIDIHDR mh16 = MapSL(segmh16);
398 dwParam1 = (DWORD)segmh16;
399 mh16->dwFlags = mh32->dwFlags;
400 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
401 if (mh16->reserved >= sizeof(MIDIHDR))
402 mh16->dwOffset = mh32->dwOffset;
404 /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
405 break;
406 /* case MOM_POSITIONCB: */
407 default:
408 ERR("Unknown msg %u\n", uMsg);
411 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
414 /* =================================
415 * M I D I O U T M A P P E R S
416 * ================================= */
418 /**************************************************************************
419 * MMDRV_MidiOut_Map16To32A [internal]
421 static MMDRV_MapType MMDRV_MidiOut_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
423 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
425 switch (wMsg) {
426 case MODM_GETNUMDEVS:
427 case MODM_DATA:
428 case MODM_RESET:
429 case MODM_SETVOLUME:
430 ret = MMDRV_MAP_OK;
431 break;
433 case MODM_OPEN:
434 case MODM_CLOSE:
435 case MODM_GETVOLUME:
436 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
437 break;
439 case MODM_GETDEVCAPS:
441 LPMIDIOUTCAPSA moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSA));
442 LPMIDIOUTCAPS16 moc16 = MapSL(*lpParam1);
444 if (moc32) {
445 *(LPMIDIOUTCAPS16*)moc32 = moc16;
446 moc32 = (LPMIDIOUTCAPSA)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16));
447 *lpParam1 = (DWORD)moc32;
448 *lpParam2 = sizeof(MIDIOUTCAPSA);
450 ret = MMDRV_MAP_OKMEM;
451 } else {
452 ret = MMDRV_MAP_NOMEM;
455 break;
456 case MODM_PREPARE:
458 LPMIDIHDR mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR));
459 LPMIDIHDR mh16 = MapSL(*lpParam1);
461 if (mh32) {
462 *(LPMIDIHDR*)mh32 = (LPMIDIHDR)*lpParam1;
463 mh32 = (LPMIDIHDR)((LPSTR)mh32 + sizeof(LPMIDIHDR));
464 mh32->lpData = MapSL((SEGPTR)mh16->lpData);
465 mh32->dwBufferLength = mh16->dwBufferLength;
466 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
467 mh32->dwUser = mh16->dwUser;
468 mh32->dwFlags = mh16->dwFlags;
469 /* FIXME: nothing on mh32->lpNext */
470 /* could link the mh32->lpNext at this level for memory house keeping */
471 mh32->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? ((LPMIDIHDR)mh16)->dwOffset : 0;
472 mh16->lpNext = mh32; /* for reuse in unprepare and write */
473 /* store size of passed MIDIHDR?? structure to know if dwOffset is available or not */
474 mh16->reserved = *lpParam2;
475 *lpParam1 = (DWORD)mh32;
476 *lpParam2 = sizeof(MIDIHDR);
478 ret = MMDRV_MAP_OKMEM;
479 } else {
480 ret = MMDRV_MAP_NOMEM;
483 break;
484 case MODM_UNPREPARE:
485 case MODM_LONGDATA:
487 LPMIDIHDR mh16 = MapSL(*lpParam1);
488 LPMIDIHDR mh32 = (LPMIDIHDR)mh16->lpNext;
490 *lpParam1 = (DWORD)mh32;
491 *lpParam2 = sizeof(MIDIHDR);
492 /* dwBufferLength can be reduced between prepare & write */
493 if (wMsg == MODM_LONGDATA && mh32->dwBufferLength < mh16->dwBufferLength) {
494 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
495 mh32->dwBufferLength, mh16->dwBufferLength);
496 } else
497 mh32->dwBufferLength = mh16->dwBufferLength;
498 ret = MMDRV_MAP_OKMEM;
500 break;
502 case MODM_CACHEPATCHES:
503 case MODM_CACHEDRUMPATCHES:
504 default:
505 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
506 break;
508 return ret;
511 /**************************************************************************
512 * MMDRV_MidiOut_UnMap16To32A [internal]
514 static MMDRV_MapType MMDRV_MidiOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
516 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
518 switch (wMsg) {
519 case MODM_GETNUMDEVS:
520 case MODM_DATA:
521 case MODM_RESET:
522 case MODM_SETVOLUME:
523 ret = MMDRV_MAP_OK;
524 break;
526 case MODM_OPEN:
527 case MODM_CLOSE:
528 case MODM_GETVOLUME:
529 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
530 break;
532 case MODM_GETDEVCAPS:
534 LPMIDIOUTCAPSA moc32 = (LPMIDIOUTCAPSA)(*lpParam1);
535 LPMIDIOUTCAPS16 moc16 = *(LPMIDIOUTCAPS16*)((LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
537 moc16->wMid = moc32->wMid;
538 moc16->wPid = moc32->wPid;
539 moc16->vDriverVersion = moc32->vDriverVersion;
540 strcpy(moc16->szPname, moc32->szPname);
541 moc16->wTechnology = moc32->wTechnology;
542 moc16->wVoices = moc32->wVoices;
543 moc16->wNotes = moc32->wNotes;
544 moc16->wChannelMask = moc32->wChannelMask;
545 moc16->dwSupport = moc32->dwSupport;
546 HeapFree(GetProcessHeap(), 0, (LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
547 ret = MMDRV_MAP_OK;
549 break;
550 case MODM_PREPARE:
551 case MODM_UNPREPARE:
552 case MODM_LONGDATA:
554 LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1);
555 LPMIDIHDR mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)));
557 assert(mh16->lpNext == mh32);
558 mh16->dwBufferLength = mh32->dwBufferLength;
559 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
560 mh16->dwUser = mh32->dwUser;
561 mh16->dwFlags = mh32->dwFlags;
562 if (mh16->reserved >= sizeof(MIDIHDR))
563 mh16->dwOffset = mh32->dwOffset;
565 if (wMsg == MODM_UNPREPARE) {
566 HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR));
567 mh16->lpNext = 0;
569 ret = MMDRV_MAP_OK;
571 break;
573 case MODM_CACHEPATCHES:
574 case MODM_CACHEDRUMPATCHES:
575 default:
576 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
577 break;
579 return ret;
582 /**************************************************************************
583 * MMDRV_MidiOut_Map32ATo16 [internal]
585 static MMDRV_MapType MMDRV_MidiOut_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
587 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
589 switch (wMsg) {
590 case MODM_CLOSE:
591 case MODM_GETNUMDEVS:
592 case MODM_DATA:
593 case MODM_RESET:
594 case MODM_SETVOLUME:
595 ret = MMDRV_MAP_OK;
596 break;
597 case MODM_GETDEVCAPS:
599 LPMIDIOUTCAPSA moc32 = (LPMIDIOUTCAPSA)*lpParam1;
600 LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPSA)+sizeof(MIDIOUTCAPS16));
602 if (ptr) {
603 *(LPMIDIOUTCAPSA*)ptr = moc32;
604 ret = MMDRV_MAP_OKMEM;
605 } else {
606 ret = MMDRV_MAP_NOMEM;
608 *lpParam1 = (DWORD)MapLS(ptr) + sizeof(LPMIDIOUTCAPSA);
609 *lpParam2 = sizeof(MIDIOUTCAPS16);
611 break;
612 case MODM_PREPARE:
614 LPMIDIHDR mh32 = (LPMIDIHDR)*lpParam1;
615 LPMIDIHDR mh16;
616 LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
617 sizeof(LPMIDIHDR) + sizeof(MIDIHDR) + mh32->dwBufferLength);
619 if (ptr) {
620 *(LPMIDIHDR*)ptr = mh32;
621 mh16 = (LPMIDIHDR)((LPSTR)ptr + sizeof(LPMIDIHDR));
622 *lpParam1 = MapLS(mh16);
623 mh16->lpData = (LPSTR)*lpParam1 + sizeof(MIDIHDR);
624 /* data will be copied on WODM_WRITE */
625 mh16->dwBufferLength = mh32->dwBufferLength;
626 mh16->dwBytesRecorded = mh32->dwBytesRecorded;
627 mh16->dwUser = mh32->dwUser;
628 mh16->dwFlags = mh32->dwFlags;
629 /* FIXME: nothing on mh32->lpNext */
630 /* could link the mh32->lpNext at this level for memory house keeping */
631 mh16->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? mh32->dwOffset : 0;
633 mh32->lpNext = (LPMIDIHDR)mh16; /* for reuse in unprepare and write */
634 mh32->reserved = *lpParam2;
636 TRACE("mh16=%08lx mh16->lpData=%08lx mh32->buflen=%lu mh32->lpData=%08lx\n",
637 *lpParam1, (DWORD)mh16->lpData,
638 mh32->dwBufferLength, (DWORD)mh32->lpData);
639 *lpParam2 = sizeof(MIDIHDR);
641 ret = MMDRV_MAP_OKMEM;
642 } else {
643 ret = MMDRV_MAP_NOMEM;
646 break;
647 case MODM_UNPREPARE:
648 case MODM_LONGDATA:
650 LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1);
651 LPMIDIHDR mh16 = (LPMIDIHDR)mh32->lpNext;
652 LPSTR ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
654 assert(*(LPMIDIHDR*)ptr == mh32);
656 if (wMsg == MODM_LONGDATA)
657 memcpy((LPSTR)mh16 + sizeof(MIDIHDR), mh32->lpData, mh32->dwBufferLength);
659 *lpParam1 = MapLS(mh16);
660 *lpParam2 = sizeof(MIDIHDR);
661 TRACE("mh16=%08lx mh16->lpData=%08lx mh32->buflen=%lu mh32->lpData=%08lx\n",
662 *lpParam1, (DWORD)mh16->lpData, mh32->dwBufferLength, (DWORD)mh32->lpData);
664 /* dwBufferLength can be reduced between prepare & write */
665 if (wMsg == MODM_LONGDATA && mh16->dwBufferLength < mh32->dwBufferLength) {
666 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
667 mh16->dwBufferLength, mh32->dwBufferLength);
668 } else
669 mh16->dwBufferLength = mh32->dwBufferLength;
670 ret = MMDRV_MAP_OKMEM;
672 break;
673 case MODM_OPEN:
675 LPMIDIOPENDESC mod32 = (LPMIDIOPENDESC)*lpParam1;
676 LPVOID ptr;
677 LPMIDIOPENDESC16 mod16;
679 /* allocated data are mapped as follows:
680 LPMIDIOPENDESC ptr to orig lParam1
681 DWORD orig dwUser, which is a pointer to DWORD:driver dwInstance
682 DWORD dwUser passed to driver
683 MIDIOPENDESC16 mod16: openDesc passed to driver
684 MIDIOPENSTRMID cIds
686 ptr = HeapAlloc( GetProcessHeap(), 0,
687 sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD) + sizeof(MIDIOPENDESC16) +
688 mod32->cIds ? (mod32->cIds - 1) * sizeof(MIDIOPENSTRMID) : 0);
690 if (ptr) {
691 SEGPTR segptr = MapLS(ptr);
692 *(LPMIDIOPENDESC*)ptr = mod32;
693 *(LPDWORD)((char*)ptr + sizeof(LPMIDIOPENDESC)) = *lpdwUser;
694 mod16 = (LPMIDIOPENDESC16)((LPSTR)ptr + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD));
696 mod16->hMidi = HMIDI_16(mod32->hMidi);
697 mod16->dwCallback = mod32->dwCallback;
698 mod16->dwInstance = mod32->dwInstance;
699 mod16->dnDevNode = mod32->dnDevNode;
700 mod16->cIds = mod32->cIds;
701 memcpy(&mod16->rgIds, &mod32->rgIds, mod32->cIds * sizeof(MIDIOPENSTRMID));
703 *lpParam1 = (DWORD)segptr + sizeof(LPMIDIOPENDESC) + 2*sizeof(DWORD);
704 *lpdwUser = (DWORD)segptr + sizeof(LPMIDIOPENDESC) + sizeof(DWORD);
706 ret = MMDRV_MAP_OKMEM;
707 } else {
708 ret = MMDRV_MAP_NOMEM;
711 break;
712 case MODM_GETVOLUME:
713 case MODM_CACHEPATCHES:
714 case MODM_CACHEDRUMPATCHES:
715 default:
716 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
717 break;
719 return ret;
722 /**************************************************************************
723 * MMDRV_MidiOut_UnMap32ATo16 [internal]
725 static MMDRV_MapType MMDRV_MidiOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
727 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
729 switch (wMsg) {
730 case MODM_CLOSE:
731 case MODM_GETNUMDEVS:
732 case MODM_DATA:
733 case MODM_RESET:
734 case MODM_SETVOLUME:
735 ret = MMDRV_MAP_OK;
736 break;
737 case MODM_GETDEVCAPS:
739 LPMIDIOUTCAPS16 moc16 = MapSL(*lpParam1);
740 LPSTR ptr = (LPSTR)moc16 - sizeof(LPMIDIOUTCAPSA);
741 LPMIDIOUTCAPSA moc32 = *(LPMIDIOUTCAPSA*)ptr;
743 moc32->wMid = moc16->wMid;
744 moc32->wPid = moc16->wPid;
745 moc32->vDriverVersion = moc16->vDriverVersion;
746 strcpy(moc32->szPname, moc16->szPname);
747 moc32->wTechnology = moc16->wTechnology;
748 moc32->wVoices = moc16->wVoices;
749 moc32->wNotes = moc16->wNotes;
750 moc32->wChannelMask = moc16->wChannelMask;
751 moc32->dwSupport = moc16->dwSupport;
752 UnMapLS( *lpParam1 );
753 HeapFree( GetProcessHeap(), 0, ptr );
754 ret = MMDRV_MAP_OK;
756 break;
757 case MODM_PREPARE:
758 case MODM_UNPREPARE:
759 case MODM_LONGDATA:
761 LPMIDIHDR mh16 = MapSL(*lpParam1);
762 LPSTR ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR);
763 LPMIDIHDR mh32 = *(LPMIDIHDR*)ptr;
765 assert(mh32->lpNext == (LPMIDIHDR)mh16);
766 UnMapLS( *lpParam1 );
767 mh32->dwBytesRecorded = mh16->dwBytesRecorded;
768 mh32->dwUser = mh16->dwUser;
769 mh32->dwFlags = mh16->dwFlags;
771 if (wMsg == MODM_UNPREPARE) {
772 HeapFree( GetProcessHeap(), 0, ptr );
773 mh32->lpNext = 0;
775 ret = MMDRV_MAP_OK;
777 break;
778 case MODM_OPEN:
780 LPMIDIOPENDESC16 mod16 = MapSL(*lpParam1);
781 LPSTR ptr = (LPSTR)mod16 - sizeof(LPMIDIOPENDESC) - 2*sizeof(DWORD);
782 UnMapLS( *lpParam1 );
783 **(DWORD**)(ptr + sizeof(LPMIDIOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPMIDIOPENDESC) + sizeof(DWORD));
785 HeapFree( GetProcessHeap(), 0, ptr );
786 ret = MMDRV_MAP_OK;
788 break;
789 case MODM_GETVOLUME:
790 case MODM_CACHEPATCHES:
791 case MODM_CACHEDRUMPATCHES:
792 default:
793 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
794 break;
796 return ret;
799 /**************************************************************************
800 * MMDRV_MidiOut_Callback [internal]
802 static void CALLBACK MMDRV_MidiOut_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
804 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
806 switch (uMsg) {
807 case MOM_OPEN:
808 case MOM_CLOSE:
809 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
810 break;
811 case MOM_DONE:
812 if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
813 /* initial map is: 32 => 16 */
814 LPMIDIHDR mh16 = MapSL(dwParam1);
815 LPMIDIHDR mh32 = *(LPMIDIHDR*)((LPSTR)mh16 - sizeof(LPMIDIHDR));
817 dwParam1 = (DWORD)mh32;
818 mh32->dwFlags = mh16->dwFlags;
819 mh32->dwOffset = mh16->dwOffset;
820 if (mh32->reserved >= sizeof(MIDIHDR))
821 mh32->dwOffset = mh16->dwOffset;
822 } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
823 /* initial map is: 16 => 32 */
824 LPMIDIHDR mh32 = (LPMIDIHDR)(dwParam1);
825 SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
826 LPMIDIHDR mh16 = MapSL(segmh16);
828 dwParam1 = (DWORD)segmh16;
829 mh16->dwFlags = mh32->dwFlags;
830 if (mh16->reserved >= sizeof(MIDIHDR))
831 mh16->dwOffset = mh32->dwOffset;
833 /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
834 break;
835 /* case MOM_POSITIONCB: */
836 default:
837 ERR("Unknown msg %u\n", uMsg);
840 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
843 /* =================================
844 * W A V E I N M A P P E R S
845 * ================================= */
847 /**************************************************************************
848 * MMDRV_WaveIn_Map16To32A [internal]
850 static MMDRV_MapType MMDRV_WaveIn_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
852 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
854 switch (wMsg) {
855 case WIDM_GETNUMDEVS:
856 case WIDM_RESET:
857 case WIDM_START:
858 case WIDM_STOP:
859 ret = MMDRV_MAP_OK;
860 break;
861 case WIDM_OPEN:
862 case WIDM_CLOSE:
863 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
864 break;
865 case WIDM_GETDEVCAPS:
867 LPWAVEINCAPSA wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSA));
868 LPWAVEINCAPS16 wic16 = MapSL(*lpParam1);
870 if (wic32) {
871 *(LPWAVEINCAPS16*)wic32 = wic16;
872 wic32 = (LPWAVEINCAPSA)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16));
873 *lpParam1 = (DWORD)wic32;
874 *lpParam2 = sizeof(WAVEINCAPSA);
876 ret = MMDRV_MAP_OKMEM;
877 } else {
878 ret = MMDRV_MAP_NOMEM;
881 break;
882 case WIDM_GETPOS:
884 LPMMTIME mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
885 LPMMTIME16 mmt16 = MapSL(*lpParam1);
887 if (mmt32) {
888 *(LPMMTIME16*)mmt32 = mmt16;
889 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
891 mmt32->wType = mmt16->wType;
892 *lpParam1 = (DWORD)mmt32;
893 *lpParam2 = sizeof(MMTIME);
895 ret = MMDRV_MAP_OKMEM;
896 } else {
897 ret = MMDRV_MAP_NOMEM;
900 break;
901 case WIDM_PREPARE:
903 LPWAVEHDR wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
904 LPWAVEHDR wh16 = MapSL(*lpParam1);
906 if (wh32) {
907 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
908 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
909 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
910 wh32->dwBufferLength = wh16->dwBufferLength;
911 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
912 wh32->dwUser = wh16->dwUser;
913 wh32->dwFlags = wh16->dwFlags;
914 wh32->dwLoops = wh16->dwLoops;
915 /* FIXME: nothing on wh32->lpNext */
916 /* could link the wh32->lpNext at this level for memory house keeping */
917 wh16->lpNext = wh32; /* for reuse in unprepare and write */
918 *lpParam1 = (DWORD)wh32;
919 *lpParam2 = sizeof(WAVEHDR);
921 ret = MMDRV_MAP_OKMEM;
922 } else {
923 ret = MMDRV_MAP_NOMEM;
926 break;
927 case WIDM_ADDBUFFER:
928 case WIDM_UNPREPARE:
930 LPWAVEHDR wh16 = MapSL(*lpParam1);
931 LPWAVEHDR wh32 = (LPWAVEHDR)wh16->lpNext;
933 *lpParam1 = (DWORD)wh32;
934 *lpParam2 = sizeof(WAVEHDR);
935 /* dwBufferLength can be reduced between prepare & write */
936 if (wMsg == WIDM_ADDBUFFER && wh32->dwBufferLength < wh16->dwBufferLength) {
937 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
938 wh32->dwBufferLength, wh16->dwBufferLength);
939 } else
940 wh32->dwBufferLength = wh16->dwBufferLength;
941 ret = MMDRV_MAP_OKMEM;
943 break;
944 case WIDM_MAPPER_STATUS:
945 /* just a single DWORD */
946 *lpParam2 = (DWORD)MapSL(*lpParam2);
947 ret = MMDRV_MAP_OK;
948 break;
949 default:
950 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
951 break;
953 return ret;
956 /**************************************************************************
957 * MMDRV_WaveIn_UnMap16To32A [internal]
959 static MMDRV_MapType MMDRV_WaveIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
961 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
963 switch (wMsg) {
964 case WIDM_GETNUMDEVS:
965 case WIDM_RESET:
966 case WIDM_START:
967 case WIDM_STOP:
968 case WIDM_MAPPER_STATUS:
969 ret = MMDRV_MAP_OK;
970 break;
971 case WIDM_OPEN:
972 case WIDM_CLOSE:
973 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
974 break;
975 case WIDM_GETDEVCAPS:
977 LPWAVEINCAPSA wic32 = (LPWAVEINCAPSA)(*lpParam1);
978 LPWAVEINCAPS16 wic16 = *(LPWAVEINCAPS16*)((LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
980 wic16->wMid = wic32->wMid;
981 wic16->wPid = wic32->wPid;
982 wic16->vDriverVersion = wic32->vDriverVersion;
983 strcpy(wic16->szPname, wic32->szPname);
984 wic16->dwFormats = wic32->dwFormats;
985 wic16->wChannels = wic32->wChannels;
986 HeapFree(GetProcessHeap(), 0, (LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
987 ret = MMDRV_MAP_OK;
989 break;
990 case WIDM_GETPOS:
992 LPMMTIME mmt32 = (LPMMTIME)(*lpParam1);
993 LPMMTIME16 mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
995 MMSYSTEM_MMTIME32to16(mmt16, mmt32);
996 HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
997 ret = MMDRV_MAP_OK;
999 break;
1000 case WIDM_ADDBUFFER:
1001 case WIDM_PREPARE:
1002 case WIDM_UNPREPARE:
1004 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
1005 LPWAVEHDR wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
1007 assert(wh16->lpNext == wh32);
1008 wh16->dwBufferLength = wh32->dwBufferLength;
1009 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1010 wh16->dwUser = wh32->dwUser;
1011 wh16->dwFlags = wh32->dwFlags;
1012 wh16->dwLoops = wh32->dwLoops;
1014 if (wMsg == WIDM_UNPREPARE) {
1015 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
1016 wh16->lpNext = 0;
1018 ret = MMDRV_MAP_OK;
1020 break;
1021 default:
1022 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1023 break;
1025 return ret;
1028 /**************************************************************************
1029 * MMDRV_WaveIn_Map32ATo16 [internal]
1031 static MMDRV_MapType MMDRV_WaveIn_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1033 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
1035 switch (wMsg) {
1036 case WIDM_CLOSE:
1037 case WIDM_GETNUMDEVS:
1038 case WIDM_RESET:
1039 case WIDM_START:
1040 case WIDM_STOP:
1041 ret = MMDRV_MAP_OK;
1042 break;
1044 case WIDM_OPEN:
1046 LPWAVEOPENDESC wod32 = (LPWAVEOPENDESC)*lpParam1;
1047 int sz = sizeof(WAVEFORMATEX);
1048 LPVOID ptr;
1049 LPWAVEOPENDESC16 wod16;
1051 /* allocated data are mapped as follows:
1052 LPWAVEOPENDESC ptr to orig lParam1
1053 DWORD orig dwUser, which is a pointer to DWORD:driver dwInstance
1054 DWORD dwUser passed to driver
1055 WAVEOPENDESC16 wod16: openDesc passed to driver
1056 WAVEFORMATEX openDesc->lpFormat passed to driver
1057 xxx extra bytes to WAVEFORMATEX
1059 if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1060 TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag);
1061 sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize;
1064 ptr = HeapAlloc( GetProcessHeap(), 0,
1065 sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
1067 if (ptr) {
1068 SEGPTR seg_ptr = MapLS( ptr );
1069 *(LPWAVEOPENDESC*)ptr = wod32;
1070 *(LPDWORD)((char*)ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
1071 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
1073 wod16->hWave = HWAVE_16(wod32->hWave);
1074 wod16->lpFormat = (LPWAVEFORMATEX)(seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16));
1075 memcpy(wod16 + 1, wod32->lpFormat, sz);
1077 wod16->dwCallback = wod32->dwCallback;
1078 wod16->dwInstance = wod32->dwInstance;
1079 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
1080 wod16->dnDevNode = wod32->dnDevNode;
1082 *lpParam1 = seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
1083 *lpdwUser = seg_ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
1085 ret = MMDRV_MAP_OKMEM;
1086 } else {
1087 ret = MMDRV_MAP_NOMEM;
1090 break;
1091 case WIDM_PREPARE:
1093 LPWAVEHDR wh32 = (LPWAVEHDR)*lpParam1;
1094 LPWAVEHDR wh16;
1095 LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
1096 sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
1098 if (ptr) {
1099 SEGPTR seg_ptr = MapLS( ptr );
1100 *(LPWAVEHDR*)ptr = wh32;
1101 wh16 = (LPWAVEHDR)((LPSTR)ptr + sizeof(LPWAVEHDR));
1102 wh16->lpData = (LPSTR)seg_ptr + sizeof(LPWAVEHDR) + sizeof(WAVEHDR);
1103 /* data will be copied on WODM_WRITE */
1104 wh16->dwBufferLength = wh32->dwBufferLength;
1105 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1106 wh16->dwUser = wh32->dwUser;
1107 wh16->dwFlags = wh32->dwFlags;
1108 wh16->dwLoops = wh32->dwLoops;
1109 /* FIXME: nothing on wh32->lpNext */
1110 /* could link the wh32->lpNext at this level for memory house keeping */
1111 wh32->lpNext = wh16; /* for reuse in unprepare and write */
1112 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1113 seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1114 wh32->dwBufferLength, (DWORD)wh32->lpData);
1115 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1116 *lpParam2 = sizeof(WAVEHDR);
1118 ret = MMDRV_MAP_OKMEM;
1119 } else {
1120 ret = MMDRV_MAP_NOMEM;
1123 break;
1124 case WIDM_ADDBUFFER:
1125 case WIDM_UNPREPARE:
1127 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
1128 LPWAVEHDR wh16 = wh32->lpNext;
1129 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1130 SEGPTR seg_ptr = MapLS( ptr );
1132 assert(*(LPWAVEHDR*)ptr == wh32);
1134 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1135 seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1136 wh32->dwBufferLength, (DWORD)wh32->lpData);
1138 if (wMsg == WIDM_ADDBUFFER)
1139 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
1141 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1142 *lpParam2 = sizeof(WAVEHDR);
1143 /* dwBufferLength can be reduced between prepare & write */
1144 if (wMsg == WIDM_ADDBUFFER && wh16->dwBufferLength < wh32->dwBufferLength) {
1145 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
1146 wh16->dwBufferLength, wh32->dwBufferLength);
1147 } else
1148 wh16->dwBufferLength = wh32->dwBufferLength;
1149 ret = MMDRV_MAP_OKMEM;
1151 break;
1152 case WIDM_GETDEVCAPS:
1154 LPWAVEINCAPSA wic32 = (LPWAVEINCAPSA)*lpParam1;
1155 LPSTR ptr = HeapAlloc( GetProcessHeap(), 0 ,sizeof(LPWAVEINCAPSA) + sizeof(WAVEINCAPS16));
1157 if (ptr) {
1158 *(LPWAVEINCAPSA*)ptr = wic32;
1159 ret = MMDRV_MAP_OKMEM;
1160 } else {
1161 ret = MMDRV_MAP_NOMEM;
1163 *lpParam1 = MapLS(ptr) + sizeof(LPWAVEINCAPSA);
1164 *lpParam2 = sizeof(WAVEINCAPS16);
1166 break;
1167 case WIDM_GETPOS:
1169 LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1170 LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMMTIME) + sizeof(MMTIME16));
1171 LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1173 if (ptr) {
1174 *(LPMMTIME*)ptr = mmt32;
1175 mmt16->wType = mmt32->wType;
1176 ret = MMDRV_MAP_OKMEM;
1177 } else {
1178 ret = MMDRV_MAP_NOMEM;
1180 *lpParam1 = MapLS(ptr) + sizeof(LPMMTIME);
1181 *lpParam2 = sizeof(MMTIME16);
1183 break;
1184 case DRVM_MAPPER_STATUS:
1186 LPDWORD p32 = (LPDWORD)*lpParam2;
1187 *lpParam2 = MapLS(p32);
1188 ret = MMDRV_MAP_OKMEM;
1190 break;
1191 default:
1192 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1193 break;
1195 return ret;
1198 /**************************************************************************
1199 * MMDRV_WaveIn_UnMap32ATo16 [internal]
1201 static MMDRV_MapType MMDRV_WaveIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1203 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
1205 switch (wMsg) {
1206 case WIDM_CLOSE:
1207 case WIDM_GETNUMDEVS:
1208 case WIDM_RESET:
1209 case WIDM_START:
1210 case WIDM_STOP:
1211 ret = MMDRV_MAP_OK;
1212 break;
1214 case WIDM_OPEN:
1216 LPWAVEOPENDESC16 wod16 = MapSL(*lpParam1);
1217 LPSTR ptr = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1218 LPWAVEOPENDESC wod32 = *(LPWAVEOPENDESC*)ptr;
1220 UnMapLS( *lpParam1 );
1221 wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1222 **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1223 HeapFree( GetProcessHeap(), 0, ptr );
1224 ret = MMDRV_MAP_OK;
1226 break;
1228 case WIDM_ADDBUFFER:
1229 case WIDM_PREPARE:
1230 case WIDM_UNPREPARE:
1232 LPWAVEHDR wh16 = MapSL(*lpParam1);
1233 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1234 LPWAVEHDR wh32 = *(LPWAVEHDR*)ptr;
1236 assert(wh32->lpNext == wh16);
1237 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1238 wh32->dwUser = wh16->dwUser;
1239 wh32->dwFlags = wh16->dwFlags;
1240 wh32->dwLoops = wh16->dwLoops;
1241 UnMapLS( *lpParam1 );
1243 if (wMsg == WIDM_UNPREPARE) {
1244 HeapFree( GetProcessHeap(), 0, ptr );
1245 wh32->lpNext = 0;
1247 ret = MMDRV_MAP_OK;
1249 break;
1250 case WIDM_GETDEVCAPS:
1252 LPWAVEINCAPS16 wic16 = MapSL(*lpParam1);
1253 LPSTR ptr = (LPSTR)wic16 - sizeof(LPWAVEINCAPSA);
1254 LPWAVEINCAPSA wic32 = *(LPWAVEINCAPSA*)ptr;
1256 wic32->wMid = wic16->wMid;
1257 wic32->wPid = wic16->wPid;
1258 wic32->vDriverVersion = wic16->vDriverVersion;
1259 strcpy(wic32->szPname, wic16->szPname);
1260 wic32->dwFormats = wic16->dwFormats;
1261 wic32->wChannels = wic16->wChannels;
1262 UnMapLS( *lpParam1 );
1263 HeapFree( GetProcessHeap(), 0, ptr );
1264 ret = MMDRV_MAP_OK;
1266 break;
1267 case WIDM_GETPOS:
1269 LPMMTIME16 mmt16 = MapSL(*lpParam1);
1270 LPSTR ptr = (LPSTR)mmt16 - sizeof(LPMMTIME);
1271 LPMMTIME mmt32 = *(LPMMTIME*)ptr;
1273 MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1274 UnMapLS( *lpParam1 );
1275 HeapFree( GetProcessHeap(), 0, ptr );
1276 ret = MMDRV_MAP_OK;
1278 break;
1279 case DRVM_MAPPER_STATUS:
1281 UnMapLS( *lpParam2 );
1282 ret = MMDRV_MAP_OK;
1284 break;
1285 default:
1286 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1287 break;
1289 return ret;
1292 /**************************************************************************
1293 * MMDRV_WaveIn_Callback [internal]
1295 static void CALLBACK MMDRV_WaveIn_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1297 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
1299 switch (uMsg) {
1300 case WIM_OPEN:
1301 case WIM_CLOSE:
1302 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1303 break;
1304 case WIM_DATA:
1305 if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
1306 /* initial map is: 32 => 16 */
1307 LPWAVEHDR wh16 = MapSL(dwParam1);
1308 LPWAVEHDR wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1310 dwParam1 = (DWORD)wh32;
1311 wh32->dwFlags = wh16->dwFlags;
1312 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1313 } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
1314 /* initial map is: 16 => 32 */
1315 LPWAVEHDR wh32 = (LPWAVEHDR)(dwParam1);
1316 SEGPTR segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1317 LPWAVEHDR wh16 = MapSL(segwh16);
1319 dwParam1 = (DWORD)segwh16;
1320 wh16->dwFlags = wh32->dwFlags;
1321 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1323 /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1324 break;
1325 default:
1326 ERR("Unknown msg %u\n", uMsg);
1329 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1332 /* =================================
1333 * W A V E O U T M A P P E R S
1334 * ================================= */
1336 /**************************************************************************
1337 * MMDRV_WaveOut_Map16To32A [internal]
1339 static MMDRV_MapType MMDRV_WaveOut_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1341 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
1343 switch (wMsg) {
1344 /* nothing to do */
1345 case WODM_BREAKLOOP:
1346 case WODM_CLOSE:
1347 case WODM_GETNUMDEVS:
1348 case WODM_PAUSE:
1349 case WODM_RESET:
1350 case WODM_RESTART:
1351 case WODM_SETPITCH:
1352 case WODM_SETPLAYBACKRATE:
1353 case WODM_SETVOLUME:
1354 ret = MMDRV_MAP_OK;
1355 break;
1357 case WODM_GETPITCH:
1358 case WODM_GETPLAYBACKRATE:
1359 case WODM_GETVOLUME:
1360 case WODM_OPEN:
1361 FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
1362 break;
1364 case WODM_GETDEVCAPS:
1366 LPWAVEOUTCAPSA woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSA));
1367 LPWAVEOUTCAPS16 woc16 = MapSL(*lpParam1);
1369 if (woc32) {
1370 *(LPWAVEOUTCAPS16*)woc32 = woc16;
1371 woc32 = (LPWAVEOUTCAPSA)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16));
1372 *lpParam1 = (DWORD)woc32;
1373 *lpParam2 = sizeof(WAVEOUTCAPSA);
1375 ret = MMDRV_MAP_OKMEM;
1376 } else {
1377 ret = MMDRV_MAP_NOMEM;
1380 break;
1381 case WODM_GETPOS:
1383 LPMMTIME mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
1384 LPMMTIME16 mmt16 = MapSL(*lpParam1);
1386 if (mmt32) {
1387 *(LPMMTIME16*)mmt32 = mmt16;
1388 mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));
1390 mmt32->wType = mmt16->wType;
1391 *lpParam1 = (DWORD)mmt32;
1392 *lpParam2 = sizeof(MMTIME);
1394 ret = MMDRV_MAP_OKMEM;
1395 } else {
1396 ret = MMDRV_MAP_NOMEM;
1399 break;
1400 case WODM_PREPARE:
1402 LPWAVEHDR wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
1403 LPWAVEHDR wh16 = MapSL(*lpParam1);
1405 if (wh32) {
1406 *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
1407 wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
1408 wh32->lpData = MapSL((SEGPTR)wh16->lpData);
1409 wh32->dwBufferLength = wh16->dwBufferLength;
1410 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1411 wh32->dwUser = wh16->dwUser;
1412 wh32->dwFlags = wh16->dwFlags;
1413 wh32->dwLoops = wh16->dwLoops;
1414 /* FIXME: nothing on wh32->lpNext */
1415 /* could link the wh32->lpNext at this level for memory house keeping */
1416 wh16->lpNext = wh32; /* for reuse in unprepare and write */
1417 *lpParam1 = (DWORD)wh32;
1418 *lpParam2 = sizeof(WAVEHDR);
1420 ret = MMDRV_MAP_OKMEM;
1421 } else {
1422 ret = MMDRV_MAP_NOMEM;
1425 break;
1426 case WODM_UNPREPARE:
1427 case WODM_WRITE:
1429 LPWAVEHDR wh16 = MapSL(*lpParam1);
1430 LPWAVEHDR wh32 = (LPWAVEHDR)wh16->lpNext;
1432 *lpParam1 = (DWORD)wh32;
1433 *lpParam2 = sizeof(WAVEHDR);
1434 /* dwBufferLength can be reduced between prepare & write */
1435 if (wMsg == WODM_WRITE && wh32->dwBufferLength < wh16->dwBufferLength) {
1436 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
1437 wh32->dwBufferLength, wh16->dwBufferLength);
1438 } else
1439 wh32->dwBufferLength = wh16->dwBufferLength;
1440 ret = MMDRV_MAP_OKMEM;
1442 break;
1443 case WODM_MAPPER_STATUS:
1444 *lpParam2 = (DWORD)MapSL(*lpParam2);
1445 ret = MMDRV_MAP_OK;
1446 break;
1447 default:
1448 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1449 break;
1451 return ret;
1454 /**************************************************************************
1455 * MMDRV_WaveOut_UnMap16To32A [internal]
1457 static MMDRV_MapType MMDRV_WaveOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1459 MMDRV_MapType ret = MMDRV_MAP_MSGERROR;
1461 switch (wMsg) {
1462 /* nothing to do */
1463 case WODM_BREAKLOOP:
1464 case WODM_CLOSE:
1465 case WODM_GETNUMDEVS:
1466 case WODM_PAUSE:
1467 case WODM_RESET:
1468 case WODM_RESTART:
1469 case WODM_SETPITCH:
1470 case WODM_SETPLAYBACKRATE:
1471 case WODM_SETVOLUME:
1472 case WODM_MAPPER_STATUS:
1473 ret = MMDRV_MAP_OK;
1474 break;
1476 case WODM_GETPITCH:
1477 case WODM_GETPLAYBACKRATE:
1478 case WODM_GETVOLUME:
1479 case WODM_OPEN:
1480 FIXME("Shouldn't be used: those 16 bit functions use the 32 bit interface\n");
1481 break;
1483 case WODM_GETDEVCAPS:
1485 LPWAVEOUTCAPSA woc32 = (LPWAVEOUTCAPSA)(*lpParam1);
1486 LPWAVEOUTCAPS16 woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1488 woc16->wMid = woc32->wMid;
1489 woc16->wPid = woc32->wPid;
1490 woc16->vDriverVersion = woc32->vDriverVersion;
1491 strcpy(woc16->szPname, woc32->szPname);
1492 woc16->dwFormats = woc32->dwFormats;
1493 woc16->wChannels = woc32->wChannels;
1494 woc16->dwSupport = woc32->dwSupport;
1495 HeapFree(GetProcessHeap(), 0, (LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
1496 ret = MMDRV_MAP_OK;
1498 break;
1499 case WODM_GETPOS:
1501 LPMMTIME mmt32 = (LPMMTIME)(*lpParam1);
1502 LPMMTIME16 mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));
1504 MMSYSTEM_MMTIME32to16(mmt16, mmt32);
1505 HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
1506 ret = MMDRV_MAP_OK;
1508 break;
1509 case WODM_PREPARE:
1510 case WODM_UNPREPARE:
1511 case WODM_WRITE:
1513 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
1514 LPWAVEHDR wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));
1516 assert(wh16->lpNext == wh32);
1517 wh16->dwBufferLength = wh32->dwBufferLength;
1518 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1519 wh16->dwUser = wh32->dwUser;
1520 wh16->dwFlags = wh32->dwFlags;
1521 wh16->dwLoops = wh32->dwLoops;
1523 if (wMsg == WODM_UNPREPARE) {
1524 HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
1525 wh16->lpNext = 0;
1527 ret = MMDRV_MAP_OK;
1529 break;
1530 default:
1531 FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
1532 break;
1534 return ret;
1537 /**************************************************************************
1538 * MMDRV_WaveOut_Map32ATo16 [internal]
1540 static MMDRV_MapType MMDRV_WaveOut_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1542 MMDRV_MapType ret;
1544 switch (wMsg) {
1545 /* nothing to do */
1546 case WODM_BREAKLOOP:
1547 case WODM_CLOSE:
1548 case WODM_GETNUMDEVS:
1549 case WODM_PAUSE:
1550 case WODM_RESET:
1551 case WODM_RESTART:
1552 case WODM_SETPITCH:
1553 case WODM_SETPLAYBACKRATE:
1554 case WODM_SETVOLUME:
1555 ret = MMDRV_MAP_OK;
1556 break;
1558 case WODM_GETDEVCAPS:
1560 LPWAVEOUTCAPSA woc32 = (LPWAVEOUTCAPSA)*lpParam1;
1561 LPSTR ptr = HeapAlloc( GetProcessHeap(), 0,
1562 sizeof(LPWAVEOUTCAPSA) + sizeof(WAVEOUTCAPS16));
1564 if (ptr) {
1565 *(LPWAVEOUTCAPSA*)ptr = woc32;
1566 ret = MMDRV_MAP_OKMEM;
1567 } else {
1568 ret = MMDRV_MAP_NOMEM;
1570 *lpParam1 = MapLS(ptr) + sizeof(LPWAVEOUTCAPSA);
1571 *lpParam2 = sizeof(WAVEOUTCAPS16);
1573 break;
1574 case WODM_GETPITCH:
1575 FIXME("NIY: no conversion yet\n");
1576 ret = MMDRV_MAP_MSGERROR;
1577 break;
1578 case WODM_GETPLAYBACKRATE:
1579 FIXME("NIY: no conversion yet\n");
1580 ret = MMDRV_MAP_MSGERROR;
1581 break;
1582 case WODM_GETPOS:
1584 LPMMTIME mmt32 = (LPMMTIME)*lpParam1;
1585 LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMMTIME) + sizeof(MMTIME16));
1586 LPMMTIME16 mmt16 = (LPMMTIME16)(ptr + sizeof(LPMMTIME));
1588 if (ptr) {
1589 *(LPMMTIME*)ptr = mmt32;
1590 mmt16->wType = mmt32->wType;
1591 ret = MMDRV_MAP_OKMEM;
1592 } else {
1593 ret = MMDRV_MAP_NOMEM;
1595 *lpParam1 = MapLS(ptr) + sizeof(LPMMTIME);
1596 *lpParam2 = sizeof(MMTIME16);
1598 break;
1599 case WODM_GETVOLUME:
1600 FIXME("NIY: no conversion yet\n");
1601 ret = MMDRV_MAP_MSGERROR;
1602 break;
1603 case WODM_OPEN:
1605 LPWAVEOPENDESC wod32 = (LPWAVEOPENDESC)*lpParam1;
1606 int sz = sizeof(WAVEFORMATEX);
1607 LPVOID ptr;
1608 LPWAVEOPENDESC16 wod16;
1610 /* allocated data are mapped as follows:
1611 LPWAVEOPENDESC ptr to orig lParam1
1612 DWORD orig dwUser, which is a pointer to DWORD:driver dwInstance
1613 DWORD dwUser passed to driver
1614 WAVEOPENDESC16 wod16: openDesc passed to driver
1615 WAVEFORMATEX openDesc->lpFormat passed to driver
1616 xxx extra bytes to WAVEFORMATEX
1618 if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1619 TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag);
1620 sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize;
1623 ptr = HeapAlloc( GetProcessHeap(), 0,
1624 sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16) + sz);
1626 if (ptr) {
1627 SEGPTR seg_ptr = MapLS( ptr );
1628 *(LPWAVEOPENDESC*)ptr = wod32;
1629 *(LPDWORD)((char*)ptr + sizeof(LPWAVEOPENDESC)) = *lpdwUser;
1630 wod16 = (LPWAVEOPENDESC16)((LPSTR)ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD));
1632 wod16->hWave = HWAVE_16(wod32->hWave);
1633 wod16->lpFormat = (LPWAVEFORMATEX)(seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD) + sizeof(WAVEOPENDESC16));
1634 memcpy(wod16 + 1, wod32->lpFormat, sz);
1636 wod16->dwCallback = wod32->dwCallback;
1637 wod16->dwInstance = wod32->dwInstance;
1638 wod16->uMappedDeviceID = wod32->uMappedDeviceID;
1639 wod16->dnDevNode = wod32->dnDevNode;
1641 *lpParam1 = seg_ptr + sizeof(LPWAVEOPENDESC) + 2*sizeof(DWORD);
1642 *lpdwUser = seg_ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD);
1644 ret = MMDRV_MAP_OKMEM;
1645 } else {
1646 ret = MMDRV_MAP_NOMEM;
1649 break;
1650 case WODM_PREPARE:
1652 LPWAVEHDR wh32 = (LPWAVEHDR)*lpParam1;
1653 LPWAVEHDR wh16;
1654 LPVOID ptr = HeapAlloc( GetProcessHeap(), 0,
1655 sizeof(LPWAVEHDR) + sizeof(WAVEHDR) + wh32->dwBufferLength);
1657 if (ptr) {
1658 SEGPTR seg_ptr = MapLS( ptr );
1659 *(LPWAVEHDR*)ptr = wh32;
1660 wh16 = (LPWAVEHDR)((LPSTR)ptr + sizeof(LPWAVEHDR));
1661 wh16->lpData = (LPSTR)seg_ptr + sizeof(LPWAVEHDR) + sizeof(WAVEHDR);
1662 /* data will be copied on WODM_WRITE */
1663 wh16->dwBufferLength = wh32->dwBufferLength;
1664 wh16->dwBytesRecorded = wh32->dwBytesRecorded;
1665 wh16->dwUser = wh32->dwUser;
1666 wh16->dwFlags = wh32->dwFlags;
1667 wh16->dwLoops = wh32->dwLoops;
1668 /* FIXME: nothing on wh32->lpNext */
1669 /* could link the wh32->lpNext at this level for memory house keeping */
1670 wh32->lpNext = wh16; /* for reuse in unprepare and write */
1671 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1672 seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1673 wh32->dwBufferLength, (DWORD)wh32->lpData);
1674 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1675 *lpParam2 = sizeof(WAVEHDR);
1677 ret = MMDRV_MAP_OKMEM;
1678 } else {
1679 ret = MMDRV_MAP_NOMEM;
1682 break;
1683 case WODM_UNPREPARE:
1684 case WODM_WRITE:
1686 LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1);
1687 LPWAVEHDR wh16 = wh32->lpNext;
1688 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1689 SEGPTR seg_ptr = MapLS( ptr );
1691 assert(*(LPWAVEHDR*)ptr == wh32);
1693 TRACE("wh16=%08lx wh16->lpData=%08lx wh32->buflen=%lu wh32->lpData=%08lx\n",
1694 seg_ptr + sizeof(LPWAVEHDR), (DWORD)wh16->lpData,
1695 wh32->dwBufferLength, (DWORD)wh32->lpData);
1697 if (wMsg == WODM_WRITE)
1698 memcpy((LPSTR)wh16 + sizeof(WAVEHDR), wh32->lpData, wh32->dwBufferLength);
1700 *lpParam1 = seg_ptr + sizeof(LPWAVEHDR);
1701 *lpParam2 = sizeof(WAVEHDR);
1702 /* dwBufferLength can be reduced between prepare & write */
1703 if (wMsg == WODM_WRITE && wh16->dwBufferLength < wh32->dwBufferLength) {
1704 ERR("Size of buffer has been increased from %ld to %ld, keeping initial value\n",
1705 wh16->dwBufferLength, wh32->dwBufferLength);
1706 } else
1707 wh16->dwBufferLength = wh32->dwBufferLength;
1708 ret = MMDRV_MAP_OKMEM;
1710 break;
1711 case DRVM_MAPPER_STATUS:
1713 LPDWORD p32 = (LPDWORD)*lpParam2;
1714 *lpParam2 = MapLS(p32);
1715 ret = MMDRV_MAP_OKMEM;
1717 break;
1718 default:
1719 FIXME("NIY: no conversion yet\n");
1720 ret = MMDRV_MAP_MSGERROR;
1721 break;
1723 return ret;
1726 /**************************************************************************
1727 * MMDRV_WaveOut_UnMap32ATo16 [internal]
1729 static MMDRV_MapType MMDRV_WaveOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2)
1731 MMDRV_MapType ret;
1733 switch (wMsg) {
1734 /* nothing to do */
1735 case WODM_BREAKLOOP:
1736 case WODM_CLOSE:
1737 case WODM_GETNUMDEVS:
1738 case WODM_PAUSE:
1739 case WODM_RESET:
1740 case WODM_RESTART:
1741 case WODM_SETPITCH:
1742 case WODM_SETPLAYBACKRATE:
1743 case WODM_SETVOLUME:
1744 ret = MMDRV_MAP_OK;
1745 break;
1747 case WODM_GETDEVCAPS:
1749 LPWAVEOUTCAPS16 woc16 = MapSL(*lpParam1);
1750 LPSTR ptr = (LPSTR)woc16 - sizeof(LPWAVEOUTCAPSA);
1751 LPWAVEOUTCAPSA woc32 = *(LPWAVEOUTCAPSA*)ptr;
1753 woc32->wMid = woc16->wMid;
1754 woc32->wPid = woc16->wPid;
1755 woc32->vDriverVersion = woc16->vDriverVersion;
1756 strcpy(woc32->szPname, woc16->szPname);
1757 woc32->dwFormats = woc16->dwFormats;
1758 woc32->wChannels = woc16->wChannels;
1759 woc32->dwSupport = woc16->dwSupport;
1760 UnMapLS( *lpParam1 );
1761 HeapFree( GetProcessHeap(), 0, ptr );
1762 ret = MMDRV_MAP_OK;
1764 break;
1765 case WODM_GETPITCH:
1766 FIXME("NIY: no conversion yet\n");
1767 ret = MMDRV_MAP_MSGERROR;
1768 break;
1769 case WODM_GETPLAYBACKRATE:
1770 FIXME("NIY: no conversion yet\n");
1771 ret = MMDRV_MAP_MSGERROR;
1772 break;
1773 case WODM_GETPOS:
1775 LPMMTIME16 mmt16 = MapSL(*lpParam1);
1776 LPSTR ptr = (LPSTR)mmt16 - sizeof(LPMMTIME);
1777 LPMMTIME mmt32 = *(LPMMTIME*)ptr;
1779 MMSYSTEM_MMTIME16to32(mmt32, mmt16);
1780 UnMapLS( *lpParam1 );
1781 HeapFree( GetProcessHeap(), 0, ptr );
1782 ret = MMDRV_MAP_OK;
1784 break;
1785 case WODM_OPEN:
1787 LPWAVEOPENDESC16 wod16 = MapSL(*lpParam1);
1788 LPSTR ptr = (LPSTR)wod16 - sizeof(LPWAVEOPENDESC) - 2*sizeof(DWORD);
1789 LPWAVEOPENDESC wod32 = *(LPWAVEOPENDESC*)ptr;
1791 wod32->uMappedDeviceID = wod16->uMappedDeviceID;
1792 **(DWORD**)(ptr + sizeof(LPWAVEOPENDESC)) = *(LPDWORD)(ptr + sizeof(LPWAVEOPENDESC) + sizeof(DWORD));
1793 UnMapLS( *lpParam1 );
1794 HeapFree( GetProcessHeap(), 0, ptr );
1795 ret = MMDRV_MAP_OK;
1797 break;
1798 case WODM_PREPARE:
1799 case WODM_UNPREPARE:
1800 case WODM_WRITE:
1802 LPWAVEHDR wh16 = MapSL(*lpParam1);
1803 LPSTR ptr = (LPSTR)wh16 - sizeof(LPWAVEHDR);
1804 LPWAVEHDR wh32 = *(LPWAVEHDR*)ptr;
1806 assert(wh32->lpNext == wh16);
1807 wh32->dwBytesRecorded = wh16->dwBytesRecorded;
1808 wh32->dwUser = wh16->dwUser;
1809 wh32->dwFlags = wh16->dwFlags;
1810 wh32->dwLoops = wh16->dwLoops;
1812 UnMapLS( *lpParam1 );
1813 if (wMsg == WODM_UNPREPARE) {
1814 HeapFree( GetProcessHeap(), 0, ptr );
1815 wh32->lpNext = 0;
1817 ret = MMDRV_MAP_OK;
1819 break;
1820 case WODM_GETVOLUME:
1821 FIXME("NIY: no conversion yet\n");
1822 ret = MMDRV_MAP_MSGERROR;
1823 break;
1824 case DRVM_MAPPER_STATUS:
1826 UnMapLS( *lpParam2 );
1827 ret = MMDRV_MAP_OK;
1829 break;
1830 default:
1831 FIXME("NIY: no conversion yet\n");
1832 ret = MMDRV_MAP_MSGERROR;
1833 break;
1835 return ret;
1838 /**************************************************************************
1839 * MMDRV_WaveOut_Callback [internal]
1841 static void CALLBACK MMDRV_WaveOut_Callback(HDRVR hDev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
1843 LPWINE_MLD mld = (LPWINE_MLD)dwInstance;
1845 switch (uMsg) {
1846 case WOM_OPEN:
1847 case WOM_CLOSE:
1848 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
1849 break;
1850 case WOM_DONE:
1851 if (mld->bFrom32 && !MMDrvs[mld->mmdIndex].bIs32) {
1852 /* initial map is: 32 => 16 */
1853 LPWAVEHDR wh16 = MapSL(dwParam1);
1854 LPWAVEHDR wh32 = *(LPWAVEHDR*)((LPSTR)wh16 - sizeof(LPWAVEHDR));
1856 dwParam1 = (DWORD)wh32;
1857 wh32->dwFlags = wh16->dwFlags;
1858 } else if (!mld->bFrom32 && MMDrvs[mld->mmdIndex].bIs32) {
1859 /* initial map is: 16 => 32 */
1860 LPWAVEHDR wh32 = (LPWAVEHDR)(dwParam1);
1861 SEGPTR segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
1862 LPWAVEHDR wh16 = MapSL(segwh16);
1864 dwParam1 = (DWORD)segwh16;
1865 wh16->dwFlags = wh32->dwFlags;
1867 /* else { 16 => 16 or 32 => 32, nothing to do, same struct is kept }*/
1868 break;
1869 default:
1870 ERR("Unknown msg %u\n", uMsg);
1873 MMDRV_Callback(mld, hDev, uMsg, dwParam1, dwParam2);
1876 #define A(_x,_y) {#_y, _x, \
1877 MMDRV_##_y##_Map16To32A, MMDRV_##_y##_UnMap16To32A, \
1878 MMDRV_##_y##_Map32ATo16, MMDRV_##_y##_UnMap32ATo16, \
1879 MMDRV_##_y##_Callback, 0, NULL, -1}
1881 /* Note: the indices of this array must match the definitions
1882 * of the MMDRV_???? manifest constants
1884 static WINE_LLTYPE llTypes[MMDRV_MAX] = {
1885 A(TRUE, Aux),
1886 A(FALSE, Mixer),
1887 A(TRUE, MidiIn),
1888 A(TRUE, MidiOut),
1889 A(TRUE, WaveIn),
1890 A(TRUE, WaveOut),
1892 #undef A
1894 /**************************************************************************
1895 * MMDRV_GetNum [internal]
1897 UINT MMDRV_GetNum(UINT type)
1899 assert(type < MMDRV_MAX);
1900 return llTypes[type].wMaxId;
1903 /**************************************************************************
1904 * WINE_Message [internal]
1906 DWORD MMDRV_Message(LPWINE_MLD mld, WORD wMsg, DWORD dwParam1,
1907 DWORD dwParam2, BOOL bFrom32)
1909 LPWINE_MM_DRIVER lpDrv;
1910 DWORD ret;
1911 WINE_MM_DRIVER_PART* part;
1912 WINE_LLTYPE* llType = &llTypes[mld->type];
1913 MMDRV_MapType map;
1914 int devID;
1916 TRACE("(%s %u %u 0x%08lx 0x%08lx 0x%08lx %c)!\n",
1917 llTypes[mld->type].typestr, mld->uDeviceID, wMsg,
1918 mld->dwDriverInstance, dwParam1, dwParam2, bFrom32?'Y':'N');
1920 if (mld->uDeviceID == (UINT16)-1) {
1921 if (!llType->bSupportMapper) {
1922 WARN("uDev=-1 requested on non-mappable ll type %s\n",
1923 llTypes[mld->type].typestr);
1924 return MMSYSERR_BADDEVICEID;
1926 devID = -1;
1927 } else {
1928 if (mld->uDeviceID >= llType->wMaxId) {
1929 WARN("uDev(%u) requested >= max (%d)\n", mld->uDeviceID, llType->wMaxId);
1930 return MMSYSERR_BADDEVICEID;
1932 devID = mld->uDeviceID;
1935 lpDrv = &MMDrvs[mld->mmdIndex];
1936 part = &lpDrv->parts[mld->type];
1938 #if 0
1939 /* some sanity checks */
1940 if (!(part->nIDMin <= devID))
1941 ERR("!(part->nIDMin(%d) <= devID(%d))\n", part->nIDMin, devID);
1942 if (!(devID < part->nIDMax))
1943 ERR("!(devID(%d) < part->nIDMax(%d))\n", devID, part->nIDMax);
1944 #endif
1946 if (lpDrv->bIs32) {
1947 assert(part->u.fnMessage32);
1949 if (bFrom32) {
1950 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
1951 mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1952 ret = part->u.fnMessage32(mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1953 TRACE("=> %lu\n", ret);
1954 } else {
1955 map = llType->Map16To32A(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
1956 switch (map) {
1957 case MMDRV_MAP_NOMEM:
1958 ret = MMSYSERR_NOMEM;
1959 break;
1960 case MMDRV_MAP_MSGERROR:
1961 FIXME("NIY: no conversion yet 16->32 (%u)\n", wMsg);
1962 ret = MMSYSERR_ERROR;
1963 break;
1964 case MMDRV_MAP_OK:
1965 case MMDRV_MAP_OKMEM:
1966 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
1967 mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1968 ret = part->u.fnMessage32(mld->uDeviceID, wMsg, mld->dwDriverInstance,
1969 dwParam1, dwParam2);
1970 TRACE("=> %lu\n", ret);
1971 if (map == MMDRV_MAP_OKMEM)
1972 llType->UnMap16To32A(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
1973 break;
1974 default:
1975 case MMDRV_MAP_PASS:
1976 FIXME("NIY: pass used ?\n");
1977 ret = MMSYSERR_NOTSUPPORTED;
1978 break;
1981 } else {
1982 assert(part->u.fnMessage16);
1984 if (bFrom32) {
1985 map = llType->Map32ATo16(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
1986 switch (map) {
1987 case MMDRV_MAP_NOMEM:
1988 ret = MMSYSERR_NOMEM;
1989 break;
1990 case MMDRV_MAP_MSGERROR:
1991 FIXME("NIY: no conversion yet 32->16 (%u)\n", wMsg);
1992 ret = MMSYSERR_ERROR;
1993 break;
1994 case MMDRV_MAP_OK:
1995 case MMDRV_MAP_OKMEM:
1996 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
1997 mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
1998 ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16, mld->uDeviceID,
1999 wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
2000 TRACE("=> %lu\n", ret);
2001 if (map == MMDRV_MAP_OKMEM)
2002 llType->UnMap32ATo16(wMsg, &mld->dwDriverInstance, &dwParam1, &dwParam2);
2003 break;
2004 default:
2005 case MMDRV_MAP_PASS:
2006 FIXME("NIY: pass used ?\n");
2007 ret = MMSYSERR_NOTSUPPORTED;
2008 break;
2010 } else {
2011 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx\n",
2012 mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
2013 ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16, mld->uDeviceID,
2014 wMsg, mld->dwDriverInstance, dwParam1, dwParam2);
2015 TRACE("=> %lu\n", ret);
2018 return ret;
2021 /**************************************************************************
2022 * MMDRV_Alloc [internal]
2024 LPWINE_MLD MMDRV_Alloc(UINT size, UINT type, LPHANDLE hndl, DWORD* dwFlags,
2025 DWORD* dwCallback, DWORD* dwInstance, BOOL bFrom32)
2027 LPWINE_MLD mld;
2029 mld = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2030 if (!mld) return NULL;
2032 /* find an empty slot in MM_MLDrvs table */
2033 for (*hndl = 0; *hndl < MAX_MM_MLDRVS; (*hndl)++) {
2034 if (!MM_MLDrvs[(UINT)*hndl]) break;
2036 if (*hndl == MAX_MM_MLDRVS) {
2037 /* the MM_MLDrvs table could be made growable in the future if needed */
2038 ERR("Too many open drivers\n");
2039 return NULL;
2041 MM_MLDrvs[(UINT)*hndl] = mld;
2042 *hndl = (HANDLE)((UINT)*hndl | 0x8000);
2044 mld->type = type;
2045 if ((UINT)*hndl < MMDRV_GetNum(type) || HIWORD(*hndl) != 0) {
2046 /* FIXME: those conditions must be fulfilled so that:
2047 * - we can distinguish between device IDs and handles
2048 * - we can use handles as 16 or 32 bit entities
2050 ERR("Shouldn't happen. Bad allocation scheme\n");
2053 mld->bFrom32 = bFrom32;
2054 mld->dwFlags = HIWORD(*dwFlags);
2055 mld->dwCallback = *dwCallback;
2056 mld->dwClientInstance = *dwInstance;
2058 *dwFlags = LOWORD(*dwFlags) | CALLBACK_FUNCTION;
2059 *dwCallback = (DWORD)llTypes[type].Callback;
2060 *dwInstance = (DWORD)mld; /* FIXME: wouldn't some 16 bit drivers only use the loword ? */
2062 return mld;
2065 /**************************************************************************
2066 * MMDRV_Free [internal]
2068 void MMDRV_Free(HANDLE hndl, LPWINE_MLD mld)
2070 if ((UINT)hndl & 0x8000) {
2071 unsigned idx = (UINT)hndl & ~0x8000;
2072 if (idx < sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0])) {
2073 MM_MLDrvs[idx] = NULL;
2074 HeapFree(GetProcessHeap(), 0, mld);
2075 return;
2078 ERR("Bad Handle %08x at %p (not freed)\n", hndl, mld);
2081 /**************************************************************************
2082 * MMDRV_Open [internal]
2084 DWORD MMDRV_Open(LPWINE_MLD mld, UINT wMsg, DWORD dwParam1, DWORD dwFlags)
2086 DWORD dwRet = MMSYSERR_BADDEVICEID;
2087 DWORD dwInstance;
2088 WINE_LLTYPE* llType = &llTypes[mld->type];
2090 mld->dwDriverInstance = (DWORD)&dwInstance;
2092 if (mld->uDeviceID == (UINT)-1 || mld->uDeviceID == (UINT16)-1) {
2093 TRACE("MAPPER mode requested !\n");
2094 /* check if mapper is supported by type */
2095 if (llType->bSupportMapper) {
2096 if (llType->nMapper == -1) {
2097 /* no driver for mapper has been loaded, try a dumb implementation */
2098 TRACE("No mapper loaded, doing it by hand\n");
2099 for (mld->uDeviceID = 0; mld->uDeviceID < llType->wMaxId; mld->uDeviceID++) {
2100 if ((dwRet = MMDRV_Open(mld, wMsg, dwParam1, dwFlags)) == MMSYSERR_NOERROR) {
2101 /* to share this function epilog */
2102 dwInstance = mld->dwDriverInstance;
2103 break;
2106 } else {
2107 mld->uDeviceID = (UINT16)-1;
2108 mld->mmdIndex = llType->lpMlds[-1].mmdIndex;
2109 TRACE("Setting mmdIndex to %u\n", mld->mmdIndex);
2110 dwRet = MMDRV_Message(mld, wMsg, dwParam1, dwFlags, TRUE);
2113 } else {
2114 if (mld->uDeviceID < llType->wMaxId) {
2115 mld->mmdIndex = llType->lpMlds[mld->uDeviceID].mmdIndex;
2116 TRACE("Setting mmdIndex to %u\n", mld->mmdIndex);
2117 dwRet = MMDRV_Message(mld, wMsg, dwParam1, dwFlags, TRUE);
2120 if (dwRet == MMSYSERR_NOERROR)
2121 mld->dwDriverInstance = dwInstance;
2122 return dwRet;
2125 /**************************************************************************
2126 * MMDRV_Close [internal]
2128 DWORD MMDRV_Close(LPWINE_MLD mld, UINT wMsg)
2130 return MMDRV_Message(mld, wMsg, 0L, 0L, TRUE);
2133 /**************************************************************************
2134 * MMDRV_GetByID [internal]
2136 LPWINE_MLD MMDRV_GetByID(UINT uDevID, UINT type)
2138 if (uDevID < llTypes[type].wMaxId)
2139 return &llTypes[type].lpMlds[uDevID];
2140 if ((uDevID == (UINT16)-1 || uDevID == (UINT)-1) && llTypes[type].nMapper != -1)
2141 return &llTypes[type].lpMlds[-1];
2142 return NULL;
2145 /**************************************************************************
2146 * MMDRV_Get [internal]
2148 LPWINE_MLD MMDRV_Get(HANDLE hndl, UINT type, BOOL bCanBeID)
2150 LPWINE_MLD mld = NULL;
2152 assert(type < MMDRV_MAX);
2154 if ((UINT)hndl >= llTypes[type].wMaxId &&
2155 hndl != (UINT16)-1 && hndl != (UINT)-1) {
2156 if ((UINT)hndl & 0x8000) {
2157 hndl = (HANDLE)((UINT)hndl & ~0x8000);
2158 if (hndl < sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0])) {
2159 mld = MM_MLDrvs[(UINT)hndl];
2160 if (!mld || !HeapValidate(GetProcessHeap(), 0, mld) || mld->type != type)
2161 mld = NULL;
2163 hndl = (HANDLE)((UINT)hndl | 0x8000);
2166 if (mld == NULL && bCanBeID) {
2167 mld = MMDRV_GetByID((UINT)hndl, type);
2169 return mld;
2172 /**************************************************************************
2173 * MMDRV_GetRelated [internal]
2175 LPWINE_MLD MMDRV_GetRelated(HANDLE hndl, UINT srcType,
2176 BOOL bSrcCanBeID, UINT dstType)
2178 LPWINE_MLD mld;
2180 if ((mld = MMDRV_Get(hndl, srcType, bSrcCanBeID)) != NULL) {
2181 WINE_MM_DRIVER_PART* part = &MMDrvs[mld->mmdIndex].parts[dstType];
2182 if (part->nIDMin < part->nIDMax)
2183 return MMDRV_GetByID(part->nIDMin, dstType);
2185 return NULL;
2188 /**************************************************************************
2189 * MMDRV_PhysicalFeatures [internal]
2191 UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD dwParam1,
2192 DWORD dwParam2)
2194 WINE_MM_DRIVER* lpDrv = &MMDrvs[mld->mmdIndex];
2196 TRACE("(%p, %04x, %08lx, %08lx)\n", mld, uMsg, dwParam1, dwParam2);
2198 /* all those function calls are undocumented */
2199 switch (uMsg) {
2200 case DRV_QUERYDRVENTRY:
2201 lstrcpynA((LPSTR)dwParam1, lpDrv->drvname, LOWORD(dwParam2));
2202 break;
2203 case DRV_QUERYDEVNODE:
2204 *(LPDWORD)dwParam1 = 0L; /* should be DevNode */
2205 break;
2206 case DRV_QUERYNAME:
2207 WARN("NIY QueryName\n");
2208 break;
2209 case DRV_QUERYDRIVERIDS:
2210 WARN("NIY call VxD\n");
2211 /* should call VxD MMDEVLDR with (DevNode, dwParam1 and dwParam2) as pmts
2212 * dwParam1 is buffer and dwParam2 is sizeof buffer
2213 * I don't know where the result is stored though
2215 break;
2216 case DRV_QUERYMAPPABLE:
2217 return (lpDrv->bIsMapper) ? 2 : 0;
2219 case DRV_QUERYDSOUNDIFACE: /* Wine-specific: Retrieve DirectSound interface */
2220 return MMDRV_Message(mld, uMsg, dwParam1, dwParam2, TRUE);
2222 default:
2223 WARN("Unknown call %04x\n", uMsg);
2224 return MMSYSERR_INVALPARAM;
2226 return 0L;
2229 /**************************************************************************
2230 * MMDRV_InitPerType [internal]
2232 static BOOL MMDRV_InitPerType(LPWINE_MM_DRIVER lpDrv, UINT type, UINT wMsg)
2234 WINE_MM_DRIVER_PART* part = &lpDrv->parts[type];
2235 DWORD ret;
2236 UINT count = 0;
2237 int i, k;
2239 part->nIDMin = part->nIDMax = 0;
2241 /* for DRVM_INIT and DRVM_ENABLE, dwParam2 should be PnP node */
2242 /* the DRVM_ENABLE is only required when the PnP node is non zero */
2244 if (lpDrv->bIs32 && part->u.fnMessage32) {
2245 ret = part->u.fnMessage32(0, DRVM_INIT, 0L, 0L, 0L);
2246 TRACE("DRVM_INIT => %08lx\n", ret);
2247 #if 0
2248 ret = part->u.fnMessage32(0, DRVM_ENABLE, 0L, 0L, 0L);
2249 TRACE("DRVM_ENABLE => %08lx\n", ret);
2250 #endif
2251 count = part->u.fnMessage32(0, wMsg, 0L, 0L, 0L);
2252 } else if (!lpDrv->bIs32 && part->u.fnMessage16) {
2253 ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16,
2254 0, DRVM_INIT, 0L, 0L, 0L);
2255 TRACE("DRVM_INIT => %08lx\n", ret);
2256 #if 0
2257 ret = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16,
2258 0, DRVM_ENABLE, 0L, 0L, 0L);
2259 TRACE("DRVM_ENABLE => %08lx\n", ret);
2260 #endif
2261 count = MMDRV_CallTo16_word_wwlll((FARPROC16)part->u.fnMessage16,
2262 0, wMsg, 0L, 0L, 0L);
2263 } else {
2264 return FALSE;
2267 TRACE("Got %u dev for (%s:%s)\n", count, lpDrv->drvname, llTypes[type].typestr);
2269 /* got some drivers */
2270 if (lpDrv->bIsMapper) {
2271 /* it seems native mappers return 0 devices :-( */
2272 if (llTypes[type].nMapper != -1)
2273 ERR("Two mappers for type %s (%d, %s)\n",
2274 llTypes[type].typestr, llTypes[type].nMapper, lpDrv->drvname);
2275 if (count > 1)
2276 ERR("Strange: mapper with %d > 1 devices\n", count);
2277 llTypes[type].nMapper = MMDrvsHi;
2278 } else {
2279 if (count == 0)
2280 return FALSE;
2281 part->nIDMin = llTypes[type].wMaxId;
2282 llTypes[type].wMaxId += count;
2283 part->nIDMax = llTypes[type].wMaxId;
2285 TRACE("Setting min=%d max=%d (ttop=%d) for (%s:%s)\n",
2286 part->nIDMin, part->nIDMax, llTypes[type].wMaxId,
2287 lpDrv->drvname, llTypes[type].typestr);
2288 /* realloc translation table */
2289 llTypes[type].lpMlds = (LPWINE_MLD)
2290 HeapReAlloc(GetProcessHeap(), 0, (llTypes[type].lpMlds) ? llTypes[type].lpMlds - 1 : NULL,
2291 sizeof(WINE_MLD) * (llTypes[type].wMaxId + 1)) + 1;
2292 /* re-build the translation table */
2293 if (llTypes[type].nMapper != -1) {
2294 TRACE("%s:Trans[%d] -> %s\n", llTypes[type].typestr, -1, MMDrvs[llTypes[type].nMapper].drvname);
2295 llTypes[type].lpMlds[-1].uDeviceID = (UINT16)-1;
2296 llTypes[type].lpMlds[-1].type = type;
2297 llTypes[type].lpMlds[-1].mmdIndex = llTypes[type].nMapper;
2298 llTypes[type].lpMlds[-1].dwDriverInstance = 0;
2300 for (i = k = 0; i <= MMDrvsHi; i++) {
2301 while (MMDrvs[i].parts[type].nIDMin <= k && k < MMDrvs[i].parts[type].nIDMax) {
2302 TRACE("%s:Trans[%d] -> %s\n", llTypes[type].typestr, k, MMDrvs[i].drvname);
2303 llTypes[type].lpMlds[k].uDeviceID = k;
2304 llTypes[type].lpMlds[k].type = type;
2305 llTypes[type].lpMlds[k].mmdIndex = i;
2306 llTypes[type].lpMlds[k].dwDriverInstance = 0;
2307 k++;
2310 return TRUE;
2313 /**************************************************************************
2314 * MMDRV_Install [internal]
2316 static BOOL MMDRV_Install(LPCSTR drvRegName, LPCSTR drvFileName, BOOL bIsMapper)
2318 int i, count = 0;
2319 char buffer[128];
2320 LPWINE_MM_DRIVER lpDrv = &MMDrvs[MMDrvsHi];
2321 LPWINE_DRIVER d;
2323 TRACE("('%s', '%s', mapper=%c);\n", drvRegName, drvFileName, bIsMapper ? 'Y' : 'N');
2325 /* be sure that size of MMDrvs matches the max number of loadable drivers !!
2326 * if not just increase size of MMDrvs */
2327 assert(MMDrvsHi <= sizeof(MMDrvs)/sizeof(MMDrvs[0]));
2329 for (i = 0; i < MMDrvsHi; i++) {
2330 if (!strcmp(drvRegName, MMDrvs[i].drvname)) return FALSE;
2333 memset(lpDrv, 0, sizeof(*lpDrv));
2335 if (!(lpDrv->hDriver = OpenDriverA(drvFileName, 0, 0))) {
2336 WARN("Couldn't open driver '%s'\n", drvFileName);
2337 return FALSE;
2340 d = DRIVER_FindFromHDrvr(lpDrv->hDriver);
2341 lpDrv->bIs32 = (d->dwFlags & WINE_GDF_16BIT) ? FALSE : TRUE;
2343 /* Then look for xxxMessage functions */
2344 #define AA(_h,_w,_x,_y,_z) \
2345 func = (WINEMM_msgFunc##_y) _z ((_h), #_x); \
2346 if (func != NULL) \
2347 { lpDrv->parts[_w].u.fnMessage##_y = func; count++; \
2348 TRACE("Got %d bit func '%s'\n", _y, #_x); }
2350 if (lpDrv->bIs32) {
2351 WINEMM_msgFunc32 func;
2353 if (d->d.d32.hModule) {
2354 #define A(_x,_y) AA(d->d.d32.hModule,_x,_y,32,GetProcAddress)
2355 A(MMDRV_AUX, auxMessage);
2356 A(MMDRV_MIXER, mixMessage);
2357 A(MMDRV_MIDIIN, midMessage);
2358 A(MMDRV_MIDIOUT, modMessage);
2359 A(MMDRV_WAVEIN, widMessage);
2360 A(MMDRV_WAVEOUT, wodMessage);
2361 #undef A
2363 } else {
2364 WINEMM_msgFunc16 func;
2367 * DESCRIPTION 'wave,aux,mixer:Creative Labs Sound Blaster 16 Driver'
2368 * The beginning of the module description indicates the driver supports
2369 * waveform, auxiliary, and mixer devices. Use one of the following
2370 * device-type names, followed by a colon (:) to indicate the type of
2371 * device your driver supports. If the driver supports more than one
2372 * type of device, separate each device-type name with a comma (,).
2374 * wave for waveform audio devices
2375 * wavemapper for wave mappers
2376 * midi for MIDI audio devices
2377 * midimapper for midi mappers
2378 * aux for auxiliary audio devices
2379 * mixer for mixer devices
2382 if (d->d.d16.hDriver16) {
2383 HMODULE16 hMod16 = GetDriverModuleHandle16(d->d.d16.hDriver16);
2385 #define A(_x,_y) AA(hMod16,_x,_y,16,GetProcAddress16)
2386 A(MMDRV_AUX, auxMessage);
2387 A(MMDRV_MIXER, mixMessage);
2388 A(MMDRV_MIDIIN, midMessage);
2389 A(MMDRV_MIDIOUT, modMessage);
2390 A(MMDRV_WAVEIN, widMessage);
2391 A(MMDRV_WAVEOUT, wodMessage);
2392 #undef A
2395 #undef AA
2397 if (TRACE_ON(mmsys)) {
2398 if ((lpDrv->bIs32) ? MMDRV_GetDescription32(drvFileName, buffer, sizeof(buffer)) :
2399 MMDRV_GetDescription16(drvFileName, buffer, sizeof(buffer)))
2400 TRACE("%s => %s\n", drvFileName, buffer);
2401 else
2402 TRACE("%s => No description\n", drvFileName);
2405 if (!count) {
2406 CloseDriver(lpDrv->hDriver, 0, 0);
2407 WARN("No message functions found\n");
2408 return FALSE;
2411 /* FIXME: being a mapper or not should be known by another way */
2412 /* it's known for NE drvs (the description is of the form '*mapper: *'
2413 * I don't have any clue for PE drvs
2415 lpDrv->bIsMapper = bIsMapper;
2416 lpDrv->drvname = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(drvRegName) + 1), drvRegName);
2418 /* Finish init and get the count of the devices */
2419 MMDRV_InitPerType(lpDrv, MMDRV_AUX, AUXDM_GETNUMDEVS);
2420 MMDRV_InitPerType(lpDrv, MMDRV_MIXER, MXDM_GETNUMDEVS);
2421 MMDRV_InitPerType(lpDrv, MMDRV_MIDIIN, MIDM_GETNUMDEVS);
2422 MMDRV_InitPerType(lpDrv, MMDRV_MIDIOUT, MODM_GETNUMDEVS);
2423 MMDRV_InitPerType(lpDrv, MMDRV_WAVEIN, WIDM_GETNUMDEVS);
2424 MMDRV_InitPerType(lpDrv, MMDRV_WAVEOUT, WODM_GETNUMDEVS);
2425 /* FIXME: if all those func calls return FALSE,
2426 * then the driver must be unloaded
2429 MMDrvsHi++;
2431 return TRUE;
2434 /**************************************************************************
2435 * MMDRV_InitFromRegistry [internal]
2437 static BOOL MMDRV_InitFromRegistry(void)
2439 HKEY hKey;
2440 char buffer[256];
2441 char* p1;
2442 char* p2;
2443 DWORD type, size;
2444 BOOL ret = FALSE;
2446 if (RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\WinMM", &hKey)) {
2447 TRACE("Cannot open WinMM config key\n");
2448 return FALSE;
2451 size = sizeof(buffer);
2452 if (!RegQueryValueExA(hKey, "Drivers", 0, &type, (LPVOID)buffer, &size)) {
2453 p1 = buffer;
2454 while (p1) {
2455 p2 = strchr(p1, ';');
2456 if (p2) *p2++ = '\0';
2457 ret |= MMDRV_Install(p1, p1, FALSE);
2458 p1 = p2;
2462 /* finish with mappers */
2463 size = sizeof(buffer);
2464 if (!RegQueryValueExA(hKey, "WaveMapper", 0, &type, (LPVOID)buffer, &size))
2465 ret |= MMDRV_Install("wavemapper", buffer, TRUE);
2466 size = sizeof(buffer);
2467 if (!RegQueryValueExA(hKey, "MidiMapper", 0, &type, (LPVOID)buffer, &size))
2468 ret |= MMDRV_Install("midimapper", buffer, TRUE);
2470 RegCloseKey(hKey);
2472 return ret;
2475 /**************************************************************************
2476 * MMDRV_InitHardcoded [internal]
2478 static BOOL MMDRV_InitHardcoded(void)
2480 /* first load hardware drivers */
2481 MMDRV_Install("wineoss.drv", "wineoss.drv", FALSE);
2483 /* finish with mappers */
2484 MMDRV_Install("wavemapper", "msacm.drv", TRUE);
2485 MMDRV_Install("midimapper", "midimap.drv", TRUE);
2487 return TRUE;
2490 /**************************************************************************
2491 * MMDRV_Init [internal]
2493 BOOL MMDRV_Init(void)
2495 /* FIXME: MMDRV_InitFromRegistry shall be MMDRV_Init in a near future */
2496 return MMDRV_InitFromRegistry() || MMDRV_InitHardcoded();