urlmon: Added TYMED_FILE support to CopyStgMedium.
[wine] / dlls / dsound / tests / dsound.c
1 /*
2  * Tests basic sound playback in DirectSound.
3  * In particular we test each standard Windows sound format to make sure
4  * we handle the sound card/driver quirks correctly.
5  *
6  * Part of this test involves playing test tones. But this only makes
7  * sense if someone is going to carefully listen to it, and would only
8  * bother everyone else.
9  * So this is only done if the test is being run in interactive mode.
10  *
11  * Copyright (c) 2002-2004 Francois Gouget
12  * Copyright (c) 2007 Maarten Lankhorst
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Lesser General Public
16  * License as published by the Free Software Foundation; either
17  * version 2.1 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27  */
28
29 #include <windows.h>
30
31 #include "wine/test.h"
32 #include "dsound.h"
33 #include "dxerr8.h"
34 #include "dsconf.h"
35 #include "mmreg.h"
36 /* MinGW doesn't have ksguid, needed for make crosstest to work. */
37 #include "initguid.h"
38 #include "ks.h"
39 #include "ksmedia.h"
40
41 #include "dsound_test.h"
42
43 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
44 static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID,LPDIRECTSOUND*,
45     LPUNKNOWN)=NULL;
46
47 static void IDirectSound_test(LPDIRECTSOUND dso, BOOL initialized,
48                               LPCGUID lpGuid)
49 {
50     HRESULT rc;
51     DSCAPS dscaps;
52     int ref;
53     IUnknown * unknown;
54     IDirectSound * ds;
55     IDirectSound8 * ds8;
56     DWORD speaker_config, new_speaker_config;
57
58     /* Try to Query for objects */
59     rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
60     ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",
61        DXGetErrorString8(rc));
62     if (rc==DS_OK)
63         IDirectSound_Release(unknown);
64
65     rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
66     ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",
67        DXGetErrorString8(rc));
68     if (rc==DS_OK)
69         IDirectSound_Release(ds);
70
71     rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
72     ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) "
73        "should have failed: %s\n",DXGetErrorString8(rc));
74     if (rc==DS_OK)
75         IDirectSound8_Release(ds8);
76
77     if (initialized == FALSE) {
78         /* try uninitialized object */
79         rc=IDirectSound_GetCaps(dso,0);
80         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps(NULL) "
81            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
82            DXGetErrorString8(rc));
83
84         rc=IDirectSound_GetCaps(dso,&dscaps);
85         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps() "
86            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
87            DXGetErrorString8(rc));
88
89         rc=IDirectSound_Compact(dso);
90         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_Compact() "
91            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
92            DXGetErrorString8(rc));
93
94         rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
95         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetSpeakerConfig() "
96            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
97            DXGetErrorString8(rc));
98
99         rc=IDirectSound_Initialize(dso,lpGuid);
100         ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
101            "IDirectSound_Initialize() failed: %s\n",DXGetErrorString8(rc));
102         if (rc==DSERR_NODRIVER) {
103             trace("  No Driver\n");
104             goto EXIT;
105         } else if (rc==E_FAIL) {
106             trace("  No Device\n");
107             goto EXIT;
108         } else if (rc==DSERR_ALLOCATED) {
109             trace("  Already In Use\n");
110             goto EXIT;
111         }
112     }
113
114     rc=IDirectSound_Initialize(dso,lpGuid);
115     ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound_Initialize() "
116        "should have returned DSERR_ALREADYINITIALIZED: %s\n",
117        DXGetErrorString8(rc));
118
119     /* DSOUND: Error: Invalid caps buffer */
120     rc=IDirectSound_GetCaps(dso,0);
121     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
122        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
123        DXGetErrorString8(rc));
124
125     ZeroMemory(&dscaps, sizeof(dscaps));
126
127     /* DSOUND: Error: Invalid caps buffer */
128     rc=IDirectSound_GetCaps(dso,&dscaps);
129     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
130        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
131        DXGetErrorString8(rc));
132
133     dscaps.dwSize=sizeof(dscaps);
134
135     /* DSOUND: Running on a certified driver */
136     rc=IDirectSound_GetCaps(dso,&dscaps);
137     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
138
139     rc=IDirectSound_Compact(dso);
140     ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %s\n",
141        DXGetErrorString8(rc));
142
143     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
144     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
145        DXGetErrorString8(rc));
146
147     rc=IDirectSound_Compact(dso);
148     ok(rc==DS_OK,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc));
149
150     rc=IDirectSound_GetSpeakerConfig(dso,0);
151     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
152        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
153        DXGetErrorString8(rc));
154
155     rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
156     ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
157        DXGetErrorString8(rc));
158
159     speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
160                                         DSSPEAKER_GEOMETRY_WIDE);
161     rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
162     ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %s\n",
163        DXGetErrorString8(rc));
164     if (rc==DS_OK) {
165         rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
166         ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
167            DXGetErrorString8(rc));
168         if (rc==DS_OK && speaker_config!=new_speaker_config)
169                trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
170                "config: expected 0x%08x, got 0x%08x\n",
171                speaker_config,new_speaker_config);
172     }
173
174 EXIT:
175     ref=IDirectSound_Release(dso);
176     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
177 }
178
179 static void IDirectSound_tests(void)
180 {
181     HRESULT rc;
182     LPDIRECTSOUND dso=NULL;
183     LPCLASSFACTORY cf=NULL;
184
185     trace("Testing IDirectSound\n");
186
187     rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
188                         &IID_IClassFactory, (void**)&cf);
189     ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IClassFactory) "
190        "failed: %s\n", DXGetErrorString8(rc));
191
192     rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
193                         &IID_IUnknown, (void**)&cf);
194     ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IUnknown) "
195        "failed: %s\n", DXGetErrorString8(rc));
196
197     /* try the COM class factory method of creation with no device specified */
198     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
199                         &IID_IDirectSound, (void**)&dso);
200     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
201        DXGetErrorString8(rc));
202     if (dso)
203         IDirectSound_test(dso, FALSE, NULL);
204
205     /* try the COM class factory method of creation with default playback
206      * device specified */
207     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
208                         &IID_IDirectSound, (void**)&dso);
209     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
210        DXGetErrorString8(rc));
211     if (dso)
212         IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
213
214     /* try the COM class factory method of creation with default voice
215      * playback device specified */
216     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
217                         &IID_IDirectSound, (void**)&dso);
218     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
219        DXGetErrorString8(rc));
220     if (dso)
221         IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
222
223     /* try the COM class factory method of creation with a bad
224      * IID specified */
225     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
226                         &CLSID_DirectSoundPrivate, (void**)&dso);
227     ok(rc==E_NOINTERFACE,
228        "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
229        "should have failed: %s\n",DXGetErrorString8(rc));
230
231     /* try the COM class factory method of creation with a bad
232      * GUID and IID specified */
233     rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
234                         &IID_IDirectSound, (void**)&dso);
235     ok(rc==REGDB_E_CLASSNOTREG,
236        "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
237        "should have failed: %s\n",DXGetErrorString8(rc));
238
239     /* try with no device specified */
240     rc=pDirectSoundCreate(NULL,&dso,NULL);
241     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
242        "DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc));
243     if (rc==S_OK && dso)
244         IDirectSound_test(dso, TRUE, NULL);
245
246     /* try with default playback device specified */
247     rc=pDirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
248     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
249        "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n",
250        DXGetErrorString8(rc));
251     if (rc==DS_OK && dso)
252         IDirectSound_test(dso, TRUE, NULL);
253
254     /* try with default voice playback device specified */
255     rc=pDirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
256     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
257        "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
258        DXGetErrorString8(rc));
259     if (rc==DS_OK && dso)
260         IDirectSound_test(dso, TRUE, NULL);
261
262     /* try with a bad device specified */
263     rc=pDirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
264     ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
265        "should have failed: %s\n",DXGetErrorString8(rc));
266     if (rc==DS_OK && dso)
267         IDirectSound_Release(dso);
268 }
269
270 static HRESULT test_dsound(LPGUID lpGuid)
271 {
272     HRESULT rc;
273     LPDIRECTSOUND dso=NULL;
274     int ref;
275
276     /* DSOUND: Error: Invalid interface buffer */
277     rc=pDirectSoundCreate(lpGuid,0,NULL);
278     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
279        "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
280
281     /* Create the DirectSound object */
282     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
283     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
284        "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
285     if (rc!=DS_OK)
286         return rc;
287
288     /* Try the enumerated device */
289     IDirectSound_test(dso, TRUE, lpGuid);
290
291     /* Try the COM class factory method of creation with enumerated device */
292     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
293                         &IID_IDirectSound, (void**)&dso);
294     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
295        DXGetErrorString8(rc));
296     if (dso)
297         IDirectSound_test(dso, FALSE, lpGuid);
298
299     /* Create a DirectSound object */
300     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
301     ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
302     if (rc==DS_OK) {
303         LPDIRECTSOUND dso1=NULL;
304
305         /* Create a second DirectSound object */
306         rc=pDirectSoundCreate(lpGuid,&dso1,NULL);
307         ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
308         if (rc==DS_OK) {
309             /* Release the second DirectSound object */
310             ref=IDirectSound_Release(dso1);
311             ok(ref==0,"IDirectSound_Release() has %d references, should have "
312                "0\n",ref);
313             ok(dso!=dso1,"DirectSound objects should be unique: dso=%p,dso1=%p\n",dso,dso1);
314         }
315
316         /* Release the first DirectSound object */
317         ref=IDirectSound_Release(dso);
318         ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
319            ref);
320         if (ref!=0)
321             return DSERR_GENERIC;
322     } else
323         return rc;
324
325     /* Create a DirectSound object */
326     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
327     ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
328     if (rc==DS_OK) {
329         LPDIRECTSOUNDBUFFER secondary;
330         DSBUFFERDESC bufdesc;
331         WAVEFORMATEX wfx;
332
333         init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
334         ZeroMemory(&bufdesc, sizeof(bufdesc));
335         bufdesc.dwSize=sizeof(bufdesc);
336         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
337         bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
338                                     wfx.nBlockAlign);
339         bufdesc.lpwfxFormat=&wfx;
340         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
341         ok(rc==DS_OK && secondary!=NULL,
342            "IDirectSound_CreateSoundBuffer() failed to create a secondary "
343            "buffer %s\n",DXGetErrorString8(rc));
344         if (rc==DS_OK && secondary!=NULL) {
345             LPDIRECTSOUND3DBUFFER buffer3d;
346             rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
347                                            (void **)&buffer3d);
348             ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
349                "failed:  %s\n",DXGetErrorString8(rc));
350             if (rc==DS_OK && buffer3d!=NULL) {
351                 ref=IDirectSound3DBuffer_AddRef(buffer3d);
352                 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
353                    "should have 2\n",ref);
354             }
355             ref=IDirectSoundBuffer_AddRef(secondary);
356             ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
357                "should have 2\n",ref);
358         }
359         /* release with buffer */
360         ref=IDirectSound_Release(dso);
361         ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
362            ref);
363         if (ref!=0)
364             return DSERR_GENERIC;
365     } else
366         return rc;
367
368     return DS_OK;
369 }
370
371 static HRESULT test_primary(LPGUID lpGuid)
372 {
373     HRESULT rc;
374     LPDIRECTSOUND dso=NULL;
375     LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
376     DSBUFFERDESC bufdesc;
377     DSCAPS dscaps;
378     WAVEFORMATEX wfx;
379     int ref;
380
381     /* Create the DirectSound object */
382     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
383     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
384        "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
385     if (rc!=DS_OK)
386         return rc;
387
388     /* Get the device capabilities */
389     ZeroMemory(&dscaps, sizeof(dscaps));
390     dscaps.dwSize=sizeof(dscaps);
391     rc=IDirectSound_GetCaps(dso,&dscaps);
392     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
393     if (rc!=DS_OK)
394         goto EXIT;
395
396     /* DSOUND: Error: Invalid buffer description pointer */
397     rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
398     ok(rc==DSERR_INVALIDPARAM,
399        "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
400        DXGetErrorString8(rc));
401
402     /* DSOUND: Error: Invalid buffer description pointer */
403     rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
404     ok(rc==DSERR_INVALIDPARAM && primary==0,
405        "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
406        "dsbo=%p\n",DXGetErrorString8(rc),primary);
407
408     /* DSOUND: Error: Invalid buffer description pointer */
409     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
410     ok(rc==DSERR_INVALIDPARAM && primary==0,
411        "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
412        "dsbo=0x%p\n",DXGetErrorString8(rc),primary);
413
414     ZeroMemory(&bufdesc, sizeof(bufdesc));
415
416     /* DSOUND: Error: Invalid size */
417     /* DSOUND: Error: Invalid buffer description */
418     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
419     ok(rc==DSERR_INVALIDPARAM && primary==0,
420        "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
421        "primary=%p\n",DXGetErrorString8(rc),primary);
422
423     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
424     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
425     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
426     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
427        DXGetErrorString8(rc));
428     if (rc!=DS_OK)
429         goto EXIT;
430
431     /* Testing the primary buffer */
432     primary=NULL;
433     ZeroMemory(&bufdesc, sizeof(bufdesc));
434     bufdesc.dwSize=sizeof(bufdesc);
435     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
436     bufdesc.lpwfxFormat = &wfx;
437     init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
438     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
439     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
440        "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
441     if (rc==DS_OK && primary!=NULL)
442         IDirectSoundBuffer_Release(primary);
443
444     primary=NULL;
445     ZeroMemory(&bufdesc, sizeof(bufdesc));
446     bufdesc.dwSize=sizeof(bufdesc);
447     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
448     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
449     ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
450        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
451        "%s\n",DXGetErrorString8(rc));
452     if (rc==DSERR_CONTROLUNAVAIL)
453         trace("  No Primary\n");
454     else if (rc==DS_OK && primary!=NULL) {
455         LONG vol;
456
457         /* Try to create a second primary buffer */
458         /* DSOUND: Error: The primary buffer already exists.
459          * Any changes made to the buffer description will be ignored. */
460         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
461         ok(rc==DS_OK && second==primary,
462            "IDirectSound_CreateSoundBuffer() should have returned original "
463            "primary buffer: %s\n",DXGetErrorString8(rc));
464         ref=IDirectSoundBuffer_Release(second);
465         ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
466            "should have 1\n",ref);
467
468         /* Try to duplicate a primary buffer */
469         /* DSOUND: Error: Can't duplicate primary buffers */
470         rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
471         /* rc=0x88780032 */
472         ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
473            "should have failed %s\n",DXGetErrorString8(rc));
474
475         rc=IDirectSoundBuffer_GetVolume(primary,&vol);
476         ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
477            DXGetErrorString8(rc));
478
479         if (winetest_interactive) {
480             trace("Playing a 5 seconds reference tone at the current "
481                   "volume.\n");
482             if (rc==DS_OK)
483                 trace("(the current volume is %d according to DirectSound)\n",
484                       vol);
485             trace("All subsequent tones should be identical to this one.\n");
486             trace("Listen for stutter, changes in pitch, volume, etc.\n");
487         }
488         test_buffer(dso,&primary,1,FALSE,0,FALSE,0,winetest_interactive &&
489                     !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0);
490
491         ref=IDirectSoundBuffer_Release(primary);
492         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
493            "should have 0\n",ref);
494     }
495
496     /* Set the CooperativeLevel back to normal */
497     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
498     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
499     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
500        DXGetErrorString8(rc));
501
502 EXIT:
503     ref=IDirectSound_Release(dso);
504     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
505     if (ref!=0)
506         return DSERR_GENERIC;
507
508     return rc;
509 }
510
511 /*
512  * Test the primary buffer at different formats while keeping the
513  * secondary buffer at a constant format.
514  */
515 static HRESULT test_primary_secondary(LPGUID lpGuid)
516 {
517     HRESULT rc;
518     LPDIRECTSOUND dso=NULL;
519     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
520     DSBUFFERDESC bufdesc;
521     DSCAPS dscaps;
522     WAVEFORMATEX wfx, wfx2;
523     int f,ref;
524
525     /* Create the DirectSound object */
526     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
527     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
528        "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
529     if (rc!=DS_OK)
530         return rc;
531
532     /* Get the device capabilities */
533     ZeroMemory(&dscaps, sizeof(dscaps));
534     dscaps.dwSize=sizeof(dscaps);
535     rc=IDirectSound_GetCaps(dso,&dscaps);
536     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
537     if (rc!=DS_OK)
538         goto EXIT;
539
540     /* We must call SetCooperativeLevel before creating primary buffer */
541     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
542     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
543     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
544        DXGetErrorString8(rc));
545     if (rc!=DS_OK)
546         goto EXIT;
547
548     ZeroMemory(&bufdesc, sizeof(bufdesc));
549     bufdesc.dwSize=sizeof(bufdesc);
550     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
551     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
552     ok(rc==DS_OK && primary!=NULL,
553        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
554        "%s\n",DXGetErrorString8(rc));
555
556     if (rc==DS_OK && primary!=NULL) {
557         for (f=0;f<NB_FORMATS;f++) {
558             /* We must call SetCooperativeLevel to be allowed to call
559              * SetFormat */
560             /* DSOUND: Setting DirectSound cooperative level to
561              * DSSCL_PRIORITY */
562             rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
563             ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
564                DXGetErrorString8(rc));
565             if (rc!=DS_OK)
566                 goto EXIT;
567
568             init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
569                         formats[f][2]);
570             wfx2=wfx;
571             rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
572             ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %s\n",
573                format_string(&wfx), DXGetErrorString8(rc));
574
575             /* There is no guarantee that SetFormat will actually change the
576              * format to what we asked for. It depends on what the soundcard
577              * supports. So we must re-query the format.
578              */
579             rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
580             ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
581                DXGetErrorString8(rc));
582             if (rc==DS_OK &&
583                 (wfx.wFormatTag!=wfx2.wFormatTag ||
584                  wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
585                  wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
586                  wfx.nChannels!=wfx2.nChannels)) {
587                 trace("Requested primary format tag=0x%04x %dx%dx%d "
588                       "avg.B/s=%d align=%d\n",
589                       wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
590                       wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
591                 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
592                       wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
593                       wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
594             }
595
596             /* Set the CooperativeLevel back to normal */
597             /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
598             rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
599             ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
600                DXGetErrorString8(rc));
601
602             init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
603
604             secondary=NULL;
605             ZeroMemory(&bufdesc, sizeof(bufdesc));
606             bufdesc.dwSize=sizeof(bufdesc);
607             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
608             bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
609                                         wfx.nBlockAlign);
610             bufdesc.lpwfxFormat=&wfx2;
611             if (winetest_interactive) {
612                 trace("  Testing a primary buffer at %dx%dx%d with a "
613                       "secondary buffer at %dx%dx%d\n",
614                       wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
615                       wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
616             }
617             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
618             ok(rc==DS_OK && secondary!=NULL,
619                "IDirectSound_CreateSoundBuffer() failed to create a secondary "
620                "buffer %s\n",DXGetErrorString8(rc));
621
622             if (rc==DS_OK && secondary!=NULL) {
623                 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
624                             winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
625
626                 ref=IDirectSoundBuffer_Release(secondary);
627                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
628                    "should have 0\n",ref);
629             }
630         }
631
632         ref=IDirectSoundBuffer_Release(primary);
633         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
634            "should have 0\n",ref);
635     }
636
637     /* Set the CooperativeLevel back to normal */
638     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
639     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
640     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
641        DXGetErrorString8(rc));
642
643 EXIT:
644     ref=IDirectSound_Release(dso);
645     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
646     if (ref!=0)
647         return DSERR_GENERIC;
648
649     return rc;
650 }
651
652 static HRESULT test_secondary(LPGUID lpGuid)
653 {
654     HRESULT rc;
655     LPDIRECTSOUND dso=NULL;
656     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
657     DSBUFFERDESC bufdesc;
658     DSCAPS dscaps;
659     WAVEFORMATEX wfx, wfx1;
660     DWORD f;
661     int ref;
662
663     /* Create the DirectSound object */
664     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
665     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
666        "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
667     if (rc!=DS_OK)
668         return rc;
669
670     /* Get the device capabilities */
671     ZeroMemory(&dscaps, sizeof(dscaps));
672     dscaps.dwSize=sizeof(dscaps);
673     rc=IDirectSound_GetCaps(dso,&dscaps);
674     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
675     if (rc!=DS_OK)
676         goto EXIT;
677
678     /* We must call SetCooperativeLevel before creating primary buffer */
679     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
680     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
681     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
682        DXGetErrorString8(rc));
683     if (rc!=DS_OK)
684         goto EXIT;
685
686     ZeroMemory(&bufdesc, sizeof(bufdesc));
687     bufdesc.dwSize=sizeof(bufdesc);
688     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
689     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
690     ok(rc==DS_OK && primary!=NULL,
691        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
692        "%s\n",DXGetErrorString8(rc));
693
694     if (rc==DS_OK && primary!=NULL) {
695         rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
696         ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
697            DXGetErrorString8(rc));
698         if (rc!=DS_OK)
699             goto EXIT1;
700
701         for (f=0;f<NB_FORMATS;f++) {
702             WAVEFORMATEXTENSIBLE wfxe;
703             init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
704                         formats[f][2]);
705             secondary=NULL;
706             ZeroMemory(&bufdesc, sizeof(bufdesc));
707             bufdesc.dwSize=sizeof(bufdesc);
708             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
709             bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
710                                         wfx.nBlockAlign);
711             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
712             ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
713                "should have returned DSERR_INVALIDPARAM, returned: %s\n",
714                DXGetErrorString8(rc));
715             if (rc==DS_OK && secondary!=NULL)
716                 IDirectSoundBuffer_Release(secondary);
717
718             secondary=NULL;
719             ZeroMemory(&bufdesc, sizeof(bufdesc));
720             bufdesc.dwSize=sizeof(bufdesc);
721             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
722             bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
723                                         wfx.nBlockAlign);
724             bufdesc.lpwfxFormat=&wfx;
725             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
726             if (wfx.wBitsPerSample != 8 && wfx.wBitsPerSample != 16)
727                 ok(rc == DSERR_CONTROLUNAVAIL && !secondary, "IDirectSound_CreateSoundBuffer() "
728                     "should have returned DSERR_CONTROLUNAVAIL and NULL, returned: %s %p\n",
729                     DXGetErrorString8(rc), secondary);
730             else
731                 ok(rc==DS_OK && secondary!=NULL,
732                     "IDirectSound_CreateSoundBuffer() failed to create a secondary "
733                     "buffer %s\n",DXGetErrorString8(rc));
734             if (secondary)
735                 IDirectSoundBuffer_Release(secondary);
736             secondary = NULL;
737
738             bufdesc.lpwfxFormat=(WAVEFORMATEX*)&wfxe;
739             wfxe.Format = wfx;
740             wfxe.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
741             wfxe.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
742             wfxe.Format.cbSize = 1;
743             wfxe.Samples.wValidBitsPerSample = wfx.wBitsPerSample;
744             wfxe.dwChannelMask = (wfx.nChannels == 1 ? KSAUDIO_SPEAKER_MONO : KSAUDIO_SPEAKER_STEREO);
745
746             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
747             ok(rc==DSERR_INVALIDPARAM && !secondary,
748                 "IDirectSound_CreateSoundBuffer() returned: %s %p\n",
749                 DXGetErrorString8(rc), secondary);
750             if (secondary)
751                 IDirectSoundBuffer_Release(secondary);
752
753             wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx) + 1;
754
755             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
756             ok(DSERR_CONTROLUNAVAIL && !secondary,
757                 "IDirectSound_CreateSoundBuffer() returned: %s %p\n",
758                 DXGetErrorString8(rc), secondary);
759             if (secondary)
760                 IDirectSoundBuffer_Release(secondary);
761
762             wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx);
763             wfxe.SubFormat = GUID_NULL;
764             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
765             ok(rc==DSERR_INVALIDPARAM && !secondary,
766                 "IDirectSound_CreateSoundBuffer() returned: %s %p\n",
767                 DXGetErrorString8(rc), secondary);
768             if (secondary)
769                 IDirectSoundBuffer_Release(secondary);
770             wfxe.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
771
772             ++wfxe.Samples.wValidBitsPerSample;
773             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
774             ok(rc==DSERR_INVALIDPARAM && !secondary,
775                 "IDirectSound_CreateSoundBuffer() returned: %s %p\n",
776                 DXGetErrorString8(rc), secondary);
777             if (secondary)
778                 IDirectSoundBuffer_Release(secondary);
779             --wfxe.Samples.wValidBitsPerSample;
780
781             wfxe.Samples.wValidBitsPerSample = 0;
782             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
783             ok(rc==DS_OK && secondary,
784                 "IDirectSound_CreateSoundBuffer() returned: %s %p\n",
785                 DXGetErrorString8(rc), secondary);
786             if (secondary)
787                 IDirectSoundBuffer_Release(secondary);
788             wfxe.Samples.wValidBitsPerSample = wfxe.Format.wBitsPerSample;
789
790             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
791             ok(rc==DS_OK && secondary!=NULL,
792                 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
793                 "buffer %s\n",DXGetErrorString8(rc));
794
795             if (rc==DS_OK && secondary!=NULL) {
796                 if (winetest_interactive) {
797                     trace("  Testing a secondary buffer at %dx%dx%d "
798                         "with a primary buffer at %dx%dx%d\n",
799                         wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
800                         wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
801                 }
802                 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
803                             winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
804
805                 ref=IDirectSoundBuffer_Release(secondary);
806                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
807                    "should have 0\n",ref);
808             }
809         }
810 EXIT1:
811         ref=IDirectSoundBuffer_Release(primary);
812         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
813            "should have 0\n",ref);
814     }
815
816     /* Set the CooperativeLevel back to normal */
817     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
818     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
819     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
820        DXGetErrorString8(rc));
821
822 EXIT:
823     ref=IDirectSound_Release(dso);
824     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
825     if (ref!=0)
826         return DSERR_GENERIC;
827
828     return rc;
829 }
830
831 static HRESULT test_block_align(LPGUID lpGuid)
832 {
833     HRESULT rc;
834     LPDIRECTSOUND dso=NULL;
835     LPDIRECTSOUNDBUFFER secondary=NULL;
836     DSBUFFERDESC bufdesc;
837     DSBCAPS dsbcaps;
838     WAVEFORMATEX wfx;
839     DWORD pos, pos2;
840     int ref;
841
842     /* Create the DirectSound object */
843     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
844     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
845        "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
846     if (rc!=DS_OK)
847         return rc;
848
849     init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2);
850     ZeroMemory(&bufdesc, sizeof(bufdesc));
851     bufdesc.dwSize=sizeof(bufdesc);
852     bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
853     bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1;
854     bufdesc.lpwfxFormat=&wfx;
855     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
856     ok(rc==DS_OK,"IDirectSound_CreateSoundBuffer() "
857        "should have returned DS_OK, returned: %s\n",
858        DXGetErrorString8(rc));
859
860     if (rc==DS_OK && secondary!=NULL) {
861         ZeroMemory(&dsbcaps, sizeof(dsbcaps));
862         dsbcaps.dwSize = sizeof(dsbcaps);
863         rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps);
864         ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
865            "returned: %s\n", DXGetErrorString8(rc));
866         if (rc==DS_OK && wfx.nBlockAlign > 1)
867         {
868             ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign),
869                "Buffer size not a multiple of nBlockAlign: requested %d, "
870                "got %d, should be %d\n", bufdesc.dwBufferBytes,
871                dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign);
872
873             rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 0);
874             ok(rc == DS_OK, "Could not set position to 0: %s\n", DXGetErrorString8(rc));
875             rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos, NULL);
876             ok(rc == DS_OK, "Could not get position: %s\n", DXGetErrorString8(rc));
877             rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 1);
878             ok(rc == DS_OK, "Could not set position to 1: %s\n", DXGetErrorString8(rc));
879             rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos2, NULL);
880             ok(rc == DS_OK, "Could not get new position: %s\n", DXGetErrorString8(rc));
881             ok(pos == pos2, "Positions not the same! Old position: %d, new position: %d\n", pos, pos2);
882         }
883         ref=IDirectSoundBuffer_Release(secondary);
884         ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, "
885            "should have 0\n",ref);
886     }
887
888     ref=IDirectSound_Release(dso);
889     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
890     if (ref!=0)
891         return DSERR_GENERIC;
892
893     return rc;
894 }
895
896 static struct fmt {
897     int bits;
898     int channels;
899 } fmts[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } };
900
901 static HRESULT test_frequency(LPGUID lpGuid)
902 {
903     HRESULT rc;
904     LPDIRECTSOUND dso=NULL;
905     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
906     DSBUFFERDESC bufdesc;
907     DSCAPS dscaps;
908     WAVEFORMATEX wfx, wfx1;
909     DWORD f, r;
910     int ref;
911     int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
912                     48000, 96000 };
913
914     /* Create the DirectSound object */
915     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
916     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
917        "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
918     if (rc!=DS_OK)
919         return rc;
920
921     /* Get the device capabilities */
922     ZeroMemory(&dscaps, sizeof(dscaps));
923     dscaps.dwSize=sizeof(dscaps);
924     rc=IDirectSound_GetCaps(dso,&dscaps);
925     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
926     if (rc!=DS_OK)
927         goto EXIT;
928
929     /* We must call SetCooperativeLevel before creating primary buffer */
930     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
931     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
932     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
933        DXGetErrorString8(rc));
934     if (rc!=DS_OK)
935         goto EXIT;
936
937     ZeroMemory(&bufdesc, sizeof(bufdesc));
938     bufdesc.dwSize=sizeof(bufdesc);
939     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
940     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
941     ok(rc==DS_OK && primary!=NULL,
942        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
943        "%s\n",DXGetErrorString8(rc));
944
945     if (rc==DS_OK && primary!=NULL) {
946         rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
947         ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
948            DXGetErrorString8(rc));
949         if (rc!=DS_OK)
950             goto EXIT1;
951
952         for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) {
953         for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) {
954             init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits,
955                         fmts[f].channels);
956             secondary=NULL;
957             ZeroMemory(&bufdesc, sizeof(bufdesc));
958             bufdesc.dwSize=sizeof(bufdesc);
959             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY;
960             bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)*
961                                         BUFFER_LEN/1000,wfx.nBlockAlign);
962             bufdesc.lpwfxFormat=&wfx;
963             if (winetest_interactive) {
964                 trace("  Testing a secondary buffer at %dx%dx%d "
965                       "with a primary buffer at %dx%dx%d\n",
966                       wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
967                       wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
968             }
969             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
970             ok(rc==DS_OK && secondary!=NULL,
971                "IDirectSound_CreateSoundBuffer() failed to create a secondary "
972                "buffer %s\n",DXGetErrorString8(rc));
973
974             if (rc==DS_OK && secondary!=NULL) {
975                 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
976                             winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]);
977
978                 ref=IDirectSoundBuffer_Release(secondary);
979                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
980                    "should have 0\n",ref);
981             }
982         }
983         }
984 EXIT1:
985         ref=IDirectSoundBuffer_Release(primary);
986         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
987            "should have 0\n",ref);
988     }
989
990     /* Set the CooperativeLevel back to normal */
991     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
992     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
993     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
994        DXGetErrorString8(rc));
995
996 EXIT:
997     ref=IDirectSound_Release(dso);
998     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
999     if (ref!=0)
1000         return DSERR_GENERIC;
1001
1002     return rc;
1003 }
1004
1005 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1006                                    LPCSTR lpcstrModule, LPVOID lpContext)
1007 {
1008     HRESULT rc;
1009     trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
1010     rc = test_dsound(lpGuid);
1011     if (rc == DSERR_NODRIVER)
1012         trace("  No Driver\n");
1013     else if (rc == DSERR_ALLOCATED)
1014         trace("  Already In Use\n");
1015     else if (rc == E_FAIL)
1016         trace("  No Device\n");
1017     else {
1018         test_block_align(lpGuid);
1019         test_primary(lpGuid);
1020         test_primary_secondary(lpGuid);
1021         test_secondary(lpGuid);
1022         test_frequency(lpGuid);
1023     }
1024
1025     return 1;
1026 }
1027
1028 static void dsound_tests(void)
1029 {
1030     HRESULT rc;
1031     rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
1032     ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
1033 }
1034
1035 START_TEST(dsound)
1036 {
1037     HMODULE hDsound;
1038
1039     CoInitialize(NULL);
1040
1041     hDsound = LoadLibrary("dsound.dll");
1042     if (hDsound)
1043     {
1044         ok( FreeLibrary(hDsound), "FreeLibrary(1) returned %d\n", GetLastError());
1045         ok( FreeLibrary(hDsound), "FreeLibrary(2) returned %d\n", GetLastError());
1046         ok(!FreeLibrary(hDsound), "DirectSound DLL still loaded\n");
1047     }
1048
1049     hDsound = LoadLibrary("dsound.dll");
1050     if (hDsound)
1051     {
1052         trace("DLL Version: %s\n", get_file_version("dsound.dll"));
1053
1054         pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
1055             "DirectSoundEnumerateA");
1056         pDirectSoundCreate = (void*)GetProcAddress(hDsound,
1057             "DirectSoundCreate");
1058
1059         IDirectSound_tests();
1060         dsound_tests();
1061
1062         FreeLibrary(hDsound);
1063     }
1064     else
1065         skip("dsound.dll not found!\n");
1066
1067     CoUninitialize();
1068 }