Implement A->W call for GetNamedSecurityInfo.
[wine] / dlls / dsound / tests / ds3d.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
28 #include <windows.h>
29
30 #include <math.h>
31 #include <stdlib.h>
32
33 #include "wine/test.h"
34 #include "windef.h"
35 #include "wingdi.h"
36 #include "dsound.h"
37 #include "dxerr8.h"
38
39 #include "dsound_test.h"
40
41 #define PI 3.14159265358979323846
42 char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
43 {
44     int i;
45     int nb_samples;
46     char* buf;
47     char* b;
48
49     nb_samples=(int)(duration*wfx->nSamplesPerSec);
50     *size=nb_samples*wfx->nBlockAlign;
51     b=buf=malloc(*size);
52     for (i=0;i<nb_samples;i++) {
53         double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
54         if (wfx->wBitsPerSample==8) {
55             unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
56             *b++=sample;
57             if (wfx->nChannels==2)
58                 *b++=sample;
59         } else {
60             signed short sample=(signed short)((double)32767.5*y-0.5);
61             b[0]=sample & 0xff;
62             b[1]=sample >> 8;
63             b+=2;
64             if (wfx->nChannels==2) {
65                 b[0]=sample & 0xff;
66                 b[1]=sample >> 8;
67                 b+=2;
68             }
69         }
70     }
71     return buf;
72 }
73
74 HWND get_hwnd()
75 {
76     HWND hwnd=GetForegroundWindow();
77     if (!hwnd)
78         hwnd=GetDesktopWindow();
79     return hwnd;
80 }
81
82 void init_format(WAVEFORMATEX* wfx, int format, int rate, int depth, int channels)
83 {
84     wfx->wFormatTag=format;
85     wfx->nChannels=channels;
86     wfx->wBitsPerSample=depth;
87     wfx->nSamplesPerSec=rate;
88     wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
89     /* FIXME: Shouldn't this test be if (format!=WAVE_FORMAT_PCM) */
90     if (wfx->nBlockAlign==0)
91     {
92         /* align compressed formats to byte boundary */
93         wfx->nBlockAlign=1;
94     }
95     wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign;
96     wfx->cbSize=0;
97 }
98
99 typedef struct {
100     char* wave;
101     DWORD wave_len;
102
103     LPDIRECTSOUNDBUFFER dsbo;
104     LPWAVEFORMATEX wfx;
105     DWORD buffer_size;
106     DWORD written;
107     DWORD played;
108     DWORD offset;
109 } play_state_t;
110
111 static int buffer_refill(play_state_t* state, DWORD size)
112 {
113     LPVOID ptr1,ptr2;
114     DWORD len1,len2;
115     HRESULT rc;
116
117     if (size>state->wave_len-state->written)
118         size=state->wave_len-state->written;
119
120     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
121                                &ptr1,&len1,&ptr2,&len2,0);
122     ok(rc==DS_OK,"Lock: 0x%lx\n",rc);
123     if (rc!=DS_OK)
124         return -1;
125
126     memcpy(ptr1,state->wave+state->written,len1);
127     state->written+=len1;
128     if (ptr2!=NULL) {
129         memcpy(ptr2,state->wave+state->written,len2);
130         state->written+=len2;
131     }
132     state->offset=state->written % state->buffer_size;
133     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
134     ok(rc==DS_OK,"Unlock: 0x%lx\n",rc);
135     if (rc!=DS_OK)
136         return -1;
137     return size;
138 }
139
140 static int buffer_silence(play_state_t* state, DWORD size)
141 {
142     LPVOID ptr1,ptr2;
143     DWORD len1,len2;
144     HRESULT rc;
145     BYTE s;
146
147     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
148                                &ptr1,&len1,&ptr2,&len2,0);
149     ok(rc==DS_OK,"Lock: 0x%lx\n",rc);
150     if (rc!=DS_OK)
151         return -1;
152
153     s=(state->wfx->wBitsPerSample==8?0x80:0);
154     memset(ptr1,s,len1);
155     if (ptr2!=NULL) {
156         memset(ptr2,s,len2);
157     }
158     state->offset=(state->offset+size) % state->buffer_size;
159     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
160     ok(rc==DS_OK,"Unlock: 0x%lx\n",rc);
161     if (rc!=DS_OK)
162         return -1;
163     return size;
164 }
165
166 static int buffer_service(play_state_t* state)
167 {
168     DWORD last_play_pos,play_pos,buf_free;
169     HRESULT rc;
170
171     rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL);
172     ok(rc==DS_OK,"GetCurrentPosition: %lx\n",rc);
173     if (rc!=DS_OK) {
174         goto STOP;
175     }
176
177     /* Update the amount played */
178     last_play_pos=state->played % state->buffer_size;
179     if (play_pos<last_play_pos)
180         state->played+=state->buffer_size-last_play_pos+play_pos;
181     else
182         state->played+=play_pos-last_play_pos;
183
184     if (winetest_debug > 1)
185         trace("buf size=%ld last_play_pos=%ld play_pos=%ld played=%ld / %ld\n",
186               state->buffer_size,last_play_pos,play_pos,state->played,state->wave_len);
187
188     if (state->played>state->wave_len)
189     {
190         /* Everything has been played */
191         goto STOP;
192     }
193
194     /* Refill the buffer */
195     if (state->offset<=play_pos)
196         buf_free=play_pos-state->offset;
197     else
198         buf_free=state->buffer_size-state->offset+play_pos;
199
200     if (winetest_debug > 1)
201         trace("offset=%ld free=%ld written=%ld / %ld\n",
202               state->offset,buf_free,state->written,state->wave_len);
203     if (buf_free==0)
204         return 1;
205
206     if (state->written<state->wave_len)
207     {
208         int w=buffer_refill(state,buf_free);
209         if (w==-1)
210             goto STOP;
211         buf_free-=w;
212         if (state->written==state->wave_len && winetest_debug > 1)
213             trace("last sound byte at %ld\n",
214                   (state->written % state->buffer_size));
215     }
216
217     if (buf_free>0) {
218         /* Fill with silence */
219         if (winetest_debug > 1)
220             trace("writing %ld bytes of silence\n",buf_free);
221         if (buffer_silence(state,buf_free)==-1)
222             goto STOP;
223     }
224     return 1;
225
226 STOP:
227     if (winetest_debug > 1)
228         trace("stopping playback\n");
229     rc=IDirectSoundBuffer_Stop(state->dsbo);
230     ok(rc==DS_OK,"Stop failed: rc=%ld\n",rc);
231     return 0;
232 }
233
234 void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
235                  BOOL is_primary, BOOL set_volume, LONG volume,
236                  BOOL set_pan, LONG pan, BOOL play, double duration,
237                  BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener,
238                  BOOL move_listener, BOOL move_sound)
239 {
240     HRESULT rc;
241     DSBCAPS dsbcaps;
242     WAVEFORMATEX wfx,wfx2;
243     DWORD size,status,freq;
244     int ref;
245
246     /* DSOUND: Error: Invalid caps pointer */
247     rc=IDirectSoundBuffer_GetCaps(dsbo,0);
248     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
249
250     ZeroMemory(&dsbcaps, sizeof(dsbcaps));
251
252     /* DSOUND: Error: Invalid caps pointer */
253     rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
254     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
255
256     dsbcaps.dwSize=sizeof(dsbcaps);
257     rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
258     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
259     if (rc==DS_OK) {
260         trace("    Caps: flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
261               dsbcaps.dwBufferBytes);
262     }
263
264     /* Query the format size. Note that it may not match sizeof(wfx) */
265     size=0;
266     rc=IDirectSoundBuffer_GetFormat(dsbo,NULL,0,&size);
267     ok(rc==DS_OK && size!=0,
268        "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
269        rc,size);
270
271     rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
272     ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
273     if (rc==DS_OK && is_primary) {
274         trace("Primary buffer default format: tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
275               wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
276               wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
277     }
278
279     /* DSOUND: Error: Invalid frequency buffer */
280     rc=IDirectSoundBuffer_GetFrequency(dsbo,0);
281     ok(rc==DSERR_INVALIDPARAM,"GetFrequency should have failed: 0x%lx\n",rc);
282
283     /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
284     rc=IDirectSoundBuffer_GetFrequency(dsbo,&freq);
285     ok((rc==DS_OK && !is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
286        (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
287        "GetFrequency failed: 0x%lx\n",rc);
288     if (rc==DS_OK) {
289         ok(freq==wfx.nSamplesPerSec,
290            "The frequency returned by GetFrequency %ld does not match the format %ld\n",
291            freq,wfx.nSamplesPerSec);
292     }
293
294     /* DSOUND: Error: Invalid status pointer */
295     rc=IDirectSoundBuffer_GetStatus(dsbo,0);
296     ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
297
298     rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
299     ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
300     ok(status==0,"status=0x%lx instead of 0\n",status);
301
302     if (is_primary) {
303         /* We must call SetCooperativeLevel to be allowed to call SetFormat */
304         /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
305         rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
306         ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
307         if (rc!=DS_OK)
308             return;
309
310         /* DSOUND: Error: Invalid format pointer */
311         rc=IDirectSoundBuffer_SetFormat(dsbo,0);
312         ok(rc==DSERR_INVALIDPARAM,"SetFormat should have failed: 0x%lx\n",rc);
313
314         init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
315         rc=IDirectSoundBuffer_SetFormat(dsbo,&wfx2);
316         ok(rc==DS_OK,"SetFormat failed: 0x%lx\n",rc);
317
318         /* There is no garantee that SetFormat will actually change the
319          * format to what we asked for. It depends on what the soundcard
320          * supports. So we must re-query the format.
321          */
322         rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
323         ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
324         if (rc==DS_OK &&
325             (wfx.wFormatTag!=wfx2.wFormatTag ||
326              wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
327              wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
328              wfx.nChannels!=wfx2.nChannels)) {
329             trace("Requested format tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
330                   wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
331                   wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
332             trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
333                   wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
334                   wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
335         }
336
337         /* Set the CooperativeLevel back to normal */
338         /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
339         rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
340         ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
341     }
342
343     if (play) {
344         play_state_t state;
345         DS3DLISTENER listener_param;
346         LPDIRECTSOUND3DBUFFER buffer=NULL;
347         DS3DBUFFER buffer_param;
348         DWORD start_time,now;
349
350         trace("    Playing %g second 440Hz tone at %ldx%dx%d\n", duration,
351               wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
352
353         if (is_primary) {
354             /* We must call SetCooperativeLevel to be allowed to call Lock */
355             /* DSOUND: Setting DirectSound cooperative level to DSSCL_WRITEPRIMARY */
356             rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_WRITEPRIMARY);
357             ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
358             if (rc!=DS_OK)
359                 return;
360         }
361         if (buffer3d) {
362             LPDIRECTSOUNDBUFFER temp_buffer;
363
364             rc=IDirectSoundBuffer_QueryInterface(dsbo,&IID_IDirectSound3DBuffer,(LPVOID *)&buffer);
365             ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
366             if (rc!=DS_OK)
367                 return;
368
369             /* check the COM interface */
370             rc=IDirectSoundBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
371             ok(rc==DS_OK && temp_buffer!=NULL,"QueryInterface failed: 0x%lx\n",rc);
372             ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
373             ref=IDirectSoundBuffer_Release(temp_buffer);
374             ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
375
376             temp_buffer=NULL;
377             rc=IDirectSound3DBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
378             ok(rc==DS_OK && temp_buffer!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
379             ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
380             ref=IDirectSoundBuffer_Release(temp_buffer);
381             ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
382
383 #if 0
384             /* FIXME: this works on windows */
385             ref=IDirectSoundBuffer_Release(dsbo);
386             ok(ref==0,"IDirectSoundBuffer_Release has %d references, should have 0\n",ref);
387
388             rc=IDirectSound3DBuffer_QueryInterface(buffer, &IID_IDirectSoundBuffer,(LPVOID *)&dsbo);
389             ok(rc==DS_OK && dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
390 #endif
391
392             /* DSOUND: Error: Invalid buffer */
393             rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
394             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
395
396             ZeroMemory(&buffer_param, sizeof(buffer_param));
397
398             /* DSOUND: Error: Invalid buffer */
399             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
400             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
401
402             buffer_param.dwSize=sizeof(buffer_param);
403             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
404             ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
405         }
406         if (set_volume) {
407             if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
408                 LONG val;
409                 rc=IDirectSoundBuffer_GetVolume(dsbo,&val);
410                 ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
411
412                 rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
413                 ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
414             } else {
415                 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
416                 rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
417                 ok(rc==DSERR_CONTROLUNAVAIL,"GetVolume should have failed: 0x%lx\n",rc);
418             }
419         }
420
421         if (set_pan) {
422             if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
423                 LONG val;
424                 rc=IDirectSoundBuffer_GetPan(dsbo,&val);
425                 ok(rc==DS_OK,"GetPan failed: 0x%lx\n",rc);
426
427                 rc=IDirectSoundBuffer_SetPan(dsbo,pan);
428                 ok(rc==DS_OK,"SetPan failed: 0x%lx\n",rc);
429             } else {
430                 /* DSOUND: Error: Buffer does not have CTRLPAN */
431                 rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
432                 ok(rc==DSERR_CONTROLUNAVAIL,"GetPan should have failed: 0x%lx\n",rc);
433             }
434         }
435
436         state.wave=wave_generate_la(&wfx,duration,&state.wave_len);
437
438         state.dsbo=dsbo;
439         state.wfx=&wfx;
440         state.buffer_size=dsbcaps.dwBufferBytes;
441         state.played=state.written=state.offset=0;
442         buffer_refill(&state,state.buffer_size);
443
444         rc=IDirectSoundBuffer_Play(dsbo,0,0,DSBPLAY_LOOPING);
445         ok(rc==DS_OK,"Play: 0x%lx\n",rc);
446
447         rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
448         ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
449         ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
450            "GetStatus: bad status: %lx\n",status);
451
452         if (listener) {
453             ZeroMemory(&listener_param,sizeof(listener_param));
454             listener_param.dwSize=sizeof(listener_param);
455             rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
456             ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
457             if (move_listener)
458             {
459                 listener_param.vPosition.x = -5.0;
460                 listener_param.vVelocity.x = 10.0/duration;
461             }
462             rc=IDirectSound3DListener_SetAllParameters(listener,&listener_param,DS3D_IMMEDIATE);
463             ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
464         }
465         if (buffer3d) {
466             if (move_sound)
467             {
468                 buffer_param.vPosition.x = 100.0;
469                 buffer_param.vVelocity.x = -200.0/duration;
470             }
471             buffer_param.flMinDistance = 10;
472             rc=IDirectSound3DBuffer_SetAllParameters(buffer,&buffer_param,DS3D_IMMEDIATE);
473             ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
474         }
475
476         start_time=GetTickCount();
477         while (buffer_service(&state)) {
478             WaitForSingleObject(GetCurrentProcess(),TIME_SLICE);
479             now=GetTickCount();
480             if (listener && move_listener) {
481                 listener_param.vPosition.x = -5.0+10.0*(now-start_time)/1000/duration;
482                 if (winetest_debug>2)
483                     trace("listener position=%g\n",listener_param.vPosition.x);
484                 rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
485                 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
486             }
487             if (buffer3d && move_sound) {
488                 buffer_param.vPosition.x = 100-200.0*(now-start_time)/1000/duration;
489                 if (winetest_debug>2)
490                     trace("sound position=%g\n",buffer_param.vPosition.x);
491                 rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
492                 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
493             }
494         }
495         /* Check the sound duration was within 10% of the expected value */
496         now=GetTickCount();
497         ok(fabs(1000*duration-now+start_time)<=100*duration,"The sound played for %ld ms instead of %g ms\n",now-start_time,1000*duration);
498
499         free(state.wave);
500         if (is_primary) {
501             /* Set the CooperativeLevel back to normal */
502             /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
503             rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
504             ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
505         }
506         if (buffer3d) {
507             ref=IDirectSound3DBuffer_Release(buffer);
508             ok(ref==0,"IDirectSound3DBuffer_Release has %d references, should have 0\n",ref);
509         }
510     }
511 }
512
513 static HRESULT test_secondary(LPGUID lpGuid, int play,
514                               int has_3d, int has_3dbuffer,
515                               int has_listener, int has_duplicate,
516                               int move_listener, int move_sound)
517 {
518     HRESULT rc;
519     LPDIRECTSOUND dso=NULL;
520     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
521     LPDIRECTSOUND3DLISTENER listener=NULL;
522     DSBUFFERDESC bufdesc;
523     WAVEFORMATEX wfx;
524     int ref;
525
526     /* Create the DirectSound object */
527     rc=DirectSoundCreate(lpGuid,&dso,NULL);
528     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%08lx\n",rc);
529     if (rc!=DS_OK)
530         return rc;
531
532     /* We must call SetCooperativeLevel before creating primary buffer */
533     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
534     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
535     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
536     if (rc!=DS_OK)
537         goto EXIT;
538
539     ZeroMemory(&bufdesc, sizeof(bufdesc));
540     bufdesc.dwSize=sizeof(bufdesc);
541     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
542     if (has_3d)
543         bufdesc.dwFlags|=DSBCAPS_CTRL3D;
544     else
545         bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
546     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
547     ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a %sprimary buffer 0x%lx\n",has_3d?"3D ":"", rc);
548
549     if (rc==DS_OK && primary!=NULL) {
550         if (has_listener) {
551             rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
552             ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
553             ref=IDirectSoundBuffer_Release(primary);
554             ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
555             if (rc==DS_OK && listener!=NULL) {
556                 DS3DLISTENER listener_param;
557                 ZeroMemory(&listener_param,sizeof(listener_param));
558                 /* DSOUND: Error: Invalid buffer */
559                 rc=IDirectSound3DListener_GetAllParameters(listener,0);
560                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
561
562                 /* DSOUND: Error: Invalid buffer */
563                 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
564                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
565
566                 listener_param.dwSize=sizeof(listener_param);
567                 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
568                 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
569             }
570             else
571                 goto EXIT;
572         }
573
574         init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2);
575         secondary=NULL;
576         ZeroMemory(&bufdesc, sizeof(bufdesc));
577         bufdesc.dwSize=sizeof(bufdesc);
578         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
579         if (has_3d)
580             bufdesc.dwFlags|=DSBCAPS_CTRL3D;
581         else
582             bufdesc.dwFlags|=(DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
583         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
584         bufdesc.lpwfxFormat=&wfx;
585         trace("  Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n",
586               has_3dbuffer?"3D ":"",
587               has_duplicate?"duplicated ":"",
588               listener!=NULL||move_sound?"with ":"",
589               move_listener?"moving ":"",
590               listener!=NULL?"listener ":"",
591               listener&&move_sound?"and moving sound ":move_sound?"moving sound ":"",
592               wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
593         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
594         ok(rc==DS_OK && secondary!=NULL,"CreateSoundBuffer failed to create a 3D secondary buffer 0x%lx\n",rc);
595         if (rc==DS_OK && secondary!=NULL) {
596             if (!has_3d)
597             {
598                 DWORD refvol,refpan,vol,pan;
599
600                 /* Check the initial secondary buffer's volume and pan */
601                 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
602                 ok(rc==DS_OK,"GetVolume(secondary) failed: %s\n",DXGetErrorString8(rc));
603                 ok(vol==0,"wrong volume for a new secondary buffer: %ld\n",vol);
604                 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
605                 ok(rc==DS_OK,"GetPan(secondary) failed: %s\n",DXGetErrorString8(rc));
606                 ok(pan==0,"wrong pan for a new secondary buffer: %ld\n",pan);
607
608                 /* Check that changing the secondary buffer's volume and pan
609                  * does not impact the primary buffer's volume and pan
610                  */
611                 rc=IDirectSoundBuffer_GetVolume(primary,&refvol);
612                 ok(rc==DS_OK,"GetVolume(primary) failed: %s\n",DXGetErrorString8(rc));
613                 rc=IDirectSoundBuffer_GetPan(primary,&refpan);
614                 ok(rc==DS_OK,"GetPan(primary) failed: %s\n",DXGetErrorString8(rc));
615
616                 rc=IDirectSoundBuffer_SetVolume(secondary,-1000);
617                 ok(rc==DS_OK,"SetVolume(secondary) failed: %s\n",DXGetErrorString8(rc));
618                 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
619                 ok(rc==DS_OK,"SetVolume(secondary) failed: %s\n",DXGetErrorString8(rc));
620                 ok(vol==-1000,"secondary: wrong volume %ld instead of -1000\n",vol);
621                 rc=IDirectSoundBuffer_SetPan(secondary,-1000);
622                 ok(rc==DS_OK,"SetPan(secondary) failed: %s\n",DXGetErrorString8(rc));
623                 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
624                 ok(rc==DS_OK,"SetPan(secondary) failed: %s\n",DXGetErrorString8(rc));
625                 ok(vol==-1000,"secondary: wrong pan %ld instead of -1000\n",pan);
626
627                 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
628                 ok(rc==DS_OK,"GetVolume(primary) failed: %s\n",DXGetErrorString8(rc));
629                 ok(vol==refvol,"The primary volume changed from %ld to %ld\n",refvol,vol);
630                 rc=IDirectSoundBuffer_GetPan(primary,&pan);
631                 ok(rc==DS_OK,"GetPan(primary) failed: %s\n",DXGetErrorString8(rc));
632                 ok(pan==refpan,"The primary pan changed from %ld to %ld\n",refpan,pan);
633
634                 rc=IDirectSoundBuffer_SetVolume(secondary,0);
635                 ok(rc==DS_OK,"SetVolume(secondary) failed: %s\n",DXGetErrorString8(rc));
636                 rc=IDirectSoundBuffer_SetPan(secondary,0);
637                 ok(rc==DS_OK,"SetPan(secondary) failed: %s\n",DXGetErrorString8(rc));
638             }
639             if (has_duplicate) {
640                 LPDIRECTSOUNDBUFFER duplicated=NULL;
641
642                 /* DSOUND: Error: Invalid source buffer */
643                 rc=IDirectSound_DuplicateSoundBuffer(dso,0,0);
644                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
645
646                 /* DSOUND: Error: Invalid dest buffer */
647                 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,0);
648                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
649
650                 /* DSOUND: Error: Invalid source buffer */
651                 rc=IDirectSound_DuplicateSoundBuffer(dso,0,&duplicated);
652                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
653
654                 duplicated=NULL;
655                 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,&duplicated);
656                 ok(rc==DS_OK && duplicated!=NULL,"IDirectSound_DuplicateSoundBuffer failed to duplicate a secondary buffer 0x%lx\n",rc);
657
658                 if (rc==DS_OK && duplicated!=NULL) {
659                     ref=IDirectSoundBuffer_Release(secondary);
660                     ok(ref==0,"IDirectSoundBuffer_Release secondary has %d references, should have 0\n",ref);
661                     secondary=duplicated;
662                 }
663             }
664
665             if (rc==DS_OK && secondary!=NULL) {
666                 double duration;
667                 duration=(move_listener || move_sound?4.0:1.0);
668                 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,winetest_interactive,duration,has_3dbuffer,listener,move_listener,move_sound);
669                 ref=IDirectSoundBuffer_Release(secondary);
670                 ok(ref==0,"IDirectSoundBuffer_Release %s has %d references, should have 0\n",has_duplicate?"duplicated":"secondary",ref);
671             }
672         }
673     }
674     if (has_listener) {
675         ref=IDirectSound3DListener_Release(listener);
676         ok(ref==0,"IDirectSound3dListener_Release listener has %d references, should have 0\n",ref);
677     } else {
678         ref=IDirectSoundBuffer_Release(primary);
679         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
680     }
681
682     /* Set the CooperativeLevel back to normal */
683     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
684     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
685     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
686
687 EXIT:
688     ref=IDirectSound_Release(dso);
689     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
690     if (ref!=0)
691         return DSERR_GENERIC;
692
693     return rc;
694 }
695
696 static HRESULT test_primary(LPGUID lpGuid)
697 {
698     HRESULT rc;
699     LPDIRECTSOUND dso=NULL;
700     LPDIRECTSOUNDBUFFER primary=NULL;
701     DSBUFFERDESC bufdesc;
702     DSCAPS dscaps;
703     int ref, i;
704
705     /* Create the DirectSound object */
706     rc=DirectSoundCreate(lpGuid,&dso,NULL);
707     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
708     if (rc!=DS_OK)
709         return rc;
710
711     /* Get the device capabilities */
712     ZeroMemory(&dscaps, sizeof(dscaps));
713     dscaps.dwSize=sizeof(dscaps);
714     rc=IDirectSound_GetCaps(dso,&dscaps);
715     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
716     if (rc!=DS_OK)
717         goto EXIT;
718
719     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
720     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
721     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
722     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
723     if (rc!=DS_OK)
724         goto EXIT;
725
726     /* Testing the primary buffer */
727     primary=NULL;
728     ZeroMemory(&bufdesc, sizeof(bufdesc));
729     bufdesc.dwSize=sizeof(bufdesc);
730     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
731     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
732     ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
733     if (rc==DS_OK && primary!=NULL) {
734         test_buffer(dso,primary,1,TRUE,0,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
735         if (winetest_interactive) {
736             LONG volume,pan;
737
738             volume = DSBVOLUME_MAX;
739             for (i = 0; i < 6; i++) {
740                 test_buffer(dso,primary,1,TRUE,volume,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
741                 volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40);
742             }
743
744             pan = DSBPAN_LEFT;
745             for (i = 0; i < 7; i++) {
746                 test_buffer(dso,primary,1,TRUE,0,TRUE,pan,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
747                 pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6);
748             }
749         }
750         ref=IDirectSoundBuffer_Release(primary);
751         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
752     }
753
754     /* Set the CooperativeLevel back to normal */
755     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
756     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
757     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
758
759 EXIT:
760     ref=IDirectSound_Release(dso);
761     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
762     if (ref!=0)
763         return DSERR_GENERIC;
764
765     return rc;
766 }
767
768 static HRESULT test_primary_3d(LPGUID lpGuid)
769 {
770     HRESULT rc;
771     LPDIRECTSOUND dso=NULL;
772     LPDIRECTSOUNDBUFFER primary=NULL;
773     DSBUFFERDESC bufdesc;
774     DSCAPS dscaps;
775     int ref;
776
777     /* Create the DirectSound object */
778     rc=DirectSoundCreate(lpGuid,&dso,NULL);
779     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
780     if (rc!=DS_OK)
781         return rc;
782
783     /* Get the device capabilities */
784     ZeroMemory(&dscaps, sizeof(dscaps));
785     dscaps.dwSize=sizeof(dscaps);
786     rc=IDirectSound_GetCaps(dso,&dscaps);
787     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
788     if (rc!=DS_OK)
789         goto EXIT;
790
791     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
792     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
793     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
794     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
795     if (rc!=DS_OK)
796         goto EXIT;
797
798     primary=NULL;
799     ZeroMemory(&bufdesc, sizeof(bufdesc));
800     bufdesc.dwSize=sizeof(bufdesc);
801     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
802     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
803     ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
804     if (rc==DS_OK && primary!=NULL) {
805         ref=IDirectSoundBuffer_Release(primary);
806         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
807         primary=NULL;
808         ZeroMemory(&bufdesc, sizeof(bufdesc));
809         bufdesc.dwSize=sizeof(bufdesc);
810         bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
811         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
812         ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
813         if (rc==DS_OK && primary!=NULL) {
814             test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
815             ref=IDirectSoundBuffer_Release(primary);
816             ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
817         }
818     }
819     /* Set the CooperativeLevel back to normal */
820     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
821     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
822     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
823
824 EXIT:
825     ref=IDirectSound_Release(dso);
826     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
827     if (ref!=0)
828         return DSERR_GENERIC;
829
830     return rc;
831 }
832
833 static HRESULT test_primary_3d_with_listener(LPGUID lpGuid)
834 {
835     HRESULT rc;
836     LPDIRECTSOUND dso=NULL;
837     LPDIRECTSOUNDBUFFER primary=NULL;
838     DSBUFFERDESC bufdesc;
839     DSCAPS dscaps;
840     int ref;
841
842     /* Create the DirectSound object */
843     rc=DirectSoundCreate(lpGuid,&dso,NULL);
844     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
845     if (rc!=DS_OK)
846         return rc;
847
848     /* Get the device capabilities */
849     ZeroMemory(&dscaps, sizeof(dscaps));
850     dscaps.dwSize=sizeof(dscaps);
851     rc=IDirectSound_GetCaps(dso,&dscaps);
852     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
853     if (rc!=DS_OK)
854         goto EXIT;
855
856     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
857     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
858     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
859     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
860     if (rc!=DS_OK)
861         goto EXIT;
862     primary=NULL;
863     ZeroMemory(&bufdesc, sizeof(bufdesc));
864     bufdesc.dwSize=sizeof(bufdesc);
865     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
866     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
867     ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer 0x%lx\n",rc);
868     if (rc==DS_OK && primary!=NULL) {
869         LPDIRECTSOUND3DLISTENER listener=NULL;
870         rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
871         ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
872         if (rc==DS_OK && listener!=NULL) {
873             LPDIRECTSOUNDBUFFER temp_buffer=NULL;
874
875             /* Checking the COM interface */
876             rc=IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
877             ok(rc==DS_OK && temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
878             ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
879             if (rc==DS_OK && temp_buffer!=NULL) {
880                 ref=IDirectSoundBuffer_Release(temp_buffer);
881                 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
882
883                 temp_buffer=NULL;
884                 rc=IDirectSound3DListener_QueryInterface(listener, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
885                 ok(rc==DS_OK && temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
886                 ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
887                 ref=IDirectSoundBuffer_Release(temp_buffer);
888                 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
889
890                 /* Testing the buffer */
891                 test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,listener,0,0);
892             }
893
894             /* Testing the reference counting */
895             ref=IDirectSound3DListener_Release(listener);
896             ok(ref==0,"IDirectSound3DListener_Release listener has %d references, should have 0\n",ref);
897         }
898
899         /* Testing the reference counting */
900         ref=IDirectSoundBuffer_Release(primary);
901         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
902     }
903
904 EXIT:
905     ref=IDirectSound_Release(dso);
906     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
907     if (ref!=0)
908 return DSERR_GENERIC;
909
910     return rc;
911 }
912
913 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
914                                    LPCSTR lpcstrModule, LPVOID lpContext)
915 {
916     trace("*** Testing %s - %s\n",lpcstrDescription,lpcstrModule);
917
918     trace("  Testing the primary buffer\n");
919     test_primary(lpGuid);
920
921     trace("  Testing 3D primary buffer\n");
922     test_primary_3d(lpGuid);
923
924     trace("  Testing 3D primary buffer with listener\n");
925     test_primary_3d_with_listener(lpGuid);
926
927     /* Testing secondary buffers */
928     test_secondary(lpGuid,winetest_interactive,0,0,0,0,0,0);
929     test_secondary(lpGuid,winetest_interactive,0,0,0,1,0,0);
930
931     /* Testing 3D secondary buffers */
932     test_secondary(lpGuid,winetest_interactive,1,0,0,0,0,0);
933     test_secondary(lpGuid,winetest_interactive,1,1,0,0,0,0);
934     test_secondary(lpGuid,winetest_interactive,1,1,0,1,0,0);
935     test_secondary(lpGuid,winetest_interactive,1,0,1,0,0,0);
936     test_secondary(lpGuid,winetest_interactive,1,0,1,1,0,0);
937     test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,0);
938     test_secondary(lpGuid,winetest_interactive,1,1,1,1,0,0);
939     test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,0);
940     test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,1);
941     test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,1);
942
943     return 1;
944 }
945
946 static void ds3d_tests()
947 {
948     HRESULT rc;
949     rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
950     ok(rc==DS_OK,"DirectSoundEnumerate failed: %ld\n",rc);
951 }
952
953 START_TEST(ds3d)
954 {
955     ds3d_tests();
956 }