Use the drivers to get device capabilities and property sets.

diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 4c29b5b..138d711 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1044,6 +1044,7 @@
 	dsb->dsb = 0;
 	dsb->dsound = ds;
 	dsb->lpVtbl = &dsbvt;
+	dsb->iks = NULL;
 
 	memcpy(&dsb->dsbd, dsbd, sizeof(*dsbd));
 	if (wfex)
@@ -1064,7 +1065,9 @@
 	else capf |= DSCAPS_SECONDARYMONO;
 	if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
 	else capf |= DSCAPS_SECONDARY8BIT;
+
 	use_hw = (ds->drvcaps.dwFlags & capf) == capf;
+	TRACE("use_hw = 0x%08x, capf = 0x%08lx, ds->drvcaps.dwFlags = 0x%08lx\n", use_hw, capf, ds->drvcaps.dwFlags);
 
 	/* FIXME: check hardware sample rate mixing capabilities */
 	/* FIXME: check app hints for software/hardware buffer (STATIC, LOCHARDWARE, etc) */
diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c
index bd926c9..4068fb3 100644
--- a/dlls/dsound/dsound_main.c
+++ b/dlls/dsound/dsound_main.c
@@ -671,37 +671,37 @@
 		return DSERR_INVALIDPARAM;
 	}
 
-	lpDSCaps->dwFlags = This->drvcaps.dwFlags;
+	lpDSCaps->dwFlags                               = This->drvcaps.dwFlags;
 	TRACE("(flags=0x%08lx)\n",lpDSCaps->dwFlags);
 
-	/* FIXME: copy caps from This->drv */
-	lpDSCaps->dwMinSecondarySampleRate		= DSBFREQUENCY_MIN;
-	lpDSCaps->dwMaxSecondarySampleRate		= DSBFREQUENCY_MAX;
+	lpDSCaps->dwMinSecondarySampleRate		= This->drvcaps.dwMinSecondarySampleRate;
+	lpDSCaps->dwMaxSecondarySampleRate		= This->drvcaps.dwMaxSecondarySampleRate;
 
-	lpDSCaps->dwPrimaryBuffers			= 1;
+	lpDSCaps->dwPrimaryBuffers			= This->drvcaps.dwPrimaryBuffers;
 
-	lpDSCaps->dwMaxHwMixingAllBuffers		= 0;
-	lpDSCaps->dwMaxHwMixingStaticBuffers		= 0;
-	lpDSCaps->dwMaxHwMixingStreamingBuffers		= 0;
+	lpDSCaps->dwMaxHwMixingAllBuffers		= This->drvcaps.dwMaxHwMixingAllBuffers;
+	lpDSCaps->dwMaxHwMixingStaticBuffers		= This->drvcaps.dwMaxHwMixingStaticBuffers;
+	lpDSCaps->dwMaxHwMixingStreamingBuffers		= This->drvcaps.dwMaxHwMixingStreamingBuffers;
 
-	lpDSCaps->dwFreeHwMixingAllBuffers		= 0;
-	lpDSCaps->dwFreeHwMixingStaticBuffers		= 0;
-	lpDSCaps->dwFreeHwMixingStreamingBuffers	= 0;
+	lpDSCaps->dwFreeHwMixingAllBuffers		= This->drvcaps.dwFreeHwMixingAllBuffers;
+	lpDSCaps->dwFreeHwMixingStaticBuffers		= This->drvcaps.dwFreeHwMixingStaticBuffers;
+	lpDSCaps->dwFreeHwMixingStreamingBuffers	= This->drvcaps.dwFreeHwMixingStreamingBuffers;
 
-	lpDSCaps->dwMaxHw3DAllBuffers			= 0;
-	lpDSCaps->dwMaxHw3DStaticBuffers		= 0;
-	lpDSCaps->dwMaxHw3DStreamingBuffers		= 0;
+	lpDSCaps->dwMaxHw3DAllBuffers			= This->drvcaps.dwMaxHw3DAllBuffers;
+	lpDSCaps->dwMaxHw3DStaticBuffers		= This->drvcaps.dwMaxHw3DStaticBuffers;
+	lpDSCaps->dwMaxHw3DStreamingBuffers		= This->drvcaps.dwMaxHw3DStreamingBuffers;
 
