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