winspool: Remove unvarying unicode parameter from WINSPOOL_OpenDriverReg.
[wine] / dlls / dsound / dsound.c
index f1cba5e..83636c2 100644 (file)
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "config.h"
-#include "wine/port.h"
-
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/fcntl.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
 
 #define NONAMELESSSTRUCT
 #define NONAMELESSUNION
 #include "windef.h"
 #include "winbase.h"
-#include "winreg.h"
-#include "winuser.h"
-#include "wingdi.h"
 #include "winuser.h"
-#include "winerror.h"
 #include "mmsystem.h"
 #include "winternl.h"
 #include "mmddk.h"
-#include "wine/windef16.h"
-#include "wine/winbase16.h"
+#include "wingdi.h"
+#include "mmreg.h"
+#include "ks.h"
+#include "ksmedia.h"
 #include "wine/debug.h"
 #include "dsound.h"
 #include "dsdriver.h"
 #include "dsound_private.h"
-#include "dsconf.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
 
-static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
-static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
+/*****************************************************************************
+ * 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);
 
-static const char * dumpCooperativeLevel(DWORD level)
+/*****************************************************************************
+ * 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);
+
+const char * dumpCooperativeLevel(DWORD level)
 {
-    static char unknown[32];
 #define LE(x) case x: return #x
     switch (level) {
         LE(DSSCL_NORMAL);
@@ -72,14 +119,13 @@ static const char * dumpCooperativeLevel(DWORD level)
         LE(DSSCL_WRITEPRIMARY);
     }
 #undef LE
-    sprintf(unknown, "Unknown(%08lx)", level);
-    return unknown;
+    return wine_dbg_sprintf("Unknown(%08x)", level);
 }
 
 static void _dump_DSCAPS(DWORD xmask) {
     struct {
         DWORD   mask;
-        char    *name;
+        const char    *name;
     } flags[] = {
 #define FE(x) { x, #x },
         FE(DSCAPS_PRIMARYMONO)
@@ -99,13 +145,13 @@ static void _dump_DSCAPS(DWORD xmask) {
 
     for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
         if ((flags[i].mask & xmask) == flags[i].mask)
-            DPRINTF("%s ",flags[i].name);
+            TRACE("%s ",flags[i].name);
 }
 
 static void _dump_DSBCAPS(DWORD xmask) {
     struct {
         DWORD   mask;
-        char    *name;
+        const char    *name;
     } flags[] = {
 #define FE(x) { x, #x },
         FE(DSBCAPS_PRIMARYBUFFER)
@@ -127,23 +173,13 @@ static void _dump_DSBCAPS(DWORD xmask) {
 
     for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
         if ((flags[i].mask & xmask) == flags[i].mask)
-            DPRINTF("%s ",flags[i].name);
+            TRACE("%s ",flags[i].name);
 }
 
 /*******************************************************************************
  *             IDirectSoundImpl_DirectSound
  */
-static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
-    LPDIRECTSOUND8 iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
-    FIXME("shouldn't be called directly\n");
-    return E_NOINTERFACE;
-}
-
-static HRESULT WINAPI DSOUND_QueryInterface(
+static HRESULT DSOUND_QueryInterface(
     LPDIRECTSOUND8 iface,
     REFIID riid,
     LPVOID * ppobj)
@@ -187,7 +223,7 @@ static HRESULT WINAPI DSOUND_QueryInterface(
     return E_NOINTERFACE;
 }
 
-static HRESULT WINAPI DSOUND_QueryInterface8(
+static HRESULT DSOUND_QueryInterface8(
     LPDIRECTSOUND8 iface,
     REFIID riid,
     LPVOID * ppobj)
@@ -243,1013 +279,339 @@ static HRESULT WINAPI DSOUND_QueryInterface8(
     return E_NOINTERFACE;
 }
 
-static ULONG WINAPI IDirectSoundImpl_AddRef(
+static ULONG IDirectSoundImpl_AddRef(
     LPDIRECTSOUND8 iface)
 {
     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-
-    return InterlockedIncrement(&This->ref);
+    ULONG ref = InterlockedIncrement(&(This->ref));
+    TRACE("(%p) ref was %d\n", This, ref - 1);
+    return ref;
 }
 
-static ULONG WINAPI IDirectSoundImpl_Release(
+static ULONG IDirectSoundImpl_Release(
     LPDIRECTSOUND8 iface)
 {
     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    ULONG ref;
-    TRACE("(%p) ref was %ld, thread is %04lx\n",
-          This, This->ref, GetCurrentThreadId());
-
-    ref = InterlockedDecrement(&This->ref);
-    if (ref == 0) {
-        HRESULT hres;
-        INT i;
-
-        timeKillEvent(This->timerID);
-        timeEndPeriod(DS_TIME_RES);
-        /* wait for timer to expire */
-        Sleep(DS_TIME_RES+1);
-
-        /* The sleep above should have allowed the timer process to expire
-         * but try to grab the lock just in case. Can't hold lock because
-         * IDirectSoundBufferImpl_Destroy also grabs the lock */
-        RtlAcquireResourceShared(&(This->buffer_list_lock), TRUE);
-        RtlReleaseResource(&(This->buffer_list_lock));
-
-        /* It is allowed to release this object even when buffers are playing */
-        if (This->buffers) {
-            WARN("%d secondary buffers not released\n", This->nrofbuffers);
-            for( i=0;i<This->nrofbuffers;i++)
-                IDirectSoundBufferImpl_Destroy(This->buffers[i]);
-        }
-
-        if (This->primary) {
-            WARN("primary buffer not released\n");
-            IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
-        }
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %d\n", This, ref + 1);
 
-        hres = DSOUND_PrimaryDestroy(This);
-        if (hres != DS_OK)
-            WARN("DSOUND_PrimaryDestroy failed\n");
+    if (!ref) {
+        if (This->device)
+            DirectSoundDevice_Release(This->device);
+        HeapFree(GetProcessHeap(),0,This);
+        TRACE("(%p) released\n", This);
+    }
+    return ref;
+}
 
-        if (This->driver)
-            IDsDriver_Close(This->driver);
+static HRESULT IDirectSoundImpl_Create(
+    LPDIRECTSOUND8 * ppDS)
+{
+    IDirectSoundImpl* pDS;
+    TRACE("(%p)\n",ppDS);
 
-        if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
-            waveOutClose(This->hwo);
+    /* Allocate memory */
+    pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
+    if (pDS == NULL) {
+        WARN("out of memory\n");
+        *ppDS = NULL;
+        return DSERR_OUTOFMEMORY;
+    }
 
-        if (This->driver)
-            IDsDriver_Release(This->driver);
+    pDS->ref    = 0;
+    pDS->device = NULL;
 
-        RtlDeleteResource(&This->buffer_list_lock);
-        This->mixlock.DebugInfo->Spare[1] = 0;
-        DeleteCriticalSection(&This->mixlock);
-        HeapFree(GetProcessHeap(),0,This);
-        dsound = NULL;
-        TRACE("(%p) released\n",This);
-    }
+    *ppDS = (LPDIRECTSOUND8)pDS;
 
-    return ref;
+    return DS_OK;
 }
 
-static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk)
+/*******************************************************************************
+ *             IDirectSound_IUnknown
+ */
+static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
+    LPUNKNOWN iface,
+    REFIID riid,
+    LPVOID * ppobj)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    FIXME("shouldn't be called directly\n");
-    return DSERR_GENERIC;
+    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface(This->pds, riid, ppobj);
 }
 
-static HRESULT WINAPI DSOUND_CreateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk,
-    BOOL from8)
+static ULONG WINAPI IDirectSound_IUnknown_AddRef(
+    LPUNKNOWN iface)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    HRESULT hres = DS_OK;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+    ULONG ref = InterlockedIncrement(&(This->ref));
+    TRACE("(%p) ref was %d\n", This, ref - 1);
+    return ref;
+}
 
-    if (This == NULL) {
-        WARN("invalid parameter: This == NULL\n");
-        return DSERR_INVALIDPARAM;
+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*)This->pds)->pUnknown = NULL;
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
     }
+    return ref;
+}
 
-    if (This->initialized == FALSE) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
+static const IUnknownVtbl DirectSound_Unknown_Vtbl =
+{
+    IDirectSound_IUnknown_QueryInterface,
+    IDirectSound_IUnknown_AddRef,
+    IDirectSound_IUnknown_Release
+};
 
