Alex Ionescu <ionucu@videotron.ca>
authorThomas Bluemel <thomas@reactsoft.com>
Sat, 12 Mar 2005 19:58:53 +0000 (19:58 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Sat, 12 Mar 2005 19:58:53 +0000 (19:58 +0000)
- Clean up IO Completion Code
- Properly delete an IO Completion. The IRPs were not freed, resulting in memory leaks

Thomas Weidenmueller <w3seek@reactos.com>
- Add SEH to IO Completion Code

svn path=/trunk/; revision=13977

reactos/ntoskrnl/io/iocomp.c

index de412e5..fe54d18 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$
- * 
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/io/iocomp.c
 
 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
 };
 
-/* FUNCTIONS *****************************************************************/
-
-NTSTATUS 
-STDCALL
-IopCreateIoCompletion(
-   PVOID                ObjectBody,
-   PVOID                Parent,
-   PWSTR                RemainingPath,
-   POBJECT_ATTRIBUTES   ObjectAttributes
-   )
-{
-   DPRINT("IopCreateIoCompletion(ObjectBody %x, Parent %x, RemainingPath %S)\n",
-      ObjectBody, Parent, RemainingPath);
+static const INFORMATION_CLASS_INFO ExIoCompletionInfoClass[] = {
 
-   if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
-   {
-      return STATUS_UNSUCCESSFUL;
-   }
+     /* IoCompletionBasicInformation */
+    ICI_SQ_SAME( sizeof(IO_COMPLETION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
+};
 
-   return STATUS_SUCCESS;
-}
+/* FUNCTIONS *****************************************************************/
 
-VOID STDCALL
+VOID 
+STDCALL
 IopDeleteIoCompletion(PVOID ObjectBody)
 {
-   PKQUEUE Queue = ObjectBody;
-
-   DPRINT("IopDeleteIoCompletion()\n");
-
-   KeRundownQueue(Queue);
+    PKQUEUE Queue = ObjectBody;
+    PLIST_ENTRY FirstEntry;
+    PLIST_ENTRY CurrentEntry;
+    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;
+            
+            /* 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;
-
-   ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
-                                   NULL,
-                                   NULL,
-                                   0,
-                                   sizeof(IO_COMPLETION_PACKET),
-                                   IOC_TAG,
-                                   0);
+    /* 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;
+
+    /* 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;
-
-   Status = ObCreateObject(ExGetPreviousMode(),
-                           ExIoCompletionType,
-                           ObjectAttributes,
-                           ExGetPreviousMode(),
-                           NULL,
-                           sizeof(KQUEUE),
-                           0,
-                           0,
-                           (PVOID*)&Queue);
-   if (!NT_SUCCESS(Status))
-   {
-     return Status;
-   }
-
-   Status = ObInsertObject ((PVOID)Queue,
-                           NULL,
-                           DesiredAccess,
-                           0,
-                           NULL,
-                           IoCompletionHandle);
-   if (!NT_SUCCESS(Status))
-   {
-     ObDereferenceObject(Queue);
-     return Status;
-   }
-
-   KeInitializeQueue(Queue, NumberOfConcurrentThreads);
-   ObDereferenceObject(Queue);
+    PKQUEUE Queue;
+    HANDLE hIoCompletionHandle;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    
+    PAGED_CODE();
 
-   return STATUS_SUCCESS;
-   /*
+    if (PreviousMode != KernelMode) {
 
-  CompletionPort = NULL OR ExistingCompletionPort
+        _SEH_TRY {
 
-  */
+            ProbeForWrite(IoCompletionHandle,
+                          sizeof(HANDLE),
+                          sizeof(ULONG));
+        } _SEH_HANDLE {
 
+            Status = _SEH_GetExceptionCode();
+        } _SEH_END;
+      
+        if (!NT_SUCCESS(Status)) {
+
+            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)) {
+
+            _SEH_TRY {
+
+                *IoCompletionHandle = hIoCompletionHandle;
+            } _SEH_HANDLE {
+
+                Status = _SEH_GetExceptionCode();
+            } _SEH_END;
+        }
+   }
+   
+   /* Return Status */
+   return 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
-
-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
-   )
+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;
-
-   if (IoCompletionInformationClass != IoCompletionBasicInformation)
-   {
-      return STATUS_INVALID_INFO_CLASS;
-   }
-   if (IoCompletionInformationLength < sizeof(IO_COMPLETION_BASIC_INFORMATION))
-   {
-      return STATUS_INFO_LENGTH_MISMATCH;
-   }
-
-   Status = ObReferenceObjectByHandle( IoCompletionHandle,
+    PKQUEUE Queue;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    
+    PAGED_CODE();
+
+    /* Check buffers and parameters */
+    DefaultQueryInfoBufferCheck(IoCompletionInformationClass,
+                                ExIoCompletionInfoClass,
+                                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,
                                        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;
-
-   Status = ObReferenceObjectByHandle( IoCompletionHandle,
+    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,
                                        ExIoCompletionType,
-                                       UserMode,
+                                       PreviousMode,
                                        (PVOID*)&Queue,
                                        NULL);
-   if (!NT_SUCCESS(Status))
-   {
-      return 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 );
-
-      /* 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
-      */
-
-   } while((NTSTATUS)ListEntry == STATUS_USER_APC);
-
-   ObDereferenceObject(Queue);
-   
-   if ((NTSTATUS)ListEntry == STATUS_TIMEOUT)
-   {
-      return STATUS_TIMEOUT;
-   }
+    
+    /* 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 {
+
+                /* Return it */
+                *CompletionKey = Packet->Key;
+                *CompletionContext = Packet->Context;
+                *IoStatusBlock = Packet->IoStatus;
+           
+            } _SEH_HANDLE {
+
+                Status = _SEH_GetExceptionCode();
+            } _SEH_END;
+
+            /* Free packet */
+            ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
+        }
    
-   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;
 }