dsound: Cleanup error handling in IDirectSoundFullDuplex::Initialize().
[wine/multimedia.git] / dlls / dsound / duplex.c
blob49cba9fa26f8a0db5a09a30b387959adf7da7d9e
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 #include <stdarg.h>
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
27 #define COBJMACROS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "mmsystem.h"
32 #include "mmddk.h"
33 #include "winternl.h"
34 #include "wine/debug.h"
35 #include "dsound.h"
36 #include "dsound_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
40 /*****************************************************************************
41 * IDirectSoundFullDuplex implementation structure
43 typedef struct IDirectSoundFullDuplexImpl
45 /* IUnknown fields */
46 const IDirectSoundFullDuplexVtbl *lpVtbl;
47 LONG ref;
49 /* IDirectSoundFullDuplexImpl fields */
50 IDirectSound8 *renderer_device;
51 IDirectSoundCapture *capture_device;
53 LPUNKNOWN pUnknown;
54 LPDIRECTSOUND8 pDS8;
55 LPDIRECTSOUNDCAPTURE pDSC;
56 } IDirectSoundFullDuplexImpl;
58 typedef struct IDirectSoundFullDuplex_IUnknown {
59 const IUnknownVtbl *lpVtbl;
60 LONG ref;
61 IDirectSoundFullDuplexImpl *pdsfd;
62 } IDirectSoundFullDuplex_IUnknown;
64 typedef struct IDirectSoundFullDuplex_IDirectSound8 {
65 const IDirectSound8Vtbl *lpVtbl;
66 LONG ref;
67 IDirectSoundFullDuplexImpl *pdsfd;
68 } IDirectSoundFullDuplex_IDirectSound8;
70 typedef struct IDirectSoundFullDuplex_IDirectSoundCapture {
71 const IDirectSoundCaptureVtbl *lpVtbl;
72 LONG ref;
73 IDirectSoundFullDuplexImpl *pdsfd;
74 } IDirectSoundFullDuplex_IDirectSoundCapture;
76 /*******************************************************************************
77 * IUnknown
79 static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface(
80 LPUNKNOWN iface,
81 REFIID riid,
82 LPVOID * ppobj)
84 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
85 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
86 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
89 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef(
90 LPUNKNOWN iface)
92 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
93 ULONG ref = InterlockedIncrement(&(This->ref));
94 TRACE("(%p) ref was %d\n", This, ref - 1);
95 return ref;
98 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release(
99 LPUNKNOWN iface)
101 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
102 ULONG ref = InterlockedDecrement(&(This->ref));
103 TRACE("(%p) ref was %d\n", This, ref + 1);
104 if (!ref) {
105 This->pdsfd->pUnknown = NULL;
106 HeapFree(GetProcessHeap(), 0, This);
107 TRACE("(%p) released\n", This);
109 return ref;
112 static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl =
114 IDirectSoundFullDuplex_IUnknown_QueryInterface,
115 IDirectSoundFullDuplex_IUnknown_AddRef,
116 IDirectSoundFullDuplex_IUnknown_Release
119 static HRESULT IDirectSoundFullDuplex_IUnknown_Create(
120 LPDIRECTSOUNDFULLDUPLEX pdsfd,
121 LPUNKNOWN * ppunk)
123 IDirectSoundFullDuplex_IUnknown * pdsfdunk;
124 TRACE("(%p,%p)\n",pdsfd,ppunk);
126 if (pdsfd == NULL) {
127 ERR("invalid parameter: pdsfd == NULL\n");
128 return DSERR_INVALIDPARAM;
131 if (ppunk == NULL) {
132 ERR("invalid parameter: ppunk == NULL\n");
133 return DSERR_INVALIDPARAM;
136 pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk));
137 if (pdsfdunk == NULL) {
138 WARN("out of memory\n");
139 *ppunk = NULL;
140 return DSERR_OUTOFMEMORY;
143 pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl;
144 pdsfdunk->ref = 0;
145 pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
147 *ppunk = (LPUNKNOWN)pdsfdunk;
149 return DS_OK;
152 /*******************************************************************************
153 * IDirectSoundFullDuplex_IDirectSound8
155 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
156 LPDIRECTSOUND8 iface,
157 REFIID riid,
158 LPVOID * ppobj)
160 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
161 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
162 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
165 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(
166 LPDIRECTSOUND8 iface)
168 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
169 ULONG ref = InterlockedIncrement(&(This->ref));
170 TRACE("(%p) ref was %d\n", This, ref - 1);
171 return ref;
174 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(
175 LPDIRECTSOUND8 iface)
177 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
178 ULONG ref = InterlockedDecrement(&(This->ref));
179 TRACE("(%p) ref was %d\n", This, ref + 1);
180 if (!ref) {
181 This->pdsfd->pDS8 = NULL;
182 HeapFree(GetProcessHeap(), 0, This);
183 TRACE("(%p) released\n", This);
185 return ref;
188 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
189 LPDIRECTSOUND8 iface,
190 LPCDSBUFFERDESC dsbd,
191 LPLPDIRECTSOUNDBUFFER ppdsb,
192 LPUNKNOWN lpunk)
194 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
195 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
196 return IDirectSound8_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk);
199 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
200 LPDIRECTSOUND8 iface,
201 LPDSCAPS lpDSCaps)
203 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
204 TRACE("(%p,%p)\n",This,lpDSCaps);
205 return IDirectSound8_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
208 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
209 LPDIRECTSOUND8 iface,
210 LPDIRECTSOUNDBUFFER psb,
211 LPLPDIRECTSOUNDBUFFER ppdsb)
213 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
214 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
215 return IDirectSound8_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
218 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
219 LPDIRECTSOUND8 iface,
220 HWND hwnd,
221 DWORD level)
223 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
224 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
225 return IDirectSound8_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
228 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(
229 LPDIRECTSOUND8 iface)
231 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
232 TRACE("(%p)\n", This);
233 return IDirectSound8_Compact(This->pdsfd->renderer_device);
236 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
237 LPDIRECTSOUND8 iface,
238 LPDWORD lpdwSpeakerConfig)
240 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
241 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
242 return IDirectSound8_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
245 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
246 LPDIRECTSOUND8 iface,
247 DWORD config)
249 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
250 TRACE("(%p,0x%08x)\n",This,config);
251 return IDirectSound8_SetSpeakerConfig(This->pdsfd->renderer_device,config);
254 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
255 LPDIRECTSOUND8 iface,
256 LPCGUID lpcGuid)
258 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
259 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
260 return IDirectSound8_Initialize(This->pdsfd->renderer_device,lpcGuid);
263 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_VerifyCertification(
264 LPDIRECTSOUND8 iface,
265 DWORD *cert)
267 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
268 TRACE("(%p, %p)\n", This, cert);
269 return IDirectSound8_VerifyCertification(This->pdsfd->renderer_device,cert);
272 static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl =
274 IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
275 IDirectSoundFullDuplex_IDirectSound8_AddRef,
276 IDirectSoundFullDuplex_IDirectSound8_Release,
277 IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
278 IDirectSoundFullDuplex_IDirectSound8_GetCaps,
279 IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
280 IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
281 IDirectSoundFullDuplex_IDirectSound8_Compact,
282 IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
283 IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
284 IDirectSoundFullDuplex_IDirectSound8_Initialize,
285 IDirectSoundFullDuplex_IDirectSound8_VerifyCertification
288 static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create(
289 LPDIRECTSOUNDFULLDUPLEX pdsfd,
290 LPDIRECTSOUND8 * ppds8)
292 IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8;
293 TRACE("(%p,%p)\n",pdsfd,ppds8);
295 if (pdsfd == NULL) {
296 ERR("invalid parameter: pdsfd == NULL\n");
297 return DSERR_INVALIDPARAM;
300 if (ppds8 == NULL) {
301 ERR("invalid parameter: ppds8 == NULL\n");
302 return DSERR_INVALIDPARAM;
305 if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
306 WARN("not initialized\n");
307 *ppds8 = NULL;
308 return DSERR_UNINITIALIZED;
311 pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8));
312 if (pdsfdds8 == NULL) {
313 WARN("out of memory\n");
314 *ppds8 = NULL;
315 return DSERR_OUTOFMEMORY;
318 pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
319 pdsfdds8->ref = 0;
320 pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
322 *ppds8 = (LPDIRECTSOUND8)pdsfdds8;
324 return DS_OK;
327 /*******************************************************************************
328 * IDirectSoundFullDuplex_IDirectSoundCapture
330 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
331 LPDIRECTSOUNDCAPTURE iface,
332 REFIID riid,
333 LPVOID * ppobj)
335 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
336 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
337 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
340 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(
341 LPDIRECTSOUNDCAPTURE iface)
343 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
344 ULONG ref = InterlockedIncrement(&(This->ref));
345 TRACE("(%p) ref was %d\n", This, ref - 1);
346 return ref;
349 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(
350 LPDIRECTSOUNDCAPTURE iface)
352 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
353 ULONG ref = InterlockedDecrement(&(This->ref));
354 TRACE("(%p) ref was %d\n", This, ref + 1);
355 if (!ref) {
356 This->pdsfd->pDSC = NULL;
357 HeapFree(GetProcessHeap(), 0, This);
358 TRACE("(%p) released\n", This);
360 return ref;
363 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
364 LPDIRECTSOUNDCAPTURE iface,
365 LPCDSCBUFFERDESC lpcDSCBufferDesc,
366 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
367 LPUNKNOWN pUnk)
369 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
370 TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
371 return IDirectSoundCapture_CreateCaptureBuffer(This->pdsfd->capture_device,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
374 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
375 LPDIRECTSOUNDCAPTURE iface,
376 LPDSCCAPS lpDSCCaps)
378 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
379 TRACE("(%p,%p)\n",This,lpDSCCaps);
380 return IDirectSoundCapture_GetCaps(This->pdsfd->capture_device, lpDSCCaps);
383 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
384 LPDIRECTSOUNDCAPTURE iface,
385 LPCGUID lpcGUID)
387 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
388 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
389 return IDirectSoundCapture_Initialize(This->pdsfd->capture_device,lpcGUID);
392 static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl =
394 IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
395 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
396 IDirectSoundFullDuplex_IDirectSoundCapture_Release,
397 IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
398 IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
399 IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
402 static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create(
403 LPDIRECTSOUNDFULLDUPLEX pdsfd,
404 LPDIRECTSOUNDCAPTURE8 * ppdsc8)
406 IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc;
407 TRACE("(%p,%p)\n",pdsfd,ppdsc8);
409 if (pdsfd == NULL) {
410 ERR("invalid parameter: pdsfd == NULL\n");
411 return DSERR_INVALIDPARAM;
414 if (ppdsc8 == NULL) {
415 ERR("invalid parameter: ppdsc8 == NULL\n");
416 return DSERR_INVALIDPARAM;
419 if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) {
420 WARN("not initialized\n");
421 *ppdsc8 = NULL;
422 return DSERR_UNINITIALIZED;
425 pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc));
426 if (pdsfddsc == NULL) {
427 WARN("out of memory\n");
428 *ppdsc8 = NULL;
429 return DSERR_OUTOFMEMORY;
432 pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
433 pdsfddsc->ref = 0;
434 pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
436 *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc;
438 return DS_OK;
441 /***************************************************************************
442 * IDirectSoundFullDuplexImpl
444 static ULONG WINAPI
445 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
447 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
448 ULONG ref = InterlockedIncrement(&(This->ref));
449 TRACE("(%p) ref was %d\n", This, ref - 1);
450 return ref;
453 static HRESULT WINAPI
454 IDirectSoundFullDuplexImpl_QueryInterface(
455 LPDIRECTSOUNDFULLDUPLEX iface,
456 REFIID riid,
457 LPVOID* ppobj )
459 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
460 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
462 if (ppobj == NULL) {
463 WARN("invalid parameter\n");
464 return E_INVALIDARG;
467 *ppobj = NULL;
469 if (IsEqualIID(riid, &IID_IUnknown)) {
470 if (!This->pUnknown) {
471 IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown);
472 if (!This->pUnknown) {
473 WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n");
474 *ppobj = NULL;
475 return E_NOINTERFACE;
478 IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown);
479 *ppobj = This->pUnknown;
480 return S_OK;
481 } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
482 IDirectSoundFullDuplexImpl_AddRef(iface);
483 *ppobj = This;
484 return S_OK;
485 } else if (IsEqualIID(riid, &IID_IDirectSound)
486 || IsEqualIID(riid, &IID_IDirectSound8)) {
487 if (!This->pDS8) {
488 IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8);
489 if (!This->pDS8) {
490 WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n");
491 *ppobj = NULL;
492 return E_NOINTERFACE;
495 IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8);
496 *ppobj = This->pDS8;
497 return S_OK;
498 } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
499 if (!This->pDSC) {
500 IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC);
501 if (!This->pDSC) {
502 WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n");
503 *ppobj = NULL;
504 return E_NOINTERFACE;
507 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC);
508 *ppobj = This->pDSC;
509 return S_OK;
512 return E_NOINTERFACE;
515 static ULONG WINAPI
516 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
518 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
519 ULONG ref = InterlockedDecrement(&(This->ref));
520 TRACE("(%p) ref was %d\n", This, ref - 1);
522 if (!ref) {
523 if (This->capture_device)
524 IDirectSoundCapture_Release(This->capture_device);
525 if (This->renderer_device)
526 IDirectSound_Release(This->renderer_device);
527 HeapFree( GetProcessHeap(), 0, This );
528 TRACE("(%p) released\n", This);
530 return ref;
533 static HRESULT WINAPI IDirectSoundFullDuplexImpl_Initialize(IDirectSoundFullDuplex *iface,
534 const GUID *capture_dev, const GUID *render_dev, const DSCBUFFERDESC *cbufdesc,
535 const DSBUFFERDESC *bufdesc, HWND hwnd, DWORD level, IDirectSoundCaptureBuffer8 **dscb8,
536 IDirectSoundBuffer8 **dsb8)
538 HRESULT hr;
539 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
541 TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This, debugstr_guid(capture_dev),
542 debugstr_guid(render_dev), cbufdesc, bufdesc, hwnd, level, dscb8, dsb8);
544 if (!dscb8 || !dsb8)
545 return E_INVALIDARG;
547 *dscb8 = NULL;
548 *dsb8 = NULL;
550 if (This->renderer_device != NULL || This->capture_device != NULL) {
551 WARN("already initialized\n");
552 return DSERR_ALREADYINITIALIZED;
555 hr = DSOUND_Create8(&IID_IDirectSound8, (void **)&This->renderer_device);
556 if (SUCCEEDED(hr))
557 hr = IDirectSound_Initialize(This->renderer_device, render_dev);
558 if (hr != DS_OK) {
559 WARN("DirectSoundDevice_Initialize() failed\n");
560 goto error;
563 IDirectSound8_SetCooperativeLevel(This->renderer_device, hwnd, level);
565 hr = IDirectSound8_CreateSoundBuffer(This->renderer_device, bufdesc,
566 (IDirectSoundBuffer**)dsb8, NULL);
567 if (hr != DS_OK) {
568 WARN("IDirectSoundBufferImpl_Create() failed\n");
569 goto error;
572 hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, (void**)&This->capture_device);
573 if (SUCCEEDED(hr))
574 hr = IDirectSoundCapture_Initialize(This->capture_device, capture_dev);
575 if (hr != DS_OK) {
576 WARN("DirectSoundCaptureDevice_Initialize() failed\n");
577 goto error;
580 hr = IDirectSoundCapture_CreateCaptureBuffer(This->capture_device, cbufdesc,
581 (IDirectSoundCaptureBuffer**)dscb8, NULL);
582 if (hr != DS_OK) {
583 WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
584 goto error;
587 return DS_OK;
589 error:
590 if (*dsb8) {
591 IDirectSoundBuffer8_Release(*dsb8);
592 *dsb8 = NULL;
594 if (This->renderer_device) {
595 IDirectSound8_Release(This->renderer_device);
596 This->renderer_device = NULL;
598 if (*dscb8) {
599 IDirectSoundCaptureBuffer8_Release(*dscb8);
600 *dscb8 = NULL;
602 if (This->capture_device) {
603 IDirectSoundCapture_Release(This->capture_device);
604 This->capture_device = NULL;
606 return hr;
609 static const IDirectSoundFullDuplexVtbl dsfdvt =
611 /* IUnknown methods */
612 IDirectSoundFullDuplexImpl_QueryInterface,
613 IDirectSoundFullDuplexImpl_AddRef,
614 IDirectSoundFullDuplexImpl_Release,
616 /* IDirectSoundFullDuplex methods */
617 IDirectSoundFullDuplexImpl_Initialize
620 HRESULT DSOUND_FullDuplexCreate(REFIID riid, void **ppv)
622 IDirectSoundFullDuplexImpl *obj;
623 HRESULT hr;
625 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
627 *ppv = NULL;
628 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj));
629 if (!obj) {
630 WARN("out of memory\n");
631 return DSERR_OUTOFMEMORY;
634 setup_dsound_options();
636 obj->lpVtbl = &dsfdvt;
637 obj->ref = 1;
639 hr = IUnknown_QueryInterface((IUnknown*)obj, riid, ppv);
640 IUnknown_Release((IUnknown*)obj);
642 return hr;
645 /***************************************************************************
646 * DirectSoundFullDuplexCreate [DSOUND.10]
648 * Create and initialize a DirectSoundFullDuplex interface.
650 * PARAMS
651 * capture_dev [I] Address of sound capture device GUID.
652 * render_dev [I] Address of sound render device GUID.
653 * cbufdesc [I] Address of capture buffer description.
654 * bufdesc [I] Address of render buffer description.
655 * hwnd [I] Handle to application window.
656 * level [I] Cooperative level.
657 * dsfd [O] Address where full duplex interface returned.
658 * dscb8 [0] Address where capture buffer interface returned.
659 * dsb8 [0] Address where render buffer interface returned.
660 * outer_unk [I] Must be NULL.
662 * RETURNS
663 * Success: DS_OK
664 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
665 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
667 HRESULT WINAPI DirectSoundFullDuplexCreate(const GUID *capture_dev, const GUID *render_dev,
668 const DSCBUFFERDESC *cbufdesc, const DSBUFFERDESC *bufdesc, HWND hwnd, DWORD level,
669 IDirectSoundFullDuplex **dsfd, IDirectSoundCaptureBuffer8 **dscb8,
670 IDirectSoundBuffer8 **dsb8, IUnknown *outer_unk)
672 HRESULT hr;
674 TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n", debugstr_guid(capture_dev),
675 debugstr_guid(render_dev), cbufdesc, bufdesc, hwnd, level, dsfd, dscb8, dsb8,
676 outer_unk);
678 if (!dsfd)
679 return DSERR_INVALIDPARAM;
680 if (outer_unk) {
681 *dsfd = NULL;
682 return DSERR_NOAGGREGATION;
685 hr = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (void**)dsfd);
686 if (hr == DS_OK) {
687 hr = IDirectSoundFullDuplex_Initialize(*dsfd, capture_dev, render_dev, cbufdesc, bufdesc,
688 hwnd, level, dscb8, dsb8);
689 if (hr != DS_OK) {
690 IDirectSoundFullDuplex_Release(*dsfd);
691 *dsfd = NULL;
692 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
696 return hr;