From 60532e9c4394b0ee7860a1fda2f6cc2435be610b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sat, 13 May 2017 16:13:49 +0000 Subject: [PATCH] [USETUP] Add & modify some file utility functions that are going to be used next. - 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 | 14 +- base/setup/usetup/filesup.c | 357 +++++++++++++++++++++++++----------- base/setup/usetup/filesup.h | 35 +++- base/setup/usetup/usetup.c | 4 +- base/setup/usetup/usetup.h | 4 +- 5 files changed, 293 insertions(+), 121 deletions(-) diff --git a/base/setup/usetup/bootsup.c b/base/setup/usetup/bootsup.c index 75319fba950..674808ace77 100644 --- a/base/setup/usetup/bootsup.c +++ b/base/setup/usetup/bootsup.c @@ -2275,7 +2275,7 @@ InstallFatBootcodeToPartition( 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' */ @@ -2292,8 +2292,8 @@ InstallFatBootcodeToPartition( /* 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"); @@ -2375,8 +2375,8 @@ InstallFatBootcodeToPartition( 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"); @@ -2390,7 +2390,7 @@ InstallFatBootcodeToPartition( 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"); @@ -2529,7 +2529,7 @@ InstallExt2BootcodeToPartition( 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' */ diff --git a/base/setup/usetup/filesup.c b/base/setup/usetup/filesup.c index 568525d095c..293e590b767 100644 --- a/base/setup/usetup/filesup.c +++ b/base/setup/usetup/filesup.c @@ -93,90 +93,6 @@ SetupCreateSingleDirectory( 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) @@ -214,7 +130,7 @@ SetupCreateDirectory( *Ptr = 0; DPRINT("PathBuffer: %S\n", PathBuffer); - if (!DoesPathExist(PathBuffer)) + if (!DoesPathExist(NULL, PathBuffer)) { DPRINT("Create: %S\n", PathBuffer); Status = SetupCreateSingleDirectory(PathBuffer); @@ -228,7 +144,7 @@ SetupCreateDirectory( Ptr++; } - if (!DoesPathExist(PathBuffer)) + if (!DoesPathExist(NULL, PathBuffer)) { DPRINT("Create: %S\n", PathBuffer); Status = SetupCreateSingleDirectory(PathBuffer); @@ -244,7 +160,6 @@ done: return Status; } - 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( - 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]; - 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, - NULL, + RootDirectory, 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)) { - 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 */ diff --git a/base/setup/usetup/filesup.h b/base/setup/usetup/filesup.h index e09a08c673b..492dff0e87f 100644 --- a/base/setup/usetup/filesup.h +++ b/base/setup/usetup/filesup.h @@ -41,13 +41,40 @@ SetupExtractFile( 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( - 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 -IsValidPath( - PWCHAR InstallDir); +UnMapFile( + IN HANDLE SectionHandle, + IN PVOID BaseAddress); /* EOF */ diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c index 8c808122655..234bfa45be6 100644 --- a/base/setup/usetup/usetup.c +++ b/base/setup/usetup/usetup.c @@ -424,7 +424,7 @@ CheckUnattendedSetup(VOID) 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; @@ -4462,7 +4462,7 @@ BootLoaderFloppyPage(PINPUT_RECORD Ir) } 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; diff --git a/base/setup/usetup/usetup.h b/base/setup/usetup/usetup.h index 37cae20f7fa..53be28b3dc5 100644 --- a/base/setup/usetup/usetup.h +++ b/base/setup/usetup/usetup.h @@ -39,8 +39,6 @@ #include #include -#include - #define NTOS_MODE_USER #include #include @@ -52,6 +50,8 @@ #include #include +#include + /* Filesystem headers */ #include #include -- 2.17.1