dsound DirectSound/DirectSound8 patch

Robert Reif reif at earthlink.net
Wed Jun 30 20:19:14 CDT 2004


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 --unidirectional-new-file dlls/dsound/buffer.c /home/wine/wine.save6/dlls/dsound/buffer.c
--- dlls/dsound/buffer.c	2004-06-29 08:02:30.000000000 -0400
+++ /home/wine/wine.save6/dlls/dsound/buffer.c	2004-03-10 18:39:27.000000000 -0500
@@ -100,7 +100,7 @@
 	ICOM_THIS(IDirectSoundNotifyImpl,iface);
 	TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
 
-        if (howmuch > 0 && notify == NULL) {
+	if (notify == NULL) {
 	    WARN("invalid parameter: notify == NULL\n");
 	    return DSERR_INVALIDPARAM;
 	}
@@ -118,7 +118,7 @@
 	    if (hres != DS_OK)
 		    WARN("IDsDriverNotify_SetNotificationPositions failed\n");
 	    return hres;
-        } else if (howmuch > 0) {
+	} else {
 	    /* Make an internal copy of the caller-supplied array.
 	     * Replace the existing copy if one is already present. */
 	    if (This->dsb->notifies) 
@@ -134,13 +134,7 @@
 	    }
 	    memcpy(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
 	    This->dsb->nrofnotifies = howmuch;
-        } else {
-           if (This->dsb->notifies) {
-               HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
-               This->dsb->notifies = NULL;
-           }
-           This->dsb->nrofnotifies = 0;
-        }
+	}
 
 	return S_OK;
 }
Binary files dlls/dsound/buffer.o and /home/wine/wine.save6/dlls/dsound/buffer.o differ
diff -u --unidirectional-new-file dlls/dsound/capture.c /home/wine/wine.save6/dlls/dsound/capture.c
--- dlls/dsound/capture.c	2004-06-29 08:02:30.000000000 -0400
+++ /home/wine/wine.save6/dlls/dsound/capture.c	2004-03-10 18:39:28.000000000 -0500
@@ -320,14 +320,18 @@
 	msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
 
     if (msg == MM_WIM_DATA) {
-        LPWAVEHDR pHdr = (LPWAVEHDR)dw1;
     	EnterCriticalSection( &(This->lock) );
 	TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
 	    captureStateString[This->state],This->index);
 	if (This->state != STATE_STOPPED) {
 	    int index = This->index;
 	    if (This->state == STATE_STARTING) { 
-                This->read_position = pHdr->dwBytesRecorded;
+		MMTIME mtime;
+		mtime.wType = TIME_BYTES;
+		waveInGetPosition(This->hwi, &mtime, sizeof(mtime));
+		TRACE("mtime.u.cb=%ld,This->buflen=%ld\n", mtime.u.cb, This->buflen);
+		mtime.u.cb = mtime.u.cb % This->buflen;
+		This->read_position = mtime.u.cb;
 		This->state = STATE_CAPTURING;
 	    }
 	    waveInUnprepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR));
@@ -667,8 +671,7 @@
 	return DSERR_INVALIDPARAM;
     }
 
