C++ - GetUserName() when process is run as administrator
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.
C++ Get Username From Process
Use OpenProcessToken to get the token (obviously), then GetTokenInformation with the TokenOwner
flag to get the SID of the owner. Then you can use LookupAccountSid to get the username.
Is there any way to get non-admin user name when running app as admin
First off, why are you using SHGetKnownFolderPath()
to determine a username? That is not what that API is meant for. There are other APIs better suited for getting usernames.
Passing a NULL
token handle to SHGetKnownFolderPath()
(or any other API that takes a user token as input) will use the user account that is associated with the calling thread, which in this case is an admin user. For what you are asking, you need to pass in an actual token for the logged-in user instead. Or else impersonate the logged-in user before calling such an API with a NULL
user token.
WTQueryUserToken()
can certainly be used to get a user token, however it can only be used inside a service that is running under the SYSTEM
account. If your app is not running as such a service, you would have to create such a service for your app to communicate with.
Otherwise, you will just have to get the username from some another API.
For instance, you can use ProcessIdToSessionId()
to get the ID of the session that your app is running in (see Getting the Session ID of the Current Process), and then you can use WTSQuerySessionInformation(WTSUserName)
to get the logged-in username of that session.
Or, you can enumerate all running processes, looking for processes that are running in the same session ID as your app, until you find the explorer.exe
process, and then you can use OpenProcess()
and OpenProcessHandle()
to get the user's access token for that process, and then use GetTokenInformation()
(TokenUser
or TokenOwner
) to get the SID of that token, and then finally use LookupAccountSid()
to get the username of that SID.
C# window xp current user when using run as
The work around that I used was to place short cuts on the public desktop so everyone gets it. Basically I was hoping for a way around just using the public desktop. I am going to go ahead and put this down as the answer but if anyone else comes up with a solution I will mark it as the answer.
Checking if the current user is in the administrator group with WinAPI
if user member of BUILTIN\Administrators (S-1-5-32-544) group (alias) this sid present in it token groups. and usually only in this case (of course possible create token for not admin user with S-1-5-32-544 and for admin user without it). so simply and effective check - list token groups and look - are S-1-5-32-544 present here, with any attributes. IsUserAdmin
not simply check for this sid, but
Even if a SID is present in the token, the system may not use the
SID in an access check. The SID may be disabled or have the SE_GROUP_USE_FOR_DENY_ONLY attribute. The system uses only enabled SIDs to grant access when performing an access check.
when admin user (member of S-1-5-32-544 Alias) interactive login to system and UAC active - system filter it token, and set SE_GROUP_USE_FOR_DENY_ONLY attribute for S-1-5-32-544 (except built-in Administrator - S-1-5-32-500)
so code can be next:
inline ULONG BOOL_TO_ERROR(BOOL f)
{
return f ? NOERROR : GetLastError();
}
ULONG IsUserInAdminGroup(BOOLEAN* pb)
{
*pb = FALSE;
HANDLE hToken;
ULONG dwError = BOOL_TO_ERROR(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken));
if (dwError == NOERROR)
{
// /RTCs must be disabled !
static volatile UCHAR guz = 0;
PVOID stack = alloca(guz);
ULONG cb = 0, rcb = 0x100;
union {
PVOID buf;
PTOKEN_GROUPS ptg;
};
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
dwError = BOOL_TO_ERROR(GetTokenInformation(hToken, ::TokenGroups, buf, cb, &rcb));
} while (dwError == ERROR_INSUFFICIENT_BUFFER);
CloseHandle(hToken);
if (dwError == NOERROR)
{
if (ULONG GroupCount = ptg->GroupCount)
{
static const SID_IDENTIFIER_AUTHORITY NT_AUTHORITY = SECURITY_NT_AUTHORITY;
PSID_AND_ATTRIBUTES Groups = ptg->Groups;
do
{
PSID Sid = Groups++->Sid;
if (*GetSidSubAuthorityCount(Sid) == 2 &&
*GetSidSubAuthority(Sid, 0) == SECURITY_BUILTIN_DOMAIN_RID &&
*GetSidSubAuthority(Sid, 1) == DOMAIN_ALIAS_RID_ADMINS &&
!memcmp(&NT_AUTHORITY, GetSidIdentifierAuthority(Sid), sizeof(SID_IDENTIFIER_AUTHORITY)))
{
*pb = TRUE;
break;
}
} while (--GroupCount);
}
return NOERROR;
}
}
return dwError;
}
also possible do direct check of user sid from token - are it member of DOMAIN_ALIAS_RID_ADMINS
alias. here question - how exactly is the task, why this necessary at all. example of code (used ntsam.h and linked with samlib.lib - part of standard windows SDK)
HRESULT IsUserInAdminGroup(PSID UserSid, BOOLEAN* pb)
{
SAM_HANDLE ServerHandle, DomainHandle;
NTSTATUS status = SamConnect(0, &ServerHandle, SAM_SERVER_LOOKUP_DOMAIN, 0);
if (0 <= status)
{
ULONG len = GetSidLengthRequired(1);
PSID BuiltIn = (PSID)alloca(len);
static const SID_IDENTIFIER_AUTHORITY NT_AUTHORITY = SECURITY_NT_AUTHORITY;
InitializeSid(BuiltIn, const_cast<SID_IDENTIFIER_AUTHORITY*>(&NT_AUTHORITY), 1);
*GetSidSubAuthority(BuiltIn, 0) = SECURITY_BUILTIN_DOMAIN_RID;
status = SamOpenDomain(ServerHandle, DOMAIN_READ, BuiltIn, &DomainHandle);
SamCloseHandle(ServerHandle);
if (0 <= status)
{
ULONG MembershipCount, *Aliases;
status = SamGetAliasMembership(DomainHandle, 1, &UserSid, &MembershipCount, &Aliases);
SamCloseHandle(DomainHandle);
if (0 <= status)
{
PVOID buf = Aliases;
if (MembershipCount)
{
do
{
if (*Aliases++ == DOMAIN_ALIAS_RID_ADMINS)
{
*pb = TRUE;
break;
}
} while (--MembershipCount);
}
SamFreeMemory(buf);
}
}
}
return HRESULT_FROM_NT(status);
}
HRESULT IsUserInAdminGroup(BOOLEAN* pb)
{
*pb = FALSE;
HANDLE hToken;
ULONG dwError = BOOL_TO_ERROR(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken));
if (dwError == NOERROR)
{
// /RTCs must be disabled !
static volatile UCHAR guz = 0;
PVOID stack = alloca(guz);
ULONG cb = 0, rcb = 0x80;
union {
PVOID buf;
PTOKEN_USER ptu;
};
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
dwError = BOOL_TO_ERROR(GetTokenInformation(hToken, ::TokenUser, buf, cb, &rcb));
} while (dwError == ERROR_INSUFFICIENT_BUFFER);
CloseHandle(hToken);
if (dwError == NOERROR)
{
return IsUserInAdminGroup(ptu->User.Sid, pb);
}
}
return HRESULT_FROM_WIN32(dwError);
}
Related Topics
Creating a Counter That Stays Synchronized Across Mpi Processes
Non-Defaulted Operator <=> Doesn't Generate == and != in C++20
How to Have Static Data Members in a Header-Only Library
Why Is It Not Possible to Overload Class Templates
Using Vector<Char> as a Buffer Without Initializing It on Resize()
Are There Gotchas Using Varargs with Reference Parameters
"Symbol(S) Not Found for Architecture X86_64" on Qtcreator Project
Why am I Getting an Error Converting a 'Float**' to 'Const Float**'
How to Directly Bind a Member Function to an Std::Function in Visual Studio 11
Converting Epoch Time to "Real" Date/Time
Getting a Vector<Derived*> into a Function That Expects a Vector<Base*>
Move Semantics == Custom Swap Function Obsolete
How to Get the Process Name in C++
Need to Call a Function at Periodic Time Intervals in C++
Slot Is Being Called Multiple Times Every Time a Signal Is Emitted
Passing End of Transmission (Ctrl + D) Character in Eclipse Cdt Console