[USETUP] Add & modify some file utility functions that are going to be used next.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 13 May 2017 16:13:49 +0000 (16:13 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 26 May 2018 17:09:38 +0000 (19:09 +0200)
- ConcatPaths that concatenates paths (or a path and a file name);
- OpenAndMapFile (resp. UnMapFile), whose purpose is to open a file and map it in memory (resp. unmap it from memory).
- Add extra optional parameters to DoesPathExist and DoesFileExist: an optional "RootDirectory" handle and, for DoesFileExist only, an optional PathName.
- Close the opened file handles only on success.

svn path=/branches/setup_improvements/; revision=74528
svn path=/branches/setup_improvements/; revision=74538
svn path=/branches/setup_improvements/; revision=74549

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

index 75319fb..674808a 100644 (file)
@@ -2275,7 +2275,7 @@ InstallFatBootcodeToPartition(
     wcscpy(DstPath, SystemRootPath->Buffer);
     wcscat(DstPath, L"\\freeldr.ini");
 
     wcscpy(DstPath, SystemRootPath->Buffer);
     wcscat(DstPath, L"\\freeldr.ini");
 
-    DoesFreeLdrExist = DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini");
+    DoesFreeLdrExist = DoesFileExist(NULL, SystemRootPath->Buffer, L"freeldr.ini");
     if (DoesFreeLdrExist)
     {
         /* Update existing 'freeldr.ini' */
     if (DoesFreeLdrExist)
     {
         /* Update existing 'freeldr.ini' */
@@ -2292,8 +2292,8 @@ InstallFatBootcodeToPartition(
     /* Check for NT and other bootloaders */
 
     // FIXME: Check for Vista+ bootloader!
     /* Check for NT and other bootloaders */
 
     // FIXME: Check for Vista+ bootloader!
-    if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE ||
-        DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE)
+    if (DoesFileExist(NULL, SystemRootPath->Buffer, L"ntldr") == TRUE ||
+        DoesFileExist(NULL, SystemRootPath->Buffer, L"boot.ini") == TRUE)
     {
         /* Search root directory for 'ntldr' and 'boot.ini' */
         DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
     {
         /* Search root directory for 'ntldr' and 'boot.ini' */
         DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
@@ -2375,8 +2375,8 @@ InstallFatBootcodeToPartition(
         PWCHAR BootSector;
         PWCHAR BootSectorFileName;
 
         PWCHAR BootSector;
         PWCHAR BootSectorFileName;
 
-        if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE ||
-            DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE)
+        if (DoesFileExist(NULL, SystemRootPath->Buffer, L"io.sys") == TRUE ||
+            DoesFileExist(NULL, SystemRootPath->Buffer, L"msdos.sys") == TRUE)
         {
             /* Search for root directory for 'io.sys' and 'msdos.sys' */
             DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
         {
             /* Search for root directory for 'io.sys' and 'msdos.sys' */
             DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
@@ -2390,7 +2390,7 @@ InstallFatBootcodeToPartition(
             BootSectorFileName = L"\\bootsect.dos";
         }
         else
             BootSectorFileName = L"\\bootsect.dos";
         }
         else
-        if (DoesFileExist(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
+        if (DoesFileExist(NULL, SystemRootPath->Buffer, L"kernel.sys") == TRUE)
         {
             /* Search for root directory for 'kernel.sys' */
             DPRINT1("Found FreeDOS boot loader\n");
         {
             /* Search for root directory for 'kernel.sys' */
             DPRINT1("Found FreeDOS boot loader\n");
@@ -2529,7 +2529,7 @@ InstallExt2BootcodeToPartition(
     wcscpy(DstPath, SystemRootPath->Buffer);
     wcscat(DstPath, L"\\freeldr.ini");
 
     wcscpy(DstPath, SystemRootPath->Buffer);
     wcscat(DstPath, L"\\freeldr.ini");
 
-    DoesFreeLdrExist = DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini");
+    DoesFreeLdrExist = DoesFileExist(NULL, SystemRootPath->Buffer, L"freeldr.ini");
     if (DoesFreeLdrExist)
     {
         /* Update existing 'freeldr.ini' */
     if (DoesFreeLdrExist)
     {
         /* Update existing 'freeldr.ini' */
index 568525d..293e590 100644 (file)
@@ -93,90 +93,6 @@ SetupCreateSingleDirectory(
     return Status;
 }
 
     return Status;
 }
 
-
-static
-BOOLEAN
-DoesPathExist(
-    PWSTR PathName)
-{
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    IO_STATUS_BLOCK IoStatusBlock;
-    UNICODE_STRING Name;
-    HANDLE FileHandle;
-    NTSTATUS Status;
-
-    RtlInitUnicodeString(&Name,
-                         PathName);
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &Name,
-                               OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
-
-    Status = NtOpenFile(&FileHandle,
-                        GENERIC_READ | SYNCHRONIZE,
-                        &ObjectAttributes,
-                        &IoStatusBlock,
-                        0,
-                        FILE_SYNCHRONOUS_IO_NONALERT);
-    if (!NT_SUCCESS(Status))
-    {
-        return FALSE;
-    }
-
-    NtClose(FileHandle);
-
-    return TRUE;
-}
-
-
-BOOLEAN
-IsValidPath(
-    PWCHAR InstallDir)
-{
-    UINT i, Length;
-
-    Length = wcslen(InstallDir);
-
-    // TODO: Add check for 8.3 too.
-
-    /* Path must be at least 2 characters long */
-//    if (Length < 2)
-//        return FALSE;
-
-    /* Path must start with a backslash */
-//    if (InstallDir[0] != L'\\')
-//        return FALSE;
-
-    /* Path must not end with a backslash */
-    if (InstallDir[Length - 1] == L'\\')
-        return FALSE;
-
-    /* Path must not contain whitespace characters */
-    for (i = 0; i < Length; i++)
-    {
-        if (isspace(InstallDir[i]))
-            return FALSE;
-    }
-
-    /* Path component must not end with a dot */
-    for (i = 0; i < Length; i++)
-    {
-        if (InstallDir[i] == L'\\' && i > 0)
-        {
-            if (InstallDir[i - 1] == L'.')
-                return FALSE;
-        }
-    }
-
-    if (InstallDir[Length - 1] == L'.')
-        return FALSE;
-
-    return TRUE;
-}
-
-
 NTSTATUS
 SetupCreateDirectory(
     PWCHAR PathName)
 NTSTATUS
 SetupCreateDirectory(
     PWCHAR PathName)
@@ -214,7 +130,7 @@ SetupCreateDirectory(
             *Ptr = 0;
 
             DPRINT("PathBuffer: %S\n", PathBuffer);
             *Ptr = 0;
 
             DPRINT("PathBuffer: %S\n", PathBuffer);
-            if (!DoesPathExist(PathBuffer))
+            if (!DoesPathExist(NULL, PathBuffer))
             {
                 DPRINT("Create: %S\n", PathBuffer);
                 Status = SetupCreateSingleDirectory(PathBuffer);
             {
                 DPRINT("Create: %S\n", PathBuffer);
                 Status = SetupCreateSingleDirectory(PathBuffer);
@@ -228,7 +144,7 @@ SetupCreateDirectory(
         Ptr++;
     }
 
         Ptr++;
     }
 
-    if (!DoesPathExist(PathBuffer))
+    if (!DoesPathExist(NULL, PathBuffer))
     {
         DPRINT("Create: %S\n", PathBuffer);
         Status = SetupCreateSingleDirectory(PathBuffer);
     {
         DPRINT("Create: %S\n", PathBuffer);
         Status = SetupCreateSingleDirectory(PathBuffer);
@@ -244,7 +160,6 @@ done:
     return Status;
 }
 
     return Status;
 }
 
-
 NTSTATUS
 SetupCopyFile(
     PWCHAR SourceFileName,
 NTSTATUS
 SetupCopyFile(
     PWCHAR SourceFileName,
@@ -561,49 +476,279 @@ SetupExtractFile(
 }
 
 
 }
 
 
+BOOLEAN
+IsValidPath(
+    IN PCWSTR InstallDir)
+{
+    UINT i, Length;
+
+    Length = wcslen(InstallDir);
+
+    // TODO: Add check for 8.3 too.
+
+    /* Path must be at least 2 characters long */
+//    if (Length < 2)
+//        return FALSE;
+
+    /* Path must start with a backslash */
+//    if (InstallDir[0] != L'\\')
+//        return FALSE;
+
+    /* Path must not end with a backslash */
+    if (InstallDir[Length - 1] == L'\\')
+        return FALSE;
+
+    /* Path must not contain whitespace characters */
+    for (i = 0; i < Length; i++)
+    {
+        if (isspace(InstallDir[i]))
+            return FALSE;
+    }
+
+    /* Path component must not end with a dot */
+    for (i = 0; i < Length; i++)
+    {
+        if (InstallDir[i] == L'\\' && i > 0)
+        {
+            if (InstallDir[i - 1] == L'.')
+                return FALSE;
+        }
+    }
+
+    if (InstallDir[Length - 1] == L'.')
+        return FALSE;
+
+    return TRUE;
+}
+
+NTSTATUS
+ConcatPaths(
+    IN OUT PWSTR PathElem1,
+    IN SIZE_T cchPathSize,
+    IN PCWSTR PathElem2 OPTIONAL)
+{
+    NTSTATUS Status;
+    SIZE_T cchPathLen;
+
+    if (!PathElem2)
+        return STATUS_SUCCESS;
+    if (cchPathSize <= 1)
+        return STATUS_SUCCESS;
+
+    cchPathLen = min(cchPathSize, wcslen(PathElem1));
+
+    if (PathElem2[0] != L'\\' && cchPathLen > 0 && PathElem1[cchPathLen-1] != L'\\')
+    {
+        /* PathElem2 does not start with '\' and PathElem1 does not end with '\' */
+        Status = RtlStringCchCatW(PathElem1, cchPathSize, L"\\");
+        if (!NT_SUCCESS(Status))
+            return Status;
+    }
+    else if (PathElem2[0] == L'\\' && cchPathLen > 0 && PathElem1[cchPathLen-1] == L'\\')
+    {
+        /* PathElem2 starts with '\' and PathElem1 ends with '\' */
+        while (*PathElem2 == L'\\')
+            ++PathElem2; // Skip any backslash
+    }
+    Status = RtlStringCchCatW(PathElem1, cchPathSize, PathElem2);
+    return Status;
+}
+
+//
+// NOTE: It may be possible to merge both DoesPathExist and DoesFileExist...
+//
+BOOLEAN
+DoesPathExist(
+    IN HANDLE RootDirectory OPTIONAL,
+    IN PCWSTR PathName)
+{
+    NTSTATUS Status;
+    HANDLE FileHandle;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    UNICODE_STRING Name;
+
+    RtlInitUnicodeString(&Name, PathName);
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &Name,
+                               OBJ_CASE_INSENSITIVE,
+                               RootDirectory,
+                               NULL);
+
+    Status = NtOpenFile(&FileHandle,
+                        FILE_LIST_DIRECTORY | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE,
+                        FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
+    if (NT_SUCCESS(Status))
+        NtClose(FileHandle);
+    else
+        DPRINT1("Failed to open directory %wZ, Status 0x%08lx\n", &Name, Status);
+
+    return NT_SUCCESS(Status);
+}
+
 BOOLEAN
 DoesFileExist(
 BOOLEAN
 DoesFileExist(
-    PWSTR PathName,
-    PWSTR FileName)
+    IN HANDLE RootDirectory OPTIONAL,
+    IN PCWSTR PathName OPTIONAL,
+    IN PCWSTR FileName)
 {
 {
+    NTSTATUS Status;
+    HANDLE FileHandle;
     OBJECT_ATTRIBUTES ObjectAttributes;
     IO_STATUS_BLOCK IoStatusBlock;
     UNICODE_STRING Name;
     WCHAR FullName[MAX_PATH];
     OBJECT_ATTRIBUTES ObjectAttributes;
     IO_STATUS_BLOCK IoStatusBlock;
     UNICODE_STRING Name;
     WCHAR FullName[MAX_PATH];
-    HANDLE FileHandle;
-    NTSTATUS Status;
 
 
-    wcscpy(FullName, PathName);
-    if (FileName != NULL)
-    {
-        if (FileName[0] != L'\\')
-            wcscat(FullName, L"\\");
-        wcscat(FullName, FileName);
-    }
+    if (PathName)
+        RtlStringCchCopyW(FullName, ARRAYSIZE(FullName), PathName);
+    else
+        FullName[0] = UNICODE_NULL;
 
 
-    RtlInitUnicodeString(&Name,
-                         FullName);
+    if (FileName)
+        ConcatPaths(FullName, ARRAYSIZE(FullName), FileName);
+
+    RtlInitUnicodeString(&Name, FullName);
 
     InitializeObjectAttributes(&ObjectAttributes,
                                &Name,
                                OBJ_CASE_INSENSITIVE,
 
     InitializeObjectAttributes(&ObjectAttributes,
                                &Name,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               RootDirectory,
                                NULL);
 
     Status = NtOpenFile(&FileHandle,
                         GENERIC_READ | SYNCHRONIZE,
                         &ObjectAttributes,
                         &IoStatusBlock,
                                NULL);
 
     Status = NtOpenFile(&FileHandle,
                         GENERIC_READ | SYNCHRONIZE,
                         &ObjectAttributes,
                         &IoStatusBlock,
-                        0,
-                        FILE_SYNCHRONOUS_IO_NONALERT);
+                        FILE_SHARE_READ | FILE_SHARE_WRITE,
+                        FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
+    if (NT_SUCCESS(Status))
+        NtClose(FileHandle);
+    else
+        DPRINT1("Failed to open file %wZ, Status 0x%08lx\n", &Name, Status);
+
+    return NT_SUCCESS(Status);
+}
+
+NTSTATUS
+OpenAndMapFile(
+    IN HANDLE RootDirectory OPTIONAL,
+    IN PCWSTR PathName OPTIONAL,
+    IN PCWSTR FileName,             // OPTIONAL
+    OUT PHANDLE FileHandle,         // IN OUT PHANDLE OPTIONAL
+    OUT PHANDLE SectionHandle,
+    OUT PVOID* BaseAddress)
+{
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    SIZE_T ViewSize;
+    PVOID ViewBase;
+    UNICODE_STRING Name;
+    WCHAR FullName[MAX_PATH];
+
+    if (PathName)
+        RtlStringCchCopyW(FullName, ARRAYSIZE(FullName), PathName);
+    else
+        FullName[0] = UNICODE_NULL;
+
+    if (FileName)
+        ConcatPaths(FullName, ARRAYSIZE(FullName), FileName);
+
+    RtlInitUnicodeString(&Name, FullName);
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &Name,
+                               OBJ_CASE_INSENSITIVE,
+                               RootDirectory,
+                               NULL);
+
+    *FileHandle = NULL;
+    *SectionHandle = NULL;
+
+    Status = NtOpenFile(FileHandle,
+                        GENERIC_READ | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ,
+                        FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
     if (!NT_SUCCESS(Status))
     {
     if (!NT_SUCCESS(Status))
     {
-      return FALSE;
+        DPRINT1("Failed to open file %wZ, Status 0x%08lx\n", &Name, Status);
+        return Status;
     }
 
     }
 
-    NtClose(FileHandle);
+    /* Map the file in memory */
 
 
-    return TRUE;
+    /* Create the section */
+    Status = NtCreateSection(SectionHandle,
+                             SECTION_MAP_READ,
+                             NULL,
+                             NULL,
+                             PAGE_READONLY,
+                             SEC_COMMIT /* | SEC_IMAGE (_NO_EXECUTE) */,
+                             *FileHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create a memory section for file %wZ, Status 0x%08lx\n", &Name, Status);
+        NtClose(*FileHandle);
+        *FileHandle = NULL;
+        return Status;
+    }
+
+    /* Map the section */
+    ViewSize = 0;
+    ViewBase = NULL;
+    Status = NtMapViewOfSection(*SectionHandle,
+                                NtCurrentProcess(),
+                                &ViewBase,
+                                0, 0,
+                                NULL,
+                                &ViewSize,
+                                ViewShare,
+                                0,
+                                PAGE_READONLY);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to map a view for file %wZ, Status 0x%08lx\n", &Name, Status);
+        NtClose(*SectionHandle);
+        *SectionHandle = NULL;
+        NtClose(*FileHandle);
+        *FileHandle = NULL;
+        return Status;
+    }
+
+    *BaseAddress = ViewBase;
+    return STATUS_SUCCESS;
+}
+
+BOOLEAN
+UnMapFile(
+    IN HANDLE SectionHandle,
+    IN PVOID BaseAddress)
+{
+    NTSTATUS Status;
+    BOOLEAN Success = TRUE;
+
+    Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("UnMapFile: NtUnmapViewOfSection(0x%p) failed with Status 0x%08lx\n",
+                BaseAddress, Status);
+        Success = FALSE;
+    }
+    Status = NtClose(SectionHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("UnMapFile: NtClose(0x%p) failed with Status 0x%08lx\n",
+                SectionHandle, Status);
+        Success = FALSE;
+    }
+
+    return Success;
 }
 
 /* EOF */
 }
 
 /* EOF */
index e09a08c..492dff0 100644 (file)
@@ -41,13 +41,40 @@ SetupExtractFile(
     PWCHAR SourceFileName,
     PWCHAR DestinationFileName);
 
     PWCHAR SourceFileName,
     PWCHAR DestinationFileName);
 
+
+BOOLEAN
+IsValidPath(
+    IN PCWSTR InstallDir);
+
+NTSTATUS
+ConcatPaths(
+    IN OUT PWSTR PathElem1,
+    IN SIZE_T cchPathSize,
+    IN PCWSTR PathElem2 OPTIONAL);
+
+BOOLEAN
+DoesPathExist(
+    IN HANDLE RootDirectory OPTIONAL,
+    IN PCWSTR PathName);
+
 BOOLEAN
 DoesFileExist(
 BOOLEAN
 DoesFileExist(
-    PWSTR PathName,
-    PWSTR FileName);
+    IN HANDLE RootDirectory OPTIONAL,
+    IN PCWSTR PathName OPTIONAL,
+    IN PCWSTR FileName);
+
+NTSTATUS
+OpenAndMapFile(
+    IN HANDLE RootDirectory OPTIONAL,
+    IN PCWSTR PathName OPTIONAL,
+    IN PCWSTR FileName,             // OPTIONAL
+    OUT PHANDLE FileHandle,         // IN OUT PHANDLE OPTIONAL
+    OUT PHANDLE SectionHandle,
+    OUT PVOID* BaseAddress);
 
 BOOLEAN
 
 BOOLEAN
-IsValidPath(
-    PWCHAR InstallDir);
+UnMapFile(
+    IN HANDLE SectionHandle,
+    IN PVOID BaseAddress);
 
 /* EOF */
 
 /* EOF */
index 8c80812..234bfa4 100644 (file)
@@ -424,7 +424,7 @@ CheckUnattendedSetup(VOID)
     INT IntValue;
     PWCHAR Value;
 
     INT IntValue;
     PWCHAR Value;
 
-    if (DoesFileExist(SourcePath.Buffer, L"unattend.inf") == FALSE)
+    if (DoesFileExist(NULL, SourcePath.Buffer, L"unattend.inf") == FALSE)
     {
         DPRINT("Does not exist: %S\\%S\n", SourcePath.Buffer, L"unattend.inf");
         return;
     {
         DPRINT("Does not exist: %S\\%S\n", SourcePath.Buffer, L"unattend.inf");
         return;
@@ -4462,7 +4462,7 @@ BootLoaderFloppyPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)    /* ENTER */
         {
         }
         else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)    /* ENTER */
         {
-            if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE)
+            if (DoesFileExist(NULL, L"\\Device\\Floppy0", L"\\") == FALSE)
             {
                 MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
                 return BOOT_LOADER_FLOPPY_PAGE;
             {
                 MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
                 return BOOT_LOADER_FLOPPY_PAGE;
index 37cae20..53be28b 100644 (file)
@@ -39,8 +39,6 @@
 #include <winuser.h>
 #include <wincon.h>
 
 #include <winuser.h>
 #include <wincon.h>
 
-#include <strsafe.h>
-
 #define NTOS_MODE_USER
 #include <ndk/cmfuncs.h>
 #include <ndk/exfuncs.h>
 #define NTOS_MODE_USER
 #include <ndk/cmfuncs.h>
 #include <ndk/exfuncs.h>
@@ -52,6 +50,8 @@
 #include <ndk/rtlfuncs.h>
 #include <ndk/setypes.h>
 
 #include <ndk/rtlfuncs.h>
 #include <ndk/setypes.h>
 
+#include <ntstrsafe.h>
+
 /* Filesystem headers */
 #include <reactos/rosioctl.h>
 #include <fslib/vfatlib.h>
 /* Filesystem headers */
 #include <reactos/rosioctl.h>
 #include <fslib/vfatlib.h>