1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */ 2 3 /* 4 * MMSYSTEM low level drivers handling functions 5 * 6 * Copyright 1999 Eric Pouech 7 * Modified for use with ReactOS by Andrew Greenwood, 2007 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 22 */ 23 24 #include "winemm.h" 25 26 WINE_DEFAULT_DEBUG_CHANNEL(winmm); 27 28 /* each known type of driver has an instance of this structure */ 29 typedef struct tagWINE_LLTYPE { 30 /* those attributes depend on the specification of the type */ 31 LPCSTR typestr; /* name (for debugging) */ 32 BOOL bSupportMapper; /* if type is allowed to support mapper */ 33 /* those attributes reflect the loaded/current situation for the type */ 34 UINT wMaxId; /* number of loaded devices (sum across all loaded drivers) */ 35 LPWINE_MLD lpMlds; /* "static" mlds to access the part though device IDs */ 36 int nMapper; /* index to mapper */ 37 } WINE_LLTYPE; 38 39 static int MMDrvsHi /* = 0 */; 40 static WINE_MM_DRIVER MMDrvs[8]; 41 static LPWINE_MLD MM_MLDrvs[40]; 42 #define MAX_MM_MLDRVS (sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0])) 43 44 #define A(_x,_y) {#_y, _x, 0, NULL, -1} 45 /* Note: the indices of this array must match the definitions 46 * of the MMDRV_???? manifest constants 47 */ 48 static WINE_LLTYPE llTypes[MMDRV_MAX] = { 49 A(TRUE, Aux), 50 A(FALSE, Mixer), 51 A(TRUE, MidiIn), 52 A(TRUE, MidiOut), 53 A(TRUE, WaveIn), 54 A(TRUE, WaveOut), 55 }; 56 #undef A 57 58 /************************************************************************** 59 * MMDRV_GetNum [internal] 60 */ 61 UINT MMDRV_GetNum(UINT type) 62 { 63 TRACE("(%04x)\n", type); 64 assert(type < MMDRV_MAX); 65 return llTypes[type].wMaxId; 66 } 67 68 /************************************************************************** 69 * MMDRV_Message [internal] 70 */ 71 DWORD MMDRV_Message(LPWINE_MLD mld, UINT wMsg, DWORD_PTR dwParam1, 72 DWORD_PTR dwParam2) 73 { 74 LPWINE_MM_DRIVER lpDrv; 75 DWORD ret; 76 WINE_MM_DRIVER_PART* part; 77 WINE_LLTYPE* llType = &llTypes[mld->type]; 78 int devID; 79 80 TRACE("(%s %u %u 0x%08lx 0x%08lx 0x%08lx)\n", 81 llTypes[mld->type].typestr, mld->uDeviceID, wMsg, 82 mld->dwDriverInstance, dwParam1, dwParam2); 83 84 if (mld->uDeviceID == (UINT16)-1) { 85 if (!llType->bSupportMapper) { 86 WARN("uDev=-1 requested on non-mappable ll type %s\n", 87 llTypes[mld->type].typestr); 88 return MMSYSERR_BADDEVICEID; 89 } 90 devID = -1; 91 } else { 92 if (mld->uDeviceID >= llType->wMaxId) { 93 WARN("uDev(%u) requested >= max (%d)\n", mld->uDeviceID, llType->wMaxId); 94 return MMSYSERR_BADDEVICEID; 95 } 96 devID = mld->uDeviceID; 97 } 98 99 lpDrv = &MMDrvs[mld->mmdIndex]; 100 part = &lpDrv->parts[mld->type]; 101 102 #if 0 103 /* some sanity checks */ 104 if (!(part->nIDMin <= devID)) 105 ERR("!(part->nIDMin(%d) <= devID(%d))\n", part->nIDMin, devID); 106 if (!(devID < part->nIDMax)) 107 ERR("!(devID(%d) < part->nIDMax(%d))\n", devID, part->nIDMax); 108 #endif 109 110 assert(part->fnMessage32); 111 112 TRACE("Calling message(dev=%u msg=%u usr=0x%08lx p1=0x%08lx p2=0x%08lx)\n", 113 mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2); 114 ret = part->fnMessage32(mld->uDeviceID, wMsg, mld->dwDriverInstance, dwParam1, dwParam2); 115 TRACE("=> %s\n", WINMM_ErrorToString(ret)); 116 117 return ret; 118 } 119 120 /************************************************************************** 121 * MMDRV_Alloc [internal] 122 */ 123 LPWINE_MLD MMDRV_Alloc(UINT size, UINT type, LPHANDLE hndl, DWORD* dwFlags, 124 DWORD_PTR* dwCallback, DWORD_PTR* dwInstance) 125 { 126 LPWINE_MLD mld; 127 UINT_PTR i; 128 TRACE("(%d, %04x, %p, %p, %p, %p)\n", 129 size, type, hndl, dwFlags, dwCallback, dwInstance); 130 131 mld = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 132 if (!mld) return NULL; 133 134 /* find an empty slot in MM_MLDrvs table */ 135 for (i = 0; i < MAX_MM_MLDRVS; i++) if (!MM_MLDrvs[i]) break; 136 137 if (i == MAX_MM_MLDRVS) { 138 /* the MM_MLDrvs table could be made growable in the future if needed */ 139 ERR("Too many open drivers\n"); 140 HeapFree(GetProcessHeap(), 0, mld); 141 return NULL; 142 } 143 MM_MLDrvs[i] = mld; 144 *hndl = (HANDLE)(i | 0x8000); 145 146 mld->type = type; 147 if ((UINT_PTR)*hndl < MMDRV_GetNum(type) || ((UINT_PTR)*hndl >> 16)) { 148 /* FIXME: those conditions must be fulfilled so that: 149 * - we can distinguish between device IDs and handles 150 * - we can use handles as 16 or 32 bit entities 151 */ 152 ERR("Shouldn't happen. Bad allocation scheme\n"); 153 } 154 155 mld->dwFlags = HIWORD(*dwFlags); 156 mld->dwCallback = *dwCallback; 157 mld->dwClientInstance = *dwInstance; 158 159 return mld; 160 } 161 162 /************************************************************************** 163 * MMDRV_Free [internal] 164 */ 165 void MMDRV_Free(HANDLE hndl, LPWINE_MLD mld) 166 { 167 TRACE("(%p, %p)\n", hndl, mld); 168 169 if ((UINT_PTR)hndl & 0x8000) { 170 UINT_PTR idx = (UINT_PTR)hndl & ~0x8000; 171 if (idx < sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0])) { 172 MM_MLDrvs[idx] = NULL; 173 HeapFree(GetProcessHeap(), 0, mld); 174 return; 175 } 176 } 177 ERR("Bad Handle %p at %p (not freed)\n", hndl, mld); 178 } 179 180 /************************************************************************** 181 * MMDRV_Open [internal] 182 */ 183 DWORD MMDRV_Open(LPWINE_MLD mld, UINT wMsg, DWORD_PTR dwParam1, DWORD dwFlags) 184 { 185 DWORD dwRet = MMSYSERR_BADDEVICEID; 186 DWORD_PTR dwInstance; 187 WINE_LLTYPE* llType = &llTypes[mld->type]; 188 TRACE("(%p, %04x, 0x%08lx, 0x%08x)\n", mld, wMsg, dwParam1, dwFlags); 189 190 mld->dwDriverInstance = (DWORD_PTR)&dwInstance; 191 192 if (mld->uDeviceID == (UINT)-1 || mld->uDeviceID == (UINT16)-1) { 193 TRACE("MAPPER mode requested !\n"); 194 /* check if mapper is supported by type */ 195 if (llType->bSupportMapper) { 196 if (llType->nMapper == -1) { 197 /* no driver for mapper has been loaded, try a dumb implementation */ 198 TRACE("No mapper loaded, doing it by hand\n"); 199 for (mld->uDeviceID = 0; mld->uDeviceID < llType->wMaxId; mld->uDeviceID++) { 200 if ((dwRet = MMDRV_Open(mld, wMsg, dwParam1, dwFlags)) == MMSYSERR_NOERROR) { 201 /* to share this function epilog */ 202 dwInstance = mld->dwDriverInstance; 203 break; 204 } 205 } 206 } else { 207 mld->uDeviceID = (UINT16)-1; 208 mld->mmdIndex = llType->lpMlds[-1].mmdIndex; 209 TRACE("Setting mmdIndex to %u\n", mld->mmdIndex); 210 dwRet = MMDRV_Message(mld, wMsg, dwParam1, dwFlags); 211 } 212 } 213 } else { 214 if (mld->uDeviceID < llType->wMaxId) { 215 mld->mmdIndex = llType->lpMlds[mld->uDeviceID].mmdIndex; 216 TRACE("Setting mmdIndex to %u\n", mld->mmdIndex); 217 dwRet = MMDRV_Message(mld, wMsg, dwParam1, dwFlags); 218 } 219 } 220 if (dwRet == MMSYSERR_NOERROR) 221 mld->dwDriverInstance = dwInstance; 222 return dwRet; 223 } 224 225 /************************************************************************** 226 * MMDRV_Close [internal] 227 */ 228 DWORD MMDRV_Close(LPWINE_MLD mld, UINT wMsg) 229 { 230 TRACE("(%p, %04x)\n", mld, wMsg); 231 return MMDRV_Message(mld, wMsg, 0L, 0L); 232 } 233 234 /************************************************************************** 235 * MMDRV_GetByID [internal] 236 */ 237 static LPWINE_MLD MMDRV_GetByID(UINT uDevID, UINT type) 238 { 239 TRACE("(%04x, %04x)\n", uDevID, type); 240 if (uDevID < llTypes[type].wMaxId) 241 return &llTypes[type].lpMlds[uDevID]; 242 if ((uDevID == (UINT16)-1 || uDevID == (UINT)-1) && llTypes[type].nMapper != -1) 243 return &llTypes[type].lpMlds[-1]; 244 return NULL; 245 } 246 247 /************************************************************************** 248 * MMDRV_Get [internal] 249 */ 250 LPWINE_MLD MMDRV_Get(HANDLE _hndl, UINT type, BOOL bCanBeID) 251 { 252 LPWINE_MLD mld = NULL; 253 UINT_PTR hndl = (UINT_PTR)_hndl; 254 TRACE("(%p, %04x, %c)\n", _hndl, type, bCanBeID ? 'Y' : 'N'); 255 256 assert(type < MMDRV_MAX); 257 258 if (hndl >= llTypes[type].wMaxId && 259 hndl != (UINT16)-1 && hndl != (UINT)-1) { 260 if (hndl & 0x8000) { 261 UINT idx = hndl & ~0x8000; 262 if (idx < sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0])) { 263 __TRY 264 { 265 mld = MM_MLDrvs[idx]; 266 if (mld && mld->type != type) mld = NULL; 267 } 268 __EXCEPT_PAGE_FAULT 269 { 270 mld = NULL; 271 } 272 __ENDTRY; 273 } 274 } 275 } 276 if (mld == NULL && bCanBeID) { 277 mld = MMDRV_GetByID(hndl, type); 278 } 279 return mld; 280 } 281 282 /************************************************************************** 283 * MMDRV_GetRelated [internal] 284 */ 285 LPWINE_MLD MMDRV_GetRelated(HANDLE hndl, UINT srcType, 286 BOOL bSrcCanBeID, UINT dstType) 287 { 288 LPWINE_MLD mld; 289 TRACE("(%p, %04x, %c, %04x)\n", 290 hndl, srcType, bSrcCanBeID ? 'Y' : 'N', dstType); 291 292 if ((mld = MMDRV_Get(hndl, srcType, bSrcCanBeID)) != NULL) { 293 WINE_MM_DRIVER_PART* part = &MMDrvs[mld->mmdIndex].parts[dstType]; 294 if (part->nIDMin < part->nIDMax) 295 return MMDRV_GetByID(part->nIDMin, dstType); 296 } 297 return NULL; 298 } 299 300 /************************************************************************** 301 * MMDRV_PhysicalFeatures [internal] 302 */ 303 UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, 304 DWORD_PTR dwParam1, DWORD_PTR dwParam2) 305 { 306 WINE_MM_DRIVER* lpDrv = &MMDrvs[mld->mmdIndex]; 307 308 TRACE("(%p, %04x, %08lx, %08lx)\n", mld, uMsg, dwParam1, dwParam2); 309 310 /* all those function calls are undocumented */ 311 switch (uMsg) { 312 case DRV_QUERYDRVENTRY: 313 lstrcpynA((LPSTR)dwParam1, lpDrv->drvname, LOWORD(dwParam2)); 314 break; 315 case DRV_QUERYDEVNODE: 316 *(LPDWORD)dwParam1 = 0L; /* should be DevNode */ 317 break; 318 case DRV_QUERYNAME: 319 WARN("NIY QueryName\n"); 320 break; 321 case DRV_QUERYDRIVERIDS: 322 WARN("NIY call VxD\n"); 323 /* should call VxD MMDEVLDR with (DevNode, dwParam1 and dwParam2) as pmts 324 * dwParam1 is buffer and dwParam2 is sizeof(buffer) 325 * I don't know where the result is stored though 326 */ 327 break; 328 case DRV_QUERYMAPPABLE: 329 return (lpDrv->bIsMapper) ? 2 : 0; 330 331 case DRVM_MAPPER_PREFERRED_GET: 332 /* FIXME: get from registry someday */ 333 #ifdef __REACTOS__ 334 if (!dwParam1 || !dwParam2) 335 return MMSYSERR_INVALPARAM; 336 #endif 337 *((LPDWORD)dwParam1) = -1; /* No preferred device */ 338 *((LPDWORD)dwParam2) = 0; 339 break; 340 341 case DRV_QUERYDEVICEINTERFACE: 342 case DRV_QUERYDEVICEINTERFACESIZE: 343 return MMDRV_Message(mld, uMsg, dwParam1, dwParam2); 344 345 case DRV_QUERYDSOUNDIFACE: /* Wine-specific: Retrieve DirectSound interface */ 346 case DRV_QUERYDSOUNDDESC: /* Wine-specific: Retrieve DirectSound driver description*/ 347 return MMDRV_Message(mld, uMsg, dwParam1, dwParam2); 348 349 default: 350 WARN("Unknown call %04x\n", uMsg); 351 return MMSYSERR_INVALPARAM; 352 } 353 return 0L; 354 } 355 356 /************************************************************************** 357 * MMDRV_InitPerType [internal] 358 */ 359 static BOOL MMDRV_InitPerType(LPWINE_MM_DRIVER lpDrv, UINT type, UINT wMsg) 360 { 361 WINE_MM_DRIVER_PART* part = &lpDrv->parts[type]; 362 DWORD ret; 363 UINT count = 0; 364 int i, k; 365 TRACE("(%p, %04x, %04x)\n", lpDrv, type, wMsg); 366 367 part->nIDMin = part->nIDMax = 0; 368 369 /* for DRVM_INIT and DRVM_ENABLE, dwParam2 should be PnP node */ 370 /* the DRVM_ENABLE is only required when the PnP node is non zero */ 371 if (part->fnMessage32) { 372 ret = part->fnMessage32(0, DRVM_INIT, 0L, 0L, 0L); 373 TRACE("DRVM_INIT => %s\n", WINMM_ErrorToString(ret)); 374 #if 0 375 ret = part->fnMessage32(0, DRVM_ENABLE, 0L, 0L, 0L); 376 TRACE("DRVM_ENABLE => %08lx\n", ret); 377 #endif 378 count = part->fnMessage32(0, wMsg, 0L, 0L, 0L); 379 } 380 else return FALSE; 381 382 TRACE("Got %u dev for (%s:%s)\n", count, lpDrv->drvname, llTypes[type].typestr); 383 384 if (HIWORD(count)) 385 return FALSE; 386 387 /* got some drivers */ 388 if (lpDrv->bIsMapper) { 389 /* it seems native mappers return 0 devices :-( */ 390 if (llTypes[type].nMapper != -1) 391 ERR("Two mappers for type %s (%d, %s)\n", 392 llTypes[type].typestr, llTypes[type].nMapper, lpDrv->drvname); 393 if (count > 1) 394 ERR("Strange: mapper with %d > 1 devices\n", count); 395 llTypes[type].nMapper = MMDrvsHi; 396 } else { 397 if (count == 0) 398 return FALSE; 399 part->nIDMin = llTypes[type].wMaxId; 400 llTypes[type].wMaxId += count; 401 part->nIDMax = llTypes[type].wMaxId; 402 } 403 TRACE("Setting min=%d max=%d (ttop=%d) for (%s:%s)\n", 404 part->nIDMin, part->nIDMax, llTypes[type].wMaxId, 405 lpDrv->drvname, llTypes[type].typestr); 406 /* realloc translation table */ 407 if (llTypes[type].lpMlds) 408 llTypes[type].lpMlds = (LPWINE_MLD) 409 HeapReAlloc(GetProcessHeap(), 0, llTypes[type].lpMlds - 1, 410 sizeof(WINE_MLD) * (llTypes[type].wMaxId + 1)) + 1; 411 else 412 llTypes[type].lpMlds = (LPWINE_MLD) 413 HeapAlloc(GetProcessHeap(), 0, 414 sizeof(WINE_MLD) * (llTypes[type].wMaxId + 1)) + 1; 415 416 /* re-build the translation table */ 417 if (llTypes[type].nMapper != -1) { 418 TRACE("%s:Trans[%d] -> %s\n", llTypes[type].typestr, -1, MMDrvs[llTypes[type].nMapper].drvname); 419 llTypes[type].lpMlds[-1].uDeviceID = (UINT16)-1; 420 llTypes[type].lpMlds[-1].type = type; 421 llTypes[type].lpMlds[-1].mmdIndex = llTypes[type].nMapper; 422 llTypes[type].lpMlds[-1].dwDriverInstance = 0; 423 } 424 for (i = k = 0; i <= MMDrvsHi; i++) { 425 while (MMDrvs[i].parts[type].nIDMin <= k && k < MMDrvs[i].parts[type].nIDMax) { 426 TRACE("%s:Trans[%d] -> %s\n", llTypes[type].typestr, k, MMDrvs[i].drvname); 427 llTypes[type].lpMlds[k].uDeviceID = k; 428 llTypes[type].lpMlds[k].type = type; 429 llTypes[type].lpMlds[k].mmdIndex = i; 430 llTypes[type].lpMlds[k].dwDriverInstance = 0; 431 k++; 432 } 433 } 434 return TRUE; 435 } 436 437 /************************************************************************** 438 * MMDRV_Install [internal] 439 */ 440 BOOL MMDRV_Install(LPCSTR drvRegName, LPCSTR drvFileName, BOOL bIsMapper) 441 { 442 int i, count = 0; 443 LPWINE_MM_DRIVER lpDrv = &MMDrvs[MMDrvsHi]; 444 LPWINE_DRIVER d; 445 WINEMM_msgFunc32 func; 446 447 TRACE("('%s', '%s', mapper=%c);\n", drvRegName, drvFileName, bIsMapper ? 'Y' : 'N'); 448 449 for (i = 0; i < MMDrvsHi; i++) { 450 if (!strcmp(drvRegName, MMDrvs[i].drvname)) return FALSE; 451 } 452 453 /* Be sure that size of MMDrvs matches the max number of loadable 454 * drivers !! 455 * If not just increase size of MMDrvs 456 */ 457 assert(MMDrvsHi <= sizeof(MMDrvs)/sizeof(MMDrvs[0])); 458 459 memset(lpDrv, 0, sizeof(*lpDrv)); 460 461 if (!(lpDrv->hDriver = OpenDriverA(drvFileName, 0, 0))) { 462 WARN("Couldn't open driver '%s'\n", drvFileName); 463 return FALSE; 464 } 465 466 d = DRIVER_FindFromHDrvr(lpDrv->hDriver); 467 468 if (!(d = DRIVER_FindFromHDrvr(lpDrv->hDriver))) { 469 CloseDriver(lpDrv->hDriver, 0, 0); 470 WARN("Couldn't get the WINE internal structure for driver '%s'\n", drvFileName); 471 return FALSE; 472 } 473 474 /* Then look for xxxMessage functions */ 475 #define AA(_h,_w,_x,_y,_z) \ 476 func = (WINEMM_msgFunc##_y) _z ((_h), #_x); \ 477 if (func != NULL) \ 478 { lpDrv->parts[_w].fnMessage##_y = func; count++; \ 479 TRACE("Got %d bit func '%s'\n", _y, #_x); } 480 481 if (d->hModule) { 482 #define A(_x,_y) AA(d->hModule,_x,_y,32,GetProcAddress) 483 A(MMDRV_AUX, auxMessage); 484 A(MMDRV_MIXER, mxdMessage); 485 A(MMDRV_MIDIIN, midMessage); 486 A(MMDRV_MIDIOUT, modMessage); 487 A(MMDRV_WAVEIN, widMessage); 488 A(MMDRV_WAVEOUT, wodMessage); 489 #undef A 490 } 491 #undef AA 492 493 if (!count) { 494 CloseDriver(lpDrv->hDriver, 0, 0); 495 WARN("No message functions found\n"); 496 return FALSE; 497 } 498 499 /* FIXME: being a mapper or not should be known by another way */ 500 /* it's known for NE drvs (the description is of the form '*mapper: *' 501 * I don't have any clue for PE drvs 502 */ 503 lpDrv->bIsMapper = bIsMapper; 504 lpDrv->drvname = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(drvRegName) + 1), drvRegName); 505 506 /* Finish init and get the count of the devices */ 507 i = 0; 508 if (MMDRV_InitPerType(lpDrv, MMDRV_AUX, AUXDM_GETNUMDEVS)) i = 1; 509 if (MMDRV_InitPerType(lpDrv, MMDRV_MIXER, MXDM_GETNUMDEVS)) i = 1; 510 if (MMDRV_InitPerType(lpDrv, MMDRV_MIDIIN, MIDM_GETNUMDEVS)) i = 1; 511 if (MMDRV_InitPerType(lpDrv, MMDRV_MIDIOUT, MODM_GETNUMDEVS)) i = 1; 512 if (MMDRV_InitPerType(lpDrv, MMDRV_WAVEIN, WIDM_GETNUMDEVS)) i = 1; 513 if (MMDRV_InitPerType(lpDrv, MMDRV_WAVEOUT, WODM_GETNUMDEVS)) i = 1; 514 /* if all those func calls return FALSE, then the driver must be unloaded */ 515 if (!i) { 516 CloseDriver(lpDrv->hDriver, 0, 0); 517 HeapFree(GetProcessHeap(), 0, lpDrv->drvname); 518 WARN("Driver initialization failed\n"); 519 return FALSE; 520 } 521 522 MMDrvsHi++; 523 524 return TRUE; 525 } 526 527 /************************************************************************** 528 * MMDRV_Init 529 */ 530 BOOL MMDRV_Init(void) 531 { 532 /* Redundant code, keeping this for reference only (for now) */ 533 #if 0 534 HKEY hKey; 535 char driver_buffer[256]; 536 char mapper_buffer[256]; 537 char midi_buffer[256]; 538 char* p; 539 DWORD type, size; 540 BOOL ret = FALSE; 541 TRACE("()\n"); 542 543 strcpy(driver_buffer, WINE_DEFAULT_WINMM_DRIVER); 544 strcpy(mapper_buffer, WINE_DEFAULT_WINMM_MAPPER); 545 strcpy(midi_buffer, WINE_DEFAULT_WINMM_MIDI); 546 547 /* @@ Wine registry key: HKCU\Software\Wine\Drivers */ 548 if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hKey)) 549 { 550 size = sizeof(driver_buffer); 551 if (RegQueryValueExA(hKey, "Audio", 0, &type, (LPVOID)driver_buffer, &size)) 552 strcpy(driver_buffer, WINE_DEFAULT_WINMM_DRIVER); 553 } 554 555 p = driver_buffer; 556 while (p) 557 { 558 char filename[sizeof(driver_buffer)+10]; 559 char *next = strchr(p, ','); 560 if (next) *next++ = 0; 561 sprintf( filename, "wine%s.drv", p ); 562 if ((ret = MMDRV_Install( filename, filename, FALSE ))) break; 563 p = next; 564 } 565 566 ret |= MMDRV_Install("beepmidi.dll", "beepmidi.dll", FALSE); 567 568 ret |= MMDRV_Install("wavemapper", WINE_DEFAULT_WINMM_MAPPER, TRUE); 569 ret |= MMDRV_Install("midimapper", WINE_DEFAULT_WINMM_MIDI, TRUE); 570 return ret; 571 #else 572 INT driver_count = 0; 573 574 driver_count += LoadRegistryMMEDrivers(NT_MME_DRIVERS_KEY); 575 driver_count += LoadRegistryMMEDrivers(NT_MME_DRIVERS32_KEY); 576 577 /* Explorer doesn't like us failing */ 578 return TRUE; 579 // return ( driver_count > 0 ); 580 #endif 581 } 582 583 /****************************************************************** 584 * ExitPerType 585 * 586 * 587 */ 588 static BOOL MMDRV_ExitPerType(LPWINE_MM_DRIVER lpDrv, UINT type) 589 { 590 WINE_MM_DRIVER_PART* part = &lpDrv->parts[type]; 591 DWORD ret; 592 TRACE("(%p, %04x)\n", lpDrv, type); 593 594 if (part->fnMessage32) { 595 #if 0 596 ret = part->fnMessage32(0, DRVM_DISABLE, 0L, 0L, 0L); 597 TRACE("DRVM_DISABLE => %08lx\n", ret); 598 #endif 599 ret = part->fnMessage32(0, DRVM_EXIT, 0L, 0L, 0L); 600 TRACE("DRVM_EXIT => %s\n", WINMM_ErrorToString(ret)); 601 } 602 603 return TRUE; 604 } 605 606 /****************************************************************** 607 * Exit 608 * 609 * 610 */ 611 void MMDRV_Exit(void) 612 { 613 unsigned int i; 614 TRACE("()\n"); 615 616 for (i = 0; i < sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0]); i++) 617 { 618 if (MM_MLDrvs[i] != NULL) 619 { 620 FIXME("Closing while ll-driver open\n"); 621 #if 0 622 /* FIXME: should generate a message depending on type */ 623 MMDRV_Free((HANDLE)(i | 0x8000), MM_MLDrvs[i]); 624 #endif 625 } 626 } 627 628 /* unload driver, in reverse order of loading */ 629 i = MMDrvsHi; 630 while (i-- > 0) 631 { 632 MMDRV_ExitPerType(&MMDrvs[i], MMDRV_AUX); 633 MMDRV_ExitPerType(&MMDrvs[i], MMDRV_MIXER); 634 MMDRV_ExitPerType(&MMDrvs[i], MMDRV_MIDIIN); 635 MMDRV_ExitPerType(&MMDrvs[i], MMDRV_MIDIOUT); 636 MMDRV_ExitPerType(&MMDrvs[i], MMDRV_WAVEIN); 637 MMDRV_ExitPerType(&MMDrvs[i], MMDRV_WAVEOUT); 638 CloseDriver(MMDrvs[i].hDriver, 0, 0); 639 } 640 if (llTypes[MMDRV_AUX].lpMlds) 641 HeapFree(GetProcessHeap(), 0, llTypes[MMDRV_AUX].lpMlds - 1); 642 if (llTypes[MMDRV_MIXER].lpMlds) 643 HeapFree(GetProcessHeap(), 0, llTypes[MMDRV_MIXER].lpMlds - 1); 644 if (llTypes[MMDRV_MIDIIN].lpMlds) 645 HeapFree(GetProcessHeap(), 0, llTypes[MMDRV_MIDIIN].lpMlds - 1); 646 if (llTypes[MMDRV_MIDIOUT].lpMlds) 647 HeapFree(GetProcessHeap(), 0, llTypes[MMDRV_MIDIOUT].lpMlds - 1); 648 if (llTypes[MMDRV_WAVEIN].lpMlds) 649 HeapFree(GetProcessHeap(), 0, llTypes[MMDRV_WAVEIN].lpMlds - 1); 650 if (llTypes[MMDRV_WAVEOUT].lpMlds) 651 HeapFree(GetProcessHeap(), 0, llTypes[MMDRV_WAVEOUT].lpMlds - 1); 652 } 653