Search
Module:
Directory

   Desktop Functions:

   Smart Device Functions:


Show Recent Changes
Subscribe (RSS)
Misc. Pages
Comments
FAQ
Helpful Tools
Playground
Suggested Reading
Website TODO List
Download Visual Studio Add-In

LookupAccountSid (advapi32)
 
.
Summary
The LookupAccountSid function accepts a security identifier (SID) as input. It retrieves the name of the account for this SID and the name of the first domain on which this SID is found.

C# Signature:

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError = true)]
static extern bool LookupAccountSid(
    string lpSystemName,
    [MarshalAs(UnmanagedType.LPArray)] byte[] Sid,
    System.Text.StringBuilder lpName,
    ref uint cchName,
    System.Text.StringBuilder ReferencedDomainName,
    ref uint cchReferencedDomainName,
    out SID_NAME_USE peUse);        
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool LookupAccountSid(
    [MarshalAs(UnmanagedType.LPTStr)] string strSystemName,
    IntPtr pSid,
    IntPtr pName,
    ref uint cchName,
    IntPtr pReferencedDomainName,
    ref uint cchReferencedDomainName,
    out SID_NAME_USE peUse);

VB Signature:

    Declare Function LookupAccountSid Lib "advapi32.dll" _
    Alias "LookupAccountSidA" ( _
    ByVal systemName As String, _
    ByVal psid As Byte(), _
    ByVal accountName As String, _
    ByRef cbAccount As Integer, _
    ByVal domainName As String, _
    ByRef cbDomainName As Integer, _
    ByRef use As Integer) As Boolean

User-Defined Types:

None.

Notes:

The LookupAccountSid function attempts to find a name for the specified SID by first checking a list of well-known SIDs. If the supplied SID does not correspond to a well-known SID, the function checks built-in and administratively defined local accounts. Next, the function checks the primary domain. Security identifiers not recognized by the primary domain are checked against the trusted domains that correspond to their SID prefixes.

If the function cannot find an account name for the SID, the LookupAccountSid function fails and GetLastError returns ERROR_NONE_MAPPED. This can occur if a network time-out prevents the function from finding the name. It also occurs for SIDs that have no corresponding account name, such as a logon SID that identifies a logon session.

In addition to looking up SIDs for local accounts, local domain accounts, and explicitly trusted domain accounts, LookupAccountSid can look up SIDs for any account in any domain in the forest, including SIDs that appear only in the SIDhistory field of an account in the forest. The SIDhistory field stores former SIDs of an account that has been moved from another domain. To look up a SID, LookupAccountSid queries the global catalog of the forest.

Windows NT 4.0: Forest lookup and account lookup by SIDhistory are not supported.

Tips & Tricks:

Please add some!

Sample Code:

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace test
{
  class Class1
  {
    const int NO_ERROR = 0;
    const int ERROR_INSUFFICIENT_BUFFER = 122;

    enum SID_NAME_USE
    {
      SidTypeUser = 1,
      SidTypeGroup,
      SidTypeDomain,
      SidTypeAlias,
      SidTypeWellKnownGroup,
      SidTypeDeletedAccount,
      SidTypeInvalid,
      SidTypeUnknown,
      SidTypeComputer
    }

    [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError = true)]
    static extern bool LookupAccountSid (
      string lpSystemName,
      [MarshalAs(UnmanagedType.LPArray)] byte[] Sid,
      StringBuilder lpName,
      ref uint cchName,
      StringBuilder ReferencedDomainName,
      ref uint cchReferencedDomainName,
      out SID_NAME_USE peUse);    

    [STAThread]
    static void Main(string[] args)
    {
      StringBuilder name = new StringBuilder();
      uint cchName = (uint)name.Capacity;
      StringBuilder referencedDomainName = new StringBuilder();
      uint cchReferencedDomainName = (uint)referencedDomainName.Capacity;
      SID_NAME_USE sidUse;
      // Sid for BUILTIN\Administrators
      byte[] Sid = new byte[] {1,2,0,0,0,0,0,5,32,0,0,0,32,2};

      int err = NO_ERROR;
      if (!LookupAccountSid(null,Sid,name,ref cchName,referencedDomainName,ref cchReferencedDomainName,out sidUse))
      {
    err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
    if (err == ERROR_INSUFFICIENT_BUFFER)
    {
      name.EnsureCapacity((int)cchName);
      referencedDomainName.EnsureCapacity((int)cchReferencedDomainName);
      err = NO_ERROR;
      if (!LookupAccountSid(null,Sid,name,ref cchName,referencedDomainName,ref cchReferencedDomainName,out sidUse))
        err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
    }
      }
      if (err == 0)
    Console.WriteLine(@"Found account {0} : {1}\{2}",sidUse,referencedDomainName.ToString(),name.ToString());
      else
    Console.WriteLine(@"Error : {0}",err);
    }
  }
}

Sample Code 2:

