1

The win32 API's SetCursorPos moves the mouse to a location on the screen. However, sometimes it does nothing.

See the following C++ code (Visual Studio 16.8.1, Windows 10)

#include <iostream>
#include <windows.h>

int main()
{
    while (true)
    {
        std::cout << "Hello World!\n";
        SetCursorPos(100, 200);
        Sleep(2000);
    }
}

Every 2 seconds, if SetCursorPos works then the cursor teleports to (100, 200). This works normally.

However if I leave this running and open the built-in Windows app called "On-Screen Keyboard", SetCursorPos no longer works (the cursor no longer teleports every 2 seconds).
Note: If trying this yourself, On-Screen Keyboard usually unfocuses itself automatically. To keep it focused to observe SetCursorPos not working, alt+tab to it, which causes it not to unfocus itself.

There are other third-party applications that, when in foreground, also seem to obstruct SetCursorPos. (When I observed those, I wasn't using the above C++ script. I was using the Python package mouse which uses SetCursorPos under the hood.)

How are these applications able to "swallow" my SetCursorPos API calls, and is there a different API or technique I can use in place of SetCursorPos to not allow those applications to interfere?


A physical USB mouse, as well as remote desktop software such as TeamViewer and Anydesk, are not obstructed by such applications, which leads me to believe they utilize some pathway besides SetCursorPos to get reliable mouse movement.

tscizzle
  • 11,191
  • 15
  • 54
  • 88
  • I suspect it's applications running at an elevated privilege level. You don't want software controlling sensitive applications. – chris Jan 12 '21 at 19:59
  • I should say you don't want _untrusted_ software controlling sensitive applications. If you trust software, you can run it as an administrator to close the privilege gap. – chris Jan 12 '21 at 20:15
  • 1
    Have you checked the return value from `SetCursorPos` for success? If it fails, have you checked the error code? – 1201ProgramAlarm Jan 12 '21 at 20:22
  • @1201ProgramAlarm `SetCursorPos` does indeed fail (returns 0) at the expected times. However, a subsequent `std::cout << GetLastError();` shows 0. – tscizzle Jan 12 '21 at 22:04
  • @chris I'm guessing that's it! Running a Command Prompt as admin, and running Python in it and using the library `mouse`, it is able to control the cursor. The logic makes sense. Any documentation one can refer to? – tscizzle Jan 12 '21 at 22:09
  • 1
    @tscizzle, I have no idea where I learned that, so it might take a specific search term, but I did find a [pretty relevant SO question](https://stackoverflow.com/questions/41186226/how-to-send-input-to-cmd-when-cmd-is-running-as-administrator). Actually, [this article](https://learn.microsoft.com/en-us/windows/win32/winauto/uiauto-securityoverview?redirectedfrom=MSDN#uiaccess_requirements_for_assistive_technology_applications_) linked from the comments there goes into it a bit. – chris Jan 12 '21 at 23:54
  • 1
    The question is the same as [C++ move mouse in windows using SetCursorPos](https://stackoverflow.com/questions/22259936/c-move-mouse-in-windows-using-setcursorpos) but I suggest it not be marked as a duplicate since the answers there do not explain the "why" part of the elevation requirement. – dxiv Jan 12 '21 at 23:58
  • @chris Running the mouse control program with elevated privilege fixed the issue for most programs, but some still cause the issue (e.g. Anydesk, specifically the window that appears when another computer is attempting to start a remote connection.) Is there another tier of elevated status? Or another method it might be using to disallow other programs' `SetCursorPos`? – tscizzle Jan 15 '21 at 18:59
  • @tscizzle, I know SYSTEM exists, but I'm not sure if affects this restriction. The process owner is a good place to start (in task manager or elsewhere). I also don't know whether `SetCursorPos` feeds back into things like mouse hooks that a particular program could be using. – chris Jan 15 '21 at 19:25
  • @chris The offending Anydesk process is indeed from the user SYSTEM. – tscizzle Jan 15 '21 at 19:56

1 Answers1

1

The answer is admin privileges.

As explained by @chris in the comments, some programs have elevated privileges, and when they are in the foreground (and thus, accepting user input), Windows doesn't let programs without elevated privileges control the mouse or keyboard. Otherwise, untrusted programs would be able to utilize trusted programs to do things untrusted programs aren't normally allowed to do.

Think of it like this. A wizard without FBI security clearance shouldn't be allowed to use an Imperius Curse on an FBI agent to effectively gain clearance.

See these links others supplied in comments: relevant SO post #1, relevant SO post #2, tangential Windows accessibility article.

Solution: run your mouse-control program with elevated privileges, too.

If running your program in Cmd, for example, open Cmd as admin by right-clicking the Cmd icon in the Start Menu or Task Bar and select "Run as admin", and then run your script inside it. If your program is a batch file, you can right-click a shortcut to it and "Run as admin".

tscizzle
  • 11,191
  • 15
  • 54
  • 88