-	lpDSCaps->dwFreeHw3DAllBuffers			= 0;
-	lpDSCaps->dwFreeHw3DStaticBuffers		= 0;
-	lpDSCaps->dwFreeHw3DStreamingBuffers		= 0;
+	lpDSCaps->dwFreeHw3DAllBuffers			= This->drvcaps.dwFreeHw3DAllBuffers;
+	lpDSCaps->dwFreeHw3DStaticBuffers		= This->drvcaps.dwFreeHw3DStaticBuffers;
+	lpDSCaps->dwFreeHw3DStreamingBuffers		= This->drvcaps.dwFreeHw3DStreamingBuffers;
 
-	lpDSCaps->dwTotalHwMemBytes			= 0;
+	lpDSCaps->dwTotalHwMemBytes			= This->drvcaps.dwTotalHwMemBytes;
 
-	lpDSCaps->dwFreeHwMemBytes			= 0;
+	lpDSCaps->dwFreeHwMemBytes			= This->drvcaps.dwFreeHwMemBytes;
 
-	lpDSCaps->dwMaxContigFreeHwMemBytes		= 0;
+	lpDSCaps->dwMaxContigFreeHwMemBytes		= This->drvcaps.dwMaxContigFreeHwMemBytes;
 
+	/* driver doesn't have these */
 	lpDSCaps->dwUnlockTransferRateHwBuffers		= 4096;	/* But we have none... */
 
 	lpDSCaps->dwPlayCpuOverheadSwBuffers		= 1;	/* 1% */
@@ -1099,7 +1099,7 @@
 			*ippDS = NULL;
 			return err;
 		}
-		(*ippDS)->drvcaps.dwFlags = 0;
+		ZeroMemory(&(*ippDS)->drvcaps, sizeof((*ippDS)->drvcaps));
 		if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
 		    (woc.dwFormats & WAVE_FORMAT_2M08) ||
 		    (woc.dwFormats & WAVE_FORMAT_4M08) ||
@@ -1134,6 +1134,9 @@
 		}
 		if (ds_emuldriver)
 		    (*ippDS)->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
+		(*ippDS)->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
+		(*ippDS)->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
+		(*ippDS)->drvcaps.dwPrimaryBuffers = 1;
 	}
 
 	DSOUND_RecalcVolPan(&((*ippDS)->volpan));
diff --git a/dlls/dsound/propset.c b/dlls/dsound/propset.c
index 30adad2..708807b 100644
--- a/dlls/dsound/propset.c
+++ b/dlls/dsound/propset.c
@@ -25,12 +25,14 @@
 #include <sys/types.h>
 #include <sys/fcntl.h>
 #ifdef HAVE_UNISTD_H
-# include <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"
@@ -43,9 +45,9 @@
 #include "wine/windef16.h"
 #include "wine/debug.h"
 #include "dsound.h"
+#include "dsconf.h"
 #include "dsdriver.h"
 #include "dsound_private.h"
-#include "dsconf.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
 
