dsound reference cound patch

Robert Reif reif at earthlink.net
Mon Jul 12 22:29:07 CDT 2004


Direct Sound allows a DirectSound object to be deleted by calling
Release even when active buffers still exist and are playing.  Wine
doesn't allow this because buffers hold a reference counted pointer
to the DirectSound object.  This is different than the way windows
does it.

This patch removes DirectSound reference counts by buffers and
adds Destroy functions to buffer components and DirectSound to
allow proper destruction even with outstanding references.
Removes trailing white space.
Adds tests for proper release even with active buffers.
-------------- next part --------------
Index: dlls/dsound/buffer.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/buffer.c,v
retrieving revision 1.24
diff -u -r1.24 buffer.c
--- dlls/dsound/buffer.c	6 Jul 2004 19:27:00 -0000	1.24
+++ dlls/dsound/buffer.c	13 Jul 2004 03:13:08 -0000
@@ -121,11 +121,11 @@
         } else if (howmuch > 0) {
 	    /* Make an internal copy of the caller-supplied array.
 	     * Replace the existing copy if one is already present. */
-	    if (This->dsb->notifies) 
-		    This->dsb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+	    if (This->dsb->notifies)
+		    This->dsb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
 			This->dsb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
 	    else
-		    This->dsb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+		    This->dsb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
 			howmuch * sizeof(DSBPOSITIONNOTIFY));
 
 	    if (This->dsb->notifies == NULL) {
@@ -160,9 +160,9 @@
 {
     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;
@@ -173,11 +173,21 @@
     dsn->dsb = dsb;
     dsb->notify = dsn;
     IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
-                                                                                                                                
+
     *pdsn = dsn;
     return DS_OK;
 }
-                                                                                                                                
+
+HRESULT WINAPI IDirectSoundNotifyImpl_Destroy(
+    IDirectSoundNotifyImpl *pdsn)
+{
+    TRACE("(%p)\n",pdsn);
+
+    while (IDirectSoundNotifyImpl_Release((LPDIRECTSOUNDNOTIFY)pdsn) > 0);
+
+    return DS_OK;
+}
+
 /*******************************************************************************
  *		IDirectSoundBuffer
  */
@@ -220,7 +230,7 @@
 	} else {
 		oldVol = This->volpan.lVolume;
 		This->volpan.lVolume = vol;
-		if (vol != oldVol) 
+		if (vol != oldVol)
 			DSOUND_RecalcVolPan(&(This->volpan));
 	}
 
@@ -230,7 +240,7 @@
 			hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
 	    		if (hres != DS_OK)
 		    		WARN("IDsDriverBuffer_SetVolumePan failed\n");
-		} else 
+		} else
 			DSOUND_ForceRemix(This);
 	}
 
@@ -291,7 +301,7 @@
 		This->freqAdjust = (freq << DSOUND_FREQSHIFT) / This->dsound->wfx.nSamplesPerSec;
 		This->nAvgBytesPerSec = freq * This->wfx.nBlockAlign;
 		DSOUND_RecalcFormat(This);
-		if (!This->hwbuf) 
+		if (!This->hwbuf)
 			DSOUND_ForceRemix(This);
 	}
 
@@ -393,7 +403,6 @@
 		This->dsound->nrofbuffers--;
 		This->dsound->buffers = HeapReAlloc(GetProcessHeap(),0,This->dsound->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*This->dsound->nrofbuffers);
 		TRACE("(%p) buffer count is now %d\n", This, This->dsound->nrofbuffers);
-		IDirectSound_Release((LPDIRECTSOUND)This->dsound);
 	}
 	RtlReleaseResource(&(This->dsound->lock));
 
@@ -757,7 +766,7 @@
 			hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
 			if (hres != DS_OK)
 				WARN("IDsDriverBuffer_SetVolumePan failed\n");
-		} else 
+		} else
 			DSOUND_ForceRemix(This);
 	}
 
@@ -941,8 +950,8 @@
 
 	*ppobj = NULL;	/* assume failure */
 
