Retrieving the SID of a user or group account using the Win32 SDK and C#

Wednesday, May 27th, 2009

SIDs are very useful for using as unique identifers, especially when you are working with computers or situations in which both local computer user accounts as well as domain accounts are available with system permissions.
SIDs are also what a large percentage of permissions-based SDK calls use, and therefore it is very useful to take a user account name and return the SID.

.NET supports some of the features of the Windows file system out of the box, but if you are looking to go much deeper then it is time to jump into the Win32 SDK and PInvoke.

Retrieving the SID is a good starting point, so without further ado, here is my function with comments inline:

if (!result)
{
// There are other ways to retrieve the last error, but they are not friendly with C#
int err = Marshal.GetLastWin32Error();
// This will occur if your flags are wrong or the buffer has not been allocated
// This error will almost always occur the first time it hits LookupAccountName because the buffer size is unknown (and therefore not allocated)
if (err == 122 || err == 1004)
{
Sid = new byte[cbSid];
// This will ensure the array is the proper size in the string builder
referencedDomainName.EnsureCapacity((int)cchReferencedDomainName);
if (!LookupAccountName(null, AccountName, Sid, ref cbSid, referencedDomainName, ref cchReferencedDomainName, out sidUse))
// This will cast the error code to a user-friendly string
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
// Initialize a C#-version of a pointer for the SID to return
IntPtr ptrSid;
if (ConvertSidToStringSid(Sid, out ptrSid))
{
// Convert the Side to a string variant
string sidString = Marshal.PtrToStringAuto(ptrSid);
// Make sure to clean up your non-managed mess
LocalFree(ptrSid);
return sidString;
}
// Return empty if it fails, you could also throw an exception here
return string.Empty;
}

It may seem like a lot of code at first, but this is about as easy as it gets when it comes to the Win32 SDK.