[RFC] dsound reference count patch

Robert Reif reif at earthlink.net
Fri Apr 23 10:41:03 CDT 2004


This patch fixes a long standing bug in wine regarding creating
multiple instances of a direct sound object and releasing a direct
sound object with active buffers.   In windows, it's ok to delete
a direct sound object with active buffers.  Our reference counting
considers that an error.  This patch breaks our reference counting
into an internal count and a user count and destroys the object
(and buffers) even when the internal count is not 0.

This patch makes the minimal amount of code changes to fix this
problem.  I'm not real happy about this because I think a deeper
restructuring of the code is needed.  The internal object doesn't
need to be a com object. It could just be a structure but it would
be a lot of work to make that change.

Comments?
-------------- next part --------------
Index: dlls/dsound/dsound_main.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/dsound_main.c,v
retrieving revision 1.98
diff -u -r1.98 dsound_main.c
--- dlls/dsound/dsound_main.c	19 Apr 2004 02:58:45 -0000	1.98
+++ dlls/dsound/dsound_main.c	23 Apr 2004 15:19:36 -0000
@@ -87,6 +87,8 @@
 
 IDirectSoundImpl*	dsound = NULL;
 
+HRESULT DSOUND_Destroy(IDirectSound8 * iface);
+
 HRESULT mmErr(UINT err)
 {
 	switch(err) {
@@ -765,45 +767,7 @@
 	TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
 	ulReturn = InterlockedDecrement(&This->ref);
 	if (ulReturn == 0) {
-		HRESULT hres;
-		UINT i;
-
-		timeKillEvent(This->timerID);
-		timeEndPeriod(DS_TIME_RES);
-		/* wait for timer to expire */
-		Sleep(DS_TIME_RES+1);
-
-		RtlAcquireResourceShared(&(This->lock), TRUE);
-
-		if (This->buffers) {
-			for( i=0;i<This->nrofbuffers;i++)
-				IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->buffers[i]);
-		}
-
-		RtlReleaseResource(&(This->lock));
-
-		if (This->primary) {
-			WARN("primary buffer not released\n");
-			IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
-		}
-
-		hres = DSOUND_PrimaryDestroy(This);
-		if (hres != DS_OK)
-			WARN("DSOUND_PrimaryDestroy failed\n");
-
-		if (This->driver)
-			IDsDriver_Close(This->driver);
-
-		if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
-			waveOutClose(This->hwo);
-
-		if (This->driver)
-			IDsDriver_Release(This->driver);
-
-		RtlDeleteResource(&This->lock);
-		DeleteCriticalSection(&This->mixlock);
-		HeapFree(GetProcessHeap(),0,This);
-		dsound = NULL;
+                DSOUND_Destroy((LPDIRECTSOUND8)This);
 		TRACE("(%p) released\n",This);
 	}
 
@@ -915,6 +879,229 @@
 	IDirectSoundImpl_VerifyCertification
 };
 
