Don't consider failure with DSERR_NODRIVER a test failure.
[wine] / dlls / dsound / tests / capture.c
1 /*
2  * Unit tests for capture functions
3  *
4  * Copyright (c) 2002 Francois Gouget
5  * Copyright (c) 2003 Robert Reif
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #define NONAMELESSSTRUCT
23 #define NONAMELESSUNION
24 #include <windows.h>
25
26 #include <math.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29
30 #include "wine/test.h"
31 #include "windef.h"
32 #include "wingdi.h"
33 #include "dsound.h"
34 #include "mmreg.h"
35 #include "dxerr8.h"
36
37 #include "dsound_test.h"
38
39 #define NOTIFICATIONS    5
40
41 static HRESULT (WINAPI *pDirectSoundCaptureCreate)(LPCGUID,LPDIRECTSOUNDCAPTURE*,LPUNKNOWN)=NULL;
42 static HRESULT (WINAPI *pDirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
43
44 static const char * get_format_str(WORD format)
45 {
46     static char msg[32];
47 #define WAVE_FORMAT(f) case f: return #f
48     switch (format) {
49     WAVE_FORMAT(WAVE_FORMAT_PCM);
50     WAVE_FORMAT(WAVE_FORMAT_ADPCM);
51     WAVE_FORMAT(WAVE_FORMAT_IBM_CVSD);
52     WAVE_FORMAT(WAVE_FORMAT_ALAW);
53     WAVE_FORMAT(WAVE_FORMAT_MULAW);
54     WAVE_FORMAT(WAVE_FORMAT_OKI_ADPCM);
55     WAVE_FORMAT(WAVE_FORMAT_IMA_ADPCM);
56     WAVE_FORMAT(WAVE_FORMAT_MEDIASPACE_ADPCM);
57     WAVE_FORMAT(WAVE_FORMAT_SIERRA_ADPCM);
58     WAVE_FORMAT(WAVE_FORMAT_G723_ADPCM);
59     WAVE_FORMAT(WAVE_FORMAT_DIGISTD);
60     WAVE_FORMAT(WAVE_FORMAT_DIGIFIX);
61     WAVE_FORMAT(WAVE_FORMAT_DIALOGIC_OKI_ADPCM);
62     WAVE_FORMAT(WAVE_FORMAT_YAMAHA_ADPCM);
63     WAVE_FORMAT(WAVE_FORMAT_SONARC);
64     WAVE_FORMAT(WAVE_FORMAT_DSPGROUP_TRUESPEECH);
65     WAVE_FORMAT(WAVE_FORMAT_ECHOSC1);
66     WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF36);
67     WAVE_FORMAT(WAVE_FORMAT_APTX);
68     WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF10);
69     WAVE_FORMAT(WAVE_FORMAT_DOLBY_AC2);
70     WAVE_FORMAT(WAVE_FORMAT_GSM610);
71     WAVE_FORMAT(WAVE_FORMAT_ANTEX_ADPCME);
72     WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_VQLPC);
73     WAVE_FORMAT(WAVE_FORMAT_DIGIREAL);
74     WAVE_FORMAT(WAVE_FORMAT_DIGIADPCM);
75     WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_CR10);
76     WAVE_FORMAT(WAVE_FORMAT_NMS_VBXADPCM);
77     WAVE_FORMAT(WAVE_FORMAT_G721_ADPCM);
78     WAVE_FORMAT(WAVE_FORMAT_MPEG);
79     WAVE_FORMAT(WAVE_FORMAT_MPEGLAYER3);
80     WAVE_FORMAT(WAVE_FORMAT_CREATIVE_ADPCM);
81     WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH8);
82     WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH10);
83     WAVE_FORMAT(WAVE_FORMAT_FM_TOWNS_SND);
84     WAVE_FORMAT(WAVE_FORMAT_OLIGSM);
85     WAVE_FORMAT(WAVE_FORMAT_OLIADPCM);
86     WAVE_FORMAT(WAVE_FORMAT_OLICELP);
87     WAVE_FORMAT(WAVE_FORMAT_OLISBC);
88     WAVE_FORMAT(WAVE_FORMAT_OLIOPR);
89     WAVE_FORMAT(WAVE_FORMAT_DEVELOPMENT);
90     WAVE_FORMAT(WAVE_FORMAT_EXTENSIBLE);
91     }
92 #undef WAVE_FORMAT
93     sprintf(msg, "Unknown(0x%04x)", format);
94     return msg;
95 }
96
97 static char * format_string(WAVEFORMATEX* wfx)
98 {
99     static char str[64];
100
101     sprintf(str, "%5ldx%2dx%d %s",
102         wfx->nSamplesPerSec, wfx->wBitsPerSample, wfx->nChannels,
103         get_format_str(wfx->wFormatTag));
104
105     return str;
106 }
107
108 typedef struct {
109     char* wave;
110     DWORD wave_len;
111
112     LPDIRECTSOUNDCAPTUREBUFFER dscbo;
113     LPWAVEFORMATEX wfx;
114     DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS];
115     HANDLE event[NOTIFICATIONS];
116     LPDIRECTSOUNDNOTIFY notify;
117
118     DWORD buffer_size;
119     DWORD read;
120     DWORD offset;
121     DWORD size;
122
123     DWORD last_pos;
124 } capture_state_t;
125
126 static int capture_buffer_service(capture_state_t* state)
127 {
128     HRESULT rc;
129     LPVOID ptr1,ptr2;
130     DWORD len1,len2;
131     DWORD capture_pos,read_pos;
132
133     rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,
134                                                     &read_pos);
135     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCurrentPosition() failed: %s\n",
136        DXGetErrorString8(rc));
137     if (rc!=DS_OK)
138         return 0;
139
140     rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,
141                                       &ptr1,&len1,&ptr2,&len2,0);
142     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Lock() failed: %s\n",
143        DXGetErrorString8(rc));
144     if (rc!=DS_OK)
145         return 0;
146
147     rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
148     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Unlock() failed: %s\n",
149        DXGetErrorString8(rc));
150     if (rc!=DS_OK)
151         return 0;
152
153     state->offset = (state->offset + state->size) % state->buffer_size;
154
155     return 1;
156 }
157
158 static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco,
159                                 LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
160 {
161     HRESULT rc;
162     DSCBCAPS dscbcaps;
163     WAVEFORMATEX wfx;
164     DWORD size,status;
165     capture_state_t state;
166     int i, ref;
167
168     /* Private dsound.dll: Error: Invalid caps pointer */
169     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0);
170     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should "
171        "have returned DSERR_INVALIDPARAM, returned: %s\n",
172        DXGetErrorString8(rc));
173
174     /* Private dsound.dll: Error: Invalid caps pointer */
175     dscbcaps.dwSize=0;
176     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
177     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should "
178        "have returned DSERR_INVALIDPARAM, returned: %s\n",
179        DXGetErrorString8(rc));
180
181     dscbcaps.dwSize=sizeof(dscbcaps);
182     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
183     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCaps() failed: %s\n",
184        DXGetErrorString8(rc));
185     if (rc==DS_OK && winetest_debug > 1) {
186         trace("    Caps: size = %ld flags=0x%08lx buffer size=%ld\n",
187             dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
188     }
189
190     /* Query the format size. Note that it may not match sizeof(wfx) */
191     /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must
192      * be non-NULL */
193     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL);
194     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetFormat() should "
195        "have returned DSERR_INVALIDPARAM, returned: %s\n",
196        DXGetErrorString8(rc));
197
198     size=0;
199     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size);
200     ok(rc==DS_OK && size!=0,"IDirectSoundCaptureBuffer_GetFormat() should "
201        "have returned the needed size: rc=%s, size=%ld\n",
202        DXGetErrorString8(rc),size);
203
204     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
205     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetFormat() failed: %s\n",
206        DXGetErrorString8(rc));
207     if (rc==DS_OK && winetest_debug > 1) {
208         trace("    Format: tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
209               wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
210               wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
211     }
212
213     /* Private dsound.dll: Error: Invalid status pointer */
214     rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0);
215     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetStatus() should "
216        "have returned DSERR_INVALIDPARAM, returned: %s\n",
217        DXGetErrorString8(rc));
218
219     rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
220     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %s\n",
221        DXGetErrorString8(rc));
222     if (rc==DS_OK && winetest_debug > 1) {
223         trace("    Status=0x%04lx\n",status);
224     }
225
226     ZeroMemory(&state, sizeof(state));
227     state.dscbo=dscbo;
228     state.wfx=&wfx;
229     state.buffer_size = dscbcaps.dwBufferBytes;
230     for (i = 0; i < NOTIFICATIONS; i++)
231         state.event[i] = CreateEvent( NULL, FALSE, FALSE, NULL );
232     state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS;
233
234     rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify,
235                                                 (void **)&(state.notify));
236     ok((rc==DS_OK)&&(state.notify!=NULL),
237        "IDirectSoundCaptureBuffer_QueryInterface() failed: %s\n",
238        DXGetErrorString8(rc));
239     if (rc!=DS_OK)
240         return;
241
242     for (i = 0; i < NOTIFICATIONS; i++) {
243         state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
244         state.posnotify[i].hEventNotify = state.event[i];
245     }
246
247     rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,
248                                                    state.posnotify);
249     ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions() failed: %s\n",
250        DXGetErrorString8(rc));
251     if (rc!=DS_OK)
252         return;
253
254     ref=IDirectSoundNotify_Release(state.notify);
255     ok(ref==0,"IDirectSoundNotify_Release(): has %d references, should have "
256        "0\n",ref);
257     if (ref!=0)
258         return;
259
260     if (record) {
261         rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
262         ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Start() failed: %s\n",
263            DXGetErrorString8(rc));
264         if (rc!=DS_OK)
265             return;
266
267         rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
268         ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %s\n",
269            DXGetErrorString8(rc));
270         ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
271            "GetStatus: bad status: %lx\n",status);
272         if (rc!=DS_OK)
273             return;
274
275         /* wait for the notifications */
276         for (i = 0; i < (NOTIFICATIONS * 2); i++) {
277             rc=MsgWaitForMultipleObjects(NOTIFICATIONS,state.event,FALSE,
278                                          3000,QS_ALLEVENTS);
279             ok(rc==(WAIT_OBJECT_0+(i%NOTIFICATIONS)),
280                "MsgWaitForMultipleObjects failed: 0x%lx\n",rc);
281             if (rc!=(WAIT_OBJECT_0+(i%NOTIFICATIONS))) {
282                 ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED),
283                    "Wrong notification: should be %d, got %ld\n",
284                     i%NOTIFICATIONS,rc-WAIT_OBJECT_0);
285             }
286             if (!capture_buffer_service(&state))
287                 break;
288         }
289
290         rc=IDirectSoundCaptureBuffer_Stop(dscbo);
291         ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Stop() failed: %s\n",
292            DXGetErrorString8(rc));
293         if (rc!=DS_OK)
294             return;
295     }
296 }
297
298 static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
299                                     LPCSTR lpcstrModule, LPVOID lpContext)
300 {
301     HRESULT rc;
302     LPDIRECTSOUNDCAPTURE dsco=NULL;
303     LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL;
304     DSCBUFFERDESC bufdesc;
305     WAVEFORMATEX wfx;
306     DSCCAPS dsccaps;
307     DWORD f;
308     int ref;
309
310     /* Private dsound.dll: Error: Invalid interface buffer */
311     trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
312     rc=pDirectSoundCaptureCreate(lpGuid,NULL,NULL);
313     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate() should have "
314        "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
315     if (rc==DS_OK) {
316         ref=IDirectSoundCapture_Release(dsco);
317         ok(ref==0,"IDirectSoundCapture_Release() has %d references, should "
318            "have 0\n",ref);
319     }
320
321     rc=pDirectSoundCaptureCreate(lpGuid,&dsco,NULL);
322     ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate() failed: "
323        "%s\n",DXGetErrorString8(rc));
324     if (rc!=DS_OK) {
325         if (rc==DSERR_NODRIVER)
326             trace("  No Driver\n");
327         goto EXIT;
328     }
329
330     /* Private dsound.dll: Error: Invalid caps buffer */
331     rc=IDirectSoundCapture_GetCaps(dsco,NULL);
332     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_GetCaps() should have "
333        "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
334
335     /* Private dsound.dll: Error: Invalid caps buffer */
336     dsccaps.dwSize=0;
337     rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
338     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_GetCaps() should have "
339        "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
340
341     dsccaps.dwSize=sizeof(dsccaps);
342     rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
343     ok(rc==DS_OK,"IDirectSoundCapture_GetCaps() failed: %s\n",
344        DXGetErrorString8(rc));
345     if (rc==DS_OK && winetest_debug > 1) {
346         trace("  Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n",
347               dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,
348               dsccaps.dwChannels);
349     }
350
351     /* Private dsound.dll: Error: Invalid size */
352     /* Private dsound.dll: Error: Invalid capture buffer description */
353     ZeroMemory(&bufdesc, sizeof(bufdesc));
354     bufdesc.dwSize=0;
355     bufdesc.dwFlags=0;
356     bufdesc.dwBufferBytes=0;
357     bufdesc.dwReserved=0;
358     bufdesc.lpwfxFormat=NULL;
359     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
360     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
361        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
362        DXGetErrorString8(rc));
363     if (rc==DS_OK) {
364         ref=IDirectSoundCaptureBuffer_Release(dscbo);
365         ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
366            "should have 0\n",ref);
367     }
368
369     /* Private dsound.dll: Error: Invalid buffer size */
370     /* Private dsound.dll: Error: Invalid capture buffer description */
371     ZeroMemory(&bufdesc, sizeof(bufdesc));
372     bufdesc.dwSize=sizeof(bufdesc);
373     bufdesc.dwFlags=0;
374     bufdesc.dwBufferBytes=0;
375     bufdesc.dwReserved=0;
376     bufdesc.lpwfxFormat=NULL;
377     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
378     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
379        "should have returned DSERR_INVALIDPARAM, returned %s\n",
380        DXGetErrorString8(rc));
381     if (rc==DS_OK) {
382         ref=IDirectSoundCaptureBuffer_Release(dscbo);
383         ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
384            "should have 0\n",ref);
385     }
386
387     /* Private dsound.dll: Error: Invalid buffer size */
388     /* Private dsound.dll: Error: Invalid capture buffer description */
389     ZeroMemory(&bufdesc, sizeof(bufdesc));
390     ZeroMemory(&wfx, sizeof(wfx));
391     bufdesc.dwSize=sizeof(bufdesc);
392     bufdesc.dwFlags=0;
393     bufdesc.dwBufferBytes=0;
394     bufdesc.dwReserved=0;
395     bufdesc.lpwfxFormat=&wfx;
396     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
397     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
398        "should have returned DSERR_INVALIDPARAM, returned :%s\n",
399        DXGetErrorString8(rc));
400     if (rc==DS_OK) {
401         ref=IDirectSoundCaptureBuffer_Release(dscbo);
402         ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
403            "should have 0\n",ref);
404     }
405
406     /* Private dsound.dll: Error: Invalid buffer size */
407     /* Private dsound.dll: Error: Invalid capture buffer description */
408     init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
409     ZeroMemory(&bufdesc, sizeof(bufdesc));
410     bufdesc.dwSize=sizeof(bufdesc);
411     bufdesc.dwFlags=0;
412     bufdesc.dwBufferBytes=0;
413     bufdesc.dwReserved=0;
414     bufdesc.lpwfxFormat=&wfx;
415     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
416     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
417        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
418        DXGetErrorString8(rc));
419     if (rc==DS_OK) {
420         ref=IDirectSoundCaptureBuffer_Release(dscbo);
421         ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
422            "should have 0\n",ref);
423     }
424
425     for (f=0;f<NB_FORMATS;f++) {
426         dscbo=NULL;
427         init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
428                     formats[f][2]);
429         ZeroMemory(&bufdesc, sizeof(bufdesc));
430         bufdesc.dwSize=sizeof(bufdesc);
431         bufdesc.dwFlags=0;
432         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
433         bufdesc.dwReserved=0;
434         bufdesc.lpwfxFormat=&wfx;
435         if (winetest_interactive)
436             trace("  Testing the capture buffer at %s\n", format_string(&wfx));
437         rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
438         ok((rc==DS_OK)&&(dscbo!=NULL),
439            "IDirectSoundCapture_CreateCaptureBuffer() failed to create a "
440            "capture buffer: %s\n",DXGetErrorString8(rc));
441         if (rc==DS_OK) {
442             test_capture_buffer(dsco, dscbo, winetest_interactive);
443             ref=IDirectSoundCaptureBuffer_Release(dscbo);
444             ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
445                "should have 0\n",ref);
446         }
447     }
448
449     /* try a non PCM format */
450 #if 0
451     init_format(&wfx,WAVE_FORMAT_MULAW,8000,8,1);
452     ZeroMemory(&bufdesc, sizeof(bufdesc));
453     bufdesc.dwSize=sizeof(bufdesc);
454     bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
455     bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
456     bufdesc.dwReserved=0;
457     bufdesc.lpwfxFormat=&wfx;
458     if (winetest_interactive)
459         trace("  Testing the capture buffer at %s\n", format_string(&wfx));
460     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
461     ok((rc==DS_OK)&&(dscbo!=NULL),"IDirectSoundCapture_CreateCaptureBuffer() "
462        "failed to create a capture buffer: %s\n",DXGetErrorString8(rc));
463     if ((rc==DS_OK)&&(dscbo!=NULL)) {
464         test_capture_buffer(dsco, dscbo, winetest_interactive);
465         ref=IDirectSoundCaptureBuffer_Release(dscbo);
466         ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
467            "should have 0\n",ref);
468     }
469 #endif
470
471     /* Try an invalid format to test error handling */
472 #if 0
473     init_format(&wfx,WAVE_FORMAT_PCM,2000000,16,2);
474     ZeroMemory(&bufdesc, sizeof(bufdesc));
475     bufdesc.dwSize=sizeof(bufdesc);
476     bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
477     bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
478     bufdesc.dwReserved=0;
479     bufdesc.lpwfxFormat=&wfx;
480     if (winetest_interactive)
481         trace("  Testing the capture buffer at %s\n", format_string(&wfx));
482     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
483     ok(rc!=DS_OK,"IDirectSoundCapture_CreateCaptureBuffer() should have failed "
484        "at 2 MHz %s\n",DXGetErrorString8(rc));
485 #endif
486
487 EXIT:
488     if (dsco!=NULL) {
489         ref=IDirectSoundCapture_Release(dsco);
490         ok(ref==0,"IDirectSoundCapture_Release() has %d references, should "
491            "have 0\n",ref);
492     }
493
494     return TRUE;
495 }
496
497 static void capture_tests()
498 {
499     HRESULT rc;
500     rc=pDirectSoundCaptureEnumerateA(&dscenum_callback,NULL);
501     ok(rc==DS_OK,"DirectSoundCaptureEnumerateA() failed: %s\n",
502        DXGetErrorString8(rc));
503 }
504
505 START_TEST(capture)
506 {
507     HMODULE hDsound;
508
509     hDsound = LoadLibraryA("dsound.dll");
510     if (!hDsound) {
511         trace("dsound.dll not found\n");
512         return;
513     }
514     pDirectSoundCaptureCreate=(void*)GetProcAddress(hDsound,"DirectSoundCaptureCreate");
515     pDirectSoundCaptureEnumerateA=(void*)GetProcAddress(hDsound,"DirectSoundCaptureEnumerateA");
516     if (!pDirectSoundCaptureCreate || !pDirectSoundCaptureEnumerateA)
517     {
518         trace("capture test skipped\n");
519         return;
520     }
521
522     capture_tests();
523 }