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.
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);