Windows - tray icon to all users? - windows

Is it allowed to have some process's icon to be displayed in all user sessions including terminal/multiple local logons, without spawning another process per each session? I don't need to share any windows between session, just the status icon to be able to check service's status without taking additional actions..

It's not even possible. Shell_NotifyIcon communicates with a single instance of Explorer.EXE, the one running in the current user context.

Processes can only access the interactive window station and desktops in the same session as the process. So this means you need one process per session.

I know at least one program that do it - TightVNC server running as a service. You can lookup their sources to understandhow it's done.

Related

Is it possible to find out whether a process was started by a user or by another process via CreateProcess or ShellExecute?

I wanted to know if there was any way of checking if a particular process was started by the user by him/her double clicking, typing the required commands in cmd, via the address bar in explorer, etc. or by another program using CreateProcess() or ShellExecute().
I tried checking the parent process id of the created process but failed to see any consistency among the parent pids of the user initiated processes. I wanted to know if there was any other way or a fool proof way using the ppids.
First you have to determine what the "process started by user" means to you. From Windows' point of view all the processes are started by another processes, whether it was somehow triggered by user or not.
I can only think of getting processes belonging to currently logged on user otherwise i doubt that you can distinguish processes created on a system.

How can I autostart a UI-application under windows that a non-admin user cannot close?

I have developed a C# Windows Forms application that runs in the background as a systray icon and does some stuff when it's clicked. It is supposed to launch when Windows starts and run continously, and a normal user without administrator rights shall not be allowed to shut it down.
What is the best way to do this? I initially intended to run it on the LocalSystem account through Task Scheduler, but then I learned (the hard way) about Session 0 isolation (i.e. the application will run but its UI elements do not show). When I run it with the logged in user, even if it runs elevated, the user can still shut it down through task manager (without requiring elevation).
Is there any way to give a process from LocalSystem access to the UI? I have a winlogon and a csrss process from LocalSystem running in session 1, so I guess it can be done, I just don't know how. Or is there maybe an easier way to disallow users to shut down a process of their own through the task manager? The only other option I can think of is to create an extra Windows Service that keeps polling if the app is running, and immediately launches it again if someone kills it - but that seems incredibly clumsy (also, I want it to stay dead when it crashed by itself, to avoid a single bug causing infinite loops of process creation).
Deponds on why they can't shut it down.
The natural way to go would to have created a service, started by a high priv account, and then had the desktop app just show what it was doing.
If there's something that they should see, but don't becasue they aren't running the service monitor app. (and acknowledge message back to the service), send them an email, send their boss an email, send yourself one and then go shout at them.....
Be a lot easier than trying to get the lid back on this tin of worms.
A nice way to make sure the desktop app is ruuning, would be simply to schedule it to run every X, but drop out immediately if it already is or the somethingwenthorriblywrong flkag is set.
Not worth writing a service to check if it's still there, as they could kill that as well, unless you want to make that a service they can't kill. :(
You are trying to be too draconian with this. Add some sort of auditing so you can see it dies or was shutdown, monitor that and deal with any adverse reports. It's a heck of a lot easier, and gives manage something to do...
You can run an administrative process in the user's logon session. One method would be to for a master process (a system service) to duplicate its own token, use SetTokenInformation to change the session associated with the token, and then call CreateProcessAsUser. The lpStartupInfo parameter can be used to associate the process with a particular window station and desktop. It may be necessary to explicitly change the permissions on the window station and desktop first.
HOWEVER, this is a bad idea from a security standpoint, because GUI applications are vulnerable to malicious messages sent from other processes on the same desktop ("shatter attacks").
It would be safer to run the process in the user's own context but apply an ACL to it. This can be done using the lpProcessAttributes parameter to CreateProcess or CreateProcessAsUser, or with the SetSecurityInfo function. I've never tried this, but it should in theory prevent the user from using task manager to close the process.
If you are creating the process from the user's context, then the user will be the owner, so a sufficiently knowledgeable person could change the permissions back in order to terminate the process. If you need to block this hole, using CreateProcessAsUser from a privileged master process (the token can be duplicated from one of the existing processes in the user's session) should (again, in theory) mean that the user is not the process owner.
Another potential issue: if you listen for messages indicating that the user is logging out (in order to exit) such a message could be faked. If you don't then you need to find some other way of exiting when the user logs out. You may need to experiment here, I'm not sure how the system will react.

