position-notify array cleanup for IDirectSoundNotify

Jerry Ji JerryJz at hotmail.com
Sat Mar 22 07:54:04 CST 2003


IDirectSoundNotify8::Release didn't remove notify array from
IDirectSoundBufferImpl. Suppose an application has set notification
positions, and one of the positions is DSBPN_OFFSETSTOP, then it set
some new positions. The new associated events will never be signaled,
even if the application call Release and QueryInterface again before
SetNotificationPositions.

ChangeLog:
	- Added position-notify array cleanup for IDirectSoundNotify.




-------------- next part --------------
Index: dlls/dsound/buffer.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/buffer.c,v
retrieving revision 1.7
diff -u -r1.7 buffer.c
--- dlls/dsound/buffer.c	15 Mar 2003 00:54:12 -0000	1.7
+++ dlls/dsound/buffer.c	22 Mar 2003 13:21:07 -0000
@@ -81,12 +81,20 @@
 
 	ref = InterlockedDecrement(&(This->ref));
 	if (!ref) {
-		if (This->dsb)
+		if (This->dsb != NULL) {
+			EnterCriticalSection(&This->dsb->lock);
+			if (This->dsb->dsn == This)	This->dsb->dsn = NULL;
+			LeaveCriticalSection(&This->dsb->lock);
 			IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
-		else if (This->dscb)
+		} else if (This->dscb != NULL) {
+			EnterCriticalSection(&This->dscb->dsound->lock);
+			if (This->dscb->dsn == This)	This->dscb->dsn = NULL;
+			LeaveCriticalSection(&This->dscb->dsound->lock);
 			IDirectSoundCaptureBuffer8_Release((LPDIRECTSOUNDCAPTUREBUFFER8)This->dscb);
+		}
+		if(This->notifies != NULL)
+			HeapFree(GetProcessHeap(), 0, This->notifies);
 		HeapFree(GetProcessHeap(),0,This);
-		return 0;
 	}
 	return ref;
 }
@@ -101,24 +109,37 @@
 	    TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
 	    for (i=0;i<howmuch;i++)
 		    TRACE("notify at %ld to 0x%08lx\n",
-                            notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
+                           notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
 	}
-	if (This->dsb) {
-		This->dsb->notifies = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->dsb->notifies,(This->dsb->nrofnotifies+howmuch)*sizeof(DSBPOSITIONNOTIFY));
-		memcpy(	This->dsb->notifies+This->dsb->nrofnotifies,
-			notify,
-			howmuch*sizeof(DSBPOSITIONNOTIFY)
-		);
-		This->dsb->nrofnotifies+=howmuch;
-	} else if (This->dscb) {
-		TRACE("notifies = %p, nrofnotifies = %d\n", This->dscb->notifies, This->dscb->nrofnotifies);
-		This->dscb->notifies = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->dscb->notifies,(This->dscb->nrofnotifies+howmuch)*sizeof(DSBPOSITIONNOTIFY));
-		memcpy(	This->dscb->notifies+This->dscb->nrofnotifies,
-			notify,
-			howmuch*sizeof(DSBPOSITIONNOTIFY)
-		);
-		This->dscb->nrofnotifies+=howmuch;
-		TRACE("notifies = %p, nrofnotifies = %d\n", This->dscb->notifies, This->dscb->nrofnotifies);
+
+	LPCRITICAL_SECTION	lpcs = NULL;
+	if (This->dsb != NULL && This->dsb->dsn == This)
+		lpcs = &This->dsb->lock;
+	else if (This->dscb != NULL && This->dscb->dsn == This)
+		lpcs = &This->dscb->dsound->lock;
+	if (lpcs != NULL) {
+		if (This->dscb != NULL )
+			IDirectSoundCaptureBuffer_Stop((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
+
+		EnterCriticalSection(lpcs);
+
+		/* Just keep one array, Please refer to MSDN or PlatSDK document for detail of
+		 * IDirectSoundNotify::SetNotificationPositions */
+		if (This->notifies != NULL) {
+			HeapFree(GetProcessHeap(), 0, This->notifies );
+		}
+		This->notifies = HeapAlloc(GetProcessHeap(), 0, howmuch * sizeof(DSBPOSITIONNOTIFY));
+		memcpy(This->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
+		This->nrofnotifies = howmuch;
+
+		LeaveCriticalSection(lpcs);
+
+		if (This->dscb != NULL) {
+			DSCBCAPS			caps;
+			LPDIRECTSOUNDCAPTUREBUFFER	dscb = (LPDIRECTSOUNDCAPTUREBUFFER)This->dscb;
+			IDirectSoundCaptureBuffer_GetCaps(dscb, &caps);
+			IDirectSoundCaptureBuffer_Start(dscb, caps.dwFlags);
+		}
 	}
 	else
 		return DSERR_INVALIDPARAM;
@@ -819,12 +840,24 @@
 	if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
 		IDirectSoundNotifyImpl	*dsn;
 
-		dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsn));
-		dsn->ref = 1;
-		dsn->dsb = This;
-		dsn->dscb = 0;
+		/* Since we don't call IDirectSoundNotify_AddRef for This->dsn (don't know where
+		 * we whould release it), we must Prevent IDirectSoundNotify_Release from changing
+		 * This->dsn manually */
+		EnterCriticalSection(&This->lock);
+		if ( This->dsn != NULL && IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->dsn) <= 1 ) {
+			This->dsn = NULL;
+		}
+		LeaveCriticalSection(&This->lock);
+		dsn = This->dsn;
+		if(dsn == NULL) {
+			dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsn));
+			dsn->ref = 1;
+			dsn->dsb = This;
+			dsn->dscb = 0;
+			This->dsn = dsn;
+			ICOM_VTBL(dsn) = &dsnvt;
+		}
 		IDirectSoundBuffer8_AddRef(iface);
