initial work on I/O completion
authorGunnar Dalsnes <hardon@online.no>
Wed, 19 Mar 2003 23:17:52 +0000 (23:17 +0000)
committerGunnar Dalsnes <hardon@online.no>
Wed, 19 Mar 2003 23:17:52 +0000 (23:17 +0000)
svn path=/trunk/; revision=4352

12 files changed:
reactos/include/ddk/extypes.h
reactos/include/ddk/iotypes.h
reactos/include/ddk/kefuncs.h
reactos/include/ddk/ketypes.h
reactos/include/ntos/synch.h
reactos/include/ntos/zw.h
reactos/include/ntos/zwtypes.h
reactos/lib/kernel32/file/iocompl.c
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/io/file.c
reactos/ntoskrnl/io/iocomp.c
reactos/ntoskrnl/ke/queue.c

index 06d4693..4e6bbc8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: extypes.h,v 1.12 2002/11/24 18:26:40 robd Exp $ */
+/* $Id: extypes.h,v 1.13 2003/03/19 23:14:11 gdalsnes Exp $ */
 
 #ifndef __INCLUDE_DDK_EXTYPES_H
 #define __INCLUDE_DDK_EXTYPES_H
 
 #ifndef __INCLUDE_DDK_EXTYPES_H
 #define __INCLUDE_DDK_EXTYPES_H
@@ -7,10 +7,12 @@
 extern POBJECT_TYPE EXPORTED ExDesktopObjectType;
 extern POBJECT_TYPE EXPORTED ExEventObjectType;
 extern POBJECT_TYPE EXPORTED ExWindowStationObjectType;
 extern POBJECT_TYPE EXPORTED ExDesktopObjectType;
 extern POBJECT_TYPE EXPORTED ExEventObjectType;
 extern POBJECT_TYPE EXPORTED ExWindowStationObjectType;
+extern POBJECT_TYPE EXPORTED ExIoCompletionType;
 #else
 extern POBJECT_TYPE IMPORTED ExDesktopObjectType;
 extern POBJECT_TYPE IMPORTED ExEventObjectType;
 extern POBJECT_TYPE IMPORTED ExWindowStationObjectType;
 #else
 extern POBJECT_TYPE IMPORTED ExDesktopObjectType;
 extern POBJECT_TYPE IMPORTED ExEventObjectType;
 extern POBJECT_TYPE IMPORTED ExWindowStationObjectType;
+extern POBJECT_TYPE IMPORTED ExIoCompletionType;
 #endif
 
 typedef ULONG INTERLOCKED_RESULT;
 #endif
 
 typedef ULONG INTERLOCKED_RESULT;
index 3bf3fa6..b72d139 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: iotypes.h,v 1.45 2002/11/24 18:26:40 robd Exp $
+/* $Id: iotypes.h,v 1.46 2003/03/19 23:14:29 gdalsnes Exp $
  *
  */
 
  *
  */
 
@@ -465,6 +465,12 @@ typedef struct _IO_STATUS_BLOCK
   ULONG Information;
 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
 
   ULONG Information;
 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
 
