From ce691463b1969dc9ec15d5ac599e13a7932d6505 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Fri, 18 Oct 2019 13:39:05 +0100 Subject: [PATCH] #5294 Prevented cursor moving off screen when a locking issue may occur --- src/lib/platform/MSWindowsScreen.cpp | 67 ++++++++++++++++++++++++++-- src/lib/platform/MSWindowsScreen.h | 19 ++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index 2d7ac131..d8a4de07 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -329,6 +329,13 @@ MSWindowsScreen::enter() bool MSWindowsScreen::leave() { + POINT pos; + if (!getThisCursorPos(&pos)) + { + LOG((CLOG_DEBUG "Unable to leave screen as Windows security has disabled critical functions required to let synergy work")); + //unable to get position this means synergy will break if the cursor leaves the screen + return false; + } // get keyboard layout of foreground window. we'll use this // keyboard layout for translating keys sent to clients. HWND window = GetForegroundWindow(); @@ -539,6 +546,60 @@ MSWindowsScreen::getCursorPos(SInt32& x, SInt32& y) const m_desks->getCursorPos(x, y); } +/* + * getThisCursorPos and setThisCursorPos will attempt to negotiate with the system + * to try get the and set the mouse position, however on the logon screen due to + * hooks this process has it may unable to work around the problem. Although these + * functions did not fix the issue at hand (#5294) its worth keeping them here anyway. + */ +bool MSWindowsScreen::getThisCursorPos(LPPOINT pos) +{ + auto result = GetCursorPos(pos); + auto error = GetLastError(); + LOG((CLOG_DEBUG3 "%s Attempt: 1 , status %d, code: %d Pos {%d, %d}", __func__, result, error, pos->x, pos->y)); + if (!result) + { + result = GetCursorPos(pos); + error = GetLastError(); + LOG((CLOG_INFO "%s Attempt: 2, status %d, code: %d Pos {%d, %d}", __func__, result, error, pos->x, pos->y)); + updateDesktopThread(); + } + return result; +} + +bool MSWindowsScreen::setThisCursorPos(int x, int y) +{ + auto result = SetCursorPos(x, y); + auto error = GetLastError(); + LOG((CLOG_DEBUG3 "%s Attempt: 1, status %d, code: %d", __func__, result, error)); + if (!result) + { + result = SetCursorPos(x, y); + error = GetLastError(); + LOG((CLOG_INFO "%s Attempt: 2, status %d, code: %d", __func__, result, error)); + updateDesktopThread(); + } + + return result; +} + +void MSWindowsScreen::updateDesktopThread() +{ + + LOG((CLOG_DEBUG3 "Failed to set cursor Attempting to switch desktop")); + SetLastError(0); + HDESK cur_hdesk = OpenInputDesktop(0, true, GENERIC_ALL); + + auto error = GetLastError(); + LOG((CLOG_DEBUG3 "\tGetting desktop Handle: %p Status code: %d", cur_hdesk, error)); + + error = GetLastError(); + LOG((CLOG_DEBUG3 "\tSetting desktop return: %d Status code: %d", SetThreadDesktop(cur_hdesk), GetLastError())); + + CloseDesktop(cur_hdesk); + +} + void MSWindowsScreen::reconfigure(UInt32 activeSides) { @@ -1524,12 +1585,12 @@ MSWindowsScreen::warpCursorNoFlush(SInt32 x, SInt32 y) // warp mouse. hopefully this inserts a mouse motion event // between the previous message and the following message. - SetCursorPos(x, y); + setThisCursorPos(x, y); // check to see if the mouse pos was set correctly POINT cursorPos; - GetCursorPos(&cursorPos); - + getThisCursorPos(&cursorPos); + // there is a bug or round error in SetCursorPos and GetCursorPos on // a high DPI setting. The check here is for Vista/7 login screen. // since this feature is mainly for client, so only check on client. diff --git a/src/lib/platform/MSWindowsScreen.h b/src/lib/platform/MSWindowsScreen.h index 4b1f2c18..ea978553 100644 --- a/src/lib/platform/MSWindowsScreen.h +++ b/src/lib/platform/MSWindowsScreen.h @@ -75,6 +75,25 @@ public: SInt32& width, SInt32& height) const; virtual void getCursorPos(SInt32& x, SInt32& y) const; + /** + * \brief Get the position of the cursor on the current machine + * \param pos the object that the function will use to store the position of the cursor + * \return true if the function was successful + */ + virtual bool getThisCursorPos(LPPOINT pos); + /** + * \brief Sets the cursor position on the current machine + * \param x The x coordinate of the cursor + * \param y The Y coordinate of the cursor + * \return True is successful + */ + virtual bool setThisCursorPos(int x, int y); + + /** + * \brief This function will attempt to switch to the current desktop the mouse is located on + */ + virtual void updateDesktopThread(); + // IPrimaryScreen overrides virtual void reconfigure(UInt32 activeSides); virtual void warpCursor(SInt32 x, SInt32 y);