+HRESULT DSOUND_Destroy(IDirectSound8 * iface)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    HRESULT hres;
+    UINT i;
+    TRACE("(%p)\n", This);
+
+    timeKillEvent(This->timerID);
+    timeEndPeriod(DS_TIME_RES);
+    /* wait for timer to expire */
+    Sleep(DS_TIME_RES+1);
+
+    if (This->buffers) {
+        WARN("%d secondary buffers not released\n", This->nrofbuffers);
+
+        for( i=0;i<This->nrofbuffers;i++)
+            IDirectSoundBuffer8_Stop((LPDIRECTSOUNDBUFFER8)This->buffers[i]);
+
+        while (This->nrofbuffers)
+            IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->buffers[0]);
+    }
+
+    if (This->primary) {
+        WARN("primary buffer not released\n");
+        IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
+    }
+
+    hres = DSOUND_PrimaryDestroy(This);
+    if (hres != DS_OK)
+        WARN("DSOUND_PrimaryDestroy failed\n");
+
+    if (This->driver)
+        IDsDriver_Close(This->driver);
+
+    if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+        waveOutClose(This->hwo);
+
+    if (This->driver)
+        IDsDriver_Release(This->driver);
+
+    RtlDeleteResource(&This->lock);
+    DeleteCriticalSection(&This->mixlock);
+    HeapFree(GetProcessHeap(),0,This);
+    dsound = NULL;
+
+    return DS_OK;
+}
+
+/*******************************************************************************
+ *		DirectSound
+ */
+
+static HRESULT WINAPI DirectSoundImpl_QueryInterface(
+    LPDIRECTSOUND8 iface,
+    REFIID riid,
+    LPVOID *ppobj)
+{
+    ICOM_THIS(DirectSoundImpl,iface);
+    TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj);
+
+    return IDirectSoundImpl_QueryInterface((LPDIRECTSOUND8)This->dsound, riid, ppobj);
+}
+
+static ULONG WINAPI DirectSoundImpl_AddRef(LPDIRECTSOUND8 iface)
+{
+    ICOM_THIS(DirectSoundImpl, iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI DirectSoundImpl_Release(LPDIRECTSOUND8 iface)
+{
+    ICOM_THIS(DirectSoundImpl, iface);
+    ULONG ulReturn;
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+
+    ulReturn = InterlockedDecrement(&This->ref);
+    if (ulReturn == 0) {
+        ULONG user_ref = InterlockedDecrement(&This->dsound->user_ref);
+        ULONG ref = IDirectSound_Release((LPDIRECTSOUND8)This->dsound);
+
+        TRACE("(%p) user ref = %ld\n", This, user_ref);
+        TRACE("(%p) ref = %ld\n", This, ref);
+
+        if (user_ref == 0 && ref != 0) {
+            TRACE("buffers still open\n");
+            DSOUND_Destroy((LPDIRECTSOUND8)This->dsound);
+        }
+        HeapFree(GetProcessHeap(),0,This);
+        TRACE("(%p) released\n",This);
+    }
+    return ulReturn;
+}
+
+static HRESULT WINAPI DirectSoundImpl_CreateSoundBuffer(
+    LPDIRECTSOUND8 iface,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER8 ppdsb,
+    LPUNKNOWN lpunk)
+{
+    ICOM_THIS(DirectSoundImpl,iface);
+    TRACE("(%p,%p,%p,%p)\n", This, dsbd, ppdsb, lpunk);
+
+    return IDirectSoundImpl_CreateSoundBuffer((LPDIRECTSOUND8)This->dsound, dsbd, ppdsb, lpunk);
+}
+
+static HRESULT WINAPI DirectSoundImpl_GetCaps(
+    LPDIRECTSOUND8 iface,
+    LPDSCAPS lpDSCaps)
+{
+    ICOM_THIS(DirectSoundImpl,iface);
+    TRACE("(%p,%p)\n", iface, lpDSCaps);
+
+    return IDirectSoundImpl_GetCaps((LPDIRECTSOUND8)This->dsound, lpDSCaps);
+}
+
+static HRESULT WINAPI DirectSoundImpl_DuplicateSoundBuffer(
+    LPDIRECTSOUND8 iface,
+    LPDIRECTSOUNDBUFFER8 psb,
+    LPLPDIRECTSOUNDBUFFER8 ppdsb)
+{
+    ICOM_THIS(DirectSoundImpl,iface);
+    TRACE("(%p,%p,%p)\n", This, psb, ppdsb);
+
+    return IDirectSoundImpl_DuplicateSoundBuffer((LPDIRECTSOUND8)This->dsound, psb, ppdsb);
+}
+
+static HRESULT WINAPI DirectSoundImpl_SetCooperativeLevel(
+    LPDIRECTSOUND8 iface,
+    HWND hwnd,
+    DWORD level)
+{
+    ICOM_THIS(DirectSoundImpl,iface);
+    TRACE("(%p,%08lx,%ld)\n", This, (DWORD)hwnd, level);
+
+    return IDirectSoundImpl_SetCooperativeLevel((LPDIRECTSOUND8)This->dsound, hwnd, level);
+}
+
+static HRESULT WINAPI DirectSoundImpl_Compact(
+    LPDIRECTSOUND8 iface)
+{
+    ICOM_THIS(DirectSoundImpl,iface);
+    TRACE("(%p)\n", This);
+
+    return IDirectSoundImpl_Compact((LPDIRECTSOUND8)This->dsound);
+}
+
+static HRESULT WINAPI DirectSoundImpl_GetSpeakerConfig(
+    LPDIRECTSOUND8 iface,
+    LPDWORD lpdwSpeakerConfig)
+{
+    ICOM_THIS(DirectSoundImpl,iface);
+    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+
+    return IDirectSoundImpl_GetSpeakerConfig((LPDIRECTSOUND8)This->dsound, lpdwSpeakerConfig);
+}
+
+static HRESULT WINAPI DirectSoundImpl_SetSpeakerConfig(
+    LPDIRECTSOUND8 iface,
+    DWORD config)
+{
+    ICOM_THIS(DirectSoundImpl,iface);
+    TRACE("(%p,0x%08lx)\n", This, config);
+
+    IDirectSoundImpl_SetSpeakerConfig((LPDIRECTSOUND8)This->dsound, config);
+}
+
+static HRESULT WINAPI DirectSoundImpl_Initialize(
+    LPDIRECTSOUND8 iface,
+    LPCGUID lpcGuid)
+{
+    ICOM_THIS(DirectSoundImpl,iface);
+    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+
+    return IDirectSoundImpl_Initialize((LPDIRECTSOUND8)This->dsound, lpcGuid);
+}
+
+static HRESULT WINAPI DirectSoundImpl_VerifyCertification(
+    LPDIRECTSOUND8 iface,
+    LPDWORD pdwCertified)
+{
+    ICOM_THIS(DirectSoundImpl,iface);
+    TRACE("(%p, %p)\n", This, pdwCertified);
+
+    return IDirectSoundImpl_VerifyCertification((LPDIRECTSOUND8)This->dsound, pdwCertified);
+}
+
+static ICOM_VTABLE(IDirectSound8) dsoundvt =
+{
+	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+	DirectSoundImpl_QueryInterface,
+	DirectSoundImpl_AddRef,
+	DirectSoundImpl_Release,
+	DirectSoundImpl_CreateSoundBuffer,
+	DirectSoundImpl_GetCaps,
+	DirectSoundImpl_DuplicateSoundBuffer,
+	DirectSoundImpl_SetCooperativeLevel,
+	DirectSoundImpl_Compact,
+	DirectSoundImpl_GetSpeakerConfig,
+	DirectSoundImpl_SetSpeakerConfig,
+	DirectSoundImpl_Initialize,
+	DirectSoundImpl_VerifyCertification
+};
+
+HRESULT DSOUND_Create(IDirectSoundImpl * dsound, DirectSoundImpl ** ippDS)
+{
+    TRACE("(%p,%p)\n", dsound, ippDS);
+
+    *ippDS = (DirectSoundImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundImpl));
+
+    if (*ippDS == NULL) {
+        WARN("out of memory\n");
+        return DSERR_OUTOFMEMORY;
+    }
+
+    (*ippDS)->lpVtbl = &dsoundvt;
+    (*ippDS)->ref = 1;
+    (*ippDS)->dsound = dsound; 
+    (*ippDS)->dsound->user_ref++;
+    IDirectSound_AddRef((LPDIRECTSOUND8)dsound);
+    return DS_OK;
+}
 
 /*******************************************************************************
  *		DirectSoundCreate (DSOUND.1)
@@ -933,7 +1120,8 @@
  */
 HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown *pUnkOuter )
 {
-	IDirectSoundImpl** ippDS=(IDirectSoundImpl**)ppDS;
+	DirectSoundImpl** ippDS=(DirectSoundImpl**)ppDS;
+	IDirectSoundImpl* pDS;
 	PIDSDRIVER drv = NULL;
 	unsigned wod, wodn;
 	HRESULT err = DSERR_INVALIDPARAM;
@@ -942,11 +1130,13 @@
 
 	TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ippDS,pUnkOuter);
 	
