dsound: Delete a bunch of code duplication to make the code more readable

Maarten Lankhorst m.b.lankhorst at gmail.com
Sat Jun 2 10:35:15 CDT 2007


I was getting annoyed of all the forwarding that makes reading the code
very hard to read, this fixes that by hooking the interface directly
into the "directsounddevice" calls, rather then another layer of
indirection.

IDirectSound8 is compatible with IDirectSound, and of course IUnknown,
that means implementing 1 interface should be enough.

Duplex has been made dependent on both interfaces, so it no longer has
it's own implementation of it, instead the _Release and _QueryInterface
functions of directsound(capture) behave slightly different when duplex
is attached.
-------------- next part --------------
>From 5a7c2a20dd3f33025555a6eb4a62240bce08b13a Mon Sep 17 00:00:00 2001
From: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date: Sat, 2 Jun 2007 17:21:54 +0200
Subject: [PATCH] dsound: Delete a bunch of code duplication to make the code more readable

---
 dlls/dsound/buffer.c         |   72 +++
 dlls/dsound/capture.c        |   41 +-
 dlls/dsound/dsound.c         | 1287 ++++++------------------------------------
 dlls/dsound/dsound_private.h |  103 +----
 dlls/dsound/duplex.c         |  838 +++++----------------------
 5 files changed, 437 insertions(+), 1904 deletions(-)

diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index b1cecd7..4431212 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..fd3992b 100644
--- a/dlls/dsound/capture.c
+++ b/dlls/dsound/capture.c
@@ -51,13 +51,11 @@ struct IDirectSoundCaptureImpl
     /* IUnknown fields */
     const IDirectSoundCaptureVtbl     *lpVtbl;
     LONG                               ref;
+    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);
     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);
     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,20 @@ IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
     IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
     ULONG ref = InterlockedIncrement(&(This->ref));
     TRACE("(%p) ref was %d\n", This, ref - 1);
+
     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 +496,8 @@ 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 && !This->DuplexID)
+        IDirectSoundCaptureImpl_Destroy(iface);
     return ref;
 }
 
@@ -591,8 +602,7 @@ static const IDirectSoundCaptureVtbl dscvt =
     IDirectSoundCaptureImpl_Initialize
 };
 
-static HRESULT IDirectSoundCaptureImpl_Create(
-    LPDIRECTSOUNDCAPTURE8 * ppDSC)
+HRESULT IDirectSoundCaptureImpl_Create(LPDIRECTSOUNDCAPTURE8 * ppDSC, LPDIRECTSOUNDFULLDUPLEX DuplexID)
 {
     IDirectSoundCaptureImpl *pDSC;
     TRACE("(%p)\n", ppDSC);
@@ -608,6 +618,7 @@ static HRESULT IDirectSoundCaptureImpl_Create(
     pDSC->lpVtbl = &dscvt;
     pDSC->ref    = 0;
     pDSC->device = NULL;
+    pDSC->DuplexID = DuplexID;
 
     *ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC;
 
diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c
index 2a72027..b6e156b 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, 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, 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,49 @@ 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;
+     BOOL from8;
+     LPDIRECTSOUNDFULLDUPLEX DuplexID;
+     DirectSoundDevice* device;
+} DirectSoundImpl;
+
+HRESULT WINAPI IDirectSoundImpl_Create(LPDIRECTSOUND8* piface, LPDIRECTSOUNDFULLDUPLEX DuplexID, BOOL from8)
+{
+    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;
+    *piface = (LPVOID)This;
+    return S_OK;
+}
+
+static HRESULT WINAPI IDirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
 {
-    DirectSoundDevice * device;
+    DirectSoundDevice *device;
     TRACE("(%p)\n", ppDevice);
 
     /* Allocate memory */
@@ -1165,37 +292,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 +334,48 @@ 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)
+{
+    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)
 {
-    ULONG ref = InterlockedIncrement(&(device->ref));
-    TRACE("(%p) ref was %d\n", device, ref - 1);
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    ULONG ref = InterlockedIncrement(&(This->ref));
+    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 +418,35 @@ 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);
     }
-    return ref;
+    HeapFree(GetProcessHeap(), 0, This);
 }
 
