From 147b4aa7e5278287e235cad1849e0d9dd0d5a0f0 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Tue, 5 May 2020 09:48:39 +0200 Subject: Added option to open named section --- src/FileStream.cpp | 122 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 91 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/FileStream.cpp b/src/FileStream.cpp index 43a5f4f..a492e66 100644 --- a/src/FileStream.cpp +++ b/src/FileStream.cpp @@ -434,54 +434,114 @@ static void BaseFile_Init(TFileStream * pStream) //----------------------------------------------------------------------------- // Local functions - base memory-mapped file support -static bool BaseMap_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags) +#ifdef PLATFORM_WINDOWS + +typedef struct _SECTION_BASIC_INFORMATION +{ + PVOID BaseAddress; + ULONG Attributes; + LARGE_INTEGER Size; +} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; + +typedef ULONG (WINAPI * NTQUERYSECTION)( + IN HANDLE SectionHandle, + IN ULONG SectionInformationClass, + OUT PVOID SectionInformation, + IN SIZE_T Length, + OUT PSIZE_T ResultLength); + +static bool RetrieveFileMappingSize(HANDLE hSection, ULARGE_INTEGER & RefFileSize) +{ + SECTION_BASIC_INFORMATION BasicInfo = {0}; + NTQUERYSECTION PfnQuerySection; + HMODULE hNtdll; + SIZE_T ReturnLength = 0; + + if((hNtdll = GetModuleHandle(_T("ntdll.dll"))) != NULL) + { + PfnQuerySection = (NTQUERYSECTION)GetProcAddress(hNtdll, "NtQuerySection"); + if(PfnQuerySection != NULL) + { + if(PfnQuerySection(hSection, 0, &BasicInfo, sizeof(SECTION_BASIC_INFORMATION), &ReturnLength) == 0) + { + RefFileSize.HighPart = BasicInfo.Size.HighPart; + RefFileSize.LowPart = BasicInfo.Size.LowPart; + return true; + } + } + } + + return false; +} +#endif + +static bool BaseMap_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStreamFlags) { #ifdef PLATFORM_WINDOWS - ULARGE_INTEGER FileSize; - HANDLE hFile; - HANDLE hMap; + ULARGE_INTEGER FileSize = {0}; + HANDLE hFile = INVALID_HANDLE_VALUE; + HANDLE hMap = NULL; bool bResult = false; // Keep compiler happy dwStreamFlags = dwStreamFlags; - // Open the file for read access - hFile = CreateFile(szFileName, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if(hFile != INVALID_HANDLE_VALUE) + // 1) Try to treat "szFileName" as a section name + hMap = OpenFileMapping(SECTION_QUERY | FILE_MAP_READ, FALSE, szFileName); + if(hMap != NULL) { - // Retrieve file size. Don't allow mapping file of a zero size. - FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart); - if(FileSize.QuadPart != 0) + // Try to retrieve the size of the mapping + if(!RetrieveFileMappingSize(hMap, FileSize)) { - // Now create mapping object - hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - if(hMap != NULL) + CloseHandle(hMap); + hMap = NULL; + } + } + + // 2) Treat the name as file name + else + { + hFile = CreateFile(szFileName, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if(hFile != INVALID_HANDLE_VALUE) + { + // Retrieve file size. Don't allow mapping file of a zero size. + FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart); + if(FileSize.QuadPart != 0) { - // Map the entire view into memory - // Note that this operation will fail if the file can't fit - // into usermode address space - pStream->Base.Map.pbFile = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); - if(pStream->Base.Map.pbFile != NULL) - { - // Retrieve file time - GetFileTime(hFile, NULL, NULL, (LPFILETIME)&pStream->Base.Map.FileTime); + // Now create file mapping over the file + hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + } + } + } - // Retrieve file size and position - pStream->Base.Map.FileSize = FileSize.QuadPart; - pStream->Base.Map.FilePos = 0; - bResult = true; - } + // Did it succeed? + if(hMap != NULL) + { + // Map the entire view into memory + // Note that this operation will fail if the file can't fit + // into usermode address space + pStream->Base.Map.pbFile = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); + if(pStream->Base.Map.pbFile != NULL) + { + // Retrieve file time. If it's named section, put 0 + if(hFile != INVALID_HANDLE_VALUE) + GetFileTime(hFile, NULL, NULL, (LPFILETIME)&pStream->Base.Map.FileTime); - // Close the map handle - CloseHandle(hMap); - } + // Retrieve file size and position + pStream->Base.Map.FileSize = FileSize.QuadPart; + pStream->Base.Map.FilePos = 0; + bResult = true; } - // Close the file handle - CloseHandle(hFile); + // Close the map handle + CloseHandle(hMap); } + // Close the file handle + if(hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + // If the file is not there and is not available for random access, // report error if(bResult == false) -- cgit v1.2.3