revised dsound DirectSound/DirectSound8 split patch

Robert Reif reif at earthlink.net
Thu Jul 1 06:01:53 CDT 2004


Sorry, had wrong second file attached.

Wine currently defines DirectSoundCreate and DirectSoundCreate8
as the same function and only supplies a DirectSound8 implementation.
They are two separate functions and interfaces in windows.

This patch separates DirectSoundCreate8 into two functions and
adds a IDirectSound implementation.  Adds proper COM behavior
for QueryInterface for IDirectSound and IDirectSound8.  The
DirectSound code is moved from dsound_main.c to a new file
dsound.c.

Fixes a bug in the dsound.h header file for IDirectSound8
CreateSoundBuffer and DuplicateSoundBuffer.

Adds new tests for proper COM behavior and enables some
commented out code for tests that work on windows .  Adds
new tests for IDirectSound8.

To Do:
Do the same thing for DirectSoundCapture and DirectSoundBuffer.
Fix DirectSound to Release properly even when buffers are active.

-------------- next part --------------
Index: dlls/dsound/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/dsound/Makefile.in,v
retrieving revision 1.20
diff -u -r1.20 Makefile.in
--- dlls/dsound/Makefile.in	27 Jan 2004 00:11:17 -0000	1.20
+++ dlls/dsound/Makefile.in	1 Jul 2004 00:20:18 -0000
@@ -9,6 +9,7 @@
 C_SRCS = \
 	buffer.c \
 	capture.c \
+	dsound.c \
 	dsound_main.c \
 	mixer.c \
 	primary.c \
Index: dlls/dsound/dsound.spec
===================================================================
RCS file: /home/wine/wine/dlls/dsound/dsound.spec,v
retrieving revision 1.16
diff -u -r1.16 dsound.spec
--- dlls/dsound/dsound.spec	1 Oct 2003 03:05:25 -0000	1.16
+++ dlls/dsound/dsound.spec	1 Jul 2004 00:20:18 -0000
@@ -1,4 +1,4 @@
-1 stdcall DirectSoundCreate(ptr ptr ptr) DirectSoundCreate8
+1 stdcall DirectSoundCreate(ptr ptr ptr)
 2 stdcall DirectSoundEnumerateA(ptr ptr)
 3 stdcall DirectSoundEnumerateW(ptr ptr)
 4 stdcall -private DllCanUnloadNow() DSOUND_DllCanUnloadNow
Index: dlls/dsound/dsound_main.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/dsound_main.c,v
retrieving revision 1.99
diff -u -r1.99 dsound_main.c
--- dlls/dsound/dsound_main.c	19 May 2004 03:22:56 -0000	1.99
+++ dlls/dsound/dsound_main.c	1 Jul 2004 00:20:18 -0000
@@ -438,773 +438,6 @@
     return DS_OK;
 }
 
