diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 10119172a829f2cfafbd67b91c2c86f9a4cc99d5..576d60bafd28d80fd7c3ce6c1d657d0197ae22ab 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -58,23 +58,12 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(
 	ICOM_THIS(IDirectSoundNotifyImpl,iface);
 	TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
 
-	if (ppobj == NULL) {
+	if (This->dsb == NULL) {
 		WARN("invalid parameter\n");
 		return E_INVALIDARG;
 	}
 
-	*ppobj = NULL;	/* assume error */
-
-	if ( IsEqualGUID(riid, &IID_IUnknown) || 
-	     IsEqualGUID(riid, &IID_IDirectSoundNotify) ||
-	     IsEqualGUID(riid, &IID_IDirectSoundNotify8) ) {
-		IDirectSoundNotify_AddRef(iface);
-		*ppobj = This;
-		return DS_OK;
-	}
-
-	FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
-	return E_NOINTERFACE;
+	return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER)This->dsb, riid, ppobj);
 }
 
 static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) {
@@ -94,14 +83,11 @@ static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) {
 	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
 
 	ref = InterlockedDecrement(&(This->ref));
-	/* FIXME: A notification should be a part of a buffer rather than pointed 
-	 * to from a buffer. Hence the -1 ref count */
-	if (ref == -1) {
-		if (This->notifies != NULL)
-			HeapFree(GetProcessHeap(), 0, This->notifies);
-
+	if (ref == 0) {
+		IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb);
+		This->dsb->notify = NULL;
 		HeapFree(GetProcessHeap(),0,This);
-		return 0;
+		TRACE("(%p) released\n",This);
 	}
 	return ref;
 }
@@ -124,23 +110,23 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(
 		    notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
 	}
 
-	if (This->hwnotify) {
+	if (This->dsb->hwnotify) {
 	    HRESULT hres;
-	    hres = IDsDriverNotify_SetNotificationPositions(This->hwnotify, howmuch, notify);
+	    hres = IDsDriverNotify_SetNotificationPositions(This->dsb->hwnotify, howmuch, notify);
 	    if (hres != DS_OK)
 		    WARN("IDsDriverNotify_SetNotificationPositions failed\n");
 	    return hres;
 	} else {
 	    /* Make an internal copy of the caller-supplied array.
 	     * Replace the existing copy if one is already present. */
-	    This->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
-	        This->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
-	    if (This->notifies == NULL) {
+	    This->dsb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+	        This->dsb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
+	    if (This->dsb->notifies == NULL) {
 		    WARN("out of memory\n");
 		    return DSERR_OUTOFMEMORY;
 	    }
-	    memcpy(This->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
-	    This->nrofnotifies = howmuch;
+	    memcpy(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
+	    This->dsb->nrofnotifies = howmuch;
 	}
 
 	return S_OK;
@@ -148,13 +134,37 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(
 
 ICOM_VTABLE(IDirectSoundNotify) dsnvt =
 {
-	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-	IDirectSoundNotifyImpl_QueryInterface,
-	IDirectSoundNotifyImpl_AddRef,
-	IDirectSoundNotifyImpl_Release,
-	IDirectSoundNotifyImpl_SetNotificationPositions,
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectSoundNotifyImpl_QueryInterface,
+    IDirectSoundNotifyImpl_AddRef,
+    IDirectSoundNotifyImpl_Release,
+    IDirectSoundNotifyImpl_SetNotificationPositions,
 };
 
+HRESULT WINAPI IDirectSoundNotifyImpl_Create(
+    IDirectSoundBufferImpl * dsb,
+    IDirectSoundNotifyImpl **pdsn)
+{
+    IDirectSoundNotifyImpl * dsn;
+    TRACE("(%p,%p)\n",dsb,pdsn);
+                                                                                                                             
+    dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dsn));
+                                                                                                                                
+    if (dsn == NULL) {
+        WARN("out of memory\n");
+        return DSERR_OUTOFMEMORY;
+    }
+
+    dsn->ref = 0;
+    dsn->lpVtbl = &dsnvt;
+    dsn->dsb = dsb;
+    dsb->notify = dsn;
+    IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
+                                                                                                                                
+    *pdsn = dsn;
+    return DS_OK;
+}
+                                                                                                                                
 /*******************************************************************************
  *		IDirectSoundBuffer
  */
@@ -361,7 +371,6 @@ static DWORD WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) {
 	for (i=0;i<This->dsound->nrofbuffers;i++)
 		if (This->dsound->buffers[i] == This)
 			break;
-
 	if (i < This->dsound->nrofbuffers) {
 		/* Put the last buffer of the list in the (now empty) position */
 		This->dsound->buffers[i] = This->dsound->buffers[This->dsound->nrofbuffers - 1];
@@ -401,8 +410,12 @@ static DWORD WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) {
 	if (This->iks)
 		IKsPropertySet_Release((LPKSPROPERTYSET)This->iks);
 
+	if (This->notifies != NULL)
+		HeapFree(GetProcessHeap(), 0, This->notifies);
+
 	HeapFree(GetProcessHeap(),0,This);
 
+	TRACE("(%p) released\n",This);
 	return 0;
 }
 
@@ -920,24 +933,24 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
 	if ( IsEqualGUID(riid, &IID_IUnknown) || 
 	     IsEqualGUID(riid, &IID_IDirectSoundBuffer) || 
 	     IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
-		IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This);
-		*ppobj = This;
-		return S_OK;
+		if (!This->dsb)
+			SecondaryBufferImpl_Create(This, &(This->dsb));
+		if (This->dsb) {
+			IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb);
+			*ppobj = This->dsb;
+			return S_OK;
+		}
+		WARN("IID_IDirectSoundBuffer\n");
+		return E_NOINTERFACE;
 	}
 
 	if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ||
 	     IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) {
-		if (!This->notify) {
-			This->notify = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),
-				HEAP_ZERO_MEMORY,sizeof(*This->notify));
-			if (This->notify) {
-				This->notify->ref = 0;	/* release when ref == -1 */
-				This->notify->lpVtbl = &dsnvt;
-			}
-		}
+		if (!This->notify)
+			IDirectSoundNotifyImpl_Create(This, &(This->notify));
 		if (This->notify) {
 			IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
-			*ppobj = (LPVOID)This->notify;
+			*ppobj = This->notify;
 			return S_OK;
 		}
 		WARN("IID_IDirectSoundNotify\n");
@@ -946,10 +959,10 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
 
 	if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
 		if (!This->ds3db)
-			IDirectSound3DBufferImpl_Create(This, &This->ds3db);
-		*ppobj = This->ds3db;
-		if (*ppobj) {
-			IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)*ppobj);
+			IDirectSound3DBufferImpl_Create(This, &(This->ds3db));
+		if (This->ds3db) {
+			IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->ds3db);
+			*ppobj = This->ds3db;
 			return S_OK;
 		}
 		WARN("IID_IDirectSound3DBuffer\n");
@@ -965,13 +978,12 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
 		/* only supported on hardware 3D secondary buffers */
 		if (!(This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) && 
 		     (This->dsbd.dwFlags & DSBCAPS_CTRL3D) && 
-		     (This->dsbd.dwFlags & DSBCAPS_LOCHARDWARE) &&
 		     (This->hwbuf != NULL) ) {
 			if (!This->iks)
-				IKsBufferPropertySetImpl_Create(This, &This->iks);
-		    	*ppobj = This->iks;
-			if (*ppobj) {
+				IKsBufferPropertySetImpl_Create(This, &(This->iks));
+			if (This->iks) {
 				IKsPropertySet_AddRef((LPKSPROPERTYSET)*ppobj);
+		    		*ppobj = This->iks;
 				return S_OK;
 			}
 		}
@@ -1013,8 +1025,8 @@ static ICOM_VTABLE(IDirectSoundBuffer8) dsbvt =
 	IDirectSoundBufferImpl_GetObjectInPath
 };
 
