[NPFS]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 1 Feb 2014 14:28:15 +0000 (14:28 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 1 Feb 2014 14:28:15 +0000 (14:28 +0000)
- Implement NpInitializeAliases + NpTranslateAlias
- Add a number of debug traces, disabled by default

svn path=/trunk/; revision=61900

reactos/drivers/filesystems/npfs/create.c
reactos/drivers/filesystems/npfs/main.c
reactos/drivers/filesystems/npfs/npfs.h
reactos/drivers/filesystems/npfs/strucsup.c
reactos/drivers/filesystems/npfs/volinfo.c

index f498a69..d1b6479 100644 (file)
@@ -59,12 +59,14 @@ NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject,
 {
     IO_STATUS_BLOCK Status;
     PAGED_CODE();
+    TRACE("Entered\n");
 
     NpSetFileObject(FileObject, NpVcb, NULL, FALSE);
     ++NpVcb->ReferenceCount;
 
     Status.Information = FILE_OPENED;
     Status.Status = STATUS_SUCCESS;
+    TRACE("Leaving, Status.Status = %lx\n", Status.Status);
     return Status;
 }
 
@@ -78,6 +80,7 @@ NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb,
     IO_STATUS_BLOCK IoStatus;
     PNP_ROOT_DCB_FCB Ccb;
     PAGED_CODE();
+    TRACE("Entered\n");
 
     IoStatus.Status = NpCreateRootDcbCcb(&Ccb);
     if (NT_SUCCESS(IoStatus.Status))
@@ -93,6 +96,7 @@ NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb,
         IoStatus.Information = 0;
     }
 
+    TRACE("Leaving, IoStatus = %lx\n", IoStatus);
     return IoStatus;
 }
 
@@ -116,6 +120,7 @@ NpCreateClientEnd(IN PNP_FCB Fcb,
     USHORT NamedPipeConfiguration;
     PLIST_ENTRY NextEntry, ListHead;
     PNP_CCB Ccb = NULL;
+    TRACE("Entered\n");
 
     IoStatus.Status = STATUS_SUCCESS;
     IoStatus.Information = 0;
@@ -167,6 +172,7 @@ NpCreateClientEnd(IN PNP_FCB Fcb,
         ((GrantedAccess & FILE_WRITE_DATA) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)))
     {
         IoStatus.Status = STATUS_ACCESS_DENIED;
+        TRACE("Leaving, IoStatus = %lx\n", IoStatus);
         return IoStatus;
     }
 
