[NPFS]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 1 Feb 2014 20:41:16 +0000 (20:41 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 1 Feb 2014 20:41:16 +0000 (20:41 +0000)
- Implement NpQueryClientProcess and NpSetClientProcess
- Add a fast I/O dispatch table and implement NpFastRead and NpFastWrite
The NPFS driver is now good enough to boot Windows 2003 to desktop!

svn path=/trunk/; revision=61906

reactos/drivers/filesystems/npfs/fsctrl.c
reactos/drivers/filesystems/npfs/main.c
reactos/drivers/filesystems/npfs/npfs.h
reactos/drivers/filesystems/npfs/read.c
reactos/drivers/filesystems/npfs/write.c

index 10288a7..dc3526d 100644 (file)
@@ -53,10 +53,86 @@ NpInternalWrite(IN PDEVICE_OBJECT DeviceObject,
 NTSTATUS
 NTAPI
 NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject,
-                     IN PIRP Irp)
+                   IN PIRP Irp)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PIO_STACK_LOCATION IoStackLocation;
+    NODE_TYPE_CODE NodeTypeCode;
+    PNP_CCB Ccb;
+    PNP_CLIENT_PROCESS ClientSession, QueryBuffer;
+    ULONG Length;
+    PAGED_CODE();
+
+    /* Get the current stack location */
+    IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    /* Decode the file object and check the node type */
+    NodeTypeCode = NpDecodeFileObject(IoStackLocation->FileObject, 0, &Ccb, 0);
+    if (NodeTypeCode != NPFS_NTC_CCB)
+    {
+        return STATUS_PIPE_DISCONNECTED;
+    }
+
+    /* Get the length of the query buffer */
+    Length = IoStackLocation->Parameters.QueryFile.Length;
+    if (Length < 8)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    QueryBuffer = Irp->AssociatedIrp.SystemBuffer;
+
+    /* Lock the Ccb */
+    ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
+
+    /* Get the CCBs client session and check if it's set */
+    ClientSession = Ccb->ClientSession;
+    if (ClientSession != NULL)
+    {
+        /* Copy first 2 fields */
+        QueryBuffer->Unknown = ClientSession->Unknown;
+        QueryBuffer->Process = ClientSession->Process;
+    }
+    else
+    {
+        /* Copy the process from the CCB */
+        QueryBuffer->Unknown = NULL;
+        QueryBuffer->Process = Ccb->Process;
+    }
+
+    /* Does the caller provide a large enough buffer for the full data? */
+    if (Length >= sizeof(NP_CLIENT_PROCESS))
+    {
+        Irp->IoStatus.Information = sizeof(NP_CLIENT_PROCESS);
+
+        /* Do we have a ClientSession structure? */
+        if (ClientSession != NULL)
+        {
+            /* Copy length and the data */
+            QueryBuffer->DataLength = ClientSession->DataLength;
+            RtlCopyMemory(QueryBuffer->Buffer,
+                          ClientSession->Buffer,
+                          ClientSession->DataLength);
+
+            /* NULL terminate the buffer */
+            NT_ASSERT(QueryBuffer->DataLength <= 30);
+            QueryBuffer->Buffer[QueryBuffer->DataLength / sizeof(WCHAR)] = 0;
+        }
+        else
+        {
+            /* No data */
+            QueryBuffer->DataLength = 0;
+            QueryBuffer->Buffer[0] = 0;
+        }
+    }
+    else
+    {
+        Irp->IoStatus.Information = FIELD_OFFSET(NP_CLIENT_PROCESS, DataLength);
+    }
+
+    /* Unlock the Ccb */
+    ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -64,8 +140,72 @@ NTAPI
 NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject,
                    IN PIRP Irp)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PIO_STACK_LOCATION IoStackLocation;
