Fixed some issues found by winapi_check.
[wine] / dlls / msacm / filter.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  *      MSACM32 library
5  *
6  *      Copyright 1998  Patrik Stridvall
7  */
8
9 #include "winbase.h"
10 #include "winnls.h"
11 #include "winerror.h"
12 #include "mmsystem.h"
13 #include "msacm.h"
14 #include "msacmdrv.h"
15 #include "wineacm.h"
16 #include "debugtools.h"
17
18 DEFAULT_DEBUG_CHANNEL(msacm);
19
20 /***********************************************************************
21  *           acmFilterChooseA (MSACM32.13)
22  */
23 MMRESULT WINAPI acmFilterChooseA(PACMFILTERCHOOSEA pafltrc)
24 {
25     FIXME("(%p): stub\n", pafltrc);
26     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
27     return MMSYSERR_ERROR;
28 }
29
30 /***********************************************************************
31  *           acmFilterChooseW (MSACM32.14)
32  */
33 MMRESULT WINAPI acmFilterChooseW(PACMFILTERCHOOSEW pafltrc)
34 {
35     FIXME("(%p): stub\n", pafltrc);
36     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
37     return MMSYSERR_ERROR;
38 }
39
40 /***********************************************************************
41  *           acmFilterDetailsA (MSACM32.15)
42  */
43 MMRESULT WINAPI acmFilterDetailsA(HACMDRIVER had, PACMFILTERDETAILSA pafd, 
44                                   DWORD fdwDetails)
45 {
46     ACMFILTERDETAILSW   afdw;
47     MMRESULT            mmr;
48
49     memset(&afdw, 0, sizeof(afdw));
50     afdw.cbStruct = sizeof(afdw);
51     afdw.dwFilterIndex = pafd->dwFilterIndex;
52     afdw.dwFilterTag = pafd->dwFilterTag; 
53     afdw.pwfltr = pafd->pwfltr;
54     afdw.cbwfltr = pafd->cbwfltr;
55
56     mmr = acmFilterDetailsW(had, &afdw, fdwDetails);
57     if (mmr == MMSYSERR_NOERROR) {
58         pafd->dwFilterTag = afdw.dwFilterTag; 
59         pafd->fdwSupport = afdw.fdwSupport; 
60         WideCharToMultiByte( CP_ACP, 0, afdw.szFilter, -1, pafd->szFilter,
61                              sizeof(pafd->szFilter), NULL, NULL );
62     }
63     return mmr;
64 }
65
66 /***********************************************************************
67  *           acmFilterDetailsW (MSACM32.16)
68  */
69 MMRESULT WINAPI acmFilterDetailsW(HACMDRIVER had, PACMFILTERDETAILSW pafd, 
70                                   DWORD fdwDetails)
71 {
72     MMRESULT                    mmr;
73     ACMFILTERTAGDETAILSA        aftd;
74
75     TRACE("(0x%08x, %p, %ld)\n", had, pafd, fdwDetails);
76
77     memset(&aftd, 0, sizeof(aftd));
78     aftd.cbStruct = sizeof(aftd);
79
80     if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
81         
82     switch (fdwDetails) {
83     case ACM_FILTERDETAILSF_FILTER:
84         if (pafd->dwFilterTag != pafd->pwfltr->dwFilterTag) {
85             mmr = MMSYSERR_INVALPARAM;
86             break;
87         }
88         if (had == (HACMDRIVER)NULL) {
89             PWINE_ACMDRIVERID           padid;
90
91             mmr = ACMERR_NOTPOSSIBLE;
92             for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
93                 /* should check for codec only */
94                 if (padid->bEnabled && 
95                     acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
96                     mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS,
97                                         (LPARAM)pafd, (LPARAM)fdwDetails);
98                     acmDriverClose(had, 0);
99                     if (mmr == MMSYSERR_NOERROR) break;
100                 }
101             }               
102         } else {
103             mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS,
104                                 (LPARAM)pafd, (LPARAM)fdwDetails);
105         }
106         break;
107     case ACM_FILTERDETAILSF_INDEX:
108         /* should check pafd->dwFilterIndex < aftd->cStandardFilters */
109         mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS,
110                             (LPARAM)pafd, (LPARAM)fdwDetails);
111         break;
112     default:
113         WARN("Unknown fdwDetails %08lx\n", fdwDetails);
114         mmr = MMSYSERR_INVALFLAG;
115         break;
116     }
117
118     TRACE("=> %d\n", mmr);
119     return mmr;
120 }
121
122 struct MSACM_FilterEnumWtoA_Instance {
123     PACMFILTERDETAILSA  pafda;
124     DWORD               dwInstance;
125     ACMFILTERENUMCBA    fnCallback;
126 };
127
128 static BOOL CALLBACK MSACM_FilterEnumCallbackWtoA(HACMDRIVERID hadid,
129                                                   PACMFILTERDETAILSW pafdw,  
130                                                   DWORD dwInstance,             
131                                                   DWORD fdwSupport)
132 {
133     struct MSACM_FilterEnumWtoA_Instance* pafei;
134
135     pafei = (struct MSACM_FilterEnumWtoA_Instance*)dwInstance;
136
137     pafei->pafda->dwFilterIndex = pafdw->dwFilterIndex; 
138     pafei->pafda->dwFilterTag = pafdw->dwFilterTag; 
139     pafei->pafda->fdwSupport = pafdw->fdwSupport; 
140     WideCharToMultiByte( CP_ACP, 0, pafdw->szFilter, -1, pafei->pafda->szFilter,
141                          sizeof(pafei->pafda->szFilter), NULL, NULL );
142
143     return (pafei->fnCallback)(hadid, pafei->pafda, 
144                                pafei->dwInstance, fdwSupport);
145 }
146
147 /***********************************************************************
148  *           acmFilterEnumA (MSACM32.17)
149  */
150 MMRESULT WINAPI acmFilterEnumA(HACMDRIVER had, PACMFILTERDETAILSA pafda, 
151                                ACMFILTERENUMCBA fnCallback, DWORD dwInstance, 
152                                DWORD fdwEnum)
153 {
154     ACMFILTERDETAILSW           afdw;
155     struct MSACM_FilterEnumWtoA_Instance afei;
156
157     memset(&afdw, 0, sizeof(afdw));
158     afdw.cbStruct = sizeof(afdw);
159     afdw.dwFilterIndex = pafda->dwFilterIndex;
160     afdw.dwFilterTag = pafda->dwFilterTag;
161     afdw.pwfltr = pafda->pwfltr;
162     afdw.cbwfltr = pafda->cbwfltr;
163
164     afei.pafda = pafda;
165     afei.dwInstance = dwInstance;
166     afei.fnCallback = fnCallback;
167
168     return acmFilterEnumW(had, &afdw, MSACM_FilterEnumCallbackWtoA, 
169                           (DWORD)&afei, fdwEnum);
170 }
171
172 static BOOL MSACM_FilterEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had, 
173                                    PACMFILTERDETAILSW pafd, 
174                                    ACMFILTERENUMCBW fnCallback, DWORD dwInstance,  
175                                    DWORD fdwEnum)
176 {
177     ACMDRIVERDETAILSW           add;
178     ACMFILTERTAGDETAILSW        aftd;
179     int                         i, j;
180
181     add.cbStruct = sizeof(add);
182     
183     if (acmDriverDetailsW((HACMDRIVERID)padid, &add, 0) != MMSYSERR_NOERROR) return FALSE;
184
185     for (i = 0; i < add.cFilterTags; i++) {
186         memset(&aftd, 0, sizeof(aftd));
187         aftd.cbStruct = sizeof(aftd);
188         aftd.dwFilterTagIndex = i;
189         if (acmFilterTagDetailsW(had, &aftd, ACM_FILTERTAGDETAILSF_INDEX) != MMSYSERR_NOERROR)
190             continue;
191         
192         if ((fdwEnum & ACM_FILTERENUMF_DWFILTERTAG) && 
193             aftd.dwFilterTag != pafd->pwfltr->dwFilterTag)
194             continue;
195         
196         for (j = 0; j < aftd.cStandardFilters; j++) {
197             pafd->dwFilterIndex = j;
198             pafd->dwFilterTag = aftd.dwFilterTag;
199             if (acmFilterDetailsW(had, pafd, ACM_FILTERDETAILSF_INDEX) != MMSYSERR_NOERROR) 
200                 continue;
201             
202             if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, add.fdwSupport))
203                 return FALSE; 
204         }
205     }
206     return TRUE;
207 }
208
209 /***********************************************************************
210  *           acmFilterEnumW (MSACM32.18)
211  */
212 MMRESULT WINAPI acmFilterEnumW(HACMDRIVER had, PACMFILTERDETAILSW pafd, 
213                                ACMFILTERENUMCBW fnCallback, DWORD dwInstance, 
214                                DWORD fdwEnum)
215 {
216     PWINE_ACMDRIVERID           padid;
217     BOOL                        ret;
218
219     TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
220           had, pafd, fnCallback, dwInstance, fdwEnum);
221
222     if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
223
224     if (fdwEnum & ~(ACM_FILTERENUMF_DWFILTERTAG))
225         FIXME("Unsupported fdwEnum values\n");
226
227     if (had) {
228         HACMDRIVERID    hadid;
229
230         if (acmDriverID(had, &hadid, 0) != MMSYSERR_NOERROR)
231             return MMSYSERR_INVALHANDLE;
232         return MSACM_FilterEnumHelper(MSACM_GetDriverID(hadid), had, pafd,
233                                       fnCallback, dwInstance, fdwEnum);
234     }
235     for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
236             /* should check for codec only */
237             if (!padid->bEnabled || acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
238                 continue;
239             ret = MSACM_FilterEnumHelper(padid, had, pafd, 
240                                          fnCallback, dwInstance, fdwEnum);
241             acmDriverClose(had, 0);
242             if (!ret) break;
243     }
244     return MMSYSERR_NOERROR;
245 }
246
247 /***********************************************************************
248  *           acmFilterTagDetailsA (MSACM32.19)
249  */
250 MMRESULT WINAPI acmFilterTagDetailsA(HACMDRIVER had, PACMFILTERTAGDETAILSA paftda, 
251                                      DWORD fdwDetails)
252 {
253     ACMFILTERTAGDETAILSW        aftdw;
254     MMRESULT                    mmr;
255
256     memset(&aftdw, 0, sizeof(aftdw));
257     aftdw.cbStruct = sizeof(aftdw);
258     aftdw.dwFilterTagIndex = paftda->dwFilterTagIndex;
259     aftdw.dwFilterTag = paftda->dwFilterTag;
260
261     mmr = acmFilterTagDetailsW(had, &aftdw, fdwDetails);
262     if (mmr == MMSYSERR_NOERROR) {
263         paftda->dwFilterTag = aftdw.dwFilterTag; 
264         paftda->dwFilterTagIndex = aftdw.dwFilterTagIndex;
265         paftda->cbFilterSize = aftdw.cbFilterSize; 
266         paftda->fdwSupport = aftdw.fdwSupport; 
267         paftda->cStandardFilters = aftdw.cStandardFilters; 
268         WideCharToMultiByte( CP_ACP, 0, aftdw.szFilterTag, -1, paftda->szFilterTag,
269                              sizeof(paftda->szFilterTag), NULL, NULL );
270     }
271     return mmr;
272 }
273
274 /***********************************************************************
275  *           acmFilterTagDetailsW (MSACM32.20)
276  */
277 MMRESULT WINAPI acmFilterTagDetailsW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd, 
278                                      DWORD fdwDetails)
279 {
280     PWINE_ACMDRIVERID   padid;
281     MMRESULT            mmr;
282
283     TRACE("(0x%08x, %p, %ld)\n", had, paftd, fdwDetails);
284
285     if (fdwDetails & ~(ACM_FILTERTAGDETAILSF_FILTERTAG|ACM_FILTERTAGDETAILSF_INDEX|
286                        ACM_FILTERTAGDETAILSF_LARGESTSIZE))
287         return MMSYSERR_INVALFLAG;
288
289     switch (fdwDetails) {
290     case ACM_FILTERTAGDETAILSF_FILTERTAG:
291         if (had == (HACMDRIVER)NULL) {
292             mmr = ACMERR_NOTPOSSIBLE;
293             for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
294                 /* should check for codec only */
295                 if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
296                     mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
297                                         (LPARAM)paftd, (LPARAM)fdwDetails);
298                     acmDriverClose(had, 0);
299                     if (mmr == MMSYSERR_NOERROR) break;
300                 }
301             }
302         } else {
303             mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
304                                 (LPARAM)paftd, (LPARAM)fdwDetails);
305         }
306         break;
307
308     case ACM_FILTERTAGDETAILSF_INDEX:
309         /* FIXME should check paftd->dwFilterTagIndex < add.cFilterTags */
310         mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
311                             (LPARAM)paftd, (LPARAM)fdwDetails);
312         break;
313
314     case ACM_FILTERTAGDETAILSF_LARGESTSIZE:
315         if (had == (HACMDRIVER)NULL) {
316             ACMFILTERTAGDETAILSW        tmp;
317             DWORD                       ft = paftd->dwFilterTag;
318
319             mmr = ACMERR_NOTPOSSIBLE;
320             for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
321                 /* should check for codec only */
322                 if (padid->bEnabled && 
323                     acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
324
325                     memset(&tmp, 0, sizeof(tmp));
326                     tmp.cbStruct = sizeof(tmp);
327                     tmp.dwFilterTag = ft;
328
329                     if (MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
330                                       (LPARAM)&tmp, 
331                                       (LPARAM)fdwDetails) == MMSYSERR_NOERROR) {
332                         if (mmr == ACMERR_NOTPOSSIBLE ||
333                             paftd->cbFilterSize < tmp.cbFilterSize) {
334                             *paftd = tmp;
335                             mmr = MMSYSERR_NOERROR;
336                         } 
337                     }
338                     acmDriverClose(had, 0);
339                 }
340             }
341         } else {
342             mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
343                                 (LPARAM)paftd, (LPARAM)fdwDetails);
344         }
345         break;
346
347     default:
348         WARN("Unsupported fdwDetails=%08lx\n", fdwDetails);
349         mmr = MMSYSERR_ERROR;
350     }
351
352     if (mmr == MMSYSERR_NOERROR && 
353         paftd->dwFilterTag == WAVE_FORMAT_PCM && paftd->szFilterTag[0] == 0)
354         MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFilterTag,
355                              sizeof(paftd->szFilterTag)/sizeof(WCHAR) );
356
357     return mmr;
358 }
359
360 struct MSACM_FilterTagEnumWtoA_Instance {
361     PACMFILTERTAGDETAILSA       paftda;
362     DWORD                       dwInstance;
363     ACMFILTERTAGENUMCBA         fnCallback;
364 };
365
366 static BOOL CALLBACK MSACM_FilterTagEnumCallbackWtoA(HACMDRIVERID hadid,
367                                                      PACMFILTERTAGDETAILSW paftdw,  
368                                                      DWORD dwInstance,             
369                                                      DWORD fdwSupport)
370 {
371     struct MSACM_FilterTagEnumWtoA_Instance* paftei;
372
373     paftei = (struct MSACM_FilterTagEnumWtoA_Instance*)dwInstance;
374
375     paftei->paftda->dwFilterTagIndex = paftdw->dwFilterTagIndex; 
376     paftei->paftda->dwFilterTag = paftdw->dwFilterTag; 
377     paftei->paftda->cbFilterSize = paftdw->cbFilterSize; 
378     paftei->paftda->fdwSupport = paftdw->fdwSupport; 
379     paftei->paftda->cStandardFilters = paftdw->cStandardFilters; 
380     WideCharToMultiByte( CP_ACP, 0, paftdw->szFilterTag, -1, paftei->paftda->szFilterTag,
381                          sizeof(paftei->paftda->szFilterTag), NULL, NULL );
382
383     return (paftei->fnCallback)(hadid, paftei->paftda, 
384                                 paftei->dwInstance, fdwSupport);
385 }
386
387 /***********************************************************************
388  *           acmFilterTagEnumA (MSACM32.21)
389  */
390 MMRESULT WINAPI acmFilterTagEnumA(HACMDRIVER had, PACMFILTERTAGDETAILSA paftda,
391                                   ACMFILTERTAGENUMCBA fnCallback, DWORD dwInstance, 
392                                   DWORD fdwEnum)
393 {
394     ACMFILTERTAGDETAILSW        aftdw;
395     struct MSACM_FilterTagEnumWtoA_Instance aftei;
396
397     memset(&aftdw, 0, sizeof(aftdw));
398     aftdw.cbStruct = sizeof(aftdw);
399     aftdw.dwFilterTagIndex = paftda->dwFilterTagIndex;
400     aftdw.dwFilterTag = paftda->dwFilterTag;
401
402     aftei.paftda = paftda;
403     aftei.dwInstance = dwInstance;
404     aftei.fnCallback = fnCallback;
405
406     return acmFilterTagEnumW(had, &aftdw, MSACM_FilterTagEnumCallbackWtoA, 
407                              (DWORD)&aftei, fdwEnum);
408 }
409
410 /***********************************************************************
411  *           acmFilterTagEnumW (MSACM32.22)
412  */
413 MMRESULT WINAPI acmFilterTagEnumW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd,
414                                   ACMFILTERTAGENUMCBW fnCallback, DWORD dwInstance, 
415                                   DWORD fdwEnum)
416 {
417     PWINE_ACMDRIVERID           padid;
418     ACMDRIVERDETAILSW           add;
419     int                         i;
420
421     TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
422           had, paftd, fnCallback, dwInstance, fdwEnum); 
423
424     if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM;
425
426     if (had) FIXME("had != NULL, not supported\n");
427     
428     for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
429         /* should check for codec only */
430         if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
431             add.cbStruct = sizeof(add);
432
433             if (acmDriverDetailsW((HACMDRIVERID)padid, &add, 0) == MMSYSERR_NOERROR) {
434                 for (i = 0; i < add.cFilterTags; i++) {
435                     paftd->dwFilterTagIndex = i;
436                     if (acmFilterTagDetailsW(had, paftd, ACM_FILTERTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
437                         if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, 
438                                           add.fdwSupport)) {
439                             padid = NULL;
440                             break;
441                         }
442                     }
443                 }
444             }
445         }
446         acmDriverClose(had, 0);
447     }
448     return MMSYSERR_NOERROR;
449 }