+typedef struct _IO_COMPLETION_PACKET{
+   ULONG             Key;
+   ULONG             Overlapped;
+   IO_STATUS_BLOCK   IoStatus;
+   LIST_ENTRY        ListEntry;
+} IO_COMPLETION_PACKET, *PIO_COMPLETION_PACKET;
 
 typedef struct _IO_PIPE_CREATE_BUFFER
 {
 
 typedef struct _IO_PIPE_CREATE_BUFFER
 {
index b99a1be..6322bf2 100644 (file)
@@ -135,6 +135,9 @@ VOID STDCALL
 KeInitializeQueue(IN PKQUEUE Queue,
                  IN ULONG Count);
 
 KeInitializeQueue(IN PKQUEUE Queue,
                  IN ULONG Count);
 
+PLIST_ENTRY STDCALL
+KeRundownQueue(IN PKQUEUE Queue);
+
 VOID STDCALL KeInitializeSemaphore (PKSEMAPHORE        Semaphore,
                                    LONG                Count,
                                    LONG                Limit);
 VOID STDCALL KeInitializeSemaphore (PKSEMAPHORE        Semaphore,
                                    LONG                Count,
                                    LONG                Limit);
index be4b6e4..7851386 100644 (file)
@@ -122,9 +122,9 @@ typedef struct _KQUEUE
 {
    DISPATCHER_HEADER Header;
    LIST_ENTRY        EntryListHead;
 {
    DISPATCHER_HEADER Header;
    LIST_ENTRY        EntryListHead;
-   ULONG             CurrentCount;
-   ULONG             MaximumCount;
-   LIST_ENTRY        ThreadListEntry;
+   ULONG             RunningThreads;
+   ULONG             MaximumThreads;
+   LIST_ENTRY        ThreadListHead;
 } KQUEUE, *PKQUEUE;
 
 struct _KDPC;
 } KQUEUE, *PKQUEUE;
 
 struct _KDPC;
index be138d4..a77a880 100644 (file)
@@ -27,6 +27,9 @@
 #define TIMER_ALL_ACCESS       (0x1f0003L)
 #define TIMER_QUERY_STATE      (1)
 #define TIMER_MODIFY_STATE     (2)
 #define TIMER_ALL_ACCESS       (0x1f0003L)
 #define TIMER_QUERY_STATE      (1)
 #define TIMER_MODIFY_STATE     (2)
+#define IO_COMPLETION_QUERY_STATE       (0x0001)
+#define IO_COMPLETION_MODIFY_STATE      (0x0002)
+#define IO_COMPLETION_ALL_ACCESS        (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
 
 #endif /* !__USE_W32API */
 
 
 #endif /* !__USE_W32API */
 
index 43f7ce7..1dedb83 100755 (executable)
@@ -1,5 +1,5 @@
 
 
-/* $Id: zw.h,v 1.8 2003/02/27 22:49:06 ekohl Exp $
+/* $Id: zw.h,v 1.9 2003/03/19 23:16:00 gdalsnes Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -497,21 +497,20 @@ ZwCreateFile(
 NTSTATUS
 STDCALL
 NtCreateIoCompletion(
 NTSTATUS
 STDCALL
 NtCreateIoCompletion(
-       OUT PHANDLE CompletionPort,
-       IN ACCESS_MASK DesiredAccess,
-       OUT PIO_STATUS_BLOCK IoStatusBlock,
-       IN ULONG NumberOfConcurrentThreads
-       );
+   OUT PHANDLE             IoCompletionHandle,
+   IN  ACCESS_MASK         DesiredAccess,
+   IN  POBJECT_ATTRIBUTES  ObjectAttributes,
+   IN  ULONG               NumberOfConcurrentThreads
+   );
 
 NTSTATUS
 STDCALL
 ZwCreateIoCompletion(
 
 NTSTATUS
 STDCALL
 ZwCreateIoCompletion(
-       OUT PHANDLE CompletionPort,
-       IN ACCESS_MASK DesiredAccess,
-       OUT PIO_STATUS_BLOCK IoStatusBlock,
-       IN ULONG NumberOfConcurrentThreads
-       );
-
+   OUT PHANDLE             IoCompletionHandle,
+   IN  ACCESS_MASK         DesiredAccess,
+   IN  POBJECT_ATTRIBUTES  ObjectAttributes,
+   IN  ULONG               NumberOfConcurrentThreads
+   );
 
 /*
  * FUNCTION: Creates a registry key
 
 /*
  * FUNCTION: Creates a registry key
@@ -2357,20 +2356,22 @@ ZwQueryInformationToken(
 NTSTATUS
 STDCALL
 NtQueryIoCompletion(
 NTSTATUS
 STDCALL
 NtQueryIoCompletion(
-       IN HANDLE CompletionPort,
-       IN ULONG CompletionKey,
-       OUT PIO_STATUS_BLOCK IoStatusBlock,
-       OUT PULONG NumberOfBytesTransferred
-       );
+   IN  HANDLE                          IoCompletionHandle,
+   IN  IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
+   OUT PVOID                           IoCompletionInformation,
+   IN  ULONG                           IoCompletionInformationLength,
+   OUT PULONG                          ResultLength OPTIONAL
+   );
+
 NTSTATUS
 STDCALL
 ZwQueryIoCompletion(
 NTSTATUS
 STDCALL
 ZwQueryIoCompletion(
-       IN HANDLE CompletionPort,
-       IN ULONG CompletionKey,
-       OUT PIO_STATUS_BLOCK IoStatusBlock,
-       OUT PULONG NumberOfBytesTransferred
-       );
-
+   IN  HANDLE                          IoCompletionHandle,
+   IN  IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
+   OUT PVOID                           IoCompletionInformation,
+   IN  ULONG                           IoCompletionInformationLength,
+   OUT PULONG                          ResultLength OPTIONAL
+   );
 
 /*
  * FUNCTION: Queries the information of a registry key object.
 
 /*
  * FUNCTION: Queries the information of a registry key object.
@@ -2990,22 +2991,23 @@ ZwReleaseSemaphore(
 NTSTATUS
 STDCALL
 NtRemoveIoCompletion(
 NTSTATUS
 STDCALL
 NtRemoveIoCompletion(
-       IN HANDLE CompletionPort,
-       OUT PULONG CompletionKey,
-       OUT PIO_STATUS_BLOCK IoStatusBlock,
-       OUT PULONG CompletionStatus,
-       IN PLARGE_INTEGER WaitTime 
-       );
+   IN  HANDLE           IoCompletionHandle,
+   OUT PULONG           CompletionKey,
+   OUT PULONG           CompletionValue,
+   OUT PIO_STATUS_BLOCK IoStatusBlock,
+   IN  PLARGE_INTEGER   Timeout OPTIONAL
+   );
 
 NTSTATUS
 STDCALL
 ZwRemoveIoCompletion(
 
 NTSTATUS
 STDCALL
 ZwRemoveIoCompletion(
-       IN HANDLE CompletionPort,
-       OUT PULONG CompletionKey,
-       OUT PIO_STATUS_BLOCK IoStatusBlock,
-       OUT PULONG CompletionStatus,
-       IN PLARGE_INTEGER WaitTime 
-       );
+   IN  HANDLE           IoCompletionHandle,
+   OUT PULONG           CompletionKey,
+   OUT PULONG           CompletionValue,
+   OUT PIO_STATUS_BLOCK IoStatusBlock,
+   IN  PLARGE_INTEGER   Timeout OPTIONAL
+   );
+
 /*
  * FUNCTION: Replaces one registry key with another
  * ARGUMENTS: 
 /*
  * FUNCTION: Replaces one registry key with another
  * ARGUMENTS: 
@@ -3392,21 +3394,22 @@ ZwSetInformationToken(
 NTSTATUS
 STDCALL
 NtSetIoCompletion(
 NTSTATUS
 STDCALL
 NtSetIoCompletion(
-       IN HANDLE CompletionPort,
-       IN ULONG CompletionKey,
-       OUT PIO_STATUS_BLOCK IoStatusBlock,
-       IN ULONG NumberOfBytesToTransfer, 
-       OUT PULONG NumberOfBytesTransferred
-       );
+   IN HANDLE   IoCompletionPortHandle,
+   IN ULONG    CompletionKey,
+   IN ULONG    CompletionValue,
+   IN NTSTATUS CompletionStatus,
+   IN ULONG    CompletionInformation
+   );
+
 NTSTATUS
 STDCALL
 ZwSetIoCompletion(
 NTSTATUS
 STDCALL
 ZwSetIoCompletion(
-       IN HANDLE CompletionPort,
-       IN ULONG CompletionKey,
-       OUT PIO_STATUS_BLOCK IoStatusBlock,
-       IN ULONG NumberOfBytesToTransfer, 
-       OUT PULONG NumberOfBytesTransferred
-       );
+   IN HANDLE   IoCompletionPortHandle,
+   IN ULONG    CompletionKey,
+   IN ULONG    CompletionValue,
+   IN NTSTATUS CompletionStatus,
+   IN ULONG    CompletionInformation
+   );
 
 /*
  * FUNCTION: Set properties for profiling
 
 /*
  * FUNCTION: Set properties for profiling
index 4c1a7bf..28a3dcc 100755 (executable)
@@ -881,6 +881,11 @@ typedef struct _FILE_COMPRESSION_INFORMATION {
        UCHAR Reserved[3];
 } FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION;
 
        UCHAR Reserved[3];
 } FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION;
 
+typedef struct _FILE_COMPLETION_INFORMATION { // Information Class 30
+   HANDLE IoCompletionHandle;
+   ULONG CompletionKey;
+} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION;
+
 typedef struct _FILE_ALL_INFORMATION {
        FILE_BASIC_INFORMATION BasicInformation;
        FILE_STANDARD_INFORMATION StandardInformation;
 typedef struct _FILE_ALL_INFORMATION {
        FILE_BASIC_INFORMATION BasicInformation;
        FILE_STANDARD_INFORMATION StandardInformation;
@@ -1069,6 +1074,14 @@ typedef enum SHUTDOWN_ACTION_TAG {
   ShutdownPowerOff
 } SHUTDOWN_ACTION;
 
   ShutdownPowerOff
 } SHUTDOWN_ACTION;
 
+typedef enum _IO_COMPLETION_INFORMATION_CLASS {
+   IoCompletionBasicInformation
+} IO_COMPLETION_INFORMATION_CLASS;
+
+typedef struct _IO_COMPLETION_BASIC_INFORMATION {
+   LONG SignalState;
+} IO_COMPLETION_BASIC_INFORMATION, *PIO_COMPLETION_BASIC_INFORMATION;
+
 #else /* __USE_W32API */
 
 #define DebugDbgLoadSymbols ((DEBUG_CONTROL_CODE)0xffffffff)
 #else /* __USE_W32API */
 
 #define DebugDbgLoadSymbols ((DEBUG_CONTROL_CODE)0xffffffff)
index 1b406fc..f6f97fb 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: iocompl.c,v 1.8 2003/02/03 14:19:30 ekohl Exp $
+/* $Id: iocompl.c,v 1.9 2003/03/19 23:16:55 gdalsnes Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
 
 #include <kernel32/error.h>
 
 
 #include <kernel32/error.h>
 
-
-typedef struct _FILE_COMPLETION_INFORMATION {
-    HANDLE CompletionPort;
-    ULONG CompletionKey;
-} FILE_COMPLETION_INFORMATION;
-typedef FILE_COMPLETION_INFORMATION *PFILE_COMPLETION_INFORMATION;
-
-
-VOID
-STDCALL
-FileIOCompletionRoutine(
-       DWORD dwErrorCode,
-       DWORD dwNumberOfBytesTransfered,
-       LPOVERLAPPED lpOverlapped
-       );
-
-
 HANDLE
 STDCALL
 CreateIoCompletionPort(
 HANDLE
 STDCALL
 CreateIoCompletionPort(
@@ -40,99 +23,146 @@ CreateIoCompletionPort(
     DWORD NumberOfConcurrentThreads
     )
 {
     DWORD NumberOfConcurrentThreads
     )
 {
-       HANDLE CompletionPort = NULL;
-       NTSTATUS errCode;
-       FILE_COMPLETION_INFORMATION CompletionInformation;
-       IO_STATUS_BLOCK IoStatusBlock;
-
-        if ( ExistingCompletionPort == NULL && FileHandle == INVALID_HANDLE_VALUE ) {
-                SetLastErrorByStatus (STATUS_INVALID_PARAMETER);
-                return FALSE;
-        }
-
-        if ( ExistingCompletionPort != NULL ) {
-                CompletionPort = ExistingCompletionPort;
-       }
-       else {
-                errCode = NtCreateIoCompletion(&CompletionPort,GENERIC_ALL,&IoStatusBlock,NumberOfConcurrentThreads);
-                if (!NT_SUCCESS(errCode) ) {
-                        SetLastErrorByStatus (errCode);
-                        return FALSE;
-                }
-
-        }
-        if ( FileHandle != INVALID_HANDLE_VALUE ) {
-
-               CompletionInformation.CompletionPort = CompletionPort;
-                CompletionInformation.CompletionKey  = CompletionKey;
-
-                errCode = NtSetInformationFile(FileHandle, &IoStatusBlock,&CompletionInformation,sizeof(FILE_COMPLETION_INFORMATION),FileCompletionInformation);
-                if ( !NT_SUCCESS(errCode) ) {
-                       if ( ExistingCompletionPort == NULL )
-                               NtClose(CompletionPort);
-                        SetLastErrorByStatus (errCode);
-                        return FALSE;
-                }
-        }
-
-        return CompletionPort;
+   HANDLE CompletionPort = NULL;
+   NTSTATUS errCode;
+   FILE_COMPLETION_INFORMATION CompletionInformation;
+   IO_STATUS_BLOCK IoStatusBlock;
+
+   if ( ExistingCompletionPort == NULL && FileHandle == INVALID_HANDLE_VALUE ) 
+   {
+      SetLastErrorByStatus (STATUS_INVALID_PARAMETER);
+      return FALSE;
+   }
+
+   if ( ExistingCompletionPort != NULL ) 
+   {
+      CompletionPort = ExistingCompletionPort;
+   }
+   else 
+   {
+
+      errCode = NtCreateIoCompletion(&CompletionPort,
+                                     IO_COMPLETION_ALL_ACCESS,
+                                     NULL,//ObjectAttributes
+                                     NumberOfConcurrentThreads);
+
+      if (!NT_SUCCESS(errCode) ) 
+      {
+         SetLastErrorByStatus (errCode);
+         return FALSE;
+      }
+
+   }
+   
+   if ( FileHandle != INVALID_HANDLE_VALUE ) 
+   {
+      CompletionInformation.IoCompletionHandle = CompletionPort;
+      CompletionInformation.CompletionKey  = CompletionKey;
+
+      errCode = NtSetInformationFile(FileHandle, 
+                                     &IoStatusBlock,
+                                     &CompletionInformation,
+                                     sizeof(FILE_COMPLETION_INFORMATION),
+                                     FileCompletionInformation);
+
+      if ( !NT_SUCCESS(errCode) ) 
+      {
+         if ( ExistingCompletionPort == NULL )
+         {
+            NtClose(CompletionPort);
+         }
+   
+         SetLastErrorByStatus (errCode);
+         return FALSE;
+      }
+   }
+
+   return CompletionPort;
 }
 
 
 WINBOOL
 STDCALL
 GetQueuedCompletionStatus(
 }
 
 
 WINBOOL
 STDCALL
 GetQueuedCompletionStatus(
-                         HANDLE CompletionPort,
-                         LPDWORD lpNumberOfBytesTransferred,
-                         LPDWORD lpCompletionKey,
-                         LPOVERLAPPED *lpOverlapped,
-                         DWORD dwMilliseconds
-                         )
+   HANDLE CompletionHandle,
+   LPDWORD lpNumberOfBytesTransferred,
+   LPDWORD lpCompletionKey,
+   LPOVERLAPPED *lpOverlapped,
+   DWORD dwMilliseconds
+   )
 {
 {
-       NTSTATUS errCode;
-       ULONG CompletionStatus;
-       LARGE_INTEGER TimeToWait;
+   NTSTATUS errCode;
+   IO_STATUS_BLOCK IoStatus;
+   LARGE_INTEGER Interval;
+
+   if (!lpNumberOfBytesTransferred||!lpCompletionKey||!lpOverlapped)
+   {
+      return ERROR_INVALID_PARAMETER;
+   }
+
+   if (dwMilliseconds != INFINITE)
+   {
+      /*
+       * System time units are 100 nanoseconds (a nanosecond is a billionth of
+       * a second).
+       */
+      Interval.QuadPart = dwMilliseconds;
+      Interval.QuadPart = -(Interval.QuadPart * 10000);
+   }  
+   else
+   {
+      /* Approximately 292000 years hence */
+      Interval.QuadPart = -0x7FFFFFFFFFFFFFFF;
+   }
+
+   errCode = NtRemoveIoCompletion(CompletionHandle,
+                                  lpCompletionKey,
+                                  lpNumberOfBytesTransferred,
+                                  &IoStatus,
+                                  &Interval);
+
+   if (!NT_SUCCESS(errCode) ) {
+      *lpOverlapped = NULL;
+      SetLastErrorByStatus(errCode);
+      return FALSE;
+   }
+
+   *lpOverlapped = (LPOVERLAPPED)IoStatus.Information;
+
+   if (!NT_SUCCESS(IoStatus.Status)){
+      //failed io operation
+      SetLastErrorByStatus (IoStatus.Status);
+      return FALSE;
+   }
+
+   return TRUE;
 
 
-       errCode = NtRemoveIoCompletion(CompletionPort,(PULONG)lpCompletionKey,(PIO_STATUS_BLOCK)lpOverlapped,&CompletionStatus,&TimeToWait);
-       if (!NT_SUCCESS(errCode) ) {
-               SetLastErrorByStatus (errCode);
-               return FALSE;
-       }
-
-       return TRUE;
 }
 
 
 WINBOOL
 STDCALL
 PostQueuedCompletionStatus(
 }
 
 
 WINBOOL
 STDCALL
 PostQueuedCompletionStatus(
-  HANDLE CompletionPort,
-  DWORD dwNumberOfBytesTransferred,
-  DWORD dwCompletionKey,
-  LPOVERLAPPED lpOverlapped
-)
-{
-       NTSTATUS errCode;
-       errCode = NtSetIoCompletion(CompletionPort,  dwCompletionKey, (PIO_STATUS_BLOCK)lpOverlapped , 0, (PULONG)&dwNumberOfBytesTransferred );
-
-       if ( !NT_SUCCESS(errCode) ) {
-               SetLastErrorByStatus (errCode);
-               return FALSE;
-       }
-       return TRUE;
-}
-
-
-// this should be a place holder ??????????????????
-VOID
-STDCALL
-FileIOCompletionRoutine(
-       DWORD dwErrorCode,
-       DWORD dwNumberOfBytesTransfered,
-       LPOVERLAPPED lpOverlapped
-       )
+   HANDLE CompletionHandle,
+   DWORD dwNumberOfBytesTransferred,
+   DWORD dwCompletionKey,
+   LPOVERLAPPED lpOverlapped
+   )
 {
 {
-       return;
+   NTSTATUS errCode;
+
+   errCode = NtSetIoCompletion(CompletionHandle,  
+                               dwCompletionKey, 
+                               dwNumberOfBytesTransferred,//CompletionValue 
+                               0,                         //IoStatusBlock->Status
+                               (ULONG)lpOverlapped );     //IoStatusBlock->Information
+
+   if ( !NT_SUCCESS(errCode) ) 
+   {
+      SetLastErrorByStatus (errCode);
+      return FALSE;
+   }
+   return TRUE;
 }
 
 
 }
 
 