-    if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) && 
-          (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) || 
+    if ( (lpcDSCBufferDesc->dwSize < sizeof(DSCBUFFERDESC)) || 
         (lpcDSCBufferDesc->dwBufferBytes == 0) ||
         (lpcDSCBufferDesc->lpwfxFormat == NULL) ) {
 	WARN("invalid lpcDSCBufferDesc\n");
@@ -824,8 +827,6 @@
 
     ref = InterlockedDecrement(&(This->ref));
     if (ref == 0) {
-        if (This->dscb->hwnotify)
-            IDsDriverNotify_Release(This->dscb->hwnotify);
 	This->dscb->notify=NULL;
 	IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
 	HeapFree(GetProcessHeap(),0,This);
@@ -842,7 +843,7 @@
     ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
     TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
 
-    if (howmuch > 0 && notify == NULL) {
+    if (notify == NULL) {
 	WARN("invalid parameter: notify == NULL\n");
 	return DSERR_INVALIDPARAM;
     }
@@ -860,7 +861,7 @@
 	if (hres != DS_OK)
 	    WARN("IDsDriverNotify_SetNotificationPositions failed\n");
 	return hres;
-    } else if (howmuch > 0) {
+    } else {
 	/* Make an internal copy of the caller-supplied array.
 	 * Replace the existing copy if one is already present. */
 	if (This->dscb->notifies)
@@ -876,12 +877,6 @@
 	}
 	memcpy(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
 	This->dscb->nrofnotifies = howmuch;
-    } else {
-        if (This->dscb->notifies) {
-            HeapFree(GetProcessHeap(), 0, This->dscb->notifies);
-            This->dscb->notifies = NULL;
-        }
-        This->dscb->nrofnotifies = 0;
     }
 
     return S_OK;
@@ -1370,11 +1365,6 @@
 	                ipDSC->nrofpwaves*sizeof(WAVEHDR));
 
                 for (c = 0; c < ipDSC->nrofpwaves; c++) {
-                    if (This->notifies[c].dwOffset == DSBPN_OFFSETSTOP) {
-                        TRACE("got DSBPN_OFFSETSTOP\n");
-                        ipDSC->nrofpwaves = c;
-                        break;
-                    }
                     if (c == 0) {
                         ipDSC->pwave[0].lpData = ipDSC->buffer;
                         ipDSC->pwave[0].dwBufferLength = 
@@ -1386,14 +1376,12 @@
                             This->notifies[c].dwOffset - 
                             This->notifies[c-1].dwOffset;
                     }
-                    ipDSC->pwave[c].dwBytesRecorded = 0;
                     ipDSC->pwave[c].dwUser = (DWORD)ipDSC;
                     ipDSC->pwave[c].dwFlags = 0;
                     ipDSC->pwave[c].dwLoops = 0;
                     err = mmErr(waveInPrepareHeader(ipDSC->hwi,
                         &(ipDSC->pwave[c]),sizeof(WAVEHDR)));
 		    if (err != DS_OK) {
-                        WARN("waveInPrepareHeader failed\n");
 			while (c--)
 			    waveInUnprepareHeader(ipDSC->hwi,
 				&(ipDSC->pwave[c]),sizeof(WAVEHDR));
@@ -1403,7 +1391,6 @@
 	            err = mmErr(waveInAddBuffer(ipDSC->hwi, 
 			&(ipDSC->pwave[c]), sizeof(WAVEHDR)));
 		    if (err != DS_OK) {
-                        WARN("waveInAddBuffer failed\n");
                         while (c--)
 			    waveInUnprepareHeader(ipDSC->hwi,
 				&(ipDSC->pwave[c]),sizeof(WAVEHDR));
@@ -1424,7 +1411,6 @@
 
                 ipDSC->pwave[0].lpData = ipDSC->buffer;
                 ipDSC->pwave[0].dwBufferLength = ipDSC->buflen; 
-                ipDSC->pwave[0].dwBytesRecorded = 0;
                 ipDSC->pwave[0].dwUser = (DWORD)ipDSC;
                 ipDSC->pwave[0].dwFlags = 0;
                 ipDSC->pwave[0].dwLoops = 0;
@@ -1439,7 +1425,6 @@
 	        err = mmErr(waveInAddBuffer(ipDSC->hwi, 
 		    &(ipDSC->pwave[0]), sizeof(WAVEHDR)));
 		if (err != DS_OK) {
-		    WARN("waveInAddBuffer failed\n");
 	    	    waveInUnprepareHeader(ipDSC->hwi,
 			&(ipDSC->pwave[0]),sizeof(WAVEHDR));
 		}
@@ -1452,8 +1437,6 @@
 	if (err == DS_OK) {
 	    /* start filling the first buffer */
 	    err = mmErr(waveInStart(ipDSC->hwi));
-            if (err != DS_OK)
-                WARN("waveInStart failed\n");
         }
     }
 
@@ -1687,7 +1670,7 @@
 IClassFactoryImpl DSOUND_CAPTURE_CF = { &DSCCF_Vtbl, 1 };
 
 /***************************************************************************
- * DirectSoundFullDuplexCreate [DSOUND.10]
+ * DirectSoundFullDuplexCreate8 [DSOUND.10]
  *
  * Create and initialize a DirectSoundFullDuplex interface.
  *
@@ -1709,7 +1692,7 @@
  *             DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
  */
 HRESULT WINAPI 
-DirectSoundFullDuplexCreate(
+DirectSoundFullDuplexCreate8(
     LPCGUID pcGuidCaptureDevice,
     LPCGUID pcGuidRenderDevice,
     LPCDSCBUFFERDESC pcDSCBufferDesc,
Binary files dlls/dsound/capture.o and /home/wine/wine.save6/dlls/dsound/capture.o differ
Common subdirectories: dlls/dsound/CVS and /home/wine/wine.save6/dlls/dsound/CVS
diff -u --unidirectional-new-file dlls/dsound/.cvsignore /home/wine/wine.save6/dlls/dsound/.cvsignore
--- dlls/dsound/.cvsignore	2004-05-29 18:35:41.000000000 -0400
+++ /home/wine/wine.save6/dlls/dsound/.cvsignore	2004-03-10 18:39:27.000000000 -0500
@@ -1,4 +1,5 @@
 Makefile
 dsound.dll.dbg.c
+dsound.spec.c
 dsound.spec.def
 version.res
Only in dlls/dsound: dsound.c
Binary files dlls/dsound/dsound.dll.so and /home/wine/wine.save6/dlls/dsound/dsound.dll.so differ
diff -u --unidirectional-new-file dlls/dsound/dsound_main.c /home/wine/wine.save6/dlls/dsound/dsound_main.c
--- dlls/dsound/dsound_main.c	2004-06-30 15:59:46.000000000 -0400
+++ /home/wine/wine.save6/dlls/dsound/dsound_main.c	2004-03-16 21:16:30.000000000 -0500
@@ -143,7 +143,6 @@
 {
     char buffer[MAX_PATH+1];
     HKEY hkey, appkey = 0;
-    DWORD len;
 
     buffer[MAX_PATH]='\0';
 
@@ -154,8 +153,7 @@
         ExitProcess(1);
     }
 
-    len = GetModuleFileNameA( 0, buffer, MAX_PATH );
-    if (len && len < MAX_PATH)
+    if (GetModuleFileNameA( 0, buffer, MAX_PATH ))
     {
         HKEY tmpkey;
 
@@ -438,6 +436,764 @@
     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)\n",This,(DWORD)hwnd,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_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 (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
  */
diff -u --unidirectional-new-file dlls/dsound/.#dsound_main.c.1.96 /home/wine/wine.save6/dlls/dsound/.#dsound_main.c.1.96
--- dlls/dsound/.#dsound_main.c.1.96	1969-12-31 19:00:00.000000000 -0500
+++ /home/wine/wine.save6/dlls/dsound/.#dsound_main.c.1.96	2004-03-16 19:25:04.000000000 -0500
@@ -0,0 +1,1421 @@
+/*  			DirectSound
+ *
+ * Copyright 1998 Marcus Meissner
+ * Copyright 1998 Rob Riggs
+ * Copyright 2000-2002 TransGaming Technologies, Inc.
+ *
+ * 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
+ */
+/*
+ * Most thread locking is complete. There may be a few race
+ * conditions still lurking.
+ *
+ * Tested with a Soundblaster clone, a Gravis UltraSound Classic,
+ * and a Turtle Beach Tropez+.
+ *
+ * TODO:
+ *	Implement SetCooperativeLevel properly (need to address focus issues)
+ *	Implement DirectSound3DBuffers (stubs in place)
+ *	Use hardware 3D support if available
+ *      Add critical section locking inside Release and AddRef methods
+ *      Handle static buffers - put those in hardware, non-static not in hardware
+ *      Hardware DuplicateSoundBuffer
+ *      Proper volume calculation, and setting volume in HEL primary buffer
+ *      Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN
+ */
+
+#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>
+#include <math.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);
+
+/* these are eligible for tuning... they must be high on slow machines... */
+/* some stuff may get more responsive with lower values though... */
+#define DS_EMULDRIVER 0 /* some games (Quake 2, UT) refuse to accept
+				emulated dsound devices. set to 0 ! */
+#define DS_HEL_MARGIN 5 /* HEL only: number of waveOut fragments ahead to mix in new buffers
+			 * (keep this close or equal to DS_HEL_QUEUE for best results) */
+#define DS_HEL_QUEUE  5 /* HEL only: number of waveOut fragments ahead to queue to driver
+			 * (this will affect HEL sound reliability and latency) */
+
+#define DS_SND_QUEUE_MAX 28 /* max number of fragments to prebuffer */
+#define DS_SND_QUEUE_MIN 12 /* min number of fragments to prebuffer */
+
+IDirectSoundImpl*	dsound = NULL;
+
+HRESULT mmErr(UINT err)
+{
+	switch(err) {
+	case MMSYSERR_NOERROR:
+		return DS_OK;
+	case MMSYSERR_ALLOCATED:
+		return DSERR_ALLOCATED;
+	case MMSYSERR_ERROR:
+	case MMSYSERR_INVALHANDLE:
+	case WAVERR_STILLPLAYING:
+		return DSERR_GENERIC; /* FIXME */
+	case MMSYSERR_NODRIVER:
+		return DSERR_NODRIVER;
+	case MMSYSERR_NOMEM:
+		return DSERR_OUTOFMEMORY;
+	case MMSYSERR_INVALPARAM:
+	case WAVERR_BADFORMAT:
+	case WAVERR_UNPREPARED:
+		return DSERR_INVALIDPARAM;
+	case MMSYSERR_NOTSUPPORTED:
+		return DSERR_UNSUPPORTED;
+	default:
+		FIXME("Unknown MMSYS error %d\n",err);
+		return DSERR_GENERIC;
+	}
+}
+
+int ds_emuldriver = DS_EMULDRIVER;
+int ds_hel_margin = DS_HEL_MARGIN;
+int ds_hel_queue = DS_HEL_QUEUE;
+int ds_snd_queue_max = DS_SND_QUEUE_MAX;
+int ds_snd_queue_min = DS_SND_QUEUE_MIN;
+int ds_hw_accel = DS_HW_ACCEL_FULL;
+int ds_default_playback = 0;
+int ds_default_capture = 0;
+
+/*
+ * Get a config key from either the app-specific or the default config
+ */
+
+inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
+                                    char *buffer, DWORD size )
+{
+    if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, buffer, &size )) return 0;
+    return RegQueryValueExA( defkey, name, 0, NULL, buffer, &size );
+}
+
+
+/*
+ * Setup the dsound options.
+ */
+
+void setup_dsound_options(void)
+{
+    char buffer[MAX_PATH+1];
+    HKEY hkey, appkey = 0;
+
+    buffer[MAX_PATH]='\0';
+
+    if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\dsound", 0, NULL,
+                         REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ))
+    {
+        ERR("Cannot create config registry key\n" );
+        ExitProcess(1);
+    }
+
+    if (GetModuleFileNameA( 0, buffer, MAX_PATH ))
+    {
+        HKEY tmpkey;
+
+        if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\AppDefaults", &tmpkey ))
+        {
+           char appname[MAX_PATH+16];
+           char *p = strrchr( buffer, '\\' );
+           if (p!=NULL) {
+                   appname[MAX_PATH]='\0';
+                   strncpy(appname,p+1,MAX_PATH);
+                   strcat(appname,"\\dsound");
+                   TRACE("appname = [%s] \n",appname);
+                   if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
+                       RegCloseKey( tmpkey );
+           }
+        }
+    }
+
+    /* get options */
+
+    if (!get_config_key( hkey, appkey, "EmulDriver", buffer, MAX_PATH ))
+        ds_emuldriver = strcmp(buffer, "N");
+
+    if (!get_config_key( hkey, appkey, "HELmargin", buffer, MAX_PATH ))
+        ds_hel_margin = atoi(buffer);
+
+    if (!get_config_key( hkey, appkey, "HELqueue", buffer, MAX_PATH ))
+        ds_hel_queue = atoi(buffer);
+
+    if (!get_config_key( hkey, appkey, "SndQueueMax", buffer, MAX_PATH ))
+        ds_snd_queue_max = atoi(buffer);
+
+    if (!get_config_key( hkey, appkey, "SndQueueMin", buffer, MAX_PATH ))
+        ds_snd_queue_min = atoi(buffer);
+
+    if (!get_config_key( hkey, appkey, "HardwareAcceleration", buffer, MAX_PATH )) {
+	if (strcmp(buffer, "Full") == 0)
+	    ds_hw_accel = DS_HW_ACCEL_FULL;
+	else if (strcmp(buffer, "Standard") == 0)
+	    ds_hw_accel = DS_HW_ACCEL_STANDARD;
+	else if (strcmp(buffer, "Basic") == 0)
+	    ds_hw_accel = DS_HW_ACCEL_BASIC;
+	else if (strcmp(buffer, "Emulation") == 0)
+	    ds_hw_accel = DS_HW_ACCEL_EMULATION;
+    }
+
+    if (!get_config_key( hkey, appkey, "DefaultPlayback", buffer, MAX_PATH ))
+	    ds_default_playback = atoi(buffer);
+
+    if (!get_config_key( hkey, appkey, "DefaultCapture", buffer, MAX_PATH ))
+	    ds_default_capture = atoi(buffer);
+
+    if (appkey) RegCloseKey( appkey );
+    RegCloseKey( hkey );
+
+    if (ds_emuldriver != DS_EMULDRIVER )
+       WARN("ds_emuldriver = %d (default=%d)\n",ds_emuldriver, DS_EMULDRIVER);
+    if (ds_hel_margin != DS_HEL_MARGIN )
+       WARN("ds_hel_margin = %d (default=%d)\n",ds_hel_margin, DS_HEL_MARGIN );
+    if (ds_hel_queue != DS_HEL_QUEUE )
+       WARN("ds_hel_queue = %d (default=%d)\n",ds_hel_queue, DS_HEL_QUEUE );
+    if (ds_snd_queue_max != DS_SND_QUEUE_MAX)
+       WARN("ds_snd_queue_max = %d (default=%d)\n",ds_snd_queue_max ,DS_SND_QUEUE_MAX);
+    if (ds_snd_queue_min != DS_SND_QUEUE_MIN)
+       WARN("ds_snd_queue_min = %d (default=%d)\n",ds_snd_queue_min ,DS_SND_QUEUE_MIN);
+    if (ds_hw_accel != DS_HW_ACCEL_FULL)
+	WARN("ds_hw_accel = %s (default=Full)\n", 
+	    ds_hw_accel==DS_HW_ACCEL_FULL ? "Full" :
+	    ds_hw_accel==DS_HW_ACCEL_STANDARD ? "Standard" :
+	    ds_hw_accel==DS_HW_ACCEL_BASIC ? "Basic" :
+	    ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" :
+	    "Unknown");
+    if (ds_default_playback != 0)
+	WARN("ds_default_playback = %d (default=0)\n",ds_default_playback);
+    if (ds_default_capture != 0)
+	WARN("ds_default_capture = %d (default=0)\n",ds_default_playback);
+}
+
+
+
+/***************************************************************************
+ * GetDeviceID	[DSOUND.9]
+ *
+ * Retrieves unique identifier of default device specified
+ *
+ * PARAMS
+ *    pGuidSrc  [I] Address of device GUID.
+ *    pGuidDest [O] Address to receive unique device GUID.
+ *
+ * RETURNS
+ *    Success: DS_OK
+ *    Failure: DSERR_INVALIDPARAM
+ *
+ * NOTES
+ *    pGuidSrc is a valid device GUID or DSDEVID_DefaultPlayback,
+ *    DSDEVID_DefaultCapture, DSDEVID_DefaultVoicePlayback, or 
+ *    DSDEVID_DefaultVoiceCapture.
+ *    Returns pGuidSrc if pGuidSrc is a valid device or the device
+ *    GUID for the specified constants.
+ */
+HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
+{
+    TRACE("(%p,%p)\n",pGuidSrc,pGuidDest);
+
+    if ( pGuidSrc == NULL) {
+	WARN("invalid parameter: pGuidSrc == NULL\n");
+	return DSERR_INVALIDPARAM;
+    }
+
+    if ( pGuidDest == NULL ) {
+	WARN("invalid parameter: pGuidDest == NULL\n");
+	return DSERR_INVALIDPARAM;
+    }
+
+    if ( IsEqualGUID( &DSDEVID_DefaultPlayback, pGuidSrc ) ||
+    	IsEqualGUID( &DSDEVID_DefaultVoicePlayback, pGuidSrc ) ) {
+	GUID guid;
+	int err = mmErr(waveOutMessage((HWAVEOUT)ds_default_playback,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
+	if (err == DS_OK) {
+	    memcpy(pGuidDest, &guid, sizeof(GUID));
+	    return DS_OK;
+	}
+    }
+
+    if ( IsEqualGUID( &DSDEVID_DefaultCapture, pGuidSrc ) ||
+    	IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) {
+	GUID guid;
+	int err = mmErr(waveInMessage((HWAVEIN)ds_default_capture,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
+	if (err == DS_OK) {
+	    memcpy(pGuidDest, &guid, sizeof(GUID));
+	    return DS_OK;
+	}
+    }
+
+    memcpy(pGuidDest, pGuidSrc, sizeof(GUID));
+
+    return DS_OK;
+}
+
+
+/***************************************************************************
+ * DirectSoundEnumerateA [DSOUND.2]
+ *
+ * Enumerate all DirectSound drivers installed in the system
+ *
+ * PARAMS
+ *    lpDSEnumCallback  [I] Address of callback function.
+ *    lpContext         [I] Address of user defined context passed to callback function.
+ *
+ * RETURNS
+ *    Success: DS_OK
+ *    Failure: DSERR_INVALIDPARAM
+ */
+HRESULT WINAPI DirectSoundEnumerateA(
+    LPDSENUMCALLBACKA lpDSEnumCallback,
+    LPVOID lpContext)
+{
+    unsigned devs, wod;
+    DSDRIVERDESC desc;
+    GUID guid;
+    int err;
+
+    TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
+	lpDSEnumCallback, lpContext);
+
+    if (lpDSEnumCallback == NULL) {
+	WARN("invalid parameter: lpDSEnumCallback == NULL\n");
+	return DSERR_INVALIDPARAM;
+    }
+
+    devs = waveOutGetNumDevs();
+    if (devs > 0) {
+	if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) {
+	    GUID temp;
+	    for (wod = 0; wod < devs; ++wod) {
+		err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
+		if (err == DS_OK) {
+		    if (IsEqualGUID( &guid, &temp ) ) {
+			err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
+			if (err == DS_OK) {
+			    TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
+				"Primary Sound Driver",desc.szDrvName,lpContext);
+			    if (lpDSEnumCallback(NULL, "Primary Sound Driver", desc.szDrvName, lpContext) == FALSE)
+				return DS_OK;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+    for (wod = 0; wod < devs; ++wod) {
+	err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
+	if (err == DS_OK) {
+	    err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
+	    if (err == DS_OK) {
+		TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
+		    debugstr_guid(&guid),desc.szDesc,desc.szDrvName,lpContext);
+		if (lpDSEnumCallback(&guid, desc.szDesc, desc.szDrvName, lpContext) == FALSE)
+		    return DS_OK;
+	    }
+	}
+    }
+    return DS_OK;
+}
+
+/***************************************************************************
+ * DirectSoundEnumerateW [DSOUND.3]
+ *
+ * Enumerate all DirectSound drivers installed in the system
+ *
+ * PARAMS
+ *    lpDSEnumCallback  [I] Address of callback function.
+ *    lpContext         [I] Address of user defined context passed to callback function.
+ *
+ * RETURNS
+ *    Success: DS_OK
+ *    Failure: DSERR_INVALIDPARAM
+ */
+HRESULT WINAPI DirectSoundEnumerateW(
+	LPDSENUMCALLBACKW lpDSEnumCallback,
+	LPVOID lpContext )
+{
+    unsigned devs, wod;
+    DSDRIVERDESC desc;
+    GUID guid;
+    int err;
+    WCHAR wDesc[MAXPNAMELEN];
+    WCHAR wName[MAXPNAMELEN];
+
+    TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
+	lpDSEnumCallback, lpContext);
+
+    if (lpDSEnumCallback == NULL) {
+	WARN("invalid parameter: lpDSEnumCallback == NULL\n");
+	return DSERR_INVALIDPARAM;
+    }
+
+    devs = waveOutGetNumDevs();
+    if (devs > 0) {
+	if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) {
+	    GUID temp;
+	    for (wod = 0; wod < devs; ++wod) {
+		err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
+		if (err == DS_OK) {
+		    if (IsEqualGUID( &guid, &temp ) ) {
+			err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
+			if (err == DS_OK) {
+			    TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
+				"Primary Sound Driver",desc.szDrvName,lpContext);
+			    MultiByteToWideChar( CP_ACP, 0, "Primary Sound Driver", -1,
+				wDesc, sizeof(wDesc)/sizeof(WCHAR) );
+				MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
+				wName, sizeof(wName)/sizeof(WCHAR) );
+			    if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
+				return DS_OK;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+    for (wod = 0; wod < devs; ++wod) {
+	err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
+	if (err == DS_OK) {
+	    err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
+	    if (err == DS_OK) {
+		TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
+		    debugstr_guid(&guid),desc.szDesc,desc.szDrvName,lpContext);
+		MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
+		    wDesc, sizeof(wDesc)/sizeof(WCHAR) );
+		    MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
+		    wName, sizeof(wName)/sizeof(WCHAR) );
+		if (lpDSEnumCallback(&guid, wDesc, wName, lpContext) == FALSE)
+		    return DS_OK;
+	    }
+	}
+    }
+    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)\n",This,(DWORD)hwnd,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_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 (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
+ */
+
+static HRESULT WINAPI
+DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
+	ICOM_THIS(IClassFactoryImpl,iface);
+
+	FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
+	return E_NOINTERFACE;
+}
+
+static ULONG WINAPI
+DSCF_AddRef(LPCLASSFACTORY iface) {
+	ICOM_THIS(IClassFactoryImpl,iface);
+	TRACE("(%p) ref was %ld\n", This, This->ref);
+	return ++(This->ref);
+}
+
+static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface) {
+	ICOM_THIS(IClassFactoryImpl,iface);
+	/* static class, won't be  freed */
+	TRACE("(%p) ref was %ld\n", This, This->ref);
+	return --(This->ref);
+}
+
+static HRESULT WINAPI DSCF_CreateInstance(
+	LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
+) {
+	ICOM_THIS(IClassFactoryImpl,iface);
+	TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
+
+	if (ppobj == NULL) {
+		WARN("invalid parameter\n");
+		return DSERR_INVALIDPARAM;
+	}
+
+	*ppobj = NULL;
+
+	if ( IsEqualGUID( &IID_IDirectSound, riid ) ||
+	     IsEqualGUID( &IID_IDirectSound8, riid ) ) {
+		/* FIXME: reuse already created dsound if present? */
+		return DirectSoundCreate8(0,(LPDIRECTSOUND8*)ppobj,pOuter);
+	}
+
+	WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);	
+	return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
+	ICOM_THIS(IClassFactoryImpl,iface);
+	FIXME("(%p)->(%d),stub!\n",This,dolock);
+	return S_OK;
+}
+
+static ICOM_VTABLE(IClassFactory) DSCF_Vtbl = {
+	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+	DSCF_QueryInterface,
+	DSCF_AddRef,
+	DSCF_Release,
+	DSCF_CreateInstance,
+	DSCF_LockServer
+};
+
+static IClassFactoryImpl DSOUND_CF = { &DSCF_Vtbl, 1 };
+
+/*******************************************************************************
+ * DirectSoundPrivate ClassFactory
+ */
+
+static HRESULT WINAPI
+DSPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
+	ICOM_THIS(IClassFactoryImpl,iface);
+
+	FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
+	return E_NOINTERFACE;
+}
+
+static ULONG WINAPI
+DSPCF_AddRef(LPCLASSFACTORY iface) {
+	ICOM_THIS(IClassFactoryImpl,iface);
+	TRACE("(%p) ref was %ld\n", This, This->ref);
+	return ++(This->ref);
+}
+
+static ULONG WINAPI 
+DSPCF_Release(LPCLASSFACTORY iface) {
+	ICOM_THIS(IClassFactoryImpl,iface);
+	/* static class, won't be  freed */
+	TRACE("(%p) ref was %ld\n", This, This->ref);
+	return --(This->ref);
+}
+
+static HRESULT WINAPI 
+DSPCF_CreateInstance(
+	LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
+) {
+	ICOM_THIS(IClassFactoryImpl,iface);
+	TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
+
+	if (ppobj == NULL) {
+		WARN("invalid parameter\n");
+		return DSERR_INVALIDPARAM;
+	}
+
+	*ppobj = NULL;
+
+	if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
+		return IKsPrivatePropertySetImpl_Create((IKsPrivatePropertySetImpl**)ppobj);
+	}
+
+	WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);	
+	return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI 
+DSPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
+	ICOM_THIS(IClassFactoryImpl,iface);
+	FIXME("(%p)->(%d),stub!\n",This,dolock);
+	return S_OK;
+}
+
+static ICOM_VTABLE(IClassFactory) DSPCF_Vtbl = {
+	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+	DSPCF_QueryInterface,
+	DSPCF_AddRef,
+	DSPCF_Release,
+	DSPCF_CreateInstance,
+	DSPCF_LockServer
+};
+
+static IClassFactoryImpl DSOUND_PRIVATE_CF = { &DSPCF_Vtbl, 1 };
+
+/*******************************************************************************
+ * DllGetClassObject [DSOUND.5]
+ * Retrieves class object from a DLL object
+ *
+ * NOTES
+ *    Docs say returns STDAPI
+ *
+ * PARAMS
+ *    rclsid [I] CLSID for the class object
+ *    riid   [I] Reference to identifier of interface for class object
+ *    ppv    [O] Address of variable to receive interface pointer for riid
+ *
+ * RETURNS
+ *    Success: S_OK
+ *    Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
+ *             E_UNEXPECTED
+ */
+DWORD WINAPI DSOUND_DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv)
+{
+    TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+
+    if (ppv == NULL) {
+	WARN("invalid parameter\n");
+	return E_INVALIDARG;
+    }
+
+    *ppv = NULL;
+
+    if ( IsEqualCLSID( &CLSID_DirectSound, rclsid ) ||
+	 IsEqualCLSID( &CLSID_DirectSound8, rclsid ) ) {
+	if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
+	    *ppv = (LPVOID)&DSOUND_CF;
+	    IClassFactory_AddRef((IClassFactory*)*ppv);
+	    return S_OK;
+	}
+    	WARN("(%s,%s,%p): no interface found.\n",
+	    debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+	return S_FALSE;
+    }
+    
+    if ( IsEqualCLSID( &CLSID_DirectSoundCapture, rclsid ) ||
+	 IsEqualCLSID( &CLSID_DirectSoundCapture8, rclsid ) ) {
+	if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
+	    *ppv = (LPVOID)&DSOUND_CAPTURE_CF;
+	    IClassFactory_AddRef((IClassFactory*)*ppv);
+	    return S_OK;
+	}
+    	WARN("(%s,%s,%p): no interface found.\n",
+	    debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+	return S_FALSE;
+    }
+    
+    if ( IsEqualCLSID( &CLSID_DirectSoundFullDuplex, rclsid ) ) {
+	if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
+	    *ppv = (LPVOID)&DSOUND_FULLDUPLEX_CF;
+	    IClassFactory_AddRef((IClassFactory*)*ppv);
+	    return S_OK;
+	}
+    	WARN("(%s,%s,%p): no interface found.\n",
+	    debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+	return S_FALSE;
+    }
+    
+    if ( IsEqualCLSID( &CLSID_DirectSoundPrivate, rclsid ) ) {
+	if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
+	    *ppv = (LPVOID)&DSOUND_PRIVATE_CF;
+	    IClassFactory_AddRef((IClassFactory*)*ppv);
+	    return S_OK;
+	}
+    	WARN("(%s,%s,%p): no interface found.\n",
+	    debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+	return S_FALSE;
+    }
+
+    WARN("(%s,%s,%p): no class found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+    return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+
+/*******************************************************************************
+ * DllCanUnloadNow [DSOUND.4]  
+ * Determines whether the DLL is in use.
+ *
+ * RETURNS
+ *    Success: S_OK
+ *    Failure: S_FALSE
+ */
+DWORD WINAPI DSOUND_DllCanUnloadNow(void)
+{
+    FIXME("(void): stub\n");
+    return S_FALSE;
+}
Binary files dlls/dsound/dsound_main.o and /home/wine/wine.save6/dlls/dsound/dsound_main.o differ
Only in dlls/dsound: dsound.o
diff -u --unidirectional-new-file dlls/dsound/dsound_private.h /home/wine/wine.save6/dlls/dsound/dsound_private.h
--- dlls/dsound/dsound_private.h	2004-06-30 19:37:20.000000000 -0400
+++ /home/wine/wine.save6/dlls/dsound/dsound_private.h	2004-03-16 21:16:30.000000000 -0500
@@ -44,25 +44,20 @@
 /*****************************************************************************
  * Predeclare the interface implementation structures
  */
-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 IDirectSoundImpl IDirectSoundImpl;
+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
@@ -100,10 +95,6 @@
     IDirectSound3DListenerImpl*	listener;
     DS3DLISTENER                ds3dl;
     BOOL                        ds3dl_need_recalc;
-
-    LPUNKNOWN                   pUnknown;
-    LPDIRECTSOUND               pDS;
-    LPDIRECTSOUND8              pDS8;
 };
 
 /* reference counted buffer memory for duplicated buffer memory */
@@ -113,66 +104,6 @@
     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
  */
diff -u --unidirectional-new-file dlls/dsound/.#dsound_private.h.1.14 /home/wine/wine.save6/dlls/dsound/.#dsound_private.h.1.14
--- dlls/dsound/.#dsound_private.h.1.14	1969-12-31 19:00:00.000000000 -0500
+++ /home/wine/wine.save6/dlls/dsound/.#dsound_private.h.1.14	2004-03-16 19:25:24.000000000 -0500
@@ -0,0 +1,403 @@
+/*  			DirectSound
+ *
+ * Copyright 1998 Marcus Meissner
+ * Copyright 1998 Rob Riggs
+ * Copyright 2000-2001 TransGaming Technologies, Inc.
+ *
+ * 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
+ */
+
+/* Linux does not support better timing than 10ms */
+#define DS_TIME_RES 10  /* Resolution of multimedia timer */
+#define DS_TIME_DEL 10  /* Delay of multimedia timer callback, and duration of HEL fragment */
+
+#define DS_HEL_FRAGS 48 /* HEL only: number of waveOut fragments in primary buffer
+			 * (changing this won't help you) */
+
+/* direct sound hardware acceleration levels */
+#define DS_HW_ACCEL_FULL        0	/* default on Windows 98 */
+#define DS_HW_ACCEL_STANDARD    1	/* default on Windows 2000 */
+#define DS_HW_ACCEL_BASIC       2
+#define DS_HW_ACCEL_EMULATION   3
+
+extern int ds_emuldriver;
+extern int ds_hel_margin;
+extern int ds_hel_queue;
+extern int ds_snd_queue_max;
+extern int ds_snd_queue_min;
+extern int ds_hw_accel;
+extern int ds_default_playback;
+extern int ds_default_capture;
+
+/*****************************************************************************
+ * Predeclare the interface implementation structures
+ */
+typedef struct IDirectSoundImpl IDirectSoundImpl;
+typedef struct IDirectSoundBufferImpl IDirectSoundBufferImpl;
+typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl;
+typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl;
+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;
+
+/*****************************************************************************
+ * IDirectSound implementation structure
+ */
+struct IDirectSoundImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSound8);
+    DWORD                       ref;
+    /* IDirectSoundImpl fields */
+    GUID                        guid;
+    PIDSDRIVER                  driver;
+    DSDRIVERDESC                drvdesc;
+    DSDRIVERCAPS                drvcaps;
+    DWORD                       priolevel;
+    WAVEFORMATEX                wfx; /* current main waveformat */
+    HWAVEOUT                    hwo;
+    LPWAVEHDR                   pwave[DS_HEL_FRAGS];
+    UINT                        timerID, pwplay, pwwrite, pwqueue, prebuf, precount;
+    DWORD                       fraglen;
+    PIDSDRIVERBUFFER            hwbuf;
+    LPBYTE                      buffer;
+    DWORD                       writelead, buflen, state, playpos, mixpos;
+    BOOL                        need_remix;
+    int                         nrofbuffers;
+    IDirectSoundBufferImpl**    buffers;
+    RTL_RWLOCK                  lock;
+    CRITICAL_SECTION            mixlock;
+    DSVOLUMEPAN                 volpan;
+    PrimaryBufferImpl*          primary;
+    DSBUFFERDESC                dsbd;
+    DWORD                       speaker_config;
+
+    /* DirectSound3DListener fields */
+    IDirectSound3DListenerImpl*	listener;
+    DS3DLISTENER                ds3dl;
+    BOOL                        ds3dl_need_recalc;
+};
+
+/* reference counted buffer memory for duplicated buffer memory */
+typedef struct BufferMemory
+{
+    DWORD                       ref;
+    LPBYTE                      memory;
+} BufferMemory;
+
+/*****************************************************************************
+ * IDirectSoundBuffer implementation structure
+ */
+struct IDirectSoundBufferImpl
+{
+    /* FIXME: document */
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSoundBuffer8);
+    DWORD                       ref;
+    /* IDirectSoundBufferImpl fields */
+    SecondaryBufferImpl*        dsb;
+    IDirectSoundImpl*           dsound;
+    CRITICAL_SECTION            lock;
+    PIDSDRIVERBUFFER            hwbuf;
+    WAVEFORMATEX                wfx;
+    BufferMemory*               buffer;
+    DWORD                       playflags,state,leadin;
+    DWORD                       playpos,startpos,writelead,buflen;
+    DWORD                       nAvgBytesPerSec;
+    DWORD                       freq;
+    DSVOLUMEPAN                 volpan, cvolpan;
+    DSBUFFERDESC                dsbd;
+    /* used for frequency conversion (PerfectPitch) */
+    ULONG                       freqAdjust, freqAcc;
+    /* used for intelligent (well, sort of) prebuffering */
+    DWORD                       probably_valid_to, last_playpos;
+    DWORD                       primary_mixpos, buf_mixpos;
+    BOOL                        need_remix;
+
+    /* IDirectSoundNotifyImpl fields */
+    IDirectSoundNotifyImpl*     notify;
+    LPDSBPOSITIONNOTIFY         notifies;
+    int                         nrofnotifies;
+    PIDSDRIVERNOTIFY            hwnotify;
+
+    /* DirectSound3DBuffer fields */
+    IDirectSound3DBufferImpl*   ds3db;
+    DS3DBUFFER                  ds3db_ds3db;
+    LONG                        ds3db_lVolume;
+    BOOL                        ds3db_need_recalc;
+
+    /* IKsPropertySet fields */
+    IKsBufferPropertySetImpl*   iks;
+};
+
+HRESULT WINAPI IDirectSoundBufferImpl_Create(
+    IDirectSoundImpl *ds,
+    IDirectSoundBufferImpl **pdsb,
+    LPCDSBUFFERDESC dsbd);
+
+/*****************************************************************************
+ * SecondaryBuffer implementation structure
+ */
+struct SecondaryBufferImpl
+{
+    ICOM_VFIELD(IDirectSoundBuffer8);
+    DWORD                       ref;
+    IDirectSoundBufferImpl*     dsb;
+};
+
+HRESULT WINAPI SecondaryBufferImpl_Create(
+    IDirectSoundBufferImpl *dsb,
+    SecondaryBufferImpl **pdsb);
+
+/*****************************************************************************
+ * PrimaryBuffer implementation structure
+ */
+struct PrimaryBufferImpl
+{
+    ICOM_VFIELD(IDirectSoundBuffer8);
+    DWORD                       ref;
+    IDirectSoundImpl*           dsound;
+};
+
+HRESULT WINAPI PrimaryBufferImpl_Create(
+    IDirectSoundImpl *ds,
+    PrimaryBufferImpl **pdsb,
+    LPCDSBUFFERDESC dsbd);
+
+/*****************************************************************************
+ * IDirectSoundCapture implementation structure
+ */
+struct IDirectSoundCaptureImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSoundCapture);
+    DWORD                              ref;
+
+    /* IDirectSoundCaptureImpl fields */
+    GUID                               guid;
+    BOOL                               initialized;
+
+    /* DirectSound driver stuff */
+    PIDSCDRIVER                        driver;
+    DSDRIVERDESC                       drvdesc;
+    DSCDRIVERCAPS                      drvcaps;
+    PIDSCDRIVERBUFFER                  hwbuf;
+
+    /* wave driver info */
+    HWAVEIN                            hwi;
+
+    /* more stuff */
+    LPBYTE                             buffer;
+    DWORD                              buflen;
+    DWORD                              read_position;
+
+    PWAVEFORMATEX                      pwfx;
+
+    IDirectSoundCaptureBufferImpl*     capture_buffer;
+    DWORD                              state;
+    LPWAVEHDR                          pwave;
+    int                                nrofpwaves;
+    int                                index;
+    CRITICAL_SECTION                   lock;
+};
+
+/*****************************************************************************
+ * IDirectSoundCaptureBuffer implementation structure
+ */
+struct IDirectSoundCaptureBufferImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSoundCaptureBuffer8);
+    DWORD                               ref;
+
+    /* IDirectSoundCaptureBufferImpl fields */
+    IDirectSoundCaptureImpl*            dsound;
+    /* FIXME: don't need this */
+    LPDSCBUFFERDESC                     pdscbd;
+    DWORD                               flags;
+
+    /* IDirectSoundCaptureNotifyImpl fields */
+    IDirectSoundCaptureNotifyImpl*      notify;
+    LPDSBPOSITIONNOTIFY                 notifies;
+    int                                 nrofnotifies;
+    PIDSDRIVERNOTIFY                    hwnotify;
+};
+
+/*****************************************************************************
+ * IDirectSoundFullDuplex implementation structure
+ */
+struct IDirectSoundFullDuplexImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSoundFullDuplex);
+    DWORD                       ref;
+
+    /* IDirectSoundFullDuplexImpl fields */
+    CRITICAL_SECTION            lock;
+};
+
+/*****************************************************************************
+ * IDirectSoundNotify implementation structure
+ */
+struct IDirectSoundNotifyImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSoundNotify);
+    DWORD                       ref;
+    IDirectSoundBufferImpl*     dsb;
+};
+
+HRESULT WINAPI IDirectSoundNotifyImpl_Create(
+    IDirectSoundBufferImpl *dsb,
+    IDirectSoundNotifyImpl **pdsn);
+
+/*****************************************************************************
+ * IDirectSoundCaptureNotify implementation structure
+ */
+struct IDirectSoundCaptureNotifyImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSoundNotify);
+    DWORD                               ref;
+    IDirectSoundCaptureBufferImpl*      dscb;
+};
+
+HRESULT WINAPI IDirectSoundCaptureNotifyImpl_Create(
+    IDirectSoundCaptureBufferImpl *dscb,
+    IDirectSoundCaptureNotifyImpl ** pdscn);
+
+/*****************************************************************************
+ *  IDirectSound3DListener implementation structure
+ */
+struct IDirectSound3DListenerImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSound3DListener);
+    DWORD                       ref;
+    /* IDirectSound3DListenerImpl fields */
+    IDirectSoundImpl*           dsound;
+};
+
+HRESULT WINAPI IDirectSound3DListenerImpl_Create(
+    PrimaryBufferImpl *pb,
+    IDirectSound3DListenerImpl **pdsl);
+
+/*****************************************************************************
+ *  IKsBufferPropertySet implementation structure
+ */
+struct IKsBufferPropertySetImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IKsPropertySet);
+    DWORD			ref;
+    /* IKsPropertySetImpl fields */
+    IDirectSoundBufferImpl*	dsb;
+};
+
+HRESULT WINAPI IKsBufferPropertySetImpl_Create(
+    IDirectSoundBufferImpl *dsb,
+    IKsBufferPropertySetImpl **piks);
+
+/*****************************************************************************
+ *  IKsPrivatePropertySet implementation structure
+ */
+struct IKsPrivatePropertySetImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IKsPropertySet);
+    DWORD			ref;
+};
+
+HRESULT WINAPI IKsPrivatePropertySetImpl_Create(
+    IKsPrivatePropertySetImpl **piks);
+
+/*****************************************************************************
+ * IDirectSound3DBuffer implementation structure
+ */
+struct IDirectSound3DBufferImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IDirectSound3DBuffer);
+    DWORD                       ref;
+    /* IDirectSound3DBufferImpl fields */
+    IDirectSoundBufferImpl*     dsb;
+};
+
+HRESULT WINAPI IDirectSound3DBufferImpl_Create(
+    IDirectSoundBufferImpl *dsb,
+    IDirectSound3DBufferImpl **pds3db);
+
+/*******************************************************************************
+ * DirectSound ClassFactory implementation structure
+ */
+struct IClassFactoryImpl
+{
+    /* IUnknown fields */
+    ICOM_VFIELD(IClassFactory);
+    DWORD                       ref;
+};
+
+extern IClassFactoryImpl DSOUND_CAPTURE_CF;
+extern IClassFactoryImpl DSOUND_FULLDUPLEX_CF;
+
+void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan);
+void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb);
+
+/* primary.c */
+
+HRESULT DSOUND_PrimaryCreate(IDirectSoundImpl *This);
+HRESULT DSOUND_PrimaryDestroy(IDirectSoundImpl *This);
+HRESULT DSOUND_PrimaryPlay(IDirectSoundImpl *This);
+HRESULT DSOUND_PrimaryStop(IDirectSoundImpl *This);
+HRESULT DSOUND_PrimaryGetPosition(IDirectSoundImpl *This, LPDWORD playpos, LPDWORD writepos);
+
+/* buffer.c */
+
+DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This,
+			      DWORD state, DWORD pplay, DWORD pwrite, DWORD pmix, DWORD bmix);
+
+/* mixer.c */
+
+void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len);
+void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb);
+void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos);
+void DSOUND_WaveQueue(IDirectSoundImpl *dsound, DWORD mixq);
+void DSOUND_PerformMix(IDirectSoundImpl *dsound);
+void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
+void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
+
+/* sound3d.c */
+
+void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb);
+
+#define STATE_STOPPED   0
+#define STATE_STARTING  1
+#define STATE_PLAYING   2
+#define STATE_CAPTURING 2
+#define STATE_STOPPING  3
+
+#define DSOUND_FREQSHIFT (14)
+
+extern IDirectSoundImpl* dsound;
+
+extern HRESULT mmErr(UINT err);
+extern void setup_dsound_options(void);
diff -u --unidirectional-new-file dlls/dsound/dsound.spec /home/wine/wine.save6/dlls/dsound/dsound.spec
--- dlls/dsound/dsound.spec	2004-06-30 15:55:33.000000000 -0400
+++ /home/wine/wine.save6/dlls/dsound/dsound.spec	2004-03-10 18:39:28.000000000 -0500
@@ -1,4 +1,4 @@
-1 stdcall DirectSoundCreate(ptr ptr ptr)
+1 stdcall DirectSoundCreate(ptr ptr ptr) DirectSoundCreate8
 2 stdcall DirectSoundEnumerateA(ptr ptr)
 3 stdcall DirectSoundEnumerateW(ptr ptr)
 4 stdcall -private DllCanUnloadNow() DSOUND_DllCanUnloadNow