-	if ( IsEqualGUID(riid, &IID_IUnknown) || 
-	     IsEqualGUID(riid, &IID_IDirectSoundBuffer) || 
+	if ( IsEqualGUID(riid, &IID_IUnknown) ||
+	     IsEqualGUID(riid, &IID_IDirectSoundBuffer) ||
 	     IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
 		if (!This->dsb)
 			SecondaryBufferImpl_Create(This, &(This->dsb));
@@ -987,8 +996,8 @@
 
 	if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
 		/* only supported on hardware 3D secondary buffers */
-		if (!(This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) && 
-		     (This->dsbd.dwFlags & DSBCAPS_CTRL3D) && 
+		if (!(This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) &&
+		     (This->dsbd.dwFlags & DSBCAPS_CTRL3D) &&
 		     (This->hwbuf != NULL) ) {
 			if (!This->iks)
 				IKsBufferPropertySetImpl_Create(This, &(This->iks));
@@ -1214,17 +1223,54 @@
 		}
 	}
 	RtlReleaseResource(&(ds->lock));
-	IDirectSound8_AddRef((LPDIRECTSOUND8)ds);
 	*pdsb = dsb;
 	return S_OK;
 }
 
+HRESULT WINAPI IDirectSoundBufferImpl_Destroy(
+    IDirectSoundBufferImpl *pdsb)
+{
+    TRACE("(%p)\n",pdsb);
+
+    /* This keeps the *_Destroy functions from possibly deleting
+     * this object until it is ready to be deleted */
+    IDirectSoundBufferImpl_AddRef((LPDIRECTSOUNDBUFFER8)pdsb);
+
+    if (pdsb->iks) {
+        WARN("iks not NULL\n");
+        IKsBufferPropertySetImpl_Destroy(pdsb->iks);
+        pdsb->iks = NULL;
+    }
+
+    if (pdsb->ds3db) {
+        WARN("ds3db not NULL\n");
+        IDirectSound3DBufferImpl_Destroy(pdsb->ds3db);
+        pdsb->ds3db = NULL;
+    }
+
+    if (pdsb->notify) {
+        WARN("notify not NULL\n");
+        IDirectSoundNotifyImpl_Destroy(pdsb->notify);
+        pdsb->notify = NULL;
+    }
+
+    if (pdsb->dsb) {
+        WARN("dsb not NULL\n");
+        SecondaryBufferImpl_Destroy(pdsb->dsb);
+        pdsb->dsb = NULL;
+    }
+
+    while (IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)pdsb) > 0);
+
+    return S_OK;
+}
+
 /*******************************************************************************
  *		SecondaryBuffer
  */
 
 static HRESULT WINAPI SecondaryBufferImpl_QueryInterface(
-	LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj) 
+	LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj)
 {
 	ICOM_THIS(SecondaryBufferImpl,iface);
 	TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
@@ -1514,4 +1560,14 @@
 	IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
 	*psb = sb;
 	return S_OK;
+}
+
+HRESULT WINAPI SecondaryBufferImpl_Destroy(
+    SecondaryBufferImpl *pdsb)
+{
+    TRACE("(%p)\n",pdsb);
+
+    while (SecondaryBufferImpl_Release((LPDIRECTSOUNDBUFFER8)pdsb) > 0);
+
+    return S_OK;
 }
