Fix memory leak in error path.
[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     ULONG ref = InterlockedIncrement(&(This->ref));
68     TRACE("(%p) ref was %ld\n", This, ref - 1);
69     return ref;
70 }
71
72 static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
73 {
74     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
75     ULONG ref = InterlockedDecrement(&(This->ref));
76     TRACE("(%p) ref was %ld\n", This, ref + 1);
77
78     if (!ref) {
79         This->dsb->iks = 0;
80         IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
81         HeapFree(GetProcessHeap(), 0, This);
82         TRACE("(%p) released\n", This);
83     }
84     return ref;
85 }
86
87 static HRESULT WINAPI IKsBufferPropertySetImpl_Get(
88     LPKSPROPERTYSET iface,
89     REFGUID guidPropSet,
90     ULONG dwPropID,
91     LPVOID pInstanceData,
92     ULONG cbInstanceData,
93     LPVOID pPropData,
94     ULONG cbPropData,
95     PULONG pcbReturned )
96 {
97     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
98     PIDSDRIVERPROPERTYSET ps;
99     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%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     ULONG ref = InterlockedIncrement(&(This->ref));
252     TRACE("(%p) ref was %ld\n", This, ref - 1);
253     return ref;
254 }
255
256 static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface)
257 {
258     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
259     ULONG ref = InterlockedDecrement(&(This->ref));
260     TRACE("(%p) ref was %ld\n", This, ref + 1);
261
262     if (!ref) {
263         HeapFree(GetProcessHeap(), 0, This);
264         TRACE("(%p) released\n", This);
265     }
266     return ref;
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                     else
395                         WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
396                     break;
397                 } else {
398                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
399                     return E_PROP_ID_UNSUPPORTED;
400                 }
401             }
402         }
403     } else if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
404                 IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
405         ULONG wid;
406         unsigned int widn;
407         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
408         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
409         widn = waveInGetNumDevs();
410         for (wid = 0; wid < widn; wid++) {
411             if (IsEqualGUID( &dev_guid, &guid) ) {
412                 DSDRIVERDESC desc;
413                 ppd->WaveDeviceId = wid;
414                 ppd->Devnode = wid;
415                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
416                 if (err == DS_OK) {
417                     PIDSCDRIVER drv;
418                     strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
419                     strncpy(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA) - 1);
420                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
421                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
422                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
423                     if (err == DS_OK && drv)
424                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
425                     else
426                         WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
427                     break;
428                 } else {
429                     WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
430                     return E_PROP_ID_UNSUPPORTED;
431                 }
432             }
433         }
434     } else {
435         BOOL found = FALSE;
436         ULONG wod;
437         unsigned int wodn;
438         /* given specific device so try the render devices first */
439         wodn = waveOutGetNumDevs();
440         for (wod = 0; wod < wodn; wod++) {
441             if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
442                 DSDRIVERDESC desc;
443                 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
444                 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
445                 ppd->WaveDeviceId = wod;
446                 ppd->Devnode = wod;
447                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
448                 if (err == DS_OK) {
449                     PIDSDRIVER drv = NULL;
450                     strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
451                     strncpy(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA) - 1);
452                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
453                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
454                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
455                     if (err == DS_OK && drv)
456                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
457                     else
458                         WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
459                     found = TRUE;
460                     break;
461                 } else {
462                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
463                     return E_PROP_ID_UNSUPPORTED;
464                 }
465             }
466         }
467
468         if (found == FALSE) {
469             ULONG wid;
470             unsigned int widn;
471             /* given specific device so try the capture devices next */
472             widn = waveInGetNumDevs();
473             for (wid = 0; wid < widn; wid++) {
474                 if (IsEqualGUID( &ppd->DeviceId, &capture_guids[wid] ) ) {
475                     DSDRIVERDESC desc;
476                     TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
477                     ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
478                     ppd->WaveDeviceId = wid;
479                     ppd->Devnode = wid;
480                     err = mmErr(waveInMessage((HWAVEIN)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
481                     if (err == DS_OK) {
482                         PIDSDRIVER drv = NULL;
483                         strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
484                         strncpy(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA) - 1);
485                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
486                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
487                         err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
488                         if (err == DS_OK && drv)
489                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
490                         else
491                             WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
492                         found = TRUE;
493                         break;
494                     } else {
495                         WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
496                         return E_PROP_ID_UNSUPPORTED;
497                     }
498                 }
499             }
500
501             if (found == FALSE) {
502                 WARN("device not found\n");
503                 return E_PROP_ID_UNSUPPORTED;
504             }
505         }
506     }
507
508     if (pcbReturned) {
509         *pcbReturned = cbPropData;
510         TRACE("*pcbReturned=%ld\n", *pcbReturned);
511     }
512
513     return S_OK;
514 }
515
516 static HRESULT WINAPI DSPROPERTY_DescriptionA(
517     REFGUID guidPropSet,
518     LPVOID pPropData,
519     ULONG cbPropData,
520     PULONG pcbReturned )
521 {
522     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA) pPropData;
523     HRESULT err;
524     GUID dev_guid;
525     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
526         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
527
528     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
529     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
530         /* default device of type specified by ppd->DataFlow */
531         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
532             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
533         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
534             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
535         } else {
536             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
537         }
538         FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
539             debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
540         return E_PROP_ID_UNSUPPORTED;
541     }
542
543     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
544     GetDeviceID(&ppd->DeviceId, &dev_guid);
545
546     if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
547          IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
548         ULONG wod;
549         unsigned int wodn;
550         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
551         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
552         wodn = waveOutGetNumDevs();
553         for (wod = 0; wod < wodn; wod++) {
554             if (IsEqualGUID( &dev_guid, &renderer_guids[wod] ) ) {
555                 DSDRIVERDESC desc;
556                 ppd->WaveDeviceId = wod;
557                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
558                 if (err == DS_OK) {
559                     PIDSDRIVER drv = NULL;
560                     /* FIXME: this is a memory leak */
561                     CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
562                     CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
563                     CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
564
565                     if (szDescription && szModule && szInterface) {
566                         strcpy(szDescription, desc.szDesc);
567                         strcpy(szModule, desc.szDrvname);
568                         strcpy(szInterface, "Interface");
569
570                         ppd->Description = szDescription;
571                         ppd->Module = szModule;
572                         ppd->Interface = szInterface;
573                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
574                         if (err == DS_OK && drv)
575                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
576                         else
577                             WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
578                         break;
579                     } else {
580                         WARN("no memory\n");
581                         HeapFree(GetProcessHeap(), 0, szDescription);
582                         HeapFree(GetProcessHeap(), 0, szModule);
583                         HeapFree(GetProcessHeap(), 0, szInterface);
584                         return E_OUTOFMEMORY;
585                     }
586                 } else {
587                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
588                     return E_PROP_ID_UNSUPPORTED;
589                 }
590             }
591         }
592     } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
593                IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
594         ULONG wid;
595         unsigned int widn;
596         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
597         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
598         widn = waveInGetNumDevs();
599         for (wid = 0; wid < widn; wid++) {
600             if (IsEqualGUID( &dev_guid, &capture_guids[wid] ) ) {
601                 DSDRIVERDESC desc;
602                 ppd->WaveDeviceId = wid;
603                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
604                 if (err == DS_OK) {
605                     PIDSCDRIVER drv;
606                     /* FIXME: this is a memory leak */
607                     CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
608                     CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
609                     CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
610
611                     if (szDescription && szModule && szInterface) {
612                         strcpy(szDescription, desc.szDesc);
613                         strcpy(szModule, desc.szDrvname);
614                         strcpy(szInterface, "Interface");
615
616                         ppd->Description = szDescription;
617                         ppd->Module = szModule;
618                         ppd->Interface = szInterface;
619                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
620                         if (err == DS_OK && drv)
621                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
622                         else
623                             WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
624                         break;
625                     } else {
626                         WARN("no memory\n");
627                         HeapFree(GetProcessHeap(), 0, szDescription);
628                         HeapFree(GetProcessHeap(), 0, szModule);
629                         HeapFree(GetProcessHeap(), 0, szInterface);
630                         return E_OUTOFMEMORY;
631                     }
632                 } else {
633                     WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
634                     return E_PROP_ID_UNSUPPORTED;
635                 }
636             }
637         }
638     } else {
639         BOOL found = FALSE;
640         ULONG wod;
641         unsigned int wodn;
642         /* given specific device so try the render devices first */
643         wodn = waveOutGetNumDevs();
644         for (wod = 0; wod < wodn; wod++) {
645             if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
646                 DSDRIVERDESC desc;
647                 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
648                 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
649                 ppd->WaveDeviceId = wod;
650                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
651                 if (err == DS_OK) {
652                     PIDSDRIVER drv = NULL;
653                     /* FIXME: this is a memory leak */
654                     CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
655                     CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
656                     CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
657
658                     if (szDescription && szModule && szInterface) {
659                         strcpy(szDescription, desc.szDesc);
660                         strcpy(szModule, desc.szDrvname);
661                         strcpy(szInterface, "Interface");
662
663                         ppd->Description = szDescription;
664                         ppd->Module = szModule;
665                         ppd->Interface = szInterface;
666                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
667                         if (err == DS_OK && drv)
668                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
669                         else
670                             WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
671                         found = TRUE;
672                         break;
673                     } else {
674                         WARN("no memory\n");
675                         HeapFree(GetProcessHeap(), 0, szDescription);
676                         HeapFree(GetProcessHeap(), 0, szModule);
677                         HeapFree(GetProcessHeap(), 0, szInterface);
678                         return E_OUTOFMEMORY;
679                     }
680                 } else {
681                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
682                     return E_PROP_ID_UNSUPPORTED;
683                 }
684             }
685         }
686
687         if (found == FALSE) {
688             ULONG wid;
689             unsigned int widn;
690             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
691             ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
692             widn = waveInGetNumDevs();
693             for (wid = 0; wid < widn; wid++) {
694                 if (IsEqualGUID( &ppd->DeviceId, &capture_guids[wod] ) ) {
695                     DSDRIVERDESC desc;
696                     ppd->WaveDeviceId = wid;
697                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
698                     if (err == DS_OK) {
699                         PIDSCDRIVER drv;
700                         /* FIXME: this is a memory leak */
701                         CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
702                         CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
703                         CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
704
705                         if (szDescription && szModule && szInterface) {
706                             strcpy(szDescription, desc.szDesc);
707                             strcpy(szModule, desc.szDrvname);
708                             strcpy(szInterface, "Interface");
709
710                             ppd->Description = szDescription;
711                             ppd->Module = szModule;
712                             ppd->Interface = szInterface;
713                             err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
714                             if (err == DS_OK && drv)
715                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
716                             else
717                                 WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
718                             found = TRUE;
719                             break;
720                         } else {
721                             WARN("no memory\n");
722                             HeapFree(GetProcessHeap(), 0, szDescription);
723                             HeapFree(GetProcessHeap(), 0, szModule);
724                             HeapFree(GetProcessHeap(), 0, szInterface);
725                             return E_OUTOFMEMORY;
726                         }
727                     } else {
728                         WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
729                         return E_PROP_ID_UNSUPPORTED;
730                     }
731                 }
732             }
733         }
734
735         if (found == FALSE) {
736             WARN("device not found\n");
737             return E_PROP_ID_UNSUPPORTED;
738         }
739     }
740
741     if (pcbReturned) {
742         *pcbReturned = cbPropData;
743         TRACE("*pcbReturned=%ld\n", *pcbReturned);
744     }
745
746     return S_OK;
747 }
748
749 static HRESULT WINAPI DSPROPERTY_DescriptionW(
750     REFGUID guidPropSet,
751     LPVOID pPropData,
752     ULONG cbPropData,
753     PULONG pcbReturned )
754 {
755     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA) pPropData;
756     HRESULT err;
757     GUID dev_guid;
758     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
759         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
760
761     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
762     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
763         /* default device of type specified by ppd->DataFlow */
764         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
765             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
766         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
767             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
768         } else {
769             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
770         }
771         FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
772             debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
773         return E_PROP_ID_UNSUPPORTED;
774     }
775
776     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
777     GetDeviceID(&ppd->DeviceId, &dev_guid);
778
779     if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
780          IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
781         ULONG wod;
782         unsigned int wodn;
783         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
784         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
785         wodn = waveOutGetNumDevs();
786         for (wod = 0; wod < wodn; wod++) {
787             if (IsEqualGUID( &dev_guid, &renderer_guids[wod] ) ) {
788                 DSDRIVERDESC desc;
789                 ppd->WaveDeviceId = wod;
790                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
791                 if (err == DS_OK) {
792                     PIDSDRIVER drv = NULL;
793                     /* FIXME: this is a memory leak */
794                     WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
795                     WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
796                     WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
797
798                     if (wDescription && wModule && wInterface) {
799                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
800                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
801                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
802
803                         ppd->Description = wDescription;
804                         ppd->Module = wModule;
805                         ppd->Interface = wInterface;
806                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
807                         if (err == DS_OK && drv)
808                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
809                         else
810                             WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
811                         break;
812                     } else {
813                         WARN("no memory\n");
814                         HeapFree(GetProcessHeap(), 0, wDescription);
815                         HeapFree(GetProcessHeap(), 0, wModule);
816                         HeapFree(GetProcessHeap(), 0, wInterface);
817                         return E_OUTOFMEMORY;
818                     }
819                 } else {
820                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
821                     return E_PROP_ID_UNSUPPORTED;
822                 }
823             }
824         }
825     } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
826                IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
827         ULONG wid;
828         unsigned int widn;
829         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
830         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
831         widn = waveInGetNumDevs();
832         for (wid = 0; wid < widn; wid++) {
833             if (IsEqualGUID( &dev_guid, &capture_guids[wid] ) ) {
834                 DSDRIVERDESC desc;
835                 ppd->WaveDeviceId = wid;
836                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
837                 if (err == DS_OK) {
838                     PIDSCDRIVER drv;
839                     /* FIXME: this is a memory leak */
840                     WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
841                     WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
842                     WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
843
844                     if (wDescription && wModule && wInterface) {
845                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
846                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
847                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
848
849                         ppd->Description = wDescription;
850                         ppd->Module = wModule;
851                         ppd->Interface = wInterface;
852                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
853                         if (err == DS_OK && drv)
854                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
855                         else
856                             WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
857                         break;
858                     } else {
859                         WARN("no memory\n");
860                         HeapFree(GetProcessHeap(), 0, wDescription);
861                         HeapFree(GetProcessHeap(), 0, wModule);
862                         HeapFree(GetProcessHeap(), 0, wInterface);
863                         return E_OUTOFMEMORY;
864                     }
865                 } else {
866                     WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
867                     return E_PROP_ID_UNSUPPORTED;
868                 }
869             }
870         }
871     } else {
872         BOOL found = FALSE;
873         ULONG wod;
874         unsigned int wodn;
875         /* given specific device so try the render devices first */
876         wodn = waveOutGetNumDevs();
877         for (wod = 0; wod < wodn; wod++) {
878             if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
879                 DSDRIVERDESC desc;
880                 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
881                 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
882                 ppd->WaveDeviceId = wod;
883                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
884                 if (err == DS_OK) {
885                     PIDSDRIVER drv = NULL;
886                     /* FIXME: this is a memory leak */
887                     WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
888                     WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
889                     WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
890
891                     if (wDescription && wModule && wInterface) {
892                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
893                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
894                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
895
896                         ppd->Description = wDescription;
897                         ppd->Module = wModule;
898                         ppd->Interface = wInterface;
899                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
900                         if (err == DS_OK && drv)
901                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
902                         else
903                             WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
904                         found = TRUE;
905                         break;
906                     } else {
907                         WARN("no memory\n");
908                         HeapFree(GetProcessHeap(), 0, wDescription);
909                         HeapFree(GetProcessHeap(), 0, wModule);
910                         HeapFree(GetProcessHeap(), 0, wInterface);
911                         return E_OUTOFMEMORY;
912                     }
913                 } else {
914                     WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
915                     return E_PROP_ID_UNSUPPORTED;
916                 }
917             }
918         }
919
920         if (found == FALSE) {
921             ULONG wid;
922             unsigned int widn;
923             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
924             ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
925             widn = waveInGetNumDevs();
926             for (wid = 0; wid < widn; wid++) {
927                 if (IsEqualGUID( &dev_guid, &capture_guids[wid] ) ) {
928                     DSDRIVERDESC desc;
929                     ppd->WaveDeviceId = wid;
930                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
931                     if (err == DS_OK) {
932                         PIDSCDRIVER drv;
933                         /* FIXME: this is a memory leak */
934                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
935                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
936                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
937
938                         if (wDescription && wModule && wInterface) {
939                             MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
940                             MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
941                             MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
942
943                             ppd->Description = wDescription;
944                             ppd->Module = wModule;
945                             ppd->Interface = wInterface;
946                             err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
947                             if (err == DS_OK && drv)
948                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
949                             else
950                                 WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
951                             found = TRUE;
952                             break;
953                         } else {
954                             WARN("no memory\n");
955                             HeapFree(GetProcessHeap(), 0, wDescription);
956                             HeapFree(GetProcessHeap(), 0, wModule);
957                             HeapFree(GetProcessHeap(), 0, wInterface);
958                             return E_OUTOFMEMORY;
959                         }
960                     } else {
961                         WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
962                         return E_PROP_ID_UNSUPPORTED;
963                     }
964                 }
965             }
966         }
967
968         if (found == FALSE) {
969             WARN("device not found\n");
970             return E_PROP_ID_UNSUPPORTED;
971         }
972     }
973
974     if (pcbReturned) {
975         *pcbReturned = cbPropData;
976         TRACE("*pcbReturned=%ld\n", *pcbReturned);
977     }
978
979     return S_OK;
980 }
981
982 static HRESULT WINAPI DSPROPERTY_Enumerate1(
983     REFGUID guidPropSet,
984     LPVOID pPropData,
985     ULONG cbPropData,
986     PULONG pcbReturned )
987 {
988     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA) pPropData;
989     HRESULT err;
990     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
991         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
992
993     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
994         if (ppd) {
995             if (ppd->Callback) {
996                 unsigned devs, wod, wid;
997                 DSDRIVERDESC desc;
998                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA data;
999
1000                 devs = waveOutGetNumDevs();
1001                 for (wod = 0; wod < devs; ++wod) {
1002                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
1003                     if (err == DS_OK) {
1004                         ZeroMemory(&data, sizeof(data));
1005                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
1006                         data.WaveDeviceId = wod;
1007                         data.DeviceId = renderer_guids[wod];
1008                         strncpy(data.DescriptionA, desc.szDesc, sizeof(data.DescriptionA));
1009                         strncpy(data.ModuleA, desc.szDrvname, sizeof(data.ModuleA));
1010
1011                         MultiByteToWideChar( CP_ACP, 0, data.DescriptionA, -1, data.DescriptionW, sizeof(data.DescriptionW) );
1012                         MultiByteToWideChar( CP_ACP, 0, data.ModuleA, -1, data.ModuleW, sizeof(data.ModuleW) );
1013
1014                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1015                         (ppd->Callback)(&data, ppd->Context);
1016                     }
1017                 }
1018
1019                 devs = waveInGetNumDevs();
1020                 for (wid = 0; wid < devs; ++wid) {
1021                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
1022                     if (err == DS_OK) {
1023                         ZeroMemory(&data, sizeof(data));
1024                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
1025                         data.WaveDeviceId = wod;
1026                         data.DeviceId = renderer_guids[wod];
1027                         strncpy(data.DescriptionA, desc.szDesc, sizeof(data.DescriptionA));
1028                         strncpy(data.ModuleA, desc.szDrvname, sizeof(data.ModuleA));
1029
1030                         MultiByteToWideChar( CP_ACP, 0, data.DescriptionA, -1, data.DescriptionW, sizeof(data.DescriptionW) );
1031                         MultiByteToWideChar( CP_ACP, 0, data.ModuleA, -1, data.ModuleW, sizeof(data.ModuleW) );
1032
1033                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1034                         (ppd->Callback)(&data, ppd->Context);
1035                     }
1036                 }
1037
1038                 return S_OK;
1039             }
1040         }
1041     } else {
1042         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1043     }
1044
1045     if (pcbReturned) {
1046         *pcbReturned = 0;
1047         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1048     }
1049
1050     return E_PROP_ID_UNSUPPORTED;
1051 }
1052
1053 static HRESULT WINAPI DSPROPERTY_EnumerateA(
1054     REFGUID guidPropSet,
1055     LPVOID pPropData,
1056     ULONG cbPropData,
1057     PULONG pcbReturned )
1058 {
1059     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA) pPropData;
1060     HRESULT err;
1061     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
1062         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
1063
1064     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1065         if (ppd) {
1066             if (ppd->Callback) {
1067                 unsigned devs, wod, wid;
1068                 DSDRIVERDESC desc;
1069                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA data;
1070
1071                 devs = waveOutGetNumDevs();
1072                 for (wod = 0; wod < devs; ++wod) {
1073                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
1074                     if (err == DS_OK) {
1075                         DWORD size;
1076                         err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0));
1077                         if (err == DS_OK) {
1078                             WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size);
1079                             if (nameW) {
1080                                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size));
1081                                 if (err == DS_OK) {
1082                                     CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR));
1083                                     if (szInterface) {
1084                                         ZeroMemory(&data, sizeof(data));
1085                                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
1086                                         data.WaveDeviceId = wod;
1087                                         data.DeviceId = renderer_guids[wod];
1088                                         data.Description = desc.szDesc;
1089                                         data.Module = desc.szDrvname;
1090                                         WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL );
1091                                         data.Interface = szInterface;
1092
1093                                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1094                                         (ppd->Callback)(&data, ppd->Context);
1095
1096                                         HeapFree(GetProcessHeap(),0,szInterface);
1097                                     }
1098                                 }
1099                                 HeapFree(GetProcessHeap(),0,nameW);
1100                             }
1101                         }
1102                     }
1103                 }
1104
1105                 devs = waveInGetNumDevs();
1106                 for (wid = 0; wid < devs; ++wid) {
1107                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
1108                     if (err == DS_OK) {
1109                         DWORD size;
1110                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0));
1111                         if (err == DS_OK) {
1112                             WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size);
1113                             if (nameW) {
1114                                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size));
1115                                 if (err == DS_OK) {
1116                                     CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR));
1117                                     if (szInterface) {
1118                                         ZeroMemory(&data, sizeof(data));
1119                                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
1120                                         data.WaveDeviceId = wid;
1121                                         data.DeviceId = capture_guids[wid];
1122                                         data.Description = desc.szDesc;
1123                                         data.Module = desc.szDrvname;
1124                                         WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL );
1125                                         data.Interface = szInterface;
1126
1127                                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1128                                         (ppd->Callback)(&data, ppd->Context);
1129
1130                                         HeapFree(GetProcessHeap(),0,szInterface);
1131                                     }
1132                                 }
1133                                 HeapFree(GetProcessHeap(),0,nameW);
1134                             }
1135                         }
1136                     }
1137                 }
1138
1139                 return S_OK;
1140             }
1141         }
1142     } else {
1143         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1144     }
1145
1146     if (pcbReturned) {
1147         *pcbReturned = 0;
1148         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1149     }
1150
1151     return E_PROP_ID_UNSUPPORTED;
1152 }
1153
1154 static HRESULT WINAPI DSPROPERTY_EnumerateW(
1155     REFGUID guidPropSet,
1156     LPVOID pPropData,
1157     ULONG cbPropData,
1158     PULONG pcbReturned )
1159 {
1160     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA) pPropData;
1161     HRESULT err;
1162     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
1163         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
1164
1165     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1166         if (ppd) {
1167             if (ppd->Callback) {
1168                 unsigned devs, wod, wid;
1169                 DSDRIVERDESC desc;
1170                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
1171
1172                 devs = waveOutGetNumDevs();
1173                 for (wod = 0; wod < devs; ++wod) {
1174                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
1175                     if (err == DS_OK) {
1176                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
1177                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
1178                         if (wDescription && wModule) {
1179                             DWORD size;
1180                             err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0));
1181                             if (err == DS_OK) {
1182                                 WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size);
1183                                 if (wInterface) {
1184                                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size));
1185                                     if (err == DS_OK) {
1186                                         ZeroMemory(&data, sizeof(data));
1187                                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
1188                                         data.WaveDeviceId = wod;
1189                                         data.DeviceId = renderer_guids[wod];
1190
1191                                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
1192                                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
1193
1194                                         data.Description = wDescription;
1195                                         data.Module = wModule;
1196                                         data.Interface = wInterface;
1197
1198                                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1199                                         (ppd->Callback)(&data, ppd->Context);
1200                                     }
1201                                     HeapFree(GetProcessHeap(),0,wInterface);
1202                                 }
1203                             }
1204                             HeapFree(GetProcessHeap(),0,wDescription);
1205                             HeapFree(GetProcessHeap(),0,wModule);
1206                         }
1207                     }
1208                 }
1209
1210                 devs = waveInGetNumDevs();
1211                 for (wid = 0; wid < devs; ++wid) {
1212                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
1213                     if (err == DS_OK) {
1214                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
1215                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
1216                         if (wDescription && wModule) {
1217                             DWORD size;
1218                             err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0));
1219                             if (err == DS_OK) {
1220                                 WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size);
1221                                 if (wInterface) {
1222                                     err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size));
1223                                     if (err == DS_OK) {
1224                                         ZeroMemory(&data, sizeof(data));
1225                                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
1226                                         data.WaveDeviceId = wid;
1227                                         data.DeviceId = capture_guids[wid];
1228
1229                                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
1230                                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
1231
1232                                         data.Description = wDescription;
1233                                         data.Module = wModule;
1234                                         data.Interface = wInterface;
1235                                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1236                                         (ppd->Callback)(&data, ppd->Context);
1237                                     }
1238                                     HeapFree(GetProcessHeap(),0,wInterface);
1239                                 }
1240                             }
1241                             HeapFree(GetProcessHeap(),0,wDescription);
1242                             HeapFree(GetProcessHeap(),0,wModule);
1243                         }
1244                     }
1245                 }
1246
1247                 return S_OK;
1248             }
1249         }
1250     } else {
1251         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1252     }
1253
1254     if (pcbReturned) {
1255         *pcbReturned = 0;
1256         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1257     }
1258
1259     return E_PROP_ID_UNSUPPORTED;
1260 }
1261
1262 static HRESULT WINAPI IKsPrivatePropertySetImpl_Get(
1263     LPKSPROPERTYSET iface,
1264     REFGUID guidPropSet,
1265     ULONG dwPropID,
1266     LPVOID pInstanceData,
1267     ULONG cbInstanceData,
1268     LPVOID pPropData,
1269     ULONG cbPropData,
1270     PULONG pcbReturned )
1271 {
1272     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1273     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
1274         This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
1275
1276     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1277         switch (dwPropID) {
1278         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1279             return DSPROPERTY_WaveDeviceMappingA(guidPropSet,pPropData,cbPropData,pcbReturned);
1280         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1281             return DSPROPERTY_Description1(guidPropSet,pPropData,cbPropData,pcbReturned);
1282         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1283             return DSPROPERTY_Enumerate1(guidPropSet,pPropData,cbPropData,pcbReturned);
1284         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1285             return DSPROPERTY_WaveDeviceMappingW(guidPropSet,pPropData,cbPropData,pcbReturned);
1286         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1287             return DSPROPERTY_DescriptionA(guidPropSet,pPropData,cbPropData,pcbReturned);
1288         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1289             return DSPROPERTY_DescriptionW(guidPropSet,pPropData,cbPropData,pcbReturned);
1290         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1291             return DSPROPERTY_EnumerateA(guidPropSet,pPropData,cbPropData,pcbReturned);
1292         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1293             return DSPROPERTY_EnumerateW(guidPropSet,pPropData,cbPropData,pcbReturned);
1294         default:
1295             FIXME("unsupported ID: %ld\n",dwPropID);
1296             break;
1297         }
1298     } else {
1299         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1300     }
1301
1302     if (pcbReturned) {
1303         *pcbReturned = 0;
1304         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1305     }
1306
1307     return E_PROP_ID_UNSUPPORTED;
1308 }
1309
1310 static HRESULT WINAPI IKsPrivatePropertySetImpl_Set(
1311     LPKSPROPERTYSET iface,
1312     REFGUID guidPropSet,
1313     ULONG dwPropID,
1314     LPVOID pInstanceData,
1315     ULONG cbInstanceData,
1316     LPVOID pPropData,
1317     ULONG cbPropData )
1318 {
1319     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1320
1321     FIXME("(%p,%s,%ld,%p,%ld,%p,%ld), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1322     return E_PROP_ID_UNSUPPORTED;
1323 }
1324
1325 static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport(
1326     LPKSPROPERTYSET iface,
1327     REFGUID guidPropSet,
1328     ULONG dwPropID,
1329     PULONG pTypeSupport )
1330 {
1331     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1332     TRACE("(%p,%s,%ld,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1333
1334     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1335         switch (dwPropID) {
1336         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1337             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1338             return S_OK;
1339         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1340             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1341             return S_OK;
1342         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1343             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1344             return S_OK;
1345         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1346             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1347             return S_OK;
1348         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1349             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1350             return S_OK;
1351         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1352             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1353             return S_OK;
1354         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1355             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1356             return S_OK;
1357         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1358             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1359             return S_OK;
1360         default:
1361             FIXME("unsupported ID: %ld\n",dwPropID);
1362             break;
1363         }
1364     } else {
1365         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1366     }
1367
1368     return E_PROP_ID_UNSUPPORTED;
1369 }
1370
1371 static IKsPropertySetVtbl ikspvt = {
1372     IKsPrivatePropertySetImpl_QueryInterface,
1373     IKsPrivatePropertySetImpl_AddRef,
1374     IKsPrivatePropertySetImpl_Release,
1375     IKsPrivatePropertySetImpl_Get,
1376     IKsPrivatePropertySetImpl_Set,
1377     IKsPrivatePropertySetImpl_QuerySupport
1378 };
1379
1380 HRESULT WINAPI IKsPrivatePropertySetImpl_Create(
1381     IKsPrivatePropertySetImpl **piks)
1382 {
1383     IKsPrivatePropertySetImpl *iks;
1384
1385     iks = HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
1386     iks->ref = 0;
1387     iks->lpVtbl = &ikspvt;
1388
1389     *piks = iks;
1390     return S_OK;
1391 }