Is there a way to have multiple windows logins go to single session?

In windows 7, is there a way to have every login go to the same user session. So when a person is met with the login screen, they login and can continue working on that same user session. I am asking this because each user has their own login, but on this machine I need a program to be running across all user sessions. Since that doesn't seem feasible, I was just going to have them all login to the same user session.
Is this possible?
The appropriate way to solve this would be to have the program run as a service, and have a client UI that loads on startup 'hook' into the service process. Loading multiple users to the same session space would effectively violate the entire windows security model.
So, you either need to use a shared user for this, or a shared process (either local as a service, or remote as a server)
So, there's one possible way you might be able to get this to work, and that's to set this up as an interactive service. Definitely not a secure way to keep your system, but if you are able to make it work, it should work for your purposes:
Interactive services (in particular, read 'using an interactive service'):
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683502(v=vs.85).aspx
Making srvany.exe (to run non-services as a service) on Windows7/Windows 2008:
http://social.technet.microsoft.com/Forums/en-US/winserverMigration/thread/98a97aee-c62b-4683-94ab-3777899cf7de/

Is it possible to see system's user desktop? How to desktop of your user from another session?

I run Windows 7.
I run windows service that runs a program with GUI.
I cannot see the GUI of my program because it was started from another session by system or even my user.
Is there a way for me to see my program?
Switch desktop to system user?
Use SetThreadDesktop() to change the thread's context in your service to the user's desktop.
SetThreadDesktop() takes a handle to the desktop as it's first parameter; to get that handle, use EnumDesktops().
EnumDesktops() takes a handle to the window station as it's first parameter; to get that handle, use EnumWindowStations()
To understand what's going on with Window Stations and Desktops, try reading this overview from from MSDN.
Be cautious with this technique. Higher-privileged processes (i.e., services) interacting with the user's desktop are the basis for shatter attacks. You need to write a separate application that runs in the user's context and communicates with your service via pipes or similar.

How can I enumerate the open windows (~EnumWindows) of another user session

I have an application that can list the opened windows of the current session. It uses the EnumWindows method from the user32.dll.
I would like to run this code from a windows service, but as the service is not attached to a user session, it returns nothing obviously.
So the question is, how can I enumerate the open windows of another user session (e.g. with a specific logon user)?
Similarly to EnumWindows, I also would like to get the foreground window of the user session as well (like GetForegroundWindow works for the current user).
As far as I'm aware, you can't access the windows of one session from another. It's also worth noting that there's not really any such thing as "the current session" - there may be multiple users logged on through terminal services, or XP's fast user switching.
One approach to this would be to add a program to each user's profile with no UI that just communicates with your service. You'd still have to cope with the fact that there could be multiple active sessions, though.
According to this document you can create a process in an other user's logon session using CreateProcessAsUser, and could enumerate the windows there. You will still need some IPC mechanism to communicate with the service.
The accepted answer is not correct.
So the question is, how can I enumerate the open windows of another user session?
You can enumerate the open windows of any session if you're running as a service running as the local System account.
To do this first enumerate the sessions with WTSEnumerateSessions. Then enumerate the window stations inside each session with EnumWindowStations. Then enumerate the desktops for each Window Station with EnumDesktops. Finally you an enumerate the Windows in those Desktops with EnumWindows.
(e.g. with a specific logon user)
There can be many concurrent logged on users via Terminal services or fast user switching.
Similarly to EnumWindows, I also would like to get the foreground window of the user session as well (like GetForegroundWindow works for the current user).
This can be done by launching an app with a found user token in the Session, Window Station, and Desktop. From there you can call any Win32 API like GetForegroundWindow and report the info back to your parent process.
You can learn more about how Sessions, Window Stations, and Desktops work here.

Resources