reactos/base/setup/usetup/filesup.c
Hermès Bélusca-Maïto 38e988ace7
[USETUP] Improve the FileSup module.
- 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
2018-05-27 20:18:53 +02:00

892 lines
27 KiB
C

/*
* 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/filesup.c
* PURPOSE: File support functions
* PROGRAMMER: Eric Kohl
* Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
/* INCLUDES *****************************************************************/
#include "usetup.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
static BOOLEAN HasCurrentCabinet = FALSE;
static WCHAR CurrentCabinetName[MAX_PATH];
static CAB_SEARCH Search;
static
NTSTATUS
SetupCreateSingleDirectory(
PWCHAR DirectoryName)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING PathName;
HANDLE DirectoryHandle;
NTSTATUS Status;
if(!RtlCreateUnicodeString(&PathName, DirectoryName))
return STATUS_NO_MEMORY;
if (PathName.Length > sizeof(WCHAR) &&
PathName.Buffer[PathName.Length / sizeof(WCHAR) - 2] == L'\\' &&
PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'.')
{
PathName.Length -= sizeof(WCHAR);
PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
}
if (PathName.Length > sizeof(WCHAR) &&
PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'\\')
{
PathName.Length -= sizeof(WCHAR);
PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
}
InitializeObjectAttributes(&ObjectAttributes,
&PathName,
OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
NULL,
NULL);
Status = NtCreateFile(&DirectoryHandle,
DIRECTORY_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_DIRECTORY_FILE,
NULL,
0);
if (NT_SUCCESS(Status))
{
NtClose(DirectoryHandle);
}
RtlFreeUnicodeString(&PathName);
return Status;
}
NTSTATUS
SetupCreateDirectory(
PWCHAR PathName)
{
PWCHAR PathBuffer = NULL;
PWCHAR Ptr, EndPtr;
ULONG BackslashCount;
ULONG Size;
NTSTATUS Status = STATUS_SUCCESS;
Size = (wcslen(PathName) + 1) * sizeof(WCHAR);
PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Size);
if (PathBuffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
wcscpy(PathBuffer, PathName);
EndPtr = PathBuffer + wcslen(PathName);
Ptr = PathBuffer;
/* Skip the '\Device\HarddiskX\PartitionY\ part */
BackslashCount = 0;
while (Ptr < EndPtr && BackslashCount < 4)
{
if (*Ptr == L'\\')
BackslashCount++;
Ptr++;
}
while (Ptr < EndPtr)
{
if (*Ptr == L'\\')
{
*Ptr = 0;
DPRINT("PathBuffer: %S\n", PathBuffer);
if (!DoesPathExist(NULL, PathBuffer))
{
DPRINT("Create: %S\n", PathBuffer);
Status = SetupCreateSingleDirectory(PathBuffer);
if (!NT_SUCCESS(Status))
goto done;
}
*Ptr = L'\\';
}
Ptr++;
}
if (!DoesPathExist(NULL, PathBuffer))
{
DPRINT("Create: %S\n", PathBuffer);
Status = SetupCreateSingleDirectory(PathBuffer);
if (!NT_SUCCESS(Status))
goto done;
}
done:
DPRINT("Done.\n");
if (PathBuffer != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
return Status;
}
NTSTATUS
SetupCopyFile(
PWCHAR SourceFileName,
PWCHAR DestinationFileName)
{
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE FileHandleSource;
HANDLE FileHandleDest;
static IO_STATUS_BLOCK IoStatusBlock;
FILE_STANDARD_INFORMATION FileStandard;
FILE_BASIC_INFORMATION FileBasic;
ULONG RegionSize;
UNICODE_STRING FileName;
NTSTATUS Status;
PVOID SourceFileMap = 0;
HANDLE SourceFileSection;
SIZE_T SourceSectionSize = 0;
LARGE_INTEGER ByteOffset;
RtlInitUnicodeString(&FileName,
SourceFileName);
InitializeObjectAttributes(&ObjectAttributes,
&FileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(&FileHandleSource,
GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ,
FILE_SEQUENTIAL_ONLY);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName);
goto done;
}
Status = NtQueryInformationFile(FileHandleSource,
&IoStatusBlock,
&FileStandard,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtQueryInformationFile failed: %x\n", Status);
goto closesrc;
}
Status = NtQueryInformationFile(FileHandleSource,
&IoStatusBlock,&FileBasic,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtQueryInformationFile failed: %x\n", Status);
goto closesrc;
}
Status = NtCreateSection(&SourceFileSection,
SECTION_MAP_READ,
NULL,
NULL,
PAGE_READONLY,
SEC_COMMIT,
FileHandleSource);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateSection failed: %x, %S\n", Status, SourceFileName);
goto closesrc;
}
Status = NtMapViewOfSection(SourceFileSection,
NtCurrentProcess(),
&SourceFileMap,
0,
0,
NULL,
&SourceSectionSize,
ViewUnmap,
0,
PAGE_READONLY );
if (!NT_SUCCESS(Status))
{
DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status, SourceFileName);
goto closesrcsec;
}
RtlInitUnicodeString(&FileName,
DestinationFileName);
InitializeObjectAttributes(&ObjectAttributes,
&FileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtCreateFile(&FileHandleDest,
GENERIC_WRITE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OVERWRITE_IF,
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SEQUENTIAL_ONLY |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (!NT_SUCCESS(Status))
{
/* Open may have failed because the file to overwrite
* is in readonly mode
*/
if (Status == STATUS_ACCESS_DENIED)
{
FILE_BASIC_INFORMATION FileBasicInfo;
/* Reattempt to open it with limited access */
Status = NtCreateFile(&FileHandleDest,
FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SEQUENTIAL_ONLY |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
/* Fail for real if we cannot open it that way */
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName);
goto unmapsrcsec;
}
/* Zero our basic info, just to set attributes */
RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
/* Reset attributes to normal, no read-only */
FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
/* We basically don't care about whether it succeed:
* if it didn't, later open will fail
*/
NtSetInformationFile(FileHandleDest, &IoStatusBlock, &FileBasicInfo,
sizeof(FileBasicInfo), FileBasicInformation);
/* Close file */
NtClose(FileHandleDest);
/* And re-attempt overwrite */
Status = NtCreateFile(&FileHandleDest,
GENERIC_WRITE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OVERWRITE_IF,
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SEQUENTIAL_ONLY |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
}
/* We failed */
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName);
goto unmapsrcsec;
}
}
RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
IoStatusBlock.Status = 0;
ByteOffset.QuadPart = 0ULL;
Status = NtWriteFile(FileHandleDest,
NULL,
NULL,
NULL,
&IoStatusBlock,
SourceFileMap,
RegionSize,
&ByteOffset,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize);
goto closedest;
}
/* Copy file date/time from source file */
Status = NtSetInformationFile(FileHandleDest,
&IoStatusBlock,
&FileBasic,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtSetInformationFile failed: %x\n", Status);
goto closedest;
}
/* shorten the file back to it's real size after completing the write */
Status = NtSetInformationFile(FileHandleDest,
&IoStatusBlock,
&FileStandard.EndOfFile,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtSetInformationFile failed: %x\n", Status);
}
closedest:
NtClose(FileHandleDest);
unmapsrcsec:
NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap);
closesrcsec:
NtClose(SourceFileSection);
closesrc:
NtClose(FileHandleSource);
done:
return Status;
}
NTSTATUS
SetupExtractFile(
PWCHAR CabinetFileName,
PWCHAR SourceFileName,
PWCHAR DestinationPathName)
{
ULONG CabStatus;
DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
CabinetFileName, SourceFileName, DestinationPathName);
if (HasCurrentCabinet)
{
DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName);
}
if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0))
{
DPRINT("Using same cabinet as last time\n");
/* Use our last location because the files should be sequential */
CabStatus = CabinetFindNextFileSequential(SourceFileName, &Search);
if (CabStatus != CAB_STATUS_SUCCESS)
{
DPRINT("Sequential miss on file: %S\n", SourceFileName);
/* Looks like we got unlucky */
CabStatus = CabinetFindFirst(SourceFileName, &Search);
}
}
else
{
DPRINT("Using new cabinet\n");
if (HasCurrentCabinet)
{
CabinetCleanup();
}
wcscpy(CurrentCabinetName, CabinetFileName);
CabinetInitialize();
CabinetSetEventHandlers(NULL, NULL, NULL);
CabinetSetCabinetName(CabinetFileName);
CabStatus = CabinetOpen();
if (CabStatus == CAB_STATUS_SUCCESS)
{
DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
HasCurrentCabinet = TRUE;
}
else
{
DPRINT("Cannot open cabinet (%d)\n", CabStatus);
return STATUS_UNSUCCESSFUL;
}
/* We have to start at the beginning here */
CabStatus = CabinetFindFirst(SourceFileName, &Search);
}
if (CabStatus != CAB_STATUS_SUCCESS)
{
DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName, CabinetGetCabinetName());
return STATUS_UNSUCCESSFUL;
}
CabinetSetDestinationPath(DestinationPathName);
CabStatus = CabinetExtractFile(&Search);
if (CabStatus != CAB_STATUS_SUCCESS)
{
DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
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 (iswspace(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(
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)
{
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,
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 */