@@ -185,6 +191,7 @@ NpCreateClientEnd(IN PNP_FCB Fcb,
     if (NextEntry == ListHead)
     {
         IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE;
+        TRACE("Leaving, IoStatus = %lx\n", IoStatus);
         return IoStatus;
     }
 
@@ -195,6 +202,7 @@ NpCreateClientEnd(IN PNP_FCB Fcb,
     if (!NT_SUCCESS(IoStatus.Status))
     {
         NpUninitializeSecurity(Ccb);
+        TRACE("Leaving, IoStatus = %lx\n", IoStatus);
         return IoStatus;
     }
 
@@ -203,9 +211,151 @@ NpCreateClientEnd(IN PNP_FCB Fcb,
 
     IoStatus.Information = FILE_OPENED;
     IoStatus.Status = STATUS_SUCCESS;
+    TRACE("Leaving, IoStatus = %lx\n", IoStatus);
     return IoStatus;
 }
 
+NTSTATUS
+NTAPI
+NpTranslateAlias(
+    PUNICODE_STRING PipeName)
+{
+    WCHAR UpcaseBuffer[MAX_INDEXED_LENGTH + 1];
+    UNICODE_STRING UpcaseString;
+    ULONG Length;
+    PNPFS_ALIAS CurrentAlias;
+    NTSTATUS Status;
+    BOOLEAN BufferAllocated, BackSlash;
+    LONG Result;
+    PAGED_CODE();
+
+    /* Get the pipe name length and check for empty string */
+    Length = PipeName->Length;
+    if (Length == 0)
+    {
+        return STATUS_SUCCESS;
+    }
+
+    /* Check if the name starts with a path separator */
+    BackSlash = (PipeName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR);
+    if (BackSlash)
+    {
+        /* We are only interested in the part after the backslash */
+        Length -= sizeof(WCHAR);
+    }
+
+    /* Check if the length is within our indexed list bounds */
+    if ((Length >= MIN_INDEXED_LENGTH * sizeof(WCHAR)) &&
+        (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR)))
+    {
+        /* Length is within bounds, use the list by length */
+        CurrentAlias = NpAliasListByLength[(Length / sizeof(WCHAR)) - MIN_INDEXED_LENGTH];
+    }
+    else
+    {
+        /* We use the generic list, search for an entry of the right size */
+        CurrentAlias = NpAliasList;
+        while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length != Length))
+        {
+            /* Check if we went past the desired length */
+            if (CurrentAlias->Name.Length > Length)
+            {
+                /* In this case there is no matching alias, return success */
+                return STATUS_SUCCESS;
+            }
+
+            /* Go to the next alias in the list */
+            CurrentAlias = CurrentAlias->Next;
+        }
+    }
+
+    /* Did we find any alias? */
+    if (CurrentAlias == NULL)
+    {
+        /* Nothing found, no matching alias */
+        return STATUS_SUCCESS;
+    }
+
+    /* Check whether we can use our stack buffer */
+    if (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR))
+    {
+        /* Initialize the upcased string */
+        UpcaseString.Buffer = UpcaseBuffer;
+        UpcaseString.MaximumLength = sizeof(UpcaseBuffer);
+
+        /* Upcase the pipe name */
+        Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, FALSE);
+        NT_ASSERT(NT_SUCCESS(Status));
+        BufferAllocated = FALSE;
+    }
+    else
+    {
+        /* Upcase the pipe name, allocate the string buffer */
+        Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, TRUE);
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+
+        BufferAllocated = TRUE;
+    }
+
+    /* Did the original name start with a backslash? */
+    if (BackSlash)
+    {
+        /* Skip it for the comparison */
+        UpcaseString.Buffer++;
+        UpcaseString.Length -= sizeof(WCHAR);
+    }
+
+    /* Make sure the length matches the "raw" length */
+    NT_ASSERT(UpcaseString.Length == Length);
+    NT_ASSERT(CurrentAlias->Name.Length == Length);
+
+    /* Loop while we have aliases */
+    do
+    {
+        /* Compare the names and check if they match */
+        Result = NpCompareAliasNames(&UpcaseString, &CurrentAlias->Name);
+        if (Result == 0)
+        {
+            /* The names match, use the target name */
+            *PipeName = *CurrentAlias->TargetName;
+
+            /* Did the original name start with a backslash? */
+            if (!BackSlash)
+            {
+                /* It didn't, so skip it in the target name as well */
+                PipeName->Buffer++;
+                PipeName->Length -= sizeof(WCHAR);
+            }
+            break;
+        }
+
+        /* Check if we went past all string candidates */
+        if (Result < 0)
+        {
+            /* Nothing found, we're done */
+            break;
+        }
+
+        /* Go to the next alias */
+        CurrentAlias = CurrentAlias->Next;
+
+        /* Keep looping while we have aliases of the right length */
+    } while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length == Length));
+
+    /* Did we allocate a buffer? */
+    if (BufferAllocated)
+    {
+        /* Free the allocated buffer */
+        ASSERT(UpcaseString.Buffer != UpcaseBuffer);
+        RtlFreeUnicodeString(&UpcaseString);
+    }
+
+    return STATUS_SUCCESS;
+}
+
 NTSTATUS
 NTAPI
 NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
@@ -223,6 +373,8 @@ NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
     ACCESS_MASK DesiredAccess;
     LIST_ENTRY DeferredList;
     UNICODE_STRING Prefix;
+    NTSTATUS Status;
+    TRACE("Entered\n");
 
     InitializeListHead(&DeferredList);
     IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
@@ -276,8 +428,9 @@ NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
         goto Quickie;
     }
 