-
-static void _dump_DSBCAPS(DWORD xmask) {
-	struct {
-		DWORD	mask;
-		char	*name;
-	} flags[] = {
-#define FE(x) { x, #x },
-		FE(DSBCAPS_PRIMARYBUFFER)
-		FE(DSBCAPS_STATIC)
-		FE(DSBCAPS_LOCHARDWARE)
-		FE(DSBCAPS_LOCSOFTWARE)
-		FE(DSBCAPS_CTRL3D)
-		FE(DSBCAPS_CTRLFREQUENCY)
-		FE(DSBCAPS_CTRLPAN)
-		FE(DSBCAPS_CTRLVOLUME)
-		FE(DSBCAPS_CTRLPOSITIONNOTIFY)
-		FE(DSBCAPS_CTRLDEFAULT)
-		FE(DSBCAPS_CTRLALL)
-		FE(DSBCAPS_STICKYFOCUS)
-		FE(DSBCAPS_GLOBALFOCUS)
-		FE(DSBCAPS_GETCURRENTPOSITION2)
-		FE(DSBCAPS_MUTE3DATMAXDISTANCE)
-#undef FE
-	};
-	int	i;
-
-	for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
-		if ((flags[i].mask & xmask) == flags[i].mask)
-			DPRINTF("%s ",flags[i].name);
-}
-
-/*******************************************************************************
- *		IDirectSound
- */
-
-static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
-	LPDIRECTSOUND8 iface,HWND hwnd,DWORD level
-) {
-	ICOM_THIS(IDirectSoundImpl,iface);
-        TRACE("(%p,%08lx,%ld(%s))\n",This,(DWORD)hwnd,level,
-                level == DSSCL_NORMAL ? "DSSCL_NORMAL" :
-                level == DSSCL_PRIORITY ? "DSSCL_PRIORITY" :
-                level == DSSCL_EXCLUSIVE ? "DSSCL_EXCLUSIVE" :
-                level == DSSCL_WRITEPRIMARY ? "DSSCL_WRITEPRIMARY" : "Unknown");
-
-	if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
-		FIXME("level=%s not fully supported\n",
-			level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
-	}
-
-	This->priolevel = level;
-
-	return DS_OK;
-}
-
-static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
-	LPDIRECTSOUND8 iface,LPCDSBUFFERDESC dsbd,LPLPDIRECTSOUNDBUFFER8 ppdsb,LPUNKNOWN lpunk
-) {
-	ICOM_THIS(IDirectSoundImpl,iface);
-	LPWAVEFORMATEX	wfex;
-	HRESULT hres = DS_OK;
-
-	TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-
-	if (This == NULL) {
-		WARN("invalid parameter: This == NULL\n");
-		return DSERR_INVALIDPARAM;
-	}
-
-	if (dsbd == NULL) {
-		WARN("invalid parameter: dsbd == NULL\n");
-		return DSERR_INVALIDPARAM;
-	}
-
-        if (dsbd->dwSize != sizeof(DSBUFFERDESC) && dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
-                WARN("invalid parameter: dsbd\n");
-                return DSERR_INVALIDPARAM;
-        }
-
-	if (ppdsb == NULL) {
-		WARN("invalid parameter: ppdsb == NULL\n");
-		return DSERR_INVALIDPARAM;
-	}
-
-	if (TRACE_ON(dsound)) {
-		TRACE("(structsize=%ld)\n",dsbd->dwSize);
-		TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
-		_dump_DSBCAPS(dsbd->dwFlags);
-		DPRINTF(")\n");
-		TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
-		TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
-	}
-
-	wfex = dsbd->lpwfxFormat;
-
-	if (wfex)
-		TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
-		   "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
-		   wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
-		   wfex->nAvgBytesPerSec, wfex->nBlockAlign,
-		   wfex->wBitsPerSample, wfex->cbSize);
-
-	if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
-		if (This->primary) {
-			WARN("Primary Buffer already created\n");
-			IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
-			*ppdsb = (LPDIRECTSOUNDBUFFER8)(This->primary);
-		} else {
-			This->dsbd = *dsbd;
-			hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
-			if (This->primary) {
-				IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
-				*ppdsb = (LPDIRECTSOUNDBUFFER8)(This->primary);
-			} else 
-				WARN("PrimaryBufferImpl_Create failed\n");
-		}
-	} else {
-		IDirectSoundBufferImpl * dsb;
-		hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
-		if (dsb) {
-			hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
-			if (*ppdsb) {
-				dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
-				IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
-			} else
-				WARN("SecondaryBufferImpl_Create failed\n");
-		} else 
-			WARN("IDirectSoundBufferImpl_Create failed\n");
-	}
-
-	return hres;
-}
-
-static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
-	LPDIRECTSOUND8 iface,LPDIRECTSOUNDBUFFER8 psb,LPLPDIRECTSOUNDBUFFER8 ppdsb
-) {
-	ICOM_THIS(IDirectSoundImpl,iface);
-	IDirectSoundBufferImpl* pdsb;
-	IDirectSoundBufferImpl* dsb;
-	HRESULT hres = DS_OK;
-	TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-
-	if (This == NULL) {
-		WARN("invalid parameter: This == NULL\n");
-		return DSERR_INVALIDPARAM;
-	}
-
-	if (psb == NULL) {
-		WARN("invalid parameter: psb == NULL\n");
-		return DSERR_INVALIDPARAM;
-	}
-
-	if (ppdsb == NULL) {
-		WARN("invalid parameter: ppdsb == NULL\n");
-		return DSERR_INVALIDPARAM;
-	}
-
-	/* FIXME: hack to make sure we have a secondary buffer */
-	if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
-		ERR("trying to duplicate primary buffer\n");
-		*ppdsb = NULL;
-		return DSERR_INVALIDCALL;
-	}
-
-	pdsb = ((SecondaryBufferImpl *)psb)->dsb;
-
-	dsb = (IDirectSoundBufferImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
-
-	if (dsb == NULL) {
-		WARN("out of memory\n");
-		*ppdsb = NULL;
-		return DSERR_OUTOFMEMORY;
-	}
-
-	memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
-
-	if (pdsb->hwbuf) {
-		TRACE("duplicating hardware buffer\n");
-
-		hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
-		if (hres != DS_OK) {
-			TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
-			dsb->hwbuf = NULL;
-			/* allocate buffer */
-			if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
-				dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
-				if (dsb->buffer == NULL) {
-					WARN("out of memory\n");
-					HeapFree(GetProcessHeap(),0,dsb);
-					*ppdsb = NULL;
-					return DSERR_OUTOFMEMORY;
-				}
-
-				dsb->buffer->memory = (LPBYTE)HeapAlloc(GetProcessHeap(),0,dsb->buflen);
-				if (dsb->buffer->memory == NULL) {
-					WARN("out of memory\n");
-					HeapFree(GetProcessHeap(),0,dsb->buffer);
-					HeapFree(GetProcessHeap(),0,dsb);
-					*ppdsb = NULL;
-					return DSERR_OUTOFMEMORY;
-				}
-				dsb->buffer->ref = 1;
-
-				/* FIXME: copy buffer ? */
-			}
-		}
-	} else {
-		dsb->hwbuf = NULL;
-		dsb->buffer->ref++;
-	}
-
-	dsb->ref = 0;
-	dsb->state = STATE_STOPPED;
-	dsb->playpos = 0;
-	dsb->buf_mixpos = 0;
-	dsb->dsound = This;
-	dsb->ds3db = NULL;
-	dsb->iks = NULL; /* FIXME? */
-	dsb->dsb = NULL;
-	memcpy(&(dsb->wfx), &(pdsb->wfx), sizeof(dsb->wfx));
-	InitializeCriticalSection(&(dsb->lock));
-	/* register buffer */
-	RtlAcquireResourceExclusive(&(This->lock), TRUE);
-	{
-		IDirectSoundBufferImpl **newbuffers;
-		if (This->buffers)
-    			newbuffers = (IDirectSoundBufferImpl**)HeapReAlloc(GetProcessHeap(),0,This->buffers,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
-		else
-    			newbuffers = (IDirectSoundBufferImpl**)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
-
-		if (newbuffers) {
-			This->buffers = newbuffers;
-			This->buffers[This->nrofbuffers] = dsb;
-			This->nrofbuffers++;
-			TRACE("buffer count is now %d\n", This->nrofbuffers);
-		} else {
-			ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers);
-			IDirectSoundBuffer8_Release(psb);
-			DeleteCriticalSection(&(dsb->lock));
-			RtlReleaseResource(&(This->lock));
-			HeapFree(GetProcessHeap(),0,dsb);
-			*ppdsb = 0;
-			return DSERR_OUTOFMEMORY;
-		}
-	}
-	RtlReleaseResource(&(This->lock));
-	IDirectSound_AddRef(iface);
-	hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
-	if (*ppdsb) {
-		dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
-		IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
-	} else
-		WARN("SecondaryBufferImpl_Create failed\n");
-
-	return hres;
-}
-
-static HRESULT WINAPI IDirectSoundImpl_GetCaps(LPDIRECTSOUND8 iface,LPDSCAPS lpDSCaps) {
-	ICOM_THIS(IDirectSoundImpl,iface);
-	TRACE("(%p,%p)\n",This,lpDSCaps);
-
-	if (This == NULL) {
-		WARN("invalid parameter: This == NULL\n");
-		return DSERR_INVALIDPARAM;
-	}
-
-	if (lpDSCaps == NULL) {
-		WARN("invalid parameter: lpDSCaps = NULL\n");
-		return DSERR_INVALIDPARAM;
-	}
-
-	/* check is there is enough room */
-	if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
-		WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
-			lpDSCaps->dwSize, sizeof(*lpDSCaps));
-		return DSERR_INVALIDPARAM;
-	}
-
-	lpDSCaps->dwFlags                               = This->drvcaps.dwFlags;
-	TRACE("(flags=0x%08lx)\n",lpDSCaps->dwFlags);
-
-	lpDSCaps->dwMinSecondarySampleRate		= This->drvcaps.dwMinSecondarySampleRate;
-	lpDSCaps->dwMaxSecondarySampleRate		= This->drvcaps.dwMaxSecondarySampleRate;
-
-	lpDSCaps->dwPrimaryBuffers			= This->drvcaps.dwPrimaryBuffers;
-
-	lpDSCaps->dwMaxHwMixingAllBuffers		= This->drvcaps.dwMaxHwMixingAllBuffers;
-	lpDSCaps->dwMaxHwMixingStaticBuffers		= This->drvcaps.dwMaxHwMixingStaticBuffers;
-	lpDSCaps->dwMaxHwMixingStreamingBuffers		= This->drvcaps.dwMaxHwMixingStreamingBuffers;
-
-	lpDSCaps->dwFreeHwMixingAllBuffers		= This->drvcaps.dwFreeHwMixingAllBuffers;
-	lpDSCaps->dwFreeHwMixingStaticBuffers		= This->drvcaps.dwFreeHwMixingStaticBuffers;
-	lpDSCaps->dwFreeHwMixingStreamingBuffers	= This->drvcaps.dwFreeHwMixingStreamingBuffers;
-
-	lpDSCaps->dwMaxHw3DAllBuffers			= This->drvcaps.dwMaxHw3DAllBuffers;
-	lpDSCaps->dwMaxHw3DStaticBuffers		= This->drvcaps.dwMaxHw3DStaticBuffers;
-	lpDSCaps->dwMaxHw3DStreamingBuffers		= This->drvcaps.dwMaxHw3DStreamingBuffers;
-
-	lpDSCaps->dwFreeHw3DAllBuffers			= This->drvcaps.dwFreeHw3DAllBuffers;
-	lpDSCaps->dwFreeHw3DStaticBuffers		= This->drvcaps.dwFreeHw3DStaticBuffers;
-	lpDSCaps->dwFreeHw3DStreamingBuffers		= This->drvcaps.dwFreeHw3DStreamingBuffers;
-
-	lpDSCaps->dwTotalHwMemBytes			= This->drvcaps.dwTotalHwMemBytes;
-
-	lpDSCaps->dwFreeHwMemBytes			= This->drvcaps.dwFreeHwMemBytes;
-
-	lpDSCaps->dwMaxContigFreeHwMemBytes		= This->drvcaps.dwMaxContigFreeHwMemBytes;
-
-	/* driver doesn't have these */
-	lpDSCaps->dwUnlockTransferRateHwBuffers		= 4096;	/* But we have none... */
-
-	lpDSCaps->dwPlayCpuOverheadSwBuffers		= 1;	/* 1% */
-
-	return DS_OK;
-}
-
-static ULONG WINAPI IDirectSoundImpl_AddRef(LPDIRECTSOUND8 iface) {
-	ICOM_THIS(IDirectSoundImpl,iface);
-	TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-	return InterlockedIncrement(&This->ref);
-}
-
-static ULONG WINAPI IDirectSoundImpl_Release(LPDIRECTSOUND8 iface) {
-	ICOM_THIS(IDirectSoundImpl,iface);
-	ULONG ulReturn;
-
-	TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
-	ulReturn = InterlockedDecrement(&This->ref);
-	if (ulReturn == 0) {
-		HRESULT hres;
-		UINT i;
-
-		timeKillEvent(This->timerID);
-		timeEndPeriod(DS_TIME_RES);
-		/* wait for timer to expire */
-		Sleep(DS_TIME_RES+1);
-
-		RtlAcquireResourceShared(&(This->lock), TRUE);
-
-		if (This->buffers) {
-			for( i=0;i<This->nrofbuffers;i++)
-				IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->buffers[i]);
-		}
-
-		RtlReleaseResource(&(This->lock));
-
-		if (This->primary) {
-			WARN("primary buffer not released\n");
-			IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
-		}
-
-		hres = DSOUND_PrimaryDestroy(This);
-		if (hres != DS_OK)
-			WARN("DSOUND_PrimaryDestroy failed\n");
-
-		if (This->driver)
-			IDsDriver_Close(This->driver);
-
-		if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
-			waveOutClose(This->hwo);
-
-		if (This->driver)
-			IDsDriver_Release(This->driver);
-
-		RtlDeleteResource(&This->lock);
-		DeleteCriticalSection(&This->mixlock);
-		HeapFree(GetProcessHeap(),0,This);
-		dsound = NULL;
-		TRACE("(%p) released\n",This);
-	}
-
-	return ulReturn;
-}
-
-static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
-	LPDIRECTSOUND8 iface,DWORD config
-) {
-	ICOM_THIS(IDirectSoundImpl,iface);
-	TRACE("(%p,0x%08lx)\n",This,config);
-
-	This->speaker_config = config;
-
-	WARN("not fully functional\n");
-	return DS_OK;
-}
-
-static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
-	LPDIRECTSOUND8 iface,REFIID riid,LPVOID *ppobj
-) {
-	ICOM_THIS(IDirectSoundImpl,iface);
-	TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-
-	if (ppobj == NULL) {
-		WARN("invalid parameter\n");
-		return E_INVALIDARG;
-	}
-
-	*ppobj = NULL;	/* assume failure */
-
-	if ( IsEqualGUID(riid, &IID_IUnknown) || 
-	     IsEqualGUID(riid, &IID_IDirectSound) || 
-	     IsEqualGUID(riid, &IID_IDirectSound8) ) {
-		IDirectSound8_AddRef((LPDIRECTSOUND8)This);
-		*ppobj = This;
-		return S_OK;
-	}
-
-	if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
-		WARN("app requested IDirectSound3DListener on dsound object\n");
-		return E_NOINTERFACE;
-	}
-
-	FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
-	return E_NOINTERFACE;
-}
-
-static HRESULT WINAPI IDirectSoundImpl_Compact(
-	LPDIRECTSOUND8 iface)
-{
-	ICOM_THIS(IDirectSoundImpl,iface);
-	TRACE("(%p)\n", This);
-	return DS_OK;
-}
-
-static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
-	LPDIRECTSOUND8 iface,
-	LPDWORD lpdwSpeakerConfig)
-{
-	ICOM_THIS(IDirectSoundImpl,iface);
-	TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-
-	if (lpdwSpeakerConfig == NULL) {
-		WARN("invalid parameter\n");
-		return DSERR_INVALIDPARAM;
-	}
-
-	WARN("not fully functional\n");
-
-	*lpdwSpeakerConfig = This->speaker_config;
-
-	return DS_OK;
-}
-
-static HRESULT WINAPI IDirectSoundImpl_Initialize(
-	LPDIRECTSOUND8 iface,
-	LPCGUID lpcGuid)
-{
-	ICOM_THIS(IDirectSoundImpl,iface);
-	TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-	return DS_OK;
-}
-
-static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
-	LPDIRECTSOUND8 iface,
-	LPDWORD pdwCertified)
-{
-	ICOM_THIS(IDirectSoundImpl,iface);
-	TRACE("(%p, %p)\n", This, pdwCertified);
-	*pdwCertified = DS_CERTIFIED;
-	return DS_OK;
-}
-
-static ICOM_VTABLE(IDirectSound8) dsvt =
-{
-	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
-	IDirectSoundImpl_QueryInterface,
-	IDirectSoundImpl_AddRef,
-	IDirectSoundImpl_Release,
-	IDirectSoundImpl_CreateSoundBuffer,
-	IDirectSoundImpl_GetCaps,
-	IDirectSoundImpl_DuplicateSoundBuffer,
-	IDirectSoundImpl_SetCooperativeLevel,
-	IDirectSoundImpl_Compact,
-	IDirectSoundImpl_GetSpeakerConfig,
-	IDirectSoundImpl_SetSpeakerConfig,
-	IDirectSoundImpl_Initialize,
-	IDirectSoundImpl_VerifyCertification
-};
-
-
-/*******************************************************************************
- *		DirectSoundCreate (DSOUND.1)
- *
- *  Creates and initializes a DirectSound interface.
- *
- *  PARAMS
- *     lpcGUID   [I] Address of the GUID that identifies the sound device.
- *     ppDS      [O] Address of a variable to receive the interface pointer.
- *     pUnkOuter [I] Must be NULL.
- *
- *  RETURNS
- *     Success: DS_OK
- *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION, 
- *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
- */
-HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown *pUnkOuter )
-{
-	IDirectSoundImpl** ippDS=(IDirectSoundImpl**)ppDS;
-	PIDSDRIVER drv = NULL;
-	unsigned wod, wodn;
-	HRESULT err = DSERR_INVALIDPARAM;
-	GUID devGuid;
-	BOOLEAN found = FALSE;
-
-	TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ippDS,pUnkOuter);
-	
-	if (ippDS == NULL) {
-		WARN("invalid parameter: ippDS == NULL\n");
-		return DSERR_INVALIDPARAM;
-	}
-
-        /* Get dsound configuration */
-        setup_dsound_options();
-
-	/* Default device? */
-	if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
-		lpcGUID = &DSDEVID_DefaultPlayback;
-
-	if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
-		WARN("invalid parameter: lpcGUID\n");
-		*ippDS = NULL;
-		return DSERR_INVALIDPARAM;
-	}
-
-	if (dsound) {
-		if (IsEqualGUID(&devGuid, &dsound->guid) ) {
-			/* FIXME: this is wrong, need to create a new instance */
-			ERR("dsound already opened\n");
-			IDirectSound_AddRef((LPDIRECTSOUND)dsound);
-			*ippDS = dsound;
-			return DS_OK;
-		} else {
-			ERR("different dsound already opened\n");
-		}
-	}
-
-	/* Enumerate WINMM audio devices and find the one we want */
-	wodn = waveOutGetNumDevs();
-	if (!wodn) {
-		WARN("no driver\n");
-		*ippDS = NULL;
-	       	return DSERR_NODRIVER;
-	}
-
-	TRACE(" expecting GUID %s.\n", debugstr_guid(&devGuid));
-	
-	for (wod=0; wod<wodn; wod++) {
-		GUID guid;
-		err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
-		if (err != DS_OK) {
-			WARN("waveOutMessage failed; err=%lx\n",err);
-			*ippDS = NULL;
-			return err;
-		}
-		TRACE("got GUID %s for wod %d.\n", debugstr_guid(&guid), wod);
-		if (IsEqualGUID( &devGuid, &guid) ) {
-			err = DS_OK;
-			found = TRUE;
-			break;
-		}
-	}
-
-	if (err != DS_OK) {
-		WARN("invalid parameter\n");
-		*ippDS = NULL;
-		return DSERR_INVALIDPARAM;
-	}
-
-	if (found == FALSE) {
-		WARN("No device found matching given ID - trying with default one !\n");
-		wod = ds_default_playback;	
-	}
-	
-	/* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
-	waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
-
-	/* Disable the direct sound driver to force emulation if requested. */
-	if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
-	    drv = NULL;
-	
-	/* Allocate memory */
-	*ippDS = (IDirectSoundImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
-	if (*ippDS == NULL) {
-		WARN("out of memory\n");
-		return DSERR_OUTOFMEMORY;
-	}
-
-	(*ippDS)->lpVtbl	= &dsvt;
-	(*ippDS)->ref		= 1;
-
-	(*ippDS)->driver	= drv;
-	(*ippDS)->priolevel	= DSSCL_NORMAL;
-	(*ippDS)->fraglen	= 0;
-	(*ippDS)->hwbuf		= NULL;
-	(*ippDS)->buffer	= NULL;
-	(*ippDS)->buflen	= 0;
-	(*ippDS)->writelead	= 0;
-	(*ippDS)->state		= STATE_STOPPED;
-	(*ippDS)->nrofbuffers	= 0;
-	(*ippDS)->buffers	= NULL;
-	(*ippDS)->primary	= NULL;
-	(*ippDS)->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
-	
-	/* 3D listener initial parameters */
-	(*ippDS)->listener	= NULL;
-	(*ippDS)->ds3dl.dwSize = sizeof(DS3DLISTENER);
-	(*ippDS)->ds3dl.vPosition.x = 0.0;
-	(*ippDS)->ds3dl.vPosition.y = 0.0;
-	(*ippDS)->ds3dl.vPosition.z = 0.0;
-	(*ippDS)->ds3dl.vVelocity.x = 0.0;
-	(*ippDS)->ds3dl.vVelocity.y = 0.0;
-	(*ippDS)->ds3dl.vVelocity.z = 0.0;
-	(*ippDS)->ds3dl.vOrientFront.x = 0.0;
-	(*ippDS)->ds3dl.vOrientFront.y = 0.0;
-	(*ippDS)->ds3dl.vOrientFront.z = 1.0;
-	(*ippDS)->ds3dl.vOrientTop.x = 0.0;
-	(*ippDS)->ds3dl.vOrientTop.y = 1.0;
-	(*ippDS)->ds3dl.vOrientTop.z = 0.0;
-	(*ippDS)->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
-	(*ippDS)->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
-	(*ippDS)->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
-
-	(*ippDS)->prebuf	= ds_snd_queue_max;
-	(*ippDS)->guid		= devGuid;
-
-	/* Get driver description */
-	if (drv) {
-		err = IDsDriver_GetDriverDesc(drv,&((*ippDS)->drvdesc));
-		if (err != DS_OK) {
-			WARN("IDsDriver_GetDriverDesc failed\n");
-			HeapFree(GetProcessHeap(),0,*ippDS);
-			*ippDS = NULL;
-			return err;
-		}
-	} else {
-		/* if no DirectSound interface available, use WINMM API instead */
-		(*ippDS)->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
-	}
-
-	(*ippDS)->drvdesc.dnDevNode = wod;
-
-	/* Set default wave format (may need it for waveOutOpen) */
-	(*ippDS)->wfx.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.
-         */
-        (*ippDS)->wfx.nSamplesPerSec = 22050;
-        (*ippDS)->wfx.wBitsPerSample = 8;
-        (*ippDS)->wfx.nChannels = 2;
-        (*ippDS)->wfx.nBlockAlign = (*ippDS)->wfx.wBitsPerSample * (*ippDS)->wfx.nChannels / 8;
-        (*ippDS)->wfx.nAvgBytesPerSec = (*ippDS)->wfx.nSamplesPerSec * (*ippDS)->wfx.nBlockAlign;
-        (*ippDS)->wfx.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 ((*ippDS)->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(&((*ippDS)->hwo),
-					  (*ippDS)->drvdesc.dnDevNode, &((*ippDS)->wfx),
-					  (DWORD)DSOUND_callback, (DWORD)(*ippDS),
-					  flags));
-		if (err != DS_OK) {
-			WARN("waveOutOpen failed\n");
-			HeapFree(GetProcessHeap(),0,*ippDS);
-			*ippDS = NULL;
-			return err;
-		}
-	}
-
-	if (drv) {
-		err = IDsDriver_Open(drv);
-		if (err != DS_OK) {
-			WARN("IDsDriver_Open failed\n");
-			HeapFree(GetProcessHeap(),0,*ippDS);
-			*ippDS = NULL;
-			return err;
-		}
-
-		/* the driver is now open, so it's now allowed to call GetCaps */
-		err = IDsDriver_GetCaps(drv,&((*ippDS)->drvcaps));
-		if (err != DS_OK) {
-			WARN("IDsDriver_GetCaps failed\n");
-			HeapFree(GetProcessHeap(),0,*ippDS);
-			*ippDS = NULL;
-			return err;
-		}
-	} else {
-		WAVEOUTCAPSA woc;
-		err = mmErr(waveOutGetDevCapsA((*ippDS)->drvdesc.dnDevNode, &woc, sizeof(woc)));
-		if (err != DS_OK) {
-			WARN("waveOutGetDevCaps failed\n");
-			HeapFree(GetProcessHeap(),0,*ippDS);
-			*ippDS = NULL;
-			return err;
-		}
-		ZeroMemory(&(*ippDS)->drvcaps, sizeof((*ippDS)->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)) {
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
-			(*ippDS)->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)) {
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
-			(*ippDS)->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)) {
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
-			(*ippDS)->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)) {
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
-			(*ippDS)->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
-		}
-		if (ds_emuldriver)
-		    (*ippDS)->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
-		(*ippDS)->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
-		(*ippDS)->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
-		(*ippDS)->drvcaps.dwPrimaryBuffers = 1;
-	}
-
-	(*ippDS)->volpan.lVolume = 0;
-	(*ippDS)->volpan.lPan = 0;
-	DSOUND_RecalcVolPan(&((*ippDS)->volpan));
-
-	InitializeCriticalSection(&((*ippDS)->mixlock));
-	RtlInitializeResource(&((*ippDS)->lock));
-
-	if (!dsound) {
-		HRESULT hres;
-		dsound = (*ippDS);
-		hres = DSOUND_PrimaryCreate(dsound);
-		if (hres != DS_OK) {
-			WARN("DSOUND_PrimaryCreate failed\n");
-			return hres;
-		}
-		timeBeginPeriod(DS_TIME_RES);
-		dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
-					       (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
-	}
-
-	return DS_OK;
-}
-
-
 /*******************************************************************************
  * DirectSound ClassFactory
  */
