Version and better logging added.

This commit is contained in:
Storm Dragon committed 2026-10-15 12:49:33 -04:00
1 parent b16c6968ae
commit 77db0b83ab
10 files changed
+326 -8

No files matched your search

+54 -6
View File
@@ -12,6 +12,7 @@
#include "reader_endpoint.h"
#include "msaa_events.h"
#include "reader_events.h"
#include "version.h"
#include <commctrl.h>
#include <gio/gio.h>
@@ -1049,6 +1050,17 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, char *, int) {
int argumentCount = 0;
wchar_t **arguments = CommandLineToArgvW(commandLine, &argumentCount);
if (arguments == nullptr) return 1;
// Version queries must work without a reader, even while another helper owns
// the singleton. The identity is embedded in this executable's sidecar.
for (int index = 1; index < argumentCount; ++index) {
if (lstrcmpW(arguments[index], L"--version") == 0) {
std::puts(WINE_ACCESS_BUILD);
LocalFree(arguments);
return 0;
}
}
std::fprintf(stderr, "wine-access: identity {\"version\":\"%s\",\"revision\":\"%s\",\"modified\":%s}\n",
WINE_ACCESS_VERSION, WINE_ACCESS_REVISION, WINE_ACCESS_MODIFIED);
bool validReader = true;
bool validEndpoint = true;
std::string readerPath, readerInterface;
@@ -1097,14 +1109,20 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, char *, int) {
// These strings remain alive until the workers have stopped at shutdown.
if (!readerPath.empty()) readerEndpoint.objectPath = readerPath.c_str();
if (!readerInterface.empty()) readerEndpoint.interfaceName = readerInterface.c_str();
if (!dialogReaderEnabled && !controllerEnabled)
if (!dialogReaderEnabled && !controllerEnabled) {
std::fprintf(stderr, "wine-access: disabled by command-line options\n");
return 0;
}
HANDLE singleton =
CreateMutexW(nullptr, TRUE, L"Local\\cthulhu-wine-access-singleton");
if (singleton == nullptr)
if (singleton == nullptr) {
std::fprintf(stderr, "wine-access: singleton creation failed (error %lu)\n",
static_cast<unsigned long>(GetLastError()));
return 1;
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
std::fprintf(stderr, "wine-access: another helper already owns this Wine desktop\n");
CloseHandle(singleton);
return 0;
}
@@ -1147,8 +1165,11 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, char *, int) {
CloseHandle(singleton);
return 1;
}
reviewService.start(connection,reviewIdentities,readerEndpoint);
if (dialogReaderEnabled && !msaaEvents.start()) {
const bool reviewActive = reviewService.start(connection,reviewIdentities,readerEndpoint);
if (!reviewActive)
std::fprintf(stderr, "wine-access: review service unavailable\n");
const bool msaaActive = dialogReaderEnabled && msaaEvents.start();
if (dialogReaderEnabled && !msaaActive) {
std::fprintf(stderr, "wine-access: MSAA event worker unavailable\n");
}
bool controllerActive = false;
@@ -1171,6 +1192,8 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, char *, int) {
DestroyWindow(window);
window = nullptr;
}
if (controllerEnabled && !controllerActive)
std::fprintf(stderr, "wine-access: controller endpoint unavailable\n");
HWINEVENTHOOK hook = nullptr;
HHOOK menuHook = nullptr;
@@ -1178,9 +1201,13 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, char *, int) {
HMODULE menuModule = nullptr;
HWND menuBridge = nullptr;
HANDLE menuHost32 = nullptr;
DWORD menuHookError = 0, inputHookError = 0;
if (dialogReaderEnabled) {
hook = SetWinEventHook(EVENT_MIN, EVENT_MAX, nullptr, winevent_callback, 0,
0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
if (hook == nullptr)
std::fprintf(stderr, "wine-access: WinEvent hook unavailable (error %lu)\n",
static_cast<unsigned long>(GetLastError()));
WNDCLASSW bridgeClass{};
bridgeClass.lpfnWndProc = menu_bridge_proc;
bridgeClass.hInstance = instance;
@@ -1189,18 +1216,27 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, char *, int) {
menuBridge = CreateWindowExW(WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW,
WINE_ACCESS_MENU_CLASS, L"", 0, 0, 0, 0, 0,
nullptr, nullptr, instance, nullptr);
if (menuBridge != nullptr && (menuModule = load_menu_hook()) != nullptr) {
if (menuBridge == nullptr) {
menuHookError = inputHookError = GetLastError();
} else if ((menuModule = load_menu_hook()) == nullptr) {
menuHookError = inputHookError = GetLastError();
} else {
const auto callback = std::bit_cast<HOOKPROC>(GetProcAddress(menuModule, "WineAccessMenuHook"));
if (callback != nullptr)
menuHook = SetWindowsHookExW(WH_CALLWNDPROC, callback, menuModule, 0);
if (menuHook == nullptr) menuHookError = GetLastError();
const auto inputCallback = std::bit_cast<HOOKPROC>(GetProcAddress(menuModule, "WineAccessInputHook"));
if (inputCallback != nullptr)
inputHook = SetWindowsHookExW(WH_GETMESSAGE, inputCallback, menuModule, 0);
if (inputHook == nullptr) inputHookError = GetLastError();
editReaderActive = menuHook != nullptr && inputHook != nullptr;
}
if (menuHook == nullptr)
std::fprintf(stderr, "wine-access: native menu hook unavailable (error %lu)\n",
static_cast<unsigned long>(GetLastError()));
static_cast<unsigned long>(menuHookError));
if (inputHook == nullptr)
std::fprintf(stderr, "wine-access: native input hook unavailable (error %lu)\n",
static_cast<unsigned long>(inputHookError));
if (menuBridge != nullptr) {
menuHost32 = start_menu_host32(menuBridge);
if (menuHost32 == nullptr)
@@ -1212,6 +1248,18 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, char *, int) {
// Native lists, tabs, trees and combo boxes can omit change WinEvents in Wine.
// Observe only the foreground control; never read background selections.
const UINT_PTR listTimer = dialogReaderEnabled ? SetTimer(nullptr, 0, 100, nullptr) : 0;
if (dialogReaderEnabled && !listTimer)
std::fprintf(stderr, "wine-access: control polling timer unavailable\n");
// Initialization status is distinct from process creation. Hook handles and
// a started host do not prove attachment to a particular application.
std::fprintf(stderr, "wine-access: ready {\"reader\":\"%s\",\"controls_enabled\":%s,"
"\"controller\":%s,\"review\":%s,\"msaa_worker\":%s,\"win_events\":%s,"
"\"menu_hook\":%s,\"input_hook\":%s,\"host32_started\":%s,\"control_poll\":%s}\n",
readerEndpoint.busName, dialogReaderEnabled ? "true" : "false",
controllerActive ? "true" : "false", reviewActive ? "true" : "false",
msaaActive ? "true" : "false", hook ? "true" : "false",
menuHook ? "true" : "false", inputHook ? "true" : "false",
menuHost32 ? "true" : "false", listTimer ? "true" : "false");
while (GetMessageW(&message, nullptr, 0, 0) > 0) {
if (listTimer && message.message == WM_TIMER && message.hwnd == nullptr &&
message.wParam == listTimer) {