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