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 "dsound_test.h"
30 
31 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
32 
33 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
34 static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID,LPDIRECTSOUND*,
35     LPUNKNOWN)=NULL;
36 
37 static BOOL gotdx8;
38 
39 static void IDirectSound_test(LPDIRECTSOUND dso, BOOL initialized,
40                               LPCGUID lpGuid)
41 {
42     HRESULT rc;
43     DSCAPS dscaps;
44     int ref;
45     IUnknown * unknown;
46     IDirectSound * ds;
47     IDirectSound8 * ds8;
48     DWORD speaker_config, new_speaker_config, ref_speaker_config;
49 
50     /* Try to Query for objects */
51     rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
52     ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %08x\n", rc);
53     if (rc==DS_OK)
54         IDirectSound_Release(unknown);
55 
56     rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
57     ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %08x\n", rc);
58     if (rc==DS_OK)
59         IDirectSound_Release(ds);
60 
61     rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
62     ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) "
63        "should have failed: %08x\n",rc);
64     if (rc==DS_OK)
65         IDirectSound8_Release(ds8);
66 
67     if (initialized == FALSE) {
68         /* try uninitialized object */
69         rc=IDirectSound_GetCaps(dso,0);
70         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps(NULL) "
71            "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
72 
73         rc=IDirectSound_GetCaps(dso,&dscaps);
74         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps() "
75            "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
76 
77         rc=IDirectSound_Compact(dso);
78         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_Compact() "
79            "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
80 
81         rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
82         ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetSpeakerConfig() "
83            "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
84 
85         rc=IDirectSound_Initialize(dso,lpGuid);
86         ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
87            "IDirectSound_Initialize() failed: %08x\n",rc);
88         if (rc==DSERR_NODRIVER) {
89             trace("  No Driver\n");
90             goto EXIT;
91         } else if (rc==E_FAIL) {
92             trace("  No Device\n");
93             goto EXIT;
94         } else if (rc==DSERR_ALLOCATED) {
95             trace("  Already In Use\n");
96             goto EXIT;
97         }
98     }
99 
100     rc=IDirectSound_Initialize(dso,lpGuid);
101     ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound_Initialize() "
102        "should have returned DSERR_ALREADYINITIALIZED: %08x\n", rc);
103 
104     /* DSOUND: Error: Invalid caps buffer */
105     rc=IDirectSound_GetCaps(dso,0);
106     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
107        "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
108 
109     ZeroMemory(&dscaps, sizeof(dscaps));
110 
111     /* DSOUND: Error: Invalid caps buffer */
112     rc=IDirectSound_GetCaps(dso,&dscaps);
113     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
114        "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
115 
116     dscaps.dwSize=sizeof(dscaps);
117 
118     /* DSOUND: Running on a certified driver */
119     rc=IDirectSound_GetCaps(dso,&dscaps);
120     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc);
121 
122     rc=IDirectSound_Compact(dso);
123     ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %08x\n", rc);
124 
125     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
126     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
127 
128     rc=IDirectSound_Compact(dso);
129     ok(rc==DS_OK,"IDirectSound_Compact() failed: %08x\n",rc);
130 
131     rc=IDirectSound_GetSpeakerConfig(dso,0);
132     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
133        "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
134 
135     rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
136     ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %08x\n", rc);
137     ref_speaker_config = speaker_config;
138 
139     speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
140                                         DSSPEAKER_GEOMETRY_WIDE);
141     if (speaker_config == ref_speaker_config)
142         speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
143                                             DSSPEAKER_GEOMETRY_NARROW);
144     if(rc==DS_OK) {
145         rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
146         ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %08x\n", rc);
147     }
148     if (rc==DS_OK) {
149         rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
150         ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %08x\n", rc);
151         if (rc==DS_OK && speaker_config!=new_speaker_config)
152                trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
153                "config: expected 0x%08x, got 0x%08x\n",
154                speaker_config,new_speaker_config);
155         IDirectSound_SetSpeakerConfig(dso,ref_speaker_config);
156     }
157 
158 EXIT:
159     ref=IDirectSound_Release(dso);
160     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
161 }
162 
163 static void IDirectSound_tests(void)
164 {
165     HRESULT rc;
166     IDirectSound *dso=(IDirectSound*)0xdeadbeef;
167     LPCLASSFACTORY cf=NULL;
168 
169     trace("Testing IDirectSound\n");
170 
171     rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
172                         &IID_IClassFactory, (void**)&cf);
173     ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IClassFactory) "
174        "failed: %08x\n", rc);
175 
176     rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
177                         &IID_IUnknown, (void**)&cf);
178     ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IUnknown) "
179        "failed: %08x\n", rc);
180 
181     /* COM aggregation */
182     rc=CoCreateInstance(&CLSID_DirectSound, (IUnknown*)&dso, CLSCTX_INPROC_SERVER,
183                         &IID_IDirectSound, (void**)&dso);
184     ok(rc==CLASS_E_NOAGGREGATION || broken(rc==DSERR_INVALIDPARAM),
185        "DirectMusicPerformance create failed: %08x, expected CLASS_E_NOAGGREGATION\n", rc);
186 
187     /* try the COM class factory method of creation with no device specified */
188     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
189                         &IID_IDirectSound, (void**)&dso);
190     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %08x\n", rc);
191     if (dso)
192         IDirectSound_test(dso, FALSE, NULL);
193 
194     /* try the COM class factory method of creation with default playback
195      * device specified */
196     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
197                         &IID_IDirectSound, (void**)&dso);
198     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %08x\n", rc);
199     if (dso)
200         IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
201 
202     /* try the COM class factory method of creation with default voice
203      * playback device specified */
204     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
205                         &IID_IDirectSound, (void**)&dso);
206     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %08x\n", rc);
207     if (dso)
208         IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
209 
210     /* try the COM class factory method of creation with a bad
211      * IID specified */
212     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
213                         &CLSID_DirectSoundPrivate, (void**)&dso);
214     ok(rc==E_NOINTERFACE,
215        "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
216        "should have failed: %08x\n",rc);
217 
218     /* try the COM class factory method of creation with a bad
219      * GUID and IID specified */
220     rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
221                         &IID_IDirectSound, (void**)&dso);
222     ok(rc==REGDB_E_CLASSNOTREG,
223        "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
224        "should have failed: %08x\n",rc);
225 
226     /* try with no device specified */
227     rc=pDirectSoundCreate(NULL,&dso,NULL);
228     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
229        "DirectSoundCreate(NULL) failed: %08x\n",rc);
230     if (rc==S_OK && dso)
231         IDirectSound_test(dso, TRUE, NULL);
232 
233     /* try with default playback device specified */
234     rc=pDirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
235     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
236        "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %08x\n", rc);
237     if (rc==DS_OK && dso)
238         IDirectSound_test(dso, TRUE, NULL);
239 
240     /* try with default voice playback device specified */
241     rc=pDirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
242     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
243        "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %08x\n", rc);
244     if (rc==DS_OK && dso)
245         IDirectSound_test(dso, TRUE, NULL);
246 
247     /* try with a bad device specified */
248     rc=pDirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
249     ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
250        "should have failed: %08x\n",rc);
251     if (rc==DS_OK && dso)
252         IDirectSound_Release(dso);
253 }
254 
255 static HRESULT test_dsound(LPGUID lpGuid)
256 {
257     HRESULT rc;
258     LPDIRECTSOUND dso=NULL;
259     int ref;
260 
261     /* DSOUND: Error: Invalid interface buffer */
262     rc=pDirectSoundCreate(lpGuid,0,NULL);
263     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
264        "DSERR_INVALIDPARAM, returned: %08x\n",rc);
265 
266     /* Create the DirectSound object */
267     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
268     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
269        "DirectSoundCreate() failed: %08x\n",rc);
270     if (rc!=DS_OK)
271         return rc;
272 
273     /* Try the enumerated device */
274     IDirectSound_test(dso, TRUE, lpGuid);
275 
276     /* Try the COM class factory method of creation with enumerated device */
277     rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
278                         &IID_IDirectSound, (void**)&dso);
279     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %08x\n", rc);
280     if (dso)
281         IDirectSound_test(dso, FALSE, lpGuid);
282 
283     /* Create a DirectSound object */
284     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
285     ok(rc==DS_OK,"DirectSoundCreate() failed: %08x\n",rc);
286     if (rc==DS_OK) {
287         LPDIRECTSOUND dso1=NULL;
288 
289         /* Create a second DirectSound object */
290         rc=pDirectSoundCreate(lpGuid,&dso1,NULL);
291         ok(rc==DS_OK,"DirectSoundCreate() failed: %08x\n",rc);
292         if (rc==DS_OK) {
293             /* Release the second DirectSound object */
294             ref=IDirectSound_Release(dso1);
295             ok(ref==0,"IDirectSound_Release() has %d references, should have "
296                "0\n",ref);
297             ok(dso!=dso1,"DirectSound objects should be unique: dso=%p,dso1=%p\n",dso,dso1);
298         }
299 
300         /* Release the first DirectSound object */
301         ref=IDirectSound_Release(dso);
302         ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
303            ref);
304         if (ref!=0)
305             return DSERR_GENERIC;
306     } else
307         return rc;
308 
309     /* Create a DirectSound object */
310     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
311     ok(rc==DS_OK,"DirectSoundCreate() failed: %08x\n",rc);
312     if (rc==DS_OK) {
313         LPDIRECTSOUNDBUFFER secondary;
314         DSBUFFERDESC bufdesc;
315         WAVEFORMATEX wfx;
316 
317         init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
318         ZeroMemory(&bufdesc, sizeof(bufdesc));
319         bufdesc.dwSize=sizeof(bufdesc);
320         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
321         bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
322                                     wfx.nBlockAlign);
323         bufdesc.lpwfxFormat=&wfx;
324         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
325         ok((rc==DS_OK && secondary!=NULL) || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */
326            "IDirectSound_CreateSoundBuffer() failed to create a secondary "
327            "buffer %08x\n",rc);
328         if (rc==DS_OK && secondary!=NULL) {
329             LPDIRECTSOUND3DBUFFER buffer3d;
330             rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
331                                            (void **)&buffer3d);
332             ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
333                "failed: %08x\n",rc);
334             if (rc==DS_OK && buffer3d!=NULL) {
335                 ref=IDirectSound3DBuffer_AddRef(buffer3d);
336                 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
337                    "should have 2\n",ref);
338             }
339             ref=IDirectSoundBuffer_AddRef(secondary);
340             ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
341                "should have 2\n",ref);
342         }
343         /* release with buffer */
344         ref=IDirectSound_Release(dso);
345         ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
346            ref);
347         if (ref!=0)
348             return DSERR_GENERIC;
349     } else
350         return rc;
351 
352     return DS_OK;
353 }
354 
355 static HRESULT test_primary(LPGUID lpGuid)
356 {
357     HRESULT rc;
358     LPDIRECTSOUND dso=NULL;
359     LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
360     DSBUFFERDESC bufdesc;
361     DSCAPS dscaps;
362     WAVEFORMATEX wfx;
363     int ref;
364 
365     /* Create the DirectSound object */
366     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
367     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
368        "DirectSoundCreate() failed: %08x\n",rc);
369     if (rc!=DS_OK)
370         return rc;
371 
372     /* Get the device capabilities */
373     ZeroMemory(&dscaps, sizeof(dscaps));
374     dscaps.dwSize=sizeof(dscaps);
375     rc=IDirectSound_GetCaps(dso,&dscaps);
376     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc);
377     if (rc!=DS_OK)
378         goto EXIT;
379 
380     /* DSOUND: Error: Invalid buffer description pointer */
381     rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
382     ok(rc==DSERR_INVALIDPARAM,
383        "IDirectSound_CreateSoundBuffer() should have failed: %08x\n", rc);
384 
385     /* DSOUND: Error: NULL pointer is invalid */
386     /* DSOUND: Error: Invalid buffer description pointer */
387     rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
388     ok(rc==DSERR_INVALIDPARAM && primary==0,
389        "IDirectSound_CreateSoundBuffer() should have failed: rc=%08x,"
390        "dsbo=%p\n",rc,primary);
391 
392     /* DSOUND: Error: Invalid size */
393     /* DSOUND: Error: Invalid buffer description */
394     primary=NULL;
395     ZeroMemory(&bufdesc, sizeof(bufdesc));
396     bufdesc.dwSize=sizeof(bufdesc)-1;
397     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
398     ok(rc==DSERR_INVALIDPARAM && primary==0,
399        "IDirectSound_CreateSoundBuffer() should have failed: rc=%08x,"
400        "primary=%p\n",rc,primary);
401 
402     /* DSOUND: Error: DSBCAPS_PRIMARYBUFFER flag with non-NULL lpwfxFormat */
403     /* DSOUND: Error: Invalid buffer description pointer */
404     primary=NULL;
405     ZeroMemory(&bufdesc, sizeof(bufdesc));
406     bufdesc.dwSize=sizeof(bufdesc);
407     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
408     bufdesc.lpwfxFormat=&wfx;
409     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
410     ok(rc==DSERR_INVALIDPARAM && primary==0,
411        "IDirectSound_CreateSoundBuffer() should have failed: rc=%08x,"
412        "primary=%p\n",rc,primary);
413 
414     /* DSOUND: Error: No DSBCAPS_PRIMARYBUFFER flag with NULL lpwfxFormat */
415     /* DSOUND: Error: Invalid buffer description pointer */
416     primary=NULL;
417     ZeroMemory(&bufdesc, sizeof(bufdesc));
418     bufdesc.dwSize=sizeof(bufdesc);
419     bufdesc.dwFlags=0;
420     bufdesc.lpwfxFormat=NULL;
421     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
422     ok(rc==DSERR_INVALIDPARAM && primary==0,
423        "IDirectSound_CreateSoundBuffer() should have failed: rc=%08x,"
424        "primary=%p\n",rc,primary);
425 
426     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
427     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
428     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
429     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
430     if (rc!=DS_OK)
431         goto EXIT;
432 
433     /* Testing the primary buffer */
434     primary=NULL;
435     ZeroMemory(&bufdesc, sizeof(bufdesc));
436     bufdesc.dwSize=sizeof(bufdesc);
437     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
438     bufdesc.lpwfxFormat = &wfx;
439     init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
440     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
441     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
442        "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
443     if (rc==DS_OK && primary!=NULL)
444         IDirectSoundBuffer_Release(primary);
445 
446     primary=NULL;
447     ZeroMemory(&bufdesc, sizeof(bufdesc));
448     bufdesc.dwSize=sizeof(bufdesc);
449     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
450     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
451     ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
452        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: %08x\n",rc);
453     if (rc==DSERR_CONTROLUNAVAIL)
454         trace("  No Primary\n");
455     else if (rc==DS_OK && primary!=NULL) {
456         LONG vol;
457 
458         /* Try to create a second primary buffer */
459         /* DSOUND: Error: The primary buffer already exists.
460          * Any changes made to the buffer description will be ignored. */
461         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
462         ok(rc==DS_OK && second==primary,
463            "IDirectSound_CreateSoundBuffer() should have returned original "
464            "primary buffer: %08x\n",rc);
465         ref=IDirectSoundBuffer_Release(second);
466         ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
467            "should have 1\n",ref);
468 
469         /* Try to duplicate a primary buffer */
470         /* DSOUND: Error: Can't duplicate primary buffers */
471         rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
472         /* rc=0x88780032 */
473         ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
474            "should have failed %08x\n",rc);
475 
476         rc=IDirectSoundBuffer_GetVolume(primary,&vol);
477         ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %08x\n", 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\n",ref);
493 
494         ref=IDirectSoundBuffer_AddRef(primary);
495         ok(ref==1,"IDirectSoundBuffer_AddRef() primary has %d references\n",ref);
496 
497         ref=IDirectSoundBuffer_Release(primary);
498         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references\n",ref);
499 
500         ref=IDirectSoundBuffer_Release(primary);
501         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
502            "should have 0\n",ref);
503     }
504 
505     /* Set the CooperativeLevel back to normal */
506     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
507     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
508     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
509 
510 EXIT:
511     ref=IDirectSound_Release(dso);
512     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
513     if (ref!=0)
514         return DSERR_GENERIC;
515 
516     return rc;
517 }
518 
519 /*
520  * Test the primary buffer at different formats while keeping the
521  * secondary buffer at a constant format.
522  */
523 static HRESULT test_primary_secondary(LPGUID lpGuid)
524 {
525     HRESULT rc;
526     LPDIRECTSOUND dso=NULL;
527     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
528     DSBUFFERDESC bufdesc;
529     DSCAPS dscaps;
530     WAVEFORMATEX wfx, wfx2;
531     int f,ref,tag;
532 
533     /* Create the DirectSound object */
534     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
535     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
536        "DirectSoundCreate() failed: %08x\n",rc);
537     if (rc!=DS_OK)
538         return rc;
539 
540     /* Get the device capabilities */
541     ZeroMemory(&dscaps, sizeof(dscaps));
542     dscaps.dwSize=sizeof(dscaps);
543     rc=IDirectSound_GetCaps(dso,&dscaps);
544     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc);
545     if (rc!=DS_OK)
546         goto EXIT;
547 
548     /* We must call SetCooperativeLevel before creating primary buffer */
549     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
550     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
551     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
552     if (rc!=DS_OK)
553         goto EXIT;
554 
555     ZeroMemory(&bufdesc, sizeof(bufdesc));
556     bufdesc.dwSize=sizeof(bufdesc);
557     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
558     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
559     ok(rc==DS_OK && primary!=NULL,
560        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer %08x\n",rc);
561 
562     if (rc==DS_OK && primary!=NULL) {
563         for (f=0;f<NB_FORMATS;f++) {
564           for (tag=0;tag<NB_TAGS;tag++) {
565             /* if float, we only want to test 32-bit */
566             if ((format_tags[tag] == WAVE_FORMAT_IEEE_FLOAT) && (formats[f][1] != 32))
567                 continue;
568 
569             /* We must call SetCooperativeLevel to be allowed to call
570              * SetFormat */
571             /* DSOUND: Setting DirectSound cooperative level to
572              * DSSCL_PRIORITY */
573             rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
574             ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
575             if (rc!=DS_OK)
576                 goto EXIT;
577 
578             init_format(&wfx,format_tags[tag],formats[f][0],formats[f][1],
579                         formats[f][2]);
580             wfx2=wfx;
581             rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
582 
583             if (wfx.wBitsPerSample <= 16)
584                 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %08x\n",
585                    format_string(&wfx), rc);
586             else
587                 ok(rc==DS_OK || rc == E_INVALIDARG, "SetFormat (%s) failed: %08x\n",
588                    format_string(&wfx), rc);
589 
590             /* There is no guarantee that SetFormat will actually change the
591              * format to what we asked for. It depends on what the soundcard
592              * supports. So we must re-query the format.
593              */
594             rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
595             ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
596             if (rc==DS_OK &&
597                 (wfx.wFormatTag!=wfx2.wFormatTag ||
598                  wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
599                  wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
600                  wfx.nChannels!=wfx2.nChannels)) {
601                 trace("Requested primary format tag=0x%04x %dx%dx%d "
602                       "avg.B/s=%d align=%d\n",
603                       wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
604                       wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
605                 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
606                       wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
607                       wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
608             }
609 
610             /* Set the CooperativeLevel back to normal */
611             /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
612             rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
613             ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
614 
615             init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
616 
617             secondary=NULL;
618             ZeroMemory(&bufdesc, sizeof(bufdesc));
619             bufdesc.dwSize=sizeof(bufdesc);
620             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
621             bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
622                                         wfx.nBlockAlign);
623             bufdesc.lpwfxFormat=&wfx2;
624             if (winetest_interactive) {
625                 trace("  Testing a primary buffer at %dx%dx%d (fmt=%d) with a "
626                       "secondary buffer at %dx%dx%d\n",
627                       wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,format_tags[tag],
628                       wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
629             }
630             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
631             ok((rc==DS_OK && secondary!=NULL) || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */
632                "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer %08x\n",rc);
633 
634             if (rc==DS_OK && secondary!=NULL) {
635                 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
636                             winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
637 
638                 ref=IDirectSoundBuffer_Release(secondary);
639                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
640                    "should have 0\n",ref);
641             }
642           }
643         }
644 
645         ref=IDirectSoundBuffer_Release(primary);
646         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
647            "should have 0\n",ref);
648     }
649 
650     /* Set the CooperativeLevel back to normal */
651     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
652     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
653     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
654 
655 EXIT:
656     ref=IDirectSound_Release(dso);
657     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
658     if (ref!=0)
659         return DSERR_GENERIC;
660 
661     return rc;
662 }
663 
664 static HRESULT test_secondary(LPGUID lpGuid)
665 {
666     HRESULT rc;
667     LPDIRECTSOUND dso=NULL;
668     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
669     DSBUFFERDESC bufdesc;
670     DSCAPS dscaps;
671     WAVEFORMATEX wfx, wfx1;
672     DWORD f, tag;
673     int ref;
674 
675     /* Create the DirectSound object */
676     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
677     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
678        "DirectSoundCreate() failed: %08x\n",rc);
679     if (rc!=DS_OK)
680         return rc;
681 
682     /* Get the device capabilities */
683     ZeroMemory(&dscaps, sizeof(dscaps));
684     dscaps.dwSize=sizeof(dscaps);
685     rc=IDirectSound_GetCaps(dso,&dscaps);
686     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc);
687     if (rc!=DS_OK)
688         goto EXIT;
689 
690     /* We must call SetCooperativeLevel before creating primary buffer */
691     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
692     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
693     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
694     if (rc!=DS_OK)
695         goto EXIT;
696 
697     ZeroMemory(&bufdesc, sizeof(bufdesc));
698     bufdesc.dwSize=sizeof(bufdesc);
699     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
700     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
701     ok(rc==DS_OK && primary!=NULL,
702        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer %08x\n",rc);
703 
704     if (rc==DS_OK && primary!=NULL) {
705         rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
706         ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
707         if (rc!=DS_OK)
708             goto EXIT1;
709 
710         for (f=0;f<NB_FORMATS;f++) {
711           for (tag=0;tag<NB_TAGS;tag++) {
712             WAVEFORMATEXTENSIBLE wfxe;
713 
714             /* if float, we only want to test 32-bit */
715             if ((format_tags[tag] == WAVE_FORMAT_IEEE_FLOAT) && (formats[f][1] != 32))
716                 continue;
717 
718             init_format(&wfx,format_tags[tag],formats[f][0],formats[f][1],
719                         formats[f][2]);
720             secondary=NULL;
721             ZeroMemory(&bufdesc, sizeof(bufdesc));
722             bufdesc.dwSize=sizeof(bufdesc);
723             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
724             bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
725                                         wfx.nBlockAlign);
726             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
727             ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
728                "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
729             if (rc==DS_OK && secondary!=NULL)
730                 IDirectSoundBuffer_Release(secondary);
731 
732             secondary=NULL;
733             ZeroMemory(&bufdesc, sizeof(bufdesc));
734             bufdesc.dwSize=sizeof(bufdesc);
735             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
736             bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
737                                         wfx.nBlockAlign);
738             bufdesc.lpwfxFormat=&wfx;
739             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
740             if (gotdx8 || wfx.wBitsPerSample <= 16 || wfx.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
741             {
742                 if (wfx.wBitsPerSample > 16)
743                     ok(broken((rc == DSERR_CONTROLUNAVAIL || rc == DSERR_INVALIDCALL || rc == DSERR_INVALIDPARAM /* 2003 */) && !secondary)
744                         || rc == DS_OK, /* driver dependent? */
745                         "IDirectSound_CreateSoundBuffer() "
746                         "should have returned (DSERR_CONTROLUNAVAIL or DSERR_INVALIDCALL) "
747                         "and NULL, returned: %08x %p\n", rc, secondary);
748                 else
749                     ok((rc==DS_OK && secondary!=NULL) || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */
750                         "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer %08x\n",rc);
751             }
752             else
753                 ok(rc==E_INVALIDARG, "Creating %d bpp buffer on dx < 8 returned: %p %08x\n",
754                    wfx.wBitsPerSample, secondary, rc);
755 
756             if (!gotdx8)
757             {
758                 win_skip("Not doing the WAVE_FORMAT_EXTENSIBLE tests\n");
759                 /* Apparently they succeed with bogus values,
760                  * which means that older dsound doesn't look at them
761                  */
762                 goto no_wfe;
763             }
764 
765             if (secondary)
766                 IDirectSoundBuffer_Release(secondary);
767             secondary = NULL;
768 
769             bufdesc.lpwfxFormat=(WAVEFORMATEX*)&wfxe;
770             wfxe.Format = wfx;
771             wfxe.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
772             wfxe.SubFormat = (format_tags[tag] == WAVE_FORMAT_PCM ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
773             wfxe.Format.cbSize = 1;
774             wfxe.Samples.wValidBitsPerSample = wfx.wBitsPerSample;
775             wfxe.dwChannelMask = (wfx.nChannels == 1 ? KSAUDIO_SPEAKER_MONO : KSAUDIO_SPEAKER_STEREO);
776 
777             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
778             ok((rc==DSERR_INVALIDPARAM || rc==DSERR_INVALIDCALL /* 2003 */) && !secondary,
779                 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
780                 rc, secondary);
781             if (secondary)
782             {
783                 IDirectSoundBuffer_Release(secondary);
784                 secondary=NULL;
785             }
786 
787             wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx) + 1;
788 
789             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
790             ok(((rc==DSERR_CONTROLUNAVAIL || rc==DSERR_INVALIDCALL || rc==DSERR_INVALIDPARAM)
791                 && !secondary)
792                || rc==DS_OK, /* 2003 / 2008 */
793                 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
794                 rc, secondary);
795             if (secondary)
796             {
797                 IDirectSoundBuffer_Release(secondary);
798                 secondary=NULL;
799             }
800 
801             wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx);
802             wfxe.SubFormat = GUID_NULL;
803             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
804             ok((rc==DSERR_INVALIDPARAM || rc==DSERR_INVALIDCALL) && !secondary,
805                 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
806                 rc, secondary);
807             if (secondary)
808             {
809                 IDirectSoundBuffer_Release(secondary);
810                 secondary=NULL;
811             }
812             wfxe.SubFormat = (format_tags[tag] == WAVE_FORMAT_PCM ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
813 
814             ++wfxe.Samples.wValidBitsPerSample;
815             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
816             ok(rc==DSERR_INVALIDPARAM && !secondary,
817                 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
818                 rc, secondary);
819             if (secondary)
820             {
821                 IDirectSoundBuffer_Release(secondary);
822                 secondary=NULL;
823             }
824             --wfxe.Samples.wValidBitsPerSample;
825 
826             wfxe.Samples.wValidBitsPerSample = 0;
827             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
828             ok(rc==DS_OK && secondary,
829                 "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
830                 rc, secondary);
831             if (secondary)
832             {
833                 IDirectSoundBuffer_Release(secondary);
834                 secondary=NULL;
835             }
836             wfxe.Samples.wValidBitsPerSample = wfxe.Format.wBitsPerSample;
837 
838             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
839             ok(rc==DS_OK && secondary!=NULL,
840                 "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer %08x\n",rc);
841 
842 no_wfe:
843             if (rc==DS_OK && secondary!=NULL) {
844                 if (winetest_interactive) {
845                     trace("  Testing a secondary buffer at %dx%dx%d (fmt=%d) "
846                         "with a primary buffer at %dx%dx%d\n",
847                         wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,format_tags[tag],
848                         wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
849                 }
850                 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
851                             winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
852 
853                 ref=IDirectSoundBuffer_Release(secondary);
854                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
855                    "should have 0\n",ref);
856             }
857           }
858         }
859 EXIT1:
860         ref=IDirectSoundBuffer_Release(primary);
861         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
862            "should have 0\n",ref);
863     }
864 
865     /* Set the CooperativeLevel back to normal */
866     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
867     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
868     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
869 
870 EXIT:
871     ref=IDirectSound_Release(dso);
872     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
873     if (ref!=0)
874         return DSERR_GENERIC;
875 
876     return rc;
877 }
878 
879 static HRESULT test_block_align(LPGUID lpGuid)
880 {
881     HRESULT rc;
882     LPDIRECTSOUND dso=NULL;
883     LPDIRECTSOUNDBUFFER secondary=NULL;
884     DSBUFFERDESC bufdesc;
885     DSBCAPS dsbcaps;
886     WAVEFORMATEX wfx;
887     DWORD pos, pos2;
888     int ref;
889 
890     /* Create the DirectSound object */
891     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
892     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
893        "DirectSoundCreate() failed: %08x\n",rc);
894     if (rc!=DS_OK)
895         return rc;
896 
897     init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2);
898     ZeroMemory(&bufdesc, sizeof(bufdesc));
899     bufdesc.dwSize=sizeof(bufdesc);
900     bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
901     bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1;
902     bufdesc.lpwfxFormat=&wfx;
903     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
904     ok(rc == DS_OK || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */
905        "IDirectSound_CreateSoundBuffer() should have returned DS_OK, returned: %08x\n", rc);
906 
907     if (rc==DS_OK && secondary!=NULL) {
908         ZeroMemory(&dsbcaps, sizeof(dsbcaps));
909         dsbcaps.dwSize = sizeof(dsbcaps);
910         rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps);
911         ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
912            "returned: %08x\n", rc);
913         if (rc==DS_OK && wfx.nBlockAlign > 1)
914         {
915             ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign),
916                "Buffer size not a multiple of nBlockAlign: requested %d, "
917                "got %d, should be %d\n", bufdesc.dwBufferBytes,
918                dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign);
919 
920             rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 0);
921             ok(rc == DS_OK, "Could not set position to 0: %08x\n", rc);
922             rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos, NULL);
923             ok(rc == DS_OK, "Could not get position: %08x\n", rc);
924             rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 1);
925             ok(rc == DS_OK, "Could not set position to 1: %08x\n", rc);
926             rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos2, NULL);
927             ok(rc == DS_OK, "Could not get new position: %08x\n", rc);
928             ok(pos == pos2, "Positions not the same! Old position: %d, new position: %d\n", pos, pos2);
929         }
930         ref=IDirectSoundBuffer_Release(secondary);
931         ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, "
932            "should have 0\n",ref);
933     }
934 
935     ref=IDirectSound_Release(dso);
936     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
937     if (ref!=0)
938         return DSERR_GENERIC;
939 
940     return rc;
941 }
942 
943 static struct fmt {
944     int bits;
945     int channels;
946 } fmts[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } };
947 
948 static HRESULT test_frequency(LPGUID lpGuid)
949 {
950     HRESULT rc;
951     LPDIRECTSOUND dso=NULL;
952     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
953     DSBUFFERDESC bufdesc;
954     DSCAPS dscaps;
955     WAVEFORMATEX wfx, wfx1;
956     DWORD f, r;
957     int ref;
958     int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
959                     48000, 96000 };
960 
961     /* Create the DirectSound object */
962     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
963     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
964        "DirectSoundCreate() failed: %08x\n",rc);
965     if (rc!=DS_OK)
966         return rc;
967 
968     /* Get the device capabilities */
969     ZeroMemory(&dscaps, sizeof(dscaps));
970     dscaps.dwSize=sizeof(dscaps);
971     rc=IDirectSound_GetCaps(dso,&dscaps);
972     ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc);
973     if (rc!=DS_OK)
974         goto EXIT;
975 
976     /* We must call SetCooperativeLevel before creating primary buffer */
977     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
978     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
979     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
980     if (rc!=DS_OK)
981         goto EXIT;
982 
983     ZeroMemory(&bufdesc, sizeof(bufdesc));
984     bufdesc.dwSize=sizeof(bufdesc);
985     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
986     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
987     ok(rc==DS_OK && primary!=NULL,
988        "IDirectSound_CreateSoundBuffer() failed to create a primary buffer %08x\n",rc);
989 
990     if (rc==DS_OK && primary!=NULL) {
991         rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
992         ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
993         if (rc!=DS_OK)
994             goto EXIT1;
995 
996         for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) {
997         for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) {
998             init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits,
999                         fmts[f].channels);
1000             secondary=NULL;
1001             ZeroMemory(&bufdesc, sizeof(bufdesc));
1002             bufdesc.dwSize=sizeof(bufdesc);
1003             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY;
1004             bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)*
1005                                         BUFFER_LEN/1000,wfx.nBlockAlign);
1006             bufdesc.lpwfxFormat=&wfx;
1007             if (winetest_interactive) {
1008                 trace("  Testing a secondary buffer at %dx%dx%d "
1009                       "with a primary buffer at %dx%dx%d\n",
1010                       wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
1011                       wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
1012             }
1013             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
1014             ok((rc==DS_OK && secondary!=NULL) || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */
1015                "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer %08x\n",rc);
1016 
1017             if (rc==DS_OK && secondary!=NULL) {
1018                 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
1019                             winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]);
1020 
1021                 ref=IDirectSoundBuffer_Release(secondary);
1022                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
1023                    "should have 0\n",ref);
1024             }
1025         }
1026         }
1027 EXIT1:
1028         ref=IDirectSoundBuffer_Release(primary);
1029         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
1030            "should have 0\n",ref);
1031     }
1032 
1033     /* Set the CooperativeLevel back to normal */
1034     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
1035     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
1036     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
1037 
1038 EXIT:
1039     ref=IDirectSound_Release(dso);
1040     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
1041     if (ref!=0)
1042         return DSERR_GENERIC;
1043 
1044     return rc;
1045 }
1046 
1047 static HRESULT test_notify(LPDIRECTSOUNDBUFFER dsb,
1048                            DWORD count, LPHANDLE event,
1049                            DWORD expected)
1050 {
1051     HRESULT rc;
1052     DWORD ret;
1053 
1054     rc=IDirectSoundBuffer_SetCurrentPosition(dsb,0);
1055     ok(rc==DS_OK,
1056        "IDirectSoundBuffer_SetCurrentPosition failed %08x\n",rc);
1057     if(rc!=DS_OK)
1058         return rc;
1059 
1060     rc=IDirectSoundBuffer_Play(dsb,0,0,0);
1061     ok(rc==DS_OK,"IDirectSoundBuffer_Play failed %08x\n",rc);
1062     if(rc!=DS_OK)
1063         return rc;
1064 
1065     rc=IDirectSoundBuffer_Stop(dsb);
1066     ok(rc==DS_OK,"IDirectSoundBuffer_Stop failed %08x\n",rc);
1067     if(rc!=DS_OK)
1068         return rc;
1069 
1070     ret=WaitForMultipleObjects(count,event,FALSE,0);
1071     ok(ret==expected,"expected %d. got %d\n",expected,ret);
1072     return rc;
1073 }
1074 
1075 static HRESULT test_duplicate(LPGUID lpGuid)
1076 {
1077     HRESULT rc;
1078     LPDIRECTSOUND dso=NULL;
1079     LPDIRECTSOUNDBUFFER primary=NULL;
1080     DSBUFFERDESC bufdesc;
1081     int ref;
1082 
1083     /* Create the DirectSound object */
1084     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
1085     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
1086        "DirectSoundCreate() failed: %08x\n",rc);
1087     if (rc!=DS_OK)
1088         return rc;
1089 
1090     /* We must call SetCooperativeLevel before creating primary buffer */
1091     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1092     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
1093     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
1094     if (rc!=DS_OK)
1095         goto EXIT;
1096 
1097     ZeroMemory(&bufdesc, sizeof(bufdesc));
1098     bufdesc.dwSize=sizeof(bufdesc);
1099     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
1100     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
1101     ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() failed "
1102        "to create a primary buffer %08x\n",rc);
1103 
1104     if (rc==DS_OK && primary!=NULL) {
1105         LPDIRECTSOUNDBUFFER original=NULL;
1106         WAVEFORMATEX wfx;
1107 
1108         init_format(&wfx,WAVE_FORMAT_PCM,22050,16,1);
1109         ZeroMemory(&bufdesc, sizeof(bufdesc));
1110         bufdesc.dwSize=sizeof(bufdesc);
1111         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLPOSITIONNOTIFY;
1112         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec/100; /* very short buffer */
1113         bufdesc.lpwfxFormat=&wfx;
1114         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&original,NULL);
1115         ok(rc==DS_OK && original!=NULL,
1116            "IDirectSound_CreateSoundBuffer() failed to create a original "
1117            "buffer %08x\n",rc);
1118         if (rc==DS_OK && original!=NULL) {
1119             LPDIRECTSOUNDBUFFER duplicated=NULL;
1120             LPDIRECTSOUNDNOTIFY notify=NULL;
1121             HANDLE event[2];
1122             LPVOID buf=NULL;
1123             DWORD bufsize;
1124             int i;
1125 
1126             /* Prepare notify events */
1127             for (i=0;i<sizeof(event)/sizeof(event[0]);i++) {
1128                 event[i] = CreateEvent(NULL,FALSE,FALSE,NULL);
1129             }
1130 
1131             /* Make silent buffer */
1132             rc=IDirectSoundBuffer_Lock(original,0,0,&buf,&bufsize,
1133                                        NULL,NULL,DSBLOCK_ENTIREBUFFER);
1134             ok(rc==DS_OK && buf!=NULL,
1135                "IDirectSoundBuffer_Lock failed to lock the buffer %08x\n",rc);
1136             if (rc==DS_OK && buf!=NULL) {
1137                 ZeroMemory(buf,bufsize);
1138                 rc=IDirectSoundBuffer_Unlock(original,buf,bufsize,
1139                                              NULL,0);
1140                 ok(rc==DS_OK,"IDirectSoundBuffer_Unlock failed to unlock "
1141                    "%08x\n",rc);
1142             }
1143 
1144             rc=IDirectSoundBuffer_QueryInterface(original,
1145                                                  &IID_IDirectSoundNotify,
1146                                                  (void**)&notify);
1147             ok(rc==DS_OK && notify!=NULL,
1148                "IDirectSoundBuffer_QueryInterface() failed to create a "
1149                "notification %08x\n",rc);
1150             if (rc==DS_OK && notify!=NULL) {
1151                 DSBPOSITIONNOTIFY dsbpn;
1152                 LPDIRECTSOUNDNOTIFY dup_notify=NULL;
1153 
1154                 dsbpn.dwOffset=DSBPN_OFFSETSTOP;
1155                 dsbpn.hEventNotify=event[0];
1156                 rc=IDirectSoundNotify_SetNotificationPositions(notify,
1157                                                                1,&dsbpn);
1158                 ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions "
1159                    "failed %08x\n",rc);
1160 
1161                 rc=IDirectSound_DuplicateSoundBuffer(dso,original,&duplicated);
1162                 ok(rc==DS_OK && duplicated!=NULL,
1163                    "IDirectSound_DuplicateSoundBuffer failed %08x\n",rc);
1164 
1165                 trace("testing duplicated buffer without notifications.\n");
1166                 test_notify(duplicated,sizeof(event)/sizeof(event[0]),
1167                             event,WAIT_TIMEOUT);
1168 
1169                 rc=IDirectSoundBuffer_QueryInterface(duplicated,
1170                                                      &IID_IDirectSoundNotify,
1171                                                      (void**)&dup_notify);
1172                 ok(rc==DS_OK&&dup_notify!=NULL,
1173                    "IDirectSoundBuffer_QueryInterface() failed to create a "
1174                    "notification %08x\n",rc);
1175                 if(rc==DS_OK&&dup_notify!=NULL) {
1176                     dsbpn.dwOffset=DSBPN_OFFSETSTOP;
1177                     dsbpn.hEventNotify=event[1];
1178                     rc=IDirectSoundNotify_SetNotificationPositions(dup_notify,
1179                                                                    1,&dsbpn);
1180                     ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions "
1181                        "failed %08x\n",rc);
1182 
1183                     trace("testing duplicated buffer with a notification.\n");
1184                     test_notify(duplicated,sizeof(event)/sizeof(event[0]),
1185                                 event,WAIT_OBJECT_0+1);
1186 
1187                     ref=IDirectSoundNotify_Release(dup_notify);
1188                     ok(ref==0,"IDirectSoundNotify_Release() has %d references, "
1189                        "should have 0\n",ref);
1190                 }
1191                 ref=IDirectSoundNotify_Release(notify);
1192                 ok(ref==0,"IDirectSoundNotify_Release() has %d references, "
1193                    "should have 0\n",ref);
1194 
1195                 trace("testing original buffer with a notification.\n");
1196                 test_notify(original,sizeof(event)/sizeof(event[0]),
1197                             event,WAIT_OBJECT_0);
1198 
1199                 ref=IDirectSoundBuffer_Release(duplicated);
1200                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
1201                    "should have 0\n",ref);
1202             }
1203             ref=IDirectSoundBuffer_Release(original);
1204             ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
1205                "should have 0\n",ref);
1206         }
1207         ref=IDirectSoundBuffer_Release(primary);
1208         ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
1209            "should have 0\n",ref);
1210     }
1211 
1212     /* Set the CooperativeLevel back to normal */
1213     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
1214     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
1215     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
1216 
1217 EXIT:
1218     ref=IDirectSound_Release(dso);
1219     ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
1220     if (ref!=0)
1221         return DSERR_GENERIC;
1222 
1223     return rc;
1224 }
1225 
1226 static HRESULT test_invalid_fmts(LPGUID lpGuid)
1227 {
1228     HRESULT rc;
1229     LPDIRECTSOUND dso=NULL;
1230     LPDIRECTSOUNDBUFFER primary=NULL;
1231     DSBUFFERDESC bufdesc;
1232 
1233     /* Create the DirectSound object */
1234     rc=pDirectSoundCreate(lpGuid,&dso,NULL);
1235     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
1236        "DirectSoundCreate() failed: %08x\n",rc);
1237     if (rc!=DS_OK)
1238         return rc;
1239 
1240     /* We must call SetCooperativeLevel before creating primary buffer */
1241     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1242     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
1243     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
1244     if (rc!=DS_OK){
1245         IDirectSound_Release(dso);
1246         return rc;
1247     }
1248 
1249     ZeroMemory(&bufdesc, sizeof(bufdesc));
1250     bufdesc.dwSize=sizeof(bufdesc);
1251     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
1252     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
1253     ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() failed "
1254        "to create a primary buffer %08x\n",rc);
1255 
1256     if (rc==DS_OK && primary!=NULL) {
1257         WAVEFORMATEX wfx;
1258         WAVEFORMATEXTENSIBLE fmtex;
1259 
1260         wfx.wFormatTag = WAVE_FORMAT_PCM;
1261         wfx.nChannels = 0;
1262         wfx.nSamplesPerSec = 44100;
1263         wfx.wBitsPerSample = 16;
1264         wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1265         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1266         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1267         ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1268 
1269         wfx.nChannels = 2;
1270         wfx.nSamplesPerSec = 44100;
1271         wfx.wBitsPerSample = 0;
1272         wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1273         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1274         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1275         ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1276 
1277         wfx.nChannels = 2;
1278         wfx.nSamplesPerSec = 44100;
1279         wfx.wBitsPerSample = 2;
1280         wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1281         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1282         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1283         ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1284 
1285         wfx.nChannels = 2;
1286         wfx.nSamplesPerSec = 44100;
1287         wfx.wBitsPerSample = 12;
1288         wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1289         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1290         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1291         ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1292 
1293         wfx.nChannels = 2;
1294         wfx.nSamplesPerSec = 0;
1295         wfx.wBitsPerSample = 16;
1296         wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1297         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1298         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1299         ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1300 
1301         wfx.nChannels = 2;
1302         wfx.nSamplesPerSec = 44100;
1303         wfx.wBitsPerSample = 16;
1304         wfx.nBlockAlign = 0;
1305         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1306         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1307         ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1308 
1309         wfx.nChannels = 2;
1310         wfx.nSamplesPerSec = 44100;
1311         wfx.wBitsPerSample = 16;
1312         wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1313         wfx.nAvgBytesPerSec = 0;
1314         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1315         ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1316 
1317         wfx.nChannels = 2;
1318         wfx.nSamplesPerSec = 44100;
1319         wfx.wBitsPerSample = 16;
1320         wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample / 8) - 1;
1321         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1322         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1323         ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1324 
1325         wfx.nChannels = 2;
1326         wfx.nSamplesPerSec = 44100;
1327         wfx.wBitsPerSample = 16;
1328         wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample / 8) + 1;
1329         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1330         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1331         ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1332 
1333         wfx.nChannels = 2;
1334         wfx.nSamplesPerSec = 44100;
1335         wfx.wBitsPerSample = 16;
1336         wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1337         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign + 1;
1338         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1339         ok(rc == S_OK, "SetFormat: %08x\n", rc);
1340 
1341         rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
1342         ok(rc == S_OK, "GetFormat: %08x\n", rc);
1343         ok(wfx.wFormatTag == WAVE_FORMAT_PCM, "format: 0x%x\n", wfx.wFormatTag);
1344         ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
1345         ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
1346         ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
1347         ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
1348         ok(wfx.nAvgBytesPerSec == 44100 * 4 + 1, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
1349 
1350         wfx.nChannels = 2;
1351         wfx.nSamplesPerSec = 44100;
1352         wfx.wBitsPerSample = 16;
1353         wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1354         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign - 1;
1355         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1356         ok(rc == S_OK, "SetFormat: %08x\n", rc);
1357 
1358         rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
1359         ok(rc == S_OK, "GetFormat: %08x\n", rc);
1360         ok(wfx.wFormatTag == WAVE_FORMAT_PCM, "format: 0x%x\n", wfx.wFormatTag);
1361         ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
1362         ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
1363         ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
1364         ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
1365         ok(wfx.nAvgBytesPerSec == 44100 * 4 - 1, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
1366 
1367         wfx.nChannels = 2;
1368         wfx.nSamplesPerSec = 44100;
1369         wfx.wBitsPerSample = 16;
1370         wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1371         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign + 1;
1372         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1373         ok(rc == S_OK, "SetFormat: %08x\n", rc);
1374 
1375         rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
1376         ok(rc == S_OK, "GetFormat: %08x\n", rc);
1377         ok(wfx.wFormatTag == WAVE_FORMAT_PCM, "format: 0x%x\n", wfx.wFormatTag);
1378         ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
1379         ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
1380         ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
1381         ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
1382         ok(wfx.nAvgBytesPerSec == 44100 * 4 + 1, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
1383 
1384         wfx.wFormatTag = WAVE_FORMAT_ALAW;
1385         wfx.nChannels = 2;
1386         wfx.nSamplesPerSec = 44100;
1387         wfx.wBitsPerSample = 16;
1388         wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
1389         wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
1390         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
1391         ok(rc == S_OK, "SetFormat: %08x\n", rc);
1392 
1393         rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
1394         ok(rc == S_OK, "GetFormat: %08x\n", rc);
1395         ok(wfx.wFormatTag == WAVE_FORMAT_ALAW, "format: 0x%x\n", wfx.wFormatTag);
1396         ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
1397         ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
1398         ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
1399         ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
1400         ok(wfx.nAvgBytesPerSec == 44100 * 4, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
1401 
1402         if(!gotdx8){
1403             win_skip("Not doing the WAVE_FORMAT_EXTENSIBLE tests\n");
1404             goto done;
1405         }
1406 
1407         fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
1408         fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
1409         fmtex.Format.nChannels = 2;
1410         fmtex.Format.nSamplesPerSec = 44100;
1411         fmtex.Format.wBitsPerSample = 16;
1412         fmtex.Format.nBlockAlign = fmtex.Format.nChannels * fmtex.Format.wBitsPerSample / 8;
1413         fmtex.Format.nAvgBytesPerSec = fmtex.Format.nSamplesPerSec * fmtex.Format.nBlockAlign;
1414         fmtex.Samples.wValidBitsPerSample = 0;
1415         fmtex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
1416         fmtex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1417         rc = IDirectSoundBuffer_SetFormat(primary, (WAVEFORMATEX*)&fmtex);
1418         ok(rc == S_OK, "SetFormat: %08x\n", rc);
1419 
1420         rc = IDirectSoundBuffer_GetFormat(primary, (WAVEFORMATEX*)&fmtex, sizeof(fmtex), NULL);
1421         ok(rc == S_OK, "GetFormat: %08x\n", rc);
1422         ok(fmtex.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE, "format: 0x%x\n", fmtex.Format.wFormatTag);
1423         ok(fmtex.Format.nChannels == 2, "channels: %u\n", fmtex.Format.nChannels);
1424         ok(fmtex.Format.nSamplesPerSec == 44100, "rate: %u\n", fmtex.Format.nSamplesPerSec);
1425         ok(fmtex.Format.wBitsPerSample == 16, "bps: %u\n", fmtex.Format.wBitsPerSample);
1426         ok(fmtex.Format.nBlockAlign == 4, "blockalign: %u\n", fmtex.Format.nBlockAlign);
1427         ok(fmtex.Format.nAvgBytesPerSec == 44100 * 4, "avgbytes: %u\n", fmtex.Format.nAvgBytesPerSec);
1428         ok(fmtex.Samples.wValidBitsPerSample == 0 || /* <= XP */
1429                 fmtex.Samples.wValidBitsPerSample == 16, /* >= Vista */
1430                 "validbits: %u\n", fmtex.Samples.wValidBitsPerSample);
1431         ok(IsEqualGUID(&fmtex.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM), "subtype incorrect\n");
1432 
1433         fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
1434         fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
1435         fmtex.Format.nChannels = 2;
1436         fmtex.Format.nSamplesPerSec = 44100;
1437         fmtex.Format.wBitsPerSample = 24;
1438         fmtex.Format.nBlockAlign = fmtex.Format.nChannels * fmtex.Format.wBitsPerSample / 8;
1439         fmtex.Format.nAvgBytesPerSec = fmtex.Format.nSamplesPerSec * fmtex.Format.nBlockAlign;
1440         fmtex.Samples.wValidBitsPerSample = 20;
1441         fmtex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
1442         fmtex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1443         rc = IDirectSoundBuffer_SetFormat(primary, (WAVEFORMATEX*)&fmtex);
1444         ok(rc == S_OK, "SetFormat: %08x\n", rc);
1445 
1446         rc = IDirectSoundBuffer_GetFormat(primary, (WAVEFORMATEX*)&fmtex, sizeof(fmtex), NULL);
1447         ok(rc == S_OK, "GetFormat: %08x\n", rc);
1448         ok(fmtex.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE, "format: 0x%x\n", fmtex.Format.wFormatTag);
1449         ok(fmtex.Format.nChannels == 2, "channels: %u\n", fmtex.Format.nChannels);
1450         ok(fmtex.Format.nSamplesPerSec == 44100, "rate: %u\n", fmtex.Format.nSamplesPerSec);
1451         ok(fmtex.Format.wBitsPerSample == 24, "bps: %u\n", fmtex.Format.wBitsPerSample);
1452         ok(fmtex.Format.nBlockAlign == 6, "blockalign: %u\n", fmtex.Format.nBlockAlign);
1453         ok(fmtex.Format.nAvgBytesPerSec == 44100 * 6, "avgbytes: %u\n", fmtex.Format.nAvgBytesPerSec);
1454         ok(fmtex.Samples.wValidBitsPerSample == 20, "validbits: %u\n", fmtex.Samples.wValidBitsPerSample);
1455         ok(IsEqualGUID(&fmtex.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM), "subtype incorrect\n");
1456 
1457         fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
1458         fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
1459         fmtex.Format.nChannels = 2;
1460         fmtex.Format.nSamplesPerSec = 44100;
1461         fmtex.Format.wBitsPerSample = 24;
1462         fmtex.Format.nBlockAlign = fmtex.Format.nChannels * fmtex.Format.wBitsPerSample / 8;
1463         fmtex.Format.nAvgBytesPerSec = fmtex.Format.nSamplesPerSec * fmtex.Format.nBlockAlign;
1464         fmtex.Samples.wValidBitsPerSample = 32;
1465         fmtex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
1466         fmtex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1467         rc = IDirectSoundBuffer_SetFormat(primary, (WAVEFORMATEX*)&fmtex);
1468         ok(rc == E_INVALIDARG, "SetFormat: %08x\n", rc);
1469 
1470         IDirectSoundBuffer_Release(primary);
1471     }
1472 
1473 done:
1474     IDirectSound_Release(dso);
1475 
1476     return S_OK;
1477 }
1478 
1479 static unsigned int number;
1480 
1481 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1482                                    LPCSTR lpcstrModule, LPVOID lpContext)
1483 {
1484     HRESULT rc;
1485     trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
1486 
1487     /* Don't test the primary device */
1488     if (!number++)
1489     {
1490         ok (!lpcstrModule[0], "lpcstrModule(%s) != NULL\n", lpcstrModule);
1491         return 1;
1492     }
1493 
1494     rc = test_dsound(lpGuid);
1495     if (rc == DSERR_NODRIVER)
1496         trace("  No Driver\n");
1497     else if (rc == DSERR_ALLOCATED)
1498         trace("  Already In Use\n");
1499     else if (rc == E_FAIL)
1500         trace("  No Device\n");
1501     else {
1502         test_block_align(lpGuid);
1503         test_primary(lpGuid);
1504         test_primary_secondary(lpGuid);
1505         test_secondary(lpGuid);
1506         test_frequency(lpGuid);
1507         test_duplicate(lpGuid);
1508         test_invalid_fmts(lpGuid);
1509     }
1510 
1511     return 1;
1512 }
1513 
1514 static void dsound_tests(void)
1515 {
1516     HRESULT rc;
1517     rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
1518     ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %08x\n",rc);
1519 }
1520 
1521 static void test_hw_buffers(void)
1522 {
1523     IDirectSound *ds;
1524     IDirectSoundBuffer *primary, *primary2, **secondaries, *secondary;
1525     IDirectSoundBuffer8 *buf8;
1526     DSCAPS caps;
1527     DSBCAPS bufcaps;
1528     DSBUFFERDESC bufdesc;
1529     WAVEFORMATEX fmt;
1530     UINT i;
1531     HRESULT hr;
1532 
1533     hr = pDirectSoundCreate(NULL, &ds, NULL);
1534     ok(hr == S_OK || hr == DSERR_NODRIVER || hr == DSERR_ALLOCATED || hr == E_FAIL,
1535             "DirectSoundCreate failed: %08x\n", hr);
1536     if(hr != S_OK)
1537         return;
1538 
1539     caps.dwSize = sizeof(caps);
1540 
1541     hr = IDirectSound_GetCaps(ds, &caps);
1542     ok(hr == S_OK, "GetCaps failed: %08x\n", hr);
1543 
1544     ok(caps.dwPrimaryBuffers == 1, "Got wrong number of primary buffers: %u\n",
1545             caps.dwPrimaryBuffers);
1546 
1547     /* DSBCAPS_LOC* is ignored for primary buffers */
1548     bufdesc.dwSize = sizeof(bufdesc);
1549     bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE |
1550         DSBCAPS_PRIMARYBUFFER;
1551     bufdesc.dwBufferBytes = 0;
1552     bufdesc.dwReserved = 0;
1553     bufdesc.lpwfxFormat = NULL;
1554     bufdesc.guid3DAlgorithm = GUID_NULL;
1555 
1556     hr = IDirectSound_CreateSoundBuffer(ds, &bufdesc, &primary, NULL);
1557     ok(hr == S_OK, "CreateSoundBuffer failed: %08x\n", hr);
1558     if(hr != S_OK){
1559         IDirectSound_Release(ds);
1560         return;
1561     }
1562 
1563     bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE |
1564         DSBCAPS_PRIMARYBUFFER;
1565 
1566     hr = IDirectSound_CreateSoundBuffer(ds, &bufdesc, &primary2, NULL);
1567     ok(hr == S_OK, "CreateSoundBuffer failed: %08x\n", hr);
1568     ok(primary == primary2, "Got different primary buffers: %p, %p\n", primary, primary2);
1569     if(hr == S_OK)
1570         IDirectSoundBuffer_Release(primary2);
1571 
1572     buf8 = (IDirectSoundBuffer8 *)0xDEADBEEF;
1573     hr = IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer8,
1574             (void**)&buf8);
1575     ok(hr == E_NOINTERFACE, "QueryInterface gave wrong failure: %08x\n", hr);
1576     ok(buf8 == NULL, "Pointer didn't get set to NULL\n");
1577 
1578     fmt.wFormatTag = WAVE_FORMAT_PCM;
1579     fmt.nChannels = 2;
1580     fmt.nSamplesPerSec = 48000;
1581     fmt.wBitsPerSample = 16;
1582     fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
1583     fmt.nAvgBytesPerSec = fmt.nBlockAlign * fmt.nSamplesPerSec;
1584     fmt.cbSize = 0;
1585 
1586     bufdesc.lpwfxFormat = &fmt;
1587     bufdesc.dwBufferBytes = fmt.nSamplesPerSec * fmt.nBlockAlign / 10;
1588     bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE |
1589         DSBCAPS_CTRLVOLUME;
1590 
1591     secondaries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1592             sizeof(IDirectSoundBuffer *) * caps.dwMaxHwMixingAllBuffers);
1593 
1594     /* try to fill all of the hw buffers */
1595     trace("dwMaxHwMixingAllBuffers: %u\n", caps.dwMaxHwMixingAllBuffers);
1596     trace("dwMaxHwMixingStaticBuffers: %u\n", caps.dwMaxHwMixingStaticBuffers);
1597     trace("dwMaxHwMixingStreamingBuffers: %u\n", caps.dwMaxHwMixingStreamingBuffers);
1598     for(i = 0; i < caps.dwMaxHwMixingAllBuffers; ++i){
1599         hr = IDirectSound_CreateSoundBuffer(ds, &bufdesc, &secondaries[i], NULL);
1600         ok(hr == S_OK || hr == E_NOTIMPL || broken(hr == DSERR_CONTROLUNAVAIL) || broken(hr == E_FAIL),
1601                 "CreateSoundBuffer(%u) failed: %08x\n", i, hr);
1602         if(hr != S_OK)
1603             break;
1604 
1605         bufcaps.dwSize = sizeof(bufcaps);
1606         hr = IDirectSoundBuffer_GetCaps(secondaries[i], &bufcaps);
1607         ok(hr == S_OK, "GetCaps failed: %08x\n", hr);
1608         ok((bufcaps.dwFlags & DSBCAPS_LOCHARDWARE) != 0,
1609                 "Buffer wasn't allocated in hardware, dwFlags: %x\n", bufcaps.dwFlags);
1610     }
1611 
1612     /* see if we can create one more */
1613     hr = IDirectSound_CreateSoundBuffer(ds, &bufdesc, &secondary, NULL);
1614     ok((i == caps.dwMaxHwMixingAllBuffers && hr == DSERR_ALLOCATED) || /* out of hw buffers */
1615             (caps.dwMaxHwMixingAllBuffers == 0 && hr == DSERR_INVALIDCALL) || /* no hw buffers at all */
1616             hr == E_NOTIMPL || /* don't support hw buffers */
1617             broken(hr == DSERR_CONTROLUNAVAIL) || /* vmware winxp, others? */
1618             broken(hr == E_FAIL) || /* broken AC97 driver */
1619             broken(hr == S_OK) /* broken driver allows more hw bufs than dscaps claims */,
1620             "CreateSoundBuffer(%u) gave wrong error: %08x\n", i, hr);
1621     if(hr == S_OK)
1622         IDirectSoundBuffer_Release(secondary);
1623 
1624     for(i = 0; i < caps.dwMaxHwMixingAllBuffers; ++i)
1625         if(secondaries[i])
1626             IDirectSoundBuffer_Release(secondaries[i]);
1627     HeapFree(GetProcessHeap(), 0, secondaries);
1628 
1629     IDirectSoundBuffer_Release(primary);
1630     IDirectSound_Release(ds);
1631 }
1632 
1633 START_TEST(dsound)
1634 {
1635     HMODULE hDsound;
1636 
1637     CoInitialize(NULL);
1638 
1639     hDsound = LoadLibrary("dsound.dll");
1640     if (hDsound)
1641     {
1642         BOOL ret;
1643 
1644         ret = FreeLibrary(hDsound);
1645         ok( ret, "FreeLibrary(1) returned %d\n", GetLastError());
1646     }
1647 
1648     hDsound = LoadLibrary("dsound.dll");
1649     if (hDsound)
1650     {
1651 
1652         pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
1653             "DirectSoundEnumerateA");
1654         pDirectSoundCreate = (void*)GetProcAddress(hDsound,
1655             "DirectSoundCreate");
1656 
1657         gotdx8 = !!GetProcAddress(hDsound, "DirectSoundCreate8");
1658 
1659         IDirectSound_tests();
1660         dsound_tests();
1661         test_hw_buffers();
1662 
1663         FreeLibrary(hDsound);
1664     }
1665     else
1666         win_skip("dsound.dll not found - skipping all tests\n");
1667 
1668     CoUninitialize();
1669 }
1670