[NPFS]
authorEric Kohl <eric.kohl@reactos.org>
Sat, 1 Jan 2011 12:40:24 +0000 (12:40 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sat, 1 Jan 2011 12:40:24 +0000 (12:40 +0000)
- Add NpfsDirectoryControl routine in order to enumerate pipes.
- Use NpfsGetFcb and NpfsGetCcb to retrieve the FCB or CCB and use SEH to protect these routines.

svn path=/trunk/; revision=50250

reactos/drivers/filesystems/npfs/create.c
reactos/drivers/filesystems/npfs/dirctl.c [new file with mode: 0644]
reactos/drivers/filesystems/npfs/npfs.c
reactos/drivers/filesystems/npfs/npfs.h
reactos/drivers/filesystems/npfs/npfs.rbuild

index 8dac8e9..fe6834a 100644 (file)
@@ -121,6 +121,8 @@ NpfsOpenFileSystem(PNPFS_FCB Fcb,
         return;
     }
 
+    RtlZeroMemory(Ccb, sizeof(NPFS_CCB));
+
     Ccb->Type = CCB_DEVICE;
     Ccb->Fcb = Fcb;
 
@@ -150,6 +152,8 @@ NpfsOpenRootDirectory(PNPFS_FCB Fcb,
         return;
     }
 
+    RtlZeroMemory(Ccb, sizeof(NPFS_CCB));
+
     Ccb->Type = CCB_DIRECTORY;
     Ccb->Fcb = Fcb;
 
@@ -881,6 +885,9 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
     {
         DPRINT("Closing the root directory!\n");
 
+        if (Ccb->u.Directory.SearchPattern.Buffer != NULL)
+            ExFreePool(Ccb->u.Directory.SearchPattern.Buffer);
+
         ExFreePool(Ccb);
         FileObject->FsContext = NULL;
         FileObject->FsContext2 = NULL;
diff --git a/reactos/drivers/filesystems/npfs/dirctl.c b/reactos/drivers/filesystems/npfs/dirctl.c
new file mode 100644 (file)
index 0000000..24370e1
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * COPYRIGHT:  See COPYING in the top level directory
+ * PROJECT:    ReactOS kernel
+ * FILE:       drivers/filesastems/npfs/dirctl.c
+ * PURPOSE:    Named pipe filesystem
+ * PROGRAMMER: Eric Kohl
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "npfs.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS *****************************************************************/
+
+static NTSTATUS
+NpfsQueryDirectory(PNPFS_CCB Ccb,
+                   PIRP Irp,
+                   PULONG Size)
+{
+    PIO_STACK_LOCATION Stack;
+    LONG BufferLength = 0;
+    PUNICODE_STRING SearchPattern = NULL;
+    FILE_INFORMATION_CLASS FileInformationClass;
+    ULONG FileIndex = 0;
+    PUCHAR Buffer = NULL;
+    BOOLEAN First = FALSE;
+    PLIST_ENTRY CurrentEntry;
+    PNPFS_VCB Vcb;
+    PNPFS_FCB PipeFcb;
+    ULONG PipeIndex;
+    BOOLEAN Found = FALSE;
+    NTSTATUS Status = STATUS_SUCCESS;
+    PFILE_NAMES_INFORMATION NamesBuffer;
+    PFILE_DIRECTORY_INFORMATION DirectoryBuffer;
+
+    Stack = IoGetCurrentIrpStackLocation(Irp);
+
+    /* Obtain the callers parameters */
+    BufferLength = Stack->Parameters.QueryDirectory.Length;
+    SearchPattern = Stack->Parameters.QueryDirectory.FileName;
+    FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass;
+    FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
+
+    DPRINT("SearchPattern: %p  '%wZ'\n", SearchPattern, SearchPattern);
+
+    /* Determine Buffer for result */
+    if (Irp->MdlAddress)
+    {
+        Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+    }
+    else
+    {
+        Buffer = Irp->UserBuffer;
+    }
+
+    /* Build the search pattern string */
+    DPRINT("Ccb->u.Directory.SearchPattern.Buffer: %p\n", Ccb->u.Directory.SearchPattern.Buffer);
+    if (Ccb->u.Directory.SearchPattern.Buffer == NULL)
+    {
+        First = TRUE;
+
+        if (SearchPattern != NULL)
+        {
+            Ccb->u.Directory.SearchPattern.Buffer =
+                ExAllocatePool(NonPagedPool, SearchPattern->Length + sizeof(WCHAR));
+            if (Ccb->u.Directory.SearchPattern.Buffer == NULL)
+            {
+                return STATUS_INSUFFICIENT_RESOURCES;
+            }
+
+            Ccb->u.Directory.SearchPattern.Length = SearchPattern->Length;
+            Ccb->u.Directory.SearchPattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR);
+            RtlCopyMemory(Ccb->u.Directory.SearchPattern.Buffer,
+                          SearchPattern->Buffer,
+                          SearchPattern->Length);
+            Ccb->u.Directory.SearchPattern.Buffer[SearchPattern->Length / sizeof(WCHAR)] = 0;
+        }
+        else
+        {
+            Ccb->u.Directory.SearchPattern.Buffer =
+                ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
+            if (Ccb->u.Directory.SearchPattern.Buffer == NULL)
+            {
+                return STATUS_INSUFFICIENT_RESOURCES;
+            }
+
+            Ccb->u.Directory.SearchPattern.Length = sizeof(WCHAR);
+            Ccb->u.Directory.SearchPattern.MaximumLength = 2 * sizeof(WCHAR);
+            Ccb->u.Directory.SearchPattern.Buffer[0] = L'*';
+            Ccb->u.Directory.SearchPattern.Buffer[1] = 0;
+        }
+    }
+    DPRINT("Search pattern: '%wZ'\n", &Ccb->u.Directory.SearchPattern);
+
+    /* Determine the file index */
+    if (First || (Stack->Flags & SL_RESTART_SCAN))
+    {
+        FileIndex = 0;
+    } else if ((Stack->Flags & SL_INDEX_SPECIFIED) == 0)
+    {
+        FileIndex = Ccb->u.Directory.FileIndex + 1;
+    }
+    DPRINT("FileIndex: %lu\n", FileIndex);
+
+    DPRINT("Buffer = %p  tofind = %wZ\n", Buffer, &Ccb->u.Directory.SearchPattern);
+
+    PipeIndex = 0;
+
+    Vcb = Ccb->Fcb->Vcb;
+    CurrentEntry = Vcb->PipeListHead.Flink;
+    while (CurrentEntry != &Vcb->PipeListHead && Found == FALSE)
+    {
+        /* Get the FCB of the next pipe */
+        PipeFcb = CONTAINING_RECORD(CurrentEntry,
+                                    NPFS_FCB,
+                                    PipeListEntry);
+
+        /* Make sure it is a pipe FCB */
+        ASSERT(PipeFcb->Type == FCB_PIPE);
+
+        DPRINT("PipeName: %wZ\n", &PipeFcb->PipeName);
+
+        if (FsRtlIsNameInExpression(&Ccb->u.Directory.SearchPattern,
+                                    &PipeFcb->PipeName,
+                                    TRUE,
+                                    NULL))
+        {
+            DPRINT("Found pipe: %wZ\n", &PipeFcb->PipeName);
+
+            if (PipeIndex >= FileIndex)
+            {
+                switch (FileInformationClass)
+                {
+                    case FileDirectoryInformation:
+                        DirectoryBuffer = (PFILE_DIRECTORY_INFORMATION)Buffer;
+                        DirectoryBuffer->NextEntryOffset = 0;
+                        DirectoryBuffer->FileIndex = PipeIndex;
+                        DirectoryBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+                        DirectoryBuffer->EndOfFile.QuadPart = PipeFcb->CurrentInstances;
+                        DirectoryBuffer->AllocationSize.LowPart = PipeFcb->MaximumInstances;
+                        DirectoryBuffer->FileNameLength = PipeFcb->PipeName.Length;
+                        RtlCopyMemory(DirectoryBuffer->FileName,
+                                      PipeFcb->PipeName.Buffer,
+                                      PipeFcb->PipeName.Length);
+                        *Size = sizeof(FILE_DIRECTORY_INFORMATION) + PipeFcb->PipeName.Length - 1;
+                        Status = STATUS_SUCCESS;
+                        break;
+
+                    case FileNamesInformation:
+                        NamesBuffer = (PFILE_NAMES_INFORMATION)Buffer;
+                        NamesBuffer->NextEntryOffset = 0;
+                        NamesBuffer->FileIndex = PipeIndex;
+                        NamesBuffer->FileNameLength = PipeFcb->PipeName.Length;
+                        RtlCopyMemory(NamesBuffer->FileName,
+                                      PipeFcb->PipeName.Buffer,
+                                      PipeFcb->PipeName.Length);
+                        *Size = sizeof(FILE_NAMES_INFORMATION) + PipeFcb->PipeName.Length - 1;
+                        Status = STATUS_SUCCESS;
+                        break;
+
+                    default:
+                        DPRINT1("Invalid information class: %lu\n", FileInformationClass);
+                        Status = STATUS_INVALID_INFO_CLASS;
+                        break;
+                }
+
+                Ccb->u.Directory.FileIndex = PipeIndex;
+                Found = TRUE;
+
+//                if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
+//                    return STATUS_SUCCESS;
+
+                break;
+            }
+
+            PipeIndex++;
+        }
+
+        CurrentEntry = CurrentEntry->Flink;
+    }
+
+    if (Found == FALSE)
+        Status = STATUS_NO_MORE_FILES;
+
+    return Status;
+}
+
+
+NTSTATUS NTAPI
+NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject,
+                     PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    PFILE_OBJECT FileObject;
+    PNPFS_CCB Ccb;
+    PNPFS_FCB Fcb;
+    NTSTATUS Status;
+    ULONG Size = 0;
+
+    DPRINT("NpfsDirectoryControl() called\n");
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    FileObject = IoStack->FileObject;
+
+    if (NpfsGetCcb(FileObject, &Ccb) != CCB_DIRECTORY)
+    {
+        Status = STATUS_INVALID_PARAMETER;
+
+        Irp->IoStatus.Status = Status;
+        Irp->IoStatus.Information = 0;
+
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        return Status;
+    }
+
+    Fcb = Ccb->Fcb;
+
+    switch (IoStack->MinorFunction)
+    {
+        case IRP_MN_QUERY_DIRECTORY:
+            Status = NpfsQueryDirectory(Ccb,
+                                        Irp,
+                                        &Size);
+            break;
+
+        case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
+            DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+
+        default:
+            DPRINT1("NPFS: MinorFunction %d\n", IoStack->MinorFunction);
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+    }
+
+    Irp->IoStatus.Status = Status;
+    Irp->IoStatus.Information = Size;
+
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+/* EOF */
index 74fe99b..dfe4ed9 100644 (file)
@@ -44,8 +44,8 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
         NpfsQueryVolumeInformation;
     DriverObject->MajorFunction[IRP_MJ_CLEANUP] = NpfsCleanup;
     DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = NpfsFlushBuffers;
-    //   DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
-    //     NpfsDirectoryControl;
+    DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
+        NpfsDirectoryControl;
     DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
         NpfsFileSystemControl;
     //   DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] =
@@ -100,4 +100,54 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
     return STATUS_SUCCESS;
 }
 