-HRESULT WINAPI SecondaryBuffer_Create(
-	IDirectSoundImpl *This,
+HRESULT WINAPI IDirectSoundBufferImpl_Create(
+	IDirectSoundImpl *ds,
 	IDirectSoundBufferImpl **pdsb,
 	LPDSBUFFERDESC dsbd)
 {
@@ -1023,6 +1035,7 @@ HRESULT WINAPI SecondaryBuffer_Create(
 	HRESULT err = DS_OK;
 	DWORD capf = 0;
 	int use_hw;
+	TRACE("(%p,%p,%p)\n",ds,pdsb,dsbd);
 
 	if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
 		WARN("invalid parameter: dsbd->dwBufferBytes = %ld\n", dsbd->dwBufferBytes);
@@ -1038,7 +1051,8 @@ HRESULT WINAPI SecondaryBuffer_Create(
 		return DSERR_OUTOFMEMORY;
 	}
 	dsb->ref = 0;
-	dsb->dsound = This;
+	dsb->dsb = 0;
+	dsb->dsound = ds;
 	dsb->lpVtbl = &dsbvt;
 
 	memcpy(&dsb->dsbd, dsbd, sizeof(*dsbd));
@@ -1050,12 +1064,17 @@ HRESULT WINAPI SecondaryBuffer_Create(
 	dsb->buflen = dsbd->dwBufferBytes;
 	dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec;
 
+	dsb->notify = NULL;
+	dsb->notifies = NULL;
+	dsb->nrofnotifies = 0;
+	dsb->hwnotify = 0;
+
 	/* Check necessary hardware mixing capabilities */
 	if (wfex->nChannels==2) capf |= DSCAPS_SECONDARYSTEREO;
 	else capf |= DSCAPS_SECONDARYMONO;
 	if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
 	else capf |= DSCAPS_SECONDARY8BIT;
-	use_hw = (This->drvcaps.dwFlags & capf) == capf;
+	use_hw = (ds->drvcaps.dwFlags & capf) == capf;
 
 	/* FIXME: check hardware sample rate mixing capabilities */
 	/* FIXME: check app hints for software/hardware buffer (STATIC, LOCHARDWARE, etc) */
@@ -1063,7 +1082,7 @@ HRESULT WINAPI SecondaryBuffer_Create(
 	/* FIXME: handle DSDHEAP_CREATEHEAP for hardware buffers */
 
 	/* Allocate system memory if applicable */
-	if ((This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) {
+	if ((ds->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) {
 		dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
 		if (dsb->buffer == NULL) {
 			WARN("out of memory\n");
@@ -1084,7 +1103,7 @@ HRESULT WINAPI SecondaryBuffer_Create(
 
 	/* Allocate the hardware buffer */
 	if (use_hw) {
-		err = IDsDriver_CreateSoundBuffer(This->driver,wfex,dsbd->dwFlags,0,
+		err = IDsDriver_CreateSoundBuffer(ds->driver,wfex,dsbd->dwFlags,0,
 						  &(dsb->buflen),&(dsb->buffer->memory),
 						  (LPVOID*)&(dsb->hwbuf));
 		if (err != DS_OK) {
@@ -1109,7 +1128,7 @@ HRESULT WINAPI SecondaryBuffer_Create(
 	dsb->state = STATE_STOPPED;
 
 	dsb->freqAdjust = (dsb->freq << DSOUND_FREQSHIFT) /
-		This->wfx.nSamplesPerSec;
+		ds->wfx.nSamplesPerSec;
 	dsb->nAvgBytesPerSec = dsb->freq *
 		dsbd->lpwfxFormat->nBlockAlign;
 
@@ -1139,29 +1158,312 @@ HRESULT WINAPI SecondaryBuffer_Create(
 	InitializeCriticalSection(&(dsb->lock));
 
 	/* register buffer */
-	RtlAcquireResourceExclusive(&(This->lock), TRUE);
+	RtlAcquireResourceExclusive(&(ds->lock), TRUE);
 	if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
-		IDirectSoundBufferImpl **newbuffers = (IDirectSoundBufferImpl**)HeapReAlloc(GetProcessHeap(),0,This->buffers,sizeof(IDirectSoundBufferImpl*)*(This->nrofbuffers+1));
+		IDirectSoundBufferImpl **newbuffers = (IDirectSoundBufferImpl**)HeapReAlloc(GetProcessHeap(),0,ds->buffers,sizeof(IDirectSoundBufferImpl*)*(ds->nrofbuffers+1));
 		if (newbuffers) {
-			This->buffers = newbuffers;
-			This->buffers[This->nrofbuffers] = dsb;
-			This->nrofbuffers++;
-			TRACE("buffer count is now %d\n", This->nrofbuffers);
+			ds->buffers = newbuffers;
+			ds->buffers[ds->nrofbuffers] = dsb;
+			ds->nrofbuffers++;
+			TRACE("buffer count is now %d\n", ds->nrofbuffers);
 		} else {
-			ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers);
+			ERR("out of memory for buffer list! Current buffer count is %d\n", ds->nrofbuffers);
 			if (dsb->buffer->memory)
 				HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
 			if (dsb->buffer)
 				HeapFree(GetProcessHeap(),0,dsb->buffer);
 			DeleteCriticalSection(&(dsb->lock));
-			RtlReleaseResource(&(This->lock));
+			RtlReleaseResource(&(ds->lock));
 			HeapFree(GetProcessHeap(),0,dsb);
 			*pdsb = NULL;
 			return DSERR_OUTOFMEMORY;
 		}
 	}
-	RtlReleaseResource(&(This->lock));
-	IDirectSound8_AddRef((LPDIRECTSOUND8)This);
+	RtlReleaseResource(&(ds->lock));
+	IDirectSound8_AddRef((LPDIRECTSOUND8)ds);
 	*pdsb = dsb;
 	return S_OK;
 }
+
+/*******************************************************************************
+ *		SecondaryBuffer
+ */
+
+static HRESULT WINAPI SecondaryBufferImpl_QueryInterface(
+	LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj) 
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+
+	return IDirectSoundBufferImpl_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb,riid,ppobj);
+}
+
+static DWORD WINAPI SecondaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface)
+{
+	ICOM_THIS(IDirectSoundBufferImpl,iface);
+	DWORD ref;
+	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+
+	ref = InterlockedIncrement(&(This->ref));
+	if (!ref) {
+		FIXME("thread-safety alert! AddRef-ing with a zero refcount!\n");
+	}
+	return ref;
+}
+
+static DWORD WINAPI SecondaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface)
+{
+	ICOM_THIS(IDirectSoundBufferImpl,iface);
+	DWORD ref;
+	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+
+	ref = InterlockedDecrement(&(This->ref));
+	if (!ref) {
+		This->dsb->dsb = NULL;
+		IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
+		HeapFree(GetProcessHeap(),0,This);
+		TRACE("(%p) released\n",This);
+	}
+	return ref;
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_GetCaps(
+	LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+  	TRACE("(%p)->(%p)\n",This,caps);
+
+	return IDirectSoundBufferImpl_GetCaps((LPDIRECTSOUNDBUFFER8)This->dsb,caps);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_GetCurrentPosition(
+	LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%p,%p)\n",This,playpos,writepos);
+
+	return IDirectSoundBufferImpl_GetCurrentPosition((LPDIRECTSOUNDBUFFER8)This->dsb,playpos,writepos);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_GetFormat(
+	LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX lpwf,DWORD wfsize,LPDWORD wfwritten)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten);
+
+	return IDirectSoundBufferImpl_GetFormat((LPDIRECTSOUNDBUFFER8)This->dsb,lpwf,wfsize,wfwritten);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_GetVolume(
+	LPDIRECTSOUNDBUFFER8 iface,LPLONG vol)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%p)\n",This,vol);
+
+	return IDirectSoundBufferImpl_GetVolume((LPDIRECTSOUNDBUFFER8)This->dsb,vol);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_GetPan(
+	LPDIRECTSOUNDBUFFER8 iface,LPLONG pan)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%p)\n",This,pan);
+
+	return IDirectSoundBufferImpl_GetPan((LPDIRECTSOUNDBUFFER8)This->dsb,pan);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_GetFrequency(
+	LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%p)\n",This,freq);
+
+	return IDirectSoundBufferImpl_GetFrequency((LPDIRECTSOUNDBUFFER8)This->dsb,freq);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_GetStatus(
+	LPDIRECTSOUNDBUFFER8 iface,LPDWORD status)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%p)\n",This,status);
+
+	return IDirectSoundBufferImpl_GetStatus((LPDIRECTSOUNDBUFFER8)This->dsb,status);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_Initialize(
+	LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND8 dsound,LPDSBUFFERDESC dbsd)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%p,%p)\n",This,dsound,dbsd);
+
+	return IDirectSoundBufferImpl_Initialize((LPDIRECTSOUNDBUFFER8)This->dsb,dsound,dbsd);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_Lock(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx)\n",
+		This,writecursor,writebytes,lplpaudioptr1,audiobytes1,lplpaudioptr2,audiobytes2,flags);
+
+	return IDirectSoundBufferImpl_Lock((LPDIRECTSOUNDBUFFER8)This->dsb,writecursor,writebytes,lplpaudioptr1,audiobytes1,lplpaudioptr2,audiobytes2,flags);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_Play(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%08lx,%08lx,%08lx)\n",This,reserved1,reserved2,flags);
+
+	return IDirectSoundBufferImpl_Play((LPDIRECTSOUNDBUFFER8)This->dsb,reserved1,reserved2,flags);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_SetCurrentPosition(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD newpos)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%ld)\n",This,newpos);
+
+	return IDirectSoundBufferImpl_SetCurrentPosition((LPDIRECTSOUNDBUFFER8)This->dsb,newpos);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_SetFormat(
+	LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX wfex)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%p)\n",This,wfex);
+
+	return IDirectSoundBufferImpl_SetFormat((LPDIRECTSOUNDBUFFER8)This->dsb,wfex);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_SetVolume(
+	LPDIRECTSOUNDBUFFER8 iface,LONG vol)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%ld)\n",This,vol);
+
+	return IDirectSoundBufferImpl_SetVolume((LPDIRECTSOUNDBUFFER8)This->dsb,vol);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_SetPan(
+	LPDIRECTSOUNDBUFFER8 iface,LONG pan)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%ld)\n",This,pan);
+
+	return IDirectSoundBufferImpl_SetPan((LPDIRECTSOUNDBUFFER8)This->dsb,pan);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_SetFrequency(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD freq)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%ld)\n",This,freq);
+
+	return IDirectSoundBufferImpl_SetFrequency((LPDIRECTSOUNDBUFFER8)This->dsb,freq);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p)\n",This);
+
+	return IDirectSoundBufferImpl_Stop((LPDIRECTSOUNDBUFFER8)This->dsb);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_Unlock(
+	LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%p,%ld,%p,%ld)\n", This,p1,x1,p2,x2);
+
+	return IDirectSoundBufferImpl_Unlock((LPDIRECTSOUNDBUFFER8)This->dsb,p1,x1,p2,x2);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_Restore(
+	LPDIRECTSOUNDBUFFER8 iface)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p)\n",This);
+
+	return IDirectSoundBufferImpl_Restore((LPDIRECTSOUNDBUFFER8)This->dsb);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_SetFX(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%lu,%p,%p)\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
+
+	return IDirectSoundBufferImpl_SetFX((LPDIRECTSOUNDBUFFER8)This->dsb,dwEffectsCount,pDSFXDesc,pdwResultCodes);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_AcquireResources(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%08lu,%lu,%p)\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
+
+	return IDirectSoundBufferImpl_AcquireResources((LPDIRECTSOUNDBUFFER8)This->dsb,dwFlags,dwEffectsCount,pdwResultCodes);
+}
+
+static HRESULT WINAPI SecondaryBufferImpl_GetObjectInPath(
+	LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject)
+{
+	ICOM_THIS(SecondaryBufferImpl,iface);
+	TRACE("(%p,%s,%lu,%s,%p)\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
+
+	return IDirectSoundBufferImpl_GetObjectInPath((LPDIRECTSOUNDBUFFER8)This->dsb,rguidObject,dwIndex,rguidInterface,ppObject);
+}
+
+static ICOM_VTABLE(IDirectSoundBuffer8) sbvt =
+{
+	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+	SecondaryBufferImpl_QueryInterface,
+	SecondaryBufferImpl_AddRef,
+	SecondaryBufferImpl_Release,
+	SecondaryBufferImpl_GetCaps,
+	SecondaryBufferImpl_GetCurrentPosition,
+	SecondaryBufferImpl_GetFormat,
+	SecondaryBufferImpl_GetVolume,
+	SecondaryBufferImpl_GetPan,
+	SecondaryBufferImpl_GetFrequency,
+	SecondaryBufferImpl_GetStatus,
+	SecondaryBufferImpl_Initialize,
+	SecondaryBufferImpl_Lock,
+	SecondaryBufferImpl_Play,
+	SecondaryBufferImpl_SetCurrentPosition,
+	SecondaryBufferImpl_SetFormat,
+	SecondaryBufferImpl_SetVolume,
+	SecondaryBufferImpl_SetPan,
+	SecondaryBufferImpl_SetFrequency,
+	SecondaryBufferImpl_Stop,
+	SecondaryBufferImpl_Unlock,
+	SecondaryBufferImpl_Restore,
+	SecondaryBufferImpl_SetFX,
+	SecondaryBufferImpl_AcquireResources,
+	SecondaryBufferImpl_GetObjectInPath
+};
+
+HRESULT WINAPI SecondaryBufferImpl_Create(
+	IDirectSoundBufferImpl *dsb,
+	SecondaryBufferImpl **psb)
+{
+	SecondaryBufferImpl *sb;
+	TRACE("(%p,%p)\n",dsb,psb);
+
+	sb = (SecondaryBufferImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*sb));
+
+	if (sb == 0) {
+		WARN("out of memory\n");
+		*psb = NULL;
+		return DSERR_OUTOFMEMORY;
+	}
+	sb->ref = 0;
+	sb->dsb = dsb;
+	sb->lpVtbl = &sbvt;
+
+	IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
+	*psb = sb;
+	return S_OK;
+}
diff --git a/dlls/dsound/capture.c b/dlls/dsound/capture.c
index d14b2f771e726f1e4a3baf450836283c74338338..6b5707a2894b050a65d9a9742f60e3c0af910235 100644
--- a/dlls/dsound/capture.c
+++ b/dlls/dsound/capture.c
@@ -325,8 +325,8 @@ DSOUND_capture_callback(
 	    }
 	    This->index = (This->index + 1) % This->nrofpwaves;
 	    waveInUnprepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR));
