Report the EAX last error as settable
[dsound-openal.git] / duplex.c
blob7cd02679865b4bb7231b2f4ce97165964be3f38b
1 /* DirectSoundFullDuplex
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2001 TransGaming Technologies, Inc.
6 * Copyright 2005 Robert Reif
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.
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.
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
23 #define CONST_VTABLE
24 #include <stdarg.h>
26 #include <windows.h>
27 #include <dsound.h>
29 #include "dsound_private.h"
32 /*****************************************************************************
33 * IDirectSoundFullDuplex implementation structure
35 typedef struct IDirectSoundFullDuplexImpl
37 IDirectSoundFullDuplex IDirectSoundFullDuplex_iface;
38 IUnknown IUnknown_iface;
39 IDirectSound8 IDirectSound8_iface;
40 IDirectSoundCapture IDirectSoundCapture_iface;
41 LONG ref, unkref, ds8ref, dscref;
42 LONG all_ref;
44 /* IDirectSoundFullDuplexImpl fields */
45 IDirectSound8 *renderer_device;
46 IDirectSoundCapture *capture_device;
47 } IDirectSoundFullDuplexImpl;
50 static void DSOUND_FullDuplexDestroy(IDirectSoundFullDuplexImpl *This)
52 if (This->capture_device)
53 IDirectSoundCapture_Release(This->capture_device);
54 if (This->renderer_device)
55 IDirectSound_Release(This->renderer_device);
56 HeapFree(GetProcessHeap(), 0, This);
57 TRACE("(%p) released\n", This);
60 /*******************************************************************************
61 * IUnknown
63 static inline IDirectSoundFullDuplexImpl *impl_from_IUnknown(IUnknown *iface)
65 return CONTAINING_RECORD(iface, IDirectSoundFullDuplexImpl, IUnknown_iface);
68 static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface(
69 IUnknown *iface, REFIID riid, void **ppobj)
71 IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
72 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
73 return IDirectSoundFullDuplex_QueryInterface(&This->IDirectSoundFullDuplex_iface, riid, ppobj);
76 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef(IUnknown *iface)
78 IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
79 ULONG ref;
81 InterlockedIncrement(&(This->all_ref));
82 ref = InterlockedIncrement(&(This->unkref));
83 TRACE("(%p) ref %lu\n", iface, ref);
85 return ref;
88 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release(IUnknown *iface)
90 IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
91 ULONG ref = InterlockedDecrement(&(This->unkref));
92 TRACE("(%p) ref %lu\n", iface, ref);
93 if(InterlockedDecrement(&(This->all_ref)) == 0)
94 DSOUND_FullDuplexDestroy(This);
95 return ref;
98 static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl = {
99 IDirectSoundFullDuplex_IUnknown_QueryInterface,
100 IDirectSoundFullDuplex_IUnknown_AddRef,
101 IDirectSoundFullDuplex_IUnknown_Release
104 /*******************************************************************************
105 * IDirectSoundFullDuplex_IDirectSound8
107 static inline IDirectSoundFullDuplexImpl *impl_from_IDirectSound8(IDirectSound8 *iface)
109 return CONTAINING_RECORD(iface, IDirectSoundFullDuplexImpl, IDirectSound8_iface);
112 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
113 IDirectSound8 *iface, REFIID riid, void **ppobj)
115 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
116 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
117 return IDirectSoundFullDuplex_QueryInterface(&This->IDirectSoundFullDuplex_iface, riid, ppobj);
120 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(IDirectSound8 *iface)
122 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
123 ULONG ref;
125 InterlockedIncrement(&(This->all_ref));
126 ref = InterlockedIncrement(&(This->ds8ref));
127 TRACE("(%p) ref %lu\n", iface, ref);
129 return ref;
132 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(IDirectSound8 *iface)
134 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
135 ULONG ref = InterlockedDecrement(&(This->ds8ref));
136 TRACE("(%p) ref %lu\n", iface, ref);
137 if(InterlockedDecrement(&(This->all_ref)) == 0)
138 DSOUND_FullDuplexDestroy(This);
139 return ref;
142 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
143 IDirectSound8 *iface, LPCDSBUFFERDESC dsbd, IDirectSoundBuffer **ppdsb,
144 IUnknown *lpunk)
146 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
147 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
148 return IDirectSound8_CreateSoundBuffer(This->renderer_device,dsbd,ppdsb,lpunk);
151 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
152 IDirectSound8 *iface, DSCAPS *lpDSCaps)
154 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
155 TRACE("(%p,%p)\n",This,lpDSCaps);
156 return IDirectSound8_GetCaps(This->renderer_device, lpDSCaps);
159 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
160 IDirectSound8 *iface, IDirectSoundBuffer *psb, IDirectSoundBuffer **ppdsb)
162 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
163 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
164 return IDirectSound8_DuplicateSoundBuffer(This->renderer_device,psb,ppdsb);
167 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
168 IDirectSound8 *iface, HWND hwnd, DWORD level)
170 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
171 TRACE("(%p,%p,%lu)\n",This,hwnd,level);
172 return IDirectSound8_SetCooperativeLevel(This->renderer_device,hwnd,level);
175 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(IDirectSound8 *iface)
177 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
178 TRACE("(%p)\n", This);
179 return IDirectSound8_Compact(This->renderer_device);
182 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
183 IDirectSound8 *iface, DWORD *lpdwSpeakerConfig)
185 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
186 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
187 return IDirectSound8_GetSpeakerConfig(This->renderer_device,lpdwSpeakerConfig);
190 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
191 IDirectSound8 *iface, DWORD config)
193 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
194 TRACE("(%p,0x%08lx)\n",This,config);
195 return IDirectSound8_SetSpeakerConfig(This->renderer_device,config);
198 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
199 IDirectSound8 *iface, LPCGUID lpcGuid)
201 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
202 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
203 return IDirectSound8_Initialize(This->renderer_device,lpcGuid);
206 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_VerifyCertification(
207 IDirectSound8 *iface, DWORD *cert)
209 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSound8(iface);
210 TRACE("(%p, %p)\n", This, cert);
211 return IDirectSound8_VerifyCertification(This->renderer_device,cert);
214 static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl = {
215 IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
216 IDirectSoundFullDuplex_IDirectSound8_AddRef,
217 IDirectSoundFullDuplex_IDirectSound8_Release,
218 IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
219 IDirectSoundFullDuplex_IDirectSound8_GetCaps,
220 IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
221 IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
222 IDirectSoundFullDuplex_IDirectSound8_Compact,
223 IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
224 IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
225 IDirectSoundFullDuplex_IDirectSound8_Initialize,
226 IDirectSoundFullDuplex_IDirectSound8_VerifyCertification
229 /*******************************************************************************
230 * IDirectSoundFullDuplex_IDirectSoundCapture
232 static inline IDirectSoundFullDuplexImpl *impl_from_IDirectSoundCapture(IDirectSoundCapture *iface)
234 return CONTAINING_RECORD(iface, IDirectSoundFullDuplexImpl, IDirectSoundCapture_iface);
237 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
238 IDirectSoundCapture *iface, REFIID riid, void **ppobj)
240 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundCapture(iface);
241 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
242 return IDirectSoundFullDuplex_QueryInterface(&This->IDirectSoundFullDuplex_iface, riid, ppobj);
245 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(IDirectSoundCapture *iface)
247 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundCapture(iface);
248 ULONG ref;
250 InterlockedIncrement(&(This->all_ref));
251 ref = InterlockedIncrement(&(This->dscref));
252 TRACE("(%p) ref %lu\n", iface, ref);
254 return ref;
257 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(IDirectSoundCapture *iface)
259 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundCapture(iface);
260 ULONG ref = InterlockedDecrement(&(This->dscref));
261 TRACE("(%p) ref %lu\n", iface, ref);
262 if(InterlockedDecrement(&(This->all_ref)) == 0)
263 DSOUND_FullDuplexDestroy(This);
264 return ref;
267 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
268 IDirectSoundCapture *iface, LPCDSCBUFFERDESC lpcDSCBufferDesc,
269 IDirectSoundCaptureBuffer **lplpDSCaptureBuffer, IUnknown *pUnk)
271 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundCapture(iface);
272 TRACE("(%p, %p, %p, %p)\n", This, lpcDSCBufferDesc, lplpDSCaptureBuffer, pUnk);
273 return IDirectSoundCapture_CreateCaptureBuffer(This->capture_device,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
276 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
277 IDirectSoundCapture *iface, LPDSCCAPS lpDSCCaps)
279 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundCapture(iface);
280 TRACE("(%p, %p)\n", This, lpDSCCaps);
281 return IDirectSoundCapture_GetCaps(This->capture_device, lpDSCCaps);
284 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
285 IDirectSoundCapture *iface, LPCGUID lpcGUID)
287 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundCapture(iface);
288 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
289 return IDirectSoundCapture_Initialize(This->capture_device,lpcGUID);
292 static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl = {
293 IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
294 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
295 IDirectSoundFullDuplex_IDirectSoundCapture_Release,
296 IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
297 IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
298 IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
301 /***************************************************************************
302 * IDirectSoundFullDuplexImpl
304 static inline IDirectSoundFullDuplexImpl *impl_from_IDirectSoundFullDuplex(IDirectSoundFullDuplex *iface)
306 return CONTAINING_RECORD(iface, IDirectSoundFullDuplexImpl, IDirectSoundFullDuplex_iface);
309 static HRESULT WINAPI IDirectSoundFullDuplexImpl_QueryInterface(
310 IDirectSoundFullDuplex *iface, REFIID riid, void **ppobj)
312 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
313 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
315 if (ppobj == NULL) {
316 WARN("invalid parameter\n");
317 return E_INVALIDARG;
320 *ppobj = NULL;
322 if (IsEqualIID(riid, &IID_IUnknown)) {
323 *ppobj = &This->IUnknown_iface;
324 IUnknown_AddRef((IUnknown*)*ppobj);
325 return S_OK;
326 } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
327 *ppobj = &This->IDirectSoundFullDuplex_iface;
328 IUnknown_AddRef((IUnknown*)*ppobj);
329 return S_OK;
330 } else if (IsEqualIID(riid, &IID_IDirectSound) ||
331 IsEqualIID(riid, &IID_IDirectSound8)) {
332 if(This->renderer_device != NULL)
334 *ppobj = &This->IDirectSound8_iface;
335 IUnknown_AddRef((IUnknown*)*ppobj);
336 return S_OK;
338 } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
339 if(This->capture_device != NULL)
341 *ppobj = &This->IDirectSoundCapture_iface;
342 IUnknown_AddRef((IUnknown*)*ppobj);
343 return S_OK;
347 return E_NOINTERFACE;
350 static ULONG WINAPI IDirectSoundFullDuplexImpl_AddRef(IDirectSoundFullDuplex *iface)
352 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
353 ULONG ref;
355 InterlockedIncrement(&(This->all_ref));
356 ref = InterlockedIncrement(&(This->ref));
357 TRACE("(%p) ref %lu\n", iface, ref);
359 return ref;
362 static ULONG WINAPI IDirectSoundFullDuplexImpl_Release(IDirectSoundFullDuplex *iface)
364 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
365 ULONG ref = InterlockedDecrement(&(This->ref));
366 TRACE("(%p) ref %lu\n", iface, ref);
367 if(InterlockedDecrement(&(This->all_ref)) == 0)
368 DSOUND_FullDuplexDestroy(This);
369 return ref;
372 static HRESULT WINAPI IDirectSoundFullDuplexImpl_Initialize(
373 IDirectSoundFullDuplex *iface,
374 LPCGUID pCaptureGuid, LPCGUID pRendererGuid,
375 LPCDSCBUFFERDESC lpDscBufferDesc, LPCDSBUFFERDESC lpDsBufferDesc,
376 HWND hWnd, DWORD dwLevel,
377 IDirectSoundCaptureBuffer8 **lplpDirectSoundCaptureBuffer8,
378 IDirectSoundBuffer8 **lplpDirectSoundBuffer8)
380 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
381 IDirectSoundCaptureBuffer *capbuffer;
382 IDirectSoundBuffer *buffer;
383 void *ptr;
384 HRESULT hr;
386 TRACE("(%p,%s,%s,%p,%p,%p,%lx,%p,%p)\n", This,
387 debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
388 lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel,
389 lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
391 if(!lplpDirectSoundBuffer8 || !lplpDirectSoundCaptureBuffer8)
393 WARN("NULL output pointers\n");
394 return DSERR_INVALIDPARAM;
397 *lplpDirectSoundCaptureBuffer8 = NULL;
398 *lplpDirectSoundBuffer8 = NULL;
400 if(This->renderer_device != NULL || This->capture_device != NULL)
402 WARN("already initialized\n");
403 return DSERR_ALREADYINITIALIZED;
406 hr = DSOUND_Create8(&IID_IDirectSound8, &ptr);
407 if(SUCCEEDED(hr))
409 This->renderer_device = ptr;
410 hr = IDirectSound8_Initialize(This->renderer_device, pRendererGuid);
412 if(hr != DS_OK)
414 WARN("DirectSoundDevice_Initialize() failed\n");
415 return hr;
418 IDirectSound8_SetCooperativeLevel(This->renderer_device, hWnd, dwLevel);
420 hr = IDirectSound8_CreateSoundBuffer(This->renderer_device, lpDsBufferDesc,
421 &buffer, NULL);
422 if(SUCCEEDED(hr))
424 hr = IDirectSoundBuffer_QueryInterface(buffer, &IID_IDirectSoundBuffer8, &ptr);
425 IDirectSoundBuffer_Release(buffer);
427 if(hr != DS_OK)
429 WARN("IDirectSoundBufferImpl_Create() failed\n");
430 return hr;
432 *lplpDirectSoundBuffer8 = ptr;
434 hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture, &ptr);
435 if(SUCCEEDED(hr))
437 This->capture_device = ptr;
438 hr = IDirectSoundCapture_Initialize(This->capture_device, pCaptureGuid);
440 if(hr != DS_OK)
442 WARN("DirectSoundCaptureDevice_Initialize() failed\n");
443 return hr;
446 hr = IDirectSoundCapture_CreateCaptureBuffer(This->capture_device, lpDscBufferDesc,
447 &capbuffer, NULL);
448 if(SUCCEEDED(hr))
450 hr = IDirectSoundCaptureBuffer_QueryInterface(capbuffer, &IID_IDirectSoundCaptureBuffer8, &ptr);
451 IDirectSoundCaptureBuffer_Release(capbuffer);
453 if(hr != DS_OK)
455 WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
456 return hr;
458 *lplpDirectSoundCaptureBuffer8 = ptr;
460 return hr;
463 static const IDirectSoundFullDuplexVtbl dsfdvt = {
464 /* IUnknown methods */
465 IDirectSoundFullDuplexImpl_QueryInterface,
466 IDirectSoundFullDuplexImpl_AddRef,
467 IDirectSoundFullDuplexImpl_Release,
469 /* IDirectSoundFullDuplex methods */
470 IDirectSoundFullDuplexImpl_Initialize
473 HRESULT DSOUND_FullDuplexCreate(
474 REFIID riid, void **ppDSFD)
476 IDirectSoundFullDuplexImpl *This = NULL;
477 HRESULT hr;
479 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD);
481 if(ppDSFD == NULL)
483 WARN("invalid parameter: ppDSFD == NULL\n");
484 return DSERR_INVALIDPARAM;
486 *ppDSFD = NULL;
488 if(!IsEqualIID(riid, &IID_IUnknown) &&
489 !IsEqualIID(riid, &IID_IDirectSoundFullDuplex))
490 return E_NOINTERFACE;
492 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
493 if(This == NULL)
495 WARN("out of memory\n");
496 return DSERR_OUTOFMEMORY;
499 This->IDirectSoundFullDuplex_iface.lpVtbl = &dsfdvt;
500 This->IUnknown_iface.lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl;
501 This->IDirectSound8_iface.lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
502 This->IDirectSoundCapture_iface.lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
504 This->all_ref = 0;
505 This->ref = 0;
506 This->unkref = 0;
507 This->ds8ref = 0;
508 This->dscref = 0;
510 This->capture_device = NULL;
511 This->renderer_device = NULL;
513 hr = IDirectSoundFullDuplexImpl_QueryInterface(&This->IDirectSoundFullDuplex_iface, riid, ppDSFD);
514 if(FAILED(hr)) DSOUND_FullDuplexDestroy(This);
515 return hr;
518 /***************************************************************************
519 * DirectSoundFullDuplexCreate [DSOUND.10]
521 * Create and initialize a DirectSoundFullDuplex interface.
523 * PARAMS
524 * pcGuidCaptureDevice [I] Address of sound capture device GUID.
525 * pcGuidRenderDevice [I] Address of sound render device GUID.
526 * pcDSCBufferDesc [I] Address of capture buffer description.
527 * pcDSBufferDesc [I] Address of render buffer description.
528 * hWnd [I] Handle to application window.
529 * dwLevel [I] Cooperative level.
530 * ppDSFD [O] Address where full duplex interface returned.
531 * ppDSCBuffer8 [0] Address where capture buffer interface returned.
532 * ppDSBuffer8 [0] Address where render buffer interface returned.
533 * pUnkOuter [I] Must be NULL.
535 * RETURNS
536 * Success: DS_OK
537 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
538 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
540 HRESULT WINAPI
541 DirectSoundFullDuplexCreate(
542 LPCGUID pcGuidCaptureDevice, LPCGUID pcGuidRenderDevice,
543 LPCDSCBUFFERDESC pcDSCBufferDesc, LPCDSBUFFERDESC pcDSBufferDesc,
544 HWND hWnd, DWORD dwLevel,
545 IDirectSoundFullDuplex **ppDSFD,
546 IDirectSoundCaptureBuffer8 **ppDSCBuffer8,
547 IDirectSoundBuffer8 **ppDSBuffer8,
548 IUnknown *pUnkOuter)
550 void *iface = NULL;
551 HRESULT hres;
553 TRACE("(%s,%s,%p,%p,%p,%lx,%p,%p,%p,%p)\n",
554 debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice),
555 pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8,
556 ppDSBuffer8, pUnkOuter);
558 if(ppDSFD == NULL)
560 WARN("invalid parameter: ppDSFD == NULL\n");
561 return DSERR_INVALIDPARAM;
563 *ppDSFD = NULL;
565 if(pUnkOuter)
567 WARN("pUnkOuter != 0\n");
568 return DSERR_NOAGGREGATION;
571 if(pcDSCBufferDesc == NULL)
573 WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
574 return DSERR_INVALIDPARAM;
577 if(pcDSBufferDesc == NULL)
579 WARN("invalid parameter: pcDSBufferDesc == NULL\n");
580 return DSERR_INVALIDPARAM;
584 if(ppDSCBuffer8 == NULL)
586 WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
587 return DSERR_INVALIDPARAM;
590 if(ppDSBuffer8 == NULL)
592 WARN("invalid parameter: ppDSBuffer8 == NULL\n");
593 return DSERR_INVALIDPARAM;
596 hres = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, &iface);
597 if(FAILED(hres)) return hres;
599 *ppDSFD = iface;
600 hres = IDirectSoundFullDuplexImpl_Initialize(*ppDSFD,
601 pcGuidCaptureDevice,
602 pcGuidRenderDevice,
603 pcDSCBufferDesc,
604 pcDSBufferDesc,
605 hWnd, dwLevel,
606 ppDSCBuffer8,
607 ppDSBuffer8);
608 if(hres != DS_OK)
610 IDirectSoundFullDuplex_Release(*ppDSFD);
611 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
612 *ppDSFD = NULL;
615 return hres;