-    if (dsbd == NULL) {
-        WARN("invalid parameter: dsbd == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
+static HRESULT IDirectSound_IUnknown_Create(
+    LPDIRECTSOUND8 pds,
+    LPUNKNOWN * ppunk)
+{
+    IDirectSound_IUnknown * pdsunk;
+    TRACE("(%p,%p)\n",pds,ppunk);
 
-    if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
-        dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
-        WARN("invalid parameter: dsbd\n");
+    if (ppunk == NULL) {
+        ERR("invalid parameter: ppunk == NULL\n");
         return DSERR_INVALIDPARAM;
     }
 
-    if (ppdsb == NULL) {
-        WARN("invalid parameter: ppdsb == NULL\n");
+    if (pds == NULL) {
+        ERR("invalid parameter: pds == NULL\n");
+        *ppunk = NULL;
         return DSERR_INVALIDPARAM;
     }
 
-    if (TRACE_ON(dsound)) {
-        TRACE("(structsize=%ld)\n",dsbd->dwSize);
-        TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
-        _dump_DSBCAPS(dsbd->dwFlags);
-        DPRINTF(")\n");
-        TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
-        TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
+    pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
+    if (pdsunk == NULL) {
+        WARN("out of memory\n");
+        *ppunk = NULL;
+        return DSERR_OUTOFMEMORY;
     }
 
-    if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
-        if (dsbd->lpwfxFormat != NULL) {
-            WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
-                 "primary buffer\n");
-            return DSERR_INVALIDPARAM;
-        }
+    pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
+    pdsunk->ref = 0;
+    pdsunk->pds = pds;
 
-        if (This->primary) {
-            WARN("Primary Buffer already created\n");
-            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
-            *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
-        } else {
-           This->dsbd = *dsbd;
-           hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
-           if (This->primary) {
-               IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
-               *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
-           } else
-               WARN("PrimaryBufferImpl_Create failed\n");
-        }
-    } else {
-        IDirectSoundBufferImpl * dsb;
+    IDirectSoundImpl_AddRef(pds);
+    *ppunk = (LPUNKNOWN)pdsunk;
 
-        if (dsbd->lpwfxFormat == NULL) {
-            WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
-                 "secondary buffer\n");
-            return DSERR_INVALIDPARAM;
-        }
+    return DS_OK;
+}
 
-        TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
-              "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
-              dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
-              dsbd->lpwfxFormat->nSamplesPerSec,
-              dsbd->lpwfxFormat->nAvgBytesPerSec,
-              dsbd->lpwfxFormat->nBlockAlign,
-              dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
+/*******************************************************************************
+ *             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);
+}
 
-        if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
-            WARN("invalid parameter: 3D buffer format must be mono\n");
-            return DSERR_INVALIDPARAM;
-        }
+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;
+}
 
-        hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
-        if (dsb) {
-            hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
-            if (*ppdsb) {
-                dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
-                IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
-            } else
-                WARN("SecondaryBufferImpl_Create failed\n");
-        } else
-           WARN("IDirectSoundBufferImpl_Create failed\n");
-   }
+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*)This->pds)->pDS = NULL;
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
+    }
+    return ref;
+}
 
-   return hres;
+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 IDirectSoundImpl_GetCaps(
-    LPDIRECTSOUND8 iface,
+static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
+    LPDIRECTSOUND iface,
     LPDSCAPS lpDSCaps)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
     TRACE("(%p,%p)\n",This,lpDSCaps);
-
-    if (This == NULL) {
-        WARN("invalid parameter: This == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (This->initialized == FALSE) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
-
-    if (lpDSCaps == NULL) {
-        WARN("invalid parameter: lpDSCaps = NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    /* check if there is enough room */
-    if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
-        WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
-             lpDSCaps->dwSize, sizeof(*lpDSCaps));
-        return DSERR_INVALIDPARAM;
-    }
-
-    lpDSCaps->dwFlags                           = This->drvcaps.dwFlags;
-    if (TRACE_ON(dsound)) {
-        TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
-        _dump_DSCAPS(lpDSCaps->dwFlags);
-        DPRINTF(")\n");
-    }
-    lpDSCaps->dwMinSecondarySampleRate          = This->drvcaps.dwMinSecondarySampleRate;
-    lpDSCaps->dwMaxSecondarySampleRate          = This->drvcaps.dwMaxSecondarySampleRate;
-    lpDSCaps->dwPrimaryBuffers                  = This->drvcaps.dwPrimaryBuffers;
-    lpDSCaps->dwMaxHwMixingAllBuffers           = This->drvcaps.dwMaxHwMixingAllBuffers;
-    lpDSCaps->dwMaxHwMixingStaticBuffers        = This->drvcaps.dwMaxHwMixingStaticBuffers;
-    lpDSCaps->dwMaxHwMixingStreamingBuffers     = This->drvcaps.dwMaxHwMixingStreamingBuffers;
-    lpDSCaps->dwFreeHwMixingAllBuffers          = This->drvcaps.dwFreeHwMixingAllBuffers;
-    lpDSCaps->dwFreeHwMixingStaticBuffers       = This->drvcaps.dwFreeHwMixingStaticBuffers;
-    lpDSCaps->dwFreeHwMixingStreamingBuffers    = This->drvcaps.dwFreeHwMixingStreamingBuffers;
-    lpDSCaps->dwMaxHw3DAllBuffers               = This->drvcaps.dwMaxHw3DAllBuffers;
-    lpDSCaps->dwMaxHw3DStaticBuffers            = This->drvcaps.dwMaxHw3DStaticBuffers;
-    lpDSCaps->dwMaxHw3DStreamingBuffers         = This->drvcaps.dwMaxHw3DStreamingBuffers;
-    lpDSCaps->dwFreeHw3DAllBuffers              = This->drvcaps.dwFreeHw3DAllBuffers;
-    lpDSCaps->dwFreeHw3DStaticBuffers           = This->drvcaps.dwFreeHw3DStaticBuffers;
-    lpDSCaps->dwFreeHw3DStreamingBuffers        = This->drvcaps.dwFreeHw3DStreamingBuffers;
-    lpDSCaps->dwTotalHwMemBytes                 = This->drvcaps.dwTotalHwMemBytes;
-    lpDSCaps->dwFreeHwMemBytes                  = This->drvcaps.dwFreeHwMemBytes;
-    lpDSCaps->dwMaxContigFreeHwMemBytes         = This->drvcaps.dwMaxContigFreeHwMemBytes;
-
-    /* driver doesn't have these */
-    lpDSCaps->dwUnlockTransferRateHwBuffers     = 4096; /* But we have none... */
-    lpDSCaps->dwPlayCpuOverheadSwBuffers        = 1;    /* 1% */
-
-    return DS_OK;
+    return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
 }
 
