Added parser template and made AVISplitter use it.
[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 <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "mmsystem.h"
27 #include "winreg.h"
28 #include "winternl.h"
29 #include "winnls.h"
30 #include "vfwmsgs.h"
31 #include "mmddk.h"
32 #include "wine/debug.h"
33 #include "dsound.h"
34 #include "dsdriver.h"
35 #include "dsound_private.h"
36 #include "initguid.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     TRACE("(%p) ref was %ld\n", This, This->ref);
68     return InterlockedIncrement(&(This->ref));
69 }
70
71 static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
72 {
73     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
74     ULONG ulReturn;
75
76     TRACE("(%p) ref was %ld\n", This, This->ref);
77     ulReturn = InterlockedDecrement(&(This->ref));
78     if (!ulReturn) {
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 ulReturn;
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=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,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->dsound;
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,%ld,%p,%ld,%p,%ld)\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->dsound;
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,%ld,%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 IKsPropertySetVtbl iksbvt = {
188     IKsBufferPropertySetImpl_QueryInterface,
189     IKsBufferPropertySetImpl_AddRef,
190     IKsBufferPropertySetImpl_Release,
191     IKsBufferPropertySetImpl_Get,
192     IKsBufferPropertySetImpl_Set,
193     IKsBufferPropertySetImpl_QuerySupport
194 };
195
196 HRESULT WINAPI 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 WINAPI 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     *ppobj = NULL;
245     return DSERR_INVALIDPARAM;
246 }
247
248 static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface)
249 {
250     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
251     TRACE("(%p) ref was %ld\n", This, This->ref);
252     return InterlockedIncrement(&(This->ref));
253 }
254
255 static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface)
256 {
257     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
258     ULONG ulReturn;
259
260     TRACE("(%p) ref was %ld\n", This, This->ref);
261     ulReturn = InterlockedDecrement(&(This->ref));
262     if (ulReturn == 0) {
263         HeapFree(GetProcessHeap(),0,This);
264         TRACE("(%p) released\n",This);
265     }
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         unsigned 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         unsigned 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         unsigned 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             unsigned 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         unsigned 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         unsigned 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                 }
609         }
610     } else {
611         BOOL found = FALSE;
612         ULONG wod;
613         unsigned int wodn;
614         /* given specific device so try the render devices first */
615         wodn = waveOutGetNumDevs();
616         for (wod = 0; wod < wodn; wod++) {
617                 if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
618                     DSDRIVERDESC desc;
619                     TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
620                     ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
621                     ppd->WaveDeviceId = wod;
622                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
623                     if (err == DS_OK) {
624                         PIDSDRIVER drv = NULL;
625                         /* FIXME: this is a memory leak */
626                         CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
627                         CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
628                         CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
629
630                         strcpy(szDescription, desc.szDesc);
631                         strcpy(szModule, desc.szDrvname);
632                         strcpy(szInterface, "Interface");
633
634                         ppd->Description = szDescription;
635                         ppd->Module = szModule;
636                         ppd->Interface = szInterface;
637                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
638                         if (err == DS_OK && drv)
639                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
640                         found = TRUE;
641                         break;
642                     } else {
643                         WARN("waveOutMessage failed\n");
644                         return E_PROP_ID_UNSUPPORTED;
645                     }
646                 }
647         }
648
649         if (found == FALSE) {
650             WARN("device not found\n");
651             return E_PROP_ID_UNSUPPORTED;
652         }
653     }
654
655     if (pcbReturned) {
656         *pcbReturned = cbPropData;
657         TRACE("*pcbReturned=%ld\n", *pcbReturned);
658     }
659
660     return S_OK;
661 }
662
663 static HRESULT WINAPI DSPROPERTY_DescriptionW(
664     REFGUID guidPropSet,
665     LPVOID pPropData,
666     ULONG cbPropData,
667     PULONG pcbReturned )
668 {
669     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA) pPropData;
670     HRESULT err;
671     GUID dev_guid;
672     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
673         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
674
675     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
676     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
677         /* default device of type specified by ppd->DataFlow */
678         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
679             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
680         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
681             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
682         } else {
683             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
684         }
685         FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
686             debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
687         return E_PROP_ID_UNSUPPORTED;
688     }
689
690     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
691     GetDeviceID(&ppd->DeviceId, &dev_guid);
692
693     if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
694          IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
695         ULONG wod;
696         unsigned int wodn;
697         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
698         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
699         wodn = waveOutGetNumDevs();
700         for (wod = 0; wod < wodn; wod++) {
701                 if (IsEqualGUID( &dev_guid, &renderer_guids[wod] ) ) {
702                     DSDRIVERDESC desc;
703                     ppd->WaveDeviceId = wod;
704                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
705                     if (err == DS_OK) {
706                         PIDSDRIVER drv = NULL;
707                         /* FIXME: this is a memory leak */
708                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
709                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
710                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
711
712                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
713                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
714                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
715
716                         ppd->Description = wDescription;
717                         ppd->Module = wModule;
718                         ppd->Interface = wInterface;
719                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
720                         if (err == DS_OK && drv)
721                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
722                             break;
723                     } else {
724                         WARN("waveOutMessage failed\n");
725                         return E_PROP_ID_UNSUPPORTED;
726                     }
727                 }
728         }
729     } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
730                IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
731         ULONG wid;
732         unsigned int widn;
733         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
734         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
735         widn = waveInGetNumDevs();
736         for (wid = 0; wid < widn; wid++) {
737                 if (IsEqualGUID( &dev_guid, &capture_guids[wid] ) ) {
738                     DSDRIVERDESC desc;
739                     ppd->WaveDeviceId = wid;
740                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
741                     if (err == DS_OK) {
742                         PIDSCDRIVER drv;
743                         /* FIXME: this is a memory leak */
744                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
745                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
746                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
747
748                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
749                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
750                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
751
752                         ppd->Description = wDescription;
753                         ppd->Module = wModule;
754                         ppd->Interface = wInterface;
755                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
756                         if (err == DS_OK && drv)
757                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
758                         break;
759                     } else {
760                         WARN("waveInMessage failed\n");
761                         return E_PROP_ID_UNSUPPORTED;
762                     }
763                 }
764         }
765     } else {
766         BOOL found = FALSE;
767         ULONG wod;
768         unsigned int wodn;
769         /* given specific device so try the render devices first */
770         wodn = waveOutGetNumDevs();
771         for (wod = 0; wod < wodn; wod++) {
772                 if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
773                     DSDRIVERDESC desc;
774                     TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
775                     ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
776                     ppd->WaveDeviceId = wod;
777                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
778                     if (err == DS_OK) {
779                         PIDSDRIVER drv = NULL;
780                         /* FIXME: this is a memory leak */
781                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
782                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
783                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
784
785                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
786                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
787                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
788
789                         ppd->Description = wDescription;
790                         ppd->Module = wModule;
791                         ppd->Interface = wInterface;
792                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
793                         if (err == DS_OK && drv)
794                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
795                         found = TRUE;
796                         break;
797                     } else {
798                         WARN("waveOutMessage failed\n");
799                         return E_PROP_ID_UNSUPPORTED;
800                     }
801                 }
802         }
803
804         if (found == FALSE) {
805             WARN("device not found\n");
806             return E_PROP_ID_UNSUPPORTED;
807         }
808     }
809
810     if (pcbReturned) {
811         *pcbReturned = cbPropData;
812         TRACE("*pcbReturned=%ld\n", *pcbReturned);
813     }
814
815     return S_OK;
816 }
817
818 static HRESULT WINAPI DSPROPERTY_Enumerate1(
819     REFGUID guidPropSet,
820     LPVOID pPropData,
821     ULONG cbPropData,
822     PULONG pcbReturned )
823 {
824     FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
825         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
826     return E_PROP_ID_UNSUPPORTED;
827 }
828
829 static HRESULT WINAPI DSPROPERTY_EnumerateA(
830     REFGUID guidPropSet,
831     LPVOID pPropData,
832     ULONG cbPropData,
833     PULONG pcbReturned )
834 {
835     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA) pPropData;
836     HRESULT err;
837     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
838         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
839
840     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
841         if (ppd) {
842             if (ppd->Callback) {
843                 unsigned devs, wod, wid;
844                 DSDRIVERDESC desc;
845                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA data;
846
847                 devs = waveOutGetNumDevs();
848                 for (wod = 0; wod < devs; ++wod) {
849                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
850                     if (err == DS_OK) {
851                         DWORD size;
852                         ZeroMemory(&data, sizeof(data));
853                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
854                         data.WaveDeviceId = wod;
855                         data.DeviceId = renderer_guids[wod];
856                         data.Description = desc.szDesc;
857                         data.Module = desc.szDrvname;
858                         err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0));
859                         if (err == DS_OK) {
860                             WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size);
861                             err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size));
862                             if (err == DS_OK) {
863                                 CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR));
864                                 WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL );
865                                 data.Interface = szInterface;
866
867                                 TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
868                                 (ppd->Callback)(&data, ppd->Context);
869
870                                 HeapFree(GetProcessHeap(),0,szInterface);
871                             }
872                             HeapFree(GetProcessHeap(),0,nameW);
873                         }
874                     }
875                 }
876
877                 devs = waveInGetNumDevs();
878                 for (wid = 0; wid < devs; ++wid) {
879                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
880                     if (err == DS_OK) {
881                         DWORD size;
882                         ZeroMemory(&data, sizeof(data));
883                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
884                         data.WaveDeviceId = wid;
885                         data.DeviceId = capture_guids[wid];
886                         data.Description = desc.szDesc;
887                         data.Module = desc.szDrvname;
888                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0));
889                         if (err == DS_OK) {
890                             WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size);
891                             err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size));
892                             if (err == DS_OK) {
893                                 CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR));
894                                 WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL );
895                                 data.Interface = szInterface;
896
897                                 TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
898                                 (ppd->Callback)(&data, ppd->Context);
899
900                                 HeapFree(GetProcessHeap(),0,szInterface);
901                             }
902                             HeapFree(GetProcessHeap(),0,nameW);
903                         }
904                     }
905                 }
906
907                 return S_OK;
908             }
909         }
910     } else {
911         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
912     }
913
914     if (pcbReturned) {
915         *pcbReturned = 0;
916         FIXME("*pcbReturned=%ld\n", *pcbReturned);
917     }
918
919     return E_PROP_ID_UNSUPPORTED;
920 }
921
922 static HRESULT WINAPI DSPROPERTY_EnumerateW(
923     REFGUID guidPropSet,
924     LPVOID pPropData,
925     ULONG cbPropData,
926     PULONG pcbReturned )
927 {
928     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA) pPropData;
929     HRESULT err;
930     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
931         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
932
933     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
934         if (ppd) {
935             if (ppd->Callback) {
936                 unsigned devs, wod, wid;
937                 DSDRIVERDESC desc;
938                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
939
940                 devs = waveOutGetNumDevs();
941                 for (wod = 0; wod < devs; ++wod) {
942                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
943                     if (err == DS_OK) {
944                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
945                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
946                         DWORD size;
947                         err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0));
948                         if (err == DS_OK) {
949                             WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size);
950                             err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size));
951                             if (err == DS_OK) {
952                                 ZeroMemory(&data, sizeof(data));
953                                 data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
954                                 data.WaveDeviceId = wod;
955                                 data.DeviceId = renderer_guids[wod];
956
957                                 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
958                                 MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
959
960                                 data.Description = wDescription;
961                                 data.Module = wModule;
962                                 data.Interface = wInterface;
963
964                                 TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
965                                 (ppd->Callback)(&data, ppd->Context);
966                             }
967                             HeapFree(GetProcessHeap(),0,wInterface);
968                         }
969                         HeapFree(GetProcessHeap(),0,wDescription);
970                         HeapFree(GetProcessHeap(),0,wModule);
971                     }
972                 }
973
974                 devs = waveInGetNumDevs();
975                 for (wid = 0; wid < devs; ++wid) {
976                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
977                     if (err == DS_OK) {
978                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
979                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
980                         DWORD size;
981                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0));
982                         if (err == DS_OK) {
983                             WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size);
984                             err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size));
985                             if (err == DS_OK) {
986                                 ZeroMemory(&data, sizeof(data));
987                                 data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
988                                 data.WaveDeviceId = wid;
989                                 data.DeviceId = capture_guids[wid];
990
991                                 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
992                                 MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
993
994                                 data.Description = wDescription;
995                                 data.Module = wModule;
996                                 data.Interface = wInterface;
997                                 TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
998                                 (ppd->Callback)(&data, ppd->Context);
999                             }
1000                             HeapFree(GetProcessHeap(),0,wInterface);
1001                         }
1002                         HeapFree(GetProcessHeap(),0,wDescription);
1003                         HeapFree(GetProcessHeap(),0,wModule);
1004                     }
1005                 }
1006
1007                 return S_OK;
1008             }
1009         }
1010     } else {
1011         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1012     }
1013
1014     if (pcbReturned) {
1015         *pcbReturned = 0;
1016         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1017     }
1018
1019     return E_PROP_ID_UNSUPPORTED;
1020 }
1021
1022 static HRESULT WINAPI IKsPrivatePropertySetImpl_Get(
1023     LPKSPROPERTYSET iface,
1024     REFGUID guidPropSet,
1025     ULONG dwPropID,
1026     LPVOID pInstanceData,
1027     ULONG cbInstanceData,
1028     LPVOID pPropData,
1029     ULONG cbPropData,
1030     PULONG pcbReturned
1031 ) {
1032     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1033     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
1034         This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
1035
1036     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1037         switch (dwPropID) {
1038         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1039             return DSPROPERTY_WaveDeviceMappingA(guidPropSet,pPropData,cbPropData,pcbReturned);
1040         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1041             return DSPROPERTY_Description1(guidPropSet,pPropData,cbPropData,pcbReturned);
1042         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1043             return DSPROPERTY_Enumerate1(guidPropSet,pPropData,cbPropData,pcbReturned);
1044         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1045             return DSPROPERTY_WaveDeviceMappingW(guidPropSet,pPropData,cbPropData,pcbReturned);
1046         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1047             return DSPROPERTY_DescriptionA(guidPropSet,pPropData,cbPropData,pcbReturned);
1048         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1049             return DSPROPERTY_DescriptionW(guidPropSet,pPropData,cbPropData,pcbReturned);
1050         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1051             return DSPROPERTY_EnumerateA(guidPropSet,pPropData,cbPropData,pcbReturned);
1052         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1053             return DSPROPERTY_EnumerateW(guidPropSet,pPropData,cbPropData,pcbReturned);
1054         default:
1055             FIXME("unsupported ID: %ld\n",dwPropID);
1056             break;
1057         }
1058     } else {
1059         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1060     }
1061
1062     if (pcbReturned) {
1063         *pcbReturned = 0;
1064         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1065     }
1066
1067     return E_PROP_ID_UNSUPPORTED;
1068 }
1069
1070 static HRESULT WINAPI IKsPrivatePropertySetImpl_Set(
1071     LPKSPROPERTYSET iface,
1072     REFGUID guidPropSet,
1073     ULONG dwPropID,
1074     LPVOID pInstanceData,
1075     ULONG cbInstanceData,
1076     LPVOID pPropData,
1077     ULONG cbPropData )
1078 {
1079     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1080
1081     FIXME("(%p,%s,%ld,%p,%ld,%p,%ld), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1082     return E_PROP_ID_UNSUPPORTED;
1083 }
1084
1085 static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport(
1086     LPKSPROPERTYSET iface,
1087     REFGUID guidPropSet,
1088     ULONG dwPropID,
1089     PULONG pTypeSupport )
1090 {
1091     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1092     TRACE("(%p,%s,%ld,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1093
1094     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1095         switch (dwPropID) {
1096         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1097             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1098             return S_OK;
1099         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1100             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1101             return S_OK;
1102         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1103             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1104             return S_OK;
1105         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1106             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1107             return S_OK;
1108         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1109             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1110             return S_OK;
1111         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1112             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1113             return S_OK;
1114         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1115             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1116             return S_OK;
1117         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1118             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1119             return S_OK;
1120         default:
1121             FIXME("unsupported ID: %ld\n",dwPropID);
1122             break;
1123         }
1124     } else {
1125         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1126     }
1127
1128     return E_PROP_ID_UNSUPPORTED;
1129 }
1130
1131 static IKsPropertySetVtbl ikspvt = {
1132     IKsPrivatePropertySetImpl_QueryInterface,
1133     IKsPrivatePropertySetImpl_AddRef,
1134     IKsPrivatePropertySetImpl_Release,
1135     IKsPrivatePropertySetImpl_Get,
1136     IKsPrivatePropertySetImpl_Set,
1137     IKsPrivatePropertySetImpl_QuerySupport
1138 };
1139
1140 HRESULT WINAPI IKsPrivatePropertySetImpl_Create(
1141     IKsPrivatePropertySetImpl **piks)
1142 {
1143     IKsPrivatePropertySetImpl *iks;
1144
1145     iks = HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
1146     iks->ref = 0;
1147     iks->lpVtbl = &ikspvt;
1148
1149     *piks = iks;
1150     return S_OK;
1151 }