Add FileMapper.hpp

This commit is contained in:
Double Sine 2019-01-14 15:13:44 +08:00
parent 818a1d28e9
commit dca49e73e5
No known key found for this signature in database
GPG Key ID: 44460E4F43EA8633

View File

@ -0,0 +1,96 @@
#include "Exceptions.hpp"
#include "ResourceGuardWin32.hpp"
#include <string>
#include <utility>
#if defined(UNICODE) || defined(_UNICODE)
using String = std::wstring;
#else
using String = std::string;
#endif
namespace Patcher {
class FileMapper {
private:
ResourceGuard<FileHandleTraits> _FileHandle;
ResourceGuard<GenericHandleTraits> _FileMapHandle;
ResourceGuard<MapViewTraits> _FileView;
public:
static bool IsExist(const String&& FilePath) {
DWORD dwAttr = GetFileAttributes(FilePath.c_str());
if (dwAttr == INVALID_FILE_ATTRIBUTES) {
if (GetLastError() == ERROR_FILE_NOT_FOUND)
return false;
else
throw SystemError(__BASE_FILE__, __LINE__, GetLastError(),
"GetFileAttributes fails.");
} else {
return (dwAttr & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
}
template<typename _Type>
_Type* GetView() const noexcept {
return reinterpret_cast<_Type*>(_FileView.GetHandle());
}
void MapFile(const String& FileName) noexcept {
ResourceGuard<FileHandleTraits> TempFileHandle;
ResourceGuard<GenericHandleTraits> TempFileMapHandle;
ResourceGuard<MapViewTraits> TempFileView;
TempFileHandle.TakeHoldOf(
CreateFile(FileName.c_str(),
GENERIC_READ | GENERIC_WRITE,
NULL,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)
);
if (TempFileHandle.IsValid() == false)
throw SystemError(__BASE_FILE__, __LINE__, GetLastError(),
"CreateFile fails.");
TempFileMapHandle.TakeHoldOf(
CreateFileMapping(TempFileHandle,
NULL,
PAGE_READWRITE,
0,
0,
NULL)
);
if (TempFileMapHandle.IsValid() == false)
throw SystemError(__BASE_FILE__, __LINE__, GetLastError(),
"CreateFileMapping fails.");
TempFileView.TakeHoldOf(
MapViewOfFile(TempFileMapHandle,
FILE_MAP_READ | FILE_MAP_WRITE,
0,
0,
0)
);
if (TempFileView.IsValid() == false)
throw SystemError(__BASE_FILE__, __LINE__, GetLastError(),
"MapViewOfFile fails.");
_FileView.Release();
_FileView = std::move(TempFileView);
_FileMapHandle.Release();
_FileMapHandle = std::move(TempFileMapHandle);
_FileHandle.Release();
_FileHandle = std::move(TempFileHandle);
}
void Release() {
_FileView.Release();
_FileMapHandle.Release();
_FileHandle.Release();
}
};
}