How to know when the Winlogon desktop is ready for inputs? - c++

I successfully used SendSAS in a service (Local System Account). I call the API four seconds after the service starts. It seems that whatever the boot process duration, Windows manage to cache (sort of) the call: the same code finally shows me a logon screen a few seconds after the power on, on a fast laptop (Win10), and also shows me the logon screen after a very much longer delay on a slow Server (2012R2) running virtualized (wmware).
I am also able to use CreateProcessAsUser (with an updated token) to inject a tiny executable in the Session 1, Station WinSta0, Desktop Winlogon. The process then uses SendInput to "auto-logon" the session (yes, this is an awful think to do do, I am aware of that).
My problem: if the tiny process starts "too early", nothing happens. If the service waits, say, 2 minutes, all is OK.
What API should I use (in the service or in the started process) to find out when the WinLogon desktop is ready to accept keyboard inputs?
I tried WTSGetActiveConsoleSessionId (in the service) and OpenInputDesktop (in the process) hopping that failure would indicate the need to wait, but with no avail.

When your process starts in session 1, attached to the WinSta0\Winlogon desktop, you can periodically test the Control Type of the currently IUIAutomationElement focused element.
The APIs to use are : IUIAutomation::GetFocusedElement and then IUIAutomationElement::GetCurrentPropertyValue for the UIA_ControlTypePropertyId property. When you successfully get a focused element of type UIA_EditControlTypeId, the Windows logon screen is ready to accept inputs.
Don't forget to add a Sleep call between each try.
Tested OK with Windows Server 2008R2 and 2012R2, and with Windows 10.

Related

How to tell that the logon screen is currently displayed?

I am writing a service application that will run with local system credentials. I will need to know from my service if the Windows logon screen is displayed at any particular time. Is there any way to do this?
PS. The screens that can be brought up by locking the workstation:
Or by trying to switch the user:
Or after a Ctrl+Alt+Del:
PS. I need this to run on Windows XP and up.
EDIT: The only viable solution that I came up with so far is to see if LogonUI.exe process is running. The issue with this approach is how to distinguish between the actual system logon process and any other process that has that image name?
As described in the comments you are trying to detect whether or not a process in an interactive desktop session should show a message box. There being no point doing so if the interactive session is not active.
In which case I believe that your proposed solution is the wrong one. Instead you should register for session change notifications by calling WTSRegisterSessionNotification. When you do this you'll get sent WM_WTSSESSION_CHANGE messages that allow you to keep track of the current state.
Note that you do this in your desktop app rather than the service. The service still sends its messages to the desktop app. But the desktop app now knows whether or not it is worth showing them.
Update
Remy suggests a better way in the comments:
And if a separate app is being used, there is no reason to detect session changes at all, that app can simply check if its currently assigned workstation/desktop is the currently interactive workstation/desktop instead, comparing GetThreadDesktop() to OpenInputDesktop(), for instance.
All such screens are presented on a separate desktop. You may try to enumerate the user's desktops and compare it with the current (I am not sure the service in session 0 - Vista and up - can do that; if not, spawn a helper process in the user session). This however may give a false positive if an UAC desktop is up. Another corner case is a userless situation (right after boot before any user looged on).
There are several states in the windows.
Logged-Off State
When Winlogon is in the logged-off state, users are prompted to identify themselves and provide authentication information. If a user provides correct user account information and no restrictions prevent it, the user is logged on and a shell program (such as Windows Explorer) is executed in the application desktop. Winlogon changes to the logged-on state.
Logged-On State
When Winlogon is in the logged-on state, users can interact with the shell, activate additional applications, and do their work. From the logged-on state, users can either stop all work and log off, or lock their workstations (leaving all work in place). If the user decides to log off, Winlogon will terminate all processes associated with that logon session and the workstation will be available for another user. If, instead, the user decides to lock the workstation, Winlogon changes to the workstation-locked state.
Workstation-Locked State
When Winlogon is in the workstation-locked state, a secure desktop is displayed until the user unlocks the workstation by providing the same identification and authentication information as the user who originally logged on, or until an administrator forces a logoff. If the workstation is unlocked, the application desktop is displayed, and work can resume.
reference: https://msdn.microsoft.com/ko-kr/library/windows/desktop/aa380547(v=vs.85).aspx
p.s. registering a secure attention sequence (SAS, CTRL+ALT+Delete) is included in Workstation-Locked state
Similarly, there are several desktop types on windows.
Winlogon desktop
Application desktop(=Default desktop)
Screensaver desktop
Secure desktop
I recommend you read this:
https://msdn.microsoft.com/ko-kr/library/windows/desktop/aa375994(v=vs.85).aspx
I don't know my answers are what you want... but I hope it helps in some ways.

DuplicateTokenEx for changing windows sessions

