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