index 93c1ce5..e41a3e8 100644 (file)
@@ -58,6 +58,8 @@ VOID
 KiDeliverNormalApc(VOID);
 
 BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc);
 KiDeliverNormalApc(VOID);
 
 BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc);
+PLIST_ENTRY STDCALL KeRundownQueue(IN PKQUEUE Queue);
+
 
 /* INITIALIZATION FUNCTIONS *************************************************/
 
 
 /* INITIALIZATION FUNCTIONS *************************************************/
 
index dc50e9f..3d1a214 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: file.c,v 1.21 2002/09/08 10:23:24 chorns Exp $
+/* $Id: file.c,v 1.22 2003/03/19 23:11:23 gdalsnes Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -236,7 +236,39 @@ NtSetInformationFile(HANDLE FileHandle,
      }
    
    DPRINT("FileObject %x\n", FileObject);
      }
    
    DPRINT("FileObject %x\n", FileObject);
-   
+
+   //io completion port?
+   if (FileInformationClass == FileCompletionInformation)
+   {
+      PKQUEUE Queue;
+
+      if (Length < sizeof(FILE_COMPLETION_INFORMATION))
+      {
+         Status = STATUS_INFO_LENGTH_MISMATCH;
+      }
+      else
+      {
+         Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
+                                            IO_COMPLETION_MODIFY_STATE,//???
+                                            ExIoCompletionType,
+                                            UserMode,
+                                            (PVOID*)&Queue,
+                                            NULL);
+         if (NT_SUCCESS(Status))
+         {   
+            //FIXME: maybe use lookaside list
+            FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
+            FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
+            FileObject->CompletionContext->Port = Queue;
+
+            ObDereferenceObject(Queue);
+         }
+      }
+
+      ObDereferenceObject(FileObject);
+      return Status;
+   }
+
    DeviceObject = FileObject->DeviceObject;
    
    Irp = IoAllocateIrp(DeviceObject->StackSize,
    DeviceObject = FileObject->DeviceObject;
    
    Irp = IoAllocateIrp(DeviceObject->StackSize,
index 21b672d..0bb9b96 100644 (file)
 
 /* INCLUDES *****************************************************************/
 
 
 /* INCLUDES *****************************************************************/
 
