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
19 IN POOL_TYPE PoolType
,
20 IN SIZE_T NumberOfBytes
)
22 PVOID Item
= ExAllocatePool(PoolType
, NumberOfBytes
);
26 RtlZeroMemory(Item
, NumberOfBytes
);
40 GetSysAudioDeviceCount(
41 IN PDEVICE_OBJECT DeviceObject
)
43 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
45 ULONG Count
, BytesReturned
;
48 /* setup the query request */
49 Pin
.Set
= KSPROPSETID_Sysaudio
;
50 Pin
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_COUNT
;
51 Pin
.Flags
= KSPROPERTY_TYPE_GET
;
53 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
55 /* query sysaudio for the device count */
56 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)&Count
, sizeof(ULONG
), &BytesReturned
);
57 if (!NT_SUCCESS(Status
))
70 Irp
->IoStatus
.Information
= Length
;
71 Irp
->IoStatus
.Status
= Status
;
72 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
79 IN PWDMAUD_CLIENT ClientInfo
,
82 IN SOUND_DEVICE_TYPE DeviceType
)
86 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
88 if (ClientInfo
->hPins
[Index
].FilterId
== FilterId
&& ClientInfo
->hPins
[Index
].PinId
== PinId
&& ClientInfo
->hPins
[Index
].Handle
&& ClientInfo
->hPins
[Index
].Type
== DeviceType
)
90 if (ClientInfo
->hPins
[Index
].Type
!= MIXER_DEVICE_TYPE
)
92 ZwClose(ClientInfo
->hPins
[Index
].Handle
);
94 ClientInfo
->hPins
[Index
].Handle
= NULL
;
103 IN PWDMAUD_CLIENT ClientInfo
,
106 IN SOUND_DEVICE_TYPE DeviceType
,
110 PWDMAUD_HANDLE Handles
;
112 if (FreeIndex
!= MAXULONG
)
114 /* re-use a free index */
115 ClientInfo
->hPins
[FreeIndex
].Handle
= PinHandle
;
116 ClientInfo
->hPins
[FreeIndex
].FilterId
= FilterId
;
117 ClientInfo
->hPins
[FreeIndex
].PinId
= PinId
;
118 ClientInfo
->hPins
[FreeIndex
].Type
= DeviceType
;
120 return STATUS_SUCCESS
;
123 Handles
= AllocateItem(NonPagedPool
, sizeof(WDMAUD_HANDLE
) * (ClientInfo
->NumPins
+1));
126 return STATUS_INSUFFICIENT_RESOURCES
;
128 if (ClientInfo
->NumPins
)
130 RtlMoveMemory(Handles
, ClientInfo
->hPins
, sizeof(WDMAUD_HANDLE
) * ClientInfo
->NumPins
);
131 FreeItem(ClientInfo
->hPins
);
134 ClientInfo
->hPins
= Handles
;
135 ClientInfo
->hPins
[ClientInfo
->NumPins
].Handle
= PinHandle
;
136 ClientInfo
->hPins
[ClientInfo
->NumPins
].Type
= DeviceType
;
137 ClientInfo
->hPins
[ClientInfo
->NumPins
].FilterId
= FilterId
;
138 ClientInfo
->hPins
[ClientInfo
->NumPins
].PinId
= PinId
;
139 ClientInfo
->NumPins
++;
141 return STATUS_SUCCESS
;
144 PKEY_VALUE_PARTIAL_INFORMATION
147 IN PUNICODE_STRING KeyName
)
151 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
153 /* now query MatchingDeviceId key */
154 Status
= ZwQueryValueKey(hSubKey
, KeyName
, KeyValuePartialInformation
, NULL
, 0, &Length
);
156 /* check for success */
157 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
160 /* allocate a buffer for key data */
161 PartialInformation
= AllocateItem(NonPagedPool
, Length
);
163 if (!PartialInformation
)
167 /* now query MatchingDeviceId key */
168 Status
= ZwQueryValueKey(hSubKey
, KeyName
, KeyValuePartialInformation
, PartialInformation
, Length
, &Length
);
170 /* check for success */
171 if (!NT_SUCCESS(Status
))
173 FreeItem(PartialInformation
);
177 if (PartialInformation
->Type
!= REG_SZ
)
179 /* invalid key type */
180 FreeItem(PartialInformation
);
184 return PartialInformation
;
192 IN ULONG ProductNameSize
,
193 OUT LPWSTR ProductName
)
195 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
196 UNICODE_STRING DriverDescName
= RTL_CONSTANT_STRING(L
"DriverDesc");
197 UNICODE_STRING MatchingDeviceIdName
= RTL_CONSTANT_STRING(L
"MatchingDeviceId");
201 /* read MatchingDeviceId value */
202 PartialInformation
= ReadKeyValue(hSubKey
, &MatchingDeviceIdName
);
204 if (!PartialInformation
)
205 return STATUS_UNSUCCESSFUL
;
208 /* extract last '&' */
209 DeviceName
= wcsrchr((LPWSTR
)PartialInformation
->Data
, L
'&');
212 DeviceName
[0] = L
'\0';
214 Length
= wcslen((LPWSTR
)PartialInformation
->Data
);
216 DPRINT("DeviceName %S PnpName %S Length %u\n", (LPWSTR
)PartialInformation
->Data
, PnpName
, Length
);
218 if (_wcsnicmp((LPWSTR
)PartialInformation
->Data
, &PnpName
[4], Length
))
220 FreeItem(PartialInformation
);
221 return STATUS_NO_MATCH
;
225 FreeItem(PartialInformation
);
227 /* read DriverDescName value */
228 PartialInformation
= ReadKeyValue(hSubKey
, &DriverDescName
);
230 if (!PartialInformation
)
232 /* failed to read driver desc key */
233 return STATUS_UNSUCCESSFUL
;
237 Length
= min(ProductNameSize
* sizeof(WCHAR
), PartialInformation
->DataLength
);
238 RtlMoveMemory(ProductName
, (PVOID
)PartialInformation
->Data
, Length
);
240 /* zero terminate it */
241 ProductName
[ProductNameSize
-1] = L
'\0';
244 FreeItem(PartialInformation
);
246 return STATUS_SUCCESS
;
254 IN ULONG ProductNameSize
,
255 OUT LPWSTR ProductName
)
257 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E96C-E325-11CE-BFC1-08002BE10318}");
259 UNICODE_STRING SubKeyName
;
261 OBJECT_ATTRIBUTES ObjectAttributes
;
262 HANDLE hKey
, hSubKey
;
265 PKEY_FULL_INFORMATION KeyInformation
;
267 for(Index
= 0; Index
< wcslen(PnpName
); Index
++)
269 if (PnpName
[Index
] == '#')
270 PnpName
[Index
] = L
'\\';
274 /* initialize key attributes */
275 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
, NULL
, NULL
);
278 Status
= ZwOpenKey(&hKey
, GENERIC_READ
, &ObjectAttributes
);
280 /* check for success */
281 if (!NT_SUCCESS(Status
))
284 /* query num of subkeys */
285 Status
= ZwQueryKey(hKey
, KeyFullInformation
, NULL
, 0, &Length
);
287 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
289 DPRINT1("ZwQueryKey failed with %x\n", Status
);
295 /* allocate key information struct */
296 KeyInformation
= AllocateItem(NonPagedPool
, Length
);
301 return STATUS_INSUFFICIENT_RESOURCES
;
304 /* query num of subkeys */
305 Status
= ZwQueryKey(hKey
, KeyFullInformation
, (PVOID
)KeyInformation
, Length
, &Length
);
307 if (!NT_SUCCESS(Status
))
309 DPRINT1("ZwQueryKey failed with %x\n", Status
);
310 FreeItem(KeyInformation
);
315 /* now iterate through all subkeys */
316 for(Index
= 0; Index
< KeyInformation
->SubKeys
; Index
++)
318 /* subkeys are always in the format 0000-XXXX */
319 swprintf(SubKey
, L
"%04u", Index
);
321 /* initialize subkey name */
322 RtlInitUnicodeString(&SubKeyName
, SubKey
);
324 /* initialize key attributes */
325 InitializeObjectAttributes(&ObjectAttributes
, &SubKeyName
, OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
, hKey
, NULL
);
327 /* open the sub key */
328 Status
= ZwOpenKey(&hSubKey
, GENERIC_READ
, &ObjectAttributes
);
330 /* check for success */
331 if (NT_SUCCESS(Status
))
333 /* compare product name */
334 Status
= CompareProductName(hSubKey
, PnpName
, ProductNameSize
, ProductName
);
339 if (NT_SUCCESS(Status
))
345 FreeItem(KeyInformation
);
350 /* no matching key found */
355 GetSysAudioDevicePnpName(
356 IN PDEVICE_OBJECT DeviceObject
,
357 IN ULONG DeviceIndex
,
363 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
365 /* first check if the device index is within bounds */
366 if (DeviceIndex
>= GetSysAudioDeviceCount(DeviceObject
))
367 return STATUS_INVALID_PARAMETER
;
369 /* setup the query request */
370 Pin
.Property
.Set
= KSPROPSETID_Sysaudio
;
371 Pin
.Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME
;
372 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
373 Pin
.PinId
= DeviceIndex
;
375 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
377 /* query sysaudio for the device path */
378 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
) + sizeof(ULONG
), NULL
, 0, &BytesReturned
);
380 /* check if the request failed */
381 if (Status
!= STATUS_BUFFER_TOO_SMALL
|| BytesReturned
== 0)
382 return STATUS_UNSUCCESSFUL
;
384 /* allocate buffer for the device */
385 *Device
= AllocateItem(NonPagedPool
, BytesReturned
);
387 return STATUS_INSUFFICIENT_RESOURCES
;
389 /* query sysaudio again for the device path */
390 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
) + sizeof(ULONG
), (PVOID
)*Device
, BytesReturned
, &BytesReturned
);
392 if (!NT_SUCCESS(Status
))
405 OUT PHANDLE DeviceHandle
,
406 OUT PFILE_OBJECT
* FileObject
)
411 /* now open the device */
412 Status
= WdmAudOpenSysAudioDevice(Device
, &hDevice
);
414 if (!NT_SUCCESS(Status
))
419 *DeviceHandle
= hDevice
;
423 Status
= ObReferenceObjectByHandle(hDevice
, FILE_READ_DATA
| FILE_WRITE_DATA
, IoFileObjectType
, KernelMode
, (PVOID
*)FileObject
, NULL
);
425 if (!NT_SUCCESS(Status
))