コード例 #1
0
        /// <summary>
        /// Creates a Security Descriptor from an SDDL string
        /// </summary>
        /// <param name="sddl">The SDDL string that represents the Security Descriptor</param>
        /// <returns>The Security Descriptor represented by the SDDL string</returns>
        /// <exception cref="System.FormatException" />
        public static SecurityDescriptor SecurityDescriptorFromString(string sddl)
        {
            var sddlRegex = new Regex(sddlExpr, RegexOptions.IgnoreCase);

            var m = sddlRegex.Match(sddl);

            if (!m.Success)
            {
                throw new FormatException("Invalid SDDL String Format");
            }

            var sd = new SecurityDescriptor();

            if (m.Groups["owner"] != null && m.Groups["owner"].Success && !string.IsNullOrEmpty(m.Groups["owner"].Value))
            {
                sd.Owner = SecurityIdentity.SecurityIdentityFromString(m.Groups["owner"].Value);
            }

            if (m.Groups["group"] != null && m.Groups["group"].Success && !string.IsNullOrEmpty(m.Groups["group"].Value))
            {
                sd.Group = SecurityIdentity.SecurityIdentityFromString(m.Groups["group"].Value);
            }

            if (m.Groups["dacl"] != null && m.Groups["dacl"].Success && !string.IsNullOrEmpty(m.Groups["dacl"].Value))
            {
                sd.DACL = AccessControlList.AccessControlListFromString(m.Groups["dacl"].Value);
            }

            if (m.Groups["sacl"] != null && m.Groups["sacl"].Success && !string.IsNullOrEmpty(m.Groups["sacl"].Value))
            {
                sd.SACL = AccessControlList.AccessControlListFromString(m.Groups["sacl"].Value);
            }

            return(sd);
        }
コード例 #2
0
 public AccessControlEntry(AccessControlEntry original)
 {
     this.accountSID        = original.accountSID;
     this.aceType           = original.aceType;
     this.flags             = original.flags;
     this.inheritObjectGuid = original.inheritObjectGuid;
     this.objectGuid        = original.objectGuid;
     this.rights            = original.rights;
 }
コード例 #3
0
 public AccessControlEntry(AccessControlEntry original)
 {
     accountSID        = original.accountSID;
     aceType           = original.aceType;
     flags             = original.flags;
     inheritObjectGuid = original.inheritObjectGuid;
     objectGuid        = original.objectGuid;
     rights            = original.rights;
 }
コード例 #4
0
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return(false);
            }
            if (obj is SecurityIdentity)
            {
                SecurityIdentity sd = (SecurityIdentity)obj;

                return(string.Compare(this.SID, sd.SID, true) == 0);
            }
            return(false);
        }
