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