Added support for alternate data formats.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include <assert.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/fcntl.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>       /* Insomnia - pow() function */
34
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
37 #include "windef.h"
38 #include "winbase.h"
39 #include "wingdi.h"
40 #include "winuser.h"
41 #include "winerror.h"
42 #include "mmsystem.h"
43 #include "winreg.h"
44 #include "winternl.h"
45 #include "winnls.h"
46 #include "mmddk.h"
47 #include "wine/windef16.h"
48 #include "wine/debug.h"
49 #include "dsound.h"
50 #include "dsdriver.h"
51 #include "dsound_private.h"
52 #include "initguid.h"
53 #include "dsconf.h"
54
55 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
56
57
58 /*******************************************************************************
59  *              IKsBufferPropertySet
60  */
61
62 /* IUnknown methods */
63 static HRESULT WINAPI IKsBufferPropertySetImpl_QueryInterface(
64     LPKSPROPERTYSET iface,
65     REFIID riid,
66     LPVOID *ppobj )
67 {
68     ICOM_THIS(IKsBufferPropertySetImpl,iface);
69     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
70
71     return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
72 }
73
74 static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface)
75 {
76     ICOM_THIS(IKsBufferPropertySetImpl,iface);
77     ULONG ulReturn;
78
79     TRACE("(%p) ref was %ld\n", This, This->ref);
80     ulReturn = InterlockedIncrement(&(This->ref));
81     return ulReturn;
82 }
83
84 static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
85 {
86     ICOM_THIS(IKsBufferPropertySetImpl,iface);
87     ULONG ulReturn;
88
89     TRACE("(%p) ref was %ld\n", This, This->ref);
90     ulReturn = InterlockedDecrement(&This->ref);
91     if (!ulReturn) {
92         This->dsb->iks = 0;
93         IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
94         HeapFree(GetProcessHeap(),0,This);
95         TRACE("(%p) released\n",This);
96     }
97     return ulReturn;
98 }
99
100 static HRESULT WINAPI IKsBufferPropertySetImpl_Get(
101     LPKSPROPERTYSET iface,
102     REFGUID guidPropSet,
103     ULONG dwPropID,
104     LPVOID pInstanceData,
105     ULONG cbInstanceData,
106     LPVOID pPropData,
107     ULONG cbPropData,
108     PULONG pcbReturned )
109 {
110     ICOM_THIS(IKsBufferPropertySetImpl,iface);
111     PIDSDRIVERPROPERTYSET ps;
112     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
113         This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
114
115     IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
116
117     if (ps) {
118         DSPROPERTY prop;
119         HRESULT hres;
120
121         prop.s.Set = *guidPropSet;
122         prop.s.Id = dwPropID;
123         prop.s.Flags = 0;       /* unused */
124         prop.s.InstanceId = (ULONG)This->dsb->dsound;
125
126         hres = IDsDriverPropertySet_Get(ps, &prop, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned);
127
128         IDsDriverPropertySet_Release(ps);
129
130         return hres;
131     }
132
133     return E_PROP_ID_UNSUPPORTED;
134 }
135
136 static HRESULT WINAPI IKsBufferPropertySetImpl_Set(
137     LPKSPROPERTYSET iface,
138     REFGUID guidPropSet,
139     ULONG dwPropID,
140     LPVOID pInstanceData,
141     ULONG cbInstanceData,
142     LPVOID pPropData,
143     ULONG cbPropData )
144 {
145     ICOM_THIS(IKsBufferPropertySetImpl,iface);
146     PIDSDRIVERPROPERTYSET ps;
147     TRACE("(%p,%s,%ld,%p,%ld,%p,%ld)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
148
149     IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
150
151     if (ps) {
152         DSPROPERTY prop;
153         HRESULT hres;
154
155         prop.s.Set = *guidPropSet;
156         prop.s.Id = dwPropID;
157         prop.s.Flags = 0;       /* unused */
158         prop.s.InstanceId = (ULONG)This->dsb->dsound;
159         hres = IDsDriverPropertySet_Set(ps,&prop,pInstanceData,cbInstanceData,pPropData,cbPropData);
160
161         IDsDriverPropertySet_Release(ps);
162
163         return hres;
164     }
165
166     return E_PROP_ID_UNSUPPORTED;
167 }
168
169 static HRESULT WINAPI IKsBufferPropertySetImpl_QuerySupport(
170     LPKSPROPERTYSET iface,
171     REFGUID guidPropSet,
172     ULONG dwPropID,
173     PULONG pTypeSupport )
174 {
175     ICOM_THIS(IKsBufferPropertySetImpl,iface);
176     PIDSDRIVERPROPERTYSET ps;
177     TRACE("(%p,%s,%ld,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
178
179     IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
180
181     if (ps) {
182         HRESULT hres;
183
184         hres = IDsDriverPropertySet_QuerySupport(ps,guidPropSet, dwPropID,pTypeSupport);
185
186         IDsDriverPropertySet_Release(ps);
187
188         return hres;
189     }
190
191     return E_PROP_ID_UNSUPPORTED;
192 }
193
194 static IKsPropertySetVtbl iksbvt = {
195     IKsBufferPropertySetImpl_QueryInterface,
196     IKsBufferPropertySetImpl_AddRef,
197     IKsBufferPropertySetImpl_Release,
198     IKsBufferPropertySetImpl_Get,
199     IKsBufferPropertySetImpl_Set,
200     IKsBufferPropertySetImpl_QuerySupport
201 };
202
203 HRESULT WINAPI IKsBufferPropertySetImpl_Create(
204     IDirectSoundBufferImpl *dsb,
205     IKsBufferPropertySetImpl **piks)
206 {
207     IKsBufferPropertySetImpl *iks;
208     TRACE("(%p,%p)\n",dsb,piks);
209
210     iks = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*iks));
211     iks->ref = 0;
212     iks->dsb = dsb;
213     dsb->iks = iks;
214     iks->lpVtbl = &iksbvt;
215
216     IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
217
218     *piks = iks;
219     return S_OK;
220 }
221
222 HRESULT WINAPI IKsBufferPropertySetImpl_Destroy(
223     IKsBufferPropertySetImpl *piks)
224 {
225     TRACE("(%p)\n",piks);
226
227     while (IKsBufferPropertySetImpl_Release((LPKSPROPERTYSET)piks) > 0);
228
229     return S_OK;
230 }
231
232 /*******************************************************************************
233  *              IKsPrivatePropertySet
234  */
235
236 /* IUnknown methods */
237 static HRESULT WINAPI IKsPrivatePropertySetImpl_QueryInterface(
238     LPKSPROPERTYSET iface,
239     REFIID riid,
240     LPVOID *ppobj )
241 {
242     ICOM_THIS(IKsPrivatePropertySetImpl,iface);
243     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
244
245     *ppobj = NULL;
246     return DSERR_INVALIDPARAM;
247 }
248
249 static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface)
250 {
251     ICOM_THIS(IKsPrivatePropertySetImpl,iface);
252     ULONG ulReturn;
253
254     TRACE("(%p) ref was %ld\n", This, This->ref);
255     ulReturn = InterlockedIncrement(&This->ref);
256     return ulReturn;
257 }
258
259 static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface)
260 {
261     ICOM_THIS(IKsPrivatePropertySetImpl,iface);
262     ULONG ulReturn;
263
264     TRACE("(%p) ref was %ld\n", This, This->ref);
265     ulReturn = InterlockedDecrement(&This->ref);
266     return ulReturn;
267 }
268
269 static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingA(
270     REFGUID guidPropSet,
271     LPVOID pPropData,
272     ULONG cbPropData,
273     PULONG pcbReturned )
274 {
275     PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA ppd;
276     FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) not implemented!\n",
277         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
278
279     ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA) pPropData;
280
281     if (!ppd) {
282         WARN("invalid parameter: pPropData\n");
283         return DSERR_INVALIDPARAM;
284     }
285
286     FIXME("DeviceName=%s\n",ppd->DeviceName);
287     FIXME("DataFlow=%s\n",
288         ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER ? "DIRECTSOUNDDEVICE_DATAFLOW_RENDER" :
289         ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE ? "DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE" : "UNKNOWN");
290
291     /* FIXME: match the name to a wave device somehow. */
292     ppd->DeviceId = GUID_NULL;
293
294     if (pcbReturned) {
295         *pcbReturned = cbPropData;
296         FIXME("*pcbReturned=%ld\n", *pcbReturned);
297     }
298
299     return S_OK;
300 }
301
302 static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingW(
303     REFGUID guidPropSet,
304     LPVOID pPropData,
305     ULONG cbPropData,
306     PULONG pcbReturned )
307 {
308     PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd;
309     FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) not implemented!\n",
310         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
311
312     ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA) pPropData;
313
314     if (!ppd) {
315         WARN("invalid parameter: pPropData\n");
316         return DSERR_INVALIDPARAM;
317     }
318
319     FIXME("DeviceName=%s\n",debugstr_w(ppd->DeviceName));
320     FIXME("DataFlow=%s\n",
321         ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER ? "DIRECTSOUNDDEVICE_DATAFLOW_RENDER" :
322         ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE ? "DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE" : "UNKNOWN");
323
324     /* FIXME: match the name to a wave device somehow. */
325     ppd->DeviceId = GUID_NULL;
326
327     if (pcbReturned) {
328         *pcbReturned = cbPropData;
329         FIXME("*pcbReturned=%ld\n", *pcbReturned);
330     }
331
332     return S_OK;
333 }
334
335 static HRESULT WINAPI DSPROPERTY_Description1(
336     REFGUID guidPropSet,
337     LPVOID pPropData,
338     ULONG cbPropData,
339     PULONG pcbReturned )
340 {
341     HRESULT err;
342     GUID guid, dev_guid;
343     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA ppd;
344     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
345         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
346
347     ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA) pPropData;
348
349     if (!ppd) {
350         WARN("invalid parameter: pPropData\n");
351         return DSERR_INVALIDPARAM;
352     }
353
354     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
355     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
356         /* default device of type specified by ppd->DataFlow */
357         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
358             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
359         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
360             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
361         } else {
362             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
363         }
364         FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
365             debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
366         return E_PROP_ID_UNSUPPORTED;
367     }
368
369     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
370     GetDeviceID(&ppd->DeviceId, &dev_guid);
371
372     if ( IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultPlayback) ||
373          IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultVoicePlayback) ) {
374         ULONG wod;
375         int wodn;
376         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
377         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
378         wodn = waveOutGetNumDevs();
379         for (wod = 0; wod < wodn; wod++) {
380             if (IsEqualGUID( &dev_guid, &renderer_guids[wod] ) ) {
381                 DSDRIVERDESC desc;
382                 ppd->WaveDeviceId = wod;
383                 ppd->Devnode = wod;
384                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
385                 if (err == DS_OK) {
386                     PIDSDRIVER drv = NULL;
387                     strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
388                     strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
389                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
390                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
391                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
392                     if (err == DS_OK && drv)
393                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
394                     break;
395                 } else {
396                     WARN("waveOutMessage failed\n");
397                     return E_PROP_ID_UNSUPPORTED;
398                 }
399             }
400         }
401     } else if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
402                 IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
403         ULONG wid;
404         int widn;
405         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
406         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
407         widn = waveInGetNumDevs();
408         for (wid = 0; wid < widn; wid++) {
409             if (IsEqualGUID( &dev_guid, &guid) ) {
410                 DSDRIVERDESC desc;
411                 ppd->WaveDeviceId = wid;
412                 ppd->Devnode = wid;
413                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
414                 if (err == DS_OK) {
415                     PIDSCDRIVER drv;
416                     strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
417                     strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
418                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
419                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
420                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
421                     if (err == DS_OK && drv)
422                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
423                     break;
424                 } else {
425                     WARN("waveInMessage failed\n");
426                     return E_PROP_ID_UNSUPPORTED;
427                 }
428             }
429         }
430     } else {
431         BOOL found = FALSE;
432         ULONG wod;
433         int wodn;
434         /* given specific device so try the render devices first */
435         wodn = waveOutGetNumDevs();
436         for (wod = 0; wod < wodn; wod++) {
437             if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
438                 DSDRIVERDESC desc;
439                 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
440                 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
441                 ppd->WaveDeviceId = wod;
442                 ppd->Devnode = wod;
443                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
444                 if (err == DS_OK) {
445                     PIDSDRIVER drv = NULL;
446                     strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
447                     strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
448                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
449                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
450                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
451                     if (err == DS_OK && drv)
452                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
453                     found = TRUE;
454                     break;
455                 } else {
456                     WARN("waveOutMessage failed\n");
457                     return E_PROP_ID_UNSUPPORTED;
458                 }
459             }
460         }
461
462         if (found == FALSE) {
463             ULONG wid;
464             int widn;
465             /* given specific device so try the capture devices next */
466             widn = waveInGetNumDevs();
467             for (wid = 0; wid < widn; wid++) {
468                 if (IsEqualGUID( &ppd->DeviceId, &capture_guids[wid] ) ) {
469                     DSDRIVERDESC desc;
470                     TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
471                     ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
472                     ppd->WaveDeviceId = wid;
473                     ppd->Devnode = wid;
474                     err = mmErr(waveInMessage((HWAVEIN)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
475                     if (err == DS_OK) {
476                         PIDSDRIVER drv = NULL;
477                         strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
478                         strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
479                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
480                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
481                         err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
482                         if (err == DS_OK && drv)
483                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
484                         found = TRUE;
485                         break;
486                     } else {
487                         WARN("waveInMessage failed\n");
488                         return E_PROP_ID_UNSUPPORTED;
489                     }
490                 }
491             }
492
493             if (found == FALSE) {
494                 WARN("device not found\n");
495                 return E_PROP_ID_UNSUPPORTED;
496             }
497         }
498     }
499
500     if (pcbReturned) {
501         *pcbReturned = cbPropData;
502         TRACE("*pcbReturned=%ld\n", *pcbReturned);
503     }
504
505     return S_OK;
506 }
507
508 static HRESULT WINAPI DSPROPERTY_DescriptionA(
509     REFGUID guidPropSet,
510     LPVOID pPropData,
511     ULONG cbPropData,
512     PULONG pcbReturned )
513 {
514     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA) pPropData;
515     HRESULT err;
516     GUID dev_guid;
517     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
518         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
519
520     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
521     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
522         /* default device of type specified by ppd->DataFlow */
523         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
524             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
525         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
526             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
527         } else {
528             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
529         }
530         FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
531             debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
532         return E_PROP_ID_UNSUPPORTED;
533     }
534
535     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
536     GetDeviceID(&ppd->DeviceId, &dev_guid);
537
538     if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
539          IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
540         ULONG wod;
541         int wodn;
542         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
543         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
544         wodn = waveOutGetNumDevs();
545         for (wod = 0; wod < wodn; wod++) {
546                 if (IsEqualGUID( &dev_guid, &renderer_guids[wod] ) ) {
547                     DSDRIVERDESC desc;
548                     ppd->WaveDeviceId = wod;
549                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
550                     if (err == DS_OK) {
551                         PIDSDRIVER drv = NULL;
552                         /* FIXME: this is a memory leak */
553                         CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
554                         CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvName) + 1);
555                         CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
556
557                         strcpy(szDescription, desc.szDesc);
558                         strcpy(szModule, desc.szDrvName);
559                         strcpy(szInterface, "Interface");
560
561                         ppd->Description = szDescription;
562                         ppd->Module = szModule;
563                         ppd->Interface = szInterface;
564                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
565                         if (err == DS_OK && drv)
566                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
567                         break;
568                     } else {
569                         WARN("waveOutMessage failed\n");
570                         return E_PROP_ID_UNSUPPORTED;
571                     }
572                 }
573         }
574     } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
575                IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
576         ULONG wid;
577         int widn;
578         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
579         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
580         widn = waveInGetNumDevs();
581         for (wid = 0; wid < widn; wid++) {
582                 if (IsEqualGUID( &dev_guid, &capture_guids[wid] ) ) {
583                     DSDRIVERDESC desc;
584                     ppd->WaveDeviceId = wid;
585                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
586                     if (err == DS_OK) {
587                         PIDSCDRIVER drv;
588                         /* FIXME: this is a memory leak */
589                         CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
590                         CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvName) + 1);
591                         CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
592
593                         strcpy(szDescription, desc.szDesc);
594                         strcpy(szModule, desc.szDrvName);
595                         strcpy(szInterface, "Interface");
596
597                         ppd->Description = szDescription;
598                         ppd->Module = szModule;
599                         ppd->Interface = szInterface;
600                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
601                         if (err == DS_OK && drv)
602                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
603                         break;
604                     } else {
605                         WARN("waveInMessage failed\n");
606                         return E_PROP_ID_UNSUPPORTED;
607                     }
608                     break;
609                 }
610         }
611     } else {
612         BOOL found = FALSE;
613         ULONG wod;
614         int wodn;
615         /* given specific device so try the render devices first */
616         wodn = waveOutGetNumDevs();
617         for (wod = 0; wod < wodn; wod++) {
618                 if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
619                     DSDRIVERDESC desc;
620                     TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
621                     ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
622                     ppd->WaveDeviceId = wod;
623                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
624                     if (err == DS_OK) {
625                         PIDSDRIVER drv = NULL;
626                         /* FIXME: this is a memory leak */
627                         CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
628                         CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvName) + 1);
629                         CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
630
631                         strcpy(szDescription, desc.szDesc);
632                         strcpy(szModule, desc.szDrvName);
633                         strcpy(szInterface, "Interface");
634
635                         ppd->Description = szDescription;
636                         ppd->Module = szModule;
637                         ppd->Interface = szInterface;
638                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
639                         if (err == DS_OK && drv)
640                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
641                         found = TRUE;
642                         break;
643                     } else {
644                         WARN("waveOutMessage failed\n");
645                         return E_PROP_ID_UNSUPPORTED;
646                     }
647                 }
648         }
649
650         if (found == FALSE) {
651             WARN("device not found\n");
652             return E_PROP_ID_UNSUPPORTED;
653         }
654     }
655
656     if (pcbReturned) {
657         *pcbReturned = cbPropData;
658         TRACE("*pcbReturned=%ld\n", *pcbReturned);
659     }
660
661     return S_OK;
662 }
663
664 static HRESULT WINAPI DSPROPERTY_DescriptionW(
665     REFGUID guidPropSet,
666     LPVOID pPropData,
667     ULONG cbPropData,
668     PULONG pcbReturned )
669 {
670     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA) pPropData;
671     HRESULT err;
672     GUID dev_guid;
673     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
674         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
675
676     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
677     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
678         /* default device of type specified by ppd->DataFlow */
679         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
680             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
681         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
682             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
683         } else {
684             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
685         }
686         FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
687             debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
688         return E_PROP_ID_UNSUPPORTED;
689     }
690
691     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
692     GetDeviceID(&ppd->DeviceId, &dev_guid);
693
694     if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
695          IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
696         ULONG wod;
697         int wodn;
698         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
699         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
700         wodn = waveOutGetNumDevs();
701         for (wod = 0; wod < wodn; wod++) {
702                 if (IsEqualGUID( &dev_guid, &renderer_guids[wod] ) ) {
703                     DSDRIVERDESC desc;
704                     ppd->WaveDeviceId = wod;
705                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
706                     if (err == DS_OK) {
707                         PIDSDRIVER drv = NULL;
708                         /* FIXME: this is a memory leak */
709                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
710                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
711                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
712
713                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
714                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
715                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
716
717                         ppd->Description = wDescription;
718                         ppd->Module = wModule;
719                         ppd->Interface = wInterface;
720                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
721                         if (err == DS_OK && drv)
722                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
723                             break;
724                     } else {
725                         WARN("waveOutMessage failed\n");
726                         return E_PROP_ID_UNSUPPORTED;
727                     }
728                 }
729         }
730     } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
731                IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
732         ULONG wid;
733         int widn;
734         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
735         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
736         widn = waveInGetNumDevs();
737         for (wid = 0; wid < widn; wid++) {
738                 if (IsEqualGUID( &dev_guid, &capture_guids[wid] ) ) {
739                     DSDRIVERDESC desc;
740                     ppd->WaveDeviceId = wid;
741                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
742                     if (err == DS_OK) {
743                         PIDSCDRIVER drv;
744                         /* FIXME: this is a memory leak */
745                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
746                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
747                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
748
749                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
750                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
751                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
752
753                         ppd->Description = wDescription;
754                         ppd->Module = wModule;
755                         ppd->Interface = wInterface;
756                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
757                         if (err == DS_OK && drv)
758                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
759                         break;
760                     } else {
761                         WARN("waveInMessage failed\n");
762                         return E_PROP_ID_UNSUPPORTED;
763                     }
764                     break;
765                 }
766         }
767     } else {
768         BOOL found = FALSE;
769         ULONG wod;
770         int wodn;
771         /* given specific device so try the render devices first */
772         wodn = waveOutGetNumDevs();
773         for (wod = 0; wod < wodn; wod++) {
774                 if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
775                     DSDRIVERDESC desc;
776                     TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
777                     ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
778                     ppd->WaveDeviceId = wod;
779                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
780                     if (err == DS_OK) {
781                         PIDSDRIVER drv = NULL;
782                         /* FIXME: this is a memory leak */
783                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
784                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
785                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
786
787                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
788                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
789                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
790
791                         ppd->Description = wDescription;
792                         ppd->Module = wModule;
793                         ppd->Interface = wInterface;
794                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
795                         if (err == DS_OK && drv)
796                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
797                         found = TRUE;
798                         break;
799                     } else {
800                         WARN("waveOutMessage failed\n");
801                         return E_PROP_ID_UNSUPPORTED;
802                     }
803                 }
804         }
805
806         if (found == FALSE) {
807             WARN("device not found\n");
808             return E_PROP_ID_UNSUPPORTED;
809         }
810     }
811
812     if (pcbReturned) {
813         *pcbReturned = cbPropData;
814         TRACE("*pcbReturned=%ld\n", *pcbReturned);
815     }
816
817     return S_OK;
818 }
819
820 static HRESULT WINAPI DSPROPERTY_Enumerate1(
821     REFGUID guidPropSet,
822     LPVOID pPropData,
823     ULONG cbPropData,
824     PULONG pcbReturned )
825 {
826     FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
827         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
828     return E_PROP_ID_UNSUPPORTED;
829 }
830
831 static HRESULT WINAPI DSPROPERTY_EnumerateA(
832     REFGUID guidPropSet,
833     LPVOID pPropData,
834     ULONG cbPropData,
835     PULONG pcbReturned )
836 {
837     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA) pPropData;
838     HRESULT err;
839     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
840         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
841
842     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
843         if (ppd) {
844             if (ppd->Callback) {
845                 unsigned devs, wod, wid;
846                 DSDRIVERDESC desc;
847                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA data;
848
849                 devs = waveOutGetNumDevs();
850                 for (wod = 0; wod < devs; ++wod) {
851                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
852                     if (err == DS_OK) {
853                         memset(&data, 0, sizeof(data));
854                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
855                         data.WaveDeviceId = wod;
856                         data.DeviceId = renderer_guids[wod];
857                         data.Description = desc.szDesc;
858                         data.Module = desc.szDrvName;
859                         data.Interface = "Interface";
860                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
861                         (ppd->Callback)(&data, ppd->Context);
862                     }
863                 }
864
865                 devs = waveInGetNumDevs();
866                 for (wid = 0; wid < devs; ++wid) {
867                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
868                     if (err == DS_OK) {
869                         memset(&data, 0, sizeof(data));
870                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
871                         data.WaveDeviceId = wid;
872                         data.DeviceId = capture_guids[wid];
873                         data.Description = desc.szDesc;
874                         data.Module = desc.szDrvName;
875                         data.Interface = "Interface";
876                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
877                         (ppd->Callback)(&data, ppd->Context);
878                     }
879                 }
880
881                 return S_OK;
882             }
883         }
884     } else {
885         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
886     }
887
888     if (pcbReturned) {
889         *pcbReturned = 0;
890         FIXME("*pcbReturned=%ld\n", *pcbReturned);
891     }
892
893     return E_PROP_ID_UNSUPPORTED;
894 }
895
896 static HRESULT WINAPI DSPROPERTY_EnumerateW(
897     REFGUID guidPropSet,
898     LPVOID pPropData,
899     ULONG cbPropData,
900     PULONG pcbReturned )
901 {
902     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA) pPropData;
903     HRESULT err;
904     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
905         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
906
907     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
908         if (ppd) {
909             if (ppd->Callback) {
910                 unsigned devs, wod, wid;
911                 DSDRIVERDESC desc;
912                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
913
914                 devs = waveOutGetNumDevs();
915                 for (wod = 0; wod < devs; ++wod) {
916                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
917                     if (err == DS_OK) {
918                         /* FIXME: this is a memory leak */
919                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
920                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
921                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
922
923                         memset(&data, 0, sizeof(data));
924                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
925                         data.WaveDeviceId = wod;
926                         data.DeviceId = renderer_guids[wod];
927
928                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
929                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
930                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
931
932                         data.Description = wDescription;
933                         data.Module = wModule;
934                         data.Interface = wInterface;
935                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
936                         (ppd->Callback)(&data, ppd->Context);
937                     }
938                 }
939
940                 devs = waveInGetNumDevs();
941                 for (wid = 0; wid < devs; ++wid) {
942                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
943                     if (err == DS_OK) {
944                         /* FIXME: this is a memory leak */
945                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
946                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
947                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
948
949                         memset(&data, 0, sizeof(data));
950                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
951                         data.WaveDeviceId = wid;
952                         data.DeviceId = capture_guids[wid];
953
954                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
955                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
956                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
957
958                         data.Description = wDescription;
959                         data.Module = wModule;
960                         data.Interface = wInterface;
961                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
962                         (ppd->Callback)(&data, ppd->Context);
963                     }
964                 }
965
966                 return S_OK;
967             }
968         }
969     } else {
970         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
971     }
972
973     if (pcbReturned) {
974         *pcbReturned = 0;
975         FIXME("*pcbReturned=%ld\n", *pcbReturned);
976     }
977
978     return E_PROP_ID_UNSUPPORTED;
979 }
980
981 static HRESULT WINAPI IKsPrivatePropertySetImpl_Get(
982     LPKSPROPERTYSET iface,
983     REFGUID guidPropSet,
984     ULONG dwPropID,
985     LPVOID pInstanceData,
986     ULONG cbInstanceData,
987     LPVOID pPropData,
988     ULONG cbPropData,
989     PULONG pcbReturned
990 ) {
991     ICOM_THIS(IKsPrivatePropertySetImpl,iface);
992     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
993         This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
994
995     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
996         switch (dwPropID) {
997         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
998             return DSPROPERTY_WaveDeviceMappingA(guidPropSet,pPropData,cbPropData,pcbReturned);
999         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1000             return DSPROPERTY_Description1(guidPropSet,pPropData,cbPropData,pcbReturned);
1001         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1002             return DSPROPERTY_Enumerate1(guidPropSet,pPropData,cbPropData,pcbReturned);
1003         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1004             return DSPROPERTY_WaveDeviceMappingW(guidPropSet,pPropData,cbPropData,pcbReturned);
1005         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1006             return DSPROPERTY_DescriptionA(guidPropSet,pPropData,cbPropData,pcbReturned);
1007         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1008             return DSPROPERTY_DescriptionW(guidPropSet,pPropData,cbPropData,pcbReturned);
1009         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1010             return DSPROPERTY_EnumerateA(guidPropSet,pPropData,cbPropData,pcbReturned);
1011         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1012             return DSPROPERTY_EnumerateW(guidPropSet,pPropData,cbPropData,pcbReturned);
1013         default:
1014             FIXME("unsupported ID: %ld\n",dwPropID);
1015             break;
1016         }
1017     } else {
1018         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1019     }
1020
1021     if (pcbReturned) {
1022         *pcbReturned = 0;
1023         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1024     }
1025
1026     return E_PROP_ID_UNSUPPORTED;
1027 }
1028
1029 static HRESULT WINAPI IKsPrivatePropertySetImpl_Set(
1030     LPKSPROPERTYSET iface,
1031     REFGUID guidPropSet,
1032     ULONG dwPropID,
1033     LPVOID pInstanceData,
1034     ULONG cbInstanceData,
1035     LPVOID pPropData,
1036     ULONG cbPropData )
1037 {
1038     ICOM_THIS(IKsPrivatePropertySetImpl,iface);
1039
1040     FIXME("(%p,%s,%ld,%p,%ld,%p,%ld), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1041     return E_PROP_ID_UNSUPPORTED;
1042 }
1043
1044 static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport(
1045     LPKSPROPERTYSET iface,
1046     REFGUID guidPropSet,
1047     ULONG dwPropID,
1048     PULONG pTypeSupport )
1049 {
1050     ICOM_THIS(IKsPrivatePropertySetImpl,iface);
1051     TRACE("(%p,%s,%ld,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1052
1053     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1054         switch (dwPropID) {
1055         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1056             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1057             return S_OK;
1058         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1059             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1060             return S_OK;
1061         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1062             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1063             return S_OK;
1064         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1065             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1066             return S_OK;
1067         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1068             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1069             return S_OK;
1070         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1071             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1072             return S_OK;
1073         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1074             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1075             return S_OK;
1076         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1077             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1078             return S_OK;
1079         default:
1080             FIXME("unsupported ID: %ld\n",dwPropID);
1081             break;
1082         }
1083     } else {
1084         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1085     }
1086
1087     return E_PROP_ID_UNSUPPORTED;
1088 }
1089
1090 static IKsPropertySetVtbl ikspvt = {
1091     IKsPrivatePropertySetImpl_QueryInterface,
1092     IKsPrivatePropertySetImpl_AddRef,
1093     IKsPrivatePropertySetImpl_Release,
1094     IKsPrivatePropertySetImpl_Get,
1095     IKsPrivatePropertySetImpl_Set,
1096     IKsPrivatePropertySetImpl_QuerySupport
1097 };
1098
1099 HRESULT WINAPI IKsPrivatePropertySetImpl_Create(
1100     IKsPrivatePropertySetImpl **piks)
1101 {
1102     IKsPrivatePropertySetImpl *iks;
1103
1104     iks = HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
1105     iks->ref = 0;
1106     iks->lpVtbl = &ikspvt;
1107
1108     *piks = iks;
1109     return S_OK;
1110 }