Index: dlls/dsound/dsound.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/dsound.c,v
retrieving revision 1.4
diff -u -r1.4 dsound.c
--- dlls/dsound/dsound.c	9 Jul 2004 19:25:39 -0000	1.4
+++ dlls/dsound/dsound.c	13 Jul 2004 03:13:10 -0000
@@ -233,7 +233,8 @@
 {
     ICOM_THIS(IDirectSoundImpl,iface);
     ULONG ref;
-    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    TRACE("(%p) ref was %ld, thread is %04lx\n",
+          This, This->ref, GetCurrentThreadId());
 
     ref = InterlockedDecrement(&This->ref);
     if (ref == 0) {
@@ -245,15 +246,19 @@
         /* 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->lock), TRUE);
+        RtlReleaseResource(&(This->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++)
-                IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->buffers[i]);
+                IDirectSoundBufferImpl_Destroy(This->buffers[i]);
         }
 
-        RtlReleaseResource(&(This->lock));
-
         if (This->primary) {
             WARN("primary buffer not released\n");
             IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
@@ -530,7 +535,6 @@
         }
     }
     RtlReleaseResource(&(This->lock));
-    IDirectSound_AddRef(iface);
     hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
     if (*ppdsb) {
         dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
Index: dlls/dsound/dsound_private.h
===================================================================
RCS file: /home/wine/wine/dlls/dsound/dsound_private.h,v
retrieving revision 1.16
diff -u -r1.16 dsound_private.h
--- dlls/dsound/dsound_private.h	4 Jul 2004 00:13:45 -0000	1.16
+++ dlls/dsound/dsound_private.h	13 Jul 2004 03:13:10 -0000
@@ -222,6 +222,8 @@
     IDirectSoundImpl *ds,
     IDirectSoundBufferImpl **pdsb,
     LPCDSBUFFERDESC dsbd);
+HRESULT WINAPI IDirectSoundBufferImpl_Destroy(
+    IDirectSoundBufferImpl *pdsb);
 
 /*****************************************************************************
  * SecondaryBuffer implementation structure
@@ -236,6 +238,8 @@
 HRESULT WINAPI SecondaryBufferImpl_Create(
     IDirectSoundBufferImpl *dsb,
     SecondaryBufferImpl **pdsb);
+HRESULT WINAPI SecondaryBufferImpl_Destroy(
+    SecondaryBufferImpl *pdsb);
 
 /*****************************************************************************
  * PrimaryBuffer implementation structure
@@ -338,6 +342,8 @@
 HRESULT WINAPI IDirectSoundNotifyImpl_Create(
     IDirectSoundBufferImpl *dsb,
     IDirectSoundNotifyImpl **pdsn);
+HRESULT WINAPI IDirectSoundNotifyImpl_Destroy(
+    IDirectSoundNotifyImpl *pdsn);
 
 /*****************************************************************************
  * IDirectSoundCaptureNotify implementation structure
@@ -385,6 +391,8 @@
 HRESULT WINAPI IKsBufferPropertySetImpl_Create(
     IDirectSoundBufferImpl *dsb,
     IKsBufferPropertySetImpl **piks);
+HRESULT WINAPI IKsBufferPropertySetImpl_Destroy(
+    IKsBufferPropertySetImpl *piks);
 
 /*****************************************************************************
  *  IKsPrivatePropertySet implementation structure
@@ -414,6 +422,8 @@
 HRESULT WINAPI IDirectSound3DBufferImpl_Create(
     IDirectSoundBufferImpl *dsb,
     IDirectSound3DBufferImpl **pds3db);
+HRESULT WINAPI IDirectSound3DBufferImpl_Destroy(
+    IDirectSound3DBufferImpl *pds3db);
 
 /*******************************************************************************
  * DirectSound ClassFactory implementation structure
Index: dlls/dsound/primary.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/primary.c,v
retrieving revision 1.24
diff -u -r1.24 primary.c
--- dlls/dsound/primary.c	6 Jul 2004 19:27:00 -0000	1.24
+++ dlls/dsound/primary.c	13 Jul 2004 03:13:11 -0000
@@ -601,7 +601,6 @@
 
 	if (ref == 0) {
 		This->dsound->primary = NULL;
-		IDirectSound_Release((LPDIRECTSOUND)This->dsound);
 		HeapFree(GetProcessHeap(),0,This);
 		TRACE("(%p) released\n",This);
 	}
@@ -1098,7 +1097,6 @@
 		ds->wfx.nAvgBytesPerSec, ds->wfx.nBlockAlign,
 		ds->wfx.wBitsPerSample, ds->wfx.cbSize);
 
-	IDirectSound_AddRef((LPDIRECTSOUND)ds);
 	*pdsb = dsb;
 	return S_OK;
 }
Index: dlls/dsound/propset.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/propset.c,v
retrieving revision 1.16
diff -u -r1.16 propset.c
--- dlls/dsound/propset.c	8 Oct 2003 22:35:26 -0000	1.16
+++ dlls/dsound/propset.c	13 Jul 2004 03:13:11 -0000
@@ -219,6 +219,16 @@
     return S_OK;
 }
 
+HRESULT WINAPI IKsBufferPropertySetImpl_Destroy(
+    IKsBufferPropertySetImpl *piks)
+{
+    TRACE("(%p)\n",piks);
+
+    while (IKsBufferPropertySetImpl_Release((LPKSPROPERTYSET)piks) > 0);
+
+    return S_OK;
+}
+
 /*******************************************************************************
  *              IKsPrivatePropertySet
  */
@@ -258,7 +268,7 @@
 
 static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingA(
     REFGUID guidPropSet,
-    LPVOID pPropData, 
+    LPVOID pPropData,
     ULONG cbPropData,
     PULONG pcbReturned )
 {
@@ -282,7 +292,7 @@
     ppd->DeviceId = GUID_NULL;
 
     if (pcbReturned) {
-	*pcbReturned = cbPropData; 
+	*pcbReturned = cbPropData;
 	FIXME("*pcbReturned=%ld\n", *pcbReturned);
     }
 
@@ -291,7 +301,7 @@
 
 static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingW(
     REFGUID guidPropSet,
-    LPVOID pPropData, 
+    LPVOID pPropData,
     ULONG cbPropData,
     PULONG pcbReturned )
 {
@@ -315,7 +325,7 @@
     ppd->DeviceId = GUID_NULL;
 
     if (pcbReturned) {
-	*pcbReturned = cbPropData; 
+	*pcbReturned = cbPropData;
 	FIXME("*pcbReturned=%ld\n", *pcbReturned);
     }
 
@@ -359,7 +369,7 @@
     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
     GetDeviceID(&ppd->DeviceId, &dev_guid);
 
-    if ( IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultPlayback) || 
+    if ( IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultPlayback) ||
 	 IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultVoicePlayback) ) {
 	ULONG wod;
 	int wodn;
@@ -475,7 +485,7 @@
     }
 
     if (pcbReturned) {
-	*pcbReturned = cbPropData; 
+	*pcbReturned = cbPropData;
 	TRACE("*pcbReturned=%ld\n", *pcbReturned);
     }
 
@@ -686,7 +696,7 @@
     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
     GetDeviceID(&ppd->DeviceId, &dev_guid);
 
-    if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) || 
+    if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
 	 IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
 	ULONG wod;
 	int wodn;
@@ -823,7 +833,7 @@
     }
 
     if (pcbReturned) {
-	*pcbReturned = cbPropData; 
+	*pcbReturned = cbPropData;
 	TRACE("*pcbReturned=%ld\n", *pcbReturned);
     }
 
