Jörg Höhle : dsound: Enforce invariant about BlockAlign and nAvgBytesPerSec.
Alexandre Julliard
julliard at winehq.org
Tue Oct 6 10:35:52 CDT 2009
Module: wine
Branch: master
Commit: dc3471ca0e7c2209ecf9758359cc62f9d958bf2c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=dc3471ca0e7c2209ecf9758359cc62f9d958bf2c
Author: Jörg Höhle <hoehle at 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)) {
More information about the wine-cvs
mailing list