diff -u --unidirectional-new-file dlls/dsound/dsound.spec.c /home/wine/wine.save6/dlls/dsound/dsound.spec.c
--- dlls/dsound/dsound.spec.c	1969-12-31 19:00:00.000000000 -0500
+++ /home/wine/wine.save6/dlls/dsound/dsound.spec.c	2004-03-16 21:19:28.000000000 -0500
@@ -0,0 +1,653 @@
+/* File generated automatically from ./dsound.spec; do not edit! */
+/* This file can be copied, modified and distributed without restriction. */
+
+extern char __wine_spec_pe_header[];
+#ifndef __GNUC__
+static void __asm__dummy_header(void) {
+#endif
+asm(".text\n\t"
+    ".align 4096\n"
+    "__wine_spec_pe_header:\t.skip 65536\n\t"
+    ".data\n\t"
+    ".align 4\n"
+    "__wine_spec_data_start:\t.long 1");
+#ifndef __GNUC__
+}
+#endif
+extern char _end[];
+extern int __wine_spec_data_start[], __wine_spec_exports[];
+
+#define __stdcall __attribute__((__stdcall__))
+
+#ifndef __GNUC__
+static void __asm__dummy(void) {
+#endif /* !defined(__GNUC__) */
+asm(".data\n"
+    "\t.align 4\n"
+    "__wine_spec_exports:\n"
+    "\t.long 0\n"
+    "\t.long 0\n"
+    "\t.long 0\n"
+    "\t.long __wine_spec_exp_names\n"
+    "\t.long 1\n"
+    "\t.long 14\n"
+    "\t.long 14\n"
+    "\t.long __wine_spec_exports_funcs\n"
+    "\t.long __wine_spec_exp_name_ptrs\n"
+    "\t.long __wine_spec_exp_ordinals\n"
+    "__wine_spec_exports_funcs:\n"
+    "\t.long DirectSoundCreate8\n"
+    "\t.long DirectSoundEnumerateA\n"
+    "\t.long DirectSoundEnumerateW\n"
+    "\t.long DSOUND_DllCanUnloadNow\n"
+    "\t.long DSOUND_DllGetClassObject\n"
+    "\t.long DirectSoundCaptureCreate8\n"
+    "\t.long DirectSoundCaptureEnumerateA\n"
+    "\t.long DirectSoundCaptureEnumerateW\n"
+    "\t.long GetDeviceID\n"
+    "\t.long DirectSoundFullDuplexCreate\n"
+    "\t.long DirectSoundCreate8\n"
+    "\t.long DirectSoundCaptureCreate8\n"
+    "\t.long DSOUND_DllRegisterServer\n"
+    "\t.long DSOUND_DllUnregisterServer\n"
+    "__wine_spec_exp_name_ptrs:\n"
+    "\t.long __wine_spec_exp_names+11\n"
+    "\t.long __wine_spec_exp_names+36\n"
+    "\t.long __wine_spec_exp_names+62\n"
+    "\t.long __wine_spec_exp_names+91\n"
+    "\t.long __wine_spec_exp_names+120\n"
+    "\t.long __wine_spec_exp_names+138\n"
+    "\t.long __wine_spec_exp_names+157\n"
+    "\t.long __wine_spec_exp_names+179\n"
+    "\t.long __wine_spec_exp_names+201\n"
+    "\t.long __wine_spec_exp_names+229\n"
+    "\t.long __wine_spec_exp_names+245\n"
+    "\t.long __wine_spec_exp_names+263\n"
+    "\t.long __wine_spec_exp_names+281\n"
+    "\t.long __wine_spec_exp_names+301\n"
+    "\t.text\n"
+    "__wine_spec_exp_names:\n"
+    "\t.string \"dsound.dll\"\n"
+    "\t.string \"DirectSoundCaptureCreate\"\n"
+    "\t.string \"DirectSoundCaptureCreate8\"\n"
+    "\t.string \"DirectSoundCaptureEnumerateA\"\n"
+    "\t.string \"DirectSoundCaptureEnumerateW\"\n"
+    "\t.string \"DirectSoundCreate\"\n"
+    "\t.string \"DirectSoundCreate8\"\n"
+    "\t.string \"DirectSoundEnumerateA\"\n"
+    "\t.string \"DirectSoundEnumerateW\"\n"
+    "\t.string \"DirectSoundFullDuplexCreate\"\n"
+    "\t.string \"DllCanUnloadNow\"\n"
+    "\t.string \"DllGetClassObject\"\n"
+    "\t.string \"DllRegisterServer\"\n"
+    "\t.string \"DllUnregisterServer\"\n"
+    "\t.string \"GetDeviceID\"\n"
+    "\t.data\n"
+    "__wine_spec_exp_ordinals:\n"
+    "\t.short 5\n"
+    "\t.short 11\n"
+    "\t.short 6\n"
+    "\t.short 7\n"
+    "\t.short 0\n"
+    "\t.short 10\n"
+    "\t.short 1\n"
+    "\t.short 2\n"
+    "\t.short 9\n"
+    "\t.short 3\n"
+    "\t.short 4\n"
+    "\t.short 12\n"
+    "\t.short 13\n"
+    "\t.short 8\n"
+    "\tjmp DirectSoundCreate8\n"
+    "\tret $12\n"
+    "\t.long DirectSoundCreate8,0x00000000\n"
+    "\tjmp DirectSoundEnumerateA\n"
+    "\tret $8\n"
+    "\t.long DirectSoundEnumerateA,0x00000000\n"
+    "\tjmp DirectSoundEnumerateW\n"
+    "\tret $8\n"
+    "\t.long DirectSoundEnumerateW,0x00000000\n"
+    "\tjmp DSOUND_DllCanUnloadNow\n"
+    "\tret $0\n"
+    "\t.long DSOUND_DllCanUnloadNow,0x00000000\n"
+    "\tjmp DSOUND_DllGetClassObject\n"
+    "\tret $12\n"
+    "\t.long DSOUND_DllGetClassObject,0x00000000\n"
+    "\tjmp DirectSoundCaptureCreate8\n"
+    "\tret $12\n"
+    "\t.long DirectSoundCaptureCreate8,0x00000000\n"
+    "\tjmp DirectSoundCaptureEnumerateA\n"
+    "\tret $8\n"
+    "\t.long DirectSoundCaptureEnumerateA,0x00000000\n"
+    "\tjmp DirectSoundCaptureEnumerateW\n"
+    "\tret $8\n"
+    "\t.long DirectSoundCaptureEnumerateW,0x00000000\n"
+    "\tjmp GetDeviceID\n"
+    "\tret $8\n"
+    "\t.long GetDeviceID,0x00000000\n"
+    "\tjmp DirectSoundFullDuplexCreate\n"
+    "\tret $40\n"
+    "\t.long DirectSoundFullDuplexCreate,0x00000000\n"
+    "\tjmp DirectSoundCreate8\n"
+    "\tret $12\n"
+    "\t.long DirectSoundCreate8,0x00000000\n"
+    "\tjmp DirectSoundCaptureCreate8\n"
+    "\tret $12\n"
+    "\t.long DirectSoundCaptureCreate8,0x00000000\n"
+    "\tjmp DSOUND_DllRegisterServer\n"
+    "\tret $0\n"
+    "\t.long DSOUND_DllRegisterServer,0x00000000\n"
+    "\tjmp DSOUND_DllUnregisterServer\n"
+    "\tret $0\n"
+    "\t.long DSOUND_DllUnregisterServer,0x00000000\n"
+    "\t.text\n"
+    "\t.align 4\n"
+);
+
+#ifndef __GNUC__
+}
+#endif /* !defined(__GNUC__) */
+
+static struct {
+  struct {
+    void        *OriginalFirstThunk;
+    unsigned int TimeDateStamp;
+    unsigned int ForwarderChain;
+    const char  *Name;
+    void        *FirstThunk;
+  } imp[7];
+  const char *data[69];
+} imports = {
+  {
+    { 0, 0, 0, "winmm.dll", &imports.data[0] },
+    { 0, 0, 0, "ole32.dll", &imports.data[30] },
+    { 0, 0, 0, "user32.dll", &imports.data[32] },
+    { 0, 0, 0, "advapi32.dll", &imports.data[34] },
+    { 0, 0, 0, "kernel32.dll", &imports.data[46] },
+    { 0, 0, 0, "ntdll.dll", &imports.data[63] },
+    { 0, 0, 0, 0, 0 },
+  },
+  {
+    /* winmm.dll */
+    "\212\000timeBeginPeriod",
+    "\213\000timeEndPeriod",
+    "\217\000timeKillEvent",
+    "\220\000timeSetEvent",
+    "\221\000waveInAddBuffer",
+    "\222\000waveInClose",
+    "\223\000waveInGetDevCapsA",
+    "\230\000waveInGetNumDevs",
+    "\231\000waveInGetPosition",
+    "\232\000waveInMessage",
+    "\233\000waveInOpen",
+    "\234\000waveInPrepareHeader",
+    "\235\000waveInReset",
+    "\236\000waveInStart",
+    "\237\000waveInStop",
+    "\240\000waveInUnprepareHeader",
+    "\242\000waveOutClose",
+    "\243\000waveOutGetDevCapsA",
+    "\250\000waveOutGetNumDevs",
+    "\253\000waveOutGetPosition",
+    "\255\000waveOutMessage",
+    "\256\000waveOutOpen",
+    "\257\000waveOutPause",
+    "\260\000waveOutPrepareHeader",
+    "\261\000waveOutReset",
+    "\262\000waveOutRestart",
+    "\265\000waveOutSetVolume",
+    "\266\000waveOutUnprepareHeader",
+    "\267\000waveOutWrite",
+    0,
+    /* ole32.dll */
+    "\373\000StringFromGUID2",
+    0,
+    /* user32.dll */
+    "\262\002wsprintfW",
+    0,
+    /* advapi32.dll */
+    "\352\000RegCloseKey",
+    "\356\000RegCreateKeyExA",
+    "\357\000RegCreateKeyExW",
+    "\362\000RegDeleteKeyW",
+    "\367\000RegEnumKeyExW",
+    "\001\001RegOpenKeyA",
+    "\002\001RegOpenKeyExA",
+    "\003\001RegOpenKeyExW",
+    "\013\001RegQueryValueExA",
+    "\027\001RegSetValueExA",
+    "\030\001RegSetValueExW",
+    0,
+    /* kernel32.dll */
+    "\373\000DeleteCriticalSection",
+    "\013\001EnterCriticalSection",
+    "\052\001ExitProcess",
+    "\000\002GetModuleFileNameA",
+    "\127\002GetTickCount",
+    "\214\002HeapAlloc",
+    "\222\002HeapFree",
+    "\225\002HeapReAlloc",
+    "\236\002InitializeCriticalSection",
+    "\307\002LeaveCriticalSection",
+    "\365\002MulDiv",
+    "\366\002MultiByteToWideChar",
+    "\244\003SetEvent",
+    "\335\003Sleep",
+    "\141\004lstrlenA",
+    "\142\004lstrlenW",
+    0,
+    /* ntdll.dll */
+    "\024\001RtlAcquireResourceExclusive",
+    "\025\001RtlAcquireResourceShared",
+    "\150\001RtlDeleteResource",
+    "\320\001RtlInitializeResource",
+    "\027\002RtlReleaseResource",
+    0,
+  }
+};
+
+#ifndef __GNUC__
+static void __asm__dummy_import(void) {
+#endif
+
+asm(".data\n\t.align 8\n"
+    "\t.type timeBeginPeriod, at function\n"
+    "\t.globl timeBeginPeriod\n"
+    "timeBeginPeriod:\n\tjmp *(imports+140)\n\tmovl %esi,%esi\n"
+    "\t.type timeEndPeriod, at function\n"
+    "\t.globl timeEndPeriod\n"
+    "timeEndPeriod:\n\tjmp *(imports+144)\n\tmovl %esi,%esi\n"
+    "\t.type timeKillEvent, at function\n"
+    "\t.globl timeKillEvent\n"
+    "timeKillEvent:\n\tjmp *(imports+148)\n\tmovl %esi,%esi\n"
+    "\t.type timeSetEvent, at function\n"
+    "\t.globl timeSetEvent\n"
+    "timeSetEvent:\n\tjmp *(imports+152)\n\tmovl %esi,%esi\n"
+    "\t.type waveInAddBuffer, at function\n"
+    "\t.globl waveInAddBuffer\n"
+    "waveInAddBuffer:\n\tjmp *(imports+156)\n\tmovl %esi,%esi\n"
+    "\t.type waveInClose, at function\n"
+    "\t.globl waveInClose\n"
+    "waveInClose:\n\tjmp *(imports+160)\n\tmovl %esi,%esi\n"
+    "\t.type waveInGetDevCapsA, at function\n"
+    "\t.globl waveInGetDevCapsA\n"
+    "waveInGetDevCapsA:\n\tjmp *(imports+164)\n\tmovl %esi,%esi\n"
+    "\t.type waveInGetNumDevs, at function\n"
+    "\t.globl waveInGetNumDevs\n"
+    "waveInGetNumDevs:\n\tjmp *(imports+168)\n\tmovl %esi,%esi\n"
+    "\t.type waveInGetPosition, at function\n"
+    "\t.globl waveInGetPosition\n"
+    "waveInGetPosition:\n\tjmp *(imports+172)\n\tmovl %esi,%esi\n"
+    "\t.type waveInMessage, at function\n"
+    "\t.globl waveInMessage\n"
+    "waveInMessage:\n\tjmp *(imports+176)\n\tmovl %esi,%esi\n"
+    "\t.type waveInOpen, at function\n"
+    "\t.globl waveInOpen\n"
+    "waveInOpen:\n\tjmp *(imports+180)\n\tmovl %esi,%esi\n"
+    "\t.type waveInPrepareHeader, at function\n"
+    "\t.globl waveInPrepareHeader\n"
+    "waveInPrepareHeader:\n\tjmp *(imports+184)\n\tmovl %esi,%esi\n"
+    "\t.type waveInReset, at function\n"
+    "\t.globl waveInReset\n"
+    "waveInReset:\n\tjmp *(imports+188)\n\tmovl %esi,%esi\n"
+    "\t.type waveInStart, at function\n"
+    "\t.globl waveInStart\n"
+    "waveInStart:\n\tjmp *(imports+192)\n\tmovl %esi,%esi\n"
+    "\t.type waveInStop, at function\n"
+    "\t.globl waveInStop\n"
+    "waveInStop:\n\tjmp *(imports+196)\n\tmovl %esi,%esi\n"
+    "\t.type waveInUnprepareHeader, at function\n"
+    "\t.globl waveInUnprepareHeader\n"
+    "waveInUnprepareHeader:\n\tjmp *(imports+200)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutClose, at function\n"
+    "\t.globl waveOutClose\n"
+    "waveOutClose:\n\tjmp *(imports+204)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutGetDevCapsA, at function\n"
+    "\t.globl waveOutGetDevCapsA\n"
+    "waveOutGetDevCapsA:\n\tjmp *(imports+208)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutGetNumDevs, at function\n"
+    "\t.globl waveOutGetNumDevs\n"
+    "waveOutGetNumDevs:\n\tjmp *(imports+212)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutGetPosition, at function\n"
+    "\t.globl waveOutGetPosition\n"
+    "waveOutGetPosition:\n\tjmp *(imports+216)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutMessage, at function\n"
+    "\t.globl waveOutMessage\n"
+    "waveOutMessage:\n\tjmp *(imports+220)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutOpen, at function\n"
+    "\t.globl waveOutOpen\n"
+    "waveOutOpen:\n\tjmp *(imports+224)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutPause, at function\n"
+    "\t.globl waveOutPause\n"
+    "waveOutPause:\n\tjmp *(imports+228)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutPrepareHeader, at function\n"
+    "\t.globl waveOutPrepareHeader\n"
+    "waveOutPrepareHeader:\n\tjmp *(imports+232)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutReset, at function\n"
+    "\t.globl waveOutReset\n"
+    "waveOutReset:\n\tjmp *(imports+236)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutRestart, at function\n"
+    "\t.globl waveOutRestart\n"
+    "waveOutRestart:\n\tjmp *(imports+240)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutSetVolume, at function\n"
+    "\t.globl waveOutSetVolume\n"
+    "waveOutSetVolume:\n\tjmp *(imports+244)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutUnprepareHeader, at function\n"
+    "\t.globl waveOutUnprepareHeader\n"
+    "waveOutUnprepareHeader:\n\tjmp *(imports+248)\n\tmovl %esi,%esi\n"
+    "\t.type waveOutWrite, at function\n"
+    "\t.globl waveOutWrite\n"
+    "waveOutWrite:\n\tjmp *(imports+252)\n\tmovl %esi,%esi\n"
+    "\t.type StringFromGUID2, at function\n"
+    "\t.globl StringFromGUID2\n"
+    "StringFromGUID2:\n\tjmp *(imports+260)\n\tmovl %esi,%esi\n"
+    "\t.type wsprintfW, at function\n"
+    "\t.globl wsprintfW\n"
+    "wsprintfW:\n\tjmp *(imports+268)\n\tmovl %esi,%esi\n"
+    "\t.type RegCloseKey, at function\n"
+    "\t.globl RegCloseKey\n"
+    "RegCloseKey:\n\tjmp *(imports+276)\n\tmovl %esi,%esi\n"
+    "\t.type RegCreateKeyExA, at function\n"
+    "\t.globl RegCreateKeyExA\n"
+    "RegCreateKeyExA:\n\tjmp *(imports+280)\n\tmovl %esi,%esi\n"
+    "\t.type RegCreateKeyExW, at function\n"
+    "\t.globl RegCreateKeyExW\n"
+    "RegCreateKeyExW:\n\tjmp *(imports+284)\n\tmovl %esi,%esi\n"
+    "\t.type RegDeleteKeyW, at function\n"
+    "\t.globl RegDeleteKeyW\n"
+    "RegDeleteKeyW:\n\tjmp *(imports+288)\n\tmovl %esi,%esi\n"
+    "\t.type RegEnumKeyExW, at function\n"
+    "\t.globl RegEnumKeyExW\n"
+    "RegEnumKeyExW:\n\tjmp *(imports+292)\n\tmovl %esi,%esi\n"
+    "\t.type RegOpenKeyA, at function\n"
+    "\t.globl RegOpenKeyA\n"
+    "RegOpenKeyA:\n\tjmp *(imports+296)\n\tmovl %esi,%esi\n"
+    "\t.type RegOpenKeyExA, at function\n"
+    "\t.globl RegOpenKeyExA\n"
+    "RegOpenKeyExA:\n\tjmp *(imports+300)\n\tmovl %esi,%esi\n"
+    "\t.type RegOpenKeyExW, at function\n"
+    "\t.globl RegOpenKeyExW\n"
+    "RegOpenKeyExW:\n\tjmp *(imports+304)\n\tmovl %esi,%esi\n"
+    "\t.type RegQueryValueExA, at function\n"
+    "\t.globl RegQueryValueExA\n"
+    "RegQueryValueExA:\n\tjmp *(imports+308)\n\tmovl %esi,%esi\n"
+    "\t.type RegSetValueExA, at function\n"
+    "\t.globl RegSetValueExA\n"
+    "RegSetValueExA:\n\tjmp *(imports+312)\n\tmovl %esi,%esi\n"
+    "\t.type RegSetValueExW, at function\n"
+    "\t.globl RegSetValueExW\n"
+    "RegSetValueExW:\n\tjmp *(imports+316)\n\tmovl %esi,%esi\n"
+    "\t.type DeleteCriticalSection, at function\n"
+    "\t.globl DeleteCriticalSection\n"
+    "DeleteCriticalSection:\n\tjmp *(imports+324)\n\tmovl %esi,%esi\n"
+    "\t.type EnterCriticalSection, at function\n"
+    "\t.globl EnterCriticalSection\n"
+    "EnterCriticalSection:\n\tjmp *(imports+328)\n\tmovl %esi,%esi\n"
+    "\t.type ExitProcess, at function\n"
+    "\t.globl ExitProcess\n"
+    "ExitProcess:\n\tjmp *(imports+332)\n\tmovl %esi,%esi\n"
+    "\t.type GetModuleFileNameA, at function\n"
+    "\t.globl GetModuleFileNameA\n"
+    "GetModuleFileNameA:\n\tjmp *(imports+336)\n\tmovl %esi,%esi\n"
+    "\t.type GetTickCount, at function\n"
+    "\t.globl GetTickCount\n"
+    "GetTickCount:\n\tjmp *(imports+340)\n\tmovl %esi,%esi\n"
+    "\t.type HeapAlloc, at function\n"
+    "\t.globl HeapAlloc\n"
+    "HeapAlloc:\n\tjmp *(imports+344)\n\tmovl %esi,%esi\n"
+    "\t.type HeapFree, at function\n"
+    "\t.globl HeapFree\n"
+    "HeapFree:\n\tjmp *(imports+348)\n\tmovl %esi,%esi\n"
+    "\t.type HeapReAlloc, at function\n"
+    "\t.globl HeapReAlloc\n"
+    "HeapReAlloc:\n\tjmp *(imports+352)\n\tmovl %esi,%esi\n"
+    "\t.type InitializeCriticalSection, at function\n"
+    "\t.globl InitializeCriticalSection\n"
+    "InitializeCriticalSection:\n\tjmp *(imports+356)\n\tmovl %esi,%esi\n"
+    "\t.type LeaveCriticalSection, at function\n"
+    "\t.globl LeaveCriticalSection\n"
+    "LeaveCriticalSection:\n\tjmp *(imports+360)\n\tmovl %esi,%esi\n"
+    "\t.type MulDiv, at function\n"
+    "\t.globl MulDiv\n"
+    "MulDiv:\n\tjmp *(imports+364)\n\tmovl %esi,%esi\n"
+    "\t.type MultiByteToWideChar, at function\n"
+    "\t.globl MultiByteToWideChar\n"
+    "MultiByteToWideChar:\n\tjmp *(imports+368)\n\tmovl %esi,%esi\n"
+    "\t.type SetEvent, at function\n"
+    "\t.globl SetEvent\n"
+    "SetEvent:\n\tjmp *(imports+372)\n\tmovl %esi,%esi\n"
+    "\t.type Sleep, at function\n"
+    "\t.globl Sleep\n"
+    "Sleep:\n\tjmp *(imports+376)\n\tmovl %esi,%esi\n"
+    "\t.type lstrlenA, at function\n"
+    "\t.globl lstrlenA\n"
+    "lstrlenA:\n\tjmp *(imports+380)\n\tmovl %esi,%esi\n"
+    "\t.type lstrlenW, at function\n"
+    "\t.globl lstrlenW\n"
+    "lstrlenW:\n\tjmp *(imports+384)\n\tmovl %esi,%esi\n"
+    "\t.type RtlAcquireResourceExclusive, at function\n"
+    "\t.globl RtlAcquireResourceExclusive\n"
+    "RtlAcquireResourceExclusive:\n\tjmp *(imports+392)\n\tmovl %esi,%esi\n"
+    "\t.type RtlAcquireResourceShared, at function\n"
+    "\t.globl RtlAcquireResourceShared\n"
+    "RtlAcquireResourceShared:\n\tjmp *(imports+396)\n\tmovl %esi,%esi\n"
+    "\t.type RtlDeleteResource, at function\n"
+    "\t.globl RtlDeleteResource\n"
+    "RtlDeleteResource:\n\tjmp *(imports+400)\n\tmovl %esi,%esi\n"
+    "\t.type RtlInitializeResource, at function\n"
+    "\t.globl RtlInitializeResource\n"
+    "RtlInitializeResource:\n\tjmp *(imports+404)\n\tmovl %esi,%esi\n"
+    "\t.type RtlReleaseResource, at function\n"
+    "\t.globl RtlReleaseResource\n"
+    "RtlReleaseResource:\n\tjmp *(imports+408)\n\tmovl %esi,%esi\n"
+".text");
+#ifndef __GNUC__
+}
+#endif
+
+static const unsigned int res_0[219] = {
+  0x0034036c,0x00560000,0x005f0053,0x00450056,0x00530052,0x004f0049,0x005f004e,0x004e0049,
+  0x004f0046,0x00000000,0xfeef04bd,0x00010000,0x00040008,0x00010371,0x00040008,0x00010371,
+  0x00000000,0x00000000,0x00000000,0x00000002,0x00000000,0x00000000,0x00000000,0x000002cc,
+  0x00530000,0x00720074,0x006e0069,0x00460067,0x006c0069,0x00490065,0x0066006e,0x0000006f,
+  0x000002a8,0x00300000,0x00300034,0x00300039,0x00450034,0x00000034,0x000a0034,0x00430001,
+  0x006d006f,0x00610070,0x0079006e,0x0061004e,0x0065006d,0x00000000,0x00690057,0x0065006e,
+  0x00540020,0x00610065,0x0000006d,0x0011004a,0x00460001,0x006c0069,0x00440065,0x00730065,
+  0x00720063,0x00700069,0x00690074,0x006e006f,0x00000000,0x00690057,0x0065006e,0x00440020,
+  0x00720069,0x00630065,0x00530074,0x0075006f,0x0064006e,0x00000000,0x000a0034,0x00460001,
+  0x006c0069,0x00560065,0x00720065,0x00690073,0x006e006f,0x00000000,0x002e0034,0x002e0038,
+  0x002e0031,0x00380038,0x00000031,0x000b0036,0x00490001,0x0074006e,0x00720065,0x0061006e,
+  0x004e006c,0x006d0061,0x00000065,0x00730064,0x0075006f,0x0064006e,0x0064002e,0x006c006c,
+  0x00000000,0x005c00dc,0x004c0001,0x00670065,0x006c0061,0x006f0043,0x00790070,0x00690072,
+  0x00680067,0x00000074,0x006f0043,0x00790070,0x00690072,0x00680067,0x00200074,0x00630028,
+  0x00200029,0x00390031,0x00330039,0x0032002d,0x00300030,0x00200034,0x00680074,0x00200065,
+  0x00690057,0x0065006e,0x00700020,0x006f0072,0x0065006a,0x00740063,0x00610020,0x00740075,
+  0x006f0068,0x00730072,0x00280020,0x00650073,0x00200065,0x00680074,0x00200065,0x00690066,
+  0x0065006c,0x00410020,0x00540055,0x004f0048,0x00530052,0x00660020,0x0072006f,0x00610020,
+  0x00630020,0x006d006f,0x006c0070,0x00740065,0x00200065,0x0069006c,0x00740073,0x00000029,
+  0x000b003e,0x004f0001,0x00690072,0x00690067,0x0061006e,0x0046006c,0x006c0069,0x006e0065,
+  0x006d0061,0x00000065,0x00730064,0x0075006f,0x0064006e,0x0064002e,0x006c006c,0x00000000,
+  0x00080030,0x00500001,0x006f0072,0x00750064,0x00740063,0x0061004e,0x0065006d,0x00000000,
+  0x00690044,0x00650072,0x00740063,0x00000058,0x0004002c,0x00500001,0x006f0072,0x00750064,
+  0x00740063,0x00650056,0x00730072,0x006f0069,0x0000006e,0x002e0034,0x00000038,0x0001002a,
+  0x004f0001,0x0045004c,0x00650053,0x0066006c,0x00650052,0x00690067,0x00740073,0x00720065,
+  0x00000000,0x00000000,0x00000044,0x00560000,0x00720061,0x00690046,0x0065006c,0x006e0049,
+  0x006f0066,0x00000000,0x00040024,0x00540000,0x00610072,0x0073006e,0x0061006c,0x00690074,
+  0x006e006f,0x00000000,0x04e40409
+};
+
+struct res_dir {
+  unsigned int Characteristics;
+  unsigned int TimeDateStamp;
+  unsigned short MajorVersion, MinorVersion;
+  unsigned short NumerOfNamedEntries, NumberOfIdEntries;
+};
+
+struct res_dir_entry {
+  unsigned int Name;
+  unsigned int OffsetToData;
+};
+
+struct res_data_entry {
+  const unsigned int *OffsetToData;
+  unsigned int Size;
+  unsigned int CodePage;
+  unsigned int ResourceHandle;
+};
+
+#define OFFSETOF(field) ((char*)&((struct res_struct *)0)->field - (char*)((struct res_struct *) 0))
+static struct res_struct{
+  struct res_dir        type_dir;
+  struct res_dir_entry  type_entries[1];
+  struct res_dir        name_0_dir;
+  struct res_dir_entry  name_0_entries[1];
+  struct res_dir        lang_0_0_dir;
+  struct res_dir_entry  lang_0_0_entries[1];
+  struct res_data_entry data_entries[1];
+} resources = {
+  { 0, 0, 0, 0, 0, 1 },
+  {
+    { 0x0010, OFFSETOF(name_0_dir) | 0x80000000 },
+  },
+  { 0, 0, 0, 0, 0, 1 }, /* name_0_dir */
+  {
+    { 0x0001, OFFSETOF(lang_0_0_dir) | 0x80000000 },
+  },
+  { 0, 0, 0, 0, 0, 1 }, /* lang_0_0_dir */
+  {
+    { 0x0000, OFFSETOF(data_entries[0]) },
+  },
+  {
+    { res_0, sizeof(res_0), 0, 0 },
+  }
+};
+#undef OFFSETOF
+
+static int __wine_spec_init_state;
+extern int __wine_main_argc;
+extern char **__wine_main_argv;
+extern char **__wine_main_environ;
+extern unsigned short **__wine_main_wargv;
+extern void _init(int, char**, char**);
+extern void _fini();
+#ifdef __GNUC__
+# ifdef __APPLE__
+extern int __stdcall DllMain( void*, unsigned int, void* ) __attribute__((weak_import));
+# else
+extern int __stdcall DllMain( void*, unsigned int, void* ) __attribute__((weak));
+# endif
+#else
+extern int __stdcall DllMain( void*, unsigned int, void* );
+static void __asm__dummy_DllMain(void) { asm(".weak DllMain"); }
+#endif
+
+static int __stdcall __wine_dll_main( void *inst, unsigned int reason, void *reserved )
+{
+    int ret;
+    if (reason == 1 && __wine_spec_init_state == 1)
+        _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );
+    ret = DllMain ? DllMain( inst, reason, reserved ) : 1;
+    if (reason == 0 && __wine_spec_init_state == 1) _fini();
+    return ret;
+}
+static const struct image_nt_headers
+{
+  int Signature;
+  struct file_header {
+    short Machine;
+    short NumberOfSections;
+    int   TimeDateStamp;
+    void *PointerToSymbolTable;
+    int   NumberOfSymbols;
+    short SizeOfOptionalHeader;
+    short Characteristics;
+  } FileHeader;
+  struct opt_header {
+    short Magic;
+    char  MajorLinkerVersion, MinorLinkerVersion;
+    int   SizeOfCode;
+    int   SizeOfInitializedData;
+    int   SizeOfUninitializedData;
+    void *AddressOfEntryPoint;
+    void *BaseOfCode;
+    void *BaseOfData;
+    void *ImageBase;
+    int   SectionAlignment;
+    int   FileAlignment;
+    short MajorOperatingSystemVersion;
+    short MinorOperatingSystemVersion;
+    short MajorImageVersion;
+    short MinorImageVersion;
+    short MajorSubsystemVersion;
+    short MinorSubsystemVersion;
+    int   Win32VersionValue;
+    void *SizeOfImage;
+    int   SizeOfHeaders;
+    int   CheckSum;
+    short Subsystem;
+    short DllCharacteristics;
+    int   SizeOfStackReserve;
+    int   SizeOfStackCommit;
+    int   SizeOfHeapReserve;
+    int   SizeOfHeapCommit;
+    int   LoaderFlags;
+    int   NumberOfRvaAndSizes;
+    struct { const void *VirtualAddress; int Size; } DataDirectory[16];
+  } OptionalHeader;
+} nt_header = {
+  0x4550,
+  { 0x014c,
+    0, 0, 0, 0,
+    sizeof(nt_header.OptionalHeader),
+    0x2000 },
+  { 0x010b,
+    0, 0,
+    0, 0, 0,
+    __wine_dll_main,
+    0, __wine_spec_data_start,
+    __wine_spec_pe_header,
+    4096,
+    4096,
+    1, 0,
+    0, 0,
+    4, 0,
+    0,
+    _end,
+    4096,
+    0,
+    0x0000,
+    0,
+    1048576, 4096,
+    1048576, 4096,
+    0,
+    16,
+    {
+      { __wine_spec_exports, 180 },
+      { &imports, sizeof(imports) },
+      { &resources, sizeof(resources) },
+    }
+  }
+};
+
+void __wine_spec_init(void)
+{
+    extern void __wine_dll_register( const struct image_nt_headers *, const char * );
+    __wine_spec_init_state = 1;
+    __wine_dll_register( &nt_header, "dsound.dll" );
+}
+
+#ifndef __GNUC__
+static void __asm__dummy_dll_init(void) {
+#endif
+asm("\t.section\t\".init\" ,\"ax\"\n"
+    "\tcall __wine_spec_init_ctor\n"
+    "\t.section\t\".text\"\n");
+#ifndef __GNUC__
+}
+#endif
+void __wine_spec_init_ctor(void)
+{
+    if (__wine_spec_init_state) return;
+    __wine_spec_init();
+    __wine_spec_init_state = 2;
+}
diff -u --unidirectional-new-file dlls/dsound/dsound.spec.def /home/wine/wine.save6/dlls/dsound/dsound.spec.def
--- dlls/dsound/dsound.spec.def	2004-06-30 19:22:21.000000000 -0400
+++ /home/wine/wine.save6/dlls/dsound/dsound.spec.def	2004-03-15 20:46:45.000000000 -0500
@@ -3,7 +3,7 @@
 LIBRARY dsound.dll
 
 EXPORTS