-	if (ippDS == NULL) {
-		WARN("invalid parameter: ippDS == NULL\n");
+	if (ppDS == NULL) {
+		WARN("invalid parameter: ppDS == NULL\n");
 		return DSERR_INVALIDPARAM;
 	}
 
+        *ippDS = NULL;
+
         /* Get dsound configuration */
         setup_dsound_options();
 
@@ -956,17 +1146,13 @@
 
 	if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
 		WARN("invalid parameter: lpcGUID\n");
-		*ippDS = NULL;
 		return DSERR_INVALIDPARAM;
 	}
 
 	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;
-			return DS_OK;
+                        TRACE("already exists, creating another instance\n");
+                        return DSOUND_Create(dsound, ippDS);
 		} else {
 			ERR("different dsound already opened\n");
 		}
@@ -976,7 +1162,6 @@
 	wodn = waveOutGetNumDevs();
 	if (!wodn) {
 		WARN("no driver\n");
-		*ippDS = NULL;
 	       	return DSERR_NODRIVER;
 	}
 
@@ -987,7 +1172,6 @@
 		err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
 		if (err != DS_OK) {
 			WARN("waveOutMessage failed; err=%lx\n",err);
-			*ippDS = NULL;
 			return err;
 		}
 		TRACE("got GUID %s for wod %d.\n", debugstr_guid(&guid), wod);
