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