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
13 IN POOL_TYPE PoolType
,
14 IN SIZE_T NumberOfBytes
)
16 PVOID Item
= ExAllocatePool(PoolType
, NumberOfBytes
);
20 RtlZeroMemory(Item
, NumberOfBytes
);
34 GetSysAudioDeviceCount(
35 IN PDEVICE_OBJECT DeviceObject
)
37 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
39 ULONG Count
, BytesReturned
;
42 /* setup the query request */
43 Pin
.Set
= KSPROPSETID_Sysaudio
;
44 Pin
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_COUNT
;
45 Pin
.Flags
= KSPROPERTY_TYPE_GET
;
47 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
49 /* query sysaudio for the device count */
50 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)&Count
, sizeof(ULONG
), &BytesReturned
);
51 if (!NT_SUCCESS(Status
))
64 Irp
->IoStatus
.Information
= Length
;
65 Irp
->IoStatus
.Status
= Status
;
66 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
73 IN PWDMAUD_CLIENT ClientInfo
,
76 IN SOUND_DEVICE_TYPE DeviceType
)
80 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
82 if (ClientInfo
->hPins
[Index
].FilterId
== FilterId
&& ClientInfo
->hPins
[Index
].PinId
== PinId
&& ClientInfo
->hPins
[Index
].Handle
&& ClientInfo
->hPins
[Index
].Type
== DeviceType
)
84 if (ClientInfo
->hPins
[Index
].Type
!= MIXER_DEVICE_TYPE
)
86 ZwClose(ClientInfo
->hPins
[Index
].Handle
);
88 ClientInfo
->hPins
[Index
].Handle
= NULL
;
97 IN PWDMAUD_CLIENT ClientInfo
,
100 IN SOUND_DEVICE_TYPE DeviceType
,
104 PWDMAUD_HANDLE Handles
;
106 if (FreeIndex
!= MAXULONG
)
108 /* re-use a free index */
109 ClientInfo
->hPins
[FreeIndex
].Handle
= PinHandle
;
110 ClientInfo
->hPins
[FreeIndex
].FilterId
= FilterId
;
111 ClientInfo
->hPins
[FreeIndex
].PinId
= PinId
;
112 ClientInfo
->hPins
[FreeIndex
].Type
= DeviceType
;
114 return STATUS_SUCCESS
;
117 Handles
= AllocateItem(NonPagedPool
, sizeof(WDMAUD_HANDLE
) * (ClientInfo
->NumPins
+1));
120 return STATUS_INSUFFICIENT_RESOURCES
;
122 if (ClientInfo
->NumPins
)
124 RtlMoveMemory(Handles
, ClientInfo
->hPins
, sizeof(WDMAUD_HANDLE
) * ClientInfo
->NumPins
);
125 FreeItem(ClientInfo
->hPins
);
128 ClientInfo
->hPins
= Handles
;
129 ClientInfo
->hPins
[ClientInfo
->NumPins
].Handle
= PinHandle
;
130 ClientInfo
->hPins
[ClientInfo
->NumPins
].Type
= DeviceType
;
131 ClientInfo
->hPins
[ClientInfo
->NumPins
].FilterId
= FilterId
;
132 ClientInfo
->hPins
[ClientInfo
->NumPins
].PinId
= PinId
;
133 ClientInfo
->NumPins
++;
135 return STATUS_SUCCESS
;
138 PKEY_VALUE_PARTIAL_INFORMATION
141 IN PUNICODE_STRING KeyName
)
145 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
147 /* now query MatchingDeviceId key */
148 Status
= ZwQueryValueKey(hSubKey
, KeyName
, KeyValuePartialInformation
, NULL
, 0, &Length
);
150 /* check for success */
151 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
154 /* allocate a buffer for key data */
155 PartialInformation
= AllocateItem(NonPagedPool
, Length
);
157 if (!PartialInformation
)
161 /* now query MatchingDeviceId key */
162 Status
= ZwQueryValueKey(hSubKey
, KeyName
, KeyValuePartialInformation
, PartialInformation
, Length
, &Length
);
164 /* check for success */
165 if (!NT_SUCCESS(Status
))
167 FreeItem(PartialInformation
);
171 if (PartialInformation
->Type
!= REG_SZ
)
173 /* invalid key type */
174 FreeItem(PartialInformation
);
178 return PartialInformation
;
186 IN ULONG ProductNameSize
,
187 OUT LPWSTR ProductName
)
189 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
190 UNICODE_STRING DriverDescName
= RTL_CONSTANT_STRING(L
"DriverDesc");
191 UNICODE_STRING MatchingDeviceIdName
= RTL_CONSTANT_STRING(L
"MatchingDeviceId");
195 /* read MatchingDeviceId value */
196 PartialInformation
= ReadKeyValue(hSubKey
, &MatchingDeviceIdName
);
198 if (!PartialInformation
)
199 return STATUS_UNSUCCESSFUL
;
202 /* extract last '&' */
203 DeviceName
= wcsrchr((LPWSTR
)PartialInformation
->Data
, L
'&');
206 DeviceName
[0] = L
'\0';
208 Length
= wcslen((LPWSTR
)PartialInformation
->Data
);
210 DPRINT("DeviceName %S PnpName %S Length %u\n", (LPWSTR
)PartialInformation
->Data
, PnpName
, Length
);
212 if (_wcsnicmp((LPWSTR
)PartialInformation
->Data
, &PnpName
[4], Length
))
214 FreeItem(PartialInformation
);
215 return STATUS_NO_MATCH
;
219 FreeItem(PartialInformation
);
221 /* read DriverDescName value */
222 PartialInformation
= ReadKeyValue(hSubKey
, &DriverDescName
);
224 if (!PartialInformation
)
226 /* failed to read driver desc key */
227 return STATUS_UNSUCCESSFUL
;
231 Length
= min(ProductNameSize
* sizeof(WCHAR
), PartialInformation
->DataLength
);
232 RtlMoveMemory(ProductName
, (PVOID
)PartialInformation
->Data
, Length
);
234 /* zero terminate it */
235 ProductName
[ProductNameSize
-1] = L
'\0';
238 FreeItem(PartialInformation
);
240 return STATUS_SUCCESS
;
248 IN ULONG ProductNameSize
,
249 OUT LPWSTR ProductName
)
251 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E96C-E325-11CE-BFC1-08002BE10318}");
253 UNICODE_STRING SubKeyName
;
255 OBJECT_ATTRIBUTES ObjectAttributes
;
256 HANDLE hKey
, hSubKey
;
259 PKEY_FULL_INFORMATION KeyInformation
;
261 for(Index
= 0; Index
< wcslen(PnpName
); Index
++)
263 if (PnpName
[Index
] == '#')
264 PnpName
[Index
] = L
'\\';
268 /* initialize key attributes */
269 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
, NULL
, NULL
);
272 Status
= ZwOpenKey(&hKey
, GENERIC_READ
, &ObjectAttributes
);
274 /* check for success */
275 if (!NT_SUCCESS(Status
))
278 /* query num of subkeys */
279 Status
= ZwQueryKey(hKey
, KeyFullInformation
, NULL
, 0, &Length
);
281 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
283 DPRINT1("ZwQueryKey failed with %x\n", Status
);
289 /* allocate key information struct */
290 KeyInformation
= AllocateItem(NonPagedPool
, Length
);
295 return STATUS_INSUFFICIENT_RESOURCES
;
298 /* query num of subkeys */
299 Status
= ZwQueryKey(hKey
, KeyFullInformation
, (PVOID
)KeyInformation
, Length
, &Length
);
301 if (!NT_SUCCESS(Status
))
303 DPRINT1("ZwQueryKey failed with %x\n", Status
);
304 FreeItem(KeyInformation
);
309 /* now iterate through all subkeys */
310 for(Index
= 0; Index
< KeyInformation
->SubKeys
; Index
++)
312 /* subkeys are always in the format 0000-XXXX */
313 swprintf(SubKey
, L
"%04u", Index
);
315 /* initialize subkey name */
316 RtlInitUnicodeString(&SubKeyName
, SubKey
);
318 /* initialize key attributes */
319 InitializeObjectAttributes(&ObjectAttributes
, &SubKeyName
, OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
, hKey
, NULL
);
321 /* open the sub key */
322 Status
= ZwOpenKey(&hSubKey
, GENERIC_READ
, &ObjectAttributes
);
324 /* check for success */
325 if (NT_SUCCESS(Status
))
327 /* compare product name */
328 Status
= CompareProductName(hSubKey
, PnpName
, ProductNameSize
, ProductName
);
333 if (NT_SUCCESS(Status
))
339 FreeItem(KeyInformation
);
344 /* no matching key found */
349 GetSysAudioDevicePnpName(
350 IN PDEVICE_OBJECT DeviceObject
,
351 IN ULONG DeviceIndex
,
357 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
359 /* first check if the device index is within bounds */
360 if (DeviceIndex
>= GetSysAudioDeviceCount(DeviceObject
))
361 return STATUS_INVALID_PARAMETER
;
363 /* setup the query request */
364 Pin
.Property
.Set
= KSPROPSETID_Sysaudio
;
365 Pin
.Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME
;
366 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
367 Pin
.PinId
= DeviceIndex
;
369 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
371 /* query sysaudio for the device path */
372 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
) + sizeof(ULONG
), NULL
, 0, &BytesReturned
);
374 /* check if the request failed */
375 if (Status
!= STATUS_BUFFER_TOO_SMALL
|| BytesReturned
== 0)
376 return STATUS_UNSUCCESSFUL
;
378 /* allocate buffer for the device */
379 *Device
= AllocateItem(NonPagedPool
, BytesReturned
);
381 return STATUS_INSUFFICIENT_RESOURCES
;
383 /* query sysaudio again for the device path */
384 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
) + sizeof(ULONG
), (PVOID
)*Device
, BytesReturned
, &BytesReturned
);
386 if (!NT_SUCCESS(Status
))
399 OUT PHANDLE DeviceHandle
,
400 OUT PFILE_OBJECT
* FileObject
)
405 /* now open the device */
406 Status
= WdmAudOpenSysAudioDevice(Device
, &hDevice
);
408 if (!NT_SUCCESS(Status
))
413 *DeviceHandle
= hDevice
;
417 Status
= ObReferenceObjectByHandle(hDevice
, FILE_READ_DATA
| FILE_WRITE_DATA
, IoFileObjectType
, KernelMode
, (PVOID
*)FileObject
, NULL
);
419 if (!NT_SUCCESS(Status
))