private static string DownLevelLogonNameFromSid(string strSystemName, IntPtr pSID, string strFullFileName, System.Windows.Forms.IWin32Window oOwner)
{
  string strDownLevelLogonName = null;

  UInt32 cchName = 0;
  UInt32 cchReferencedDomainName = 0;
  SID_NAME_USE SidType = SID_NAME_USE.SidTypeUnknown;
  LookupAccountSid(strSystemName, pSID, IntPtr.Zero, ref cchName, IntPtr.Zero, ref cchReferencedDomainName, out SidType);
  int nLastError = Marshal.GetLastWin32Error();
  if (nLastError != ERROR_INSUFFICIENT_BUFFER)
  {
   ErrorMsgBox("LookupAccountSid failed for file " + strFullFileName + ", Win32 error code: " + nLastError.ToString(), oOwner);
   return null;
  }
  IntPtr pAccountName = Marshal.AllocHGlobal((int)cchName * sizeof(Char));
  IntPtr pReferencedDomainName = Marshal.AllocHGlobal((int)cchReferencedDomainName * sizeof(Char));
  if (pAccountName == IntPtr.Zero || pReferencedDomainName == IntPtr.Zero)
  {
   ErrorMsgBox("No Memory!");
   return null;
  }

  for (int i = 0; i < 2; i++)
  {
   // Two tries to handle occasional timeouts.
   bool bOK = LookupAccountSid(strSystemName, pSID, pAccountName, ref cchName, pReferencedDomainName, ref cchReferencedDomainName, out SidType);
   if (bOK)
   {
    if (pSID != IntPtr.Zero)
    {
     string strReferencedDomainName = Marshal.PtrToStringAuto(pReferencedDomainName);
     string strAccountName = Marshal.PtrToStringAuto(pAccountName);
     if (strReferencedDomainName.Length > 0)
      strDownLevelLogonName = strReferencedDomainName + @"\" + strAccountName;
     else
      strDownLevelLogonName = strAccountName;
    }
    break;
   }
   else
   {
    nLastError = Marshal.GetLastWin32Error();
    if (nLastError == ERROR_NONE_MAPPED)
    {
     if (i == 1)
      ErrorMsgBox("No mapping between account names and security IDs done for file " + strFullFileName + " (Win32 error code " + nLastError.ToString() + ")", oOwner);
    }
    else
    {
     ErrorMsgBox("LookupAccountSid failed for file " + strFullFileName + ", Win32 error code: " + nLastError.ToString(), oOwner);
    }
    System.Threading.Thread.Sleep(500); // 500 ms
   }
  } // end for

  Marshal.FreeHGlobal(pReferencedDomainName);
  Marshal.FreeHGlobal(pAccountName);

  return strDownLevelLogonName;
}

VB.NET Example:

    Private Shared Function MyLookupAccountSid(ByRef i_Sid() As Byte) As String

    'Input format is the format returned from "ConvertStringSidToSid"
    'Note; This function needs some work. For example, checking l_Result for error codes!

    Dim result As String = ""
    Try
        '****************************************************************
        '* Declares
        '****************************************************************

        Dim l_Result As Long
        Dim l_use As Long
        Dim l_UserName As String
        Dim l_Domain As String
        Dim l_UserNameLength As Integer = 0
        Dim l_DomainLength As Integer = 0

        '****************************************************************
        '* First call, populate l_UserNameLength and l_DomainLength
        '****************************************************************

        l_Result = LookupAccountSid(Nothing, i_Sid, l_UserName, l_UserNameLength, l_Domain, l_DomainLength, l_use)

        '****************************************************************
        '* Allocate space
        '****************************************************************

        l_UserName = Strings.StrDup(l_UserNameLength + 1, " ")  'Need space for terminating chr(0)?
        l_Domain = Strings.StrDup(l_DomainLength + 1, " ")

        '****************************************************************
        '* Fetch username and domain
        '****************************************************************

        l_Result = LookupAccountSid(Nothing, i_Sid, l_UserName, l_UserNameLength, l_Domain, l_DomainLength, l_use)

        '****************************************************************
        '* Build result
        '****************************************************************

        result = l_Domain.Substring(0, l_DomainLength) & "\" & l_UserName.Substring(0, l_UserNameLength)

    Catch ex As Exception
        result = ""
    End Try

    Return result

    End Function

Alternative Managed API:

Available in .Net 2.0:

    using System.Security.Principal;

    // convert the user sid to a domain\name
    string account = new SecurityIdentifier(stringSid).Translate(typeof(NTAccount)).ToString();

But SecurityIdentifier.Translate() method works only on domain accounts. To resolve local SIDs into account name you can use Win32 API function LookupAccountSid().

Documentation

Please edit this page!

Do you have...

  • helpful tips or sample code to share for using this API in managed code?
  • corrections to the existing content?
  • variations of the signature you want to share?
  • additional languages you want to include?

Select "Edit This Page" on the right hand toolbar and edit it! Or add new pages containing supporting types needed for this API (structures, delegates, and more).

 
Access PInvoke.net directly from VS:
Terms of Use
Edit This Page
Find References
Show Printable Version
Revisions