msacm: Add support for ACM_METRIC_DRIVER_SUPPORT.
[wine] / dlls / msacm / tests / msacm.c
1 /*
2  * Unit tests for msacm functions
3  *
4  * Copyright (c) 2004 Robert Reif
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <math.h>
25
26 #include "wine/test.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winnls.h"
30 #include "mmsystem.h"
31 #define NOBITMAP
32 #include "mmreg.h"
33 #include "msacm.h"
34
35 static BOOL CALLBACK FormatTagEnumProc(HACMDRIVERID hadid,
36                                        PACMFORMATTAGDETAILS paftd,
37                                        DWORD dwInstance,
38                                        DWORD fdwSupport)
39 {
40     if (winetest_interactive)
41         trace("   Format 0x%04lx: %s\n", paftd->dwFormatTag, paftd->szFormatTag);
42
43     return TRUE;
44 }
45
46 static BOOL CALLBACK FormatEnumProc(HACMDRIVERID hadid,
47                                     LPACMFORMATDETAILS pafd,
48                                     DWORD dwInstance,
49                                     DWORD fd)
50 {
51     if (winetest_interactive)
52         trace("   0x%04lx, %s\n", pafd->dwFormatTag, pafd->szFormat);
53
54     return TRUE;
55 }
56
57 static BOOL CALLBACK DriverEnumProc(HACMDRIVERID hadid,
58                                     DWORD dwInstance,
59                                     DWORD fdwSupport)
60 {
61     MMRESULT rc;
62     ACMDRIVERDETAILS dd;
63     HACMDRIVER had;
64
65     if (winetest_interactive) {
66         trace("id: %p\n", hadid);
67         trace("  Supports:\n");
68         if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_ASYNC)
69             trace("    async conversions\n");
70         if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC)
71             trace("    different format conversions\n");
72         if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CONVERTER)
73             trace("    same format conversions\n");
74         if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_FILTER)
75             trace("    filtering\n");
76     }
77
78     /* try an invalid pointer */
79     rc = acmDriverDetails(hadid, 0, 0);
80     ok(rc == MMSYSERR_INVALPARAM,
81        "acmDriverDetails(): rc = %08x, should be %08x\n",
82        rc, MMSYSERR_INVALPARAM);
83
84     /* try an invalid structure size */
85     ZeroMemory(&dd, sizeof(dd));
86     rc = acmDriverDetails(hadid, &dd, 0);
87     ok(rc == MMSYSERR_INVALPARAM,
88        "acmDriverDetails(): rc = %08x, should be %08x\n",
89        rc, MMSYSERR_INVALPARAM);
90
91     /* MSDN says this should fail but it doesn't in practice */
92     dd.cbStruct = 4;
93     rc = acmDriverDetails(hadid, &dd, 0);
94     ok(rc == MMSYSERR_NOERROR,
95        "acmDriverDetails(): rc = %08x, should be %08x\n",
96        rc, MMSYSERR_NOERROR);
97
98     /* try an invalid handle */
99     dd.cbStruct = sizeof(dd);
100     rc = acmDriverDetails((HACMDRIVERID)1, &dd, 0);
101     ok(rc == MMSYSERR_INVALHANDLE,
102        "acmDriverDetails(): rc = %08x, should be %08x\n",
103        rc, MMSYSERR_INVALHANDLE);
104
105     /* try an invalid handle and pointer */
106     rc = acmDriverDetails((HACMDRIVERID)1, 0, 0);
107     ok(rc == MMSYSERR_INVALPARAM,
108        "acmDriverDetails(): rc = %08x, should be %08x\n",
109        rc, MMSYSERR_INVALPARAM);
110
111     /* try invalid details */
112     rc = acmDriverDetails(hadid, &dd, -1);
113     ok(rc == MMSYSERR_INVALFLAG,
114        "acmDriverDetails(): rc = %08x, should be %08x\n",
115        rc, MMSYSERR_INVALFLAG);
116
117     /* try valid parameters */
118     rc = acmDriverDetails(hadid, &dd, 0);
119     ok(rc == MMSYSERR_NOERROR,
120        "acmDriverDetails(): rc = %08x, should be %08x\n",
121        rc, MMSYSERR_NOERROR);
122
123     /* cbStruct should contain size of returned data (at most sizeof(dd)) 
124        TODO: should it be *exactly* sizeof(dd), as tested here?
125      */
126     if (rc == MMSYSERR_NOERROR) {    
127         ok(dd.cbStruct == sizeof(dd),
128             "acmDriverDetails(): cbStruct = %08lx, should be %08lx\n",
129             dd.cbStruct, (unsigned long)sizeof(dd));
130     }
131
132     if (rc == MMSYSERR_NOERROR && winetest_interactive) {
133         trace("  Short name: %s\n", dd.szShortName);
134         trace("  Long name: %s\n", dd.szLongName);
135         trace("  Copyright: %s\n", dd.szCopyright);
136         trace("  Licensing: %s\n", dd.szLicensing);
137         trace("  Features: %s\n", dd.szFeatures);
138         trace("  Supports %lu formats\n", dd.cFormatTags);
139         trace("  Supports %lu filter formats\n", dd.cFilterTags);
140     }
141
142     /* try invalid pointer */
143     rc = acmDriverOpen(0, hadid, 0);
144     ok(rc == MMSYSERR_INVALPARAM,
145        "acmDriverOpen(): rc = %08x, should be %08x\n",
146        rc, MMSYSERR_INVALPARAM);
147
148     /* try invalid handle */
149     rc = acmDriverOpen(&had, (HACMDRIVERID)1, 0);
150     ok(rc == MMSYSERR_INVALHANDLE,
151        "acmDriverOpen(): rc = %08x, should be %08x\n",
152        rc, MMSYSERR_INVALHANDLE);
153
154     /* try invalid open */
155     rc = acmDriverOpen(&had, hadid, -1);
156     ok(rc == MMSYSERR_INVALFLAG,
157        "acmDriverOpen(): rc = %08x, should be %08x\n",
158        rc, MMSYSERR_INVALFLAG);
159
160     /* try valid parameters */
161     rc = acmDriverOpen(&had, hadid, 0);
162     ok(rc == MMSYSERR_NOERROR,
163        "acmDriverOpen(): rc = %08x, should be %08x\n",
164        rc, MMSYSERR_NOERROR);
165
166     if (rc == MMSYSERR_NOERROR) {
167         DWORD dwSize;
168         HACMDRIVERID hid;
169
170         /* try bad pointer */
171         rc = acmDriverID((HACMOBJ)had, 0, 0);
172         ok(rc == MMSYSERR_INVALPARAM,
173            "acmDriverID(): rc = %08x, should be %08x\n",
174            rc, MMSYSERR_INVALPARAM);
175
176         /* try bad handle */
177         rc = acmDriverID((HACMOBJ)1, &hid, 0);
178         ok(rc == MMSYSERR_INVALHANDLE,
179            "acmMetrics(): rc = %08x, should be %08x\n",
180            rc, MMSYSERR_INVALHANDLE);
181
182         /* try bad handle and pointer */
183         rc = acmDriverID((HACMOBJ)1, 0, 0);
184         ok(rc == MMSYSERR_INVALHANDLE,
185            "acmMetrics(): rc = %08x, should be %08x\n",
186            rc, MMSYSERR_INVALHANDLE);
187
188         /* try bad flag */
189         rc = acmDriverID((HACMOBJ)had, &hid, 1);
190         ok(rc == MMSYSERR_INVALFLAG,
191            "acmDriverID(): rc = %08x, should be %08x\n",
192            rc, MMSYSERR_INVALFLAG);
193
194         /* try valid parameters */
195         rc = acmDriverID((HACMOBJ)had, &hid, 0);
196         ok(rc == MMSYSERR_NOERROR,
197            "acmDriverID(): rc = %08x, should be %08x\n",
198            rc, MMSYSERR_NOERROR);
199         ok(hid == hadid,
200            "acmDriverID() returned ID %p doesn't equal %p\n",
201            hid, hadid);
202
203         /* try bad pointer */
204         rc = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, 0);
205         ok(rc == MMSYSERR_INVALPARAM,
206            "acmMetrics(): rc = %08x, should be %08x\n",
207            rc, MMSYSERR_INVALPARAM);
208
209         /* try bad handle */
210         rc = acmMetrics((HACMOBJ)1, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
211         ok(rc == MMSYSERR_INVALHANDLE,
212            "acmMetrics(): rc = %08x, should be %08x\n",
213            rc, MMSYSERR_INVALHANDLE);
214
215         /* try bad pointer and handle */
216         rc = acmMetrics((HACMOBJ)1, ACM_METRIC_MAX_SIZE_FORMAT, 0);
217         ok(rc == MMSYSERR_INVALHANDLE,
218            "acmMetrics(): rc = %08x, should be %08x\n",
219            rc, MMSYSERR_INVALHANDLE);
220
221         /* try valid parameters */
222         rc = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
223         ok(rc == MMSYSERR_NOERROR,
224            "acmMetrics(): rc = %08x, should be %08x\n",
225            rc, MMSYSERR_NOERROR);
226         if (rc == MMSYSERR_NOERROR) {
227             ACMFORMATDETAILS fd;
228             WAVEFORMATEX * pwfx;
229             ACMFORMATTAGDETAILS aftd;
230
231             /* try bad pointer */
232             rc = acmFormatEnum(had, 0, FormatEnumProc, 0, 0);
233             ok(rc == MMSYSERR_INVALPARAM,
234                "acmFormatEnum(): rc = %08x, should be %08x\n",
235                 rc, MMSYSERR_INVALPARAM);
236
237             /* try bad structure size */
238             ZeroMemory(&fd, sizeof(fd));
239             rc = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0);
240             ok(rc == MMSYSERR_INVALPARAM,
241                "acmFormatEnum(): rc = %08x, should be %08x\n",
242                rc, MMSYSERR_INVALPARAM);
243
244             fd.cbStruct = sizeof(fd) - 1;
245             rc = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0);
246             ok(rc == MMSYSERR_INVALPARAM,
247                "acmFormatEnum(): rc = %08x, should be %08x\n",
248                rc, MMSYSERR_INVALPARAM);
249
250             if (dwSize < sizeof(WAVEFORMATEX))
251                 dwSize = sizeof(WAVEFORMATEX);
252
253             pwfx = (WAVEFORMATEX *) malloc(dwSize);
254
255             ZeroMemory(pwfx, dwSize);
256             pwfx->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX);
257             pwfx->wFormatTag = WAVE_FORMAT_UNKNOWN;
258
259             fd.cbStruct = sizeof(fd);
260             fd.pwfx = pwfx;
261             fd.cbwfx = dwSize;
262             fd.dwFormatTag = WAVE_FORMAT_UNKNOWN;
263
264             /* try valid parameters */
265             rc = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0);
266             ok(rc == MMSYSERR_NOERROR,
267                "acmFormatEnum(): rc = %08x, should be %08x\n",
268                rc, MMSYSERR_NOERROR);
269
270             /* try bad pointer */
271             rc = acmFormatTagEnum(had, 0, FormatTagEnumProc, 0, 0);
272             ok(rc == MMSYSERR_INVALPARAM,
273                "acmFormatTagEnum(): rc = %08x, should be %08x\n",
274                 rc, MMSYSERR_INVALPARAM);
275
276             /* try bad structure size */
277             ZeroMemory(&aftd, sizeof(aftd));
278             rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 0);
279             ok(rc == MMSYSERR_INVALPARAM,
280                "acmFormatTagEnum(): rc = %08x, should be %08x\n",
281                rc, MMSYSERR_INVALPARAM);
282
283             aftd.cbStruct = sizeof(aftd) - 1;
284             rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 0);
285             ok(rc == MMSYSERR_INVALPARAM,
286                "acmFormatTagEnum(): rc = %08x, should be %08x\n",
287                rc, MMSYSERR_INVALPARAM);
288
289             aftd.cbStruct = sizeof(aftd);
290             aftd.dwFormatTag = WAVE_FORMAT_UNKNOWN;
291
292             /* try bad flag */
293             rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 1);
294             ok(rc == MMSYSERR_INVALFLAG,
295                "acmFormatTagEnum(): rc = %08x, should be %08x\n",
296                rc, MMSYSERR_INVALFLAG);
297
298             /* try valid parameters */
299             rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 0);
300             ok(rc == MMSYSERR_NOERROR,
301                "acmFormatTagEnum(): rc = %08x, should be %08x\n",
302                rc, MMSYSERR_NOERROR);
303
304             free(pwfx);
305
306             /* try invalid handle */
307             rc = acmDriverClose((HACMDRIVER)1, 0);
308             ok(rc == MMSYSERR_INVALHANDLE,
309                "acmDriverClose(): rc = %08x, should be %08x\n",
310                rc, MMSYSERR_INVALHANDLE);
311
312             /* try invalid flag */
313             rc = acmDriverClose(had, 1);
314             ok(rc == MMSYSERR_INVALFLAG,
315                "acmDriverClose(): rc = %08x, should be %08x\n",
316                rc, MMSYSERR_INVALFLAG);
317
318             /* try valid parameters */
319             rc = acmDriverClose(had, 0);
320             ok(rc == MMSYSERR_NOERROR,
321                "acmDriverClose(): rc = %08x, should be %08x\n",
322                rc, MMSYSERR_NOERROR);
323
324             /* try closing again */
325             rc = acmDriverClose(had, 0);
326             ok(rc == MMSYSERR_INVALHANDLE,
327                "acmDriverClose(): rc = %08x, should be %08x\n",
328                rc, MMSYSERR_INVALHANDLE);
329         }
330     }
331
332     return TRUE;
333 }
334
335 static const char * get_metric(UINT uMetric)
336 {
337     switch (uMetric) {
338     case ACM_METRIC_COUNT_CODECS:
339         return "ACM_METRIC_COUNT_CODECS";
340     case ACM_METRIC_COUNT_CONVERTERS:
341         return "ACM_METRIC_COUNT_CONVERTERS";
342     case ACM_METRIC_COUNT_DISABLED:
343         return "ACM_METRIC_COUNT_DISABLED";
344     case ACM_METRIC_COUNT_DRIVERS:
345         return "ACM_METRIC_COUNT_DRIVERS";
346     case ACM_METRIC_COUNT_FILTERS:
347         return "ACM_METRIC_COUNT_FILTERS";
348     case ACM_METRIC_COUNT_HARDWARE:
349         return "ACM_METRIC_COUNT_HARDWARE";
350     case ACM_METRIC_COUNT_LOCAL_CODECS:
351         return "ACM_METRIC_COUNT_LOCAL_CODECS";
352     case ACM_METRIC_COUNT_LOCAL_CONVERTERS:
353         return "ACM_METRIC_COUNT_LOCAL_CONVERTERS";
354     case ACM_METRIC_COUNT_LOCAL_DISABLED:
355         return "ACM_METRIC_COUNT_LOCAL_DISABLED";
356     case ACM_METRIC_COUNT_LOCAL_DRIVERS:
357         return "ACM_METRIC_COUNT_LOCAL_DRIVERS";
358     case ACM_METRIC_COUNT_LOCAL_FILTERS:
359         return "ACM_METRIC_COUNT_LOCAL_FILTERS";
360     case ACM_METRIC_DRIVER_PRIORITY:
361         return "ACM_METRIC_DRIVER_PRIORITY";
362     case ACM_METRIC_DRIVER_SUPPORT:
363         return "ACM_METRIC_DRIVER_SUPPORT";
364     case ACM_METRIC_HARDWARE_WAVE_INPUT:
365         return "ACM_METRIC_HARDWARE_WAVE_INPUT";
366     case ACM_METRIC_HARDWARE_WAVE_OUTPUT:
367         return "ACM_METRIC_HARDWARE_WAVE_OUTPUT";
368     case ACM_METRIC_MAX_SIZE_FILTER:
369         return "ACM_METRIC_MAX_SIZE_FILTER";
370     case ACM_METRIC_MAX_SIZE_FORMAT:
371         return "ACM_METRIC_MAX_SIZE_FORMAT";
372     }
373
374     return "UNKNOWN";
375 }
376
377 static DWORD check_count(UINT uMetric)
378 {
379     DWORD dwMetric;
380     MMRESULT rc;
381
382     /* try invalid result pointer */
383     rc = acmMetrics(NULL, uMetric, 0);
384     ok(rc == MMSYSERR_INVALPARAM,
385        "acmMetrics(NULL, %s, 0): rc = 0x%08x, should be 0x%08x\n",
386        get_metric(uMetric), rc, MMSYSERR_INVALPARAM);
387
388     /* try invalid handle */
389     rc = acmMetrics((HACMOBJ)1, uMetric, &dwMetric);
390     ok(rc == MMSYSERR_INVALHANDLE,
391        "acmMetrics(1, %s, %p): rc = 0x%08x, should be 0x%08x\n",
392        get_metric(uMetric), &dwMetric, rc, MMSYSERR_INVALHANDLE);
393
394     /* try invalid result pointer and handle */
395     rc = acmMetrics((HACMOBJ)1, uMetric, 0);
396     ok(rc == MMSYSERR_INVALHANDLE,
397        "acmMetrics(1, %s, 0): rc = 0x%08x, should be 0x%08x\n",
398        get_metric(uMetric), rc, MMSYSERR_INVALHANDLE);
399
400     /* try valid parameters */
401     rc = acmMetrics(NULL, uMetric, &dwMetric);
402     ok(rc == MMSYSERR_NOERROR, "acmMetrics() failed: rc = 0x%08x\n", rc);
403
404     if (rc == MMSYSERR_NOERROR && winetest_interactive)
405         trace("%s: %lu\n", get_metric(uMetric), dwMetric);
406
407     return dwMetric;
408 }
409
410 static void msacm_tests(void)
411 {
412     MMRESULT rc;
413     DWORD dwCount;
414     DWORD dwACMVersion = acmGetVersion();
415
416     if (winetest_interactive) {
417         trace("ACM version = %u.%02u build %u%s\n",
418             HIWORD(dwACMVersion) >> 8,
419             HIWORD(dwACMVersion) & 0xff,
420             LOWORD(dwACMVersion),
421             LOWORD(dwACMVersion)  ==  0 ? " (Retail)" : "");
422     }
423
424     dwCount = check_count(ACM_METRIC_COUNT_CODECS);
425     dwCount = check_count(ACM_METRIC_COUNT_CONVERTERS);
426     dwCount = check_count(ACM_METRIC_COUNT_DISABLED);
427     dwCount = check_count(ACM_METRIC_COUNT_DRIVERS);
428     dwCount = check_count(ACM_METRIC_COUNT_FILTERS);
429     dwCount = check_count(ACM_METRIC_COUNT_HARDWARE);
430     dwCount = check_count(ACM_METRIC_COUNT_LOCAL_CODECS);
431     dwCount = check_count(ACM_METRIC_COUNT_LOCAL_CONVERTERS);
432     dwCount = check_count(ACM_METRIC_COUNT_LOCAL_DISABLED);
433     dwCount = check_count(ACM_METRIC_COUNT_LOCAL_DRIVERS);
434     dwCount = check_count(ACM_METRIC_COUNT_LOCAL_FILTERS);
435
436     if (winetest_interactive)
437         trace("enabled drivers:\n");
438
439     rc = acmDriverEnum(DriverEnumProc, 0, 0);
440     ok(rc == MMSYSERR_NOERROR,
441       "acmDriverEnum() failed, rc=%08x, should be 0x%08x\n",
442       rc, MMSYSERR_NOERROR);
443 }
444
445 START_TEST(msacm)
446 {
447     msacm_tests();
448 }