[PATCH 1/3] dsound: Prevent reopening device from leaving dsound object in invalid state

Andrew Eikum aeikum at codeweavers.com
Tue May 17 13:40:33 CDT 2016


From: Maarten Lankhorst <wine at mblankhorst.nl>

Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
---
 dlls/dsound/dsound.c         |  49 +++----
 dlls/dsound/dsound_private.h |   3 -
 dlls/dsound/primary.c        | 333 ++++++++++++++++++++-----------------------
 3 files changed, 175 insertions(+), 210 deletions(-)

diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c
index 0b5c3b4..195da0b 100644
--- a/dlls/dsound/dsound.c
+++ b/dlls/dsound/dsound.c
@@ -161,24 +161,20 @@ static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
     device->guid = GUID_NULL;
 
     /* Set default wave format (may need it for waveOutOpen) */
-    device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEXTENSIBLE));
     device->primary_pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEXTENSIBLE));
-    if (!device->pwfx || !device->primary_pwfx) {
+    if (!device->primary_pwfx) {
         WARN("out of memory\n");
-        HeapFree(GetProcessHeap(),0,device->primary_pwfx);
-        HeapFree(GetProcessHeap(),0,device->pwfx);
         HeapFree(GetProcessHeap(),0,device);
         return DSERR_OUTOFMEMORY;
     }
 
-    device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
-    device->pwfx->nSamplesPerSec = 22050;
-    device->pwfx->wBitsPerSample = 8;
-    device->pwfx->nChannels = 2;
-    device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
-    device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
-    device->pwfx->cbSize = 0;
-    memcpy(device->primary_pwfx, device->pwfx, sizeof(*device->pwfx));
+    device->primary_pwfx->wFormatTag = WAVE_FORMAT_PCM;
+    device->primary_pwfx->nSamplesPerSec = 22050;
+    device->primary_pwfx->wBitsPerSample = 8;
+    device->primary_pwfx->nChannels = 2;
+    device->primary_pwfx->nBlockAlign = device->primary_pwfx->wBitsPerSample * device->primary_pwfx->nChannels / 8;
+    device->primary_pwfx->nAvgBytesPerSec = device->primary_pwfx->nSamplesPerSec * device->primary_pwfx->nBlockAlign;
+    device->primary_pwfx->cbSize = 0;
 
     InitializeCriticalSection(&(device->mixlock));
     device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
@@ -228,12 +224,12 @@ static ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
         if (hr != DS_OK)
             WARN("DSOUND_PrimaryDestroy failed\n");
 
-        if(device->client)
+        if(device->client) {
+            IAudioClient_Stop(device->client);
             IAudioClient_Release(device->client);
+        }
         if(device->render)
             IAudioRenderClient_Release(device->render);
-        if(device->clock)
-            IAudioClock_Release(device->clock);
         if(device->volume)
             IAudioStreamVolume_Release(device->volume);
 
@@ -323,6 +319,7 @@ static HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGU
     device->mmdevice = mmdevice;
     device->guid = devGUID;
     device->sleepev = CreateEventW(0, 0, 0, 0);
+    device->buflen = ds_hel_buflen;
 
     hr = DSOUND_ReopenDevice(device, FALSE);
     if (FAILED(hr))
@@ -381,13 +378,9 @@ static HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGU
 
     ZeroMemory(&device->volpan, sizeof(device->volpan));
 
-    hr = DSOUND_PrimaryCreate(device);
-    if (hr == DS_OK) {
-        device->thread_finished = CreateEventW(0, 0, 0, 0);
-        device->thread = CreateThread(0, 0, DSOUND_mixthread, device, 0, 0);
-        SetThreadPriority(device->thread, THREAD_PRIORITY_TIME_CRITICAL);
-    } else
-        WARN("DSOUND_PrimaryCreate failed: %08x\n", hr);
+    device->thread_finished = CreateEventW(0, 0, 0, 0);
+    device->thread = CreateThread(0, 0, DSOUND_mixthread, device, 0, 0);
+    SetThreadPriority(device->thread, THREAD_PRIORITY_TIME_CRITICAL);
 
     *ppDevice = device;
     list_add_tail(&DSOUND_renderers, &device->entry);
@@ -851,7 +844,6 @@ static HRESULT WINAPI IDirectSound8Impl_SetCooperativeLevel(IDirectSound8 *iface
 {
     IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
     DirectSoundDevice *device = This->device;
-    DWORD oldlevel;
     HRESULT hr = S_OK;
 
     TRACE("(%p,%p,%s)\n", This, hwnd, dumpCooperativeLevel(level));
@@ -868,15 +860,10 @@ static HRESULT WINAPI IDirectSound8Impl_SetCooperativeLevel(IDirectSound8 *iface
 
     RtlAcquireResourceExclusive(&device->buffer_list_lock, TRUE);
     EnterCriticalSection(&device->mixlock);
-    oldlevel = device->priolevel;
-    device->priolevel = level;
-    if ((level == DSSCL_WRITEPRIMARY) != (oldlevel == DSSCL_WRITEPRIMARY)) {
+    if ((level == DSSCL_WRITEPRIMARY) != (device->priolevel == DSSCL_WRITEPRIMARY))
         hr = DSOUND_ReopenDevice(device, level == DSSCL_WRITEPRIMARY);
-        if (FAILED(hr))
-            device->priolevel = oldlevel;
-        else
-            DSOUND_PrimaryOpen(device);
-    }
+    if (SUCCEEDED(hr))
+        device->priolevel = level;
     LeaveCriticalSection(&device->mixlock);
     RtlReleaseResource(&device->buffer_list_lock);
     return hr;
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 8bf9c9d..3da0c19 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -100,7 +100,6 @@ struct DirectSoundDevice
 
     IMMDevice *mmdevice;
     IAudioClient *client;
-    IAudioClock *clock;
     IAudioStreamVolume *volume;
     IAudioRenderClient *render;
 
@@ -204,13 +203,11 @@ void DSOUND_ParseSpeakerConfig(DirectSoundDevice *device) DECLSPEC_HIDDEN;
 
 /* primary.c */
 
-HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device) DECLSPEC_HIDDEN;
 HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device) DECLSPEC_HIDDEN;
 HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device) DECLSPEC_HIDDEN;
 HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device) DECLSPEC_HIDDEN;
 LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex) DECLSPEC_HIDDEN;
 HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave) DECLSPEC_HIDDEN;
-HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device) DECLSPEC_HIDDEN;
 HRESULT primarybuffer_create(DirectSoundDevice *device, IDirectSoundBufferImpl **ppdsb,
     const DSBUFFERDESC *dsbd) DECLSPEC_HIDDEN;
 void primarybuffer_destroy(IDirectSoundBufferImpl *This) DECLSPEC_HIDDEN;
diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c
index a5fe039..72c9475 100644
--- a/dlls/dsound/primary.c
+++ b/dlls/dsound/primary.c
@@ -197,16 +197,8 @@ static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client
     return S_OK;
 }
 
-HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
+static void DSOUND_ReleaseDevice(DirectSoundDevice *device)
 {
-    WAVEFORMATEX *wfx = NULL;
-    HRESULT hres;
-    REFERENCE_TIME period, buflen = 800000;
-    UINT32 frames;
-    DWORD period_ms;
-
-    TRACE("(%p, %d)\n", device, forcewave);
-
     if(device->client){
         IAudioClient_Release(device->client);
         device->client = NULL;
@@ -215,10 +207,6 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
         IAudioRenderClient_Release(device->render);
         device->render = NULL;
     }
-    if(device->clock){
-        IAudioClock_Release(device->clock);
-        device->clock = NULL;
-    }
     if(device->volume){
         IAudioStreamVolume_Release(device->volume);
         device->volume = NULL;
@@ -229,145 +217,75 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
         device->playpos %= device->buflen;
         device->pad = 0;
     }
-
-    hres = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
-            CLSCTX_INPROC_SERVER, NULL, (void **)&device->client);
-    if(FAILED(hres)) {
-        WARN("Activate failed: %08x\n", hres);
-        return hres;
-    }
-
-    device->speaker_config = DSOUND_FindSpeakerConfig(device->mmdevice, 0);
-
-    DSOUND_ParseSpeakerConfig(device);
-
-    hres = DSOUND_WaveFormat(device, device->client, forcewave, &wfx);
-    if (FAILED(hres)) {
-        IAudioClient_Release(device->client);
-        device->client = NULL;
-        return hres;
-    }
-    HeapFree(GetProcessHeap(), 0, device->pwfx);
-    device->pwfx = wfx;
-
-    hres = IAudioClient_Initialize(device->client,
-            AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST |
-            AUDCLNT_STREAMFLAGS_EVENTCALLBACK, buflen, 0, device->pwfx, NULL);
-    if(FAILED(hres)){
-        IAudioClient_Release(device->client);
-        device->client = NULL;
-        WARN("Initialize failed: %08x\n", hres);
-        return hres;
-    }
-    IAudioClient_SetEventHandle(device->client, device->sleepev);
-
-    hres = IAudioClient_GetService(device->client, &IID_IAudioRenderClient,
-            (void**)&device->render);
-    if(FAILED(hres)){
-        IAudioClient_Release(device->client);
-        device->client = NULL;
-        WARN("GetService failed: %08x\n", hres);
-        return hres;
-    }
-
-    hres = IAudioClient_GetService(device->client, &IID_IAudioClock,
-            (void**)&device->clock);
-    if(FAILED(hres)){
-        IAudioClient_Release(device->client);
-        IAudioRenderClient_Release(device->render);
-        device->client = NULL;
-        device->render = NULL;
-        WARN("GetService failed: %08x\n", hres);
-        return hres;
-    }
-
-    hres = IAudioClient_GetService(device->client, &IID_IAudioStreamVolume,
-            (void**)&device->volume);
-    if(FAILED(hres)){
-        IAudioClient_Release(device->client);
-        IAudioRenderClient_Release(device->render);
-        IAudioClock_Release(device->clock);
-        device->client = NULL;
-        device->render = NULL;
-        device->clock = NULL;
-        WARN("GetService failed: %08x\n", hres);
-        return hres;
-    }
-
-    /* Now kick off the timer so the event fires periodically */
-    hres = IAudioClient_Start(device->client);
-    if (FAILED(hres))
-        WARN("starting failed with %08x\n", hres);
-
-    hres = IAudioClient_GetStreamLatency(device->client, &period);
-    if (FAILED(hres)) {
-        WARN("GetStreamLatency failed with %08x\n", hres);
-        period = 100000;
-    }
-    period_ms = (period + 9999) / 10000;
-
-    hres = IAudioClient_GetBufferSize(device->client, &frames);
-    if (FAILED(hres)) {
-        WARN("GetBufferSize failed with %08x\n", hres);
-        frames = (UINT64)device->pwfx->nSamplesPerSec * buflen / 10000000;
-    }
-
-    device->fraglen = MulDiv(device->pwfx->nSamplesPerSec, period, 10000000) * device->pwfx->nBlockAlign;
-    device->aclen = frames * device->pwfx->nBlockAlign;
-    TRACE("period %u ms fraglen %u buflen %u\n", period_ms, device->fraglen, device->aclen);
-
-    if (period_ms < 3)
-        device->sleeptime = 5;
-    else
-        device->sleeptime = period_ms * 5 / 2;
-
-    return S_OK;
 }
 
-HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
+static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device, WAVEFORMATEX *wfx, DWORD frames, BOOL forcewave)
 {
-	IDirectSoundBufferImpl** dsb = device->buffers;
-	LPBYTE newbuf;
-        int i;
+    IDirectSoundBufferImpl** dsb = device->buffers;
+    LPBYTE newbuf;
+    DWORD new_buflen;
+    BOOL mixfloat = FALSE;
+    int i;
 
-	TRACE("(%p)\n", device);
+    TRACE("(%p)\n", device);
 
-	/* on original windows, the buffer it set to a fixed size, no matter what the settings are.
-	   on windows this size is always fixed (tested on win-xp) */
-	if (!device->buflen)
-		device->buflen = ds_hel_buflen;
-	device->buflen -= device->buflen % device->pwfx->nBlockAlign;
+    new_buflen = device->buflen;
+    new_buflen -= new_buflen % wfx->nBlockAlign;
 
-	if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
-	else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
+    if (wfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
+        (wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+         IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)wfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
+        mixfloat = TRUE;
 
     /* reallocate emulated primary buffer */
-    if (device->buffer)
-        newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer, device->buflen);
-    else
-        newbuf = HeapAlloc(GetProcessHeap(),0, device->buflen);
+    if (forcewave) {
+        if (device->buffer)
+            newbuf = HeapReAlloc(GetProcessHeap(), 0, device->buffer, new_buflen);
+        else
+            newbuf = HeapAlloc(GetProcessHeap(), 0, new_buflen);
 
-    if (!newbuf) {
-        ERR("failed to allocate primary buffer\n");
-        return DSERR_OUTOFMEMORY;
-        /* but the old buffer might still exist and must be re-prepared */
+        if (!newbuf) {
+            ERR("failed to allocate primary buffer\n");
+            return DSERR_OUTOFMEMORY;
+        }
+        FillMemory(newbuf, new_buflen, (wfx->wBitsPerSample == 8) ? 128 : 0);
+    } else if (!mixfloat) {
+        DWORD alloc_len = frames * sizeof(float);
+
+        if (device->buffer)
+            newbuf = HeapReAlloc(GetProcessHeap(), 0, device->buffer, alloc_len);
+        else
+            newbuf = HeapAlloc(GetProcessHeap(), 0, alloc_len);
+
+        if (!newbuf) {
+            ERR("failed to allocate primary buffer\n");
+            return DSERR_OUTOFMEMORY;
+        }
+        FillMemory(newbuf, alloc_len, (wfx->wBitsPerSample == 8) ? 128 : 0);
+    } else {
+        HeapFree(GetProcessHeap(), 0, device->buffer);
+        newbuf = NULL;
     }
 
-    device->writelead = (device->pwfx->nSamplesPerSec / 100) * device->pwfx->nBlockAlign;
-
     device->buffer = newbuf;
+    device->buflen = new_buflen;
+    HeapFree(GetProcessHeap(), 0, device->pwfx);
+    device->pwfx = wfx;
+
+    if (device->state == STATE_PLAYING)
+        device->state = STATE_STARTING;
+    else if (device->state == STATE_STOPPING)
+        device->state = STATE_STOPPED;
+
+    device->writelead = (wfx->nSamplesPerSec / 100) * wfx->nBlockAlign;
 
     TRACE("buflen: %u, fraglen: %u\n", device->buflen, device->fraglen);
 
-    if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
-            (device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
-             IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)device->pwfx)->SubFormat,
-                 &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
+    if (!mixfloat)
+        device->normfunction = normfunctions[wfx->wBitsPerSample/8 - 1];
+    else
         device->normfunction = NULL;
-    else
-        device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
 
-    FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
     device->playpos = 0;
 
     for (i = 0; i < device->nrofbuffers; i++) {
@@ -379,35 +297,105 @@ HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
     return DS_OK;
 }
 
-
-static void DSOUND_PrimaryClose(DirectSoundDevice *device)
+HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
 {
-    HRESULT hr;
+    HRESULT hres;
+    REFERENCE_TIME period;
+    UINT32 frames;
+    DWORD period_ms;
+    IAudioClient *client = NULL;
+    IAudioRenderClient *render = NULL;
+    IAudioStreamVolume *volume = NULL;
+    DWORD fraglen;
+    WAVEFORMATEX *wfx = NULL;
+    DWORD oldspeakerconfig = device->speaker_config;
 
-    TRACE("(%p)\n", device);
+    TRACE("(%p, %d)\n", device, forcewave);
 
-    if(device->client){
-        hr = IAudioClient_Stop(device->client);
-        if(FAILED(hr))
-            WARN("Stop failed: %08x\n", hr);
+    hres = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
+            CLSCTX_INPROC_SERVER, NULL, (void **)&client);
+    if(FAILED(hres)){
+        WARN("Activate failed: %08x\n", hres);
+        return hres;
     }
-}
 
-HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device)
-{
-	HRESULT err = DS_OK;
-	TRACE("(%p)\n", device);
+    hres = DSOUND_WaveFormat(device, client, forcewave, &wfx);
+    if (FAILED(hres)) {
+        IAudioClient_Release(client);
+        return hres;
+    }
+
+    hres = IAudioClient_Initialize(client,
+            AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST |
+            AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 800000, 0, wfx, NULL);
+    if(FAILED(hres)){
+        IAudioClient_Release(client);
+        ERR("Initialize failed: %08x\n", hres);
+        return hres;
+    }
+
+    IAudioClient_SetEventHandle(client, device->sleepev);
+
+    hres = IAudioClient_GetService(client, &IID_IAudioRenderClient, (void**)&render);
+    if(FAILED(hres))
+        goto err_service;
+
+    hres = IAudioClient_GetService(client, &IID_IAudioStreamVolume, (void**)&volume);
+    if(FAILED(hres))
+        goto err_service;
+
+    /* Now kick off the timer so the event fires periodically */
+    hres = IAudioClient_Start(client);
+    if (FAILED(hres)) {
+        WARN("Start failed with %08x\n", hres);
+        goto err;
+    }
+    hres = IAudioClient_GetStreamLatency(client, &period);
+    if (FAILED(hres)) {
+        WARN("GetStreamLatency failed with %08x\n", hres);
+        goto err;
+    }
+    hres = IAudioClient_GetBufferSize(client, &frames);
+    if (FAILED(hres)) {
+        WARN("GetBufferSize failed with %08x\n", hres);
+        goto err;
+    }
+
+    period_ms = (period + 9999) / 10000;
+    fraglen = MulDiv(wfx->nSamplesPerSec, period, 10000000) * wfx->nBlockAlign;
+    TRACE("period %u ms fraglen %u buflen %u\n", period_ms, fraglen, frames * wfx->nBlockAlign);
+
+    hres = DSOUND_PrimaryOpen(device, wfx, frames, forcewave);
+    if(FAILED(hres))
+        goto err;
+
+    DSOUND_ReleaseDevice(device);
+    device->client = client;
+    device->render = render;
+    device->volume = volume;
+    device->fraglen = fraglen;
+    device->aclen = frames * wfx->nBlockAlign;
 
-	device->buflen = ds_hel_buflen;
-	err = DSOUND_PrimaryOpen(device);
+    if (period_ms < 3)
+        device->sleeptime = 5;
+    else
+        device->sleeptime = period_ms * 5 / 2;
 
-	if (err != DS_OK) {
-		WARN("DSOUND_PrimaryOpen failed\n");
-		return err;
-	}
+    return S_OK;
 
-	device->state = STATE_STOPPED;
-	return DS_OK;
+err_service:
+    ERR("GetService failed: %08x\n", hres);
+err:
+    device->speaker_config = oldspeakerconfig;
+    DSOUND_ParseSpeakerConfig(device);
+    if (volume)
+        IAudioStreamVolume_Release(volume);
+    if (render)
+        IAudioRenderClient_Release(render);
+    if (client)
+        IAudioClient_Release(client);
+    HeapFree(GetProcessHeap(), 0, wfx);
+    return hres;
 }
 
 HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
