Files
wine-access/native_query.h

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