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