mirror of
https://github.com/reactos/reactos.git
synced 2024-07-27 22:58:42 +00:00
- Set a completion routine for irps send to lower devices by KsSynchronousIoControlDevice
- Fix a bug in PcPropertyHandler - Implement more aspects of IOCTL_GETCAPABILITIES svn path=/trunk/; revision=39728
This commit is contained in:
parent
dfb4c51505
commit
4c08a87ceb
|
@ -227,6 +227,21 @@ KsSetTargetState(
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CompletionRoutine(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context;
|
||||||
|
|
||||||
|
IoStatusBlock->Information = Irp->IoStatus.Information;
|
||||||
|
IoStatusBlock->Status = Irp->IoStatus.Status;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@implemented
|
@implemented
|
||||||
*/
|
*/
|
||||||
|
@ -269,14 +284,17 @@ KsSynchronousIoControlDevice(
|
||||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||||
IoStack->FileObject = FileObject;
|
IoStack->FileObject = FileObject;
|
||||||
|
|
||||||
|
IoSetCompletionRoutine(Irp, CompletionRoutine, (PVOID)&IoStatusBlock, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
Status = IoCallDriver(DeviceObject, Irp);
|
Status = IoCallDriver(DeviceObject, Irp);
|
||||||
if (Status == STATUS_PENDING)
|
if (Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL);
|
KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL);
|
||||||
|
Status = IoStatusBlock.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
*BytesReturned = IoStatusBlock.Information;
|
*BytesReturned = IoStatusBlock.Information;
|
||||||
return IoStatusBlock.Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ PcPropertyHandler(
|
||||||
{
|
{
|
||||||
for(Index = 0; Index < Descriptor->DeviceDescriptor->AutomationTable->PropertyCount; Index++)
|
for(Index = 0; Index < Descriptor->DeviceDescriptor->AutomationTable->PropertyCount; Index++)
|
||||||
{
|
{
|
||||||
if (IsEqualGUID(&Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Set, &Property->Set))
|
if (IsEqualGUID(Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Set, &Property->Set))
|
||||||
{
|
{
|
||||||
if (Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Id == Property->Id)
|
if (Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Id == Property->Id)
|
||||||
{
|
{
|
||||||
|
@ -171,17 +171,14 @@ PcPropertyHandler(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("Num of Property Sets %u\n", Descriptor->FilterPropertySet.FreeKsPropertySetOffset);
|
|
||||||
for(Index = 0; Index < Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++)
|
for(Index = 0; Index < Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++)
|
||||||
{
|
{
|
||||||
if (IsEqualGUIDAligned(&Property->Set, Descriptor->FilterPropertySet.Properties[Index].Set))
|
if (IsEqualGUIDAligned(&Property->Set, Descriptor->FilterPropertySet.Properties[Index].Set))
|
||||||
{
|
{
|
||||||
DPRINT("Found Property Set Properties %u\n", Descriptor->FilterPropertySet.Properties[Index].PropertiesCount);
|
|
||||||
for(ItemIndex = 0; ItemIndex < Descriptor->FilterPropertySet.Properties[Index].PropertiesCount; ItemIndex++)
|
for(ItemIndex = 0; ItemIndex < Descriptor->FilterPropertySet.Properties[Index].PropertiesCount; ItemIndex++)
|
||||||
{
|
{
|
||||||
if (Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].PropertyId == Property->Id)
|
if (Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].PropertyId == Property->Id)
|
||||||
{
|
{
|
||||||
DPRINT("Found property set identifier %u\n", Property->Id);
|
|
||||||
if (Property->Flags & KSPROPERTY_TYPE_SET)
|
if (Property->Flags & KSPROPERTY_TYPE_SET)
|
||||||
PropertyHandler = Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].SetPropertyHandler;
|
PropertyHandler = Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].SetPropertyHandler;
|
||||||
|
|
||||||
|
@ -215,7 +212,7 @@ PcPropertyHandler(
|
||||||
|
|
||||||
/* the information member is set by the handler */
|
/* the information member is set by the handler */
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
DPRINT("Result %x\n", Status);
|
DPRINT("Result %x Length %u\n", Status, Irp->IoStatus.Information);
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
#include "wdmaud.h"
|
#include "wdmaud.h"
|
||||||
|
|
||||||
|
const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
|
||||||
const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
|
const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
|
||||||
const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
|
const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
|
||||||
const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
|
const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
|
||||||
|
@ -371,42 +372,55 @@ WdmAudCapabilities(
|
||||||
IN PWDMAUD_CLIENT ClientInfo)
|
IN PWDMAUD_CLIENT ClientInfo)
|
||||||
{
|
{
|
||||||
KSP_PIN PinProperty;
|
KSP_PIN PinProperty;
|
||||||
KSPROPERTY Property;
|
|
||||||
KSCOMPONENTID ComponentId;
|
KSCOMPONENTID ComponentId;
|
||||||
KSMULTIPLE_ITEM * MultipleItem;
|
KSMULTIPLE_ITEM * MultipleItem;
|
||||||
ULONG BytesReturned;
|
ULONG BytesReturned;
|
||||||
PKSDATARANGE_AUDIO DataRangeAudio;
|
PKSDATARANGE_AUDIO DataRangeAudio;
|
||||||
PKSDATARANGE DataRange;
|
PKSDATARANGE DataRange;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG Index;
|
ULONG Index;
|
||||||
ULONG wChannels = 0;
|
ULONG wChannels = 0;
|
||||||
ULONG dwFormats = 0;
|
ULONG dwFormats = 0;
|
||||||
ULONG dwSupport = 0;
|
ULONG dwSupport = 0;
|
||||||
|
ULONG PinId;
|
||||||
|
|
||||||
Property.Set = KSPROPSETID_General;
|
DPRINT("WdmAudCapabilities entered\n");
|
||||||
Property.Id = KSPROPERTY_GENERAL_COMPONENTID;
|
|
||||||
Property.Flags = KSPROPERTY_TYPE_GET;
|
PinProperty.PinId = DeviceInfo->DeviceIndex; // used as index of the virtual audio device
|
||||||
|
PinProperty.Property.Set = KSPROPSETID_Sysaudio;
|
||||||
|
PinProperty.Property.Id = KSPROPERTY_SYSAUDIO_COMPONENT_ID;
|
||||||
|
PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
|
||||||
|
|
||||||
RtlZeroMemory(&ComponentId, sizeof(KSCOMPONENTID));
|
RtlZeroMemory(&ComponentId, sizeof(KSCOMPONENTID));
|
||||||
|
|
||||||
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
|
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
|
||||||
if (!NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("KSPROPERTY_GENERAL_COMPONENTID failed with %x\n", Status);
|
DeviceInfo->u.WaveOutCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7;
|
||||||
return SetIrpIoStatus(Irp, Status, 0);
|
DeviceInfo->u.WaveOutCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision);
|
||||||
}
|
}
|
||||||
|
|
||||||
PinProperty.PinId = 0; //FIXME
|
//FIXME
|
||||||
|
// Reserved index defines the audio device index
|
||||||
|
// pin offset should be first determined
|
||||||
|
// by determing the pin type of the target filter
|
||||||
|
PinId = 0;
|
||||||
|
|
||||||
|
PinProperty.Reserved = DeviceInfo->DeviceIndex;
|
||||||
|
PinProperty.PinId = PinId;
|
||||||
PinProperty.Property.Set = KSPROPSETID_Pin;
|
PinProperty.Property.Set = KSPROPSETID_Pin;
|
||||||
PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES;
|
PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES;
|
||||||
PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
|
PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
|
||||||
|
|
||||||
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)NULL, 0, &BytesReturned);
|
|
||||||
|
BytesReturned = 0;
|
||||||
|
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned);
|
||||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||||
{
|
{
|
||||||
DPRINT1("KSPROPERTY_PIN_DATARANGES failed with %x\n", Status);
|
|
||||||
return SetIrpIoStatus(Irp, Status, 0);
|
return SetIrpIoStatus(Irp, Status, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned);
|
MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned);
|
||||||
if (!MultipleItem)
|
if (!MultipleItem)
|
||||||
|
@ -415,7 +429,7 @@ WdmAudCapabilities(
|
||||||
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
|
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
ExFreePool(MultipleItem);
|
ExFreePool(MultipleItem);
|
||||||
|
@ -452,8 +466,8 @@ WdmAudCapabilities(
|
||||||
DeviceInfo->u.WaveOutCaps.dwFormats = dwFormats;
|
DeviceInfo->u.WaveOutCaps.dwFormats = dwFormats;
|
||||||
DeviceInfo->u.WaveOutCaps.dwSupport = dwSupport;
|
DeviceInfo->u.WaveOutCaps.dwSupport = dwSupport;
|
||||||
DeviceInfo->u.WaveOutCaps.wChannels = wChannels;
|
DeviceInfo->u.WaveOutCaps.wChannels = wChannels;
|
||||||
DeviceInfo->u.WaveOutCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7;
|
|
||||||
DeviceInfo->u.WaveOutCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision);
|
ExFreePool(MultipleItem);
|
||||||
|
|
||||||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,14 +261,14 @@ CreatePinWorkerRoutine(
|
||||||
ASSERT(WorkerContext->DispatchContext->FileObject != NULL);
|
ASSERT(WorkerContext->DispatchContext->FileObject != NULL);
|
||||||
ASSERT(WorkerContext->DispatchContext->Handle != NULL);
|
ASSERT(WorkerContext->DispatchContext->Handle != NULL);
|
||||||
ASSERT(WorkerContext->AudioClient);
|
ASSERT(WorkerContext->AudioClient);
|
||||||
ASSERT(WorkerContext->AudioClient->Handels);
|
ASSERT(WorkerContext->AudioClient->Handels);
|
||||||
ASSERT(WorkerContext->AudioClient->Handels[WorkerContext->AudioClient->NumDevices -1] == NULL);
|
ASSERT(WorkerContext->AudioClient->Handels[WorkerContext->AudioClient->NumDevices -1] == NULL);
|
||||||
|
|
||||||
/* store pin context */
|
/* store pin context */
|
||||||
FileObject->FsContext2 = (PVOID)WorkerContext->DispatchContext;
|
FileObject->FsContext2 = (PVOID)WorkerContext->DispatchContext;
|
||||||
|
|
||||||
/* store pin handle in client specific struct */
|
/* store pin handle in client specific struct */
|
||||||
WorkerContext->AudioClient->Handels[WorkerContext->AudioClient->NumDevices-1] = PinHandle;
|
WorkerContext->AudioClient->Handels[WorkerContext->AudioClient->NumDevices-1] = PinHandle;
|
||||||
|
|
||||||
DPRINT1("Successfully created Pin %p\n", WorkerContext->Irp);
|
DPRINT1("Successfully created Pin %p\n", WorkerContext->Irp);
|
||||||
*((PHANDLE)WorkerContext->Irp->UserBuffer) = PinHandle;
|
*((PHANDLE)WorkerContext->Irp->UserBuffer) = PinHandle;
|
||||||
|
@ -319,7 +319,37 @@ SysAudioHandleProperty(
|
||||||
Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
|
Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||||
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
|
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Sysaudio))
|
if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Pin))
|
||||||
|
{
|
||||||
|
/* ros specific request */
|
||||||
|
if (Property->Id == KSPROPERTY_PIN_DATARANGES)
|
||||||
|
{
|
||||||
|
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_PIN))
|
||||||
|
{
|
||||||
|
/* too small buffer */
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPROPERTY) + sizeof(ULONG));
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, ((KSP_PIN*)Property)->Reserved);
|
||||||
|
if (!Entry)
|
||||||
|
{
|
||||||
|
/* too small buffer */
|
||||||
|
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY,
|
||||||
|
(PVOID)IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
|
||||||
|
IoStack->Parameters.DeviceIoControl.InputBufferLength,
|
||||||
|
Irp->UserBuffer,
|
||||||
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength,
|
||||||
|
&BytesReturned);
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = BytesReturned;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Sysaudio))
|
||||||
{
|
{
|
||||||
if (Property->Id == KSPROPERTY_SYSAUDIO_COMPONENT_ID)
|
if (Property->Id == KSPROPERTY_SYSAUDIO_COMPONENT_ID)
|
||||||
{
|
{
|
||||||
|
@ -350,7 +380,7 @@ SysAudioHandleProperty(
|
||||||
PropertyRequest.Flags = KSPROPERTY_TYPE_GET;
|
PropertyRequest.Flags = KSPROPERTY_TYPE_GET;
|
||||||
|
|
||||||
/* call the filter */
|
/* call the filter */
|
||||||
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_WRITE_STREAM, (PVOID)&PropertyRequest, sizeof(KSPROPERTY), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
|
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PropertyRequest, sizeof(KSPROPERTY), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("KsSynchronousIoControlDevice failed with %x for KSPROPERTY_GENERAL_COMPONENTID\n", Status);
|
DPRINT1("KsSynchronousIoControlDevice failed with %x for KSPROPERTY_GENERAL_COMPONENTID\n", Status);
|
||||||
|
|
|
@ -27,8 +27,6 @@ Dispatch_fnDeviceIoControl(
|
||||||
DPRINT1("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
DPRINT1("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
|
||||||
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
|
||||||
{
|
{
|
||||||
return SysAudioHandleProperty(DeviceObject, Irp);
|
return SysAudioHandleProperty(DeviceObject, Irp);
|
||||||
|
@ -87,26 +85,26 @@ Dispatch_fnClose(
|
||||||
|
|
||||||
DPRINT1("Dispatch_fnClose called DeviceObject %p Irp %p\n", DeviceObject);
|
DPRINT1("Dispatch_fnClose called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
IoStatus = IoGetCurrentIrpStackLocation(Irp);
|
IoStatus = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
Client = (PSYSAUDIO_CLIENT)IoStatus->FileObject->FsContext2;
|
Client = (PSYSAUDIO_CLIENT)IoStatus->FileObject->FsContext2;
|
||||||
|
|
||||||
DPRINT1("Client %p NumDevices %u\n", Client, Client->NumDevices);
|
DPRINT1("Client %p NumDevices %u\n", Client, Client->NumDevices);
|
||||||
for(Index = 0; Index < Client->NumDevices; Index++)
|
for(Index = 0; Index < Client->NumDevices; Index++)
|
||||||
{
|
{
|
||||||
if (Client->Handels[Index])
|
if (Client->Handels[Index])
|
||||||
{
|
{
|
||||||
ZwClose(Client->Handels[Index]);
|
ZwClose(Client->Handels[Index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Client->Handels)
|
if (Client->Handels)
|
||||||
ExFreePool(Client->Handels);
|
ExFreePool(Client->Handels);
|
||||||
|
|
||||||
if (Client->Devices)
|
if (Client->Devices)
|
||||||
ExFreePool(Client->Devices);
|
ExFreePool(Client->Devices);
|
||||||
|
|
||||||
ExFreePool(Client);
|
ExFreePool(Client);
|
||||||
|
|
||||||
//FIXME
|
//FIXME
|
||||||
// cleanup resources
|
// cleanup resources
|
||||||
|
|
Loading…
Reference in a new issue