-    // Status = NpTranslateAlias(&FileName);; // ignore this for now
-    // if (!NT_SUCCESS(Status)) goto Quickie;
+    Status = NpTranslateAlias(&FileName);
+    if (!NT_SUCCESS(Status)) goto Quickie;
+
     if (RelatedFileObject)
     {
         if (Type == NPFS_NTC_ROOT_DCB)
@@ -355,6 +508,7 @@ Quickie:
 
     Irp->IoStatus = IoStatus;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
     return IoStatus.Status;
 }
 
@@ -380,6 +534,7 @@ NpCreateExistingNamedPipe(IN PNP_FCB Fcb,
     USHORT NamedPipeConfiguration, CheckShareAccess;
     BOOLEAN AccessGranted;
     PAGED_CODE();
+    TRACE("Entered\n");
 
     Privileges = NULL;
 
@@ -424,17 +579,23 @@ NpCreateExistingNamedPipe(IN PNP_FCB Fcb,
                            &AccessState->GenerateOnClose);
 
     SeUnlockSubjectContext(SubjectSecurityContext);
-    if (!AccessGranted) return IoStatus;
+    if (!AccessGranted)
+    {
+        TRACE("Leaving, IoStatus = %lx\n", IoStatus);
+        return IoStatus;
+    }
 
     if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
     {
         IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
+        TRACE("Leaving, IoStatus = %lx\n", IoStatus);
         return IoStatus;
     }
 
     if (Disposition == FILE_CREATE)
     {
         IoStatus.Status = STATUS_ACCESS_DENIED;
+        TRACE("Leaving, IoStatus = %lx\n", IoStatus);
         return IoStatus;
     }
 
@@ -455,6 +616,7 @@ NpCreateExistingNamedPipe(IN PNP_FCB Fcb,
     if (CheckShareAccess != ShareAccess)
     {
         IoStatus.Status = STATUS_ACCESS_DENIED;
+        TRACE("Leaving, IoStatus = %lx\n", IoStatus);
         return IoStatus;
     }
 
@@ -476,6 +638,7 @@ NpCreateExistingNamedPipe(IN PNP_FCB Fcb,
     {
         --Ccb->Fcb->CurrentInstances;
         NpDeleteCcb(Ccb, List);
+        TRACE("Leaving, IoStatus = %lx\n", IoStatus);
         return IoStatus;
     }
 
@@ -485,6 +648,7 @@ NpCreateExistingNamedPipe(IN PNP_FCB Fcb,
 
     IoStatus.Status = STATUS_SUCCESS;
     IoStatus.Information = 1;
+    TRACE("Leaving, IoStatus = %lx\n", IoStatus);
     return IoStatus;
 }
 
@@ -509,6 +673,7 @@ NpCreateNewNamedPipe(IN PNP_DCB Dcb,
     PNP_CCB Ccb;
     PNP_FCB Fcb;
     PAGED_CODE();
+    TRACE("Entered\n");
 
     if (!(Parameters->TimeoutSpecified) ||
         !(Parameters->MaximumInstances) ||
@@ -611,9 +776,11 @@ NpCreateNewNamedPipe(IN PNP_DCB Dcb,
     IoStatus->Status = STATUS_SUCCESS;
     IoStatus->Information = FILE_CREATED;
 
+    TRACE("Leaving, STATUS_SUCCESS\n");
     return STATUS_SUCCESS;
 
 Quickie:
+    TRACE("Leaving, Status = %lx\n", Status);
     IoStatus->Information = 0;
     IoStatus->Status = Status;
     return Status;
@@ -635,6 +802,7 @@ NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
     UNICODE_STRING Prefix;
     PNAMED_PIPE_CREATE_PARAMETERS Parameters;
     IO_STATUS_BLOCK IoStatus;
+    TRACE("Entered\n");
 
     InitializeListHead(&DeferredList);
     Process = IoGetRequestorProcess(Irp);
@@ -741,6 +909,7 @@ Quickie:
     NpCompleteDeferredIrps(&DeferredList);
     FsRtlExitFileSystem();
 
+    TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
     Irp->IoStatus = IoStatus;
     IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
     return IoStatus.Status;
index 449cfc4..c30d64e 100644 (file)
 /* GLOBALS ********************************************************************/
 
 PDEVICE_OBJECT NpfsDeviceObject;
+PVOID NpAliases;
+PNPFS_ALIAS NpAliasList;
+PNPFS_ALIAS NpAliasListByLength[MAX_INDEXED_LENGTH + 1 - MIN_INDEXED_LENGTH];
 
 /* FUNCTIONS ******************************************************************/
 
+NTSTATUS
+NTAPI
+NpReadAlias(
+    PWSTR ValueName,
+    ULONG ValueType,
+    PVOID ValueData,
+    ULONG ValueLength,
+    PVOID Context,
+    PVOID EntryContext)
+{
+    PNPFS_QUERY_VALUE_CONTEXT QueryContext = Context;
+    PWSTR CurrentString;
+    USHORT Length;
+    PNPFS_ALIAS CurrentAlias;
+    UNICODE_STRING TempString;
+    PUNICODE_STRING CurrentTargetName;
+
+    /* Check if we have the expected type */
+    if (ValueType != REG_MULTI_SZ)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Check if only the size is requested */
+    if (QueryContext->SizeOnly)
+    {
+        /* Count this entry */
+        QueryContext->NumberOfEntries++;
+
+        /* Get the length of the value name (i.e. the target name). */
+        Length = wcslen(ValueName) * sizeof(WCHAR);
+
+        /* Add the size of the name plus a '\' and a UNICODE_STRING structure */
+        QueryContext->FullSize += Length + sizeof(UNICODE_NULL) +
+                                  sizeof(OBJ_NAME_PATH_SEPARATOR) +
+                                  sizeof(UNICODE_STRING);
+
+        /* Loop while we have alias names */
+        CurrentString = ValueData;
+        while (*CurrentString != UNICODE_NULL)
+        {
+            /* Count this alias */
+            QueryContext->NumberOfAliases++;
+
+            /* Get the length of the current string (i.e. the alias name) */
+            Length = wcslen(CurrentString) * sizeof(WCHAR);
+
+            /* Count the length plus the size of an NPFS_ALIAS structure */
+            QueryContext->FullSize += Length + sizeof(UNICODE_NULL) + sizeof(NPFS_ALIAS);
+
+            /* Go to the next string */
+            CurrentString += (Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
+        }
+    }
+    else
+    {
+        /* Get the next name string pointer */
+        CurrentTargetName = QueryContext->CurrentTargetName++;
+
+        /* Get the length of the value name (i.e. the target name). */
+        Length = wcslen(ValueName) * sizeof(WCHAR);
+
+        /* Initialize the current name string (one char more than the name) */
+        CurrentTargetName->Buffer = QueryContext->CurrentStringPointer;
+        CurrentTargetName->Length = Length + sizeof(OBJ_NAME_PATH_SEPARATOR);
+        CurrentTargetName->MaximumLength = CurrentTargetName->Length + sizeof(UNICODE_NULL);
+
+        /* Update the current string pointer */
+        QueryContext->CurrentStringPointer +=
+            CurrentTargetName->MaximumLength / sizeof(WCHAR);
+
+        /* Prepend a '\' before the name */
+        CurrentTargetName->Buffer[0] = OBJ_NAME_PATH_SEPARATOR;
+
+        /* Append the value name (including the NULL termination) */
+        RtlCopyMemory(&CurrentTargetName->Buffer[1],
+                      ValueName,
+                      Length + sizeof(UNICODE_NULL));
+
+        /* Upcase the target name */
+        RtlUpcaseUnicodeString(CurrentTargetName, CurrentTargetName, 0);
+
+        /* Loop while we have alias names */
+        CurrentString = ValueData;
+        while (*CurrentString != UNICODE_NULL)
+        {
+            /* Get the next alias pointer */
+            CurrentAlias = QueryContext->CurrentAlias++;
+
+            /* Get the length of the current string (i.e. the alias name) */
+            Length = wcslen(CurrentString) * sizeof(WCHAR);
+
+            /* Setup the alias structure */
+            CurrentAlias->TargetName = CurrentTargetName;
+            CurrentAlias->Name.Buffer = QueryContext->CurrentStringPointer;
+            CurrentAlias->Name.Length = Length;
+            CurrentAlias->Name.MaximumLength = Length + sizeof(UNICODE_NULL);
+
+            /* Upcase the alias name */
+            TempString.Buffer = CurrentString;
+            TempString.Length = Length;
+            RtlUpcaseUnicodeString(&CurrentAlias->Name,
+                                   &TempString,
+                                   FALSE);
+
+            /* Update the current string pointer */
+            QueryContext->CurrentStringPointer +=
+                CurrentAlias->Name.MaximumLength / sizeof(WCHAR);
+
+            /* Go to the next string */
+            CurrentString += (Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
+        }
+    }
+
+    return STATUS_SUCCESS;
+}
+
+LONG
+NTAPI
+NpCompareAliasNames(
+    _In_ PCUNICODE_STRING String1,
+    _In_ PCUNICODE_STRING String2)
+{
+    ULONG Count;
+    PWCHAR P1, P2;
+
+    /* First check if the string sizes match */
+    if (String1->Length != String2->Length)
+    {
+        /* They don't, return positive if the first is longer, negative otherwise */
+        return String1->Length - String2->Length;
+    }
+
+    /* Now loop all characters */
+    Count = String1->Length / sizeof(WCHAR);
+    P1 = String1->Buffer;
+    P2 = String2->Buffer;
+    while (Count)
+    {
+        /* Check if they don't match */
+        if (*P1 != *P2)
+        {
+            /* Return positive if the first char is greater, negative otherwise */
+            return *P1 - *P2;
+        }
+
+        /* Go to the next buffer position */
+        P1++;
+        P2++;
+        Count--;
+    }
+
+    /* All characters matched, return 0 */
+    return 0;
+}
+
+NTSTATUS
+NTAPI
+NpInitializeAliases(VOID)
+{
+    RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+    NPFS_QUERY_VALUE_CONTEXT Context;
+    NTSTATUS Status;
+    USHORT Length;
+    ULONG i;
+    PNPFS_ALIAS CurrentAlias, *AliasPointer;
+
+    /* Initialize the query table */
+    QueryTable[0].QueryRoutine = NpReadAlias;
+    QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
+    QueryTable[0].Name = NULL;
+    QueryTable[0].EntryContext = NULL;
+    QueryTable[0].DefaultType = REG_NONE;
+    QueryTable[0].DefaultData = NULL;
+    QueryTable[0].DefaultLength = 0;
+    QueryTable[1].QueryRoutine = NULL;
+    QueryTable[1].Flags = 0;
+    QueryTable[1].Name = NULL;
+
+    /* Setup the query context */
+    Context.SizeOnly = 1;
+    Context.FullSize = 0;
+    Context.NumberOfAliases = 0;
+    Context.NumberOfEntries = 0;
+
+    /* Query the registry values (calculate length only) */
+    Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES | RTL_REGISTRY_OPTIONAL,
+                                    L"Npfs\\Aliases",
+                                    QueryTable,
+                                    &Context,
+                                    NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+            return STATUS_SUCCESS;
+
+        return Status;
+    }
+
+    /* Check if there is anything */
+    if (Context.FullSize == 0)
+    {
+        /* Nothing to do, return success */
+        return STATUS_SUCCESS;
+    }
+
+    /* Allocate a structure large enough to hold all the data */
+    NpAliases = ExAllocatePoolWithTag(NonPagedPool, Context.FullSize, 'sfpN');
+    if (NpAliases == NULL)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* Now setup the actual pointers in the context */
+    Context.CurrentTargetName = NpAliases;
+    CurrentAlias = (PNPFS_ALIAS)&Context.CurrentTargetName[Context.NumberOfEntries];
+    Context.CurrentAlias = CurrentAlias;
+    Context.CurrentStringPointer = (PWCHAR)&CurrentAlias[Context.NumberOfAliases];
+
+    /* This time query the real data */
+    Context.SizeOnly = FALSE;
+    Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES | RTL_REGISTRY_OPTIONAL,
+                                    L"Npfs\\Aliases",
+                                    QueryTable,
+                                    &Context,
+                                    NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        ExFreePoolWithTag(NpAliases, 0);
+        NpAliases = NULL;
+        return Status;
+    }
+
+    /* Make sure we didn't go past the end of the allocation! */
+    NT_ASSERT((PUCHAR)Context.CurrentStringPointer <=
+              ((PUCHAR)NpAliases + Context.FullSize));
+
+    /* Loop all aliases we got */
+    for (i = 0; i < Context.NumberOfAliases; i++)
+    {
+        /* Get the length and check what list to use */
+        Length = CurrentAlias->Name.Length;
+        if ((Length >= MIN_INDEXED_LENGTH * sizeof(WCHAR)) &&
+            (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR)))
+        {
+            /* For this length range, we use an indexed list */
+            AliasPointer = &NpAliasListByLength[(Length / sizeof(WCHAR)) - 5];
+        }
+        else
+        {
+            /* Length is outside of the range, use the default list */
+            AliasPointer = &NpAliasList;
+        }
+
+        /* Loop through all aliases already in the list until we find one that
+           is greater than our current alias */
+        while ((*AliasPointer != NULL) &&
+               (NpCompareAliasNames(&CurrentAlias->Name,
+                                    &(*AliasPointer)->Name) > 0))
+        {
+            /* Go to the next alias */
+            AliasPointer = &(*AliasPointer)->Next;
+        }
+
+        /* Insert the alias in the list */
+        CurrentAlias->Next = *AliasPointer;
+        *AliasPointer = CurrentAlias;
+
+        /* Go to the next alias in the array */
+        CurrentAlias++;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
 NTSTATUS
 NTAPI
 NpFsdDirectoryControl(IN PDEVICE_OBJECT DeviceObject,
                      IN PIRP Irp)
 {
+    TRACE("Entered\n");
     UNIMPLEMENTED;
 
     Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
@@ -45,6 +323,13 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
 
     DPRINT1("Next-Generation NPFS-Lite\n");
 
+    Status = NpInitializeAliases();
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to initialize aliases!\n");
+        return Status;
+    }
+
     DriverObject->MajorFunction[IRP_MJ_CREATE] = NpFsdCreate;
     DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = NpFsdCreateNamedPipe;
     DriverObject->MajorFunction[IRP_MJ_CLOSE] = NpFsdClose;
index 77c7fce..c33ce43 100644 (file)
 #include <ntifs.h>
 #include <ntndk.h>
 #include <pseh/pseh2.h>
-#define UNIMPLEMENTED
-#define DPRINT1 DbgPrint
+//#define UNIMPLEMENTED
+//#define DPRINT1 DbgPrint
+
+#define NDEBUG
+#include <debug.h>
+#define TRACE(...) /* DPRINT1("%s: ", __FUNCTION__); DbgPrint(__VA_ARGS__) */
 
 //
 // Allow Microsoft Extensions
@@ -26,6 +30,9 @@
 #pragma warning(disable:4100)
 #endif
 
+#define MIN_INDEXED_LENGTH 5
+#define MAX_INDEXED_LENGTH 9
+
 
 /* TYPEDEFS & DEFINES *********************************************************/
 
@@ -326,6 +333,32 @@ typedef struct _NP_VCB
 
 extern PNP_VCB NpVcb;
 
+//
+// Defines an alias
+//
+typedef struct _NPFS_ALIAS
+{
+    struct _NPFS_ALIAS *Next;
+    PUNICODE_STRING TargetName;
+    UNICODE_STRING Name;
+} NPFS_ALIAS, *PNPFS_ALIAS;
+
+//
+// Private structure used to enumerate the alias values
+//
+typedef struct _NPFS_QUERY_VALUE_CONTEXT
+{
+    BOOLEAN SizeOnly;
+    SIZE_T FullSize;
+    ULONG NumberOfAliases;
+    ULONG NumberOfEntries;
+    PNPFS_ALIAS CurrentAlias;
+    PUNICODE_STRING CurrentTargetName;
+    PWCHAR CurrentStringPointer;
+} NPFS_QUERY_VALUE_CONTEXT, *PNPFS_QUERY_VALUE_CONTEXT;
+
+extern PNPFS_ALIAS NpAliasList;
+extern PNPFS_ALIAS NpAliasListByLength[MAX_INDEXED_LENGTH + 1 - MIN_INDEXED_LENGTH];
 
 /* FUNCTIONS ******************************************************************/
 
@@ -385,6 +418,12 @@ NpCompleteDeferredIrps(IN PLIST_ENTRY DeferredList)
     }
 }
 
+LONG
+NTAPI
+NpCompareAliasNames(
+    _In_ PCUNICODE_STRING String1,
+    _In_ PCUNICODE_STRING String2);
+
 BOOLEAN
 NTAPI
 NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table,
@@ -415,7 +454,7 @@ NTAPI
 NpAddDataQueueEntry(IN ULONG NamedPipeEnd,
                     IN PNP_CCB Ccb,
                     IN PNP_DATA_QUEUE DataQueue,
-                    IN ULONG Who, 
+                    IN ULONG Who,
                     IN ULONG Type,
                     IN ULONG DataSize,
                     IN PIRP Irp,
@@ -510,20 +549,20 @@ NpSetConnectedPipeState(IN PNP_CCB Ccb,
 NTSTATUS
 NTAPI
 NpSetListeningPipeState(IN PNP_CCB Ccb,
-                        IN PIRP Irp, 
+                        IN PIRP Irp,
                         IN PLIST_ENTRY List);
 
 
 NTSTATUS
 NTAPI
-NpSetDisconnectedPipeState(IN PNP_CCB Ccb, 
+NpSetDisconnectedPipeState(IN PNP_CCB Ccb,
                            IN PLIST_ENTRY List);
 
 NTSTATUS
 NTAPI
 NpSetClosingPipeState(IN PNP_CCB Ccb,
-                      IN PIRP Irp, 
-                      IN ULONG NamedPipeEnd, 
+                      IN PIRP Irp,
+                      IN ULONG NamedPipeEnd,
                       IN PLIST_ENTRY List);
 
 VOID
@@ -594,7 +633,7 @@ NTSTATUS
 NTAPI
 NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
             IN LARGE_INTEGER WaitTime,
-            IN PIRP Irp, 
+            IN PIRP Irp,
             IN PUNICODE_STRING AliasName);
 
 NTSTATUS
@@ -607,27 +646,27 @@ NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
 
 IO_STATUS_BLOCK
 NTAPI
-NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue, 
+NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue,
                 IN BOOLEAN Peek,
                 IN BOOLEAN ReadOverflowOperation,
                 IN PVOID Buffer,
-                IN ULONG BufferSize, 
-                IN ULONG Mode, 
+                IN ULONG BufferSize,
+                IN ULONG Mode,
                 IN PNP_CCB Ccb,
                 IN PLIST_ENTRY List);
 
 
-NTSTATUS 
+NTSTATUS
 NTAPI
 NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
-                 IN ULONG Mode, 
-                 IN PVOID OutBuffer, 
-                 IN ULONG OutBufferSize, 
-                 IN ULONG PipeType, 
-                 OUT PULONG BytesWritten, 
-                 IN PNP_CCB Ccb, 
-                 IN ULONG NamedPipeEnd, 
-                 IN PETHREAD Thread, 
+                 IN ULONG Mode,
+                 IN PVOID OutBuffer,
+                 IN ULONG OutBufferSize,
+                 IN ULONG PipeType,
+                 OUT PULONG BytesWritten,
+                 IN PNP_CCB Ccb,
+                 IN ULONG NamedPipeEnd,
+                 IN PETHREAD Thread,
                  IN PLIST_ENTRY List);
 
 NTSTATUS
index faa15f7..73d0360 100644 (file)
@@ -15,8 +15,6 @@
 
 /* GLOBALS ********************************************************************/
 
-#define UNIMPLEMENTED
-
 PWCHAR NpRootDCBName = L"\\";
 PNP_VCB NpVcb;
 
index 79e8471..54c9240 100644 (file)
@@ -23,6 +23,7 @@ NpQueryFsVolumeInfo(IN PVOID Buffer,
     PFILE_FS_VOLUME_INFORMATION InfoBuffer = Buffer;
     NTSTATUS Status;
     USHORT NameLength;
+    TRACE("Entered\n");
 
     *Length -= sizeof(*InfoBuffer);
 
@@ -47,6 +48,7 @@ NpQueryFsVolumeInfo(IN PVOID Buffer,
     RtlCopyMemory(InfoBuffer->VolumeLabel, L"Named Pipe", NameLength);
     *Length -= NameLength;
 
+    TRACE("Leaving, Status = %lx\n", Status);
     return Status;
 }
 
@@ -56,6 +58,7 @@ NpQueryFsSizeInfo(IN PVOID Buffer,
                   IN OUT PULONG Length)
 {
     PFILE_FS_SIZE_INFORMATION InfoBuffer = Buffer;
+    TRACE("Entered\n");
 
     *Length -= sizeof(*InfoBuffer);
 
@@ -64,6 +67,7 @@ NpQueryFsSizeInfo(IN PVOID Buffer,
     InfoBuffer->SectorsPerAllocationUnit = 1;
     InfoBuffer->BytesPerSector = 1;
 
+    TRACE("Leaving, Status = STATUS_SUCCESS\n");
     return STATUS_SUCCESS;
 }
 
@@ -74,6 +78,7 @@ NpQueryFsDeviceInfo(IN PVOID Buffer,
 {
     PFILE_FS_DEVICE_INFORMATION InfoBuffer = Buffer;
     NTSTATUS Status;
+    TRACE("Entered\n");
 
     if (*Length >= sizeof(*InfoBuffer))
     {
@@ -87,6 +92,7 @@ NpQueryFsDeviceInfo(IN PVOID Buffer,
     {
         Status = STATUS_BUFFER_OVERFLOW;
     }
+    TRACE("Leaving, Status = %lx\n", Status);
     return Status;
 }
 
@@ -98,6 +104,7 @@ NpQueryFsAttributeInfo(IN PVOID Buffer,
     PFILE_FS_ATTRIBUTE_INFORMATION InfoBuffer = Buffer;
     NTSTATUS Status;
     USHORT NameLength;
+    TRACE("Entered\n");
 
     NameLength = (USHORT)(*Length - 12);
     if (NameLength < 8)
@@ -117,6 +124,7 @@ NpQueryFsAttributeInfo(IN PVOID Buffer,
     InfoBuffer->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES;
     RtlCopyMemory(InfoBuffer->FileSystemName, L"NPFS", NameLength);
 
+    TRACE("Leaving, Status = %lx\n", Status);
     return Status;
 }
 
@@ -126,11 +134,13 @@ NpQueryFsFullSizeInfo(IN PVOID Buffer,
                       IN OUT PULONG Length)
 {
     PFILE_FS_FULL_SIZE_INFORMATION InfoBuffer = Buffer;
+    TRACE("Entered\n");
 
     *Length -= sizeof(*InfoBuffer);
 
     RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
 
+    TRACE("Leaving, Status = STATUS_SUCCESS\n");
     return STATUS_SUCCESS;
 }
 
@@ -145,6 +155,7 @@ NpCommonQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject,
     PVOID Buffer;
     NTSTATUS Status;
     PAGED_CODE();
+    TRACE("Entered\n");
 
     IoStack = IoGetCurrentIrpStackLocation(Irp);
     Buffer = Irp->AssociatedIrp.SystemBuffer;
@@ -174,6 +185,7 @@ NpCommonQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject,
     }
 
     Irp->IoStatus.Information = IoStack->Parameters.QueryVolume.Length - Length;
+    TRACE("Leaving, Status = %lx\n", Status);
     return Status;
 }
 
@@ -184,6 +196,7 @@ NpFsdQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject,
 {
     NTSTATUS Status;
     PAGED_CODE();
+    TRACE("Entered\n");
 
     FsRtlEnterFileSystem();
     ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
@@ -199,6 +212,7 @@ NpFsdQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject,
         IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
     }
 
+    TRACE("Leaving, Status = %lx\n", Status);
     return Status;
 }