mshtml: Implement IHTMLStyle_put_textDecorationUnderline.
[wine] / dlls / dsound / tests / ds3d8.c
1 /*
2  * Tests the panning and 3D functions of DirectSound
3  *
4  * Part of this test involves playing test tones. But this only makes
5  * sense if someone is going to carefully listen to it, and would only
6  * bother everyone else.
7  * So this is only done if the test is being run in interactive mode.
8  *
9  * Copyright (c) 2002-2004 Francois Gouget
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25
26 #include <windows.h>
27
28 #include <math.h>
29
30 #include "wine/test.h"
31 #include "dsound.h"
32 #include "mmreg.h"
33 #include "dsound_test.h"
34
35 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
36 static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL;
37
38 typedef struct {
39     char* wave;
40     DWORD wave_len;
41
42     LPDIRECTSOUNDBUFFER dsbo;
43     LPWAVEFORMATEX wfx;
44     DWORD buffer_size;
45     DWORD written;
46     DWORD played;
47     DWORD offset;
48 } play_state_t;
49
50 static int buffer_refill8(play_state_t* state, DWORD size)
51 {
52     LPVOID ptr1,ptr2;
53     DWORD len1,len2;
54     HRESULT rc;
55
56     if (size>state->wave_len-state->written)
57         size=state->wave_len-state->written;
58
59     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
60                                &ptr1,&len1,&ptr2,&len2,0);
61     ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %08x\n", rc);
62     if (rc!=DS_OK)
63         return -1;
64
65     memcpy(ptr1,state->wave+state->written,len1);
66     state->written+=len1;
67     if (ptr2!=NULL) {
68         memcpy(ptr2,state->wave+state->written,len2);
69         state->written+=len2;
70     }
71     state->offset=state->written % state->buffer_size;
72     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
73     ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %08x\n", rc);
74     if (rc!=DS_OK)
75         return -1;
76     return size;
77 }
78
79 static int buffer_silence8(play_state_t* state, DWORD size)
80 {
81     LPVOID ptr1,ptr2;
82     DWORD len1,len2;
83     HRESULT rc;
84     BYTE s;
85
86     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
87                                &ptr1,&len1,&ptr2,&len2,0);
88     ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %08x\n", rc);
89     if (rc!=DS_OK)
90         return -1;
91
92     s=(state->wfx->wBitsPerSample==8?0x80:0);
93     memset(ptr1,s,len1);
94     if (ptr2!=NULL) {
95         memset(ptr2,s,len2);
96     }
97     state->offset=(state->offset+size) % state->buffer_size;
98     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
99     ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %08x\n", rc);
100     if (rc!=DS_OK)
101         return -1;
102     return size;
103 }
104
105 static int buffer_service8(play_state_t* state)
106 {
107     DWORD last_play_pos,play_pos,buf_free;
108     HRESULT rc;
109
110     rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL);
111     ok(rc==DS_OK,"IDirectSoundBuffer_GetCurrentPosition() failed: %08x\n", rc);
112     if (rc!=DS_OK) {
113         goto STOP;
114     }
115
116     /* Update the amount played */
117     last_play_pos=state->played % state->buffer_size;
118     if (play_pos<last_play_pos)
119         state->played+=state->buffer_size-last_play_pos+play_pos;
120     else
121         state->played+=play_pos-last_play_pos;
122
123     if (winetest_debug > 1)
124         trace("buf size=%d last_play_pos=%d play_pos=%d played=%d / %d\n",
125               state->buffer_size,last_play_pos,play_pos,state->played,
126               state->wave_len);
127
128     if (state->played>state->wave_len)
129     {
130         /* Everything has been played */
131         goto STOP;
132     }
133
134     /* Refill the buffer */
135     if (state->offset<=play_pos)
136         buf_free=play_pos-state->offset;
137     else
138         buf_free=state->buffer_size-state->offset+play_pos;
139
140     if (winetest_debug > 1)
141         trace("offset=%d free=%d written=%d / %d\n",
142               state->offset,buf_free,state->written,state->wave_len);
143     if (buf_free==0)
144         return 1;
145
146     if (state->written<state->wave_len)
147     {
148         int w=buffer_refill8(state,buf_free);
149         if (w==-1)
150             goto STOP;
151         buf_free-=w;
152         if (state->written==state->wave_len && winetest_debug > 1)
153             trace("last sound byte at %d\n",
154                   (state->written % state->buffer_size));
155     }
156
157     if (buf_free>0) {
158         /* Fill with silence */
159         if (winetest_debug > 1)
160             trace("writing %d bytes of silence\n",buf_free);
161         if (buffer_silence8(state,buf_free)==-1)
162             goto STOP;
163     }
164     return 1;
165
166 STOP:
167     if (winetest_debug > 1)
168         trace("stopping playback\n");
169     rc=IDirectSoundBuffer_Stop(state->dsbo);
170     ok(rc==DS_OK,"IDirectSoundBuffer_Stop() failed: %08x\n", rc);
171     return 0;
172 }
173
174 void test_buffer8(LPDIRECTSOUND8 dso, LPDIRECTSOUNDBUFFER * dsbo,
175                   BOOL is_primary, BOOL set_volume, LONG volume,
176                   BOOL set_pan, LONG pan, BOOL play, double duration,
177                   BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener,
178                   BOOL move_listener, BOOL move_sound)
179 {
180     HRESULT rc;
181     DSBCAPS dsbcaps;
182     WAVEFORMATEX wfx,wfx2;
183     DWORD size,status,freq;
184     int ref;
185
186     /* DSOUND: Error: Invalid caps pointer */
187     rc=IDirectSoundBuffer_GetCaps(*dsbo,0);
188     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
189        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
190
191     ZeroMemory(&dsbcaps, sizeof(dsbcaps));
192
193     /* DSOUND: Error: Invalid caps pointer */
194     rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps);
195     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
196        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
197
198     dsbcaps.dwSize=sizeof(dsbcaps);
199     rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps);
200     ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %08x\n", rc);
201     if (rc==DS_OK && winetest_debug > 1) {
202         trace("    Caps: flags=0x%08x size=%d\n",dsbcaps.dwFlags,
203               dsbcaps.dwBufferBytes);
204     }
205
206     /* Query the format size. */
207     size=0;
208     rc=IDirectSoundBuffer_GetFormat(*dsbo,NULL,0,&size);
209     ok(rc==DS_OK && size!=0,"IDirectSoundBuffer_GetFormat() should have "
210        "returned the needed size: rc=%08x size=%d\n",rc,size);
211
212     ok(size == sizeof(WAVEFORMATEX) || size == sizeof(WAVEFORMATEXTENSIBLE),
213        "Expected a correct structure size, got %d\n", size);
214
215     if (size == sizeof(WAVEFORMATEX)) {
216         rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,size,NULL);
217     } else if (size == sizeof(WAVEFORMATEXTENSIBLE)) {
218         WAVEFORMATEXTENSIBLE wfxe;
219         rc=IDirectSoundBuffer_GetFormat(*dsbo,(WAVEFORMATEX*)&wfxe,size,NULL);
220         wfx = wfxe.Format;
221     }
222     ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
223     if (rc==DS_OK && winetest_debug > 1) {
224         trace("    Format: %s tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
225               is_primary ? "Primary" : "Secondary",
226               wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
227               wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
228     }
229
230     /* DSOUND: Error: Invalid frequency buffer */
231     rc=IDirectSoundBuffer_GetFrequency(*dsbo,0);
232     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetFrequency() should have "
233        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
234
235     /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
236     rc=IDirectSoundBuffer_GetFrequency(*dsbo,&freq);
237     ok((rc==DS_OK && !is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
238        (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
239        "IDirectSoundBuffer_GetFrequency() failed: %08x\n",rc);
240     if (rc==DS_OK) {
241         ok(freq==wfx.nSamplesPerSec,"The frequency returned by GetFrequency "
242            "%d does not match the format %d\n",freq,wfx.nSamplesPerSec);
243     }
244
245     /* DSOUND: Error: Invalid status pointer */
246     rc=IDirectSoundBuffer_GetStatus(*dsbo,0);
247     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetStatus() should have "
248        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
249
250     rc=IDirectSoundBuffer_GetStatus(*dsbo,&status);
251     ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %08x\n", rc);
252     ok(status==0,"status=0x%x instead of 0\n",status);
253
254     if (is_primary) {
255         DSBCAPS new_dsbcaps;
256         /* We must call SetCooperativeLevel to be allowed to call SetFormat */
257         /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
258         rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
259         ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) "
260            "failed: %08x\n",rc);
261         if (rc!=DS_OK)
262             return;
263
264         /* DSOUND: Error: Invalid format pointer */
265         rc=IDirectSoundBuffer_SetFormat(*dsbo,0);
266         ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_SetFormat() should have "
267            "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
268
269         init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
270         rc=IDirectSoundBuffer_SetFormat(*dsbo,&wfx2);
271         ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %08x\n",
272            format_string(&wfx2), rc);
273
274         /* There is no guarantee that SetFormat will actually change the
275          * format to what we asked for. It depends on what the soundcard
276          * supports. So we must re-query the format.
277          */
278         rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,sizeof(wfx),NULL);
279         ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
280         if (rc==DS_OK &&
281             (wfx.wFormatTag!=wfx2.wFormatTag ||
282              wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
283              wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
284              wfx.nChannels!=wfx2.nChannels)) {
285             trace("Requested format tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
286                   wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
287                   wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
288             trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
289                   wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
290                   wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
291         }
292
293         ZeroMemory(&new_dsbcaps, sizeof(new_dsbcaps));
294         new_dsbcaps.dwSize = sizeof(new_dsbcaps);
295         rc=IDirectSoundBuffer_GetCaps(*dsbo,&new_dsbcaps);
296         ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %08x\n", rc);
297         if (rc==DS_OK && winetest_debug > 1) {
298             trace("    new Caps: flags=0x%08x size=%d\n",new_dsbcaps.dwFlags,
299                   new_dsbcaps.dwBufferBytes);
300         }
301
302         /* Check for primary buffer size change */
303         ok(new_dsbcaps.dwBufferBytes == dsbcaps.dwBufferBytes,
304            "    buffer size changed after SetFormat() - "
305            "previous size was %u, current size is %u\n",
306            dsbcaps.dwBufferBytes, new_dsbcaps.dwBufferBytes);
307         dsbcaps.dwBufferBytes = new_dsbcaps.dwBufferBytes;
308
309         /* Check for primary buffer flags change */
310         ok(new_dsbcaps.dwFlags == dsbcaps.dwFlags,
311            "    flags changed after SetFormat() - "
312            "previous flags were %08x, current flags are %08x\n",
313            dsbcaps.dwFlags, new_dsbcaps.dwFlags);
314
315         /* Set the CooperativeLevel back to normal */
316         /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
317         rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
318         ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) "
319            "failed: %08x\n",rc);
320     }
321
322     if (play) {
323         play_state_t state;
324         DS3DLISTENER listener_param;
325         LPDIRECTSOUND3DBUFFER buffer=NULL;
326         DS3DBUFFER buffer_param;
327         DWORD start_time,now;
328         LPVOID buffer1;
329         DWORD length1;
330
331         if (winetest_interactive) {
332             trace("    Playing %g second 440Hz tone at %dx%dx%d\n", duration,
333                   wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
334         }
335
336         if (is_primary) {
337             /* We must call SetCooperativeLevel to be allowed to call Lock */
338             /* DSOUND: Setting DirectSound cooperative level to
339              * DSSCL_WRITEPRIMARY */
340             rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),
341                                                  DSSCL_WRITEPRIMARY);
342             ok(rc==DS_OK,
343                "IDirectSound8_SetCooperativeLevel(DSSCL_WRITEPRIMARY) failed: %08x\n",rc);
344             if (rc!=DS_OK)
345                 return;
346         }
347         if (buffer3d) {
348             LPDIRECTSOUNDBUFFER temp_buffer;
349
350             rc=IDirectSoundBuffer_QueryInterface(*dsbo,&IID_IDirectSound3DBuffer,
351                                                  (LPVOID *)&buffer);
352             ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
353             if (rc!=DS_OK)
354                 return;
355
356             /* check the COM interface */
357             rc=IDirectSoundBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer,
358                                                  (LPVOID *)&temp_buffer);
359             ok(rc==DS_OK && temp_buffer!=NULL,
360                "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
361             ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n",
362                temp_buffer,*dsbo);
363             ref=IDirectSoundBuffer_Release(temp_buffer);
364             ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
365                "should have 1\n",ref);
366
367             temp_buffer=NULL;
368             rc=IDirectSound3DBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer,
369                                                    (LPVOID *)&temp_buffer);
370             ok(rc==DS_OK && temp_buffer!=NULL,
371                "IDirectSound3DBuffer_QueryInterface() failed: %08x\n", rc);
372             ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n",
373                temp_buffer,*dsbo);
374             ref=IDirectSoundBuffer_Release(temp_buffer);
375             ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
376                "should have 1\n",ref);
377
378             ref=IDirectSoundBuffer_Release(*dsbo);
379             ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
380                "should have 0\n",ref);
381
382             rc=IDirectSound3DBuffer_QueryInterface(buffer,
383                                                    &IID_IDirectSoundBuffer,
384                                                    (LPVOID *)dsbo);
385             ok(rc==DS_OK && *dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface() "
386                "failed: %08x\n",rc);
387
388             /* DSOUND: Error: Invalid buffer */
389             rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
390             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
391                "failed: %08x\n",rc);
392
393             ZeroMemory(&buffer_param, sizeof(buffer_param));
394
395             /* DSOUND: Error: Invalid buffer */
396             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
397             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
398                "failed: %08x\n",rc);
399
400             buffer_param.dwSize=sizeof(buffer_param);
401             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
402             ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters() failed: %08x\n", rc);
403         }
404         if (set_volume) {
405             if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
406                 LONG val;
407                 rc=IDirectSoundBuffer_GetVolume(*dsbo,&val);
408                 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %08x\n", rc);
409
410                 rc=IDirectSoundBuffer_SetVolume(*dsbo,volume);
411                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume() failed: %08x\n", rc);
412             } else {
413                 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
414                 rc=IDirectSoundBuffer_GetVolume(*dsbo,&volume);
415                 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetVolume() "
416                    "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc);
417             }
418         }
419
420         if (set_pan) {
421             if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
422                 LONG val;
423                 rc=IDirectSoundBuffer_GetPan(*dsbo,&val);
424                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan() failed: %08x\n", rc);
425
426                 rc=IDirectSoundBuffer_SetPan(*dsbo,pan);
427                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan() failed: %08x\n", rc);
428             } else {
429                 /* DSOUND: Error: Buffer does not have CTRLPAN */
430                 rc=IDirectSoundBuffer_GetPan(*dsbo,&pan);
431                 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetPan() "
432                    "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc);
433             }
434         }
435
436         /* try an offset past the end of the buffer */
437         rc = IDirectSoundBuffer_Lock(*dsbo, dsbcaps.dwBufferBytes, 0, &buffer1,
438                                       &length1, NULL, NULL,
439                                       DSBLOCK_ENTIREBUFFER);
440         ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have "
441            "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
442
443         /* try a size larger than the buffer */
444         rc = IDirectSoundBuffer_Lock(*dsbo, 0, dsbcaps.dwBufferBytes + 1,
445                                      &buffer1, &length1, NULL, NULL,
446                                      DSBLOCK_FROMWRITECURSOR);
447         ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have "
448            "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
449
450         state.wave=wave_generate_la(&wfx,duration,&state.wave_len);
451
452         state.dsbo=*dsbo;
453         state.wfx=&wfx;
454         state.buffer_size=dsbcaps.dwBufferBytes;
455         state.played=state.written=state.offset=0;
456         buffer_refill8(&state,state.buffer_size);
457
458         rc=IDirectSoundBuffer_Play(*dsbo,0,0,DSBPLAY_LOOPING);
459         ok(rc==DS_OK,"IDirectSoundBuffer_Play() failed: %08x\n", rc);
460
461         rc=IDirectSoundBuffer_GetStatus(*dsbo,&status);
462         ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %08x\n", rc);
463         ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
464            "GetStatus: bad status: %x\n",status);
465
466         if (listener) {
467             ZeroMemory(&listener_param,sizeof(listener_param));
468             listener_param.dwSize=sizeof(listener_param);
469             rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
470             ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
471                "failed: %08x\n",rc);
472             if (move_listener) {
473                 listener_param.vPosition.x = -5.0f;
474                 listener_param.vVelocity.x = (float)(10.0/duration);
475             }
476             rc=IDirectSound3DListener_SetAllParameters(listener,
477                                                        &listener_param,
478                                                        DS3D_IMMEDIATE);
479             ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08x\n", rc);
480         }
481         if (buffer3d) {
482             if (move_sound) {
483                 buffer_param.vPosition.x = 100.0f;
484                 buffer_param.vVelocity.x = (float)(-200.0/duration);
485             }
486             buffer_param.flMinDistance = 10;
487             rc=IDirectSound3DBuffer_SetAllParameters(buffer,&buffer_param,
488                                                      DS3D_IMMEDIATE);
489             ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %08x\n", rc);
490         }
491
492         start_time=GetTickCount();
493         while (buffer_service8(&state)) {
494             WaitForSingleObject(GetCurrentProcess(),TIME_SLICE);
495             now=GetTickCount();
496             if (listener && move_listener) {
497                 listener_param.vPosition.x = (float)(-5.0+10.0*(now-start_time)/1000/duration);
498                 if (winetest_debug>2)
499                     trace("listener position=%g\n",listener_param.vPosition.x);
500                 rc=IDirectSound3DListener_SetPosition(listener,
501                     listener_param.vPosition.x,listener_param.vPosition.y,
502                     listener_param.vPosition.z,DS3D_IMMEDIATE);
503                 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08x\n",rc);
504             }
505             if (buffer3d && move_sound) {
506                 buffer_param.vPosition.x = (float)(100-200.0*(now-start_time)/1000/duration);
507                 if (winetest_debug>2)
508                     trace("sound position=%g\n",buffer_param.vPosition.x);
509                 rc=IDirectSound3DBuffer_SetPosition(buffer,
510                     buffer_param.vPosition.x,buffer_param.vPosition.y,
511                     buffer_param.vPosition.z,DS3D_IMMEDIATE);
512                 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %08x\n", rc);
513             }
514         }
515         /* Check the sound duration was within 10% of the expected value */
516         now=GetTickCount();
517         ok(fabs(1000*duration-now+start_time)<=100*duration,
518            "The sound played for %d ms instead of %g ms\n",
519            now-start_time,1000*duration);
520
521         free(state.wave);
522         if (is_primary) {
523             /* Set the CooperativeLevel back to normal */
524             /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
525             rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
526             ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) "
527                "failed: %08x\n",rc);
528         }
529         if (buffer3d) {
530             ref=IDirectSound3DBuffer_Release(buffer);
531             ok(ref==0,"IDirectSound3DBuffer_Release() has %d references, "
532                "should have 0\n",ref);
533         }
534     }
535 }
536
537 static HRESULT test_secondary8(LPGUID lpGuid, int play,
538                                int has_3d, int has_3dbuffer,
539                                int has_listener, int has_duplicate,
540                                int move_listener, int move_sound)
541 {
542     HRESULT rc;
543     LPDIRECTSOUND8 dso=NULL;
544     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
545     LPDIRECTSOUND3DLISTENER listener=NULL;
546     DSBUFFERDESC bufdesc;
547     WAVEFORMATEX wfx, wfx1;
548     int ref;
549
550     /* Create the DirectSound object */
551     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
552     ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
553     if (rc!=DS_OK)
554         return rc;
555
556     /* We must call SetCooperativeLevel before creating primary buffer */
557     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
558     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
559     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
560     if (rc!=DS_OK)
561         goto EXIT;
562
563     ZeroMemory(&bufdesc, sizeof(bufdesc));
564     bufdesc.dwSize=sizeof(bufdesc);
565     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
566     if (has_3d)
567         bufdesc.dwFlags|=DSBCAPS_CTRL3D;
568     else
569         bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
570     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
571     ok((rc==DS_OK && primary!=NULL) || (rc == DSERR_CONTROLUNAVAIL),
572        "IDirectSound8_CreateSoundBuffer() failed to create a %sprimary buffer: %08x\n",has_3d?"3D ":"", rc);
573     if (rc == DSERR_CONTROLUNAVAIL)
574         trace("  No Primary\n");
575     else if (rc==DS_OK && primary!=NULL) {
576         rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
577         ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
578         if (rc!=DS_OK)
579             goto EXIT1;
580
581         if (has_listener) {
582             rc=IDirectSoundBuffer_QueryInterface(primary,
583                                                  &IID_IDirectSound3DListener,
584                                                  (void **)&listener);
585             ok(rc==DS_OK && listener!=NULL,
586                "IDirectSoundBuffer_QueryInterface() failed to get a 3D "
587                "listener %08x\n",rc);
588             ref=IDirectSoundBuffer_Release(primary);
589             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
590                "should have 0\n",ref);
591             if (rc==DS_OK && listener!=NULL) {
592                 DS3DLISTENER listener_param;
593                 ZeroMemory(&listener_param,sizeof(listener_param));
594                 /* DSOUND: Error: Invalid buffer */
595                 rc=IDirectSound3DListener_GetAllParameters(listener,0);
596                 ok(rc==DSERR_INVALIDPARAM,
597                    "IDirectSound3dListener_GetAllParameters() should have "
598                    "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
599
600                 /* DSOUND: Error: Invalid buffer */
601                 rc=IDirectSound3DListener_GetAllParameters(listener,
602                                                            &listener_param);
603                 ok(rc==DSERR_INVALIDPARAM,
604                    "IDirectSound3dListener_GetAllParameters() should have "
605                    "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
606
607                 listener_param.dwSize=sizeof(listener_param);
608                 rc=IDirectSound3DListener_GetAllParameters(listener,
609                                                            &listener_param);
610                 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
611                    "failed: %08x\n",rc);
612             } else {
613                 ok(listener==NULL, "IDirectSoundBuffer_QueryInterface() "
614                    "failed but returned a listener anyway\n");
615                 ok(rc!=DS_OK, "IDirectSoundBuffer_QueryInterface() succeeded "
616                    "but returned a NULL listener\n");
617                 if (listener) {
618                     ref=IDirectSound3DListener_Release(listener);
619                     ok(ref==0,"IDirectSound3dListener_Release() listener has "
620                        "%d references, should have 0\n",ref);
621                 }
622                 goto EXIT2;
623             }
624         }
625
626         init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2);
627         secondary=NULL;
628         ZeroMemory(&bufdesc, sizeof(bufdesc));
629         bufdesc.dwSize=sizeof(bufdesc);
630         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
631         if (has_3d)
632             bufdesc.dwFlags|=DSBCAPS_CTRL3D;
633         else
634             bufdesc.dwFlags|=
635                 (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
636         bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
637                                     wfx.nBlockAlign);
638         bufdesc.lpwfxFormat=&wfx;
639         if (has_3d) {
640             /* a stereo 3D buffer should fail */
641             rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
642             ok(rc==DSERR_INVALIDPARAM,
643                "IDirectSound8_CreateSoundBuffer(secondary) should have "
644                "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
645             if (secondary)
646                 ref=IDirectSoundBuffer_Release(secondary);
647             init_format(&wfx,WAVE_FORMAT_PCM,22050,16,1);
648         }
649
650         if (winetest_interactive) {
651             trace("  Testing a %s%ssecondary buffer %s%s%s%sat %dx%dx%d "
652                   "with a primary buffer at %dx%dx%d\n",
653                   has_3dbuffer?"3D ":"",
654                   has_duplicate?"duplicated ":"",
655                   listener!=NULL||move_sound?"with ":"",
656                   move_listener?"moving ":"",
657                   listener!=NULL?"listener ":"",
658                   listener&&move_sound?"and moving sound ":move_sound?
659                   "moving sound ":"",
660                   wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
661                   wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
662         }
663         rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
664         ok(rc==DS_OK && secondary!=NULL,"IDirectSound8_CreateSoundBuffer() "
665            "failed to create a %s%ssecondary buffer %s%s%s%sat %dx%dx%d (%s): %08x\n",
666            has_3dbuffer?"3D ":"", has_duplicate?"duplicated ":"",
667            listener!=NULL||move_sound?"with ":"", move_listener?"moving ":"",
668            listener!=NULL?"listener ":"",
669            listener&&move_sound?"and moving sound ":move_sound?
670            "moving sound ":"",
671            wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
672            getDSBCAPS(bufdesc.dwFlags),rc);
673         if (rc==DS_OK && secondary!=NULL) {
674             if (!has_3d) {
675                 LONG refvol,vol,refpan,pan;
676
677                 /* Check the initial secondary buffer's volume and pan */
678                 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
679                 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(secondary) failed: %08x\n",rc);
680                 ok(vol==0,"wrong volume for a new secondary buffer: %d\n",vol);
681                 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
682                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(secondary) failed: %08x\n",rc);
683                 ok(pan==0,"wrong pan for a new secondary buffer: %d\n",pan);
684
685                 /* Check that changing the secondary buffer's volume and pan
686                  * does not impact the primary buffer's volume and pan
687                  */
688                 rc=IDirectSoundBuffer_GetVolume(primary,&refvol);
689                 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(primary) failed: %08x\n",rc);
690                 rc=IDirectSoundBuffer_GetPan(primary,&refpan);
691                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %08x\n",rc);
692
693                 rc=IDirectSoundBuffer_SetVolume(secondary,-1000);
694                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
695                 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
696                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
697                 ok(vol==-1000,"secondary: wrong volume %d instead of -1000\n",
698                    vol);
699                 rc=IDirectSoundBuffer_SetPan(secondary,-1000);
700                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc);
701                 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
702                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc);
703                 ok(pan==-1000,"secondary: wrong pan %d instead of -1000\n",
704                    pan);
705
706                 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
707                 ok(rc==DS_OK,"IDirectSoundBuffer_`GetVolume(primary) failed: i%08x\n",rc);
708                 ok(vol==refvol,"The primary volume changed from %d to %d\n",
709                    refvol,vol);
710                 rc=IDirectSoundBuffer_GetPan(primary,&pan);
711                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %08x\n",rc);
712                 ok(pan==refpan,"The primary pan changed from %d to %d\n",
713                    refpan,pan);
714
715                 rc=IDirectSoundBuffer_SetVolume(secondary,0);
716                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
717                 rc=IDirectSoundBuffer_SetPan(secondary,0);
718                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc);
719             }
720             if (has_duplicate) {
721                 LPDIRECTSOUNDBUFFER duplicated=NULL;
722
723                 /* DSOUND: Error: Invalid source buffer */
724                 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,0);
725                 ok(rc==DSERR_INVALIDPARAM,
726                    "IDirectSound8_DuplicateSoundBuffer() should have returned "
727                    "DSERR_INVALIDPARAM, returned: %08x\n",rc);
728
729                 /* DSOUND: Error: Invalid dest buffer */
730                 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,0);
731                 ok(rc==DSERR_INVALIDPARAM,
732                    "IDirectSound8_DuplicateSoundBuffer() should have returned "
733                    "DSERR_INVALIDPARAM, returned: %08x\n",rc);
734
735                 /* DSOUND: Error: Invalid source buffer */
736                 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,&duplicated);
737                 ok(rc==DSERR_INVALIDPARAM,
738                    "IDirectSound8_DuplicateSoundBuffer() should have returned "
739                    "DSERR_INVALIDPARAM, returned: %08x\n",rc);
740
741                 duplicated=NULL;
742                 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,
743                                                       &duplicated);
744                 ok(rc==DS_OK && duplicated!=NULL,
745                    "IDirectSound8_DuplicateSoundBuffer() failed to duplicate "
746                    "a secondary buffer: %08x\n",rc);
747
748                 if (rc==DS_OK && duplicated!=NULL) {
749                     ref=IDirectSoundBuffer_Release(secondary);
750                     ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d "
751                        "references, should have 0\n",ref);
752                     secondary=duplicated;
753                 }
754             }
755
756             if (rc==DS_OK && secondary!=NULL) {
757                 double duration;
758                 duration=(move_listener || move_sound?4.0:1.0);
759                 test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0,
760                              winetest_interactive,duration,has_3dbuffer,
761                              listener,move_listener,move_sound);
762                 ref=IDirectSoundBuffer_Release(secondary);
763                 ok(ref==0,"IDirectSoundBuffer_Release() %s has %d references, "
764                    "should have 0\n",has_duplicate?"duplicated":"secondary",
765                    ref);
766             }
767         }
768 EXIT1:
769         if (has_listener) {
770             ref=IDirectSound3DListener_Release(listener);
771             ok(ref==0,"IDirectSound3dListener_Release() listener has %d "
772                "references, should have 0\n",ref);
773         } else {
774             ref=IDirectSoundBuffer_Release(primary);
775             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
776                "should have 0\n",ref);
777         }
778     } else {
779         ok(primary==NULL,"IDirectSound8_CreateSoundBuffer(primary) failed "
780            "but primary created anyway\n");
781         ok(rc!=DS_OK,"IDirectSound8_CreateSoundBuffer(primary) succeeded "
782            "but primary not created\n");
783         if (primary) {
784             ref=IDirectSoundBuffer_Release(primary);
785             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
786                "should have 0\n",ref);
787         }
788     }
789 EXIT2:
790     /* Set the CooperativeLevel back to normal */
791     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
792     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
793     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc);
794
795 EXIT:
796     ref=IDirectSound8_Release(dso);
797     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
798     if (ref!=0)
799         return DSERR_GENERIC;
800
801     return rc;
802 }
803
804 static HRESULT test_for_driver8(LPGUID lpGuid)
805 {
806     HRESULT rc;
807     LPDIRECTSOUND8 dso=NULL;
808     int ref;
809
810     /* Create the DirectSound object */
811     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
812     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
813        "DirectSoundCreate8() failed: %08x\n",rc);
814     if (rc!=DS_OK)
815         return rc;
816
817     ref=IDirectSound8_Release(dso);
818     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
819     if (ref!=0)
820         return DSERR_GENERIC;
821
822     return rc;
823 }
824
825 static HRESULT test_primary8(LPGUID lpGuid)
826 {
827     HRESULT rc;
828     LPDIRECTSOUND8 dso=NULL;
829     LPDIRECTSOUNDBUFFER primary=NULL;
830     DSBUFFERDESC bufdesc;
831     DSCAPS dscaps;
832     int ref, i;
833
834     /* Create the DirectSound object */
835     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
836     ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
837     if (rc!=DS_OK)
838         return rc;
839
840     /* Get the device capabilities */
841     ZeroMemory(&dscaps, sizeof(dscaps));
842     dscaps.dwSize=sizeof(dscaps);
843     rc=IDirectSound8_GetCaps(dso,&dscaps);
844     ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
845     if (rc!=DS_OK)
846         goto EXIT;
847
848     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
849     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
850     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
851     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
852     if (rc!=DS_OK)
853         goto EXIT;
854
855     /* Testing the primary buffer */
856     primary=NULL;
857     ZeroMemory(&bufdesc, sizeof(bufdesc));
858     bufdesc.dwSize=sizeof(bufdesc);
859     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
860     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
861     ok((rc==DS_OK && primary!=NULL) || (rc == DSERR_CONTROLUNAVAIL),
862        "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: %08x\n",rc);
863     if (rc == DSERR_CONTROLUNAVAIL)
864         trace("  No Primary\n");
865     else if (rc==DS_OK && primary!=NULL) {
866         test_buffer8(dso,&primary,1,TRUE,0,TRUE,0,winetest_interactive &&
867                      !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
868         if (winetest_interactive) {
869             LONG volume,pan;
870
871             volume = DSBVOLUME_MAX;
872             for (i = 0; i < 6; i++) {
873                 test_buffer8(dso,&primary,1,TRUE,volume,TRUE,0,
874                              winetest_interactive &&
875                              !(dscaps.dwFlags & DSCAPS_EMULDRIVER),
876                              1.0,0,NULL,0,0);
877                 volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40);
878             }
879
880             pan = DSBPAN_LEFT;
881             for (i = 0; i < 7; i++) {
882                 test_buffer8(dso,&primary,1,TRUE,0,TRUE,pan,
883                              winetest_interactive &&
884                              !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
885                 pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6);
886             }
887         }
888         ref=IDirectSoundBuffer_Release(primary);
889         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
890            "should have 0\n",ref);
891     }
892
893     /* Set the CooperativeLevel back to normal */
894     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
895     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
896     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc);
897
898 EXIT:
899     ref=IDirectSound8_Release(dso);
900     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
901     if (ref!=0)
902         return DSERR_GENERIC;
903
904     return rc;
905 }
906
907 static HRESULT test_primary_3d8(LPGUID lpGuid)
908 {
909     HRESULT rc;
910     LPDIRECTSOUND8 dso=NULL;
911     LPDIRECTSOUNDBUFFER primary=NULL;
912     DSBUFFERDESC bufdesc;
913     DSCAPS dscaps;
914     int ref;
915
916     /* Create the DirectSound object */
917     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
918     ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
919     if (rc!=DS_OK)
920         return rc;
921
922     /* Get the device capabilities */
923     ZeroMemory(&dscaps, sizeof(dscaps));
924     dscaps.dwSize=sizeof(dscaps);
925     rc=IDirectSound8_GetCaps(dso,&dscaps);
926     ok(rc==DS_OK,"IDirectSound8_GetCaps failed: %08x\n",rc);
927     if (rc!=DS_OK)
928         goto EXIT;
929
930     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
931     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
932     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
933     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
934     if (rc!=DS_OK)
935         goto EXIT;
936
937     primary=NULL;
938     ZeroMemory(&bufdesc, sizeof(bufdesc));
939     bufdesc.dwSize=sizeof(bufdesc);
940     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
941     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
942     ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() failed "
943        "to create a primary buffer: %08x\n",rc);
944     if (rc==DS_OK && primary!=NULL) {
945         ref=IDirectSoundBuffer_Release(primary);
946         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
947            "should have 0\n",ref);
948         primary=NULL;
949         ZeroMemory(&bufdesc, sizeof(bufdesc));
950         bufdesc.dwSize=sizeof(bufdesc);
951         bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
952         rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
953         ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() "
954            "failed to create a 3D primary buffer: %08x\n",rc);
955         if (rc==DS_OK && primary!=NULL) {
956             test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,
957                          winetest_interactive &&
958                          !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
959             ref=IDirectSoundBuffer_Release(primary);
960             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
961                "should have 0\n",ref);
962         }
963     }
964     /* Set the CooperativeLevel back to normal */
965     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
966     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
967     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc);
968
969 EXIT:
970     ref=IDirectSound8_Release(dso);
971     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
972     if (ref!=0)
973         return DSERR_GENERIC;
974
975     return rc;
976 }
977
978 static HRESULT test_primary_3d_with_listener8(LPGUID lpGuid)
979 {
980     HRESULT rc;
981     LPDIRECTSOUND8 dso=NULL;
982     LPDIRECTSOUNDBUFFER primary=NULL;
983     DSBUFFERDESC bufdesc;
984     DSCAPS dscaps;
985     int ref;
986
987     /* Create the DirectSound object */
988     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
989     ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
990     if (rc!=DS_OK)
991         return rc;
992
993     /* Get the device capabilities */
994     ZeroMemory(&dscaps, sizeof(dscaps));
995     dscaps.dwSize=sizeof(dscaps);
996     rc=IDirectSound8_GetCaps(dso,&dscaps);
997     ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
998     if (rc!=DS_OK)
999         goto EXIT;
1000
1001     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
1002     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1003     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
1004     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
1005     if (rc!=DS_OK)
1006         goto EXIT;
1007     primary=NULL;
1008     ZeroMemory(&bufdesc, sizeof(bufdesc));
1009     bufdesc.dwSize=sizeof(bufdesc);
1010     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
1011     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
1012     ok(rc==DS_OK && primary!=NULL,"IDirectSound8_CreateSoundBuffer() failed "
1013        "to create a 3D primary buffer %08x\n",rc);
1014     if (rc==DS_OK && primary!=NULL) {
1015         LPDIRECTSOUND3DLISTENER listener=NULL;
1016         rc=IDirectSoundBuffer_QueryInterface(primary,
1017                                              &IID_IDirectSound3DListener,
1018                                              (void **)&listener);
1019         ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface() "
1020            "failed to get a 3D listener: %08x\n",rc);
1021         if (rc==DS_OK && listener!=NULL) {
1022             LPDIRECTSOUNDBUFFER temp_buffer=NULL;
1023
1024             /* Checking the COM interface */
1025             rc=IDirectSoundBuffer_QueryInterface(primary,
1026                                                  &IID_IDirectSoundBuffer,
1027                                                  (LPVOID *)&temp_buffer);
1028             ok(rc==DS_OK && temp_buffer!=NULL,
1029                "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
1030             ok(temp_buffer==primary,"COM interface broken: %p != %p\n",temp_buffer,primary);
1031             if (rc==DS_OK && temp_buffer!=NULL) {
1032                 ref=IDirectSoundBuffer_Release(temp_buffer);
1033                 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
1034                    "should have 1\n",ref);
1035
1036                 temp_buffer=NULL;
1037                 rc=IDirectSound3DListener_QueryInterface(listener,
1038                     &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
1039                 ok(rc==DS_OK && temp_buffer!=NULL,
1040                    "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
1041                 ok(temp_buffer==primary,"COM interface broken: %p != %p\n",temp_buffer,primary);
1042                 ref=IDirectSoundBuffer_Release(temp_buffer);
1043                 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
1044                    "should have 1\n",ref);
1045
1046                 /* Testing the buffer */
1047                 test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,
1048                              winetest_interactive &&
1049                              !(dscaps.dwFlags & DSCAPS_EMULDRIVER),
1050                              1.0,0,listener,0,0);
1051             }
1052
1053             /* Testing the reference counting */
1054             ref=IDirectSound3DListener_Release(listener);
1055             ok(ref==0,"IDirectSound3DListener_Release() listener has %d "
1056                "references, should have 0\n",ref);
1057         }
1058
1059         /* Testing the reference counting */
1060         ref=IDirectSoundBuffer_Release(primary);
1061         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
1062            "should have 0\n",ref);
1063     }
1064
1065 EXIT:
1066     ref=IDirectSound8_Release(dso);
1067     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
1068     if (ref!=0)
1069 return DSERR_GENERIC;
1070
1071     return rc;
1072 }
1073
1074 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1075                                    LPCSTR lpcstrModule, LPVOID lpContext)
1076 {
1077     HRESULT rc;
1078     trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
1079
1080     rc = test_for_driver8(lpGuid);
1081     if (rc == DSERR_NODRIVER) {
1082         trace("  No Driver\n");
1083         return 1;
1084     } else if (rc == DSERR_ALLOCATED) {
1085         trace("  Already In Use\n");
1086         return 1;
1087     } else if (rc == E_FAIL) {
1088         trace("  No Device\n");
1089         return 1;
1090     }
1091
1092     trace("  Testing the primary buffer\n");
1093     test_primary8(lpGuid);
1094
1095     trace("  Testing 3D primary buffer\n");
1096     test_primary_3d8(lpGuid);
1097
1098     trace("  Testing 3D primary buffer with listener\n");
1099     test_primary_3d_with_listener8(lpGuid);
1100
1101     /* Testing secondary buffers */
1102     test_secondary8(lpGuid,winetest_interactive,0,0,0,0,0,0);
1103     test_secondary8(lpGuid,winetest_interactive,0,0,0,1,0,0);
1104
1105     /* Testing 3D secondary buffers */
1106     test_secondary8(lpGuid,winetest_interactive,1,0,0,0,0,0);
1107     test_secondary8(lpGuid,winetest_interactive,1,1,0,0,0,0);
1108     test_secondary8(lpGuid,winetest_interactive,1,1,0,1,0,0);
1109     test_secondary8(lpGuid,winetest_interactive,1,0,1,0,0,0);
1110     test_secondary8(lpGuid,winetest_interactive,1,0,1,1,0,0);
1111     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,0,0);
1112     test_secondary8(lpGuid,winetest_interactive,1,1,1,1,0,0);
1113     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,1,0);
1114     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,0,1);
1115     test_secondary8(lpGuid,winetest_interactive,1,1,1,0,1,1);
1116
1117     return 1;
1118 }
1119
1120 static void ds3d8_tests(void)
1121 {
1122     HRESULT rc;
1123     rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
1124     ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %08x\n",rc);
1125 }
1126
1127 START_TEST(ds3d8)
1128 {
1129     HMODULE hDsound;
1130
1131     CoInitialize(NULL);
1132
1133     hDsound = LoadLibrary("dsound.dll");
1134     if (hDsound)
1135     {
1136         trace("DLL Version: %s\n", get_file_version("dsound.dll"));
1137
1138         pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
1139             "DirectSoundEnumerateA");
1140         pDirectSoundCreate8 = (void*)GetProcAddress(hDsound,
1141             "DirectSoundCreate8");
1142         if (pDirectSoundCreate8)
1143             ds3d8_tests();
1144         else
1145             skip("ds3d8 test skipped\n");
1146
1147         FreeLibrary(hDsound);
1148     }
1149     else
1150         skip("dsound.dll not found!\n");
1151
1152     CoUninitialize();
1153 }