- Fix formatting/function order

- Use only one SEH block in NtRemoveIoCompletion
- Get the completion status from the IRP, not from the Mini-Packet, if the completion came from an IRP and not a Mini-Packet.

svn path=/trunk/; revision=22721
This commit is contained in:
Alex Ionescu 2006-06-30 17:53:00 +00:00
parent cabeb71d14
commit b42accc93a

View file

@ -1,10 +1,10 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Kernel
* PROJECT: ReactOS kernel * LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/io/iocomp.c * FILE: ntoskrnl/io/event.c
* PURPOSE: No purpose listed. * PURPOSE: I/O Wrappers for the Executive Event Functions
* * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* PROGRAMMERS: David Welch (welch@mcmail.com) * Thomas Weidenmueller (w3seek@reactos.org)
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -17,7 +17,7 @@ POBJECT_TYPE IoCompletionType;
NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside; NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
static GENERIC_MAPPING IopCompletionMapping = GENERIC_MAPPING IopCompletionMapping =
{ {
STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE, STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE,
STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE, STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE,
@ -25,23 +25,24 @@ static GENERIC_MAPPING IopCompletionMapping =
IO_COMPLETION_ALL_ACCESS IO_COMPLETION_ALL_ACCESS
}; };
static const INFORMATION_CLASS_INFO IoCompletionInfoClass[] = { static const INFORMATION_CLASS_INFO IoCompletionInfoClass[] =
{
/* IoCompletionBasicInformation */ /* IoCompletionBasicInformation */
ICI_SQ_SAME(sizeof(IO_COMPLETION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY), ICI_SQ_SAME(sizeof(IO_COMPLETION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
}; };
/* FUNCTIONS *****************************************************************/ /* PRIVATE FUNCTIONS *********************************************************/
VOID VOID
STDCALL NTAPI
IopFreeIoCompletionPacket(PIO_COMPLETION_PACKET Packet) IopFreeIoCompletionPacket(PIO_COMPLETION_PACKET Packet)
{ {
PKPRCB Prcb = KeGetCurrentPrcb(); PKPRCB Prcb = KeGetCurrentPrcb();
PNPAGED_LOOKASIDE_LIST List; PNPAGED_LOOKASIDE_LIST List;
/* Use the P List */ /* Use the P List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[LookasideCompletionList].P; List = (PNPAGED_LOOKASIDE_LIST)Prcb->
PPLookasideList[LookasideCompletionList].P;
List->L.TotalFrees++; List->L.TotalFrees++;
/* Check if the Free was within the Depth or not */ /* Check if the Free was within the Depth or not */
@ -51,7 +52,8 @@ IopFreeIoCompletionPacket(PIO_COMPLETION_PACKET Packet)
List->L.FreeMisses++; List->L.FreeMisses++;
/* Use the L List */ /* Use the L List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[LookasideCompletionList].L; List = (PNPAGED_LOOKASIDE_LIST)Prcb->
PPLookasideList[LookasideCompletionList].L;
List->L.TotalFrees++; List->L.TotalFrees++;
/* Check if the Free was within the Depth or not */ /* Check if the Free was within the Depth or not */
@ -68,7 +70,7 @@ IopFreeIoCompletionPacket(PIO_COMPLETION_PACKET Packet)
} }
VOID VOID
STDCALL NTAPI
IopDeleteIoCompletion(PVOID ObjectBody) IopDeleteIoCompletion(PVOID ObjectBody)
{ {
PKQUEUE Queue = ObjectBody; PKQUEUE Queue = ObjectBody;
@ -77,19 +79,18 @@ IopDeleteIoCompletion(PVOID ObjectBody)
PIRP Irp; PIRP Irp;
PIO_COMPLETION_PACKET Packet; PIO_COMPLETION_PACKET Packet;
DPRINT("IopDeleteIoCompletion()\n");
/* Rundown the Queue */ /* Rundown the Queue */
FirstEntry = KeRundownQueue(Queue); FirstEntry = KeRundownQueue(Queue);
if (FirstEntry)
/* Clean up the IRPs */ {
if (FirstEntry) { /* Loop the packets */
CurrentEntry = FirstEntry; CurrentEntry = FirstEntry;
do { do
{
/* Get the Packet */ /* Get the Packet */
Packet = CONTAINING_RECORD(CurrentEntry, IO_COMPLETION_PACKET, ListEntry); Packet = CONTAINING_RECORD(CurrentEntry,
IO_COMPLETION_PACKET,
ListEntry);
/* Go to next Entry */ /* Go to next Entry */
CurrentEntry = CurrentEntry->Flink; CurrentEntry = CurrentEntry->Flink;
@ -110,11 +111,33 @@ IopDeleteIoCompletion(PVOID ObjectBody)
} }
} }
VOID
FASTCALL
IopInitIoCompletionImplementation(VOID)
{
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING Name;
/* 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;
ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoCompletionType);
}
/* PUBLIC FUNCTIONS **********************************************************/
/* /*
* @implemented * @implemented
*/ */
NTSTATUS NTSTATUS
STDCALL NTAPI
IoSetIoCompletion(IN PVOID IoCompletion, IoSetIoCompletion(IN PVOID IoCompletion,
IN PVOID KeyContext, IN PVOID KeyContext,
IN PVOID ApcContext, IN PVOID ApcContext,
@ -128,7 +151,8 @@ IoSetIoCompletion(IN PVOID IoCompletion,
PIO_COMPLETION_PACKET Packet; PIO_COMPLETION_PACKET Packet;
/* Get the P List */ /* Get the P List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[LookasideCompletionList].P; List = (PNPAGED_LOOKASIDE_LIST)Prcb->
PPLookasideList[LookasideCompletionList].P;
/* Try to allocate the Packet */ /* Try to allocate the Packet */
List->L.TotalAllocates++; List->L.TotalAllocates++;
@ -141,7 +165,8 @@ IoSetIoCompletion(IN PVOID IoCompletion,
List->L.AllocateMisses++; List->L.AllocateMisses++;
/* Get L List */ /* Get L List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[LookasideCompletionList].L; List = (PNPAGED_LOOKASIDE_LIST)Prcb->
PPLookasideList[LookasideCompletionList].L;
/* Try to allocate the Packet */ /* Try to allocate the Packet */
List->L.TotalAllocates++; List->L.TotalAllocates++;
@ -173,6 +198,7 @@ IoSetIoCompletion(IN PVOID IoCompletion,
} }
else else
{ {
/* Out of memory, fail */
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
@ -184,7 +210,7 @@ IoSetIoCompletion(IN PVOID IoCompletion,
* @unimplemented * @unimplemented
*/ */
NTSTATUS NTSTATUS
STDCALL NTAPI
IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject, IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp, IN PIRP Irp,
IN PIO_COMPLETION_ROUTINE CompletionRoutine, IN PIO_COMPLETION_ROUTINE CompletionRoutine,
@ -197,30 +223,8 @@ IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject,
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
VOID
FASTCALL
IopInitIoCompletionImplementation(VOID)
{
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING Name;
DPRINT("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;
ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoCompletionType);
}
NTSTATUS NTSTATUS
STDCALL NTAPI
NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle, NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle,
IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_ATTRIBUTES ObjectAttributes,
@ -230,23 +234,26 @@ NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle,
HANDLE hIoCompletionHandle; HANDLE hIoCompletionHandle;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE(); PAGED_CODE();
if (PreviousMode != KernelMode) { /* Check if this was a user-mode call */
if (PreviousMode != KernelMode)
_SEH_TRY { {
/* Wrap probing in SEH */
_SEH_TRY
{
/* Probe the handle */
ProbeForWriteHandle(IoCompletionHandle); ProbeForWriteHandle(IoCompletionHandle);
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if (!NT_SUCCESS(Status)) {
return Status;
} }
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Fail on exception */
if (!NT_SUCCESS(Status)) return Status;
} }
/* Create the Object */ /* Create the Object */
@ -259,10 +266,8 @@ NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle,
0, 0,
0, 0,
(PVOID*)&Queue); (PVOID*)&Queue);
if (NT_SUCCESS(Status))
/* Check for success */ {
if (NT_SUCCESS(Status)) {
/* Initialize the Queue */ /* Initialize the Queue */
KeInitializeQueue(Queue, NumberOfConcurrentThreads); KeInitializeQueue(Queue, NumberOfConcurrentThreads);
@ -273,16 +278,20 @@ NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle,
0, 0,
NULL, NULL,
&hIoCompletionHandle); &hIoCompletionHandle);
if (NT_SUCCESS(Status))
if (NT_SUCCESS(Status)) { {
/* Protect writing the handle in SEH */
_SEH_TRY { _SEH_TRY
{
/* Write the handle back */
*IoCompletionHandle = hIoCompletionHandle; *IoCompletionHandle = hIoCompletionHandle;
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) { }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
/* Get the exception code */
Status = _SEH_GetExceptionCode(); Status = _SEH_GetExceptionCode();
} _SEH_END; }
_SEH_END;
} }
} }
@ -291,7 +300,7 @@ NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle,
} }
NTSTATUS NTSTATUS
STDCALL NTAPI
NtOpenIoCompletion(OUT PHANDLE IoCompletionHandle, NtOpenIoCompletion(OUT PHANDLE IoCompletionHandle,
IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes) IN POBJECT_ATTRIBUTES ObjectAttributes)
@ -299,23 +308,26 @@ NtOpenIoCompletion(OUT PHANDLE IoCompletionHandle,
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
HANDLE hIoCompletionHandle; HANDLE hIoCompletionHandle;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE(); PAGED_CODE();
if(PreviousMode != KernelMode) { /* Check if this was a user-mode call */
if (PreviousMode != KernelMode)
_SEH_TRY { {
/* Wrap probing in SEH */
_SEH_TRY
{
/* Probe the handle */
ProbeForWriteHandle(IoCompletionHandle); ProbeForWriteHandle(IoCompletionHandle);
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) {
return Status;
} }
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Fail on exception */
if (!NT_SUCCESS(Status)) return Status;
} }
/* Open the Object */ /* Open the Object */
@ -326,25 +338,28 @@ NtOpenIoCompletion(OUT PHANDLE IoCompletionHandle,
DesiredAccess, DesiredAccess,
NULL, NULL,
&hIoCompletionHandle); &hIoCompletionHandle);
if (NT_SUCCESS(Status))
if (NT_SUCCESS(Status)) { {
/* Protect writing the handle in SEH */
_SEH_TRY { _SEH_TRY
{
/* Write the handle back */
*IoCompletionHandle = hIoCompletionHandle; *IoCompletionHandle = hIoCompletionHandle;
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) { }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
/* Get the exception code */
Status = _SEH_GetExceptionCode(); Status = _SEH_GetExceptionCode();
} _SEH_END; }
_SEH_END;
} }
/* Return Status */ /* Return Status */
return Status; return Status;
} }
NTSTATUS NTSTATUS
STDCALL NTAPI
NtQueryIoCompletion(IN HANDLE IoCompletionHandle, NtQueryIoCompletion(IN HANDLE IoCompletionHandle,
IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass, IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
OUT PVOID IoCompletionInformation, OUT PVOID IoCompletionInformation,
@ -354,22 +369,18 @@ NtQueryIoCompletion(IN HANDLE IoCompletionHandle,
PKQUEUE Queue; PKQUEUE Queue;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE(); PAGED_CODE();
/* Check buffers and parameters */ /* Check buffers and parameters */
Status = DefaultQueryInfoBufferCheck(IoCompletionInformationClass, Status = DefaultQueryInfoBufferCheck(IoCompletionInformationClass,
IoCompletionInfoClass, IoCompletionInfoClass,
sizeof(IoCompletionInfoClass) / sizeof(IoCompletionInfoClass[0]), sizeof(IoCompletionInfoClass) /
sizeof(IoCompletionInfoClass[0]),
IoCompletionInformation, IoCompletionInformation,
IoCompletionInformationLength, IoCompletionInformationLength,
ResultLength, ResultLength,
PreviousMode); PreviousMode);
if(!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) return Status;
DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
return Status;
}
/* Get the Object */ /* Get the Object */
Status = ObReferenceObjectByHandle(IoCompletionHandle, Status = ObReferenceObjectByHandle(IoCompletionHandle,
@ -378,39 +389,41 @@ NtQueryIoCompletion(IN HANDLE IoCompletionHandle,
PreviousMode, PreviousMode,
(PVOID*)&Queue, (PVOID*)&Queue,
NULL); NULL);
if (NT_SUCCESS(Status))
/* Check for Success */ {
if (NT_SUCCESS(Status)) { /* Protect write in SEH */
_SEH_TRY
_SEH_TRY { {
/* Return Info */ /* Return Info */
((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth = KeReadStateQueue(Queue); ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->
Depth = KeReadStateQueue(Queue);
/* Dereference the queue */
ObDereferenceObject(Queue); ObDereferenceObject(Queue);
/* Return Result Length if needed */ /* Return Result Length if needed */
if (ResultLength) { if (ResultLength)
{
*ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION); *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
} }
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) { }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
/* Get exception code */
Status = _SEH_GetExceptionCode(); Status = _SEH_GetExceptionCode();
} _SEH_END; }
_SEH_END;
} }
/* Return Status */ /* Return Status */
return Status; return Status;
} }
/*
* Dequeues an I/O completion message from an I/O completion object
*/
NTSTATUS NTSTATUS
STDCALL NTAPI
NtRemoveIoCompletion(IN HANDLE IoCompletionHandle, NtRemoveIoCompletion(IN HANDLE IoCompletionHandle,
OUT PVOID *CompletionKey, OUT PVOID *KeyContext,
OUT PVOID *CompletionContext, OUT PVOID *ApcContext,
OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER Timeout OPTIONAL) IN PLARGE_INTEGER Timeout OPTIONAL)
{ {
@ -420,32 +433,41 @@ NtRemoveIoCompletion(IN HANDLE IoCompletionHandle,
PLIST_ENTRY ListEntry; PLIST_ENTRY ListEntry;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PIRP Irp;
PVOID Apc, Key;
IO_STATUS_BLOCK IoStatus;
PAGED_CODE(); PAGED_CODE();
if (PreviousMode != KernelMode) { /* Check if the call was from user mode */
if (PreviousMode != KernelMode)
{
/* Protect probes in SEH */
_SEH_TRY
{
/* Probe the pointers */
ProbeForWritePointer(KeyContext);
ProbeForWritePointer(ApcContext);
_SEH_TRY { /* Probe the I/O Status Block */
ProbeForWritePointer(CompletionKey);
ProbeForWritePointer(CompletionContext);
ProbeForWrite(IoStatusBlock, ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK), sizeof(IO_STATUS_BLOCK),
sizeof(ULONG)); sizeof(ULONG));
if (Timeout != NULL) { if (Timeout)
{
/* Probe and capture the timeout */
SafeTimeout = ProbeForReadLargeInteger(Timeout); SafeTimeout = ProbeForReadLargeInteger(Timeout);
Timeout = &SafeTimeout; Timeout = &SafeTimeout;
} }
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if (!NT_SUCCESS(Status)) {
return Status;
} }
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Fail on exception */
if (!NT_SUCCESS(Status)) return Status;
} }
/* Open the Object */ /* Open the Object */
@ -455,57 +477,66 @@ NtRemoveIoCompletion(IN HANDLE IoCompletionHandle,
PreviousMode, PreviousMode,
(PVOID*)&Queue, (PVOID*)&Queue,
NULL); NULL);
if (NT_SUCCESS(Status))
/* Check for success */ {
if (NT_SUCCESS(Status)) {
/* Remove queue */ /* Remove queue */
ListEntry = KeRemoveQueue(Queue, PreviousMode, Timeout); ListEntry = KeRemoveQueue(Queue, PreviousMode, Timeout);
/* If we got a timeout or user_apc back, return the status */ /* If we got a timeout or user_apc back, return the status */
if ((NTSTATUS)ListEntry == STATUS_TIMEOUT || (NTSTATUS)ListEntry == STATUS_USER_APC) { if (((NTSTATUS)ListEntry == STATUS_TIMEOUT) ||
((NTSTATUS)ListEntry == STATUS_USER_APC))
{
/* Set this as the status */
Status = (NTSTATUS)ListEntry; Status = (NTSTATUS)ListEntry;
}
} else { else
{
/* Get the Packet Data */ /* Get the Packet Data */
Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry); Packet = CONTAINING_RECORD(ListEntry,
IO_COMPLETION_PACKET,
ListEntry);
/* Check if this is piggybacked on an IRP */ /* Check if this is piggybacked on an IRP */
if (Packet->PacketType == IrpCompletionPacket) if (Packet->PacketType == IrpCompletionPacket)
{ {
/* Get the IRP */ /* Get the IRP */
PIRP Irp = NULL; Irp = CONTAINING_RECORD(ListEntry,
Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.ListEntry); IRP,
Tail.Overlay.ListEntry);
/* Return values to user */ /* Save values */
_SEH_TRY { Key = Irp->Tail.CompletionKey;
Apc = Irp->Overlay.AsynchronousParameters.UserApcContext;
*CompletionKey = Irp->Tail.CompletionKey; IoStatus = Irp->IoStatus;
*CompletionContext = Irp->Overlay.AsynchronousParameters.UserApcContext;
*IoStatusBlock = Packet->IoStatus;
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
Status = _SEH_GetExceptionCode();
} _SEH_END;
/* Free the IRP */
IoFreeIrp(Irp); IoFreeIrp(Irp);
} }
else else
{ {
/* This is a user-mode generated or API generated mini-packet */ /* Save values */
_SEH_TRY { Key = Packet->Key;
Apc = Packet->Context;
*CompletionKey = Packet->Key; IoStatus = Packet->IoStatus;
*CompletionContext = Packet->Context;
*IoStatusBlock = Packet->IoStatus;
} _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
Status = _SEH_GetExceptionCode();
} _SEH_END;
/* Free the packet */
IopFreeIoCompletionPacket(Packet); IopFreeIoCompletionPacket(Packet);
} }
/* Enter SEH to write back the values */
_SEH_TRY
{
/* Write the values to caller */
*ApcContext = Apc;
*KeyContext = Key;
*IoStatusBlock = IoStatus;
}
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
} }
/* Dereference the Object */ /* Dereference the Object */
@ -516,11 +547,8 @@ NtRemoveIoCompletion(IN HANDLE IoCompletionHandle,
return Status; return Status;
} }
/*
* Queues an I/O completion message to an I/O completion object
*/
NTSTATUS NTSTATUS
STDCALL NTAPI
NtSetIoCompletion(IN HANDLE IoCompletionPortHandle, NtSetIoCompletion(IN HANDLE IoCompletionPortHandle,
IN PVOID CompletionKey, IN PVOID CompletionKey,
IN PVOID CompletionContext, IN PVOID CompletionContext,
@ -529,7 +557,6 @@ NtSetIoCompletion(IN HANDLE IoCompletionPortHandle,
{ {
NTSTATUS Status; NTSTATUS Status;
PKQUEUE Queue; PKQUEUE Queue;
PAGED_CODE(); PAGED_CODE();
/* Get the Object */ /* Get the Object */
@ -539,10 +566,8 @@ NtSetIoCompletion(IN HANDLE IoCompletionPortHandle,
ExGetPreviousMode(), ExGetPreviousMode(),
(PVOID*)&Queue, (PVOID*)&Queue,
NULL); NULL);
if (NT_SUCCESS(Status))
/* Check for Success */ {
if (NT_SUCCESS(Status)) {
/* Set the Completion */ /* Set the Completion */
Status = IoSetIoCompletion(Queue, Status = IoSetIoCompletion(Queue,
CompletionKey, CompletionKey,
@ -550,6 +575,8 @@ NtSetIoCompletion(IN HANDLE IoCompletionPortHandle,
CompletionStatus, CompletionStatus,
CompletionInformation, CompletionInformation,
TRUE); TRUE);
/* Dereference the object */
ObDereferenceObject(Queue); ObDereferenceObject(Queue);
} }