EnumThemeColors() and EnumThemeSizes() actually do not return a single
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
30 #include <windows.h>
31 #include <stdio.h>
32
33 #include "wine/test.h"
34 #include "dsound.h"
35 #include "dxerr8.h"
36 #include "dsconf.h"
37
38 #include "dsound_test.h"
39
40 static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL;
41
42 int align(int length, int align)
43 {
44     return (length / align) * align;
45 }
46
47 static void IDirectSound8_test(LPDIRECTSOUND8 dso, BOOL initialized,
48                                LPCGUID lpGuid)
49 {
50     HRESULT rc;
51     DSCAPS dscaps;
52     int ref;
53     IUnknown * unknown;
54     IDirectSound * ds;
55     IDirectSound8 * ds8;
56     DWORD speaker_config, new_speaker_config;
57     DWORD certified;
58
59     /* Try to Query for objects */
60     rc=IDirectSound8_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
61     ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IUnknown) failed: %s\n",
62        DXGetErrorString8(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: %s\n",
68        DXGetErrorString8(rc));
69     if (rc==DS_OK)
70         IDirectSound_Release(ds);
71
72     rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
73     ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound8) "
74        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
75        DXGetErrorString8(rc));
76     if (rc==DS_OK)
77         IDirectSound8_Release(ds8);
78
79     if (initialized == FALSE) {
80         /* try unitialized object */
81         rc=IDirectSound8_GetCaps(dso,0);
82         ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetCaps(NULL) "
83            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
84            DXGetErrorString8(rc));
85
86         rc=IDirectSound8_GetCaps(dso,&dscaps);
87         ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetCaps() "
88            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
89            DXGetErrorString8(rc));
90
91         rc=IDirectSound8_Compact(dso);
92         ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_Compact() "
93            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
94            DXGetErrorString8(rc));
95
96         rc=IDirectSound8_GetSpeakerConfig(dso,&speaker_config);
97         ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetSpeakerConfig() "
98            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
99            DXGetErrorString8(rc));
100
101         rc=IDirectSound8_VerifyCertification(dso, &certified);
102         ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_VerifyCertification() "
103            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
104            DXGetErrorString8(rc));
105
106         rc=IDirectSound8_Initialize(dso,lpGuid);
107         ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
108            "IDirectSound8_Initialize() failed: %s\n",DXGetErrorString8(rc));
109         if (rc==DSERR_NODRIVER) {
110             trace("  No Driver\n");
111             goto EXIT;
112         } else if (rc==E_FAIL) {
113             trace("  No Device\n");
114             goto EXIT;
115         } else if (rc==DSERR_ALLOCATED) {
116             trace("  Already In Use\n");
117             goto EXIT;
118         }
119     }
120
121     rc=IDirectSound8_Initialize(dso,lpGuid);
122     ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound8_Initialize() "
123        "should have returned DSERR_ALREADYINITIALIZED: %s\n",
124        DXGetErrorString8(rc));
125
126     /* DSOUND: Error: Invalid caps buffer */
127     rc=IDirectSound8_GetCaps(dso,0);
128     ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() "
129        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
130        DXGetErrorString8(rc));
131
132     ZeroMemory(&dscaps, sizeof(dscaps));
133
134     /* DSOUND: Error: Invalid caps buffer */
135     rc=IDirectSound8_GetCaps(dso,&dscaps);
136     ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() "
137        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
138        DXGetErrorString8(rc));
139
140     dscaps.dwSize=sizeof(dscaps);
141
142     /* DSOUND: Running on a certified driver */
143     rc=IDirectSound8_GetCaps(dso,&dscaps);
144     ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
145
146     rc=IDirectSound8_Compact(dso);
147     ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound8_Compact() failed: %s\n",
148        DXGetErrorString8(rc));
149
150     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
151     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
152        DXGetErrorString8(rc));
153
154     rc=IDirectSound8_Compact(dso);
155     ok(rc==DS_OK,"IDirectSound8_Compact() failed: %s\n",DXGetErrorString8(rc));
156
157     rc=IDirectSound8_GetSpeakerConfig(dso,0);
158     ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetSpeakerConfig(NULL) "
159        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
160        DXGetErrorString8(rc));
161
162     rc=IDirectSound8_GetSpeakerConfig(dso,&speaker_config);
163     ok(rc==DS_OK,"IDirectSound8_GetSpeakerConfig() failed: %s\n",
164        DXGetErrorString8(rc));
165
166     speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
167                                         DSSPEAKER_GEOMETRY_WIDE);
168     rc=IDirectSound8_SetSpeakerConfig(dso,speaker_config);
169     ok(rc==DS_OK,"IDirectSound8_SetSpeakerConfig() failed: %s\n",
170        DXGetErrorString8(rc));
171     if (rc==DS_OK) {
172         rc=IDirectSound8_GetSpeakerConfig(dso,&new_speaker_config);
173         ok(rc==DS_OK,"IDirectSound8_GetSpeakerConfig() failed: %s\n",
174            DXGetErrorString8(rc));
175         if (rc==DS_OK && speaker_config!=new_speaker_config)
176                trace("IDirectSound8_GetSpeakerConfig() failed to set speaker "
177                "config: expected 0x%08lx, got 0x%08lx\n",
178                speaker_config,new_speaker_config);
179     }
180
181     rc=IDirectSound8_VerifyCertification(dso, &certified);
182     ok(rc==DS_OK||rc==E_NOTIMPL,"IDirectSound8_VerifyCertification() failed: %s\n",
183        DXGetErrorString8(rc));
184
185 EXIT:
186     ref=IDirectSound8_Release(dso);
187     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
188 }
189
190 static void IDirectSound8_tests(void)
191 {
192     HRESULT rc;
193     LPDIRECTSOUND8 dso=NULL;
194
195     trace("Testing IDirectSound8\n");
196
197     /* try the COM class factory method of creation with no device specified */
198     rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
199                         &IID_IDirectSound8, (void**)&dso);
200     ok(rc==S_OK,"CoCreateInstance() failed: %s\n",DXGetErrorString8(rc));
201     if (dso)
202         IDirectSound8_test(dso, FALSE, NULL);
203
204     /* try the COM class factory method of creation with default playback
205      *  device specified */
206     rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
207                         &IID_IDirectSound8, (void**)&dso);
208     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound8) failed: %s\n",
209        DXGetErrorString8(rc));
210     if (dso)
211         IDirectSound8_test(dso, FALSE, &DSDEVID_DefaultPlayback);
212
213     /* try the COM class factory method of creation with default voice
214      * playback device specified */
215     rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
216                         &IID_IDirectSound8, (void**)&dso);
217     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound8) failed: %s\n",
218        DXGetErrorString8(rc));
219     if (dso)
220         IDirectSound8_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
221
222     /* try the COM class factory method of creation with a bad
223      * IID specified */
224     rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
225                         &CLSID_DirectSoundPrivate, (void**)&dso);
226     ok(rc==E_NOINTERFACE,
227        "CoCreateInstance(CLSID_DirectSound8,CLSID_DirectSoundPrivate) "
228        "should have failed: %s\n",DXGetErrorString8(rc));
229
230     /* try the COM class factory method of creation with a bad
231      * GUID and IID specified */
232     rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
233                         &IID_IDirectSound8, (void**)&dso);
234     ok(rc==REGDB_E_CLASSNOTREG,
235        "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound8) "
236        "should have failed: %s\n",DXGetErrorString8(rc));
237
238     /* try with no device specified */
239     rc=pDirectSoundCreate8(NULL,&dso,NULL);
240     ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
241        "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
242     if (rc==DS_OK && dso)
243         IDirectSound8_test(dso, TRUE, NULL);
244
245     /* try with default playback device specified */
246     rc=pDirectSoundCreate8(&DSDEVID_DefaultPlayback,&dso,NULL);
247     ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
248        "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
249     if (rc==DS_OK && dso)
250         IDirectSound8_test(dso, TRUE, NULL);
251
252     /* try with default voice playback device specified */
253     rc=pDirectSoundCreate8(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
254     ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
255        "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
256     if (rc==DS_OK && dso)
257         IDirectSound8_test(dso, TRUE, NULL);
258
259     /* try with a bad device specified */
260     rc=pDirectSoundCreate8(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
261     ok(rc==DSERR_NODRIVER,"DirectSoundCreate8(DSDEVID_DefaultVoiceCapture) "
262        "should have failed: %s\n",DXGetErrorString8(rc));
263 }
264
265 static HRESULT test_dsound8(LPGUID lpGuid)
266 {
267     HRESULT rc;
268     LPDIRECTSOUND8 dso=NULL;
269     int ref;
270
271     /* DSOUND: Error: Invalid interface buffer */
272     rc=pDirectSoundCreate8(lpGuid,0,NULL);
273     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate8() should have returned "
274        "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
275
276     /* Create the DirectSound8 object */
277     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
278     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
279        "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
280     if (rc!=DS_OK)
281         return rc;
282
283     /* Try the enumerated device */
284     IDirectSound8_test(dso, TRUE, lpGuid);
285
286     /* Try the COM class factory method of creation with enumerated device */
287     rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
288                         &IID_IDirectSound8, (void**)&dso);
289     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
290        DXGetErrorString8(rc));
291     if (dso)
292         IDirectSound8_test(dso, FALSE, lpGuid);
293
294     /* Create a DirectSound8 object */
295     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
296     ok(rc==DS_OK,"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
297     if (rc==DS_OK) {
298         LPDIRECTSOUND8 dso1=NULL;
299
300         /* Create a second DirectSound8 object */
301         rc=pDirectSoundCreate8(lpGuid,&dso1,NULL);
302         ok(rc==DS_OK,"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
303         if (rc==DS_OK) {
304             /* Release the second DirectSound8 object */
305             ref=IDirectSound8_Release(dso1);
306             ok(ref==0,"IDirectSound8_Release() has %d references, "
307                "should have 0\n",ref);
308             ok(dso!=dso1,"DirectSound8 objects should be unique: "
309                "dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
310         }
311
312         /* Release the first DirectSound8 object */
313         ref=IDirectSound8_Release(dso);
314         ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",
315            ref);
316         if (ref!=0)
317             return DSERR_GENERIC;
318     } else
319         return rc;
320
321     /* Create a DirectSound8 object */
322     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
323     ok(rc==DS_OK,"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
324     if (rc==DS_OK) {
325         LPDIRECTSOUNDBUFFER secondary;
326         DSBUFFERDESC bufdesc;
327         WAVEFORMATEX wfx;
328
329         init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
330         ZeroMemory(&bufdesc, sizeof(bufdesc));
331         bufdesc.dwSize=sizeof(bufdesc);
332         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
333         bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
334                                     wfx.nBlockAlign);
335         bufdesc.lpwfxFormat=&wfx;
336         rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
337         ok(rc==DS_OK && secondary!=NULL,
338            "IDirectSound8_CreateSoundBuffer() failed to create a secondary "
339            "buffer: %s\n",DXGetErrorString8(rc));
340         if (rc==DS_OK && secondary!=NULL) {
341             LPDIRECTSOUND3DBUFFER buffer3d;
342             LPDIRECTSOUNDBUFFER8 buffer8;
343             rc=IDirectSound8_QueryInterface(secondary,
344                                             &IID_IDirectSound3DBuffer,
345                                             (void **)&buffer3d);
346             ok(rc==DS_OK && buffer3d!=NULL,
347                "IDirectSound8_QueryInterface() failed: %s\n",
348                DXGetErrorString8(rc));
349             if (rc==DS_OK && buffer3d!=NULL) {
350                 ref=IDirectSound3DBuffer_AddRef(buffer3d);
351                 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
352                    "should have 2\n",ref);
353             }
354             rc=IDirectSound8_QueryInterface(secondary,
355                                             &IID_IDirectSoundBuffer8,
356                                             (void **)&buffer8);
357             if (rc==DS_OK && buffer8!=NULL) {
358                 ref=IDirectSoundBuffer8_AddRef(buffer8);
359                 ok(ref==3,"IDirectSoundBuffer8_AddRef() has %d references, "
360                    "should have 3\n",ref);
361             }
362             ref=IDirectSoundBuffer_AddRef(secondary);
363             ok(ref==4,"IDirectSoundBuffer_AddRef() has %d references, "
364                "should have 4\n",ref);
365         }
366         /* release with buffer */
367         ref=IDirectSound8_Release(dso);
368         ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",
369            ref);
370         if (ref!=0)
371             return DSERR_GENERIC;
372     } else
373         return rc;
374
375     return DS_OK;
376 }
377
378 static HRESULT test_primary8(LPGUID lpGuid)
379 {
380     HRESULT rc;
381     LPDIRECTSOUND8 dso=NULL;
382     LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
383     DSBUFFERDESC bufdesc;
384     DSCAPS dscaps;
385     WAVEFORMATEX wfx;
386     int ref;
387
388     /* Create the DirectSound object */
389     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
390     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
391        "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
392     if (rc!=DS_OK)
393         return rc;
394
395     /* Get the device capabilities */
396     ZeroMemory(&dscaps, sizeof(dscaps));
397     dscaps.dwSize=sizeof(dscaps);
398     rc=IDirectSound8_GetCaps(dso,&dscaps);
399     ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
400     if (rc!=DS_OK)
401         goto EXIT;
402
403     /* DSOUND: Error: Invalid buffer description pointer */
404     rc=IDirectSound8_CreateSoundBuffer(dso,0,0,NULL);
405     ok(rc==DSERR_INVALIDPARAM,
406        "IDirectSound8_CreateSoundBuffer should have returned "
407        "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
408
409     /* DSOUND: Error: Invalid buffer description pointer */
410     rc=IDirectSound8_CreateSoundBuffer(dso,0,&primary,NULL);
411     ok(rc==DSERR_INVALIDPARAM && primary==0,
412        "IDirectSound8_CreateSoundBuffer() should have returned "
413        "DSERR_INVALIDPARAM, returned: rc=%s,dsbo=0x%lx\n",
414        DXGetErrorString8(rc),(DWORD)primary);
415
416     /* DSOUND: Error: Invalid buffer description pointer */
417     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,0,NULL);
418     ok(rc==DSERR_INVALIDPARAM && primary==0,
419        "IDirectSound8_CreateSoundBuffer() should have failed: rc=%s,"
420        "dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
421
422     ZeroMemory(&bufdesc, sizeof(bufdesc));
423
424     /* DSOUND: Error: Invalid size */
425     /* DSOUND: Error: Invalid buffer description */
426     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
427     ok(rc==DSERR_INVALIDPARAM && primary==0,
428        "IDirectSound8_CreateSoundBuffer() should have failed: rc=%s,"
429        "primary=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
430
431     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
432     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
433     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
434     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
435        DXGetErrorString8(rc));
436     if (rc!=DS_OK)
437         goto EXIT;
438
439     /* Testing the primary buffer */
440     primary=NULL;
441     ZeroMemory(&bufdesc, sizeof(bufdesc));
442     bufdesc.dwSize=sizeof(bufdesc);
443     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
444     bufdesc.lpwfxFormat = &wfx;
445     init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
446     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
447     ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() should have "
448        "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
449     if (rc==DS_OK && primary!=NULL)
450         IDirectSoundBuffer_Release(primary);
451
452     primary=NULL;
453     ZeroMemory(&bufdesc, sizeof(bufdesc));
454     bufdesc.dwSize=sizeof(bufdesc);
455     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
456     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
457     ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
458        "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: "
459        "%s\n",DXGetErrorString8(rc));
460     if (rc==DSERR_CONTROLUNAVAIL)
461         trace("  No Primary\n");
462     else if (rc==DS_OK && primary!=NULL) {
463         LONG vol;
464
465         /* Try to create a second primary buffer */
466         /* DSOUND: Error: The primary buffer already exists.
467          * Any changes made to the buffer description will be ignored. */
468         rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
469         ok(rc==DS_OK && second==primary,
470            "IDirectSound8_CreateSoundBuffer() should have returned original "
471            "primary buffer: %s\n",DXGetErrorString8(rc));
472         ref=IDirectSoundBuffer_Release(second);
473         ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
474            "should have 1\n",ref);
475
476         /* Try to duplicate a primary buffer */
477         /* DSOUND: Error: Can't duplicate primary buffers */
478         rc=IDirectSound8_DuplicateSoundBuffer(dso,primary,&third);
479         /* rc=0x88780032 */
480         ok(rc!=DS_OK,"IDirectSound8_DuplicateSoundBuffer() primary buffer "
481            "should have failed %s\n",DXGetErrorString8(rc));
482
483         rc=IDirectSoundBuffer_GetVolume(primary,&vol);
484         ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
485            DXGetErrorString8(rc));
486
487         if (winetest_interactive) {
488             trace("Playing a 5 seconds reference tone at the current volume.\n");
489             if (rc==DS_OK)
490                 trace("(the current volume is %ld according to DirectSound)\n",
491                       vol);
492             trace("All subsequent tones should be identical to this one.\n");
493             trace("Listen for stutter, changes in pitch, volume, etc.\n");
494         }
495         test_buffer8(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive &&
496                      !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0);
497
498         ref=IDirectSoundBuffer_Release(primary);
499         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
500            "should have 0\n",ref);
501     }
502
503     /* Set the CooperativeLevel back to normal */
504     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
505     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
506     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
507        DXGetErrorString8(rc));
508
509 EXIT:
510     ref=IDirectSound8_Release(dso);
511     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
512     if (ref!=0)
513         return DSERR_GENERIC;
514
515     return rc;
516 }
517
518 /*
519  * Test the primary buffer at different formats while keeping the
520  * secondary buffer at a constant format.
521  */
522 static HRESULT test_primary_secondary8(LPGUID lpGuid)
523 {
524     HRESULT rc;
525     LPDIRECTSOUND8 dso=NULL;
526     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
527     DSBUFFERDESC bufdesc;
528     DSCAPS dscaps;
529     WAVEFORMATEX wfx, wfx2;
530     int ref;
531     unsigned int f;
532
533     /* Create the DirectSound object */
534     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
535     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
536        "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(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=IDirectSound8_GetCaps(dso,&dscaps);
544     ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(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=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
551     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
552        DXGetErrorString8(rc));
553     if (rc!=DS_OK)
554         goto EXIT;
555
556     ZeroMemory(&bufdesc, sizeof(bufdesc));
557     bufdesc.dwSize=sizeof(bufdesc);
558     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
559     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
560     ok(rc==DS_OK && primary!=NULL,
561        "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer "
562        "%s\n",DXGetErrorString8(rc));
563
564     if (rc==DS_OK && primary!=NULL) {
565         for (f=0;f<NB_FORMATS;f++) {
566             /* We must call SetCooperativeLevel to be allowed to call
567              * SetFormat */
568             /* DSOUND: Setting DirectSound cooperative level to
569              * DSSCL_PRIORITY */
570             rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
571             ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
572                DXGetErrorString8(rc));
573             if (rc!=DS_OK)
574                 goto EXIT;
575
576             init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
577                         formats[f][2]);
578             wfx2=wfx;
579             rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
580             ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat() failed: %s\n",
581                DXGetErrorString8(rc));
582
583             /* There is no garantee that SetFormat will actually change the
584              * format to what we asked for. It depends on what the soundcard
585              * supports. So we must re-query the format.
586              */
587             rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
588             ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
589                DXGetErrorString8(rc));
590             if (rc==DS_OK &&
591                 (wfx.wFormatTag!=wfx2.wFormatTag ||
592                  wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
593                  wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
594                  wfx.nChannels!=wfx2.nChannels)) {
595                 trace("Requested primary format tag=0x%04x %ldx%dx%d "
596                       "avg.B/s=%ld align=%d\n",
597                       wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
598                       wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
599                 trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
600                       wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
601                       wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
602             }
603
604             /* Set the CooperativeLevel back to normal */
605             /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
606             rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
607             ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
608                DXGetErrorString8(rc));
609
610             init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
611
612             secondary=NULL;
613             ZeroMemory(&bufdesc, sizeof(bufdesc));
614             bufdesc.dwSize=sizeof(bufdesc);
615             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
616             bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
617                                         wfx.nBlockAlign);
618             bufdesc.lpwfxFormat=&wfx2;
619             if (winetest_interactive) {
620                 trace("  Testing a primary buffer at %ldx%dx%d with a "
621                       "secondary buffer at %ldx%dx%d\n",
622                       wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
623                       wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
624             }
625             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
626             ok(rc==DS_OK && secondary!=NULL,
627                "IDirectSound_CreateSoundBuffer() failed to create a secondary "
628                "buffer %s\n",DXGetErrorString8(rc));
629
630             if (rc==DS_OK && secondary!=NULL) {
631                 test_buffer8(dso,secondary,0,FALSE,0,FALSE,0,
632                              winetest_interactive,1.0,0,NULL,0,0);
633
634                 ref=IDirectSoundBuffer_Release(secondary);
635                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
636                    "should have 0\n",ref);
637             }
638         }
639
640         ref=IDirectSoundBuffer_Release(primary);
641         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
642            "should have 0\n",ref);
643     }
644
645     /* Set the CooperativeLevel back to normal */
646     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
647     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
648     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
649        DXGetErrorString8(rc));
650
651 EXIT:
652     ref=IDirectSound8_Release(dso);
653     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
654     if (ref!=0)
655         return DSERR_GENERIC;
656
657     return rc;
658 }
659
660 static HRESULT test_secondary8(LPGUID lpGuid)
661 {
662     HRESULT rc;
663     LPDIRECTSOUND8 dso=NULL;
664     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
665     DSBUFFERDESC bufdesc;
666     DSCAPS dscaps;
667     WAVEFORMATEX wfx, wfx1;
668     DWORD f;
669     int ref;
670
671     /* Create the DirectSound object */
672     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
673     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
674        "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
675     if (rc!=DS_OK)
676         return rc;
677
678     /* Get the device capabilities */
679     ZeroMemory(&dscaps, sizeof(dscaps));
680     dscaps.dwSize=sizeof(dscaps);
681     rc=IDirectSound8_GetCaps(dso,&dscaps);
682     ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
683     if (rc!=DS_OK)
684         goto EXIT;
685
686     /* We must call SetCooperativeLevel before creating primary buffer */
687     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
688     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
689     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
690        DXGetErrorString8(rc));
691     if (rc!=DS_OK)
692         goto EXIT;
693
694     ZeroMemory(&bufdesc, sizeof(bufdesc));
695     bufdesc.dwSize=sizeof(bufdesc);
696     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
697     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
698     ok(rc==DS_OK && primary!=NULL,
699        "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer "
700        "%s\n",DXGetErrorString8(rc));
701
702     if (rc==DS_OK && primary!=NULL) {
703         rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
704         ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
705            DXGetErrorString8(rc));
706         if (rc!=DS_OK)
707             goto EXIT1;
708
709         for (f=0;f<NB_FORMATS;f++) {
710             init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
711                         formats[f][2]);
712             secondary=NULL;
713             ZeroMemory(&bufdesc, sizeof(bufdesc));
714             bufdesc.dwSize=sizeof(bufdesc);
715             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
716             bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
717                                         wfx.nBlockAlign);
718             rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
719             ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() "
720                "should have returned DSERR_INVALIDPARAM, returned: %s\n",
721                DXGetErrorString8(rc));
722             if (rc==DS_OK && secondary!=NULL)
723                 IDirectSoundBuffer_Release(secondary);
724
725             secondary=NULL;
726             ZeroMemory(&bufdesc, sizeof(bufdesc));
727             bufdesc.dwSize=sizeof(bufdesc);
728             bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
729             bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
730                                         wfx.nBlockAlign);
731             bufdesc.lpwfxFormat=&wfx;
732             if (winetest_interactive) {
733                 trace("  Testing a secondary buffer at %ldx%dx%d "
734                       "with a primary buffer at %ldx%dx%d\n",
735                       wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
736                       wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
737             }
738             rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
739             ok(rc==DS_OK && secondary!=NULL,
740                "IDirectSound8_CreateSoundBuffer() failed to create a secondary "
741                "buffer: %s\n",DXGetErrorString8(rc));
742
743             if (rc==DS_OK && secondary!=NULL) {
744                 test_buffer8(dso,secondary,0,FALSE,0,FALSE,0,
745                              winetest_interactive,1.0,0,NULL,0,0);
746
747                 ref=IDirectSoundBuffer_Release(secondary);
748                 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
749                    "should have 0\n",ref);
750             }
751         }
752 EXIT1:
753         ref=IDirectSoundBuffer_Release(primary);
754         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
755            "should have 0\n",ref);
756     }
757
758     /* Set the CooperativeLevel back to normal */
759     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
760     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
761     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
762        DXGetErrorString8(rc));
763
764 EXIT:
765     ref=IDirectSound8_Release(dso);
766     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
767     if (ref!=0)
768         return DSERR_GENERIC;
769
770     return rc;
771 }
772
773 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
774                                    LPCSTR lpcstrModule, LPVOID lpContext)
775 {
776     HRESULT rc;
777     trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
778     rc = test_dsound8(lpGuid);
779     if (rc == DSERR_NODRIVER)
780         trace("  No Driver\n");
781     else if (rc == DSERR_ALLOCATED)
782         trace("  Already In Use\n");
783     else if (rc == E_FAIL)
784         trace("  No Device\n");
785     else {
786         test_primary8(lpGuid);
787         test_primary_secondary8(lpGuid);
788         test_secondary8(lpGuid);
789     }
790
791     return 1;
792 }
793
794 static void dsound8_tests(void)
795 {
796     HRESULT rc;
797     rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
798     ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
799 }
800
801 const char * get_file_version(const char * file_name)
802 {
803     static char version[32];
804     DWORD size;
805     DWORD handle;
806
807     size = GetFileVersionInfoSizeA("dsound.dll", &handle);
808     if (size) {
809         char * data = HeapAlloc(GetProcessHeap(), 0, size);
810         if (data) {
811             if (GetFileVersionInfoA("dsound.dll", handle, size, data)) {
812                 VS_FIXEDFILEINFO *pFixedVersionInfo;
813                 UINT len;
814                 if (VerQueryValueA(data, "\\", (LPVOID *)&pFixedVersionInfo, &len)) {
815                     sprintf(version, "%ld.%ld.%ld.%ld",
816                             pFixedVersionInfo->dwFileVersionMS >> 16,
817                             pFixedVersionInfo->dwFileVersionMS & 0xffff,
818                             pFixedVersionInfo->dwFileVersionLS >> 16,
819                             pFixedVersionInfo->dwFileVersionLS & 0xffff);
820                 } else
821                     sprintf(version, "not available");
822             } else
823                 sprintf(version, "failed");
824
825             HeapFree(GetProcessHeap(), 0, data);
826         } else
827             sprintf(version, "failed");
828     } else
829         sprintf(version, "not available");
830
831     return version;
832 }
833
834 START_TEST(dsound8)
835 {
836     HMODULE hDsound;
837
838     CoInitialize(NULL);
839
840     hDsound = LoadLibraryA("dsound.dll");
841     if (!hDsound) {
842         trace("dsound.dll not found\n");
843         return;
844     }
845
846     trace("DLL Version: %s\n", get_file_version("dsound.dll"));
847
848     pDirectSoundCreate8 = (void*)GetProcAddress(hDsound, "DirectSoundCreate8");
849     if (!pDirectSoundCreate8) {
850         trace("dsound8 test skipped\n");
851         return;
852     }
853
854     IDirectSound8_tests();
855     dsound8_tests();
856
857     CoUninitialize();
858 }