@@ -906,10 +916,10 @@
     }
 
     if (pcbReturned) {
-	*pcbReturned = 0; 
+	*pcbReturned = 0;
 	FIXME("*pcbReturned=%ld\n", *pcbReturned);
     }
-    
+
     return E_PROP_ID_UNSUPPORTED;
 }
 
@@ -942,7 +952,7 @@
 			    WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
 			    WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
 			    WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
-			    
+
 			    memset(&data, 0, sizeof(data));
 			    data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
 			    data.WaveDeviceId = wod;
@@ -971,7 +981,7 @@
 			    WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
 			    WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
 			    WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
-			    
+
 			    memset(&data, 0, sizeof(data));
 			    data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
 			    data.WaveDeviceId = wid;
@@ -998,10 +1008,10 @@
     }
 
     if (pcbReturned) {
-	*pcbReturned = 0; 
+	*pcbReturned = 0;
 	FIXME("*pcbReturned=%ld\n", *pcbReturned);
     }
-    
+
     return E_PROP_ID_UNSUPPORTED;
 }
 
@@ -1046,7 +1056,7 @@
     }
 
     if (pcbReturned) {
-	*pcbReturned = 0; 
+	*pcbReturned = 0;
 	FIXME("*pcbReturned=%ld\n", *pcbReturned);
     }
 
Index: dlls/dsound/sound3d.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/sound3d.c,v
retrieving revision 1.29
diff -u -r1.29 sound3d.c
--- dlls/dsound/sound3d.c	17 Mar 2004 01:44:15 -0000	1.29
+++ dlls/dsound/sound3d.c	13 Jul 2004 03:13:12 -0000
@@ -207,7 +207,7 @@
 	TRACE("(%p)\n",dsb);
 
 	/* initial buffer volume */
