ntdll: Added Urals time.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 %ld\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 %ld\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 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 %ld\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 %ld\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%08lx)\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 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     pdsfdds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds));
262     if (pdsfdds == NULL) {
263         WARN("out of memory\n");
264         *ppds = NULL;
265         return DSERR_OUTOFMEMORY;
266     }
267
268     pdsfdds->lpVtbl = &DirectSoundFullDuplex_DirectSound_Vtbl;
269     pdsfdds->ref = 0;
270     pdsfdds->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
271
272     *ppds = (LPDIRECTSOUND)pdsfdds;
273
274     return DS_OK;
275 }
276
277 /*******************************************************************************
278  * IDirectSoundFullDuplex_IDirectSound8
279  */
280 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
281     LPDIRECTSOUND8 iface,
282     REFIID riid,
283     LPVOID * ppobj)
284 {
285     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
286     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
287     return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
288 }
289
290 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(
291     LPDIRECTSOUND8 iface)
292 {
293     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
294     ULONG ref = InterlockedIncrement(&(This->ref));
295     TRACE("(%p) ref was %ld\n", This, ref - 1);
296     return ref;
297 }
298
299 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(
300     LPDIRECTSOUND8 iface)
301 {
302     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
303     ULONG ref = InterlockedDecrement(&(This->ref));
304     TRACE("(%p) ref was %ld\n", This, ref + 1);
305     if (!ref) {
306         IDirectSound_Release(This->pdsfd->pDS8);
307         HeapFree(GetProcessHeap(), 0, This);
308         TRACE("(%p) released\n", This);
309     }
310     return ref;
311 }
312
313 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
314     LPDIRECTSOUND8 iface,
315     LPCDSBUFFERDESC dsbd,
316     LPLPDIRECTSOUNDBUFFER ppdsb,
317     LPUNKNOWN lpunk)
318 {
319     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
320     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
321     return DirectSoundDevice_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk,TRUE);
322 }
323
324 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
325     LPDIRECTSOUND8 iface,
326     LPDSCAPS lpDSCaps)
327 {
328     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
329     TRACE("(%p,%p)\n",This,lpDSCaps);
330     return DirectSoundDevice_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
331 }
332
333 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
334     LPDIRECTSOUND8 iface,
335     LPDIRECTSOUNDBUFFER psb,
336     LPLPDIRECTSOUNDBUFFER ppdsb)
337 {
338     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
339     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
340     return DirectSoundDevice_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
341 }
342
343 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
344     LPDIRECTSOUND8 iface,
345     HWND hwnd,
346     DWORD level)
347 {
348     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
349     TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
350     return DirectSoundDevice_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
351 }
352
353 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(
354     LPDIRECTSOUND8 iface)
355 {
356     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
357     TRACE("(%p)\n", This);
358     return DirectSoundDevice_Compact(This->pdsfd->renderer_device);
359 }
360
361 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
362     LPDIRECTSOUND8 iface,
363     LPDWORD lpdwSpeakerConfig)
364 {
365     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
366     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
367     return DirectSoundDevice_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
368 }
369
370 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
371     LPDIRECTSOUND8 iface,
372     DWORD config)
373 {
374     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
375     TRACE("(%p,0x%08lx)\n",This,config);
376     return DirectSoundDevice_SetSpeakerConfig(This->pdsfd->renderer_device,config);
377 }
378
379 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
380     LPDIRECTSOUND8 iface,
381     LPCGUID lpcGuid)
382 {
383     IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
384     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
385     return DirectSoundDevice_Initialize(&This->pdsfd->renderer_device,lpcGuid);
386 }
387
388 static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl =
389 {
390     IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
391     IDirectSoundFullDuplex_IDirectSound8_AddRef,
392     IDirectSoundFullDuplex_IDirectSound8_Release,
393     IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
394     IDirectSoundFullDuplex_IDirectSound8_GetCaps,
395     IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
396     IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
397     IDirectSoundFullDuplex_IDirectSound8_Compact,
398     IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
399     IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
400     IDirectSoundFullDuplex_IDirectSound8_Initialize
401 };
402
403 HRESULT IDirectSoundFullDuplex_IDirectSound8_Create(
404     LPDIRECTSOUNDFULLDUPLEX pdsfd,
405     LPDIRECTSOUND8 * ppds8)
406 {
407     IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8;
408     TRACE("(%p,%p)\n",pdsfd,ppds8);
409
410     if (pdsfd == NULL) {
411         ERR("invalid parameter: pdsfd == NULL\n");
412         return DSERR_INVALIDPARAM;
413     }
414
415     if (ppds8 == NULL) {
416         ERR("invalid parameter: ppds8 == NULL\n");
417         return DSERR_INVALIDPARAM;
418     }
419
420     pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8));
421     if (pdsfdds8 == NULL) {
422         WARN("out of memory\n");
423         *ppds8 = NULL;
424         return DSERR_OUTOFMEMORY;
425     }
426
427     pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
428     pdsfdds8->ref = 0;
429     pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
430
431     *ppds8 = (LPDIRECTSOUND8)pdsfdds8;
432
433     return DS_OK;
434 }
435
436 /*******************************************************************************
437  * IDirectSoundFullDuplex_IDirectSoundCapture
438  */
439 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
440     LPDIRECTSOUNDCAPTURE iface,
441     REFIID riid,
442     LPVOID * ppobj)
443 {
444     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
445     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
446     return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
447 }
448
449 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(
450     LPDIRECTSOUNDCAPTURE iface)
451 {
452     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
453     ULONG ref = InterlockedIncrement(&(This->ref));
454     TRACE("(%p) ref was %ld\n", This, ref - 1);
455     return ref;
456 }
457
458 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(
459     LPDIRECTSOUNDCAPTURE iface)
460 {
461     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
462     ULONG ref = InterlockedDecrement(&(This->ref));
463     TRACE("(%p) ref was %ld\n", This, ref + 1);
464     if (!ref) {
465         IDirectSoundCapture_Release(This->pdsfd->pDSC);
466         HeapFree(GetProcessHeap(), 0, This);
467         TRACE("(%p) released\n", This);
468     }
469     return ref;
470 }
471
472 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
473     LPDIRECTSOUNDCAPTURE iface,
474     LPCDSCBUFFERDESC lpcDSCBufferDesc,
475     LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
476     LPUNKNOWN pUnk)
477 {
478     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
479     TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
480     return IDirectSoundCaptureImpl_CreateCaptureBuffer(This->pdsfd->pDSC,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
481 }
482
483 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
484     LPDIRECTSOUNDCAPTURE iface,
485     LPDSCCAPS lpDSCCaps)
486 {
487     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
488     TRACE("(%p,%p)\n",This,lpDSCCaps);
489     return IDirectSoundCaptureImpl_GetCaps(This->pdsfd->pDSC, lpDSCCaps);
490 }
491
492 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
493     LPDIRECTSOUNDCAPTURE iface,
494     LPCGUID lpcGUID)
495 {
496     IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
497     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
498     return IDirectSoundCaptureImpl_Initialize(This->pdsfd->pDSC,lpcGUID);
499 }
500
501 static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl =
502 {
503     IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
504     IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
505     IDirectSoundFullDuplex_IDirectSoundCapture_Release,
506     IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
507     IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
508     IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
509 };
510
511 HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create(
512     LPDIRECTSOUNDFULLDUPLEX pdsfd,
513     LPDIRECTSOUNDCAPTURE8 * ppdsc8)
514 {
515     IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc;
516     TRACE("(%p,%p)\n",pdsfd,ppdsc8);
517
518     if (pdsfd == NULL) {
519         ERR("invalid parameter: pdsfd == NULL\n");
520         return DSERR_INVALIDPARAM;
521     }
522
523     if (ppdsc8 == NULL) {
524         ERR("invalid parameter: ppdsc8 == NULL\n");
525         return DSERR_INVALIDPARAM;
526     }
527
528     pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc));
529     if (pdsfddsc == NULL) {
530         WARN("out of memory\n");
531         *ppdsc8 = NULL;
532         return DSERR_OUTOFMEMORY;
533     }
534
535     pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
536     pdsfddsc->ref = 0;
537     pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
538
539     *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc;
540
541     return DS_OK;
542 }
543
544 /***************************************************************************
545  * IDirectSoundFullDuplexImpl
546  */
547 static ULONG WINAPI
548 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
549 {
550     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
551     ULONG ref = InterlockedIncrement(&(This->ref));
552     TRACE("(%p) ref was %ld\n", This, ref - 1);
553     return ref;
554 }
555
556 static HRESULT WINAPI
557 IDirectSoundFullDuplexImpl_QueryInterface(
558     LPDIRECTSOUNDFULLDUPLEX iface,
559     REFIID riid,
560     LPVOID* ppobj )
561 {
562     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
563     TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
564
565     if (ppobj == NULL) {
566         WARN("invalid parameter\n");
567         return E_INVALIDARG;
568     }
569
570     *ppobj = NULL;
571
572     if (IsEqualIID(riid, &IID_IUnknown)) {
573         if (!This->pUnknown) {
574             IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown);
575             if (!This->pUnknown) {
576                 WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n");
577                 *ppobj = NULL;
578                 return E_NOINTERFACE;
579             }
580         }
581         IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown);
582         *ppobj = This->pUnknown;
583         return S_OK;
584     } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
585         IDirectSoundFullDuplexImpl_AddRef(iface);
586         *ppobj = This;
587         return S_OK;
588     } else if (IsEqualIID(riid, &IID_IDirectSound)) {
589         if (!This->pDS) {
590             IDirectSoundFullDuplex_IDirectSound_Create(iface, &This->pDS);
591             if (!This->pDS) {
592                 WARN("IDirectSoundFullDuplex_IDirectSound_Create() failed\n");
593                 *ppobj = NULL;
594                 return E_NOINTERFACE;
595             }
596         }
597         IDirectSoundFullDuplex_IDirectSound_AddRef(This->pDS);
598         *ppobj = This->pDS;
599         return S_OK;
600     } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
601         if (!This->pDS8) {
602             IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8);
603             if (!This->pDS8) {
604                 WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n");
605                 *ppobj = NULL;
606                 return E_NOINTERFACE;
607             }
608         }
609         IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8);
610         *ppobj = This->pDS8;
611         return S_OK;
612     } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
613         if (!This->pDSC) {
614             IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC);
615             if (!This->pDSC) {
616                 WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n");
617                 *ppobj = NULL;
618                 return E_NOINTERFACE;
619             }
620         }
621         IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC);
622         *ppobj = This->pDSC;
623         return S_OK;
624     }
625
626     return E_NOINTERFACE;
627 }
628
629 static ULONG WINAPI
630 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
631 {
632     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
633     ULONG ref = InterlockedDecrement(&(This->ref));
634     TRACE("(%p) ref was %ld\n", This, ref - 1);
635
636     if (!ref) {
637         if (This->capture_device)
638             DirectSoundCaptureDevice_Release(This->capture_device);
639         if (This->renderer_device)
640             DirectSoundDevice_Release(This->renderer_device);
641         HeapFree( GetProcessHeap(), 0, This );
642         TRACE("(%p) released\n", This);
643     }
644     return ref;
645 }
646
647 static HRESULT WINAPI
648 IDirectSoundFullDuplexImpl_Initialize(
649     LPDIRECTSOUNDFULLDUPLEX iface,
650     LPCGUID pCaptureGuid,
651     LPCGUID pRendererGuid,
652     LPCDSCBUFFERDESC lpDscBufferDesc,
653     LPCDSBUFFERDESC lpDsBufferDesc,
654     HWND hWnd,
655     DWORD dwLevel,
656     LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
657     LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
658 {
659     HRESULT hr;
660     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
661     IDirectSoundBufferImpl * dsb;
662
663     TRACE("(%p,%s,%s,%p,%p,%lx,%lx,%p,%p)\n", This,
664         debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
665         lpDscBufferDesc, lpDsBufferDesc, (DWORD)hWnd, dwLevel,
666         lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
667
668     if (This->renderer_device != NULL || This->capture_device != NULL) {
669         WARN("already initialized\n");
670         *lplpDirectSoundCaptureBuffer8 = NULL;
671         *lplpDirectSoundBuffer8 = NULL;
672         return DSERR_ALREADYINITIALIZED;
673     }
674
675     hr = DirectSoundDevice_Initialize(&This->renderer_device, pRendererGuid);
676     if (hr != DS_OK) {
677         WARN("DirectSoundDevice_Initialize() failed\n");
678         *lplpDirectSoundCaptureBuffer8 = NULL;
679         *lplpDirectSoundBuffer8 = NULL;
680         return hr;
681     }
682
683     if (dwLevel==DSSCL_PRIORITY || dwLevel==DSSCL_EXCLUSIVE) {
684         WARN("level=%s not fully supported\n",
685              dwLevel==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
686     }
687     This->renderer_device->priolevel = dwLevel;
688
689     hr = DSOUND_PrimarySetFormat(This->renderer_device, lpDsBufferDesc->lpwfxFormat);
690     if (hr != DS_OK) {
691         WARN("DSOUND_PrimarySetFormat() failed\n");
692         *lplpDirectSoundCaptureBuffer8 = NULL;
693         *lplpDirectSoundBuffer8 = NULL;
694         return hr;
695     }
696     hr = IDirectSoundBufferImpl_Create(This->renderer_device, &dsb, lpDsBufferDesc);
697     if (hr != DS_OK) {
698         WARN("IDirectSoundBufferImpl_Create() failed\n");
699         *lplpDirectSoundCaptureBuffer8 = NULL;
700         *lplpDirectSoundBuffer8 = NULL;
701         return hr;
702     }
703
704     hr = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl **)lplpDirectSoundBuffer8);
705     if (hr != DS_OK) {
706         WARN("SecondaryBufferImpl_Create() failed\n");
707         *lplpDirectSoundCaptureBuffer8 = NULL;
708         *lplpDirectSoundBuffer8 = NULL;
709         return hr;
710     }
711     IDirectSoundBuffer8_AddRef(*lplpDirectSoundBuffer8);
712
713     hr = DirectSoundCaptureDevice_Initialize(&This->capture_device, pCaptureGuid);
714     if (hr != DS_OK) {
715         WARN("DirectSoundCaptureDevice_Initialize() failed\n");
716         *lplpDirectSoundCaptureBuffer8 = NULL;
717         *lplpDirectSoundBuffer8 = NULL;
718         return hr;
719     }
720
721     hr = IDirectSoundCaptureBufferImpl_Create(This->capture_device,
722          (IDirectSoundCaptureBufferImpl **)lplpDirectSoundCaptureBuffer8,
723          lpDscBufferDesc);
724     if (hr != DS_OK) {
725         WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
726         *lplpDirectSoundCaptureBuffer8 = NULL;
727         *lplpDirectSoundBuffer8 = NULL;
728         return hr;
729     }
730
731     return hr;
732 }
733
734 static const IDirectSoundFullDuplexVtbl dsfdvt =
735 {
736     /* IUnknown methods */
737     IDirectSoundFullDuplexImpl_QueryInterface,
738     IDirectSoundFullDuplexImpl_AddRef,
739     IDirectSoundFullDuplexImpl_Release,
740
741     /* IDirectSoundFullDuplex methods */
742     IDirectSoundFullDuplexImpl_Initialize
743 };
744
745 HRESULT DSOUND_FullDuplexCreate(LPDIRECTSOUNDFULLDUPLEX* ppDSFD, IUnknown *pUnkOuter)
746 {
747     IDirectSoundFullDuplexImpl *This = NULL;
748
749     if (pUnkOuter) {
750         WARN("pUnkOuter != 0\n");
751         *ppDSFD = NULL;
752         return DSERR_NOAGGREGATION;
753     }
754
755     if (ppDSFD == NULL) {
756         WARN("invalid parameter: ppDSFD == NULL\n");
757         return DSERR_INVALIDPARAM;
758     }
759
760     /* Get dsound configuration */
761     setup_dsound_options();
762
763     This = HeapAlloc(GetProcessHeap(),
764         HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
765
766     if (This == NULL) {
767         WARN("out of memory\n");
768         *ppDSFD = NULL;
769         return DSERR_OUTOFMEMORY;
770     }
771
772     This->lpVtbl = &dsfdvt;
773     This->ref = 1;
774     This->capture_device = NULL;
775     This->renderer_device = NULL;
776
777     return DS_OK;
778 }
779
780 /***************************************************************************
781  * DirectSoundFullDuplexCreate [DSOUND.10]
782  *
783  * Create and initialize a DirectSoundFullDuplex interface.
784  *
785  * PARAMS
786  *    pcGuidCaptureDevice [I] Address of sound capture device GUID.
787  *    pcGuidRenderDevice  [I] Address of sound render device GUID.
788  *    pcDSCBufferDesc     [I] Address of capture buffer description.
789  *    pcDSBufferDesc      [I] Address of  render buffer description.
790  *    hWnd                [I] Handle to application window.
791  *    dwLevel             [I] Cooperative level.
792  *    ppDSFD              [O] Address where full duplex interface returned.
793  *    ppDSCBuffer8        [0] Address where capture buffer interface returned.
794  *    ppDSBuffer8         [0] Address where render buffer interface returned.
795  *    pUnkOuter           [I] Must be NULL.
796  *
797  * RETURNS
798  *    Success: DS_OK
799  *    Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
800  *             DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
801  */
802 HRESULT WINAPI
803 DirectSoundFullDuplexCreate(
804     LPCGUID pcGuidCaptureDevice,
805     LPCGUID pcGuidRenderDevice,
806     LPCDSCBUFFERDESC pcDSCBufferDesc,
807     LPCDSBUFFERDESC pcDSBufferDesc,
808     HWND hWnd,
809     DWORD dwLevel,
810     LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
811     LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
812     LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
813     LPUNKNOWN pUnkOuter)
814 {
815     HRESULT hres;
816     IDirectSoundFullDuplexImpl *This = NULL;
817     TRACE("(%s,%s,%p,%p,%p,%lx,%p,%p,%p,%p)\n",
818         debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice),
819         pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8,
820         ppDSBuffer8, pUnkOuter);
821
822     if (pUnkOuter) {
823         WARN("pUnkOuter != 0\n");
824         *ppDSFD = NULL;
825         return DSERR_NOAGGREGATION;
826     }
827
828     if (pcDSCBufferDesc == NULL) {
829         WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
830         *ppDSFD = NULL;
831         return DSERR_INVALIDPARAM;
832     }
833
834     if (pcDSBufferDesc == NULL) {
835         WARN("invalid parameter: pcDSBufferDesc == NULL\n");
836         *ppDSFD = NULL;
837         return DSERR_INVALIDPARAM;
838     }
839
840     if (ppDSFD == NULL) {
841         WARN("invalid parameter: ppDSFD == NULL\n");
842         return DSERR_INVALIDPARAM;
843     }
844
845     if (ppDSCBuffer8 == NULL) {
846         WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
847         *ppDSFD = NULL;
848         return DSERR_INVALIDPARAM;
849     }
850
851     if (ppDSBuffer8 == NULL) {
852         WARN("invalid parameter: ppDSBuffer8 == NULL\n");
853         *ppDSFD = NULL;
854         return DSERR_INVALIDPARAM;
855     }
856
857     /* Get dsound configuration */
858     setup_dsound_options();
859
860     This = HeapAlloc(GetProcessHeap(),
861         HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
862
863     if (This == NULL) {
864         WARN("out of memory\n");
865         *ppDSFD = NULL;
866         return DSERR_OUTOFMEMORY;
867     }
868
869     This->lpVtbl = &dsfdvt;
870     This->ref = 1;
871     This->capture_device = NULL;
872     This->renderer_device = NULL;
873
874     hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This,
875                                                  pcGuidCaptureDevice,
876                                                  pcGuidRenderDevice,
877                                                  pcDSCBufferDesc,
878                                                  pcDSBufferDesc,
879                                                  hWnd, dwLevel, ppDSCBuffer8,
880                                                  ppDSBuffer8);
881     if (hres != DS_OK) {
882         HeapFree(GetProcessHeap(), 0, This);
883         WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
884         *ppDSFD = NULL;
885     } else
886         *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
887
888     return hres;
889 }
890
891 /*******************************************************************************
892  * DirectSoundFullDuplex ClassFactory
893  */
894
895 static HRESULT WINAPI
896 DSFDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
897 {
898     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
899
900     FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
901     return E_NOINTERFACE;
902 }
903
904 static ULONG WINAPI
905 DSFDCF_AddRef(LPCLASSFACTORY iface)
906 {
907     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
908     TRACE("(%p) ref was %ld\n", This, This->ref);
909     return InterlockedIncrement(&(This->ref));
910 }
911
912 static ULONG WINAPI
913 DSFDCF_Release(LPCLASSFACTORY iface)
914 {
915     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
916     /* static class, won't be  freed */
917     TRACE("(%p) ref was %ld\n", This, This->ref);
918     return InterlockedDecrement(&(This->ref));
919 }
920
921 static HRESULT WINAPI
922 DSFDCF_CreateInstance(
923     LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
924 {
925     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
926
927     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
928
929     if (pOuter) {
930         WARN("aggregation not supported\n");
931         return CLASS_E_NOAGGREGATION;
932     }
933
934     if (ppobj == NULL) {
935         WARN("invalid parameter\n");
936         return E_INVALIDARG;
937     }
938
939     *ppobj = NULL;
940
941     if ( IsEqualGUID( &IID_IDirectSoundFullDuplex, riid ) )
942         return DSOUND_FullDuplexCreate((LPDIRECTSOUNDFULLDUPLEX*)ppobj,pOuter);
943
944     WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj); 
945     return E_NOINTERFACE;
946 }
947
948 static HRESULT WINAPI
949 DSFDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
950 {
951     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
952     FIXME("(%p)->(%d),stub!\n",This,dolock);
953     return S_OK;
954 }
955
956 static const IClassFactoryVtbl DSFDCF_Vtbl =
957 {
958     DSFDCF_QueryInterface,
959     DSFDCF_AddRef,
960     DSFDCF_Release,
961     DSFDCF_CreateInstance,
962     DSFDCF_LockServer
963 };
964
965 IClassFactoryImpl DSOUND_FULLDUPLEX_CF = { &DSFDCF_Vtbl, 1 };