[PATCH] dsound: Restore old format on SetFormat failure.

Nick Bowler nbowler at draconx.ca
Sun Oct 3 10:52:00 CDT 2010


The Typing of the Dead, and apparently some other games, expect this to
happen.  Without this, the game has no sound and hangs shortly after
starting.

Fixes bug #18823.
---
 dlls/dsound/primary.c |   20 +++++++++++++++-----
 1 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c
index 8a054f8..aa8450f 100644
--- a/dlls/dsound/primary.c
+++ b/dlls/dsound/primary.c
@@ -441,10 +441,17 @@ HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LP
 	return DS_OK;
 }
 
+static DWORD DSOUND_GetFormatSize(LPCWAVEFORMATEX wfex)
+{
+	if (wfex->wFormatTag == WAVE_FORMAT_PCM)
+		return sizeof(WAVEFORMATEX);
+	else
+		return sizeof(WAVEFORMATEX) + wfex->cbSize;
+}
+
 LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex)
 {
-	DWORD size = wfex->wFormatTag == WAVE_FORMAT_PCM ?
-		sizeof(WAVEFORMATEX) : sizeof(WAVEFORMATEX) + wfex->cbSize;
+	DWORD size = DSOUND_GetFormatSize(wfex);
 	LPWAVEFORMATEX pwfx = HeapAlloc(GetProcessHeap(),0,size);
 	if (pwfx == NULL) {
 		WARN("out of memory\n");
@@ -501,11 +508,10 @@ static HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATE
 	device->pwfx = DSOUND_CopyFormat(wfex);
 	if (device->pwfx == NULL) {
 		device->pwfx = oldpwfx;
+		oldpwfx = NULL;
 		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);
@@ -520,9 +526,12 @@ static HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATE
 		}
 
 		if (err != DSERR_BUFFERLOST && FAILED(err)) {
+			DWORD size = DSOUND_GetFormatSize(oldpwfx);
 			WARN("IDsDriverBuffer_SetFormat failed\n");
-			if (!forced)
+			if (!forced) {
+				CopyMemory(device->pwfx, oldpwfx, size);
 				err = DS_OK;
+			}
 			goto done;
 		}
 
@@ -599,6 +608,7 @@ done:
 	RtlReleaseResource(&(device->buffer_list_lock));
 	/* **** */
 
+	HeapFree(GetProcessHeap(), 0, oldpwfx);
 	return err;
 }
 
-- 
1.7.2.2




More information about the wine-patches mailing list