From 92b99b865eca36e35662641f09680bb86ea2c5fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Tue, 23 May 2017 11:39:12 +0000 Subject: [PATCH] [SETUPLIB][USETUP] Move some code to the SetupLib. - filesup.c's functions ConcatPaths(), Does[Path|File]Exist(), NtPathToDiskPartComponents(), OpenAndMapFile(), UnMapFile(); - Move the inicache library to setuplib as it'll be used for the 1st stage GUI setup too (indeed, there is no good INI file API under Win32; the Win32 profile "API" is just good enough to manipulate the win16 ini files, and are here anyways for backward compatibility purposes only); - Move the OS detector too. - Remove the duplicated ConcatPaths() code in arcname.c. svn path=/branches/setup_improvements/; revision=74634 svn path=/branches/setup_improvements/; revision=74638 --- base/setup/lib/CMakeLists.txt | 3 + base/setup/lib/arcname.c | 136 ++++------ base/setup/lib/filesup.c | 372 +++++++++++++++++++++++++ base/setup/lib/filesup.h | 57 ++++ base/setup/{usetup => lib}/inicache.c | 31 +-- base/setup/{usetup => lib}/inicache.h | 27 +- base/setup/{usetup => lib}/osdetect.c | 15 +- base/setup/{usetup => lib}/osdetect.h | 4 + base/setup/lib/precomp.h | 5 +- base/setup/lib/setuplib.h | 3 + base/setup/usetup/CMakeLists.txt | 2 - base/setup/usetup/filesup.c | 375 +------------------------- base/setup/usetup/filesup.h | 57 ---- base/setup/usetup/usetup.h | 2 - 14 files changed, 520 insertions(+), 569 deletions(-) create mode 100644 base/setup/lib/filesup.c create mode 100644 base/setup/lib/filesup.h rename base/setup/{usetup => lib}/inicache.c (95%) rename base/setup/{usetup => lib}/inicache.h (64%) rename base/setup/{usetup => lib}/osdetect.c (99%) rename base/setup/{usetup => lib}/osdetect.h (97%) diff --git a/base/setup/lib/CMakeLists.txt b/base/setup/lib/CMakeLists.txt index a37be9d1fb6..6d687deb1af 100644 --- a/base/setup/lib/CMakeLists.txt +++ b/base/setup/lib/CMakeLists.txt @@ -1,9 +1,12 @@ list(APPEND SOURCE arcname.c + filesup.c fsutil.c genlist.c + inicache.c ntverrsrc.c + osdetect.c partlist.c precomp.h) diff --git a/base/setup/lib/arcname.c b/base/setup/lib/arcname.c index 60af00dbb12..f40b79173e5 100644 --- a/base/setup/lib/arcname.c +++ b/base/setup/lib/arcname.c @@ -23,6 +23,7 @@ #include "precomp.h" +#include "filesup.h" #include "partlist.h" #include "arcname.h" @@ -114,7 +115,7 @@ ArcGetNextTokenA( OUT PANSI_STRING TokenSpecifier, OUT PULONG Key) { - HRESULT hr; + NTSTATUS Status; PCSTR p = ArcPath; ULONG SpecifierLength; ULONG KeyValue; @@ -154,9 +155,10 @@ ArcGetNextTokenA( #endif /* We should have succeeded, copy the token specifier in the buffer */ - hr = StringCbCopyNA(TokenSpecifier->Buffer, TokenSpecifier->MaximumLength, - ArcPath, SpecifierLength); - if (FAILED(hr)) + Status = RtlStringCbCopyNA(TokenSpecifier->Buffer, + TokenSpecifier->MaximumLength, + ArcPath, SpecifierLength); + if (!NT_SUCCESS(Status)) return NULL; TokenSpecifier->Length = strlen(TokenSpecifier->Buffer) * sizeof(CHAR); @@ -174,7 +176,7 @@ ArcGetNextTokenU( OUT PUNICODE_STRING TokenSpecifier, OUT PULONG Key) { - HRESULT hr; + NTSTATUS Status; PCWSTR p = ArcPath; ULONG SpecifierLength; ULONG KeyValue; @@ -216,9 +218,10 @@ ArcGetNextTokenU( #endif /* We should have succeeded, copy the token specifier in the buffer */ - hr = StringCbCopyNW(TokenSpecifier->Buffer, TokenSpecifier->MaximumLength, - ArcPath, SpecifierLength); - if (FAILED(hr)) + Status = RtlStringCbCopyNW(TokenSpecifier->Buffer, + TokenSpecifier->MaximumLength, + ArcPath, SpecifierLength); + if (!NT_SUCCESS(Status)) return NULL; TokenSpecifier->Length = wcslen(TokenSpecifier->Buffer) * sizeof(WCHAR); @@ -298,7 +301,7 @@ ArcPathNormalize( OUT PUNICODE_STRING NormalizedArcPath, IN PCWSTR ArcPath) { - HRESULT hr; + NTSTATUS Status; PCWSTR EndOfArcName; PCWSTR p; @@ -315,24 +318,32 @@ ArcPathNormalize( while ((p = wcsstr(ArcPath, L"()")) && (p < EndOfArcName)) { #if 0 - hr = StringCbCopyNW(NormalizedArcPath->Buffer, NormalizedArcPath->MaximumLength, - ArcPath, (p - ArcPath) * sizeof(WCHAR)); + Status = RtlStringCbCopyNW(NormalizedArcPath->Buffer, + NormalizedArcPath->MaximumLength, + ArcPath, (p - ArcPath) * sizeof(WCHAR)); #else - hr = StringCbCatNW(NormalizedArcPath->Buffer, NormalizedArcPath->MaximumLength, - ArcPath, (p - ArcPath) * sizeof(WCHAR)); + Status = RtlStringCbCatNW(NormalizedArcPath->Buffer, + NormalizedArcPath->MaximumLength, + ArcPath, (p - ArcPath) * sizeof(WCHAR)); #endif - if (FAILED(hr)) + if (!NT_SUCCESS(Status)) return FALSE; - hr = StringCbCatW(NormalizedArcPath->Buffer, NormalizedArcPath->MaximumLength, L"(0)"); - if (FAILED(hr)) + + Status = RtlStringCbCatW(NormalizedArcPath->Buffer, + NormalizedArcPath->MaximumLength, + L"(0)"); + if (!NT_SUCCESS(Status)) return FALSE; #if 0 NormalizedArcPath->Buffer += wcslen(NormalizedArcPath->Buffer); #endif ArcPath = p + 2; } - hr = StringCbCatW(NormalizedArcPath->Buffer, NormalizedArcPath->MaximumLength, ArcPath); - if (FAILED(hr)) + + Status = RtlStringCbCatW(NormalizedArcPath->Buffer, + NormalizedArcPath->MaximumLength, + ArcPath); + if (!NT_SUCCESS(Status)) return FALSE; NormalizedArcPath->Length = wcslen(NormalizedArcPath->Buffer) * sizeof(WCHAR); @@ -450,7 +461,7 @@ ResolveArcNameManually( IN OUT PCWSTR* ArcNamePath, IN PPARTLIST PartList OPTIONAL) { - HRESULT hr; + NTSTATUS Status; WCHAR TokenBuffer[50]; UNICODE_STRING Token; PCWSTR p, q; @@ -525,7 +536,8 @@ ResolveArcNameManually( return STATUS_NOT_SUPPORTED; } - hr = StringCbPrintfW(NtName->Buffer, NtName->MaximumLength, L"\\Device\\Ramdisk%lu", AdapterKey); + Status = RtlStringCbPrintfW(NtName->Buffer, NtName->MaximumLength, + L"\\Device\\Ramdisk%lu", AdapterKey); goto Quit; } } @@ -644,14 +656,23 @@ ResolveArcNameManually( if (ControllerType == CdRomController) // and so, AdapterType == ScsiAdapter and PeripheralType == FDiskPeripheral - hr = StringCbPrintfW(NtName->Buffer, NtName->MaximumLength, L"\\Device\\Scsi\\CdRom%lu", ControllerKey); + { + Status = RtlStringCbPrintfW(NtName->Buffer, NtName->MaximumLength, + L"\\Device\\Scsi\\CdRom%lu", ControllerKey); + } else /* Now, ControllerType == DiskController */ if (PeripheralType == CdRomPeripheral) - hr = StringCbPrintfW(NtName->Buffer, NtName->MaximumLength, L"\\Device\\CdRom%lu", PeripheralKey); + { + Status = RtlStringCbPrintfW(NtName->Buffer, NtName->MaximumLength, + L"\\Device\\CdRom%lu", PeripheralKey); + } else if (PeripheralType == FDiskPeripheral) - hr = StringCbPrintfW(NtName->Buffer, NtName->MaximumLength, L"\\Device\\Floppy%lu", PeripheralKey); + { + Status = RtlStringCbPrintfW(NtName->Buffer, NtName->MaximumLength, + L"\\Device\\Floppy%lu", PeripheralKey); + } else if (PeripheralType == RDiskPeripheral) { @@ -676,78 +697,30 @@ ResolveArcNameManually( ASSERT(PartEntry->DiskEntry == DiskEntry); } - hr = StringCbPrintfW(NtName->Buffer, NtName->MaximumLength, L"\\Device\\Harddisk%lu\\Partition%lu", - DiskEntry->DiskNumber, PartitionNumber); + Status = RtlStringCbPrintfW(NtName->Buffer, NtName->MaximumLength, + L"\\Device\\Harddisk%lu\\Partition%lu", + DiskEntry->DiskNumber, PartitionNumber); } #if 0 else if (PeripheralType == VDiskPeripheral) { // TODO: Check how Win 7+ deals with virtual disks. - hr = StringCbPrintfW(NtName->Buffer, NtName->MaximumLength, L"\\Device\\VirtualHarddisk%lu\\Partition%lu", - PeripheralKey, PartitionNumber); + Status = RtlStringCbPrintfW(NtName->Buffer, NtName->MaximumLength, + L"\\Device\\VirtualHarddisk%lu\\Partition%lu", + PeripheralKey, PartitionNumber); } #endif Quit: - if (FAILED(hr)) - { - /* - * We can directly cast the HRESULTs into NTSTATUS since the error codes - * returned by StringCbPrintfW: - * STRSAFE_E_INVALID_PARAMETER == 0x80070057, - * STRSAFE_E_INSUFFICIENT_BUFFER == 0x8007007a, - * do not have assigned values in the NTSTATUS space. - */ - return (NTSTATUS)hr; - } + if (!NT_SUCCESS(Status)) + return Status; *ArcNamePath = p; return STATUS_SUCCESS; } -/**** FIXME: Redundant with filesup.c ! ****\ -|** (but filesup.c is not yet included in **| -\** setuplib, hence this code copy) **/ - -static -HRESULT -ConcatPaths( - IN OUT PWSTR PathElem1, - IN SIZE_T cchPathSize, - IN PCWSTR PathElem2 OPTIONAL) -{ - HRESULT hr; - SIZE_T cchPathLen; - - if (!PathElem2) - return S_OK; - if (cchPathSize <= 1) - return S_OK; - - 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 '\' */ - hr = StringCchCatW(PathElem1, cchPathSize, L"\\"); - if (FAILED(hr)) - return hr; - } - 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 - } - hr = StringCchCatW(PathElem1, cchPathSize, PathElem2); - return hr; -} - -/*******************************************/ - - BOOLEAN ArcPathToNtPath( OUT PUNICODE_STRING NtPath, @@ -825,9 +798,8 @@ ArcPathToNtPath( */ if (BeginOfPath && *BeginOfPath) { - HRESULT hr; - hr = ConcatPaths(NtPath->Buffer, NtPath->MaximumLength / sizeof(WCHAR), BeginOfPath); - if (FAILED(hr)) + Status = ConcatPaths(NtPath->Buffer, NtPath->MaximumLength / sizeof(WCHAR), BeginOfPath); + if (!NT_SUCCESS(Status)) { /* Buffer not large enough, or whatever...: just bail out */ return FALSE; diff --git a/base/setup/lib/filesup.c b/base/setup/lib/filesup.c new file mode 100644 index 00000000000..75509058954 --- /dev/null +++ b/base/setup/lib/filesup.c @@ -0,0 +1,372 @@ +/* + * PROJECT: ReactOS Setup Library + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: File support functions. + * COPYRIGHT: Copyright 2017-2018 Hermes Belusca-Maito + */ + +/* INCLUDES *****************************************************************/ + +#include "precomp.h" + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ +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( + 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]; + + 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); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + 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); +} + +/* + * 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 && *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 && *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, + IN PCWSTR PathName OPTIONAL, + IN PCWSTR FileName, // OPTIONAL + OUT PHANDLE FileHandle, // IN OUT PHANDLE OPTIONAL + OUT PHANDLE SectionHandle, + OUT PVOID* BaseAddress, + OUT PULONG FileSize OPTIONAL) +{ + 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)) + { + DPRINT1("Failed to open file '%wZ', Status 0x%08lx\n", &Name, Status); + 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 */ + 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/lib/filesup.h b/base/setup/lib/filesup.h new file mode 100644 index 00000000000..bf5a2835f2f --- /dev/null +++ b/base/setup/lib/filesup.h @@ -0,0 +1,57 @@ +/* + * PROJECT: ReactOS Setup Library + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: File support functions. + * COPYRIGHT: Copyright 2017-2018 Hermes Belusca-Maito + */ + +#pragma once + +#if 0 + +BOOLEAN +IsValidPath( + IN PCWSTR InstallDir); + +#endif + +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( + IN HANDLE RootDirectory OPTIONAL, + 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, + IN PCWSTR PathName OPTIONAL, + IN PCWSTR FileName, // OPTIONAL + OUT PHANDLE FileHandle, // IN OUT PHANDLE OPTIONAL + OUT PHANDLE SectionHandle, + OUT PVOID* BaseAddress, + OUT PULONG FileSize OPTIONAL); + +BOOLEAN +UnMapFile( + IN HANDLE SectionHandle, + IN PVOID BaseAddress); + +/* EOF */ diff --git a/base/setup/usetup/inicache.c b/base/setup/lib/inicache.c similarity index 95% rename from base/setup/usetup/inicache.c rename to base/setup/lib/inicache.c index 38dd44fefd2..295d9570577 100644 --- a/base/setup/usetup/inicache.c +++ b/base/setup/lib/inicache.c @@ -1,32 +1,15 @@ /* - * ReactOS kernel - * Copyright (C) 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS text-mode setup - * FILE: base/setup/usetup/inicache.c - * PURPOSE: INI file parser that caches contents of INI file in memory - * PROGRAMMER: Royce Mitchell III + * PROJECT: ReactOS Setup Library + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: INI file parser that caches contents of INI file in memory. + * COPYRIGHT: Copyright 2002-2018 Royce Mitchell III */ /* INCLUDES *****************************************************************/ -#include "usetup.h" +#include "precomp.h" + +#include "inicache.h" #define NDEBUG #include diff --git a/base/setup/usetup/inicache.h b/base/setup/lib/inicache.h similarity index 64% rename from base/setup/usetup/inicache.h rename to base/setup/lib/inicache.h index 33db2a38e97..d9b7a3d2883 100644 --- a/base/setup/usetup/inicache.h +++ b/base/setup/lib/inicache.h @@ -1,27 +1,8 @@ /* - * ReactOS kernel - * Copyright (C) 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS text-mode setup - * FILE: base/setup/usetup/inicache.h - * PURPOSE: INI file parser that caches contents of INI file in memory - * PROGRAMMER: Royce Mitchell III + * PROJECT: ReactOS Setup Library + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: INI file parser that caches contents of INI file in memory. + * COPYRIGHT: Copyright 2002-2018 Royce Mitchell III */ #pragma once diff --git a/base/setup/usetup/osdetect.c b/base/setup/lib/osdetect.c similarity index 99% rename from base/setup/usetup/osdetect.c rename to base/setup/lib/osdetect.c index 97cc6430ea7..a695da7466a 100644 --- a/base/setup/usetup/osdetect.c +++ b/base/setup/lib/osdetect.c @@ -6,7 +6,18 @@ * COPYRIGHT: Copyright 2017-2018 Hermes Belusca-Maito */ -#include "usetup.h" +/* INCLUDES *****************************************************************/ + +#include "precomp.h" + +#include "ntverrsrc.h" +// #include "arcname.h" +#include "filesup.h" +#include "genlist.h" +#include "inicache.h" +#include "partlist.h" +#include "arcname.h" +#include "osdetect.h" // HACK! #include @@ -17,8 +28,6 @@ /* GLOBALS ******************************************************************/ -extern PPARTLIST PartitionList; - /* Language-independent Vendor strings */ static const PCWSTR KnownVendors[] = { L"ReactOS", L"Microsoft" }; diff --git a/base/setup/usetup/osdetect.h b/base/setup/lib/osdetect.h similarity index 97% rename from base/setup/usetup/osdetect.h rename to base/setup/lib/osdetect.h index 50767840863..b20fc427b78 100644 --- a/base/setup/usetup/osdetect.h +++ b/base/setup/lib/osdetect.h @@ -6,6 +6,8 @@ * COPYRIGHT: Copyright 2017-2018 Hermes Belusca-Maito */ +#pragma once + typedef struct _NTOS_INSTALLATION { LIST_ENTRY ListEntry; @@ -24,3 +26,5 @@ typedef struct _NTOS_INSTALLATION PGENERIC_LIST CreateNTOSInstallationsList( IN PPARTLIST List); + +/* EOF */ diff --git a/base/setup/lib/precomp.h b/base/setup/lib/precomp.h index ea82da4f39c..0ce5c12e093 100644 --- a/base/setup/lib/precomp.h +++ b/base/setup/lib/precomp.h @@ -16,8 +16,6 @@ #include #include -#include - #define NTOS_MODE_USER #include #include @@ -29,6 +27,9 @@ #include #include +#include + + /* Filesystem headers */ #include // For extra partition IDs diff --git a/base/setup/lib/setuplib.h b/base/setup/lib/setuplib.h index 055ed5eef71..a53fc3cb2d8 100644 --- a/base/setup/lib/setuplib.h +++ b/base/setup/lib/setuplib.h @@ -29,9 +29,12 @@ extern HANDLE ProcessHeap; #include "linklist.h" #include "ntverrsrc.h" // #include "arcname.h" +#include "filesup.h" #include "fsutil.h" #include "genlist.h" +#include "inicache.h" #include "partlist.h" #include "arcname.h" +#include "osdetect.h" /* EOF */ diff --git a/base/setup/usetup/CMakeLists.txt b/base/setup/usetup/CMakeLists.txt index 714182e7e77..13aea12e163 100644 --- a/base/setup/usetup/CMakeLists.txt +++ b/base/setup/usetup/CMakeLists.txt @@ -24,10 +24,8 @@ list(APPEND SOURCE fslist.c genlist.c inffile.c - inicache.c keytrans.c mui.c - osdetect.c partlist.c progress.c registry.c diff --git a/base/setup/usetup/filesup.c b/base/setup/usetup/filesup.c index b466e4e38d8..6094ba3365d 100644 --- a/base/setup/usetup/filesup.c +++ b/base/setup/usetup/filesup.c @@ -1,22 +1,5 @@ /* - * ReactOS kernel - * Copyright (C) 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* COPYRIGHT: See COPYING in the top level directory + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS text-mode setup * FILE: base/setup/usetup/filesup.c * PURPOSE: File support functions @@ -520,360 +503,4 @@ IsValidPath( 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( - 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]; - - 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); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - 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); -} - -/* - * 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 && *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 && *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, - IN PCWSTR PathName OPTIONAL, - IN PCWSTR FileName, // OPTIONAL - OUT PHANDLE FileHandle, // IN OUT PHANDLE OPTIONAL - OUT PHANDLE SectionHandle, - OUT PVOID* BaseAddress, - OUT PULONG FileSize OPTIONAL) -{ - 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)) - { - DPRINT1("Failed to open file '%wZ', Status 0x%08lx\n", &Name, Status); - 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 */ - 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 87ab8354fe3..5c2c296ecfd 100644 --- a/base/setup/usetup/filesup.h +++ b/base/setup/usetup/filesup.h @@ -1,21 +1,3 @@ -/* - * ReactOS kernel - * Copyright (C) 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS text-mode setup @@ -46,43 +28,4 @@ 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( - IN HANDLE RootDirectory OPTIONAL, - 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, - IN PCWSTR PathName OPTIONAL, - IN PCWSTR FileName, // OPTIONAL - OUT PHANDLE FileHandle, // IN OUT PHANDLE OPTIONAL - OUT PHANDLE SectionHandle, - OUT PVOID* BaseAddress, - OUT PULONG FileSize OPTIONAL); - -BOOLEAN -UnMapFile( - IN HANDLE SectionHandle, - IN PVOID BaseAddress); - /* EOF */ diff --git a/base/setup/usetup/usetup.h b/base/setup/usetup/usetup.h index aed5dcec4c7..eeb11545b49 100644 --- a/base/setup/usetup/usetup.h +++ b/base/setup/usetup/usetup.h @@ -60,7 +60,6 @@ /* Internal Headers */ #include "consup.h" #include "inffile.h" -#include "inicache.h" #include "progress.h" #include "infros.h" #include "filequeue.h" @@ -70,7 +69,6 @@ #include "cabinet.h" #include "filesup.h" #include "genlist.h" -#include "osdetect.h" #include "mui.h" extern HANDLE ProcessHeap;