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