Replace a few more direct lpVtbl accesses by the proper macros.
[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 <stdio.h>
27
28 #include "wine/test.h"
29 #include "dsound.h"
30 #include "mmreg.h"
31 #include "dxerr8.h"
32 #include "dsconf.h"
33
34 #include "dsound_test.h"
35
36 #define NOTIFICATIONS    5
37
38 static HRESULT (WINAPI *pDirectSoundCaptureCreate)(LPCGUID,LPDIRECTSOUNDCAPTURE*,LPUNKNOWN)=NULL;
39 static HRESULT (WINAPI *pDirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
40
41 static const char * get_format_str(WORD format)
42 {
43     static char msg[32];
44 #define WAVE_FORMAT(f) case f: return #f
45     switch (format) {
46     WAVE_FORMAT(WAVE_FORMAT_PCM);
47     WAVE_FORMAT(WAVE_FORMAT_ADPCM);
48     WAVE_FORMAT(WAVE_FORMAT_IBM_CVSD);
49     WAVE_FORMAT(WAVE_FORMAT_ALAW);
50     WAVE_FORMAT(WAVE_FORMAT_MULAW);
51     WAVE_FORMAT(WAVE_FORMAT_OKI_ADPCM);
52     WAVE_FORMAT(WAVE_FORMAT_IMA_ADPCM);
53     WAVE_FORMAT(WAVE_FORMAT_MEDIASPACE_ADPCM);
54     WAVE_FORMAT(WAVE_FORMAT_SIERRA_ADPCM);
55     WAVE_FORMAT(WAVE_FORMAT_G723_ADPCM);
56     WAVE_FORMAT(WAVE_FORMAT_DIGISTD);
57     WAVE_FORMAT(WAVE_FORMAT_DIGIFIX);
58     WAVE_FORMAT(WAVE_FORMAT_DIALOGIC_OKI_ADPCM);
59     WAVE_FORMAT(WAVE_FORMAT_YAMAHA_ADPCM);
60     WAVE_FORMAT(WAVE_FORMAT_SONARC);
61     WAVE_FORMAT(WAVE_FORMAT_DSPGROUP_TRUESPEECH);
62     WAVE_FORMAT(WAVE_FORMAT_ECHOSC1);
63     WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF36);
64     WAVE_FORMAT(WAVE_FORMAT_APTX);
65     WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF10);
66     WAVE_FORMAT(WAVE_FORMAT_DOLBY_AC2);
67     WAVE_FORMAT(WAVE_FORMAT_GSM610);
68     WAVE_FORMAT(WAVE_FORMAT_ANTEX_ADPCME);
69     WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_VQLPC);
70     WAVE_FORMAT(WAVE_FORMAT_DIGIREAL);
71     WAVE_FORMAT(WAVE_FORMAT_DIGIADPCM);
72     WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_CR10);
73     WAVE_FORMAT(WAVE_FORMAT_NMS_VBXADPCM);
74     WAVE_FORMAT(WAVE_FORMAT_G721_ADPCM);
75     WAVE_FORMAT(WAVE_FORMAT_MPEG);
76     WAVE_FORMAT(WAVE_FORMAT_MPEGLAYER3);
77     WAVE_FORMAT(WAVE_FORMAT_CREATIVE_ADPCM);
78     WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH8);
79     WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH10);
80     WAVE_FORMAT(WAVE_FORMAT_FM_TOWNS_SND);
81     WAVE_FORMAT(WAVE_FORMAT_OLIGSM);
82     WAVE_FORMAT(WAVE_FORMAT_OLIADPCM);
83     WAVE_FORMAT(WAVE_FORMAT_OLICELP);
84     WAVE_FORMAT(WAVE_FORMAT_OLISBC);
85     WAVE_FORMAT(WAVE_FORMAT_OLIOPR);
86     WAVE_FORMAT(WAVE_FORMAT_DEVELOPMENT);
87     WAVE_FORMAT(WAVE_FORMAT_EXTENSIBLE);
88     }
89 #undef WAVE_FORMAT
90     sprintf(msg, "Unknown(0x%04x)", format);
91     return msg;
92 }
93
94 static char * format_string(WAVEFORMATEX* wfx)
95 {
96     static char str[64];
97
98     sprintf(str, "%5ldx%2dx%d %s",
99         wfx->nSamplesPerSec, wfx->wBitsPerSample, wfx->nChannels,
100         get_format_str(wfx->wFormatTag));
101
102     return str;
103 }
104
105 static void IDirectSoundCapture_test(LPDIRECTSOUNDCAPTURE dsco,
106                                      BOOL initialized, LPCGUID lpGuid)
107 {
108     HRESULT rc;
109     DSCCAPS dsccaps;
110     int ref;
111     IUnknown * unknown;
112     IDirectSoundCapture * dsc;
113
114     /* Try to Query for objects */
115     rc=IDirectSoundCapture_QueryInterface(dsco, &IID_IUnknown,
116                                           (LPVOID*)&unknown);
117     ok(rc==DS_OK, "IDirectSoundCapture_QueryInterface(IID_IUnknown) "
118        "failed: %s\n", DXGetErrorString8(rc));
119     if (rc==DS_OK)
120         IDirectSoundCapture_Release(unknown);
121
122     rc=IDirectSoundCapture_QueryInterface(dsco, &IID_IDirectSoundCapture,
123                                           (LPVOID*)&dsc);
124     ok(rc==DS_OK, "IDirectSoundCapture_QueryInterface(IID_IDirectSoundCapture) "
125        "failed: %s\n", DXGetErrorString8(rc));
126     if (rc==DS_OK)
127         IDirectSoundCapture_Release(dsc);
128
129     if (initialized == FALSE) {
130         /* try unitialized object */
131         rc=IDirectSoundCapture_GetCaps(dsco,0);
132         ok(rc==DSERR_UNINITIALIZED, "IDirectSoundCapture_GetCaps(NULL) "
133            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
134            DXGetErrorString8(rc));
135
136         rc=IDirectSoundCapture_GetCaps(dsco, &dsccaps);
137         ok(rc==DSERR_UNINITIALIZED,"IDirectSoundCapture_GetCaps() "
138            "should have returned DSERR_UNINITIALIZED, returned: %s\n",
139            DXGetErrorString8(rc));
140
141         rc=IDirectSoundCapture_Initialize(dsco, lpGuid);
142         ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
143            "IDirectSoundCapture_Initialize() failed: %s\n",
144            DXGetErrorString8(rc));
145         if (rc==DSERR_NODRIVER) {
146             trace("  No Driver\n");
147             goto EXIT;
148         } else if (rc==E_FAIL) {
149             trace("  No Device\n");
150             goto EXIT;
151         } else if (rc==DSERR_ALLOCATED) {
152             trace("  Already In Use\n");
153             goto EXIT;
154         }
155     }
156
157     rc=IDirectSoundCapture_Initialize(dsco, lpGuid);
158     ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSoundCapture_Initialize() "
159        "should have returned DSERR_ALREADYINITIALIZED: %s\n",
160        DXGetErrorString8(rc));
161
162     /* DSOUND: Error: Invalid caps buffer */
163     rc=IDirectSoundCapture_GetCaps(dsco, 0);
164     ok(rc==DSERR_INVALIDPARAM, "IDirectSoundCapture_GetCaps(NULL) "
165        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
166        DXGetErrorString8(rc));
167
168     ZeroMemory(&dsccaps, sizeof(dsccaps));
169
170     /* DSOUND: Error: Invalid caps buffer */
171     rc=IDirectSound_GetCaps(dsco, &dsccaps);
172     ok(rc==DSERR_INVALIDPARAM, "IDirectSound_GetCaps() "
173        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
174        DXGetErrorString8(rc));
175
176     dsccaps.dwSize=sizeof(dsccaps);
177
178     /* DSOUND: Running on a certified driver */
179     rc=IDirectSoundCapture_GetCaps(dsco, &dsccaps);
180     ok(rc==DS_OK, "IDirectSoundCapture_GetCaps() failed: %s\n",
181        DXGetErrorString8(rc));
182
183 EXIT:
184     ref=IDirectSoundCapture_Release(dsco);
185     ok(ref==0, "IDirectSoundCapture_Release() has %d references, "
186        "should have 0\n", ref);
187 }
188
189 static void IDirectSoundCapture_tests(void)
190 {
191     HRESULT rc;
192     LPDIRECTSOUNDCAPTURE dsco=NULL;
193
194     trace("Testing IDirectSoundCapture\n");
195
196     /* try the COM class factory method of creation with no device specified */
197     rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
198                         &IID_IDirectSoundCapture, (void**)&dsco);
199     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSoundCapture) failed: %s\n",
200        DXGetErrorString8(rc));
201     if (dsco)
202         IDirectSoundCapture_test(dsco, FALSE, NULL);
203
204     /* try the COM class factory method of creation with default capture
205      * device specified */
206     rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
207                         &IID_IDirectSoundCapture, (void**)&dsco);
208     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSoundCapture) failed: %s\n",
209        DXGetErrorString8(rc));
210     if (dsco)
211         IDirectSoundCapture_test(dsco, FALSE, &DSDEVID_DefaultCapture);
212
213     /* try the COM class factory method of creation with default voice
214      * capture device specified */
215     rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
216                         &IID_IDirectSoundCapture, (void**)&dsco);
217     ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSoundCapture) failed: %s\n",
218        DXGetErrorString8(rc));
219     if (dsco)
220         IDirectSoundCapture_test(dsco, FALSE, &DSDEVID_DefaultVoiceCapture);
221
222     /* try the COM class factory method of creation with a bad
223      * IID specified */
224     rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
225                         &CLSID_DirectSoundPrivate, (void**)&dsco);
226     ok(rc==E_NOINTERFACE,
227        "CoCreateInstance(CLSID_DirectSoundCapture,CLSID_DirectSoundPrivate) "
228        "should have failed: %s\n",DXGetErrorString8(rc));
229
230     /* try with no device specified */
231     rc=pDirectSoundCaptureCreate(NULL,&dsco,NULL);
232     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
233        "DirectSoundCaptureCreate(NULL) failed: %s\n",DXGetErrorString8(rc));
234     if (rc==S_OK && dsco)
235         IDirectSoundCapture_test(dsco, TRUE, NULL);
236
237     /* try with default capture device specified */
238     rc=pDirectSoundCaptureCreate(&DSDEVID_DefaultCapture,&dsco,NULL);
239     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
240        "DirectSoundCaptureCreate(DSDEVID_DefaultCapture) failed: %s\n",
241        DXGetErrorString8(rc));
242     if (rc==DS_OK && dsco)
243         IDirectSoundCapture_test(dsco, TRUE, NULL);
244
245     /* try with default voice capture device specified */
246     rc=pDirectSoundCaptureCreate(&DSDEVID_DefaultVoiceCapture,&dsco,NULL);
247     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
248        "DirectSoundCaptureCreate(DSDEVID_DefaultVoiceCapture) failed: %s\n",
249        DXGetErrorString8(rc));
250     if (rc==DS_OK && dsco)
251         IDirectSoundCapture_test(dsco, TRUE, NULL);
252
253     /* try with a bad device specified */
254     rc=pDirectSoundCaptureCreate(&DSDEVID_DefaultVoicePlayback,&dsco,NULL);
255     ok(rc==DSERR_NODRIVER,
256        "DirectSoundCaptureCreate(DSDEVID_DefaultVoicePlatback) "
257        "should have failed: %s\n",DXGetErrorString8(rc));
258     if (rc==DS_OK && dsco)
259         IDirectSoundCapture_Release(dsco);
260 }
261
262 typedef struct {
263     char* wave;
264     DWORD wave_len;
265
266     LPDIRECTSOUNDCAPTUREBUFFER dscbo;
267     LPWAVEFORMATEX wfx;
268     DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS];
269     HANDLE event[NOTIFICATIONS];
270     LPDIRECTSOUNDNOTIFY notify;
271
272     DWORD buffer_size;
273     DWORD read;
274     DWORD offset;
275     DWORD size;
276
277     DWORD last_pos;
278 } capture_state_t;
279
280 static int capture_buffer_service(capture_state_t* state)
281 {
282     HRESULT rc;
283     LPVOID ptr1,ptr2;
284     DWORD len1,len2;
285     DWORD capture_pos,read_pos;
286
287     rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,
288                                                     &read_pos);
289     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCurrentPosition() failed: %s\n",
290        DXGetErrorString8(rc));
291     if (rc!=DS_OK)
292         return 0;
293
294     rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,
295                                       &ptr1,&len1,&ptr2,&len2,0);
296     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Lock() failed: %s\n",
297        DXGetErrorString8(rc));
298     if (rc!=DS_OK)
299         return 0;
300
301     rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
302     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Unlock() failed: %s\n",
303        DXGetErrorString8(rc));
304     if (rc!=DS_OK)
305         return 0;
306
307     state->offset = (state->offset + state->size) % state->buffer_size;
308
309     return 1;
310 }
311
312 static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco,
313                                 LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
314 {
315     HRESULT rc;
316     DSCBCAPS dscbcaps;
317     WAVEFORMATEX wfx;
318     DWORD size,status;
319     capture_state_t state;
320     int i, ref;
321
322     /* Private dsound.dll: Error: Invalid caps pointer */
323     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0);
324     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should "
325        "have returned DSERR_INVALIDPARAM, returned: %s\n",
326        DXGetErrorString8(rc));
327
328     /* Private dsound.dll: Error: Invalid caps pointer */
329     dscbcaps.dwSize=0;
330     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
331     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should "
332        "have returned DSERR_INVALIDPARAM, returned: %s\n",
333        DXGetErrorString8(rc));
334
335     dscbcaps.dwSize=sizeof(dscbcaps);
336     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
337     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCaps() failed: %s\n",
338        DXGetErrorString8(rc));
339     if (rc==DS_OK && winetest_debug > 1) {
340         trace("    Caps: size = %ld flags=0x%08lx buffer size=%ld\n",
341             dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
342     }
343
344     /* Query the format size. Note that it may not match sizeof(wfx) */
345     /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must
346      * be non-NULL */
347     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL);
348     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetFormat() should "
349        "have returned DSERR_INVALIDPARAM, returned: %s\n",
350        DXGetErrorString8(rc));
351
352     size=0;
353     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size);
354     ok(rc==DS_OK && size!=0,"IDirectSoundCaptureBuffer_GetFormat() should "
355        "have returned the needed size: rc=%s, size=%ld\n",
356        DXGetErrorString8(rc),size);
357
358     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
359     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetFormat() failed: %s\n",
360        DXGetErrorString8(rc));
361     if (rc==DS_OK && winetest_debug > 1) {
362         trace("    Format: tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
363               wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
364               wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
365     }
366
367     /* Private dsound.dll: Error: Invalid status pointer */
368     rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0);
369     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetStatus() should "
370        "have returned DSERR_INVALIDPARAM, returned: %s\n",
371        DXGetErrorString8(rc));
372
373     rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
374     ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %s\n",
375        DXGetErrorString8(rc));
376     if (rc==DS_OK && winetest_debug > 1) {
377         trace("    Status=0x%04lx\n",status);
378     }
379
380     ZeroMemory(&state, sizeof(state));
381     state.dscbo=dscbo;
382     state.wfx=&wfx;
383     state.buffer_size = dscbcaps.dwBufferBytes;
384     for (i = 0; i < NOTIFICATIONS; i++)
385         state.event[i] = CreateEvent( NULL, FALSE, FALSE, NULL );
386     state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS;
387
388     rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify,
389                                                 (void **)&(state.notify));
390     ok((rc==DS_OK)&&(state.notify!=NULL),
391        "IDirectSoundCaptureBuffer_QueryInterface() failed: %s\n",
392        DXGetErrorString8(rc));
393     if (rc!=DS_OK)
394         return;
395
396     for (i = 0; i < NOTIFICATIONS; i++) {
397         state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
398         state.posnotify[i].hEventNotify = state.event[i];
399     }
400
401     rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,
402                                                    state.posnotify);
403     ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions() failed: %s\n",
404        DXGetErrorString8(rc));
405     if (rc!=DS_OK)
406         return;
407
408     ref=IDirectSoundNotify_Release(state.notify);
409     ok(ref==0,"IDirectSoundNotify_Release(): has %d references, should have "
410        "0\n",ref);
411     if (ref!=0)
412         return;
413
414     if (record) {
415         rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
416         ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Start() failed: %s\n",
417            DXGetErrorString8(rc));
418         if (rc!=DS_OK)
419             return;
420
421         rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
422         ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %s\n",
423            DXGetErrorString8(rc));
424         ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
425            "GetStatus: bad status: %lx\n",status);
426         if (rc!=DS_OK)
427             return;
428
429         /* wait for the notifications */
430         for (i = 0; i < (NOTIFICATIONS * 2); i++) {
431             rc=WaitForMultipleObjects(NOTIFICATIONS,state.event,FALSE,3000);
432             ok(rc==(WAIT_OBJECT_0+(i%NOTIFICATIONS)),
433                "WaitForMultipleObjects failed: 0x%lx\n",rc);
434             if (rc!=(WAIT_OBJECT_0+(i%NOTIFICATIONS))) {
435                 ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED),
436                    "Wrong notification: should be %d, got %ld\n",
437                     i%NOTIFICATIONS,rc-WAIT_OBJECT_0);
438             }
439             if (!capture_buffer_service(&state))
440                 break;
441         }
442
443         rc=IDirectSoundCaptureBuffer_Stop(dscbo);
444         ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Stop() failed: %s\n",
445            DXGetErrorString8(rc));
446         if (rc!=DS_OK)
447             return;
448     }
449 }
450
451 static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
452                                     LPCSTR lpcstrModule, LPVOID lpContext)
453 {
454     HRESULT rc;
455     LPDIRECTSOUNDCAPTURE dsco=NULL;
456     LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL;
457     DSCBUFFERDESC bufdesc;
458     WAVEFORMATEX wfx;
459     DSCCAPS dsccaps;
460     DWORD f;
461     int ref;
462
463     /* Private dsound.dll: Error: Invalid interface buffer */
464     trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
465     rc=pDirectSoundCaptureCreate(lpGuid,NULL,NULL);
466     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate() should have "
467        "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
468     if (rc==DS_OK) {
469         ref=IDirectSoundCapture_Release(dsco);
470         ok(ref==0,"IDirectSoundCapture_Release() has %d references, should "
471            "have 0\n",ref);
472     }
473
474     rc=pDirectSoundCaptureCreate(lpGuid,&dsco,NULL);
475     ok((rc==DS_OK)||(rc==DSERR_NODRIVER)||(rc==E_FAIL)||(rc==DSERR_ALLOCATED),
476        "DirectSoundCaptureCreate() failed: %s\n",DXGetErrorString8(rc));
477     if (rc!=DS_OK) {
478         if (rc==DSERR_NODRIVER)
479             trace("  No Driver\n");
480         else if (rc==E_FAIL)
481             trace("  No Device\n");
482         else if (rc==DSERR_ALLOCATED)
483             trace("  Already In Use\n");
484         goto EXIT;
485     }
486
487     /* Private dsound.dll: Error: Invalid caps buffer */
488     rc=IDirectSoundCapture_GetCaps(dsco,NULL);
489     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_GetCaps() should have "
490        "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
491
492     /* Private dsound.dll: Error: Invalid caps buffer */
493     dsccaps.dwSize=0;
494     rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
495     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_GetCaps() should have "
496        "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
497
498     dsccaps.dwSize=sizeof(dsccaps);
499     rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
500     ok(rc==DS_OK,"IDirectSoundCapture_GetCaps() failed: %s\n",
501        DXGetErrorString8(rc));
502     if (rc==DS_OK && winetest_debug > 1) {
503         trace("  Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n",
504               dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,
505               dsccaps.dwChannels);
506     }
507
508     /* Private dsound.dll: Error: Invalid size */
509     /* Private dsound.dll: Error: Invalid capture buffer description */
510     ZeroMemory(&bufdesc, sizeof(bufdesc));
511     bufdesc.dwSize=0;
512     bufdesc.dwFlags=0;
513     bufdesc.dwBufferBytes=0;
514     bufdesc.dwReserved=0;
515     bufdesc.lpwfxFormat=NULL;
516     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
517     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
518        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
519        DXGetErrorString8(rc));
520     if (rc==DS_OK) {
521         ref=IDirectSoundCaptureBuffer_Release(dscbo);
522         ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
523            "should have 0\n",ref);
524     }
525
526     /* Private dsound.dll: Error: Invalid buffer size */
527     /* Private dsound.dll: Error: Invalid capture buffer description */
528     ZeroMemory(&bufdesc, sizeof(bufdesc));
529     bufdesc.dwSize=sizeof(bufdesc);
530     bufdesc.dwFlags=0;
531     bufdesc.dwBufferBytes=0;
532     bufdesc.dwReserved=0;
533     bufdesc.lpwfxFormat=NULL;
534     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
535     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
536        "should have returned DSERR_INVALIDPARAM, returned %s\n",
537        DXGetErrorString8(rc));
538     if (rc==DS_OK) {
539         ref=IDirectSoundCaptureBuffer_Release(dscbo);
540         ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
541            "should have 0\n",ref);
542     }
543
544     /* Private dsound.dll: Error: Invalid buffer size */
545     /* Private dsound.dll: Error: Invalid capture buffer description */
546     ZeroMemory(&bufdesc, sizeof(bufdesc));
547     ZeroMemory(&wfx, sizeof(wfx));
548     bufdesc.dwSize=sizeof(bufdesc);
549     bufdesc.dwFlags=0;
550     bufdesc.dwBufferBytes=0;
551     bufdesc.dwReserved=0;
552     bufdesc.lpwfxFormat=&wfx;
553     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
554     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
555        "should have returned DSERR_INVALIDPARAM, returned :%s\n",
556        DXGetErrorString8(rc));
557     if (rc==DS_OK) {
558         ref=IDirectSoundCaptureBuffer_Release(dscbo);
559         ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
560            "should have 0\n",ref);
561     }
562
563     /* Private dsound.dll: Error: Invalid buffer size */
564     /* Private dsound.dll: Error: Invalid capture buffer description */
565     init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
566     ZeroMemory(&bufdesc, sizeof(bufdesc));
567     bufdesc.dwSize=sizeof(bufdesc);
568     bufdesc.dwFlags=0;
569     bufdesc.dwBufferBytes=0;
570     bufdesc.dwReserved=0;
571     bufdesc.lpwfxFormat=&wfx;
572     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
573     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
574        "should have returned DSERR_INVALIDPARAM, returned: %s\n",
575        DXGetErrorString8(rc));
576     if (rc==DS_OK) {
577         ref=IDirectSoundCaptureBuffer_Release(dscbo);
578         ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
579            "should have 0\n",ref);
580     }
581
582     for (f=0;f<NB_FORMATS;f++) {
583         dscbo=NULL;
584         init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
585                     formats[f][2]);
586         ZeroMemory(&bufdesc, sizeof(bufdesc));
587         bufdesc.dwSize=sizeof(bufdesc);
588         bufdesc.dwFlags=0;
589         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
590         bufdesc.dwReserved=0;
591         bufdesc.lpwfxFormat=&wfx;
592         if (winetest_interactive)
593             trace("  Testing the capture buffer at %s\n", format_string(&wfx));
594         rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
595         ok(((rc==DS_OK)&&(dscbo!=NULL))||(rc==DSERR_BADFORMAT)||
596            ((rc==DSERR_NODRIVER))||(rc==DSERR_ALLOCATED)||(rc==E_INVALIDARG),
597            "IDirectSoundCapture_CreateCaptureBuffer() failed to create a "
598            "%s capture buffer: %s\n",format_string(&wfx),DXGetErrorString8(rc));
599         if (rc==DS_OK) {
600             test_capture_buffer(dsco, dscbo, winetest_interactive);
601             ref=IDirectSoundCaptureBuffer_Release(dscbo);
602             ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
603                "should have 0\n",ref);
604         } else if (rc==DSERR_BADFORMAT) {
605             ok(!(dsccaps.dwFormats & formats[f][3]),
606                "IDirectSoundCapture_CreateCaptureBuffer() failed to create a "
607                "capture buffer: format listed as supported but using it failed\n");
608             if (!(dsccaps.dwFormats & formats[f][3]))
609                 trace("  Format not supported: %s\n", format_string(&wfx));
610         } else if (rc==DSERR_NODRIVER) {
611             trace("  No Driver\n");
612         } else if (rc==DSERR_ALLOCATED) {
613             trace("  Already In Use\n");
614         } else if (rc==E_INVALIDARG) { /* try the old version struct */
615             DSCBUFFERDESC1 bufdesc1;
616             ZeroMemory(&bufdesc1, sizeof(bufdesc1));
617             bufdesc1.dwSize=sizeof(bufdesc1);
618             bufdesc1.dwFlags=0;
619             bufdesc1.dwBufferBytes=wfx.nAvgBytesPerSec;
620             bufdesc1.dwReserved=0;
621             bufdesc1.lpwfxFormat=&wfx;
622             rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,
623                 (DSCBUFFERDESC*)&bufdesc1,&dscbo,NULL);
624             ok(rc==DS_OK,
625                "IDirectSoundCapture_CreateCaptureBuffer() failed to create a "
626                "%s capture buffer: %s\n",format_string(&wfx),
627                DXGetErrorString8(rc));
628             if (rc==DS_OK) {
629                 test_capture_buffer(dsco, dscbo, winetest_interactive);
630                 ref=IDirectSoundCaptureBuffer_Release(dscbo);
631                 ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d "
632                    "references, should have 0\n",ref);
633             }
634         }
635     }
636
637     /* try a non PCM format */
638 #if 0
639     init_format(&wfx,WAVE_FORMAT_MULAW,8000,8,1);
640     ZeroMemory(&bufdesc, sizeof(bufdesc));
641     bufdesc.dwSize=sizeof(bufdesc);
642     bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
643     bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
644     bufdesc.dwReserved=0;
645     bufdesc.lpwfxFormat=&wfx;
646     if (winetest_interactive)
647         trace("  Testing the capture buffer at %s\n", format_string(&wfx));
648     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
649     ok((rc==DS_OK)&&(dscbo!=NULL),"IDirectSoundCapture_CreateCaptureBuffer() "
650        "failed to create a capture buffer: %s\n",DXGetErrorString8(rc));
651     if ((rc==DS_OK)&&(dscbo!=NULL)) {
652         test_capture_buffer(dsco, dscbo, winetest_interactive);
653         ref=IDirectSoundCaptureBuffer_Release(dscbo);
654         ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
655            "should have 0\n",ref);
656     }
657 #endif
658
659     /* Try an invalid format to test error handling */
660 #if 0
661     init_format(&wfx,WAVE_FORMAT_PCM,2000000,16,2);
662     ZeroMemory(&bufdesc, sizeof(bufdesc));
663     bufdesc.dwSize=sizeof(bufdesc);
664     bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
665     bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
666     bufdesc.dwReserved=0;
667     bufdesc.lpwfxFormat=&wfx;
668     if (winetest_interactive)
669         trace("  Testing the capture buffer at %s\n", format_string(&wfx));
670     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
671     ok(rc!=DS_OK,"IDirectSoundCapture_CreateCaptureBuffer() should have failed "
672        "at 2 MHz %s\n",DXGetErrorString8(rc));
673 #endif
674
675 EXIT:
676     if (dsco!=NULL) {
677         ref=IDirectSoundCapture_Release(dsco);
678         ok(ref==0,"IDirectSoundCapture_Release() has %d references, should "
679            "have 0\n",ref);
680     }
681
682     return TRUE;
683 }
684
685 static void capture_tests(void)
686 {
687     HRESULT rc;
688     rc=pDirectSoundCaptureEnumerateA(&dscenum_callback,NULL);
689     ok(rc==DS_OK,"DirectSoundCaptureEnumerateA() failed: %s\n",
690        DXGetErrorString8(rc));
691 }
692
693 START_TEST(capture)
694 {
695     HMODULE hDsound;
696
697     CoInitialize(NULL);
698
699     hDsound = LoadLibraryA("dsound.dll");
700     if (!hDsound) {
701         trace("dsound.dll not found\n");
702         return;
703     }
704
705     trace("DLL Version: %s\n", get_file_version("dsound.dll"));
706
707     pDirectSoundCaptureCreate=(void*)GetProcAddress(hDsound,"DirectSoundCaptureCreate");
708     pDirectSoundCaptureEnumerateA=(void*)GetProcAddress(hDsound,"DirectSoundCaptureEnumerateA");
709     if (!pDirectSoundCaptureCreate || !pDirectSoundCaptureEnumerateA)
710     {
711         trace("capture test skipped\n");
712         return;
713     }
714
715     IDirectSoundCapture_tests();
716     capture_tests();
717
718     CoUninitialize();
719 }