コード例 #5
0
        /// <summary>
        /// Creates a Security Identity for a well known SID (such as LOCAL SYSTEM)
        /// </summary>
        /// <param name="sidType">The type of well known SID</param>
        /// <returns>A populated Security Identity</returns>
        public static SecurityIdentity SecurityIdentityFromWellKnownSid(WELL_KNOWN_SID_TYPE sidType)
        {
            if (sidType == WELL_KNOWN_SID_TYPE.None)
            {
                throw new ExternalException("Unable to Get Well Known SID");
            }

            var secId = new SecurityIdentity
            {
                wellKnownSidType = sidType
            };

            // Get the size required for the SID
            var size = GetSidLengthRequired(SID_MAX_SUB_AUTHORITIES);;

            var sidStruct = Marshal.AllocHGlobal((IntPtr)size);

            try
            {
                // Get the SID struct from the well known SID type
                if (!CreateWellKnownSid(sidType, IntPtr.Zero, sidStruct, ref size))
                {
                    throw new ExternalException("Unable to Get Well Known SID");
                }

                var sidString = IntPtr.Zero;

                // Convert the SID structure to a SID string
                ConvertSidToStringSid(sidStruct, out sidString);

                try
                {
                    // Marshal and store the SID string
                    secId.sid = Marshal.PtrToStringAnsi(sidString);
                }
                finally
                {
                    if (sidString != IntPtr.Zero)
                    {
                        Util.LocalFree(sidString);
                    }
                }

                uint nameLen   = 0;
                uint domainLen = 0;


                // Get the lengths of the object and domain names
                LookupAccountSid(null, sidStruct, IntPtr.Zero, ref nameLen, IntPtr.Zero, ref domainLen, out var nameUse);

                if (nameLen == 0)
                {
                    throw new ExternalException("Unable to Find SID");
                }

                var accountName = Marshal.AllocHGlobal((IntPtr)nameLen);
                var domainName  = domainLen > 0 ? Marshal.AllocHGlobal((IntPtr)domainLen) : IntPtr.Zero;

                try
                {
                    // Get the object and domain names
                    if (!LookupAccountSid(null, sidStruct, accountName, ref nameLen, domainName, ref domainLen, out nameUse))
                    {
                        throw new ExternalException("Unable to Find SID");
                    }

                    // Marshal and store the object name
                    secId.name = string.Format("{0}{1}{2}", domainLen > 1 ? Marshal.PtrToStringAnsi(domainName) : "", domainLen > 1 ? "\\" : "", Marshal.PtrToStringAnsi(accountName));
                }
                finally
                {
                    if (accountName != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(accountName);
                    }
                    if (domainName != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(domainName);
                    }
                }
            }
            finally
            {
                if (sidStruct != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(sidStruct);
                }
            }

            return(secId);
        }
