user32: ClipCursor should use virtual screen resolution for empty/invalid rects.
[wine] / dlls / dsound / duplex.c
1 /*              DirectSoundFullDuplex
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998 Rob Riggs
5  * Copyright 2000-2001 TransGaming Technologies, Inc.
6  * Copyright 2005 Robert Reif
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include <stdarg.h>
24
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "mmsystem.h"
31 #include "mmddk.h"
32 #include "winreg.h"
33 #include "winternl.h"
34 #include "winnls.h"
35 #include "wine/debug.h"
36 #include "dsound.h"
37 #include "dsdriver.h"
38 #include "dsound_private.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
41
42 /*******************************************************************************
43  * IUnknown
44  */
45 static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface(
46     LPUNKNOWN iface,
47     REFIID riid,
48     LPVOID * ppobj)
49 {
50     IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
51     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
52     return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
53 }
54
55 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef(
56     LPUNKNOWN iface)
57 {
58     IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
59     ULONG ref = InterlockedIncrement(&(This->ref));
60     TRACE("(%p) ref was %d\n", This, ref - 1);
61     return ref;
62 }
63
64 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release(
65     LPUNKNOWN iface)
66 {
67     IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
68     ULONG ref = InterlockedDecrement(&(This->ref));
69     TRACE("(%p) ref was %d\n", This, ref + 1);
70     if (!ref) {
71         IDirectSound_Release(This->pdsfd->pUnknown);
72         HeapFree(GetProcessHeap(), 0, This);
73         TRACE("(%p) released\n", This);
74     }
75     return ref;
76 }
77
78 static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl =
79 {
80     IDirectSoundFullDuplex_IUnknown_QueryInterface,
81     IDirectSoundFullDuplex_IUnknown_AddRef,
82     IDirectSoundFullDuplex_IUnknown_Release
83 };
84
85 static HRESULT IDirectSoundFullDuplex_IUnknown_Create(
86     LPDIRECTSOUNDFULLDUPLEX pdsfd,
87     LPUNKNOWN * ppunk)
88 {
89     IDirectSoundFullDuplex_IUnknown * pdsfdunk;
90     TRACE("(%p,%p)\n",pdsfd,ppunk);
91
92     if (pdsfd == NULL) {
93         ERR("invalid parameter: pdsfd == NULL\n");
94         return DSERR_INVALIDPARAM;
95     }
96
97     if (ppunk == NULL) {
98         ERR("invalid parameter: ppunk == NULL\n");
99         return DSERR_INVALIDPARAM;
100     }
101
102     pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk));
103     if (pdsfdunk == NULL) {
104         WARN("out of memory\n");
105         *ppunk = NULL;
106         return DSERR_OUTOFMEMORY;
107     }
108
109     pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl;
110     pdsfdunk->ref = 0;
111     pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
112
113     *ppunk = (LPUNKNOWN)pdsfdunk;
114
115     return DS_OK;
116 }
117
118 /*******************************************************************************
119  * IDirectSoundFullDuplex_IDirectSound
120  */
121 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_QueryInterface(
122     LPDIRECTSOUND iface,
123     REFIID riid,
124     LPVOID * ppobj)
125 {
126     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
127     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
128     return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
129 }
130
131 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound_AddRef(
132     LPDIRECTSOUND iface)
133 {
134     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
135     ULONG ref = InterlockedIncrement(&(This->ref));
136     TRACE("(%p) ref was %d\n", This, ref - 1);
137     return ref;
138 }
139
140 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound_Release(
141     LPDIRECTSOUND iface)
142 {
143     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
144     ULONG ref = InterlockedDecrement(&(This->ref));
145     TRACE("(%p) ref was %d\n", This, ref + 1);
146     if (!ref) {
147         IDirectSound_Release(This->pdsfd->pDS);
148         HeapFree(GetProcessHeap(), 0, This);
149         TRACE("(%p) released\n", This);
150     }
151     return ref;
152 }
153
154 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_CreateSoundBuffer(
155     LPDIRECTSOUND iface,
156     LPCDSBUFFERDESC dsbd,
157     LPLPDIRECTSOUNDBUFFER ppdsb,
158     LPUNKNOWN lpunk)
159 {
160     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
161     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
162     return DirectSoundDevice_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk,FALSE);
163 }
164
165 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_GetCaps(
166     LPDIRECTSOUND iface,
167     LPDSCAPS lpDSCaps)
168 {
169     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
170     TRACE("(%p,%p)\n",This,lpDSCaps);
171     return DirectSoundDevice_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
172 }
173
174 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_DuplicateSoundBuffer(
175     LPDIRECTSOUND iface,
176     LPDIRECTSOUNDBUFFER psb,
177     LPLPDIRECTSOUNDBUFFER ppdsb)
178 {
179     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
180     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
181     return DirectSoundDevice_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
182 }
183
184 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_SetCooperativeLevel(
185     LPDIRECTSOUND iface,
186     HWND hwnd,
187     DWORD level)
188 {
189     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
190     TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
191     return DirectSoundDevice_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
192 }
193
194 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_Compact(
195     LPDIRECTSOUND iface)
196 {
197     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
198     TRACE("(%p)\n", This);
199     return DirectSoundDevice_Compact(This->pdsfd->renderer_device);
200 }
201
202 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_GetSpeakerConfig(
203     LPDIRECTSOUND iface,
204     LPDWORD lpdwSpeakerConfig)
205 {
206     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
207     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
208     return DirectSoundDevice_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
209 }
210
211 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_SetSpeakerConfig(
212     LPDIRECTSOUND iface,
213     DWORD config)
214 {
215     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
216     TRACE("(%p,0x%08x)\n",This,config);
217     return DirectSoundDevice_SetSpeakerConfig(This->pdsfd->renderer_device,config);
218 }
219
220 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_Initialize(
221     LPDIRECTSOUND iface,
222     LPCGUID lpcGuid)
223 {
224     IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
225     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
226     return DirectSoundDevice_Initialize(&This->pdsfd->renderer_device,lpcGuid);
227 }
228
229 static const IDirectSoundVtbl DirectSoundFullDuplex_DirectSound_Vtbl =
230 {
231     IDirectSoundFullDuplex_IDirectSound_QueryInterface,
232     IDirectSoundFullDuplex_IDirectSound_AddRef,
233     IDirectSoundFullDuplex_IDirectSound_Release,
234     IDirectSoundFullDuplex_IDirectSound_CreateSoundBuffer,
235     IDirectSoundFullDuplex_IDirectSound_GetCaps,
236     IDirectSoundFullDuplex_IDirectSound_DuplicateSoundBuffer,
237     IDirectSoundFullDuplex_IDirectSound_SetCooperativeLevel,
238     IDirectSoundFullDuplex_IDirectSound_Compact,
239     IDirectSoundFullDuplex_IDirectSound_GetSpeakerConfig,
240     IDirectSoundFullDuplex_IDirectSound_SetSpeakerConfig,
241     IDirectSoundFullDuplex_IDirectSound_Initialize
242 };
243
244 static HRESULT IDirectSoundFullDuplex_IDirectSound_Create(
245     LPDIRECTSOUNDFULLDUPLEX pdsfd,
246     LPDIRECTSOUND * ppds)
247 {
248     IDirectSoundFullDuplex_IDirectSound * pdsfdds;
249     TRACE("(%p,%p)\n",pdsfd,ppds);
250
251     if (pdsfd == NULL) {
252         ERR("invalid parameter: pdsfd == NULL\n");
253         return DSERR_INVALIDPARAM;
254     }
255
256     if (ppds == NULL) {
257         ERR("invalid parameter: ppds == NULL\n");
258         return DSERR_INVALIDPARAM;
259     }
260
261     if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
262         WARN("not initialized\n");
263         *ppds = NULL;
264         return DSERR_UNINITIALIZED;
265     }
266
267     pdsfdds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds));
268     if (pdsfdds == NULL) {
269         WARN("out of memory\n");
270         *ppds = NULL;
271         return DSERR_OUTOFMEMORY;
272     }
273
274     pdsfdds->lpVtbl = &DirectSoundFullDuplex_DirectSound_Vtbl;
275     pdsfdds->ref = 0;
276     pdsfdds->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
277
278     *ppds = (LPDIRECTSOUND)pdsfdds;
279
280     return DS_OK;
281 }
282
283 /*******************************************************************************
284  * IDirectSoundFullDuplex_IDirectSound8
285  */
286 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
287     LPDIRECTSOUND8 iface,
288     REFIID riid,
289     LPVOID * ppobj)
290 {
291     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
292     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
293     return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
294 }
295
296 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(
297     LPDIRECTSOUND8 iface)
298 {
299     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
300     ULONG ref = InterlockedIncrement(&(This->ref));
301     TRACE("(%p) ref was %d\n", This, ref - 1);
302     return ref;
303 }
304
305 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(
306     LPDIRECTSOUND8 iface)
307 {
308     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
309     ULONG ref = InterlockedDecrement(&(This->ref));
310     TRACE("(%p) ref was %d\n", This, ref + 1);
311     if (!ref) {
312         IDirectSound_Release(This->pdsfd->pDS8);
313         HeapFree(GetProcessHeap(), 0, This);
314         TRACE("(%p) released\n", This);
315     }
316     return ref;
317 }
318
319 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
320     LPDIRECTSOUND8 iface,
321     LPCDSBUFFERDESC dsbd,
322     LPLPDIRECTSOUNDBUFFER ppdsb,
323     LPUNKNOWN lpunk)
324 {
325     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
326     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
327     return DirectSoundDevice_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk,TRUE);
328 }
329
330 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
331     LPDIRECTSOUND8 iface,
332     LPDSCAPS lpDSCaps)
333 {
334     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
335     TRACE("(%p,%p)\n",This,lpDSCaps);
336     return DirectSoundDevice_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
337 }
338
339 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
340     LPDIRECTSOUND8 iface,
341     LPDIRECTSOUNDBUFFER psb,
342     LPLPDIRECTSOUNDBUFFER ppdsb)
343 {
344     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
345     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
346     return DirectSoundDevice_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
347 }
348
349 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
350     LPDIRECTSOUND8 iface,
351     HWND hwnd,
352     DWORD level)
353 {
354     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
355     TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
356     return DirectSoundDevice_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
357 }
358
359 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(
360     LPDIRECTSOUND8 iface)
361 {
362     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
363     TRACE("(%p)\n", This);
364     return DirectSoundDevice_Compact(This->pdsfd->renderer_device);
365 }
366
367 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
368     LPDIRECTSOUND8 iface,
369     LPDWORD lpdwSpeakerConfig)
370 {
371     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
372     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
373     return DirectSoundDevice_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
374 }
375
376 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
377     LPDIRECTSOUND8 iface,
378     DWORD config)
379 {
380     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
381     TRACE("(%p,0x%08x)\n",This,config);
382     return DirectSoundDevice_SetSpeakerConfig(This->pdsfd->renderer_device,config);
383 }
384
385 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
386     LPDIRECTSOUND8 iface,
387     LPCGUID lpcGuid)
388 {
389     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
390     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
391     return DirectSoundDevice_Initialize(&This->pdsfd->renderer_device,lpcGuid);
392 }
393
394 static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl =
395 {
396     IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
397     IDirectSoundFullDuplex_IDirectSound8_AddRef,
398     IDirectSoundFullDuplex_IDirectSound8_Release,
399     IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
400     IDirectSoundFullDuplex_IDirectSound8_GetCaps,
401     IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
402     IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
403     IDirectSoundFullDuplex_IDirectSound8_Compact,
404     IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
405     IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
406     IDirectSoundFullDuplex_IDirectSound8_Initialize
407 };
408
409 static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create(
410     LPDIRECTSOUNDFULLDUPLEX pdsfd,
411     LPDIRECTSOUND8 * ppds8)
412 {
413     IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8;
414     TRACE("(%p,%p)\n",pdsfd,ppds8);
415
416     if (pdsfd == NULL) {
417         ERR("invalid parameter: pdsfd == NULL\n");
418         return DSERR_INVALIDPARAM;
419     }
420
421     if (ppds8 == NULL) {
422         ERR("invalid parameter: ppds8 == NULL\n");
423         return DSERR_INVALIDPARAM;
424     }
425
426     if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
427         WARN("not initialized\n");
428         *ppds8 = NULL;
429         return DSERR_UNINITIALIZED;
430     }
431
432     pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8));
433     if (pdsfdds8 == NULL) {
434         WARN("out of memory\n");
435         *ppds8 = NULL;
436         return DSERR_OUTOFMEMORY;
437     }
438
439     pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
440     pdsfdds8->ref = 0;
441     pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
442
443     *ppds8 = (LPDIRECTSOUND8)pdsfdds8;
444
445     return DS_OK;
446 }
447
448 /*******************************************************************************
449  * IDirectSoundFullDuplex_IDirectSoundCapture
450  */
451 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
452     LPDIRECTSOUNDCAPTURE iface,
453     REFIID riid,
454     LPVOID * ppobj)
455 {
456     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
457     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
458     return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
459 }
460
461 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(
462     LPDIRECTSOUNDCAPTURE iface)
463 {
464     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
465     ULONG ref = InterlockedIncrement(&(This->ref));
466     TRACE("(%p) ref was %d\n", This, ref - 1);
467     return ref;
468 }
469
470 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(
471     LPDIRECTSOUNDCAPTURE iface)
472 {
473     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
474     ULONG ref = InterlockedDecrement(&(This->ref));
475     TRACE("(%p) ref was %d\n", This, ref + 1);
476     if (!ref) {
477         IDirectSoundCapture_Release(This->pdsfd->pDSC);
478         HeapFree(GetProcessHeap(), 0, This);
479         TRACE("(%p) released\n", This);
480     }
481     return ref;
482 }
483
484 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
485     LPDIRECTSOUNDCAPTURE iface,
486     LPCDSCBUFFERDESC lpcDSCBufferDesc,
487     LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
488     LPUNKNOWN pUnk)
489 {
490     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
491     TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
492     return IDirectSoundCaptureImpl_CreateCaptureBuffer(This->pdsfd->pDSC,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
493 }
494
495 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
496     LPDIRECTSOUNDCAPTURE iface,
497     LPDSCCAPS lpDSCCaps)
498 {
499     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
500     TRACE("(%p,%p)\n",This,lpDSCCaps);
501     return IDirectSoundCaptureImpl_GetCaps(This->pdsfd->pDSC, lpDSCCaps);
502 }
503
504 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
505     LPDIRECTSOUNDCAPTURE iface,
506     LPCGUID lpcGUID)
507 {
508     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
509     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
510     return IDirectSoundCaptureImpl_Initialize(This->pdsfd->pDSC,lpcGUID);
511 }
512
513 static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl =
514 {
515     IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
516     IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
517     IDirectSoundFullDuplex_IDirectSoundCapture_Release,
518     IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
519     IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
520     IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
521 };
522
523 static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create(
524     LPDIRECTSOUNDFULLDUPLEX pdsfd,
525     LPDIRECTSOUNDCAPTURE8 * ppdsc8)
526 {
527     IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc;
528     TRACE("(%p,%p)\n",pdsfd,ppdsc8);
529
530     if (pdsfd == NULL) {
531         ERR("invalid parameter: pdsfd == NULL\n");
532         return DSERR_INVALIDPARAM;
533     }
534
535     if (ppdsc8 == NULL) {
536         ERR("invalid parameter: ppdsc8 == NULL\n");
537         return DSERR_INVALIDPARAM;
538     }
539
540     if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) {
541         WARN("not initialized\n");
542         *ppdsc8 = NULL;
543         return DSERR_UNINITIALIZED;
544     }
545
546     pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc));
547     if (pdsfddsc == NULL) {
548         WARN("out of memory\n");
549         *ppdsc8 = NULL;
550         return DSERR_OUTOFMEMORY;
551     }
552
553     pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
554     pdsfddsc->ref = 0;
555     pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
556
557     *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc;
558
559     return DS_OK;
560 }
561
562 /***************************************************************************
563  * IDirectSoundFullDuplexImpl
564  */
565 static ULONG WINAPI
566 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
567 {
568     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
569     ULONG ref = InterlockedIncrement(&(This->ref));
570     TRACE("(%p) ref was %d\n", This, ref - 1);
571     return ref;
572 }
573
574 static HRESULT WINAPI
575 IDirectSoundFullDuplexImpl_QueryInterface(
576     LPDIRECTSOUNDFULLDUPLEX iface,
577     REFIID riid,
578     LPVOID* ppobj )
579 {
580     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
581     TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
582
583     if (ppobj == NULL) {
584         WARN("invalid parameter\n");
585         return E_INVALIDARG;
586     }
587
588     *ppobj = NULL;
589
590     if (IsEqualIID(riid, &IID_IUnknown)) {
591         if (!This->pUnknown) {
592             IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown);
593             if (!This->pUnknown) {
594                 WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n");
595                 *ppobj = NULL;
596                 return E_NOINTERFACE;
597             }
598         }
599         IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown);
600         *ppobj = This->pUnknown;
601         return S_OK;
602     } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
603         IDirectSoundFullDuplexImpl_AddRef(iface);
604         *ppobj = This;
605         return S_OK;
606     } else if (IsEqualIID(riid, &IID_IDirectSound)) {
607         if (!This->pDS) {
608             IDirectSoundFullDuplex_IDirectSound_Create(iface, &This->pDS);
609             if (!This->pDS) {
610                 WARN("IDirectSoundFullDuplex_IDirectSound_Create() failed\n");
611                 *ppobj = NULL;
612                 return E_NOINTERFACE;
613             }
614         }
615         IDirectSoundFullDuplex_IDirectSound_AddRef(This->pDS);
616         *ppobj = This->pDS;
617         return S_OK;
618     } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
619         if (!This->pDS8) {
620             IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8);
621             if (!This->pDS8) {
622                 WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n");
623                 *ppobj = NULL;
624                 return E_NOINTERFACE;
625             }
626         }
627         IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8);
628         *ppobj = This->pDS8;
629         return S_OK;
630     } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
631         if (!This->pDSC) {
632             IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC);
633             if (!This->pDSC) {
634                 WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n");
635                 *ppobj = NULL;
636                 return E_NOINTERFACE;
637             }
638         }
639         IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC);
640         *ppobj = This->pDSC;
641         return S_OK;
642     }
643
644     return E_NOINTERFACE;
645 }
646
647 static ULONG WINAPI
648 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
649 {
650     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
651     ULONG ref = InterlockedDecrement(&(This->ref));
652     TRACE("(%p) ref was %d\n", This, ref - 1);
653
654     if (!ref) {
655         if (This->capture_device)
656             DirectSoundCaptureDevice_Release(This->capture_device);
657         if (This->renderer_device)
658             DirectSoundDevice_Release(This->renderer_device);
659         HeapFree( GetProcessHeap(), 0, This );
660         TRACE("(%p) released\n", This);
661     }
662     return ref;
663 }
664
665 static HRESULT WINAPI
666 IDirectSoundFullDuplexImpl_Initialize(
667     LPDIRECTSOUNDFULLDUPLEX iface,
668     LPCGUID pCaptureGuid,
669     LPCGUID pRendererGuid,
670     LPCDSCBUFFERDESC lpDscBufferDesc,
671     LPCDSBUFFERDESC lpDsBufferDesc,
672     HWND hWnd,
673     DWORD dwLevel,
674     LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
675     LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
676 {
677     HRESULT hr;
678     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
679     IDirectSoundBufferImpl * dsb;
680
681     TRACE("(%p,%s,%s,%p,%p,%x,%x,%p,%p)\n", This,
682         debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
683         lpDscBufferDesc, lpDsBufferDesc, (DWORD)hWnd, dwLevel,
684         lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
685
686     if (This->renderer_device != NULL || This->capture_device != NULL) {
687         WARN("already initialized\n");
688         *lplpDirectSoundCaptureBuffer8 = NULL;
689         *lplpDirectSoundBuffer8 = NULL;
690         return DSERR_ALREADYINITIALIZED;
691     }
692
693     hr = DirectSoundDevice_Initialize(&This->renderer_device, pRendererGuid);
694     if (hr != DS_OK) {
695         WARN("DirectSoundDevice_Initialize() failed\n");
696         *lplpDirectSoundCaptureBuffer8 = NULL;
697         *lplpDirectSoundBuffer8 = NULL;
698         return hr;
699     }
700
701     if (dwLevel==DSSCL_PRIORITY || dwLevel==DSSCL_EXCLUSIVE) {
702         WARN("level=%s not fully supported\n",
703              dwLevel==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
704     }
705     This->renderer_device->priolevel = dwLevel;
706
707     hr = DSOUND_PrimarySetFormat(This->renderer_device, lpDsBufferDesc->lpwfxFormat);
708     if (hr != DS_OK) {
709         WARN("DSOUND_PrimarySetFormat() failed\n");
710         *lplpDirectSoundCaptureBuffer8 = NULL;
711         *lplpDirectSoundBuffer8 = NULL;
712         return hr;
713     }
714     hr = IDirectSoundBufferImpl_Create(This->renderer_device, &dsb, lpDsBufferDesc);
715     if (hr != DS_OK) {
716         WARN("IDirectSoundBufferImpl_Create() failed\n");
717         *lplpDirectSoundCaptureBuffer8 = NULL;
718         *lplpDirectSoundBuffer8 = NULL;
719         return hr;
720     }
721
722     hr = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl **)lplpDirectSoundBuffer8);
723     if (hr != DS_OK) {
724         WARN("SecondaryBufferImpl_Create() failed\n");
725         *lplpDirectSoundCaptureBuffer8 = NULL;
726         *lplpDirectSoundBuffer8 = NULL;
727         return hr;
728     }
729     IDirectSoundBuffer8_AddRef(*lplpDirectSoundBuffer8);
730
731     hr = DirectSoundCaptureDevice_Initialize(&This->capture_device, pCaptureGuid);
732     if (hr != DS_OK) {
733         WARN("DirectSoundCaptureDevice_Initialize() failed\n");
734         *lplpDirectSoundCaptureBuffer8 = NULL;
735         *lplpDirectSoundBuffer8 = NULL;
736         return hr;
737     }
738
739     hr = IDirectSoundCaptureBufferImpl_Create(This->capture_device,
740          (IDirectSoundCaptureBufferImpl **)lplpDirectSoundCaptureBuffer8,
741          lpDscBufferDesc);
742     if (hr != DS_OK) {
743         WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
744         *lplpDirectSoundCaptureBuffer8 = NULL;
745         *lplpDirectSoundBuffer8 = NULL;
746         return hr;
747     }
748
749     return hr;
750 }
751
752 static const IDirectSoundFullDuplexVtbl dsfdvt =
753 {
754     /* IUnknown methods */
755     IDirectSoundFullDuplexImpl_QueryInterface,
756     IDirectSoundFullDuplexImpl_AddRef,
757     IDirectSoundFullDuplexImpl_Release,
758
759     /* IDirectSoundFullDuplex methods */
760     IDirectSoundFullDuplexImpl_Initialize
761 };
762
763 HRESULT DSOUND_FullDuplexCreate(
764     REFIID riid,
765     LPDIRECTSOUNDFULLDUPLEX* ppDSFD)
766 {
767     IDirectSoundFullDuplexImpl *This = NULL;
768     TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD);
769
770     if (ppDSFD == NULL) {
771         WARN("invalid parameter: ppDSFD == NULL\n");
772         return DSERR_INVALIDPARAM;
773     }
774
775     if (!IsEqualIID(riid, &IID_IUnknown) &&
776         !IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
777         *ppDSFD = 0;
778         return E_NOINTERFACE;
779     }
780
781     /* Get dsound configuration */
782     setup_dsound_options();
783
784     This = HeapAlloc(GetProcessHeap(),
785         HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
786
787     if (This == NULL) {
788         WARN("out of memory\n");
789         *ppDSFD = NULL;
790         return DSERR_OUTOFMEMORY;
791     }
792
793     This->lpVtbl = &dsfdvt;
794     This->ref = 1;
795     This->capture_device = NULL;
796     This->renderer_device = NULL;
797
798     *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
799
800     return DS_OK;
801 }
802
803 /***************************************************************************
804  * DirectSoundFullDuplexCreate [DSOUND.10]
805  *
806  * Create and initialize a DirectSoundFullDuplex interface.
807  *
808  * PARAMS
809  *    pcGuidCaptureDevice [I] Address of sound capture device GUID.
810  *    pcGuidRenderDevice  [I] Address of sound render device GUID.
811  *    pcDSCBufferDesc     [I] Address of capture buffer description.
812  *    pcDSBufferDesc      [I] Address of  render buffer description.
813  *    hWnd                [I] Handle to application window.
814  *    dwLevel             [I] Cooperative level.
815  *    ppDSFD              [O] Address where full duplex interface returned.
816  *    ppDSCBuffer8        [0] Address where capture buffer interface returned.
817  *    ppDSBuffer8         [0] Address where render buffer interface returned.
818  *    pUnkOuter           [I] Must be NULL.
819  *
820  * RETURNS
821  *    Success: DS_OK
822  *    Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
823  *             DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
824  */
825 HRESULT WINAPI
826 DirectSoundFullDuplexCreate(
827     LPCGUID pcGuidCaptureDevice,
828     LPCGUID pcGuidRenderDevice,
829     LPCDSCBUFFERDESC pcDSCBufferDesc,
830     LPCDSBUFFERDESC pcDSBufferDesc,
831     HWND hWnd,
832     DWORD dwLevel,
833     LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
834     LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
835     LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
836     LPUNKNOWN pUnkOuter)
837 {
838     HRESULT hres;
839     IDirectSoundFullDuplexImpl *This = NULL;
840     TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n",
841         debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice),
842         pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8,
843         ppDSBuffer8, pUnkOuter);
844
845     if (pUnkOuter) {
846         WARN("pUnkOuter != 0\n");
847         *ppDSFD = NULL;
848         return DSERR_NOAGGREGATION;
849     }
850
851     if (pcDSCBufferDesc == NULL) {
852         WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
853         *ppDSFD = NULL;
854         return DSERR_INVALIDPARAM;
855     }
856
857     if (pcDSBufferDesc == NULL) {
858         WARN("invalid parameter: pcDSBufferDesc == NULL\n");
859         *ppDSFD = NULL;
860         return DSERR_INVALIDPARAM;
861     }
862
863     if (ppDSFD == NULL) {
864         WARN("invalid parameter: ppDSFD == NULL\n");
865         return DSERR_INVALIDPARAM;
866     }
867
868     if (ppDSCBuffer8 == NULL) {
869         WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
870         *ppDSFD = NULL;
871         return DSERR_INVALIDPARAM;
872     }
873
874     if (ppDSBuffer8 == NULL) {
875         WARN("invalid parameter: ppDSBuffer8 == NULL\n");
876         *ppDSFD = NULL;
877         return DSERR_INVALIDPARAM;
878     }
879
880     /* Get dsound configuration */
881     setup_dsound_options();
882
883     This = HeapAlloc(GetProcessHeap(),
884         HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
885
886     if (This == NULL) {
887         WARN("out of memory\n");
888         *ppDSFD = NULL;
889         return DSERR_OUTOFMEMORY;
890     }
891
892     This->lpVtbl = &dsfdvt;
893     This->ref = 1;
894     This->capture_device = NULL;
895     This->renderer_device = NULL;
896
897     hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This,
898                                                  pcGuidCaptureDevice,
899                                                  pcGuidRenderDevice,
900                                                  pcDSCBufferDesc,
901                                                  pcDSBufferDesc,
902                                                  hWnd, dwLevel, ppDSCBuffer8,
903                                                  ppDSBuffer8);
904     if (hres != DS_OK) {
905         HeapFree(GetProcessHeap(), 0, This);
906         WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
907         *ppDSFD = NULL;
908     } else
909         *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
910
911     return hres;
912 }