reactos/ntoskrnl/io
diff -u -r1.16 -r1.17
--- iocomp.c 25 Nov 2004 22:18:16 -0000 1.16
+++ iocomp.c 21 Dec 2004 02:34:32 -0000 1.17
@@ -279,6 +279,8 @@
{
PKQUEUE Queue;
NTSTATUS Status;
+ PIO_COMPLETION_PACKET Packet;
+ PLIST_ENTRY ListEntry;
Status = ObReferenceObjectByHandle( IoCompletionHandle,
IO_COMPLETION_MODIFY_STATE,
@@ -286,29 +288,45 @@
UserMode,
(PVOID*)&Queue,
NULL);
- if (NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
- PIO_COMPLETION_PACKET Packet;
- PLIST_ENTRY ListEntry;
+ return Status;
+ }
- /*
- Try 2 remove packet from queue. Wait (optionaly) if
- no packet in queue or max num of threads allready running.
- */
+ /*
+ 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 );
- ObDereferenceObject(Queue);
-
- Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
+ /* 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 (CompletionKey) *CompletionKey = Packet->Key;
- if (CompletionContext) *CompletionContext = Packet->Context;
- if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
+ } while((NTSTATUS)ListEntry == STATUS_USER_APC);
- ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
+ ObDereferenceObject(Queue);
+
+ if ((NTSTATUS)ListEntry == STATUS_TIMEOUT)
+ {
+ return STATUS_TIMEOUT;
}
+
+ ASSERT(ListEntry);
+
+ Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
- return Status;
+ if (CompletionKey) *CompletionKey = Packet->Key;
+ if (CompletionContext) *CompletionContext = Packet->Context;
+ if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
+
+ ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
+
+ return STATUS_SUCCESS;
}