-		ICOM_VTBL(dsn) = &dsnvt;
 		*ppobj = (LPVOID)dsn;
 		return S_OK;
 	}
Index: dlls/dsound/capture.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/capture.c,v
retrieving revision 1.7
diff -u -r1.7 capture.c
--- dlls/dsound/capture.c	15 Mar 2003 00:54:12 -0000	1.7
+++ dlls/dsound/capture.c	22 Mar 2003 13:21:10 -0000
@@ -300,8 +300,8 @@
 	    }
 	    This->index = (This->index + 1) % This->nrofpwaves;
 	    waveInUnprepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR));
-	    if (This->capture_buffer->nrofnotifies)
-		SetEvent(This->capture_buffer->notifies[This->index].hEventNotify);
+	    if (This->capture_buffer->dsn != NULL && This->capture_buffer->dsn->nrofnotifies != 0)
+		SetEvent(This->capture_buffer->dsn->notifies[This->index].hEventNotify);
 	    if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
 		TRACE("end of buffer\n");
 		This->state = STATE_STOPPED;
@@ -696,14 +696,23 @@
     if (IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
         IDirectSoundNotifyImpl  *dsn;
 
-        dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),0,
-            sizeof(*dsn));
-        dsn->ref = 1;
-        dsn->dsb = 0;
-        dsn->dscb = This;
-	/* FIXME: get this right someday */
-        IDirectSoundCaptureBuffer8_AddRef(iface);
-        ICOM_VTBL(dsn) = &dsnvt;
+	/* Since we don't call IDirectSoundNotify_AddRef for This->dsn (don't know where
+	 * we whould release it), we must Prevent IDirectSoundNotify_Release from changing
+	 * This->dsn manually */
+	EnterCriticalSection(&This->dsound->lock);
+	if ( This->dsn != NULL && IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->dsn) <= 1 ) {
+		This->dsn = NULL;
+	}
+	LeaveCriticalSection(&This->dsound->lock);
+	dsn = This->dsn;
+	if(dsn == NULL) {
+		dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsn));
+		dsn->ref = 1;
+		dsn->dsb = 0;
+		dsn->dscb = This;
+	        ICOM_VTBL(dsn) = &dsnvt;
+	}
+	IDirectSoundCaptureBuffer8_AddRef(iface);
         *ppobj = (LPVOID)dsn;
         return DS_OK;
     }
@@ -778,9 +787,6 @@
         else
             ERR("does not reference dsound\n");
 
-        if (This->notifies)
-            HeapFree(GetProcessHeap(),0, This->notifies);
-        
         HeapFree( GetProcessHeap(), 0, This );
     }
 