コード例 #6
0
        /// <summary>
        /// Creates a Security Identity from an object name (e.g. DOMAIN\AccountName)
        /// </summary>
        /// <param name="name">A security object name (i.e. a Computer, Account, or Group)</param>
        /// <returns>A populated Security Identity</returns>
        public static SecurityIdentity SecurityIdentityFromName(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }

            if (name == "")
            {
                throw new ArgumentException("Argument 'name' cannot be the empty string.", "name");
            }

            var attribs = new LSA_OBJECT_ATTRIBUTES
            {
                Attributes               = 0,
                ObjectName               = IntPtr.Zero,
                RootDirectory            = IntPtr.Zero,
                SecurityDescriptor       = IntPtr.Zero,
                SecurityQualityOfService = IntPtr.Zero
            };

            attribs.Length = (uint)Marshal.SizeOf(attribs);


            var status = LsaOpenPolicy(IntPtr.Zero, ref attribs, ACCESS_MASK.POLICY_LOOKUP_NAMES, out var handle);

            if (status != 0)
            {
                throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(LsaNtStatusToWinError(status)));
            }

            try
            {
                var nameString = new LSA_UNICODE_STRING
                {
                    Buffer    = name,
                    Length    = (ushort)(name.Length * UnicodeEncoding.CharSize),
                    MaxLength = (ushort)(name.Length * UnicodeEncoding.CharSize + UnicodeEncoding.CharSize)
                };

                status = LsaLookupNames2(handle, 0, 1, new LSA_UNICODE_STRING[] { nameString }, out var domains, out var sids);

                if (status != 0)
                {
                    throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(LsaNtStatusToWinError(status)));
                }

                try
                {
                    var secId = new SecurityIdentity();

                    var lsaSid = (LSA_TRANSLATED_SID2)Marshal.PtrToStructure(sids, typeof(LSA_TRANSLATED_SID2));

                    var sidStruct = lsaSid.Sid;

                    var sidString = IntPtr.Zero;

                    // Get the SID string
                    if (!ConvertSidToStringSid(sidStruct, out sidString))
                    {
                        throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(Util.GetLastError()));
                    }

                    try
                    {
                        // Marshal and store the SID string
                        secId.sid = Marshal.PtrToStringAnsi(sidString);
                    }
                    finally
                    {
                        if (sidString != IntPtr.Zero)
                        {
                            Util.LocalFree(sidString);
                        }
                    }

                    // Check if the SID is a well known SID
                    secId.wellKnownSidType = (WELL_KNOWN_SID_TYPE)Array.IndexOf <string>(wellKnownSids, secId.sid);


                    uint nameLen   = 0;
                    uint domainLen = 0;

                    // Get the lengths for the object and domain names
                    LookupAccountSid(null, sidStruct, IntPtr.Zero, ref nameLen, IntPtr.Zero, ref domainLen, out var nameUse);

                    if (nameLen == 0)
                    {
                        throw new ExternalException("Unable to Find SID: " + Util.GetErrorMessage(Util.GetLastError()));
                    }

                    var accountName = Marshal.AllocHGlobal((IntPtr)nameLen);
                    var domainName  = domainLen > 0 ? Marshal.AllocHGlobal((IntPtr)domainLen) : IntPtr.Zero;

                    try
                    {
                        // Get the object and domain names
                        if (!LookupAccountSid(null, sidStruct, accountName, ref nameLen, domainName, ref domainLen, out nameUse))
                        {
                            throw new ExternalException("Unable to Find SID: " + Util.GetErrorMessage(Util.GetLastError()));
                        }

                        // Marshal and store the object name
                        secId.name = string.Format("{0}{1}{2}", domainLen > 1 ? Marshal.PtrToStringAnsi(domainName) : "", domainLen > 1 ? "\\" : "", Marshal.PtrToStringAnsi(accountName));

                        return(secId);
                    }
                    finally
                    {
                        if (accountName != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(accountName);
                        }
                        if (domainName != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(domainName);
                        }
                    }
                }
                finally
                {
                    if (domains != IntPtr.Zero)
                    {
                        LsaFreeMemory(domains);
                    }
                    if (sids != IntPtr.Zero)
                    {
                        LsaFreeMemory(sids);
                    }
                }
            }
            finally
            {
                if (handle != IntPtr.Zero)
                {
                    LsaClose(handle);
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// Creates a Security Identity from a SID string
        /// </summary>
        /// <param name="sid">A SID string (Format: S-1-1-...) or well known SID abbreviation (e.g. DA)</param>
        /// <returns>A populated Security Identity</returns>
        public static SecurityIdentity SecurityIdentityFromString(string sid)
        {
            if (sid == null)
            {
                throw new ArgumentNullException("sid");
            }

            if (sid == "")
            {
                throw new ArgumentException("Argument 'sid' cannot be the empty string.", "sid");
            }

            if (!sid.StartsWith("S-"))
            {
                // If the string is not a SID string (S-1-n-...) assume it is a SDDL abbreviation
                return(SecurityIdentityFromWellKnownSid(GetWellKnownSidTypeFromSddlAbbreviation(sid)));
            }

            var secId = new SecurityIdentity
            {
                sid = sid
            };

            // Check if the SID is a well known SID
            secId.wellKnownSidType = (WELL_KNOWN_SID_TYPE)Array.IndexOf <string>(wellKnownSids, secId.sid);


            // Convert the SID string to a SID structure
            if (!ConvertStringSidToSid(sid, out var sidStruct))
            {
                throw new ExternalException(string.Format("Error Converting SID String to SID Structur: {0}", Util.GetErrorMessage(Util.GetLastError())));
            }

            try
            {
                uint nameLen   = 0;
                uint domainLen = 0;


                // Get the lengths of the object and domain names
                LookupAccountSid(null, sidStruct, IntPtr.Zero, ref nameLen, IntPtr.Zero, ref domainLen, out var nameUse);

                if (nameLen == 0)
                {
                    throw new ExternalException("Unable to Find SID");
                }

                var accountName = Marshal.AllocHGlobal((IntPtr)nameLen);
                var domainName  = domainLen > 0 ? Marshal.AllocHGlobal((IntPtr)domainLen) : IntPtr.Zero;

                try
                {
                    // Get the object and domain names
                    if (!LookupAccountSid(null, sidStruct, accountName, ref nameLen, domainName, ref domainLen, out nameUse))
                    {
                        throw new ExternalException("Unable to Find SID");
                    }

                    // Marshal and store the object name
                    secId.name = string.Format("{0}{1}{2}", domainLen > 1 ? Marshal.PtrToStringAnsi(domainName) : "", domainLen > 1 ? "\\" : "", Marshal.PtrToStringAnsi(accountName));
                }
                finally
                {
                    if (accountName != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(accountName);
                    }
                    if (domainName != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(domainName);
                    }
                }
            }
            finally
            {
                if (sidStruct != IntPtr.Zero)
                {
                    Util.LocalFree(sidStruct);
                }
            }

            return(secId);
        }
コード例 #8
0
 public AccessControlEntry(SecurityIdentity account)
 {
     this.AccountSID = account;
 }
コード例 #9
0
        public static AccessControlEntry AccessControlEntryFromString(string aceString)
        {
            Regex aceRegex = new Regex(aceExpr, RegexOptions.IgnoreCase);

            Match aceMatch = aceRegex.Match(aceString);

            if (!aceMatch.Success)
            {
                throw new FormatException("Invalid ACE String Format");
            }

            AccessControlEntry ace = new AccessControlEntry();

            if (aceMatch.Groups["ace_type"] != null && aceMatch.Groups["ace_type"].Success && !string.IsNullOrEmpty(aceMatch.Groups["ace_type"].Value))
            {
                int aceTypeValue = Array.IndexOf(aceTypeStrings, aceMatch.Groups["ace_type"].Value.ToUpper());

                if (aceTypeValue == -1)
                {
                    throw new FormatException("Invalid ACE String Format");
                }

                ace.aceType = (AceType)aceTypeValue;
            }
            else
            {
                throw new FormatException("Invalid ACE String Format");
            }

            if (aceMatch.Groups["ace_flags"] != null && aceMatch.Groups["ace_flags"].Success && !string.IsNullOrEmpty(aceMatch.Groups["ace_flags"].Value))
            {
                string aceFlagsValue = aceMatch.Groups["ace_flags"].Value.ToUpper();
                for (int i = 0; i < aceFlagsValue.Length - 1; i += 2)
                {
                    int flagValue = Array.IndexOf(aceFlagStrings, aceFlagsValue.Substring(i, 2));

                    if (flagValue == -1)
                    {
                        throw new FormatException("Invalid ACE String Format");
                    }

                    ace.flags = ace.flags | ((AceFlags)(int)Math.Pow(2.0d, flagValue));
                }
            }

            if (aceMatch.Groups["rights"] != null && aceMatch.Groups["rights"].Success && !string.IsNullOrEmpty(aceMatch.Groups["rights"].Value))
            {
                string rightsValue = aceMatch.Groups["rights"].Value.ToUpper();
                for (int i = 0; i < rightsValue.Length - 1; i += 2)
                {
                    int rightValue = Array.IndexOf(rightsStrings, rightsValue.Substring(i, 2));

                    if (rightValue == -1)
                    {
                        throw new FormatException("Invalid ACE String Format");
                    }

                    ace.Add((AceRights)(int)Math.Pow(2.0d, rightValue));
                }
            }

            if (aceMatch.Groups["object_guid"] != null && aceMatch.Groups["object_guid"].Success && !string.IsNullOrEmpty(aceMatch.Groups["object_guid"].Value))
            {
                ace.objectGuid = new Guid(aceMatch.Groups["object_guid"].Value);
            }

            if (aceMatch.Groups["inherit_object_guid"] != null && aceMatch.Groups["inherit_object_guid"].Success && !string.IsNullOrEmpty(aceMatch.Groups["inherit_object_guid"].Value))
            {
                ace.inheritObjectGuid = new Guid(aceMatch.Groups["inherit_object_guid"].Value);
            }

            if (aceMatch.Groups["account_sid"] != null && aceMatch.Groups["account_sid"].Success && !string.IsNullOrEmpty(aceMatch.Groups["account_sid"].Value))
            {
                ace.AccountSID = SecurityIdentity.SecurityIdentityFromString(aceMatch.Groups["account_sid"].Value.ToUpper());
            }
            else
            {
                throw new FormatException("Invalid ACE String Format");
            }

            return(ace);
        }
コード例 #10
0
        /// <summary>
        /// Creates a Security Identity for a well known SID (such as LOCAL SYSTEM)
        /// </summary>
        /// <param name="sidType">The type of well known SID</param>
        /// <returns>A populated Security Identity</returns>
        public static SecurityIdentity SecurityIdentityFromWellKnownSid(WELL_KNOWN_SID_TYPE sidType)
        {
            if (sidType == WELL_KNOWN_SID_TYPE.None)
            {
                throw new ExternalException("Unable to Get Well Known SID");
            }

            SecurityIdentity secId = new SecurityIdentity();

            secId.wellKnownSidType = sidType;

            // Get the size required for the SID
            uint size = SecurityIdentity.GetSidLengthRequired(SecurityIdentity.SID_MAX_SUB_AUTHORITIES); ;

            IntPtr sidStruct = Marshal.AllocHGlobal((IntPtr)size);

            try
            {
                // Get the SID struct from the well known SID type
                if (!SecurityIdentity.CreateWellKnownSid(sidType, IntPtr.Zero, sidStruct, ref size))
                {
                    throw new ExternalException("Unable to Get Well Known SID");
                }

                IntPtr sidString = IntPtr.Zero;

                // Convert the SID structure to a SID string
                SecurityIdentity.ConvertSidToStringSid(sidStruct, out sidString);

                try
                {
                    // Marshal and store the SID string
                    secId.sid = Marshal.PtrToStringAnsi(sidString);
                }
                finally
                {
                    if (sidString != IntPtr.Zero) Util.LocalFree(sidString);
                }

                uint nameLen = 0;
                uint domainLen = 0;

                SID_NAME_USE nameUse;

                // Get the lengths of the object and domain names
                SecurityIdentity.LookupAccountSid(null, sidStruct, IntPtr.Zero, ref nameLen, IntPtr.Zero, ref domainLen, out nameUse);

                if (nameLen == 0)
                {
                    throw new ExternalException("Unable to Find SID");
                }

                IntPtr accountName = Marshal.AllocHGlobal((IntPtr)nameLen);
                IntPtr domainName = domainLen > 0 ? Marshal.AllocHGlobal((IntPtr)domainLen) : IntPtr.Zero;

                try
                {
                    // Get the object and domain names
                    if (!SecurityIdentity.LookupAccountSid(null, sidStruct, accountName, ref nameLen, domainName, ref domainLen, out nameUse))
                    {
                        throw new ExternalException("Unable to Find SID");
                    }

                    // Marshal and store the object name
                    secId.name = String.Format("{0}{1}{2}", domainLen > 1 ? Marshal.PtrToStringAnsi(domainName) : "", domainLen > 1 ? "\\" : "", Marshal.PtrToStringAnsi(accountName));
                }
                finally
                {
                    if (accountName != IntPtr.Zero) Marshal.FreeHGlobal(accountName);
                    if (domainName != IntPtr.Zero) Marshal.FreeHGlobal(domainName);
                }
            }
            finally
            {
                if (sidStruct != IntPtr.Zero) Marshal.FreeHGlobal(sidStruct);
            }

            return secId;
        }
コード例 #11
0
        /// <summary>
        /// Creates a Security Identity from a SID string
        /// </summary>
        /// <param name="sid">A SID string (Format: S-1-1-...) or well known SID abbreviation (e.g. DA)</param>
        /// <returns>A populated Security Identity</returns>
        public static SecurityIdentity SecurityIdentityFromString(string sid)
        {
            if (sid == null)
            {
                throw new ArgumentNullException("sid");
            }

            if (sid == "")
            {
                throw new ArgumentException("Argument 'sid' cannot be the empty string.", "sid");
            }

            if (!sid.StartsWith("S-"))
            {
                // If the string is not a SID string (S-1-n-...) assume it is a SDDL abbreviation
                return SecurityIdentity.SecurityIdentityFromWellKnownSid(SecurityIdentity.GetWellKnownSidTypeFromSddlAbbreviation(sid));
            }

            SecurityIdentity secId = new SecurityIdentity();
            secId.sid = sid;

            // Check if the SID is a well known SID
            secId.wellKnownSidType = (WELL_KNOWN_SID_TYPE)Array.IndexOf<string>(SecurityIdentity.wellKnownSids, secId.sid);

            IntPtr sidStruct;

            // Convert the SID string to a SID structure
            if (!SecurityIdentity.ConvertStringSidToSid(sid, out sidStruct))
            {
                throw new ExternalException(String.Format("Error Converting SID String to SID Structur: {0}", Util.GetErrorMessage(Util.GetLastError())));
            }

            try
            {
                uint nameLen = 0;
                uint domainLen = 0;

                SID_NAME_USE nameUse;

                // Get the lengths of the object and domain names
                SecurityIdentity.LookupAccountSid(null, sidStruct, IntPtr.Zero, ref nameLen, IntPtr.Zero, ref domainLen, out nameUse);

                if (nameLen == 0) throw new ExternalException("Unable to Find SID");

                IntPtr accountName = Marshal.AllocHGlobal((IntPtr)nameLen);
                IntPtr domainName = domainLen > 0 ? Marshal.AllocHGlobal((IntPtr)domainLen) : IntPtr.Zero;

                try
                {
                    // Get the object and domain names
                    if (!SecurityIdentity.LookupAccountSid(null, sidStruct, accountName, ref nameLen, domainName, ref domainLen, out nameUse))
                    {
                        throw new ExternalException("Unable to Find SID");
                    }

                    // Marshal and store the object name
                    secId.name = String.Format("{0}{1}{2}", domainLen > 1 ? Marshal.PtrToStringAnsi(domainName) : "", domainLen > 1 ? "\\" : "", Marshal.PtrToStringAnsi(accountName));
                }
                finally
                {
                    if (accountName != IntPtr.Zero) Marshal.FreeHGlobal(accountName);
                    if (domainName != IntPtr.Zero) Marshal.FreeHGlobal(domainName);
                }
            }
            finally
            {
                if (sidStruct != IntPtr.Zero) Util.LocalFree(sidStruct);
            }

            return secId;
        }
コード例 #12
0
        /// <summary>
        /// Creates a Security Identity from an object name (e.g. DOMAIN\AccountName)
        /// </summary>
        /// <param name="name">A security object name (i.e. a Computer, Account, or Group)</param>
        /// <returns>A populated Security Identity</returns>
        public static SecurityIdentity SecurityIdentityFromName(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }

            if (name == "")
            {
                throw new ArgumentException("Argument 'name' cannot be the empty string.", "name");
            }

            LSA_OBJECT_ATTRIBUTES attribs = new LSA_OBJECT_ATTRIBUTES();
            attribs.Attributes = 0;
            attribs.ObjectName = IntPtr.Zero;
            attribs.RootDirectory = IntPtr.Zero;
            attribs.SecurityDescriptor = IntPtr.Zero;
            attribs.SecurityQualityOfService = IntPtr.Zero;
            attribs.Length = (uint)Marshal.SizeOf(attribs);

            IntPtr handle;

            int status = SecurityIdentity.LsaOpenPolicy(IntPtr.Zero, ref attribs, ACCESS_MASK.POLICY_LOOKUP_NAMES, out handle);

            if(status != 0)
            {
                throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(SecurityIdentity.LsaNtStatusToWinError(status)));
            }

            try
            {
                LSA_UNICODE_STRING nameString = new LSA_UNICODE_STRING();
                nameString.Buffer = name;
                nameString.Length = (ushort)(name.Length * UnicodeEncoding.CharSize);
                nameString.MaxLength = (ushort)(name.Length * UnicodeEncoding.CharSize + UnicodeEncoding.CharSize);

                IntPtr domains;
                IntPtr sids;

                status = SecurityIdentity.LsaLookupNames2(handle, 0, 1, new LSA_UNICODE_STRING[] { nameString }, out domains, out sids);

                if(status != 0)
                {
                    throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(SecurityIdentity.LsaNtStatusToWinError(status)));
                }

                try
                {
                    SecurityIdentity secId = new SecurityIdentity();

                    LSA_TRANSLATED_SID2 lsaSid = (LSA_TRANSLATED_SID2)Marshal.PtrToStructure(sids, typeof(LSA_TRANSLATED_SID2));

                    IntPtr sidStruct = lsaSid.Sid;

                    IntPtr sidString = IntPtr.Zero;

                    // Get the SID string
                    if (!SecurityIdentity.ConvertSidToStringSid(sidStruct, out sidString))
                    {
                        throw new ExternalException("Unable to Find Object: " + Util.GetErrorMessage(Util.GetLastError()));
                    }

                    try
                    {
                        // Marshal and store the SID string
                        secId.sid = Marshal.PtrToStringAnsi(sidString);
                    }
                    finally
                    {
                        if (sidString != IntPtr.Zero) Util.LocalFree(sidString);
                    }

                    // Check if the SID is a well known SID
                    secId.wellKnownSidType = (WELL_KNOWN_SID_TYPE)Array.IndexOf<string>(SecurityIdentity.wellKnownSids, secId.sid);

                    SID_NAME_USE nameUse;

                    uint nameLen = 0;
                    uint domainLen = 0;

                    // Get the lengths for the object and domain names
                    SecurityIdentity.LookupAccountSid(null, sidStruct, IntPtr.Zero, ref nameLen, IntPtr.Zero, ref domainLen, out nameUse);

                    if (nameLen == 0)
                    {
                        throw new ExternalException("Unable to Find SID: " + Util.GetErrorMessage(Util.GetLastError()));
                    }

                    IntPtr accountName = Marshal.AllocHGlobal((IntPtr)nameLen);
                    IntPtr domainName = domainLen > 0 ? Marshal.AllocHGlobal((IntPtr)domainLen) : IntPtr.Zero;

                    try
                    {
                        // Get the object and domain names
                        if (!SecurityIdentity.LookupAccountSid(null, sidStruct, accountName, ref nameLen, domainName, ref domainLen, out nameUse))
                        {
                            throw new ExternalException("Unable to Find SID: " + Util.GetErrorMessage(Util.GetLastError()));
                        }

                        // Marshal and store the object name
                        secId.name = String.Format("{0}{1}{2}", domainLen > 1 ? Marshal.PtrToStringAnsi(domainName) : "", domainLen > 1 ? "\\" : "", Marshal.PtrToStringAnsi(accountName));

                        return secId;
                    }
                    finally
                    {
                        if (accountName != IntPtr.Zero) Marshal.FreeHGlobal(accountName);
                        if (domainName != IntPtr.Zero) Marshal.FreeHGlobal(domainName);
                    }
                }
                finally
                {
                    if (domains != IntPtr.Zero) SecurityIdentity.LsaFreeMemory(domains);
                    if (sids != IntPtr.Zero) SecurityIdentity.LsaFreeMemory(sids);
                }
            }
            finally
            {
                if (handle != IntPtr.Zero) SecurityIdentity.LsaClose(handle);
            }
        }