dsound: Remove code duplication to make code readable

Maarten Lankhorst m.b.lankhorst at gmail.com
Mon Jun 4 10:39:46 CDT 2007


This one uses a liveref to know wether to die or not.
If AddRef's ref == 1, liveref is being incremented, if Released to 0,
liveref is being decremented and if it's then zero, all 3 interfaces
attached get destroyed.
-------------- next part --------------
>From d6dfcebbfbad2b22464c19a3e7866352bca1c0af Mon Sep 17 00:00:00 2001
From: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date: Mon, 4 Jun 2007 17:09:49 +0200
Subject: [PATCH] dsound: Remove code duplication to make code readable

---
 dlls/dsound/buffer.c         |   72 +++
 dlls/dsound/capture.c        |   51 ++-
 dlls/dsound/dsound.c         | 1292 ++++++-----------------------------------
 dlls/dsound/dsound_private.h |  102 +----
 dlls/dsound/duplex.c         |  867 ++++++----------------------
 5 files changed, 478 insertions(+), 1906 deletions(-)

diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 2437758..27605d1 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -35,6 +35,78 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
 
+/*
+ * Add secondary buffer to buffer list.
+ * Gets exclusive access to buffer for writing.
+ */
+static HRESULT DirectSoundDevice_AddBuffer(
+    DirectSoundDevice * device,
+    IDirectSoundBufferImpl * pDSB)
+{
+    IDirectSoundBufferImpl **newbuffers;
+    HRESULT hr = DS_OK;
+
+    TRACE("(%p, %p)\n", device, pDSB);
+
+    RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
+
+    if (device->buffers)
+        newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
+    else
+        newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
+
+    if (newbuffers) {
+        device->buffers = newbuffers;
+        device->buffers[device->nrofbuffers] = pDSB;
+        device->nrofbuffers++;
+        TRACE("buffer count is now %d\n", device->nrofbuffers);
+    } else {
+        ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers);
+        hr = DSERR_OUTOFMEMORY;
+    }
+
+    RtlReleaseResource(&(device->buffer_list_lock));
+
+    return hr;
+}
+
+/*
+ * Remove secondary buffer from buffer list.
+ * Gets exclusive access to buffer for writing.
+ */
+static HRESULT DirectSoundDevice_RemoveBuffer(
+    DirectSoundDevice * device,
+    IDirectSoundBufferImpl * pDSB)
+{
+    int i;
+    HRESULT hr = DS_OK;
+
+    TRACE("(%p, %p)\n", device, pDSB);
+
+    RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
+
+    for (i = 0; i < device->nrofbuffers; i++)
+        if (device->buffers[i] == pDSB)
+            break;
+
+    if (i < device->nrofbuffers) {
+        /* Put the last buffer of the list in the (now empty) position */
+        device->buffers[i] = device->buffers[device->nrofbuffers - 1];
+        device->nrofbuffers--;
+        device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers);
+        TRACE("buffer count is now %d\n", device->nrofbuffers);
+    }
+
+    if (device->nrofbuffers == 0) {
+        HeapFree(GetProcessHeap(),0,device->buffers);
+        device->buffers = NULL;
+    }
+
+    RtlReleaseResource(&(device->buffer_list_lock));
+
+    return hr;
+}
+
 static HRESULT SecondaryBufferImpl_Destroy(SecondaryBufferImpl *pdsb);
 
 /*******************************************************************************
diff --git a/dlls/dsound/capture.c b/dlls/dsound/capture.c
index 34c36dd..f75311e 100644
--- a/dlls/dsound/capture.c
+++ b/dlls/dsound/capture.c
@@ -50,14 +50,12 @@ struct IDirectSoundCaptureImpl
 {
     /* IUnknown fields */
     const IDirectSoundCaptureVtbl     *lpVtbl;
-    LONG                               ref;
+    LONG                               ref, *liveref;
+    LPDIRECTSOUNDFULLDUPLEX            DuplexID;
 
     DirectSoundCaptureDevice          *device;
 };
 
-static HRESULT IDirectSoundCaptureImpl_Create(LPDIRECTSOUNDCAPTURE8 * ppds);
-
-
 /*****************************************************************************
  * IDirectSoundCaptureNotify implementation structure
  */