-static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
-    LPDIRECTSOUND8 iface,
+static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
+    LPDIRECTSOUND iface,
     LPDIRECTSOUNDBUFFER psb,
     LPLPDIRECTSOUNDBUFFER ppdsb)
 {
-    IDirectSoundBufferImpl* pdsb;
-    IDirectSoundBufferImpl* dsb;
-    HRESULT hres = DS_OK;
-    int size;
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-
-    if (This == NULL) {
-        WARN("invalid parameter: This == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (This->initialized == FALSE) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
-
-    if (psb == NULL) {
-        WARN("invalid parameter: psb == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (ppdsb == NULL) {
-        WARN("invalid parameter: ppdsb == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    /* FIXME: hack to make sure we have a secondary buffer */
-    if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
-        WARN("trying to duplicate primary buffer\n");
-        *ppdsb = NULL;
-        return DSERR_INVALIDCALL;
-    }
-
-    pdsb = ((SecondaryBufferImpl *)psb)->dsb;
-
-    dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
-
-    if (dsb == NULL) {
-        WARN("out of memory\n");
-        *ppdsb = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
-
-    memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
-
-    if (pdsb->hwbuf) {
-        TRACE("duplicating hardware buffer\n");
-
-        hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
-        if (hres != DS_OK) {
-            TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
-            dsb->hwbuf = NULL;
-            /* allocate buffer */
-            if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
-                dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
-                if (dsb->buffer == NULL) {
-                    WARN("out of memory\n");
-                    HeapFree(GetProcessHeap(),0,dsb);
-                    *ppdsb = NULL;
-                    return DSERR_OUTOFMEMORY;
-                }
-
-                dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
-                if (dsb->buffer->memory == NULL) {
-                    WARN("out of memory\n");
-                    HeapFree(GetProcessHeap(),0,dsb->buffer);
-                    HeapFree(GetProcessHeap(),0,dsb);
-                    *ppdsb = NULL;
-                    return DSERR_OUTOFMEMORY;
-                }
-                dsb->buffer->ref = 1;
-
-                /* FIXME: copy buffer ? */
-            }
-        }
-    } else {
-        dsb->hwbuf = NULL;
-        dsb->buffer->ref++;
-    }
-
-    dsb->ref = 0;
-    dsb->state = STATE_STOPPED;
-    dsb->playpos = 0;
-    dsb->buf_mixpos = 0;
-    dsb->dsound = This;
-    dsb->ds3db = NULL;
-    dsb->iks = NULL; /* FIXME? */
-    dsb->dsb = NULL;
-
-    /* variable sized struct so calculate size based on format */
-    size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
-
-    dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
-    if (dsb->pwfx == NULL) {
-            WARN("out of memory\n");
-            HeapFree(GetProcessHeap(),0,dsb->buffer);
-            HeapFree(GetProcessHeap(),0,dsb);
-            *ppdsb = NULL;
-            return DSERR_OUTOFMEMORY;
-    }
-
-    memcpy(dsb->pwfx, pdsb->pwfx, size);
-
-    InitializeCriticalSection(&(dsb->lock));
-    dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock";
-
-    /* register buffer */
-    hres = DSOUND_AddBuffer(This, dsb);
-    if (hres != DS_OK) {
-        IDirectSoundBuffer8_Release(psb);
-        dsb->lock.DebugInfo->Spare[1] = 0;
-        DeleteCriticalSection(&(dsb->lock));
-        HeapFree(GetProcessHeap(),0,dsb->buffer);
-        HeapFree(GetProcessHeap(),0,dsb->pwfx);
-        HeapFree(GetProcessHeap(),0,dsb);
-        *ppdsb = 0;
-    } else {
-        hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
-        if (*ppdsb) {
-            dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
-            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
-        } else
-            WARN("SecondaryBufferImpl_Create failed\n");
-    }
-
-    return hres;
+    return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
 }
 
-static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
-    LPDIRECTSOUND8 iface,
+static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
+    LPDIRECTSOUND iface,
     HWND hwnd,
     DWORD level)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
-
-    if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
-        FIXME("level=%s not fully supported\n",
-              level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
-    }
-    This->priolevel = level;
-    return DS_OK;
+    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 IDirectSoundImpl_Compact(
-    LPDIRECTSOUND8 iface)
+static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
+    LPDIRECTSOUND iface)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p)\n",This);
-
-    if (This->initialized == FALSE) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
-
-    if (This->priolevel != DSSCL_PRIORITY) {
-        WARN("incorrect priority level\n");
-        return DSERR_PRIOLEVELNEEDED;
-    }
-
-    return DS_OK;
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p)\n", This);
+    return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
 }
 
-static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
-    LPDIRECTSOUND8 iface,
+static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
+    LPDIRECTSOUND iface,
     LPDWORD lpdwSpeakerConfig)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
-
-    if (This->initialized == FALSE) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
-
-    if (lpdwSpeakerConfig == NULL) {
-        WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    WARN("not fully functional\n");
-    *lpdwSpeakerConfig = This->speaker_config;
-    return DS_OK;
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+    return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
 }
 
-static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
-    LPDIRECTSOUND8 iface,
+static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
+    LPDIRECTSOUND iface,
     DWORD config)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p,0x%08lx)\n",This,config);
-
-    if (This->initialized == FALSE) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
-
-    This->speaker_config = config;
-    WARN("not fully functional\n");
-    return DS_OK;
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p,0x%08x)\n",This,config);
+    return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
 }
 
-static HRESULT WINAPI IDirectSoundImpl_Initialize(
-    LPDIRECTSOUND8 iface,
+static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
+    LPDIRECTSOUND iface,
     LPCGUID lpcGuid)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
-
-    This->initialized = TRUE;
-
-    return DS_OK;
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+    return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
 }
 
-static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
-    LPDIRECTSOUND8 iface,
-    LPDWORD pdwCertified)
+static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p, %p)\n",This,pdwCertified);
-
-    if (This->initialized == FALSE) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
-
-    if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
-        *pdwCertified = DS_CERTIFIED;
-    else
-        *pdwCertified = DS_UNCERTIFIED;
-    return DS_OK;
-}
-
-static IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
-{
-    IDirectSoundImpl_QueryInterface,
-    IDirectSoundImpl_AddRef,
-    IDirectSoundImpl_Release,
-    IDirectSoundImpl_CreateSoundBuffer,
-    IDirectSoundImpl_GetCaps,
-    IDirectSoundImpl_DuplicateSoundBuffer,
-    IDirectSoundImpl_SetCooperativeLevel,
-    IDirectSoundImpl_Compact,
-    IDirectSoundImpl_GetSpeakerConfig,
-    IDirectSoundImpl_SetSpeakerConfig,
-    IDirectSoundImpl_Initialize,
-    IDirectSoundImpl_VerifyCertification
+    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
 };
 