-	    if (This->capture_buffer->notify && This->capture_buffer->notify->nrofnotifies)
-		SetEvent(This->capture_buffer->notify->notifies[This->index].hEventNotify);
+	    if (This->capture_buffer->nrofnotifies)
+		SetEvent(This->capture_buffer->notifies[This->index].hEventNotify);
 	    if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
 		TRACE("end of buffer\n");
 		This->state = STATE_STOPPED;
@@ -377,10 +377,9 @@ IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
 {
     ULONG uRef;
     ICOM_THIS(IDirectSoundCaptureImpl,iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
 
     EnterCriticalSection( &(This->lock) );
-
-    TRACE( "(%p) was 0x%08lx\n", This, This->ref );
     uRef = ++(This->ref);
 
     if (This->driver) 
@@ -396,10 +395,10 @@ IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
 {
     ULONG uRef;
     ICOM_THIS(IDirectSoundCaptureImpl,iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
 
     EnterCriticalSection( &(This->lock) );
 
-    TRACE( "(%p) was 0x%08lx\n", This, This->ref );
     uRef = --(This->ref);
 
     LeaveCriticalSection( &(This->lock) );
@@ -418,9 +417,9 @@ IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
         DeleteCriticalSection( &(This->lock) );
         HeapFree( GetProcessHeap(), 0, This );
 	dsound_capture = NULL;
+	TRACE("(%p) released\n",This);
     }
 
-    TRACE( "returning 0x%08lx\n", uRef );
     return uRef;
 }
 
@@ -704,6 +703,9 @@ DSOUND_CreateDirectSoundCaptureBuffer(
         This->ref = 1;
         This->dsound = ipDSC;
         This->dsound->capture_buffer = This;
+	This->notify = NULL;
+	This->nrofnotifies = 0;
+	This->hwnotify = NULL;
 
         This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
             lpcDSCBufferDesc->dwSize);
@@ -765,6 +767,131 @@ DSOUND_CreateDirectSoundCaptureBuffer(
     return DS_OK;
 }
 
+/*******************************************************************************
+ *		IDirectSoundCaptureNotify
+ */
+static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface(
+    LPDIRECTSOUNDNOTIFY iface,
+    REFIID riid,
+    LPVOID *ppobj)
+{
+    ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+
+    if (This->dscb == NULL) {
+	WARN("invalid parameter\n");
+	return E_INVALIDARG;
+    }
+
+    return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj);
+}
+
+static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
+{
+    ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
+    DWORD ref;
+
+    TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+
+    ref = InterlockedIncrement(&(This->ref));
+    return ref;
+}
+
+static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
+{
+    ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
+    DWORD ref;
+
+    TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+
+    ref = InterlockedDecrement(&(This->ref));
+    if (ref == 0) {
+	This->dscb->notify=NULL;
+	IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
+	HeapFree(GetProcessHeap(),0,This);
+	TRACE("(%p) released\n",This);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
+    LPDIRECTSOUNDNOTIFY iface,
+    DWORD howmuch,
+    LPCDSBPOSITIONNOTIFY notify)
+{
+    ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
+    TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
+
+    if (notify == NULL) {
+	WARN("invalid parameter: notify == NULL\n");
+	return DSERR_INVALIDPARAM;
+    }
+
+    if (TRACE_ON(dsound)) {
+	int	i;
+	for (i=0;i<howmuch;i++)
+	    TRACE("notify at %ld to 0x%08lx\n",
+	    notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
+    }
+
+    if (This->dscb->hwnotify) {
+	HRESULT hres;
+	hres = IDsDriverNotify_SetNotificationPositions(This->dscb->hwnotify, howmuch, notify);
+	if (hres != DS_OK)
+	    WARN("IDsDriverNotify_SetNotificationPositions failed\n");
+	return hres;
+    } else {
+	/* Make an internal copy of the caller-supplied array.
+	 * Replace the existing copy if one is already present. */
+	This->dscb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+	    This->dscb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
+	if (This->dscb->notifies == NULL) {
+	    WARN("out of memory\n");
+	    return DSERR_OUTOFMEMORY;
+	}
+	memcpy(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
+	This->dscb->nrofnotifies = howmuch;
+    }
+
+    return S_OK;
+}
+
+ICOM_VTABLE(IDirectSoundNotify) dscnvt =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectSoundCaptureNotifyImpl_QueryInterface,
+    IDirectSoundCaptureNotifyImpl_AddRef,
+    IDirectSoundCaptureNotifyImpl_Release,
+    IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
+};
+
+HRESULT WINAPI IDirectSoundCaptureNotifyImpl_Create(
+    IDirectSoundCaptureBufferImpl *dscb,
+    IDirectSoundCaptureNotifyImpl **pdscn)
+{
+    IDirectSoundCaptureNotifyImpl * dscn;
+    TRACE("(%p,%p)\n",dscb,pdscn);
+
+    dscn = (IDirectSoundCaptureNotifyImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dscn));
+
+    if (dscn == NULL) {
+	WARN("out of memory\n");
+	return DSERR_OUTOFMEMORY;
+    }
+
+    dscn->ref = 0;
+    dscn->lpVtbl = &dscnvt;
+    dscn->dscb = dscb;
+    dscb->notify = dscn;
+    IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
+
+    *pdscn = dscn;
+    return DS_OK;
+}
+
+/*******************************************************************************
+ *		IDirectSoundCaptureBuffer
+ */
 static HRESULT WINAPI
 IDirectSoundCaptureBufferImpl_QueryInterface(
     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
@@ -772,6 +899,7 @@ IDirectSoundCaptureBufferImpl_QueryInterface(
     LPVOID* ppobj )
 {
     ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
+    HRESULT hres;
     TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
 
     if (ppobj == NULL) {
@@ -783,24 +911,16 @@ IDirectSoundCaptureBufferImpl_QueryInterface(
 
     if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ||
          IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) {
-	if (!This->notify) {
-	    This->notify = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),
-		HEAP_ZERO_MEMORY, sizeof(*This->notify));
-	    if (This->notify) {
-		This->notify->ref = 0;	/* release when ref = -1 */
-		This->notify->lpVtbl = &dsnvt;
-	    }
-	}
+	if (!This->notify)
+	    hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
 	if (This->notify) {
 	    if (This->dsound->hwbuf) {
-		HRESULT err;
-		
-		err = IDsCaptureDriverBuffer_QueryInterface(This->dsound->hwbuf, 
-		    &IID_IDsDriverNotify, (LPVOID*)&(This->notify->hwnotify));
-		if (err != DS_OK) {
+		hres = IDsCaptureDriverBuffer_QueryInterface(This->dsound->hwbuf, 
+		    &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify));
+		if (hres != DS_OK) {
 		    WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
 		    *ppobj = 0;
-		    return err;
+		    return hres;
 	        }
 	    }
 
@@ -809,7 +929,6 @@ IDirectSoundCaptureBufferImpl_QueryInterface(
 	    return DS_OK;
 	}
 
-	*ppobj = 0;
 	WARN("IID_IDirectSoundNotify\n");
 	return E_FAIL;
     }
@@ -822,9 +941,6 @@ IDirectSoundCaptureBufferImpl_QueryInterface(
     }
 
     FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
-
-    *ppobj = 0;
-
     return E_NOINTERFACE;
 }
 
@@ -833,13 +949,12 @@ IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
 {
     ULONG uRef;
     ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
-    TRACE( "(%p)\n", This );
+    TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
 
     assert(This->dsound);
 
     EnterCriticalSection( &(This->dsound->lock) );
 
-    TRACE( "(%p) was 0x%08lx\n", This, This->ref );
     uRef = ++(This->ref);
 
     LeaveCriticalSection( &(This->dsound->lock) );
@@ -852,13 +967,12 @@ IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
 {
     ULONG uRef;
     ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
-    TRACE( "(%p)\n", This );
+    TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
 
     assert(This->dsound);
 
     EnterCriticalSection( &(This->dsound->lock) );
 
-    TRACE( "(%p) was 0x%08lx\n", This, This->ref );
     uRef = --(This->ref);
 
     LeaveCriticalSection( &(This->dsound->lock) );
@@ -890,10 +1004,13 @@ IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
         if (This->notify)
 	    IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
         
+	if (This->notifies != NULL)
+		HeapFree(GetProcessHeap(), 0, This->notifies);
+
         HeapFree( GetProcessHeap(), 0, This );
+	TRACE("(%p) released\n",This);
     }
 
-    TRACE( "returning 0x%08lx\n", uRef );
     return uRef;
 }
 
@@ -1205,10 +1322,10 @@ IDirectSoundCaptureBufferImpl_Start(
         IDirectSoundCaptureImpl* ipDSC = This->dsound;
 
         if (ipDSC->buffer) {
-            if (This->notify && This->notify->nrofnotifies) {
+            if (This->nrofnotifies) {
             	unsigned c;
 
-		ipDSC->nrofpwaves = This->notify->nrofnotifies;
+		ipDSC->nrofpwaves = This->nrofnotifies;
 
                 /* prepare headers */
                 ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,
@@ -1218,13 +1335,13 @@ IDirectSoundCaptureBufferImpl_Start(
                     if (c == 0) {
                         ipDSC->pwave[0].lpData = ipDSC->buffer;
                         ipDSC->pwave[0].dwBufferLength = 
-                            This->notify->notifies[0].dwOffset + 1;
+                            This->notifies[0].dwOffset + 1;
                     } else {
                         ipDSC->pwave[c].lpData = ipDSC->buffer + 
-                            This->notify->notifies[c-1].dwOffset + 1;
+                            This->notifies[c-1].dwOffset + 1;
                         ipDSC->pwave[c].dwBufferLength = 
-                            This->notify->notifies[c].dwOffset - 
-                            This->notify->notifies[c-1].dwOffset;
+                            This->notifies[c].dwOffset - 
+                            This->notifies[c-1].dwOffset;
                     }
                     ipDSC->pwave[c].dwUser = (DWORD)ipDSC;
                     ipDSC->pwave[c].dwFlags = 0;
@@ -1604,10 +1721,10 @@ IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
 {
     ULONG uRef;
     ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
 
     EnterCriticalSection( &(This->lock) );
 
-    TRACE( "(%p) was 0x%08lx\n", This, This->ref );
     uRef = ++(This->ref);
 
     LeaveCriticalSection( &(This->lock) );
@@ -1620,18 +1737,18 @@ IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
 {
     ULONG uRef;
     ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
 
     EnterCriticalSection( &(This->lock) );
 
-    TRACE( "(%p) was 0x%08lx\n", This, This->ref );
     uRef = --(This->ref);
 
     LeaveCriticalSection( &(This->lock) );
 
     if ( uRef == 0 ) {
-        TRACE("deleting object\n");
         DeleteCriticalSection( &(This->lock) );
         HeapFree( GetProcessHeap(), 0, This );
+	TRACE("(%p) released\n",This);
     }
 
     return uRef;
diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c
index 204745469a8dbf3d6c823467d676a6312c0091ba..bd926c9cf9fdd833b88ef7ababa0295d36d43450 100644
--- a/dlls/dsound/dsound_main.c
+++ b/dlls/dsound/dsound_main.c
@@ -529,39 +529,52 @@ static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
 		   wfex->wBitsPerSample, wfex->cbSize);
 
 	if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
-		*ppdsb=(LPDIRECTSOUNDBUFFER8)This->primary;
-		if (*ppdsb==NULL)
-			WARN("PrimaryBuffer_Create failed\n");
-		else {
+		if (This->primary) {
+			WARN("Primary Buffer already created\n");
+			IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
+			*ppdsb = (LPDIRECTSOUNDBUFFER8)(This->primary);
+		} else {
 			This->dsbd = *dsbd;
-			IDirectSoundBuffer_AddRef(*ppdsb);
+			hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
+			if (This->primary) {
+				IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
+				*ppdsb = (LPDIRECTSOUNDBUFFER8)(This->primary);
+			} else 
+				WARN("PrimaryBufferImpl_Create failed\n");
 		}
 	} else {
-		hres = SecondaryBuffer_Create(This, (IDirectSoundBufferImpl**)ppdsb, dsbd);
-		if (hres != DS_OK)
-			WARN("SecondaryBuffer_Create failed\n");
-		else 
-			IDirectSoundBuffer_AddRef(*ppdsb);
+		IDirectSoundBufferImpl * dsb;
+		hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
+		if (dsb) {
+			hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
+			if (*ppdsb) {
+				dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
+				IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
+			} else
+				WARN("SecondaryBufferImpl_Create failed\n");
+		} else 
+			WARN("IDirectSoundBufferImpl_Create failed\n");
 	}
 
 	return hres;
 }
 
 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
-	LPDIRECTSOUND8 iface,LPDIRECTSOUNDBUFFER8 pdsb,LPLPDIRECTSOUNDBUFFER8 ppdsb
+	LPDIRECTSOUND8 iface,LPDIRECTSOUNDBUFFER8 psb,LPLPDIRECTSOUNDBUFFER8 ppdsb
 ) {
 	ICOM_THIS(IDirectSoundImpl,iface);
-	IDirectSoundBufferImpl* ipdsb=(IDirectSoundBufferImpl*)pdsb;
+	IDirectSoundBufferImpl* pdsb;
 	IDirectSoundBufferImpl* dsb;
-	TRACE("(%p,%p,%p)\n",This,pdsb,ppdsb);
+	HRESULT hres = DS_OK;
+	TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
 
 	if (This == NULL) {
 		WARN("invalid parameter: This == NULL\n");
 		return DSERR_INVALIDPARAM;
 	}
 
-	if (pdsb == NULL) {
-		WARN("invalid parameter: pdsb == NULL\n");
+	if (psb == NULL) {
+		WARN("invalid parameter: psb == NULL\n");
 		return DSERR_INVALIDPARAM;
 	}
 
@@ -570,13 +583,16 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
 		return DSERR_INVALIDPARAM;
 	}
 
-	if (ipdsb->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) {
+	/* FIXME: hack to make sure we have a secondary buffer */
+	if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
 		ERR("trying to duplicate primary buffer\n");
 		*ppdsb = NULL;
 		return DSERR_INVALIDCALL;
 	}
 
-	if (ipdsb->hwbuf) {
+	pdsb = ((SecondaryBufferImpl *)psb)->dsb;
+
+	if (pdsb->hwbuf) {
 		FIXME("need to duplicate hardware buffer\n");
 		*ppdsb = NULL;
 		return DSERR_INVALIDCALL;
@@ -590,8 +606,8 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
 		return DSERR_OUTOFMEMORY;
 	}
 
-	memcpy(dsb, ipdsb, sizeof(IDirectSoundBufferImpl));
-	dsb->ref = 1;
+	memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
+	dsb->ref = 0;
 	dsb->state = STATE_STOPPED;
 	dsb->playpos = 0;
 	dsb->buf_mixpos = 0;
@@ -600,7 +616,8 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
 	dsb->hwbuf = NULL;
 	dsb->ds3db = NULL;
 	dsb->iks = NULL; /* FIXME? */
-	memcpy(&(dsb->wfx), &(ipdsb->wfx), sizeof(dsb->wfx));
+	dsb->dsb = NULL;
+	memcpy(&(dsb->wfx), &(pdsb->wfx), sizeof(dsb->wfx));
 	InitializeCriticalSection(&(dsb->lock));
 	/* register buffer */
 	RtlAcquireResourceExclusive(&(This->lock), TRUE);
@@ -613,7 +630,7 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
 			TRACE("buffer count is now %d\n", This->nrofbuffers);
 		} else {
 			ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers);
-			IDirectSoundBuffer8_Release(pdsb);
+			IDirectSoundBuffer8_Release(psb);
 			DeleteCriticalSection(&(dsb->lock));
 			RtlReleaseResource(&(This->lock));
 			HeapFree(GetProcessHeap(),0,dsb);
@@ -623,10 +640,15 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
 	}
 	RtlReleaseResource(&(This->lock));
 	IDirectSound_AddRef(iface);
-	*ppdsb = (LPDIRECTSOUNDBUFFER8)dsb;
-	return DS_OK;
-}
+	hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
+	if (*ppdsb) {
+		dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
+		IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
+	} else
+		WARN("SecondaryBufferImpl_Create failed\n");
 
+	return hres;
+}
 
 static HRESULT WINAPI IDirectSoundImpl_GetCaps(LPDIRECTSOUND8 iface,LPDSCAPS lpDSCaps) {
 	ICOM_THIS(IDirectSoundImpl,iface);
@@ -699,7 +721,6 @@ static ULONG WINAPI IDirectSoundImpl_Release(LPDIRECTSOUND8 iface) {
 
 	TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
 	ulReturn = InterlockedDecrement(&This->ref);
-
 	if (ulReturn == 0) {
 		HRESULT hres;
 		UINT i;
@@ -718,8 +739,10 @@ static ULONG WINAPI IDirectSoundImpl_Release(LPDIRECTSOUND8 iface) {
 
 		RtlReleaseResource(&(This->lock));
 
-		if (This->primary)
+		if (This->primary) {
+			WARN("primary buffer not released\n");
 			IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
+		}
 
 		hres = DSOUND_PrimaryDestroy(This);
 		if (hres != DS_OK)
@@ -739,8 +762,9 @@ static ULONG WINAPI IDirectSoundImpl_Release(LPDIRECTSOUND8 iface) {
 		DeleteCriticalSection(&This->ds3dl_lock);
 		HeapFree(GetProcessHeap(),0,This);
 		dsound = NULL;
-		return 0;
+		TRACE("(%p) released\n",This);
 	}
+
 	return ulReturn;
 }
 
@@ -748,7 +772,11 @@ static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
 	LPDIRECTSOUND8 iface,DWORD config
 ) {
 	ICOM_THIS(IDirectSoundImpl,iface);
-	FIXME("(%p,0x%08lx):stub\n",This,config);
+	TRACE("(%p,0x%08lx)\n",This,config);
+
+	This->speaker_config = config;
+
+	WARN("not fully functional\n");
 	return DS_OK;
 }
 
@@ -796,7 +824,16 @@ static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
 {
 	ICOM_THIS(IDirectSoundImpl,iface);
 	TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-	*lpdwSpeakerConfig = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
+
+	if (lpdwSpeakerConfig == NULL) {
+		WARN("invalid parameter\n");
+		return DSERR_INVALIDPARAM;
+	}
+
+	WARN("not fully functional\n");
+
+	*lpdwSpeakerConfig = This->speaker_config;
+
 	return DS_OK;
 }
 
@@ -883,6 +920,7 @@ HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown
 
 	if (dsound) {
 		if (IsEqualGUID(&devGuid, &dsound->guid) ) {
+			/* FIXME: this is wrong, need to create a new instance */
 			ERR("dsound already opened\n");
 			IDirectSound_AddRef((LPDIRECTSOUND)dsound);
 			*ippDS = dsound;
@@ -957,6 +995,7 @@ HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown
 	(*ippDS)->nrofbuffers	= 0;
 	(*ippDS)->buffers	= NULL;
 	(*ippDS)->primary	= NULL;
+	(*ippDS)->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
 	
 	/* 3D listener initial parameters */
 	(*ippDS)->listener	= NULL;
@@ -1115,15 +1154,7 @@ HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown
 					       (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
 	}
 
-	/* create a user accessable primary buffer */
-	(*ippDS)->dsbd.dwSize = sizeof((*ippDS)->dsbd);
-	err = PrimaryBuffer_Create((*ippDS), (PrimaryBufferImpl**)&((*ippDS)->primary), &((*ippDS)->dsbd));
-	if ((*ippDS)->primary)
-		IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(*ippDS)->primary);
-	else 
-		WARN("PrimaryBuffer_Create failed\n");
-
-	return err;
+	return DS_OK;
 }
 
 
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index f1fe3b9e52c1434b1e8dbb61318a2a099ecbe13a..f66cb4b3a2462c42d1058b775feaf13f64529384 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -50,11 +50,13 @@ typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl;
 typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl;
 typedef struct IDirectSoundFullDuplexImpl IDirectSoundFullDuplexImpl;
 typedef struct IDirectSoundNotifyImpl IDirectSoundNotifyImpl;
+typedef struct IDirectSoundCaptureNotifyImpl IDirectSoundCaptureNotifyImpl;
 typedef struct IDirectSound3DListenerImpl IDirectSound3DListenerImpl;
 typedef struct IDirectSound3DBufferImpl IDirectSound3DBufferImpl;
 typedef struct IKsBufferPropertySetImpl IKsBufferPropertySetImpl;
 typedef struct IKsPrivatePropertySetImpl IKsPrivatePropertySetImpl;
 typedef struct PrimaryBufferImpl PrimaryBufferImpl;
+typedef struct SecondaryBufferImpl SecondaryBufferImpl;
 typedef struct IClassFactoryImpl IClassFactoryImpl;
 
 /*****************************************************************************
@@ -87,6 +89,7 @@ struct IDirectSoundImpl
     DSVOLUMEPAN                 volpan;
     PrimaryBufferImpl*          primary;
     DSBUFFERDESC                dsbd;
+    DWORD                       speaker_config;
 
     /* DirectSound3DListener fields */
     IDirectSound3DListenerImpl*	listener;
@@ -112,9 +115,8 @@ struct IDirectSoundBufferImpl
     ICOM_VFIELD(IDirectSoundBuffer8);
     DWORD                       ref;
     /* IDirectSoundBufferImpl fields */
+    SecondaryBufferImpl*        dsb;
     IDirectSoundImpl*           dsound;
-    IDirectSound3DBufferImpl*   ds3db;
-    IKsBufferPropertySetImpl*   iks;
     CRITICAL_SECTION            lock;
     PIDSDRIVERBUFFER            hwbuf;
     WAVEFORMATEX                wfx;
@@ -131,30 +133,56 @@ struct IDirectSoundBufferImpl
     DWORD                       probably_valid_to, last_playpos;
     DWORD                       primary_mixpos, buf_mixpos;
     BOOL                        need_remix;
+
     /* IDirectSoundNotifyImpl fields */
     IDirectSoundNotifyImpl*     notify;
+    LPDSBPOSITIONNOTIFY         notifies;
+    int                         nrofnotifies;
+    PIDSDRIVERNOTIFY            hwnotify;
 
     /* DirectSound3DBuffer fields */
+    IDirectSound3DBufferImpl*   ds3db;
     DS3DBUFFER                  ds3db_ds3db;
     LONG                        ds3db_lVolume;
     BOOL                        ds3db_need_recalc;
+
+    /* IKsPropertySet fields */
+    IKsBufferPropertySetImpl*   iks;
 };
 
-HRESULT WINAPI SecondaryBuffer_Create(
-	IDirectSoundImpl *This,
-	IDirectSoundBufferImpl **pdsb,
-	LPDSBUFFERDESC dsbd);
+HRESULT WINAPI IDirectSoundBufferImpl_Create(
+    IDirectSoundImpl *ds,
+    IDirectSoundBufferImpl **pdsb,
+    LPDSBUFFERDESC dsbd);
 
-struct PrimaryBufferImpl {
+/*****************************************************************************
+ * SecondaryBuffer implementation structure
+ */
+struct SecondaryBufferImpl
+{
+    ICOM_VFIELD(IDirectSoundBuffer8);
+    DWORD                       ref;
+    IDirectSoundBufferImpl*     dsb;
+};
+
+HRESULT WINAPI SecondaryBufferImpl_Create(
+    IDirectSoundBufferImpl *dsb,
+    SecondaryBufferImpl **pdsb);
+
+/*****************************************************************************
+ * PrimaryBuffer implementation structure
+ */
+struct PrimaryBufferImpl
+{
     ICOM_VFIELD(IDirectSoundBuffer8);
     DWORD                       ref;
     IDirectSoundImpl*           dsound;
 };
 
-HRESULT WINAPI PrimaryBuffer_Create(
-	IDirectSoundImpl *This,
-	PrimaryBufferImpl **pdsb,
-	LPDSBUFFERDESC dsbd);
+HRESULT WINAPI PrimaryBufferImpl_Create(
+    IDirectSoundImpl *ds,
+    PrimaryBufferImpl **pdsb,
+    LPDSBUFFERDESC dsbd);
 
 /*****************************************************************************
  * IDirectSoundCapture implementation structure
@@ -208,8 +236,12 @@ struct IDirectSoundCaptureBufferImpl
     /* FIXME: don't need this */
     LPDSCBUFFERDESC                     pdscbd;
     DWORD                               flags;
-    /* IDirectSoundNotifyImpl fields */
-    IDirectSoundNotifyImpl*             notify;
+
+    /* IDirectSoundCaptureNotifyImpl fields */
+    IDirectSoundCaptureNotifyImpl*      notify;
+    LPDSBPOSITIONNOTIFY                 notifies;
+    int                                 nrofnotifies;
+    PIDSDRIVERNOTIFY                    hwnotify;
 };
 
 /*****************************************************************************
@@ -233,13 +265,28 @@ struct IDirectSoundNotifyImpl
     /* IUnknown fields */
     ICOM_VFIELD(IDirectSoundNotify);
     DWORD                       ref;
-    /* IDirectSoundNotifyImpl fields */
-    LPDSBPOSITIONNOTIFY         notifies;
-    int                         nrofnotifies;
+    IDirectSoundBufferImpl*     dsb;
+};
 
-    PIDSDRIVERNOTIFY            hwnotify;
+HRESULT WINAPI IDirectSoundNotifyImpl_Create(
+    IDirectSoundBufferImpl *dsb,
+    IDirectSoundNotifyImpl **pdsn);
+
+/*****************************************************************************
+ * IDirectSoundCaptureNotify implementation structure
+ */
+struct IDirectSoundCaptureNotifyImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSoundNotify);
+    DWORD                               ref;
+    IDirectSoundCaptureBufferImpl*      dscb;
 };
 
+HRESULT WINAPI IDirectSoundCaptureNotifyImpl_Create(
+    IDirectSoundCaptureBufferImpl *dscb,
+    IDirectSoundCaptureNotifyImpl ** pdscn);
+
 /*****************************************************************************
  *  IDirectSound3DListener implementation structure
  */
@@ -253,8 +300,8 @@ struct IDirectSound3DListenerImpl
 };
 
 HRESULT WINAPI IDirectSound3DListenerImpl_Create(
-	PrimaryBufferImpl *This,
-	IDirectSound3DListenerImpl **pdsl);
+    PrimaryBufferImpl *pb,
+    IDirectSound3DListenerImpl **pdsl);
 
 /*****************************************************************************
  *  IKsBufferPropertySet implementation structure
@@ -269,8 +316,8 @@ struct IKsBufferPropertySetImpl
 };
 
 HRESULT WINAPI IKsBufferPropertySetImpl_Create(
-	IDirectSoundBufferImpl *This,
-	IKsBufferPropertySetImpl **piks);
+    IDirectSoundBufferImpl *dsb,
+    IKsBufferPropertySetImpl **piks);
 
 /*****************************************************************************
  *  IKsPrivatePropertySet implementation structure
@@ -283,7 +330,7 @@ struct IKsPrivatePropertySetImpl
 };
 
 HRESULT WINAPI IKsPrivatePropertySetImpl_Create(
-	IKsPrivatePropertySetImpl **piks);
+    IKsPrivatePropertySetImpl **piks);
 
 /*****************************************************************************
  * IDirectSound3DBuffer implementation structure
@@ -299,8 +346,8 @@ struct IDirectSound3DBufferImpl
 };
 
 HRESULT WINAPI IDirectSound3DBufferImpl_Create(
-	IDirectSoundBufferImpl *This,
-	IDirectSound3DBufferImpl **pds3db);
+    IDirectSoundBufferImpl *dsb,
+    IDirectSound3DBufferImpl **pds3db);
 
 /*******************************************************************************
  * DirectSound ClassFactory implementation structure
@@ -356,6 +403,5 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb);
 extern IDirectSoundImpl* dsound;
 extern IDirectSoundCaptureImpl* dsound_capture;
 
-extern ICOM_VTABLE(IDirectSoundNotify) dsnvt;
 extern HRESULT mmErr(UINT err);
 extern void setup_dsound_options(void);
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index cf927e12b815faf5c4a0c7b16d4a722f7f068ed3..64191c3f4d5f33b75c07aeab5f8f080a25fc5957 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -68,6 +68,7 @@ void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan)
 void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
 {
 	DWORD sw;
+	TRACE("(%p)\n",dsb);
 
 	sw = dsb->wfx.nChannels * (dsb->wfx.wBitsPerSample / 8);
 	/* calculate the 10ms write lead */
@@ -79,14 +80,15 @@ void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len)
 	int			i;
 	DWORD			offset;
 	LPDSBPOSITIONNOTIFY	event;
