Wine-20041201 vendor drop
Added: vendor/wine/dlls/dsound/
Added: vendor/wine/dlls/dsound/current/
Added: vendor/wine/dlls/dsound/current/Makefile.in
Added: vendor/wine/dlls/dsound/current/buffer.c
Added: vendor/wine/dlls/dsound/current/capture.c
Added: vendor/wine/dlls/dsound/current/dsound.c
Added: vendor/wine/dlls/dsound/current/dsound.spec
Added: vendor/wine/dlls/dsound/current/dsound_main.c
Added: vendor/wine/dlls/dsound/current/dsound_private.h
Added: vendor/wine/dlls/dsound/current/mixer.c
Added: vendor/wine/dlls/dsound/current/primary.c
Added: vendor/wine/dlls/dsound/current/propset.c
Added: vendor/wine/dlls/dsound/current/regsvr.c
Added: vendor/wine/dlls/dsound/current/sound3d.c
Added: vendor/wine/dlls/dsound/current/version.rc

Added: vendor/wine/dlls/dsound/current/Makefile.in
--- vendor/wine/dlls/dsound/current/Makefile.in	2004-12-31 14:53:28 UTC (rev 12510)
+++ vendor/wine/dlls/dsound/current/Makefile.in	2004-12-31 14:53:50 UTC (rev 12511)
@@ -0,0 +1,26 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = dsound.dll
+IMPORTS   = winmm ole32 user32 advapi32 kernel32 ntdll
+EXTRALIBS = -ldxguid -luuid
+
+C_SRCS = \
+	buffer.c \
+	capture.c \
+	dsound.c \
+	dsound_main.c \
+	mixer.c \
+	primary.c \
+	propset.c \
+	regsvr.c \
+	sound3d.c
+
+RC_SRCS = version.rc
+
+SUBDIRS = tests
+
+@MAKE_DLL_RULES@
+
+### Dependencies:

Added: vendor/wine/dlls/dsound/current/buffer.c
--- vendor/wine/dlls/dsound/current/buffer.c	2004-12-31 14:53:28 UTC (rev 12510)
+++ vendor/wine/dlls/dsound/current/buffer.c	2004-12-31 14:53:50 UTC (rev 12511)
@@ -0,0 +1,1567 @@
+/*  			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
+ */
+
+#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>
+
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+#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"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dsound);
+
+/*******************************************************************************
+ *		IDirectSoundNotify
+ */
+static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(
+	LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID *ppobj
+) {
+	IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
+	TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+
+	if (This->dsb == NULL) {
+		WARN("invalid parameter\n");
+		return E_INVALIDARG;
+	}
+
+	return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER)This->dsb, riid, ppobj);
+}
+
+static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
+{
+	IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
+	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+	return InterlockedIncrement(&(This->ref));
+}
+
+static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) {
+	IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
+	ULONG ref;
+
+	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+
+	ref = InterlockedDecrement(&(This->ref));
+	if (ref == 0) {
+		IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb);
+		This->dsb->notify = NULL;
+		HeapFree(GetProcessHeap(),0,This);
+		TRACE("(%p) released\n",This);
+	}
+	return ref;
+}
+
+static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(
+	LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify
+) {
+	IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
+	TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
+
+        if (howmuch > 0 && notify == NULL) {
+	    WARN("invalid parameter: notify == NULL\n");
+	    return DSERR_INVALIDPARAM;
+	}
+
+	if (TRACE_ON(dsound)) {
+	    unsigned int	i;
+	    for (i=0;i<howmuch;i++)
+		TRACE("notify at %ld to 0x%08lx\n",
+		    notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
+	}
+
+	if (This->dsb->hwnotify) {
+	    HRESULT hres;
+	    hres = IDsDriverNotify_SetNotificationPositions(This->dsb->hwnotify, howmuch, notify);
+	    if (hres != DS_OK)
+		    WARN("IDsDriverNotify_SetNotificationPositions failed\n");
+	    return hres;
+        } else if (howmuch > 0) {
+	    /* Make an internal copy of the caller-supplied array.
+	     * Replace the existing copy if one is already present. */
+	    if (This->dsb->notifies)
+		    This->dsb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+			This->dsb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
+	    else
+		    This->dsb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+			howmuch * sizeof(DSBPOSITIONNOTIFY));
+
+	    if (This->dsb->notifies == NULL) {
+		    WARN("out of memory\n");
+		    return DSERR_OUTOFMEMORY;
+	    }
+	    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;
+}
+
+IDirectSoundNotifyVtbl dsnvt =
+{
+    IDirectSoundNotifyImpl_QueryInterface,
+    IDirectSoundNotifyImpl_AddRef,
+    IDirectSoundNotifyImpl_Release,
+    IDirectSoundNotifyImpl_SetNotificationPositions,
+};
+
+HRESULT WINAPI IDirectSoundNotifyImpl_Create(
+    IDirectSoundBufferImpl * dsb,
+    IDirectSoundNotifyImpl **pdsn)
+{
+    IDirectSoundNotifyImpl * dsn;
+    TRACE("(%p,%p)\n",dsb,pdsn);
+
+    dsn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dsn));
+
+    if (dsn == NULL) {
+        WARN("out of memory\n");
+        return DSERR_OUTOFMEMORY;
+    }
+
+    dsn->ref = 0;
+    dsn->lpVtbl = &dsnvt;
+    dsn->dsb = dsb;
+    dsb->notify = dsn;
+    IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
+
+    *pdsn = dsn;
+    return DS_OK;
+}
+
+HRESULT WINAPI IDirectSoundNotifyImpl_Destroy(
+    IDirectSoundNotifyImpl *pdsn)
+{
+    TRACE("(%p)\n",pdsn);
+
+    while (IDirectSoundNotifyImpl_Release((LPDIRECTSOUNDNOTIFY)pdsn) > 0);
+
+    return DS_OK;
+}
+
+/*******************************************************************************
+ *		IDirectSoundBuffer
+ */
+
+static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat(
+	LPDIRECTSOUNDBUFFER8 iface,LPCWAVEFORMATEX wfex
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+
+	TRACE("(%p,%p)\n",This,wfex);
+	/* This method is not available on secondary buffers */
+	WARN("invalid call\n");
+	return DSERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(
+	LPDIRECTSOUNDBUFFER8 iface,LONG vol
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	LONG oldVol;
+	HRESULT hres = DS_OK;
+
+	TRACE("(%p,%ld)\n",This,vol);
+
+	if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
+		WARN("control unavailable: This->dsbd.dwFlags = 0x%08lx\n", This->dsbd.dwFlags);
+		return DSERR_CONTROLUNAVAIL;
+	}
+
+	if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) {
+		WARN("invalid parameter: vol = %ld\n", vol);
+		return DSERR_INVALIDPARAM;
+	}
+
+	/* **** */
+	EnterCriticalSection(&(This->lock));
+
+	if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) {
+		oldVol = This->ds3db_lVolume;
+		This->ds3db_lVolume = vol;
+	} else {
+		oldVol = This->volpan.lVolume;
+		This->volpan.lVolume = vol;
+		if (vol != oldVol)
+			DSOUND_RecalcVolPan(&(This->volpan));
+	}
+
+	if (vol != oldVol) {
+		if (This->hwbuf) {
+			hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
+	    		if (hres != DS_OK)
+		    		WARN("IDsDriverBuffer_SetVolumePan failed\n");
+		} else
+			DSOUND_ForceRemix(This);
+	}
+
+	LeaveCriticalSection(&(This->lock));
+	/* **** */
+
+	return hres;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume(
+	LPDIRECTSOUNDBUFFER8 iface,LPLONG vol
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	TRACE("(%p,%p)\n",This,vol);
+
+	if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
+		WARN("control unavailable\n");
+		return DSERR_CONTROLUNAVAIL;
+	}
+
+	if (vol == NULL) {
+		WARN("invalid parameter: vol == NULL\n");
+		return DSERR_INVALIDPARAM;
+	}
+
+	*vol = This->volpan.lVolume;
+
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD freq
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	DWORD oldFreq;
+
+	TRACE("(%p,%ld)\n",This,freq);
+
+	if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
+		WARN("control unavailable\n");
+		return DSERR_CONTROLUNAVAIL;
+	}
+
+	if (freq == DSBFREQUENCY_ORIGINAL)
+		freq = This->pwfx->nSamplesPerSec;
+
+	if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX)) {
+		WARN("invalid parameter: freq = %ld\n", freq);
+		return DSERR_INVALIDPARAM;
+	}
+
+	/* **** */
+	EnterCriticalSection(&(This->lock));
+
+	oldFreq = This->freq;
+	This->freq = freq;
+	if (freq != oldFreq) {
+		This->freqAdjust = (freq << DSOUND_FREQSHIFT) / This->dsound->pwfx->nSamplesPerSec;
+		This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign;
+		DSOUND_RecalcFormat(This);
+		if (!This->hwbuf)
+			DSOUND_ForceRemix(This);
+	}
+
+	LeaveCriticalSection(&(This->lock));
+	/* **** */
+
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_Play(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags
+) {
+	HRESULT hres = DS_OK;
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	TRACE("(%p,%08lx,%08lx,%08lx)\n",This,reserved1,reserved2,flags);
+
+	/* **** */
+	EnterCriticalSection(&(This->lock));
+
+	This->playflags = flags;
+	if (This->state == STATE_STOPPED) {
+		This->leadin = TRUE;
+		This->startpos = This->buf_mixpos;
+		This->state = STATE_STARTING;
+	} else if (This->state == STATE_STOPPING)
+		This->state = STATE_PLAYING;
+	if (This->hwbuf) {
+		hres = IDsDriverBuffer_Play(This->hwbuf, 0, 0, This->playflags);
+		if (hres != DS_OK)
+			WARN("IDsDriverBuffer_Play failed\n");
+		else
+			This->state = STATE_PLAYING;
+	}
+
+	LeaveCriticalSection(&(This->lock));
+	/* **** */
+
+	return hres;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface)
+{
+	HRESULT hres = DS_OK;
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	TRACE("(%p)\n",This);
+
+	/* **** */
+	EnterCriticalSection(&(This->lock));
+
+	if (This->state == STATE_PLAYING)
+		This->state = STATE_STOPPING;
+	else if (This->state == STATE_STARTING)
+		This->state = STATE_STOPPED;
+	if (This->hwbuf) {
+		hres = IDsDriverBuffer_Stop(This->hwbuf);
+		if (hres != DS_OK)
+			WARN("IDsDriverBuffer_Stop failed\n");
+		else
+			This->state = STATE_STOPPED;
+	}
+	DSOUND_CheckEvent(This, 0);
+
+	LeaveCriticalSection(&(This->lock));
+	/* **** */
+
+	return hres;
+}
+
+static ULONG WINAPI IDirectSoundBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface)
+{
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+	return InterlockedIncrement(&(This->ref));
+}
+
+static ULONG WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface)
+{
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	ULONG ref;
+
+	TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
+
+	ref = InterlockedDecrement(&(This->ref));
+	if (ref)
+		return ref;
+
+	DSOUND_RemoveBuffer(This->dsound, This);
+
+	This->lock.DebugInfo->Spare[1] = 0;
+	DeleteCriticalSection(&(This->lock));
+
+	if (This->hwbuf) {
+		IDsDriverBuffer_Release(This->hwbuf);
+		if (This->dsound->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
+			This->buffer->ref--;
+			if (This->buffer->ref==0) {
+				HeapFree(GetProcessHeap(),0,This->buffer->memory);
+				HeapFree(GetProcessHeap(),0,This->buffer);
+			}
+		}
+	} else {
+		This->buffer->ref--;
+		if (This->buffer->ref==0) {
+			HeapFree(GetProcessHeap(),0,This->buffer->memory);
+			HeapFree(GetProcessHeap(),0,This->buffer);
+		}
+	}
+
+	if (This->notifies != NULL)
+		HeapFree(GetProcessHeap(), 0, This->notifies);
+
+	if (This->pwfx)
+		HeapFree(GetProcessHeap(), 0, This->pwfx);
+
+	HeapFree(GetProcessHeap(),0,This);
+
+	TRACE("(%p) released\n",This);
+	return 0;
+}
+
+DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This,
+			      DWORD state, DWORD pplay, DWORD pwrite, DWORD pmix, DWORD bmix)
+{
+	DWORD bplay;
+
+	TRACE("primary playpos=%ld, mixpos=%ld\n", pplay, pmix);
+	TRACE("this mixpos=%ld, time=%ld\n", bmix, GetTickCount());
+
+	/* the actual primary play position (pplay) is always behind last mixed (pmix),
+	 * unless the computer is too slow or something */
+	/* we need to know how far away we are from there */
+#if 0 /* we'll never fill the primary entirely */
+	if (pmix == pplay) {
+		if ((state == STATE_PLAYING) || (state == STATE_STOPPING)) {
+			/* wow, the software mixer is really doing well,
+			 * seems the entire primary buffer is filled! */
+			pmix += This->dsound->buflen;
+		}
+		/* else: the primary buffer is not playing, so probably empty */
+	}
+#endif
+	if (pmix < pplay) pmix += This->dsound->buflen; /* wraparound */
+	pmix -= pplay;
+	/* detect buffer underrun */
+	if (pwrite < pplay) pwrite += This->dsound->buflen; /* wraparound */
+	pwrite -= pplay;
+	if (pmix > (ds_snd_queue_max * This->dsound->fraglen + pwrite + This->dsound->writelead)) {
+		WARN("detected an underrun: primary queue was %ld\n",pmix);
+		pmix = 0;
+	}
+	/* divide the offset by its sample size */
+	pmix /= This->dsound->pwfx->nBlockAlign;
+	TRACE("primary back-samples=%ld\n",pmix);
+	/* adjust for our frequency */
+	pmix = (pmix * This->freqAdjust) >> DSOUND_FREQSHIFT;
+	/* multiply by our own sample size */
+	pmix *= This->pwfx->nBlockAlign;
+	TRACE("this back-offset=%ld\n", pmix);
+	/* subtract from our last mixed position */
+	bplay = bmix;
+	while (bplay < pmix) bplay += This->buflen; /* wraparound */
+	bplay -= pmix;
+	if (This->leadin && ((bplay < This->startpos) || (bplay > bmix))) {
+		/* seems we haven't started playing yet */
+		TRACE("this still in lead-in phase\n");
+		bplay = This->startpos;
+	}
+	/* return the result */
+	return bplay;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(
+	LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos
+) {
+	HRESULT	hres;
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	TRACE("(%p,%p,%p)\n",This,playpos,writepos);
+	if (This->hwbuf) {
+		hres=IDsDriverBuffer_GetPosition(This->hwbuf,playpos,writepos);
+		if (hres != DS_OK) {
+		    WARN("IDsDriverBuffer_GetPosition failed\n");
+		    return hres;
+		}
+	} else {
+		if (playpos && (This->state != STATE_PLAYING)) {
+			/* we haven't been merged into the primary buffer (yet) */
+			*playpos = This->buf_mixpos;
+		} else if (playpos) {
+			DWORD pplay, pwrite, lplay, splay, pstate;
+			/* let's get this exact; first, recursively call GetPosition on the primary */
+			EnterCriticalSection(&(This->dsound->mixlock));
+			if (DSOUND_PrimaryGetPosition(This->dsound, &pplay, &pwrite) != DS_OK)
+				WARN("DSOUND_PrimaryGetPosition failed\n");
+			/* detect HEL mode underrun */
+			pstate = This->dsound->state;
+			if (!(This->dsound->hwbuf || This->dsound->pwqueue)) {
+				TRACE("detected an underrun\n");
+				/* pplay = ? */
+				if (pstate == STATE_PLAYING)
+					pstate = STATE_STARTING;
+				else if (pstate == STATE_STOPPING)
+					pstate = STATE_STOPPED;
+			}
+			/* get data for ourselves while we still have the lock */
+			pstate &= This->state;
+			lplay = This->primary_mixpos;
+			splay = This->buf_mixpos;
+			if ((This->dsbd.dwFlags & DSBCAPS_GETCURRENTPOSITION2) || This->dsound->hwbuf) {
+				/* calculate play position using this */
+				*playpos = DSOUND_CalcPlayPosition(This, pstate, pplay, pwrite, lplay, splay);
+			} else {
+				/* (unless the app isn't using GETCURRENTPOSITION2) */
+				/* don't know exactly how this should be handled...
+				 * the docs says that play cursor is reported as directly
+				 * behind write cursor, hmm... */
+				/* let's just do what might work for Half-Life */
+				DWORD wp;
+				wp = (This->dsound->pwplay + ds_hel_margin) * This->dsound->fraglen;
+				wp %= This->dsound->buflen;
+				*playpos = DSOUND_CalcPlayPosition(This, pstate, wp, pwrite, lplay, splay);
+			}
+			LeaveCriticalSection(&(This->dsound->mixlock));
+		}
+		if (writepos)
+                    *writepos = This->buf_mixpos;
+	}
+	if (writepos) {
+		if (This->state != STATE_STOPPED) {
+			/* apply the documented 10ms lead to writepos */
+			*writepos += This->writelead;
+		}
+		*writepos %= This->buflen;
+	}
+	if (playpos)
+            This->last_playpos = *playpos;
+	TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, This, GetTickCount());
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus(
+	LPDIRECTSOUNDBUFFER8 iface,LPDWORD status
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	TRACE("(%p,%p), thread is %04lx\n",This,status,GetCurrentThreadId());
+
+	if (status == NULL) {
+		WARN("invalid parameter: status = NULL\n");
+		return DSERR_INVALIDPARAM;
+	}
+
+	*status = 0;
+	if ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING)) {
+		*status |= DSBSTATUS_PLAYING;
+		if (This->playflags & DSBPLAY_LOOPING)
+			*status |= DSBSTATUS_LOOPING;
+	}
+
+	TRACE("status=%lx\n", *status);
+	return DS_OK;
+}
+
+
+static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat(
+    LPDIRECTSOUNDBUFFER8 iface,
+    LPWAVEFORMATEX lpwf,
+    DWORD wfsize,
+    LPDWORD wfwritten)
+{
+    DWORD size;
+    IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+    TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten);
+
+    size = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
+
+    if (lpwf) { /* NULL is valid */
+        if (wfsize >= size) {
+            memcpy(lpwf,This->pwfx,size);
+            if (wfwritten)
+                *wfwritten = size;
+        } else {
+            WARN("invalid parameter: wfsize to small\n");
+            if (wfwritten)
+                *wfwritten = 0;
+            return DSERR_INVALIDPARAM;
+        }
+    } else {
+        if (wfwritten)
+            *wfwritten = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
+        else {
+            WARN("invalid parameter: wfwritten == NULL\n");
+            return DSERR_INVALIDPARAM;
+        }
+    }
+
+    return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
+) {
+	HRESULT hres = DS_OK;
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+
+	TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx) at %ld\n",
+		This,
+		writecursor,
+		writebytes,
+		lplpaudioptr1,
+		audiobytes1,
+		lplpaudioptr2,
+		audiobytes2,
+		flags,
+		GetTickCount()
+	);
+
+	if (flags & DSBLOCK_FROMWRITECURSOR) {
+		DWORD writepos;
+		/* GetCurrentPosition does too much magic to duplicate here */
+		hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writepos);
+		if (hres != DS_OK) {
+			WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n");
+			return hres;
+		}
+		writecursor += writepos;
+	}
+	writecursor %= This->buflen;
+	if (flags & DSBLOCK_ENTIREBUFFER)
+		writebytes = This->buflen;
+	if (writebytes > This->buflen)
+		writebytes = This->buflen;
+
+	EnterCriticalSection(&(This->lock));
+
+	if ((writebytes == This->buflen) &&
+	    ((This->state == STATE_STARTING) ||
+	     (This->state == STATE_PLAYING)))
+		/* some games, like Half-Life, try to be clever (not) and
+		 * keep one secondary buffer, and mix sounds into it itself,
+		 * locking the entire buffer every time... so we can just forget
+		 * about tracking the last-written-to-position... */
+		This->probably_valid_to = (DWORD)-1;
+	else
+		This->probably_valid_to = writecursor;
+
+	if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
+		hres = IDsDriverBuffer_Lock(This->hwbuf,
+				     lplpaudioptr1, audiobytes1,
+				     lplpaudioptr2, audiobytes2,
+				     writecursor, writebytes,
+				     0);
+		if (hres != DS_OK) {
+			WARN("IDsDriverBuffer_Lock failed\n");
+			LeaveCriticalSection(&(This->lock));
+			return hres;
+		}
+	} else {
+		BOOL remix = FALSE;
+		if (writecursor+writebytes <= This->buflen) {
+			*(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
+			*audiobytes1 = writebytes;
+			if (lplpaudioptr2)
+				*(LPBYTE*)lplpaudioptr2 = NULL;
+			if (audiobytes2)
+				*audiobytes2 = 0;
+			TRACE("->%ld.0\n",writebytes);
+		} else {
+			*(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
+			*audiobytes1 = This->buflen-writecursor;
+			if (lplpaudioptr2)
+				*(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
+			if (audiobytes2)
+				*audiobytes2 = writebytes-(This->buflen-writecursor);
+			TRACE("->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0);
+		}
+		if (This->state == STATE_PLAYING) {
+			/* if the segment between playpos and buf_mixpos is touched,
+			 * we need to cancel some mixing */
+			/* we'll assume that the app always calls GetCurrentPosition before
+			 * locking a playing buffer, so that last_playpos is up-to-date */
+			if (This->buf_mixpos >= This->last_playpos) {
+				if (This->buf_mixpos > writecursor &&
+				    This->last_playpos < writecursor+writebytes)
+					remix = TRUE;
+			} else {
+				if (This->buf_mixpos > writecursor ||
+				    This->last_playpos < writecursor+writebytes)
+					remix = TRUE;
+			}
+			if (remix) {
+				TRACE("locking prebuffered region, ouch\n");
+				DSOUND_MixCancelAt(This, writecursor);
+			}
+		}
+	}
+
+	LeaveCriticalSection(&(This->lock));
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD newpos
+) {
+	HRESULT hres = DS_OK;
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	TRACE("(%p,%ld)\n",This,newpos);
+
+	/* **** */
+	EnterCriticalSection(&(This->lock));
+
+	newpos %= This->buflen;
+	This->buf_mixpos = newpos;
+	if (This->hwbuf) {
+		hres = IDsDriverBuffer_SetPosition(This->hwbuf, This->buf_mixpos);
+		if (hres != DS_OK)
+			WARN("IDsDriverBuffer_SetPosition failed\n");
+	}
+
+	LeaveCriticalSection(&(This->lock));
+	/* **** */
+
+	return hres;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_SetPan(
+	LPDIRECTSOUNDBUFFER8 iface,LONG pan
+) {
+	HRESULT hres = DS_OK;
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+
+	TRACE("(%p,%ld)\n",This,pan);
+
+	if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) {
+		WARN("invalid parameter: pan = %ld\n", pan);
+		return DSERR_INVALIDPARAM;
+	}
+
+	/* You cannot use both pan and 3D controls */
+	if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
+	    (This->dsbd.dwFlags & DSBCAPS_CTRL3D)) {
+		WARN("control unavailable\n");
+		return DSERR_CONTROLUNAVAIL;
+	}
+
+	/* **** */
+	EnterCriticalSection(&(This->lock));
+
+	if (This->volpan.lPan != pan) {
+		This->volpan.lPan = pan;
+		DSOUND_RecalcVolPan(&(This->volpan));
+
+		if (This->hwbuf) {
+			hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
+			if (hres != DS_OK)
+				WARN("IDsDriverBuffer_SetVolumePan failed\n");
+		} else
+			DSOUND_ForceRemix(This);
+	}
+
+	LeaveCriticalSection(&(This->lock));
+	/* **** */
+
+	return hres;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_GetPan(
+	LPDIRECTSOUNDBUFFER8 iface,LPLONG pan
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	TRACE("(%p,%p)\n",This,pan);
+
+	if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
+		WARN("control unavailable\n");
+		return DSERR_CONTROLUNAVAIL;
+	}
+
+	if (pan == NULL) {
+		WARN("invalid parameter: pan = NULL\n");
+		return DSERR_INVALIDPARAM;
+	}
+
+	*pan = This->volpan.lPan;
+
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(
+	LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	DWORD probably_valid_to;
+	HRESULT hres = DS_OK;
+
+	TRACE("(%p,%p,%ld,%p,%ld)\n", This,p1,x1,p2,x2);
+
+	/* **** */
+	EnterCriticalSection(&(This->lock));
+
+	if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
+		hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2);
+		if (hres != DS_OK)
+			WARN("IDsDriverBuffer_Unlock failed\n");
+	}
+
+        if (hres == DS_OK) {
+		if (p2) probably_valid_to = (((LPBYTE)p2)-This->buffer->memory) + x2;
+		else probably_valid_to = (((LPBYTE)p1)-This->buffer->memory) + x1;
+		probably_valid_to %= This->buflen;
+		if ((probably_valid_to == 0) && ((x1+x2) == This->buflen) &&
+		    ((This->state == STATE_STARTING) ||
+		     (This->state == STATE_PLAYING)))
+			/* see IDirectSoundBufferImpl_Lock */
+			probably_valid_to = (DWORD)-1;
+		This->probably_valid_to = probably_valid_to;
+	}
+
+	LeaveCriticalSection(&(This->lock));
+	/* **** */
+
+	TRACE("probably_valid_to=%ld\n", This->probably_valid_to);
+	return hres;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_Restore(
+	LPDIRECTSOUNDBUFFER8 iface
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	FIXME("(%p):stub\n",This);
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(
+	LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	TRACE("(%p,%p)\n",This,freq);
+
+	if (freq == NULL) {
+		WARN("invalid parameter: freq = NULL\n");
+		return DSERR_INVALIDPARAM;
+	}
+
+	*freq = This->freq;
+	TRACE("-> %ld\n", *freq);
+
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	DWORD u;
+
+	FIXME("(%p,%lu,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
+
+	if (pdwResultCodes)
+		for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
+
+	WARN("control unavailable\n");
+	return DSERR_CONTROLUNAVAIL;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(
+	LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	DWORD u;
+
+	FIXME("(%p,%08lu,%lu,%p): stub\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
+
+	if (pdwResultCodes)
+		for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
+
+	WARN("control unavailable\n");
+	return DSERR_CONTROLUNAVAIL;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath(
+	LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+
+	FIXME("(%p,%s,%lu,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
+
+	WARN("control unavailable\n");
+	return DSERR_CONTROLUNAVAIL;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_Initialize(
+	LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND dsound,LPCDSBUFFERDESC dbsd
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+	FIXME("(%p,%p,%p):stub\n",This,dsound,dbsd);
+	DPRINTF("Re-Init!!!\n");
+	WARN("already initialized\n");
+	return DSERR_ALREADYINITIALIZED;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(
+	LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
+  	TRACE("(%p)->(%p)\n",This,caps);
+
+	if (caps == NULL) {
+		WARN("invalid parameter: caps == NULL\n");
+		return DSERR_INVALIDPARAM;
+	}
+
+	if (caps->dwSize < sizeof(*caps)) {
+		WARN("invalid parameter: caps->dwSize = %ld < %d\n",caps->dwSize, sizeof(*caps));
+		return DSERR_INVALIDPARAM;
+	}
+
+	caps->dwFlags = This->dsbd.dwFlags;
+	if (This->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE;
+	else caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
+
+	caps->dwBufferBytes = This->buflen;
+
+	/* This value represents the speed of the "unlock" command.
+	   As unlock is quite fast (it does not do anything), I put
+	   4096 ko/s = 4 Mo / s */
+	/* FIXME: hwbuf speed */
+	caps->dwUnlockTransferRate = 4096;
+	caps->dwPlayCpuOverhead = 0;
+
+	return DS_OK;
+}
+
+static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
+	LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj
+) {
+	IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)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_IDirectSoundBuffer) ||
+	     IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
+		if (!This->dsb)
+			SecondaryBufferImpl_Create(This, &(This->dsb));
+		if (This->dsb) {
+			IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb);
+			*ppobj = This->dsb;
+			return S_OK;
+		}
+		WARN("IID_IDirectSoundBuffer\n");
+		return E_NOINTERFACE;
+	}
+
+	if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
+		if (!This->notify)
+			IDirectSoundNotifyImpl_Create(This, &(This->notify));
+		if (This->notify) {
+			IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
+			*ppobj = This->notify;
[truncated at 1000 lines; 10802 more skipped]