Implement A->W call for GetNamedSecurityInfo.
[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
42 static char * format_string(WAVEFORMATEX* wfx)
43 {
44     static char str[64];
45
46     sprintf(str, "%ldx%dx%d %s",
47         wfx->nSamplesPerSec, wfx->wBitsPerSample, wfx->nChannels,
48         wfx->wFormatTag == WAVE_FORMAT_PCM ? "PCM" :
49         wfx->wFormatTag == WAVE_FORMAT_MULAW ? "MULAW" :
50         wfx->wFormatTag == WAVE_FORMAT_IMA_ADPCM ? "IMA ADPCM" : "Unknown");
51
52     return str;
53 }
54
55 typedef struct {
56     char* wave;
57     DWORD wave_len;
58
59     LPDIRECTSOUNDCAPTUREBUFFER dscbo;
60     LPWAVEFORMATEX wfx;
61     DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS];
62     HANDLE event[NOTIFICATIONS];
63     LPDIRECTSOUNDNOTIFY notify;
64
65     DWORD buffer_size;
66     DWORD read;
67     DWORD offset;
68     DWORD size;
69
70     DWORD last_pos;
71 } capture_state_t;
72
73 static int capture_buffer_service(capture_state_t* state)
74 {
75     HRESULT rc;
76     LPVOID ptr1,ptr2;
77     DWORD len1,len2;
78     DWORD capture_pos,read_pos;
79
80     rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,&read_pos);
81     ok(rc==DS_OK,"GetCurrentPosition failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
82     if (rc!=DS_OK)
83         return 0;
84
85     rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,&ptr1,&len1,&ptr2,&len2,0);
86     ok(rc==DS_OK,"Lock failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
87     if (rc!=DS_OK)
88         return 0;
89
90     rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
91     ok(rc==DS_OK,"Unlock failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
92     if (rc!=DS_OK)
93         return 0;
94
95     state->offset = (state->offset + state->size) % state->buffer_size;
96
97     return 1;
98 }
99
100 static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, 
101                                 LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
102 {
103     HRESULT rc;
104     DSCBCAPS dscbcaps;
105     WAVEFORMATEX wfx;
106     DWORD size,status;
107     capture_state_t state;
108     int i;
109
110     /* Private dsound.dll: Error: Invalid caps pointer */
111     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0);
112     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
113
114     /* Private dsound.dll: Error: Invalid caps pointer */
115     dscbcaps.dwSize=0;
116     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
117     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
118
119     dscbcaps.dwSize=sizeof(dscbcaps);
120     rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
121     ok(rc==DS_OK,"GetCaps failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
122     if (rc==DS_OK) {
123         trace("    Caps: size = %ld flags=0x%08lx buffer size=%ld\n",
124             dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
125     }
126
127     /* Query the format size. Note that it may not match sizeof(wfx) */
128     /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must be non-NULL */
129     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL);
130     ok(rc==DSERR_INVALIDPARAM,
131        "GetFormat should have returned an error: rc=0x%lx(%s)\n",rc,DXGetErrorString8(rc));
132
133     size=0;
134     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size);
135     ok(rc==DS_OK && size!=0,
136        "GetFormat should have returned the needed size: rc=0x%lx(%s) size=%ld\n",
137        rc,DXGetErrorString8(rc),size);
138
139     rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
140     ok(rc==DS_OK,"GetFormat failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
141     if (rc==DS_OK) {
142         trace("    tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
143               wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
144               wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
145     }
146
147     /* Private dsound.dll: Error: Invalid status pointer */
148     rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0);
149     ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
150
151     rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
152     ok(rc==DS_OK,"GetStatus failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
153     if (rc==DS_OK) {
154         trace("    status=0x%04lx\n",status);
155     }
156
157     ZeroMemory(&state, sizeof(state));
158     state.dscbo=dscbo;
159     state.wfx=&wfx;
160     state.buffer_size = dscbcaps.dwBufferBytes;
161     for (i = 0; i < NOTIFICATIONS; i++)
162         state.event[i] = CreateEvent( NULL, FALSE, FALSE, NULL );
163     state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS;
164
165     rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify,(void **)&(state.notify));
166     ok((rc==DS_OK)&&(state.notify!=NULL),"QueryInterface failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
167     if (rc!=DS_OK)
168         return;
169
170     for (i = 0; i < NOTIFICATIONS; i++) {
171         state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
172         state.posnotify[i].hEventNotify = state.event[i];
173     }
174
175     rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,state.posnotify);
176     ok(rc==DS_OK,"SetNotificationPositions failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
177     if (rc!=DS_OK)
178         return;
179
180     rc=IDirectSoundNotify_Release(state.notify);
181     ok(rc==0,"Release: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
182     if (rc!=0)
183         return;
184
185     if (record) {
186         rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
187         ok(rc==DS_OK,"Start: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
188         if (rc!=DS_OK)
189             return;
190
191         rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
192         ok(rc==DS_OK,"GetStatus failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
193         ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
194            "GetStatus: bad status: %lx\n",status);
195         if (rc!=DS_OK)
196             return;
197
198         /* wait for the notifications */
199         for (i = 0; i < (NOTIFICATIONS * 2); i++) {
200             rc=MsgWaitForMultipleObjects( NOTIFICATIONS, state.event, FALSE, 3000, QS_ALLEVENTS );
201             ok(rc==(WAIT_OBJECT_0+(i%NOTIFICATIONS)),"MsgWaitForMultipleObjects failed: 0x%lx\n",rc);
202             if (rc!=(WAIT_OBJECT_0+(i%NOTIFICATIONS))) {
203                 ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED),"Wrong notification: should be %d, got %ld\n", 
204                     i%NOTIFICATIONS,rc-WAIT_OBJECT_0);
205             }
206             if (!capture_buffer_service(&state))
207                 break;
208         }
209
210         rc=IDirectSoundCaptureBuffer_Stop(dscbo);
211         ok(rc==DS_OK,"Stop: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
212         if (rc!=DS_OK)
213             return;
214     }
215 }
216
217 static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
218                                     LPCSTR lpcstrModule, LPVOID lpContext)
219 {
220     HRESULT rc;
221     LPDIRECTSOUNDCAPTURE dsco=NULL;
222     LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL;
223     DSCBUFFERDESC bufdesc;
224     WAVEFORMATEX wfx;
225     DSCCAPS dsccaps;
226     int f, ref;
227
228     /* Private dsound.dll: Error: Invalid interface buffer */
229     trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
230     rc=DirectSoundCaptureCreate(lpGuid,NULL,NULL);
231     ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate didn't fail: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
232     if (rc==DS_OK) {
233         ref=IDirectSoundCapture_Release(dsco);
234         ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
235     }
236
237     rc=DirectSoundCaptureCreate(lpGuid,&dsco,NULL);
238     ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
239     if (rc!=DS_OK)
240         goto EXIT;
241
242     /* Private dsound.dll: Error: Invalid caps buffer */
243     rc=IDirectSoundCapture_GetCaps(dsco,NULL);
244     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
245
246     /* Private dsound.dll: Error: Invalid caps buffer */
247     dsccaps.dwSize=0;
248     rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
249     ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
250
251     dsccaps.dwSize=sizeof(dsccaps);
252     rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
253     ok(rc==DS_OK,"GetCaps failed: 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
254     if (rc==DS_OK) {
255         trace("  DirectSoundCapture Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n",
256               dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,dsccaps.dwChannels);
257     }
258
259     /* Private dsound.dll: Error: Invalid size */
260     /* Private dsound.dll: Error: Invalid capture buffer description */
261     ZeroMemory(&bufdesc, sizeof(bufdesc));
262     bufdesc.dwSize=0;
263     bufdesc.dwFlags=0;
264     bufdesc.dwBufferBytes=0;
265     bufdesc.dwReserved=0;
266     bufdesc.lpwfxFormat=NULL;
267     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
268     ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
269     if (rc==DS_OK) {
270         ref=IDirectSoundCaptureBuffer_Release(dscbo);
271         ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
272     }
273
274     /* Private dsound.dll: Error: Invalid buffer size */
275     /* Private dsound.dll: Error: Invalid capture buffer description */
276     ZeroMemory(&bufdesc, sizeof(bufdesc));
277     bufdesc.dwSize=sizeof(bufdesc);
278     bufdesc.dwFlags=0;
279     bufdesc.dwBufferBytes=0;
280     bufdesc.dwReserved=0;
281     bufdesc.lpwfxFormat=NULL;
282     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
283     ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
284     if (rc==DS_OK) {
285         ref=IDirectSoundCaptureBuffer_Release(dscbo);
286         ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
287     }
288
289     /* Private dsound.dll: Error: Invalid buffer size */
290     /* Private dsound.dll: Error: Invalid capture buffer description */
291     ZeroMemory(&bufdesc, sizeof(bufdesc));
292     ZeroMemory(&wfx, sizeof(wfx));
293     bufdesc.dwSize=sizeof(bufdesc);
294     bufdesc.dwFlags=0;
295     bufdesc.dwBufferBytes=0;
296     bufdesc.dwReserved=0;
297     bufdesc.lpwfxFormat=&wfx;
298     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
299     ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
300     if (rc==DS_OK) {
301         ref=IDirectSoundCaptureBuffer_Release(dscbo);
302         ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
303     }
304
305     /* Private dsound.dll: Error: Invalid buffer size */
306     /* Private dsound.dll: Error: Invalid capture buffer description */
307     init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
308     ZeroMemory(&bufdesc, sizeof(bufdesc));
309     bufdesc.dwSize=sizeof(bufdesc);
310     bufdesc.dwFlags=0;
311     bufdesc.dwBufferBytes=0;
312     bufdesc.dwReserved=0;
313     bufdesc.lpwfxFormat=&wfx;
314     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
315     ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
316     if (rc==DS_OK) {
317         ref=IDirectSoundCaptureBuffer_Release(dscbo);
318         ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
319     }
320
321     for (f=0;f<NB_FORMATS;f++) {
322         dscbo=NULL;
323         init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],formats[f][2]);
324         ZeroMemory(&bufdesc, sizeof(bufdesc));
325         bufdesc.dwSize=sizeof(bufdesc);
326         bufdesc.dwFlags=0;
327         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
328         bufdesc.dwReserved=0;
329         bufdesc.lpwfxFormat=&wfx;
330         trace("  Testing the capture buffer at %s\n", format_string(&wfx));
331         rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
332         ok((rc==DS_OK)&&(dscbo!=NULL),"CreateCaptureBuffer failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
333         if (rc==DS_OK) {
334             test_capture_buffer(dsco, dscbo, winetest_interactive);
335             ref=IDirectSoundCaptureBuffer_Release(dscbo);
336             ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
337         }
338     }
339
340     /* try a non PCM format */
341 #if 0
342     init_format(&wfx,WAVE_FORMAT_MULAW,8000,8,1);
343     ZeroMemory(&bufdesc, sizeof(bufdesc));
344     bufdesc.dwSize=sizeof(bufdesc);
345     bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
346     bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
347     bufdesc.dwReserved=0;
348     bufdesc.lpwfxFormat=&wfx;
349     trace("  Testing the capture buffer at %s\n", format_string(&wfx));
350     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
351     ok((rc==DS_OK)&&(dscbo!=NULL),"CreateCaptureBuffer failed to create a capture buffer 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
352     if ((rc==DS_OK)&&(dscbo!=NULL)) {
353         test_capture_buffer(dsco, dscbo, winetest_interactive);
354         ref=IDirectSoundCaptureBuffer_Release(dscbo);
355         ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
356     }
357 #endif
358
359     /* Try an invalid format to test error handling */
360 #if 0
361     init_format(&wfx,WAVE_FORMAT_PCM,2000000,16,2);
362     ZeroMemory(&bufdesc, sizeof(bufdesc));
363     bufdesc.dwSize=sizeof(bufdesc);
364     bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
365     bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
366     bufdesc.dwReserved=0;
367     bufdesc.lpwfxFormat=&wfx;
368     trace("  Testing the capture buffer at %s\n", format_string(&wfx));
369     rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
370     ok(rc!=DS_OK,"CreateCaptureBuffer should have failed at 2 MHz 0x%lx(%s)\n",rc,DXGetErrorString8(rc));
371 #endif
372
373 EXIT:
374     if (dsco!=NULL) {
375         ref=IDirectSoundCapture_Release(dsco);
376         ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
377     }
378
379     return TRUE;
380 }
381
382 static void capture_tests()
383 {
384     HRESULT rc;
385     rc=DirectSoundCaptureEnumerateA(&dscenum_callback,NULL);
386     ok(rc==DS_OK,"DirectSoundCaptureEnumerate failed: 0x%08lx(%s)\n",rc,DXGetErrorString8(rc));
387 }
388
389 START_TEST(capture)
390 {
391     capture_tests();
392 }