@@ -1000,7 +1184,6 @@
 
 	if (err != DS_OK) {
 		WARN("invalid parameter\n");
-		*ippDS = NULL;
 		return DSERR_INVALIDPARAM;
 	}
 
@@ -1017,83 +1200,83 @@
 	    drv = NULL;
 	
 	/* Allocate memory */
-	*ippDS = (IDirectSoundImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
-	if (*ippDS == NULL) {
+	pDS = (IDirectSoundImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
+	if (pDS == NULL) {
 		WARN("out of memory\n");
 		return DSERR_OUTOFMEMORY;
 	}
 
-	(*ippDS)->lpVtbl	= &dsvt;
-	(*ippDS)->ref		= 1;
-
-	(*ippDS)->driver	= drv;
-	(*ippDS)->priolevel	= DSSCL_NORMAL;
-	(*ippDS)->fraglen	= 0;
-	(*ippDS)->hwbuf		= NULL;
-	(*ippDS)->buffer	= NULL;
-	(*ippDS)->buflen	= 0;
-	(*ippDS)->writelead	= 0;
-	(*ippDS)->state		= STATE_STOPPED;
-	(*ippDS)->nrofbuffers	= 0;
-	(*ippDS)->buffers	= NULL;
-	(*ippDS)->primary	= NULL;
-	(*ippDS)->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
+	pDS->lpVtbl	= &dsvt;
+	pDS->ref	= 1;
+	pDS->user_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);
 	
 	/* 3D listener initial parameters */
-	(*ippDS)->listener	= NULL;
-	(*ippDS)->ds3dl.dwSize = sizeof(DS3DLISTENER);
-	(*ippDS)->ds3dl.vPosition.x = 0.0;
-	(*ippDS)->ds3dl.vPosition.y = 0.0;
-	(*ippDS)->ds3dl.vPosition.z = 0.0;
-	(*ippDS)->ds3dl.vVelocity.x = 0.0;
-	(*ippDS)->ds3dl.vVelocity.y = 0.0;
-	(*ippDS)->ds3dl.vVelocity.z = 0.0;
-	(*ippDS)->ds3dl.vOrientFront.x = 0.0;
-	(*ippDS)->ds3dl.vOrientFront.y = 0.0;
-	(*ippDS)->ds3dl.vOrientFront.z = 1.0;
-	(*ippDS)->ds3dl.vOrientTop.x = 0.0;
-	(*ippDS)->ds3dl.vOrientTop.y = 1.0;
-	(*ippDS)->ds3dl.vOrientTop.z = 0.0;
-	(*ippDS)->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
-	(*ippDS)->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
-	(*ippDS)->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
+	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;
 
-	(*ippDS)->prebuf	= ds_snd_queue_max;
-	(*ippDS)->guid		= devGuid;
+	pDS->prebuf	= ds_snd_queue_max;
+	pDS->guid	= devGuid;
 
 	/* Get driver description */
 	if (drv) {
-		err = IDsDriver_GetDriverDesc(drv,&((*ippDS)->drvdesc));
+		err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
 		if (err != DS_OK) {
 			WARN("IDsDriver_GetDriverDesc failed\n");
-			HeapFree(GetProcessHeap(),0,*ippDS);
-			*ippDS = NULL;
+			HeapFree(GetProcessHeap(),0,pDS);
 			return err;
 		}
 	} else {
 		/* if no DirectSound interface available, use WINMM API instead */
-		(*ippDS)->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
+		pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
 	}
 
-	(*ippDS)->drvdesc.dnDevNode = wod;
+	pDS->drvdesc.dnDevNode = wod;
 
 	/* Set default wave format (may need it for waveOutOpen) */
-	(*ippDS)->wfx.wFormatTag	= WAVE_FORMAT_PCM;
+	pDS->wfx.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.
          */
-        (*ippDS)->wfx.nSamplesPerSec = 22050;
-        (*ippDS)->wfx.wBitsPerSample = 8;
-        (*ippDS)->wfx.nChannels = 2;
-        (*ippDS)->wfx.nBlockAlign = (*ippDS)->wfx.wBitsPerSample * (*ippDS)->wfx.nChannels / 8;
-        (*ippDS)->wfx.nAvgBytesPerSec = (*ippDS)->wfx.nSamplesPerSec * (*ippDS)->wfx.nBlockAlign;
-        (*ippDS)->wfx.cbSize = 0;
+        pDS->wfx.nSamplesPerSec = 22050;
+        pDS->wfx.wBitsPerSample = 8;
+        pDS->wfx.nChannels = 2;
+        pDS->wfx.nBlockAlign = pDS->wfx.wBitsPerSample * pDS->wfx.nChannels / 8;
+        pDS->wfx.nAvgBytesPerSec = pDS->wfx.nSamplesPerSec * pDS->wfx.nBlockAlign;
+        pDS->wfx.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 ((*ippDS)->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+	if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
 	{
 		DWORD flags = CALLBACK_FUNCTION;
 
@@ -1101,14 +1284,13 @@
 		if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
 		    flags |= WAVE_DIRECTSOUND;
 
-                err = mmErr(waveOutOpen(&((*ippDS)->hwo),
-					  (*ippDS)->drvdesc.dnDevNode, &((*ippDS)->wfx),
-					  (DWORD)DSOUND_callback, (DWORD)(*ippDS),
+                err = mmErr(waveOutOpen(&(pDS->hwo),
+					  pDS->drvdesc.dnDevNode, &(pDS->wfx),
+					  (DWORD)DSOUND_callback, (DWORD)pDS,
 					  flags));
 		if (err != DS_OK) {
 			WARN("waveOutOpen failed\n");
-			HeapFree(GetProcessHeap(),0,*ippDS);
-			*ippDS = NULL;
+			HeapFree(GetProcessHeap(),0,pDS);
 			return err;
 		}
 	}
@@ -1117,78 +1299,75 @@
 		err = IDsDriver_Open(drv);
 		if (err != DS_OK) {
 			WARN("IDsDriver_Open failed\n");
-			HeapFree(GetProcessHeap(),0,*ippDS);
-			*ippDS = NULL;
+			HeapFree(GetProcessHeap(),0,pDS);
 			return err;
 		}
 
 		/* the driver is now open, so it's now allowed to call GetCaps */
-		err = IDsDriver_GetCaps(drv,&((*ippDS)->drvcaps));
+		err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
 		if (err != DS_OK) {
 			WARN("IDsDriver_GetCaps failed\n");
-			HeapFree(GetProcessHeap(),0,*ippDS);
-			*ippDS = NULL;
+			HeapFree(GetProcessHeap(),0,pDS);
 			return err;
 		}
 	} else {
 		WAVEOUTCAPSA woc;
-		err = mmErr(waveOutGetDevCapsA((*ippDS)->drvdesc.dnDevNode, &woc, sizeof(woc)));
+		err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
 		if (err != DS_OK) {
 			WARN("waveOutGetDevCaps failed\n");
-			HeapFree(GetProcessHeap(),0,*ippDS);
-			*ippDS = NULL;
+			HeapFree(GetProcessHeap(),0,pDS);
 			return err;
 		}
-		ZeroMemory(&(*ippDS)->drvcaps, sizeof((*ippDS)->drvcaps));
+		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)) {
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
+			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)) {
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
+			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)) {
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
+			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)) {
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
+			pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
+			pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
 		}
 		if (ds_emuldriver)
