2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/legacy/wdmaud/sup.c
5 * PURPOSE: Misc support routines
6 * PROGRAMMER: Andrew Greenwood
12 GetSysAudioDeviceCount(
13 IN PDEVICE_OBJECT DeviceObject
)
15 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
17 ULONG Count
, BytesReturned
;
20 /* setup the query request */
21 Pin
.Set
= KSPROPSETID_Sysaudio
;
22 Pin
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_COUNT
;
23 Pin
.Flags
= KSPROPERTY_TYPE_GET
;
25 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
27 /* query sysaudio for the device count */
28 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)&Count
, sizeof(ULONG
), &BytesReturned
);
29 if (!NT_SUCCESS(Status
))
42 Irp
->IoStatus
.Information
= Length
;
43 Irp
->IoStatus
.Status
= Status
;
44 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
51 IN PWDMAUD_CLIENT ClientInfo
,
54 IN SOUND_DEVICE_TYPE DeviceType
)
58 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
60 if (ClientInfo
->hPins
[Index
].FilterId
== FilterId
&& ClientInfo
->hPins
[Index
].PinId
== PinId
&& ClientInfo
->hPins
[Index
].Handle
&& ClientInfo
->hPins
[Index
].Type
== DeviceType
)
62 if (ClientInfo
->hPins
[Index
].Type
!= MIXER_DEVICE_TYPE
)
64 ZwClose(ClientInfo
->hPins
[Index
].Handle
);
66 ClientInfo
->hPins
[Index
].Handle
= NULL
;
75 IN PWDMAUD_CLIENT ClientInfo
,
78 IN SOUND_DEVICE_TYPE DeviceType
,
82 PWDMAUD_HANDLE Handles
;
84 if (FreeIndex
!= MAXULONG
)
86 /* re-use a free index */
87 ClientInfo
->hPins
[FreeIndex
].Handle
= PinHandle
;
88 ClientInfo
->hPins
[FreeIndex
].FilterId
= FilterId
;
89 ClientInfo
->hPins
[FreeIndex
].PinId
= PinId
;
90 ClientInfo
->hPins
[FreeIndex
].Type
= DeviceType
;
92 return STATUS_SUCCESS
;
95 Handles
= ExAllocatePool(NonPagedPool
, sizeof(WDMAUD_HANDLE
) * (ClientInfo
->NumPins
+1));
98 return STATUS_INSUFFICIENT_RESOURCES
;
100 if (ClientInfo
->NumPins
)
102 RtlMoveMemory(Handles
, ClientInfo
->hPins
, sizeof(WDMAUD_HANDLE
) * ClientInfo
->NumPins
);
103 ExFreePool(ClientInfo
->hPins
);
106 ClientInfo
->hPins
= Handles
;
107 ClientInfo
->hPins
[ClientInfo
->NumPins
].Handle
= PinHandle
;
108 ClientInfo
->hPins
[ClientInfo
->NumPins
].Type
= DeviceType
;
109 ClientInfo
->hPins
[ClientInfo
->NumPins
].FilterId
= FilterId
;
110 ClientInfo
->hPins
[ClientInfo
->NumPins
].PinId
= PinId
;
111 ClientInfo
->NumPins
++;
113 return STATUS_SUCCESS
;
116 PKEY_VALUE_PARTIAL_INFORMATION
119 IN PUNICODE_STRING KeyName
)
123 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
125 /* now query MatchingDeviceId key */
126 Status
= ZwQueryValueKey(hSubKey
, KeyName
, KeyValuePartialInformation
, NULL
, 0, &Length
);
128 /* check for success */
129 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
132 /* allocate a buffer for key data */
133 PartialInformation
= ExAllocatePool(NonPagedPool
, Length
);
135 if (!PartialInformation
)
139 /* now query MatchingDeviceId key */
140 Status
= ZwQueryValueKey(hSubKey
, KeyName
, KeyValuePartialInformation
, PartialInformation
, Length
, &Length
);
142 /* check for success */
143 if (!NT_SUCCESS(Status
))
145 ExFreePool(PartialInformation
);
149 if (PartialInformation
->Type
!= REG_SZ
)
151 /* invalid key type */
152 ExFreePool(PartialInformation
);
156 return PartialInformation
;
164 IN ULONG ProductNameSize
,
165 OUT LPWSTR ProductName
)
167 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
168 UNICODE_STRING DriverDescName
= RTL_CONSTANT_STRING(L
"DriverDesc");
169 UNICODE_STRING MatchingDeviceIdName
= RTL_CONSTANT_STRING(L
"MatchingDeviceId");
173 /* read MatchingDeviceId value */
174 PartialInformation
= ReadKeyValue(hSubKey
, &MatchingDeviceIdName
);
176 if (!PartialInformation
)
177 return STATUS_UNSUCCESSFUL
;
180 /* extract last '&' */
181 DeviceName
= wcsrchr((LPWSTR
)PartialInformation
->Data
, L
'&');
184 DeviceName
[0] = L
'\0';
186 Length
= wcslen((LPWSTR
)PartialInformation
->Data
);
188 DPRINT("DeviceName %S PnpName %S Length %u\n", (LPWSTR
)PartialInformation
->Data
, PnpName
, Length
);
190 if (_wcsnicmp((LPWSTR
)PartialInformation
->Data
, &PnpName
[4], Length
))
192 ExFreePool(PartialInformation
);
193 return STATUS_NO_MATCH
;
197 ExFreePool(PartialInformation
);
199 /* read DriverDescName value */
200 PartialInformation
= ReadKeyValue(hSubKey
, &DriverDescName
);
202 if (!PartialInformation
)
204 /* failed to read driver desc key */
205 return STATUS_UNSUCCESSFUL
;
209 Length
= min(ProductNameSize
* sizeof(WCHAR
), PartialInformation
->DataLength
);
210 RtlMoveMemory(ProductName
, (PVOID
)PartialInformation
->Data
, Length
);
212 /* zero terminate it */
213 ProductName
[ProductNameSize
-1] = L
'\0';
216 ExFreePool(PartialInformation
);
218 return STATUS_SUCCESS
;
226 IN ULONG ProductNameSize
,
227 OUT LPWSTR ProductName
)
229 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E96C-E325-11CE-BFC1-08002BE10318}");
231 UNICODE_STRING SubKeyName
;
233 OBJECT_ATTRIBUTES ObjectAttributes
;
234 HANDLE hKey
, hSubKey
;
237 PKEY_FULL_INFORMATION KeyInformation
;
239 for(Index
= 0; Index
< wcslen(PnpName
); Index
++)
241 if (PnpName
[Index
] == '#')
242 PnpName
[Index
] = L
'\\';
246 /* initialize key attributes */
247 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
, NULL
, NULL
);
250 Status
= ZwOpenKey(&hKey
, GENERIC_READ
, &ObjectAttributes
);
252 /* check for success */
253 if (!NT_SUCCESS(Status
))
256 /* query num of subkeys */
257 Status
= ZwQueryKey(hKey
, KeyFullInformation
, NULL
, 0, &Length
);
259 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
261 DPRINT1("ZwQueryKey failed with %x\n", Status
);
267 /* allocate key information struct */
268 KeyInformation
= ExAllocatePool(NonPagedPool
, Length
);
273 return STATUS_INSUFFICIENT_RESOURCES
;
276 /* query num of subkeys */
277 Status
= ZwQueryKey(hKey
, KeyFullInformation
, (PVOID
)KeyInformation
, Length
, &Length
);
279 if (!NT_SUCCESS(Status
))
281 DPRINT1("ZwQueryKey failed with %x\n", Status
);
282 ExFreePool(KeyInformation
);
287 /* now iterate through all subkeys */
288 for(Index
= 0; Index
< KeyInformation
->SubKeys
; Index
++)
290 /* subkeys are always in the format 0000-XXXX */
291 swprintf(SubKey
, L
"%04u", Index
);
293 /* initialize subkey name */
294 RtlInitUnicodeString(&SubKeyName
, SubKey
);
296 /* initialize key attributes */
297 InitializeObjectAttributes(&ObjectAttributes
, &SubKeyName
, OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
, hKey
, NULL
);
299 /* open the sub key */
300 Status
= ZwOpenKey(&hSubKey
, GENERIC_READ
, &ObjectAttributes
);
302 /* check for success */
303 if (NT_SUCCESS(Status
))
305 /* compare product name */
306 Status
= CompareProductName(hSubKey
, PnpName
, ProductNameSize
, ProductName
);
311 if (NT_SUCCESS(Status
))
317 ExFreePool(KeyInformation
);
322 /* no matching key found */
327 GetSysAudioDevicePnpName(
328 IN PDEVICE_OBJECT DeviceObject
,
329 IN ULONG DeviceIndex
,
335 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
337 /* first check if the device index is within bounds */
338 if (DeviceIndex
>= GetSysAudioDeviceCount(DeviceObject
))
339 return STATUS_INVALID_PARAMETER
;
341 /* setup the query request */
342 Pin
.Property
.Set
= KSPROPSETID_Sysaudio
;
343 Pin
.Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME
;
344 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
345 Pin
.PinId
= DeviceIndex
;
347 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
349 /* query sysaudio for the device path */
350 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
) + sizeof(ULONG
), NULL
, 0, &BytesReturned
);
352 /* check if the request failed */
353 if (Status
!= STATUS_BUFFER_TOO_SMALL
|| BytesReturned
== 0)
354 return STATUS_UNSUCCESSFUL
;
356 /* allocate buffer for the device */
357 *Device
= ExAllocatePool(NonPagedPool
, BytesReturned
);
359 return STATUS_INSUFFICIENT_RESOURCES
;
361 /* query sysaudio again for the device path */
362 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
) + sizeof(ULONG
), (PVOID
)*Device
, BytesReturned
, &BytesReturned
);
364 if (!NT_SUCCESS(Status
))
377 OUT PHANDLE DeviceHandle
,
378 OUT PFILE_OBJECT
* FileObject
)
383 /* now open the device */
384 Status
= WdmAudOpenSysAudioDevice(Device
, &hDevice
);
386 if (!NT_SUCCESS(Status
))
391 *DeviceHandle
= hDevice
;
395 Status
= ObReferenceObjectByHandle(hDevice
, FILE_READ_DATA
| FILE_WRITE_DATA
, IoFileObjectType
, KernelMode
, (PVOID
*)FileObject
, NULL
);
397 if (!NT_SUCCESS(Status
))