130 lines
3.8 KiB
C++
130 lines
3.8 KiB
C++
//
|
|
// Created by DaLaw2 on 2026/1/3.
|
|
//
|
|
|
|
#include <format>
|
|
#include <stdexcept>
|
|
|
|
#include "shmcpp/detail/handle/win32/handle.hpp"
|
|
#include "shmcpp/detail/handle/win32/native_api.hpp"
|
|
#include "shmcpp/detail/handle/win32/utils.hpp"
|
|
|
|
namespace shmcpp::detail {
|
|
Win32Handle::Win32Handle(const HANDLE handle, const std::size_t size, const std::string& name) noexcept
|
|
: handle_(handle), size_(size), name_(name) {
|
|
}
|
|
|
|
Win32Handle::~Win32Handle() noexcept {
|
|
if (handle_ != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(handle_);
|
|
}
|
|
}
|
|
|
|
Win32Handle::Win32Handle(Win32Handle&& other) noexcept {
|
|
this->handle_ = other.handle_;
|
|
this->size_ = other.size_;
|
|
this->name_ = std::move(other.name_);
|
|
other.handle_ = INVALID_HANDLE_VALUE;
|
|
other.size_ = 0;
|
|
}
|
|
|
|
Win32Handle& Win32Handle::operator=(Win32Handle&& other) noexcept {
|
|
if (this != &other) {
|
|
if (handle_ != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(handle_);
|
|
}
|
|
this->handle_ = other.handle_;
|
|
this->size_ = other.size_;
|
|
this->name_ = std::move(other.name_);
|
|
other.handle_ = INVALID_HANDLE_VALUE;
|
|
other.size_ = 0;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
Win32Handle Win32Handle::create(const std::string& name, const std::size_t size) {
|
|
const DWORD high = size >> 32;
|
|
const DWORD low = size & 0xFFFFFFFF;
|
|
const HANDLE handle = CreateFileMappingA(
|
|
INVALID_HANDLE_VALUE,
|
|
nullptr,
|
|
PAGE_READWRITE,
|
|
high,
|
|
low,
|
|
name.c_str()
|
|
);
|
|
if (handle == nullptr) {
|
|
DWORD err = GetLastError();
|
|
throw std::runtime_error(
|
|
std::format("{}: {}", err, getWindowsErrorMessage(err))
|
|
);
|
|
}
|
|
return Win32Handle{handle, size, name};
|
|
}
|
|
|
|
Win32Handle Win32Handle::open(const std::string& name) {
|
|
const HANDLE handle = OpenFileMappingA(
|
|
SECTION_QUERY | FILE_MAP_ALL_ACCESS,
|
|
FALSE,
|
|
name.c_str()
|
|
);
|
|
if (handle == nullptr) {
|
|
DWORD err = GetLastError();
|
|
throw std::runtime_error(
|
|
std::format("{}: {}", err, getWindowsErrorMessage(err))
|
|
);
|
|
}
|
|
SECTION_BASIC_INFORMATION sbi{};
|
|
NTSTATUS status = ZwQuerySection(
|
|
handle,
|
|
SectionBasicInformation,
|
|
&sbi,
|
|
sizeof(sbi),
|
|
nullptr
|
|
);
|
|
if (status < 0) {
|
|
CloseHandle(handle);
|
|
throw std::runtime_error(
|
|
std::format("Failed to query section size: NTSTATUS {:#x}", static_cast<unsigned>(status))
|
|
);
|
|
}
|
|
std::size_t size = sbi.MaximumSize.QuadPart;
|
|
return Win32Handle{handle, size, name};
|
|
}
|
|
|
|
void Win32Handle::remove(const std::string&) {
|
|
// No operation for Windows
|
|
}
|
|
|
|
MappedView Win32Handle::map(std::size_t offset, std::size_t length) {
|
|
if (length == 0)
|
|
throw std::invalid_argument("length cannot be zero");
|
|
const DWORD high = offset >> 32;
|
|
const DWORD low = offset & 0xFFFFFFFF;
|
|
LPVOID ptr = MapViewOfFile(
|
|
this->handle_,
|
|
FILE_MAP_ALL_ACCESS,
|
|
high,
|
|
low,
|
|
length
|
|
);
|
|
if (ptr == nullptr) {
|
|
DWORD err = GetLastError();
|
|
throw std::runtime_error(
|
|
std::format("{}: {}", err, getWindowsErrorMessage(err))
|
|
);
|
|
}
|
|
return MappedView{ptr, length};
|
|
}
|
|
|
|
size_t Win32Handle::size() const noexcept {
|
|
return size_;
|
|
}
|
|
|
|
const std::string& Win32Handle::name() const noexcept {
|
|
return name_;
|
|
}
|
|
|
|
static_assert(Handle<Win32Handle>);
|
|
}
|