@@ -101,7 +99,7 @@ HRESULT DSOUND_CaptureCreate(
     /* Get dsound configuration */
     setup_dsound_options();
 
-    hr = IDirectSoundCaptureImpl_Create(&pDSC);
+    hr = IDirectSoundCaptureImpl_Create(&pDSC, NULL, NULL);
     if (hr == DS_OK) {
         IDirectSoundCapture_AddRef(pDSC);
         *ppDSC = pDSC;
@@ -130,7 +128,7 @@ HRESULT DSOUND_CaptureCreate8(
     /* Get dsound configuration */
     setup_dsound_options();
 
-    hr = IDirectSoundCaptureImpl_Create(&pDSC8);
+    hr = IDirectSoundCaptureImpl_Create(&pDSC8, NULL, NULL);
     if (hr == DS_OK) {
         IDirectSoundCapture_AddRef(pDSC8);
         *ppDSC8 = pDSC8;
@@ -454,11 +452,18 @@ IDirectSoundCaptureImpl_QueryInterface(
         IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
         *ppobj = This;
         return DS_OK;
-    } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
+    } else if (IsEqualIID(riid, &IID_IDirectSoundCapture) ||
+               IsEqualIID(riid, &IID_IDirectSoundCapture8)) {
         IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
         *ppobj = This;
         return DS_OK;
     }
+    else if (This->DuplexID && IsEqualIID(riid, &IID_IDirectSoundFullDuplex))
+    {
+        IDirectSound_AddRef((LPDIRECTSOUNDFULLDUPLEX)(This->DuplexID));
+        *ppobj = This->DuplexID;
+        return S_OK;
+    }
 
     WARN("unsupported riid: %s\n", debugstr_guid(riid));
     return E_NOINTERFACE;
@@ -470,9 +475,23 @@ IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
     IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
     ULONG ref = InterlockedIncrement(&(This->ref));
     TRACE("(%p) ref was %d\n", This, ref - 1);
+
+    if (ref == 1 && This->DuplexID)
+        InterlockedIncrement(This->liveref);
+
     return ref;
 }
 
+void IDirectSoundCaptureImpl_Destroy(LPDIRECTSOUNDCAPTURE8 device)
+{
+    IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)device;
+    if (This->device)
+        DirectSoundCaptureDevice_Release(This->device);
+
+    HeapFree(GetProcessHeap(), 0, This);
+    TRACE("(%p) released\n", This);
+}
+
 static ULONG WINAPI
 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
 {
@@ -480,13 +499,14 @@ IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
     ULONG ref = InterlockedDecrement(&(This->ref));
     TRACE("(%p) ref was %d\n", This, ref + 1);
 
-    if (!ref) {
-        if (This->device)
-            DirectSoundCaptureDevice_Release(This->device);
-
-        HeapFree( GetProcessHeap(), 0, This );
-        TRACE("(%p) released\n", This);
+    if (!ref)
+    {
+        if (!This->DuplexID)
+            IDirectSoundCaptureImpl_Destroy(iface);
+        else if (!InterlockedDecrement(This->liveref))
+            IDirectSoundFullDuplexImpl_Destroy(This->DuplexID);
     }
+
     return ref;
 }
 
@@ -591,8 +611,7 @@ static const IDirectSoundCaptureVtbl dscvt =
     IDirectSoundCaptureImpl_Initialize
 };
 
-static HRESULT IDirectSoundCaptureImpl_Create(
-    LPDIRECTSOUNDCAPTURE8 * ppDSC)
+HRESULT IDirectSoundCaptureImpl_Create(LPDIRECTSOUNDCAPTURE8 * ppDSC, LPDIRECTSOUNDFULLDUPLEX DuplexID, LONG *liveref)
 {
     IDirectSoundCaptureImpl *pDSC;
     TRACE("(%p)\n", ppDSC);
@@ -608,6 +627,8 @@ static HRESULT IDirectSoundCaptureImpl_Create(
     pDSC->lpVtbl = &dscvt;
     pDSC->ref    = 0;
     pDSC->device = NULL;
+    pDSC->DuplexID = DuplexID;
+    pDSC->liveref = liveref;
 
     *ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC;
 
diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c
index 2a72027..3c78859 100644
--- a/dlls/dsound/dsound.c
+++ b/dlls/dsound/dsound.c
@@ -4,6 +4,7 @@
  * Copyright 1998 Rob Riggs
  * Copyright 2000-2002 TransGaming Technologies, Inc.
  * Copyright 2004 Robert Reif
+ * Copyright 2007 Maarten Lankhorst
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -38,75 +39,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
 
-/*****************************************************************************
- * IDirectSound COM components
- */
-struct IDirectSound_IUnknown {
-    const IUnknownVtbl         *lpVtbl;
-    LONG                        ref;
-    LPDIRECTSOUND8              pds;
-};
-
-static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
-
-struct IDirectSound_IDirectSound {
-    const IDirectSoundVtbl     *lpVtbl;
-    LONG                        ref;
-    LPDIRECTSOUND8              pds;
-};
-
-static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
-
-/*****************************************************************************
- * IDirectSound8 COM components
- */
-struct IDirectSound8_IUnknown {
-    const IUnknownVtbl         *lpVtbl;
-    LONG                        ref;
-    LPDIRECTSOUND8              pds;
-};
-
-static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
-static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
-
-struct IDirectSound8_IDirectSound {
-    const IDirectSoundVtbl     *lpVtbl;
-    LONG                        ref;
-    LPDIRECTSOUND8              pds;
-};
-
-static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
-static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
-
-struct IDirectSound8_IDirectSound8 {
-    const IDirectSound8Vtbl    *lpVtbl;
-    LONG                        ref;
-    LPDIRECTSOUND8              pds;
-};
-
-static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds);
-static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
-
-/*****************************************************************************
- * IDirectSound implementation structure
- */
-struct IDirectSoundImpl
-{
-    LONG                        ref;
-
-    DirectSoundDevice          *device;
-    LPUNKNOWN                   pUnknown;
-    LPDIRECTSOUND               pDS;
-    LPDIRECTSOUND8              pDS8;
-};
-
-static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds);
-
-static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
-static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
-
-static HRESULT DirectSoundDevice_VerifyCertification(DirectSoundDevice * device, LPDWORD pdwCertified);
-
 const char * dumpCooperativeLevel(DWORD level)
 {
     static char unknown[32];
@@ -176,835 +108,51 @@ static void _dump_DSBCAPS(DWORD xmask) {
             TRACE("%s ",flags[i].name);
 }
 
-/*******************************************************************************
- *		IDirectSoundImpl_DirectSound
- */
-static HRESULT DSOUND_QueryInterface(
-    LPDIRECTSOUND8 iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-
-    if (ppobj == NULL) {
-        WARN("invalid parameter\n");
-        return E_INVALIDARG;
-    }
-
-    if (IsEqualIID(riid, &IID_IUnknown)) {
-        if (!This->pUnknown) {
-            IDirectSound_IUnknown_Create(iface, &This->pUnknown);
-            if (!This->pUnknown) {
-                WARN("IDirectSound_IUnknown_Create() failed\n");
-                *ppobj = NULL;
-                return E_NOINTERFACE;
-            }
-        }
-        IDirectSound_IUnknown_AddRef(This->pUnknown);
-        *ppobj = This->pUnknown;
-        return S_OK;
-    } else if (IsEqualIID(riid, &IID_IDirectSound)) {
-        if (!This->pDS) {
-            IDirectSound_IDirectSound_Create(iface, &This->pDS);
-            if (!This->pDS) {
-                WARN("IDirectSound_IDirectSound_Create() failed\n");
-                *ppobj = NULL;
-                return E_NOINTERFACE;
-            }
-        }
-        IDirectSound_IDirectSound_AddRef(This->pDS);
-        *ppobj = This->pDS;
-        return S_OK;
-    }
-
-    *ppobj = NULL;
-    WARN("Unknown IID %s\n",debugstr_guid(riid));
-    return E_NOINTERFACE;
-}
-
-static HRESULT DSOUND_QueryInterface8(
-    LPDIRECTSOUND8 iface,
-    REFIID riid,
-    LPVOID * ppobj)
+HRESULT DSOUND_Create(REFIID riid, LPDIRECTSOUND *ppDS)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-
-    if (ppobj == NULL) {
-        WARN("invalid parameter\n");
-        return E_INVALIDARG;
-    }
-
-    if (IsEqualIID(riid, &IID_IUnknown)) {
-        if (!This->pUnknown) {
-            IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
-            if (!This->pUnknown) {
-                WARN("IDirectSound8_IUnknown_Create() failed\n");
-                *ppobj = NULL;
-                return E_NOINTERFACE;
-            }
-        }
-        IDirectSound8_IUnknown_AddRef(This->pUnknown);
-        *ppobj = This->pUnknown;
-        return S_OK;
-    } else if (IsEqualIID(riid, &IID_IDirectSound)) {
-        if (!This->pDS) {
-            IDirectSound8_IDirectSound_Create(iface, &This->pDS);
-            if (!This->pDS) {
-                WARN("IDirectSound8_IDirectSound_Create() failed\n");
-                *ppobj = NULL;
-                return E_NOINTERFACE;
-            }
-        }
-        IDirectSound8_IDirectSound_AddRef(This->pDS);
-        *ppobj = This->pDS;
-        return S_OK;
-    } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
-        if (!This->pDS8) {
-            IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
-            if (!This->pDS8) {
-                WARN("IDirectSound8_IDirectSound8_Create() failed\n");
-                *ppobj = NULL;
-                return E_NOINTERFACE;
-            }
-        }
-        IDirectSound8_IDirectSound8_AddRef(This->pDS8);
-        *ppobj = This->pDS8;
-        return S_OK;
-    }
-
-    *ppobj = NULL;
-    WARN("Unknown IID %s\n",debugstr_guid(riid));
-    return E_NOINTERFACE;
-}
-
-static ULONG IDirectSoundImpl_AddRef(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
-    return ref;
-}
-
-static ULONG IDirectSoundImpl_Release(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref + 1);
-
-    if (!ref) {
-        if (This->device)
-            DirectSoundDevice_Release(This->device);
-        HeapFree(GetProcessHeap(),0,This);
-        TRACE("(%p) released\n", This);
-    }
-    return ref;
-}
-
-static HRESULT IDirectSoundImpl_Create(
-    LPDIRECTSOUND8 * ppDS)
-{
-    IDirectSoundImpl* pDS;
-    TRACE("(%p)\n",ppDS);
+    HRESULT hr;
+    TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
 
-    /* Allocate memory */
-    pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
-    if (pDS == NULL) {
-        WARN("out of memory\n");
+    if (!IsEqualIID(riid, &IID_IUnknown) &&
+        !IsEqualIID(riid, &IID_IDirectSound)) {
         *ppDS = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
-
-    pDS->ref    = 0;
-    pDS->device = NULL;
-
-    *ppDS = (LPDIRECTSOUND8)pDS;
-
-    return DS_OK;
-}
-
-/*******************************************************************************
- *		IDirectSound_IUnknown
- */
-static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
-    LPUNKNOWN iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return DSOUND_QueryInterface(This->pds, riid, ppobj);
-}
-
-static ULONG WINAPI IDirectSound_IUnknown_AddRef(
-    LPUNKNOWN iface)
-{
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
-    return ref;
-}
-
-static ULONG WINAPI IDirectSound_IUnknown_Release(
-    LPUNKNOWN iface)
-{
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref + 1);
-    if (!ref) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
-    }
-    return ref;
-}
-
-static const IUnknownVtbl DirectSound_Unknown_Vtbl =
-{
-    IDirectSound_IUnknown_QueryInterface,
-    IDirectSound_IUnknown_AddRef,
-    IDirectSound_IUnknown_Release
-};
-
-static HRESULT IDirectSound_IUnknown_Create(
-    LPDIRECTSOUND8 pds,
-    LPUNKNOWN * ppunk)
-{
-    IDirectSound_IUnknown * pdsunk;
-    TRACE("(%p,%p)\n",pds,ppunk);
-
-    if (ppunk == NULL) {
-        ERR("invalid parameter: ppunk == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (pds == NULL) {
-        ERR("invalid parameter: pds == NULL\n");
-        *ppunk = NULL;
-        return DSERR_INVALIDPARAM;
-    }
-
-    pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
-    if (pdsunk == NULL) {
-        WARN("out of memory\n");
-        *ppunk = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
-
-    pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
-    pdsunk->ref = 0;
-    pdsunk->pds = pds;
-
-    IDirectSoundImpl_AddRef(pds);
-    *ppunk = (LPUNKNOWN)pdsunk;
-
-    return DS_OK;
-}
-
-/*******************************************************************************
- *		IDirectSound_IDirectSound
- */
-static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
-    LPDIRECTSOUND iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return DSOUND_QueryInterface(This->pds, riid, ppobj);
-}
-
-static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
-    return ref;
-}
-
-static ULONG WINAPI IDirectSound_IDirectSound_Release(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref + 1);
-    if (!ref) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
-    }
-    return ref;
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,FALSE);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
-    LPDIRECTSOUND iface,
-    LPDSCAPS lpDSCaps)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%p)\n",This,lpDSCaps);
-    return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-    return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
-    LPDIRECTSOUND iface,
-    HWND hwnd,
-    DWORD level)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
-    return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p)\n", This);
-    return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    LPDWORD lpdwSpeakerConfig)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    DWORD config)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,0x%08x)\n",This,config);
-    return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
-    LPDIRECTSOUND iface,
-    LPCGUID lpcGuid)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-    return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
-}
-
-static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
-{
-    IDirectSound_IDirectSound_QueryInterface,
-    IDirectSound_IDirectSound_AddRef,
-    IDirectSound_IDirectSound_Release,
-    IDirectSound_IDirectSound_CreateSoundBuffer,
-    IDirectSound_IDirectSound_GetCaps,
-    IDirectSound_IDirectSound_DuplicateSoundBuffer,
-    IDirectSound_IDirectSound_SetCooperativeLevel,
-    IDirectSound_IDirectSound_Compact,
-    IDirectSound_IDirectSound_GetSpeakerConfig,
-    IDirectSound_IDirectSound_SetSpeakerConfig,
-    IDirectSound_IDirectSound_Initialize
-};
-
-static HRESULT IDirectSound_IDirectSound_Create(
-    LPDIRECTSOUND8  pds,
-    LPDIRECTSOUND * ppds)
-{
-    IDirectSound_IDirectSound * pdsds;
-    TRACE("(%p,%p)\n",pds,ppds);
-
-    if (ppds == NULL) {
-        ERR("invalid parameter: ppds == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (pds == NULL) {
-        ERR("invalid parameter: pds == NULL\n");
-        *ppds = NULL;
-        return DSERR_INVALIDPARAM;
-    }
-
-    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
-    if (pdsds == NULL) {
-        WARN("out of memory\n");
-        *ppds = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
-
-    pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
-    pdsds->ref = 0;
-    pdsds->pds = pds;
-
-    IDirectSoundImpl_AddRef(pds);
-    *ppds = (LPDIRECTSOUND)pdsds;
-
-    return DS_OK;
-}
-
-/*******************************************************************************
- *		IDirectSound8_IUnknown
- */
-static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
-    LPUNKNOWN iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
-}
-
-static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
-    LPUNKNOWN iface)
-{
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
-    return ref;
-}
-
-static ULONG WINAPI IDirectSound8_IUnknown_Release(
-    LPUNKNOWN iface)
-{
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref + 1);
-    if (!ref) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
-    }
-    return ref;
-}
-
-static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
-{
-    IDirectSound8_IUnknown_QueryInterface,
-    IDirectSound8_IUnknown_AddRef,
-    IDirectSound8_IUnknown_Release
-};
-
-static HRESULT IDirectSound8_IUnknown_Create(
-    LPDIRECTSOUND8 pds,
-    LPUNKNOWN * ppunk)
-{
-    IDirectSound8_IUnknown * pdsunk;
-    TRACE("(%p,%p)\n",pds,ppunk);
-
-    if (ppunk == NULL) {
-        ERR("invalid parameter: ppunk == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (pds == NULL) {
-        ERR("invalid parameter: pds == NULL\n");
-        *ppunk = NULL;
-        return DSERR_INVALIDPARAM;
-    }
-
-    pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
-    if (pdsunk == NULL) {
-        WARN("out of memory\n");
-        *ppunk = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
-
-    pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
-    pdsunk->ref = 0;
-    pdsunk->pds = pds;
-
-    IDirectSoundImpl_AddRef(pds);
-    *ppunk = (LPUNKNOWN)pdsunk;
-
-    return DS_OK;
-}
-
-/*******************************************************************************
- *		IDirectSound8_IDirectSound
- */
-static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
-    LPDIRECTSOUND iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
-}
-
-static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
-    return ref;
-}
-
-static ULONG WINAPI IDirectSound8_IDirectSound_Release(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref + 1);
-    if (!ref) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
-    }
-    return ref;
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
-    LPDIRECTSOUND iface,
-    LPDSCAPS lpDSCaps)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%p)\n",This,lpDSCaps);
-    return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-    return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
-    LPDIRECTSOUND iface,
-    HWND hwnd,
-    DWORD level)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
-    return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p)\n", This);
-    return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    LPDWORD lpdwSpeakerConfig)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    DWORD config)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,0x%08x)\n",This,config);
-    return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
-    LPDIRECTSOUND iface,
-    LPCGUID lpcGuid)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-    return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
-}
-
-static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
-{
-    IDirectSound8_IDirectSound_QueryInterface,
-    IDirectSound8_IDirectSound_AddRef,
-    IDirectSound8_IDirectSound_Release,
-    IDirectSound8_IDirectSound_CreateSoundBuffer,
-    IDirectSound8_IDirectSound_GetCaps,
-    IDirectSound8_IDirectSound_DuplicateSoundBuffer,
-    IDirectSound8_IDirectSound_SetCooperativeLevel,
-    IDirectSound8_IDirectSound_Compact,
-    IDirectSound8_IDirectSound_GetSpeakerConfig,
-    IDirectSound8_IDirectSound_SetSpeakerConfig,
-    IDirectSound8_IDirectSound_Initialize
-};
-
-static HRESULT IDirectSound8_IDirectSound_Create(
-    LPDIRECTSOUND8 pds,
-    LPDIRECTSOUND * ppds)
-{
-    IDirectSound8_IDirectSound * pdsds;
-    TRACE("(%p,%p)\n",pds,ppds);
-
-    if (ppds == NULL) {
-        ERR("invalid parameter: ppds == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (pds == NULL) {
-        ERR("invalid parameter: pds == NULL\n");
-        *ppds = NULL;
-        return DSERR_INVALIDPARAM;
-    }
-
-    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
-    if (pdsds == NULL) {
-        WARN("out of memory\n");
-        *ppds = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
-
-    pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
-    pdsds->ref = 0;
-    pdsds->pds = pds;
-
-    IDirectSoundImpl_AddRef(pds);
-    *ppds = (LPDIRECTSOUND)pdsds;
-
-    return DS_OK;
-}
-
-/*******************************************************************************
- *		IDirectSound8_IDirectSound8
- */
-static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
-    LPDIRECTSOUND8 iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
-}
-
-static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
-    return ref;
-}
-
-static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref + 1);
-    if (!ref) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
-    }
-    return ref;
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
-    LPDIRECTSOUND8 iface,
-    LPDSCAPS lpDSCaps)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%p)\n",This,lpDSCaps);
-    return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-    return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
-    LPDIRECTSOUND8 iface,
-    HWND hwnd,
-    DWORD level)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
-    return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p)\n", This);
-    return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
-    LPDIRECTSOUND8 iface,
-    LPDWORD lpdwSpeakerConfig)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
-    LPDIRECTSOUND8 iface,
-    DWORD config)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,0x%08x)\n",This,config);
-    return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
-    LPDIRECTSOUND8 iface,
-    LPCGUID lpcGuid)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-    return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
-}
-
-static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
-    LPDIRECTSOUND8 iface,
-    LPDWORD pdwCertified)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p, %p)\n", This, pdwCertified);
-    return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified);
-}
-
-static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
-{
-    IDirectSound8_IDirectSound8_QueryInterface,
-    IDirectSound8_IDirectSound8_AddRef,
-    IDirectSound8_IDirectSound8_Release,
-    IDirectSound8_IDirectSound8_CreateSoundBuffer,
-    IDirectSound8_IDirectSound8_GetCaps,
-    IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
-    IDirectSound8_IDirectSound8_SetCooperativeLevel,
-    IDirectSound8_IDirectSound8_Compact,
-    IDirectSound8_IDirectSound8_GetSpeakerConfig,
-    IDirectSound8_IDirectSound8_SetSpeakerConfig,
-    IDirectSound8_IDirectSound8_Initialize,
-    IDirectSound8_IDirectSound8_VerifyCertification
-};
-
-static HRESULT IDirectSound8_IDirectSound8_Create(
-    LPDIRECTSOUND8 pds,
-    LPDIRECTSOUND8 * ppds)
-{
-    IDirectSound8_IDirectSound8 * pdsds;
-    TRACE("(%p,%p)\n",pds,ppds);
-
-    if (ppds == NULL) {
-        ERR("invalid parameter: ppds == NULL\n");
-        return DSERR_INVALIDPARAM;
+        return E_NOINTERFACE;
     }
 
-    if (pds == NULL) {
-        ERR("invalid parameter: pds == NULL\n");
-        *ppds = NULL;
-        return DSERR_INVALIDPARAM;
-    }
+    /* Get dsound configuration */
+    setup_dsound_options();
 
-    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
-    if (pdsds == NULL) {
-        WARN("out of memory\n");
-        *ppds = NULL;
-        return DSERR_OUTOFMEMORY;
+    hr = IDirectSoundImpl_Create((LPDIRECTSOUND8 *)ppDS, NULL, NULL, FALSE);
+    if (FAILED(hr)) {
+        WARN("IDirectSoundImpl_Create failed: %08x\n", hr);
+        *ppDS = NULL;
     }
+    IDirectSound_AddRef(*ppDS);
 
-    pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
-    pdsds->ref = 0;
-    pdsds->pds = pds;
-
-    IDirectSoundImpl_AddRef(pds);
-    *ppds = (LPDIRECTSOUND8)pdsds;
-
-    return DS_OK;
+    return hr;
 }
 
-HRESULT DSOUND_Create(
-    REFIID riid,
-    LPDIRECTSOUND *ppDS)
+HRESULT DSOUND_Create8(REFIID riid, LPDIRECTSOUND8 *ppDS)
 {
-    LPDIRECTSOUND8 pDS;
     HRESULT hr;
     TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
 
     if (!IsEqualIID(riid, &IID_IUnknown) &&
-        !IsEqualIID(riid, &IID_IDirectSound)) {
-        *ppDS = 0;
+        !IsEqualIID(riid, &IID_IDirectSound) &&
+        !IsEqualIID(riid, &IID_IDirectSound8)) {
+        *ppDS = NULL;
         return E_NOINTERFACE;
     }
 
     /* Get dsound configuration */
     setup_dsound_options();
 
-    hr = IDirectSoundImpl_Create(&pDS);
-    if (hr == DS_OK) {
-        hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
-        if (*ppDS)
-            IDirectSound_IDirectSound_AddRef(*ppDS);
-        else {
-            WARN("IDirectSound_IDirectSound_Create failed\n");
-            IDirectSound8_Release(pDS);
-        }
-    } else {
-        WARN("IDirectSoundImpl_Create failed\n");
-        *ppDS = 0;
+    hr = IDirectSoundImpl_Create(ppDS, NULL, NULL, TRUE);
+    if (FAILED(hr)) {
+        WARN("IDirectSoundImpl_Create failed: %08x\n", hr);
+        *ppDS = NULL;
     }
+    IDirectSound_AddRef(*ppDS);
 
     return hr;
 }
@@ -1030,7 +178,6 @@ HRESULT WINAPI DirectSoundCreate(
     IUnknown *pUnkOuter)
 {
     HRESULT hr;
-    LPDIRECTSOUND pDS;
 
     TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
 
@@ -1045,55 +192,16 @@ HRESULT WINAPI DirectSoundCreate(
         return DSERR_INVALIDPARAM;
     }
 
-    hr = DSOUND_Create(&IID_IDirectSound, &pDS);
-    if (hr == DS_OK) {
-        hr = IDirectSound_Initialize(pDS, lpcGUID);
-        if (hr != DS_OK) {
-            if (hr != DSERR_ALREADYINITIALIZED) {
-                IDirectSound_Release(pDS);
-                pDS = 0;
-            } else
-                hr = DS_OK;
-        }
-    }
-
-    *ppDS = pDS;
-
-    return hr;
-}
-
-HRESULT DSOUND_Create8(
-    REFIID riid,
-    LPDIRECTSOUND8 *ppDS)
-{
-    LPDIRECTSOUND8 pDS;
-    HRESULT hr;
-    TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
-
-    if (!IsEqualIID(riid, &IID_IUnknown) &&
-        !IsEqualIID(riid, &IID_IDirectSound) &&
-        !IsEqualIID(riid, &IID_IDirectSound8)) {
-        *ppDS = 0;
-        return E_NOINTERFACE;
-    }
-
-    /* Get dsound configuration */
-    setup_dsound_options();
-
-    hr = IDirectSoundImpl_Create(&pDS);
-    if (hr == DS_OK) {
-        hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
-        if (*ppDS)
-            IDirectSound8_IDirectSound8_AddRef(*ppDS);
-        else {
-            WARN("IDirectSound8_IDirectSound8_Create failed\n");
-            IDirectSound8_Release(pDS);
+    hr = DSOUND_Create(&IID_IDirectSound, ppDS);
+    if (!FAILED(hr))
+    {
+        hr = IDirectSound_Initialize(*ppDS, lpcGUID);
+        if (FAILED(hr))
+        {
+            IDirectSound_Release(*ppDS);
+            *ppDS = NULL;
         }
-    } else {
-        WARN("IDirectSoundImpl_Create failed\n");
-        *ppDS = 0;
     }
-
     return hr;
 }
 
@@ -1118,7 +226,6 @@ HRESULT WINAPI DirectSoundCreate8(
     IUnknown *pUnkOuter)
 {
     HRESULT hr;
-    LPDIRECTSOUND8 pDS;
 
     TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
 
@@ -1133,29 +240,50 @@ HRESULT WINAPI DirectSoundCreate8(
         return DSERR_INVALIDPARAM;
     }
 
-    hr = DSOUND_Create8(&IID_IDirectSound8, &pDS);
-    if (hr == DS_OK) {
-        hr = IDirectSound8_Initialize(pDS, lpcGUID);
-        if (hr != DS_OK) {
-            if (hr != DSERR_ALREADYINITIALIZED) {
-                IDirectSound8_Release(pDS);
-                pDS = 0;
-            } else
-                hr = DS_OK;
+    hr = DSOUND_Create8(&IID_IDirectSound8, ppDS);
+    if (!FAILED(hr))
+    {
+        hr = IDirectSound_Initialize(*ppDS, lpcGUID);
+        if (FAILED(hr))
+        {
+            IDirectSound_Release(*ppDS);
+            *ppDS = NULL;
         }
     }
 
-    *ppDS = pDS;
-
     return hr;
 }
 
-/*******************************************************************************
- *        DirectSoundDevice
- */
-static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
+static const IDirectSound8Vtbl DS8_Impl;
+
+typedef struct DirectSoundImpl {
+     const IDirectSound8Vtbl *lpVtbl;
+     LONG ref, *liveref;
+     BOOL from8;
+     LPDIRECTSOUNDFULLDUPLEX DuplexID;
+     DirectSoundDevice* device;
+} DirectSoundImpl;
+
+HRESULT WINAPI IDirectSoundImpl_Create(LPDIRECTSOUND8* piface, LPDIRECTSOUNDFULLDUPLEX DuplexID, LONG *liveref, BOOL from8)
 {
-    DirectSoundDevice * device;
+    DirectSoundImpl* This = HeapAlloc(GetProcessHeap(), 0, sizeof(DirectSoundImpl));
+    *piface = NULL;
+    if (!This)
+        return DSERR_OUTOFMEMORY;
+
+    This->lpVtbl = &DS8_Impl;
+    This->ref = 0;
+    This->from8 = from8;
+    This->device = NULL;
+    This->DuplexID = DuplexID;
+    This->liveref = liveref;
+    *piface = (LPVOID)This;
+    return S_OK;
+}
+
+static HRESULT WINAPI IDirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
+{
+    DirectSoundDevice *device;
     TRACE("(%p)\n", ppDevice);
 
     /* Allocate memory */
@@ -1165,37 +293,16 @@ static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
         return DSERR_OUTOFMEMORY;
     }
 
+    /* Lot of things are defaulting to 0, please don't set here */
     device->ref            = 1;
-    device->driver         = NULL;
     device->priolevel      = DSSCL_NORMAL;
-    device->fraglen        = 0;
-    device->hwbuf          = NULL;
-    device->buffer         = NULL;
-    device->buflen         = 0;
-    device->writelead      = 0;
     device->state          = STATE_STOPPED;
-    device->nrofbuffers    = 0;
-    device->buffers        = NULL;
-    device->primary        = NULL;
     device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
-    device->tmp_buffer     = NULL;
-    device->tmp_buffer_len = 0;
 
     /* 3D listener initial parameters */
-    device->listener       = NULL;
     device->ds3dl.dwSize   = sizeof(DS3DLISTENER);
-    device->ds3dl.vPosition.x = 0.0;
-    device->ds3dl.vPosition.y = 0.0;
-    device->ds3dl.vPosition.z = 0.0;
-    device->ds3dl.vVelocity.x = 0.0;
-    device->ds3dl.vVelocity.y = 0.0;
-    device->ds3dl.vVelocity.z = 0.0;
-    device->ds3dl.vOrientFront.x = 0.0;
-    device->ds3dl.vOrientFront.y = 0.0;
     device->ds3dl.vOrientFront.z = 1.0;
-    device->ds3dl.vOrientTop.x = 0.0;
     device->ds3dl.vOrientTop.y = 1.0;
-    device->ds3dl.vOrientTop.z = 0.0;
     device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
     device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
     device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
@@ -1228,24 +335,51 @@ static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
 
     RtlInitializeResource(&(device->buffer_list_lock));
 
-   *ppDevice = device;
+    *ppDevice = device;
 
     return DS_OK;
 }
 
-static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
+
+static HRESULT WINAPI DirectSound_QueryInterface(LPDIRECTSOUND8 iface, REFIID riid, LPVOID *ppobj)
 {
-    ULONG ref = InterlockedIncrement(&(device->ref));
-    TRACE("(%p) ref was %d\n", device, ref - 1);
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+
+    if (ppobj == NULL) {
+        WARN("invalid parameter\n");
+        return E_INVALIDARG;
+    }
+
+    *ppobj = NULL;
+    if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectSound) || (This->from8 && IsEqualIID(riid, &IID_IDirectSound8)))
+        *ppobj = This;
+    else if (This->DuplexID && IsEqualIID(riid, &IID_IDirectSoundFullDuplex))
+        *ppobj = This->DuplexID;
+    else
+        return E_NOINTERFACE;
+    IDirectSound_AddRef((IUnknown *)(*ppobj));
+    return S_OK;
+}
+
+static ULONG WINAPI DirectSound_AddRef(LPDIRECTSOUND8 iface)
+{
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    ULONG ref = InterlockedIncrement(&(This->ref));
+    if (ref == 1 && This->DuplexID)
+        InterlockedIncrement(This->liveref);
+
+    TRACE("(%p) ref was %d\n", This, ref - 1);
     return ref;
 }
 
-ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
+void IDirectSoundImpl_Destroy(LPDIRECTSOUND8 device)
 {
-    HRESULT hr;
-    ULONG ref = InterlockedDecrement(&(device->ref));
-    TRACE("(%p) ref was %u\n", device, ref + 1);
-    if (!ref) {
+    DirectSoundImpl *This = (DirectSoundImpl*)device;
+    if (This->device && !InterlockedDecrement(&(This->device->ref)))
+    {
+        HRESULT hr;
+        DirectSoundDevice *device = This->device;
         int i;
         timeKillEvent(device->timerID);
         timeEndPeriod(DS_TIME_RES);
@@ -1288,21 +422,38 @@ ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
         HeapFree(GetProcessHeap(),0,device->tmp_buffer);
         HeapFree(GetProcessHeap(),0,device->buffer);
         RtlDeleteResource(&device->buffer_list_lock);
+        HeapFree(GetProcessHeap(),0,device->pwfx);
         device->mixlock.DebugInfo->Spare[0] = 0;
         DeleteCriticalSection(&device->mixlock);
         HeapFree(GetProcessHeap(),0,device);
-        TRACE("(%p) released\n", device);
+        TRACE("Device (%p) released\n", device);
+    }
+    HeapFree(GetProcessHeap(), 0, This);
+}
+
+static ULONG WINAPI DirectSound_Release(LPDIRECTSOUND8 iface)
+{
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %u\n", This, ref + 1);
+
+    if (!ref)
+    {
+        if (!This->DuplexID)
+            IDirectSoundImpl_Destroy(iface);
+        else if (!InterlockedDecrement(This->liveref))
+            IDirectSoundFullDuplexImpl_Destroy(This->DuplexID);
     }
     return ref;
 }
 
-HRESULT DirectSoundDevice_GetCaps(
-    DirectSoundDevice * device,
-    LPDSCAPS lpDSCaps)
+static HRESULT WINAPI DirectSound_GetCaps(LPDIRECTSOUND8 iface, LPDSCAPS lpDSCaps)
 {
-    TRACE("(%p,%p)\n",device,lpDSCaps);
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    DirectSoundDevice *device = This->device;
+    TRACE("(%p,%p)\n",This,lpDSCaps);
 
-    if (device == NULL) {
+    if (!This->device) {
         WARN("not initialized\n");
         return DSERR_UNINITIALIZED;
     }
@@ -1350,16 +501,17 @@ HRESULT DirectSoundDevice_GetCaps(
     return DS_OK;
 }
 
-HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
+static HRESULT WINAPI DirectSound_Initialize(LPDIRECTSOUND8 iface, LPCGUID lpcGUID)
 {
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
     HRESULT hr = DS_OK;
     unsigned wod, wodn;
     BOOLEAN found = FALSE;
     GUID devGUID;
-    DirectSoundDevice * device = *ppDevice;
-    TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
+    DirectSoundDevice *device = This->device;
+    TRACE("(%p,%s)\n",This,debugstr_guid(lpcGUID));
 
-    if (*ppDevice != NULL) {
+    if (device) {
         WARN("already initialized\n");
         return DSERR_ALREADYINITIALIZED;
     }
@@ -1395,8 +547,8 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG
     if (DSOUND_renderer[wod]) {
         if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
             device = DSOUND_renderer[wod];
-            DirectSoundDevice_AddRef(device);
-            *ppDevice = device;
+            InterlockedIncrement(&(device->ref));
+            This->device = device;
             return DS_OK;
         } else {
             ERR("device GUID doesn't match\n");
@@ -1404,14 +556,14 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG
             return hr;
         }
     } else {
-        hr = DirectSoundDevice_Create(&device);
+        hr = IDirectSoundDevice_Create(&device);
         if (hr != DS_OK) {
-            WARN("DirectSoundDevice_Create failed\n");
+            WARN("DirectSoundCreate failed\n");
             return hr;
         }
     }
 
-    *ppDevice = device;
+    This->device = device;
     device->guid = devGUID;
 
     /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
@@ -1529,17 +681,14 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG
     return hr;
 }
 
-HRESULT DirectSoundDevice_CreateSoundBuffer(
-    DirectSoundDevice * device,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk,
-    BOOL from8)
+static HRESULT WINAPI DirectSound_CreateSoundBuffer(LPDIRECTSOUND8 iface, LPCDSBUFFERDESC dsbd, LPLPDIRECTSOUNDBUFFER ppdsb, LPUNKNOWN lpunk)
 {
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    DirectSoundDevice *device = This->device;
     HRESULT hres = DS_OK;
-    TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk);
+    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
 
-    if (device == NULL) {
+    if (!This->device) {
         WARN("not initialized\n");
         return DSERR_UNINITIALIZED;
     }
@@ -1606,7 +755,7 @@ HRESULT DirectSoundDevice_CreateSoundBuffer(
               dsbd->lpwfxFormat->nBlockAlign,
               dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
 
-        if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
+        if (This->from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
             WARN("invalid parameter: 3D buffer format must be mono\n");
             return DSERR_INVALIDPARAM;
         }
@@ -1626,16 +775,15 @@ HRESULT DirectSoundDevice_CreateSoundBuffer(
    return hres;
 }
 
-HRESULT DirectSoundDevice_DuplicateSoundBuffer(
-    DirectSoundDevice * device,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
+static HRESULT WINAPI DirectSound_DuplicateSoundBuffer(LPDIRECTSOUND8 iface, LPDIRECTSOUNDBUFFER psb, LPLPDIRECTSOUNDBUFFER ppdsb)
 {
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
     HRESULT hres = DS_OK;
     IDirectSoundBufferImpl* dsb;
-    TRACE("(%p,%p,%p)\n",device,psb,ppdsb);
+    DirectSoundDevice *device = This->device;
+    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
 
-    if (device == NULL) {
+    if (!This->device) {
         WARN("not initialized\n");
         return DSERR_UNINITIALIZED;
     }
@@ -1677,14 +825,12 @@ HRESULT DirectSoundDevice_DuplicateSoundBuffer(
     return hres;
 }
 
-HRESULT DirectSoundDevice_SetCooperativeLevel(
-    DirectSoundDevice * device,
-    HWND hwnd,
-    DWORD level)
+static HRESULT WINAPI DirectSound_SetCooperativeLevel(LPDIRECTSOUND8 iface, HWND hwnd, DWORD level)
 {
-    TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    TRACE("(%p,%p,%s)\n",iface,hwnd,dumpCooperativeLevel(level));
 
-    if (device == NULL) {
+    if (!This->device) {
         WARN("not initialized\n");
         return DSERR_UNINITIALIZED;
     }
@@ -1694,21 +840,21 @@ HRESULT DirectSoundDevice_SetCooperativeLevel(
              level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
     }
 
-    device->priolevel = level;
+    This->device->priolevel = level;
     return DS_OK;
 }
 
-HRESULT DirectSoundDevice_Compact(
-    DirectSoundDevice * device)
+static HRESULT WINAPI DirectSound_Compact(LPDIRECTSOUND8 iface)
 {
-    TRACE("(%p)\n", device);
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    TRACE("(%p)\n", This);
 
-    if (device == NULL) {
+    if (!This->device) {
         WARN("not initialized\n");
         return DSERR_UNINITIALIZED;
     }
 
-    if (device->priolevel < DSSCL_PRIORITY) {
+    if (This->device->priolevel < DSSCL_PRIORITY) {
         WARN("incorrect priority level\n");
         return DSERR_PRIOLEVELNEEDED;
     }
@@ -1716,13 +862,12 @@ HRESULT DirectSoundDevice_Compact(
     return DS_OK;
 }
 
-HRESULT DirectSoundDevice_GetSpeakerConfig(
-    DirectSoundDevice * device,
-    LPDWORD lpdwSpeakerConfig)
+static HRESULT WINAPI DirectSound_GetSpeakerConfig(LPDIRECTSOUND8 iface, LPDWORD lpdwSpeakerConfig)
 {
-    TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
 
-    if (device == NULL) {
+    if (!This->device) {
         WARN("not initialized\n");
         return DSERR_UNINITIALIZED;
     }
@@ -1733,38 +878,36 @@ HRESULT DirectSoundDevice_GetSpeakerConfig(
     }
 
     WARN("not fully functional\n");
-    *lpdwSpeakerConfig = device->speaker_config;
+    *lpdwSpeakerConfig = This->device->speaker_config;
     return DS_OK;
 }
 
-HRESULT DirectSoundDevice_SetSpeakerConfig(
-    DirectSoundDevice * device,
-    DWORD config)
+static HRESULT WINAPI DirectSound_SetSpeakerConfig(LPDIRECTSOUND8 iface, DWORD config)
 {
-    TRACE("(%p,0x%08x)\n",device,config);
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    TRACE("(%p,0x%08x)\n",This,config);
 
-    if (device == NULL) {
+    if (!This->device) {
         WARN("not initialized\n");
         return DSERR_UNINITIALIZED;
     }
 
-    device->speaker_config = config;
+    This->device->speaker_config = config;
     WARN("not fully functional\n");
     return DS_OK;
 }
 
-static HRESULT DirectSoundDevice_VerifyCertification(
-    DirectSoundDevice * device,
-    LPDWORD pdwCertified)
+static HRESULT WINAPI DirectSound_VerifyCertification(LPDIRECTSOUND8 iface, LPDWORD pdwCertified)
 {
-    TRACE("(%p, %p)\n",device,pdwCertified);
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    TRACE("(%p, %p)\n",This,pdwCertified);
 
-    if (device == NULL) {
+    if (!This->device) {
         WARN("not initialized\n");
         return DSERR_UNINITIALIZED;
     }
 
-    if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
+    if (This->device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
         *pdwCertified = DS_CERTIFIED;
     else
         *pdwCertified = DS_UNCERTIFIED;
@@ -1772,74 +915,17 @@ static HRESULT DirectSoundDevice_VerifyCertification(
     return DS_OK;
 }
 
-/*
- * Add secondary buffer to buffer list.
- * Gets exclusive access to buffer for writing.
- */
-HRESULT DirectSoundDevice_AddBuffer(
-    DirectSoundDevice * device,
-    IDirectSoundBufferImpl * pDSB)
-{
-    IDirectSoundBufferImpl **newbuffers;
-    HRESULT hr = DS_OK;
-
-    TRACE("(%p, %p)\n", device, pDSB);
-
-    RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
-
-    if (device->buffers)
-        newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
-    else
-        newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
-
-    if (newbuffers) {
-        device->buffers = newbuffers;
-        device->buffers[device->nrofbuffers] = pDSB;
-        device->nrofbuffers++;
-        TRACE("buffer count is now %d\n", device->nrofbuffers);
-    } else {
-        ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers);
-        hr = DSERR_OUTOFMEMORY;
-    }
-
-    RtlReleaseResource(&(device->buffer_list_lock));
-
-    return hr;
-}
-
-/*
- * Remove secondary buffer from buffer list.
- * Gets exclusive access to buffer for writing.
- */
-HRESULT DirectSoundDevice_RemoveBuffer(
-    DirectSoundDevice * device,
-    IDirectSoundBufferImpl * pDSB)
-{
-    int i;
-    HRESULT hr = DS_OK;
-
-    TRACE("(%p, %p)\n", device, pDSB);
-
-    RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
-
-    for (i = 0; i < device->nrofbuffers; i++)
-        if (device->buffers[i] == pDSB)
-            break;
-
-    if (i < device->nrofbuffers) {
-        /* Put the last buffer of the list in the (now empty) position */
-        device->buffers[i] = device->buffers[device->nrofbuffers - 1];
-        device->nrofbuffers--;
-        device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers);
-        TRACE("buffer count is now %d\n", device->nrofbuffers);
-    }
-
-    if (device->nrofbuffers == 0) {
-        HeapFree(GetProcessHeap(),0,device->buffers);
-        device->buffers = NULL;
-    }
-
-    RtlReleaseResource(&(device->buffer_list_lock));
-
-    return hr;
-}
+static const IDirectSound8Vtbl DS8_Impl = {
+    DirectSound_QueryInterface,
+    DirectSound_AddRef,
+    DirectSound_Release,
+    DirectSound_CreateSoundBuffer,
+    DirectSound_GetCaps,
+    DirectSound_DuplicateSoundBuffer,
+    DirectSound_SetCooperativeLevel,
+    DirectSound_Compact,
+    DirectSound_GetSpeakerConfig,
+    DirectSound_SetSpeakerConfig,
+    DirectSound_Initialize,
+    DirectSound_VerifyCertification
+};
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index c46c945..ad2d5fb 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -46,20 +46,9 @@ extern int ds_default_bits_per_sample;
 /*****************************************************************************
  * Predeclare the interface implementation structures
  */
-typedef struct IDirectSoundImpl              IDirectSoundImpl;
-typedef struct IDirectSound_IUnknown         IDirectSound_IUnknown;
-typedef struct IDirectSound_IDirectSound     IDirectSound_IDirectSound;
-typedef struct IDirectSound8_IUnknown        IDirectSound8_IUnknown;
-typedef struct IDirectSound8_IDirectSound    IDirectSound8_IDirectSound;
-typedef struct IDirectSound8_IDirectSound8   IDirectSound8_IDirectSound8;
 typedef struct IDirectSoundBufferImpl        IDirectSoundBufferImpl;
 typedef struct IDirectSoundCaptureImpl       IDirectSoundCaptureImpl;
 typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl;
-typedef struct IDirectSoundFullDuplexImpl    IDirectSoundFullDuplexImpl;
-typedef struct IDirectSoundFullDuplex_IUnknown IDirectSoundFullDuplex_IUnknown;
-typedef struct IDirectSoundFullDuplex_IDirectSound IDirectSoundFullDuplex_IDirectSound;
-typedef struct IDirectSoundFullDuplex_IDirectSound8 IDirectSoundFullDuplex_IDirectSound8;
-typedef struct IDirectSoundFullDuplex_IDirectSoundCapture IDirectSoundFullDuplex_IDirectSoundCapture;
 typedef struct IDirectSoundNotifyImpl        IDirectSoundNotifyImpl;
 typedef struct IDirectSoundCaptureNotifyImpl IDirectSoundCaptureNotifyImpl;
 typedef struct IDirectSound3DListenerImpl    IDirectSound3DListenerImpl;
@@ -115,39 +104,6 @@ typedef struct BufferMemory
     LPBYTE                      memory;
 } BufferMemory;
 
-ULONG DirectSoundDevice_Release(DirectSoundDevice * device);
-HRESULT DirectSoundDevice_Initialize(
-    DirectSoundDevice ** ppDevice,
-    LPCGUID lpcGUID);
-HRESULT DirectSoundDevice_AddBuffer(
-    DirectSoundDevice * device,
-    IDirectSoundBufferImpl * pDSB);
-HRESULT DirectSoundDevice_RemoveBuffer(
-    DirectSoundDevice * device,
-    IDirectSoundBufferImpl * pDSB);
-HRESULT DirectSoundDevice_GetCaps(DirectSoundDevice * device, LPDSCAPS lpDSCaps);
-HRESULT DirectSoundDevice_CreateSoundBuffer(
-    DirectSoundDevice * device,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk,
-    BOOL from8);
-HRESULT DirectSoundDevice_DuplicateSoundBuffer(
-    DirectSoundDevice * device,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb);
-HRESULT DirectSoundDevice_SetCooperativeLevel(
-    DirectSoundDevice * devcie,
-    HWND hwnd,
-    DWORD level);
-HRESULT DirectSoundDevice_Compact(DirectSoundDevice * device);
-HRESULT DirectSoundDevice_GetSpeakerConfig(
-    DirectSoundDevice * device,
-    LPDWORD lpdwSpeakerConfig);
-HRESULT DirectSoundDevice_SetSpeakerConfig(
-    DirectSoundDevice * device,
-    DWORD config);
-
 /*****************************************************************************
  * IDirectSoundBuffer implementation structure
  */
@@ -300,52 +256,6 @@ HRESULT IDirectSoundCaptureBufferImpl_Create(
     LPCDSCBUFFERDESC lpcDSCBufferDesc);
 
 /*****************************************************************************
- * IDirectSoundFullDuplex implementation structure
- */
-struct IDirectSoundFullDuplexImpl
-{
-    /* IUnknown fields */
-    const IDirectSoundFullDuplexVtbl *lpVtbl;
-    LONG                              ref;
-
-    /* IDirectSoundFullDuplexImpl fields */
-    DirectSoundDevice                *renderer_device;
-    DirectSoundCaptureDevice         *capture_device;
-
-    LPUNKNOWN                         pUnknown;
-    LPDIRECTSOUND                     pDS;
-    LPDIRECTSOUND8                    pDS8;
-    LPDIRECTSOUNDCAPTURE              pDSC;
-};
-
-/*****************************************************************************
- * IDirectSoundFullDuplex COM components
- */
-struct IDirectSoundFullDuplex_IUnknown {
-    const IUnknownVtbl         *lpVtbl;
-    LONG                        ref;
-    IDirectSoundFullDuplexImpl *pdsfd;
-};
-
-struct IDirectSoundFullDuplex_IDirectSound {
-    const IDirectSoundVtbl     *lpVtbl;
-    LONG                        ref;
-    IDirectSoundFullDuplexImpl *pdsfd;
-};
-
-struct IDirectSoundFullDuplex_IDirectSound8 {
-    const IDirectSound8Vtbl    *lpVtbl;
-    LONG                        ref;
-    IDirectSoundFullDuplexImpl *pdsfd;
-};
-
-struct IDirectSoundFullDuplex_IDirectSoundCapture {
-    const IDirectSoundCaptureVtbl *lpVtbl;
-    LONG                           ref;
-    IDirectSoundFullDuplexImpl    *pdsfd;
-};
-
-/*****************************************************************************
  *  IDirectSound3DListener implementation structure
  */
 struct IDirectSound3DListenerImpl
@@ -415,12 +325,12 @@ HRESULT IDirectSound3DBufferImpl_Destroy(
  */
 
 /* dsound.c */
-
 HRESULT DSOUND_Create(REFIID riid, LPDIRECTSOUND *ppDS);
 HRESULT DSOUND_Create8(REFIID riid, LPDIRECTSOUND8 *ppDS);
+HRESULT WINAPI IDirectSoundImpl_Create(LPDIRECTSOUND8* ppDevice, LPDIRECTSOUNDFULLDUPLEX DuplexIF, LONG *liveref, BOOL from8);
+void IDirectSoundImpl_Destroy(LPDIRECTSOUND8 device);
 
 /* primary.c */
-
 HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device);
 HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device);
 HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device);
@@ -429,15 +339,13 @@ HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LP
 HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex);
 
 /* duplex.c */
- 
 HRESULT DSOUND_FullDuplexCreate(REFIID riid, LPDIRECTSOUNDFULLDUPLEX* ppDSFD);
+void IDirectSoundFullDuplexImpl_Destroy(LPDIRECTSOUNDFULLDUPLEX DuplexID);
 
 /* buffer.c */
-
 DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This, DWORD pplay, DWORD pwrite);
 
 /* mixer.c */
-
 void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len);
 void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb);
 void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos);
@@ -449,11 +357,11 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR d
 void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
 
 /* sound3d.c */
-
 void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb);
 
 /* capture.c */
- 
+HRESULT IDirectSoundCaptureImpl_Create(LPDIRECTSOUNDCAPTURE8 * ppds, LPDIRECTSOUNDFULLDUPLEX DuplexID, LONG *liveref);
+void IDirectSoundCaptureImpl_Destroy(LPDIRECTSOUNDCAPTURE8 device);
 HRESULT DSOUND_CaptureCreate(REFIID riid, LPDIRECTSOUNDCAPTURE *ppDSC);
 HRESULT DSOUND_CaptureCreate8(REFIID riid, LPDIRECTSOUNDCAPTURE8 *ppDSC8);
 HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer(
diff --git a/dlls/dsound/duplex.c b/dlls/dsound/duplex.c
index c61432d..6dc6485 100644
--- a/dlls/dsound/duplex.c
+++ b/dlls/dsound/duplex.c
@@ -4,6 +4,7 @@
  * Copyright 1998 Rob Riggs
  * Copyright 2000-2001 TransGaming Technologies, Inc.
  * Copyright 2005 Robert Reif
+ * Copyright 2007 Maarten Lankhorst
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -37,609 +38,114 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
 
-/*******************************************************************************
- * IUnknown
- */
-static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface(
-    LPUNKNOWN iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
-}
-
-static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef(
-    LPUNKNOWN iface)
-{
-    IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
-    return ref;
-}
-
-static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release(
-    LPUNKNOWN iface)
+typedef struct IDirectSoundFullDuplexImpl
 {
-    IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref + 1);
-    if (!ref) {
-        IDirectSound_Release(This->pdsfd->pUnknown);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
-    }
-    return ref;
-}
+    const IDirectSoundFullDuplexVtbl *lpVtbl;
+    LONG ref, liveref;
+    LPDIRECTSOUND8 pDS;
+    LPDIRECTSOUNDCAPTURE8 pDSC;
+    LPUNKNOWN pUnk;
+    BOOL init;
+} IDirectSoundFullDuplexImpl;
 
-static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl =
-{
-    IDirectSoundFullDuplex_IUnknown_QueryInterface,
-    IDirectSoundFullDuplex_IUnknown_AddRef,
-    IDirectSoundFullDuplex_IUnknown_Release
-};
+typedef struct IUnkDuplexImpl {
+    const IUnknownVtbl *lpVtbl;
+    LONG ref, *liveref;
+    LPDIRECTSOUNDFULLDUPLEX pDuplex;
+} IUnkDuplexImpl;
 
-static HRESULT IDirectSoundFullDuplex_IUnknown_Create(
-    LPDIRECTSOUNDFULLDUPLEX pdsfd,
-    LPUNKNOWN * ppunk)
-{
-    IDirectSoundFullDuplex_IUnknown * pdsfdunk;
-    TRACE("(%p,%p)\n",pdsfd,ppunk);
-
-    if (pdsfd == NULL) {
-        ERR("invalid parameter: pdsfd == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (ppunk == NULL) {
-        ERR("invalid parameter: ppunk == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk));
-    if (pdsfdunk == NULL) {
-        WARN("out of memory\n");
-        *ppunk = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
-
-    pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl;
-    pdsfdunk->ref = 0;
-    pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
-
-    *ppunk = (LPUNKNOWN)pdsfdunk;
-
-    return DS_OK;
-}
-
-/*******************************************************************************
- * IDirectSoundFullDuplex_IDirectSound
- */
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_QueryInterface(
-    LPDIRECTSOUND iface,
-    REFIID riid,
-    LPVOID * ppobj)
+static ULONG WINAPI IUnkDuplex_AddRef(LPUNKNOWN iface)
 {
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
-}
-
-static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound_AddRef(
-    LPDIRECTSOUND iface)
-{
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
+    IUnkDuplexImpl *This = (IUnkDuplexImpl *)iface;
     ULONG ref = InterlockedIncrement(&(This->ref));
+    if (ref == 1)
+        InterlockedIncrement(This->liveref);
     TRACE("(%p) ref was %d\n", This, ref - 1);
     return ref;
 }
 
-static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound_Release(
-    LPDIRECTSOUND iface)
-{
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref + 1);
-    if (!ref) {
-        IDirectSound_Release(This->pdsfd->pDS);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
-    }
-    return ref;
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_CreateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk)
-{
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    return DirectSoundDevice_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk,FALSE);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_GetCaps(
-    LPDIRECTSOUND iface,
-    LPDSCAPS lpDSCaps)
-{
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p,%p)\n",This,lpDSCaps);
-    return DirectSoundDevice_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_DuplicateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
-{
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-    return DirectSoundDevice_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_SetCooperativeLevel(
-    LPDIRECTSOUND iface,
-    HWND hwnd,
-    DWORD level)
-{
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
-    return DirectSoundDevice_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_Compact(
-    LPDIRECTSOUND iface)
+static HRESULT WINAPI IUnkDuplex_QueryInterface(LPUNKNOWN iface, REFIID riid, LPVOID* ppobj)
 {
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p)\n", This);
-    return DirectSoundDevice_Compact(This->pdsfd->renderer_device);
+    IUnkDuplexImpl *This = (IUnkDuplexImpl *)iface;
+    return IDirectSoundFullDuplex_QueryInterface(This->pDuplex, riid, ppobj);
 }
 
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_GetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    LPDWORD lpdwSpeakerConfig)
-{
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return DirectSoundDevice_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_SetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    DWORD config)
-{
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p,0x%08x)\n",This,config);
-    return DirectSoundDevice_SetSpeakerConfig(This->pdsfd->renderer_device,config);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_Initialize(
-    LPDIRECTSOUND iface,
-    LPCGUID lpcGuid)
-{
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-    return DirectSoundDevice_Initialize(&This->pdsfd->renderer_device,lpcGuid);
-}
-
-static const IDirectSoundVtbl DirectSoundFullDuplex_DirectSound_Vtbl =
-{
-    IDirectSoundFullDuplex_IDirectSound_QueryInterface,
-    IDirectSoundFullDuplex_IDirectSound_AddRef,
-    IDirectSoundFullDuplex_IDirectSound_Release,
-    IDirectSoundFullDuplex_IDirectSound_CreateSoundBuffer,
-    IDirectSoundFullDuplex_IDirectSound_GetCaps,
-    IDirectSoundFullDuplex_IDirectSound_DuplicateSoundBuffer,
-    IDirectSoundFullDuplex_IDirectSound_SetCooperativeLevel,
-    IDirectSoundFullDuplex_IDirectSound_Compact,
-    IDirectSoundFullDuplex_IDirectSound_GetSpeakerConfig,
-    IDirectSoundFullDuplex_IDirectSound_SetSpeakerConfig,
-    IDirectSoundFullDuplex_IDirectSound_Initialize
-};
-
-static HRESULT IDirectSoundFullDuplex_IDirectSound_Create(
-    LPDIRECTSOUNDFULLDUPLEX pdsfd,
-    LPDIRECTSOUND * ppds)
+static ULONG WINAPI IUnkDuplex_Release(LPUNKNOWN iface)
 {
-    IDirectSoundFullDuplex_IDirectSound * pdsfdds;
-    TRACE("(%p,%p)\n",pdsfd,ppds);
-
-    if (pdsfd == NULL) {
-        ERR("invalid parameter: pdsfd == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (ppds == NULL) {
-        ERR("invalid parameter: ppds == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
-        WARN("not initialized\n");
-        *ppds = NULL;
-        return DSERR_UNINITIALIZED;
-    }
-
-    pdsfdds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds));
-    if (pdsfdds == NULL) {
-        WARN("out of memory\n");
-        *ppds = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
-
-    pdsfdds->lpVtbl = &DirectSoundFullDuplex_DirectSound_Vtbl;
-    pdsfdds->ref = 0;
-    pdsfdds->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
-
-    *ppds = (LPDIRECTSOUND)pdsfdds;
-
-    return DS_OK;
-}
-
-/*******************************************************************************
- * IDirectSoundFullDuplex_IDirectSound8
- */
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
-    LPDIRECTSOUND8 iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
-}
-
-static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
-    return ref;
-}
-
-static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+    IUnkDuplexImpl *This = (IUnkDuplexImpl *)iface;
     ULONG ref = InterlockedDecrement(&(This->ref));
     TRACE("(%p) ref was %d\n", This, ref + 1);
-    if (!ref) {
-        IDirectSound_Release(This->pdsfd->pDS8);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
-    }
+    if (!ref && !InterlockedDecrement(This->liveref))
+        IDirectSoundFullDuplexImpl_Destroy(This->pDuplex);
     return ref;
 }
 
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    return DirectSoundDevice_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk,TRUE);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
-    LPDIRECTSOUND8 iface,
-    LPDSCAPS lpDSCaps)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
-    TRACE("(%p,%p)\n",This,lpDSCaps);
-    return DirectSoundDevice_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
-    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-    return DirectSoundDevice_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
-    LPDIRECTSOUND8 iface,
-    HWND hwnd,
-    DWORD level)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
-    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
-    return DirectSoundDevice_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
-    TRACE("(%p)\n", This);
-    return DirectSoundDevice_Compact(This->pdsfd->renderer_device);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
-    LPDIRECTSOUND8 iface,
-    LPDWORD lpdwSpeakerConfig)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
-    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return DirectSoundDevice_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
-    LPDIRECTSOUND8 iface,
-    DWORD config)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
-    TRACE("(%p,0x%08x)\n",This,config);
-    return DirectSoundDevice_SetSpeakerConfig(This->pdsfd->renderer_device,config);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
-    LPDIRECTSOUND8 iface,
-    LPCGUID lpcGuid)
-{
-    IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
-    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-    return DirectSoundDevice_Initialize(&This->pdsfd->renderer_device,lpcGuid);
-}
-
-static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl =
-{
-    IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
-    IDirectSoundFullDuplex_IDirectSound8_AddRef,
-    IDirectSoundFullDuplex_IDirectSound8_Release,
-    IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
-    IDirectSoundFullDuplex_IDirectSound8_GetCaps,
-    IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
-    IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
-    IDirectSoundFullDuplex_IDirectSound8_Compact,
-    IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
-    IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
-    IDirectSoundFullDuplex_IDirectSound8_Initialize
+static const IUnknownVtbl IUnkDuplexVtbl = {
+    IUnkDuplex_QueryInterface,
+    IUnkDuplex_AddRef,
+    IUnkDuplex_Release
 };
 
-static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create(
-    LPDIRECTSOUNDFULLDUPLEX pdsfd,
-    LPDIRECTSOUND8 * ppds8)
-{
-    IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8;
-    TRACE("(%p,%p)\n",pdsfd,ppds8);
-
-    if (pdsfd == NULL) {
-        ERR("invalid parameter: pdsfd == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (ppds8 == NULL) {
-        ERR("invalid parameter: ppds8 == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
-        WARN("not initialized\n");
-        *ppds8 = NULL;
-        return DSERR_UNINITIALIZED;
-    }
-
-    pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8));
-    if (pdsfdds8 == NULL) {
-        WARN("out of memory\n");
-        *ppds8 = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
-
-    pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
-    pdsfdds8->ref = 0;
-    pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
-
-    *ppds8 = (LPDIRECTSOUND8)pdsfdds8;
-
-    return DS_OK;
-}
-
-/*******************************************************************************
- * IDirectSoundFullDuplex_IDirectSoundCapture
- */
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
-    LPDIRECTSOUNDCAPTURE iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
-}
-
-static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(
-    LPDIRECTSOUNDCAPTURE iface)
-{
-    IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
-    return ref;
-}
-
-static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(
-    LPDIRECTSOUNDCAPTURE iface)
-{
-    IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref + 1);
-    if (!ref) {
-        IDirectSoundCapture_Release(This->pdsfd->pDSC);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
-    }
-    return ref;
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
-    LPDIRECTSOUNDCAPTURE iface,
-    LPCDSCBUFFERDESC lpcDSCBufferDesc,
-    LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
-    LPUNKNOWN pUnk)
-{
-    IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
-    return IDirectSoundCaptureImpl_CreateCaptureBuffer(This->pdsfd->pDSC,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
-    LPDIRECTSOUNDCAPTURE iface,
-    LPDSCCAPS lpDSCCaps)
-{
-    IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
-    TRACE("(%p,%p)\n",This,lpDSCCaps);
-    return IDirectSoundCaptureImpl_GetCaps(This->pdsfd->pDSC, lpDSCCaps);
-}
-
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
-    LPDIRECTSOUNDCAPTURE iface,
-    LPCGUID lpcGUID)
-{
-    IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
-    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
-    return IDirectSoundCaptureImpl_Initialize(This->pdsfd->pDSC,lpcGUID);
-}
-
-static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl =
-{
-    IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
-    IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
-    IDirectSoundFullDuplex_IDirectSoundCapture_Release,
-    IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
-    IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
-    IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
-};
-
-static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create(
-    LPDIRECTSOUNDFULLDUPLEX pdsfd,
-    LPDIRECTSOUNDCAPTURE8 * ppdsc8)
-{
-    IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc;
-    TRACE("(%p,%p)\n",pdsfd,ppdsc8);
-
-    if (pdsfd == NULL) {
-        ERR("invalid parameter: pdsfd == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (ppdsc8 == NULL) {
-        ERR("invalid parameter: ppdsc8 == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) {
-        WARN("not initialized\n");
-        *ppdsc8 = NULL;
-        return DSERR_UNINITIALIZED;
-    }
-
-    pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc));
-    if (pdsfddsc == NULL) {
-        WARN("out of memory\n");
-        *ppdsc8 = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
-
-    pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
-    pdsfddsc->ref = 0;
-    pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
-
-    *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc;
-
-    return DS_OK;
-}
-
-/***************************************************************************
- * IDirectSoundFullDuplexImpl
- */
 static ULONG WINAPI
 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
 {
     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
     ULONG ref = InterlockedIncrement(&(This->ref));
+
     TRACE("(%p) ref was %d\n", This, ref - 1);
+    if (ref == 1)
+        InterlockedIncrement(&This->liveref);
+
     return ref;
 }
 
+/* Query the DirectSound Object, then DirectSoundCapture if it failed */
+
 static HRESULT WINAPI
 IDirectSoundFullDuplexImpl_QueryInterface(
     LPDIRECTSOUNDFULLDUPLEX iface,
     REFIID riid,
     LPVOID* ppobj )
 {
+    HRESULT hr = E_NOINTERFACE;
     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
     TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
 
     if (ppobj == NULL) {
-	WARN("invalid parameter\n");
-	return E_INVALIDARG;
+        WARN("invalid parameter\n");
+        return E_INVALIDARG;
     }
 
-    *ppobj = NULL;
-
-    if (IsEqualIID(riid, &IID_IUnknown)) {
-        if (!This->pUnknown) {
-            IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown);
-            if (!This->pUnknown) {
-                WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n");
-                *ppobj = NULL;
-                return E_NOINTERFACE;
-            }
-        }
-        IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown);
-        *ppobj = This->pUnknown;
+    if (IsEqualIID(riid, &IID_IUnknown))
+    {
+        *ppobj = This->pUnk;
+        IUnkDuplex_AddRef(This->pUnk);
         return S_OK;
-    } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
-        IDirectSoundFullDuplexImpl_AddRef(iface);
+    }
+    if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex))
+    {
         *ppobj = This;
-        return S_OK;
-    } else if (IsEqualIID(riid, &IID_IDirectSound)) {
-        if (!This->pDS) {
-            IDirectSoundFullDuplex_IDirectSound_Create(iface, &This->pDS);
-            if (!This->pDS) {
-                WARN("IDirectSoundFullDuplex_IDirectSound_Create() failed\n");
-                *ppobj = NULL;
-                return E_NOINTERFACE;
-            }
-        }
-        IDirectSoundFullDuplex_IDirectSound_AddRef(This->pDS);
-        *ppobj = This->pDS;
-        return S_OK;
-    } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
-        if (!This->pDS8) {
-            IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8);
-            if (!This->pDS8) {
-                WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n");
-                *ppobj = NULL;
-                return E_NOINTERFACE;
-            }
-        }
-        IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8);
-        *ppobj = This->pDS8;
-        return S_OK;
-    } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
-        if (!This->pDSC) {
-            IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC);
-            if (!This->pDSC) {
-                WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n");
-                *ppobj = NULL;
-                return E_NOINTERFACE;
-            }
-        }
-        IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC);
-        *ppobj = This->pDSC;
+        IDirectSoundFullDuplex_AddRef(iface);
         return S_OK;
     }
 
