private static IdentityReferenceCollection TranslateToNTAccounts(IdentityReferenceCollection sourceSids, out bool someFailed)
{
if (sourceSids == null)
{
throw new ArgumentNullException("sourceSids");
}
if (sourceSids.Count == 0)
{
throw new ArgumentException(SR.Arg_EmptyCollection, "sourceSids");
}
Contract.EndContractBlock();
IntPtr[] SidArrayPtr = new IntPtr[sourceSids.Count];
GCHandle[] HandleArray = new GCHandle[sourceSids.Count];
SafeLsaPolicyHandle LsaHandle = SafeLsaPolicyHandle.InvalidHandle;
SafeLsaMemoryHandle ReferencedDomainsPtr = SafeLsaMemoryHandle.InvalidHandle;
SafeLsaMemoryHandle NamesPtr = SafeLsaMemoryHandle.InvalidHandle;
try
{
//
// Pin all elements in the array of SIDs
//
int currentSid = 0;
foreach (IdentityReference id in sourceSids)
{
SecurityIdentifier sid = id as SecurityIdentifier;
if (sid == null)
{
throw new ArgumentException(SR.Argument_ImproperType, "sourceSids");
}
HandleArray[currentSid] = GCHandle.Alloc(sid.BinaryForm, GCHandleType.Pinned);
SidArrayPtr[currentSid] = HandleArray[currentSid].AddrOfPinnedObject();
currentSid++;
}
//
// Open LSA policy (for lookup requires it)
//
LsaHandle = Win32.LsaOpenPolicy(null, PolicyRights.POLICY_LOOKUP_NAMES);
//
// Perform the actual lookup
//
someFailed = false;
uint ReturnCode;
ReturnCode = Interop.mincore.LsaLookupSids(LsaHandle, sourceSids.Count, SidArrayPtr, ref ReferencedDomainsPtr, ref NamesPtr);
//
// Make a decision regarding whether it makes sense to proceed
// based on the return code and the value of the forceSuccess argument
//
if (ReturnCode == Interop.StatusOptions.STATUS_NO_MEMORY ||
ReturnCode == Interop.StatusOptions.STATUS_INSUFFICIENT_RESOURCES)
{
throw new OutOfMemoryException();
}
else if (ReturnCode == Interop.StatusOptions.STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
else if (ReturnCode == Interop.StatusOptions.STATUS_NONE_MAPPED ||
ReturnCode == Interop.StatusOptions.STATUS_SOME_NOT_MAPPED)
{
someFailed = true;
}
else if (ReturnCode != 0)
{
int win32ErrorCode = Interop.mincore.RtlNtStatusToDosError(unchecked ((int)ReturnCode));
Debug.Assert(false, string.Format(CultureInfo.InvariantCulture, "Interop.LsaLookupSids returned {0}", win32ErrorCode));
throw new Win32Exception(win32ErrorCode);
}
NamesPtr.Initialize((uint)sourceSids.Count, (uint)Marshal.SizeOf <Interop.LSA_TRANSLATED_NAME>());
Win32.InitializeReferencedDomainsPointer(ReferencedDomainsPtr);
//
// Interpret the results and generate NTAccount objects
//
IdentityReferenceCollection Result = new IdentityReferenceCollection(sourceSids.Count);
if (ReturnCode == 0 || ReturnCode == Interop.StatusOptions.STATUS_SOME_NOT_MAPPED)
{
//
// Interpret the results and generate NT Account objects
//
Interop.LSA_REFERENCED_DOMAIN_LIST rdl = ReferencedDomainsPtr.Read <Interop.LSA_REFERENCED_DOMAIN_LIST>(0);
string[] ReferencedDomains = new string[rdl.Entries];
for (int i = 0; i < rdl.Entries; i++)
{
Interop.LSA_TRUST_INFORMATION ti = (Interop.LSA_TRUST_INFORMATION)Marshal.PtrToStructure <Interop.LSA_TRUST_INFORMATION>(new IntPtr((long)rdl.Domains + i * Marshal.SizeOf <Interop.LSA_TRUST_INFORMATION>()));
ReferencedDomains[i] = Marshal.PtrToStringUni(ti.Name.Buffer, ti.Name.Length / sizeof(char));
}
Interop.LSA_TRANSLATED_NAME[] translatedNames = new Interop.LSA_TRANSLATED_NAME[sourceSids.Count];
NamesPtr.ReadArray(0, translatedNames, 0, translatedNames.Length);
for (int i = 0; i < sourceSids.Count; i++)
{
Interop.LSA_TRANSLATED_NAME Ltn = translatedNames[i];
switch ((SidNameUse)Ltn.Use)
{
case SidNameUse.User:
case SidNameUse.Group:
case SidNameUse.Alias:
case SidNameUse.Computer:
case SidNameUse.WellKnownGroup:
string account = Marshal.PtrToStringUni(Ltn.Name.Buffer, Ltn.Name.Length / sizeof(char));;
string domain = ReferencedDomains[Ltn.DomainIndex];
Result.Add(new NTAccount(domain, account));
break;
default:
someFailed = true;
Result.Add(sourceSids[i]);
break;
}
}
}
else
{
for (int i = 0; i < sourceSids.Count; i++)
{
Result.Add(sourceSids[i]);
}
}
return(Result);
}
finally
{
for (int i = 0; i < sourceSids.Count; i++)
{
if (HandleArray[i].IsAllocated)
{
HandleArray[i].Free();
}
}
LsaHandle.Dispose();
ReferencedDomainsPtr.Dispose();
NamesPtr.Dispose();
}
}