[USETUP] Improve the FileSup module.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 21 May 2017 23:45:43 +0000 (23:45 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 27 May 2018 18:18:53 +0000 (20:18 +0200)
- Add a NtPathToDiskPartComponents() helper, that takes in input a fully qualified NT path to a file on hard disk,
  e.g.: \Device\Harddisk1\Partition2\foo\bar, and returns in output the disk number ('1'), the partition number ('2'),
  and the the path component "\foo\bar" that is after the device-harddisk-partition identifier.
- Make the OpenAndMapFile() return the file size of the opened file.

Both of these additions will be used soon.

- Turn a isspace() call into a iswspace() one.

svn path=/branches/setup_improvements/; revision=74619

base/setup/usetup/filesup.c
base/setup/usetup/filesup.h

index 293e590..49defff 100644 (file)
@@ -501,7 +501,7 @@ IsValidPath(
     /* Path must not contain whitespace characters */
     for (i = 0; i < Length; i++)
     {
-        if (isspace(InstallDir[i]))
+        if (iswspace(InstallDir[i]))
             return FALSE;
     }
 
@@ -633,6 +633,117 @@ DoesFileExist(
     return NT_SUCCESS(Status);
 }
 
+/*
+ * The format of NtPath should be:
+ *    \Device\HarddiskXXX\PartitionYYY[\path] ,
+ * where XXX and YYY respectively represent the hard disk and partition numbers,
+ * and [\path] represent an optional path (separated by '\\').
+ *
+ * If a NT path of such a form is correctly parsed, the function returns respectively:
+ * - in pDiskNumber: the hard disk number XXX,
+ * - in pPartNumber: the partition number YYY,
+ * - in PathComponent: pointer value (inside NtPath) to the beginning of \path.
+ *
+ * NOTE: The function does not accept leading whitespace.
+ */
+BOOLEAN
+NtPathToDiskPartComponents(
+    IN PCWSTR NtPath,
+    OUT PULONG pDiskNumber,
+    OUT PULONG pPartNumber,
+    OUT PCWSTR* PathComponent OPTIONAL)
+{
+    ULONG DiskNumber, PartNumber;
+    PCWSTR Path;
+
+    *pDiskNumber = 0;
+    *pPartNumber = 0;
+    if (PathComponent) *PathComponent = NULL;
+
+    Path = NtPath;
+
+    if (_wcsnicmp(Path, L"\\Device\\Harddisk", 16) != 0)
+    {
+        /* The NT path doesn't start with the prefix string, thus it cannot be a hard disk device path */
+        DPRINT1("'%S' : Not a possible hard disk device.\n", NtPath);
+        return FALSE;
+    }
+
+    Path += 16;
+
+    /* A number must be present now */
+    if (!iswdigit(*Path))
+    {
+        DPRINT1("'%S' : expected a number! Not a regular hard disk device.\n", Path);
+        return FALSE;
+    }
+    DiskNumber = wcstoul(Path, (PWSTR*)&Path, 10);
+
+    /* Either NULL termination, or a path separator must be present now */
+    if (!Path)
+    {
+        DPRINT1("An error happened!\n");
+        return FALSE;
+    }
+    else if (*Path && *Path != OBJ_NAME_PATH_SEPARATOR)
+    {
+        DPRINT1("'%S' : expected a path separator!\n", Path);
+        return FALSE;
+    }
+
+    if (!*Path)
+    {
+        DPRINT1("The path only specified a hard disk (and nothing else, like a partition...), so we stop there.\n");
+        goto Quit;
+    }
+
+    /* Here, *Path == L'\\' */
+
+    if (_wcsnicmp(Path, L"\\Partition", 10) != 0)
+    {
+        /* Actually, \Partition is optional so, if we don't have it, we still return success. Or should we? */
+        DPRINT1("'%S' : unexpected format!\n", NtPath);
+        goto Quit;
+    }
+
+    Path += 10;
+
+    /* A number must be present now */
+    if (!iswdigit(*Path))
+    {
+        /* If we don't have a number it means this part of path is actually not a partition specifier, so we shouldn't fail either. Or should we? */
+        DPRINT1("'%S' : expected a number!\n", Path);
+        goto Quit;
+    }
+    PartNumber = wcstoul(Path, (PWSTR*)&Path, 10);
+
+    /* Either NULL termination, or a path separator must be present now */
+    if (!Path)
+    {
+        /* We fail here because wcstoul failed for whatever reason */
+        DPRINT1("An error happened!\n");
+        return FALSE;
+    }
+    else if (*Path && *Path != OBJ_NAME_PATH_SEPARATOR)
+    {
+        /* We shouldn't fail here because it just means this part of path is actually not a partition specifier. Or should we? */
+        DPRINT1("'%S' : expected a path separator!\n", Path);
+        goto Quit;
+    }
+
+    /* OK, here we really have a partition specifier: return its number */
+    *pPartNumber = PartNumber;
+
+Quit:
+    /* Return the disk number */
+    *pDiskNumber = DiskNumber;
+
+    /* Return the path component also, if the user wants it */
+    if (PathComponent) *PathComponent = Path;
+
+    return TRUE;
+}
+
 NTSTATUS
 OpenAndMapFile(
     IN HANDLE RootDirectory OPTIONAL,
@@ -640,7 +751,8 @@ OpenAndMapFile(
     IN PCWSTR FileName,             // OPTIONAL
     OUT PHANDLE FileHandle,         // IN OUT PHANDLE OPTIONAL
     OUT PHANDLE SectionHandle,
-    OUT PVOID* BaseAddress)
+    OUT PVOID* BaseAddress,
+    OUT PULONG FileSize OPTIONAL)
 {
     NTSTATUS Status;
     OBJECT_ATTRIBUTES ObjectAttributes;
@@ -681,6 +793,31 @@ OpenAndMapFile(
         return Status;
     }
 
+    if (FileSize)
+    {
+        /* Query the file size */
+        FILE_STANDARD_INFORMATION FileInfo;
+        Status = NtQueryInformationFile(*FileHandle,
+                                        &IoStatusBlock,
+                                        &FileInfo,
+                                        sizeof(FileInfo),
+                                        FileStandardInformation);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
+            NtClose(*FileHandle);
+            *FileHandle = NULL;
+            return Status;
+        }
+
+        if (FileInfo.EndOfFile.HighPart != 0)
+            DPRINT1("WARNING!! The file %wZ is too large!\n", Name);
+
+        *FileSize = FileInfo.EndOfFile.LowPart;
+
+        DPRINT("File size: %lu\n", *FileSize);
+    }
+
     /* Map the file in memory */
 
     /* Create the section */
index 492dff0..317fad9 100644 (file)
@@ -63,6 +63,13 @@ DoesFileExist(
     IN PCWSTR PathName OPTIONAL,
     IN PCWSTR FileName);
 
+BOOLEAN
+NtPathToDiskPartComponents(
+    IN PCWSTR NtPath,
+    OUT PULONG pDiskNumber,
+    OUT PULONG pPartNumber,
+    OUT PCWSTR* PathComponent OPTIONAL);
+
 NTSTATUS
 OpenAndMapFile(
     IN HANDLE RootDirectory OPTIONAL,
@@ -70,7 +77,8 @@ OpenAndMapFile(
     IN PCWSTR FileName,             // OPTIONAL
     OUT PHANDLE FileHandle,         // IN OUT PHANDLE OPTIONAL
     OUT PHANDLE SectionHandle,
-    OUT PVOID* BaseAddress);
+    OUT PVOID* BaseAddress,
+    OUT PULONG FileSize OPTIONAL);
 
 BOOLEAN
 UnMapFile(