-  DirectSoundCreate at 12 @1
+  DirectSoundCreate at 12=DirectSoundCreate8 at 12 @1
   DirectSoundEnumerateA at 8 @2
   DirectSoundEnumerateW at 8 @3
   DllCanUnloadNow at 0=DSOUND_DllCanUnloadNow at 0 @4 PRIVATE
Binary files dlls/dsound/dsound.spec.o and /home/wine/wine.save6/dlls/dsound/dsound.spec.o differ
diff -u --unidirectional-new-file dlls/dsound/Makefile /home/wine/wine.save6/dlls/dsound/Makefile
--- dlls/dsound/Makefile	2004-06-30 19:37:31.000000000 -0400
+++ /home/wine/wine.save6/dlls/dsound/Makefile	2004-03-16 21:18:01.000000000 -0500
@@ -9,7 +9,6 @@
 C_SRCS = \
 	buffer.c \
 	capture.c \
-	dsound.c \
 	dsound_main.c \
 	mixer.c \
 	primary.c \
@@ -29,7 +28,7 @@
 # ALTNAMES     : alternate names for this dll (optional)
 # EXTRALIBS    : extra libraries to link in (optional)
 # SPEC_SRCS16  : interface definition files for 16-bit dlls (optional)
-# SUBSYSTEM    : (optional) subsystem (for native dlls)
+# DLLMODE      : (optional) subsystem mode (for native dlls)
 #
 # plus all variables required by the global Make.rules.in
 #