@@ -103,9 +105,28 @@
     PULONG pcbReturned )
 {
     ICOM_THIS(IKsBufferPropertySetImpl,iface);
-    FIXME("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p) stub!\n",
+    PIDSDRIVERPROPERTYSET ps;
+    TRACE("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
 	This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
 
+    IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
+
+    if (ps) {
+	DSPROPERTY prop;
+	HRESULT hres;
+
+	prop.s.Set = *guidPropSet;
+	prop.s.Id = dwPropID;
+	prop.s.Flags = 0;	/* unused */
+	prop.s.InstanceId = (ULONG)This->dsb->dsound;
+
+	hres = IDsDriverPropertySet_Get(ps, &prop, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned);
+
+	IDsDriverPropertySet_Release(ps);
+
+	return hres;
+    }
+
     return E_PROP_ID_UNSUPPORTED;
 }
 
@@ -119,8 +140,26 @@
     ULONG cbPropData )
 {
     ICOM_THIS(IKsBufferPropertySetImpl,iface);
+    PIDSDRIVERPROPERTYSET ps;
+    TRACE("(%p,%s,%ld,%p,%ld,%p,%ld)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
 
-    FIXME("(%p,%s,%ld,%p,%ld,%p,%ld), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
+    IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
+
+    if (ps) {
+	DSPROPERTY prop;
+	HRESULT hres;
+
+	prop.s.Set = *guidPropSet;
+	prop.s.Id = dwPropID;
+	prop.s.Flags = 0;	/* unused */
+	prop.s.InstanceId = (ULONG)This->dsb->dsound;
+	hres = IDsDriverPropertySet_Set(ps,&prop,pInstanceData,cbInstanceData,pPropData,cbPropData);
+
+	IDsDriverPropertySet_Release(ps);
+
+	return hres;
+    }
+
     return E_PROP_ID_UNSUPPORTED;
 }
 
@@ -131,7 +170,20 @@
     PULONG pTypeSupport )
 {
     ICOM_THIS(IKsBufferPropertySetImpl,iface);
-    FIXME("(%p,%s,%ld,%p) stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
+    PIDSDRIVERPROPERTYSET ps;
+    TRACE("(%p,%s,%ld,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
+
+    IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
+
+    if (ps) {
+	HRESULT hres;
+
+    	hres = IDsDriverPropertySet_QuerySupport(ps,guidPropSet, dwPropID,pTypeSupport);
+
+	IDsDriverPropertySet_Release(ps);
+
+	return hres;
+    }
 
     return E_PROP_ID_UNSUPPORTED;
 }
@@ -151,8 +203,9 @@
     IKsBufferPropertySetImpl **piks)
 {
     IKsBufferPropertySetImpl *iks;
+    TRACE("(%p,%p)\n",dsb,piks);
 
-    iks = (IKsBufferPropertySetImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
+    iks = (IKsBufferPropertySetImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*iks));
     iks->ref = 0;
     iks->dsb = dsb;
     dsb->iks = iks;
@@ -299,79 +352,86 @@
 	FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
 	    debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
 	return E_PROP_ID_UNSUPPORTED;
-    } else {
-	GetDeviceID(&ppd->DeviceId, &dev_guid);
-
-	if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) || 
-	     IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
-	    ULONG wod;
-	    int wodn;
-	    TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
-	    ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
-	    wodn = waveOutGetNumDevs();
-	    for (wod = 0; wod < wodn; wod++) {
-		err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
-		if (err == DS_OK) {
-		    if (IsEqualGUID( &dev_guid, &guid) ) {
-			DSDRIVERDESC desc;
-			ppd->WaveDeviceId = wod;
-			ppd->Devnode = wod;
-			err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
-			if (err == DS_OK) {
-			    strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
-			    strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
-			    MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
-			    MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
-			    break;
-			} else {
-			    WARN("waveOutMessage failed\n");
-			    return E_PROP_ID_UNSUPPORTED;
-			}
-		    }
-		} else {
-		    WARN("waveOutMessage failed\n");
-		    return E_PROP_ID_UNSUPPORTED;
-		}
-	    }
-	} else if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
-	            IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
-	    ULONG wid;
-	    int widn;
-	    TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
-	    ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
-	    widn = waveInGetNumDevs();
-	    for (wid = 0; wid < widn; wid++) {
-		err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
-		if (err == DS_OK) {
-		    if (IsEqualGUID( &dev_guid, &guid) ) {
-			DSDRIVERDESC desc;
-			ppd->WaveDeviceId = wid;
-			ppd->Devnode = wid;
-			err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
-			if (err == DS_OK) {
-			    strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
-			    strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
-			    MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
-			    MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
-			    break;
-			} else {
-			    WARN("waveInMessage failed\n");
-			    return E_PROP_ID_UNSUPPORTED;
-			}
-			break;
-		    }
-		} else {
-		    WARN("waveInMessage failed\n");
-		    return E_PROP_ID_UNSUPPORTED;
-		}
-	    }
-	} else {
-	    FIXME("DeviceId=Unknown\n");
-	    return E_PROP_ID_UNSUPPORTED;
-	}
     }
 
     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