-HRESULT WINAPI IDirectSoundImpl_Create(
-    LPCGUID lpcGUID,
-    LPDIRECTSOUND8 * ppDS)
+static HRESULT IDirectSound_IDirectSound_Create(
+    LPDIRECTSOUND8  pds,
+    LPDIRECTSOUND * ppds)
 {
-    HRESULT err;
-    PIDSDRIVER drv = NULL;
-    IDirectSoundImpl* pDS;
-    unsigned wod, wodn;
-    BOOLEAN found = FALSE;
-    TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
-
-    /* Enumerate WINMM audio devices and find the one we want */
-    wodn = waveOutGetNumDevs();
-    if (!wodn) {
-        WARN("no driver\n");
-        *ppDS = NULL;
-        return DSERR_NODRIVER;
-    }
-
-    TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
-
-    for (wod=0; wod<wodn; wod++) {
-        if (IsEqualGUID( lpcGUID, &renderer_guids[wod])) {
-            found = TRUE;
-            break;
-        }
-    }
-
-    if (found == FALSE) {
-        WARN("No device found matching given ID!\n");
-        *ppDS = NULL;
-        return DSERR_NODRIVER;
-    }
-
-    /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
-    waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
-
-    /* Disable the direct sound driver to force emulation if requested. */
-    if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
-        drv = NULL;
+    IDirectSound_IDirectSound * pdsds;
+    TRACE("(%p,%p)\n",pds,ppds);
 
-    /* Allocate memory */
-    pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
-    if (ppDS == NULL) {
-        WARN("out of memory\n");
-        *ppDS = NULL;
-        return DSERR_OUTOFMEMORY;
+    if (ppds == NULL) {
+        ERR("invalid parameter: ppds == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
 
-    pDS->lpVtbl         = &IDirectSoundImpl_Vtbl;
-    pDS->ref            = 0;
-
-    pDS->driver         = drv;
-    pDS->priolevel      = DSSCL_NORMAL;
-    pDS->fraglen        = 0;
-    pDS->hwbuf          = NULL;
-    pDS->buffer         = NULL;
-    pDS->buflen         = 0;
-    pDS->writelead      = 0;
-    pDS->state          = STATE_STOPPED;
-    pDS->nrofbuffers    = 0;
-    pDS->buffers        = NULL;
-    pDS->primary        = NULL;
-    pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
-    pDS->initialized    = FALSE;
-
-    /* 3D listener initial parameters */
-    pDS->listener       = NULL;
-    pDS->ds3dl.dwSize   = sizeof(DS3DLISTENER);
-    pDS->ds3dl.vPosition.x = 0.0;
-    pDS->ds3dl.vPosition.y = 0.0;
-    pDS->ds3dl.vPosition.z = 0.0;
-    pDS->ds3dl.vVelocity.x = 0.0;
-    pDS->ds3dl.vVelocity.y = 0.0;
-    pDS->ds3dl.vVelocity.z = 0.0;
-    pDS->ds3dl.vOrientFront.x = 0.0;
-    pDS->ds3dl.vOrientFront.y = 0.0;
-    pDS->ds3dl.vOrientFront.z = 1.0;
-    pDS->ds3dl.vOrientTop.x = 0.0;
-    pDS->ds3dl.vOrientTop.y = 1.0;
-    pDS->ds3dl.vOrientTop.z = 0.0;
-    pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
-    pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
-    pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
-
-    pDS->prebuf         = ds_snd_queue_max;
-    pDS->guid           = *lpcGUID;
-
-    /* Get driver description */
-    if (drv) {
-        err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
-        if (err != DS_OK) {
-            WARN("IDsDriver_GetDriverDesc failed\n");
-            HeapFree(GetProcessHeap(),0,pDS);
-            *ppDS = NULL;
-            return err;
-        }
-    } else {
-        /* if no DirectSound interface available, use WINMM API instead */
-        pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
+    if (pds == NULL) {
+        ERR("invalid parameter: pds == NULL\n");
+        *ppds = NULL;
+        return DSERR_INVALIDPARAM;
     }
 
-    pDS->drvdesc.dnDevNode = wod;
-
-    /* Set default wave format (may need it for waveOutOpen) */
-    pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
-    if (pDS->pwfx == NULL) {
+    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
+    if (pdsds == NULL) {
         WARN("out of memory\n");
-        HeapFree(GetProcessHeap(),0,pDS);
-        *ppDS = NULL;
+        *ppds = NULL;
         return DSERR_OUTOFMEMORY;
     }
 
-    pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
-    /* We rely on the sound driver to return the actual sound format of
-     * the device if it does not support 22050x8x2 and is given the
-     * WAVE_DIRECTSOUND flag.
-     */
-    pDS->pwfx->nSamplesPerSec = 22050;
-    pDS->pwfx->wBitsPerSample = 8;
-    pDS->pwfx->nChannels = 2;
-    pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
-    pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
-    pDS->pwfx->cbSize = 0;
-
-    /* If the driver requests being opened through MMSYSTEM
-     * (which is recommended by the DDK), it is supposed to happen
-     * before the DirectSound interface is opened */
-    if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
-    {
-        DWORD flags = CALLBACK_FUNCTION;
-
-        /* disable direct sound if requested */
-        if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
-            flags |= WAVE_DIRECTSOUND;
-
-        err = mmErr(waveOutOpen(&(pDS->hwo),
-                                pDS->drvdesc.dnDevNode, pDS->pwfx,
-                                (DWORD)DSOUND_callback, (DWORD)pDS,
-                                flags));
-        if (err != DS_OK) {
-            WARN("waveOutOpen failed\n");
-            HeapFree(GetProcessHeap(),0,pDS);
-            *ppDS = NULL;
-            return err;
-        }
-    }
-
-    if (drv) {
-        err = IDsDriver_Open(drv);
-        if (err != DS_OK) {
-            WARN("IDsDriver_Open failed\n");
-            HeapFree(GetProcessHeap(),0,pDS);
-            *ppDS = NULL;
-            return err;
-        }
-
-        /* the driver is now open, so it's now allowed to call GetCaps */
-        err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
-        if (err != DS_OK) {
-            WARN("IDsDriver_GetCaps failed\n");
-            HeapFree(GetProcessHeap(),0,pDS);
-            *ppDS = NULL;
-            return err;
-        }
-    } else {
-        WAVEOUTCAPSA woc;
-        err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
-        if (err != DS_OK) {
-            WARN("waveOutGetDevCaps failed\n");
-            HeapFree(GetProcessHeap(),0,pDS);
-            *ppDS = NULL;
-            return err;
-        }
-        ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
-        if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
-            (woc.dwFormats & WAVE_FORMAT_2M08) ||
-            (woc.dwFormats & WAVE_FORMAT_4M08) ||
-            (woc.dwFormats & WAVE_FORMAT_48M08) ||
-            (woc.dwFormats & WAVE_FORMAT_96M08)) {
-            pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
-            pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
-        }
-        if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
-            (woc.dwFormats & WAVE_FORMAT_2M16) ||
-            (woc.dwFormats & WAVE_FORMAT_4M16) ||
-            (woc.dwFormats & WAVE_FORMAT_48M16) ||
-            (woc.dwFormats & WAVE_FORMAT_96M16)) {
-            pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
-            pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
-        }
-        if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
-            (woc.dwFormats & WAVE_FORMAT_2S08) ||
-            (woc.dwFormats & WAVE_FORMAT_4S08) ||
-            (woc.dwFormats & WAVE_FORMAT_48S08) ||
-            (woc.dwFormats & WAVE_FORMAT_96S08)) {
-            pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
-            pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
-        }
-        if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
-            (woc.dwFormats & WAVE_FORMAT_2S16) ||
-            (woc.dwFormats & WAVE_FORMAT_4S16) ||
-            (woc.dwFormats & WAVE_FORMAT_48S16) ||
-            (woc.dwFormats & WAVE_FORMAT_96S16)) {
-            pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
-            pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
-        }
-        if (ds_emuldriver)
-            pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
-        pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
-        pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
-        pDS->drvcaps.dwPrimaryBuffers = 1;
-    }
-
-    InitializeCriticalSection(&(pDS->mixlock));
-    pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
-
-    RtlInitializeResource(&(pDS->buffer_list_lock));
+    pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
+    pdsds->ref = 0;
+    pdsds->pds = pds;
 
-    *ppDS = (LPDIRECTSOUND8)pDS;
+    IDirectSoundImpl_AddRef(pds);
+    *ppds = (LPDIRECTSOUND)pdsds;
 
     return DS_OK;
 }
+
 /*******************************************************************************
- *             IDirectSound_IUnknown
+ *             IDirectSound8_IUnknown
  */
-static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
+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_QueryInterface(This->pds, riid, ppobj);
+    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
 }
 
-static ULONG WINAPI IDirectSound_IUnknown_AddRef(
+static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
     LPUNKNOWN iface)
 {
     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-    return InterlockedIncrement(&This->ref);
+    ULONG ref = InterlockedIncrement(&(This->ref));
+    TRACE("(%p) ref was %d\n", This, ref - 1);
+    return ref;
 }
 
-static ULONG WINAPI IDirectSound_IUnknown_Release(
+static ULONG WINAPI IDirectSound8_IUnknown_Release(
     LPUNKNOWN iface)
 {
     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    ULONG ulReturn;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-    ulReturn = InterlockedDecrement(&This->ref);
-    if (ulReturn == 0) {
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %d\n", This, ref + 1);
+    if (!ref) {
+        ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
         IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(),0,This);
-        TRACE("(%p) released\n",This);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
     }
-    return ulReturn;
+    return ref;
 }
 
-static IUnknownVtbl DirectSound_Unknown_Vtbl =
-{
-    IDirectSound_IUnknown_QueryInterface,
-    IDirectSound_IUnknown_AddRef,
-    IDirectSound_IUnknown_Release
-};
-
-HRESULT WINAPI 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;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-    return InterlockedIncrement(&This->ref);
-}
-
-static ULONG WINAPI IDirectSound_IDirectSound_Release(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    ULONG ulReturn;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-    ulReturn = InterlockedDecrement(&This->ref);
-    if (ulReturn == 0) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(),0,This);
-        TRACE("(%p) released\n",This);
-    }
-    return ulReturn;
-}
-
-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 DSOUND_CreateSoundBuffer(This->pds,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 IDirectSoundImpl_GetCaps(This->pds, 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 IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
-    LPDIRECTSOUND iface,
-    HWND hwnd,
-    DWORD level)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
-    return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p)\n", This);
-    return IDirectSoundImpl_Compact(This->pds);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    LPDWORD lpdwSpeakerConfig)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    DWORD config)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,0x%08lx)\n",This,config);
-    return IDirectSoundImpl_SetSpeakerConfig(This->pds,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 IDirectSoundImpl_Initialize(This->pds,lpcGuid);
-}
-
-static 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
-};
-
-HRESULT WINAPI 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;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-    return InterlockedIncrement(&This->ref);
-}
-
-static ULONG WINAPI IDirectSound8_IUnknown_Release(
-    LPUNKNOWN iface)
-{
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    ULONG ulReturn;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-    ulReturn = InterlockedDecrement(&This->ref);
-    if (ulReturn == 0) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(),0,This);
-        TRACE("(%p) released\n",This);
-    }
-    return ulReturn;
-}
-
-static IUnknownVtbl DirectSound8_Unknown_Vtbl =
+static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
 {
     IDirectSound8_IUnknown_QueryInterface,
     IDirectSound8_IUnknown_AddRef,
     IDirectSound8_IUnknown_Release
 };
 
