/*
* 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 <limits.h>
-#define NTOS_MODE_KERNEL
-#include <ntos.h>
-//#include <ntos/synch.h>
-
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
-#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;
}