Index: dlls/dsound/dsound_private.h
===================================================================
RCS file: /home/wine/wine/dlls/dsound/dsound_private.h,v
retrieving revision 1.15
diff -u -r1.15 dsound_private.h
--- dlls/dsound/dsound_private.h	17 Mar 2004 01:44:15 -0000	1.15
+++ dlls/dsound/dsound_private.h	1 Jul 2004 00:20:18 -0000
@@ -44,20 +44,25 @@
 /*****************************************************************************
  * Predeclare the interface implementation structures
  */
-typedef struct IDirectSoundImpl IDirectSoundImpl;
-typedef struct IDirectSoundBufferImpl IDirectSoundBufferImpl;
-typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl;
+typedef struct IDirectSoundImpl              IDirectSoundImpl;
+typedef struct IDirectSound_IUnknown         IDirectSound_IUnknown;
+typedef struct IDirectSound_IDirectSound     IDirectSound_IDirectSound;
+typedef struct IDirectSound8_IUnknown        IDirectSound8_IUnknown;
+typedef struct IDirectSound8_IDirectSound    IDirectSound8_IDirectSound;
+typedef struct IDirectSound8_IDirectSound8   IDirectSound8_IDirectSound8;
+typedef struct IDirectSoundBufferImpl        IDirectSoundBufferImpl;
+typedef struct IDirectSoundCaptureImpl       IDirectSoundCaptureImpl;
 typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl;
-typedef struct IDirectSoundFullDuplexImpl IDirectSoundFullDuplexImpl;
-typedef struct IDirectSoundNotifyImpl IDirectSoundNotifyImpl;
+typedef struct IDirectSoundFullDuplexImpl    IDirectSoundFullDuplexImpl;
+typedef struct IDirectSoundNotifyImpl        IDirectSoundNotifyImpl;
 typedef struct IDirectSoundCaptureNotifyImpl IDirectSoundCaptureNotifyImpl;
-typedef struct IDirectSound3DListenerImpl IDirectSound3DListenerImpl;
-typedef struct IDirectSound3DBufferImpl IDirectSound3DBufferImpl;
-typedef struct IKsBufferPropertySetImpl IKsBufferPropertySetImpl;
-typedef struct IKsPrivatePropertySetImpl IKsPrivatePropertySetImpl;
-typedef struct PrimaryBufferImpl PrimaryBufferImpl;
-typedef struct SecondaryBufferImpl SecondaryBufferImpl;
-typedef struct IClassFactoryImpl IClassFactoryImpl;
+typedef struct IDirectSound3DListenerImpl    IDirectSound3DListenerImpl;
+typedef struct IDirectSound3DBufferImpl      IDirectSound3DBufferImpl;
+typedef struct IKsBufferPropertySetImpl      IKsBufferPropertySetImpl;
+typedef struct IKsPrivatePropertySetImpl     IKsPrivatePropertySetImpl;
+typedef struct PrimaryBufferImpl             PrimaryBufferImpl;
+typedef struct SecondaryBufferImpl           SecondaryBufferImpl;
+typedef struct IClassFactoryImpl             IClassFactoryImpl;
 
 /*****************************************************************************
  * IDirectSound implementation structure
@@ -95,6 +100,10 @@
     IDirectSound3DListenerImpl*	listener;
     DS3DLISTENER                ds3dl;
     BOOL                        ds3dl_need_recalc;
+
+    LPUNKNOWN                   pUnknown;
+    LPDIRECTSOUND               pDS;
+    LPDIRECTSOUND8              pDS8;
 };
 
 /* reference counted buffer memory for duplicated buffer memory */