@@ -73,7 +72,7 @@
 CC        = gcc
 CFLAGS    = -g -O2
 CPPFLAGS  = 
-LIBS      = 
+LIBS      = -lm 
 BISON     = bison
 YACC      = $(BISON) -y
 LEX       = flex
@@ -96,10 +95,13 @@
 AS        = as
 LD        = ld
 LDFLAGS   = 
+LDCOMBINE = $(LD) -r
 RM        = rm -f
 MV        = mv
 LINT      = 
 LINTFLAGS = 
+LDDLLFLAGS   = -shared -Wl,-Bsymbolic,-z,defs,-init,__wine_spec_init,-fini,__wine_spec_fini
+LDDLL        = $(CC) $(LDDLLFLAGS)
 INCLUDES     = -I$(SRCDIR) -I. -I$(TOPSRCDIR)/include -I$(TOPOBJDIR)/include $(EXTRAINCL)
 EXTRACFLAGS  = -Wall -pipe -mpreferred-stack-boundary=2 -fno-strict-aliasing -gstabs+ -Wpointer-arith
 ALLCFLAGS    = $(INCLUDES) $(DEFS) $(DLLFLAGS) $(EXTRACFLAGS) $(CPPFLAGS) $(CFLAGS)
@@ -324,8 +326,11 @@
 
 # Rules for .so files
 