-HRESULT WINAPI IDirectSound8_IUnknown_Create(
+static HRESULT IDirectSound8_IUnknown_Create(
     LPDIRECTSOUND8 pds,
     LPUNKNOWN * ppunk)
 {
@@ -1301,23 +663,24 @@ static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
     LPDIRECTSOUND iface)
 {
     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-    return InterlockedIncrement(&This->ref);
+    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 ulReturn;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-    ulReturn = InterlockedDecrement(&This->ref);
-    if (ulReturn == 0) {
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %d\n", This, ref + 1);
+    if (!ref) {
+        ((IDirectSoundImpl*)This->pds)->pDS = NULL;
         IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(),0,This);
-        TRACE("(%p) released\n",This);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
     }
-    return ulReturn;
+    return ref;
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
@@ -1328,7 +691,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
 {
     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
+    return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
@@ -1337,7 +700,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
 {
     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
     TRACE("(%p,%p)\n",This,lpDSCaps);
-    return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
+    return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
@@ -1347,7 +710,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
 {
     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-    return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
+    return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
@@ -1356,8 +719,8 @@ static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
     DWORD level)
 {
     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
-    return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
+    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
+    return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
@@ -1365,7 +728,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
 {
     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
     TRACE("(%p)\n", This);
-    return IDirectSoundImpl_Compact(This->pds);
+    return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
@@ -1374,7 +737,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
 {
     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
+    return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
@@ -1382,8 +745,8 @@ static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
     DWORD config)
 {
     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,0x%08lx)\n",This,config);
-    return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
+    TRACE("(%p,0x%08x)\n",This,config);
+    return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
@@ -1392,10 +755,10 @@ static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
 {
     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-    return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
+    return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
 }
 
-static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
+static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
 {
     IDirectSound8_IDirectSound_QueryInterface,
     IDirectSound8_IDirectSound_AddRef,
@@ -1410,7 +773,7 @@ static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
     IDirectSound8_IDirectSound_Initialize
 };
 
-HRESULT WINAPI IDirectSound8_IDirectSound_Create(
+static HRESULT IDirectSound8_IDirectSound_Create(
     LPDIRECTSOUND8 pds,
     LPDIRECTSOUND * ppds)
 {
@@ -1462,23 +825,24 @@ static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
     LPDIRECTSOUND8 iface)
 {
     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-    return InterlockedIncrement(&This->ref);
+    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 ulReturn;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-    ulReturn = InterlockedDecrement(&This->ref);
-    if (ulReturn == 0) {
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %d\n", This, ref + 1);
+    if (!ref) {
+        ((IDirectSoundImpl*)This->pds)->pDS8 = NULL;
         IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(),0,This);
-        TRACE("(%p) released\n",This);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
     }
-    return ulReturn;
+    return ref;
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
@@ -1489,7 +853,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
 {
     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
+    return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
@@ -1498,7 +862,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
 {
     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
     TRACE("(%p,%p)\n",This,lpDSCaps);
-    return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
+    return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
@@ -1508,7 +872,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
 {
     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-    return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
+    return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
@@ -1517,8 +881,8 @@ static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
     DWORD level)
 {
     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
-    return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
+    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
+    return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
@@ -1526,7 +890,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
 {
     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
     TRACE("(%p)\n", This);
-    return IDirectSoundImpl_Compact(This->pds);
+    return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
@@ -1535,7 +899,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
 {
     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
+    return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
@@ -1543,8 +907,8 @@ static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
     DWORD config)
 {
     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,0x%08lx)\n",This,config);
-    return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
+    TRACE("(%p,0x%08x)\n",This,config);
+    return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
@@ -1553,7 +917,7 @@ static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
 {
     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-    return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
+    return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
 }
 
 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
@@ -1562,10 +926,10 @@ static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
 {
     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
     TRACE("(%p, %p)\n", This, pdwCertified);
-    return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
+    return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified);
 }
 
-static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
+static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
 {
     IDirectSound8_IDirectSound8_QueryInterface,
     IDirectSound8_IDirectSound8_AddRef,
@@ -1581,7 +945,7 @@ static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
     IDirectSound8_IDirectSound8_VerifyCertification
 };
 
-HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
+static HRESULT IDirectSound8_IDirectSound8_Create(
     LPDIRECTSOUND8 pds,
     LPDIRECTSOUND8 * ppds)
 {
@@ -1616,75 +980,35 @@ HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
     return DS_OK;
 }
 
-HRESULT WINAPI DSOUND_Create(
-    LPCGUID lpcGUID,
-    LPDIRECTSOUND *ppDS,
-    IUnknown *pUnkOuter)
+HRESULT DSOUND_Create(
+    REFIID riid,
+    LPDIRECTSOUND *ppDS)
 {
+    LPDIRECTSOUND8 pDS;
     HRESULT hr;
-    GUID devGuid;
-
-    TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
-
-    if (pUnkOuter != NULL) {
-        WARN("invalid parameter: pUnkOuter != NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
+    TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
 
-    if (ppDS == NULL) {
-        WARN("invalid parameter: ppDS == NULL\n");
-        return DSERR_INVALIDPARAM;
+    if (!IsEqualIID(riid, &IID_IUnknown) &&
+        !IsEqualIID(riid, &IID_IDirectSound)) {
+        *ppDS = 0;
+        return E_NOINTERFACE;
     }
 
     /* Get dsound configuration */
     setup_dsound_options();
 
-    /* Default device? */
-    if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
-        lpcGUID = &DSDEVID_DefaultPlayback;
-
-    if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
-        WARN("invalid parameter: lpcGUID\n");
-        *ppDS = NULL;
-        return DSERR_INVALIDPARAM;
-    }
-
-    if (dsound) {
-        if (IsEqualGUID(&devGuid, &dsound->guid)) {
-            hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
-            if (*ppDS)
-                IDirectSound_IDirectSound_AddRef(*ppDS);
-            else
-                WARN("IDirectSound_IDirectSound_Create failed\n");
-        } else {
-            ERR("different dsound already opened (only support one sound card at a time now)\n");
-            *ppDS = NULL;
-            hr = DSERR_ALLOCATED;
+    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 {
-        LPDIRECTSOUND8 pDS;
-        hr = IDirectSoundImpl_Create(&devGuid, &pDS);
-        if (hr == DS_OK) {
-            hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
-            if (hr == DS_OK) {
-                hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
-                if (*ppDS) {
-                    IDirectSound_IDirectSound_AddRef(*ppDS);
-
-                    dsound = (IDirectSoundImpl*)pDS;
-                    timeBeginPeriod(DS_TIME_RES);
-                    dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
-                                       (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
-                } else {
-                    WARN("IDirectSound_IDirectSound_Create failed\n");
-                    IDirectSound8_Release(pDS);
-                }
-            } else {
-                WARN("DSOUND_PrimaryCreate failed\n");
-                IDirectSound8_Release(pDS);
-            }
-        } else
-            WARN("IDirectSoundImpl_Create failed\n");
+        WARN("IDirectSoundImpl_Create failed\n");
+        *ppDS = 0;
     }
 
     return hr;
@@ -1711,85 +1035,68 @@ HRESULT WINAPI DirectSoundCreate(
     IUnknown *pUnkOuter)
 {
     HRESULT hr;
+    LPDIRECTSOUND pDS;
 
     TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
 
-    hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
-    if (hr == DS_OK)
-        IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
-
-    return hr;
-}
-
-HRESULT WINAPI DSOUND_Create8(
-    LPCGUID lpcGUID,
-    LPDIRECTSOUND8 *ppDS,
-    IUnknown *pUnkOuter)
-{
-    HRESULT hr;
-    GUID devGuid;
-
-    TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
+    if (ppDS == NULL) {
+        WARN("invalid parameter: ppDS == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
 
     if (pUnkOuter != NULL) {
         WARN("invalid parameter: pUnkOuter != NULL\n");
+        *ppDS = 0;
         return DSERR_INVALIDPARAM;
     }
 
-    if (ppDS == NULL) {
-        WARN("invalid parameter: ppDS == NULL\n");
-        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;
+        }
     }
 
-    /* Get dsound configuration */
-    setup_dsound_options();
+    *ppDS = pDS;
 
-    /* Default device? */
-    if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
-        lpcGUID = &DSDEVID_DefaultPlayback;
+    return hr;
+}
 
-    if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
-        WARN("invalid parameter: lpcGUID\n");
-        *ppDS = NULL;
-        return DSERR_INVALIDPARAM;
+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;
     }
 
-    if (dsound) {
-        if (IsEqualGUID(&devGuid, &dsound->guid)) {
-            hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
-            if (*ppDS)
-                IDirectSound8_IDirectSound8_AddRef(*ppDS);
-            else
-                WARN("IDirectSound8_IDirectSound8_Create failed\n");
-        } else {
-            ERR("different dsound already opened (only support one sound card at a time now)\n");
-            *ppDS = NULL;
-            hr = DSERR_ALLOCATED;
+    /* 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);
         }
     } else {
-        LPDIRECTSOUND8 pDS;
-        hr = IDirectSoundImpl_Create(&devGuid, &pDS);
-        if (hr == DS_OK) {
-            hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
-            if (hr == DS_OK) {
-                hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
-                if (*ppDS) {
-                    IDirectSound8_IDirectSound8_AddRef(*ppDS);
-
-                    dsound = (IDirectSoundImpl*)pDS;
-                    timeBeginPeriod(DS_TIME_RES);
-                    dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
-                                       (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
-                } else {
-                    WARN("IDirectSound8_IDirectSound8_Create failed\n");
-                    IDirectSound8_Release(pDS);
-                }
-            } else {
-                WARN("DSOUND_PrimaryCreate failed\n");
-                IDirectSound8_Release(pDS);
-            }
-        } else
-            WARN("IDirectSoundImpl_Create failed\n");
+        WARN("IDirectSoundImpl_Create failed\n");
+        *ppDS = 0;
     }
 
     return hr;
@@ -1816,47 +1123,704 @@ HRESULT WINAPI DirectSoundCreate8(
     IUnknown *pUnkOuter)
 {
     HRESULT hr;
+    LPDIRECTSOUND8 pDS;
 
     TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
 
-    hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
-    if (hr == DS_OK)
-        IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
+    if (ppDS == NULL) {
+        WARN("invalid parameter: ppDS == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (pUnkOuter != NULL) {
+        WARN("invalid parameter: pUnkOuter != NULL\n");
+        *ppDS = 0;
+        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;
+        }
+    }
+
+    *ppDS = pDS;
+
+    return hr;
+}
+
+/*******************************************************************************
+ *        DirectSoundDevice
+ */
+static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
+{
+    DirectSoundDevice * device;
+    TRACE("(%p)\n", ppDevice);
+
+    /* Allocate memory */
+    device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
+    if (device == NULL) {
+        WARN("out of memory\n");
+        return DSERR_OUTOFMEMORY;
+    }
+
+    device->ref            = 1;
+    device->priolevel      = DSSCL_NORMAL;
+    device->state          = STATE_STOPPED;
+    device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
+
+    /* 3D listener initial parameters */
+    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;
+
+    device->prebuf = ds_snd_queue_max;
+    device->guid = GUID_NULL;
+
+    /* Set default wave format (may need it for waveOutOpen) */
+    device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
+    if (device->pwfx == NULL) {
+        WARN("out of memory\n");
+        HeapFree(GetProcessHeap(),0,device);
+        return DSERR_OUTOFMEMORY;
+    }
+
+    /* We rely on the sound driver to return the actual sound format of
+     * the device if it does not support 22050x8x2 and is given the
+     * WAVE_DIRECTSOUND flag.
+     */
+    device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
+    device->pwfx->nSamplesPerSec = ds_default_sample_rate;
+    device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
+    device->pwfx->nChannels = 2;
+    device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
+    device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
+    device->pwfx->cbSize = 0;
+
+    InitializeCriticalSection(&(device->mixlock));
+    device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
+
+    RtlInitializeResource(&(device->buffer_list_lock));
+
+   *ppDevice = device;
+
+    return DS_OK;
+}
+
+static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
+{
+    ULONG ref = InterlockedIncrement(&(device->ref));
+    TRACE("(%p) ref was %d\n", device, ref - 1);
+    return ref;
+}
+
+ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
+{
+    HRESULT hr;
+    ULONG ref = InterlockedDecrement(&(device->ref));
+    TRACE("(%p) ref was %u\n", device, ref + 1);
+    if (!ref) {
+        int i;
+        timeKillEvent(device->timerID);
+        timeEndPeriod(DS_TIME_RES);
+
+        /* The kill event should have allowed the timer process to expire
+         * but try to grab the lock just in case. Can't hold lock because
+         * IDirectSoundBufferImpl_Destroy also grabs the lock */
+        RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
+        RtlReleaseResource(&(device->buffer_list_lock));
+
+        /* It is allowed to release this object even when buffers are playing */
+        if (device->buffers) {
+            WARN("%d secondary buffers not released\n", device->nrofbuffers);
+            for( i=0;i<device->nrofbuffers;i++)
+                IDirectSoundBufferImpl_Destroy(device->buffers[i]);
+        }
+
+        if (device->primary) {
+            WARN("primary buffer not released\n");
+            IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
+        }
+
+        hr = DSOUND_PrimaryDestroy(device);
+        if (hr != DS_OK)
+            WARN("DSOUND_PrimaryDestroy failed\n");
+
+        if (device->driver)
+            IDsDriver_Close(device->driver);
+
+        if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+            waveOutClose(device->hwo);
+
+        if (device->driver)
+            IDsDriver_Release(device->driver);
+
+        DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
+
+        HeapFree(GetProcessHeap(), 0, device->tmp_buffer);
+        HeapFree(GetProcessHeap(), 0, device->mix_buffer);
+        if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)
+            HeapFree(GetProcessHeap(), 0, device->buffer);
+        RtlDeleteResource(&device->buffer_list_lock);
+        device->mixlock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&device->mixlock);
+        HeapFree(GetProcessHeap(),0,device);
+        TRACE("(%p) released\n", device);
+    }
+    return ref;
+}
+
+HRESULT DirectSoundDevice_GetCaps(
+    DirectSoundDevice * device,
+    LPDSCAPS lpDSCaps)
+{
+    TRACE("(%p,%p)\n",device,lpDSCaps);
+
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
+
+    if (lpDSCaps == NULL) {
+        WARN("invalid parameter: lpDSCaps = NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    /* check if there is enough room */
+    if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
+        WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps->dwSize);
+        return DSERR_INVALIDPARAM;
+    }
+
+    lpDSCaps->dwFlags                           = device->drvcaps.dwFlags;
+    if (TRACE_ON(dsound)) {
+        TRACE("(flags=0x%08x:\n",lpDSCaps->dwFlags);
+        _dump_DSCAPS(lpDSCaps->dwFlags);
+        TRACE(")\n");
+    }
+    lpDSCaps->dwMinSecondarySampleRate          = device->drvcaps.dwMinSecondarySampleRate;
+    lpDSCaps->dwMaxSecondarySampleRate          = device->drvcaps.dwMaxSecondarySampleRate;
+    lpDSCaps->dwPrimaryBuffers                  = device->drvcaps.dwPrimaryBuffers;
+    lpDSCaps->dwMaxHwMixingAllBuffers           = device->drvcaps.dwMaxHwMixingAllBuffers;
+    lpDSCaps->dwMaxHwMixingStaticBuffers        = device->drvcaps.dwMaxHwMixingStaticBuffers;
+    lpDSCaps->dwMaxHwMixingStreamingBuffers     = device->drvcaps.dwMaxHwMixingStreamingBuffers;
+    lpDSCaps->dwFreeHwMixingAllBuffers          = device->drvcaps.dwFreeHwMixingAllBuffers;
+    lpDSCaps->dwFreeHwMixingStaticBuffers       = device->drvcaps.dwFreeHwMixingStaticBuffers;
+    lpDSCaps->dwFreeHwMixingStreamingBuffers    = device->drvcaps.dwFreeHwMixingStreamingBuffers;
+    lpDSCaps->dwMaxHw3DAllBuffers               = device->drvcaps.dwMaxHw3DAllBuffers;
+    lpDSCaps->dwMaxHw3DStaticBuffers            = device->drvcaps.dwMaxHw3DStaticBuffers;
+    lpDSCaps->dwMaxHw3DStreamingBuffers         = device->drvcaps.dwMaxHw3DStreamingBuffers;
+    lpDSCaps->dwFreeHw3DAllBuffers              = device->drvcaps.dwFreeHw3DAllBuffers;
+    lpDSCaps->dwFreeHw3DStaticBuffers           = device->drvcaps.dwFreeHw3DStaticBuffers;
+    lpDSCaps->dwFreeHw3DStreamingBuffers        = device->drvcaps.dwFreeHw3DStreamingBuffers;
+    lpDSCaps->dwTotalHwMemBytes                 = device->drvcaps.dwTotalHwMemBytes;
+    lpDSCaps->dwFreeHwMemBytes                  = device->drvcaps.dwFreeHwMemBytes;
+    lpDSCaps->dwMaxContigFreeHwMemBytes         = device->drvcaps.dwMaxContigFreeHwMemBytes;
+
+    /* driver doesn't have these */
+    lpDSCaps->dwUnlockTransferRateHwBuffers     = 4096; /* But we have none... */
+    lpDSCaps->dwPlayCpuOverheadSwBuffers        = 1;    /* 1% */
+
+    return DS_OK;
+}
+
+HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
+{
+    HRESULT hr = DS_OK;
+    unsigned wod, wodn;
+    BOOLEAN found = FALSE;
+    GUID devGUID;
+    DirectSoundDevice * device = *ppDevice;
+    TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
+
+    if (*ppDevice != NULL) {
+        WARN("already initialized\n");
+        return DSERR_ALREADYINITIALIZED;
+    }
+
+    /* Default device? */
+    if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
+        lpcGUID = &DSDEVID_DefaultPlayback;
+
+    if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
+        WARN("invalid parameter: lpcGUID\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    /* Enumerate WINMM audio devices and find the one we want */
+    wodn = waveOutGetNumDevs();
+    if (!wodn) {
+        WARN("no driver\n");
+        return DSERR_NODRIVER;
+    }
+
+    for (wod=0; wod<wodn; wod++) {
+        if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
+            found = TRUE;
+            break;
+        }
+    }
+
+    if (found == FALSE) {
+        WARN("No device found matching given ID!\n");
+        return DSERR_NODRIVER;
+    }
+
+    if (DSOUND_renderer[wod]) {
+        if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
+            device = DSOUND_renderer[wod];
+            DirectSoundDevice_AddRef(device);
+            *ppDevice = device;
+            return DS_OK;
+        } else {
+            ERR("device GUID doesn't match\n");
+            hr = DSERR_GENERIC;
+            return hr;
+        }
+    } else {
+        hr = DirectSoundDevice_Create(&device);
+        if (hr != DS_OK) {
+            WARN("DirectSoundDevice_Create failed\n");
+            return hr;
+        }
+    }
+
+    *ppDevice = device;
+    device->guid = devGUID;
+    device->driver = NULL;
+
+    device->drvdesc.dnDevNode = wod;
+    hr = DSOUND_ReopenDevice(device, FALSE);
+    if (FAILED(hr))
+    {
+        WARN("DSOUND_ReopenDevice failed: %08x\n", hr);
+        return hr;
+    }
+
+    if (device->driver) {
+        /* the driver is now open, so it's now allowed to call GetCaps */
+        hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
+        if (hr != DS_OK) {
+            WARN("IDsDriver_GetCaps failed\n");
+            return hr;
+        }
+    } else {
+        WAVEOUTCAPSA woc;
+        hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
+        if (hr != DS_OK) {
+            WARN("waveOutGetDevCaps failed\n");
+            return hr;
+        }
+        ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
+        if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
+            (woc.dwFormats & WAVE_FORMAT_2M08) ||
+            (woc.dwFormats & WAVE_FORMAT_4M08) ||
+            (woc.dwFormats & WAVE_FORMAT_48M08) ||
+            (woc.dwFormats & WAVE_FORMAT_96M08)) {
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
+        }
+        if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
+            (woc.dwFormats & WAVE_FORMAT_2M16) ||
+            (woc.dwFormats & WAVE_FORMAT_4M16) ||
+            (woc.dwFormats & WAVE_FORMAT_48M16) ||
+            (woc.dwFormats & WAVE_FORMAT_96M16)) {
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
+        }
+        if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
+            (woc.dwFormats & WAVE_FORMAT_2S08) ||
+            (woc.dwFormats & WAVE_FORMAT_4S08) ||
+            (woc.dwFormats & WAVE_FORMAT_48S08) ||
+            (woc.dwFormats & WAVE_FORMAT_96S08)) {
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
+        }
+        if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
+            (woc.dwFormats & WAVE_FORMAT_2S16) ||
+            (woc.dwFormats & WAVE_FORMAT_4S16) ||
+            (woc.dwFormats & WAVE_FORMAT_48S16) ||
+            (woc.dwFormats & WAVE_FORMAT_96S16)) {
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
+        }
+        if (ds_emuldriver)
+            device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
+        device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
+        device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
+        ZeroMemory(&device->volpan, sizeof(device->volpan));
+    }
+
+    hr = DSOUND_PrimaryCreate(device);
+    if (hr == DS_OK) {
+        UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id;
+        TIMECAPS time;
+
+        DSOUND_renderer[device->drvdesc.dnDevNode] = device;
+        timeGetDevCaps(&time, sizeof(TIMECAPS));
+        TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax);
+        if (triggertime < time.wPeriodMin)
+            triggertime = time.wPeriodMin;
+        if (res < time.wPeriodMin)
+            res = time.wPeriodMin;
+        if (timeBeginPeriod(res) == TIMERR_NOCANDO)
+            WARN("Could not set minimum resolution, don't expect sound\n");
+        id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
+        if (!id)
+        {
+            WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
+            id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC);
+            if (!id) ERR("Could not create timer, sound playback will not occur\n");
+        }
+        DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = id;
+    } else {
+        WARN("DSOUND_PrimaryCreate failed\n");
+    }
 
     return hr;
 }
 
+HRESULT DirectSoundDevice_CreateSoundBuffer(
+    DirectSoundDevice * device,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER ppdsb,
+    LPUNKNOWN lpunk,
+    BOOL from8)
+{
+    HRESULT hres = DS_OK;
+    TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk);
+
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
+
+    if (dsbd == NULL) {
+        WARN("invalid parameter: dsbd == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
+        dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
+        WARN("invalid parameter: dsbd\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (ppdsb == NULL) {
+        WARN("invalid parameter: ppdsb == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+    *ppdsb = NULL;
+
+    if (TRACE_ON(dsound)) {
+        TRACE("(structsize=%d)\n",dsbd->dwSize);
+        TRACE("(flags=0x%08x:\n",dsbd->dwFlags);
+        _dump_DSBCAPS(dsbd->dwFlags);
+        TRACE(")\n");
+        TRACE("(bufferbytes=%d)\n",dsbd->dwBufferBytes);
+        TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
+    }
+
+    if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
+        if (dsbd->lpwfxFormat != NULL) {
+            WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
+                 "primary buffer\n");
+            return DSERR_INVALIDPARAM;
+        }
+
+        if (device->primary) {
+            WARN("Primary Buffer already created\n");
+            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
+            *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
+        } else {
+           device->dsbd = *dsbd;
+           device->dsbd.dwFlags &= ~(DSBCAPS_LOCHARDWARE | DSBCAPS_LOCSOFTWARE);
+           if (device->hwbuf)
+               device->dsbd.dwFlags |= DSBCAPS_LOCHARDWARE;
+           else device->dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
+           hres = PrimaryBufferImpl_Create(device, &(device->primary), &(device->dsbd));
+           if (device->primary) {
+               IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
+               *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
+           } else
+               WARN("PrimaryBufferImpl_Create failed\n");
+        }
+    } else {
+        IDirectSoundBufferImpl * dsb;
+        WAVEFORMATEXTENSIBLE *pwfxe;
+
+        if (dsbd->lpwfxFormat == NULL) {
+            WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
+                 "secondary buffer\n");
+            return DSERR_INVALIDPARAM;
+        }
+        pwfxe = (WAVEFORMATEXTENSIBLE*)dsbd->lpwfxFormat;
+
+        if (pwfxe->Format.wBitsPerSample != 16 && pwfxe->Format.wBitsPerSample != 8 && pwfxe->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE)
+        {
+            WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd->lpwfxFormat->wBitsPerSample);
+            return DSERR_CONTROLUNAVAIL;
+        }
+        if (pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
+        {
+            /* check if cbSize is at least 22 bytes */
+            if (pwfxe->Format.cbSize < (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)))
+            {
+                WARN("Too small a cbSize %u\n", pwfxe->Format.cbSize);
+                return DSERR_INVALIDPARAM;
+            }
+
+            /* cbSize should be 22 bytes, with one possible exception */
+            if (pwfxe->Format.cbSize > (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) &&
+                !(IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) &&
+                pwfxe->Format.cbSize == sizeof(WAVEFORMATEXTENSIBLE)))
+            {
+                WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize);
+                return DSERR_CONTROLUNAVAIL;
+            }
+
+            if (!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))
+            {
+                if (!IsEqualGUID(&pwfxe->SubFormat, &GUID_NULL))
+                    FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat));
+                return DSERR_INVALIDPARAM;
+            }
+            if (pwfxe->Samples.wValidBitsPerSample > dsbd->lpwfxFormat->wBitsPerSample)
+            {
+                WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe->Samples.wValidBitsPerSample, pwfxe->Format.wBitsPerSample);
+                return DSERR_INVALIDPARAM;
+            }
+            if (pwfxe->Samples.wValidBitsPerSample && pwfxe->Samples.wValidBitsPerSample < dsbd->lpwfxFormat->wBitsPerSample)
+            {
+                FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe->Samples.wValidBitsPerSample, dsbd->lpwfxFormat->wBitsPerSample);
+                return DSERR_CONTROLUNAVAIL;
+            }
+        }
+
+        TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
+              "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
+              dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
+              dsbd->lpwfxFormat->nSamplesPerSec,
+              dsbd->lpwfxFormat->nAvgBytesPerSec,
+              dsbd->lpwfxFormat->nBlockAlign,
+              dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
+
+        if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
+            WARN("invalid parameter: 3D buffer format must be mono\n");
+            return DSERR_INVALIDPARAM;
+        }
+
+        hres = IDirectSoundBufferImpl_Create(device, &dsb, dsbd);
+        if (dsb) {
+            hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
+            if (*ppdsb) {
+                dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
+                IDirectSoundBuffer_AddRef(*ppdsb);
+            } else
+                WARN("SecondaryBufferImpl_Create failed\n");
+        } else
+           WARN("IDirectSoundBufferImpl_Create failed\n");
+   }
+
+   return hres;
+}
+
+HRESULT DirectSoundDevice_DuplicateSoundBuffer(
+    DirectSoundDevice * device,
+    LPDIRECTSOUNDBUFFER psb,
+    LPLPDIRECTSOUNDBUFFER ppdsb)
+{
+    HRESULT hres = DS_OK;
+    IDirectSoundBufferImpl* dsb;
+    TRACE("(%p,%p,%p)\n",device,psb,ppdsb);
+
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
+
+    if (psb == NULL) {
+        WARN("invalid parameter: psb == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (ppdsb == NULL) {
+        WARN("invalid parameter: ppdsb == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    /* make sure we have a secondary buffer */
+    if ((PrimaryBufferImpl *)psb == device->primary) {
+        WARN("trying to duplicate primary buffer\n");
+        *ppdsb = NULL;
+        return DSERR_INVALIDCALL;
+    }
+
+    /* duplicate the actual buffer implementation */
+    hres = IDirectSoundBufferImpl_Duplicate(device, &dsb,
+                                           ((SecondaryBufferImpl *)psb)->dsb);
+
+    if (hres == DS_OK) {
+        /* create a new secondary buffer using the new implementation */
+        hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
+        if (*ppdsb) {
+            dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
+            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
+        } else {
+            WARN("SecondaryBufferImpl_Create failed\n");
+            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
+            IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)dsb);
+        }
+    }
+
+    return hres;
+}
+
+HRESULT DirectSoundDevice_SetCooperativeLevel(
+    DirectSoundDevice * device,
+    HWND hwnd,
+    DWORD level)
+{
+    TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
+
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
+
+    if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
+        WARN("level=%s not fully supported\n",
+             level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
+    }
+
+    device->priolevel = level;
+    return DS_OK;
+}
+
+HRESULT DirectSoundDevice_Compact(
+    DirectSoundDevice * device)
+{
+    TRACE("(%p)\n", device);
+
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
+
+    if (device->priolevel < DSSCL_PRIORITY) {
+        WARN("incorrect priority level\n");
+        return DSERR_PRIOLEVELNEEDED;
+    }
+
+    return DS_OK;
+}
+
+HRESULT DirectSoundDevice_GetSpeakerConfig(
+    DirectSoundDevice * device,
+    LPDWORD lpdwSpeakerConfig)
+{
+    TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
+
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
+
+    if (lpdwSpeakerConfig == NULL) {
+        WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    WARN("not fully functional\n");
+    *lpdwSpeakerConfig = device->speaker_config;
+    return DS_OK;
+}
+
+HRESULT DirectSoundDevice_SetSpeakerConfig(
+    DirectSoundDevice * device,
+    DWORD config)
+{
+    TRACE("(%p,0x%08x)\n",device,config);
+
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
+
+    device->speaker_config = config;
+    WARN("not fully functional\n");
+    return DS_OK;
+}
+
+HRESULT DirectSoundDevice_VerifyCertification(
+    DirectSoundDevice * device,
+    LPDWORD pdwCertified)
+{
+    TRACE("(%p, %p)\n",device,pdwCertified);
+
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
+
+    if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
+        *pdwCertified = DS_CERTIFIED;
+    else
+        *pdwCertified = DS_UNCERTIFIED;
+
+    return DS_OK;
+}
+
 /*
  * Add secondary buffer to buffer list.
  * Gets exclusive access to buffer for writing.
  */
-HRESULT DSOUND_AddBuffer(
-    IDirectSoundImpl * pDS,
+HRESULT DirectSoundDevice_AddBuffer(
+    DirectSoundDevice * device,
     IDirectSoundBufferImpl * pDSB)
 {
     IDirectSoundBufferImpl **newbuffers;
     HRESULT hr = DS_OK;
 
-    TRACE("(%p, %p)\n", pDS, pDSB);
+    TRACE("(%p, %p)\n", device, pDSB);
 
-    RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
+    RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
 
-    if (pDS->buffers)
-        newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
+    if (device->buffers)
+        newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
     else
-        newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
+        newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
 
     if (newbuffers) {
-        pDS->buffers = newbuffers;
-        pDS->buffers[pDS->nrofbuffers] = pDSB;
-        pDS->nrofbuffers++;
-        TRACE("buffer count is now %d\n", pDS->nrofbuffers);
+        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", pDS->nrofbuffers);
+        ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers);
         hr = DSERR_OUTOFMEMORY;
     }
 
-    RtlReleaseResource(&(pDS->buffer_list_lock));
+    RtlReleaseResource(&(device->buffer_list_lock));
 
     return hr;
 }
@@ -1865,35 +1829,35 @@ HRESULT DSOUND_AddBuffer(
  * Remove secondary buffer from buffer list.
  * Gets exclusive access to buffer for writing.
  */
-HRESULT DSOUND_RemoveBuffer(
-    IDirectSoundImpl * pDS,
+HRESULT DirectSoundDevice_RemoveBuffer(
+    DirectSoundDevice * device,
     IDirectSoundBufferImpl * pDSB)
 {
     int i;
     HRESULT hr = DS_OK;
 
-    TRACE("(%p, %p)\n", pDS, pDSB);
+    TRACE("(%p, %p)\n", device, pDSB);
 
-    RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
+    RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
 
-    for (i = 0; i < pDS->nrofbuffers; i++)
-        if (pDS->buffers[i] == pDSB)
+    for (i = 0; i < device->nrofbuffers; i++)
+        if (device->buffers[i] == pDSB)
             break;
 
-    if (i < pDS->nrofbuffers) {
+    if (i < device->nrofbuffers) {
         /* Put the last buffer of the list in the (now empty) position */
-        pDS->buffers[i] = pDS->buffers[pDS->nrofbuffers - 1];
-        pDS->nrofbuffers--;
-        pDS->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->nrofbuffers);
-        TRACE("buffer count is now %d\n", pDS->nrofbuffers);
+        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 (pDS->nrofbuffers == 0) {
-        HeapFree(GetProcessHeap(),0,pDS->buffers);
-        pDS->buffers = NULL;
+    if (device->nrofbuffers == 0) {
+        HeapFree(GetProcessHeap(),0,device->buffers);
+        device->buffers = NULL;
     }
 
-    RtlReleaseResource(&(pDS->buffer_list_lock));
+    RtlReleaseResource(&(device->buffer_list_lock));
 
     return hr;
 }