ReactOS  0.4.14-dev-50-g13bb5e2
devicelist.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Configuration of network devices
4  * FILE: dll/directx/dsound_new/devicelist.c
5  * PURPOSE: Enumeration of audio devices
6  *
7  * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
8  */
9 
10 #include "precomp.h"
11 
12 ULONG
15  BOOL bCapture,
16  ULONG Offset)
17 {
18  ULONG Index;
19 
20  for(Index = Offset; Index < Filter->PinCount; Index++)
21  {
22  if (Filter->Pin[Index] == PIN_TYPE_PLAYBACK && !bCapture)
23  return Index;
24 
25  if (Filter->Pin[Index] == PIN_TYPE_RECORDING && bCapture)
26  return Index;
27  }
28  return ULONG_MAX;
29 }
30 
31 
32 DWORD
35  OUT HDEVINFO * OutHandle)
36 {
38 
40  NULL,
41  NULL,
42  DIGCF_DEVICEINTERFACE); //DIGCF_PRESENT
43 
44  /* check for success */
46  {
47  /* failed to create device list */
48  return GetLastError();
49  }
50 
51  /* store result */
52  *OutHandle = DeviceHandle;
53 
54  return ERROR_SUCCESS;
55 }
56 
57 BOOL
60 {
62 }
63 
64 BOOL
68  LPFILTERINFO *OutPath)
69 {
70  ULONG Length, Index = 0;
74  LPFILTERINFO LastDevice = NULL, RootDevice = NULL, CurDevice;
75  BOOL Result;
76 
77 
78  do
79  {
80  InterfaceData.cbSize = sizeof(InterfaceData);
81  InterfaceData.Reserved = 0;
82 
83  /* query device interface */
85  NULL,
87  Index,
88  &InterfaceData);
89 
90  if (!Result)
91  {
92  /* failed */
93  DPRINT("SetupDiEnumDeviceInterfaces Index %u failed with %lx\n", Index, GetLastError());
94  break;
95  }
96 
97  /* allocate device interface struct */
101  Length);
102 
103  if (!DetailData)
104  {
105  /* insufficient memory */
106  break;
107  }
108 
109  /* initialize device interface detail struct */
110  DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
111 
112  DeviceData.cbSize = sizeof(DeviceData);
113  DeviceData.Reserved = 0;
114 
116  &InterfaceData,
117  DetailData,
118  Length,
119  NULL,
120  &DeviceData);
121 
122  if (!Result)
123  {
124  /* failed */
125  DPRINT("SetupDiGetDeviceInterfaceDetail failed with %x\n", GetLastError());
126  HeapFree(GetProcessHeap(), 0, DetailData);
127 
128  break;
129  }
130 
131  /* allocate device path struct */
132  CurDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FILTERINFO));
133  if (!CurDevice)
134  {
135  /* no memory */
136  HeapFree(GetProcessHeap(), 0, DetailData);
137  break;
138  }
139 
140  /* store device path */
141  CopyMemory(&CurDevice->DeviceData, &DeviceData, sizeof(SP_DEVINFO_DATA));
142  wcscpy(CurDevice->DevicePath, DetailData->DevicePath);
143  CurDevice->MappedId[0] = ULONG_MAX;
144  CurDevice->MappedId[1] = ULONG_MAX;
145 
146  DPRINT("DevicePath %S\n", CurDevice->DevicePath);
147 
148  if (!RootDevice)
149  RootDevice = CurDevice;
150 
151  if (LastDevice)
152  {
153  LastDevice->lpNext = CurDevice;
154  }
155 
156  /* set as last device */
157  LastDevice = CurDevice;
158 
159  /* free device interface struct */
160  HeapFree(GetProcessHeap(), 0, DetailData);
161 
162  /* increment device interface index */
163  Index++;
164  }while(TRUE);
165 
166  /* store result */
167  *OutPath = RootDevice;
168 
169  if (!RootDevice)
170  return FALSE;
171 
172 
173  return TRUE;
174 }
175 
176 DWORD
179  PSP_DEVINFO_DATA FILTERINFOData,
180  DWORD KeyType,
182  OUT HKEY * OutKey)
183 {
184  HKEY hKey;
185 
186  /* try open device registry key */
187  hKey = SetupDiOpenDevRegKey(Handle, FILTERINFOData, DICS_FLAG_CONFIGSPECIFIC, 0, KeyType, DesiredAccess);
188 
189  if (hKey == INVALID_HANDLE_VALUE)
190  return GetLastError();
191 
192  /* store result */
193  *OutKey = hKey;
194 
195  return ERROR_SUCCESS;
196 }
197 
198 VOID
200  LPFILTERINFO CurInfo,
201  OUT PULONG WaveInPins,
202  OUT PULONG WaveOutPins)
203 {
204  ULONG Index;
205  KSPIN_COMMUNICATION Communication;
207 
208  *WaveInPins = 0;
209  *WaveOutPins = 0;
210 
211  /* traverse all pins */
212  for(Index = 0; Index < CurInfo->PinCount; Index++)
213  {
214  if (GetFilterPinCommunication(CurInfo->hFilter, Index, &Communication) == ERROR_SUCCESS &&
216  {
217  if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN)
218  {
219  /* found a wave out device */
220  CurInfo->Pin[Index] = PIN_TYPE_PLAYBACK;
221  (*WaveOutPins)++;
222  }
223  else if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT)
224  {
225  /* found a wave in device */
226  CurInfo->Pin[Index] = PIN_TYPE_RECORDING;
227  (*WaveInPins)++;
228  }
229  else
230  {
231  /* bridge pin / topology pin etc */
232  CurInfo->Pin[Index] = PIN_TYPE_NONE;
233  }
234  }
235  else
236  {
237  /* bridge pin / topology pin etc */
238  CurInfo->Pin[Index] = PIN_TYPE_NONE;
239  }
240  }
241 }
242 
243 BOOL
245  LPFILTERINFO CurInfo,
246  BOOL bRecord)
247 {
250  DWORD Size, dwResult;
251 
252  if (bRecord)
254  else
256 
257  /* sanity check */
258  //ASSERT(DeviceCount);
259 
260  for(Index = 0; Index < DeviceCount; Index++)
261  {
262  Size = 0;
263 
264  /* query device interface size */
265  if (bRecord)
267  else
269 
270  if (dwResult != MMSYSERR_NOERROR)
271  {
272  DPRINT("Failed DRV_QUERYDEVICEINTERFACESIZE with %lx bRecord %u Index %u\n", dwResult, bRecord, Index);
273  continue;
274  }
275 
276  /* sanity check */
277  ASSERT(Size < MAX_PATH);
278 
279  /* now get the device interface string */
280  if (bRecord)
282  else
284 
285  if (dwResult != MMSYSERR_NOERROR)
286  {
287  DPRINT("Failed DRV_QUERYDEVICEINTERFACE with %lx bRecord %u Index %u\n", dwResult, bRecord, Index);
288  continue;
289  }
290 
291  if (!wcsicmp(CurInfo->DevicePath, Buffer))
292  {
293  if (bRecord)
294  CurInfo->MappedId[0] = Index;
295  else
296  CurInfo->MappedId[1] = Index;
297 
298  return TRUE;
299  }
300  }
301 
302  DPRINT1("Failed to find device %ws bRecord %u Count %u\n", CurInfo->DevicePath, bRecord, DeviceCount);
303 
304  // HACK
305  if (bRecord)
306  CurInfo->MappedId[0] = 0;
307  else
308  CurInfo->MappedId[1] = 0;
309 
310 
311  return TRUE;
312 }
313 
314 HRESULT
316  LPFILTERINFO CurInfo,
317  OUT PULONG WaveInCount,
318  OUT PULONG WaveOutCount)
319 {
320  DWORD Status;
321  ULONG PinCount, WaveInPins, WaveOutPins;
322 
323  /* first step open filter */
324  Status = OpenFilter((LPCWSTR)CurInfo->DevicePath, &CurInfo->hFilter);
325  if (Status != ERROR_SUCCESS)
326  {
327  DPRINT("Failed to open filter with %lx Path %ws\n", Status, CurInfo->DevicePath);
328  return E_FAIL;
329  }
330 
331  /* get filter pin count */
333  if (Status != ERROR_SUCCESS)
334  {
335  DPRINT("Failed to get pin count with %lx\n", Status);
336  return E_FAIL;
337  }
338 
339  /* sanity check */
340  ASSERT(PinCount);
341 
342  /* store pin count */
343  CurInfo->PinCount = PinCount;
344 
345  /* now allocate an pin array */
346  CurInfo->Pin = HeapAlloc(GetProcessHeap(), 0, PinCount * sizeof(ULONG));
347  if (!CurInfo->Pin)
348  {
349  /* no memory */
350  return E_FAIL;
351  }
352 
353  /* no try to find playback / recording pins */
354  FindAudioFilterPins(CurInfo, &WaveInPins, &WaveOutPins);
355 
356  DPRINT("WaveInPins %u WaveOutPins %u %S\n", WaveInPins, WaveOutPins, CurInfo->DevicePath);
357 
358  if (WaveOutPins)
359  {
360  /* create a unique guid for this playback device */
361  if (FindWinMMDeviceIndex(CurInfo, TRUE))
362  {
363  (*WaveOutCount)++;
364  INIT_GUID(CurInfo->DeviceGuid[0], 0xbd6dd71a, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + *WaveInCount);
365  }
366  }
367 
368 
369  if (WaveInPins)
370  {
371  if (FindWinMMDeviceIndex(CurInfo, FALSE))
372  {
373  /* create a unique guid for this record device */
374  (*WaveInCount)++;
375  INIT_GUID(CurInfo->DeviceGuid[1], 0xbd6dd71b, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + *WaveOutCount);
376  }
377  }
378 
379  return S_OK;
380 }
381 
382 
383 HRESULT
385  LPFILTERINFO *OutRootInfo)
386 {
387  HDEVINFO hList;
388  DWORD Status;
389  HRESULT hResult;
390  ULONG WaveOutCount, WaveInCount;
391  GUID AudioDeviceGuid = {STATIC_KSCATEGORY_AUDIO};
392  LPFILTERINFO CurInfo;
393 
394  /* try open the device list */
395  Status = OpenDeviceList(&AudioDeviceGuid, &hList);
396 
397  if (Status != ERROR_SUCCESS)
398  {
399  DPRINT1("OpenDeviceList failed with %lx\n", Status);
400  return E_FAIL;
401  }
402 
403  if (!GetDeviceListInterfaces(hList, &AudioDeviceGuid, OutRootInfo))
404  {
405  DPRINT1("No devices found\n");
407  return S_FALSE;
408  }
409 
410  /* sanity check */
411  ASSERT(*OutRootInfo);
412 
413  CurInfo = *OutRootInfo;
414 
415  WaveOutCount = 0;
416  WaveInCount = 0;
417 
418  /* now check all audio filters */
419  while(CurInfo)
420  {
421  /* now check details of the audio filter */
422  hResult = EnumerateAudioFilter(CurInfo, &WaveInCount, &WaveOutCount);
423 
424  if (hResult != S_OK)
425  {
426  DPRINT1("EnumerateAudioFilter failed with %lx\n", Status);
427  break;
428  }
429 
430  /* move to next filter */
431  CurInfo = CurInfo->lpNext;
432  }
433 
434  /* close device list */
436 
437  /* done */
438  return hResult;
439 }
440 
441 BOOL
443  IN ULONG DeviceID,
445  BOOL bPlayback)
446 {
447  LPFILTERINFO CurInfo;
448  if (!RootInfo)
449  return FALSE;
450 
451  /* get first entry */
452  CurInfo = RootInfo;
453 
454  while(CurInfo)
455  {
456  if ((bPlayback && CurInfo->MappedId[1] == DeviceID) ||
457  (!bPlayback && CurInfo->MappedId[0] == DeviceID))
458  {
459  /* found filter */
460  *Filter = CurInfo;
461  return TRUE;
462  }
463 
464  CurInfo = CurInfo->lpNext;
465  }
466  return FALSE;
467 }
468 
469 BOOL
471  LPCGUID pGuidSrc,
473 {
474  LPFILTERINFO CurInfo;
475  if (!RootInfo)
476  return FALSE;
477 
478  /* get first entry */
479  CurInfo = RootInfo;
480 
481  while(CurInfo)
482  {
483  if (IsEqualGUID(&CurInfo->DeviceGuid[0], pGuidSrc) ||
484  IsEqualGUID(&CurInfo->DeviceGuid[1], pGuidSrc))
485  {
486  /* found filter */
487  *Filter = CurInfo;
488  return TRUE;
489  }
490 
491  CurInfo = CurInfo->lpNext;
492  }
493 
494  return FALSE;
495 }
HRESULT EnumAudioDeviceInterfaces(LPFILTERINFO *OutRootInfo)
Definition: devicelist.c:384
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
_Inout_ PUSB_DEVICE_HANDLE DeviceHandle
Definition: hubbusif.h:121
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL FindDeviceByGuid(LPCGUID pGuidSrc, LPFILTERINFO *Filter)
Definition: devicelist.c:470
BOOL FindWinMMDeviceIndex(LPFILTERINFO CurInfo, BOOL bRecord)
Definition: devicelist.c:244
#define STATIC_KSCATEGORY_AUDIO
Definition: ksmedia.h:169
WCHAR DevicePath[ANYSIZE_ARRAY]
Definition: setupapi.h:850
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
UINT WINAPI waveOutMessage(HWAVEOUT hWaveOut, UINT uMessage, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
Definition: winmm.c:2541
struct tagFILTERINFO * lpNext
Definition: precomp.h:49
DWORD GetFilterPinCommunication(IN HANDLE hFilter, IN ULONG PinId, OUT PKSPIN_COMMUNICATION Communication)
Definition: misc.c:427
BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData, DWORD DeviceInterfaceDetailDataSize, PDWORD RequiredSize, PSP_DEVINFO_DATA DeviceInfoData)
Definition: devinst.c:3016
_In_ USHORT DeviceID
Definition: iotypes.h:860
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define DRV_QUERYDEVICEINTERFACESIZE
Definition: mmddk.h:97
BOOL GetDeviceListInterfaces(HDEVINFO DeviceHandle, IN LPGUID InterfaceGuid, LPFILTERINFO *OutPath)
Definition: devicelist.c:65
_In_ const GUID _In_ ULONG PinCount
Definition: strmini.h:504
#define E_FAIL
Definition: ddrawi.h:102
UINT WINAPI waveInMessage(HWAVEIN hWaveIn, UINT uMessage, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
Definition: winmm.c:2816
DWORD OpenDeviceKey(HDEVINFO Handle, PSP_DEVINFO_DATA FILTERINFOData, DWORD KeyType, REGSAM DesiredAccess, OUT HKEY *OutKey)
Definition: devicelist.c:177
VOID FindAudioFilterPins(LPFILTERINFO CurInfo, OUT PULONG WaveInPins, OUT PULONG WaveOutPins)
Definition: devicelist.c:199
struct _SP_DEVICE_INTERFACE_DETAIL_DATA_W SP_DEVICE_INTERFACE_DETAIL_DATA_W
WCHAR DevicePath[MAX_PATH]
Definition: precomp.h:42
PULONG Pin
Definition: precomp.h:45
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
unsigned int BOOL
Definition: ntddk_ex.h:94
_Must_inspect_result_ _In_opt_ PFLT_FILTER Filter
Definition: fltkernel.h:1802
ULONG DeviceCount
Definition: mpu401.c:26
#define S_FALSE
Definition: winerror.h:2357
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
HANDLE hFilter
Definition: precomp.h:43
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
UINT WINAPI waveOutGetNumDevs(void)
Definition: winmm.c:2140
KSPIN_DATAFLOW
Definition: ks.h:1248
ULONG GetPinIdFromFilter(LPFILTERINFO Filter, BOOL bCapture, ULONG Offset)
Definition: devicelist.c:13
_In_ HANDLE Handle
Definition: extypes.h:390
GUID DeviceGuid[2]
Definition: precomp.h:46
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
#define DICS_FLAG_CONFIGSPECIFIC
Definition: setupapi.h:115
#define UlongToHandle(ul)
Definition: basetsd.h:97
DWORD GetFilterPinCount(IN HANDLE hFilter, OUT PULONG NumPins)
Definition: misc.c:357
BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
Definition: devinst.c:2898
#define MAX_PATH
Definition: compat.h:26
#define CopyMemory
Definition: winbase.h:1633
static const UCHAR Index[8]
Definition: usbohci.c:18
unsigned long DWORD
Definition: ntddk_ex.h:95
struct _SP_DEVICE_INTERFACE_DETAIL_DATA_W * PSP_DEVICE_INTERFACE_DETAIL_DATA_W
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
DWORD OpenDeviceList(IN LPGUID InterfaceGuid, OUT HDEVINFO *OutHandle)
Definition: devicelist.c:33
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const GUID InterfaceGuid
Definition: wlanapi.c:25
#define SetupDiGetClassDevs
Definition: setupapi.h:2588
HKEY WINAPI SetupDiOpenDevRegKey(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Scope, DWORD HwProfile, DWORD KeyType, REGSAM samDesired)
Definition: devinst.c:5919
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define wcsicmp
Definition: string.h:1152
Status
Definition: gdiplustypes.h:24
LPFILTERINFO RootInfo
Definition: dsound.c:13
HWND hList
Definition: livecd.c:10
#define S_OK
Definition: intsafe.h:59
KSPIN_COMMUNICATION
Definition: ks.h:1253
#define INIT_GUID(guid, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
Definition: precomp.h:52
ULONG PinCount
Definition: precomp.h:44
BOOL CloseDeviceList(HDEVINFO Handle)
Definition: devicelist.c:58
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK DesiredAccess
Definition: create.c:4157
BOOL WINAPI SetupDiEnumDeviceInterfaces(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, CONST GUID *InterfaceClassGuid, DWORD MemberIndex, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
Definition: devinst.c:2785
ACCESS_MASK REGSAM
Definition: winreg.h:69
unsigned int * PULONG
Definition: retypes.h:1
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4021
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define DPRINT1
Definition: precomp.h:8
#define DIGCF_DEVICEINTERFACE
Definition: setupapi.h:174
ULONG MappedId[2]
Definition: precomp.h:47
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
IN PVOID IN PVOID InterfaceData
Definition: pci.h:359
UINT WINAPI waveInGetNumDevs(void)
Definition: winmm.c:2568
DataFlow
DWORD OpenFilter(IN LPCWSTR lpFileName, IN PHANDLE OutHandle)
Definition: misc.c:277
#define DRV_QUERYDEVICEINTERFACE
Definition: mmddk.h:96
BOOL FindDeviceByMappedId(IN ULONG DeviceID, LPFILTERINFO *Filter, BOOL bPlayback)
Definition: devicelist.c:442
#define HeapFree(x, y, z)
Definition: compat.h:394
#define ULONG_MAX
Definition: limits.h:44
HRESULT EnumerateAudioFilter(LPFILTERINFO CurInfo, OUT PULONG WaveInCount, OUT PULONG WaveOutCount)
Definition: devicelist.c:315
DWORD GetFilterPinDataFlow(IN HANDLE hFilter, IN ULONG PinId, OUT PKSPIN_DATAFLOW DataFlow)
Definition: misc.c:444