-HRESULT DirectSoundDevice_GetCaps(
-    DirectSoundDevice * device,
-    LPDSCAPS lpDSCaps)
+static ULONG WINAPI DirectSound_Release(LPDIRECTSOUND8 iface)
 {
-    TRACE("(%p,%p)\n",device,lpDSCaps);
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %u\n", This, ref + 1);
 
-    if (device == NULL) {
+    if (ref || This->DuplexID)
+        return ref;
+
+    IDirectSoundImpl_Destroy(iface);
+    return 0;
+}
+
+static HRESULT WINAPI DirectSound_GetCaps(LPDIRECTSOUND8 iface, LPDSCAPS lpDSCaps)
+{
+    DirectSoundImpl *This = (DirectSoundImpl*)iface;
+    DirectSoundDevice *device = This->device;
+    TRACE("(%p,%p)\n",This,lpDSCaps);
+
+    if (!This->device) {
         WARN("not initialized\n");
         return DSERR_UNINITIALIZED;
     }
@@ -1350,16 +494,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 +540,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 +549,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 +674,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 +748,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 +768,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 +818,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 +833,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 +855,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 +871,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 +908,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..7338103 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
@@ -414,13 +324,13 @@ HRESULT IDirectSound3DBufferImpl_Destroy(
 /*******************************************************************************
  */
 
-/* dsound.c */
-
+/* main.c */
 HRESULT DSOUND_Create(REFIID riid, LPDIRECTSOUND *ppDS);
 HRESULT DSOUND_Create8(REFIID riid, LPDIRECTSOUND8 *ppDS);
+HRESULT WINAPI IDirectSoundImpl_Create(LPDIRECTSOUND8* ppDevice, LPDIRECTSOUNDFULLDUPLEX DuplexIF, 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,12 @@ HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LP
 HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex);
 
 /* duplex.c */
- 
 HRESULT DSOUND_FullDuplexCreate(REFIID riid, LPDIRECTSOUNDFULLDUPLEX* ppDSFD);
 
 /* 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 +356,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);
+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..b1d5082 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,98 @@
 
 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;
+    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;
+    LPDIRECTSOUNDFULLDUPLEX pDuplex;
+} IUnkDuplexImpl;
 
-static HRESULT IDirectSoundFullDuplex_IUnknown_Create(
-    LPDIRECTSOUNDFULLDUPLEX pdsfd,
-    LPUNKNOWN * ppunk)
+static ULONG WINAPI IUnkDuplex_AddRef(LPUNKNOWN iface)
 {
-    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)
-{
-    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));
     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)
+static HRESULT WINAPI IUnkDuplex_QueryInterface(LPUNKNOWN iface, REFIID riid, LPVOID* ppobj)
 {
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p,%p)\n",This,lpDSCaps);
-    return DirectSoundDevice_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
+    IUnkDuplexImpl *This = (IUnkDuplexImpl *)iface;
+    return IDirectSoundFullDuplex_QueryInterface(This->pDuplex, riid, ppobj);
 }
 
-static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_DuplicateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
+static ULONG WINAPI IUnkDuplex_Release(LPUNKNOWN iface)
 {
-    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)
-{
-    IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
-    TRACE("(%p)\n", This);
-    return DirectSoundDevice_Compact(This->pdsfd->renderer_device);
-}
-
-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)
-{
-    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;
-    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);
-    }
-    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 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;
+    IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)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 const IUnknownVtbl IUnkDuplexVtbl = {
+    IUnkDuplex_QueryInterface,
+    IUnkDuplex_AddRef,
+    IUnkDuplex_Release
 };
 
-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);
+
     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;
 }
 
 static ULONG WINAPI
@@ -647,15 +137,15 @@ IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
 {
     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
     ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %d\n", This, ref - 1);
+
+    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);
+        IDirectSoundCaptureImpl_Destroy(This->pDSC);
+        IDirectSoundImpl_Destroy(This->pDS);
+        HeapFree(GetProcessHeap(), 0, This->pUnk);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
     }
     return ref;
 }
@@ -674,76 +164,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;
     }
-    hr = IDirectSoundBufferImpl_Create(This->renderer_device, &dsb, lpDsBufferDesc);
-    if (hr != DS_OK) {
-        WARN("IDirectSoundBufferImpl_Create() failed\n");
-        *lplpDirectSoundCaptureBuffer8 = NULL;
-        *lplpDirectSoundBuffer8 = NULL;
-        return hr;
+
+    if (lplpDirectSoundCaptureBuffer8 == NULL) {
+        WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
 
-    hr = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl **)lplpDirectSoundBuffer8);
-    if (hr != DS_OK) {
-        WARN("SecondaryBufferImpl_Create() failed\n");
-        *lplpDirectSoundCaptureBuffer8 = NULL;
-        *lplpDirectSoundBuffer8 = NULL;
-        return hr;
+    hr = IDirectSound8_Initialize(This->pDS, pRendererGuid);
+    if (FAILED(hr) || FAILED(hr)) {
+        WARN("Could not create device: %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 = 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;
     }
 
-    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_Initialize(This->pDSC, pCaptureGuid);
+    if (FAILED(hr)) {
+        WARN("Could not create device: %08x\n", hr);
+        goto err;
     }
 
+    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 +245,6 @@ static const IDirectSoundFullDuplexVtbl dsfdvt =
     IDirectSoundFullDuplexImpl_QueryInterface,
     IDirectSoundFullDuplexImpl_AddRef,
     IDirectSoundFullDuplexImpl_Release,
-
     /* IDirectSoundFullDuplex methods */
     IDirectSoundFullDuplexImpl_Initialize
 };
@@ -763,6 +254,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 +272,35 @@ 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;
+    pUnk->pDuplex = (LPDIRECTSOUNDFULLDUPLEX)This;
+    pUnk->lpVtbl = &IUnkDuplexVtbl;
+    hr = IDirectSoundCaptureImpl_Create(&This->pDSC, (LPDIRECTSOUNDFULLDUPLEX)This);
+    if (FAILED(hr))
+        goto erroutofmem;
+    hr = IDirectSoundImpl_Create(&This->pDS, (LPDIRECTSOUNDFULLDUPLEX)This, 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;
 
     return DS_OK;
+
+erroutofmem:
+    WARN("out of memory\n");
+    HeapFree(GetProcessHeap(), 0, This);
+    HeapFree(GetProcessHeap(), 0, pUnk);
+    *ppDSFD = NULL;
+    return DSERR_OUTOFMEMORY;
 }
 
 /***************************************************************************
@@ -822,89 +327,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