Fix the case of product and company names.
[wine] / dlls / dsound / tests / dsound.c
1 /*
2  * Unit tests for dsound functions
3  *
4  * Copyright (c) 2002 Francois Gouget
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #define NONAMELESSSTRUCT
22 #define NONAMELESSUNION
23 #include <windows.h>
24
25 #include <math.h>
26 #include <stdlib.h>
27
28 #include "wine/test.h"
29 #include "windef.h"
30 #include "wingdi.h"
31 #include "dsound.h"
32
33 #ifndef DSBCAPS_CTRLDEFAULT
34 #define DSBCAPS_CTRLDEFAULT      0x000000E0
35 #endif
36
37 static const unsigned int formats[][3]={
38     { 8000,  8, 1},
39     { 8000,  8, 2},
40     { 8000, 16, 1},
41     { 8000, 16, 2},
42     {11025,  8, 1},
43     {11025,  8, 2},
44     {11025, 16, 1},
45     {11025, 16, 2},
46     {22050,  8, 1},
47     {22050,  8, 2},
48     {22050, 16, 1},
49     {22050, 16, 2},
50     {44100,  8, 1},
51     {44100,  8, 2},
52     {44100, 16, 1},
53     {44100, 16, 2},
54     {48000,  8, 1},
55     {48000,  8, 2},
56     {48000, 16, 1},
57     {48000, 16, 2},
58     {96000,  8, 1},
59     {96000,  8, 2},
60     {96000, 16, 1},
61     {96000, 16, 2}
62 };
63 #define NB_FORMATS (sizeof(formats)/sizeof(*formats))
64
65 /* The time slice determines how often we will service the buffer and the
66  * buffer will be four time slices long
67  */
68 #define TIME_SLICE    100
69 #define BUFFER_LEN    (4*TIME_SLICE)
70 #define TONE_DURATION (6*TIME_SLICE)
71
72 /* This test can play a test tone. But this only makes sense if someone
73  * is going to carefully listen to it, and would only bother everyone else.
74  * So this is only done if the test is being run in interactive mode.
75  */
76
77 #define PI 3.14159265358979323846
78 static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
79 {
80     int i;
81     int nb_samples;
82     char* buf;
83     char* b;
84
85     nb_samples=(int)(duration*wfx->nSamplesPerSec);
86     *size=nb_samples*wfx->nBlockAlign;
87     b=buf=malloc(*size);
88     for (i=0;i<nb_samples;i++) {
89         double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
90         if (wfx->wBitsPerSample==8) {
91             unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
92             *b++=sample;
93             if (wfx->nChannels==2)
94                *b++=sample;
95         } else {
96             signed short sample=(signed short)((double)32767.5*y-0.5);
97             b[0]=sample & 0xff;
98             b[1]=sample >> 8;
99             b+=2;
100             if (wfx->nChannels==2) {
101                 b[0]=sample & 0xff;
102                 b[1]=sample >> 8;
103                 b+=2;
104             }
105         }
106     }
107     return buf;
108 }
109
110 static HWND get_hwnd()
111 {
112     HWND hwnd=GetForegroundWindow();
113     if (!hwnd)
114         hwnd=GetDesktopWindow();
115     return hwnd;
116 }
117
118 static void init_format(WAVEFORMATEX* wfx, int rate, int depth, int channels)
119 {
120     wfx->wFormatTag=WAVE_FORMAT_PCM;
121     wfx->nChannels=channels;
122     wfx->wBitsPerSample=depth;
123     wfx->nSamplesPerSec=rate;
124     wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
125     wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign;
126     wfx->cbSize=0;
127 }
128
129 typedef struct {
130     char* wave;
131     DWORD wave_len;
132
133     LPDIRECTSOUNDBUFFER dsbo;
134     LPWAVEFORMATEX wfx;
135     DWORD buffer_size;
136     DWORD written;
137     DWORD offset;
138
139     DWORD last_pos;
140 } play_state_t;
141
142 static int buffer_refill(play_state_t* state, DWORD size)
143 {
144     LPVOID ptr1,ptr2;
145     DWORD len1,len2;
146     HRESULT rc;
147
148     if (size>state->wave_len-state->written)
149         size=state->wave_len-state->written;
150
151     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
152                                &ptr1,&len1,&ptr2,&len2,0);
153     ok(rc==DS_OK,"Lock: 0x%lx",rc);
154     if (rc!=DS_OK)
155         return -1;
156
157     memcpy(ptr1,state->wave+state->written,len1);
158     state->written+=len1;
159     if (ptr2!=NULL) {
160         memcpy(ptr2,state->wave+state->written,len2);
161         state->written+=len2;
162     }
163     state->offset=state->written % state->buffer_size;
164     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
165     ok(rc==DS_OK,"Unlock: 0x%lx",rc);
166     if (rc!=DS_OK)
167         return -1;
168     return size;
169 }
170
171 static int buffer_silence(play_state_t* state, DWORD size)
172 {
173     LPVOID ptr1,ptr2;
174     DWORD len1,len2;
175     HRESULT rc;
176     BYTE s;
177
178     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
179                                &ptr1,&len1,&ptr2,&len2,0);
180     ok(rc==DS_OK,"Lock: 0x%lx",rc);
181     if (rc!=DS_OK)
182         return -1;
183
184     s=(state->wfx->wBitsPerSample==8?0x80:0);
185     memset(ptr1,s,len1);
186     if (ptr2!=NULL) {
187         memset(ptr2,s,len2);
188     }
189     state->offset=(state->offset+size) % state->buffer_size;
190     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
191     ok(rc==DS_OK,"Unlock: 0x%lx",rc);
192     if (rc!=DS_OK)
193         return -1;
194     return size;
195 }
196
197 static int buffer_service(play_state_t* state)
198 {
199     DWORD play_pos,write_pos,buf_free;
200     HRESULT rc;
201
202     rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,&write_pos);
203     ok(rc==DS_OK,"GetCurrentPosition: %lx",rc);
204     if (rc!=DS_OK) {
205         goto STOP;
206     }
207
208     /* Refill the buffer */
209     if (state->offset<=play_pos) {
210         buf_free=play_pos-state->offset;
211     } else {
212         buf_free=state->buffer_size-state->offset+play_pos;
213     }
214     if (winetest_debug > 1)
215         trace("buf pos=%ld free=%ld written=%ld / %ld\n",
216               play_pos,buf_free,state->written,state->wave_len);
217     if (buf_free==0)
218         return 1;
219
220     if (state->written<state->wave_len) {
221         int w=buffer_refill(state,buf_free);
222         if (w==-1)
223             goto STOP;
224         buf_free-=w;
225         if (state->written==state->wave_len) {
226             state->last_pos=(state->offset<play_pos)?play_pos:0;
227             if (winetest_debug > 1)
228                 trace("last sound byte at %ld\n",
229                       (state->written % state->buffer_size));
230         }
231     } else {
232         if (state->last_pos!=0 && play_pos<state->last_pos) {
233             /* We wrapped around the end of the buffer */
234             state->last_pos=0;
235         }
236         if (state->last_pos==0 &&
237             play_pos>(state->written % state->buffer_size)) {
238             /* Now everything has been played */
239             goto STOP;
240         }
241     }
242
243     if (buf_free>0) {
244         /* Fill with silence */
245         if (winetest_debug > 1)
246             trace("writing %ld bytes of silence\n",buf_free);
247         if (buffer_silence(state,buf_free)==-1)
248             goto STOP;
249     }
250     return 1;
251
252 STOP:
253     if (winetest_debug > 1)
254         trace("stopping playback\n");
255     rc=IDirectSoundBuffer_Stop(state->dsbo);
256     ok(rc==DS_OK,"Stop failed: rc=%ld",rc);
257     return 0;
258 }
259
260 static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
261                         int is_primary, int play, int buffer3d, 
262                         LPDIRECTSOUND3DLISTENER listener, 
263                         int move_listener, int move_sound)
264 {
265     HRESULT rc;
266     DSBCAPS dsbcaps;
267     WAVEFORMATEX wfx,wfx2;
268     DWORD size,status,freq;
269     int ref;
270
271     /* DSOUND: Error: Invalid caps pointer */
272     rc=IDirectSoundBuffer_GetCaps(dsbo,0);
273     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
274
275     ZeroMemory(&dsbcaps, sizeof(dsbcaps));
276
277     /* DSOUND: Error: Invalid caps pointer */
278     rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
279     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
280
281     dsbcaps.dwSize=sizeof(dsbcaps);
282     rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
283     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
284     if (rc==DS_OK) {
285         trace("    Caps: flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
286               dsbcaps.dwBufferBytes);
287     }
288
289     /* Query the format size. Note that it may not match sizeof(wfx) */
290     size=0;
291     rc=IDirectSoundBuffer_GetFormat(dsbo,NULL,0,&size);
292     ok(rc==DS_OK && size!=0,
293        "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
294        rc,size);
295
296     rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
297     ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
298     if (rc==DS_OK) {
299         trace("    tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
300               wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
301               wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
302     }
303
304     /* DSOUND: Error: Invalid frequency buffer */
305     rc=IDirectSoundBuffer_GetFrequency(dsbo,0);
306     ok(rc==DSERR_INVALIDPARAM,"GetFrequency should have failed: 0x%lx\n",rc);
307
308     /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
309     rc=IDirectSoundBuffer_GetFrequency(dsbo,&freq);
310     ok((rc==DS_OK&&!is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary),
311         "GetFrequency failed: 0x%lx\n",rc);
312     if (rc==DS_OK) {
313         ok(freq==wfx.nSamplesPerSec,
314            "The frequency returned by GetFrequency %ld does not match the format %ld\n",
315            freq,wfx.nSamplesPerSec);
316     }
317
318     /* DSOUND: Error: Invalid status pointer */
319     rc=IDirectSoundBuffer_GetStatus(dsbo,0);
320     ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
321
322     rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
323     ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
324     if (rc==DS_OK) {
325         trace("    status=0x%04lx\n",status);
326     }
327
328     if (is_primary) {
329         /* We must call SetCooperativeLevel to be allowed to call SetFormat */
330         /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
331         rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
332         ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
333         if(rc!=DS_OK)
334             return;
335
336         /* DSOUND: Error: Invalid format pointer */
337         rc=IDirectSoundBuffer_SetFormat(dsbo,0);
338         ok(rc==DSERR_INVALIDPARAM,"SetFormat should have failed: 0x%lx\n",rc);
339
340         init_format(&wfx2,11025,16,2);
341         rc=IDirectSoundBuffer_SetFormat(dsbo,&wfx2);
342         ok(rc==DS_OK,"SetFormat failed: 0x%lx\n",rc);
343
344         /* There is no garantee that SetFormat will actually change the
345          * format to what we asked for. It depends on what the soundcard
346          * supports. So we must re-query the format.
347          */
348         rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
349         ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
350         if (rc==DS_OK) {
351             trace("    tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
352                   wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
353                   wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
354         }
355
356         /* Set the CooperativeLevel back to normal */
357         /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
358         rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
359         ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
360     }
361
362     if (play) {
363         play_state_t state;
364         LONG volume;
365         LPDIRECTSOUND3DBUFFER buffer=NULL;
366         DS3DBUFFER buffer_param;
367         DS3DLISTENER listener_param;
368         trace("    Playing 440Hz LA at %ldx%dx%d\n",
369               wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
370
371         if (is_primary) {
372             /* We must call SetCooperativeLevel to be allowed to call Lock */
373             /* DSOUND: Setting DirectSound cooperative level to DSSCL_WRITEPRIMARY */
374             rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_WRITEPRIMARY);
375             ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
376             if (rc!=DS_OK)
377                 return;
378         }
379         if (buffer3d) {
380             LPDIRECTSOUNDBUFFER temp_buffer;
381
382             rc=IDirectSoundBuffer_QueryInterface(dsbo,&IID_IDirectSound3DBuffer,(LPVOID *)&buffer);
383             ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
384             if(rc!=DS_OK)
385                 return;
386
387             /* check the COM interface */
388             rc=IDirectSoundBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
389             ok(rc==DS_OK&&temp_buffer!=NULL,"QueryInterface failed: 0x%lx\n",rc);
390             ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
391             ref=IDirectSoundBuffer_Release(temp_buffer);
392             ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
393
394             temp_buffer=NULL;
395             rc=IDirectSound3DBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
396             ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
397             ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
398             ref=IDirectSoundBuffer_Release(temp_buffer);
399             ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
400
401 #if 0       /* FIXME: this works on windows */
402             ref=IDirectSoundBuffer_Release(dsbo);
403             ok(ref==0,"IDirectSoundBuffer_Release has %d references, should have 0\n",ref);
404
405             rc=IDirectSound3DBuffer_QueryInterface(buffer, &IID_IDirectSoundBuffer,(LPVOID *)&dsbo);
406             ok(rc==DS_OK&&dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
407 #endif
408
409             /* DSOUND: Error: Invalid buffer */
410             rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
411             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
412
413             ZeroMemory(&buffer_param, sizeof(buffer_param));
414
415             /* DSOUND: Error: Invalid buffer */
416             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
417             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
418
419             buffer_param.dwSize=sizeof(buffer_param);
420             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
421             ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
422         }
423         if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
424             rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
425             ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
426
427             rc=IDirectSoundBuffer_SetVolume(dsbo,-300);
428             ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
429         }
430
431         /* DSOUND: Error: Buffer does not have CTRLVOLUME */
432         rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
433         ok((rc==DS_OK&&!is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary),"GetVolume failed: 0x%lx\n",rc);
434         if (rc==DS_OK) {
435             trace("    volume=%ld\n",volume);
436         }
437
438         state.wave=wave_generate_la(&wfx,((double)TONE_DURATION)/1000,&state.wave_len);
439
440         state.dsbo=dsbo;
441         state.wfx=&wfx;
442         state.buffer_size=dsbcaps.dwBufferBytes;
443         state.written=state.offset=0;
444         buffer_refill(&state,state.buffer_size);
445
446         rc=IDirectSoundBuffer_Play(dsbo,0,0,DSBPLAY_LOOPING);
447         ok(rc==DS_OK,"Play: 0x%lx\n",rc);
448
449         rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
450         ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
451         ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
452            "GetStatus: bad status: %lx",status);
453
454         if (listener) {
455             ZeroMemory(&listener_param,sizeof(listener_param));
456             listener_param.dwSize=sizeof(listener_param);
457             rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
458             ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
459             if (move_listener)
460                 listener_param.vPosition.x = -5.0;
461             else
462                 listener_param.vPosition.x = 0.0;
463             listener_param.vPosition.y = 0.0;
464             listener_param.vPosition.z = 0.0;
465             rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
466             ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
467         }
468         if (buffer3d) {
469             if (move_sound)
470                 buffer_param.vPosition.x = 5.0;
471             else
472                 buffer_param.vPosition.x = 0.0;
473             buffer_param.vPosition.y = 0.0;
474             buffer_param.vPosition.z = 0.0;
475             rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
476             ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
477         }
478
479         while (buffer_service(&state)) {
480             WaitForSingleObject(GetCurrentProcess(),TIME_SLICE/2);
481             if (listener&&move_listener) {
482                 listener_param.vPosition.x += 0.5;
483                 rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
484                 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
485             }
486             if (buffer3d&&move_sound) {
487                 buffer_param.vPosition.x -= 0.5;
488                 rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
489                 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
490             }
491         }
492
493         if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
494             rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
495             ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
496         }
497
498         free(state.wave);
499         if (is_primary) {
500             /* Set the CooperativeLevel back to normal */
501             /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
502             rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
503             ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
504         }
505         if (buffer3d) {
506             ref=IDirectSound3DBuffer_Release(buffer);
507             ok(ref==0,"IDirectSound3DBuffer_Release has %d references, should have 0\n",ref); 
508         }
509     }
510 }
511
512 static HRESULT test_secondary(LPGUID lpGuid, int play, 
513                               int has_3d, int has_3dbuffer, 
514                               int has_listener, int has_duplicate, 
515                               int move_listener, int move_sound)
516 {
517     HRESULT rc;
518     LPDIRECTSOUND dso=NULL;
519     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
520     LPDIRECTSOUND3DLISTENER listener=NULL;
521     DSBUFFERDESC bufdesc;
522     DSCAPS dscaps;
523     WAVEFORMATEX wfx;
524     int f,ref;
525
526     /* Create the DirectSound object */
527     rc=DirectSoundCreate(lpGuid,&dso,NULL);
528     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
529     if (rc!=DS_OK)
530         return rc;
531
532     /* Get the device capabilities */
533     ZeroMemory(&dscaps, sizeof(dscaps));
534     dscaps.dwSize=sizeof(dscaps);
535     rc=IDirectSound_GetCaps(dso,&dscaps);
536     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
537     if (rc!=DS_OK)
538         goto EXIT;
539
540         /* We must call SetCooperativeLevel before creating primary buffer */
541         /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
542         rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
543         ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
544         if(rc!=DS_OK)
545             goto EXIT;
546
547     ZeroMemory(&bufdesc, sizeof(bufdesc));
548     bufdesc.dwSize=sizeof(bufdesc);
549     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
550     if (has_3d)
551         bufdesc.dwFlags|=DSBCAPS_CTRL3D;
552     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
553     ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a %sprimary buffer 0x%lx\n",has_3d?"3D ":"", rc);
554     if (rc==DS_OK&&primary!=NULL) {
555         if (has_listener) {
556             rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
557             ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
558             ref=IDirectSoundBuffer_Release(primary);
559             ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
560             if(rc==DS_OK&&listener!=NULL) {
561                 DS3DLISTENER listener_param;
562                 ZeroMemory(&listener_param,sizeof(listener_param));
563                 /* DSOUND: Error: Invalid buffer */
564                 rc=IDirectSound3DListener_GetAllParameters(listener,0);
565                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
566
567                 /* DSOUND: Error: Invalid buffer */
568                 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
569                 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
570
571                 listener_param.dwSize=sizeof(listener_param);
572                 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
573                 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
574             } else
575                 goto EXIT;
576         } 
577
578         for (f=0;f<NB_FORMATS;f++) {
579             init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
580             secondary=NULL;
581             ZeroMemory(&bufdesc, sizeof(bufdesc));
582             bufdesc.dwSize=sizeof(bufdesc);
583             bufdesc.dwFlags=DSBCAPS_CTRLDEFAULT|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRL3D;
584             if (has_3d)
585                 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
586             bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
587             bufdesc.lpwfxFormat=&wfx;
588             trace("  Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n",
589                 has_3dbuffer?"3D ":"",
590                 has_duplicate?"duplicated ":"",
591                 listener!=NULL||move_sound?"with ":"",
592                 move_listener?"moving ":"",
593                 listener!=NULL?"listener ":"",
594                 listener&&move_sound?"and moving sound ":move_sound?"moving sound ":"",
595             wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
596             rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
597             ok(rc==DS_OK&&secondary!=NULL,"CreateSoundBuffer failed to create a 3D secondary buffer 0x%lx\n",rc);
598             if (rc==DS_OK&&secondary!=NULL) {
599                 if (has_duplicate) {
600                     LPDIRECTSOUNDBUFFER duplicated=NULL;
601
602                     /* DSOUND: Error: Invalid source buffer */
603                     rc=IDirectSound_DuplicateSoundBuffer(dso,0,0);
604                     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
605
606                     /* DSOUND: Error: Invalid dest buffer */
607                     rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,0);
608                     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
609
610                     /* DSOUND: Error: Invalid source buffer */
611                     rc=IDirectSound_DuplicateSoundBuffer(dso,0,&duplicated);
612                     ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
613
614                     duplicated=NULL;
615                     rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,&duplicated);
616                     ok(rc==DS_OK&&duplicated!=NULL,"IDirectSound_DuplicateSoundBuffer failed to duplicate a secondary buffer 0x%lx\n",rc);
617
618                     if (rc==DS_OK&&duplicated!=NULL) {
619                         ref=IDirectSoundBuffer_Release(secondary);
620                         ok(ref==0,"IDirectSoundBuffer_Release secondary has %d references, should have 0\n",ref); 
621                         secondary=duplicated;
622                     } 
623                 }
624
625                 if (rc==DS_OK&&secondary!=NULL) {
626                     test_buffer(dso,secondary,0,winetest_interactive,has_3dbuffer,listener,move_listener,move_sound);
627                     ref=IDirectSoundBuffer_Release(secondary);
628                     ok(ref==0,"IDirectSoundBuffer_Release %s has %d references, should have 0\n",has_duplicate?"duplicated":"secondary",ref);
629                 }
630             }
631         }
632         if (has_listener) {
633             ref=IDirectSound3DListener_Release(listener);
634             ok(ref==0,"IDirectSound3dListener_Release listener has %d references, should have 0\n",ref);
635         } else {
636             ref=IDirectSoundBuffer_Release(primary);
637             ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
638         }
639     }
640         /* Set the CooperativeLevel back to normal */
641         /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
642         rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
643         ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
644
645 EXIT:
646     ref=IDirectSound_Release(dso);
647     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
648     if (ref!=0)
649         return DSERR_GENERIC;
650
651     return rc;
652 }
653
654 static HRESULT test_dsound(LPGUID lpGuid)
655 {
656     HRESULT rc;
657     LPDIRECTSOUND dso=NULL;
658     DSCAPS dscaps;
659     DWORD speaker_config, new_speaker_config;
660     int ref;
661
662     /* DSOUND: Error: Invalid interface buffer */
663     rc=DirectSoundCreate(lpGuid,0,NULL);
664     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate should have failed: 0x%lx\n",rc);
665
666     /* Create the DirectSound object */
667     rc=DirectSoundCreate(lpGuid,&dso,NULL);
668     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
669     if (rc!=DS_OK)
670         return rc;
671
672     /* DSOUND: Error: Invalid caps buffer */
673     rc=IDirectSound_GetCaps(dso,0);
674     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
675
676     ZeroMemory(&dscaps, sizeof(dscaps));
677
678     /* DSOUND: Error: Invalid caps buffer */
679     rc=IDirectSound_GetCaps(dso,&dscaps);
680     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
681
682     dscaps.dwSize=sizeof(dscaps);
683
684     /* DSOUND: Running on a certified driver */
685     rc=IDirectSound_GetCaps(dso,&dscaps);
686     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
687     if (rc==DS_OK) {
688         trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
689               dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
690               dscaps.dwMaxSecondarySampleRate);
691     }
692
693     rc=IDirectSound_GetSpeakerConfig(dso,0);
694     ok(rc==DSERR_INVALIDPARAM,"GetSpeakerConfig should have failed: 0x%lx\n",rc);
695
696     rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
697     ok(rc==DS_OK,"GetSpeakerConfig failed: 0x%lx\n",rc);
698     if (rc==DS_OK) {
699         trace("  DirectSound SpeakerConfig: 0x%08lx\n", speaker_config);
700     }
701  
702     speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,DSSPEAKER_GEOMETRY_WIDE);
703     rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
704     ok(rc==DS_OK,"SetSpeakerConfig failed: 0x%lx\n",rc);
705     if (rc==DS_OK) {
706         rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
707         ok(rc==DS_OK,"GetSpeakerConfig failed: 0x%lx\n",rc);
708         if (rc==DS_OK)
709             ok(speaker_config==new_speaker_config,"SetSpeakerConfig failed to set speaker config: expected 0x%08lx, got 0x%08lx\n",
710                 speaker_config,new_speaker_config);
711     }
712
713     /* Release the DirectSound object */
714     ref=IDirectSound_Release(dso);
715     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
716     if (ref!=0)
717         return DSERR_GENERIC; 
718
719 #if 0   /* FIXME: this works on windows */ 
720     /* Create a DirectSound object */
721     rc=DirectSoundCreate(lpGuid,&dso,NULL);
722     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
723     if (rc==DS_OK) {
724         LPDIRECTSOUND dso1=NULL;
725
726         /* Create a second DirectSound object */
727         rc=DirectSoundCreate(lpGuid,&dso1,NULL);
728         ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
729         if (rc==DS_OK) {
730             /* Release the second DirectSound object */
731             ref=IDirectSound_Release(dso1);
732             ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
733             ok(dso!=dso1,"DirectSound objects should be unique: dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
734         }
735
736         /* Release the first DirectSound object */
737         ref=IDirectSound_Release(dso);
738         ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
739         if (ref!=0)
740             return DSERR_GENERIC; 
741     } else
742         return rc;
743 #endif
744
745     return DS_OK;
746 }
747
748 static HRESULT test_primary(LPGUID lpGuid)
749 {
750     HRESULT rc;
751     LPDIRECTSOUND dso=NULL;
752     LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
753     DSBUFFERDESC bufdesc;
754     DSCAPS dscaps;
755     int ref;
756
757     /* Create the DirectSound object */
758     rc=DirectSoundCreate(lpGuid,&dso,NULL);
759     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
760     if (rc!=DS_OK)
761         return rc;
762
763     /* Get the device capabilities */
764     ZeroMemory(&dscaps, sizeof(dscaps));
765     dscaps.dwSize=sizeof(dscaps);
766     rc=IDirectSound_GetCaps(dso,&dscaps);
767     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
768     if (rc!=DS_OK)
769         goto EXIT;
770
771     /* DSOUND: Error: Invalid buffer description pointer */
772     rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
773     ok(rc==DSERR_INVALIDPARAM,"CreateSoundBuffer should have failed: 0x%lx\n",rc);
774
775     /* DSOUND: Error: Invalid buffer description pointer */
776     rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
777     ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,dsbo=0x%lx\n",rc,(DWORD)primary);
778
779     /* DSOUND: Error: Invalid buffer description pointer */
780     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
781     ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,dsbo=0x%lx\n",rc,(DWORD)primary);
782
783     ZeroMemory(&bufdesc, sizeof(bufdesc));
784
785     /* DSOUND: Error: Invalid size */
786     /* DSOUND: Error: Invalid buffer description */
787     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
788     ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,primary=0x%lx\n",rc,(DWORD)primary);
789
790     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
791     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
792     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
793     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
794     if (rc!=DS_OK)
795         goto EXIT;
796
797     /* Testing the primary buffer */
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         /* Try to create a second primary buffer */
806         /* DSOUND: Error: The primary buffer already exists.  Any changes made to the buffer description will be ignored. */
807         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
808         ok(rc==DS_OK&&second==primary,"CreateSoundBuffer should have returned original primary buffer: 0x%lx\n",rc);
809         ref=IDirectSoundBuffer_Release(second);
810         ok(ref==1,"IDirectSoundBuffer_Release primary has %d references, should have 1\n",ref); 
811         /* Try to duplicate a primary buffer */
812         /* DSOUND: Error: Can't duplicate primary buffers */
813         rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
814         /* rc=0x88780032 */
815         ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer primary buffer should have failed 0x%lx\n",rc);
816         test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
817         ref=IDirectSoundBuffer_Release(primary);
818         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref); 
819     }
820     /* Set the CooperativeLevel back to normal */
821     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
822     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
823     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
824
825 EXIT:
826     ref=IDirectSound_Release(dso);
827     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
828     if (ref!=0)
829         return DSERR_GENERIC;
830
831     return rc;
832 }
833
834 static HRESULT test_primary_3d(LPGUID lpGuid)
835 {
836     HRESULT rc;
837     LPDIRECTSOUND dso=NULL;
838     LPDIRECTSOUNDBUFFER primary=NULL;
839     DSBUFFERDESC bufdesc;
840     DSCAPS dscaps;
841     int ref;
842
843     /* Create the DirectSound object */
844     rc=DirectSoundCreate(lpGuid,&dso,NULL);
845     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
846     if (rc!=DS_OK)
847         return rc;
848
849     /* Get the device capabilities */
850     ZeroMemory(&dscaps, sizeof(dscaps));
851     dscaps.dwSize=sizeof(dscaps);
852     rc=IDirectSound_GetCaps(dso,&dscaps);
853     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
854     if (rc!=DS_OK)
855         goto EXIT;
856
857     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
858     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
859     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
860     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
861     if (rc!=DS_OK)
862         goto EXIT;
863     primary=NULL;
864     ZeroMemory(&bufdesc, sizeof(bufdesc));
865     bufdesc.dwSize=sizeof(bufdesc);
866     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
867     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
868     ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
869     if (rc==DS_OK&&primary!=NULL) {
870         ref=IDirectSoundBuffer_Release(primary);
871         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref); 
872         primary=NULL;
873         ZeroMemory(&bufdesc, sizeof(bufdesc));
874         bufdesc.dwSize=sizeof(bufdesc);
875         bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
876         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
877         ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
878         if (rc==DS_OK&&primary!=NULL) {
879             test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
880             ref=IDirectSoundBuffer_Release(primary);
881             ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref); 
882         }
883     }
884     /* Set the CooperativeLevel back to normal */
885     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
886     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
887     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
888
889 EXIT:
890     ref=IDirectSound_Release(dso);
891     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
892     if (ref!=0)
893         return DSERR_GENERIC;
894
895     return rc;
896 }
897
898 static HRESULT test_primary_3d_with_listener(LPGUID lpGuid)
899 {
900     HRESULT rc;
901     LPDIRECTSOUND dso=NULL;
902     LPDIRECTSOUNDBUFFER primary=NULL;
903     DSBUFFERDESC bufdesc;
904     DSCAPS dscaps;
905     int ref;
906
907     /* Create the DirectSound object */
908     rc=DirectSoundCreate(lpGuid,&dso,NULL);
909     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
910     if (rc!=DS_OK)
911         return rc;
912
913     /* Get the device capabilities */
914     ZeroMemory(&dscaps, sizeof(dscaps));
915     dscaps.dwSize=sizeof(dscaps);
916     rc=IDirectSound_GetCaps(dso,&dscaps);
917     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
918     if (rc!=DS_OK)
919         goto EXIT;
920
921     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
922     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
923     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
924     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
925     if (rc!=DS_OK)
926         goto EXIT;
927     primary=NULL;
928     ZeroMemory(&bufdesc, sizeof(bufdesc));
929     bufdesc.dwSize=sizeof(bufdesc);
930     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
931     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
932     ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer 0x%lx\n",rc);
933     if (rc==DS_OK&&primary!=NULL) {
934         LPDIRECTSOUND3DLISTENER listener=NULL;
935         rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
936         ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
937         if (rc==DS_OK&&listener!=NULL) {
938             LPDIRECTSOUNDBUFFER temp_buffer=NULL;
939
940             /* Checking the COM interface */
941             rc=IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
942             ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
943             ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
944             if(rc==DS_OK&&temp_buffer!=NULL) {
945                 ref=IDirectSoundBuffer_Release(temp_buffer);
946                 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
947
948                 temp_buffer=NULL;
949                 rc=IDirectSound3DListener_QueryInterface(listener, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
950                 ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
951                 ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
952                 ref=IDirectSoundBuffer_Release(temp_buffer);
953                 ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
954
955                 /* Testing the buffer */
956                 test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,listener,0,0);
957             }
958
959             /* Testing the reference counting */
960             ref=IDirectSound3DListener_Release(listener);
961             ok(ref==0,"IDirectSound3DListener_Release listener has %d references, should have 0\n",ref);
962         }
963
964         /* Testing the reference counting */
965         ref=IDirectSoundBuffer_Release(primary);
966         ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref); 
967     }
968
969 EXIT:
970     ref=IDirectSound_Release(dso);
971     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
972     if (ref!=0)
973         return DSERR_GENERIC;
974
975     return rc;
976 }
977
978 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
979                                    LPCSTR lpcstrModule, LPVOID lpContext)
980 {
981     HRESULT rc;
982
983     trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
984     rc=test_dsound(lpGuid);
985     ok(rc==DS_OK,"DirectSound test failed\n");
986    
987     trace("  Testing the primary buffer\n");
988     rc=test_primary(lpGuid);
989     ok(rc==DS_OK,"Primary Buffer test failed\n");
990
991     trace("  Testing 3D primary buffer\n");
992     rc=test_primary_3d(lpGuid);
993     ok(rc==DS_OK,"3D Primary Buffer test failed\n");
994
995     trace("  Testing 3D primary buffer with listener\n");
996     rc=test_primary_3d_with_listener(lpGuid);
997     ok(rc==DS_OK,"3D Primary Buffer with listener test failed\n");
998
999     /* Testing secondary buffers */
1000     test_secondary(lpGuid,winetest_interactive,0,0,0,0,0,0);
1001     test_secondary(lpGuid,winetest_interactive,0,0,0,1,0,0);
1002
1003     /* Testing 3D secondary buffers */
1004     test_secondary(lpGuid,winetest_interactive,1,0,0,0,0,0);
1005     test_secondary(lpGuid,winetest_interactive,1,1,0,0,0,0);
1006     test_secondary(lpGuid,winetest_interactive,1,1,0,1,0,0);
1007     test_secondary(lpGuid,winetest_interactive,1,0,1,0,0,0);
1008     test_secondary(lpGuid,winetest_interactive,1,0,1,1,0,0);
1009     test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,0);
1010     test_secondary(lpGuid,winetest_interactive,1,1,1,1,0,0);
1011     test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,0);
1012     test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,1);
1013     test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,1);
1014
1015     return 1;
1016 }
1017
1018 static void dsound_out_tests()
1019 {
1020     HRESULT rc;
1021     rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
1022     ok(rc==DS_OK,"DirectSoundEnumerate failed: %ld\n",rc);
1023 }
1024
1025 #define NOTIFICATIONS    5
1026
1027 typedef struct {
1028     char* wave;
1029     DWORD wave_len;
1030
1031     LPDIRECTSOUNDCAPTUREBUFFER dscbo;
1032     LPWAVEFORMATEX wfx;
1033     DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS];
1034     HANDLE event;
1035     LPDIRECTSOUNDNOTIFY notify;
1036
1037     DWORD buffer_size;
1038     DWORD read;
1039     DWORD offset;
1040     DWORD size;
1041
1042     DWORD last_pos;
1043 } capture_state_t;
1044
1045 static int capture_buffer_service(capture_state_t* state)
1046 {
1047     HRESULT rc;
1048     LPVOID ptr1,ptr2;
1049     DWORD len1,len2;
1050     DWORD capture_pos,read_pos;
1051
1052     rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,&read_pos);
1053     ok(rc==DS_OK,"GetCurrentPosition failed: 0x%lx\n",rc);
1054     if (rc!=DS_OK)
1055         return 0;
1056
1057     rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,&ptr1,&len1,&ptr2,&len2,0);
1058     ok(rc==DS_OK,"Lock failed: 0x%lx\n",rc);
1059     if (rc!=DS_OK)
1060         return 0;
1061
1062     rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
1063     ok(rc==DS_OK,"Unlock failed: 0x%lx\n",rc);
1064     if (rc!=DS_OK)
1065         return 0;
1066
1067     state->offset = (state->offset + state->size) % state->buffer_size;
1068
1069     return 1;
1070 }
1071
1072 static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, 
1073                                 LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
1074 {
1075     HRESULT rc;
1076     DSCBCAPS dscbcaps;
1077     WAVEFORMATEX wfx;
1078     DWORD size,status;
1079     capture_state_t state;
1080     int i;
1081
1082     /* Private dsound.dll: Error: Invalid caps pointer */
1083     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0);
1084     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1085
1086     /* Private dsound.dll: Error: Invalid caps pointer */
1087     dscbcaps.dwSize=0;
1088     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
1089     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1090
1091     dscbcaps.dwSize=sizeof(dscbcaps);
1092     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
1093     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
1094     if (rc==DS_OK) {
1095         trace("    Caps: size = %ld flags=0x%08lx buffer size=%ld\n",
1096             dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
1097     }
1098
1099     /* Query the format size. Note that it may not match sizeof(wfx) */
1100     /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must be non-NULL */
1101     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL);
1102     ok(rc==DSERR_INVALIDPARAM,
1103        "GetFormat should have returned an error: rc=0x%lx\n",rc);
1104
1105     size=0;
1106     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size);
1107     ok(rc==DS_OK && size!=0,
1108        "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
1109        rc,size);
1110
1111     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
1112     ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
1113     if (rc==DS_OK) {
1114         trace("    tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
1115               wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
1116               wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
1117     }
1118
1119     /* Private dsound.dll: Error: Invalid status pointer */
1120     rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0);
1121     ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
1122
1123     rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
1124     ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
1125     if (rc==DS_OK) {
1126         trace("    status=0x%04lx\n",status);
1127     }
1128
1129     ZeroMemory(&state, sizeof(state));
1130     state.dscbo=dscbo;
1131     state.wfx=&wfx;
1132     state.buffer_size = dscbcaps.dwBufferBytes;
1133     state.event = CreateEvent( NULL, FALSE, FALSE, NULL );
1134     state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS;
1135
1136     rc=IDirectSoundCapture_QueryInterface(dscbo,&IID_IDirectSoundNotify,(void **)&(state.notify));
1137     ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
1138     if (rc!=DS_OK)
1139         return;
1140
1141     for (i = 0; i < NOTIFICATIONS; i++) {
1142         state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
1143         state.posnotify[i].hEventNotify = state.event;
1144     }
1145
1146     rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,state.posnotify);
1147     ok(rc==DS_OK,"SetNotificationPositions failed: 0x%lx\n",rc);
1148     if (rc!=DS_OK)
1149         return;
1150
1151     if (record) {
1152         rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
1153         ok(rc==DS_OK,"Start: 0x%lx\n",rc);
1154         if (rc!=DS_OK)
1155             return;
1156
1157         rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
1158         ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
1159         ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
1160            "GetStatus: bad status: %lx",status);
1161         if (rc!=DS_OK)
1162             return;
1163
1164         /* wait for the notifications */
1165         for (i = 0; i < (NOTIFICATIONS * 2); i++) {
1166             rc=MsgWaitForMultipleObjects( 1, &(state.event), FALSE, 3000, QS_ALLEVENTS );
1167             ok(rc==WAIT_OBJECT_0,"MsgWaitForMultipleObjects failed: 0x%lx\n",rc);
1168             if (rc!=WAIT_OBJECT_0)
1169                 break;
1170             if (!capture_buffer_service(&state))
1171                 break;
1172         }
1173
1174         rc=IDirectSoundCaptureBuffer_Stop(dscbo);
1175         ok(rc==DS_OK,"Stop: 0x%lx\n",rc);
1176         if (rc!=DS_OK)
1177             return;
1178     }
1179
1180     rc=IDirectSoundNotify_Release(state.notify);
1181     ok(rc==0,"Release: 0x%lx\n",rc);
1182     if (rc!=0)
1183         return;
1184 }
1185
1186 static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1187                                     LPCSTR lpcstrModule, LPVOID lpContext)
1188 {
1189     HRESULT rc;
1190     LPDIRECTSOUNDCAPTURE dsco=NULL;
1191     LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL;
1192     DSCBUFFERDESC bufdesc;
1193     WAVEFORMATEX wfx;
1194     DSCCAPS dsccaps;
1195     int f, ref;
1196
1197     /* Private dsound.dll: Error: Invalid interface buffer */
1198     trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
1199     rc=DirectSoundCaptureCreate(lpGuid,NULL,NULL);
1200     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate didn't fail: 0x%lx\n",rc);
1201     if (rc==DS_OK) {
1202         ref=IDirectSoundCapture_Release(dsco);
1203         ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
1204     }
1205
1206     rc=DirectSoundCaptureCreate(lpGuid,&dsco,NULL);
1207     ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate failed: 0x%lx\n",rc);
1208     if (rc!=DS_OK)
1209         goto EXIT;
1210
1211     /* Private dsound.dll: Error: Invalid caps buffer */
1212     rc=IDirectSoundCapture_GetCaps(dsco,NULL);
1213     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1214
1215     /* Private dsound.dll: Error: Invalid caps buffer */
1216     dsccaps.dwSize=0;
1217     rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
1218     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
1219
1220     dsccaps.dwSize=sizeof(dsccaps);
1221     rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
1222     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
1223     if (rc==DS_OK) {
1224         trace("  DirectSoundCapture Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n",
1225               dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,dsccaps.dwChannels);
1226     }
1227
1228     /* Private dsound.dll: Error: Invalid size */
1229     /* Private dsound.dll: Error: Invalid capture buffer description */
1230     ZeroMemory(&bufdesc, sizeof(bufdesc));
1231     bufdesc.dwSize=0;
1232     bufdesc.dwFlags=0;
1233     bufdesc.dwBufferBytes=0;
1234     bufdesc.dwReserved=0;
1235     bufdesc.lpwfxFormat=NULL;
1236     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1237     ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1238     if (rc==DS_OK) {
1239         ref=IDirectSoundCaptureBuffer_Release(dscbo);
1240         ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1241     }
1242
1243     /* Private dsound.dll: Error: Invalid buffer size */
1244     /* Private dsound.dll: Error: Invalid capture buffer description */
1245     ZeroMemory(&bufdesc, sizeof(bufdesc));
1246     bufdesc.dwSize=sizeof(bufdesc);
1247     bufdesc.dwFlags=0;
1248     bufdesc.dwBufferBytes=0;
1249     bufdesc.dwReserved=0;
1250     bufdesc.lpwfxFormat=NULL;
1251     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1252     ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1253     if (rc==DS_OK) {
1254         ref=IDirectSoundCaptureBuffer_Release(dscbo);
1255         ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1256     }
1257
1258     /* Private dsound.dll: Error: Invalid buffer size */
1259     /* Private dsound.dll: Error: Invalid capture buffer description */
1260     ZeroMemory(&bufdesc, sizeof(bufdesc));
1261     ZeroMemory(&wfx, sizeof(wfx));
1262     bufdesc.dwSize=sizeof(bufdesc);
1263     bufdesc.dwFlags=0;
1264     bufdesc.dwBufferBytes=0;
1265     bufdesc.dwReserved=0;
1266     bufdesc.lpwfxFormat=&wfx;
1267     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1268     ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1269     if (rc==DS_OK) {
1270         ref=IDirectSoundCaptureBuffer_Release(dscbo);
1271         ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1272     }
1273
1274     /* Private dsound.dll: Error: Invalid buffer size */
1275     /* Private dsound.dll: Error: Invalid capture buffer description */
1276     init_format(&wfx,11025,8,1);
1277     ZeroMemory(&bufdesc, sizeof(bufdesc));
1278     bufdesc.dwSize=sizeof(bufdesc);
1279     bufdesc.dwFlags=0;
1280     bufdesc.dwBufferBytes=0;
1281     bufdesc.dwReserved=0;
1282     bufdesc.lpwfxFormat=&wfx;
1283     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1284     ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
1285     if (rc==DS_OK) {
1286         ref=IDirectSoundCaptureBuffer_Release(dscbo);
1287         ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1288     }
1289
1290     for (f=0;f<NB_FORMATS;f++) {
1291         init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
1292         ZeroMemory(&bufdesc, sizeof(bufdesc));
1293         bufdesc.dwSize=sizeof(bufdesc);
1294         bufdesc.dwFlags=0;
1295         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
1296         bufdesc.dwReserved=0;
1297         bufdesc.lpwfxFormat=&wfx;
1298         trace("  Testing the capture buffer at %ldx%dx%d\n",
1299             wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
1300         rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1301         ok(rc==DS_OK,"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc);
1302         if (rc==DS_OK) {
1303             test_capture_buffer(dsco, dscbo, winetest_interactive);
1304             ref=IDirectSoundCaptureBuffer_Release(dscbo);
1305             ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
1306         }
1307     }
1308
1309     /* Try an invalid format to test error handling */
1310 #if 0
1311     init_format(&wfx,2000000,16,2);
1312     ZeroMemory(&bufdesc, sizeof(bufdesc));
1313     bufdesc.dwSize=sizeof(bufdesc);
1314     bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
1315     bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
1316     bufdesc.dwReserved=0;
1317     bufdesc.lpwfxFormat=&wfx;
1318     trace("  Testing the capture buffer at %ldx%dx%d\n",
1319         wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
1320     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
1321     ok(rc!=DS_OK,"CreateCaptureBuffer should have failed at 2 MHz 0x%lx\n",rc);
1322 #endif
1323
1324 EXIT:
1325     if (dsco!=NULL) {
1326         ref=IDirectSoundCapture_Release(dsco);
1327         ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
1328     }
1329
1330     return TRUE;
1331 }
1332
1333 static void dsound_in_tests()
1334 {
1335     HRESULT rc;
1336     rc=DirectSoundCaptureEnumerateA(&dscenum_callback,NULL);
1337     ok(rc==DS_OK,"DirectSoundCaptureEnumerate failed: %ld\n",rc);
1338 }
1339
1340 START_TEST(dsound)
1341 {
1342     dsound_out_tests();
1343     dsound_in_tests();
1344 }