@@ -1037,10 +1043,10 @@
         IDirectSoundCaptureImpl* ipDSC = This->dsound;
 
         if (ipDSC->buffer) {
-            if (This->nrofnotifies) {
+            if (This->dsn != NULL && This->dsn->nrofnotifies != 0) {
             	unsigned c;
 
-		ipDSC->nrofpwaves = This->nrofnotifies;
+		ipDSC->nrofpwaves = This->dsn->nrofnotifies;
 
                 /* prepare headers */
                 ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,
@@ -1049,14 +1055,14 @@
                 for (c = 0; c < ipDSC->nrofpwaves; c++) {
                     if (c == 0) {
                         ipDSC->pwave[0].lpData = ipDSC->buffer;
-                        ipDSC->pwave[0].dwBufferLength = 
-                            This->notifies[0].dwOffset + 1;
+                        ipDSC->pwave[0].dwBufferLength =
+                            This->dsn->notifies[0].dwOffset + 1;
                     } else {
-                        ipDSC->pwave[c].lpData = ipDSC->buffer + 
-                            This->notifies[c-1].dwOffset + 1;
-                        ipDSC->pwave[c].dwBufferLength = 
-                            This->notifies[c].dwOffset - 
-                            This->notifies[c-1].dwOffset;
+                        ipDSC->pwave[c].lpData = ipDSC->buffer +
+                            This->dsn->notifies[c-1].dwOffset + 1;
+                        ipDSC->pwave[c].dwBufferLength =
+                            This->dsn->notifies[c].dwOffset -
+                            This->dsn->notifies[c-1].dwOffset;
                     }
                     ipDSC->pwave[c].dwUser = (DWORD)ipDSC;
                     ipDSC->pwave[c].dwFlags = 0;
Index: dlls/dsound/dsound_private.h
===================================================================
RCS file: /home/wine/wine/dlls/dsound/dsound_private.h,v
retrieving revision 1.5
diff -u -r1.5 dsound_private.h
--- dlls/dsound/dsound_private.h	15 Mar 2003 00:54:12 -0000	1.5
+++ dlls/dsound/dsound_private.h	22 Mar 2003 13:21:11 -0000
@@ -117,8 +117,7 @@
     DWORD                     primary_mixpos, buf_mixpos;
     BOOL                      need_remix;
     /* IDirectSoundNotifyImpl fields */
-    LPDSBPOSITIONNOTIFY       notifies;
-    int                       nrofnotifies;
+    IDirectSoundNotifyImpl    *dsn;
 };
 
 HRESULT WINAPI SecondaryBuffer_Create(
@@ -189,8 +188,7 @@
     IDirectSoundCaptureImpl*           dsound;
     /* FIXME: don't need this */
     LPDSCBUFFERDESC                    pdscbd;
-    LPDSBPOSITIONNOTIFY                notifies;
-    int                                nrofnotifies;
+    IDirectSoundNotifyImpl             *dsn;
     DWORD                              flags;
 };
 
@@ -218,6 +216,9 @@
     /* IDirectSoundNotifyImpl fields */
     IDirectSoundBufferImpl*          dsb;
     IDirectSoundCaptureBufferImpl*   dscb;
+    /* position-notify array */
+    LPDSBPOSITIONNOTIFY              notifies;
+    int                              nrofnotifies;
 };
 
 /*****************************************************************************
Index: dlls/dsound/mixer.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/mixer.c,v
retrieving revision 1.10
diff -u -r1.10 mixer.c
--- dlls/dsound/mixer.c	17 Mar 2003 21:23:12 -0000	1.10
+++ dlls/dsound/mixer.c	22 Mar 2003 13:21:14 -0000
@@ -79,13 +79,13 @@
 	DWORD			offset;
 	LPDSBPOSITIONNOTIFY	event;
 
-	if (dsb->nrofnotifies == 0)
+	if (dsb->dsn == NULL || dsb->dsn->nrofnotifies == 0)
 		return;
 
 	TRACE("(%p) buflen = %ld, playpos = %ld, len = %d\n",
 		dsb, dsb->buflen, dsb->playpos, len);
-	for (i = 0; i < dsb->nrofnotifies ; i++) {
-		event = dsb->notifies + i;
+	for (i = 0; i < dsb->dsn->nrofnotifies ; i++) {
+		event = dsb->dsn->notifies + i;
 		offset = event->dwOffset;
 		TRACE("checking %d, position %ld, event = %p\n",
 			i, offset, event->hEventNotify);





More information about the wine-patches mailing list