59 lines
2.2 KiB
C++
59 lines
2.2 KiB
C++
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
#pragma once
|
|
#include <windows.h>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
|
|
namespace native_control {
|
|
inline bool query(HWND window, UINT message, WPARAM wp, LPARAM lp, DWORD_PTR *result) {
|
|
return SendMessageTimeoutW(window, message, wp, lp, SMTO_ABORTIFHUNG,
|
|
100, result) != 0;
|
|
}
|
|
|
|
// Common-control messages above WM_USER do not marshal embedded pointers.
|
|
// Own the target allocation and process handle together, including failures.
|
|
class RemoteBuffer {
|
|
public:
|
|
RemoteBuffer(HWND window, size_t size) {
|
|
DWORD processId = 0;
|
|
GetWindowThreadProcessId(window, &processId);
|
|
process_ = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |
|
|
PROCESS_VM_WRITE | PROCESS_QUERY_LIMITED_INFORMATION,
|
|
FALSE, processId);
|
|
if (!process_ || !IsWow64Process(process_, &wow64_)) return;
|
|
memory_ = VirtualAllocEx(process_, nullptr, size,
|
|
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
|
// Every byte of the allocation must be addressable by the target.
|
|
if (memory_ && wow64_ &&
|
|
(address() > UINT32_MAX || size - 1 > UINT32_MAX - address())) {
|
|
VirtualFreeEx(process_, memory_, 0, MEM_RELEASE);
|
|
memory_ = nullptr;
|
|
}
|
|
}
|
|
~RemoteBuffer() {
|
|
if (memory_) VirtualFreeEx(process_, memory_, 0, MEM_RELEASE);
|
|
if (process_) CloseHandle(process_);
|
|
}
|
|
RemoteBuffer(const RemoteBuffer &) = delete;
|
|
RemoteBuffer &operator=(const RemoteBuffer &) = delete;
|
|
|
|
explicit operator bool() const { return memory_ != nullptr; }
|
|
bool is32Bit() const { return wow64_ != FALSE; }
|
|
uintptr_t address(size_t offset = 0) const {
|
|
return reinterpret_cast<uintptr_t>(memory_) + offset;
|
|
}
|
|
bool write(const void *buffer, size_t size) const {
|
|
return WriteProcessMemory(process_, memory_, buffer, size, nullptr) != 0;
|
|
}
|
|
bool read(void *buffer, size_t size, size_t offset = 0) const {
|
|
return ReadProcessMemory(process_, reinterpret_cast<const void *>(address(offset)),
|
|
buffer, size, nullptr) != 0;
|
|
}
|
|
|
|
private:
|
|
HANDLE process_ = nullptr;
|
|
void *memory_ = nullptr;
|
|
BOOL wow64_ = FALSE;
|
|
};
|
|
} // namespace native_control
|