+
+FCB_TYPE
+NpfsGetFcb(PFILE_OBJECT FileObject,
+           PNPFS_FCB *Fcb)
+{
+    PNPFS_FCB LocalFcb = NULL;
+    FCB_TYPE FcbType = FCB_INVALID;
+
+    _SEH2_TRY
+    {
+        LocalFcb = (PNPFS_FCB)FileObject->FsContext;
+        FcbType = LocalFcb->Type;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        LocalFcb = NULL;
+        FcbType = FCB_INVALID;
+    }
+    _SEH2_END;
+
+    *Fcb = LocalFcb;
+
+    return FcbType;
+}
+
+
+CCB_TYPE
+NpfsGetCcb(PFILE_OBJECT FileObject,
+           PNPFS_CCB *Ccb)
+{
+    PNPFS_CCB LocalCcb = NULL;
+    CCB_TYPE CcbType = CCB_INVALID;
+
+    _SEH2_TRY
+    {
+        LocalCcb = (PNPFS_CCB)FileObject->FsContext2;
+        CcbType = LocalCcb->Type;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        LocalCcb = NULL;
+        CcbType = CCB_INVALID;
+    }
+    _SEH2_END;
+
+    *Ccb = LocalCcb;
+
+    return CcbType;
+}
+
 /* EOF */
