update for HEAD-2003050101
[reactos.git] / ntoskrnl / io / iocomp.c
index 21b672d..0bb9b96 100644 (file)
 
 /* INCLUDES *****************************************************************/
 
+#include <limits.h>
 #include <ddk/ntddk.h>
+#include <ntos/synch.h>
 
+#define NDEBUG
 #include <internal/debug.h>
 
+#define IOC_TAG   TAG('I', 'O', 'C', 'T')   
+
+POBJECT_TYPE ExIoCompletionType;
+
+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
+};
+
 /* FUNCTIONS *****************************************************************/
 
+NTSTATUS 
+STDCALL
+NtpCreateIoCompletion(
+   PVOID                ObjectBody,
+   PVOID                Parent,
+   PWSTR                RemainingPath,
+   POBJECT_ATTRIBUTES   ObjectAttributes
+   )
+{
+   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;
+}
+
+VOID STDCALL
+NtpDeleteIoCompletion(PVOID ObjectBody)
+{
+   PKQUEUE Queue = ObjectBody;
+
+   DPRINT("NtpDeleteIoCompletion()\n");
+
+   KeRundownQueue(Queue);
+}
+
+
+VOID 
+NtInitializeIoCompletionImplementation(VOID)
+{
+   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);
+}
+
+
 NTSTATUS
 STDCALL
-NtCreateIoCompletion ( 
-       OUT     PHANDLE                 CompletionPort,
-       IN      ACCESS_MASK             DesiredAccess,
-       OUT     PIO_STATUS_BLOCK        IoStatusBlock,
-       IN      ULONG                   NumberOfConcurrentThreads
-       )
+NtCreateIoCompletion(
+   OUT PHANDLE             IoCompletionHandle,
+   IN  ACCESS_MASK         DesiredAccess,
+   IN  POBJECT_ATTRIBUTES  ObjectAttributes,
+   IN  ULONG               NumberOfConcurrentThreads
+   )
 {
-       UNIMPLEMENTED;
+   PKQUEUE     Queue;
+   NTSTATUS    Status;
+   
+   Status = ObCreateObject(IoCompletionHandle,
+                           DesiredAccess,
+                           ObjectAttributes,
+                           ExIoCompletionType,
+                           (PVOID*)&Queue);
+
+   if (NT_SUCCESS(Status))
+   {
+      (void) KeInitializeQueue(Queue, NumberOfConcurrentThreads);
+      ObDereferenceObject(Queue);
+   }
+
+   return Status;
+   /*
+
+  CompletionPort = NULL OR ExistingCompletionPort
+
+  */
+
 }
 
+/*
+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                 CompletionPort,
-       IN      ACCESS_MASK             DesiredAccess,
-       IN      POBJECT_ATTRIBUTES      ObjectAttributes
-       )
+NtOpenIoCompletion(
+   OUT PHANDLE             IoCompletionHandle,
+   IN  ACCESS_MASK         DesiredAccess,
+   IN  POBJECT_ATTRIBUTES  ObjectAttributes
+   )
 {
-       return(STATUS_SUCCESS);
+   NTSTATUS Status;
+   
+   Status = ObOpenObjectByName(ObjectAttributes,
+                               ExIoCompletionType,
+                               NULL,
+                               UserMode,
+                               DesiredAccess,
+                               NULL,
+                               IoCompletionHandle);  //<- ???
+   
+   return Status;
 }
 
 
 NTSTATUS
 STDCALL
-NtQueryIoCompletion (
-       IN      HANDLE                  CompletionPort,
-       IN      ULONG                   CompletionKey,
-       OUT     PIO_STATUS_BLOCK        IoStatusBlock,
-       OUT     PULONG                  NumberOfBytesTransferred
-       )
+NtQueryIoCompletion(
+   IN  HANDLE                          IoCompletionHandle,
+   IN  IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
+   OUT PVOID                           IoCompletionInformation,
+   IN  ULONG                           IoCompletionInformationLength,
+   OUT PULONG                          ResultLength OPTIONAL
+   )
 {
-       UNIMPLEMENTED;
+   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,
+                                       IO_COMPLETION_QUERY_STATE,
+                                       ExIoCompletionType,
+                                       UserMode,
+                                       (PVOID*)&Queue,
+                                       NULL);
+   if (NT_SUCCESS(Status))
+   {
+      ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->SignalState = 
+         Queue->Header.SignalState;
+
+      ObDereferenceObject(Queue);
+
+      if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
+   }
+
+   return Status;
 }
 
 
+/*
+ * Dequeues an I/O completion message from an I/O completion object
+ */
 NTSTATUS
 STDCALL
-NtRemoveIoCompletion (
-       IN      HANDLE                  CompletionPort,
-       OUT     PULONG                  CompletionKey,
-       OUT     PIO_STATUS_BLOCK        IoStatusBlock,
-       OUT     PULONG                  CompletionStatus,
-               PLARGE_INTEGER          WaitTime
-               )
+NtRemoveIoCompletion(
+   IN  HANDLE           IoCompletionHandle,
+   OUT PULONG           CompletionKey,
+   OUT PULONG           CompletionValue,
+   OUT PIO_STATUS_BLOCK IoStatusBlock,
+   IN  PLARGE_INTEGER   Timeout OPTIONAL
+   )
 {
-       UNIMPLEMENTED;
+   PKQUEUE  Queue;
+   NTSTATUS Status;
+      
+   Status = ObReferenceObjectByHandle( IoCompletionHandle,
+                                       IO_COMPLETION_MODIFY_STATE,
+                                       ExIoCompletionType,
+                                       UserMode,
+                                       (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 );
+
+      ObDereferenceObject(Queue);
+
+      Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
+
+      if (CompletionKey) *CompletionKey = Packet->Key;
+      if (CompletionValue) *CompletionValue = Packet->Overlapped;
+      if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
+
+      ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
+   }
+
+   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                  CompletionPort,
-       IN      ULONG                   CompletionKey,
-       OUT     PIO_STATUS_BLOCK        IoStatusBlock,
-       IN      ULONG                   NumberOfBytesToTransfer, 
-       OUT     PULONG                  NumberOfBytesTransferred
-       )
+NtSetIoCompletion(
+   IN HANDLE   IoCompletionPortHandle,
+   IN ULONG    CompletionKey,
+   IN ULONG    CompletionValue,
+   IN NTSTATUS CompletionStatus,
+   IN ULONG    CompletionInformation
+   )
 {
-       UNIMPLEMENTED;
+   NTSTATUS                Status;
+   PKQUEUE                 Queue;
+
+   Status = ObReferenceObjectByHandle( IoCompletionPortHandle,
+                                       IO_COMPLETION_MODIFY_STATE,
+                                       ExIoCompletionType,
+                                       UserMode,
+                                       (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;
 }