Following the provided link to the code http://www.hightechtalks.com/csharp/lsa-functions-276626.html
IntPtr GetSIDInformation(string account) { LSA_UNICODE_STRING[] names = new LSA_UNICODE_STRING[1]; LSA_TRANSLATED_SID2 lts; IntPtr tsids = IntPtr.Zero; IntPtr tdom = IntPtr.Zero; names[0] = InitLsaString(account); lts.Sid = IntPtr.Zero; Console.WriteLine("String account: {0}", names[0].Length); int ret = Win32Sec.LsaLookupNames2(lsaHandle, 0, 1, names, ref tdom, ref tsids); if (ret != 0) { throw new Win32Exception(Win32Sec.LsaNtStatusToWinError(ret)); } lts = (LSA_TRANSLATED_SID2) Marshal.PtrToStructure(tsids, typeof(LSA_TRANSLATED_SID2)); Win32Sec.LsaFreeMemory(tsids); Win32Sec.LsaFreeMemory(tdom); return lts.Sid; }
lts (LSA_TRANSLATED_SID2 structure) contains a pointer that points to memory that is freed up by a call to Win32Sec.LsaFreeMemory. Using a pointer after freeing memory is bad practice and will have unpredictable results - it may even βworkβ.
Fine-tuning the code by reference using the SecurityIdentifier class (.Net 2 and higher) with a slight cleaning of unnecessary code avoids a memory problem.
using System; namespace Willys.LsaSecurity { using System.ComponentModel; using System.Runtime.InteropServices; using System.Security; using System.Security.Principal; using LSA_HANDLE = IntPtr; [StructLayout(LayoutKind.Sequential)] struct LSA_OBJECT_ATTRIBUTES { internal int Length; internal IntPtr RootDirectory; internal IntPtr ObjectName; internal int Attributes; internal IntPtr SecurityDescriptor; internal IntPtr SecurityQualityOfService; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct LSA_UNICODE_STRING { internal ushort Length; internal ushort MaximumLength; [MarshalAs(UnmanagedType.LPWStr)] internal string Buffer; } sealed class Win32Sec { [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] internal static extern uint LsaOpenPolicy( LSA_UNICODE_STRING[] SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, int AccessMask, out IntPtr PolicyHandle ); [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] internal static extern uint LsaAddAccountRights( LSA_HANDLE PolicyHandle, IntPtr pSID, LSA_UNICODE_STRING[] UserRights, int CountOfRights ); [DllImport("advapi32")] internal static extern int LsaNtStatusToWinError(int NTSTATUS); [DllImport("advapi32")] internal static extern int LsaClose(IntPtr PolicyHandle); } sealed class Sid : IDisposable { public IntPtr pSid = IntPtr.Zero; public SecurityIdentifier sid = null; public Sid(string account) { sid = (SecurityIdentifier) (new NTAccount(account)).Translate(typeof(SecurityIdentifier)); Byte[] buffer = new Byte[sid.BinaryLength]; sid.GetBinaryForm(buffer, 0); pSid = Marshal.AllocHGlobal(sid.BinaryLength); Marshal.Copy(buffer, 0, pSid, sid.BinaryLength); } public void Dispose() { if (pSid != IntPtr.Zero) { Marshal.FreeHGlobal(pSid); pSid = IntPtr.Zero; } GC.SuppressFinalize(this); } ~Sid() { Dispose(); } } public sealed class LsaWrapper : IDisposable { enum Access : int { POLICY_READ = 0x20006, POLICY_ALL_ACCESS = 0x00F0FFF, POLICY_EXECUTE = 0X20801, POLICY_WRITE = 0X207F8 } const uint STATUS_ACCESS_DENIED = 0xc0000022; const uint STATUS_INSUFFICIENT_RESOURCES = 0xc000009a; const uint STATUS_NO_MEMORY = 0xc0000017; IntPtr lsaHandle; public LsaWrapper() : this(null) { }
Bob reynolds
source share