[SHELL32] CDrivesFolder: Implement the eject and disconnect menu items. CORE-13841
[reactos.git] / dll / win32 / msacm32 / format.c
1 /*
2 * MSACM32 library
3 *
4 * Copyright 1998 Patrik Stridvall
5 * 2000 Eric Pouech
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "wineacm.h"
23
24 struct MSACM_FillFormatData {
25 HWND hWnd;
26 #define WINE_ACMFF_TAG 0
27 #define WINE_ACMFF_FORMAT 1
28 #define WINE_ACMFF_WFX 2
29 int mode;
30 WCHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
31 PACMFORMATCHOOSEW afc;
32 DWORD ret;
33 };
34
35 static BOOL CALLBACK MSACM_FillFormatTagsCB(HACMDRIVERID hadid,
36 PACMFORMATTAGDETAILSW paftd,
37 DWORD_PTR dwInstance,
38 DWORD fdwSupport)
39 {
40 struct MSACM_FillFormatData* affd = (struct MSACM_FillFormatData*)dwInstance;
41
42 switch (affd->mode) {
43 case WINE_ACMFF_TAG:
44 if (paftd->cStandardFormats > 0)
45 {
46 if (SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
47 CB_FINDSTRINGEXACT, -1,
48 (LPARAM)paftd->szFormatTag) == CB_ERR)
49 {
50 int index = SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
51 CB_ADDSTRING, 0, (LPARAM)paftd->szFormatTag);
52 if (((affd->afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT) &&
53 (paftd->dwFormatTag == affd->afc->pwfx->wFormatTag)) ||
54 (!(affd->afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT) &&
55 (paftd->dwFormatTag == WAVE_FORMAT_PCM)))
56 SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
57 CB_SETCURSEL, index, 0);
58 }
59 }
60 break;
61 case WINE_ACMFF_FORMAT:
62 if (strcmpW(affd->szFormatTag, paftd->szFormatTag) == 0) {
63 HACMDRIVER had;
64
65 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
66 ACMFORMATDETAILSW afd = {0};
67 unsigned int i, len;
68 MMRESULT mmr;
69 WCHAR buffer[ACMFORMATDETAILS_FORMAT_CHARS+16];
70
71 afd.cbStruct = sizeof(afd);
72 afd.dwFormatTag = paftd->dwFormatTag;
73 afd.pwfx = HeapAlloc(MSACM_hHeap, 0, paftd->cbFormatSize);
74 if (!afd.pwfx) return FALSE;
75 afd.pwfx->wFormatTag = paftd->dwFormatTag;
76 if (paftd->dwFormatTag != WAVE_FORMAT_PCM)
77 afd.pwfx->cbSize = paftd->cbFormatSize - sizeof(WAVEFORMATEX);
78 afd.cbwfx = paftd->cbFormatSize;
79
80 for (i = 0; i < paftd->cStandardFormats; i++) {
81 static const WCHAR fmtW[] = {'%','d',' ','K','o','/','s','\0'};
82 int j, index;
83
84 afd.dwFormatIndex = i;
85 afd.fdwSupport = 0;
86 mmr = acmFormatDetailsW(had, &afd, ACM_FORMATDETAILSF_INDEX);
87 if (mmr == MMSYSERR_NOERROR) {
88 lstrcpynW(buffer, afd.szFormat, ACMFORMATTAGDETAILS_FORMATTAG_CHARS + 1);
89 len = strlenW(buffer);
90 for (j = len; j < ACMFORMATTAGDETAILS_FORMATTAG_CHARS; j++)
91 buffer[j] = ' ';
92 wsprintfW(buffer + ACMFORMATTAGDETAILS_FORMATTAG_CHARS,
93 fmtW, (afd.pwfx->nAvgBytesPerSec + 512) / 1024);
94 index = SendDlgItemMessageW(affd->hWnd,
95 IDD_ACMFORMATCHOOSE_CMB_FORMAT,
96 CB_ADDSTRING, 0, (LPARAM)buffer);
97 if ((affd->afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT) &&
98 affd->afc->cbwfx >= paftd->cbFormatSize &&
99 !memcmp(afd.pwfx, affd->afc->pwfx, paftd->cbFormatSize))
100 SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT,
101 CB_SETCURSEL, index, 0);
102 }
103 }
104 acmDriverClose(had, 0);
105 HeapFree(MSACM_hHeap, 0, afd.pwfx);
106 }
107 }
108 break;
109 case WINE_ACMFF_WFX:
110 if (strcmpW(affd->szFormatTag, paftd->szFormatTag) == 0) {
111 HACMDRIVER had;
112
113 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
114 ACMFORMATDETAILSW afd = {0};
115
116 afd.cbStruct = sizeof(afd);
117 afd.dwFormatTag = paftd->dwFormatTag;
118 afd.pwfx = affd->afc->pwfx;
119 afd.cbwfx = affd->afc->cbwfx;
120
121 afd.dwFormatIndex = SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT,
122 CB_GETCURSEL, 0, 0);
123 affd->ret = acmFormatDetailsW(had, &afd, ACM_FORMATDETAILSF_INDEX);
124 acmDriverClose(had, 0);
125 return TRUE;
126 }
127 }
128 break;
129 default:
130 FIXME("Unknown mode (%d)\n", affd->mode);
131 break;
132 }
133 return TRUE;
134 }
135
136 static BOOL MSACM_FillFormatTags(HWND hWnd, PACMFORMATCHOOSEW afc)
137 {
138 ACMFORMATTAGDETAILSW aftd;
139 struct MSACM_FillFormatData affd;
140
141 memset(&aftd, 0, sizeof(aftd));
142 aftd.cbStruct = sizeof(aftd);
143
144 affd.hWnd = hWnd;
145 affd.mode = WINE_ACMFF_TAG;
146 affd.afc = afc;
147
148 acmFormatTagEnumW(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD_PTR)&affd, 0);
149 if (SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_GETCURSEL, 0, 0) == CB_ERR)
150 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_SETCURSEL, 0, 0);
151 return TRUE;
152 }
153
154 static BOOL MSACM_FillFormat(HWND hWnd, PACMFORMATCHOOSEW afc)
155 {
156 ACMFORMATTAGDETAILSW aftd;
157 struct MSACM_FillFormatData affd;
158
159 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_RESETCONTENT, 0, 0);
160
161 memset(&aftd, 0, sizeof(aftd));
162 aftd.cbStruct = sizeof(aftd);
163
164 affd.hWnd = hWnd;
165 affd.mode = WINE_ACMFF_FORMAT;
166 affd.afc = afc;
167 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
168 CB_GETLBTEXT,
169 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
170 CB_GETCURSEL, 0, 0),
171 (LPARAM)affd.szFormatTag);
172
173 acmFormatTagEnumW(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD_PTR)&affd, 0);
174 if (SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_GETCURSEL, 0, 0) == CB_ERR)
175 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_SETCURSEL, 0, 0);
176 return TRUE;
177 }
178
179 static MMRESULT MSACM_GetWFX(HWND hWnd, PACMFORMATCHOOSEW afc)
180 {
181 ACMFORMATTAGDETAILSW aftd;
182 struct MSACM_FillFormatData affd;
183
184 memset(&aftd, 0, sizeof(aftd));
185 aftd.cbStruct = sizeof(aftd);
186
187 affd.hWnd = hWnd;
188 affd.mode = WINE_ACMFF_WFX;
189 affd.afc = afc;
190 affd.ret = MMSYSERR_NOERROR;
191 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
192 CB_GETLBTEXT,
193 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
194 CB_GETCURSEL, 0, 0),
195 (LPARAM)affd.szFormatTag);
196
197 acmFormatTagEnumW(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD_PTR)&affd, 0);
198 return affd.ret;
199 }
200
201 static const WCHAR fmt_prop[] = {'a','c','m','p','r','o','p','\0'};
202
203 static INT_PTR CALLBACK FormatChooseDlgProc(HWND hWnd, UINT msg,
204 WPARAM wParam, LPARAM lParam)
205 {
206 PACMFORMATCHOOSEW afc = (PACMFORMATCHOOSEW)GetPropW(hWnd, fmt_prop);
207
208 TRACE("hwnd=%p msg=%i 0x%08lx 0x%08lx\n", hWnd, msg, wParam, lParam);
209
210 switch (msg) {
211 case WM_INITDIALOG:
212 afc = (PACMFORMATCHOOSEW)lParam;
213 SetPropW(hWnd, fmt_prop, (HANDLE)afc);
214 MSACM_FillFormatTags(hWnd, afc);
215 MSACM_FillFormat(hWnd, afc);
216 if ((afc->fdwStyle & ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP|
217 ACMFORMATCHOOSE_STYLEF_SHOWHELP|
218 ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT|
219 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE|
220 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE)) != 0)
221 FIXME("Unsupported style %08x\n", afc->fdwStyle);
222 if (!(afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP))
223 ShowWindow(GetDlgItem(hWnd, IDD_ACMFORMATCHOOSE_BTN_HELP), SW_HIDE);
224 return TRUE;
225
226 case WM_COMMAND:
227 switch (LOWORD(wParam)) {
228 case IDOK:
229 EndDialog(hWnd, MSACM_GetWFX(hWnd, afc));
230 return TRUE;
231 case IDCANCEL:
232 EndDialog(hWnd, ACMERR_CANCELED);
233 return TRUE;
234 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG:
235 switch (HIWORD(wParam)) {
236 case CBN_SELCHANGE:
237 MSACM_FillFormat(hWnd, afc);
238 break;
239 default:
240 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
241 HIWORD(wParam), lParam);
242 break;
243 }
244 break;
245 case IDD_ACMFORMATCHOOSE_BTN_HELP:
246 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP)
247 SendMessageW(afc->hwndOwner,
248 RegisterWindowMessageW(ACMHELPMSGSTRINGW), 0L, 0L);
249 break;
250
251 default:
252 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
253 LOWORD(wParam), HIWORD(wParam), lParam);
254 break;
255 }
256 break;
257 case WM_CONTEXTMENU:
258 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
259 SendMessageW(afc->hwndOwner,
260 RegisterWindowMessageW(ACMHELPMSGCONTEXTMENUW),
261 wParam, lParam);
262 break;
263 #if defined(WM_CONTEXTHELP)
264 case WM_CONTEXTHELP:
265 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
266 SendMessageW(afc->hwndOwner,
267 RegisterWindowMessageW(ACMHELPMSGCONTEXTHELPW),
268 wParam, lParam);
269 break;
270 #endif
271 default:
272 TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08lx 0x%08lx\n",
273 hWnd, msg, wParam, lParam );
274 break;
275 }
276 return FALSE;
277 }
278
279 /***********************************************************************
280 * acmFormatChooseA (MSACM32.@)
281 */
282 MMRESULT WINAPI acmFormatChooseA(PACMFORMATCHOOSEA pafmtc)
283 {
284 ACMFORMATCHOOSEW afcw;
285 MMRESULT ret;
286 LPWSTR title = NULL;
287 LPWSTR name = NULL;
288 LPWSTR templ = NULL;
289 DWORD sz;
290
291 if (pafmtc->cbStruct < sizeof(ACMFORMATCHOOSEA))
292 return MMSYSERR_INVALPARAM;
293
294 afcw.cbStruct = sizeof(afcw);
295 afcw.fdwStyle = pafmtc->fdwStyle;
296 afcw.hwndOwner = pafmtc->hwndOwner;
297 afcw.pwfx = pafmtc->pwfx;
298 afcw.cbwfx = pafmtc->cbwfx;
299 if (pafmtc->pszTitle)
300 {
301 sz = MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTitle, -1, NULL, 0);
302 if (!(title = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR))))
303 {
304 ret = MMSYSERR_NOMEM;
305 goto done;
306 }
307 MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTitle, -1, title, sz);
308 }
309 afcw.pszTitle = title;
310 if (pafmtc->pszName)
311 {
312 sz = MultiByteToWideChar(CP_ACP, 0, pafmtc->pszName, -1, NULL, 0);
313 if (!(name = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR))))
314 {
315 ret = MMSYSERR_NOMEM;
316 goto done;
317 }
318 MultiByteToWideChar(CP_ACP, 0, pafmtc->pszName, -1, name, sz);
319 }
320 afcw.pszName = name;
321 afcw.cchName = pafmtc->cchName;
322 afcw.fdwEnum = pafmtc->fdwEnum;
323 afcw.pwfxEnum = pafmtc->pwfxEnum;
324 afcw.hInstance = pafmtc->hInstance;
325 if (pafmtc->pszTemplateName)
326 {
327 sz = MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTemplateName, -1, NULL, 0);
328 if (!(templ = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR))))
329 {
330 ret = MMSYSERR_NOMEM;
331 goto done;
332 }
333 MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTemplateName, -1, templ, sz);
334 }
335 afcw.pszTemplateName = templ;
336 /* FIXME: hook procs not supported yet */
337 if (pafmtc->pfnHook)
338 {
339 FIXME("Unsupported hook procs\n");
340 ret = MMSYSERR_NOTSUPPORTED;
341 goto done;
342 }
343 ret = acmFormatChooseW(&afcw);
344 if (ret == MMSYSERR_NOERROR)
345 {
346 WideCharToMultiByte(CP_ACP, 0, afcw.szFormatTag, -1, pafmtc->szFormatTag, sizeof(pafmtc->szFormatTag),
347 NULL, NULL);
348 WideCharToMultiByte(CP_ACP, 0, afcw.szFormat, -1, pafmtc->szFormat, sizeof(pafmtc->szFormat),
349 NULL, NULL);
350 if (pafmtc->pszName)
351 WideCharToMultiByte(CP_ACP, 0, afcw.pszName, -1, pafmtc->pszName, pafmtc->cchName, NULL, NULL);
352 }
353 done:
354 HeapFree(GetProcessHeap(), 0, title);
355 HeapFree(GetProcessHeap(), 0, name);
356 HeapFree(GetProcessHeap(), 0, templ);
357 return ret;
358 }
359
360 /***********************************************************************
361 * acmFormatChooseW (MSACM32.@)
362 */
363 MMRESULT WINAPI acmFormatChooseW(PACMFORMATCHOOSEW pafmtc)
364 {
365 if (pafmtc->cbStruct < sizeof(ACMFORMATCHOOSEW))
366 return MMSYSERR_INVALPARAM;
367
368 if (!pafmtc->pwfx)
369 return MMSYSERR_INVALPARAM;
370
371 if (pafmtc->fdwStyle & ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE)
372 return DialogBoxIndirectParamW(MSACM_hInstance32, (LPCDLGTEMPLATEW)pafmtc->hInstance,
373 pafmtc->hwndOwner, FormatChooseDlgProc, (LPARAM)pafmtc);
374
375 if (pafmtc->fdwStyle & ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE)
376 return DialogBoxParamW(pafmtc->hInstance, pafmtc->pszTemplateName,
377 pafmtc->hwndOwner, FormatChooseDlgProc, (LPARAM)pafmtc);
378
379 return DialogBoxParamW(MSACM_hInstance32, MAKEINTRESOURCEW(DLG_ACMFORMATCHOOSE_ID),
380 pafmtc->hwndOwner, FormatChooseDlgProc, (LPARAM)pafmtc);
381 }
382
383 /***********************************************************************
384 * acmFormatDetailsA (MSACM32.@)
385 */
386 MMRESULT WINAPI acmFormatDetailsA(HACMDRIVER had, PACMFORMATDETAILSA pafd,
387 DWORD fdwDetails)
388 {
389 ACMFORMATDETAILSW afdw;
390 MMRESULT mmr;
391
392 if (!pafd)
393 return MMSYSERR_INVALPARAM;
394
395 memset(&afdw, 0, sizeof(afdw));
396 afdw.cbStruct = sizeof(afdw);
397 afdw.dwFormatIndex = pafd->dwFormatIndex;
398 afdw.dwFormatTag = pafd->dwFormatTag;
399 afdw.fdwSupport = pafd->fdwSupport;
400 afdw.pwfx = pafd->pwfx;
401 afdw.cbwfx = pafd->cbwfx;
402
403 mmr = acmFormatDetailsW(had, &afdw, fdwDetails);
404 if (mmr == MMSYSERR_NOERROR) {
405 pafd->dwFormatTag = afdw.dwFormatTag;
406 pafd->fdwSupport = afdw.fdwSupport;
407 WideCharToMultiByte( CP_ACP, 0, afdw.szFormat, -1,
408 pafd->szFormat, sizeof(pafd->szFormat), NULL, NULL );
409 }
410 return mmr;
411 }
412
413 /***********************************************************************
414 * acmFormatDetailsW (MSACM32.@)
415 */
416 MMRESULT WINAPI acmFormatDetailsW(HACMDRIVER had, PACMFORMATDETAILSW pafd, DWORD fdwDetails)
417 {
418 MMRESULT mmr;
419 static const WCHAR fmt1[] = {'%','d',' ','H','z',0};
420 static const WCHAR fmt2[] = {';',' ','%','d',' ','b','i','t','s',0};
421 ACMFORMATTAGDETAILSW aftd = {0};
422
423 TRACE("(%p, %p, %d)\n", had, pafd, fdwDetails);
424
425 if (!pafd)
426 return MMSYSERR_INVALPARAM;
427
428 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
429
430 if (!pafd->pwfx)
431 return MMSYSERR_INVALPARAM;
432
433 if (pafd->cbwfx < sizeof(PCMWAVEFORMAT))
434 return MMSYSERR_INVALPARAM;
435
436 if (pafd->fdwSupport)
437 return MMSYSERR_INVALPARAM;
438
439 if (pafd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
440 return MMSYSERR_INVALPARAM;
441
442 switch (fdwDetails) {
443 case ACM_FORMATDETAILSF_FORMAT:
444 if (pafd->dwFormatTag != pafd->pwfx->wFormatTag) {
445 mmr = MMSYSERR_INVALPARAM;
446 break;
447 }
448 if (had == NULL) {
449 PWINE_ACMDRIVERID padid;
450
451 mmr = ACMERR_NOTPOSSIBLE;
452 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
453 /* should check for codec only */
454 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
455 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
456 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
457 acmDriverClose(had, 0);
458 if (mmr == MMSYSERR_NOERROR) break;
459 }
460 }
461 } else {
462 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
463 }
464 break;
465 case ACM_FORMATDETAILSF_INDEX:
466 aftd.cbStruct = sizeof(aftd);
467 aftd.dwFormatTag = pafd->dwFormatTag;
468 mmr = acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_FORMATTAG);
469 if (mmr != MMSYSERR_NOERROR)
470 break;
471 if (pafd->dwFormatIndex >= aftd.cStandardFormats)
472 {
473 mmr = MMSYSERR_INVALPARAM;
474 break;
475 }
476 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
477 break;
478 default:
479 WARN("Unknown fdwDetails %08x\n", fdwDetails);
480 mmr = MMSYSERR_INVALFLAG;
481 break;
482 }
483
484 if (mmr == MMSYSERR_NOERROR && pafd->szFormat[0] == 0) {
485 wsprintfW(pafd->szFormat, fmt1, pafd->pwfx->nSamplesPerSec);
486 if (pafd->pwfx->wBitsPerSample) {
487 wsprintfW(pafd->szFormat + lstrlenW(pafd->szFormat), fmt2,
488 pafd->pwfx->wBitsPerSample);
489 }
490 MultiByteToWideChar( CP_ACP, 0, (pafd->pwfx->nChannels == 1) ? "; Mono" : "; Stereo", -1,
491 pafd->szFormat + strlenW(pafd->szFormat),
492 sizeof(pafd->szFormat)/sizeof(WCHAR) - strlenW(pafd->szFormat) );
493 }
494
495 TRACE("=> %d\n", mmr);
496 return mmr;
497 }
498
499 struct MSACM_FormatEnumWtoA_Instance {
500 PACMFORMATDETAILSA pafda;
501 DWORD_PTR dwInstance;
502 ACMFORMATENUMCBA fnCallback;
503 };
504
505 static BOOL CALLBACK MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid,
506 PACMFORMATDETAILSW pafdw,
507 DWORD_PTR dwInstance,
508 DWORD fdwSupport)
509 {
510 struct MSACM_FormatEnumWtoA_Instance* pafei;
511
512 pafei = (struct MSACM_FormatEnumWtoA_Instance*)dwInstance;
513
514 pafei->pafda->dwFormatIndex = pafdw->dwFormatIndex;
515 pafei->pafda->dwFormatTag = pafdw->dwFormatTag;
516 pafei->pafda->fdwSupport = pafdw->fdwSupport;
517 WideCharToMultiByte( CP_ACP, 0, pafdw->szFormat, -1,
518 pafei->pafda->szFormat, sizeof(pafei->pafda->szFormat), NULL, NULL );
519
520 return (pafei->fnCallback)(hadid, pafei->pafda,
521 pafei->dwInstance, fdwSupport);
522 }
523
524 /***********************************************************************
525 * acmFormatEnumA (MSACM32.@)
526 */
527 MMRESULT WINAPI acmFormatEnumA(HACMDRIVER had, PACMFORMATDETAILSA pafda,
528 ACMFORMATENUMCBA fnCallback,
529 DWORD_PTR dwInstance, DWORD fdwEnum)
530 {
531 ACMFORMATDETAILSW afdw;
532 struct MSACM_FormatEnumWtoA_Instance afei;
533
534 if (!pafda)
535 return MMSYSERR_INVALPARAM;
536
537 if (!fnCallback)
538 return MMSYSERR_INVALPARAM;
539
540 if (pafda->cbStruct < sizeof(*pafda))
541 return MMSYSERR_INVALPARAM;
542
543 memset(&afdw, 0, sizeof(afdw));
544 afdw.cbStruct = sizeof(afdw);
545 afdw.dwFormatIndex = pafda->dwFormatIndex;
546 afdw.dwFormatTag = pafda->dwFormatTag;
547 afdw.fdwSupport = pafda->fdwSupport;
548 afdw.pwfx = pafda->pwfx;
549 afdw.cbwfx = pafda->cbwfx;
550
551 afei.pafda = pafda;
552 afei.dwInstance = dwInstance;
553 afei.fnCallback = fnCallback;
554
555 return acmFormatEnumW(had, &afdw, MSACM_FormatEnumCallbackWtoA,
556 (DWORD_PTR)&afei, fdwEnum);
557 }
558
559 /***********************************************************************
560 * acmFormatEnumW (MSACM32.@)
561 */
562 static BOOL MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had,
563 PACMFORMATDETAILSW pafd, PWAVEFORMATEX pwfxRef,
564 ACMFORMATENUMCBW fnCallback,
565 DWORD_PTR dwInstance, DWORD fdwEnum)
566 {
567 ACMFORMATTAGDETAILSW aftd;
568 unsigned int i, j;
569
570 if (fdwEnum & ACM_FORMATENUMF_SUGGEST) {
571 HDRVR hdrvr;
572 ACMDRVFORMATSUGGEST adfs;
573 pafd->dwFormatIndex = 0;
574 memset(&aftd, 0, sizeof(aftd));
575 aftd.cbStruct = sizeof(aftd);
576 memset(&adfs, 0, sizeof(adfs));
577 adfs.cbStruct = sizeof(adfs);
578
579 for (i = 0; i < padid->cFormatTags; i++) {
580 aftd.dwFormatTag = i;
581 pafd->dwFormatTag = aftd.dwFormatTag;
582 pafd->pwfx->wFormatTag = pafd->dwFormatTag;
583
584 if (acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_INDEX) != MMSYSERR_NOERROR)
585 continue;
586
587 adfs.cbwfxSrc = aftd.cbFormatSize;
588 adfs.cbwfxDst = aftd.cbFormatSize;
589 adfs.pwfxSrc = pwfxRef;
590 adfs.pwfxDst = pafd->pwfx;
591 pafd->fdwSupport = padid->fdwSupport;
592
593 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) &&
594 aftd.dwFormatTag != pwfxRef->wFormatTag)
595 continue;
596
597 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
598 !(pafd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_HARDWARE))
599 continue;
600
601 hdrvr = OpenDriver(padid->pszFileName,0,0);
602 SendDriverMessage(hdrvr,ACMDM_FORMAT_SUGGEST,(LPARAM)&adfs,(fdwEnum & 0x000000FFL));
603
604 if (acmFormatDetailsW(had, pafd, ACM_FORMATDETAILSF_FORMAT) != MMSYSERR_NOERROR)
605 continue;
606
607 pafd->cbwfx = sizeof(*(pafd->pwfx));
608
609 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
610 return FALSE;
611 }
612 } else {
613 for (i = 0; i < padid->cFormatTags; i++) {
614 memset(&aftd, 0, sizeof(aftd));
615 aftd.cbStruct = sizeof(aftd);
616 aftd.dwFormatTagIndex = i;
617 if (acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_INDEX) != MMSYSERR_NOERROR)
618 continue;
619
620 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) && aftd.dwFormatTag != pwfxRef->wFormatTag)
621 continue;
622
623 for (j = 0; j < aftd.cStandardFormats; j++) {
624 pafd->dwFormatIndex = j;
625 pafd->dwFormatTag = aftd.dwFormatTag;
626 pafd->fdwSupport = 0;
627 if (acmFormatDetailsW(had, pafd, ACM_FORMATDETAILSF_INDEX) != MMSYSERR_NOERROR)
628 continue;
629
630 if ((fdwEnum & ACM_FORMATENUMF_NCHANNELS) &&
631 pafd->pwfx->nChannels != pwfxRef->nChannels)
632 continue;
633 if ((fdwEnum & ACM_FORMATENUMF_NSAMPLESPERSEC) &&
634 pafd->pwfx->nSamplesPerSec != pwfxRef->nSamplesPerSec)
635 continue;
636 if ((fdwEnum & ACM_FORMATENUMF_WBITSPERSAMPLE) &&
637 pafd->pwfx->wBitsPerSample != pwfxRef->wBitsPerSample)
638 continue;
639 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
640 !(pafd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_HARDWARE))
641 continue;
642
643 /* more checks to be done on fdwEnum */
644
645 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
646 return FALSE;
647 }
648 /* the "formats" used by the filters are also reported */
649 }
650 }
651 return TRUE;
652 }
653
654 /**********************************************************************/
655
656 MMRESULT WINAPI acmFormatEnumW(HACMDRIVER had, PACMFORMATDETAILSW pafd,
657 ACMFORMATENUMCBW fnCallback,
658 DWORD_PTR dwInstance, DWORD fdwEnum)
659 {
660 PWINE_ACMDRIVERID padid;
661 WAVEFORMATEX wfxRef;
662 BOOL ret;
663 DWORD cbwfxMax;
664 MMRESULT mmr;
665
666 TRACE("(%p, %p, %p, %ld, %d)\n",
667 had, pafd, fnCallback, dwInstance, fdwEnum);
668
669 if (!pafd)
670 return MMSYSERR_INVALPARAM;
671
672 if (!fnCallback)
673 return MMSYSERR_INVALPARAM;
674
675 if (pafd->cbStruct < sizeof(*pafd))
676 return MMSYSERR_INVALPARAM;
677
678 if (pafd->fdwSupport)
679 return MMSYSERR_INVALPARAM;
680
681 if (!pafd->pwfx)
682 return MMSYSERR_INVALPARAM;
683
684 if (fdwEnum & (ACM_FORMATENUMF_WFORMATTAG|ACM_FORMATENUMF_NCHANNELS|
685 ACM_FORMATENUMF_NSAMPLESPERSEC|ACM_FORMATENUMF_WBITSPERSAMPLE|
686 ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST))
687 wfxRef = *pafd->pwfx;
688
689 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
690 !(fdwEnum & (ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT)))
691 return MMSYSERR_INVALPARAM;
692
693 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) &&
694 (pafd->dwFormatTag != pafd->pwfx->wFormatTag))
695 return MMSYSERR_INVALPARAM;
696
697 if (fdwEnum & (ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT))
698 FIXME("Unsupported fdwEnum values %08x\n", fdwEnum);
699
700 mmr = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &cbwfxMax);
701 if (mmr != MMSYSERR_NOERROR)
702 return mmr;
703 if (pafd->cbwfx < cbwfxMax)
704 return MMSYSERR_INVALPARAM;
705
706 if (had) {
707 HACMDRIVERID hadid;
708
709 if (acmDriverID((HACMOBJ)had, &hadid, 0) != MMSYSERR_NOERROR)
710 return MMSYSERR_INVALHANDLE;
711 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid), had, pafd, &wfxRef,
712 fnCallback, dwInstance, fdwEnum);
713 return MMSYSERR_NOERROR;
714 }
715 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
716 /* should check for codec only */
717 if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ||
718 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
719 continue;
720 ret = MSACM_FormatEnumHelper(padid, had, pafd, &wfxRef,
721 fnCallback, dwInstance, fdwEnum);
722 acmDriverClose(had, 0);
723 if (!ret) break;
724 }
725 return MMSYSERR_NOERROR;
726 }
727
728 /***********************************************************************
729 * acmFormatSuggest (MSACM32.@)
730 */
731 MMRESULT WINAPI acmFormatSuggest(HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
732 PWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest)
733 {
734 ACMFORMATTAGDETAILSW aftd = {0};
735 ACMDRVFORMATSUGGEST adfg;
736 MMRESULT mmr;
737
738 TRACE("(%p, %p, %p, %d, %d)\n",
739 had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest);
740
741 if (!pwfxSrc || !pwfxDst)
742 return MMSYSERR_INVALPARAM;
743
744 if (fdwSuggest & ~(ACM_FORMATSUGGESTF_NCHANNELS|ACM_FORMATSUGGESTF_NSAMPLESPERSEC|
745 ACM_FORMATSUGGESTF_WBITSPERSAMPLE|ACM_FORMATSUGGESTF_WFORMATTAG))
746 return MMSYSERR_INVALFLAG;
747
748 /* if we were given PCM, try to convert to PCM */
749 if (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && !had &&
750 !(fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
751 {
752 ACMFORMATDETAILSW afd = {0};
753 afd.cbStruct = sizeof(afd);
754 afd.dwFormatTag = WAVE_FORMAT_PCM;
755 afd.pwfx = pwfxSrc;
756 afd.cbwfx = sizeof(PCMWAVEFORMAT);
757 if (!acmFormatDetailsW(had, &afd, ACM_FORMATDETAILSF_FORMAT))
758 {
759 memcpy(pwfxDst, pwfxSrc, sizeof(PCMWAVEFORMAT));
760 return MMSYSERR_NOERROR;
761 }
762 }
763
764 aftd.cbStruct = sizeof(aftd);
765 if (fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)
766 aftd.dwFormatTag = pwfxDst->wFormatTag;
767 mmr = acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_LARGESTSIZE);
768 if ((fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) && mmr == ACMERR_NOTPOSSIBLE)
769 return ACMERR_NOTPOSSIBLE;
770
771 if (cbwfxDst < aftd.cbFormatSize)
772 return MMSYSERR_INVALPARAM;
773
774 adfg.cbStruct = sizeof(adfg);
775 adfg.fdwSuggest = fdwSuggest;
776 adfg.pwfxSrc = pwfxSrc;
777 adfg.cbwfxSrc = (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) ?
778 sizeof(WAVEFORMATEX) : (sizeof(WAVEFORMATEX) + pwfxSrc->cbSize);
779 adfg.pwfxDst = pwfxDst;
780 adfg.cbwfxDst = cbwfxDst;
781
782 if (had == NULL) {
783 PWINE_ACMDRIVERID padid;
784
785 /* MS doc says: ACM finds the best suggestion.
786 * Well, first found will be the "best"
787 */
788 mmr = ACMERR_NOTPOSSIBLE;
789 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
790 /* should check for codec only */
791 if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ||
792 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
793 continue;
794
795 if (MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L) == MMSYSERR_NOERROR) {
796 mmr = MMSYSERR_NOERROR;
797 break;
798 }
799 acmDriverClose(had, 0);
800 }
801 } else {
802 mmr = MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L);
803 }
804 return mmr;
805 }
806
807 /***********************************************************************
808 * acmFormatTagDetailsA (MSACM32.@)
809 */
810 MMRESULT WINAPI acmFormatTagDetailsA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
811 DWORD fdwDetails)
812 {
813 ACMFORMATTAGDETAILSW aftdw;
814 MMRESULT mmr;
815
816 memset(&aftdw, 0, sizeof(aftdw));
817 aftdw.cbStruct = sizeof(aftdw);
818 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
819 aftdw.dwFormatTag = paftda->dwFormatTag;
820
821 mmr = acmFormatTagDetailsW(had, &aftdw, fdwDetails);
822 if (mmr == MMSYSERR_NOERROR) {
823 paftda->dwFormatTag = aftdw.dwFormatTag;
824 paftda->dwFormatTagIndex = aftdw.dwFormatTagIndex;
825 paftda->cbFormatSize = aftdw.cbFormatSize;
826 paftda->fdwSupport = aftdw.fdwSupport;
827 paftda->cStandardFormats = aftdw.cStandardFormats;
828 WideCharToMultiByte( CP_ACP, 0, aftdw.szFormatTag, -1, paftda->szFormatTag,
829 sizeof(paftda->szFormatTag), NULL, NULL );
830 }
831 return mmr;
832 }
833
834 /***********************************************************************
835 * acmFormatTagDetailsW (MSACM32.@)
836 */
837 MMRESULT WINAPI acmFormatTagDetailsW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
838 DWORD fdwDetails)
839 {
840 PWINE_ACMDRIVERID padid;
841 MMRESULT mmr = ACMERR_NOTPOSSIBLE;
842
843 TRACE("(%p, %p, %d)\n", had, paftd, fdwDetails);
844
845 if (fdwDetails & ~(ACM_FORMATTAGDETAILSF_FORMATTAG|ACM_FORMATTAGDETAILSF_INDEX|
846 ACM_FORMATTAGDETAILSF_LARGESTSIZE))
847 return MMSYSERR_INVALFLAG;
848
849 switch (fdwDetails) {
850 case ACM_FORMATTAGDETAILSF_FORMATTAG:
851 if (had == NULL) {
852 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
853 /* should check for codec only */
854 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
855 MSACM_FindFormatTagInCache(padid, paftd->dwFormatTag, NULL) &&
856 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
857 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
858 acmDriverClose(had, 0);
859 if (mmr == MMSYSERR_NOERROR) break;
860 }
861 }
862 } else {
863 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
864
865 if (pad && MSACM_FindFormatTagInCache(pad->obj.pACMDriverID, paftd->dwFormatTag, NULL))
866 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
867 }
868 break;
869
870 case ACM_FORMATTAGDETAILSF_INDEX:
871 if (had != NULL) {
872 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
873
874 if (pad && paftd->dwFormatTagIndex < pad->obj.pACMDriverID->cFormatTags)
875 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
876 }
877 break;
878
879 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
880 if (had == NULL) {
881 ACMFORMATTAGDETAILSW tmp;
882 DWORD ft = paftd->dwFormatTag;
883
884 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
885 /* should check for codec only */
886 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
887 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
888
889 memset(&tmp, 0, sizeof(tmp));
890 tmp.cbStruct = sizeof(tmp);
891 tmp.dwFormatTag = ft;
892
893 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
894 (LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) {
895 if (mmr == ACMERR_NOTPOSSIBLE ||
896 paftd->cbFormatSize < tmp.cbFormatSize) {
897 *paftd = tmp;
898 mmr = MMSYSERR_NOERROR;
899 }
900 }
901 acmDriverClose(had, 0);
902 }
903 }
904 } else {
905 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
906 }
907 break;
908
909 default:
910 WARN("Unsupported fdwDetails=%08x\n", fdwDetails);
911 mmr = MMSYSERR_ERROR;
912 }
913
914 if (mmr == MMSYSERR_NOERROR &&
915 paftd->dwFormatTag == WAVE_FORMAT_PCM && paftd->szFormatTag[0] == 0)
916 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
917 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
918
919 return mmr;
920 }
921
922 struct MSACM_FormatTagEnumWtoA_Instance {
923 PACMFORMATTAGDETAILSA paftda;
924 DWORD_PTR dwInstance;
925 ACMFORMATTAGENUMCBA fnCallback;
926 };
927
928 static BOOL CALLBACK MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid,
929 PACMFORMATTAGDETAILSW paftdw,
930 DWORD_PTR dwInstance,
931 DWORD fdwSupport)
932 {
933 struct MSACM_FormatTagEnumWtoA_Instance* paftei;
934
935 paftei = (struct MSACM_FormatTagEnumWtoA_Instance*)dwInstance;
936
937 paftei->paftda->dwFormatTagIndex = paftdw->dwFormatTagIndex;
938 paftei->paftda->dwFormatTag = paftdw->dwFormatTag;
939 paftei->paftda->cbFormatSize = paftdw->cbFormatSize;
940 paftei->paftda->fdwSupport = paftdw->fdwSupport;
941 paftei->paftda->cStandardFormats = paftdw->cStandardFormats;
942 WideCharToMultiByte( CP_ACP, 0, paftdw->szFormatTag, -1, paftei->paftda->szFormatTag,
943 sizeof(paftei->paftda->szFormatTag), NULL, NULL );
944
945 return (paftei->fnCallback)(hadid, paftei->paftda,
946 paftei->dwInstance, fdwSupport);
947 }
948
949 /***********************************************************************
950 * acmFormatTagEnumA (MSACM32.@)
951 */
952 MMRESULT WINAPI acmFormatTagEnumA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
953 ACMFORMATTAGENUMCBA fnCallback,
954 DWORD_PTR dwInstance, DWORD fdwEnum)
955 {
956 ACMFORMATTAGDETAILSW aftdw;
957 struct MSACM_FormatTagEnumWtoA_Instance aftei;
958
959 if (!paftda)
960 return MMSYSERR_INVALPARAM;
961
962 if (paftda->cbStruct < sizeof(*paftda))
963 return MMSYSERR_INVALPARAM;
964
965 if (fdwEnum != 0)
966 return MMSYSERR_INVALFLAG;
967
968 memset(&aftdw, 0, sizeof(aftdw));
969 aftdw.cbStruct = sizeof(aftdw);
970 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
971 aftdw.dwFormatTag = paftda->dwFormatTag;
972
973 aftei.paftda = paftda;
974 aftei.dwInstance = dwInstance;
975 aftei.fnCallback = fnCallback;
976
977 return acmFormatTagEnumW(had, &aftdw, MSACM_FormatTagEnumCallbackWtoA,
978 (DWORD_PTR)&aftei, fdwEnum);
979 }
980
981 /***********************************************************************
982 * acmFormatTagEnumW (MSACM32.@)
983 */
984 MMRESULT WINAPI acmFormatTagEnumW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
985 ACMFORMATTAGENUMCBW fnCallback,
986 DWORD_PTR dwInstance, DWORD fdwEnum)
987 {
988 PWINE_ACMDRIVERID padid;
989 unsigned int i;
990 BOOL bPcmDone = FALSE;
991
992 TRACE("(%p, %p, %p, %ld, %d)\n",
993 had, paftd, fnCallback, dwInstance, fdwEnum);
994
995 if (!paftd)
996 return MMSYSERR_INVALPARAM;
997
998 if (paftd->cbStruct < sizeof(*paftd))
999 return MMSYSERR_INVALPARAM;
1000
1001 if (fdwEnum != 0)
1002 return MMSYSERR_INVALFLAG;
1003
1004 /* (WS) MSDN info page says that if had != 0, then we should find
1005 * the specific driver to get its tags from. Therefore I'm removing
1006 * the FIXME call and adding a search block below. It also seems
1007 * that the lack of this functionality was the responsible for
1008 * codecs to be multiply and incorrectly listed.
1009 */
1010
1011 /* if (had) FIXME("had != NULL, not supported\n"); */
1012
1013 if (had) {
1014 if (acmDriverID((HACMOBJ)had, (HACMDRIVERID *)&padid, 0) != MMSYSERR_NOERROR)
1015 return MMSYSERR_INVALHANDLE;
1016
1017 for (i = 0; i < padid->cFormatTags; i++) {
1018 paftd->dwFormatTagIndex = i;
1019 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
1020 (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
1021 if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
1022 if (paftd->szFormatTag[0] == 0)
1023 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
1024 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
1025 /* (WS) I'm preserving this PCM hack since it seems to be
1026 * correct. Please notice this block was borrowed from
1027 * below.
1028 */
1029 if (bPcmDone) continue;
1030 bPcmDone = TRUE;
1031 }
1032 if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport))
1033 return MMSYSERR_NOERROR;
1034 }
1035 }
1036 }
1037 /* if had==0 then search for the first suitable driver */
1038 else {
1039 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
1040 /* should check for codec only */
1041 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
1042 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
1043 for (i = 0; i < padid->cFormatTags; i++) {
1044 paftd->dwFormatTagIndex = i;
1045 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
1046 (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
1047 if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
1048 if (paftd->szFormatTag[0] == 0)
1049 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
1050 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
1051 /* FIXME (EPP): I'm not sure this is the correct
1052 * algorithm (should make more sense to apply the same
1053 * for all already loaded formats, but this will do
1054 * for now
1055 */
1056 if (bPcmDone) continue;
1057 bPcmDone = TRUE;
1058 }
1059 if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) {
1060 acmDriverClose(had, 0);
1061 return MMSYSERR_NOERROR;
1062 }
1063 }
1064 }
1065 acmDriverClose(had, 0);
1066 }
1067 }
1068 }
1069 return MMSYSERR_NOERROR;
1070 }