@@ -417,8 +405,6 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
 	/* **** */
 	EnterCriticalSection(&(device->mixlock));
 
-	DSOUND_PrimaryClose(device);
-
 	if(device->primary && (device->primary->ref || device->primary->numIfaces))
 		WARN("Destroying primary buffer while references held (%u %u)\n", device->primary->ref, device->primary->numIfaces);
 
@@ -470,10 +456,14 @@ WAVEFORMATEX *DSOUND_CopyFormat(const WAVEFORMATEX *wfex)
     WAVEFORMATEX *pwfx;
     if(wfex->wFormatTag == WAVE_FORMAT_PCM){
         pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX));
+        if (!pwfx)
+            return NULL;
         CopyMemory(pwfx, wfex, sizeof(PCMWAVEFORMAT));
         pwfx->cbSize = 0;
     }else{
         pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX) + wfex->cbSize);
+        if (!pwfx)
+            return NULL;
         CopyMemory(pwfx, wfex, sizeof(WAVEFORMATEX) + wfex->cbSize);
     }
 
@@ -490,7 +480,6 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passe
 	HRESULT err = S_OK;
 	WAVEFORMATEX *old_fmt;
 	WAVEFORMATEXTENSIBLE *fmtex, *passed_fmtex = (WAVEFORMATEXTENSIBLE*)passed_fmt;
