Home
Products
Forums
Help
Publish Article

Get user account SID and domain name

In our earlier article, How to get user SID using DirectoryServices classes, we showed you how to use DirectoryServices classes to do it. Here is another technique but this time it will not use DirectoryServices, but it uses PInvoke/Interop to call LookupAccountName Win32 API. Following code shows the prototype that you will need to define to call the API.

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

namespace PardesiServices.SecurityInterop
{
	[ StructLayout( LayoutKind.Sequential )]
	public struct SID_IDENTIFIER_AUTHORITY
	{
		[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
		public byte[] Value;
	};
	public class SecurityApiWin32
	{	
		[DllImport("Advapi32.dll",  SetLastError=true)]
		public static extern int LookupAccountName(
			string ServerName,
			string AccountName,
			IntPtr Sid,
			ref int SidSize,
			StringBuilder DomainName,
			ref int DomainNameSize,
			ref short SidUse);
	}
}						
						

Then you can call this prototype to get the user's domain, SID and type of account. Remeber that every account created under windows in User account. It can be of different type i.e. User or Group. There is one thing that we would like to point out. The buffer for variables Sid and DomainName are to be supplied by the caller and they should be of size to accomodate all the information that API needs to return. If you pass the values for SidSize and DomainNameSize variables as ZERO initially, then the API fills these variables with the actual required sizes. And then in next call you can allocate the memory buffer both the variables and get the required information. The SID value is returned as IntPtr. To convert this into string representation. You can either use Win32 ConvertSidToString API using PInvoke or the utility function ConvertByteToStringSid that we wrote that converts Byte array into text string. We prefer to use ConvertByteToStringSid because it is guranteed to work on every platform whereas ConvertSidToString is only available on Windows 2000 and higher. And the other advantage is that you will not incur another PInvoke context switch overhead for second call.

public bool LookupAccountName(string strServer, string strAccountName,
	 out string accountSid, out string strDomainName,
	 out short AccountType)
{
	bool bRet = false;
	int lSidSize = 256;
	int lDomainNameSize = 256;

	accountSid = "";
	strDomainName = "";
	AccountType = 0;
	StringBuilder strName;
	lSidSize = 0;
	IntPtr Sid = IntPtr.Zero;
			
	// First get the required buffer sizes for SID and domain name.
	int nRet = SecurityApiWin32.LookupAccountName(
						strServer,
						strAccountName,
						Sid,
						ref lSidSize,
						null,
						ref lDomainNameSize,
						ref AccountType);
	bRet = (0 != nRet);
	if (!bRet)
	{
		int nErr = Marshal.GetLastWin32Error();
		if (122 == nErr) // Buffer too small
		{
			// Allocate the buffers with actual sizes that are required
			// for SID and domain name.
			strName = new StringBuilder(lDomainNameSize);
			Sid = Marshal.AllocHGlobal(lSidSize);
			nRet = SecurityApiWin32.LookupAccountName(
				strServer,
				strAccountName,
				Sid,
				ref lSidSize,
				strName,
				ref lDomainNameSize,
				ref AccountType);
			bRet = (0 != nRet);
			if (bRet)
			{
				byte [] sidArray = new byte[lSidSize];
				strDomainName = strName.ToString();
				Marshal.Copy(Sid, sidArray, 0, lSidSize);
				accountSid = ConvertByteToStringSid(sidArray);
				Console.WriteLine("Domain Name: {0}", strDomainName);
				Console.WriteLine("Account Sid: {0}", accountSid);
			}
		}
		else
		{
			Console.WriteLine(nErr);
		}
	}
	Marshal.FreeHGlobal(Sid);
	return bRet;
}						
						
Go Freelance
Home     About us     Contact us    Copyright    Privacy Policy    Return Policy    Advertisers
Copyright © Netomatix