5

I have a simple C++ program that prompt the user name

#include <windows.h>
#include <Lmcons.h>
#include <winbase.h>

int _tmain(int argc, _TCHAR* argv[])
{
    wchar_t username[UNLEN + 1];
    DWORD username_len = UNLEN + 1;
    ::GetUserName(username, &username_len);

    MessageBox(NULL, username, NULL, 1);
    return 1;
}

GetUserName() performs as expected in administrator accounts, meaning print the real user name.

However, when run as administrator in a non-administrator account, I get the administrator name, and not the the real logged user.

I believe this behavior is expected since it is documented in GetUserName():
If the current thread is impersonating another client, the GetUserName function returns the user name of the client that the thread is impersonating.

Question

Is there a way to get the real logged in user (the non-admin one), even if the process run as administrator?

idanshmu
  • 5,061
  • 6
  • 46
  • 92
  • The above "solutions" don't work. This does: https://stackoverflow.com/questions/5218778/how-do-i-get-the-currently-logged-username-from-a-windows-service-in-net – UserX Aug 31 '17 at 18:13
  • 1
    @UserX, that question asks about getting the currently logged-on user from a service. This question asks about getting the currently logged-on user from an interactive application. They're different problems, and need different solutions. – Harry Johnston Aug 31 '17 at 21:22

2 Answers2

8

I believe the question you want to ask Windows is "which user is logged into the current session".

To do this, call ProcessIdToSessionId() with your own process's ID to determine the current session ID.

Then call WTSQuerySessionInformation() with the WTSUserName option to fetch the user name.

Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
  • 1
    According to https://msdn.microsoft.com/en-us/library/aa383838%28v=vs.85%29.aspx , it's not – igal k Feb 24 '15 at 09:28
  • 1
    @igalk: XP is out of support, so references to it are slowly disappearing from the documentation. According to a reliable source, WTSQuerySessionInformation() has been available since Windows 2000. – Harry Johnston Feb 24 '15 at 19:29
4

The problem is not a thread which is impersonating. You're running the entire application under the administrator login. That's why Windows asked you to login with an administrator account, when you started it from a non-admin account.

Thus, the result you get from GetUserName() is correct. That name is the real logged-in user of your app.

If you wanted the other name, the standard solution is to start as a normal user, and have an "elevate" button which restarts your application with elevated privileges. Look as Task Manager, it does this if you want to see all running processes. At this point you can of course pass anything you want to the new process, including that user name.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • I'd like to know if there is an option to get the real logged-in user whiting an elevated process? – idanshmu Feb 23 '15 at 12:59
  • @idanshmu: I don't think the question is well-defined. **What** real logged-in user? Because as far as Windows is concerned, you provided the administrator password to log in as administrator. How are you not the administrator, then? – MSalters Feb 23 '15 at 13:12
  • The **real** user is the one who activated the process, if I'm log in as `idan` and run process as administrator, the **real** user is `idan`. Anyway, I'd like to be able to get `idan` instead of the administrator name. for example, I've been told that even though you run the process as administrator, the active desktop is still on the **real** user control. there must be some way to get this name. – idanshmu Feb 23 '15 at 13:17
  • Well, the desktop is just a big window managed by an Explorer.Exe process. And that process presumably has "idan" as its owner. But for security reasons, UIPI (UI Process Isolation) will separate your Administrator app from less-secure processes. Why do you even need this name? – MSalters Feb 23 '15 at 13:23
  • I don't want the process user name. I'd like to be able to get *real* user name, regardless of the way my app is being run. To me, `GetUserName()` should return the last logged user (excluding of course the required logging due to the elevated process). – idanshmu Feb 23 '15 at 13:29
  • But 'last logged in" wouldn't be the same as the desktop owner, if the last log in was for a "Run As..." command, or if that was on another desktop (XP introduced Fast User Switching after all). I think your definition of "real" user does not match a concept in Windows. – MSalters Feb 23 '15 at 13:38
  • I 100% agree that my _definition of **real** user does not match a concept in Windows_. However the question still remains open based on my definition and desire. – idanshmu Feb 23 '15 at 13:44
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/71498/discussion-between-msalters-and-idanshmu). – MSalters Feb 23 '15 at 14:03