+    GetDeviceID(&ppd->DeviceId, &dev_guid);
+
+    if ( IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultPlayback) || 
+	 IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultVoicePlayback) ) {
+	ULONG wod;
+	int wodn;
+	TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
+	ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
+	wodn = waveOutGetNumDevs();
+	for (wod = 0; wod < wodn; wod++) {
+	    err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
+	    if (err == DS_OK) {
+		if (IsEqualGUID( &dev_guid, &guid) ) {
+		    DSDRIVERDESC desc;
+		    ppd->WaveDeviceId = wod;
+		    ppd->Devnode = wod;
+		    err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
+		    if (err == DS_OK) {
+			PIDSDRIVER drv = NULL;
+			strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
+			strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
+			MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
+			MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
+			err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
+			if (err == DS_OK && drv)
+				ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
+			break;
+		    } else {
+			WARN("waveOutMessage failed\n");
+			return E_PROP_ID_UNSUPPORTED;
+		    }
+		}
+	    } else {
+		WARN("waveOutMessage failed\n");
+		return E_PROP_ID_UNSUPPORTED;
+	    }
+	}
+    } else if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
+	        IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
+	ULONG wid;
+	int widn;
+	TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
+	ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
+	widn = waveInGetNumDevs();
+	for (wid = 0; wid < widn; wid++) {
+	    err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
+	    if (err == DS_OK) {
+		if (IsEqualGUID( &dev_guid, &guid) ) {
+		    DSDRIVERDESC desc;
+		    ppd->WaveDeviceId = wid;
+		    ppd->Devnode = wid;
+		    err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
+		    if (err == DS_OK) {
+			PIDSCDRIVER drv;
+			strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
+			strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
+			MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
+			MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
+			err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
+			if (err == DS_OK && drv)
+				ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
+			break;
+		    } else {
+			WARN("waveInMessage failed\n");
+			return E_PROP_ID_UNSUPPORTED;
+		    }
+		    break;
+		}
+	    } else {
+		WARN("waveInMessage failed\n");
+		return E_PROP_ID_UNSUPPORTED;
+	    }
+	}
+    } else {
+	FIXME("DeviceId=Unknown\n");
+	return E_PROP_ID_UNSUPPORTED;
+    }
 
     if (pcbReturned) {
 	*pcbReturned = cbPropData; 
@@ -417,93 +477,100 @@
 	FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
 	    debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
 	return E_PROP_ID_UNSUPPORTED;
-    } else {
-	GetDeviceID(&ppd->DeviceId, &dev_guid);
-
-	if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) || 
-	     IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
-	    ULONG wod;
-	    int wodn;
-	    TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
-	    ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
-	    wodn = waveOutGetNumDevs();
-	    for (wod = 0; wod < wodn; wod++) {
-		err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
-		if (err == DS_OK) {
-		    if (IsEqualGUID( &dev_guid, &guid) ) {
-			DSDRIVERDESC desc;
-			ppd->WaveDeviceId = wod;
-			err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
-			if (err == DS_OK) {
-			    /* FIXME: this is a memory leak */
-			    WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
-			    WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
-			    WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
-
-			    MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
-			    MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
-			    MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
-
-			    ppd->Description = wDescription;
-			    ppd->Module = wModule;
-			    ppd->Interface = wInterface;
-			    break;
-			} else {
-			    WARN("waveOutMessage failed\n");
-			    return E_PROP_ID_UNSUPPORTED;
-			}
-		    }
-		} else {
-		    WARN("waveOutMessage failed\n");
-		    return E_PROP_ID_UNSUPPORTED;
-		}
-	    }
-	} else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
-		   IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
-	    ULONG wid;
-	    int widn;
-	    TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
-	    ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
-	    widn = waveInGetNumDevs();
-	    for (wid = 0; wid < widn; wid++) {
-		err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
-		if (err == DS_OK) {
-		    if (IsEqualGUID( &dev_guid, &guid) ) {
-			DSDRIVERDESC desc;
-			ppd->WaveDeviceId = wid;
-			err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
-			if (err == DS_OK) {
-			    /* FIXME: this is a memory leak */
-			    WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
-			    WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
-			    WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
-
-			    MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
-			    MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
-			    MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
-
-			    ppd->Description = wDescription;
-			    ppd->Module = wModule;
-			    ppd->Interface = wInterface;
-			    break;
-			} else {
-			    WARN("waveInMessage failed\n");
-			    return E_PROP_ID_UNSUPPORTED;
-			}
-			break;
-		    }
-		} else {
-		    WARN("waveInMessage failed\n");
-		    return E_PROP_ID_UNSUPPORTED;
-		}
-	    }
-	} else {
-	    FIXME("DeviceId=Unknown\n");
-	    return E_PROP_ID_UNSUPPORTED;
-	}
     }
 
     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
