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