shmcpp/src/handle/win32/handle.cpp
2026-01-11 13:27:05 +08:00

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>);
}