I have a service which runs as system (in session 0) that is capable of spawning processes on the desktop (in user's sessions). I'm following the exact method described here: http://www.developerfusion.com/community/blog-entry/8389765/creating-a-process-in-another-user-session/
This code has been working for years, but I recently found out that the windows file I/O on the child programs is acting MUCH worse for the spawned process than if ran manually by a regular user.
The penalty can be seen by launching notepad (from the daemon running in session 0), and trying to open a file through the windows dialog. It takes more than 10 seconds just for the "open" file browser to come up. I used process monitor and saw that the File and registry access had almost 1,000,000 events. When doing the same process on a notepad launched manually, there are ~6,000 events.
I'm assuming I am missing some flag in the token impersonation, but I haven’t been able to find anything online. I ruled out my CreateProcessAsUser code by running it from session 1 vs session 0, and the session 1 code ran the same as the manual launch. Any ideas would be appreciated.
Extra information: This problem may be very specific because I have a roaming profile on the network instead of on the local machine.

How to reset windows idle timer through a windows service

I have used the template provided Here, to create a windows service. I would like to use this service to reset the system idle timer to avoid the OS going to sleep mode.
SetThreadExecutionState, seems the be the right way of doing so. However, it appears that this method, does not work when the program is running as a service. I have even tried sending an event with keybd_event function, but it appears that there are some security measures in place (see question No. 12747430), to filter out mouse/keyboard events for non-desktop applications ( Even though 'Allow service to interact with desktop' option, is checked for the service).
So here's the question: How can i reset the system idle timer through a windows service? (should not be dependent on user's desktop and should work on login screen as well)
PS: the OS is windows 7 x64
Thanks in advance

Service blocks windows startup

We have automatically started service which in some cases spends a lot of the time loading necessary data, let's say 10 minutes. During this time it works as expected (processing some huge data files required to start). I report the progess by C++ SetServiceStatus function, it is working fine.
This service is not dependent on anything and has only one dependency which is again our own service. It is started after those 10 minutes, it needs the first "server" service to be fully running to accept the requests.
I thought that windows would start all other automatic services (in less then 10 minutes as usually) and then start working normally but system is completely blocked during startup (i can't login to computer or ping the computer) until this one specific service is started (reports SERVICE_RUNNING by SetServiceStatus). When out service completely starts, the other missing system services (required for network, remote desktop, whatever, it's quite random) are also started. Is this normal behaviour? Why are non-depending processes (as remote desktop, network connections, etc.) waiting for this process? Am I missing something?
I tried to add some dependencies to postpone the startup of my service but I ended up with many dependencies and behaviour still somehow random (as order of services is random). Sometimes I was able to login but for example Start button started working only after those 10 minutes when my service was started. I am not sure what is "the last service" to depend on and what services to include to my depend-list and on some computers this services can be disabled and it can bring new problems... so I don't like this solution very much.
Another option was Delayed start option for our service. This should start service when all other automatic services are running. Well, this works fine, windows boots, computer running and responding, our service is started, but the performance is very bad, many times slower than usually, it seems that delayed started services have much lower priority or something like that.
My only current solution is to report to system that my service is running (by SetServiceStatus function), but to continue loading (this works, I tested it). But then we have problem with our dependent service as it needs to be started when the first one is really ready. It can be solved but I still wonder how is this possible and if there is something I could use to keep the current state of automatic started service which reports "started" when it is really fully started and prepared to work. Thanks for any ideas.
Set SERVICE_RUNNING as soon as possible, and then continue processing in background. Make your other service resilient to the first service being in a running state, but not yet ready to service.
The longer the service is in the starting state the more problems we get from different windows versions.

How can I Execute a Function when Windows Shut down

How Can I execute a function when Windows shutdown. Here is my scenario, I am mounting a drive using WNetAddConnection2 function in my application. Now I want user to set the option if the drive will be mounted on next system startup or not.
If he selects , not to mount on next startup , then I need to remove the drive using WNetCancelConnection2 , but this should only happen when user shutdown the system.
I can only think of only solution. Create a service which will check the user option and then decide whether to mount the drive or not.
Are there any other ways to go ahead with it?
If you have a main window (even an invisible one) that can process messages, you can handle the WM_ENDSESSION message.
See: http://msdn.microsoft.com/en-us/library/aa376889(v=VS.85).aspx
If you can make your app into a Windows service (or have your app communicate state with one that you provide) you can perform required actions on receipt of SERVICE_CONTROL_SHUTDOWN in your service control handler function. This would decouple your app that handles user interaction from the shutdown handling, which requires something to be running all the time (what if the user logs off?).
explorer.exe is the GUI process of windows which usually only gets shut down if Windows shuts down (exceptions have to be made for certain error conditions). You could listen on the WM_DESTROY window message for the process ID of explorer.exe and dismount then.
The way I can think of is to:
Register your program to auto Start up (when PC starts). Here's a tutorial on howto.
Store the user option (as mentioned above) in a repository or registry (if you know how). When your app would have started, you can read your registry and act accordingly.
For shutdown, your application will have to hook itself on a SystemEvent to detect shutdown (then you can act accordingly). Here's an example on howto (C#). For C++, you can listen to WM_ENDSESSION message.
I hope that my 2 cents can help you.