mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-26 07:14:33 +08:00
[fix] prevent remote input from blocking transport callbacks
This commit is contained in:
@@ -64,6 +64,7 @@ int GuiApplication::RunUnattended(void* stop_event) {
|
||||
}
|
||||
|
||||
// Quiesce network callbacks before destroying the controllers they use.
|
||||
remote_input_.Stop();
|
||||
CloseAllRemoteSessions();
|
||||
WaitForSessionCleanup();
|
||||
keyboard_.ReleaseAllRemotePressedKeys("unattended_host_exit");
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace {
|
||||
struct InputResult {
|
||||
UINT sent;
|
||||
DWORD error;
|
||||
bool requires_worker = false;
|
||||
};
|
||||
|
||||
InputResult InjectOnUserDesktop(INPUT* inputs, UINT count) {
|
||||
@@ -25,7 +26,10 @@ InputResult InjectOnUserDesktop(INPUT* inputs, UINT count) {
|
||||
ScopedInteractiveDesktop desktop;
|
||||
if (!desktop.Bind(L"")) {
|
||||
const DWORD error = GetLastError();
|
||||
return {0, error != ERROR_SUCCESS ? error : ERROR_GEN_FAILURE};
|
||||
// A library may have created a window/hook on an opted-in thread. This
|
||||
// failure occurs before SendInput, so retrying on the worker is safe.
|
||||
return {0, error != ERROR_SUCCESS ? error : ERROR_GEN_FAILURE,
|
||||
error == ERROR_BUSY};
|
||||
}
|
||||
if (!desktop.IsReceivingInput()) {
|
||||
return {0, ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION};
|
||||
@@ -99,8 +103,13 @@ UINT SendInputOnUserDesktop(INPUT* inputs, UINT count) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
static UserDesktopInputWorker worker;
|
||||
const InputResult result = worker.Send(inputs, count);
|
||||
InputResult result{0, ERROR_SUCCESS, true};
|
||||
if (ScopedUserDesktopInputThread::IsCurrent())
|
||||
result = InjectOnUserDesktop(inputs, count);
|
||||
if (result.requires_worker) {
|
||||
static UserDesktopInputWorker worker;
|
||||
result = worker.Send(inputs, count);
|
||||
}
|
||||
const DWORD error = result.error;
|
||||
if (error != ERROR_SUCCESS) {
|
||||
// Include session identity even when Windows reports no useful SendInput
|
||||
|
||||
@@ -11,9 +11,23 @@
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
// Executes on a worker without windows or hooks, attached to this process's
|
||||
// current user input desktop. Returns a SendInput count and preserves the
|
||||
// worker's failure code in the calling thread's last-error value.
|
||||
// Opt in only on the remote input worker. UI/hook callers keep using the
|
||||
// fallback worker. Desktop attachment is still checked for each injection.
|
||||
class ScopedUserDesktopInputThread {
|
||||
public:
|
||||
ScopedUserDesktopInputThread() { ++depth_; }
|
||||
~ScopedUserDesktopInputThread() { --depth_; }
|
||||
ScopedUserDesktopInputThread(const ScopedUserDesktopInputThread&) = delete;
|
||||
ScopedUserDesktopInputThread& operator=(const ScopedUserDesktopInputThread&) =
|
||||
delete;
|
||||
static bool IsCurrent() { return depth_ != 0; }
|
||||
private:
|
||||
inline static thread_local unsigned depth_ = 0;
|
||||
};
|
||||
|
||||
// Executes directly on an opted-in worker, or on the fallback input worker,
|
||||
// attached to this process's current user input desktop. Returns a SendInput
|
||||
// count and preserves the failure code in the calling thread's last-error value.
|
||||
UINT SendInputOnUserDesktop(const INPUT& input);
|
||||
|
||||
// Synchronously injects one ordered batch. The caller owns the buffer until
|
||||
|
||||
Reference in New Issue
Block a user