-$(MODULE).so: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) Makefile.in
-	$(WINEGCC) -B$(TOOLSDIR)/tools/winebuild -shared $(SRCDIR)/$(MAINSPEC) $(ALL_OBJS) $(RC_SRCS:.rc=.res) $(SUBSYSTEM:%=-Wb,--subsystem,%) -o $@ -L$(DLLDIR) $(DELAYIMPORTS:%=-Wb,-d%) $(IMPORTS:%=-l%) $(ALL_LIBS)
+$(MAINSPEC).c: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) $(WINEBUILD)
+	$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll $(SRCDIR)/$(MAINSPEC) $(DLLMODE:%=--mode %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%)
+
+$(MODULE).so: $(MAINSPEC).o $(ALL_OBJS) Makefile.in
+	$(LDDLL) $(MAINSPEC).o $(ALL_OBJS) -o $@ -L$(DLLDIR) $(ALL_LIBS) -lc
 
 # Rules for .dll files
 
@@ -341,7 +346,7 @@
 $(WIN16_FILES:%=__checklink16__%): checklink16
 
 checklink16:: $(MAINSPEC).o $(OBJS) $(MODULE).dbg.o dummy
-	$(CC) -o checklink -Wl,-rpath,$(TOPOBJDIR)/libs $(TOPSRCDIR)/dlls/checklink.c $(MAINSPEC).o $(OBJS) $(MODULE).dbg.o -L$(DLLDIR) $(ALL_LIBS) -lm && $(RM) checklink $(MAINSPEC).c $(MAINSPEC).o
+	$(CC) -o checklink -Wl,-rpath,$(TOPOBJDIR)/libs $(TOPSRCDIR)/dlls/checklink.c $(MAINSPEC).o $(OBJS) $(MODULE).dbg.o -L$(DLLDIR) $(ALL_LIBS) && $(RM) checklink
 
 checklink:: $(WIN16_FILES:%=__checklink16__%)
 
@@ -351,11 +356,6 @@
 
 crosstest:: $(SUBDIRS:%=%/__crosstest__)
 
-# Rule to explicitly generate the .spec.c for debugging
-
-$(MAINSPEC).c: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) $(WINEBUILD)
-	$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll $(SRCDIR)/$(MAINSPEC) $(SUBSYSTEM:%=--subsystem %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%)
-
 # Rules for auto documentation
 
 man: $(C_SRCS)
@@ -443,32 +443,6 @@
  ../../include/imm.h ../../include/rpcdce.h ../../include/rpcdcep.h \
  ../../include/rpcnterr.h ../../include/cguid.h \
  ../../include/dsdriver.h ./dsound_private.h
-dsound.o: dsound.c ../../include/config.h ../../include/wine/port.h \
- ../../include/windef.h ../../include/winnt.h ../../include/basetsd.h \
- ../../include/pshpack2.h ../../include/poppack.h \
- ../../include/pshpack4.h ../../include/guiddef.h \
- ../../include/winbase.h ../../include/winerror.h \
- ../../include/winreg.h ../../include/winuser.h ../../include/wingdi.h \
- ../../include/mmsystem.h ../../include/pshpack1.h \
- ../../include/winternl.h ../../include/mmddk.h \
- ../../include/wine/windef16.h ../../include/wine/winbase16.h \
- ../../include/winnls.h ../../include/wine/library.h \
- ../../include/wine/debug.h ../../include/dsound.h \
- ../../include/objbase.h ../../include/rpc.h ../../include/windows.h \
- ../../include/winresrc.h ../../include/commctrl.h \
- ../../include/prsht.h ../../include/dde.h ../../include/dlgs.h \
- ../../include/winver.h ../../include/excpt.h ../../include/wincon.h \
- ../../include/winnetwk.h ../../include/cderr.h ../../include/ddeml.h \
- ../../include/lzexpand.h ../../include/nb30.h \
- ../../include/shellapi.h ../../include/winsock2.h \
- ../../include/winsock.h ../../include/wincrypt.h \
- ../../include/winspool.h ../../include/ole2.h ../../include/oleauto.h \
- ../../include/oaidl.h ../../include/rpcndr.h ../../include/objidl.h \
- ../../include/unknwn.h ../../include/wtypes.h ../../include/oleidl.h \
- ../../include/commdlg.h ../../include/winsvc.h ../../include/mcx.h \
- ../../include/imm.h ../../include/rpcdce.h ../../include/rpcdcep.h \
- ../../include/rpcnterr.h ../../include/cguid.h \
- ../../include/dsdriver.h ./dsound_private.h ../../include/dsconf.h
 dsound_main.o: dsound_main.c ../../include/config.h \
  ../../include/wine/port.h ../../include/windef.h \
  ../../include/winnt.h ../../include/basetsd.h \
diff -u --unidirectional-new-file dlls/dsound/Makefile.in /home/wine/wine.save6/dlls/dsound/Makefile.in
--- dlls/dsound/Makefile.in	2004-06-30 19:34:16.000000000 -0400
+++ /home/wine/wine.save6/dlls/dsound/Makefile.in	2004-03-10 18:39:27.000000000 -0500
@@ -9,7 +9,6 @@
 C_SRCS = \
 	buffer.c \
 	capture.c \
-	dsound.c \
 	dsound_main.c \
 	mixer.c \
 	primary.c \
