How to logoff a user when the workstation is locked? - c++

I wrote a Windows application that comes with two modules: service and user-mode applications. The service implements its own scheduler and may log-off a user at a predefined time. For that I was using the following call that is triggered from my user-mode module running in a logged-on user session that has to be logged off:
BOOL result = ExitWindowsEx(EWX_LOGOFF, reason);
This works fine, except of the situation when a user's account is locked. In that case that API doesn't seem to do anything at all even through I get 1 returned from it.
So I was curious, is there any other way to log off a user when their account is locked? (One condition I have in this case is that if that user had any unsaved documents then the log-off should not be forced.)

Try this:
DWORD dFlags = EWX_LOGOFF | EWX_FORCE | 0x10200;
BOOL result = ExitWindowsEx(dFlags, reason);

Related

Calling OpenWindowStation from a service running under a "user" account

My service start an interactive client process with something really similar to this: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379608(v=vs.85).aspx
It works when the service Log On as Local System, and it work if it's running under an Administrator account with the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME privileges.
My issue is when using a Standard User account OR Local Service, it fails at OpenWindowStation with error code 5 (ACCESS DENIED).
// Get a handle to the interactive window station.
hwinsta = OpenWindowStation(_T("winsta0"), // the interactive window station
FALSE, // handle is not inheritable
READ_CONTROL | WRITE_DAC); // rights to read/write the DACL
Is it possible to call OpenWindowStation from a Standard User account or my service must run under an Administrator account? I tried almost all Local Policies without success
Thanks!
Unfortunately it can't be done, it seems that only an Administrator can open the interactive station.

CreateProcessAsUser creates blank/black window

I'm using CreateProcessAsUser to create a process under user-specified credentials.
I'm posting what are hopefully the relevant parts of the code. Let me know if you want to see anything more.
First LogonUser to get the token:
result = LogonUser(
username,
wcschr(username, '#') ? NULL : (domain ? domain : L"."),
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hrunastoken);
I then load the profile, set the lpDesktop value of the STARTUPINFO structure to NULL (which makes it use the desktop of the calling process), and call CreateProcessAsUser:
result = CreateProcessAsUser(
hrunastoken,
NULL,
apptorun,
NULL,
NULL,
FALSE,
CREATE_UNICODE_ENVIRONMENT,
envblock ? envblock : NULL,
NULL,
&si,
&pi);
This works fine - it logs in and creates the process successfully, and the process "works". The problem is that the windows it creates are black, as in this screenshot of a notepad process started with my program:
Possibly relevant context:
My account is a local account on a Windows 7 machine with full admin rights, and I am logged on with that account. I used psexec (Sysinternals utility) to open a command prompt running interactively under the local system account. I am launching my program from that command prompt. The credentials I am passing to it are from my account.
I have not done anything with permissions to windowstations/desktops; I assume the process I create should have rights to those as the process is being created in my session and using the same account I'm already logged in with - albeit going through the SYSTEM account first. Using Process Explorer, I don't see any difference in the permissions on the values and handles to windowstation/desktop by the process opened via my program vs opened normally. Maybe that's completely irrelevant.
I also cannot use CreateProcessWithLogonW function because it must work when run from the SYSTEM account - that function as well as the "runas" program that comes with Windows don't work under SYSTEM.
Funnily enough, I can't use my current method to open processes unless I'm running it under the SYSTEM account, as "a required privilege is not held by the client", so I can't compare the windows created when starting my program under my account vs the SYSTEM account...
The default DACL for window stations and desktops grant full access to the logon SID (which is unique to the current logon session) rather than to the user's SID. (The user's SID also appears in the DACL for the window station but has only limited permissions. It does not appear in the desktop DACL.)
The call to LogonUser generates a new session (and associated logon SID) rather than reusing the existing one, so your process does not have access to the desktop, and only has minimal access to the window station. (Actually I'm slightly puzzled as to how the process manages to run at all; when I tried to reproduce your results the process exited immediately with exit code 0xC0000142, as expected.)
The second piece of code in this answer shows how to change the DACL on the window station and desktop to allow the process to run properly. (This may not be the best solution, however, depending on your specific goals.)

Trying to interpret user session states on Windows OS

If I call the following API from a local service running on Windows 7:
WTS_SESSION_INFO* pWSI;
DWORD nCntWSI;
WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWSI, &nCntWSI);
and then go through all returned WTS_SESSION_INFO structs in pWSI and check WTS_CONNECTSTATE_CLASS State members, can someone explain what is the difference between WTSActive and WTSConnected?
Connected means the user has connected and has been (or soon will be) presented with a login screen but hasn't completed it and been verified yet. He might be typing his password, for example.
If the user has locked the workstation, it's been locked by a screensaver, or he has switched to another user account, it doesn't end his session. The user remains logged in and his session would remain marked active. So being connected but not active means there are no processes running under that user's account. (The one caveat being there could be a service or other process running in a separate session under that user's credentials, but that's a different matter.)

How to get the logged on user from a process running as root?

I have a program running as root and call another program to run(A).
I want A to run when the user logs on. I've used command: su - 'username' -c A,
or in the A main function, I've called: setuid(current_uid_logged).
But I don't know the way to get the user-name of the logged on user, or the uid in the root process.
Ways that I've tried: getenv("USERNAME") or getlogin() always return root account.
I've confused with getlogin(), my program is running when kernel start and wait for user login (I have a thread to wait a Finder process (Mac OSX) running to detect user logged on), wait 10 seconds and call getlogin() but sometime, it returned root but can return user login. I think Finder process is running when user logged on.
But when I call my app to run with sudo command, getlogin() always returns current user logged on.
How do I do this?
getlogin(3) returns the name of the user who owns the process's controlling terminal. This has nothing to do with the username of whoever might log in to the GUI of the operating system. Instead, getlogin(3) and getuid(2) will only ever return the name / uid of the user account that started the program -- they have more to do with the process history than with any user sitting in front of the computer.
There are similar stories with the environment variables USER and LOGNAME -- if either one was set in a process, it was by a process higher in the process's call tree. It too cannot be influenced by whichever user eventually sits in front of the computer.
I'm sure there is some mechanism to discover the currently-logged-on user on an OS X machine, but it won't be a traditional Unix API that provides it to you.
how about uid_t getuid()?
more details at http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man2/getuid.2.html

How to know whether I have admin authority in windows?

Is there any APIs in windows to detect whether the current user(current now) has the admin authority?
BOOL IsHasAuthority()
{
}
Many Thanks!
How to Determine Whether a Process or Thread Is Running As an Administrator
Use this solution when you are writing
an application that must determine
whether any of the following is true:
The current user can perform administrative tasks. The current
user is a member of the
Administrators group. A supplied token handle represents an
administrator with an elevated token.
A token handle represents a user who is a member of the
Administrators group.
The program is running with an elevated token or needs to spawn a
child program that is elevated so it
can perform administrative tasks.
You can use the Windows API function CheckTokenMembership(). The MSDN documentation for that function has an example demonstrating how to check for membership in the Administrators local group.