diff options
Diffstat (limited to 'src/FileStream.cpp')
-rw-r--r-- | src/FileStream.cpp | 122 |
1 files changed, 91 insertions, 31 deletions
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)
|