Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensup.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel Streaming 00004 * FILE: drivers/wdm/audio/legacy/wdmaud/sup.c 00005 * PURPOSE: Misc support routines 00006 * PROGRAMMER: Andrew Greenwood 00007 * Johannes Anderwald 00008 */ 00009 #include "wdmaud.h" 00010 00011 PVOID 00012 AllocateItem( 00013 IN POOL_TYPE PoolType, 00014 IN SIZE_T NumberOfBytes) 00015 { 00016 PVOID Item = ExAllocatePool(PoolType, NumberOfBytes); 00017 if (!Item) 00018 return Item; 00019 00020 RtlZeroMemory(Item, NumberOfBytes); 00021 return Item; 00022 } 00023 00024 VOID 00025 FreeItem( 00026 IN PVOID Item) 00027 { 00028 ExFreePool(Item); 00029 } 00030 00031 00032 00033 ULONG 00034 GetSysAudioDeviceCount( 00035 IN PDEVICE_OBJECT DeviceObject) 00036 { 00037 PWDMAUD_DEVICE_EXTENSION DeviceExtension; 00038 KSPROPERTY Pin; 00039 ULONG Count, BytesReturned; 00040 NTSTATUS Status; 00041 00042 /* setup the query request */ 00043 Pin.Set = KSPROPSETID_Sysaudio; 00044 Pin.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT; 00045 Pin.Flags = KSPROPERTY_TYPE_GET; 00046 00047 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00048 00049 /* query sysaudio for the device count */ 00050 Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned); 00051 if (!NT_SUCCESS(Status)) 00052 return 0; 00053 00054 return Count; 00055 } 00056 00057 00058 NTSTATUS 00059 SetIrpIoStatus( 00060 IN PIRP Irp, 00061 IN NTSTATUS Status, 00062 IN ULONG Length) 00063 { 00064 Irp->IoStatus.Information = Length; 00065 Irp->IoStatus.Status = Status; 00066 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00067 return Status; 00068 00069 } 00070 00071 ULONG 00072 ClosePin( 00073 IN PWDMAUD_CLIENT ClientInfo, 00074 IN ULONG FilterId, 00075 IN ULONG PinId, 00076 IN SOUND_DEVICE_TYPE DeviceType) 00077 { 00078 ULONG Index; 00079 00080 for(Index = 0; Index < ClientInfo->NumPins; Index++) 00081 { 00082 if (ClientInfo->hPins[Index].FilterId == FilterId && ClientInfo->hPins[Index].PinId == PinId && ClientInfo->hPins[Index].Handle && ClientInfo->hPins[Index].Type == DeviceType) 00083 { 00084 if (ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) 00085 { 00086 ZwClose(ClientInfo->hPins[Index].Handle); 00087 } 00088 ClientInfo->hPins[Index].Handle = NULL; 00089 return Index; 00090 } 00091 } 00092 return MAXULONG; 00093 } 00094 00095 NTSTATUS 00096 InsertPinHandle( 00097 IN PWDMAUD_CLIENT ClientInfo, 00098 IN ULONG FilterId, 00099 IN ULONG PinId, 00100 IN SOUND_DEVICE_TYPE DeviceType, 00101 IN HANDLE PinHandle, 00102 IN ULONG FreeIndex) 00103 { 00104 PWDMAUD_HANDLE Handles; 00105 00106 if (FreeIndex != MAXULONG) 00107 { 00108 /* re-use a free index */ 00109 ClientInfo->hPins[FreeIndex].Handle = PinHandle; 00110 ClientInfo->hPins[FreeIndex].FilterId = FilterId; 00111 ClientInfo->hPins[FreeIndex].PinId = PinId; 00112 ClientInfo->hPins[FreeIndex].Type = DeviceType; 00113 00114 return STATUS_SUCCESS; 00115 } 00116 00117 Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); 00118 00119 if (!Handles) 00120 return STATUS_INSUFFICIENT_RESOURCES; 00121 00122 if (ClientInfo->NumPins) 00123 { 00124 RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); 00125 FreeItem(ClientInfo->hPins); 00126 } 00127 00128 ClientInfo->hPins = Handles; 00129 ClientInfo->hPins[ClientInfo->NumPins].Handle = PinHandle; 00130 ClientInfo->hPins[ClientInfo->NumPins].Type = DeviceType; 00131 ClientInfo->hPins[ClientInfo->NumPins].FilterId = FilterId; 00132 ClientInfo->hPins[ClientInfo->NumPins].PinId = PinId; 00133 ClientInfo->NumPins++; 00134 00135 return STATUS_SUCCESS; 00136 } 00137 00138 PKEY_VALUE_PARTIAL_INFORMATION 00139 ReadKeyValue( 00140 IN HANDLE hSubKey, 00141 IN PUNICODE_STRING KeyName) 00142 { 00143 NTSTATUS Status; 00144 ULONG Length; 00145 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation; 00146 00147 /* now query MatchingDeviceId key */ 00148 Status = ZwQueryValueKey(hSubKey, KeyName, KeyValuePartialInformation, NULL, 0, &Length); 00149 00150 /* check for success */ 00151 if (Status != STATUS_BUFFER_TOO_SMALL) 00152 return NULL; 00153 00154 /* allocate a buffer for key data */ 00155 PartialInformation = AllocateItem(NonPagedPool, Length); 00156 00157 if (!PartialInformation) 00158 return NULL; 00159 00160 00161 /* now query MatchingDeviceId key */ 00162 Status = ZwQueryValueKey(hSubKey, KeyName, KeyValuePartialInformation, PartialInformation, Length, &Length); 00163 00164 /* check for success */ 00165 if (!NT_SUCCESS(Status)) 00166 { 00167 FreeItem(PartialInformation); 00168 return NULL; 00169 } 00170 00171 if (PartialInformation->Type != REG_SZ) 00172 { 00173 /* invalid key type */ 00174 FreeItem(PartialInformation); 00175 return NULL; 00176 } 00177 00178 return PartialInformation; 00179 } 00180 00181 00182 NTSTATUS 00183 CompareProductName( 00184 IN HANDLE hSubKey, 00185 IN LPWSTR PnpName, 00186 IN ULONG ProductNameSize, 00187 OUT LPWSTR ProductName) 00188 { 00189 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation; 00190 UNICODE_STRING DriverDescName = RTL_CONSTANT_STRING(L"DriverDesc"); 00191 UNICODE_STRING MatchingDeviceIdName = RTL_CONSTANT_STRING(L"MatchingDeviceId"); 00192 ULONG Length; 00193 LPWSTR DeviceName; 00194 00195 /* read MatchingDeviceId value */ 00196 PartialInformation = ReadKeyValue(hSubKey, &MatchingDeviceIdName); 00197 00198 if (!PartialInformation) 00199 return STATUS_UNSUCCESSFUL; 00200 00201 00202 /* extract last '&' */ 00203 DeviceName = wcsrchr((LPWSTR)PartialInformation->Data, L'&'); 00204 ASSERT(DeviceName); 00205 /* terminate it */ 00206 DeviceName[0] = L'\0'; 00207 00208 Length = wcslen((LPWSTR)PartialInformation->Data); 00209 00210 DPRINT("DeviceName %S PnpName %S Length %u\n", (LPWSTR)PartialInformation->Data, PnpName, Length); 00211 00212 if (_wcsnicmp((LPWSTR)PartialInformation->Data, &PnpName[4], Length)) 00213 { 00214 FreeItem(PartialInformation); 00215 return STATUS_NO_MATCH; 00216 } 00217 00218 /* free buffer */ 00219 FreeItem(PartialInformation); 00220 00221 /* read DriverDescName value */ 00222 PartialInformation = ReadKeyValue(hSubKey, &DriverDescName); 00223 00224 if (!PartialInformation) 00225 { 00226 /* failed to read driver desc key */ 00227 return STATUS_UNSUCCESSFUL; 00228 } 00229 00230 /* copy key name */ 00231 Length = min(ProductNameSize * sizeof(WCHAR), PartialInformation->DataLength); 00232 RtlMoveMemory(ProductName, (PVOID)PartialInformation->Data, Length); 00233 00234 /* zero terminate it */ 00235 ProductName[ProductNameSize-1] = L'\0'; 00236 00237 /* free buffer */ 00238 FreeItem(PartialInformation); 00239 00240 return STATUS_SUCCESS; 00241 } 00242 00243 00244 00245 NTSTATUS 00246 FindProductName( 00247 IN LPWSTR PnpName, 00248 IN ULONG ProductNameSize, 00249 OUT LPWSTR ProductName) 00250 { 00251 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E96C-E325-11CE-BFC1-08002BE10318}"); 00252 00253 UNICODE_STRING SubKeyName; 00254 WCHAR SubKey[20]; 00255 OBJECT_ATTRIBUTES ObjectAttributes; 00256 HANDLE hKey, hSubKey; 00257 NTSTATUS Status; 00258 ULONG Length, Index; 00259 PKEY_FULL_INFORMATION KeyInformation; 00260 00261 for(Index = 0; Index < wcslen(PnpName); Index++) 00262 { 00263 if (PnpName[Index] == '#') 00264 PnpName[Index] = L'\\'; 00265 } 00266 00267 00268 /* initialize key attributes */ 00269 InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, NULL, NULL); 00270 00271 /* open the key */ 00272 Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes); 00273 00274 /* check for success */ 00275 if (!NT_SUCCESS(Status)) 00276 return Status; 00277 00278 /* query num of subkeys */ 00279 Status = ZwQueryKey(hKey, KeyFullInformation, NULL, 0, &Length); 00280 00281 if (Status != STATUS_BUFFER_TOO_SMALL) 00282 { 00283 DPRINT1("ZwQueryKey failed with %x\n", Status); 00284 /* failed */ 00285 ZwClose(hKey); 00286 return Status; 00287 } 00288 00289 /* allocate key information struct */ 00290 KeyInformation = AllocateItem(NonPagedPool, Length); 00291 if (!KeyInformation) 00292 { 00293 /* no memory */ 00294 ZwClose(hKey); 00295 return STATUS_INSUFFICIENT_RESOURCES; 00296 } 00297 00298 /* query num of subkeys */ 00299 Status = ZwQueryKey(hKey, KeyFullInformation, (PVOID)KeyInformation, Length, &Length); 00300 00301 if (!NT_SUCCESS(Status)) 00302 { 00303 DPRINT1("ZwQueryKey failed with %x\n", Status); 00304 FreeItem(KeyInformation); 00305 ZwClose(hKey); 00306 return Status; 00307 } 00308 00309 /* now iterate through all subkeys */ 00310 for(Index = 0; Index < KeyInformation->SubKeys; Index++) 00311 { 00312 /* subkeys are always in the format 0000-XXXX */ 00313 swprintf(SubKey, L"%04u", Index); 00314 00315 /* initialize subkey name */ 00316 RtlInitUnicodeString(&SubKeyName, SubKey); 00317 00318 /* initialize key attributes */ 00319 InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, hKey, NULL); 00320 00321 /* open the sub key */ 00322 Status = ZwOpenKey(&hSubKey, GENERIC_READ, &ObjectAttributes); 00323 00324 /* check for success */ 00325 if (NT_SUCCESS(Status)) 00326 { 00327 /* compare product name */ 00328 Status = CompareProductName(hSubKey, PnpName, ProductNameSize, ProductName); 00329 00330 /* close subkey */ 00331 ZwClose(hSubKey); 00332 00333 if (NT_SUCCESS(Status)) 00334 break; 00335 } 00336 } 00337 00338 /* free buffer */ 00339 FreeItem(KeyInformation); 00340 00341 /* close key */ 00342 ZwClose(hKey); 00343 00344 /* no matching key found */ 00345 return Status; 00346 } 00347 00348 NTSTATUS 00349 GetSysAudioDevicePnpName( 00350 IN PDEVICE_OBJECT DeviceObject, 00351 IN ULONG DeviceIndex, 00352 OUT LPWSTR * Device) 00353 { 00354 ULONG BytesReturned; 00355 KSP_PIN Pin; 00356 NTSTATUS Status; 00357 PWDMAUD_DEVICE_EXTENSION DeviceExtension; 00358 00359 /* first check if the device index is within bounds */ 00360 if (DeviceIndex >= GetSysAudioDeviceCount(DeviceObject)) 00361 return STATUS_INVALID_PARAMETER; 00362 00363 /* setup the query request */ 00364 Pin.Property.Set = KSPROPSETID_Sysaudio; 00365 Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME; 00366 Pin.Property.Flags = KSPROPERTY_TYPE_GET; 00367 Pin.PinId = DeviceIndex; 00368 00369 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00370 00371 /* query sysaudio for the device path */ 00372 Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), NULL, 0, &BytesReturned); 00373 00374 /* check if the request failed */ 00375 if (Status != STATUS_BUFFER_TOO_SMALL || BytesReturned == 0) 00376 return STATUS_UNSUCCESSFUL; 00377 00378 /* allocate buffer for the device */ 00379 *Device = AllocateItem(NonPagedPool, BytesReturned); 00380 if (!Device) 00381 return STATUS_INSUFFICIENT_RESOURCES; 00382 00383 /* query sysaudio again for the device path */ 00384 Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), (PVOID)*Device, BytesReturned, &BytesReturned); 00385 00386 if (!NT_SUCCESS(Status)) 00387 { 00388 /* failed */ 00389 FreeItem(*Device); 00390 return Status; 00391 } 00392 00393 return Status; 00394 } 00395 00396 NTSTATUS 00397 OpenDevice( 00398 IN LPWSTR Device, 00399 OUT PHANDLE DeviceHandle, 00400 OUT PFILE_OBJECT * FileObject) 00401 { 00402 NTSTATUS Status; 00403 HANDLE hDevice; 00404 00405 /* now open the device */ 00406 Status = WdmAudOpenSysAudioDevice(Device, &hDevice); 00407 00408 if (!NT_SUCCESS(Status)) 00409 { 00410 return Status; 00411 } 00412 00413 *DeviceHandle = hDevice; 00414 00415 if (FileObject) 00416 { 00417 Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL); 00418 00419 if (!NT_SUCCESS(Status)) 00420 { 00421 ZwClose(hDevice); 00422 } 00423 } 00424 00425 return Status; 00426 00427 } Generated on Sun May 27 2012 04:28:40 for ReactOS by
1.7.6.1
|