-	BOOL forced = (device->priolevel == DSSCL_WRITEPRIMARY);
 
 	TRACE("(%p,%p)\n", device, passed_fmt);
 
@@ -540,28 +529,20 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passe
 			fmtex->Samples.wValidBitsPerSample = fmtex->Format.wBitsPerSample;
 		}
 
-		DSOUND_PrimaryClose(device);
-
-		err = DSOUND_ReopenDevice(device, forced);
+		err = DSOUND_ReopenDevice(device, TRUE);
 		if (FAILED(err)) {
 			ERR("No formats could be opened\n");
-			goto done;
-		}
-
-		err = DSOUND_PrimaryOpen(device);
-		if (err != DS_OK) {
-			ERR("DSOUND_PrimaryOpen failed\n");
-			goto done;
-		}
-
-done:
-		if (err != DS_OK)
+			HeapFree(GetProcessHeap(), 0, device->primary_pwfx);
 			device->primary_pwfx = old_fmt;
-		else
+		} else
 			HeapFree(GetProcessHeap(), 0, old_fmt);
 	} else {
-		HeapFree(GetProcessHeap(), 0, device->primary_pwfx);
-		device->primary_pwfx = DSOUND_CopyFormat(passed_fmt);
+		WAVEFORMATEX *wfx = DSOUND_CopyFormat(passed_fmt);
+		if (wfx) {
+			HeapFree(GetProcessHeap(), 0, device->primary_pwfx);
+			device->primary_pwfx = wfx;
+		} else
+			err = DSERR_OUTOFMEMORY;
 	}
 
 out:
-- 
2.8.2





More information about the wine-patches mailing list