Robert Reif wrote:
Move initialization to IDirectSound_Initialize. Fix error paths to handle a failed IDirectSound_Initialize. Add tests for IDirectSound_Initialize.
This patch fixes wine to fail the same way windows does when run with a defective device driver.
This revised patch fixes a problem when trying to initialize an initialized object when creating the object more than once.
Index: dlls/dsound/dsound.c =================================================================== RCS file: /home/wine/wine/dlls/dsound/dsound.c,v retrieving revision 1.31 diff -u -p -r1.31 dsound.c --- dlls/dsound/dsound.c 15 Mar 2005 15:40:36 -0000 1.31 +++ dlls/dsound/dsound.c 6 May 2005 16:02:54 -0000 @@ -684,11 +684,107 @@ static HRESULT WINAPI IDirectSoundImpl_I LPCGUID lpcGuid) { IDirectSoundImpl *This = (IDirectSoundImpl *)iface; + HRESULT hr = DS_OK; TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
- This->initialized = TRUE; + if (This->initialized == TRUE) { + WARN("already initialized\n"); + return DSERR_ALREADYINITIALIZED; + }
- return DS_OK; + /* If the driver requests being opened through MMSYSTEM + * (which is recommended by the DDK), it is supposed to happen + * before the DirectSound interface is opened */ + if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) + { + DWORD flags = CALLBACK_FUNCTION; + + /* disable direct sound if requested */ + if (ds_hw_accel != DS_HW_ACCEL_EMULATION) + flags |= WAVE_DIRECTSOUND; + + hr = mmErr(waveOutOpen(&(This->hwo), + This->drvdesc.dnDevNode, This->pwfx, + (DWORD)DSOUND_callback, (DWORD)This, + flags)); + if (hr != DS_OK) { + WARN("waveOutOpen failed\n"); + return hr; + } + } + + if (This->driver) { + hr = IDsDriver_Open(This->driver); + if (hr != DS_OK) { + WARN("IDsDriver_Open failed\n"); + return hr; + } + + /* the driver is now open, so it's now allowed to call GetCaps */ + hr = IDsDriver_GetCaps(This->driver,&(This->drvcaps)); + if (hr != DS_OK) { + WARN("IDsDriver_GetCaps failed\n"); + return hr; + } + } else { + WAVEOUTCAPSA woc; + hr = mmErr(waveOutGetDevCapsA(This->drvdesc.dnDevNode, &woc, sizeof(woc))); + if (hr != DS_OK) { + WARN("waveOutGetDevCaps failed\n"); + return hr; + } + ZeroMemory(&This->drvcaps, sizeof(This->drvcaps)); + if ((woc.dwFormats & WAVE_FORMAT_1M08) || + (woc.dwFormats & WAVE_FORMAT_2M08) || + (woc.dwFormats & WAVE_FORMAT_4M08) || + (woc.dwFormats & WAVE_FORMAT_48M08) || + (woc.dwFormats & WAVE_FORMAT_96M08)) { + This->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; + This->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; + } + if ((woc.dwFormats & WAVE_FORMAT_1M16) || + (woc.dwFormats & WAVE_FORMAT_2M16) || + (woc.dwFormats & WAVE_FORMAT_4M16) || + (woc.dwFormats & WAVE_FORMAT_48M16) || + (woc.dwFormats & WAVE_FORMAT_96M16)) { + This->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; + This->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; + } + if ((woc.dwFormats & WAVE_FORMAT_1S08) || + (woc.dwFormats & WAVE_FORMAT_2S08) || + (woc.dwFormats & WAVE_FORMAT_4S08) || + (woc.dwFormats & WAVE_FORMAT_48S08) || + (woc.dwFormats & WAVE_FORMAT_96S08)) { + This->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; + This->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; + } + if ((woc.dwFormats & WAVE_FORMAT_1S16) || + (woc.dwFormats & WAVE_FORMAT_2S16) || + (woc.dwFormats & WAVE_FORMAT_4S16) || + (woc.dwFormats & WAVE_FORMAT_48S16) || + (woc.dwFormats & WAVE_FORMAT_96S16)) { + This->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; + This->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; + } + if (ds_emuldriver) + This->drvcaps.dwFlags |= DSCAPS_EMULDRIVER; + This->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN; + This->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX; + This->drvcaps.dwPrimaryBuffers = 1; + } + + hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)This); + if (hr == DS_OK) { + This->initialized = TRUE; + DSOUND_renderer = (IDirectSoundImpl*)This; + timeBeginPeriod(DS_TIME_RES); + DSOUND_renderer->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer, + (DWORD)DSOUND_renderer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); + } else { + WARN("DSOUND_PrimaryCreate failed\n"); + } + + return hr; }
static HRESULT WINAPI IDirectSoundImpl_VerifyCertification( @@ -841,11 +937,11 @@ HRESULT WINAPI IDirectSoundImpl_Create( return DSERR_OUTOFMEMORY; }
- pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM; /* We rely on the sound driver to return the actual sound format of * the device if it does not support 22050x8x2 and is given the * WAVE_DIRECTSOUND flag. */ + pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM; pDS->pwfx->nSamplesPerSec = 22050; pDS->pwfx->wBitsPerSample = 8; pDS->pwfx->nChannels = 2; @@ -853,95 +949,6 @@ HRESULT WINAPI IDirectSoundImpl_Create( pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign; pDS->pwfx->cbSize = 0;
- /* If the driver requests being opened through MMSYSTEM - * (which is recommended by the DDK), it is supposed to happen - * before the DirectSound interface is opened */ - if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) - { - DWORD flags = CALLBACK_FUNCTION; - - /* disable direct sound if requested */ - if (ds_hw_accel != DS_HW_ACCEL_EMULATION) - flags |= WAVE_DIRECTSOUND; - - err = mmErr(waveOutOpen(&(pDS->hwo), - pDS->drvdesc.dnDevNode, pDS->pwfx, - (DWORD)DSOUND_callback, (DWORD)pDS, - flags)); - if (err != DS_OK) { - WARN("waveOutOpen failed\n"); - HeapFree(GetProcessHeap(),0,pDS); - *ppDS = NULL; - return err; - } - } - - if (drv) { - err = IDsDriver_Open(drv); - if (err != DS_OK) { - WARN("IDsDriver_Open failed\n"); - HeapFree(GetProcessHeap(),0,pDS); - *ppDS = NULL; - return err; - } - - /* the driver is now open, so it's now allowed to call GetCaps */ - err = IDsDriver_GetCaps(drv,&(pDS->drvcaps)); - if (err != DS_OK) { - WARN("IDsDriver_GetCaps failed\n"); - HeapFree(GetProcessHeap(),0,pDS); - *ppDS = NULL; - return err; - } - } else { - WAVEOUTCAPSA woc; - err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc))); - if (err != DS_OK) { - WARN("waveOutGetDevCaps failed\n"); - HeapFree(GetProcessHeap(),0,pDS); - *ppDS = NULL; - return err; - } - ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps)); - if ((woc.dwFormats & WAVE_FORMAT_1M08) || - (woc.dwFormats & WAVE_FORMAT_2M08) || - (woc.dwFormats & WAVE_FORMAT_4M08) || - (woc.dwFormats & WAVE_FORMAT_48M08) || - (woc.dwFormats & WAVE_FORMAT_96M08)) { - pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; - pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; - } - if ((woc.dwFormats & WAVE_FORMAT_1M16) || - (woc.dwFormats & WAVE_FORMAT_2M16) || - (woc.dwFormats & WAVE_FORMAT_4M16) || - (woc.dwFormats & WAVE_FORMAT_48M16) || - (woc.dwFormats & WAVE_FORMAT_96M16)) { - pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; - pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; - } - if ((woc.dwFormats & WAVE_FORMAT_1S08) || - (woc.dwFormats & WAVE_FORMAT_2S08) || - (woc.dwFormats & WAVE_FORMAT_4S08) || - (woc.dwFormats & WAVE_FORMAT_48S08) || - (woc.dwFormats & WAVE_FORMAT_96S08)) { - pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; - pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; - } - if ((woc.dwFormats & WAVE_FORMAT_1S16) || - (woc.dwFormats & WAVE_FORMAT_2S16) || - (woc.dwFormats & WAVE_FORMAT_4S16) || - (woc.dwFormats & WAVE_FORMAT_48S16) || - (woc.dwFormats & WAVE_FORMAT_96S16)) { - pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; - pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; - } - if (ds_emuldriver) - pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER; - pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN; - pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX; - pDS->drvcaps.dwPrimaryBuffers = 1; - } - InitializeCriticalSection(&(pDS->mixlock)); pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
@@ -1610,16 +1617,6 @@ HRESULT WINAPI DSOUND_Create(
TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
- if (pUnkOuter != NULL) { - WARN("invalid parameter: pUnkOuter != NULL\n"); - return DSERR_INVALIDPARAM; - } - - if (ppDS == NULL) { - WARN("invalid parameter: ppDS == NULL\n"); - return DSERR_INVALIDPARAM; - } - /* Get dsound configuration */ setup_dsound_options();
@@ -1649,22 +1646,11 @@ HRESULT WINAPI DSOUND_Create( LPDIRECTSOUND8 pDS; hr = IDirectSoundImpl_Create(&devGuid, &pDS); if (hr == DS_OK) { - hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS); - if (hr == DS_OK) { - hr = IDirectSound_IDirectSound_Create(pDS, ppDS); - if (*ppDS) { - IDirectSound_IDirectSound_AddRef(*ppDS); - - DSOUND_renderer = (IDirectSoundImpl*)pDS; - timeBeginPeriod(DS_TIME_RES); - DSOUND_renderer->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer, - (DWORD)DSOUND_renderer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); - } else { - WARN("IDirectSound_IDirectSound_Create failed\n"); - IDirectSound8_Release(pDS); - } - } else { - WARN("DSOUND_PrimaryCreate failed\n"); + hr = IDirectSound_IDirectSound_Create(pDS, ppDS); + if (*ppDS) + IDirectSound_IDirectSound_AddRef(*ppDS); + else { + WARN("IDirectSound_IDirectSound_Create failed\n"); IDirectSound8_Release(pDS); } } else @@ -1695,12 +1681,33 @@ HRESULT WINAPI DirectSoundCreate( IUnknown *pUnkOuter) { HRESULT hr; + LPDIRECTSOUND pDS;
TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
- hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter); - if (hr == DS_OK) - IDirectSound_Initialize(*ppDS, lpcGUID); + if (ppDS == NULL) { + WARN("invalid parameter: ppDS == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (pUnkOuter != NULL) { + WARN("invalid parameter: pUnkOuter != NULL\n"); + *ppDS = 0; + return DSERR_INVALIDPARAM; + } + + hr = DSOUND_Create(lpcGUID, &pDS, pUnkOuter); + if (hr == DS_OK) { + IDirectSound_IDirectSound * pp = (IDirectSound_IDirectSound *)pDS; + IDirectSoundImpl * p = (IDirectSoundImpl *)(pp->pds); + if (!(p->initialized)) { + hr = IDirectSound_Initialize(pDS, lpcGUID); + if (hr != DS_OK) + IDirectSound_Release(pDS); + } + } + + *ppDS = pDS;
return hr; } @@ -1715,16 +1722,6 @@ HRESULT WINAPI DSOUND_Create8(
TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
- if (pUnkOuter != NULL) { - WARN("invalid parameter: pUnkOuter != NULL\n"); - return DSERR_INVALIDPARAM; - } - - if (ppDS == NULL) { - WARN("invalid parameter: ppDS == NULL\n"); - return DSERR_INVALIDPARAM; - } - /* Get dsound configuration */ setup_dsound_options();
@@ -1754,22 +1751,11 @@ HRESULT WINAPI DSOUND_Create8( LPDIRECTSOUND8 pDS; hr = IDirectSoundImpl_Create(&devGuid, &pDS); if (hr == DS_OK) { - hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS); - if (hr == DS_OK) { - hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS); - if (*ppDS) { - IDirectSound8_IDirectSound8_AddRef(*ppDS); - - DSOUND_renderer = (IDirectSoundImpl*)pDS; - timeBeginPeriod(DS_TIME_RES); - DSOUND_renderer->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer, - (DWORD)DSOUND_renderer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); - } else { - WARN("IDirectSound8_IDirectSound8_Create failed\n"); - IDirectSound8_Release(pDS); - } - } else { - WARN("DSOUND_PrimaryCreate failed\n"); + hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS); + if (*ppDS) + IDirectSound8_IDirectSound8_AddRef(*ppDS); + else { + WARN("IDirectSound8_IDirectSound8_Create failed\n"); IDirectSound8_Release(pDS); } } else @@ -1800,12 +1786,33 @@ HRESULT WINAPI DirectSoundCreate8( IUnknown *pUnkOuter) { HRESULT hr; + LPDIRECTSOUND8 pDS;
TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
- hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter); - if (hr == DS_OK) - IDirectSound8_Initialize(*ppDS, lpcGUID); + if (ppDS == NULL) { + WARN("invalid parameter: ppDS == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (pUnkOuter != NULL) { + WARN("invalid parameter: pUnkOuter != NULL\n"); + *ppDS = 0; + return DSERR_INVALIDPARAM; + } + + hr = DSOUND_Create8(lpcGUID, &pDS, pUnkOuter); + if (hr == DS_OK) { + IDirectSound8_IDirectSound8 * pp = (IDirectSound8_IDirectSound8 *)pDS; + IDirectSoundImpl * p = (IDirectSoundImpl *)(pp->pds); + if (!(p->initialized)) { + hr = IDirectSound8_Initialize(pDS, lpcGUID); + if (hr != DS_OK) + IDirectSound8_Release(pDS); + } + } + + *ppDS = pDS;
return hr; } Index: dlls/dsound/tests/dsound.c =================================================================== RCS file: /home/wine/wine/dlls/dsound/tests/dsound.c,v retrieving revision 1.52 diff -u -p -r1.52 dsound.c --- dlls/dsound/tests/dsound.c 30 Mar 2005 10:21:44 -0000 1.52 +++ dlls/dsound/tests/dsound.c 6 May 2005 16:02:55 -0000 @@ -93,16 +93,21 @@ static void IDirectSound_test(LPDIRECTSO "IDirectSound_Initialize() failed: %s\n",DXGetErrorString8(rc)); if (rc==DSERR_NODRIVER) { trace(" No Driver\n"); - return; + goto EXIT; } else if (rc==E_FAIL) { trace(" No Device\n"); - return; + goto EXIT; } else if (rc==DSERR_ALLOCATED) { trace(" Already In Use\n"); - return; + goto EXIT; } }
+ rc=IDirectSound_Initialize(dso,lpGuid); + ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound_Initialize() " + "should have returned DSERR_ALREADYINITIALIZED: %s\n", + DXGetErrorString8(rc)); + /* DSOUND: Error: Invalid caps buffer */ rc=IDirectSound_GetCaps(dso,0); ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) " @@ -158,6 +163,7 @@ static void IDirectSound_test(LPDIRECTSO speaker_config,new_speaker_config); }
+EXIT: ref=IDirectSound_Release(dso); ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref); } @@ -238,6 +244,8 @@ static void IDirectSound_tests() rc=DirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL); ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) " "should have failed: %s\n",DXGetErrorString8(rc)); + if (rc==DS_OK && dso) + IDirectSound_Release(dso); }
static HRESULT test_dsound(LPGUID lpGuid) Index: dlls/dsound/tests/dsound8.c =================================================================== RCS file: /home/wine/wine/dlls/dsound/tests/dsound8.c,v retrieving revision 1.21 diff -u -p -r1.21 dsound8.c --- dlls/dsound/tests/dsound8.c 11 Apr 2005 12:52:00 -0000 1.21 +++ dlls/dsound/tests/dsound8.c 6 May 2005 16:02:56 -0000 @@ -108,16 +108,21 @@ static void IDirectSound8_test(LPDIRECTS "IDirectSound8_Initialize() failed: %s\n",DXGetErrorString8(rc)); if (rc==DSERR_NODRIVER) { trace(" No Driver\n"); - return; + goto EXIT; } else if (rc==E_FAIL) { trace(" No Device\n"); - return; + goto EXIT; } else if (rc==DSERR_ALLOCATED) { trace(" Already In Use\n"); - return; + goto EXIT; } }
+ rc=IDirectSound8_Initialize(dso,lpGuid); + ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound8_Initialize() " + "should have returned DSERR_ALREADYINITIALIZED: %s\n", + DXGetErrorString8(rc)); + /* DSOUND: Error: Invalid caps buffer */ rc=IDirectSound8_GetCaps(dso,0); ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() " @@ -177,6 +182,7 @@ static void IDirectSound8_test(LPDIRECTS ok(rc==DS_OK||rc==E_NOTIMPL,"IDirectSound8_VerifyCertification() failed: %s\n", DXGetErrorString8(rc));
+EXIT: ref=IDirectSound8_Release(dso); ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref); }