X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fio%2Fiocomp.c;h=01adc7479c7f228061ef8aa3df90c344a93e360f;hp=61fcdbb1454ec25738f5229a3ab3d4812b967583;hb=3354ce28a8597585980ee88084f5c06ae59df604;hpb=59d5c9f0163b20fbedcfba4dc031e79d9e0764d5 diff --git a/reactos/ntoskrnl/io/iocomp.c b/reactos/ntoskrnl/io/iocomp.c index 61fcdbb1454..01adc7479c7 100644 --- a/reactos/ntoskrnl/io/iocomp.c +++ b/reactos/ntoskrnl/io/iocomp.c @@ -1,314 +1,564 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/iocomp.c - * PURPOSE: - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - Changed NtQueryIoCompletion + * FILE: ntoskrnl/io/iocomp.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ -#include -#define NTOS_MODE_KERNEL -#include -//#include - +#include #define NDEBUG #include -#define IOC_TAG TAG('I', 'O', 'C', 'T') - -POBJECT_TYPE ExIoCompletionType; +POBJECT_TYPE IoCompletionType; -NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside; +NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside; -static GENERIC_MAPPING ExIoCompletionMapping = +static GENERIC_MAPPING IopCompletionMapping = { - STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE, - STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE, - STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE, - IO_COMPLETION_ALL_ACCESS + STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE, + STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE, + IO_COMPLETION_ALL_ACCESS +}; + +static const INFORMATION_CLASS_INFO IoCompletionInfoClass[] = { + + /* IoCompletionBasicInformation */ + ICI_SQ_SAME( sizeof(IO_COMPLETION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), }; /* FUNCTIONS *****************************************************************/ -NTSTATUS +VOID STDCALL -NtpCreateIoCompletion( - PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - POBJECT_ATTRIBUTES ObjectAttributes - ) +IopFreeIoCompletionPacket(PIO_COMPLETION_PACKET Packet) { - DPRINT("NtpCreateIoCompletion(ObjectBody %x, Parent %x, RemainingPath %S)\n", - ObjectBody, Parent, RemainingPath); - - if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) - { - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; + PKPRCB Prcb = KeGetCurrentPrcb(); + PNPAGED_LOOKASIDE_LIST List; + + /* Use the P List */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[LookasideCompletionList].P; + List->L.TotalFrees++; + + /* Check if the Free was within the Depth or not */ + if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) + { + /* Let the balancer know */ + List->L.FreeMisses++; + + /* Use the L List */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[LookasideCompletionList].L; + List->L.TotalFrees++; + + /* Check if the Free was within the Depth or not */ + if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) + { + /* All lists failed, use the pool */ + List->L.FreeMisses++; + ExFreePool(Packet); + } + } + + /* The free was within dhe Depth */ + InterlockedPushEntrySList(&List->L.ListHead, (PSINGLE_LIST_ENTRY)Packet); } -VOID STDCALL -NtpDeleteIoCompletion(PVOID ObjectBody) +VOID +STDCALL +IopDeleteIoCompletion(PVOID ObjectBody) { - PKQUEUE Queue = ObjectBody; - - DPRINT("NtpDeleteIoCompletion()\n"); - - KeRundownQueue(Queue); + PKQUEUE Queue = ObjectBody; + PLIST_ENTRY FirstEntry; + PLIST_ENTRY CurrentEntry; + PIRP Irp; + PIO_COMPLETION_PACKET Packet; + + DPRINT("IopDeleteIoCompletion()\n"); + + /* Rundown the Queue */ + FirstEntry = KeRundownQueue(Queue); + + /* Clean up the IRPs */ + if (FirstEntry) { + + CurrentEntry = FirstEntry; + do { + + /* Get the Packet */ + Packet = CONTAINING_RECORD(CurrentEntry, IO_COMPLETION_PACKET, ListEntry); + + /* Go to next Entry */ + CurrentEntry = CurrentEntry->Flink; + + /* Check if it's part of an IRP, or a separate packet */ + if (Packet->PacketType == IrpCompletionPacket) + { + /* Get the IRP and free it */ + Irp = CONTAINING_RECORD(Packet, IRP, Tail.Overlay.ListEntry); + IoFreeIrp(Irp); + } + else + { + /* Use common routine */ + IopFreeIoCompletionPacket(Packet); + } + } while (FirstEntry != CurrentEntry); + } } +/* + * @implemented + */ +NTSTATUS +STDCALL +IoSetIoCompletion(IN PVOID IoCompletion, + IN PVOID KeyContext, + IN PVOID ApcContext, + IN NTSTATUS IoStatus, + IN ULONG_PTR IoStatusInformation, + IN BOOLEAN Quota) +{ + PKQUEUE Queue = (PKQUEUE)IoCompletion; + PNPAGED_LOOKASIDE_LIST List; + PKPRCB Prcb = KeGetCurrentPrcb(); + PIO_COMPLETION_PACKET Packet; + + /* Get the P List */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[LookasideCompletionList].P; + + /* Try to allocate the Packet */ + List->L.TotalAllocates++; + Packet = (PVOID)InterlockedPopEntrySList(&List->L.ListHead); + + /* Check if that failed, use the L list if it did */ + if (!Packet) + { + /* Let the balancer know */ + List->L.AllocateMisses++; + + /* Get L List */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[LookasideCompletionList].L; + + /* Try to allocate the Packet */ + List->L.TotalAllocates++; + Packet = (PVOID)InterlockedPopEntrySList(&List->L.ListHead); + } + + /* Still failed, use pool */ + if (!Packet) + { + /* Let the balancer know */ + List->L.AllocateMisses++; + + /* Allocate from Nonpaged Pool */ + Packet = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Packet), IOC_TAG); + } + + /* Make sure we have one by now... */ + if (Packet) + { + /* Set up the Packet */ + Packet->PacketType = IrpMiniCompletionPacket; + Packet->Key = KeyContext; + Packet->Context = ApcContext; + Packet->IoStatus.Status = IoStatus; + Packet->IoStatus.Information = IoStatusInformation; + + /* Insert the Queue */ + KeInsertQueue(Queue, &Packet->ListEntry); + } + else + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Return Success */ + return STATUS_SUCCESS; +} -VOID -NtInitializeIoCompletionImplementation(VOID) +/* + * @unimplemented + */ +NTSTATUS +STDCALL +IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_COMPLETION_ROUTINE CompletionRoutine, + IN PVOID Context, + IN BOOLEAN InvokeOnSuccess, + IN BOOLEAN InvokeOnError, + IN BOOLEAN InvokeOnCancel) { - ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); - - RtlCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion"); - - ExIoCompletionType->Tag = IOC_TAG; - ExIoCompletionType->MaxObjects = ULONG_MAX; - ExIoCompletionType->MaxHandles = ULONG_MAX; - ExIoCompletionType->TotalObjects = 0; - ExIoCompletionType->TotalHandles = 0; - ExIoCompletionType->PagedPoolCharge = 0; - ExIoCompletionType->NonpagedPoolCharge = sizeof(KQUEUE); - ExIoCompletionType->Mapping = &ExIoCompletionMapping; - ExIoCompletionType->Dump = NULL; - ExIoCompletionType->Open = NULL; - ExIoCompletionType->Close = NULL; - ExIoCompletionType->Delete = NtpDeleteIoCompletion; - ExIoCompletionType->Parse = NULL; - ExIoCompletionType->Security = NULL; - ExIoCompletionType->QueryName = NULL; - ExIoCompletionType->OkayToClose = NULL; - ExIoCompletionType->Create = NtpCreateIoCompletion; - ExIoCompletionType->DuplicationNotify = NULL; - - ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside, - NULL, - NULL, - 0, - sizeof(IO_COMPLETION_PACKET), - IOC_TAG, - 0); + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } +VOID +FASTCALL +IopInitIoCompletionImplementation(VOID) +{ + OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; + UNICODE_STRING Name; + + DPRINT1("Creating IoCompletion Object Type\n"); + + /* Initialize the Driver object type */ + RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); + RtlInitUnicodeString(&Name, L"IoCompletion"); + ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); + ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KQUEUE); + ObjectTypeInitializer.PoolType = NonPagedPool; + ObjectTypeInitializer.ValidAccessMask = IO_COMPLETION_ALL_ACCESS; + ObjectTypeInitializer.UseDefaultObject = TRUE; + ObjectTypeInitializer.GenericMapping = IopCompletionMapping; + ObjectTypeInitializer.DeleteProcedure = IopDeleteIoCompletion; + ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoCompletionType); +} NTSTATUS STDCALL -NtCreateIoCompletion( - OUT PHANDLE IoCompletionHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG NumberOfConcurrentThreads - ) +NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG NumberOfConcurrentThreads) { - PKQUEUE Queue; - NTSTATUS Status; - - Status = ObRosCreateObject(IoCompletionHandle, - DesiredAccess, - ObjectAttributes, - ExIoCompletionType, - (PVOID*)&Queue); - - if (NT_SUCCESS(Status)) - { - (void) KeInitializeQueue(Queue, NumberOfConcurrentThreads); - ObDereferenceObject(Queue); - } + PKQUEUE Queue; + HANDLE hIoCompletionHandle; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; - return Status; - /* + PAGED_CODE(); - CompletionPort = NULL OR ExistingCompletionPort + if (PreviousMode != KernelMode) { - */ - + _SEH_TRY { -} + ProbeForWrite(IoCompletionHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } _SEH_HANDLE { -/* -DesiredAccess: -ZERO -IO_COMPLETION_QUERY_STATE Query access -IO_COMPLETION_MODIFY_STATE Modify access -IO_COMPLETION_ALL_ACCESS All of the preceding + STANDARD_RIGHTS_ALL - -ObjectAttributes -OBJ_OPENLINK and OBJ_PERMANENT are not valid attributes - -Return Value -STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED or -STATUS_OBJECT_NAME_NOT_FOUND. -*/ -NTSTATUS -STDCALL -NtOpenIoCompletion( - OUT PHANDLE IoCompletionHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes - ) -{ - NTSTATUS Status; - - Status = ObOpenObjectByName(ObjectAttributes, - ExIoCompletionType, - NULL, - UserMode, - DesiredAccess, - NULL, - IoCompletionHandle); //<- ??? - + Status = _SEH_GetExceptionCode(); + } _SEH_END; + + if (!NT_SUCCESS(Status)) { + + return Status; + } + } + + /* Create the Object */ + Status = ObCreateObject(PreviousMode, + IoCompletionType, + ObjectAttributes, + PreviousMode, + NULL, + sizeof(KQUEUE), + 0, + 0, + (PVOID*)&Queue); + + /* Check for success */ + if (NT_SUCCESS(Status)) { + + /* Initialize the Queue */ + KeInitializeQueue(Queue, NumberOfConcurrentThreads); + + /* Insert it */ + Status = ObInsertObject(Queue, + NULL, + DesiredAccess, + 0, + NULL, + &hIoCompletionHandle); + ObDereferenceObject(Queue); + + if (NT_SUCCESS(Status)) { + + _SEH_TRY { + + *IoCompletionHandle = hIoCompletionHandle; + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + } _SEH_END; + } + } + + /* Return Status */ return Status; } - NTSTATUS STDCALL -NtQueryIoCompletion( - IN HANDLE IoCompletionHandle, - IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass, - OUT PVOID IoCompletionInformation, - IN ULONG IoCompletionInformationLength, - OUT PULONG ResultLength OPTIONAL - ) +NtOpenIoCompletion(OUT PHANDLE IoCompletionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) { - PKQUEUE Queue; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + HANDLE hIoCompletionHandle; + NTSTATUS Status = STATUS_SUCCESS; - if (IoCompletionInformationClass != IoCompletionBasicInformation) - { - return STATUS_INVALID_INFO_CLASS; - } - if (IoCompletionInformationLength < sizeof(IO_COMPLETION_BASIC_INFORMATION)) - { - return STATUS_INFO_LENGTH_MISMATCH; - } + PAGED_CODE(); - Status = ObReferenceObjectByHandle( IoCompletionHandle, - IO_COMPLETION_QUERY_STATE, - ExIoCompletionType, - UserMode, - (PVOID*)&Queue, - NULL); - if (NT_SUCCESS(Status)) - { - ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->SignalState = - Queue->Header.SignalState; + if(PreviousMode != KernelMode) { - ObDereferenceObject(Queue); + _SEH_TRY { - if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION); - } + ProbeForWrite(IoCompletionHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } _SEH_HANDLE { - return Status; + Status = _SEH_GetExceptionCode(); + } _SEH_END; + + if(!NT_SUCCESS(Status)) { + + return Status; + } + } + + /* Open the Object */ + Status = ObOpenObjectByName(ObjectAttributes, + IoCompletionType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + &hIoCompletionHandle); + + if (NT_SUCCESS(Status)) { + + _SEH_TRY { + + *IoCompletionHandle = hIoCompletionHandle; + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + } _SEH_END; + } + + /* Return Status */ + return Status; } -/* - * Dequeues an I/O completion message from an I/O completion object - */ NTSTATUS STDCALL -NtRemoveIoCompletion( - IN HANDLE IoCompletionHandle, - OUT PULONG CompletionKey, - OUT PULONG CompletionValue, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN PLARGE_INTEGER Timeout OPTIONAL - ) +NtQueryIoCompletion(IN HANDLE IoCompletionHandle, + IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass, + OUT PVOID IoCompletionInformation, + IN ULONG IoCompletionInformationLength, + OUT PULONG ResultLength OPTIONAL) { - PKQUEUE Queue; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle( IoCompletionHandle, - IO_COMPLETION_MODIFY_STATE, - ExIoCompletionType, - UserMode, + PKQUEUE Queue; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + /* Check buffers and parameters */ + DefaultQueryInfoBufferCheck(IoCompletionInformationClass, + IoCompletionInfoClass, + IoCompletionInformation, + IoCompletionInformationLength, + ResultLength, + PreviousMode, + &Status); + if(!NT_SUCCESS(Status)) { + + DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status); + return Status; + } + + /* Get the Object */ + Status = ObReferenceObjectByHandle(IoCompletionHandle, + IO_COMPLETION_QUERY_STATE, + IoCompletionType, + PreviousMode, (PVOID*)&Queue, NULL); - if (NT_SUCCESS(Status)) - { - PIO_COMPLETION_PACKET Packet; - PLIST_ENTRY ListEntry; - /* - Try 2 remove packet from queue. Wait (optionaly) if - no packet in queue or max num of threads allready running. - */ - ListEntry = KeRemoveQueue(Queue, UserMode, Timeout ); + /* Check for Success */ + if (NT_SUCCESS(Status)) { - ObDereferenceObject(Queue); + _SEH_TRY { - Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry); + /* Return Info */ + ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth = KeReadStateQueue(Queue); + ObDereferenceObject(Queue); - if (CompletionKey) *CompletionKey = Packet->Key; - if (CompletionValue) *CompletionValue = Packet->Overlapped; - if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus; + /* Return Result Length if needed */ + if (ResultLength) { - ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet); - } + *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION); + } + } _SEH_HANDLE { - return Status; -} + Status = _SEH_GetExceptionCode(); + } _SEH_END; + } + /* Return Status */ + return Status; +} /* -ASSOSIERT MED FOB's IoCompletionContext - -typedef struct _IO_COMPLETION_CONTEXT { - PVOID Port; - ULONG Key; -} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT; - -*/ + * Dequeues an I/O completion message from an I/O completion object + */ +NTSTATUS +STDCALL +NtRemoveIoCompletion(IN HANDLE IoCompletionHandle, + OUT PVOID *CompletionKey, + OUT PVOID *CompletionContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER Timeout OPTIONAL) +{ + LARGE_INTEGER SafeTimeout; + PKQUEUE Queue; + PIO_COMPLETION_PACKET Packet; + PLIST_ENTRY ListEntry; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + if (PreviousMode != KernelMode) { + + _SEH_TRY { + + ProbeForWrite(CompletionKey, + sizeof(PVOID), + sizeof(ULONG)); + ProbeForWrite(CompletionContext, + sizeof(PVOID), + sizeof(ULONG)); + ProbeForWrite(IoStatusBlock, + sizeof(IO_STATUS_BLOCK), + sizeof(ULONG)); + if (Timeout != NULL) { + + ProbeForRead(Timeout, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + SafeTimeout = *Timeout; + Timeout = &SafeTimeout; + } + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + } _SEH_END; + + if (!NT_SUCCESS(Status)) { + + return Status; + } + } + + /* Open the Object */ + Status = ObReferenceObjectByHandle(IoCompletionHandle, + IO_COMPLETION_MODIFY_STATE, + IoCompletionType, + PreviousMode, + (PVOID*)&Queue, + NULL); + /* Check for success */ + if (NT_SUCCESS(Status)) { + + /* Remove queue */ + ListEntry = KeRemoveQueue(Queue, PreviousMode, Timeout); + + /* If we got a timeout or user_apc back, return the status */ + if ((NTSTATUS)ListEntry == STATUS_TIMEOUT || (NTSTATUS)ListEntry == STATUS_USER_APC) { + + Status = (NTSTATUS)ListEntry; + + } else { + + /* Get the Packet Data */ + Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry); + + _SEH_TRY { + + /* Check if this is piggybacked on an IRP */ + if (Packet->PacketType == IrpCompletionPacket) + { + /* Get the IRP */ + PIRP Irp = NULL; + Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.ListEntry); + + /* Return values to user */ + *CompletionKey = Irp->Tail.CompletionKey; + *CompletionContext = Irp->Overlay.AsynchronousParameters.UserApcContext; + *IoStatusBlock = Packet->IoStatus; + IoFreeIrp(Irp); + } + else + { + /* This is a user-mode generated or API generated mini-packet */ + *CompletionKey = Packet->Key; + *CompletionContext = Packet->Context; + *IoStatusBlock = Packet->IoStatus; + IopFreeIoCompletionPacket(Packet); + } + + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + } _SEH_END; + } + + /* Dereference the Object */ + ObDereferenceObject(Queue); + } + + /* Return status */ + return Status; +} /* * Queues an I/O completion message to an I/O completion object */ NTSTATUS STDCALL -NtSetIoCompletion( - IN HANDLE IoCompletionPortHandle, - IN ULONG CompletionKey, - IN ULONG CompletionValue, - IN NTSTATUS CompletionStatus, - IN ULONG CompletionInformation - ) +NtSetIoCompletion(IN HANDLE IoCompletionPortHandle, + IN PVOID CompletionKey, + IN PVOID CompletionContext, + IN NTSTATUS CompletionStatus, + IN ULONG CompletionInformation) { - NTSTATUS Status; - PKQUEUE Queue; + NTSTATUS Status; + PKQUEUE Queue; + + PAGED_CODE(); - Status = ObReferenceObjectByHandle( IoCompletionPortHandle, + /* Get the Object */ + Status = ObReferenceObjectByHandle(IoCompletionPortHandle, IO_COMPLETION_MODIFY_STATE, - ExIoCompletionType, - UserMode, + IoCompletionType, + ExGetPreviousMode(), (PVOID*)&Queue, NULL); - if (NT_SUCCESS(Status)) - { - PIO_COMPLETION_PACKET Packet; - - Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside); - - Packet->Key = CompletionKey; - Packet->Overlapped = CompletionValue; - Packet->IoStatus.Status = CompletionStatus; - Packet->IoStatus.Information = CompletionInformation; - - KeInsertQueue(Queue, &Packet->ListEntry); - ObDereferenceObject(Queue); - } - return Status; + /* Check for Success */ + if (NT_SUCCESS(Status)) { + + /* Set the Completion */ + Status = IoSetIoCompletion(Queue, + CompletionKey, + CompletionContext, + CompletionStatus, + CompletionInformation, + TRUE); + ObDereferenceObject(Queue); + } + + /* Return status */ + return Status; }