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