+#include <limits.h>
 #include <ddk/ntddk.h>
 #include <ddk/ntddk.h>
+#include <ntos/synch.h>
 
 
+#define NDEBUG
 #include <internal/debug.h>
 
 #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 *****************************************************************/
 
 /* 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
 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
 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
 }
 
 
 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
 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
 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;
 }
 }
index c44c7f2..2d30736 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: queue.c,v 1.4 2002/11/10 18:17:41 chorns Exp $
+/* $Id: queue.c,v 1.5 2003/03/19 23:10:31 gdalsnes Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/queue.c
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/queue.c
@@ -31,6 +31,7 @@
 #include <ddk/ntddk.h>
 #include <internal/ke.h>
 #include <internal/id.h>
 #include <ddk/ntddk.h>
 #include <internal/ke.h>
 #include <internal/id.h>
+#include <internal/ps.h>
 
 #define NDEBUG
 #include <internal/debug.h>
 
 #define NDEBUG
 #include <internal/debug.h>
@@ -46,9 +47,9 @@ KeInitializeQueue(IN PKQUEUE Queue,
                               sizeof(KQUEUE)/sizeof(ULONG),
                               0);
   InitializeListHead(&Queue->EntryListHead);
                               sizeof(KQUEUE)/sizeof(ULONG),
                               0);
   InitializeListHead(&Queue->EntryListHead);
-  InitializeListHead(&Queue->ThreadListEntry);
-  Queue->CurrentCount = 0;
-  Queue->MaximumCount = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
+  InitializeListHead(&Queue->ThreadListHead);
+  Queue->RunningThreads = 0;
+  Queue->MaximumThreads = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
 }
 
 
 }
 
 
@@ -59,12 +60,47 @@ KeReadStateQueue(IN PKQUEUE Queue)
 }
 
 
 }
 
 
+LONG STDCALL
+KiInsertQueue(
+   IN PKQUEUE Queue,
+   IN PLIST_ENTRY Entry,
+   BOOLEAN Head
+   )
+{
+   ULONG InitialState;
+  
+   DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
+   
+   KeAcquireDispatcherDatabaseLock(FALSE);
+   
+   InitialState = Queue->Header.SignalState;
+   Queue->Header.SignalState++;
+   
+   if (Head)
+   {
+      InsertHeadList(&Queue->EntryListHead, Entry);
+   }
+   else
+   {
+      InsertTailList(&Queue->EntryListHead, Entry);
+   }
+
+   if (Queue->RunningThreads < Queue->MaximumThreads && InitialState == 0)
+   {
+      KeDispatcherObjectWake(&Queue->Header);
+   }
+
+   KeReleaseDispatcherDatabaseLock(FALSE);
+   return InitialState;
+}
+
+
+
 LONG STDCALL
 KeInsertHeadQueue(IN PKQUEUE Queue,
                  IN PLIST_ENTRY Entry)
 {
 LONG STDCALL
 KeInsertHeadQueue(IN PKQUEUE Queue,
                  IN PLIST_ENTRY Entry)
 {
-  UNIMPLEMENTED;
-  return 0;
+   return KiInsertQueue(Queue,Entry,TRUE);
 }
 
 
 }
 
 
@@ -72,8 +108,7 @@ LONG STDCALL
 KeInsertQueue(IN PKQUEUE Queue,
              IN PLIST_ENTRY Entry)
 {
 KeInsertQueue(IN PKQUEUE Queue,
              IN PLIST_ENTRY Entry)
 {
-  UNIMPLEMENTED;
-  return 0;
+   return KiInsertQueue(Queue,Entry,FALSE);
 }
 
 
 }
 
 
@@ -82,16 +117,88 @@ KeRemoveQueue(IN PKQUEUE Queue,
              IN KPROCESSOR_MODE WaitMode,
              IN PLARGE_INTEGER Timeout OPTIONAL)
 {
              IN KPROCESSOR_MODE WaitMode,
              IN PLARGE_INTEGER Timeout OPTIONAL)
 {
-  UNIMPLEMENTED;
-  return NULL;
+   PLIST_ENTRY ListEntry;
+   NTSTATUS Status;
+   PKTHREAD Thread = KeGetCurrentThread();
+
+   KeAcquireDispatcherDatabaseLock(FALSE);
+
+   //assiciate new thread with queue?
+   if (Thread->Queue != Queue)
+   {
+      //remove association from other queue
+      if (!IsListEmpty(&Thread->QueueListEntry))
+      {
+         RemoveEntryList(&Thread->QueueListEntry);
+      }
+
+      //associate with this queue
+      InsertHeadList(&Queue->ThreadListHead, &Thread->QueueListEntry);
+      Queue->RunningThreads++;
+      Thread->Queue = Queue;
+   }
+   
+   if (Queue->RunningThreads <= Queue->MaximumThreads && !IsListEmpty(&Queue->EntryListHead))
+   {
+      ListEntry = RemoveHeadList(&Queue->EntryListHead);
+      Queue->Header.SignalState--;
+      KeReleaseDispatcherDatabaseLock(FALSE);
+      return ListEntry;
+   }
+
+   //need to wait for it...
+   KeReleaseDispatcherDatabaseLock(FALSE);
+
+   Status = KeWaitForSingleObject(Queue,
+                                  WrQueue,
+                                  WaitMode,
+                                  TRUE,//Alertable,
+                                  Timeout);
+
+   if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
+   {
+      return (PVOID)Status;
+   }
+   else
+   {
+      KeAcquireDispatcherDatabaseLock(FALSE);
+      ListEntry = RemoveHeadList(&Queue->EntryListHead);
+      KeReleaseDispatcherDatabaseLock(FALSE);
+      return ListEntry;
+   }
+
 }
 
 
 PLIST_ENTRY STDCALL
 KeRundownQueue(IN PKQUEUE Queue)
 {
 }
 
 
 PLIST_ENTRY STDCALL
 KeRundownQueue(IN PKQUEUE Queue)
 {
-  UNIMPLEMENTED;
-  return NULL;
+   PLIST_ENTRY EnumEntry;
+   PKTHREAD Thread;
+
+   DPRINT("KeRundownQueue(Queue %x)\n", Queue);
+
+   //FIXME: should we wake thread waiting on a queue? 
+
+   KeAcquireDispatcherDatabaseLock(FALSE);
+
+   // Clear Queue and QueueListEntry members of all threads associated with this queue
+   while (!IsListEmpty(&Queue->ThreadListHead))
+   {
+      EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
+      InitializeListHead(EnumEntry);
+      Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
+      Thread->Queue = NULL;
+   }
+
+   if (!IsListEmpty(&Queue->EntryListHead))
+      EnumEntry = Queue->EntryListHead.Flink;
+   else
+      EnumEntry = NULL;
+
+   KeReleaseDispatcherDatabaseLock(FALSE);
+
+   return EnumEntry;
 }
 
 /* EOF */
 }
 
 /* EOF */