+	TRACE("(%p,%d)\n",dsb,len);
 
-	if (!dsb->notify || dsb->notify->nrofnotifies == 0)
+	if (dsb->nrofnotifies == 0)
 		return;
 
 	TRACE("(%p) buflen = %ld, playpos = %ld, len = %d\n",
 		dsb, dsb->buflen, dsb->playpos, len);
-	for (i = 0; i < dsb->notify->nrofnotifies ; i++) {
-		event = dsb->notify->notifies + i;
+	for (i = 0; i < dsb->nrofnotifies ; i++) {
+		event = dsb->notifies + i;
 		offset = event->dwOffset;
 		TRACE("checking %d, position %ld, event = %p\n",
 			i, offset, event->hEventNotify);
@@ -354,7 +356,7 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
 	BYTE	*buf, *ibuf, *obuf;
 	INT16	*ibufs, *obufs;
 
-	TRACE("%p,%ld,%ld)\n",dsb,writepos,fraglen);
+	TRACE("(%p,%ld,%ld)\n",dsb,writepos,fraglen);
 
 	len = fraglen;
 	if (!(dsb->playflags & DSBPLAY_LOOPING)) {
@@ -440,6 +442,7 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR
 	INT     advance = dsb->dsound->wfx.wBitsPerSample >> 3;
 	BYTE	*buf, *ibuf, *obuf;
 	INT16	*ibufs, *obufs;
+	TRACE("(%p,%ld,%ld)\n",dsb,writepos,len);
 
 	nBlockAlign = dsb->dsound->wfx.nBlockAlign;
 	len = len / nBlockAlign * nBlockAlign;  /* data alignment */
@@ -552,6 +555,7 @@ void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos)
 
 void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb)
 {
+	TRACE("(%p)\n",dsb);
 	EnterCriticalSection(&dsb->lock);
 	if (dsb->state == STATE_PLAYING) {
 #if 0 /* this may not be quite reliable yet */
@@ -585,6 +589,7 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD playpos, DWORD wri
 	DWORD buf_left = dsb->buflen - buf_writepos;
 	int still_behind;
 
+	TRACE("(%p,%ld,%ld,%ld)\n",dsb,playpos,writepos,mixlen);
 	TRACE("buf_writepos=%ld, primary_writepos=%ld\n", buf_writepos, writepos);
 	TRACE("buf_done=%ld, primary_done=%ld\n", buf_done, primary_done);
 	TRACE("buf_mixpos=%ld, primary_mixpos=%ld, mixlen=%ld\n", dsb->buf_mixpos, dsb->primary_mixpos,
@@ -724,7 +729,7 @@ static DWORD DSOUND_MixToPrimary(DWORD playpos, DWORD writepos, DWORD mixlen, BO
 	INT			i, len, maxlen = 0;
 	IDirectSoundBufferImpl	*dsb;
 
-	TRACE("(%ld,%ld,%ld)\n", playpos, writepos, mixlen);
+	TRACE("(%ld,%ld,%ld,%d)\n", playpos, writepos, mixlen, recover);
 	for (i = dsound->nrofbuffers - 1; i >= 0; i--) {
 		dsb = dsound->buffers[i];
 
@@ -808,6 +813,7 @@ static void DSOUND_MixReset(DWORD writepos)
 
 static void DSOUND_CheckReset(IDirectSoundImpl *dsound, DWORD writepos)
 {
+	TRACE("(%p,%ld)\n",dsound,writepos);
 	if (dsound->need_remix) {
 		DSOUND_MixReset(writepos);
 		dsound->need_remix = FALSE;
@@ -827,6 +833,7 @@ static void DSOUND_CheckReset(IDirectSoundImpl *dsound, DWORD writepos)
 
 void DSOUND_WaveQueue(IDirectSoundImpl *dsound, DWORD mixq)
 {
+	TRACE("(%p,%ld)\n",dsound,mixq);
 	if (mixq + dsound->pwqueue > ds_hel_queue) mixq = ds_hel_queue - dsound->pwqueue;
 	TRACE("queueing %ld buffers, starting at %d\n", mixq, dsound->pwwrite);
 	for (; mixq; mixq--) {
@@ -1034,6 +1041,7 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWOR
 void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
 {
         IDirectSoundImpl* This = (IDirectSoundImpl*)dwUser;
+	TRACE("(%p,%x,%lx,%lx,%lx)\n",hwo,msg,dwUser,dw1,dw2);
 	TRACE("entering at %ld, msg=%08x(%s)\n", GetTickCount(), msg, 
 		msg==MM_WOM_DONE ? "MM_WOM_DONE" : msg==MM_WOM_CLOSE ? "MM_WOM_CLOSE" : 
 		msg==MM_WOM_OPEN ? "MM_WOM_OPEN" : "UNKNOWN");
diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c
index ef394c6fd75d6873e086f91d311f438f11f589e6..4abf248d4a5bb68307d92107e857cc1e06ea0450 100644
--- a/dlls/dsound/primary.c
+++ b/dlls/dsound/primary.c
@@ -303,7 +303,7 @@ HRESULT DSOUND_PrimaryGetPosition(IDirectSoundImpl *This, LPDWORD playpos, LPDWO
 
 
 /*******************************************************************************
- *		IDirectSoundBuffer
+ *		PrimaryBuffer
  */
 /* This sets this format for the <em>Primary Buffer Only</em> */
 /* See file:///cdrom/sdk52/docs/worddoc/dsound.doc page 120 */
@@ -573,9 +573,11 @@ static DWORD WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) {
 	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
 	ref = InterlockedDecrement(&(This->ref));
 
-	if (ref == -1) {
+	if (ref == 0) {
 		This->dsound->primary = NULL;
+		IDirectSound_Release((LPDIRECTSOUND)This->dsound);
 		HeapFree(GetProcessHeap(),0,This);
+		TRACE("(%p) released\n",This);
 	}
 
 	return ref;
@@ -942,16 +944,12 @@ static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(
 	}
 
         if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
-		if (This->dsound->dsbd.dwFlags & DSBCAPS_CTRL3D) {
-			if (!This->dsound->listener)
-				IDirectSound3DListenerImpl_Create(This, &This->dsound->listener);
-	
+		if (!This->dsound->listener)
+			IDirectSound3DListenerImpl_Create(This, &This->dsound->listener);
+		if (This->dsound->listener) {
 			*ppobj = This->dsound->listener;
-	
-			if (This->dsound->listener) {
-				IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)*ppobj);
-				return S_OK;
-			}
+			IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)*ppobj);
+			return S_OK;
 		}
 
 		WARN("IID_IDirectSound3DListener failed\n");
@@ -996,14 +994,14 @@ static ICOM_VTABLE(IDirectSoundBuffer8) dspbvt =
 	PrimaryBufferImpl_GetObjectInPath
 };
 
-HRESULT WINAPI PrimaryBuffer_Create(
-	IDirectSoundImpl *This,
+HRESULT WINAPI PrimaryBufferImpl_Create(
+	IDirectSoundImpl *ds,
 	PrimaryBufferImpl **pdsb,
 	LPDSBUFFERDESC dsbd)
 {
 	PrimaryBufferImpl *dsb;
 
-	TRACE("%p,%p,%p)\n",This,pdsb,dsbd);
+	TRACE("%p,%p,%p)\n",ds,pdsb,dsbd);
 
 	if (dsbd->lpwfxFormat) {
 		WARN("invalid parameter: dsbd->lpwfxFormat != NULL\n");
@@ -1019,19 +1017,20 @@ HRESULT WINAPI PrimaryBuffer_Create(
 		return DSERR_OUTOFMEMORY;
 	}
 
-	dsb->ref = -1;
-	dsb->dsound = This;
+	dsb->ref = 0;
+	dsb->dsound = ds;
 	dsb->lpVtbl = &dspbvt;
 
-	memcpy(&This->dsbd, dsbd, sizeof(*dsbd));
+	memcpy(&ds->dsbd, dsbd, sizeof(*dsbd));
 
 	TRACE("Created primary buffer at %p\n", dsb);
 	TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
 		"bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
-		This->wfx.wFormatTag, This->wfx.nChannels, This->wfx.nSamplesPerSec,
-		This->wfx.nAvgBytesPerSec, This->wfx.nBlockAlign,
-		This->wfx.wBitsPerSample, This->wfx.cbSize);
+		ds->wfx.wFormatTag, ds->wfx.nChannels, ds->wfx.nSamplesPerSec,
+		ds->wfx.nAvgBytesPerSec, ds->wfx.nBlockAlign,
+		ds->wfx.wBitsPerSample, ds->wfx.cbSize);
 
+	IDirectSound_AddRef((LPDIRECTSOUND)ds);
 	*pdsb = dsb;
 	return S_OK;
 }
diff --git a/dlls/dsound/propset.c b/dlls/dsound/propset.c
index 55ec34852d6a317aa55f78bf73572b92d7938e14..30adad224c868119ff048542db0a68d8f96e73ce 100644
--- a/dlls/dsound/propset.c
+++ b/dlls/dsound/propset.c
@@ -72,9 +72,7 @@ static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface)
     ULONG ulReturn;
 
     TRACE("(%p) ref was %ld\n", This, This->ref);
-    ulReturn = InterlockedIncrement(&This->ref);
-    if (ulReturn == 1)
-	IDirectSoundBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->dsb);
+    ulReturn = InterlockedIncrement(&(This->ref));
     return ulReturn;
 }
 
@@ -85,10 +83,13 @@ static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
 
     TRACE("(%p) ref was %ld\n", This, This->ref);
     ulReturn = InterlockedDecrement(&This->ref);
-    if (ulReturn)
-	return ulReturn;
-    IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
-    return 0;
+    if (!ulReturn) {
+	This->dsb->iks = 0;
+	IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
+	HeapFree(GetProcessHeap(),0,This);
+	TRACE("(%p) released\n",This);
+    }
+    return ulReturn;
 }
 
 static HRESULT WINAPI IKsBufferPropertySetImpl_Get(
@@ -146,16 +147,19 @@ static ICOM_VTABLE(IKsPropertySet) iksbvt = {
 };
 
 HRESULT WINAPI IKsBufferPropertySetImpl_Create(
-    IDirectSoundBufferImpl *This,
+    IDirectSoundBufferImpl *dsb,
     IKsBufferPropertySetImpl **piks)
 {
     IKsBufferPropertySetImpl *iks;
 
     iks = (IKsBufferPropertySetImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
     iks->ref = 0;
-    iks->dsb = This;
+    iks->dsb = dsb;
+    dsb->iks = iks;
     iks->lpVtbl = &iksbvt;
 
+    IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
+
     *piks = iks;
     return S_OK;
 }
diff --git a/dlls/dsound/sound3d.c b/dlls/dsound/sound3d.c
index 9b3660150f6d48f7501a3d739c7c15874311e3e9..2105bcf9e817e026a84fdb98b5a824d61171627d 100644
--- a/dlls/dsound/sound3d.c
+++ b/dlls/dsound/sound3d.c
@@ -395,10 +395,11 @@ static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface
 	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
 	ulReturn = InterlockedDecrement(&This->ref);
 	if (!ulReturn) {
-		IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This);
 		This->dsb->ds3db = NULL;
+		IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
 		DeleteCriticalSection(&(This->lock));
 		HeapFree(GetProcessHeap(),0,This);
+		TRACE("(%p) released\n",This);
 	}
 
 	return ulReturn;
@@ -766,11 +767,11 @@ static ICOM_VTABLE(IDirectSound3DBuffer) ds3dbvt =
 };
 
 HRESULT WINAPI IDirectSound3DBufferImpl_Create(
-	IDirectSoundBufferImpl *This,
+	IDirectSoundBufferImpl *dsb,
 	IDirectSound3DBufferImpl **pds3db)
 {
 	IDirectSound3DBufferImpl *ds3db;
-	TRACE("(%p,%p)\n",This,pds3db);
+	TRACE("(%p,%p)\n",dsb,pds3db);
 
 	ds3db = (IDirectSound3DBufferImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*ds3db));
 
@@ -781,7 +782,7 @@ HRESULT WINAPI IDirectSound3DBufferImpl_Create(
 	}
 
 	ds3db->ref = 0;
-	ds3db->dsb = This;
+	ds3db->dsb = dsb;
 	ds3db->lpVtbl = &ds3dbvt;
 
 	ds3db->dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
@@ -805,6 +806,8 @@ HRESULT WINAPI IDirectSound3DBufferImpl_Create(
 
 	InitializeCriticalSection(&(ds3db->lock));
 
+	IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
+
 	*pds3db = ds3db;
 	return S_OK;
 }
@@ -836,9 +839,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(
 	}
 
 	if ( IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
-		*ppobj = This->dsound->primary;
-		IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppobj);
-		return S_OK;
+		if (!This->dsound->primary)
+			PrimaryBufferImpl_Create(This->dsound, &(This->dsound->primary), &(This->dsound->dsbd));
+		if (This->dsound->primary) {
+			*ppobj = This->dsound->primary;
+			IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppobj);
+			return S_OK;
+		}
 	}
 
         FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
@@ -873,6 +880,7 @@ static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER i
 		IDirectSound8_Release((LPDIRECTSOUND8)This->dsound);
 		This->dsound->listener = 0;
 		HeapFree(GetProcessHeap(),0,This);
+		TRACE("(%p) released\n",This);
 	}
 
 	return ulReturn;