How can I get the SID of the current Windows account?
Asked Answered
C

11

32

I am looking for an easy way to get the SID for the current Windows user account. I know I can do it through WMI, but I don't want to go that route.

Apologies to everybody that answered in C# for not specifying it's C++. :-)

Capua answered 30/10, 2008 at 18:27 Comment(1)
programming language/environment?Impermeable
A
56

In Win32, call GetTokenInformation, passing a token handle and the TokenUser constant. It will fill in a TOKEN_USER structure for you. One of the elements in there is the user's SID. It's a BLOB (binary), but you can turn it into a string by using ConvertSidToStringSid.

To get hold of the current token handle, use OpenThreadToken or OpenProcessToken.

If you prefer ATL, it has the CAccessToken class, which has all sorts of interesting things in it.

.NET has the Thread.CurrentPrinciple property, which returns an IPrincipal reference. You can get the SID:

IPrincipal principal = Thread.CurrentPrincipal;
WindowsIdentity identity = principal.Identity as WindowsIdentity;
if (identity != null)
    Console.WriteLine(identity.User);

Also in .NET, you can use WindowsIdentity.GetCurrent(), which returns the current user ID:

WindowsIdentity identity = WindowsIdentity.GetCurrent();
if (identity != null)
    Console.WriteLine(identity.User);
Analogize answered 30/10, 2008 at 18:37 Comment(1)
Using .NET from Powershell: > [System.Security.Principal.WindowsIdentity]::GetCurrent().User.ValueStudnia
E
10
ATL::CAccessToken accessToken;
ATL::CSid currentUserSid;
if (accessToken.GetProcessToken(TOKEN_READ | TOKEN_QUERY) &&
    accessToken.GetUser(&currentUserSid))
    return currentUserSid.Sid();
Excisable answered 13/11, 2012 at 6:7 Comment(1)
This is very concise.Cowart
B
7

This should give you what you need:

using System.Security.Principal;

...

var sid = WindowsIdentity.GetCurrent().User;

The User property of WindowsIdentity returns the SID, per MSDN Docs

Bucella answered 30/10, 2008 at 18:37 Comment(0)
R
3

CodeProject has a few different methods you can try... You didn't mention what languages you wanted a solution in.

If you want to access it via a batch file or something, you can look as PsGetSid by Sysinternals. It translates SIDs to names and vice versa.

Rigmarole answered 30/10, 2008 at 18:31 Comment(0)
P
2

In C# you can use either

using Microsoft.Win32.Security;

...

string username = Environment.UserName + "@" + Environment.GetEnvironmentVariable("USERDNSDOMAIN");

Sid sidUser = new Sid (username);

Or...

using System.Security.AccessControl;

using System.Security.Principal;

...

WindowsIdentity m_Self = WindowsIdentity.GetCurrent();

SecurityIdentifier m_SID = m_Self.Owner;");

Preshrunk answered 30/10, 2008 at 18:53 Comment(0)
C
2

I found another way to get SID:

System.Security.Principal.WindowsIdentity id = System.Security.Principal.WindowsIdentity.GetCurrent();
string sid = id.User.AccountDomainSid.ToString();
Cantlon answered 13/1, 2012 at 12:26 Comment(1)
This is the sid of the domain not of the user account use id.User.ToString() for the user's sidBaziotes
T
1

And in native code:

function GetCurrentUserSid: string;

    hAccessToken: THandle;
    userToken: PTokenUser;
    dwInfoBufferSize: DWORD;
    dw: DWORD;

    if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, ref hAccessToken) then
        dw <- GetLastError;
        if dw <> ERROR_NO_TOKEN then
            RaiseLastOSError(dw);

        if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, ref hAccessToken) then
            RaiseLastOSError;
    try
        userToken <- GetMemory(1024);
        try
            if not GetTokenInformation(hAccessToken, TokenUser, userToken, 1024, ref dwInfoBufferSize) then
                RaiseLastOSError;
            Result <- SidToString(userToken.User.Sid);
        finally
            FreeMemory(userToken);
    finally
        CloseHandle(hAccessToken);
Tuesday answered 16/8, 2017 at 15:11 Comment(0)
O
1