-    return E_NOINTERFACE;
+    if (!This->init)
+        return E_NOINTERFACE;
+
+    hr = IDirectSound_QueryInterface(This->pDS, riid, ppobj);
+    if (FAILED(hr))
+        hr = IDirectSoundCapture_QueryInterface(This->pDSC, riid, ppobj);
+    return hr;
+}
+
+void IDirectSoundFullDuplexImpl_Destroy(LPDIRECTSOUNDFULLDUPLEX iface)
+{
+    IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
+    IDirectSoundCaptureImpl_Destroy(This->pDSC);
+    IDirectSoundImpl_Destroy(This->pDS);
+    HeapFree(GetProcessHeap(), 0, This->pUnk);
+    HeapFree(GetProcessHeap(), 0, This);
+    TRACE("(%p) released\n", This);
 }
 
 static ULONG WINAPI
@@ -647,16 +153,11 @@ IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
 {
     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
     ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
 
-    if (!ref) {
-        if (This->capture_device)
-            DirectSoundCaptureDevice_Release(This->capture_device);
-        if (This->renderer_device)
-            DirectSoundDevice_Release(This->renderer_device);
-        HeapFree( GetProcessHeap(), 0, This );
-	TRACE("(%p) released\n", This);
-    }
+    TRACE("(%p) ref was %d\n", This, ref + 1);
+
+    if (!ref && !InterlockedDecrement(&This->liveref))
+        IDirectSoundFullDuplexImpl_Destroy(iface);
     return ref;
 }
 
