Module: wine Branch: master Commit: dc3471ca0e7c2209ecf9758359cc62f9d958bf2c URL: http://source.winehq.org/git/wine.git/?a=commit;h=dc3471ca0e7c2209ecf9758359...
Author: Jörg Höhle hoehle@users.sourceforge.net Date: Sun Oct 4 08:05:20 2009 +0200
dsound: Enforce invariant about BlockAlign and nAvgBytesPerSec.
---
dlls/dsound/buffer.c | 32 ++++++------------------- dlls/dsound/capture.c | 11 +++----- dlls/dsound/dsound_private.h | 1 + dlls/dsound/primary.c | 53 +++++++++++++++++++++++++++++++++-------- 4 files changed, 55 insertions(+), 42 deletions(-)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c index 2d64341..4b486fd 100644 --- a/dlls/dsound/buffer.c +++ b/dlls/dsound/buffer.c @@ -957,7 +957,7 @@ HRESULT IDirectSoundBufferImpl_Create( LPWAVEFORMATEX wfex = dsbd->lpwfxFormat; HRESULT err = DS_OK; DWORD capf = 0; - int use_hw, alloc_size, cp_size; + int use_hw; TRACE("(%p,%p,%p)\n",device,pdsb,dsbd);
if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) { @@ -985,23 +985,13 @@ HRESULT IDirectSoundBufferImpl_Create( /* size depends on version */ CopyMemory(&dsb->dsbd, dsbd, dsbd->dwSize);
- /* variable sized struct so calculate size based on format */ - if (wfex->wFormatTag == WAVE_FORMAT_PCM) { - alloc_size = sizeof(WAVEFORMATEX); - cp_size = sizeof(PCMWAVEFORMAT); - } else - alloc_size = cp_size = sizeof(WAVEFORMATEX) + wfex->cbSize; - - dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,alloc_size); + dsb->pwfx = DSOUND_CopyFormat(wfex); if (dsb->pwfx == NULL) { - WARN("out of memory\n"); HeapFree(GetProcessHeap(),0,dsb); *pdsb = NULL; return DSERR_OUTOFMEMORY; }
- CopyMemory(dsb->pwfx, wfex, cp_size); - if (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign) dsb->buflen = dsbd->dwBufferBytes + (dsbd->lpwfxFormat->nBlockAlign - @@ -1185,7 +1175,6 @@ HRESULT IDirectSoundBufferImpl_Duplicate( { IDirectSoundBufferImpl *dsb; HRESULT hres = DS_OK; - int size; TRACE("(%p,%p,%p)\n", device, pdsb, pdsb);
dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb)); @@ -1224,20 +1213,15 @@ HRESULT IDirectSoundBufferImpl_Duplicate( DSOUND_RecalcFormat(dsb); DSOUND_MixToTemporary(dsb, 0, dsb->buflen, FALSE);
- /* variable sized struct so calculate size based on format */ - size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize; - - dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size); + dsb->pwfx = DSOUND_CopyFormat(pdsb->pwfx); if (dsb->pwfx == NULL) { - WARN("out of memory\n"); - HeapFree(GetProcessHeap(),0,dsb->buffer); - HeapFree(GetProcessHeap(),0,dsb); - *ppdsb = NULL; - return DSERR_OUTOFMEMORY; + HeapFree(GetProcessHeap(),0,dsb->tmp_buffer); + HeapFree(GetProcessHeap(),0,dsb->buffer); + HeapFree(GetProcessHeap(),0,dsb); + *ppdsb = NULL; + return DSERR_OUTOFMEMORY; }
- CopyMemory(dsb->pwfx, pdsb->pwfx, size); - RtlInitializeResource(&dsb->lock);
/* register buffer */ diff --git a/dlls/dsound/capture.c b/dlls/dsound/capture.c index 0e75dd7..95b38af 100644 --- a/dlls/dsound/capture.c +++ b/dlls/dsound/capture.c @@ -1365,13 +1365,10 @@ HRESULT IDirectSoundCaptureBufferImpl_Create( wfex->nAvgBytesPerSec, wfex->nBlockAlign, wfex->wBitsPerSample, wfex->cbSize);
- if (wfex->wFormatTag == WAVE_FORMAT_PCM) { - device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)); - CopyMemory(device->pwfx, wfex, sizeof(PCMWAVEFORMAT)); - device->pwfx->cbSize = 0; - } else { - device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize); - CopyMemory(device->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize); + device->pwfx = DSOUND_CopyFormat(wfex); + if ( device->pwfx == NULL ) { + *ppobj = NULL; + return DSERR_OUTOFMEMORY; }
*ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 221433f..e028358 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -437,6 +437,7 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device); HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device); HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device); HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos); +LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex); HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex, BOOL forced); HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave);
diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index a57a5af..6b3ca35 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -17,6 +17,10 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * TODO: + * When PrimarySetFormat (via ReopenDevice or PrimaryOpen) fails, + * it leaves dsound in unusable (not really open) state. */
#include <stdarg.h> @@ -437,11 +441,36 @@ HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LP return DS_OK; }
+LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex) +{ + DWORD size = wfex->wFormatTag == WAVE_FORMAT_PCM ? + sizeof(WAVEFORMATEX) : sizeof(WAVEFORMATEX) + wfex->cbSize; + LPWAVEFORMATEX pwfx = HeapAlloc(GetProcessHeap(),0,size); + if (pwfx == NULL) { + WARN("out of memory\n"); + } else if (wfex->wFormatTag != WAVE_FORMAT_PCM) { + CopyMemory(pwfx, wfex, size); + } else { + CopyMemory(pwfx, wfex, sizeof(PCMWAVEFORMAT)); + pwfx->cbSize=0; + if (pwfx->nBlockAlign != pwfx->nChannels * pwfx->wBitsPerSample/8) { + WARN("Fixing bad nBlockAlign (%u)\n", pwfx->nBlockAlign); + pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample/8; + } + if (pwfx->nAvgBytesPerSec != pwfx->nSamplesPerSec * pwfx->nBlockAlign) { + WARN("Fixing bad nAvgBytesPerSec (%u)\n", pwfx->nAvgBytesPerSec); + pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign; + } + } + return pwfx; +} + HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex, BOOL forced) { HRESULT err = DSERR_BUFFERLOST; - int i, alloc_size, cp_size; + int i; DWORD nSamplesPerSec, bpp, chans; + LPWAVEFORMATEX oldpwfx; TRACE("(%p,%p)\n", device, wfex);
if (device->priolevel == DSSCL_NORMAL) { @@ -464,19 +493,19 @@ HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex, RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock));
- if (wfex->wFormatTag == WAVE_FORMAT_PCM) { - alloc_size = sizeof(WAVEFORMATEX); - cp_size = sizeof(PCMWAVEFORMAT); - } else - alloc_size = cp_size = sizeof(WAVEFORMATEX) + wfex->cbSize; - - device->pwfx = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,device->pwfx,alloc_size); - nSamplesPerSec = device->pwfx->nSamplesPerSec; bpp = device->pwfx->wBitsPerSample; chans = device->pwfx->nChannels;
- CopyMemory(device->pwfx, wfex, cp_size); + oldpwfx = device->pwfx; + device->pwfx = DSOUND_CopyFormat(wfex); + if (device->pwfx == NULL) { + device->pwfx = oldpwfx; + err = DSERR_OUTOFMEMORY; + goto done; + } + /* TODO: on failure below (bad format?), reinstall oldpwfx */ + HeapFree(GetProcessHeap(), 0, oldpwfx);
if (!(device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) && device->hwbuf) { err = IDsDriverBuffer_SetFormat(device->hwbuf, device->pwfx); @@ -484,8 +513,10 @@ HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex, /* On bad format, try to re-create, big chance it will work then, only do this if we <HAVE> to */ if (forced && (device->pwfx->nSamplesPerSec/100 != wfex->nSamplesPerSec/100 || err == DSERR_BADFORMAT)) { + DWORD cp_size = wfex->wFormatTag == WAVE_FORMAT_PCM ? + sizeof(PCMWAVEFORMAT) : sizeof(WAVEFORMATEX) + wfex->cbSize; err = DSERR_BUFFERLOST; - CopyMemory(device->pwfx, wfex, cp_size); + CopyMemory(device->pwfx, wfex, cp_size); }
if (err != DSERR_BUFFERLOST && FAILED(err)) {