Files
wine-access/review_query.h
2026-10-11 22:07:14 -07:00

61 lines
2.1 KiB
C++

// SPDX-License-Identifier: LGPL-2.1-or-later
#pragma once
#include <windows.h>
#include <algorithm>
#include <cstdint>
#include <memory>
#include <vector>
struct ReviewQuery {
UINT message;
WPARAM index;
DWORD_PTR answer = 0;
bool complete = false;
};
inline void CALLBACK review_query_completed(HWND, UINT, ULONG_PTR data, LRESULT result) {
auto &reply = *reinterpret_cast<ReviewQuery *>(data);
reply.answer = result;
reply.complete = true;
}
// Only scalar messages may use this path. The capture STA owns one batch;
// late callbacks retain their storage until all replies arrive or it exits.
inline bool review_query_many(HWND window, std::vector<ReviewQuery> &requests, uint64_t deadline) {
static thread_local std::unique_ptr<std::vector<ReviewQuery>> pending;
auto pump = [deadline] {
MSG message{};
while (GetTickCount64() < deadline && PeekMessageW(&message, nullptr, 0, 0, PM_REMOVE)) {
TranslateMessage(&message);
DispatchMessageW(&message);
}
};
if (requests.empty()) return GetTickCount64() < deadline;
auto complete = [](const auto &items) {
return std::all_of(items.begin(), items.end(), [](const auto &item) { return item.complete; });
};
pump();
if (GetTickCount64() >= deadline) return false;
if (pending && !complete(*pending)) return false;
pending = std::make_unique<std::vector<ReviewQuery>>(requests);
for (auto &item : *pending) {
if (!SendMessageCallbackW(window, item.message, item.index, 0, review_query_completed,
reinterpret_cast<ULONG_PTR>(&item))) {
// Keep any requests already sent alive, including during failure.
item.complete = true;
item.answer = static_cast<DWORD_PTR>(-1);
}
}
while (!complete(*pending)) {
auto now = GetTickCount64();
if (now >= deadline) return false;
MsgWaitForMultipleObjectsEx(0, nullptr, static_cast<DWORD>(deadline-now), QS_ALLINPUT, MWMO_INPUTAVAILABLE);
pump();
}
if (GetTickCount64() >= deadline) return false;
requests = *pending;
pending.reset();
return std::none_of(requests.begin(), requests.end(), [](const auto &item) {
return item.answer == static_cast<DWORD_PTR>(-1);
});
}