This question is tagged as c++ And I answer in c++ language, So I recommend use of WMI tool :

So, As WMI commands in powershell, bellow command get SID of system-pc1 user :

Get-WmiObject win32_useraccount -Filter "name = 'system-pc1'" | Select-Object sid

First, you need to get current username with bellow code :

char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);

Now you can try with WQL language and execute this query in c++ as bellow (in this example , I used of system-pc1 username in WQL_WIN32_USERACCOUNT_QUERY query :

#define                 NETWORK_RESOURCE                    "root\\CIMV2"
#define                 WQL_LANGUAGE                        "WQL"
#define                 WQL_WIN32_USERACCOUNT_QUERY         "SELECT * FROM Win32_Useraccount where name='system-pc1'"
#define                 WQL_SID                             "SID"

IWbemLocator            *pLoc = 0;              // Obtain initial locator to WMI to a particular host computer
IWbemServices           *pSvc = 0;              // To use of connection that created with CoCreateInstance()
ULONG                   uReturn = 0;
HRESULT                 hResult = S_OK;         // Result when we initializing
IWbemClassObject        *pClsObject = NULL;     // A class for handle IEnumWbemClassObject objects
IEnumWbemClassObject    *pEnumerator = NULL;    // To enumerate objects
VARIANT                 vtSID = { 0 };          // OS name property

// Initialize COM library
hResult = CoInitializeEx(0, COINIT_MULTITHREADED);
if (SUCCEEDED(hResult))
{
    // Initialize security
    hResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
        RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    if (SUCCEEDED(hResult))
    {
        // Create only one object on the local system
        hResult = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
            IID_IWbemLocator, (LPVOID*)&pLoc);

        if (SUCCEEDED(hResult))
        {
            // Connect to specific host system namespace
            hResult = pLoc->ConnectServer(TEXT(NETWORK_RESOURCE), NULL, NULL,
                0, NULL, 0, 0, &pSvc);
            if (SUCCEEDED(hResult))
            {
                /* Set the IWbemServices proxy
                * So the impersonation of the user will be occurred */
                hResult = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
                    NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
                    NULL, EOAC_NONE);
                if (SUCCEEDED(hResult))
                {
                    /* Use the IWbemServices pointer to make requests of WMI
                    * For example, query for user account */
                    hResult = pSvc->ExecQuery(TEXT(WQL_LANGUAGE), TEXT(WQL_WIN32_USERACCOUNT_QUERY),
                        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
                    if (SUCCEEDED(hResult))
                    {
                        // Go to get the next object from IEnumWbemClassObject
                        pEnumerator->Next(WBEM_INFINITE, 1, &pClsObject, &uReturn);
                        if (uReturn != 0)
                        {
                            // Get the value of the "sid, ..." property
                            pClsObject->Get(TEXT(WQL_SID), 0, &vtSID, 0, 0);
                            VariantClear(&vtSID);

                            // Print SID
                            wcout << vtSID.bstrVal;

                            pClsObject->Release();
                            pClsObject = NULL;
                        }
                    }
                }
            }
        }
    }

    // Cleanup
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    // Uninitialize COM library
    CoUninitialize();

This example does works properly!

Orenorenburg answered 12/11, 2018 at 6:28 Comment(0)
T
1

in cmd.exe

whoami /user

if you need it programatically, please ask more specified

Tat answered 14/11, 2019 at 9:44 Comment(2)
Questioner specifically asks for a C++ solution.Epileptoid
Fair enough, calling system("whoami /user"); is technically a C++ solution, and I should've specified I would like to do this through calling Windows API directly instead.Capua
R
0

You didn't specify what language you want. But if you're up for C# this article offers both the WMI method as well as a faster (while more verbose) method utilizing the Win32 API.

http://www.codeproject.com/KB/cs/processownersid.aspx

I don't think there's currently another way of doing this without using WMI or the Win32 API.

Renaissance answered 30/10, 2008 at 18:34 Comment(0)
D
0

This one is the shortest of them all I believe.

UserPrincipal.Current.Sid;

Available with .net >= 3.5

Demetria answered 23/10, 2012 at 14:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.