-		    (*ippDS)->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
-		(*ippDS)->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
-		(*ippDS)->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
-		(*ippDS)->drvcaps.dwPrimaryBuffers = 1;
+		    pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
+		pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
+		pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
+		pDS->drvcaps.dwPrimaryBuffers = 1;
 	}
 
-	(*ippDS)->volpan.lVolume = 0;
-	(*ippDS)->volpan.lPan = 0;
-	DSOUND_RecalcVolPan(&((*ippDS)->volpan));
+	pDS->volpan.lVolume = 0;
+	pDS->volpan.lPan = 0;
+	DSOUND_RecalcVolPan(&(pDS->volpan));
 
-	InitializeCriticalSection(&((*ippDS)->mixlock));
-	RtlInitializeResource(&((*ippDS)->lock));
+	InitializeCriticalSection(&(pDS->mixlock));
+	RtlInitializeResource(&(pDS->lock));
 
 	if (!dsound) {
 		HRESULT hres;
-		dsound = (*ippDS);
+		dsound = pDS;
 		hres = DSOUND_PrimaryCreate(dsound);
 		if (hres != DS_OK) {
 			WARN("DSOUND_PrimaryCreate failed\n");
@@ -1199,7 +1378,7 @@
 					       (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
 	}
 
-	return DS_OK;
+	return DSOUND_Create(dsound, ippDS);
 }
 
 
Index: dlls/dsound/dsound_private.h
===================================================================
RCS file: /home/wine/wine/dlls/dsound/dsound_private.h,v
retrieving revision 1.15
diff -u -r1.15 dsound_private.h
--- dlls/dsound/dsound_private.h	17 Mar 2004 01:44:15 -0000	1.15
+++ dlls/dsound/dsound_private.h	23 Apr 2004 15:19:36 -0000
@@ -55,6 +55,7 @@
 typedef struct IDirectSound3DBufferImpl IDirectSound3DBufferImpl;
 typedef struct IKsBufferPropertySetImpl IKsBufferPropertySetImpl;
 typedef struct IKsPrivatePropertySetImpl IKsPrivatePropertySetImpl;
+typedef struct DirectSoundImpl DirectSoundImpl;
 typedef struct PrimaryBufferImpl PrimaryBufferImpl;
 typedef struct SecondaryBufferImpl SecondaryBufferImpl;
 typedef struct IClassFactoryImpl IClassFactoryImpl;
@@ -95,6 +96,19 @@
     IDirectSound3DListenerImpl*	listener;
     DS3DLISTENER                ds3dl;
     BOOL                        ds3dl_need_recalc;
+
+    DWORD                       user_ref;
+};
+
+/*****************************************************************************
+ * DirectSound implementation structure
+ */
+struct DirectSoundImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSound8);
+    DWORD                       ref;
+    IDirectSoundImpl*           dsound;
 };
 
 /* reference counted buffer memory for duplicated buffer memory */
Index: dlls/dsound/tests/dsound.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/tests/dsound.c,v
retrieving revision 1.20
diff -u -r1.20 dsound.c
--- dlls/dsound/tests/dsound.c	20 Jan 2004 21:49:48 -0000	1.20
+++ dlls/dsound/tests/dsound.c	23 Apr 2004 15:19:37 -0000
@@ -749,7 +749,6 @@
     if (ref!=0)
 	return DSERR_GENERIC; 
 
-#if 0	/* FIXME: this works on windows */ 
     /* Create a DirectSound object */
     rc=DirectSoundCreate(lpGuid,&dso,NULL);
     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
@@ -773,7 +772,6 @@
 	    return DSERR_GENERIC; 
     } else
 	return rc;
-#endif
 
     return DS_OK;
 }


More information about the wine-patches mailing list