dmloader: complete rewrite and full implementation.
[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 #include "mmreg.h"
32 #include "msacm.h"
33
34 static BOOL CALLBACK FormatTagEnumProc(HACMDRIVERID hadid,
35                                        PACMFORMATTAGDETAILS paftd,
36                                        DWORD dwInstance,
37                                        DWORD fdwSupport)
38 {
39     trace("   Format 0x%04lx: %s\n", paftd->dwFormatTag, paftd->szFormatTag);
40
41     return TRUE;
42 }
43
44 static BOOL CALLBACK FormatEnumProc(HACMDRIVERID hadid,
45                                     LPACMFORMATDETAILS pafd,
46                                     DWORD dwInstance,
47                                     DWORD fd)
48 {
49     trace("   0x%04lx, %s\n", pafd->dwFormatTag, pafd->szFormat);
50
51     return TRUE;
52 }
53
54 static BOOL CALLBACK DriverEnumProc(HACMDRIVERID hadid,
55                                     DWORD dwInstance,
56                                     DWORD fdwSupport)
57 {
58     MMRESULT rc;
59     ACMDRIVERDETAILS dd;
60     HACMDRIVER had;
61
62     trace("id: %p\n", hadid);
63     trace("  Supports:\n");
64     if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_ASYNC)
65         trace("    async conversions\n");
66     if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC)
67         trace("    different format conversions\n");
68     if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CONVERTER)
69         trace("    same format conversions\n");
70     if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_FILTER)
71         trace("    filtering\n");
72
73     /* try an invalid pointer */
74     rc = acmDriverDetails(hadid, 0, 0);
75     ok(rc == MMSYSERR_INVALPARAM,
76        "acmDriverDetails(): rc = %08x, should be %08x\n",
77        rc, MMSYSERR_INVALPARAM);
78
79     /* try an invalid structure size */
80     ZeroMemory(&dd, sizeof(dd));
81     rc = acmDriverDetails(hadid, &dd, 0);
82     ok(rc == MMSYSERR_INVALPARAM,
83        "acmDriverDetails(): rc = %08x, should be %08x\n",
84        rc, MMSYSERR_INVALPARAM);
85
86     /* MSDN says this should fail but it doesn't in practice */
87     dd.cbStruct = 4;
88     rc = acmDriverDetails(hadid, &dd, 0);
89     ok(rc == MMSYSERR_NOERROR,
90        "acmDriverDetails(): rc = %08x, should be %08x\n",
91        rc, MMSYSERR_NOERROR);
92
93     /* try an invalid handle */
94     dd.cbStruct = sizeof(dd);
95     rc = acmDriverDetails((HACMDRIVERID)1, &dd, 0);
96     ok(rc == MMSYSERR_INVALHANDLE,
97        "acmDriverDetails(): rc = %08x, should be %08x\n",
98        rc, MMSYSERR_INVALHANDLE);
99
100     /* try an invalid handle and pointer */
101     rc = acmDriverDetails((HACMDRIVERID)1, 0, 0);
102     ok(rc == MMSYSERR_INVALPARAM,
103        "acmDriverDetails(): rc = %08x, should be %08x\n",
104        rc, MMSYSERR_INVALPARAM);
105
106     /* try invalid details */
107     rc = acmDriverDetails(hadid, &dd, -1);
108     ok(rc == MMSYSERR_INVALFLAG,
109        "acmDriverDetails(): rc = %08x, should be %08x\n",
110        rc, MMSYSERR_INVALFLAG);
111
112     /* try valid parameters */
113     rc = acmDriverDetails(hadid, &dd, 0);
114     ok(rc == MMSYSERR_NOERROR,
115        "acmDriverDetails(): rc = %08x, should be %08x\n",
116        rc, MMSYSERR_NOERROR);
117
118     if (rc == MMSYSERR_NOERROR) {
119         trace("  Short name: %s\n", dd.szShortName);
120         trace("  Long name: %s\n", dd.szLongName);
121         trace("  Copyright: %s\n", dd.szCopyright);
122         trace("  Licensing: %s\n", dd.szLicensing);
123         trace("  Features: %s\n", dd.szFeatures);
124         trace("  Supports %lu formats\n", dd.cFormatTags);
125         trace("  Supports %lu filter formats\n", dd.cFilterTags);
126     }
127
128     /* try invalid pointer */
129     rc = acmDriverOpen(0, hadid, 0);
130     ok(rc == MMSYSERR_INVALPARAM,
131        "acmDriverOpen(): rc = %08x, should be %08x\n",
132        rc, MMSYSERR_INVALPARAM);
133
134     /* try invalid handle */
135     rc = acmDriverOpen(&had, (HACMDRIVERID)1, 0);
136     ok(rc == MMSYSERR_INVALHANDLE,
137        "acmDriverOpen(): rc = %08x, should be %08x\n",
138        rc, MMSYSERR_INVALHANDLE);
139
140     /* try invalid open */
141     rc = acmDriverOpen(&had, hadid, -1);
142     ok(rc == MMSYSERR_INVALFLAG,
143        "acmDriverOpen(): rc = %08x, should be %08x\n",
144        rc, MMSYSERR_INVALFLAG);
145
146     /* try valid parameters */
147     rc = acmDriverOpen(&had, hadid, 0);
148     ok(rc == MMSYSERR_NOERROR,
149        "acmDriverOpen(): rc = %08x, should be %08x\n",
150        rc, MMSYSERR_NOERROR);
151
152     if (rc == MMSYSERR_NOERROR) {
153         DWORD dwSize;
154         HACMDRIVERID hid;
155
156         /* try bad pointer */
157         rc = acmDriverID((HACMOBJ)had, 0, 0);
158         ok(rc == MMSYSERR_INVALPARAM,
159            "acmDriverID(): rc = %08x, should be %08x\n",
160            rc, MMSYSERR_INVALPARAM);
161
162         /* try bad handle */
163         rc = acmDriverID((HACMOBJ)1, &hid, 0);
164         ok(rc == MMSYSERR_INVALHANDLE,
165            "acmMetrics(): rc = %08x, should be %08x\n",
166            rc, MMSYSERR_INVALHANDLE);
167
168         /* try bad handle and pointer */
169         rc = acmDriverID((HACMOBJ)1, 0, 0);
170         ok(rc == MMSYSERR_INVALHANDLE,
171            "acmMetrics(): rc = %08x, should be %08x\n",
172            rc, MMSYSERR_INVALHANDLE);
173
174         /* try bad flag */
175         rc = acmDriverID((HACMOBJ)had, &hid, 1);
176         ok(rc == MMSYSERR_INVALFLAG,
177            "acmDriverID(): rc = %08x, should be %08x\n",
178            rc, MMSYSERR_INVALFLAG);
179
180         /* try valid parameters */
181         rc = acmDriverID((HACMOBJ)had, &hid, 0);
182         ok(rc == MMSYSERR_NOERROR,
183            "acmDriverID(): rc = %08x, should be %08x\n",
184            rc, MMSYSERR_NOERROR);
185         ok(hid == hadid,
186            "acmDriverID() returned ID %08lx doesn't equal %08lx\n",
187            (DWORD)hid, (DWORD)hadid);
188
189         /* try bad pointer */
190         rc = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, 0);
191         ok(rc == MMSYSERR_INVALPARAM,
192            "acmMetrics(): rc = %08x, should be %08x\n",
193            rc, MMSYSERR_INVALPARAM);
194
195         /* try bad handle */
196         rc = acmMetrics((HACMOBJ)1, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
197         ok(rc == MMSYSERR_INVALHANDLE,
198            "acmMetrics(): rc = %08x, should be %08x\n",
199            rc, MMSYSERR_INVALHANDLE);
200
201         /* try bad pointer and handle */
202         rc = acmMetrics((HACMOBJ)1, ACM_METRIC_MAX_SIZE_FORMAT, 0);
203         ok(rc == MMSYSERR_INVALHANDLE,
204            "acmMetrics(): rc = %08x, should be %08x\n",
205            rc, MMSYSERR_INVALHANDLE);
206
207         /* try valid parameters */
208         rc = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
209         ok(rc == MMSYSERR_NOERROR,
210            "acmMetrics(): rc = %08x, should be %08x\n",
211            rc, MMSYSERR_NOERROR);
212         if (rc == MMSYSERR_NOERROR) {
213             ACMFORMATDETAILS fd;
214             WAVEFORMATEX * pwfx;
215             ACMFORMATTAGDETAILS aftd;
216
217             /* try bad pointer */
218             rc = acmFormatEnum(had, 0, FormatEnumProc, 0, 0);
219             ok(rc == MMSYSERR_INVALPARAM,
220                "acmFormatEnum(): rc = %08x, should be %08x\n",
221                 rc, MMSYSERR_INVALPARAM);
222
223             /* try bad structure size */
224             ZeroMemory(&fd, sizeof(fd));
225             rc = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0);
226             ok(rc == MMSYSERR_INVALPARAM,
227                "acmFormatEnum(): rc = %08x, should be %08x\n",
228                rc, MMSYSERR_INVALPARAM);
229
230             fd.cbStruct = sizeof(fd) - 1;
231             rc = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0);
232             ok(rc == MMSYSERR_INVALPARAM,
233                "acmFormatEnum(): rc = %08x, should be %08x\n",
234                rc, MMSYSERR_INVALPARAM);
235
236             if (dwSize < sizeof(WAVEFORMATEX))
237                 dwSize = sizeof(WAVEFORMATEX);
238
239             pwfx = (WAVEFORMATEX *) malloc(dwSize);
240
241             ZeroMemory(pwfx, dwSize);
242             pwfx->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX);
243             pwfx->wFormatTag = WAVE_FORMAT_UNKNOWN;
244
245             fd.cbStruct = sizeof(fd);
246             fd.pwfx = pwfx;
247             fd.cbwfx = dwSize;
248             fd.dwFormatTag = WAVE_FORMAT_UNKNOWN;
249
250             /* try valid parameters */
251             rc = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0);
252             ok(rc == MMSYSERR_NOERROR,
253                "acmFormatEnum(): rc = %08x, should be %08x\n",
254                rc, MMSYSERR_NOERROR);
255
256             /* try bad pointer */
257             rc = acmFormatTagEnum(had, 0, FormatTagEnumProc, 0, 0);
258             ok(rc == MMSYSERR_INVALPARAM,
259                "acmFormatTagEnum(): rc = %08x, should be %08x\n",
260                 rc, MMSYSERR_INVALPARAM);
261
262             /* try bad structure size */
263             ZeroMemory(&aftd, sizeof(fd));
264             rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 0);
265             ok(rc == MMSYSERR_INVALPARAM,
266                "acmFormatTagEnum(): rc = %08x, should be %08x\n",
267                rc, MMSYSERR_INVALPARAM);
268
269             aftd.cbStruct = sizeof(aftd) - 1;
270             rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 0);
271             ok(rc == MMSYSERR_INVALPARAM,
272                "acmFormatTagEnum(): rc = %08x, should be %08x\n",
273                rc, MMSYSERR_INVALPARAM);
274
275             aftd.cbStruct = sizeof(aftd);
276             aftd.dwFormatTag = WAVE_FORMAT_UNKNOWN;
277
278             /* try bad flag */
279             rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 1);
280             ok(rc == MMSYSERR_INVALFLAG,
281                "acmFormatTagEnum(): rc = %08x, should be %08x\n",
282                rc, MMSYSERR_INVALFLAG);
283
284             /* try valid parameters */
285             rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 0);
286             ok(rc == MMSYSERR_NOERROR,
287                "acmFormatTagEnum(): rc = %08x, should be %08x\n",
288                rc, MMSYSERR_NOERROR);
289
290             free(pwfx);
291
292             /* try invalid handle */
293             rc = acmDriverClose((HACMDRIVER)1, 0);
294             ok(rc == MMSYSERR_INVALHANDLE,
295                "acmDriverClose(): rc = %08x, should be %08x\n",
296                rc, MMSYSERR_INVALHANDLE);
297
298             /* try invalid flag */
299             rc = acmDriverClose(had, 1);
300             ok(rc == MMSYSERR_INVALFLAG,
301                "acmDriverClose(): rc = %08x, should be %08x\n",
302                rc, MMSYSERR_INVALFLAG);
303
304             /* try valid parameters */
305             rc = acmDriverClose(had, 0);
306             ok(rc == MMSYSERR_NOERROR,
307                "acmDriverClose(): rc = %08x, should be %08x\n",
308                rc, MMSYSERR_NOERROR);
309
310             /* try closing again */
311             rc = acmDriverClose(had, 0);
312             ok(rc == MMSYSERR_INVALHANDLE,
313                "acmDriverClose(): rc = %08x, should be %08x\n",
314                rc, MMSYSERR_INVALHANDLE);
315         }
316     }
317
318     return TRUE;
319 }
320
321 static const char * get_metric(UINT uMetric)
322 {
323     switch (uMetric) {
324     case ACM_METRIC_COUNT_CODECS:
325         return "ACM_METRIC_COUNT_CODECS";
326     case ACM_METRIC_COUNT_CONVERTERS:
327         return "ACM_METRIC_COUNT_CONVERTERS";
328     case ACM_METRIC_COUNT_DISABLED:
329         return "ACM_METRIC_COUNT_DISABLED";
330     case ACM_METRIC_COUNT_DRIVERS:
331         return "ACM_METRIC_COUNT_DRIVERS";
332     case ACM_METRIC_COUNT_FILTERS:
333         return "ACM_METRIC_COUNT_FILTERS";
334     case ACM_METRIC_COUNT_HARDWARE:
335         return "ACM_METRIC_COUNT_HARDWARE";
336     case ACM_METRIC_COUNT_LOCAL_CODECS:
337         return "ACM_METRIC_COUNT_LOCAL_CODECS";
338     case ACM_METRIC_COUNT_LOCAL_CONVERTERS:
339         return "ACM_METRIC_COUNT_LOCAL_CONVERTERS";
340     case ACM_METRIC_COUNT_LOCAL_DISABLED:
341         return "ACM_METRIC_COUNT_LOCAL_DISABLED";
342     case ACM_METRIC_COUNT_LOCAL_DRIVERS:
343         return "ACM_METRIC_COUNT_LOCAL_DRIVERS";
344     case ACM_METRIC_COUNT_LOCAL_FILTERS:
345         return "ACM_METRIC_COUNT_LOCAL_FILTERS";
346     case ACM_METRIC_DRIVER_PRIORITY:
347         return "ACM_METRIC_DRIVER_PRIORITY";
348     case ACM_METRIC_DRIVER_SUPPORT:
349         return "ACM_METRIC_DRIVER_SUPPORT";
350     case ACM_METRIC_HARDWARE_WAVE_INPUT:
351         return "ACM_METRIC_HARDWARE_WAVE_INPUT";
352     case ACM_METRIC_HARDWARE_WAVE_OUTPUT:
353         return "ACM_METRIC_HARDWARE_WAVE_OUTPUT";
354     case ACM_METRIC_MAX_SIZE_FILTER:
355         return "ACM_METRIC_MAX_SIZE_FILTER";
356     case ACM_METRIC_MAX_SIZE_FORMAT:
357         return "ACM_METRIC_MAX_SIZE_FORMAT";
358     }
359
360     return "UNKNOWN";
361 }
362
363 static DWORD check_count(UINT uMetric)
364 {
365     DWORD dwMetric;
366     MMRESULT rc;
367
368     /* try invalid result pointer */
369     rc = acmMetrics(NULL, uMetric, 0);
370     ok(rc == MMSYSERR_INVALPARAM,
371        "acmMetrics(NULL, %s, 0): rc = 0x%08x, should be 0x%08x\n",
372        get_metric(uMetric), rc, MMSYSERR_INVALPARAM);
373
374     /* try invalid handle */
375     rc = acmMetrics((HACMOBJ)1, uMetric, &dwMetric);
376     ok(rc == MMSYSERR_INVALHANDLE,
377        "acmMetrics(1, %s, %p): rc = 0x%08x, should be 0x%08x\n",
378        get_metric(uMetric), &dwMetric, rc, MMSYSERR_INVALHANDLE);
379
380     /* try invalid result pointer and handle */
381     rc = acmMetrics((HACMOBJ)1, uMetric, 0);
382     ok(rc == MMSYSERR_INVALHANDLE,
383        "acmMetrics(1, %s, 0): rc = 0x%08x, should be 0x%08x\n",
384        get_metric(uMetric), rc, MMSYSERR_INVALHANDLE);
385
386     /* try valid parameters */
387     rc = acmMetrics(NULL, uMetric, &dwMetric);
388     ok(rc == MMSYSERR_NOERROR, "acmMetrics() failed: rc = 0x%08x\n", rc);
389
390     if (rc == MMSYSERR_NOERROR)
391         trace("%s: %lu\n", get_metric(uMetric), dwMetric);
392
393     return dwMetric;
394 }
395
396 static void msacm_tests()
397 {
398     MMRESULT rc;
399     DWORD dwCount;
400     DWORD dwACMVersion = acmGetVersion();
401
402     trace("ACM version = %u.%02u build %u%s\n",
403         HIWORD(dwACMVersion) >> 8,
404         HIWORD(dwACMVersion) & 0xff,
405         LOWORD(dwACMVersion),
406         LOWORD(dwACMVersion)  ==  0 ? " (Retail)" : "");
407
408     dwCount = check_count(ACM_METRIC_COUNT_CODECS);
409     dwCount = check_count(ACM_METRIC_COUNT_CONVERTERS);
410     dwCount = check_count(ACM_METRIC_COUNT_DISABLED);
411     dwCount = check_count(ACM_METRIC_COUNT_DRIVERS);
412     dwCount = check_count(ACM_METRIC_COUNT_FILTERS);
413     dwCount = check_count(ACM_METRIC_COUNT_HARDWARE);
414     dwCount = check_count(ACM_METRIC_COUNT_LOCAL_CODECS);
415     dwCount = check_count(ACM_METRIC_COUNT_LOCAL_CONVERTERS);
416     dwCount = check_count(ACM_METRIC_COUNT_LOCAL_DISABLED);
417     dwCount = check_count(ACM_METRIC_COUNT_LOCAL_DRIVERS);
418     dwCount = check_count(ACM_METRIC_COUNT_LOCAL_FILTERS);
419
420     trace("enabled drivers:\n");
421     rc = acmDriverEnum(DriverEnumProc, 0, 0);
422     ok(rc == MMSYSERR_NOERROR,
423       "acmDriverEnum() failed, rc=%08x, should be 0x%08x\n",
424       rc, MMSYSERR_NOERROR);
425 }
426
427 START_TEST(msacm)
428 {
429     msacm_tests();
430 }