Fix block align error message to show length before fix up.
[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, &DSOUND_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, &DSOUND_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, &DSOUND_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, &DSOUND_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, &DSOUND_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, &DSOUND_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, &DSOUND_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, &DSOUND_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, &DSOUND_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, &DSOUND_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, &DSOUND_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 = DSOUND_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 = DSOUND_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 = DSOUND_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                 devs = waveInGetNumDevs();
1105                 for (wid = 0; wid < devs; ++wid) {
1106                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
1107                     if (err == DS_OK) {
1108                         DWORD size;
1109                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0));
1110                         if (err == DS_OK) {
1111                             WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size);
1112                             if (nameW) {
1113                                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size));
1114                                 if (err == DS_OK) {
1115                                     CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR));
1116                                     if (szInterface) {
1117                                         ZeroMemory(&data, sizeof(data));
1118                                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
1119                                         data.WaveDeviceId = wid;
1120                                         data.DeviceId = DSOUND_capture_guids[wid];
1121                                         data.Description = desc.szDesc;
1122                                         data.Module = desc.szDrvname;
1123                                         WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL );
1124                                         data.Interface = szInterface;
1125
1126                                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1127                                         (ppd->Callback)(&data, ppd->Context);
1128                                     }
1129                                     HeapFree(GetProcessHeap(),0,szInterface);
1130                                 }
1131                             }
1132                             HeapFree(GetProcessHeap(),0,nameW);
1133                         }
1134                     }
1135                 }
1136
1137                 return S_OK;
1138             }
1139         }
1140     } else {
1141         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1142     }
1143
1144     if (pcbReturned) {
1145         *pcbReturned = 0;
1146         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1147     }
1148
1149     return E_PROP_ID_UNSUPPORTED;
1150 }
1151
1152 static HRESULT WINAPI DSPROPERTY_EnumerateW(
1153     REFGUID guidPropSet,
1154     LPVOID pPropData,
1155     ULONG cbPropData,
1156     PULONG pcbReturned )
1157 {
1158     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA) pPropData;
1159     HRESULT err;
1160     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
1161         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
1162
1163     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1164         if (ppd) {
1165             if (ppd->Callback) {
1166                 unsigned devs, wod, wid;
1167                 DSDRIVERDESC desc;
1168                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
1169
1170                 devs = waveOutGetNumDevs();
1171                 for (wod = 0; wod < devs; ++wod) {
1172                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
1173                     if (err == DS_OK) {
1174                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
1175                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
1176                         if (wDescription && wModule) {
1177                             DWORD size;
1178                             err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0));
1179                             if (err == DS_OK) {
1180                                 WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size);
1181                                 if (wInterface) {
1182                                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size));
1183                                     if (err == DS_OK) {
1184                                         ZeroMemory(&data, sizeof(data));
1185                                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
1186                                         data.WaveDeviceId = wod;
1187                                         data.DeviceId = DSOUND_renderer_guids[wod];
1188
1189                                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
1190                                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
1191
1192                                         data.Description = wDescription;
1193                                         data.Module = wModule;
1194                                         data.Interface = wInterface;
1195
1196                                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1197                                         (ppd->Callback)(&data, ppd->Context);
1198                                     }
1199                                 }
1200                                 HeapFree(GetProcessHeap(),0,wInterface);
1201                             }
1202                         }
1203                         HeapFree(GetProcessHeap(),0,wDescription);
1204                         HeapFree(GetProcessHeap(),0,wModule);
1205                     }
1206                 }
1207
1208                 devs = waveInGetNumDevs();
1209                 for (wid = 0; wid < devs; ++wid) {
1210                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
1211                     if (err == DS_OK) {
1212                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
1213                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
1214                         if (wDescription && wModule) {
1215                             DWORD size;
1216                             err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0));
1217                             if (err == DS_OK) {
1218                                 WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size);
1219                                 if (wInterface) {
1220                                     err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size));
1221                                     if (err == DS_OK) {
1222                                         ZeroMemory(&data, sizeof(data));
1223                                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
1224                                         data.WaveDeviceId = wid;
1225                                         data.DeviceId = DSOUND_capture_guids[wid];
1226
1227                                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
1228                                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 );
1229
1230                                         data.Description = wDescription;
1231                                         data.Module = wModule;
1232                                         data.Interface = wInterface;
1233                                         TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1234                                         (ppd->Callback)(&data, ppd->Context);
1235                                     }
1236                                 }
1237                                 HeapFree(GetProcessHeap(),0,wInterface);
1238                             }
1239                         }
1240                         HeapFree(GetProcessHeap(),0,wDescription);
1241                         HeapFree(GetProcessHeap(),0,wModule);
1242                     }
1243                 }
1244
1245                 return S_OK;
1246             }
1247         }
1248     } else {
1249         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1250     }
1251
1252     if (pcbReturned) {
1253         *pcbReturned = 0;
1254         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1255     }
1256
1257     return E_PROP_ID_UNSUPPORTED;
1258 }
1259
1260 static HRESULT WINAPI IKsPrivatePropertySetImpl_Get(
1261     LPKSPROPERTYSET iface,
1262     REFGUID guidPropSet,
1263     ULONG dwPropID,
1264     LPVOID pInstanceData,
1265     ULONG cbInstanceData,
1266     LPVOID pPropData,
1267     ULONG cbPropData,
1268     PULONG pcbReturned )
1269 {
1270     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1271     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
1272         This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
1273
1274     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1275         switch (dwPropID) {
1276         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1277             return DSPROPERTY_WaveDeviceMappingA(guidPropSet,pPropData,cbPropData,pcbReturned);
1278         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1279             return DSPROPERTY_Description1(guidPropSet,pPropData,cbPropData,pcbReturned);
1280         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1281             return DSPROPERTY_Enumerate1(guidPropSet,pPropData,cbPropData,pcbReturned);
1282         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1283             return DSPROPERTY_WaveDeviceMappingW(guidPropSet,pPropData,cbPropData,pcbReturned);
1284         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1285             return DSPROPERTY_DescriptionA(guidPropSet,pPropData,cbPropData,pcbReturned);
1286         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1287             return DSPROPERTY_DescriptionW(guidPropSet,pPropData,cbPropData,pcbReturned);
1288         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1289             return DSPROPERTY_EnumerateA(guidPropSet,pPropData,cbPropData,pcbReturned);
1290         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1291             return DSPROPERTY_EnumerateW(guidPropSet,pPropData,cbPropData,pcbReturned);
1292         default:
1293             FIXME("unsupported ID: %ld\n",dwPropID);
1294             break;
1295         }
1296     } else {
1297         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1298     }
1299
1300     if (pcbReturned) {
1301         *pcbReturned = 0;
1302         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1303     }
1304
1305     return E_PROP_ID_UNSUPPORTED;
1306 }
1307
1308 static HRESULT WINAPI IKsPrivatePropertySetImpl_Set(
1309     LPKSPROPERTYSET iface,
1310     REFGUID guidPropSet,
1311     ULONG dwPropID,
1312     LPVOID pInstanceData,
1313     ULONG cbInstanceData,
1314     LPVOID pPropData,
1315     ULONG cbPropData )
1316 {
1317     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1318
1319     FIXME("(%p,%s,%ld,%p,%ld,%p,%ld), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1320     return E_PROP_ID_UNSUPPORTED;
1321 }
1322
1323 static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport(
1324     LPKSPROPERTYSET iface,
1325     REFGUID guidPropSet,
1326     ULONG dwPropID,
1327     PULONG pTypeSupport )
1328 {
1329     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1330     TRACE("(%p,%s,%ld,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1331
1332     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1333         switch (dwPropID) {
1334         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1335             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1336             return S_OK;
1337         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1338             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1339             return S_OK;
1340         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1341             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1342             return S_OK;
1343         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1344             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1345             return S_OK;
1346         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1347             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1348             return S_OK;
1349         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1350             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1351             return S_OK;
1352         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1353             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1354             return S_OK;
1355         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1356             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1357             return S_OK;
1358         default:
1359             FIXME("unsupported ID: %ld\n",dwPropID);
1360             break;
1361         }
1362     } else {
1363         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1364     }
1365
1366     return E_PROP_ID_UNSUPPORTED;
1367 }
1368
1369 static IKsPropertySetVtbl ikspvt = {
1370     IKsPrivatePropertySetImpl_QueryInterface,
1371     IKsPrivatePropertySetImpl_AddRef,
1372     IKsPrivatePropertySetImpl_Release,
1373     IKsPrivatePropertySetImpl_Get,
1374     IKsPrivatePropertySetImpl_Set,
1375     IKsPrivatePropertySetImpl_QuerySupport
1376 };
1377
1378 HRESULT WINAPI IKsPrivatePropertySetImpl_Create(
1379     IKsPrivatePropertySetImpl **piks)
1380 {
1381     IKsPrivatePropertySetImpl *iks;
1382
1383     iks = HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
1384     iks->ref = 0;
1385     iks->lpVtbl = &ikspvt;
1386
1387     *piks = iks;
1388     return S_OK;
1389 }