Type a page name and press Enter. You'll jump to the page if it exists, or you can create it if it doesn't.
To create a page in a module other than advapi32, prefix the name with the module name and a period.
LsaLookupSids (advapi32)
.
C# Signature:
[DllImport("advapi32.dll", SetLastError=true)]
private static extern Int32 LsaLookupSids(
IntPtr PolicyHandle,
int Count,
IntPtr ptrEnumBuf,
out IntPtr ptrDomainList,
ref IntPtr ptrNameList);
VB Signature:
Declare Auto Function LsaLookupSids Lib "advapi32.dll" (PolicyHandle As IntPtr, Count As Integer, ByRef Sids As IntPtr, ByRef ReferencedDomains As IntPtr, ByRef Names As IntPtr) As Integer
User-Defined Types:
VB.NET:
<StructLayout(LayoutKind.Sequential)>
Structure LSA_REFERENCED_DOMAIN_LIST
Public Entries As ULong
Public Domains As LSA_TRUST_INFORMATION
End Structure
<StructLayout(LayoutKind.Sequential)>
Structure LSA_TRUST_INFORMATION
Public Name As LSA_UNICODE_STRING
Public Sid As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Structure LSA_UNICODE_STRING
Public Length, MaximumLength As UShort
<MarshalAs(UnmanagedType.LPWStr)> Public Buffer As String
End Structure
Alternative Managed API:
Do you know one? Please contribute it!
Notes:
There's a bug in the GetSIDInformation function below that causes it to fail on Win7 (at least 64-bit). tsids is freed after translating to an LSA_TRANSLATED_SID2, but this leaves the Sid IntPtr dangling, which causes a failure when I go to use it later.
Tips & Tricks:
Please add some!
Sample Code:
using System;
using System.Collections.Generic;
using System.Text;
namespace LsaSecurity
{
/*
* LsaWrapper class credit: Willy Denoyette [MVP]
*
* http://www.hightechtalks.com/csharp/lsa-functions-276626.html
*
* Added support for:
*
* LsaLookupSids
*
* for the purposes of providing a working example.
*
*
*
*/
using System.Runtime.InteropServices;
using System.Security;
using System.Management;
using System.Runtime.CompilerServices;
using System.ComponentModel;
using LSA_HANDLE = IntPtr;
public class Program
{
public static void Main()
{
using (LsaWrapper lsaSec = new LsaWrapper())
{
string[] accounts = lsaSec.GetUsersWithPrivilege("SeNetworkLogonRight");
public LsaWrapper()
: this(null)
{ }
// // local system if systemName is null
public LsaWrapper(string systemName)
{
LSA_OBJECT_ATTRIBUTES lsaAttr;
lsaAttr.RootDirectory = IntPtr.Zero;
lsaAttr.ObjectName = IntPtr.Zero;
lsaAttr.Attributes = 0;
lsaAttr.SecurityDescriptor = IntPtr.Zero;
lsaAttr.SecurityQualityOfService = IntPtr.Zero;
lsaAttr.Length = Marshal.SizeOf(typeof(LSA_OBJECT_ATTRIBUTES));
lsaHandle = IntPtr.Zero;
LSA_UNICODE_STRING[] system = null;
if (systemName != null)
{
system = new LSA_UNICODE_STRING[1];
system[0] = InitLsaString(systemName);
}
uint ret = Win32Sec.LsaOpenPolicy(system, ref lsaAttr, (int)Access.POLICY_ALL_ACCESS, out lsaHandle);
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
}
public string[] GetUsersWithPrivilege(string privilege)
{
LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1];
privileges[0] = InitLsaString(privilege);
IntPtr buffer;
int count;
uint ret =
Win32Sec.LsaEnumerateAccountsWithUserRight(lsaHandle, privileges, out buffer, out count);
if (ret != 0)
{
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if (ret == STATUS_INSUFFICIENT_RESOURCES || ret == STATUS_NO_MEMORY)
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
}
LSA_ENUMERATION_INFORMATION[] lsaInfo = new LSA_ENUMERATION_INFORMATION[count];
for (int i = 0, elemOffs = (int)buffer; i < count; i++)
{
lsaInfo[i] = (LSA_ENUMERATION_INFORMATION)Marshal.PtrToStructure((IntPtr)elemOffs, typeof(LSA_ENUMERATION_INFORMATION));
elemOffs += Marshal.SizeOf(typeof(LSA_ENUMERATION_INFORMATION));
}
LSA_HANDLE domains;
LSA_HANDLE names;
ret = Win32Sec.LsaLookupSids(lsaHandle, lsaInfo.Length, buffer, out domains, out names);
if (ret != 0)
{
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if (ret == STATUS_INSUFFICIENT_RESOURCES || ret == STATUS_NO_MEMORY)
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
}
/*string[] retNames = new string[count];
LSA_TRANSLATED_NAME[] lsaNames = new LSA_TRANSLATED_NAME[count];
for (int i = 0, elemOffs = (int)names; i < count; i++)
{
lsaNames[i] = (LSA_TRANSLATED_NAME)Marshal.PtrToStructure((LSA_HANDLE)elemOffs, typeof(LSA_TRANSLATED_NAME));
elemOffs += Marshal.SizeOf(typeof(LSA_TRANSLATED_NAME));
// Following code also fetches Domains and associates domains and usernames
string[] retNames = new string[count];
List<int> currentDomain = new List<int>();
int domainCount = 0;
LSA_TRANSLATED_NAME[] lsaNames = new LSA_TRANSLATED_NAME[count];
for (int i = 0, elemOffs = (int)names; i < count; i++)
{
lsaNames[i] = (LSA_TRANSLATED_NAME)Marshal.PtrToStructure((LSA_HANDLE)elemOffs, typeof(LSA_TRANSLATED_NAME));
elemOffs += Marshal.SizeOf(typeof(LSA_TRANSLATED_NAME));
LSA_UNICODE_STRING name = lsaNames[i].Name;
retNames[i] = name.Buffer.Substring(0, name.Length / 2);
if (!currentDomain.Contains(lsaNames[i].DomainIndex))
{
domainCount = domainCount + 1;
currentDomain.Add(lsaNames[i].DomainIndex);
}
//Error: not necessary to count domain names
}
string[] domainPtrNames = new string[count];
LSA_REFERENCED_DOMAIN_LIST[] lsaDomainNames = new LSA_REFERENCED_DOMAIN_LIST[count];
//Error: LSA_REFERENCED_DOMAIN_LIST is a structure, not an array
for (int i = 0, elemOffs = (int)domains; i < count; i++)
//Error: not necessary
{
lsaDomainNames[i] = (LSA_REFERENCED_DOMAIN_LIST)Marshal.PtrToStructure((LSA_HANDLE)elemOffs, typeof(LSA_REFERENCED_DOMAIN_LIST));
elemOffs += Marshal.SizeOf(typeof(LSA_REFERENCED_DOMAIN_LIST));
}
LSA_TRUST_INFORMATION[] lsaDomainName = new LSA_TRUST_INFORMATION[count];
string[] domainNames = new string[domainCount];
for (int i = 0, elemOffs = (int)lsaDomainNames[i].Domains; i < domainCount; i++)
{
lsaDomainName[i] = (LSA_TRUST_INFORMATION)Marshal.PtrToStructure((LSA_HANDLE)elemOffs, typeof(LSA_TRUST_INFORMATION));
elemOffs += Marshal.SizeOf(typeof(LSA_TRUST_INFORMATION));
static LSA_UNICODE_STRING InitLsaString(string s)
{
// Unicode strings max. 32KB
if (s.Length > 0x7ffe)
throw new ArgumentException("String too long");
LSA_UNICODE_STRING lus = new LSA_UNICODE_STRING();
lus.Buffer = s;
lus.Length = (ushort)(s.Length * sizeof(char));
lus.MaximumLength = (ushort)(lus.Length + sizeof(char));
// If unicode issues then do this instead of previous two line
//lus.Length = (ushort)(s.Length * 2); // Unicode char is 2 bytes
//lus.MaximumLength = (ushort)(lus.Length + 2)
return lus;
}
public bool WriteToConsole
{
set { this._writeToConsole = value; }
}
}
}
An IntPtr is a pointer to a memory location (unmanaged) that adapts to the platform it is running on (64-bit, etc.) UNLIKE a standard int/Integer. You should always use this type for unmanaged calls that require it, even though an int will appear to work on your development machine.
1/13/2008 4:00:13 AM - Damon Carr-72.43.165.29
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).