mirror of
https://github.com/reactos/reactos.git
synced 2024-07-12 07:35:10 +00:00
[USBCCGP]
- Implement counting of all interface descriptors - Store device descriptor and configuration descriptor in pdo device extension - Store all interface descriptors for an composite audio device - Implement parsing and constructing a special configuration descriptor for each individual device function - Implement URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE for device descriptor and configuration descriptor - USBGCCGP now receives select configuration request - Tested in XP + Ros USB Stack + USB Audio Device svn path=/branches/usb-bringup-trunk/; revision=55261
This commit is contained in:
parent
43220d11a5
commit
a960e537aa
|
@ -201,6 +201,66 @@ CountInterfaceDescriptors(
|
||||||
return Count;
|
return Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
AllocateInterfaceDescriptorsArray(
|
||||||
|
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||||
|
OUT PUSB_INTERFACE_DESCRIPTOR **OutArray)
|
||||||
|
{
|
||||||
|
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||||
|
PVOID CurrentPosition;
|
||||||
|
ULONG Count = 0;
|
||||||
|
PUSB_INTERFACE_DESCRIPTOR *Array;
|
||||||
|
|
||||||
|
Count = CountInterfaceDescriptors(ConfigurationDescriptor);
|
||||||
|
ASSERT(Count);
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate array
|
||||||
|
//
|
||||||
|
Array = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * Count);
|
||||||
|
if (!Array)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
//
|
||||||
|
// enumerate all interfaces
|
||||||
|
//
|
||||||
|
CurrentPosition = ConfigurationDescriptor;
|
||||||
|
Count = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// find next descriptor
|
||||||
|
//
|
||||||
|
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, CurrentPosition, -1, -1, -1, -1, -1);
|
||||||
|
if (!InterfaceDescriptor)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store descriptor
|
||||||
|
//
|
||||||
|
Array[Count] = InterfaceDescriptor;
|
||||||
|
Count++;
|
||||||
|
|
||||||
|
//
|
||||||
|
// advance to next descriptor
|
||||||
|
//
|
||||||
|
CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||||
|
|
||||||
|
}while(TRUE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
*OutArray = Array;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
USBCCGP_ScanConfigurationDescriptor(
|
USBCCGP_ScanConfigurationDescriptor(
|
||||||
|
|
|
@ -279,7 +279,9 @@ FDO_CreateChildPdo(
|
||||||
PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index];
|
PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index];
|
||||||
PDODeviceExtension->NextDeviceObject = DeviceObject;
|
PDODeviceExtension->NextDeviceObject = DeviceObject;
|
||||||
PDODeviceExtension->FunctionIndex = Index;
|
PDODeviceExtension->FunctionIndex = Index;
|
||||||
|
PDODeviceExtension->ConfigurationDescriptor = FDODeviceExtension->ConfigurationDescriptor;
|
||||||
RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||||
|
RtlCopyMemory(&PDODeviceExtension->DeviceDescriptor, &FDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
||||||
|
|
||||||
//
|
//
|
||||||
// patch the stack size
|
// patch the stack size
|
||||||
|
|
|
@ -787,23 +787,18 @@ USBCCGP_EnumWithAudioLegacy(
|
||||||
FDODeviceExtension->FunctionDescriptor[0].FunctionNumber = 0;
|
FDODeviceExtension->FunctionDescriptor[0].FunctionNumber = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME: how many interfaces should be stored?
|
// store interfaces
|
||||||
//
|
//
|
||||||
|
Status = AllocateInterfaceDescriptorsArray(FDODeviceExtension->ConfigurationDescriptor, &FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList);
|
||||||
FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * 1);
|
if (!NT_SUCCESS(Status))
|
||||||
if (!FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList)
|
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// no memory
|
// failed to allocate descriptor array
|
||||||
//
|
//
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
DPRINT1("[USBCCGP] Failed to allocate descriptor array %x\n", Status);
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// store interface descriptor
|
|
||||||
//
|
|
||||||
FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList[0] = InterfaceDescriptor;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// now init the device ids
|
// now init the device ids
|
||||||
//
|
//
|
||||||
|
@ -817,6 +812,11 @@ USBCCGP_EnumWithAudioLegacy(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// number of interfaces
|
||||||
|
//
|
||||||
|
FDODeviceExtension->FunctionDescriptor[0].NumberOfInterfaces = CountInterfaceDescriptors(FDODeviceExtension->ConfigurationDescriptor);
|
||||||
|
|
||||||
//
|
//
|
||||||
// store function count
|
// store function count
|
||||||
//
|
//
|
||||||
|
|
|
@ -323,6 +323,280 @@ PDO_HandlePnp(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBCCGP_BuildConfigurationDescriptor(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
|
||||||
|
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||||
|
ULONG TotalSize, Index;
|
||||||
|
PURB Urb;
|
||||||
|
PVOID Buffer;
|
||||||
|
PUCHAR BufferPtr;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
DPRINT1("USBCCGP_BuildConfigurationDescriptor\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get configuration descriptor
|
||||||
|
//
|
||||||
|
ConfigurationDescriptor = PDODeviceExtension->ConfigurationDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// calculate size of configuration descriptor
|
||||||
|
//
|
||||||
|
TotalSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
|
||||||
|
|
||||||
|
for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get current interface descriptor
|
||||||
|
//
|
||||||
|
InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
|
||||||
|
|
||||||
|
//
|
||||||
|
// add to size and move to next descriptor
|
||||||
|
//
|
||||||
|
TotalSize += InterfaceDescriptor->bLength;
|
||||||
|
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// reached end of configuration descriptor
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// association descriptors are removed
|
||||||
|
//
|
||||||
|
if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
|
||||||
|
{
|
||||||
|
if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// reached next descriptor
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// append size
|
||||||
|
//
|
||||||
|
TotalSize += InterfaceDescriptor->bLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// move to next descriptor
|
||||||
|
//
|
||||||
|
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||||
|
}while(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// now allocate temporary buffer for the configuration descriptor
|
||||||
|
//
|
||||||
|
Buffer = AllocateItem(NonPagedPool, TotalSize);
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate buffer
|
||||||
|
//
|
||||||
|
DPRINT1("[USBCCGP] Failed to allocate %lu Bytes\n", TotalSize);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// first copy the configuration descriptor
|
||||||
|
//
|
||||||
|
RtlCopyMemory(Buffer, ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
|
||||||
|
BufferPtr = (PUCHAR)((ULONG_PTR)Buffer + ConfigurationDescriptor->bLength);
|
||||||
|
|
||||||
|
for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get current interface descriptor
|
||||||
|
//
|
||||||
|
InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy descriptor and move to next descriptor
|
||||||
|
//
|
||||||
|
RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
|
||||||
|
BufferPtr += InterfaceDescriptor->bLength;
|
||||||
|
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// reached end of configuration descriptor
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// association descriptors are removed
|
||||||
|
//
|
||||||
|
if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
|
||||||
|
{
|
||||||
|
if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// reached next descriptor
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy descriptor
|
||||||
|
//
|
||||||
|
RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
|
||||||
|
BufferPtr += InterfaceDescriptor->bLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// move to next descriptor
|
||||||
|
//
|
||||||
|
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||||
|
}while(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// modify configuration descriptor
|
||||||
|
//
|
||||||
|
ConfigurationDescriptor = Buffer;
|
||||||
|
ConfigurationDescriptor->wTotalLength = TotalSize;
|
||||||
|
ConfigurationDescriptor->bNumInterfaces = PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
ASSERT(Urb);
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy descriptor
|
||||||
|
//
|
||||||
|
RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, min(TotalSize, Urb->UrbControlDescriptorRequest.TransferBufferLength));
|
||||||
|
|
||||||
|
//
|
||||||
|
// store final size
|
||||||
|
//
|
||||||
|
Urb->UrbControlDescriptorRequest.TransferBufferLength = TotalSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// free buffer
|
||||||
|
//
|
||||||
|
FreeItem(Buffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
PDO_HandleInternalDeviceControl(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PURB Urb;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
ASSERT(Urb);
|
||||||
|
|
||||||
|
if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
|
||||||
|
{
|
||||||
|
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x\n", Urb->UrbHeader.Function);
|
||||||
|
|
||||||
|
if(Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// is the buffer big enough
|
||||||
|
//
|
||||||
|
if (Urb->UrbControlDescriptorRequest.TransferBufferLength < sizeof(USB_DEVICE_DESCRIPTOR))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// invalid buffer size
|
||||||
|
//
|
||||||
|
DPRINT1("[USBCCGP] invalid device descriptor size %lu\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
|
||||||
|
Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_INVALID_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy device descriptor
|
||||||
|
//
|
||||||
|
ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
|
||||||
|
RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &PDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// build configuration descriptor
|
||||||
|
//
|
||||||
|
Status = USBCCGP_BuildConfigurationDescriptor(DeviceObject, Irp);
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DPRINT1("IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||||
|
DPRINT1("InputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.InputBufferLength);
|
||||||
|
DPRINT1("OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
|
||||||
|
DPRINT1("Type3InputBuffer %p\n", IoStack->Parameters.DeviceIoControl.Type3InputBuffer);
|
||||||
|
|
||||||
|
ASSERT(FALSE);
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
PDO_Dispatch(
|
PDO_Dispatch(
|
||||||
|
@ -339,6 +613,8 @@ PDO_Dispatch(
|
||||||
{
|
{
|
||||||
case IRP_MJ_PNP:
|
case IRP_MJ_PNP:
|
||||||
return PDO_HandlePnp(DeviceObject, Irp);
|
return PDO_HandlePnp(DeviceObject, Irp);
|
||||||
|
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
|
||||||
|
return PDO_HandleInternalDeviceControl(DeviceObject, Irp);
|
||||||
default:
|
default:
|
||||||
DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
|
DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
|
|
|
@ -50,6 +50,8 @@ typedef struct
|
||||||
PDEVICE_OBJECT NextDeviceObject; // next device object
|
PDEVICE_OBJECT NextDeviceObject; // next device object
|
||||||
DEVICE_CAPABILITIES Capabilities; // device capabilities
|
DEVICE_CAPABILITIES Capabilities; // device capabilities
|
||||||
ULONG FunctionIndex; // function index
|
ULONG FunctionIndex; // function index
|
||||||
|
USB_DEVICE_DESCRIPTOR DeviceDescriptor; // usb device descriptor
|
||||||
|
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; // usb configuration descriptor
|
||||||
}PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
}PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
||||||
|
|
||||||
/* descriptor.c */
|
/* descriptor.c */
|
||||||
|
@ -73,6 +75,15 @@ USBCCGP_GetDescriptor(
|
||||||
IN LANGID LanguageId,
|
IN LANGID LanguageId,
|
||||||
OUT PVOID *OutDescriptor);
|
OUT PVOID *OutDescriptor);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
CountInterfaceDescriptors(
|
||||||
|
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
AllocateInterfaceDescriptorsArray(
|
||||||
|
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||||
|
OUT PUSB_INTERFACE_DESCRIPTOR **OutArray);
|
||||||
|
|
||||||
/* misc.c */
|
/* misc.c */
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
Loading…
Reference in a new issue