1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */ 2 3 /* 4 * MSACM32 library 5 * 6 * Copyright 1998 Patrik Stridvall 7 * 1999 Eric Pouech 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 "config.h" 25 #include "wine/port.h" 26 27 #include <stdarg.h> 28 #include <stdio.h> 29 30 #include "windef.h" 31 #include "winbase.h" 32 #include "wingdi.h" 33 #include "winuser.h" 34 #include "winnls.h" 35 #include "mmsystem.h" 36 #include "mmreg.h" 37 #include "msacm.h" 38 #include "msacmdrv.h" 39 #include "wineacm.h" 40 #include "wine/debug.h" 41 #include "wine/unicode.h" 42 43 WINE_DEFAULT_DEBUG_CHANNEL(msacm); 44 45 /*********************************************************************** 46 * acmDriverAddA (MSACM32.@) 47 */ 48 MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule, 49 LPARAM lParam, DWORD dwPriority, DWORD fdwAdd) 50 { 51 MMRESULT resultW; 52 WCHAR * driverW = NULL; 53 LPARAM lParamW = lParam; 54 55 TRACE("(%p, %p, %08lx, %08x, %08x)\n", 56 phadid, hinstModule, lParam, dwPriority, fdwAdd); 57 58 if (!phadid) { 59 WARN("invalid parameter\n"); 60 return MMSYSERR_INVALPARAM; 61 } 62 63 /* Check if any unknown flags */ 64 if (fdwAdd & 65 ~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND| 66 ACM_DRIVERADDF_GLOBAL)) { 67 WARN("invalid flag\n"); 68 return MMSYSERR_INVALFLAG; 69 } 70 71 /* Check if any incompatible flags */ 72 if ((fdwAdd & ACM_DRIVERADDF_FUNCTION) && 73 (fdwAdd & ACM_DRIVERADDF_NOTIFYHWND)) { 74 WARN("invalid flag\n"); 75 return MMSYSERR_INVALFLAG; 76 } 77 78 /* A->W translation of name */ 79 if ((fdwAdd & ACM_DRIVERADDF_TYPEMASK) == ACM_DRIVERADDF_NAME) { 80 INT len; 81 82 if (lParam == 0) return MMSYSERR_INVALPARAM; 83 len = MultiByteToWideChar(CP_ACP, 0, (LPSTR)lParam, -1, NULL, 0); 84 driverW = HeapAlloc(MSACM_hHeap, 0, len * sizeof(WCHAR)); 85 if (!driverW) return MMSYSERR_NOMEM; 86 MultiByteToWideChar(CP_ACP, 0, (LPSTR)lParam, -1, driverW, len); 87 lParamW = (LPARAM)driverW; 88 } 89 90 resultW = acmDriverAddW(phadid, hinstModule, lParamW, dwPriority, fdwAdd); 91 HeapFree(MSACM_hHeap, 0, driverW); 92 return resultW; 93 } 94 95 /*********************************************************************** 96 * acmDriverAddW (MSACM32.@) 97 * 98 */ 99 MMRESULT WINAPI acmDriverAddW(PHACMDRIVERID phadid, HINSTANCE hinstModule, 100 LPARAM lParam, DWORD dwPriority, DWORD fdwAdd) 101 { 102 PWINE_ACMLOCALDRIVER pLocalDrv = NULL; 103 104 TRACE("(%p, %p, %08lx, %08x, %08x)\n", 105 phadid, hinstModule, lParam, dwPriority, fdwAdd); 106 107 if (!phadid) { 108 WARN("invalid parameter\n"); 109 return MMSYSERR_INVALPARAM; 110 } 111 112 /* Check if any unknown flags */ 113 if (fdwAdd & 114 ~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND| 115 ACM_DRIVERADDF_GLOBAL)) { 116 WARN("invalid flag\n"); 117 return MMSYSERR_INVALFLAG; 118 } 119 120 /* Check if any incompatible flags */ 121 if ((fdwAdd & ACM_DRIVERADDF_FUNCTION) && 122 (fdwAdd & ACM_DRIVERADDF_NOTIFYHWND)) { 123 WARN("invalid flag\n"); 124 return MMSYSERR_INVALFLAG; 125 } 126 127 switch (fdwAdd & ACM_DRIVERADDF_TYPEMASK) { 128 case ACM_DRIVERADDF_NAME: 129 /* 130 hInstModule (unused) 131 lParam name of value in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32 132 dwPriority (unused, set to 0) 133 */ 134 *phadid = (HACMDRIVERID) MSACM_RegisterDriverFromRegistry((LPCWSTR)lParam); 135 if (!*phadid) { 136 ERR("Unable to register driver via ACM_DRIVERADDF_NAME\n"); 137 return MMSYSERR_INVALPARAM; 138 } 139 break; 140 case ACM_DRIVERADDF_FUNCTION: 141 /* 142 hInstModule Handle of module which contains driver entry proc 143 lParam Driver function address 144 dwPriority (unused, set to 0) 145 */ 146 fdwAdd &= ~ACM_DRIVERADDF_TYPEMASK; 147 /* FIXME: fdwAdd ignored */ 148 /* Application-supplied acmDriverProc's are placed at the top of the priority unless 149 fdwAdd indicates ACM_DRIVERADDF_GLOBAL 150 */ 151 pLocalDrv = MSACM_RegisterLocalDriver(hinstModule, (DRIVERPROC)lParam); 152 *phadid = pLocalDrv ? (HACMDRIVERID) MSACM_RegisterDriver(NULL, NULL, pLocalDrv) : NULL; 153 if (!*phadid) { 154 ERR("Unable to register driver via ACM_DRIVERADDF_FUNCTION\n"); 155 return MMSYSERR_INVALPARAM; 156 } 157 break; 158 case ACM_DRIVERADDF_NOTIFYHWND: 159 /* 160 hInstModule (unused) 161 lParam Handle of notification window 162 dwPriority Window message to send for notification broadcasts 163 */ 164 *phadid = (HACMDRIVERID) MSACM_RegisterNotificationWindow((HWND)lParam, dwPriority); 165 if (!*phadid) { 166 ERR("Unable to register driver via ACM_DRIVERADDF_NOTIFYHWND\n"); 167 return MMSYSERR_INVALPARAM; 168 } 169 break; 170 default: 171 ERR("invalid flag value 0x%08x for fdwAdd\n", fdwAdd); 172 return MMSYSERR_INVALFLAG; 173 } 174 175 MSACM_BroadcastNotification(); 176 return MMSYSERR_NOERROR; 177 } 178 179 /*********************************************************************** 180 * acmDriverClose (MSACM32.@) 181 */ 182 MMRESULT WINAPI acmDriverClose(HACMDRIVER had, DWORD fdwClose) 183 { 184 PWINE_ACMDRIVER pad; 185 PWINE_ACMDRIVERID padid; 186 PWINE_ACMDRIVER* tpad; 187 188 TRACE("(%p, %08x)\n", had, fdwClose); 189 190 if (fdwClose) { 191 WARN("invalid flag\n"); 192 return MMSYSERR_INVALFLAG; 193 } 194 195 pad = MSACM_GetDriver(had); 196 if (!pad) { 197 WARN("invalid handle\n"); 198 return MMSYSERR_INVALHANDLE; 199 } 200 201 padid = pad->obj.pACMDriverID; 202 203 /* remove driver from list */ 204 for (tpad = &(padid->pACMDriverList); *tpad; tpad = &((*tpad)->pNextACMDriver)) { 205 if (*tpad == pad) { 206 *tpad = (*tpad)->pNextACMDriver; 207 break; 208 } 209 } 210 211 /* close driver if it has been opened */ 212 if (pad->hDrvr && !pad->pLocalDrvrInst) 213 CloseDriver(pad->hDrvr, 0, 0); 214 else if (pad->pLocalDrvrInst) 215 MSACM_CloseLocalDriver(pad->pLocalDrvrInst); 216 217 pad->obj.dwType = 0; 218 HeapFree(MSACM_hHeap, 0, pad); 219 220 return MMSYSERR_NOERROR; 221 } 222 223 /*********************************************************************** 224 * acmDriverDetailsA (MSACM32.@) 225 */ 226 MMRESULT WINAPI acmDriverDetailsA(HACMDRIVERID hadid, PACMDRIVERDETAILSA padd, DWORD fdwDetails) 227 { 228 MMRESULT mmr; 229 ACMDRIVERDETAILSW addw; 230 231 TRACE("(%p, %p, %08x)\n", hadid, padd, fdwDetails); 232 233 if (!padd) { 234 WARN("invalid parameter\n"); 235 return MMSYSERR_INVALPARAM; 236 } 237 238 if (padd->cbStruct < 4) { 239 WARN("invalid parameter\n"); 240 return MMSYSERR_INVALPARAM; 241 } 242 243 addw.cbStruct = sizeof(addw); 244 mmr = acmDriverDetailsW(hadid, &addw, fdwDetails); 245 if (mmr == 0) { 246 ACMDRIVERDETAILSA padda; 247 248 padda.fccType = addw.fccType; 249 padda.fccComp = addw.fccComp; 250 padda.wMid = addw.wMid; 251 padda.wPid = addw.wPid; 252 padda.vdwACM = addw.vdwACM; 253 padda.vdwDriver = addw.vdwDriver; 254 padda.fdwSupport = addw.fdwSupport; 255 padda.cFormatTags = addw.cFormatTags; 256 padda.cFilterTags = addw.cFilterTags; 257 padda.hicon = addw.hicon; 258 WideCharToMultiByte( CP_ACP, 0, addw.szShortName, -1, padda.szShortName, 259 sizeof(padda.szShortName), NULL, NULL ); 260 WideCharToMultiByte( CP_ACP, 0, addw.szLongName, -1, padda.szLongName, 261 sizeof(padda.szLongName), NULL, NULL ); 262 WideCharToMultiByte( CP_ACP, 0, addw.szCopyright, -1, padda.szCopyright, 263 sizeof(padda.szCopyright), NULL, NULL ); 264 WideCharToMultiByte( CP_ACP, 0, addw.szLicensing, -1, padda.szLicensing, 265 sizeof(padda.szLicensing), NULL, NULL ); 266 WideCharToMultiByte( CP_ACP, 0, addw.szFeatures, -1, padda.szFeatures, 267 sizeof(padda.szFeatures), NULL, NULL ); 268 padda.cbStruct = min(padd->cbStruct, sizeof(*padd)); 269 memcpy(padd, &padda, padda.cbStruct); 270 } 271 return mmr; 272 } 273 274 /*********************************************************************** 275 * acmDriverDetailsW (MSACM32.@) 276 */ 277 MMRESULT WINAPI acmDriverDetailsW(HACMDRIVERID hadid, PACMDRIVERDETAILSW padd, DWORD fdwDetails) 278 { 279 HACMDRIVER acmDrvr; 280 MMRESULT mmr; 281 282 TRACE("(%p, %p, %08x)\n", hadid, padd, fdwDetails); 283 284 if (!padd) { 285 WARN("invalid parameter\n"); 286 return MMSYSERR_INVALPARAM; 287 } 288 289 if (padd->cbStruct < 4) { 290 WARN("invalid parameter\n"); 291 return MMSYSERR_INVALPARAM; 292 } 293 294 if (fdwDetails) { 295 WARN("invalid flag\n"); 296 return MMSYSERR_INVALFLAG; 297 } 298 299 mmr = acmDriverOpen(&acmDrvr, hadid, 0); 300 if (mmr == MMSYSERR_NOERROR) { 301 ACMDRIVERDETAILSW paddw; 302 paddw.cbStruct = sizeof(paddw); 303 mmr = MSACM_Message(acmDrvr, ACMDM_DRIVER_DETAILS, (LPARAM)&paddw, 0); 304 305 acmDriverClose(acmDrvr, 0); 306 paddw.cbStruct = min(padd->cbStruct, sizeof(*padd)); 307 memcpy(padd, &paddw, paddw.cbStruct); 308 } 309 else if (mmr == MMSYSERR_NODRIVER) 310 return MMSYSERR_NOTSUPPORTED; 311 312 return mmr; 313 } 314 315 /*********************************************************************** 316 * acmDriverEnum (MSACM32.@) 317 */ 318 MMRESULT WINAPI acmDriverEnum(ACMDRIVERENUMCB fnCallback, DWORD_PTR dwInstance, 319 DWORD fdwEnum) 320 { 321 PWINE_ACMDRIVERID padid; 322 DWORD fdwSupport; 323 324 TRACE("(%p, %08lx, %08x)\n", fnCallback, dwInstance, fdwEnum); 325 326 if (!fnCallback) { 327 WARN("invalid parameter\n"); 328 return MMSYSERR_INVALPARAM; 329 } 330 331 if (fdwEnum & ~(ACM_DRIVERENUMF_NOLOCAL|ACM_DRIVERENUMF_DISABLED)) { 332 WARN("invalid flag\n"); 333 return MMSYSERR_INVALFLAG; 334 } 335 336 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 337 fdwSupport = padid->fdwSupport; 338 339 if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) { 340 if (fdwEnum & ACM_DRIVERENUMF_DISABLED) 341 fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED; 342 else 343 continue; 344 } 345 if (!(*fnCallback)((HACMDRIVERID)padid, dwInstance, fdwSupport)) 346 break; 347 } 348 349 return MMSYSERR_NOERROR; 350 } 351 352 /*********************************************************************** 353 * acmDriverID (MSACM32.@) 354 */ 355 MMRESULT WINAPI acmDriverID(HACMOBJ hao, PHACMDRIVERID phadid, DWORD fdwDriverID) 356 { 357 PWINE_ACMOBJ pao; 358 359 TRACE("(%p, %p, %08x)\n", hao, phadid, fdwDriverID); 360 361 if (fdwDriverID) { 362 WARN("invalid flag\n"); 363 return MMSYSERR_INVALFLAG; 364 } 365 366 pao = MSACM_GetObj(hao, WINE_ACMOBJ_DONTCARE); 367 if (!pao) { 368 WARN("invalid handle\n"); 369 return MMSYSERR_INVALHANDLE; 370 } 371 372 if (!phadid) { 373 WARN("invalid parameter\n"); 374 return MMSYSERR_INVALPARAM; 375 } 376 377 *phadid = (HACMDRIVERID) pao->pACMDriverID; 378 379 return MMSYSERR_NOERROR; 380 } 381 382 /*********************************************************************** 383 * acmDriverMessage (MSACM32.@) 384 * 385 * Note: MSDN documentation (July 2001) is incomplete. This function 386 * accepts sending messages to an HACMDRIVERID in addition to the 387 * documented HACMDRIVER. In fact, for DRV_QUERYCONFIGURE and DRV_CONFIGURE, 388 * this might actually be the required mode of operation. 389 * 390 * Note: For DRV_CONFIGURE, msacm supplies its own DRVCONFIGINFO structure 391 * when the application fails to supply one. Some native drivers depend on 392 * this and refuse to display unless a valid DRVCONFIGINFO structure is 393 * built and supplied. 394 */ 395 LRESULT WINAPI acmDriverMessage(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2) 396 { 397 TRACE("(%p, %04x, %08lx, %08lx\n", had, uMsg, lParam1, lParam2); 398 399 if ((uMsg >= ACMDM_USER && uMsg < ACMDM_RESERVED_LOW) || 400 uMsg == ACMDM_DRIVER_ABOUT || 401 uMsg == DRV_QUERYCONFIGURE || 402 uMsg == DRV_CONFIGURE) 403 { 404 PWINE_ACMDRIVERID padid; 405 LRESULT lResult; 406 LPDRVCONFIGINFO pConfigInfo = NULL; 407 LPWSTR section_name = NULL; 408 LPWSTR alias_name = NULL; 409 410 /* Check whether handle is an HACMDRIVERID */ 411 padid = MSACM_GetDriverID((HACMDRIVERID)had); 412 413 /* If the message is DRV_CONFIGURE, and the application provides no 414 DRVCONFIGINFO structure, msacm must supply its own. 415 */ 416 if (uMsg == DRV_CONFIGURE && lParam2 == 0) { 417 LPWSTR pAlias; 418 419 /* Get the alias from the HACMDRIVERID */ 420 if (padid) { 421 pAlias = padid->pszDriverAlias; 422 if (pAlias == NULL) { 423 WARN("DRV_CONFIGURE: no alias for this driver, cannot self-supply alias\n"); 424 } 425 } else { 426 FIXME("DRV_CONFIGURE: reverse lookup HACMDRIVER -> HACMDRIVERID not implemented\n"); 427 pAlias = NULL; 428 } 429 430 if (pAlias != NULL) { 431 /* DRVCONFIGINFO is only 12 bytes long, but native msacm 432 * reports a 16-byte structure to codecs, so allocate 16 bytes, 433 * just to be on the safe side. 434 */ 435 const unsigned int iStructSize = 16; 436 pConfigInfo = HeapAlloc(MSACM_hHeap, 0, iStructSize); 437 if (!pConfigInfo) { 438 ERR("OOM while supplying DRVCONFIGINFO for DRV_CONFIGURE, using NULL\n"); 439 } else { 440 static const WCHAR drivers32[] = {'D','r','i','v','e','r','s','3','2','\0'}; 441 442 pConfigInfo->dwDCISize = iStructSize; 443 444 section_name = HeapAlloc(MSACM_hHeap, 0, (strlenW(drivers32) + 1) * sizeof(WCHAR)); 445 if (section_name) strcpyW(section_name, drivers32); 446 pConfigInfo->lpszDCISectionName = section_name; 447 alias_name = HeapAlloc(MSACM_hHeap, 0, (strlenW(pAlias) + 1) * sizeof(WCHAR)); 448 if (alias_name) strcpyW(alias_name, pAlias); 449 pConfigInfo->lpszDCIAliasName = alias_name; 450 451 if (pConfigInfo->lpszDCISectionName == NULL || pConfigInfo->lpszDCIAliasName == NULL) { 452 HeapFree(MSACM_hHeap, 0, alias_name); 453 HeapFree(MSACM_hHeap, 0, section_name); 454 HeapFree(MSACM_hHeap, 0, pConfigInfo); 455 pConfigInfo = NULL; 456 ERR("OOM while supplying DRVCONFIGINFO for DRV_CONFIGURE, using NULL\n"); 457 } 458 } 459 } 460 461 lParam2 = (LPARAM)pConfigInfo; 462 } 463 464 if (padid) { 465 /* Handle is really an HACMDRIVERID, must have an open session to get an HACMDRIVER */ 466 if (padid->pACMDriverList != NULL) { 467 lResult = MSACM_Message((HACMDRIVER)padid->pACMDriverList, uMsg, lParam1, lParam2); 468 } else { 469 MMRESULT mmr = acmDriverOpen(&had, (HACMDRIVERID)padid, 0); 470 if (mmr != MMSYSERR_NOERROR) { 471 lResult = MMSYSERR_INVALPARAM; 472 } else { 473 lResult = acmDriverMessage(had, uMsg, lParam1, lParam2); 474 acmDriverClose(had, 0); 475 } 476 } 477 } else { 478 lResult = MSACM_Message(had, uMsg, lParam1, lParam2); 479 } 480 if (pConfigInfo) { 481 HeapFree(MSACM_hHeap, 0, alias_name); 482 HeapFree(MSACM_hHeap, 0, section_name); 483 HeapFree(MSACM_hHeap, 0, pConfigInfo); 484 } 485 return lResult; 486 } 487 WARN("invalid parameter\n"); 488 return MMSYSERR_INVALPARAM; 489 } 490 491 /*********************************************************************** 492 * acmDriverOpen (MSACM32.@) 493 */ 494 MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen) 495 { 496 PWINE_ACMDRIVERID padid; 497 PWINE_ACMDRIVER pad = NULL; 498 MMRESULT ret; 499 500 TRACE("(%p, %p, %08u)\n", phad, hadid, fdwOpen); 501 502 if (!phad) { 503 WARN("invalid parameter\n"); 504 return MMSYSERR_INVALPARAM; 505 } 506 507 if (fdwOpen) { 508 WARN("invalid flag\n"); 509 return MMSYSERR_INVALFLAG; 510 } 511 512 padid = MSACM_GetDriverID(hadid); 513 if (!padid) { 514 WARN("invalid handle\n"); 515 return MMSYSERR_INVALHANDLE; 516 } 517 518 pad = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER)); 519 if (!pad) { 520 WARN("no memory\n"); 521 return MMSYSERR_NOMEM; 522 } 523 524 pad->obj.dwType = WINE_ACMOBJ_DRIVER; 525 pad->obj.pACMDriverID = padid; 526 pad->hDrvr = 0; 527 pad->pLocalDrvrInst = NULL; 528 529 if (padid->pLocalDriver == NULL) 530 { 531 ACMDRVOPENDESCW adod; 532 int len; 533 LPWSTR section_name; 534 535 /* this is not an externally added driver... need to actually load it */ 536 if (!padid->pszDriverAlias) 537 { 538 ret = MMSYSERR_ERROR; 539 goto gotError; 540 } 541 542 adod.cbStruct = sizeof(adod); 543 adod.fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; 544 adod.fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; 545 adod.dwVersion = acmGetVersion(); 546 adod.dwFlags = fdwOpen; 547 adod.dwError = 0; 548 len = strlen("Drivers32") + 1; 549 section_name = HeapAlloc(MSACM_hHeap, 0, len * sizeof(WCHAR)); 550 MultiByteToWideChar(CP_ACP, 0, "Drivers32", -1, section_name, len); 551 adod.pszSectionName = section_name; 552 adod.pszAliasName = padid->pszDriverAlias; 553 adod.dnDevNode = 0; 554 555 pad->hDrvr = OpenDriver(padid->pszDriverAlias, NULL, (DWORD_PTR)&adod); 556 557 HeapFree(MSACM_hHeap, 0, section_name); 558 if (!pad->hDrvr) 559 { 560 ret = adod.dwError; 561 if (ret == MMSYSERR_NOERROR) 562 ret = MMSYSERR_NODRIVER; 563 goto gotError; 564 } 565 } 566 else 567 { 568 ACMDRVOPENDESCW adod; 569 570 pad->hDrvr = NULL; 571 572 adod.cbStruct = sizeof(adod); 573 adod.fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; 574 adod.fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; 575 adod.dwVersion = acmGetVersion(); 576 adod.dwFlags = fdwOpen; 577 adod.dwError = 0; 578 adod.pszSectionName = NULL; 579 adod.pszAliasName = NULL; 580 adod.dnDevNode = 0; 581 582 pad->pLocalDrvrInst = MSACM_OpenLocalDriver(padid->pLocalDriver, (DWORD_PTR)&adod); 583 if (!pad->pLocalDrvrInst) 584 { 585 ret = adod.dwError; 586 if (ret == MMSYSERR_NOERROR) 587 ret = MMSYSERR_NODRIVER; 588 goto gotError; 589 } 590 } 591 592 /* insert new pad at beg of list */ 593 pad->pNextACMDriver = padid->pACMDriverList; 594 padid->pACMDriverList = pad; 595 596 /* FIXME: Create a WINE_ACMDRIVER32 */ 597 *phad = (HACMDRIVER)pad; 598 TRACE("%s => %p\n", debugstr_w(padid->pszDriverAlias), pad); 599 600 return MMSYSERR_NOERROR; 601 gotError: 602 WARN("failed: ret = %08x\n", ret); 603 if (pad && !pad->hDrvr) 604 HeapFree(MSACM_hHeap, 0, pad); 605 return ret; 606 } 607 608 /*********************************************************************** 609 * acmDriverPriority (MSACM32.@) 610 */ 611 MMRESULT WINAPI acmDriverPriority(HACMDRIVERID hadid, DWORD dwPriority, DWORD fdwPriority) 612 { 613 614 TRACE("(%p, %08x, %08x)\n", hadid, dwPriority, fdwPriority); 615 616 /* Check for unknown flags */ 617 if (fdwPriority & 618 ~(ACM_DRIVERPRIORITYF_ENABLE|ACM_DRIVERPRIORITYF_DISABLE| 619 ACM_DRIVERPRIORITYF_BEGIN|ACM_DRIVERPRIORITYF_END)) { 620 WARN("invalid flag\n"); 621 return MMSYSERR_INVALFLAG; 622 } 623 624 /* Check for incompatible flags */ 625 if ((fdwPriority & ACM_DRIVERPRIORITYF_ENABLE) && 626 (fdwPriority & ACM_DRIVERPRIORITYF_DISABLE)) { 627 WARN("invalid flag\n"); 628 return MMSYSERR_INVALFLAG; 629 } 630 631 /* Check for incompatible flags */ 632 if ((fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) && 633 (fdwPriority & ACM_DRIVERPRIORITYF_END)) { 634 WARN("invalid flag\n"); 635 return MMSYSERR_INVALFLAG; 636 } 637 638 /* According to MSDN, ACM_DRIVERPRIORITYF_BEGIN and ACM_DRIVERPRIORITYF_END 639 may only appear by themselves, and in addition, hadid and dwPriority must 640 both be zero */ 641 if ((fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) || 642 (fdwPriority & ACM_DRIVERPRIORITYF_END)) { 643 if (fdwPriority & ~(ACM_DRIVERPRIORITYF_BEGIN|ACM_DRIVERPRIORITYF_END)) { 644 WARN("ACM_DRIVERPRIORITYF_[BEGIN|END] cannot be used with any other flags\n"); 645 return MMSYSERR_INVALPARAM; 646 } 647 if (dwPriority) { 648 WARN("priority invalid with ACM_DRIVERPRIORITYF_[BEGIN|END]\n"); 649 return MMSYSERR_INVALPARAM; 650 } 651 if (hadid) { 652 WARN("non-null hadid invalid with ACM_DRIVERPRIORITYF_[BEGIN|END]\n"); 653 return MMSYSERR_INVALPARAM; 654 } 655 /* FIXME: MSDN wording suggests that deferred notification should be 656 implemented as a system-wide lock held by a calling task, and that 657 re-enabling notifications should broadcast them across all processes. 658 This implementation uses a simple DWORD counter. One consequence of the 659 current implementation is that applications will never see 660 MMSYSERR_ALLOCATED as a return error. 661 */ 662 if (fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) { 663 MSACM_DisableNotifications(); 664 } else if (fdwPriority & ACM_DRIVERPRIORITYF_END) { 665 MSACM_EnableNotifications(); 666 } 667 return MMSYSERR_NOERROR; 668 } else { 669 PWINE_ACMDRIVERID padid; 670 PWINE_ACMNOTIFYWND panwnd; 671 BOOL bPerformBroadcast = FALSE; 672 673 /* Fetch driver ID */ 674 padid = MSACM_GetDriverID(hadid); 675 panwnd = MSACM_GetNotifyWnd(hadid); 676 if (!padid && !panwnd) { 677 WARN("invalid handle\n"); 678 return MMSYSERR_INVALHANDLE; 679 } 680 681 if (padid) { 682 /* Check whether driver ID is appropriate for requested op */ 683 if (dwPriority) { 684 if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL) { 685 return MMSYSERR_NOTSUPPORTED; 686 } 687 if (dwPriority != 1 && dwPriority != (DWORD)-1) { 688 FIXME("unexpected priority %d, using sign only\n", dwPriority); 689 if ((signed)dwPriority < 0) dwPriority = (DWORD)-1; 690 if (dwPriority > 0) dwPriority = 1; 691 } 692 693 if (dwPriority == 1 && (padid->pPrevACMDriverID == NULL || 694 (padid->pPrevACMDriverID->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL))) { 695 /* do nothing - driver is first of list, or first after last 696 local driver */ 697 } else if (dwPriority == (DWORD)-1 && padid->pNextACMDriverID == NULL) { 698 /* do nothing - driver is last of list */ 699 } else { 700 MSACM_RePositionDriver(padid, dwPriority); 701 bPerformBroadcast = TRUE; 702 } 703 } 704 705 /* Check whether driver ID should be enabled or disabled */ 706 if (fdwPriority & ACM_DRIVERPRIORITYF_DISABLE) { 707 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED)) { 708 padid->fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED; 709 bPerformBroadcast = TRUE; 710 } 711 } else if (fdwPriority & ACM_DRIVERPRIORITYF_ENABLE) { 712 if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) { 713 padid->fdwSupport &= ~ACMDRIVERDETAILS_SUPPORTF_DISABLED; 714 bPerformBroadcast = TRUE; 715 } 716 } 717 } 718 719 if (panwnd) { 720 if (dwPriority) { 721 return MMSYSERR_NOTSUPPORTED; 722 } 723 724 /* Check whether notify window should be enabled or disabled */ 725 if (fdwPriority & ACM_DRIVERPRIORITYF_DISABLE) { 726 if (!(panwnd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED)) { 727 panwnd->fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED; 728 bPerformBroadcast = TRUE; 729 } 730 } else if (fdwPriority & ACM_DRIVERPRIORITYF_ENABLE) { 731 if (panwnd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) { 732 panwnd->fdwSupport &= ~ACMDRIVERDETAILS_SUPPORTF_DISABLED; 733 bPerformBroadcast = TRUE; 734 } 735 } 736 } 737 738 /* Perform broadcast of changes */ 739 if (bPerformBroadcast) { 740 MSACM_WriteCurrentPriorities(); 741 MSACM_BroadcastNotification(); 742 } 743 return MMSYSERR_NOERROR; 744 } 745 } 746 747 /*********************************************************************** 748 * acmDriverRemove (MSACM32.@) 749 */ 750 MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove) 751 { 752 PWINE_ACMDRIVERID padid; 753 PWINE_ACMNOTIFYWND panwnd; 754 755 TRACE("(%p, %08x)\n", hadid, fdwRemove); 756 757 padid = MSACM_GetDriverID(hadid); 758 panwnd = MSACM_GetNotifyWnd(hadid); 759 if (!padid && !panwnd) { 760 WARN("invalid handle\n"); 761 return MMSYSERR_INVALHANDLE; 762 } 763 764 if (fdwRemove) { 765 WARN("invalid flag\n"); 766 return MMSYSERR_INVALFLAG; 767 } 768 769 if (padid) MSACM_UnregisterDriver(padid); 770 if (panwnd) MSACM_UnRegisterNotificationWindow(panwnd); 771 MSACM_BroadcastNotification(); 772 773 return MMSYSERR_NOERROR; 774 } 775