J Reece Wilson
2e5742dd2f
[*] Refactor IProcessSectionView::MapIPCMemory length type to machine word
285 lines
9.3 KiB
C++
285 lines
9.3 KiB
C++
/***
|
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: ProcessSectionView.NT.hpp
|
|
Date: 2022-08-09
|
|
Author: Reece
|
|
***/
|
|
#include <Source/RuntimeInternal.hpp>
|
|
#include "ProcessSectionView.NT.hpp"
|
|
#include "Process.hpp"
|
|
#include <Source/IO/FS/FileStream.NT.hpp>
|
|
#include "ProcessSectionFileMapView.NT.hpp"
|
|
#include <Source/IO/IPC/IPCHandle.hpp>
|
|
#include <Windows.h>
|
|
|
|
namespace Aurora::Process
|
|
{
|
|
AuSPtr<IProcessSectionMapView> ProcessSectionView::Allocate(AuUInt length)
|
|
{
|
|
HANDLE hFileMap;
|
|
|
|
if (!length)
|
|
{
|
|
SysPushErrorArg("invalid length");
|
|
return {};
|
|
}
|
|
|
|
hFileMap = ::CreateFileMappingA(INVALID_HANDLE_VALUE,
|
|
nullptr,
|
|
PAGE_READWRITE,
|
|
#if defined(AURORA_IS_64BIT)
|
|
AuBitsToHigher(length),
|
|
AuBitsToLower(length),
|
|
#else
|
|
0,
|
|
length,
|
|
#endif
|
|
nullptr);
|
|
if ((hFileMap == INVALID_HANDLE_VALUE) ||
|
|
(!hFileMap))
|
|
{
|
|
SysPushErrorIO("Couldn't create file map");
|
|
return {};
|
|
}
|
|
|
|
auto map = ::MapViewOfFile(hFileMap,
|
|
SECTION_MAP_READ | SECTION_MAP_WRITE,
|
|
0,
|
|
0,
|
|
length);
|
|
if (!map)
|
|
{
|
|
SysPushErrorIO("Couldn't create allocation of section");
|
|
AuWin32CloseHandle(hFileMap);
|
|
return {};
|
|
}
|
|
|
|
auto newObject = AuMakeShared<ProcessSectionFileMapView>(AuUInt(map), hFileMap);
|
|
if (!newObject)
|
|
{
|
|
SysPushErrorMem();
|
|
AuWin32CloseHandle(hFileMap);
|
|
return {};
|
|
}
|
|
|
|
return newObject;
|
|
}
|
|
|
|
AuSPtr<IProcessSectionMapView> ProcessSectionView::MapFileByPath(const AuString &str,
|
|
AuUInt64 offset,
|
|
AuUInt length,
|
|
AuFS::EFileOpenMode mode,
|
|
AuFS::EFileAdvisoryLockLevel sectionLock)
|
|
{
|
|
auto file = AuFS::OpenShared(str, mode, AuFS::EFileAdvisoryLockLevel::eNoSafety);
|
|
return file ? this->MapFileByObject(file, offset, length, mode, sectionLock) : AuSPtr<IProcessSectionMapView> {};
|
|
}
|
|
|
|
AuSPtr<IProcessSectionMapView> ProcessSectionView::MapFileByObject(const AuSPtr<AuFS::IFileStream> &stream,
|
|
AuUInt64 offset,
|
|
AuUInt length,
|
|
AuFS::EFileOpenMode mode,
|
|
AuFS::EFileAdvisoryLockLevel processLockLevel)
|
|
{
|
|
HANDLE hFileMap;
|
|
ULONG desiredAccess {}, pageAttributes {};
|
|
|
|
if (!stream)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
if (!length)
|
|
{
|
|
SysPushErrorArg("invalid length");
|
|
return {};
|
|
}
|
|
|
|
auto ok = AuStaticCast<AuFS::WinFileStream>(stream);
|
|
if (processLockLevel != AuFS::EFileAdvisoryLockLevel::eNoSafety)
|
|
{
|
|
DWORD dwFlags {};
|
|
OVERLAPPED overlapped {};
|
|
|
|
if (processLockLevel == AuFS::EFileAdvisoryLockLevel::eBlockReadWrite)
|
|
{
|
|
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
|
|
}
|
|
|
|
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
|
|
|
|
overlapped.Offset = AuBitsToLower(offset);
|
|
overlapped.OffsetHigh = AuBitsToHigher(offset);
|
|
|
|
if (!::LockFileEx(ok->GetHandle(),
|
|
dwFlags,
|
|
0,
|
|
AuBitsToLower(length),
|
|
AuBitsToHigher(length),
|
|
&overlapped))
|
|
{
|
|
SysPushErrorIO("No Lock");
|
|
return {};
|
|
}
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case AuFS::EFileOpenMode::eRead:
|
|
{
|
|
desiredAccess = SECTION_MAP_READ;
|
|
pageAttributes = PAGE_READONLY;
|
|
break;
|
|
}
|
|
case AuFS::EFileOpenMode::eWrite:
|
|
case AuFS::EFileOpenMode::eReadWrite:
|
|
{
|
|
desiredAccess = SECTION_MAP_READ | SECTION_MAP_WRITE;
|
|
pageAttributes = PAGE_READWRITE;
|
|
break;
|
|
}
|
|
default:
|
|
SysPushErrorGeneric();
|
|
return {};
|
|
};
|
|
|
|
hFileMap = ::CreateFileMappingA(ok->GetHandle(),
|
|
nullptr,
|
|
pageAttributes,
|
|
#if defined(AURORA_IS_64BIT)
|
|
AuBitsToHigher(length),
|
|
AuBitsToLower(length),
|
|
#else
|
|
0,
|
|
length,
|
|
#endif
|
|
nullptr);
|
|
if ((hFileMap == INVALID_HANDLE_VALUE) ||
|
|
(!hFileMap))
|
|
{
|
|
SysPushErrorIO("Couldn't create file map. Is the requeted access mode too high for the given object?");
|
|
return {};
|
|
}
|
|
|
|
auto map = ::MapViewOfFile(hFileMap,
|
|
desiredAccess,
|
|
AuBitsToHigher(offset),
|
|
AuBitsToLower(offset),
|
|
length);
|
|
if (!map)
|
|
{
|
|
SysPushErrorIO("Couldn't create map of section");
|
|
AuWin32CloseHandle(hFileMap);
|
|
return {};
|
|
}
|
|
|
|
auto newObject = AuMakeShared<ProcessSectionFileMapView>(AuUInt(map), hFileMap);
|
|
if (!newObject)
|
|
{
|
|
SysPushErrorMem();
|
|
AuWin32CloseHandle(hFileMap);
|
|
::UnmapViewOfFile(map);
|
|
return {};
|
|
}
|
|
|
|
return newObject;
|
|
}
|
|
|
|
AuSPtr<IProcessSectionMapView> ProcessSectionView::MapIPCMemory(const AuString &handleString,
|
|
AuUInt64 offset,
|
|
AuUInt length,
|
|
AuFS::EFileOpenMode mode)
|
|
{
|
|
AuIPC::IPCHandle handle;
|
|
HANDLE hFileMap;
|
|
ULONG desiredAccess {}, pageAttributes {};
|
|
|
|
if (!length)
|
|
{
|
|
SysPushErrorArg("invalid length");
|
|
return {};
|
|
}
|
|
|
|
if (!handle.FromString(handleString))
|
|
{
|
|
SysPushErrorParseError("{}", handleString);
|
|
return {};
|
|
}
|
|
|
|
auto token = handle.GetToken(AuIPC::EIPCHandleType::eIPCMemory, 0);
|
|
if (!token)
|
|
{
|
|
SysPushErrorParseError();
|
|
return {};
|
|
}
|
|
|
|
auto actualLength = token->token.word;
|
|
auto path = token->token.ToNTPath();
|
|
|
|
if (actualLength < offset + length)
|
|
{
|
|
SysPushErrorIO("Out of range");
|
|
return {};
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case AuFS::EFileOpenMode::eRead:
|
|
{
|
|
desiredAccess = SECTION_MAP_READ;
|
|
pageAttributes = PAGE_READONLY;
|
|
break;
|
|
}
|
|
case AuFS::EFileOpenMode::eWrite:
|
|
case AuFS::EFileOpenMode::eReadWrite:
|
|
{
|
|
desiredAccess = SECTION_MAP_READ | SECTION_MAP_WRITE;
|
|
pageAttributes = PAGE_READWRITE;
|
|
break;
|
|
}
|
|
default:
|
|
SysPushErrorGeneric();
|
|
return {};
|
|
};
|
|
|
|
hFileMap = ::OpenFileMappingA(desiredAccess,
|
|
FALSE,
|
|
path.c_str());
|
|
if ((hFileMap == INVALID_HANDLE_VALUE) ||
|
|
(!hFileMap))
|
|
{
|
|
SysPushErrorIO("Couldn't create IPC map (handle: {})", handleString);
|
|
return {};
|
|
}
|
|
|
|
auto map = ::MapViewOfFile(hFileMap,
|
|
desiredAccess,
|
|
AuBitsToHigher(offset),
|
|
AuBitsToLower(offset),
|
|
length);
|
|
if (!map)
|
|
{
|
|
SysPushErrorIO("Couldn't create map of IPC section (handle: {})", handleString);
|
|
AuWin32CloseHandle(hFileMap);
|
|
return {};
|
|
}
|
|
|
|
auto newObject = AuMakeShared<ProcessSectionFileMapView>(AuUInt(map), hFileMap);
|
|
if (!newObject)
|
|
{
|
|
SysPushErrorMem();
|
|
AuWin32CloseHandle(hFileMap);
|
|
::UnmapViewOfFile(map);
|
|
return {};
|
|
}
|
|
|
|
return newObject;
|
|
}
|
|
|
|
AUKN_SYM AuSPtr<IProcessSectionView> GetGlobalProcessSpace()
|
|
{
|
|
static ProcessSectionView gSingleton;
|
|
return AuUnsafeRaiiToShared(&gSingleton);
|
|
}
|
|
} |