index 2e47e68..0049fd3 100644 (file)
@@ -3,9 +3,11 @@
 
 #include <ntifs.h>
 #include <ndk/iotypes.h>
+#include <pseh/pseh2.h>
 
 typedef enum _FCB_TYPE
 {
+    FCB_INVALID,
     FCB_DEVICE,
     FCB_DIRECTORY,
     FCB_PIPE
@@ -13,6 +15,7 @@ typedef enum _FCB_TYPE
 
 typedef enum _CCB_TYPE
 {
+    CCB_INVALID,
     CCB_DEVICE,
     CCB_DIRECTORY,
     CCB_PIPE
@@ -55,6 +58,14 @@ typedef struct _NPFS_FCB
     LARGE_INTEGER TimeOut;
 } NPFS_FCB, *PNPFS_FCB;
 
+
+typedef struct _NPFS_CCB_DIRECTORY_DATA
+{
+    UNICODE_STRING SearchPattern;
+    ULONG FileIndex;
+} NPFS_CCB_DIRECTORY_DATA, *PNPFS_CCB_DIRECTORY_DATA;
+
+
 typedef struct _NPFS_CCB
 {
     LIST_ENTRY CcbListEntry;
@@ -79,6 +90,12 @@ typedef struct _NPFS_CCB
     ULONG MaxDataLength;
 
     FAST_MUTEX DataListLock;    /* Data queue lock */
+
+    union
+    {
+        NPFS_CCB_DIRECTORY_DATA Directory;
+    } u;
+
 } NPFS_CCB, *PNPFS_CCB;
 
 typedef struct _NPFS_CONTEXT
@@ -130,6 +147,9 @@ NTSTATUS NTAPI NpfsCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 DRIVER_DISPATCH NpfsClose;
 NTSTATUS NTAPI NpfsClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 
+DRIVER_DISPATCH NpfsDirectoryControl;
+NTSTATUS NTAPI NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+
 DRIVER_DISPATCH NpfsRead;
 NTSTATUS NTAPI NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 
@@ -159,5 +179,12 @@ PNPFS_FCB
 NpfsFindPipe(PNPFS_VCB Vcb,
              PUNICODE_STRING PipeName);
 
+FCB_TYPE
+NpfsGetFcb(PFILE_OBJECT FileObject,
+           PNPFS_FCB *Fcb);
+
+CCB_TYPE
+NpfsGetCcb(PFILE_OBJECT FileObject,
+           PNPFS_CCB *Ccb);
 
 #endif /* __DRIVERS_FS_NP_NPFS_H */
index a9030bf..945dd4c 100644 (file)
@@ -4,7 +4,9 @@
        <include base="npfs">.</include>
        <library>ntoskrnl</library>
        <library>hal</library>
+       <library>pseh</library>
        <file>create.c</file>
+       <file>dirctl.c</file>
        <file>finfo.c</file>
        <file>fsctrl.c</file>
        <file>npfs.c</file>