+    NODE_TYPE_CODE NodeTypeCode;
+    PNP_CCB Ccb;
+    ULONG Length;
+    PNP_CLIENT_PROCESS InputBuffer, ClientSession, OldClientSession;
+    PAGED_CODE();
+
+    /* Get the current stack location */
+    IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    /* Only kernel calls are allowed! */
+    if (IoStackLocation->MinorFunction != IRP_MN_KERNEL_CALL)
+    {
+        return STATUS_ACCESS_DENIED;
+    }
+
+    /* Decode the file object and check the node type */
+    NodeTypeCode = NpDecodeFileObject(IoStackLocation->FileObject, 0, &Ccb, 0);
+    if (NodeTypeCode != NPFS_NTC_CCB)
+    {
+        return STATUS_PIPE_DISCONNECTED;
+    }
+
+    /* Get the length of the query buffer and check if it's valid */
+    Length = IoStackLocation->Parameters.QueryFile.Length;
+    if (Length != sizeof(NP_CLIENT_PROCESS))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Get the buffer and check if the data Length is valid */
+    InputBuffer = Irp->AssociatedIrp.SystemBuffer;
+    if (InputBuffer->DataLength > 30)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Allocate a new structure */
+    ClientSession = ExAllocatePoolWithQuotaTag(PagedPool,
+                                               sizeof(NP_CLIENT_PROCESS),
+                                               'iFpN');
+
+    /* Copy the full input buffer */
+    RtlCopyMemory(ClientSession, InputBuffer, sizeof(NP_CLIENT_PROCESS));
+
+    /* Lock the Ccb */
+    ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
+
+    /* Get the old ClientSession and set the new */
+    OldClientSession = Ccb->ClientSession;
+    Ccb->ClientSession = ClientSession;
+
+    /* Copy the process to the CCB */
+    Ccb->Process = ClientSession->Process;
+
+    /* Unlock the Ccb */
+    ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+
+    /* Check if there was already a ClientSession */
+    if (OldClientSession != NULL)
+    {
+        /* Free it */
+        ExFreePoolWithTag(OldClientSession, 'iFpN');
+    }
+
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -201,7 +341,7 @@ NpListen(IN PDEVICE_OBJECT DeviceObject,
 NTSTATUS
 NTAPI
 NpPeek(IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp, 
+       IN PIRP Irp,
        IN PLIST_ENTRY List)
 {
     PIO_STACK_LOCATION IoStack;
@@ -490,7 +630,7 @@ NpTransceive(IN PDEVICE_OBJECT DeviceObject,
     }
 
     if (!NT_SUCCESS(Status)) goto Quickie;
+
     if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
     ASSERT(ReadQueue->QueueState == Empty);
     Status = NpAddDataQueueEntry(NamedPipeEnd,
@@ -648,7 +788,7 @@ NpCommonFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
             NpAcquireSharedVcb();
             Status = NpInternalTransceive(DeviceObject, Irp, &DeferredList);
             break;
+
         case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
             Overflow = TRUE;
             // on purpose
index c30d64e..d45e00d 100644 (file)
@@ -20,6 +20,14 @@ PVOID NpAliases;
 PNPFS_ALIAS NpAliasList;
 PNPFS_ALIAS NpAliasListByLength[MAX_INDEXED_LENGTH + 1 - MIN_INDEXED_LENGTH];
 
+FAST_IO_DISPATCH NpFastIoDispatch =
+{
+    sizeof(FAST_IO_DISPATCH),
+    NULL,
+    NpFastRead,
+    NpFastWrite,
+};
+
 /* FUNCTIONS ******************************************************************/
 
 NTSTATUS
@@ -311,6 +319,7 @@ NpFsdDirectoryControl(IN PDEVICE_OBJECT DeviceObject,
     return STATUS_NOT_IMPLEMENTED;
 }
 
+
 NTSTATUS
 NTAPI
 DriverEntry(IN PDRIVER_OBJECT DriverObject,
@@ -321,7 +330,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
     NTSTATUS Status;
     UNREFERENCED_PARAMETER(RegistryPath);
 
-    DPRINT1("Next-Generation NPFS-Lite\n");
+    DPRINT1("Next-Generation NPFS-Advanced\n");
 
     Status = NpInitializeAliases();
     if (!NT_SUCCESS(Status))
@@ -347,6 +356,8 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
 
     DriverObject->DriverUnload = NULL;
 
+    DriverObject->FastIoDispatch = &NpFastIoDispatch;
+
     RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe");
     Status = IoCreateDevice(DriverObject,
                             sizeof(NP_VCB),
index c33ce43..7bc2fbf 100644 (file)
@@ -360,6 +360,18 @@ typedef struct _NPFS_QUERY_VALUE_CONTEXT
 extern PNPFS_ALIAS NpAliasList;
 extern PNPFS_ALIAS NpAliasListByLength[MAX_INDEXED_LENGTH + 1 - MIN_INDEXED_LENGTH];
 
+//
+// This structure is actually a user-mode structure and should go into a share header
+//
+typedef struct _NP_CLIENT_PROCESS
+{
+    PVOID Unknown;
+    PVOID Process;
+    USHORT DataLength;
+    WCHAR Buffer[17];
+} NP_CLIENT_PROCESS, *PNP_CLIENT_PROCESS;
+
+
 /* FUNCTIONS ******************************************************************/
 
 //
@@ -674,6 +686,34 @@ NTAPI
 NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
           IN PIRP Irp);
 
+_Function_class_(FAST_IO_READ)
+_IRQL_requires_same_
+BOOLEAN
+NTAPI
+NpFastRead(
+    _In_ PFILE_OBJECT FileObject,
+    _In_ PLARGE_INTEGER FileOffset,
+    _In_ ULONG Length,
+    _In_ BOOLEAN Wait,
+    _In_ ULONG LockKey,
+    _Out_ PVOID Buffer,
+    _Out_ PIO_STATUS_BLOCK IoStatus,
+    _In_ PDEVICE_OBJECT DeviceObject);
+
+_Function_class_(FAST_IO_WRITE)
+_IRQL_requires_same_
+BOOLEAN
+NTAPI
+NpFastWrite(
+    _In_ PFILE_OBJECT FileObject,
+    _In_ PLARGE_INTEGER FileOffset,
+    _In_ ULONG Length,
+    _In_ BOOLEAN Wait,
+    _In_ ULONG LockKey,
+    _In_ PVOID Buffer,
+    _Out_ PIO_STATUS_BLOCK IoStatus,
+    _In_ PDEVICE_OBJECT DeviceObject);
+
 
 NTSTATUS
 NTAPI
index 4189868..60e48d3 100644 (file)
@@ -16,6 +16,8 @@
 /* GLOBALS ********************************************************************/
 
 LONG NpSlowReadCalls;
+ULONG NpFastReadTrue;
+ULONG NpFastReadFalse;
 
 /* FUNCTIONS ******************************************************************/
 
@@ -23,8 +25,8 @@ BOOLEAN
 NTAPI
 NpCommonRead(IN PFILE_OBJECT FileObject,
              IN PVOID Buffer,
-             IN ULONG BufferSize, 
-             OUT PIO_STATUS_BLOCK IoStatus, 
+             IN ULONG BufferSize,
+             OUT PIO_STATUS_BLOCK IoStatus,
              IN PIRP Irp,
              IN PLIST_ENTRY List)
 {
@@ -190,4 +192,46 @@ NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
     return IoStatus.Status;
 }
 
+
+_Function_class_(FAST_IO_READ)
+_IRQL_requires_same_
+BOOLEAN
+NTAPI
+NpFastRead(
+    _In_ PFILE_OBJECT FileObject,
+    _In_ PLARGE_INTEGER FileOffset,
+    _In_ ULONG Length,
+    _In_ BOOLEAN Wait,
+    _In_ ULONG LockKey,
+    _Out_ PVOID Buffer,
+    _Out_ PIO_STATUS_BLOCK IoStatus,
+    _In_ PDEVICE_OBJECT DeviceObject)
+{
+    LIST_ENTRY DeferredList;
+    BOOLEAN Result;
+    PAGED_CODE();
+
+    InitializeListHead(&DeferredList);
+
+    FsRtlEnterFileSystem();
+    NpAcquireSharedVcb();
+
+    Result = NpCommonRead(FileObject,
+                          Buffer,
+                          Length,
+                          IoStatus,
+                          NULL,
+                          &DeferredList);
+    if (Result)
+        ++NpFastReadTrue;
+    else
+        ++NpFastReadFalse;
+
+    NpReleaseVcb();
+    NpCompleteDeferredIrps(&DeferredList);
+    FsRtlExitFileSystem();
+
+    return Result;
+}
+
 /* EOF */
index f8aa150..7297a5b 100644 (file)
@@ -16,6 +16,8 @@
 /* GLOBALS ********************************************************************/
 
 LONG NpSlowWriteCalls;
+ULONG NpFastWriteTrue;
+ULONG NpFastWriteFalse;
 
 /* FUNCTIONS ******************************************************************/
 
@@ -23,10 +25,10 @@ BOOLEAN
 NTAPI
 NpCommonWrite(IN PFILE_OBJECT FileObject,
               IN PVOID Buffer,
-              IN ULONG DataSize, 
-              IN PETHREAD Thread, 
-              IN PIO_STATUS_BLOCK IoStatus, 
-              IN PIRP Irp, 
+              IN ULONG DataSize,
+              IN PETHREAD Thread,
+              IN PIO_STATUS_BLOCK IoStatus,
+              IN PIRP Irp,
               IN PLIST_ENTRY List)
 {
     NODE_TYPE_CODE NodeType;
@@ -207,4 +209,47 @@ NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
     return IoStatus.Status;
 }
 
+
+_Function_class_(FAST_IO_WRITE)
+_IRQL_requires_same_
+BOOLEAN
+NTAPI
+NpFastWrite(
+    _In_ PFILE_OBJECT FileObject,
+    _In_ PLARGE_INTEGER FileOffset,
+    _In_ ULONG Length,
+    _In_ BOOLEAN Wait,
+    _In_ ULONG LockKey,
+    _In_ PVOID Buffer,
+    _Out_ PIO_STATUS_BLOCK IoStatus,
+    _In_ PDEVICE_OBJECT DeviceObject)
+{
+    LIST_ENTRY DeferredList;
+    BOOLEAN Result;
+    PAGED_CODE();
+
+    InitializeListHead(&DeferredList);
+
+    FsRtlEnterFileSystem();
+    NpAcquireSharedVcb();
+
+    Result = NpCommonWrite(FileObject,
+                           Buffer,
+                           Length,
+                           PsGetCurrentThread(),
+                           IoStatus,
+                           NULL,
+                           &DeferredList);
+    if (Result)
+        ++NpFastWriteTrue;
+    else
+        ++NpFastWriteFalse;
+
+    NpReleaseVcb();
+    NpCompleteDeferredIrps(&DeferredList);
+    FsRtlExitFileSystem();
+
+    return Result;
+}
+
 /* EOF */