-	lVolume = dsb->ds3db_lVolume; 
+	lVolume = dsb->ds3db_lVolume;
 	
 	switch (dsb->ds3db_ds3db.dwMode)
 	{
@@ -448,8 +448,8 @@
 {
 	ICOM_THIS(IDirectSound3DBufferImpl,iface);
 	TRACE("returning: Cone Orientation vector = (%f,%f,%f)\n",
-		This->dsb->ds3db_ds3db.vConeOrientation.x, 
-		This->dsb->ds3db_ds3db.vConeOrientation.y, 
+		This->dsb->ds3db_ds3db.vConeOrientation.x,
+		This->dsb->ds3db_ds3db.vConeOrientation.y,
 		This->dsb->ds3db_ds3db.vConeOrientation.z);
 	*lpvConeOrientation = This->dsb->ds3db_ds3db.vConeOrientation;
 	return DS_OK;
@@ -770,6 +770,16 @@
 	return S_OK;
 }
 
+HRESULT WINAPI IDirectSound3DBufferImpl_Destroy(
+    IDirectSound3DBufferImpl *pds3db)
+{
+    TRACE("(%p)\n",pds3db);
+
+    while (IDirectSound3DBufferImpl_Release((LPDIRECTSOUND3DBUFFER)pds3db) > 0);
+
+    return S_OK;
+}
+
 /*******************************************************************************
  *	      IDirectSound3DListener
  */
@@ -835,7 +845,6 @@
 
 	/* Free all resources */
 	if( ulReturn == 0 ) {
-		IDirectSound8_Release((LPDIRECTSOUND8)This->dsound);
 		This->dsound->listener = 0;
 		HeapFree(GetProcessHeap(),0,This);
 		TRACE("(%p) released\n",This);
@@ -1133,8 +1142,6 @@
 	dsl->dsound->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
 
 	dsl->dsound->ds3dl_need_recalc = TRUE;
-
-	IDirectSound8_AddRef((LPDIRECTSOUND8)This->dsound);
 
 	*pdsl = dsl;
 	return S_OK;
Index: dlls/dsound/tests/dsound.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/tests/dsound.c,v
retrieving revision 1.23
diff -u -r1.23 dsound.c
--- dlls/dsound/tests/dsound.c	12 Jul 2004 19:45:28 -0000	1.23
+++ dlls/dsound/tests/dsound.c	13 Jul 2004 03:13:13 -0000
@@ -325,6 +325,39 @@
     } else
         return rc;
 
+    /* Create a DirectSound object */
+    rc=DirectSoundCreate(lpGuid,&dso,NULL);
+    ok(rc==DS_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
+    if (rc==DS_OK) {
+        LPDIRECTSOUNDBUFFER secondary;
+        DSBUFFERDESC bufdesc;
+        WAVEFORMATEX wfx;
+
+        init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
+        ZeroMemory(&bufdesc, sizeof(bufdesc));
+        bufdesc.dwSize=sizeof(bufdesc);
+        bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
+        bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
+        bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
+        bufdesc.lpwfxFormat=&wfx;
+        rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
+        ok(rc==DS_OK && secondary!=NULL,"CreateSoundBuffer failed to create a secondary buffer 0x%lx\n", rc);
+        if (rc==DS_OK && secondary!=NULL) {
+            LPDIRECTSOUND3DBUFFER buffer3d;
+            rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer, (void **)&buffer3d);
+            ok(rc==DS_OK && buffer3d!=NULL,"QueryInterface failed:  %s\n",DXGetErrorString9(rc));
+            /* add some more refs */
+            IDirectSound3DBuffer_AddRef(buffer3d);
+            IDirectSoundBuffer_AddRef(secondary);
+        }
+        /* release with buffer */
+        ref=IDirectSound_Release(dso);
+        ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
+        if (ref!=0)
+            return DSERR_GENERIC;
+    } else
+        return rc;
+
     return DS_OK;
 }
 
@@ -408,6 +441,39 @@
         }
 
         /* Release the first DirectSound8 object */
+        ref=IDirectSound8_Release(dso);
+        ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
+        if (ref!=0)
+            return DSERR_GENERIC;
+    } else
+        return rc;
+
+    /* Create a DirectSound8 object */
+    rc=DirectSoundCreate8(lpGuid,&dso,NULL);
+    ok(rc==DS_OK,"DirectSoundCreate8 failed: %s\n",DXGetErrorString9(rc));
+    if (rc==DS_OK) {
+        LPDIRECTSOUNDBUFFER secondary;
+        DSBUFFERDESC bufdesc;
+        WAVEFORMATEX wfx;
+
+        init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
+        ZeroMemory(&bufdesc, sizeof(bufdesc));
+        bufdesc.dwSize=sizeof(bufdesc);
+        bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
+        bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
+        bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
+        bufdesc.lpwfxFormat=&wfx;
+        rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
+        ok(rc==DS_OK && secondary!=NULL,"CreateSoundBuffer failed to create a secondary buffer 0x%lx\n", rc);
+        if (rc==DS_OK && secondary!=NULL) {
+            LPDIRECTSOUND3DBUFFER buffer3d;
+            rc=IDirectSound8_QueryInterface(secondary, &IID_IDirectSound3DBuffer, (void **)&buffer3d);
+            ok(rc==DS_OK && buffer3d!=NULL,"QueryInterface failed:  %s\n",DXGetErrorString9(rc));
+            /* add some more refs */
+            IDirectSound3DBuffer_AddRef(buffer3d);
+            IDirectSoundBuffer8_AddRef(secondary);
+        }
+        /* release with buffer */
         ref=IDirectSound8_Release(dso);
         ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
         if (ref!=0)


More information about the wine-patches mailing list