@@ -103,6 +112,66 @@
     DWORD                       ref;
     LPBYTE                      memory;
 } BufferMemory;
+
+HRESULT WINAPI IDirectSoundImpl_Create(
+    LPCGUID lpcGUID,
+    LPDIRECTSOUND8 * ppds);
+
+/*****************************************************************************
+ * IDirectSound COM components
+ */
+struct IDirectSound_IUnknown {
+    ICOM_VFIELD(IUnknown);
+    DWORD                       ref;
+    LPDIRECTSOUND8              pds;
+};
+
+HRESULT WINAPI IDirectSound_IUnknown_Create(
+    LPDIRECTSOUND8 pds,
+    LPUNKNOWN * ppunk);
+
+struct IDirectSound_IDirectSound {
+    ICOM_VFIELD(IDirectSound);
+    DWORD                       ref;
+    LPDIRECTSOUND8              pds;
+};
+
+HRESULT WINAPI IDirectSound_IDirectSound_Create(
+    LPDIRECTSOUND8 pds,
+    LPDIRECTSOUND * ppds);
+
+/*****************************************************************************
+ * IDirectSound8 COM components
+ */
+struct IDirectSound8_IUnknown {
+    ICOM_VFIELD(IUnknown);
+    DWORD                       ref;
+    LPDIRECTSOUND8              pds;
+};
+
+HRESULT WINAPI IDirectSound8_IUnknown_Create(
+    LPDIRECTSOUND8 pds,
+    LPUNKNOWN * ppunk);
+
+struct IDirectSound8_IDirectSound {
+    ICOM_VFIELD(IDirectSound);
+    DWORD                       ref;
+    LPDIRECTSOUND8              pds;
+};
+
+HRESULT WINAPI IDirectSound8_IDirectSound_Create(
+    LPDIRECTSOUND8 pds,
+    LPDIRECTSOUND * ppds);
+
+struct IDirectSound8_IDirectSound8 {
+    ICOM_VFIELD(IDirectSound8);
+    DWORD                       ref;
+    LPDIRECTSOUND8              pds;
+};
+
+HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
+    LPDIRECTSOUND8 pds,
+    LPDIRECTSOUND8 * ppds);
 
 /*****************************************************************************
  * IDirectSoundBuffer implementation structure
Index: dlls/dsound/tests/dsound.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/tests/dsound.c,v
retrieving revision 1.21
diff -u -r1.21 dsound.c
--- dlls/dsound/tests/dsound.c	17 Jun 2004 23:03:11 -0000	1.21
+++ dlls/dsound/tests/dsound.c	1 Jul 2004 00:20:19 -0000
@@ -36,6 +36,7 @@
 #include "windef.h"
 #include "wingdi.h"
 #include "dsound.h"
+#include "dxerr9.h"
 
 #include "dsound_test.h"
 
@@ -46,32 +47,51 @@
     LPDIRECTSOUND dso=NULL;
     DSCAPS dscaps;
     int ref;
+    IUnknown * unknown;
+    IDirectSound * ds;
+    IDirectSound8 * ds8;
 
     /* DSOUND: Error: Invalid interface buffer */
     rc=DirectSoundCreate(lpGuid,0,NULL);
-    ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate should have failed: 0x%lx\n",rc);
+    ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate should have failed: %s\n",DXGetErrorString9(rc));
 
     /* Create the DirectSound object */
     rc=DirectSoundCreate(lpGuid,&dso,NULL);
-    ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
+    ok(rc==DS_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
     if (rc!=DS_OK)
         return rc;
 
+    /* Try to Query for objects */
+    rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
+    ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",DXGetErrorString9(rc));
+    if (rc==DS_OK)
+        IDirectSound_Release(unknown);
+
+    rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
+    ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",DXGetErrorString9(rc));
+    if (rc==DS_OK)
+        IDirectSound_Release(ds);
+
+    rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
+    ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) should have failed: %s\n",DXGetErrorString9(rc));
+    if (rc==DS_OK)
+        IDirectSound8_Release(ds8);
+
     /* DSOUND: Error: Invalid caps buffer */
     rc=IDirectSound_GetCaps(dso,0);
-    ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
+    ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
 
     ZeroMemory(&dscaps, sizeof(dscaps));
 
     /* DSOUND: Error: Invalid caps buffer */
     rc=IDirectSound_GetCaps(dso,&dscaps);
-    ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
+    ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
 
     dscaps.dwSize=sizeof(dscaps);
 
     /* DSOUND: Running on a certified driver */
     rc=IDirectSound_GetCaps(dso,&dscaps);
-    ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
+    ok(rc==DS_OK,"GetCaps failed: %s\n",DXGetErrorString9(rc));
     if (rc==DS_OK) {
         trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
               dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
@@ -84,17 +104,15 @@
     if (ref!=0)
         return DSERR_GENERIC;
 
-#if 0
-    /* FIXME: this works on windows */
     /* Create a DirectSound object */
     rc=DirectSoundCreate(lpGuid,&dso,NULL);
-    ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
+    ok(rc==DS_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
     if (rc==DS_OK) {
         LPDIRECTSOUND dso1=NULL;
 
         /* Create a second DirectSound object */
         rc=DirectSoundCreate(lpGuid,&dso1,NULL);
-        ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
+        ok(rc==DS_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
         if (rc==DS_OK) {
             /* Release the second DirectSound object */
             ref=IDirectSound_Release(dso1);
@@ -109,7 +127,96 @@
             return DSERR_GENERIC;
     } else
         return rc;
-#endif
+
+    return DS_OK;
+}
+
+static HRESULT test_dsound8(LPGUID lpGuid)
+{
+    HRESULT rc;
+    LPDIRECTSOUND8 dso=NULL;
+    DSCAPS dscaps;
+    int ref;
+    IUnknown * unknown;
+    IDirectSound * ds;
+    IDirectSound8 * ds8;
+
+    /* DSOUND: Error: Invalid interface buffer */
+    rc=DirectSoundCreate8(lpGuid,0,NULL);
+    ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate8 should have failed: %s\n",DXGetErrorString9(rc));
+
+    /* Create the DirectSound8 object */
+    rc=DirectSoundCreate8(lpGuid,&dso,NULL);
+    ok(rc==DS_OK,"DirectSoundCreate8 failed: %s\n",DXGetErrorString9(rc));
+    if (rc!=DS_OK)
+        return rc;
+
+    /* Try to Query for objects */
+    rc=IDirectSound8_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
+    ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IUnknown) failed: %s\n",DXGetErrorString9(rc));
+    if (rc==DS_OK)
+        IDirectSound8_Release(unknown);
+
+    rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
+    ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound) failed: %s\n",DXGetErrorString9(rc));
+    if (rc==DS_OK)
+        IDirectSound_Release(ds);
+
+    rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
+    ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound8) failed: %s\n",DXGetErrorString9(rc));
+    if (rc==DS_OK)
+        IDirectSound8_Release(ds8);
+
+    /* DSOUND: Error: Invalid caps buffer */
+    rc=IDirectSound8_GetCaps(dso,0);
+    ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
+
+    ZeroMemory(&dscaps, sizeof(dscaps));
+
+    /* DSOUND: Error: Invalid caps buffer */
+    rc=IDirectSound8_GetCaps(dso,&dscaps);
+    ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: %s\n",DXGetErrorString9(rc));
+
+    dscaps.dwSize=sizeof(dscaps);
+
+    /* DSOUND: Running on a certified driver */
+    rc=IDirectSound8_GetCaps(dso,&dscaps);
+    ok(rc==DS_OK,"GetCaps failed: %s\n",DXGetErrorString9(rc));
+    if (rc==DS_OK) {
+        trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
+              dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
+              dscaps.dwMaxSecondarySampleRate);
+    }
+
+    /* Release the DirectSound8 object */
+    ref=IDirectSound8_Release(dso);
+    ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
+    if (ref!=0)
+        return DSERR_GENERIC;
+
+    /* Create a DirectSound8 object */
+    rc=DirectSoundCreate8(lpGuid,&dso,NULL);
+    ok(rc==DS_OK,"DirectSoundCreate failed: %s\n",DXGetErrorString9(rc));
+    if (rc==DS_OK) {
+        LPDIRECTSOUND8 dso1=NULL;
+
+        /* Create a second DirectSound8 object */
+        rc=DirectSoundCreate8(lpGuid,&dso1,NULL);
+        ok(rc==DS_OK,"DirectSoundCreate8 failed: %s\n",DXGetErrorString9(rc));
+        if (rc==DS_OK) {
+            /* Release the second DirectSound8 object */
+            ref=IDirectSound8_Release(dso1);
+            ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
+            ok(dso!=dso1,"DirectSound8 objects should be unique: dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
+        }
+
+        /* Release the first DirectSound8 object */
+        ref=IDirectSound8_Release(dso);
+        ok(ref==0,"IDirectSound8_Release has %d references, should have 0\n",ref);
+        if (ref!=0)
+            return DSERR_GENERIC;
+    } else
+        return rc;
 
     return DS_OK;
 }
@@ -294,6 +401,7 @@
 {
     trace("*** Testing %s - %s\n",lpcstrDescription,lpcstrModule);
     test_dsound(lpGuid);
+    test_dsound8(lpGuid);
     test_primary(lpGuid);
     test_secondary(lpGuid);
 
Index: include/dsound.h
===================================================================
RCS file: /home/wine/wine/include/dsound.h,v
retrieving revision 1.44
diff -u -r1.44 dsound.h
--- include/dsound.h	19 Apr 2004 02:58:45 -0000	1.44
+++ include/dsound.h	1 Jul 2004 00:20:33 -0000
@@ -456,9 +456,9 @@
 #define INTERFACE IDirectSound8
 #define IDirectSound8_METHODS \
     IUnknown_METHODS \
-    STDMETHOD(CreateSoundBuffer)(THIS_ LPCDSBUFFERDESC lpcDSBufferDesc, LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer, IUnknown *pUnkOuter) PURE; \
+    STDMETHOD(CreateSoundBuffer)(THIS_ LPCDSBUFFERDESC lpcDSBufferDesc, LPLPDIRECTSOUNDBUFFER lplpDirectSoundBuffer, IUnknown *pUnkOuter) PURE; \
     STDMETHOD(GetCaps)(THIS_ LPDSCAPS lpDSCaps) PURE; \
-    STDMETHOD(DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER8 lpDsbOriginal, LPLPDIRECTSOUNDBUFFER8 lplpDsbDuplicate) PURE; \
+    STDMETHOD(DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER lpDsbOriginal, LPLPDIRECTSOUNDBUFFER lplpDsbDuplicate) PURE; \
     STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwLevel) PURE; \
     STDMETHOD(Compact)(THIS) PURE; \
     STDMETHOD(GetSpeakerConfig)(THIS_ LPDWORD lpdwSpeakerConfig) PURE; \
