Alex Ionescu <ionucu(a)videotron.ca>
- Clean up IO Completion Code
- Properly delete an IO Completion. The IRPs were not freed, resulting
in memory leaks
Thomas Weidenmueller <w3seek(a)reactos.com>
- Add SEH to IO Completion Code
Modified: trunk/reactos/ntoskrnl/io/iocomp.c
_____
Modified: trunk/reactos/ntoskrnl/io/iocomp.c
--- trunk/reactos/ntoskrnl/io/iocomp.c 2005-03-12 19:46:27 UTC (rev
13976)
+++ trunk/reactos/ntoskrnl/io/iocomp.c 2005-03-12 19:58:53 UTC (rev
13977)
@@ -1,5 +1,4 @@
-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/iocomp.c
@@ -18,372 +17,467 @@
POBJECT_TYPE ExIoCompletionType;
-NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
+NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
static GENERIC_MAPPING ExIoCompletionMapping =
{
- 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 ExIoCompletionInfoClass[] = {
+
+ /* IoCompletionBasicInformation */
+ ICI_SQ_SAME( sizeof(IO_COMPLETION_BASIC_INFORMATION),
sizeof(ULONG), ICIF_QUERY ),
+};
+
/* FUNCTIONS
*****************************************************************/
-NTSTATUS
+VOID
STDCALL
-IopCreateIoCompletion(
- PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- POBJECT_ATTRIBUTES ObjectAttributes
- )
-{
- DPRINT("IopCreateIoCompletion(ObjectBody %x, Parent %x,
RemainingPath %S)\n",
- ObjectBody, Parent, RemainingPath);
-
- if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- return STATUS_SUCCESS;
-}
-
-VOID STDCALL
IopDeleteIoCompletion(PVOID ObjectBody)
{
- PKQUEUE Queue = ObjectBody;
+ PKQUEUE Queue = ObjectBody;
+ PLIST_ENTRY FirstEntry;
+ PLIST_ENTRY CurrentEntry;
+ PIO_COMPLETION_PACKET Packet;
- DPRINT("IopDeleteIoCompletion()\n");
+ DPRINT("IopDeleteIoCompletion()\n");
- KeRundownQueue(Queue);
+ /* 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;
+
+ /* Free it */
+ ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside,
Packet);
+ } while (FirstEntry != CurrentEntry);
+ }
}
-
/*
- * @unimplemented
+ * @implemented
*/
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
- )
+IoSetIoCompletion(IN PVOID IoCompletion,
+ IN PVOID KeyContext,
+ IN PVOID ApcContext,
+ IN NTSTATUS IoStatus,
+ IN ULONG_PTR IoStatusInformation,
+ IN BOOLEAN Quota)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PKQUEUE Queue = (PKQUEUE)IoCompletion;
+ PIO_COMPLETION_PACKET Packet;
+
+ /* Allocate the Packet */
+ Packet =
ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
+ if (NULL == Packet) return STATUS_NO_MEMORY;
+
+ /* Set up the Packet */
+ Packet->Key = KeyContext;
+ Packet->Context = ApcContext;
+ Packet->IoStatus.Status = IoStatus;
+ Packet->IoStatus.Information = IoStatusInformation;
+
+ /* Insert the Queue */
+ KeInsertQueue(Queue, &Packet->ListEntry);
+
+ /* Return Success */
+ return STATUS_SUCCESS;
}
/*
- * @implemented
+ * @unimplemented
*/
NTSTATUS
STDCALL
-IoSetIoCompletion (
- IN PVOID IoCompletion,
- IN PVOID KeyContext,
- IN PVOID ApcContext,
- IN NTSTATUS IoStatus,
- IN ULONG_PTR IoStatusInformation,
- IN BOOLEAN Quota
- )
+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)
{
- PKQUEUE Queue = (PKQUEUE) IoCompletion;
- PIO_COMPLETION_PACKET Packet;
-
- Packet =
ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
- if (NULL == Packet)
- {
- return STATUS_NO_MEMORY;
- }
-
- Packet->Key = KeyContext;
- Packet->Context = ApcContext;
- Packet->IoStatus.Status = IoStatus;
- Packet->IoStatus.Information = IoStatusInformation;
-
- KeInsertQueue(Queue, &Packet->ListEntry);
-
- return STATUS_SUCCESS;
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
}
VOID
FASTCALL
IopInitIoCompletionImplementation(VOID)
{
- ExIoCompletionType = ExAllocatePool(NonPagedPool,
sizeof(OBJECT_TYPE));
-
- RtlpCreateUnicodeString(&ExIoCompletionType->TypeName,
L"IoCompletion", NonPagedPool);
-
- ExIoCompletionType->Tag = IOC_TAG;
- ExIoCompletionType->PeakObjects = 0;
- ExIoCompletionType->PeakHandles = 0;
- 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 = IopDeleteIoCompletion;
- ExIoCompletionType->Parse = NULL;
- ExIoCompletionType->Security = NULL;
- ExIoCompletionType->QueryName = NULL;
- ExIoCompletionType->OkayToClose = NULL;
- ExIoCompletionType->Create = IopCreateIoCompletion;
- ExIoCompletionType->DuplicationNotify = NULL;
+ /* Create the IO Completion Type */
+ ExIoCompletionType = ExAllocatePool(NonPagedPool,
sizeof(OBJECT_TYPE));
+ RtlInitUnicodeString(&ExIoCompletionType->TypeName,
L"IoCompletion");
+ ExIoCompletionType->Tag = IOC_TAG;
+ ExIoCompletionType->PeakObjects = 0;
+ ExIoCompletionType->PeakHandles = 0;
+ 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 = IopDeleteIoCompletion;
+ ExIoCompletionType->Parse = NULL;
+ ExIoCompletionType->Security = NULL;
+ ExIoCompletionType->QueryName = NULL;
+ ExIoCompletionType->OkayToClose = NULL;
+ ExIoCompletionType->Create = NULL;
+ ExIoCompletionType->DuplicationNotify = NULL;
- ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
- NULL,
- NULL,
- 0,
- sizeof(IO_COMPLETION_PACKET),
- IOC_TAG,
- 0);
+ /* Initialize the Lookaside List we'll use for packets */
+ ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
+ NULL,
+ NULL,
+ 0,
+ sizeof(IO_COMPLETION_PACKET),
+ IOC_TAG,
+ 0);
}
-
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;
+ PKQUEUE Queue;
+ HANDLE hIoCompletionHandle;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
- Status = ObCreateObject(ExGetPreviousMode(),
- ExIoCompletionType,
- ObjectAttributes,
- ExGetPreviousMode(),
- NULL,
- sizeof(KQUEUE),
- 0,
- 0,
- (PVOID*)&Queue);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ if (PreviousMode != KernelMode) {
- Status = ObInsertObject ((PVOID)Queue,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- IoCompletionHandle);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Queue);
- return Status;
- }
+ _SEH_TRY {
- KeInitializeQueue(Queue, NumberOfConcurrentThreads);
- ObDereferenceObject(Queue);
+ ProbeForWrite(IoCompletionHandle,
+ sizeof(HANDLE),
+ sizeof(ULONG));
+ } _SEH_HANDLE {
- return STATUS_SUCCESS;
- /*
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+
+ if (!NT_SUCCESS(Status)) {
- CompletionPort = NULL OR ExistingCompletionPort
+ return Status;
+ }
+ }
- */
-
+ /* Create the Object */
+ Status = ObCreateObject(PreviousMode,
+ ExIoCompletionType,
+ 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)) {
-/*
-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
+ _SEH_TRY {
-ObjectAttributes
-OBJ_OPENLINK and OBJ_PERMANENT are not valid attributes
+ *IoCompletionHandle = hIoCompletionHandle;
+ } _SEH_HANDLE {
-Return Value
-STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED or
-STATUS_OBJECT_NAME_NOT_FOUND.
-*/
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+ }
+ }
+
+ /* Return Status */
+ return Status;
+}
+
NTSTATUS
STDCALL
-NtOpenIoCompletion(
- OUT PHANDLE IoCompletionHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes
- )
+NtOpenIoCompletion(OUT PHANDLE IoCompletionHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
{
- NTSTATUS Status;
-
- Status = ObOpenObjectByName(ObjectAttributes,
- ExIoCompletionType,
- NULL,
- UserMode,
- DesiredAccess,
- NULL,
- IoCompletionHandle); //<- ???
-
- return Status;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ HANDLE hIoCompletionHandle;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ if(PreviousMode != KernelMode) {
+
+ _SEH_TRY {
+
+ ProbeForWrite(IoCompletionHandle,
+ sizeof(HANDLE),
+ sizeof(ULONG));
+ } _SEH_HANDLE {
+
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+
+ if(!NT_SUCCESS(Status)) {
+
+ return Status;
+ }
+ }
+
+ /* Open the Object */
+ Status = ObOpenObjectByName(ObjectAttributes,
+ ExIoCompletionType,
+ NULL,
+ PreviousMode,
+ DesiredAccess,
+ NULL,
+ &hIoCompletionHandle);
+
+ 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
- )
+NtQueryIoCompletion(IN HANDLE IoCompletionHandle,
+ IN IO_COMPLETION_INFORMATION_CLASS
IoCompletionInformationClass,
+ OUT PVOID IoCompletionInformation,
+ IN ULONG IoCompletionInformationLength,
+ OUT PULONG ResultLength OPTIONAL)
{
- PKQUEUE Queue;
- NTSTATUS Status;
+ PKQUEUE Queue;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
- if (IoCompletionInformationClass != IoCompletionBasicInformation)
- {
- return STATUS_INVALID_INFO_CLASS;
- }
- if (IoCompletionInformationLength <
sizeof(IO_COMPLETION_BASIC_INFORMATION))
- {
- return STATUS_INFO_LENGTH_MISMATCH;
- }
+ /* Check buffers and parameters */
+ DefaultQueryInfoBufferCheck(IoCompletionInformationClass,
+ ExIoCompletionInfoClass,
+ IoCompletionInformation,
+ IoCompletionInformationLength,
+ ResultLength,
+ PreviousMode,
+ &Status);
+ if(!NT_SUCCESS(Status)) {
- Status = ObReferenceObjectByHandle( IoCompletionHandle,
+ DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
+ return Status;
+ }
+
+ /* Get the Object */
+ Status = ObReferenceObjectByHandle(IoCompletionHandle,
IO_COMPLETION_QUERY_STATE,
ExIoCompletionType,
- UserMode,
+ PreviousMode,
(PVOID*)&Queue,
NULL);
- if (NT_SUCCESS(Status))
- {
-
((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth =
- Queue->Header.SignalState;
+
+ /* Check for Success */
+ if (NT_SUCCESS(Status)) {
+
+ _SEH_TRY {
- ObDereferenceObject(Queue);
+ /* Return Info */
+
((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth =
KeReadStateQueue(Queue);
+ ObDereferenceObject(Queue);
- if (ResultLength) *ResultLength =
sizeof(IO_COMPLETION_BASIC_INFORMATION);
- }
+ /* Return Result Length if needed */
+ if (ResultLength) {
- return Status;
+ *ResultLength =
sizeof(IO_COMPLETION_BASIC_INFORMATION);
+ }
+ } _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 PVOID *CompletionKey,
- OUT PVOID *CompletionContext,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- IN PLARGE_INTEGER Timeout OPTIONAL
- )
+NtRemoveIoCompletion(IN HANDLE IoCompletionHandle,
+ OUT PVOID *CompletionKey,
+ OUT PVOID *CompletionContext,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PLARGE_INTEGER Timeout OPTIONAL)
{
- PKQUEUE Queue;
- NTSTATUS Status;
- PIO_COMPLETION_PACKET Packet;
- PLIST_ENTRY ListEntry;
+ LARGE_INTEGER SafeTimeout;
+ PKQUEUE Queue;
+ PIO_COMPLETION_PACKET Packet;
+ PLIST_ENTRY ListEntry;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
- Status = ObReferenceObjectByHandle( IoCompletionHandle,
+ 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,
ExIoCompletionType,
- UserMode,
+ PreviousMode,
(PVOID*)&Queue,
NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+
+ /* Check for success */
+ if (NT_SUCCESS(Status)) {
- /*
- Try 2 remove packet from queue. Wait (optionaly) if
- no packet in queue or max num of threads allready running.
- */
-
- do {
-
- ListEntry = KeRemoveQueue(Queue, UserMode, Timeout );
+ /* Remove queue */
+ ListEntry = KeRemoveQueue(Queue, PreviousMode, Timeout);
- /* Nebbets book says nothing about NtRemoveIoCompletion returning
STATUS_USER_APC,
- and the umode equivalent GetQueuedCompletionStatus says nothing
about this either,
- so my guess it we should restart the operation. Need further
investigation. -Gunnar
- */
+ /* 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 {
- } while((NTSTATUS)ListEntry == STATUS_USER_APC);
+ /* Return it */
+ *CompletionKey = Packet->Key;
+ *CompletionContext = Packet->Context;
+ *IoStatusBlock = Packet->IoStatus;
+
+ } _SEH_HANDLE {
- ObDereferenceObject(Queue);
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+
+ /* Free packet */
+ ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside,
Packet);
+ }
- if ((NTSTATUS)ListEntry == STATUS_TIMEOUT)
- {
- return STATUS_TIMEOUT;
- }
-
- ASSERT(ListEntry);
-
- Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET,
ListEntry);
-
- if (CompletionKey) *CompletionKey = Packet->Key;
- if (CompletionContext) *CompletionContext = Packet->Context;
- if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
-
- ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
-
- return STATUS_SUCCESS;
+ /* Dereference the Object */
+ ObDereferenceObject(Queue);
+ }
+
+ /* Return status */
+ return Status;
}
-
/*
-ASSOSIERT MED FOB's IoCompletionContext
-
-typedef struct _IO_COMPLETION_CONTEXT {
- PVOID Port;
- ULONG Key;
-} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT;
-
-*/
-
-
-/*
* Queues an I/O completion message to an I/O completion object
*/
NTSTATUS
STDCALL
-NtSetIoCompletion(
- IN HANDLE IoCompletionPortHandle,
- IN PVOID CompletionKey,
- IN PVOID CompletionContext,
- 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;
-
- Status = ObReferenceObjectByHandle( IoCompletionPortHandle,
+ NTSTATUS Status;
+ PKQUEUE Queue;
+
+ PAGED_CODE();
+
+ /* Get the Object */
+ Status = ObReferenceObjectByHandle(IoCompletionPortHandle,
IO_COMPLETION_MODIFY_STATE,
ExIoCompletionType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID*)&Queue,
NULL);
- if (NT_SUCCESS(Status))
- {
- Status = IoSetIoCompletion(Queue, CompletionKey,
CompletionContext,
- CompletionStatus,
CompletionInformation, TRUE);
- 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;
}