Binary files dlls/dsound/mixer.o and /home/wine/wine.save6/dlls/dsound/mixer.o differ
Only in dlls/dsound: old
Only in dlls/dsound: old1
Binary files dlls/dsound/primary.o and /home/wine/wine.save6/dlls/dsound/primary.o differ
Binary files dlls/dsound/propset.o and /home/wine/wine.save6/dlls/dsound/propset.o differ
Binary files dlls/dsound/regsvr.o and /home/wine/wine.save6/dlls/dsound/regsvr.o differ
diff -u --unidirectional-new-file dlls/dsound/.#sound3d.c.1.28 /home/wine/wine.save6/dlls/dsound/.#sound3d.c.1.28
--- dlls/dsound/.#sound3d.c.1.28	1969-12-31 19:00:00.000000000 -0500
+++ /home/wine/wine.save6/dlls/dsound/.#sound3d.c.1.28	2004-03-16 19:25:13.000000000 -0500
@@ -0,0 +1,1141 @@
+/*  			DirectSound
+ *
+ * Copyright 1998 Marcus Meissner
+ * Copyright 1998 Rob Riggs
+ * Copyright 2000-2001 TransGaming Technologies, Inc.
+ * Copyright 2002-2003 Rok Mandeljc <rok.mandeljc at gimb.org>
+ *
+ * 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
+ */
+/*
+ * Most thread locking is complete. There may be a few race
+ * conditions still lurking.
+ *
+ * Tested with a Soundblaster clone, a Gravis UltraSound Classic,
+ * and a Turtle Beach Tropez+.
+ *
+ * TODO:
+ *	Implement SetCooperativeLevel properly (need to address focus issues)
+ *	Implement DirectSound3DBuffers (stubs in place)
+ *	Use hardware 3D support if available
+ *      Add critical section locking inside Release and AddRef methods
+ *      Handle static buffers - put those in hardware, non-static not in hardware
+ *      Hardware DuplicateSoundBuffer
+ *      Proper volume calculation, and setting volume in HEL primary buffer
+ *      Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN
+ */
+
+#include "config.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>
+#include <math.h>	/* Insomnia - pow() function */
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "mmsystem.h"
+#include "winreg.h"
+#include "winternl.h"
+#include "mmddk.h"
+#include "wine/windef16.h"
+#include "wine/debug.h"
+#include "dsound.h"
+#include "dsdriver.h"
+#include "dsound_private.h"
+
+/* default intensity level for human ears */
+#define DEFAULT_INTENSITY 0.000000000001f
+/* default velocity of sound in the air */
+#define DEFAULT_VELOCITY 340
+
+WINE_DEFAULT_DEBUG_CHANNEL(dsound3d);
+
+/*******************************************************************************
+ *              Auxiliary functions
+ */
+
+/* scalar product (i believe it's called dot product in english) */
+static inline D3DVALUE ScalarProduct (LPD3DVECTOR a, LPD3DVECTOR b)
+{
+	D3DVALUE c;
+	c = (a->x*b->x) + (a->y*b->y) + (a->z*b->z);
+	TRACE("(%f,%f,%f) * (%f,%f,%f) = %f)\n", a->x, a->y, a->z, b->x, b->y, \
+	      b->z, c);
+	return c;
+}
+
+/* vector product (i believe it's called cross product in english */
+static inline D3DVECTOR VectorProduct (LPD3DVECTOR a, LPD3DVECTOR b)
+{
+	D3DVECTOR c;
+	c.x = (a->y*b->z) - (a->z*b->y);
+	c.y = (a->z*b->x) - (a->x*b->z);
+	c.z = (a->x*b->y) - (a->y*b->x);
+	TRACE("(%f,%f,%f) x (%f,%f,%f) = (%f,%f,%f)\n", a->x, a->y, a->z, b->x, b->y, \
+	      b->z, c.x, c.y, c.z);
+	return c;
+}
+
+/* magnitude (length) of vector */
+static inline D3DVALUE VectorMagnitude (LPD3DVECTOR a)
+{
+	D3DVALUE l;
+	l = sqrt (ScalarProduct (a, a));
+	TRACE("|(%f,%f,%f)| = %f\n", a->x, a->y, a->z, l);
+	return l;
+}
+
+/* conversion between radians and degrees */
+static inline D3DVALUE RadToDeg (D3DVALUE angle)
+{
+	D3DVALUE newangle;
+	newangle = angle * (360/(2*M_PI));
+	TRACE("%f rad = %f deg\n", angle, newangle);
+	return newangle;
+}
+
+/* conversion between degrees and radians */
+static inline D3DVALUE DegToRad (D3DVALUE angle)
+{
+	D3DVALUE newangle;
+	newangle = angle * (2*M_PI/360);
+	TRACE("%f deg = %f rad\n", angle, newangle);
+	return newangle;
+}
+
+/* angle between vectors - deg version */
+static inline D3DVALUE AngleBetweenVectorsDeg (LPD3DVECTOR a, LPD3DVECTOR b)
+{
+	D3DVALUE la, lb, product, angle, cos;
+	/* definition of scalar product: a*b = |a|*|b|*cos...therefore: */
+	product = ScalarProduct (a,b);
+	la = VectorMagnitude (a);
+	lb = VectorMagnitude (b);
+	cos = product/(la*lb);
+	angle = acos(cos);
+	/* we now have angle in radians */
+	angle = RadToDeg(angle);
+	TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %f degrees\n",  a->x, a->y, a->z, b->x,
+	      b->y, b->z, angle);
+	return angle;	
+}
+
+/* angle between vectors - rad version */
+static inline D3DVALUE AngleBetweenVectorsRad (LPD3DVECTOR a, LPD3DVECTOR b)
+{
+	D3DVALUE la, lb, product, angle, cos;
+	/* definition of scalar product: a*b = |a|*|b|*cos...therefore: */
+	product = ScalarProduct (a,b);
+	la = VectorMagnitude (a);
+	lb = VectorMagnitude (b);
+	cos = product/(la*lb);
+	angle = acos(cos);
+	TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %f radians\n",  a->x, a->y, a->z, b->x,
+	      b->y, b->z, angle);
+	return angle;	
+}
+
+/* calculates vector between two points */
+static inline D3DVECTOR VectorBetweenTwoPoints (LPD3DVECTOR a, LPD3DVECTOR b)
+{
+	D3DVECTOR c;
+	c.x = b->x - a->x;
+	c.y = b->y - a->y;
+	c.z = b->z - a->z;
+	TRACE("A (%f,%f,%f), B (%f,%f,%f), AB = (%f,%f,%f)\n", a->x, a->y, a->z, b->x, b->y,
+	      b->z, c.x, c.y, c.z);
+	return c;
+}
+
+/* calculates the length of vector's projection on another vector */
+static inline D3DVALUE ProjectVector (LPD3DVECTOR a, LPD3DVECTOR p)
+{
+	D3DVALUE prod, result;
+	prod = ScalarProduct(a, p);
+	result = prod/VectorMagnitude(p);
+	TRACE("length projection of (%f,%f,%f) on (%f,%f,%f) = %f\n", a->x, a->y, a->z, p->x,
+              p->y, p->z, result);
+	return result;
+}
+
+/*******************************************************************************
+ *              3D Buffer and Listener mixing
+ */
+
+void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
+{
+	/* volume, at which the sound will be played after all calcs. */
+	D3DVALUE lVolume = 0;
+	/* intensity (used for distance related stuff) */
+	double flIntensity;
+	double flTemp;
+	/* stuff for distance related stuff calc. */
+	D3DVECTOR vDistance;
+	D3DVALUE flDistance = 0;
+	/* panning related stuff */
+	D3DVALUE flAngle;
+	D3DVECTOR vLeft;
+	/* doppler shift related stuff */
+#if 0
+	D3DVALUE flFreq, flBufferVel, flListenerVel;
+#endif
+
+	TRACE("(%p)\n",dsb);
+
+	/* initial buffer volume */
+	lVolume = dsb->ds3db_lVolume; 
+	
+	switch (dsb->ds3db_ds3db.dwMode)
+	{
+		case DS3DMODE_DISABLE:
+			TRACE("3D processing disabled\n");
+			/* this one is here only to eliminate annoying warning message */
+			DSOUND_RecalcVolPan (&dsb->volpan);
+			DSOUND_ForceRemix (dsb);
+			break;
+		case DS3DMODE_NORMAL:
+			TRACE("Normal 3D processing mode\n");
+			/* we need to calculate distance between buffer and listener*/
+			vDistance = VectorBetweenTwoPoints(&dsb->ds3db_ds3db.vPosition, &dsb->dsound->ds3dl.vPosition);
+			flDistance = VectorMagnitude (&vDistance);
+			break;
+		case DS3DMODE_HEADRELATIVE:
+			TRACE("Head-relative 3D processing mode\n");
+			/* distance between buffer and listener is same as buffer's position */
+			flDistance = VectorMagnitude (&dsb->ds3db_ds3db.vPosition);
+			break;
+	}
+	
+	if (flDistance > dsb->ds3db_ds3db.flMaxDistance)
+	{
+		/* some apps don't want you to hear too distant sounds... */
+		if (dsb->dsbd.dwFlags & DSBCAPS_MUTE3DATMAXDISTANCE)
+		{
+			dsb->volpan.lVolume = DSBVOLUME_MIN;
+			DSOUND_RecalcVolPan (&dsb->volpan);		
+			/* i guess mixing here would be a waste of power */
+			return;
+		}
+		else
+			flDistance = dsb->ds3db_ds3db.flMaxDistance;
+	}		
+
+	if (flDistance < dsb->ds3db_ds3db.flMinDistance)
+		flDistance = dsb->ds3db_ds3db.flMinDistance;
+	
+	/* the following formula is taken from my physics book. I think it's ok for the *real* world...i hope m$ does it that way */
+	lVolume += 10000; /* ms likes working with negative volume...i don't */
+	lVolume /= 1000; /* convert hundreths of dB into B */
+	/* intensity level (loudness) = log10(Intensity/DefaultIntensity)...therefore */
+	flIntensity = pow(10,lVolume)*DEFAULT_INTENSITY;	
+	flTemp = (flDistance/dsb->ds3db_ds3db.flMinDistance)*(flDistance/dsb->ds3db_ds3db.flMinDistance);
+	flIntensity /= flTemp;
+	lVolume = log10(flIntensity/DEFAULT_INTENSITY);
+	lVolume *= 1000; /* convert back to hundreths of dB */
+	lVolume -= 10000; /* we need to do it in ms way */
+	TRACE("dist. att: Distance = %f, MinDistance = %f => adjusting volume %ld to %f\n", flDistance, dsb->ds3db_ds3db.flMinDistance, dsb->ds3db_lVolume, lVolume);
+
+	/* conning */
+	/* sometimes it happens that vConeOrientation vector = (0,0,0); in this case angle is "nan" and it's useless*/
+	if (dsb->ds3db_ds3db.vConeOrientation.x == 0 && dsb->ds3db_ds3db.vConeOrientation.y == 0 && dsb->ds3db_ds3db.vConeOrientation.z == 0)
+	{
+		TRACE("conning: cones not set\n");
+	}
+	else
+	{
+		/* calculate angle */
+		flAngle = AngleBetweenVectorsDeg(&dsb->ds3db_ds3db.vConeOrientation, &vDistance);
+		/* if by any chance it happens that OutsideConeAngle = InsideConeAngle (that means that conning has no effect) */
+		if (dsb->ds3db_ds3db.dwInsideConeAngle != dsb->ds3db_ds3db.dwOutsideConeAngle)
+		{
+			/* my test show that for my way of calc., we need only half of angles */
+			DWORD dwInsideConeAngle = dsb->ds3db_ds3db.dwInsideConeAngle/2;
+			DWORD dwOutsideConeAngle = dsb->ds3db_ds3db.dwOutsideConeAngle/2;
+			/* full volume */
+			if (flAngle < dwInsideConeAngle)
+				flAngle = dwInsideConeAngle;
+			/* min (app defined) volume */
+			if (flAngle > dwOutsideConeAngle)
+				flAngle = dwOutsideConeAngle;
+			/* this probably isn't the right thing, but it's ok for the time being */
+			lVolume += ((dsb->ds3db_ds3db.lConeOutsideVolume)/((dwOutsideConeAngle) - (dwInsideConeAngle))) * flAngle;
+		}
+		TRACE("conning: Angle = %f deg; InsideConeAngle(/2) = %ld deg; OutsideConeAngle(/2) = %ld deg; ConeOutsideVolume = %ld => adjusting volume to %f\n",
+		       flAngle, dsb->ds3db_ds3db.dwInsideConeAngle/2, dsb->ds3db_ds3db.dwOutsideConeAngle/2, dsb->ds3db_ds3db.lConeOutsideVolume, lVolume);
+	}
+	dsb->volpan.lVolume = lVolume;
+	
+	/* panning */
+	if (dsb->dsound->ds3dl.vPosition.x == dsb->ds3db_ds3db.vPosition.x &&
+	    dsb->dsound->ds3dl.vPosition.y == dsb->ds3db_ds3db.vPosition.y &&
+	    dsb->dsound->ds3dl.vPosition.z == dsb->ds3db_ds3db.vPosition.z) {
+		dsb->volpan.lPan = 0;
+		flAngle = 0.0;
+	}
+	else
+	{
+		vDistance = VectorBetweenTwoPoints(&dsb->dsound->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition);
+		vLeft = VectorProduct(&dsb->dsound->ds3dl.vOrientFront, &dsb->dsound->ds3dl.vOrientTop);
+		flAngle = AngleBetweenVectorsRad(&vLeft, &vDistance);
+		/* for now, we'll use "linear formula" (which is probably incorrect); if someone has it in book, correct it */
+		dsb->volpan.lPan = 10000*2*flAngle/M_PI - 10000;
+	}
+	TRACE("panning: Angle = %f rad, lPan = %ld\n", flAngle, dsb->volpan.lPan);
+
+	/* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */
+#if 0	
+	/* doppler shift*/
+	if ((VectorMagnitude(&ds3db.vVelocity) == 0) && (VectorMagnitude(&dsb->dsound->ds3dl.vVelocity) == 0))
+	{
+		TRACE("doppler: Buffer and Listener don't have velocities\n");
+	}
+	else
+	{
+		/* calculate length of ds3db.vVelocity component which causes Doppler Effect
+		   NOTE: if buffer moves TOWARDS the listener, it's velocity component is NEGATIVE
+		         if buffer moves AWAY from listener, it's velocity component is POSITIVE */
+		flBufferVel = ProjectVector(&dsb->ds3db_ds3db.vVelocity, &vDistance);
+		/* calculate length of ds3dl.vVelocity component which causes Doppler Effect
+		   NOTE: if listener moves TOWARDS the buffer, it's velocity component is POSITIVE
+		         if listener moves AWAY from buffer, it's velocity component is NEGATIVE */
+		flListenerVel = ProjectVector(&dsb->dsound->ds3dl.vVelocity, &vDistance);
+		/* formula taken from Gianicoli D.: Physics, 4th edition: */
+		/* FIXME: replace dsb->freq with appropriate frequency ! */
+		flFreq = dsb->freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel));
+		TRACE("doppler: Buffer velocity (component) = %lf, Listener velocity (component) = %lf => Doppler shift: %ld Hz -> %lf Hz\n", flBufferVel, flListenerVel, \
+		      dsb->freq, flFreq);
+		/* FIXME: replace following line with correct frequency setting ! */
+		dsb->freq = flFreq;
+	}
+#endif	
+	
+	/* time for remix */
+	DSOUND_RecalcVolPan(&dsb->volpan);
+}
+
+static void DSOUND_Mix3DBuffer(IDirectSoundBufferImpl *dsb)
+{
+	TRACE("(%p)\n",dsb);
+
+	DSOUND_Calc3DBuffer(dsb);
+	DSOUND_ForceRemix(dsb);			
+}
+
+static void WINAPI DSOUND_ChangeListener(IDirectSound3DListenerImpl *ds3dl)
+{
+	int i;
+	TRACE("(%p)\n",ds3dl);
+	for (i = 0; i < ds3dl->dsound->nrofbuffers; i++)
+	{
+		/* some buffers don't have 3d buffer (Ultima IX seems to
+		crash without the following line) */
+		if (ds3dl->dsound->buffers[i]->ds3db == NULL)
+			continue;
+		if (ds3dl->dsound->buffers[i]->ds3db_need_recalc == TRUE)
+		{
+			DSOUND_Mix3DBuffer(ds3dl->dsound->buffers[i]);
+		}
+	}
+}
+
+/*******************************************************************************
+ *              IDirectSound3DBuffer
+ */
+
+/* IUnknown methods */
+static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface(
+	LPDIRECTSOUND3DBUFFER iface, REFIID riid, LPVOID *ppobj)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+
+	TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+	return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
+}
+
+static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	ULONG ref;
+
+	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+	ref = InterlockedIncrement(&This->ref);
+	if (!ref) {
+		FIXME("thread-safety alert! AddRef-ing with a zero refcount!\n");
+	}
+	return ref;
+}
+
+static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	ULONG ulReturn;
+
+	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+	ulReturn = InterlockedDecrement(&This->ref);
+	if (!ulReturn) {
+		This->dsb->ds3db = NULL;
+		IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
+		HeapFree(GetProcessHeap(),0,This);
+		TRACE("(%p) released\n",This);
+	}
+
+	return ulReturn;
+}
+
+/* IDirectSound3DBuffer methods */
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters(
+	LPDIRECTSOUND3DBUFFER iface,
+	LPDS3DBUFFER lpDs3dBuffer)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("(%p,%p)\n",This,lpDs3dBuffer);
+
+	if (lpDs3dBuffer == NULL) {
+		WARN("invalid parameter: lpDs3dBuffer == NULL\n");
+		return DSERR_INVALIDPARAM;
+	}
+
+	if (lpDs3dBuffer->dwSize < sizeof(*lpDs3dBuffer)) {
+		WARN("invalid parameter: lpDs3dBuffer->dwSize = %ld < %d\n",lpDs3dBuffer->dwSize, sizeof(*lpDs3dBuffer));
+		return DSERR_INVALIDPARAM;
+	}
+	
+	TRACE("returning: all parameters\n");
+	*lpDs3dBuffer = This->dsb->ds3db_ds3db;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles(
+	LPDIRECTSOUND3DBUFFER iface,
+	LPDWORD lpdwInsideConeAngle,
+	LPDWORD lpdwOutsideConeAngle)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("returning: Inside Cone Angle = %ld degrees; Outside Cone Angle = %ld degrees\n",
+		This->dsb->ds3db_ds3db.dwInsideConeAngle, This->dsb->ds3db_ds3db.dwOutsideConeAngle);
+	*lpdwInsideConeAngle = This->dsb->ds3db_ds3db.dwInsideConeAngle;
+	*lpdwOutsideConeAngle = This->dsb->ds3db_ds3db.dwOutsideConeAngle;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation(
+	LPDIRECTSOUND3DBUFFER iface,
+	LPD3DVECTOR lpvConeOrientation)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("returning: Cone Orientation vector = (%f,%f,%f)\n",
+		This->dsb->ds3db_ds3db.vConeOrientation.x, 
+		This->dsb->ds3db_ds3db.vConeOrientation.y, 
+		This->dsb->ds3db_ds3db.vConeOrientation.z);
+	*lpvConeOrientation = This->dsb->ds3db_ds3db.vConeOrientation;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume(
+	LPDIRECTSOUND3DBUFFER iface,
+	LPLONG lplConeOutsideVolume)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("returning: Cone Outside Volume = %ld\n", This->dsb->ds3db_ds3db.lConeOutsideVolume);
+	*lplConeOutsideVolume = This->dsb->ds3db_ds3db.lConeOutsideVolume;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance(
+	LPDIRECTSOUND3DBUFFER iface,
+	LPD3DVALUE lpfMaxDistance)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("returning: Max Distance = %f\n", This->dsb->ds3db_ds3db.flMaxDistance);
+	*lpfMaxDistance = This->dsb->ds3db_ds3db.flMaxDistance;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance(
+	LPDIRECTSOUND3DBUFFER iface,
+	LPD3DVALUE lpfMinDistance)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("returning: Min Distance = %f\n", This->dsb->ds3db_ds3db.flMinDistance);
+	*lpfMinDistance = This->dsb->ds3db_ds3db.flMinDistance;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode(
+	LPDIRECTSOUND3DBUFFER iface,
+	LPDWORD lpdwMode)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("returning: Mode = %ld\n", This->dsb->ds3db_ds3db.dwMode);
+	*lpdwMode = This->dsb->ds3db_ds3db.dwMode;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition(
+	LPDIRECTSOUND3DBUFFER iface,
+	LPD3DVECTOR lpvPosition)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("returning: Position vector = (%f,%f,%f)\n",
+		This->dsb->ds3db_ds3db.vPosition.x,
+		This->dsb->ds3db_ds3db.vPosition.y,
+		This->dsb->ds3db_ds3db.vPosition.z);
+	*lpvPosition = This->dsb->ds3db_ds3db.vPosition;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity(
+	LPDIRECTSOUND3DBUFFER iface,
+	LPD3DVECTOR lpvVelocity)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("returning: Velocity vector = (%f,%f,%f)\n",
+		This->dsb->ds3db_ds3db.vVelocity.x,
+		This->dsb->ds3db_ds3db.vVelocity.y,
+		This->dsb->ds3db_ds3db.vVelocity.z);
+	*lpvVelocity = This->dsb->ds3db_ds3db.vVelocity;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters(
+	LPDIRECTSOUND3DBUFFER iface,
+	LPCDS3DBUFFER lpcDs3dBuffer,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	DWORD status = DSERR_INVALIDPARAM;
+	TRACE("(%p,%p,%lx)\n",iface,lpcDs3dBuffer,dwApply);
+
+	if (lpcDs3dBuffer == NULL) {
+		WARN("invalid parameter: lpcDs3dBuffer == NULL\n");
+		return status;
+	}
+
+	if (lpcDs3dBuffer->dwSize != sizeof(DS3DBUFFER)) {
+		WARN("invalid parameter: lpcDs3dBuffer->dwSize = %ld != %d\n",
+			lpcDs3dBuffer->dwSize, sizeof(DS3DBUFFER));
+		return status;
+	}
+
+	TRACE("setting: all parameters; dwApply = %ld\n", dwApply);
+	This->dsb->ds3db_ds3db = *lpcDs3dBuffer;
+
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		DSOUND_Mix3DBuffer(This->dsb);
+	}
+	This->dsb->ds3db_need_recalc = TRUE;
+	status = DS_OK;
+
+	return status;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles(
+	LPDIRECTSOUND3DBUFFER iface,
+	DWORD dwInsideConeAngle,
+	DWORD dwOutsideConeAngle,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("setting: Inside Cone Angle = %ld; Outside Cone Angle = %ld; dwApply = %ld\n",
+		dwInsideConeAngle, dwOutsideConeAngle, dwApply);
+	This->dsb->ds3db_ds3db.dwInsideConeAngle = dwInsideConeAngle;
+	This->dsb->ds3db_ds3db.dwOutsideConeAngle = dwOutsideConeAngle;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		DSOUND_Mix3DBuffer(This->dsb);
+	}
+	This->dsb->ds3db_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation(
+	LPDIRECTSOUND3DBUFFER iface,
+	D3DVALUE x, D3DVALUE y, D3DVALUE z,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("setting: Cone Orientation vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
+	This->dsb->ds3db_ds3db.vConeOrientation.x = x;
+	This->dsb->ds3db_ds3db.vConeOrientation.y = y;
+	This->dsb->ds3db_ds3db.vConeOrientation.z = z;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsb->ds3db_need_recalc = FALSE;
+		DSOUND_Mix3DBuffer(This->dsb);
+	}
+	This->dsb->ds3db_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume(
+	LPDIRECTSOUND3DBUFFER iface,
+	LONG lConeOutsideVolume,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("setting: ConeOutsideVolume = %ld; dwApply = %ld\n", lConeOutsideVolume, dwApply);
+	This->dsb->ds3db_ds3db.lConeOutsideVolume = lConeOutsideVolume;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsb->ds3db_need_recalc = FALSE;
+		DSOUND_Mix3DBuffer(This->dsb);
+	}
+	This->dsb->ds3db_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance(
+	LPDIRECTSOUND3DBUFFER iface,
+	D3DVALUE fMaxDistance,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("setting: MaxDistance = %f; dwApply = %ld\n", fMaxDistance, dwApply);
+	This->dsb->ds3db_ds3db.flMaxDistance = fMaxDistance;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsb->ds3db_need_recalc = FALSE;
+		DSOUND_Mix3DBuffer(This->dsb);
+	}
+	This->dsb->ds3db_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance(
+	LPDIRECTSOUND3DBUFFER iface,
+	D3DVALUE fMinDistance,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("setting: MinDistance = %f; dwApply = %ld\n", fMinDistance, dwApply);
+	This->dsb->ds3db_ds3db.flMinDistance = fMinDistance;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsb->ds3db_need_recalc = FALSE;
+		DSOUND_Mix3DBuffer(This->dsb);
+	}
+	This->dsb->ds3db_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode(
+	LPDIRECTSOUND3DBUFFER iface,
+	DWORD dwMode,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("setting: Mode = %ld; dwApply = %ld\n", dwMode, dwApply);
+	This->dsb->ds3db_ds3db.dwMode = dwMode;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsb->ds3db_need_recalc = FALSE;
+		DSOUND_Mix3DBuffer(This->dsb);
+	}
+	This->dsb->ds3db_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition(
+	LPDIRECTSOUND3DBUFFER iface,
+	D3DVALUE x, D3DVALUE y, D3DVALUE z,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("setting: Position vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
+	This->dsb->ds3db_ds3db.vPosition.x = x;
+	This->dsb->ds3db_ds3db.vPosition.y = y;
+	This->dsb->ds3db_ds3db.vPosition.z = z;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsb->ds3db_need_recalc = FALSE;
+		DSOUND_Mix3DBuffer(This->dsb);
+	}
+	This->dsb->ds3db_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity(
+	LPDIRECTSOUND3DBUFFER iface,
+	D3DVALUE x, D3DVALUE y, D3DVALUE z,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DBufferImpl,iface);
+	TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
+	This->dsb->ds3db_ds3db.vVelocity.x = x;
+	This->dsb->ds3db_ds3db.vVelocity.y = y;
+	This->dsb->ds3db_ds3db.vVelocity.z = z;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsb->ds3db_need_recalc = FALSE;
+		DSOUND_Mix3DBuffer(This->dsb);
+	}
+	This->dsb->ds3db_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static ICOM_VTABLE(IDirectSound3DBuffer) ds3dbvt =
+{
+	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+	/* IUnknown methods */
+	IDirectSound3DBufferImpl_QueryInterface,
+	IDirectSound3DBufferImpl_AddRef,
+	IDirectSound3DBufferImpl_Release,
+	/* IDirectSound3DBuffer methods */
+	IDirectSound3DBufferImpl_GetAllParameters,
+	IDirectSound3DBufferImpl_GetConeAngles,
+	IDirectSound3DBufferImpl_GetConeOrientation,
+	IDirectSound3DBufferImpl_GetConeOutsideVolume,
+	IDirectSound3DBufferImpl_GetMaxDistance,
+	IDirectSound3DBufferImpl_GetMinDistance,
+	IDirectSound3DBufferImpl_GetMode,
+	IDirectSound3DBufferImpl_GetPosition,
+	IDirectSound3DBufferImpl_GetVelocity,
+	IDirectSound3DBufferImpl_SetAllParameters,
+	IDirectSound3DBufferImpl_SetConeAngles,
+	IDirectSound3DBufferImpl_SetConeOrientation,
+	IDirectSound3DBufferImpl_SetConeOutsideVolume,
+	IDirectSound3DBufferImpl_SetMaxDistance,
+	IDirectSound3DBufferImpl_SetMinDistance,
+	IDirectSound3DBufferImpl_SetMode,
+	IDirectSound3DBufferImpl_SetPosition,
+	IDirectSound3DBufferImpl_SetVelocity,
+};
+
+HRESULT WINAPI IDirectSound3DBufferImpl_Create(
+	IDirectSoundBufferImpl *dsb,
+	IDirectSound3DBufferImpl **pds3db)
+{
+	IDirectSound3DBufferImpl *ds3db;
+	TRACE("(%p,%p)\n",dsb,pds3db);
+
+	ds3db = (IDirectSound3DBufferImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*ds3db));
+
+	if (ds3db == NULL) {
+		WARN("out of memory\n");
+		*pds3db = 0;
+		return DSERR_OUTOFMEMORY;
+	}
+
+	ds3db->ref = 0;
+	ds3db->dsb = dsb;
+	ds3db->lpVtbl = &ds3dbvt;
+
+	ds3db->dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
+	ds3db->dsb->ds3db_ds3db.vPosition.x = 0.0;
+	ds3db->dsb->ds3db_ds3db.vPosition.y = 0.0;
+	ds3db->dsb->ds3db_ds3db.vPosition.z = 0.0;
+	ds3db->dsb->ds3db_ds3db.vVelocity.x = 0.0;
+	ds3db->dsb->ds3db_ds3db.vVelocity.y = 0.0;
+	ds3db->dsb->ds3db_ds3db.vVelocity.z = 0.0;
+	ds3db->dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
+	ds3db->dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
+	ds3db->dsb->ds3db_ds3db.vConeOrientation.x = 0.0;
+	ds3db->dsb->ds3db_ds3db.vConeOrientation.y = 0.0;
+	ds3db->dsb->ds3db_ds3db.vConeOrientation.z = 0.0;
+	ds3db->dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
+	ds3db->dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
+	ds3db->dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
+	ds3db->dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
+
+	ds3db->dsb->ds3db_need_recalc = TRUE;
+
+	IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
+
+	*pds3db = ds3db;
+	return S_OK;
+}
+
+/*******************************************************************************
+ *	      IDirectSound3DListener
+ */
+
+/* IUnknown methods */
+static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(
+	LPDIRECTSOUND3DLISTENER iface, REFIID riid, LPVOID *ppobj)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,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_IDirectSound3DListener ) ) {
+                IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)This);
+		*ppobj = This;
+		return S_OK;
+	}
+
+	if ( IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
+		if (!This->dsound->primary)
+			PrimaryBufferImpl_Create(This->dsound, &(This->dsound->primary), &(This->dsound->dsbd));
+		if (This->dsound->primary) {
+			*ppobj = This->dsound->primary;
+			IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppobj);
+			return S_OK;
+		}
+	}
+
+        FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
+	return E_NOINTERFACE;
+}
+
+static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	ULONG ref;
+	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+
+	ref = InterlockedIncrement(&This->ref);
+
+	if (!ref) {
+		FIXME("thread-safety alert! AddRef-ing with a zero refcount!\n");
+	}
+
+	return ref;
+}
+
+static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	ULONG ulReturn;
+
+	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+	ulReturn = InterlockedDecrement(&This->ref);
+
+	/* Free all resources */
+	if( ulReturn == 0 ) {
+		IDirectSound8_Release((LPDIRECTSOUND8)This->dsound);
+		This->dsound->listener = 0;
+		HeapFree(GetProcessHeap(),0,This);
+		TRACE("(%p) released\n",This);
+	}
+
+	return ulReturn;
+}
+
+/* IDirectSound3DListener methods */
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(
+	LPDIRECTSOUND3DLISTENER iface,
+	LPDS3DLISTENER lpDS3DL)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("(%p,%p)\n",This,lpDS3DL);
+
+	if (lpDS3DL == NULL) {
+		WARN("invalid parameter: lpDS3DL == NULL\n");
+		return DSERR_INVALIDPARAM;
+	}
+
+	if (lpDS3DL->dwSize < sizeof(*lpDS3DL)) {
+		WARN("invalid parameter: lpDS3DL->dwSize = %ld < %d\n",lpDS3DL->dwSize, sizeof(*lpDS3DL));
+		return DSERR_INVALIDPARAM;
+	}
+	
+	TRACE("returning: all parameters\n");
+	*lpDS3DL = This->dsound->ds3dl;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(
+	LPDIRECTSOUND3DLISTENER iface,
+	LPD3DVALUE lpfDistanceFactor)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("returning: Distance Factor = %f\n", This->dsound->ds3dl.flDistanceFactor);
+	*lpfDistanceFactor = This->dsound->ds3dl.flDistanceFactor;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(
+	LPDIRECTSOUND3DLISTENER iface,
+	LPD3DVALUE lpfDopplerFactor)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("returning: Doppler Factor = %f\n", This->dsound->ds3dl.flDopplerFactor);
+	*lpfDopplerFactor = This->dsound->ds3dl.flDopplerFactor;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(
+	LPDIRECTSOUND3DLISTENER iface,
+	LPD3DVECTOR lpvOrientFront,
+	LPD3DVECTOR lpvOrientTop)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->dsound->ds3dl.vOrientFront.x, \
+	This->dsound->ds3dl.vOrientFront.y, This->dsound->ds3dl.vOrientFront.z, This->dsound->ds3dl.vOrientTop.x, This->dsound->ds3dl.vOrientTop.y, \
+	This->dsound->ds3dl.vOrientTop.z);
+	*lpvOrientFront = This->dsound->ds3dl.vOrientFront;
+	*lpvOrientTop = This->dsound->ds3dl.vOrientTop;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(
+	LPDIRECTSOUND3DLISTENER iface,
+	LPD3DVECTOR lpvPosition)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("returning: Position vector = (%f,%f,%f)\n", This->dsound->ds3dl.vPosition.x, This->dsound->ds3dl.vPosition.y, This->dsound->ds3dl.vPosition.z);
+	*lpvPosition = This->dsound->ds3dl.vPosition;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(
+	LPDIRECTSOUND3DLISTENER iface,
+	LPD3DVALUE lpfRolloffFactor)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("returning: RolloffFactor = %f\n", This->dsound->ds3dl.flRolloffFactor);
+	*lpfRolloffFactor = This->dsound->ds3dl.flRolloffFactor;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(
+	LPDIRECTSOUND3DLISTENER iface,
+	LPD3DVECTOR lpvVelocity)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->dsound->ds3dl.vVelocity.x, This->dsound->ds3dl.vVelocity.y, This->dsound->ds3dl.vVelocity.z);
+	*lpvVelocity = This->dsound->ds3dl.vVelocity;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(
+	LPDIRECTSOUND3DLISTENER iface,
+	LPCDS3DLISTENER lpcDS3DL,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("setting: all parameters; dwApply = %ld\n", dwApply);
+	This->dsound->ds3dl = *lpcDS3DL;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsound->ds3dl_need_recalc = FALSE;
+		DSOUND_ChangeListener(This);
+	}
+	This->dsound->ds3dl_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(
+	LPDIRECTSOUND3DLISTENER iface,
+	D3DVALUE fDistanceFactor,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("setting: Distance Factor = %f; dwApply = %ld\n", fDistanceFactor, dwApply);
+	This->dsound->ds3dl.flDistanceFactor = fDistanceFactor;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsound->ds3dl_need_recalc = FALSE;
+		DSOUND_ChangeListener(This);
+	}
+	This->dsound->ds3dl_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(
+	LPDIRECTSOUND3DLISTENER iface,
+	D3DVALUE fDopplerFactor,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("setting: Doppler Factor = %f; dwApply = %ld\n", fDopplerFactor, dwApply);
+	This->dsound->ds3dl.flDopplerFactor = fDopplerFactor;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsound->ds3dl_need_recalc = FALSE;
+		DSOUND_ChangeListener(This);
+	}
+	This->dsound->ds3dl_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(
+	LPDIRECTSOUND3DLISTENER iface,
+	D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront,
+	D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("setting: Front vector = (%f,%f,%f); Top vector = (%f,%f,%f); dwApply = %ld\n", \
+	xFront, yFront, zFront, xTop, yTop, zTop, dwApply);
+	This->dsound->ds3dl.vOrientFront.x = xFront;
+	This->dsound->ds3dl.vOrientFront.y = yFront;
+	This->dsound->ds3dl.vOrientFront.z = zFront;
+	This->dsound->ds3dl.vOrientTop.x = xTop;
+	This->dsound->ds3dl.vOrientTop.y = yTop;
+	This->dsound->ds3dl.vOrientTop.z = zTop;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsound->ds3dl_need_recalc = FALSE;
+		DSOUND_ChangeListener(This);
+	}
+	This->dsound->ds3dl_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(
+	LPDIRECTSOUND3DLISTENER iface,
+	D3DVALUE x, D3DVALUE y, D3DVALUE z,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("setting: Position vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
+	This->dsound->ds3dl.vPosition.x = x;
+	This->dsound->ds3dl.vPosition.y = y;
+	This->dsound->ds3dl.vPosition.z = z;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsound->ds3dl_need_recalc = FALSE;
+		DSOUND_ChangeListener(This);
+	}
+	This->dsound->ds3dl_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(
+	LPDIRECTSOUND3DLISTENER iface,
+	D3DVALUE fRolloffFactor,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("setting: Rolloff Factor = %f; dwApply = %ld\n", fRolloffFactor, dwApply);
+	This->dsound->ds3dl.flRolloffFactor = fRolloffFactor;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsound->ds3dl_need_recalc = FALSE;
+		DSOUND_ChangeListener(This);
+	}
+	This->dsound->ds3dl_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(
+	LPDIRECTSOUND3DLISTENER iface,
+	D3DVALUE x, D3DVALUE y, D3DVALUE z,
+	DWORD dwApply)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
+	This->dsound->ds3dl.vVelocity.x = x;
+	This->dsound->ds3dl.vVelocity.y = y;
+	This->dsound->ds3dl.vVelocity.z = z;
+	if (dwApply == DS3D_IMMEDIATE)
+	{
+		This->dsound->ds3dl_need_recalc = FALSE;
+		DSOUND_ChangeListener(This);
+	}
+	This->dsound->ds3dl_need_recalc = TRUE;
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings(
+	LPDIRECTSOUND3DLISTENER iface)
+{
+	ICOM_THIS(IDirectSound3DListenerImpl,iface);
+	TRACE("\n");
+	DSOUND_ChangeListener(This);
+	return DS_OK;
+}
+
+static ICOM_VTABLE(IDirectSound3DListener) ds3dlvt =
+{
+	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+	/* IUnknown methods */
+	IDirectSound3DListenerImpl_QueryInterface,
+	IDirectSound3DListenerImpl_AddRef,
+	IDirectSound3DListenerImpl_Release,
+	/* IDirectSound3DListener methods */
+	IDirectSound3DListenerImpl_GetAllParameter,
+	IDirectSound3DListenerImpl_GetDistanceFactor,
+	IDirectSound3DListenerImpl_GetDopplerFactor,
+	IDirectSound3DListenerImpl_GetOrientation,
+	IDirectSound3DListenerImpl_GetPosition,
+	IDirectSound3DListenerImpl_GetRolloffFactor,
+	IDirectSound3DListenerImpl_GetVelocity,
+	IDirectSound3DListenerImpl_SetAllParameters,
+	IDirectSound3DListenerImpl_SetDistanceFactor,
+	IDirectSound3DListenerImpl_SetDopplerFactor,
+	IDirectSound3DListenerImpl_SetOrientation,
+	IDirectSound3DListenerImpl_SetPosition,
+	IDirectSound3DListenerImpl_SetRolloffFactor,
+	IDirectSound3DListenerImpl_SetVelocity,
+	IDirectSound3DListenerImpl_CommitDeferredSettings,
+};
+
+HRESULT WINAPI IDirectSound3DListenerImpl_Create(
+	PrimaryBufferImpl *This,
+	IDirectSound3DListenerImpl **pdsl)
+{
+	IDirectSound3DListenerImpl *dsl;
+	TRACE("(%p,%p)\n",This,pdsl);
+
+	dsl = (IDirectSound3DListenerImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsl));
+
+	if (dsl == NULL) {
+		WARN("out of memory\n");
+		*pdsl = 0;
+		return DSERR_OUTOFMEMORY;
+	}
+
+	dsl->ref = 0;
+	dsl->lpVtbl = &ds3dlvt;
+
+	dsl->dsound = This->dsound;
+
+	dsl->dsound->ds3dl.dwSize = sizeof(DS3DLISTENER);
+	dsl->dsound->ds3dl.vPosition.x = 0.0;
+	dsl->dsound->ds3dl.vPosition.y = 0.0;
+	dsl->dsound->ds3dl.vPosition.z = 0.0;
+	dsl->dsound->ds3dl.vVelocity.x = 0.0;
+	dsl->dsound->ds3dl.vVelocity.y = 0.0;
+	dsl->dsound->ds3dl.vVelocity.z = 0.0;
+	dsl->dsound->ds3dl.vOrientFront.x = 0.0;
+	dsl->dsound->ds3dl.vOrientFront.y = 0.0;
+	dsl->dsound->ds3dl.vOrientFront.z = 1.0;
+	dsl->dsound->ds3dl.vOrientTop.x = 0.0;
+	dsl->dsound->ds3dl.vOrientTop.y = 1.0;
+	dsl->dsound->ds3dl.vOrientTop.z = 0.0;
+	dsl->dsound->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
+	dsl->dsound->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
+	dsl->dsound->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
+
+	dsl->dsound->ds3dl_need_recalc = TRUE;
+
+	IDirectSound8_AddRef((LPDIRECTSOUND8)This->dsound);
+
+	*pdsl = dsl;
+	return S_OK;
+}
Binary files dlls/dsound/sound3d.o and /home/wine/wine.save6/dlls/dsound/sound3d.o differ
Common subdirectories: dlls/dsound/tests and /home/wine/wine.save6/dlls/dsound/tests
Only in dlls/dsound: trace
diff -u --unidirectional-new-file dlls/dsound/version.rc /home/wine/wine.save6/dlls/dsound/version.rc
--- dlls/dsound/version.rc	2004-05-29 18:35:41.000000000 -0400
+++ /home/wine/wine.save6/dlls/dsound/version.rc	2004-03-10 18:39:28.000000000 -0500
@@ -19,10 +19,10 @@
 #define WINE_OLESELFREGISTER
 #define WINE_FILEDESCRIPTION_STR "Wine DirectSound"
 #define WINE_FILENAME_STR "dsound.dll"
-#define WINE_FILEVERSION 5,3,0,900
-#define WINE_FILEVERSION_STR "5.3.0.900"
-#define WINE_PRODUCTVERSION 5,3,0,900
-#define WINE_PRODUCTVERSION_STR "5.3"
+#define WINE_FILEVERSION 4,8,1,881
+#define WINE_FILEVERSION_STR "4.8.1.881"
+#define WINE_PRODUCTVERSION 4,8,1,881
+#define WINE_PRODUCTVERSION_STR "4.8"
 #define WINE_PRODUCTNAME_STR "DirectX"
 
 #include "wine/wine_common_ver.rc"
Binary files dlls/dsound/version.res and /home/wine/wine.save6/dlls/dsound/version.res differ


More information about the wine-patches mailing list