-------------- next part --------------
diff -u -N wine.cvs/dlls/dsound/dsound.c wine/dlls/dsound/dsound.c
--- dlls/dsound/dsound.c	1969-12-31 19:00:00.000000000 -0500
+++ dlls/dsound/dsound.c	2004-06-30 19:33:32.000000000 -0400
@@ -0,0 +1,1674 @@
+/*  			DirectSound
+ *
+ * Copyright 1998 Marcus Meissner
+ * Copyright 1998 Rob Riggs
+ * Copyright 2000-2002 TransGaming Technologies, Inc.
+ * Copyright 2004 Robert Reif
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+//#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "mmsystem.h"
+#include "winternl.h"
+#include "mmddk.h"
+#include "wine/windef16.h"
+#include "wine/winbase16.h"
+#include "wine/debug.h"
+#include "dsound.h"
+#include "dsdriver.h"
+#include "dsound_private.h"
+#include "dsconf.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dsound);
+
+static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
+static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
+static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
+static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
+static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
+
+static const char * dumpCooperativeLevel(DWORD level)
+{
+    static char unknown[32];
+#define LE(x) case x: return #x
+    switch (level) {
+        LE(DSSCL_NORMAL);
+        LE(DSSCL_PRIORITY);
+        LE(DSSCL_EXCLUSIVE);
+        LE(DSSCL_WRITEPRIMARY);
+    }
+#undef LE
+    sprintf(unknown, "Unknown(%08lx)", level);
+    return unknown;
+}
+
+static void _dump_DSBCAPS(DWORD xmask) {
+    struct {
+        DWORD   mask;
+        char    *name;
+    } flags[] = {
+#define FE(x) { x, #x },
+        FE(DSBCAPS_PRIMARYBUFFER)
+        FE(DSBCAPS_STATIC)
+        FE(DSBCAPS_LOCHARDWARE)
+        FE(DSBCAPS_LOCSOFTWARE)
+        FE(DSBCAPS_CTRL3D)
+        FE(DSBCAPS_CTRLFREQUENCY)
+        FE(DSBCAPS_CTRLPAN)
+        FE(DSBCAPS_CTRLVOLUME)
+        FE(DSBCAPS_CTRLPOSITIONNOTIFY)
+        FE(DSBCAPS_CTRLDEFAULT)
+        FE(DSBCAPS_CTRLALL)
+        FE(DSBCAPS_STICKYFOCUS)
+        FE(DSBCAPS_GLOBALFOCUS)
+        FE(DSBCAPS_GETCURRENTPOSITION2)
+        FE(DSBCAPS_MUTE3DATMAXDISTANCE)
+#undef FE
+    };
+    int     i;
+
+    for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+        if ((flags[i].mask & xmask) == flags[i].mask)
+            DPRINTF("%s ",flags[i].name);
+}
+
+/*******************************************************************************
+ *		IDirectSoundImpl_DirectSound
+ */
+static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
+    LPDIRECTSOUND8 iface,
+    REFIID riid,
+    LPVOID * ppobj)
+{
+    TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
+    FIXME("shouldnt be called directly\n");
+    return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI DSOUND_QueryInterface(
+    LPDIRECTSOUND8 iface,
+    REFIID riid,
+    LPVOID * ppobj)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+
+    if (ppobj == NULL) {
+        WARN("invalid parameter\n");
+        return E_INVALIDARG;
+    }
+
+    if (IsEqualIID(riid, &IID_IUnknown)) {
+        if (!This->pUnknown) {
+            IDirectSound_IUnknown_Create(iface, &This->pUnknown);
+            if (!This->pUnknown) {
+                WARN("IDirectSound_IUnknown_Create() failed\n");
+                *ppobj = NULL;
+                return E_NOINTERFACE;
+            }
+        }
+        IDirectSound_IUnknown_AddRef(This->pUnknown);
+        *ppobj = This->pUnknown;
+        return S_OK;
+    } else if (IsEqualIID(riid, &IID_IDirectSound)) {
+        if (!This->pDS) {
+            IDirectSound_IDirectSound_Create(iface, &This->pDS);
+            if (!This->pDS) {
+                WARN("IDirectSound_IDirectSound_Create() failed\n");
+                *ppobj = NULL;
+                return E_NOINTERFACE;
+            }
+        }
+        IDirectSound_IDirectSound_AddRef(This->pDS);
+        *ppobj = This->pDS;
+        return S_OK;
+    }
+
+    *ppobj = NULL;
+    WARN("Unknown IID %s\n",debugstr_guid(riid));
+    return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI DSOUND_QueryInterface8(
+    LPDIRECTSOUND8 iface,
+    REFIID riid,
+    LPVOID * ppobj)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+
+    if (ppobj == NULL) {
+        WARN("invalid parameter\n");
+        return E_INVALIDARG;
+    }
+
+    if (IsEqualIID(riid, &IID_IUnknown)) {
+        if (!This->pUnknown) {
+            IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
+            if (!This->pUnknown) {
+                WARN("IDirectSound8_IUnknown_Create() failed\n");
+                *ppobj = NULL;
+                return E_NOINTERFACE;
+            }
+        }
+        IDirectSound8_IUnknown_AddRef(This->pUnknown);
+        *ppobj = This->pUnknown;
+        return S_OK;
+    } else if (IsEqualIID(riid, &IID_IDirectSound)) {
+        if (!This->pDS) {
+            IDirectSound8_IDirectSound_Create(iface, &This->pDS);
+            if (!This->pDS) {
+                WARN("IDirectSound8_IDirectSound_Create() failed\n");
+                *ppobj = NULL;
+                return E_NOINTERFACE;
+            }
+        }
+        IDirectSound8_IDirectSound_AddRef(This->pDS);
+        *ppobj = This->pDS;
+        return S_OK;
+    } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
+        if (!This->pDS8) {
+            IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
+            if (!This->pDS8) {
+                WARN("IDirectSound8_IDirectSound8_Create() failed\n");
+                *ppobj = NULL;
+                return E_NOINTERFACE;
+            }
+        }
+        IDirectSound8_IDirectSound8_AddRef(This->pDS8);
+        *ppobj = This->pDS8;
+        return S_OK;
+    }
+
+    *ppobj = NULL;
+    WARN("Unknown IID %s\n",debugstr_guid(riid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI IDirectSoundImpl_AddRef(
+    LPDIRECTSOUND8 iface)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI IDirectSoundImpl_Release(
+    LPDIRECTSOUND8 iface)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    ULONG ref;
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+
+    ref = InterlockedDecrement(&This->ref);
+    if (ref == 0) {
+        HRESULT hres;
+        UINT i;
+
+        timeKillEvent(This->timerID);
+        timeEndPeriod(DS_TIME_RES);
+        /* wait for timer to expire */
+        Sleep(DS_TIME_RES+1);
+
+        RtlAcquireResourceShared(&(This->lock), TRUE);
+
+        if (This->buffers) {
+            for( i=0;i<This->nrofbuffers;i++)
+                IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->buffers[i]);
+        }
+
+        RtlReleaseResource(&(This->lock));
+
+        if (This->primary) {
+            WARN("primary buffer not released\n");
+            IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
+        }
+
+        hres = DSOUND_PrimaryDestroy(This);
+        if (hres != DS_OK)
+            WARN("DSOUND_PrimaryDestroy failed\n");
+
+        if (This->driver)
+            IDsDriver_Close(This->driver);
+
+        if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+            waveOutClose(This->hwo);
+
+        if (This->driver)
+            IDsDriver_Release(This->driver);
+
+        RtlDeleteResource(&This->lock);
+        DeleteCriticalSection(&This->mixlock);
+        HeapFree(GetProcessHeap(),0,This);
+        dsound = NULL;
+        TRACE("(%p) released\n",This);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
+    LPDIRECTSOUND8 iface,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER ppdsb,
+    LPUNKNOWN lpunk)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    LPWAVEFORMATEX  wfex;
+    HRESULT hres = DS_OK;
+    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+
+    if (This == NULL) {
+        WARN("invalid parameter: This == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (dsbd == NULL) {
+        WARN("invalid parameter: dsbd == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (dsbd->dwSize != sizeof(DSBUFFERDESC) && dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
+        WARN("invalid parameter: dsbd\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (ppdsb == NULL) {
+        WARN("invalid parameter: ppdsb == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (TRACE_ON(dsound)) {
+        TRACE("(structsize=%ld)\n",dsbd->dwSize);
+        TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
+        _dump_DSBCAPS(dsbd->dwFlags);
+        DPRINTF(")\n");
+        TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
+        TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
+    }
+
+    wfex = dsbd->lpwfxFormat;
+
+    if (wfex)
+        TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
+        "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
+        wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
+        wfex->nAvgBytesPerSec, wfex->nBlockAlign,
+        wfex->wBitsPerSample, wfex->cbSize);
+
+    if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
+        if (This->primary) {
+            WARN("Primary Buffer already created\n");
+            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
+            *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
+        } else {
+           This->dsbd = *dsbd;
+           hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
+           if (This->primary) {
+               IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
+               *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
+           } else
+               WARN("PrimaryBufferImpl_Create failed\n");
+        }
+    } else {
+        IDirectSoundBufferImpl * dsb;
+        hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
+        if (dsb) {
+            hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
+            if (*ppdsb) {
+                dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
+                IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
+            } else
+                WARN("SecondaryBufferImpl_Create failed\n");
+        } else
+           WARN("IDirectSoundBufferImpl_Create failed\n");
+   }
+
+   return hres;
+}
+
+static HRESULT WINAPI IDirectSoundImpl_GetCaps(
+    LPDIRECTSOUND8 iface,
+    LPDSCAPS lpDSCaps)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p,%p)\n",This,lpDSCaps);
+
+    if (This == NULL) {
+        WARN("invalid parameter: This == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (lpDSCaps == NULL) {
+        WARN("invalid parameter: lpDSCaps = NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    /* check if there is enough room */
+    if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
+        WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
+             lpDSCaps->dwSize, sizeof(*lpDSCaps));
+        return DSERR_INVALIDPARAM;
+    }
+
+    TRACE("(flags=0x%08lx)\n",lpDSCaps->dwFlags);
+    lpDSCaps->dwFlags                           = This->drvcaps.dwFlags;
+    lpDSCaps->dwMinSecondarySampleRate          = This->drvcaps.dwMinSecondarySampleRate;
+    lpDSCaps->dwMaxSecondarySampleRate          = This->drvcaps.dwMaxSecondarySampleRate;
+    lpDSCaps->dwPrimaryBuffers                  = This->drvcaps.dwPrimaryBuffers;
+    lpDSCaps->dwMaxHwMixingAllBuffers           = This->drvcaps.dwMaxHwMixingAllBuffers;
+    lpDSCaps->dwMaxHwMixingStaticBuffers        = This->drvcaps.dwMaxHwMixingStaticBuffers;
+    lpDSCaps->dwMaxHwMixingStreamingBuffers     = This->drvcaps.dwMaxHwMixingStreamingBuffers;
+    lpDSCaps->dwFreeHwMixingAllBuffers          = This->drvcaps.dwFreeHwMixingAllBuffers;
+    lpDSCaps->dwFreeHwMixingStaticBuffers       = This->drvcaps.dwFreeHwMixingStaticBuffers;
+    lpDSCaps->dwFreeHwMixingStreamingBuffers    = This->drvcaps.dwFreeHwMixingStreamingBuffers;
+    lpDSCaps->dwMaxHw3DAllBuffers               = This->drvcaps.dwMaxHw3DAllBuffers;
+    lpDSCaps->dwMaxHw3DStaticBuffers            = This->drvcaps.dwMaxHw3DStaticBuffers;
+    lpDSCaps->dwMaxHw3DStreamingBuffers         = This->drvcaps.dwMaxHw3DStreamingBuffers;
+    lpDSCaps->dwFreeHw3DAllBuffers              = This->drvcaps.dwFreeHw3DAllBuffers;
+    lpDSCaps->dwFreeHw3DStaticBuffers           = This->drvcaps.dwFreeHw3DStaticBuffers;
+    lpDSCaps->dwFreeHw3DStreamingBuffers        = This->drvcaps.dwFreeHw3DStreamingBuffers;
+    lpDSCaps->dwTotalHwMemBytes                 = This->drvcaps.dwTotalHwMemBytes;
+    lpDSCaps->dwFreeHwMemBytes                  = This->drvcaps.dwFreeHwMemBytes;
+    lpDSCaps->dwMaxContigFreeHwMemBytes         = This->drvcaps.dwMaxContigFreeHwMemBytes;
+
+    /* driver doesn't have these */
+    lpDSCaps->dwUnlockTransferRateHwBuffers     = 4096; /* But we have none... */
+    lpDSCaps->dwPlayCpuOverheadSwBuffers        = 1;    /* 1% */
+
+    return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
+    LPDIRECTSOUND8 iface,
+    LPDIRECTSOUNDBUFFER psb,
+    LPLPDIRECTSOUNDBUFFER ppdsb)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+    IDirectSoundBufferImpl* pdsb;
+    IDirectSoundBufferImpl* dsb;
+    HRESULT hres = DS_OK;
+    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+
+    if (This == NULL) {
+        WARN("invalid parameter: This == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (psb == NULL) {
+        WARN("invalid parameter: psb == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (ppdsb == NULL) {
+        WARN("invalid parameter: ppdsb == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    /* FIXME: hack to make sure we have a secondary buffer */
+    if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
+        WARN("trying to duplicate primary buffer\n");
+        *ppdsb = NULL;
+        return DSERR_INVALIDCALL;
+    }
+
+    pdsb = ((SecondaryBufferImpl *)psb)->dsb;
+
+    dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
+
+    if (dsb == NULL) {
+        WARN("out of memory\n");
+        *ppdsb = NULL;
+        return DSERR_OUTOFMEMORY;
+    }
+
+    memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
+
+    if (pdsb->hwbuf) {
+        TRACE("duplicating hardware buffer\n");
+
+        hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
+        if (hres != DS_OK) {
+            TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
+            dsb->hwbuf = NULL;
+            /* allocate buffer */
+            if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
+                dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
+                if (dsb->buffer == NULL) {
+                    WARN("out of memory\n");
+                    HeapFree(GetProcessHeap(),0,dsb);
+                    *ppdsb = NULL;
+                    return DSERR_OUTOFMEMORY;
+                }
+
+                dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
+                if (dsb->buffer->memory == NULL) {
+                    WARN("out of memory\n");
+                    HeapFree(GetProcessHeap(),0,dsb->buffer);
+                    HeapFree(GetProcessHeap(),0,dsb);
+                    *ppdsb = NULL;
+                    return DSERR_OUTOFMEMORY;
+                }
+                dsb->buffer->ref = 1;
+
+                /* FIXME: copy buffer ? */
+            }
+        }
+    } else {
+        dsb->hwbuf = NULL;
+        dsb->buffer->ref++;
+    }
+
+    dsb->ref = 0;
+    dsb->state = STATE_STOPPED;
+    dsb->playpos = 0;
+    dsb->buf_mixpos = 0;
+    dsb->dsound = This;
+    dsb->ds3db = NULL;
+    dsb->iks = NULL; /* FIXME? */
+    dsb->dsb = NULL;
+    memcpy(&(dsb->wfx), &(pdsb->wfx), sizeof(dsb->wfx));
+    InitializeCriticalSection(&(dsb->lock));
+    /* register buffer */
+    RtlAcquireResourceExclusive(&(This->lock), TRUE);
+    {
+        IDirectSoundBufferImpl **newbuffers;
+        if (This->buffers)
+            newbuffers = HeapReAlloc(GetProcessHeap(),0,This->buffers,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
+        else
+            newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
+
+        if (newbuffers) {
+            This->buffers = newbuffers;
+            This->buffers[This->nrofbuffers] = dsb;
+            This->nrofbuffers++;
+            TRACE("buffer count is now %d\n", This->nrofbuffers);
+        } else {
+            ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers);
+            IDirectSoundBuffer8_Release(psb);
+            DeleteCriticalSection(&(dsb->lock));
+            RtlReleaseResource(&(This->lock));
+            HeapFree(GetProcessHeap(),0,dsb);
+            *ppdsb = 0;
+            return DSERR_OUTOFMEMORY;
+        }
+    }
+    RtlReleaseResource(&(This->lock));
+    IDirectSound_AddRef(iface);
+    hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
+    if (*ppdsb) {
+        dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
+        IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
+    } else
+        WARN("SecondaryBufferImpl_Create failed\n");
+
+    return hres;
+}
+
+static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
+    LPDIRECTSOUND8 iface,
+    HWND hwnd,
+    DWORD level)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
+
+    if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
+        FIXME("level=%s not fully supported\n",
+              level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
+    }
+    This->priolevel = level;
+    return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundImpl_Compact(
+    LPDIRECTSOUND8 iface)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p)\n",This);
+
+    return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
+    LPDIRECTSOUND8 iface,
+    LPDWORD lpdwSpeakerConfig)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
+
+    if (lpdwSpeakerConfig == NULL) {
+        WARN("invalid parameter\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    WARN("not fully functional\n");
+    *lpdwSpeakerConfig = This->speaker_config;
+    return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
+    LPDIRECTSOUND8 iface,
+    DWORD config)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p,0x%08lx)\n",This,config);
+
+    This->speaker_config = config;
+    WARN("not fully functional\n");
+    return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundImpl_Initialize(
+    LPDIRECTSOUND8 iface,
+    LPCGUID lpcGuid)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
+
+    return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
+    LPDIRECTSOUND8 iface,
+    LPDWORD pdwCertified)
+{
+    ICOM_THIS(IDirectSoundImpl,iface);
+    TRACE("(%p, %p)\n",This,pdwCertified);
+
+    *pdwCertified = DS_CERTIFIED;
+    return DS_OK;
+}
+
+static ICOM_VTABLE(IDirectSound8) IDirectSoundImpl_Vtbl =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectSoundImpl_QueryInterface,
+    IDirectSoundImpl_AddRef,
+    IDirectSoundImpl_Release,
+    IDirectSoundImpl_CreateSoundBuffer,
+    IDirectSoundImpl_GetCaps,
+    IDirectSoundImpl_DuplicateSoundBuffer,
+    IDirectSoundImpl_SetCooperativeLevel,
+    IDirectSoundImpl_Compact,
+    IDirectSoundImpl_GetSpeakerConfig,
+    IDirectSoundImpl_SetSpeakerConfig,
+    IDirectSoundImpl_Initialize,
+    IDirectSoundImpl_VerifyCertification
+};
+
+HRESULT WINAPI IDirectSoundImpl_Create(
+    LPCGUID lpcGUID,
+    LPDIRECTSOUND8 * ppDS)
+{
+    HRESULT err = DSERR_INVALIDPARAM;
+    PIDSDRIVER drv = NULL;
+    IDirectSoundImpl* pDS;
+    unsigned wod, wodn;
+    BOOLEAN found = FALSE;
+    TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
+
+    /* Enumerate WINMM audio devices and find the one we want */
+    wodn = waveOutGetNumDevs();
+    if (!wodn) {
+        WARN("no driver\n");
+        *ppDS = NULL;
+        return DSERR_NODRIVER;
+    }
+
+    TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
+
+    for (wod=0; wod<wodn; wod++) {
+        GUID guid;
+        err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
+        if (err != DS_OK) {
+            WARN("waveOutMessage failed; err=%lx\n",err);
+            *ppDS = NULL;
+            return err;
+        }
+        TRACE("got GUID %s for wod %d.\n", debugstr_guid(&guid), wod);
+        if (IsEqualGUID( lpcGUID, &guid)) {
+            err = DS_OK;
+            found = TRUE;
+            break;
+        }
+    }
+
+    if (err != DS_OK) {
+        WARN("invalid parameter\n");
+        *ppDS = NULL;
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (found == FALSE) {
+        WARN("No device found matching given ID - trying with default one !\n");
+        wod = ds_default_playback;
+    }
+
+    /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
+    waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
+
+    /* Disable the direct sound driver to force emulation if requested. */
+    if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
+        drv = NULL;
+
+    /* Allocate memory */
+    pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
+    if (ppDS == NULL) {
+        WARN("out of memory\n");
+        *ppDS = NULL;
+        return DSERR_OUTOFMEMORY;
+    }
+
+    pDS->lpVtbl         = &IDirectSoundImpl_Vtbl;
+    pDS->ref            = 0;
+
+    pDS->driver         = drv;
+    pDS->priolevel      = DSSCL_NORMAL;
+    pDS->fraglen        = 0;
+    pDS->hwbuf          = NULL;
+    pDS->buffer         = NULL;
+    pDS->buflen         = 0;
+    pDS->writelead      = 0;
+    pDS->state          = STATE_STOPPED;
+    pDS->nrofbuffers    = 0;
+    pDS->buffers        = NULL;
+    pDS->primary        = NULL;
+    pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
+
+    /* 3D listener initial parameters */
+    pDS->listener       = NULL;
+    pDS->ds3dl.dwSize   = sizeof(DS3DLISTENER);
+    pDS->ds3dl.vPosition.x = 0.0;
+    pDS->ds3dl.vPosition.y = 0.0;
+    pDS->ds3dl.vPosition.z = 0.0;
+    pDS->ds3dl.vVelocity.x = 0.0;
+    pDS->ds3dl.vVelocity.y = 0.0;
+    pDS->ds3dl.vVelocity.z = 0.0;
+    pDS->ds3dl.vOrientFront.x = 0.0;
+    pDS->ds3dl.vOrientFront.y = 0.0;
+    pDS->ds3dl.vOrientFront.z = 1.0;
+    pDS->ds3dl.vOrientTop.x = 0.0;
+    pDS->ds3dl.vOrientTop.y = 1.0;
+    pDS->ds3dl.vOrientTop.z = 0.0;
+    pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
+    pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
+    pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
+
+    pDS->prebuf         = ds_snd_queue_max;
+    pDS->guid           = *lpcGUID;
+
+    /* Get driver description */
+    if (drv) {
+        err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
+        if (err != DS_OK) {
+            WARN("IDsDriver_GetDriverDesc failed\n");
+                 HeapFree(GetProcessHeap(),0,pDS);
+                 *ppDS = NULL;
+                 return err;
+        }
+    } else {
+        /* if no DirectSound interface available, use WINMM API instead */
+        pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
+    }
+
+    pDS->drvdesc.dnDevNode = wod;
+
+    /* Set default wave format (may need it for waveOutOpen) */
+    pDS->wfx.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->wfx.nSamplesPerSec = 22050;
+    pDS->wfx.wBitsPerSample = 8;
+    pDS->wfx.nChannels = 2;
+    pDS->wfx.nBlockAlign = pDS->wfx.wBitsPerSample * pDS->wfx.nChannels / 8;
+    pDS->wfx.nAvgBytesPerSec = pDS->wfx.nSamplesPerSec * pDS->wfx.nBlockAlign;
+    pDS->wfx.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->wfx),
+                                (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;
+    }
+
+    pDS->volpan.lVolume = 0;
+    pDS->volpan.lPan = 0;
+    DSOUND_RecalcVolPan(&(pDS->volpan));
+
+    InitializeCriticalSection(&(pDS->mixlock));
+    RtlInitializeResource(&(pDS->lock));
+
+    *ppDS = (LPDIRECTSOUND8)pDS;
+
+    return DS_OK;
+}
+/*******************************************************************************
+ *		IDirectSound_IUnknown
+ */
+static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
+    LPUNKNOWN iface,
+    REFIID riid,
+    LPVOID * ppobj)
+{
+    ICOM_THIS(IDirectSound_IUnknown,iface);
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface(This->pds, riid, ppobj);
+}
+
+static ULONG WINAPI IDirectSound_IUnknown_AddRef(
+    LPUNKNOWN iface)
+{
+    ICOM_THIS(IDirectSound_IUnknown,iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI IDirectSound_IUnknown_Release(
+    LPUNKNOWN iface)
+{
+    ICOM_THIS(IDirectSound_IUnknown,iface);
+    ULONG ulReturn;
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    ulReturn = InterlockedDecrement(&This->ref);
+    if (ulReturn == 0) {
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(),0,This);
+        TRACE("(%p) released\n",This);
+    }
+    return ulReturn;
+}
+
+static ICOM_VTABLE(IUnknown) DirectSound_Unknown_Vtbl =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectSound_IUnknown_QueryInterface,
+    IDirectSound_IUnknown_AddRef,
+    IDirectSound_IUnknown_Release
+};
+
+HRESULT WINAPI IDirectSound_IUnknown_Create(
+    LPDIRECTSOUND8 pds,
+    LPUNKNOWN * ppunk)
+{
+    IDirectSound_IUnknown * pdsunk;
+    TRACE("(%p,%p)\n",pds,ppunk);
+
+    if (ppunk == NULL) {
+        ERR("invalid parameter\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (pds == NULL) {
+        ERR("invalid parameter\n");
+        *ppunk = NULL;
+        return DSERR_INVALIDPARAM;
+    }
+
+    pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
+    if (pdsunk == NULL) {
+        WARN("out of memory\n");
+        *ppunk = NULL;
+        return DSERR_OUTOFMEMORY;
+    }
+
+    pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
+    pdsunk->ref = 0;
+    pdsunk->pds = pds;
+
+    IDirectSoundImpl_AddRef(pds);
+    *ppunk = (LPUNKNOWN)pdsunk;
+
+    return DS_OK;
+}
+
+/*******************************************************************************
+ *		IDirectSound_IDirectSound
+ */
+static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
+    LPDIRECTSOUND iface,
+    REFIID riid,
+    LPVOID * ppobj)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface(This->pds, riid, ppobj);
+}
+
+static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
+    LPDIRECTSOUND iface)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI IDirectSound_IDirectSound_Release(
+    LPDIRECTSOUND iface)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    ULONG ulReturn;
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    ulReturn = InterlockedDecrement(&This->ref);
+    if (ulReturn == 0) {
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(),0,This);
+        TRACE("(%p) released\n",This);
+    }
+    return ulReturn;
+}
+
+static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
+    LPDIRECTSOUND iface,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER ppdsb,
+    LPUNKNOWN lpunk)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+    return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
+}
+
+static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
+    LPDIRECTSOUND iface,
+    LPDSCAPS lpDSCaps)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    TRACE("(%p,%p)\n",This,lpDSCaps);
+    return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
+}
+
+static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
+    LPDIRECTSOUND iface,
+    LPDIRECTSOUNDBUFFER psb,
+    LPLPDIRECTSOUNDBUFFER ppdsb)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+    return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
+}
+
+static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
+    LPDIRECTSOUND iface,
+    HWND hwnd,
+    DWORD level)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
+    return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
+}
+
+static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
+    LPDIRECTSOUND iface)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    TRACE("(%p)\n", This);
+    return IDirectSoundImpl_Compact(This->pds);
+}
+
+static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
+    LPDIRECTSOUND iface,
+    LPDWORD lpdwSpeakerConfig)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+    return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
+}
+
+static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
+    LPDIRECTSOUND iface,
+    DWORD config)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    TRACE("(%p,0x%08lx)\n",This,config);
+    return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
+}
+
+static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
+    LPDIRECTSOUND iface,
+    LPCGUID lpcGuid)
+{
+    ICOM_THIS(IDirectSound_IDirectSound,iface);
+    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+    return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
+}
+
+static ICOM_VTABLE(IDirectSound) DirectSound_DirectSound_Vtbl =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectSound_IDirectSound_QueryInterface,
+    IDirectSound_IDirectSound_AddRef,
+    IDirectSound_IDirectSound_Release,
+    IDirectSound_IDirectSound_CreateSoundBuffer,
+    IDirectSound_IDirectSound_GetCaps,
+    IDirectSound_IDirectSound_DuplicateSoundBuffer,
+    IDirectSound_IDirectSound_SetCooperativeLevel,
+    IDirectSound_IDirectSound_Compact,
+    IDirectSound_IDirectSound_GetSpeakerConfig,
+    IDirectSound_IDirectSound_SetSpeakerConfig,
+    IDirectSound_IDirectSound_Initialize
+};
+
+HRESULT WINAPI IDirectSound_IDirectSound_Create(
+    LPDIRECTSOUND8  pds,
+    LPDIRECTSOUND * ppds)
+{
+    IDirectSound_IDirectSound * pdsds;
+    TRACE("(%p,%p)\n",pds,ppds);
+
+    if (ppds == NULL) {
+        ERR("invalid parameter\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (pds == NULL) {
+        ERR("invalid parameter\n");
+        *ppds = NULL;
+        return DSERR_INVALIDPARAM;
+    }
+
+    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
+    if (pdsds == NULL) {
+        WARN("out of memory\n");
+        *ppds = NULL;
+        return DSERR_OUTOFMEMORY;
+    }
+
+    pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
+    pdsds->ref = 0;
+    pdsds->pds = pds;
+
+    IDirectSoundImpl_AddRef(pds);
+    *ppds = (LPDIRECTSOUND)pdsds;
+
+    return DS_OK;
+}
+
+/*******************************************************************************
+ *		IDirectSound8_IUnknown
+ */
+static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
+    LPUNKNOWN iface,
+    REFIID riid,
+    LPVOID * ppobj)
+{
+    ICOM_THIS(IDirectSound_IUnknown,iface);
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
+}
+
+static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
+    LPUNKNOWN iface)
+{
+    ICOM_THIS(IDirectSound_IUnknown,iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI IDirectSound8_IUnknown_Release(
+    LPUNKNOWN iface)
+{
+    ICOM_THIS(IDirectSound_IUnknown,iface);
+    ULONG ulReturn;
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    ulReturn = InterlockedDecrement(&This->ref);
+    if (ulReturn == 0) {
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(),0,This);
+        TRACE("(%p) released\n",This);
+    }
+    return ulReturn;
+}
+
+static ICOM_VTABLE(IUnknown) DirectSound8_Unknown_Vtbl =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectSound8_IUnknown_QueryInterface,
+    IDirectSound8_IUnknown_AddRef,
+    IDirectSound8_IUnknown_Release
+};
+
+HRESULT WINAPI IDirectSound8_IUnknown_Create(
+    LPDIRECTSOUND8 pds,
+    LPUNKNOWN * ppunk)
+{
+    IDirectSound8_IUnknown * pdsunk;
+    TRACE("(%p,%p)\n",pds,ppunk);
+
+    if (ppunk == NULL) {
+        ERR("invalid parameter\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (pds == NULL) {
+        ERR("invalid parameter\n");
+        *ppunk = NULL;
+        return DSERR_INVALIDPARAM;
+    }
+
+    pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
+    if (pdsunk == NULL) {
+        WARN("out of memory\n");
+        *ppunk = NULL;
+        return DSERR_OUTOFMEMORY;
+    }
+
+    pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
+    pdsunk->ref = 0;
+    pdsunk->pds = pds;
+
+    IDirectSoundImpl_AddRef(pds);
+    *ppunk = (LPUNKNOWN)pdsunk;
+
+    return DS_OK;
+}
+
+/*******************************************************************************
+ *		IDirectSound8_IDirectSound
+ */
+static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
+    LPDIRECTSOUND iface,
+    REFIID riid,
+    LPVOID * ppobj)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
+}
+
+static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
+    LPDIRECTSOUND iface)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI IDirectSound8_IDirectSound_Release(
+    LPDIRECTSOUND iface)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    ULONG ulReturn;
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    ulReturn = InterlockedDecrement(&This->ref);
+    if (ulReturn == 0) {
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(),0,This);
+        TRACE("(%p) released\n",This);
+    }
+    return ulReturn;
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
+    LPDIRECTSOUND iface,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER ppdsb,
+    LPUNKNOWN lpunk)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+    return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
+    LPDIRECTSOUND iface,
+    LPDSCAPS lpDSCaps)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p,%p)\n",This,lpDSCaps);
+    return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
+    LPDIRECTSOUND iface,
+    LPDIRECTSOUNDBUFFER psb,
+    LPLPDIRECTSOUNDBUFFER ppdsb)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+    return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
+    LPDIRECTSOUND iface,
+    HWND hwnd,
+    DWORD level)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
+    return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
+    LPDIRECTSOUND iface)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p)\n", This);
+    return IDirectSoundImpl_Compact(This->pds);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
+    LPDIRECTSOUND iface,
+    LPDWORD lpdwSpeakerConfig)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+    return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
+    LPDIRECTSOUND iface,
+    DWORD config)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p,0x%08lx)\n",This,config);
+    return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
+    LPDIRECTSOUND iface,
+    LPCGUID lpcGuid)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+    return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
+}
+
+static ICOM_VTABLE(IDirectSound) DirectSound8_DirectSound_Vtbl =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectSound8_IDirectSound_QueryInterface,
+    IDirectSound8_IDirectSound_AddRef,
+    IDirectSound8_IDirectSound_Release,
+    IDirectSound8_IDirectSound_CreateSoundBuffer,
+    IDirectSound8_IDirectSound_GetCaps,
+    IDirectSound8_IDirectSound_DuplicateSoundBuffer,
+    IDirectSound8_IDirectSound_SetCooperativeLevel,
+    IDirectSound8_IDirectSound_Compact,
+    IDirectSound8_IDirectSound_GetSpeakerConfig,
+    IDirectSound8_IDirectSound_SetSpeakerConfig,
+    IDirectSound8_IDirectSound_Initialize
+};
+
+HRESULT WINAPI IDirectSound8_IDirectSound_Create(
+    LPDIRECTSOUND8 pds,
+    LPDIRECTSOUND * ppds)
+{
+    IDirectSound8_IDirectSound * pdsds;
+    TRACE("(%p,%p)\n",pds,ppds);
+
+    if (ppds == NULL) {
+        ERR("invalid parameter\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (pds == NULL) {
+        ERR("invalid parameter\n");
+        *ppds = NULL;
+        return DSERR_INVALIDPARAM;
+    }
+
+    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
+    if (pdsds == NULL) {
+        WARN("out of memory\n");
+        *ppds = NULL;
+        return DSERR_OUTOFMEMORY;
+    }
+
+    pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
+    pdsds->ref = 0;
+    pdsds->pds = pds;
+
+    IDirectSoundImpl_AddRef(pds);
+    *ppds = (LPDIRECTSOUND)pdsds;
+
+    return DS_OK;
+}
+
+/*******************************************************************************
+ *		IDirectSound8_IDirectSound8
+ */
+static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
+    LPDIRECTSOUND8 iface,
+    REFIID riid,
+    LPVOID * ppobj)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
+}
+
+static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
+    LPDIRECTSOUND8 iface)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
+    LPDIRECTSOUND8 iface)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    ULONG ulReturn;
+    TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
+    ulReturn = InterlockedDecrement(&This->ref);
+    if (ulReturn == 0) {
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(),0,This);
+        TRACE("(%p) released\n",This);
+    }
+    return ulReturn;
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
+    LPDIRECTSOUND8 iface,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER ppdsb,
+    LPUNKNOWN lpunk)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+    return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
+    LPDIRECTSOUND8 iface,
+    LPDSCAPS lpDSCaps)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound,iface);
+    TRACE("(%p,%p)\n",This,lpDSCaps);
+    return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
+    LPDIRECTSOUND8 iface,
+    LPDIRECTSOUNDBUFFER psb,
+    LPLPDIRECTSOUNDBUFFER ppdsb)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+    return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
+    LPDIRECTSOUND8 iface,
+    HWND hwnd,
+    DWORD level)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
+    return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
+    LPDIRECTSOUND8 iface)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    TRACE("(%p)\n", This);
+    return IDirectSoundImpl_Compact(This->pds);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
+    LPDIRECTSOUND8 iface,
+    LPDWORD lpdwSpeakerConfig)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+    return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
+    LPDIRECTSOUND8 iface,
+    DWORD config)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    TRACE("(%p,0x%08lx)\n",This,config);
+    return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
+    LPDIRECTSOUND8 iface,
+    LPCGUID lpcGuid)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+    return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
+    LPDIRECTSOUND8 iface,
+    LPDWORD pdwCertified)
+{
+    ICOM_THIS(IDirectSound8_IDirectSound8,iface);
+    TRACE("(%p, %p)\n", This, pdwCertified);
+    return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
+}
+
+static ICOM_VTABLE(IDirectSound8) DirectSound8_DirectSound8_Vtbl =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IDirectSound8_IDirectSound8_QueryInterface,
+    IDirectSound8_IDirectSound8_AddRef,
+    IDirectSound8_IDirectSound8_Release,
+    IDirectSound8_IDirectSound8_CreateSoundBuffer,
+    IDirectSound8_IDirectSound8_GetCaps,
+    IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
+    IDirectSound8_IDirectSound8_SetCooperativeLevel,
+    IDirectSound8_IDirectSound8_Compact,
+    IDirectSound8_IDirectSound8_GetSpeakerConfig,
+    IDirectSound8_IDirectSound8_SetSpeakerConfig,
+    IDirectSound8_IDirectSound8_Initialize,
+    IDirectSound8_IDirectSound8_VerifyCertification
+};
+
+HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
+    LPDIRECTSOUND8 pds,
+    LPDIRECTSOUND8 * ppds)
+{
+    IDirectSound8_IDirectSound8 * pdsds;
+    TRACE("(%p,%p)\n",pds,ppds);
+
+    if (ppds == NULL) {
+        ERR("invalid parameter\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (pds == NULL) {
+        ERR("invalid parameter\n");
+        *ppds = NULL;
+        return DSERR_INVALIDPARAM;
+    }
+
+    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
+    if (pdsds == NULL) {
+        WARN("out of memory\n");
+        *ppds = NULL;
+        return DSERR_OUTOFMEMORY;
+    }
+
+    pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
+    pdsds->ref = 0;
+    pdsds->pds = pds;
+
+    IDirectSoundImpl_AddRef(pds);
+    *ppds = (LPDIRECTSOUND8)pdsds;
+
+    return DS_OK;
+}
+
+/*******************************************************************************
+ *		DirectSoundCreate (DSOUND.1)
+ *
+ *  Creates and initializes a DirectSound interface.
+ *
+ *  PARAMS
+ *     lpcGUID   [I] Address of the GUID that identifies the sound device.
+ *     ppDS      [O] Address of a variable to receive the interface pointer.
+ *     pUnkOuter [I] Must be NULL.
+ *
+ *  RETURNS
+ *     Success: DS_OK
+ *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
+ *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
+ */
+HRESULT WINAPI DirectSoundCreate(
+    LPCGUID lpcGUID,
+    LPDIRECTSOUND *ppDS,
+    IUnknown *pUnkOuter)
+{
+    HRESULT hr;
+    GUID devGuid;
+
+    TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
+
+    if (ppDS == NULL) {
+        WARN("invalid parameter: ppDS == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    /* Get dsound configuration */
+    setup_dsound_options();
+
+    /* Default device? */
+    if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
+        lpcGUID = &DSDEVID_DefaultPlayback;
+
+    if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
+        WARN("invalid parameter: lpcGUID\n");
+        *ppDS = NULL;
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (dsound) {
+        if (IsEqualGUID(&devGuid, &dsound->guid)) {
+            hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
+            if (*ppDS)
+                IDirectSound_IDirectSound_AddRef(*ppDS);
+            return hr;
+        } else {
+            ERR("different dsound already opened (only support one sound card at a time now)\n");
+            *ppDS = NULL;
+            hr = DSERR_ALLOCATED;
+        }
+    } else {
+        LPDIRECTSOUND8 pDS;
+        hr = IDirectSoundImpl_Create(&devGuid, &pDS);
+        if (pDS) {
+            HRESULT hres;
+            dsound = (IDirectSoundImpl*)pDS;
+            hres = DSOUND_PrimaryCreate(dsound);
+            if (hres != DS_OK) {
+                WARN("DSOUND_PrimaryCreate failed\n");
+                return hres;
+            }
+            timeBeginPeriod(DS_TIME_RES);
+            dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
+                               (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
+        }
+        hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
+        if (*ppDS)
+            IDirectSound_IDirectSound_AddRef(*ppDS);
+    }
+                                                                                                                                             
+    return hr;
+}
+
+/*******************************************************************************
+ *        DirectSoundCreate8 (DSOUND.11)
+ *
+ *  Creates and initializes a DirectSound8 interface.
+ *
+ *  PARAMS
+ *     lpcGUID   [I] Address of the GUID that identifies the sound device.
+ *     ppDS      [O] Address of a variable to receive the interface pointer.
+ *     pUnkOuter [I] Must be NULL.
+ *
+ *  RETURNS
+ *     Success: DS_OK
+ *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
+ *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
+ */
+HRESULT WINAPI DirectSoundCreate8(
+    LPCGUID lpcGUID,
+    LPDIRECTSOUND8 *ppDS,
+    IUnknown *pUnkOuter)
+{
+    HRESULT hr;
+    GUID devGuid;
+
+    TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
+
+    if (ppDS == NULL) {
+        WARN("invalid parameter: ppDS == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
+
+    /* Get dsound configuration */
+    setup_dsound_options();
+
+    /* Default device? */
+    if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
+        lpcGUID = &DSDEVID_DefaultPlayback;
+
+    if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
+        WARN("invalid parameter: lpcGUID\n");
+        *ppDS = NULL;
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (dsound) {
+        if (IsEqualGUID(&devGuid, &dsound->guid)) {
+            hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
+            if (*ppDS)
+                IDirectSound8_IDirectSound8_AddRef(*ppDS);
+            return hr;
+        } else {
+            ERR("different dsound already opened (only support one sound card at a time now)\n");
+            *ppDS = NULL;
+            hr = DSERR_ALLOCATED;
+        }
+    } else {
+        LPDIRECTSOUND8 pDS;
+        hr = IDirectSoundImpl_Create(&devGuid, &pDS);
+        if (pDS) {
+            HRESULT hres;
+            dsound = (IDirectSoundImpl*)pDS;
+            hres = DSOUND_PrimaryCreate(dsound);
+            if (hres != DS_OK) {
+                WARN("DSOUND_PrimaryCreate failed\n");
+                return hres;
+            }
+            timeBeginPeriod(DS_TIME_RES);
+            dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
+                               (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
+        }
+        hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
+        if (*ppDS)
+            IDirectSound8_IDirectSound8_AddRef(*ppDS);
+    }
+                                                                                                                                             
+    return hr;
+}
+


More information about the wine-patches mailing list