+    GetDeviceID(&ppd->DeviceId, &dev_guid);
+
+    if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) || 
+	 IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
+	ULONG wod;
+	int wodn;
+	TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
+	ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
+	wodn = waveOutGetNumDevs();
+	for (wod = 0; wod < wodn; wod++) {
+	    err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
+	    if (err == DS_OK) {
+		if (IsEqualGUID( &dev_guid, &guid) ) {
+		    DSDRIVERDESC desc;
+		    ppd->WaveDeviceId = wod;
+		    err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
+		    if (err == DS_OK) {
+			PIDSDRIVER drv = NULL;
+			/* FIXME: this is a memory leak */
+			WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
+			WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
+			WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
+
+			MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
+			MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
+			MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
+
+			ppd->Description = wDescription;
+			ppd->Module = wModule;
+			ppd->Interface = wInterface;
+			err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
+			if (err == DS_OK && drv)
+				ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
+			    break;
+		    } else {
+			WARN("waveOutMessage failed\n");
+			return E_PROP_ID_UNSUPPORTED;
+		    }
+		}
+	    } else {
+		WARN("waveOutMessage failed\n");
+		return E_PROP_ID_UNSUPPORTED;
+	    }
+	}
+    } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
+	       IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
+	ULONG wid;
+	int widn;
+	TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
+	ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
+	widn = waveInGetNumDevs();
+	for (wid = 0; wid < widn; wid++) {
+	    err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
+	    if (err == DS_OK) {
+		if (IsEqualGUID( &dev_guid, &guid) ) {
+		    DSDRIVERDESC desc;
+		    ppd->WaveDeviceId = wid;
+		    err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
+		    if (err == DS_OK) {
+			PIDSCDRIVER drv;
+			/* FIXME: this is a memory leak */
+			WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
+			WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
+			WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
+
+			MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
+			MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
+			MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
+
+			ppd->Description = wDescription;
+			ppd->Module = wModule;
+			ppd->Interface = wInterface;
+			err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
+			if (err == DS_OK && drv)
+				ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
+			break;
+		    } else {
+			WARN("waveInMessage failed\n");
+			return E_PROP_ID_UNSUPPORTED;
+		    }
+		    break;
+		}
+	    } else {
+		WARN("waveInMessage failed\n");
+		return E_PROP_ID_UNSUPPORTED;
+	    }
+	}
+    } else {
+	FIXME("DeviceId=Unknown\n");
+	return E_PROP_ID_UNSUPPORTED;
+    }
 
     if (pcbReturned) {
 	*pcbReturned = cbPropData; 
diff --git a/dlls/winmm/winealsa/audio.c b/dlls/winmm/winealsa/audio.c
index 2e41831..ed3ff75 100644
--- a/dlls/winmm/winealsa/audio.c
+++ b/dlls/winmm/winealsa/audio.c
@@ -2009,6 +2009,8 @@
 
     pCaps->dwPrimaryBuffers = 1;
     TRACE("caps=0x%X\n",(unsigned int)pCaps->dwFlags);
+    pCaps->dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
+    pCaps->dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
 
     /* the other fields only apply to secondary buffers, which we don't support
      * (unless we want to mess with wavetable synthesizers and MIDI) */
diff --git a/dlls/winmm/wineaudioio/audio.c b/dlls/winmm/wineaudioio/audio.c
index 25416ec..b046eab 100644
--- a/dlls/winmm/wineaudioio/audio.c
+++ b/dlls/winmm/wineaudioio/audio.c
@@ -1562,6 +1562,8 @@
     pCaps->dwFlags = DSCAPS_PRIMARYMONO | DSCAPS_PRIMARYSTEREO |
 	DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARY16BIT;
     pCaps->dwPrimaryBuffers = 1;
+    pCaps->dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
+    pCaps->dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
     /* the other fields only apply to secondary buffers, which we don't support
      * (unless we want to mess with wavetable synthesizers and MIDI) */
     return DS_OK;
diff --git a/dlls/winmm/wineoss/audio.c b/dlls/winmm/wineoss/audio.c
index 0523cfa..057f464 100644
--- a/dlls/winmm/wineoss/audio.c
+++ b/dlls/winmm/wineoss/audio.c
@@ -553,7 +553,9 @@
     /* direct sound caps */
     ossdev->ds_caps.dwFlags = 0;
     ossdev->ds_caps.dwPrimaryBuffers = 1;
-
+    ossdev->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
+    ossdev->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
+                                                                                
     if (WINE_TRACE_ON(wave)) {
         /* Note that this only reports the formats supported by the hardware.
          * The driver may support other formats and do the conversions in