@@ -674,76 +175,78 @@ IDirectSoundFullDuplexImpl_Initialize(
 {
     HRESULT hr;
     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
-    IDirectSoundBufferImpl * dsb;
 
     TRACE("(%p,%s,%s,%p,%p,%x,%x,%p,%p)\n", This,
         debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
         lpDscBufferDesc, lpDsBufferDesc, (DWORD)hWnd, dwLevel,
         lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
 
-    if (This->renderer_device != NULL || This->capture_device != NULL) {
+    *lplpDirectSoundCaptureBuffer8 = NULL;
+    *lplpDirectSoundBuffer8 = NULL;
+
+    if (This->init) {
         WARN("already initialized\n");
-        *lplpDirectSoundCaptureBuffer8 = NULL;
-        *lplpDirectSoundBuffer8 = NULL;
         return DSERR_ALREADYINITIALIZED;
     }
 
-    hr = DirectSoundDevice_Initialize(&This->renderer_device, pRendererGuid);
-    if (hr != DS_OK) {
-        WARN("DirectSoundDevice_Initialize() failed\n");
-        *lplpDirectSoundCaptureBuffer8 = NULL;
-        *lplpDirectSoundBuffer8 = NULL;
-        return hr;
+    if (lpDsBufferDesc == NULL) {
+        WARN("invalid parameter: pcDSBufferDesc == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
 
-    if (dwLevel==DSSCL_PRIORITY || dwLevel==DSSCL_EXCLUSIVE) {
-        WARN("level=%s not fully supported\n",
-             dwLevel==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
+    if (lpDscBufferDesc == NULL) {
+        WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
-    This->renderer_device->priolevel = dwLevel;
-
-    hr = DSOUND_PrimarySetFormat(This->renderer_device, lpDsBufferDesc->lpwfxFormat);
-    if (hr != DS_OK) {
-        WARN("DSOUND_PrimarySetFormat() failed\n");
-        *lplpDirectSoundCaptureBuffer8 = NULL;
-        *lplpDirectSoundBuffer8 = NULL;
-        return hr;
+
+    if (lplpDirectSoundBuffer8 == NULL) {
+        WARN("invalid parameter: ppDSBuffer8 == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (lplpDirectSoundCaptureBuffer8 == NULL) {
+        WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
-    hr = IDirectSoundBufferImpl_Create(This->renderer_device, &dsb, lpDsBufferDesc);
-    if (hr != DS_OK) {
-        WARN("IDirectSoundBufferImpl_Create() failed\n");
-        *lplpDirectSoundCaptureBuffer8 = NULL;
-        *lplpDirectSoundBuffer8 = NULL;
-        return hr;
+
+    hr = IDirectSound8_Initialize(This->pDS, pRendererGuid);
+    if (FAILED(hr)) {
+        WARN("Could not create device: %08x\n", hr);
+        goto err;
     }
 
-    hr = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl **)lplpDirectSoundBuffer8);
-    if (hr != DS_OK) {
-        WARN("SecondaryBufferImpl_Create() failed\n");
-        *lplpDirectSoundCaptureBuffer8 = NULL;
-        *lplpDirectSoundBuffer8 = NULL;
-        return hr;
+    hr = IDirectSound_SetCooperativeLevel(This->pDS, hWnd, dwLevel);
+        WARN("Could not set priority level: %08x\n", hr);
+
+    hr = IDirectSound8_CreateSoundBuffer(This->pDS, lpDsBufferDesc, (LPDIRECTSOUNDBUFFER*)lplpDirectSoundBuffer8, NULL);
+    if (FAILED(hr))
+    {
+        WARN("Could not allocate buffer: %08x\n", hr);
+        goto err;
     }
-    IDirectSoundBuffer8_AddRef(*lplpDirectSoundBuffer8);
-
-    hr = DirectSoundCaptureDevice_Initialize(&This->capture_device, pCaptureGuid);
-    if (hr != DS_OK) {
-        WARN("DirectSoundCaptureDevice_Initialize() failed\n");
-        *lplpDirectSoundCaptureBuffer8 = NULL;
-        *lplpDirectSoundBuffer8 = NULL;
-        return hr;
+
+    hr = IDirectSoundCapture_Initialize(This->pDSC, pCaptureGuid);
+    if (FAILED(hr)) {
+        WARN("Could not create device: %08x\n", hr);
+        goto err;
     }
 
-    hr = IDirectSoundCaptureBufferImpl_Create(This->capture_device,
-         (IDirectSoundCaptureBufferImpl **)lplpDirectSoundCaptureBuffer8,
-         lpDscBufferDesc);
-    if (hr != DS_OK) {
-        WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
-        *lplpDirectSoundCaptureBuffer8 = NULL;
-        *lplpDirectSoundBuffer8 = NULL;
-        return hr;
+    hr = IDirectSoundCapture_CreateCaptureBuffer(This->pDSC, lpDscBufferDesc, (LPDIRECTSOUNDCAPTUREBUFFER*)lplpDirectSoundCaptureBuffer8, NULL);
+
+    if (FAILED(hr)) {
+        WARN("Creating capture buffer failed: %08x\n", hr);
+        goto err;
     }
+    This->init = 1;
+    return hr;
 
+    err:
+    if (*lplpDirectSoundCaptureBuffer8)
+        IDirectSoundBuffer_Release(*lplpDirectSoundCaptureBuffer8);
+    if (*lplpDirectSoundBuffer8)
+        IDirectSoundBuffer_Release(*lplpDirectSoundBuffer8);
+    *lplpDirectSoundBuffer8 = NULL;
+    *lplpDirectSoundCaptureBuffer8 = NULL;
     return hr;
 }
 
@@ -753,7 +256,6 @@ static const IDirectSoundFullDuplexVtbl dsfdvt =
     IDirectSoundFullDuplexImpl_QueryInterface,
     IDirectSoundFullDuplexImpl_AddRef,
     IDirectSoundFullDuplexImpl_Release,
-
     /* IDirectSoundFullDuplex methods */
     IDirectSoundFullDuplexImpl_Initialize
 };
@@ -763,6 +265,8 @@ HRESULT DSOUND_FullDuplexCreate(
     LPDIRECTSOUNDFULLDUPLEX* ppDSFD)
 {
     IDirectSoundFullDuplexImpl *This = NULL;
+    IUnkDuplexImpl *pUnk = NULL;
+    HRESULT hr;
     TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD);
 
     if (ppDSFD == NULL) {
@@ -779,23 +283,45 @@ HRESULT DSOUND_FullDuplexCreate(
     /* Get dsound configuration */
     setup_dsound_options();
 
-    This = HeapAlloc(GetProcessHeap(),
-        HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
-
-    if (This == NULL) {
-        WARN("out of memory\n");
-        *ppDSFD = NULL;
-        return DSERR_OUTOFMEMORY;
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
+    pUnk = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IUnkDuplexImpl));
+    if (!This || !pUnk)
+        goto erroutofmem;
+    This->pUnk = (LPUNKNOWN)pUnk;
+    This->liveref = 1;
+    pUnk->pDuplex = (LPDIRECTSOUNDFULLDUPLEX)This;
+    pUnk->lpVtbl = &IUnkDuplexVtbl;
+    pUnk->liveref = &This->liveref;
+    hr = IDirectSoundCaptureImpl_Create(&This->pDSC, (LPDIRECTSOUNDFULLDUPLEX)This, &This->liveref);
+    if (FAILED(hr))
+        goto erroutofmem;
+    hr = IDirectSoundImpl_Create(&This->pDS, (LPDIRECTSOUNDFULLDUPLEX)This, &This->liveref, TRUE);
+    if (FAILED(hr))
+    {
+        IDirectSoundCaptureImpl_Destroy(This->pDSC);
+        goto erroutofmem;
     }
 
     This->lpVtbl = &dsfdvt;
-    This->ref = 1;
-    This->capture_device = NULL;
-    This->renderer_device = NULL;
-
-    *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
+    if (IsEqualIID(riid, &IID_IUnknown))
+    {
+        *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)pUnk;
+        pUnk->ref = 1;
+    }
+    else
+    {
+        *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
+        This->ref = 1;
+    }
 
     return DS_OK;
+
+erroutofmem:
+    WARN("out of memory\n");
+    HeapFree(GetProcessHeap(), 0, This);
+    HeapFree(GetProcessHeap(), 0, pUnk);
+    *ppDSFD = NULL;
+    return DSERR_OUTOFMEMORY;
 }
 
 /***************************************************************************
@@ -822,89 +348,48 @@ HRESULT DSOUND_FullDuplexCreate(
  */
 HRESULT WINAPI
 DirectSoundFullDuplexCreate(
-    LPCGUID pcGuidCaptureDevice,
-    LPCGUID pcGuidRenderDevice,
-    LPCDSCBUFFERDESC pcDSCBufferDesc,
-    LPCDSBUFFERDESC pcDSBufferDesc,
+    LPCGUID pCaptureGuid,
+    LPCGUID pRendererGuid,
+    LPCDSCBUFFERDESC lpDscBufferDesc,
+    LPCDSBUFFERDESC lpDsBufferDesc,
     HWND hWnd,
     DWORD dwLevel,
     LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
-    LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
-    LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
+    LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
+    LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8,
     LPUNKNOWN pUnkOuter)
 {
     HRESULT hres;
-    IDirectSoundFullDuplexImpl *This = NULL;
     TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n",
-        debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice),
-        pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8,
-        ppDSBuffer8, pUnkOuter);
-
-    if (pUnkOuter) {
-        WARN("pUnkOuter != 0\n");
-        *ppDSFD = NULL;
-        return DSERR_NOAGGREGATION;
-    }
-
-    if (pcDSCBufferDesc == NULL) {
-        WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
-        *ppDSFD = NULL;
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (pcDSBufferDesc == NULL) {
-        WARN("invalid parameter: pcDSBufferDesc == NULL\n");
-        *ppDSFD = NULL;
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (ppDSFD == NULL) {
-        WARN("invalid parameter: ppDSFD == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
+        debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
+        lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel, ppDSFD, lplpDirectSoundCaptureBuffer8,
+        lplpDirectSoundBuffer8, pUnkOuter);
 
-    if (ppDSCBuffer8 == NULL) {
-        WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
-        *ppDSFD = NULL;
+    if (!ppDSFD) {
+        WARN("ppDSFD == 0\n");
         return DSERR_INVALIDPARAM;
     }
 
-    if (ppDSBuffer8 == NULL) {
-        WARN("invalid parameter: ppDSBuffer8 == NULL\n");
+    if (pUnkOuter) {
+        WARN("pUnkOuter != 0\n");
         *ppDSFD = NULL;
-        return DSERR_INVALIDPARAM;
+        return DSERR_NOAGGREGATION;
     }
 
     /* Get dsound configuration */
     setup_dsound_options();
 
-    This = HeapAlloc(GetProcessHeap(),
-        HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
+    hres = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, ppDSFD);
+    if (FAILED(hres))
+        return hres;
 
-    if (This == NULL) {
-        WARN("out of memory\n");
-        *ppDSFD = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
+    hres = IDirectSoundFullDuplex_Initialize(*ppDSFD, pCaptureGuid, pRendererGuid, lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel, lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
 
-    This->lpVtbl = &dsfdvt;
-    This->ref = 1;
-    This->capture_device = NULL;
-    This->renderer_device = NULL;
-
-    hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This,
-                                                 pcGuidCaptureDevice,
-                                                 pcGuidRenderDevice,
-                                                 pcDSCBufferDesc,
-                                                 pcDSBufferDesc,
-                                                 hWnd, dwLevel, ppDSCBuffer8,
-                                                 ppDSBuffer8);
-    if (hres != DS_OK) {
-        HeapFree(GetProcessHeap(), 0, This);
-        WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
+    if (FAILED(hres))
+    {
+        IDirectSoundFullDuplexImpl_Release(*ppDSFD);
         *ppDSFD = NULL;
-    } else
-        *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
+    }
 
     return hres;
 }
-- 
1.4.4.2



More information about the wine-patches mailing list