shell32/tests: With recent PSDKs, CSIDL_MYDOCUMENTS is a synonym for CSIDL_PERSONAL...
[wine] / dlls / dsound / propset.c
1 /*                      DirectSound
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998 Rob Riggs
5  * Copyright 2000-2002 TransGaming Technologies, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #define COBJMACROS
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "mmsystem.h"
29 #include "winternl.h"
30 #include "winnls.h"
31 #include "vfwmsgs.h"
32 #include "mmddk.h"
33 #include "wine/debug.h"
34 #include "dsound.h"
35 #include "dsdriver.h"
36 #include "dsound_private.h"
37 #include "dsconf.h"
38
39 #ifdef NONAMELESSSTRUCT
40 # define S(x) (x).s
41 #else
42 # define S(x) (x)
43 #endif
44
45 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
46
47
48 /*******************************************************************************
49  *              IKsBufferPropertySet
50  */
51
52 /* IUnknown methods */
53 static HRESULT WINAPI IKsBufferPropertySetImpl_QueryInterface(
54     LPKSPROPERTYSET iface,
55     REFIID riid,
56     LPVOID *ppobj )
57 {
58     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
59     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
60
61     return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
62 }
63
64 static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface)
65 {
66     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
67     ULONG ref = InterlockedIncrement(&(This->ref));
68     TRACE("(%p) ref was %d\n", This, ref - 1);
69     return ref;
70 }
71
72 static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
73 {
74     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
75     ULONG ref = InterlockedDecrement(&(This->ref));
76     TRACE("(%p) ref was %d\n", This, ref + 1);
77
78     if (!ref) {
79         This->dsb->iks = 0;
80         IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
81         HeapFree(GetProcessHeap(), 0, This);
82         TRACE("(%p) released\n", This);
83     }
84     return ref;
85 }
86
87 static HRESULT WINAPI IKsBufferPropertySetImpl_Get(
88     LPKSPROPERTYSET iface,
89     REFGUID guidPropSet,
90     ULONG dwPropID,
91     LPVOID pInstanceData,
92     ULONG cbInstanceData,
93     LPVOID pPropData,
94     ULONG cbPropData,
95     PULONG pcbReturned )
96 {
97     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
98     PIDSDRIVERPROPERTYSET ps;
99     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
100         This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
101
102     if (This->dsb->hwbuf) {
103         IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
104
105         if (ps) {
106             DSPROPERTY prop;
107             HRESULT hres;
108
109             S(prop).Set = *guidPropSet;
110             S(prop).Id = dwPropID;
111             S(prop).Flags = 0;  /* unused */
112             S(prop).InstanceId = (ULONG)This->dsb->device;
113
114             hres = IDsDriverPropertySet_Get(ps, &prop, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned);
115
116             IDsDriverPropertySet_Release(ps);
117
118             return hres;
119         }
120     }
121
122     return E_PROP_ID_UNSUPPORTED;
123 }
124
125 static HRESULT WINAPI IKsBufferPropertySetImpl_Set(
126     LPKSPROPERTYSET iface,
127     REFGUID guidPropSet,
128     ULONG dwPropID,
129     LPVOID pInstanceData,
130     ULONG cbInstanceData,
131     LPVOID pPropData,
132     ULONG cbPropData )
133 {
134     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
135     PIDSDRIVERPROPERTYSET ps;
136     TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
137
138     if (This->dsb->hwbuf) {
139         IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
140
141         if (ps) {
142             DSPROPERTY prop;
143             HRESULT hres;
144
145             S(prop).Set = *guidPropSet;
146             S(prop).Id = dwPropID;
147             S(prop).Flags = 0;  /* unused */
148             S(prop).InstanceId = (ULONG)This->dsb->device;
149             hres = IDsDriverPropertySet_Set(ps,&prop,pInstanceData,cbInstanceData,pPropData,cbPropData);
150
151             IDsDriverPropertySet_Release(ps);
152
153             return hres;
154         }
155     }
156
157     return E_PROP_ID_UNSUPPORTED;
158 }
159
160 static HRESULT WINAPI IKsBufferPropertySetImpl_QuerySupport(
161     LPKSPROPERTYSET iface,
162     REFGUID guidPropSet,
163     ULONG dwPropID,
164     PULONG pTypeSupport )
165 {
166     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
167     PIDSDRIVERPROPERTYSET ps;
168     TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
169
170     if (This->dsb->hwbuf) {
171         IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
172
173         if (ps) {
174             HRESULT hres;
175
176             hres = IDsDriverPropertySet_QuerySupport(ps,guidPropSet, dwPropID,pTypeSupport);
177
178             IDsDriverPropertySet_Release(ps);
179
180             return hres;
181         }
182     }
183
184     return E_PROP_ID_UNSUPPORTED;
185 }
186
187 static const IKsPropertySetVtbl iksbvt = {
188     IKsBufferPropertySetImpl_QueryInterface,
189     IKsBufferPropertySetImpl_AddRef,
190     IKsBufferPropertySetImpl_Release,
191     IKsBufferPropertySetImpl_Get,
192     IKsBufferPropertySetImpl_Set,
193     IKsBufferPropertySetImpl_QuerySupport
194 };
195
196 HRESULT IKsBufferPropertySetImpl_Create(
197     IDirectSoundBufferImpl *dsb,
198     IKsBufferPropertySetImpl **piks)
199 {
200     IKsBufferPropertySetImpl *iks;
201     TRACE("(%p,%p)\n",dsb,piks);
202
203     iks = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*iks));
204     if (iks == 0) {
205         WARN("out of memory\n");
206         *piks = NULL;
207         return DSERR_OUTOFMEMORY;
208     }
209
210     iks->ref = 0;
211     iks->dsb = dsb;
212     dsb->iks = iks;
213     iks->lpVtbl = &iksbvt;
214
215     IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
216
217     *piks = iks;
218     return S_OK;
219 }
220
221 HRESULT IKsBufferPropertySetImpl_Destroy(
222     IKsBufferPropertySetImpl *piks)
223 {
224     TRACE("(%p)\n",piks);
225
226     while (IKsBufferPropertySetImpl_Release((LPKSPROPERTYSET)piks) > 0);
227
228     return S_OK;
229 }
230
231 /*******************************************************************************
232  *              IKsPrivatePropertySet
233  */
234
235 /* IUnknown methods */
236 static HRESULT WINAPI IKsPrivatePropertySetImpl_QueryInterface(
237     LPKSPROPERTYSET iface,
238     REFIID riid,
239     LPVOID *ppobj )
240 {
241     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
242     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
243
244     if (IsEqualIID(riid, &IID_IUnknown) ||
245         IsEqualIID(riid, &IID_IKsPropertySet)) {
246         *ppobj = iface;
247         IUnknown_AddRef(iface);
248         return S_OK;
249     }
250     *ppobj = NULL;
251     return E_NOINTERFACE;
252 }
253
254 static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface)
255 {
256     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
257     ULONG ref = InterlockedIncrement(&(This->ref));
258     TRACE("(%p) ref was %d\n", This, ref - 1);
259     return ref;
260 }
261
262 static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface)
263 {
264     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
265     ULONG ref = InterlockedDecrement(&(This->ref));
266     TRACE("(%p) ref was %d\n", This, ref + 1);
267
268     if (!ref) {
269         HeapFree(GetProcessHeap(), 0, This);
270         TRACE("(%p) released\n", This);
271     }
272     return ref;
273 }
274
275 static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingA(
276     LPVOID pPropData,
277     ULONG cbPropData,
278     PULONG pcbReturned )
279 {
280     HRESULT hr = DSERR_INVALIDPARAM;
281     PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA ppd;
282     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
283           pPropData,cbPropData,pcbReturned);
284
285     ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA) pPropData;
286
287     if (!ppd) {
288         WARN("invalid parameter: pPropData\n");
289         return DSERR_INVALIDPARAM;
290     }
291
292     if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
293         ULONG wod;
294         unsigned int wodn;
295         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
296         wodn = waveOutGetNumDevs();
297         for (wod = 0; wod < wodn; wod++) {
298             WAVEOUTCAPSA capsA;
299             MMRESULT res;
300             res = waveOutGetDevCapsA(wod, &capsA, sizeof(capsA));
301             if (res == MMSYSERR_NOERROR) {
302                 if (lstrcmpA(capsA.szPname, ppd->DeviceName) == 0) {
303                     ppd->DeviceId = DSOUND_renderer_guids[wod];
304                     hr = DS_OK;
305                     TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
306                           ppd->DeviceName);
307                     break;
308                 }
309             }
310         }
311     } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
312         ULONG wid;
313         unsigned int widn;
314         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
315         widn = waveInGetNumDevs();
316         for (wid = 0; wid < widn; wid++) {
317             WAVEINCAPSA capsA;
318             MMRESULT res;
319             res = waveInGetDevCapsA(wid, &capsA, sizeof(capsA));
320             if (res == MMSYSERR_NOERROR) {
321                 if (lstrcmpA(capsA.szPname, ppd->DeviceName) == 0) {
322                     ppd->DeviceId = DSOUND_capture_guids[wid];
323                     TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
324                           ppd->DeviceName);
325                     hr = DS_OK;
326                     break;
327                 }
328             }
329         }
330     }
331
332     if (pcbReturned)
333         *pcbReturned = cbPropData;
334
335     return hr;
336 }
337
338 static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingW(
339     LPVOID pPropData,
340     ULONG cbPropData,
341     PULONG pcbReturned )
342 {
343     HRESULT hr = DSERR_INVALIDPARAM;
344     PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd;
345     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
346           pPropData,cbPropData,pcbReturned);
347
348     ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA) pPropData;
349
350     if (!ppd) {
351         WARN("invalid parameter: pPropData\n");
352         return DSERR_INVALIDPARAM;
353     }
354
355     if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
356         ULONG wod;
357         unsigned int wodn;
358         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
359         wodn = waveOutGetNumDevs();
360         for (wod = 0; wod < wodn; wod++) {
361             WAVEOUTCAPSW capsW;
362             MMRESULT res;
363             res = waveOutGetDevCapsW(wod, &capsW, sizeof(capsW));
364             if (res == MMSYSERR_NOERROR) {
365                 if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
366                     ppd->DeviceId = DSOUND_renderer_guids[wod];
367                     hr = DS_OK;
368                     TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
369                           debugstr_w(ppd->DeviceName));
370                     break;
371                 }
372             }
373         }
374     } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
375         ULONG wid;
376         unsigned int widn;
377         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
378         widn = waveInGetNumDevs();
379         for (wid = 0; wid < widn; wid++) {
380             WAVEINCAPSW capsW;
381             MMRESULT res;
382             res = waveInGetDevCapsW(wid, &capsW, sizeof(capsW));
383             if (res == MMSYSERR_NOERROR) {
384                 if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
385                     ppd->DeviceId = DSOUND_capture_guids[wid];
386                     hr = DS_OK;
387                     TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
388                           debugstr_w(ppd->DeviceName));
389                     break;
390                 }
391             }
392         }
393     }
394
395     if (pcbReturned)
396         *pcbReturned = cbPropData;
397
398     return hr;
399 }
400
401 static HRESULT WINAPI DSPROPERTY_Description1(
402     LPVOID pPropData,
403     ULONG cbPropData,
404     PULONG pcbReturned )
405 {
406     HRESULT err;
407     GUID guid, dev_guid;
408     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA ppd;
409     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
410         pPropData,cbPropData,pcbReturned);
411
412     ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA) pPropData;
413
414     if (!ppd) {
415         WARN("invalid parameter: pPropData\n");
416         return DSERR_INVALIDPARAM;
417     }
418
419     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
420     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
421         /* default device of type specified by ppd->DataFlow */
422         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
423             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
424         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
425             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
426         } else {
427             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
428         }
429         FIXME("(pPropData=%p,cbPropData=%d,pcbReturned=%p) GUID_NULL not implemented!\n",
430               pPropData,cbPropData,pcbReturned);
431         return E_PROP_ID_UNSUPPORTED;
432     }
433
434     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
435     GetDeviceID(&ppd->DeviceId, &dev_guid);
436
437     if ( IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultPlayback) ||
438          IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultVoicePlayback) ) {
439         ULONG wod;
440         unsigned int wodn;
441         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
442         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
443         wodn = waveOutGetNumDevs();
444         for (wod = 0; wod < wodn; wod++) {
445             if (IsEqualGUID( &dev_guid, &DSOUND_renderer_guids[wod] ) ) {
446                 DSDRIVERDESC desc;
447                 ppd->WaveDeviceId = wod;
448                 ppd->Devnode = wod;
449                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
450                 if (err == DS_OK) {
451                     PIDSDRIVER drv = NULL;
452                     lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA));
453                     lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA));
454                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
455                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
456                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
457                     if (err == DS_OK && drv)
458                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
459                     else
460                         WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
461                     break;
462                 } else {
463                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
464                     return E_PROP_ID_UNSUPPORTED;
465                 }
466             }
467         }
468     } else if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
469                 IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
470         ULONG wid;
471         unsigned int widn;
472         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
473         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
474         widn = waveInGetNumDevs();
475         for (wid = 0; wid < widn; wid++) {
476             if (IsEqualGUID( &dev_guid, &guid) ) {
477                 DSDRIVERDESC desc;
478                 ppd->WaveDeviceId = wid;
479                 ppd->Devnode = wid;
480                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
481                 if (err == DS_OK) {
482                     PIDSCDRIVER drv;
483                     lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA));
484                     lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA));
485                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
486                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
487                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0));
488                     if (err == DS_OK && drv)
489                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
490                     else
491                         WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
492                     break;
493                 } else {
494                     WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
495                     return E_PROP_ID_UNSUPPORTED;
496                 }
497             }
498         }
499     } else {
500         BOOL found = FALSE;
501         ULONG wod;
502         unsigned int wodn;
503         /* given specific device so try the render devices first */
504         wodn = waveOutGetNumDevs();
505         for (wod = 0; wod < wodn; wod++) {
506             if (IsEqualGUID( &ppd->DeviceId, &DSOUND_renderer_guids[wod] ) ) {
507                 DSDRIVERDESC desc;
508                 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
509                 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
510                 ppd->WaveDeviceId = wod;
511                 ppd->Devnode = wod;
512                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
513                 if (err == DS_OK) {
514                     PIDSDRIVER drv = NULL;
515                     lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA));
516                     lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA));
517                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
518                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
519                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
520                     if (err == DS_OK && drv)
521                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
522                     else
523                         WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
524                     found = TRUE;
525                     break;
526                 } else {
527                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
528                     return E_PROP_ID_UNSUPPORTED;
529                 }
530             }
531         }
532
533         if (found == FALSE) {
534             ULONG wid;
535             unsigned int widn;
536             /* given specific device so try the capture devices next */
537             widn = waveInGetNumDevs();
538             for (wid = 0; wid < widn; wid++) {
539                 if (IsEqualGUID( &ppd->DeviceId, &DSOUND_capture_guids[wid] ) ) {
540                     DSDRIVERDESC desc;
541                     TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
542                     ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
543                     ppd->WaveDeviceId = wid;
544                     ppd->Devnode = wid;
545                     err = mmErr(waveInMessage((HWAVEIN)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
546                     if (err == DS_OK) {
547                         PIDSDRIVER drv = NULL;
548                         lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA));
549                         lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA));
550                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
551                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
552                         err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
553                         if (err == DS_OK && drv)
554                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
555                         else
556                             WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
557                         found = TRUE;
558                         break;
559                     } else {
560                         WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
561                         return E_PROP_ID_UNSUPPORTED;
562                     }
563                 }
564             }
565
566             if (found == FALSE) {
567                 WARN("device not found\n");
568                 return E_PROP_ID_UNSUPPORTED;
569             }
570         }
571     }
572
573     if (pcbReturned) {
574         *pcbReturned = cbPropData;
575         TRACE("*pcbReturned=%d\n", *pcbReturned);
576     }
577
578     return S_OK;
579 }
580
581 static HRESULT WINAPI DSPROPERTY_DescriptionA(
582     LPVOID pPropData,
583     ULONG cbPropData,
584     PULONG pcbReturned )
585 {
586     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA) pPropData;
587     HRESULT err;
588     GUID dev_guid;
589     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
590           pPropData,cbPropData,pcbReturned);
591
592     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
593     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
594         /* default device of type specified by ppd->DataFlow */
595         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
596             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
597         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
598             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
599         } else {
600             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
601         }
602         FIXME("(pPropData=%p,cbPropData=%d,pcbReturned=%p) GUID_NULL not implemented!\n",
603               pPropData,cbPropData,pcbReturned);
604         return E_PROP_ID_UNSUPPORTED;
605     }
606
607     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
608     GetDeviceID(&ppd->DeviceId, &dev_guid);
609
610     if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
611          IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
612         ULONG wod;
613         unsigned int wodn;
614         if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) )
615             TRACE("DSDEVID_DefaultPlayback\n");
616         else
617             TRACE("DSDEVID_DefaultVoicePlayback\n");
618         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
619         wodn = waveOutGetNumDevs();
620         for (wod = 0; wod < wodn; wod++) {
621             if (IsEqualGUID( &dev_guid, &DSOUND_renderer_guids[wod] ) ) {
622                 DSDRIVERDESC desc;
623                 ppd->WaveDeviceId = wod;
624                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
625                 if (err == DS_OK) {
626                     PIDSDRIVER drv = NULL;
627                     /* FIXME: this is a memory leak */
628                     CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
629                     CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
630                     CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
631
632                     if (szDescription && szModule && szInterface) {
633                         strcpy(szDescription, desc.szDesc);
634                         strcpy(szModule, desc.szDrvname);
635                         strcpy(szInterface, "Interface");
636
637                         ppd->Description = szDescription;
638                         ppd->Module = szModule;
639                         ppd->Interface = szInterface;
640                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
641                         if (err == DS_OK && drv)
642                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
643                         else
644                             WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
645                         break;
646                     } else {
647                         WARN("no memory\n");
648                         HeapFree(GetProcessHeap(), 0, szDescription);
649                         HeapFree(GetProcessHeap(), 0, szModule);
650                         HeapFree(GetProcessHeap(), 0, szInterface);
651                         return E_OUTOFMEMORY;
652                     }
653                 } else {
654                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
655                     return E_PROP_ID_UNSUPPORTED;
656                 }
657             }
658         }
659     } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
660                IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
661         ULONG wid;
662         unsigned int widn;
663         if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) )
664             TRACE("DSDEVID_DefaultCapture\n");
665         else
666             TRACE("DSDEVID_DefaultVoiceCapture\n");
667         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
668         widn = waveInGetNumDevs();
669         for (wid = 0; wid < widn; wid++) {
670             if (IsEqualGUID( &dev_guid, &DSOUND_capture_guids[wid] ) ) {
671                 DSDRIVERDESC desc;
672                 ppd->WaveDeviceId = wid;
673                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
674                 if (err == DS_OK) {
675                     PIDSCDRIVER drv;
676                     /* FIXME: this is a memory leak */
677                     CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
678                     CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
679                     CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
680
681                     if (szDescription && szModule && szInterface) {
682                         strcpy(szDescription, desc.szDesc);
683                         strcpy(szModule, desc.szDrvname);
684                         strcpy(szInterface, "Interface");
685
686                         ppd->Description = szDescription;
687                         ppd->Module = szModule;
688                         ppd->Interface = szInterface;
689                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0));
690                         if (err == DS_OK && drv)
691                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
692                         else
693                             WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
694                         break;
695                     } else {
696                         WARN("no memory\n");
697                         HeapFree(GetProcessHeap(), 0, szDescription);
698                         HeapFree(GetProcessHeap(), 0, szModule);
699                         HeapFree(GetProcessHeap(), 0, szInterface);
700                         return E_OUTOFMEMORY;
701                     }
702                 } else {
703                     WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
704                     return E_PROP_ID_UNSUPPORTED;
705                 }
706             }
707         }
708     } else {
709         BOOL found = FALSE;
710         ULONG wod;
711         unsigned int wodn;
712         /* given specific device so try the render devices first */
713         TRACE("Checking renderer devices\n");
714         wodn = waveOutGetNumDevs();
715         for (wod = 0; wod < wodn; wod++) {
716             if (IsEqualGUID( &ppd->DeviceId, &DSOUND_renderer_guids[wod] ) ) {
717                 DSDRIVERDESC desc;
718                 TRACE("DSOUND_renderer_guids[%d]\n", wod);
719                 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
720                 ppd->WaveDeviceId = wod;
721                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
722                 if (err == DS_OK) {
723                     PIDSDRIVER drv = NULL;
724                     /* FIXME: this is a memory leak */
725                     CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
726                     CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
727                     CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
728
729                     if (szDescription && szModule && szInterface) {
730                         strcpy(szDescription, desc.szDesc);
731                         strcpy(szModule, desc.szDrvname);
732                         strcpy(szInterface, "Interface");
733
734                         ppd->Description = szDescription;
735                         ppd->Module = szModule;
736                         ppd->Interface = szInterface;
737                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
738                         if (err == DS_OK && drv)
739                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
740                         else
741                             WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
742                         found = TRUE;
743                         break;
744                     } else {
745                         WARN("no memory\n");
746                         HeapFree(GetProcessHeap(), 0, szDescription);
747                         HeapFree(GetProcessHeap(), 0, szModule);
748                         HeapFree(GetProcessHeap(), 0, szInterface);
749                         return E_OUTOFMEMORY;
750                     }
751                 } else {
752                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
753                     return E_PROP_ID_UNSUPPORTED;
754                 }
755             }
756         }
757
758         if (found == FALSE) {
759             ULONG wid;
760             unsigned int widn;
761             TRACE("Checking capture devices\n");
762             ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
763             widn = waveInGetNumDevs();
764             for (wid = 0; wid < widn; wid++) {
765                 if (IsEqualGUID( &ppd->DeviceId, &DSOUND_capture_guids[wid] ) ) {
766                     DSDRIVERDESC desc;
767                     TRACE("DSOUND_capture_guids[%d]\n", wid);
768                     ppd->WaveDeviceId = wid;
769                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
770                     if (err == DS_OK) {
771                         PIDSCDRIVER drv;
772                         /* FIXME: this is a memory leak */
773                         CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
774                         CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
775                         CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
776
777                         if (szDescription && szModule && szInterface) {
778                             strcpy(szDescription, desc.szDesc);
779                             strcpy(szModule, desc.szDrvname);
780                             strcpy(szInterface, "Interface");
781
782                             ppd->Description = szDescription;
783                             ppd->Module = szModule;
784                             ppd->Interface = szInterface;
785                             err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0));
786                             if (err == DS_OK && drv)
787                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
788                             else
789                                 WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
790                             found = TRUE;
791                             break;
792                         } else {
793                             WARN("no memory\n");
794                             HeapFree(GetProcessHeap(), 0, szDescription);
795                             HeapFree(GetProcessHeap(), 0, szModule);
796                             HeapFree(GetProcessHeap(), 0, szInterface);
797                             return E_OUTOFMEMORY;
798                         }
799                     } else {
800                         WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
801                         return E_PROP_ID_UNSUPPORTED;
802                     }
803                 }
804             }
805         }
806
807         if (found == FALSE) {
808             WARN("device not found\n");
809             return E_PROP_ID_UNSUPPORTED;
810         }
811     }
812
813     if (pcbReturned) {
814         *pcbReturned = cbPropData;
815         TRACE("*pcbReturned=%d\n", *pcbReturned);
816     }
817
818     return S_OK;
819 }
820
821 static HRESULT WINAPI DSPROPERTY_DescriptionW(
822     LPVOID pPropData,
823     ULONG cbPropData,
824     PULONG pcbReturned )
825 {
826     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA) pPropData;
827     HRESULT err;
828     GUID dev_guid;
829     TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
830           pPropData,cbPropData,pcbReturned);
831
832     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
833     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
834         /* default device of type specified by ppd->DataFlow */
835         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
836             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
837         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
838             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
839         } else {
840             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
841         }
842         FIXME("(pPropData=%p,cbPropData=%d,pcbReturned=%p) GUID_NULL not implemented!\n",
843               pPropData,cbPropData,pcbReturned);
844         return E_PROP_ID_UNSUPPORTED;
845     }
846
847     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
848     GetDeviceID(&ppd->DeviceId, &dev_guid);
849
850     if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
851          IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
852         ULONG wod;
853         unsigned int wodn;
854         if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) )
855             TRACE("DSDEVID_DefaultPlayback\n");
856         else
857             TRACE("DSDEVID_DefaultVoicePlayback\n");
858         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
859         wodn = waveOutGetNumDevs();
860         for (wod = 0; wod < wodn; wod++) {
861             if (IsEqualGUID( &dev_guid, &DSOUND_renderer_guids[wod] ) ) {
862                 DSDRIVERDESC desc;
863                 TRACE("DSOUND_renderer_guids[%d]\n", wod);
864                 ppd->WaveDeviceId = wod;
865                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
866                 if (err == DS_OK) {
867                     PIDSDRIVER drv = NULL;
868                     /* FIXME: this is a memory leak */
869                     WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
870                     WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
871                     WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
872
873                     if (wDescription && wModule && wInterface) {
874                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
875                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
876                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
877
878                         ppd->Description = wDescription;
879                         ppd->Module = wModule;
880                         ppd->Interface = wInterface;
881                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
882                         if (err == DS_OK && drv)
883                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
884                         else
885                             WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
886                         break;
887                     } else {
888                         WARN("no memory\n");
889                         HeapFree(GetProcessHeap(), 0, wDescription);
890                         HeapFree(GetProcessHeap(), 0, wModule);
891                         HeapFree(GetProcessHeap(), 0, wInterface);
892                         return E_OUTOFMEMORY;
893                     }
894                 } else {
895                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
896                     return E_PROP_ID_UNSUPPORTED;
897                 }
898             }
899         }
900     } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
901                IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
902         ULONG wid;
903         unsigned int widn;
904         if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture))
905             TRACE("DSDEVID_DefaultCapture\n");
906         else
907             TRACE("DSDEVID_DefaultVoiceCapture\n");
908         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
909         widn = waveInGetNumDevs();
910         for (wid = 0; wid < widn; wid++) {
911             if (IsEqualGUID( &dev_guid, &DSOUND_capture_guids[wid] ) ) {
912                 DSDRIVERDESC desc;
913                 ppd->WaveDeviceId = wid;
914                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
915                 if (err == DS_OK) {
916                     PIDSCDRIVER drv;
917                     /* FIXME: this is a memory leak */
918                     WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
919                     WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
920                     WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
921
922                     if (wDescription && wModule && wInterface) {
923                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
924                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
925                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
926
927                         ppd->Description = wDescription;
928                         ppd->Module = wModule;
929                         ppd->Interface = wInterface;
930                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0));
931                         if (err == DS_OK && drv)
932                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
933                         else
934                             WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
935                         break;
936                     } else {
937                         WARN("no memory\n");
938                         HeapFree(GetProcessHeap(), 0, wDescription);
939                         HeapFree(GetProcessHeap(), 0, wModule);
940                         HeapFree(GetProcessHeap(), 0, wInterface);
941                         return E_OUTOFMEMORY;
942                     }
943                 } else {
944                     WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
945                     return E_PROP_ID_UNSUPPORTED;
946                 }
947             }
948         }
949     } else {
950         BOOL found = FALSE;
951         ULONG wod;
952         unsigned int wodn;
953         TRACE("Checking renderer devices\n");
954         /* given specific device so try the render devices first */
955         wodn = waveOutGetNumDevs();
956         for (wod = 0; wod < wodn; wod++) {
957             if (IsEqualGUID( &ppd->DeviceId, &DSOUND_renderer_guids[wod] ) ) {
958                 DSDRIVERDESC desc;
959                 TRACE("DSOUND_renderer_guids[%d]\n", wod);
960                 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
961                 ppd->WaveDeviceId = wod;
962                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
963                 if (err == DS_OK) {
964                     PIDSDRIVER drv = NULL;
965                     /* FIXME: this is a memory leak */
966                     WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
967                     WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
968                     WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
969
970                     if (wDescription && wModule && wInterface) {
971                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
972                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
973                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
974
975                         ppd->Description = wDescription;
976                         ppd->Module = wModule;
977                         ppd->Interface = wInterface;
978                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
979                         if (err == DS_OK && drv)
980                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
981                         else
982                             WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
983                         found = TRUE;
984                         break;
985                     } else {
986                         WARN("no memory\n");
987                         HeapFree(GetProcessHeap(), 0, wDescription);
988                         HeapFree(GetProcessHeap(), 0, wModule);
989                         HeapFree(GetProcessHeap(), 0, wInterface);
990                         return E_OUTOFMEMORY;
991                     }
992                 } else {
993                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
994                     return E_PROP_ID_UNSUPPORTED;
995                 }
996             }
997         }
998
999         if (found == FALSE) {
1000             ULONG wid;
1001             unsigned int widn;
1002             TRACE("Checking capture devices\n");
1003             ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
1004             widn = waveInGetNumDevs();
1005             for (wid = 0; wid < widn; wid++) {
1006                 if (IsEqualGUID( &dev_guid, &DSOUND_capture_guids[wid] ) ) {
1007                     DSDRIVERDESC desc;
1008                     TRACE("DSOUND_capture_guids[%d]\n", wid);
1009                     ppd->WaveDeviceId = wid;
1010                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
1011                     if (err == DS_OK) {
1012                         PIDSCDRIVER drv;
1013                         /* FIXME: this is a memory leak */
1014                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
1015                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
1016                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
1017
1018                         if (wDescription && wModule && wInterface) {
1019                             MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
1020                             MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
1021                             MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
1022
1023                             ppd->Description = wDescription;
1024                             ppd->Module = wModule;
1025                             ppd->Interface = wInterface;
1026                             err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0));
1027                             if (err == DS_OK && drv)
1028                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
1029                             else
1030                                 WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
1031                             found = TRUE;
1032                             break;
1033                         } else {
1034                             WARN("no memory\n");
1035                             HeapFree(GetProcessHeap(), 0, wDescription);
1036                             HeapFree(GetProcessHeap(), 0, wModule);
1037                             HeapFree(GetProcessHeap(), 0, wInterface);
1038                             return E_OUTOFMEMORY;
1039                         }
1040                     } else {
1041                         WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
1042                         return E_PROP_ID_UNSUPPORTED;
1043                     }
1044                 }
1045             }
1046         }
1047
1048         if (found == FALSE) {
1049             WARN("device not found\n");
1050             return E_PROP_ID_UNSUPPORTED;
1051         }
1052     }
1053
1054     if (pcbReturned) {
1055         *pcbReturned = cbPropData;
1056         TRACE("*pcbReturned=%d\n", *pcbReturned);
1057     }
1058
1059     return S_OK;
1060 }
1061
1062 static HRESULT WINAPI DSPROPERTY_Enumerate1(
1063     LPVOID pPropData,
1064     ULONG cbPropData,
1065     PULONG pcbReturned )
1066 {
1067     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA) pPropData;
1068     HRESULT err;
1069     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
1070           pPropData,cbPropData,pcbReturned);
1071
1072     if (ppd) {
1073         if (ppd->Callback) {
1074             unsigned devs, wod, wid;
1075             DSDRIVERDESC desc;
1076             DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA data;
1077
1078             devs = waveOutGetNumDevs();
1079             for (wod = 0; wod < devs; ++wod) {
1080                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
1081                 if (err == DS_OK) {
1082                     PIDSCDRIVER drv;
1083                     ZeroMemory(&data, sizeof(data));
1084                     data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
1085                     data.WaveDeviceId = wod;
1086                     data.DeviceId = DSOUND_renderer_guids[wod];
1087                     lstrcpynA(data.DescriptionA, desc.szDesc, sizeof(data.DescriptionA));
1088                     lstrcpynA(data.ModuleA, desc.szDrvname, sizeof(data.ModuleA));
1089
1090                     MultiByteToWideChar( CP_ACP, 0, data.DescriptionA, -1, data.DescriptionW, sizeof(data.DescriptionW)/sizeof(WCHAR) );
1091                     MultiByteToWideChar( CP_ACP, 0, data.ModuleA, -1, data.ModuleW, sizeof(data.ModuleW)/sizeof(WCHAR) );
1092
1093                     data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
1094                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
1095                     if (err == DS_OK && drv)
1096                         data.Type = DIRECTSOUNDDEVICE_TYPE_VXD;
1097                     else
1098                         WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
1099
1100                     TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1101                     (ppd->Callback)(&data, ppd->Context);
1102                 }
1103             }
1104
1105             devs = waveInGetNumDevs();
1106             for (wid = 0; wid < devs; ++wid) {
1107                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
1108                 if (err == DS_OK) {
1109                     PIDSCDRIVER drv;
1110                     ZeroMemory(&data, sizeof(data));
1111                     data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
1112                     data.WaveDeviceId = wid;
1113                     data.DeviceId = DSOUND_capture_guids[wid];
1114                     lstrcpynA(data.DescriptionA, desc.szDesc, sizeof(data.DescriptionA));
1115                     lstrcpynA(data.ModuleA, desc.szDrvname, sizeof(data.ModuleA));
1116
1117                     MultiByteToWideChar( CP_ACP, 0, data.DescriptionA, -1, data.DescriptionW, sizeof(data.DescriptionW)/sizeof(WCHAR) );
1118                     MultiByteToWideChar( CP_ACP, 0, data.ModuleA, -1, data.ModuleW, sizeof(data.ModuleW)/sizeof(WCHAR) );
1119
1120                     data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
1121                     err = mmErr(waveInMessage((HWAVEIN)wid, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
1122                     if (err == DS_OK && drv)
1123                         data.Type = DIRECTSOUNDDEVICE_TYPE_VXD;
1124                     else
1125                         WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
1126
1127                     TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1128                     (ppd->Callback)(&data, ppd->Context);
1129                 }
1130             }
1131
1132             return S_OK;
1133         }
1134     }
1135
1136     if (pcbReturned) {
1137         *pcbReturned = 0;
1138         FIXME("*pcbReturned=%d\n", *pcbReturned);
1139     }
1140
1141     return E_PROP_ID_UNSUPPORTED;
1142 }
1143
1144 static HRESULT WINAPI DSPROPERTY_EnumerateA(
1145     LPVOID pPropData,
1146     ULONG cbPropData,
1147     PULONG pcbReturned )
1148 {
1149     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA) pPropData;
1150     HRESULT err;
1151     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
1152           pPropData,cbPropData,pcbReturned);
1153
1154     if (ppd) {
1155         if (ppd->Callback) {
1156             unsigned devs, wod, wid;
1157             DSDRIVERDESC desc;
1158             DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA data;
1159
1160             devs = waveOutGetNumDevs();
1161             for (wod = 0; wod < devs; ++wod) {
1162                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
1163                 if (err == DS_OK) {
1164                     DWORD size;
1165                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0));
1166                     if (err == DS_OK) {
1167                         WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size);
1168                         if (nameW) {
1169                             err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size));
1170                             if (err == DS_OK) {
1171                                 CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR));
1172                                 if (szInterface) {
1173                                     PIDSCDRIVER drv;
1174                                     ZeroMemory(&data, sizeof(data));
1175                                     data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
1176                                     data.WaveDeviceId = wod;
1177                                     data.DeviceId = DSOUND_renderer_guids[wod];
1178                                     data.Description = desc.szDesc;
1179                                     data.Module = desc.szDrvname;
1180                                     WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL );
1181                                     data.Interface = szInterface;
1182
1183                                     data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
1184                                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
1185                                     if (err == DS_OK && drv)
1186                                         data.Type = DIRECTSOUNDDEVICE_TYPE_VXD;
1187                                     else
1188                                         WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
1189
1190                                     TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1191                                     (ppd->Callback)(&data, ppd->Context);
1192                                 }
1193                                 HeapFree(GetProcessHeap(),0,szInterface);
1194                             }
1195                         }
1196                         HeapFree(GetProcessHeap(),0,nameW);
1197                     }
1198                 }
1199             }
1200
1201             devs = waveInGetNumDevs();
1202             for (wid = 0; wid < devs; ++wid) {
1203                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
1204                 if (err == DS_OK) {
1205                     DWORD size;
1206                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0));
1207                     if (err == DS_OK) {
1208                         WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size);
1209                         if (nameW) {
1210                             err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size));
1211                             if (err == DS_OK) {
1212                                 CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR));
1213                                 if (szInterface) {
1214                                     PIDSCDRIVER drv;
1215                                     ZeroMemory(&data, sizeof(data));
1216                                     data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
1217                                     data.WaveDeviceId = wid;
1218                                     data.DeviceId = DSOUND_capture_guids[wid];
1219                                     data.Description = desc.szDesc;
1220                                     data.Module = desc.szDrvname;
1221                                     WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL );
1222                                     data.Interface = szInterface;
1223
1224                                     data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
1225                                     err = mmErr(waveInMessage((HWAVEIN)wid, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
1226                                     if (err == DS_OK && drv)
1227                                         data.Type = DIRECTSOUNDDEVICE_TYPE_VXD;
1228                                     else
1229                                         WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
1230
1231                                     TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1232                                     (ppd->Callback)(&data, ppd->Context);
1233                                 }
1234                                 HeapFree(GetProcessHeap(),0,szInterface);
1235                             }
1236                         }
1237                         HeapFree(GetProcessHeap(),0,nameW);
1238                     }
1239                 }
1240             }
1241
1242             return S_OK;
1243         }
1244     }
1245
1246     if (pcbReturned) {
1247         *pcbReturned = 0;
1248         FIXME("*pcbReturned=%d\n", *pcbReturned);
1249     }
1250
1251     return E_PROP_ID_UNSUPPORTED;
1252 }
1253
1254 static HRESULT WINAPI DSPROPERTY_EnumerateW(
1255     LPVOID pPropData,
1256     ULONG cbPropData,
1257     PULONG pcbReturned )
1258 {
1259     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA) pPropData;
1260     HRESULT err;
1261     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
1262           pPropData,cbPropData,pcbReturned);
1263
1264     if (ppd) {
1265         if (ppd->Callback) {
1266             unsigned devs, wod, wid;
1267             DSDRIVERDESC desc;
1268             DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
1269
1270             devs = waveOutGetNumDevs();
1271             for (wod = 0; wod < devs; ++wod) {
1272                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
1273                 if (err == DS_OK) {
1274                     WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
1275                     WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
1276                     if (wDescription && wModule) {
1277                         DWORD size;
1278                         err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0));
1279                         if (err == DS_OK) {
1280                             WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size);
1281                             if (wInterface) {
1282                                 err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size));
1283                                 if (err == DS_OK) {
1284                                     PIDSCDRIVER drv;
1285                                     ZeroMemory(&data, sizeof(data));
1286                                     data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
1287                                     data.WaveDeviceId = wod;
1288                                     data.DeviceId = DSOUND_renderer_guids[wod];
1289
1290                                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
1291                                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
1292
1293                                     data.Description = wDescription;
1294                                     data.Module = wModule;
1295                                     data.Interface = wInterface;
1296
1297                                     data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
1298                                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
1299                                     if (err == DS_OK && drv)
1300                                         data.Type = DIRECTSOUNDDEVICE_TYPE_VXD;
1301                                     else
1302                                         WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
1303
1304                                     TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1305                                     (ppd->Callback)(&data, ppd->Context);
1306                                     }
1307                             }
1308                             HeapFree(GetProcessHeap(),0,wInterface);
1309                         }
1310                     }
1311                     HeapFree(GetProcessHeap(),0,wDescription);
1312                     HeapFree(GetProcessHeap(),0,wModule);
1313                 }
1314             }
1315
1316             devs = waveInGetNumDevs();
1317             for (wid = 0; wid < devs; ++wid) {
1318                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
1319                 if (err == DS_OK) {
1320                     WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
1321                     WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
1322                     if (wDescription && wModule) {
1323                         DWORD size;
1324                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0));
1325                         if (err == DS_OK) {
1326                             WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size);
1327                             if (wInterface) {
1328                                 err = mmErr(waveInMessage((HWAVEIN)wid, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size));
1329                                 if (err == DS_OK) {
1330                                     PIDSCDRIVER drv;
1331                                     ZeroMemory(&data, sizeof(data));
1332                                     data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
1333                                     data.WaveDeviceId = wid;
1334                                     data.DeviceId = DSOUND_capture_guids[wid];
1335
1336                                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
1337                                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
1338
1339                                     data.Description = wDescription;
1340                                     data.Module = wModule;
1341                                     data.Interface = wInterface;
1342                                     data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
1343                                     err = mmErr(waveInMessage((HWAVEIN)wid, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
1344                                     if (err == DS_OK && drv)
1345                                         data.Type = DIRECTSOUNDDEVICE_TYPE_VXD;
1346                                     else
1347                                         WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
1348
1349                                     TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1350                                     (ppd->Callback)(&data, ppd->Context);
1351                                 }
1352                             }
1353                             HeapFree(GetProcessHeap(),0,wInterface);
1354                         }
1355                     }
1356                     HeapFree(GetProcessHeap(),0,wDescription);
1357                     HeapFree(GetProcessHeap(),0,wModule);
1358                 }
1359             }
1360
1361             return S_OK;
1362         }
1363     }
1364
1365     if (pcbReturned) {
1366         *pcbReturned = 0;
1367         FIXME("*pcbReturned=%d\n", *pcbReturned);
1368     }
1369
1370     return E_PROP_ID_UNSUPPORTED;
1371 }
1372
1373 static HRESULT WINAPI IKsPrivatePropertySetImpl_Get(
1374     LPKSPROPERTYSET iface,
1375     REFGUID guidPropSet,
1376     ULONG dwPropID,
1377     LPVOID pInstanceData,
1378     ULONG cbInstanceData,
1379     LPVOID pPropData,
1380     ULONG cbPropData,
1381     PULONG pcbReturned )
1382 {
1383     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1384     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
1385           This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
1386
1387     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1388         switch (dwPropID) {
1389         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1390             return DSPROPERTY_WaveDeviceMappingA(pPropData,cbPropData,pcbReturned);
1391         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1392             return DSPROPERTY_Description1(pPropData,cbPropData,pcbReturned);
1393         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1394             return DSPROPERTY_Enumerate1(pPropData,cbPropData,pcbReturned);
1395         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1396             return DSPROPERTY_WaveDeviceMappingW(pPropData,cbPropData,pcbReturned);
1397         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1398             return DSPROPERTY_DescriptionA(pPropData,cbPropData,pcbReturned);
1399         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1400             return DSPROPERTY_DescriptionW(pPropData,cbPropData,pcbReturned);
1401         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1402             return DSPROPERTY_EnumerateA(pPropData,cbPropData,pcbReturned);
1403         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1404             return DSPROPERTY_EnumerateW(pPropData,cbPropData,pcbReturned);
1405         default:
1406             FIXME("unsupported ID: %d\n",dwPropID);
1407             break;
1408         }
1409     } else {
1410         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1411     }
1412
1413     if (pcbReturned) {
1414         *pcbReturned = 0;
1415         FIXME("*pcbReturned=%d\n", *pcbReturned);
1416     }
1417
1418     return E_PROP_ID_UNSUPPORTED;
1419 }
1420
1421 static HRESULT WINAPI IKsPrivatePropertySetImpl_Set(
1422     LPKSPROPERTYSET iface,
1423     REFGUID guidPropSet,
1424     ULONG dwPropID,
1425     LPVOID pInstanceData,
1426     ULONG cbInstanceData,
1427     LPVOID pPropData,
1428     ULONG cbPropData )
1429 {
1430     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1431
1432     FIXME("(%p,%s,%d,%p,%d,%p,%d), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1433     return E_PROP_ID_UNSUPPORTED;
1434 }
1435
1436 static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport(
1437     LPKSPROPERTYSET iface,
1438     REFGUID guidPropSet,
1439     ULONG dwPropID,
1440     PULONG pTypeSupport )
1441 {
1442     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1443     TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1444
1445     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1446         switch (dwPropID) {
1447         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1448             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1449             return S_OK;
1450         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1451             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1452             return S_OK;
1453         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1454             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1455             return S_OK;
1456         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1457             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1458             return S_OK;
1459         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1460             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1461             return S_OK;
1462         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1463             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1464             return S_OK;
1465         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1466             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1467             return S_OK;
1468         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1469             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1470             return S_OK;
1471         default:
1472             FIXME("unsupported ID: %d\n",dwPropID);
1473             break;
1474         }
1475     } else {
1476         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1477     }
1478
1479     return E_PROP_ID_UNSUPPORTED;
1480 }
1481
1482 static const IKsPropertySetVtbl ikspvt = {
1483     IKsPrivatePropertySetImpl_QueryInterface,
1484     IKsPrivatePropertySetImpl_AddRef,
1485     IKsPrivatePropertySetImpl_Release,
1486     IKsPrivatePropertySetImpl_Get,
1487     IKsPrivatePropertySetImpl_Set,
1488     IKsPrivatePropertySetImpl_QuerySupport
1489 };
1490
1491 HRESULT IKsPrivatePropertySetImpl_Create(
1492     REFIID riid,
1493     IKsPrivatePropertySetImpl **piks)
1494 {
1495     IKsPrivatePropertySetImpl *iks;
1496     TRACE("(%s, %p)\n", debugstr_guid(riid), piks);
1497
1498     if (!IsEqualIID(riid, &IID_IUnknown) &&
1499         !IsEqualIID(riid, &IID_IKsPropertySet)) {
1500         *piks = 0;
1501         return E_NOINTERFACE;
1502     }
1503
1504     iks = HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
1505     iks->ref = 1;
1506     iks->lpVtbl = &ikspvt;
1507
1508     *piks = iks;
1509     return S_OK;
1510 }