public static uint ReadSecurityDescriptor(
            IntPtr pSECURITY_DESCRIPTOR,
            ref SecurityDescriptor ObjSecurityDescriptor)
        {
            Logger.Log(string.Format("SecurityDescriptorWrapper.ReadSecurityDescriptor()"), Logger.SecurityDescriptorLogLevel);

            Dictionary <string, List <LwAccessControlEntry> > SdDacls = null;
            IntPtr ptrSid;
            uint   errorReturn = 0;
            bool   bRet        = false;

            ObjSecurityDescriptor = new SecurityDescriptor();
            ObjSecurityDescriptor.InitailizeToNull();

            SecurityDescriptorApi.SECURITY_DESCRIPTOR sSECURITY_DESCRIPTOR = new SecurityDescriptorApi.SECURITY_DESCRIPTOR();

            try
            {
                if (pSECURITY_DESCRIPTOR != IntPtr.Zero)
                {
                    SdDacls = new Dictionary <string, List <LwAccessControlEntry> >();
                    IntPtr pDaclOffset;
                    bool   lpbDaclPresent   = false;
                    bool   lpbDaclDefaulted = false;

                    bRet = SecurityDescriptorApi.GetSecurityDescriptorDacl(pSECURITY_DESCRIPTOR, out lpbDaclPresent, out pDaclOffset, out lpbDaclDefaulted);
                    Logger.Log("SecurityDescriptorApi.GetSecurityDescriptorDacl iRet value", Logger.SecurityDescriptorLogLevel);

                    SecurityDescriptorApi.ACL_SIZE_INFORMATION AclSize = new SecurityDescriptorApi.ACL_SIZE_INFORMATION();
                    SecurityDescriptorApi.GetAclInformation(pDaclOffset, AclSize,
                                                            ((uint)Marshal.SizeOf(typeof(SecurityDescriptorApi.ACL_SIZE_INFORMATION))),
                                                            SecurityDescriptorApi.ACL_INFORMATION_CLASS.AclSizeInformation);

                    if (pDaclOffset != IntPtr.Zero)
                    {
                        SdDacls = new Dictionary <string, List <LwAccessControlEntry> >();
                        List <LwAccessControlEntry> daclInfo = new List <LwAccessControlEntry>();
                        for (int idx = 0; idx < AclSize.AceCount; idx++)
                        {
                            IntPtr pAce;
                            string sUsername, sDomain;

                            int err = SecurityDescriptorApi.GetAce(pDaclOffset, idx, out pAce);
                            SecurityDescriptorApi.ACCESS_ALLOWED_ACE ace = (SecurityDescriptorApi.ACCESS_ALLOWED_ACE)Marshal.PtrToStructure(pAce, typeof(SecurityDescriptorApi.ACCESS_ALLOWED_ACE));

                            IntPtr iter   = (IntPtr)((int)pAce + (int)Marshal.OffsetOf(typeof(SecurityDescriptorApi.ACCESS_ALLOWED_ACE), "SidStart"));
                            string strSID = GetObjectStringSid(iter);

                            //Commented this, to use it in feature
                            //IntPtr pTrustee = IntPtr.Zero;
                            //SecurityDescriptorApi.BuildTrusteeWithSid(out pTrustee, ptrSid);
                            //SecurityDescriptorApi.TRUSTEE trustee = new SecurityDescriptorApi.TRUSTEE();
                            //Marshal.PtrToStructure(pTrustee, trustee);

                            GetObjectLookUpName(iter, out sUsername, out sDomain);
                            if (String.IsNullOrEmpty(sUsername))
                            {
                                sUsername = strSID;
                            }

                            Logger.Log("Trustee = " + sUsername, Logger.SecurityDescriptorLogLevel);
                            Logger.Log(string.Format("SID={0} : AceType={1}/ AceMask={2}/ AceFlags={3}",
                                                     strSID,
                                                     ace.Header.AceType.ToString(),
                                                     ace.Mask.ToString(),
                                                     ace.Header.AceFlags.ToString()), Logger.SecurityDescriptorLogLevel);

                            LwAccessControlEntry Ace = new LwAccessControlEntry();
                            Ace.Username   = sUsername + "(" + sUsername + "@" + sDomain + ")";
                            Ace.SID        = strSID;
                            Ace.AceType    = Convert.ToInt32(ace.Header.AceType);
                            Ace.AccessMask = ace.Mask.ToString();
                            Ace.AceFlags   = Convert.ToInt32(ace.Header.AceFlags.ToString());
                            Ace.AceSize    = Convert.ToInt32(ace.Header.AceSize.ToString());

                            daclInfo.Add(Ace);
                        }
                        if (daclInfo != null && daclInfo.Count != 0)
                        {
                            List <LwAccessControlEntry> objectDacl = new List <LwAccessControlEntry>();
                            foreach (LwAccessControlEntry Ace in daclInfo)
                            {
                                if (!SdDacls.ContainsKey(Ace.Username))
                                {
                                    objectDacl = new List <LwAccessControlEntry>();
                                    objectDacl.Add(Ace);
                                    SdDacls.Add(Ace.Username, objectDacl);
                                }
                                else
                                {
                                    objectDacl = SdDacls[Ace.Username];
                                    objectDacl.Add(Ace);
                                    SdDacls[Ace.Username] = objectDacl;
                                }
                            }
                        }
                        ObjSecurityDescriptor.Descretionary_Access_Control_List = SdDacls;
                    }
                    else
                    {
                        ObjSecurityDescriptor.Descretionary_Access_Control_List = null;
                        ObjSecurityDescriptor.IsAccessDenied = true;
                    }

                    sSECURITY_DESCRIPTOR = (SecurityDescriptorApi.SECURITY_DESCRIPTOR)Marshal.PtrToStructure(pSECURITY_DESCRIPTOR, typeof(SecurityDescriptorApi.SECURITY_DESCRIPTOR));

                    //Get Security Descriptor Control
                    uint dwRevision;
                    SecurityDescriptorApi.SECURITY_DESCRIPTOR_CONTROL pControl;
                    SecurityDescriptorApi.GetSecurityDescriptorControl(pSECURITY_DESCRIPTOR, out pControl, out dwRevision);
                    ObjSecurityDescriptor.Control  = (uint)pControl;
                    ObjSecurityDescriptor.Revision = dwRevision;

                    //Get Security Descriptor Owner
                    bool lpbOwnerDefaulted = false;
                    ptrSid = IntPtr.Zero;
                    bRet   = SecurityDescriptorApi.GetSecurityDescriptorOwner(pSECURITY_DESCRIPTOR, out ptrSid, out lpbOwnerDefaulted);
                    Logger.Log("SecurityDescriptorApi.GetSecurityDescriptorOwner iRet value: " + Marshal.GetLastWin32Error());
                    ObjSecurityDescriptor.Owner = GetObjectStringSid(ptrSid);
                    SecurityDescriptorApi.FreeSid(ptrSid);

                    //Get Security Descriptor Group
                    bool lpbGroupDefaulted = false;
                    ptrSid = IntPtr.Zero;
                    bRet   = SecurityDescriptorApi.GetSecurityDescriptorGroup(pSECURITY_DESCRIPTOR, out ptrSid, out lpbGroupDefaulted);
                    Logger.Log("SecurityDescriptorApi.GetSecurityDescriptorGroup iRet value: " + Marshal.GetLastWin32Error());
                    ObjSecurityDescriptor.PrimaryGroupID = GetObjectStringSid(ptrSid);
                    SecurityDescriptorApi.FreeSid(ptrSid);

                    ObjSecurityDescriptor.Size = SecurityDescriptorApi.GetSecurityDescriptorLength(pSECURITY_DESCRIPTOR);

                    ObjSecurityDescriptor.pSecurityDescriptor = pSECURITY_DESCRIPTOR;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException("SecurityDescriptorWrapper.ReadSecurityDescriptor()", ex);
            }

            return(errorReturn);
        }
        public static uint ApiSetSecurityDescriptorDacl(
            object editedObjects,
            object addedObjects,
            object deletedObjects,
            IntPtr pSecurityDesriptorIn,
            out IntPtr pSecurityDescriptorOut)
        {
            uint errorReturn = 0;
            Dictionary <string, object> editAces   = editedObjects as Dictionary <string, object>;
            Dictionary <string, object> newAces    = addedObjects as Dictionary <string, object>;
            Dictionary <string, object> deleteAces = deletedObjects as Dictionary <string, object>;

            pSecurityDescriptorOut = IntPtr.Zero;

            try
            {
                Logger.Log("SecurityDescriptorWrapper.ApiSetSecurityDescriptorDacl", Logger.SecurityDescriptorLogLevel);

                IntPtr pNewSd; IntPtr pDaclOffset; IntPtr pNewDacl; IntPtr ptrSid;
                bool   lpbDaclPresent           = false;
                bool   lpbDaclDefaulted         = false;
                SecurityDescriptorApi.LwACL acl = new SecurityDescriptorApi.LwACL();

                pDaclOffset = Marshal.AllocHGlobal(Marshal.SizeOf(acl));
                bool bRet = SecurityDescriptorApi.GetSecurityDescriptorDacl(pSecurityDesriptorIn, out lpbDaclPresent, out pDaclOffset, out lpbDaclDefaulted);
                Logger.Log("SecurityDescriptorApi.ApiSetSecurityDescriptorDacl iRet value", Logger.SecurityDescriptorLogLevel);

                if (pDaclOffset != IntPtr.Zero)
                {
                    acl = (SecurityDescriptorApi.LwACL)Marshal.PtrToStructure(pDaclOffset, typeof(SecurityDescriptorApi.LwACL));
                }

                SecurityDescriptorApi.ACL_SIZE_INFORMATION AclSize = new SecurityDescriptorApi.ACL_SIZE_INFORMATION();
                SecurityDescriptorApi.GetAclInformation(pDaclOffset, AclSize,
                                                        ((uint)Marshal.SizeOf(typeof(SecurityDescriptorApi.ACL_SIZE_INFORMATION))),
                                                        SecurityDescriptorApi.ACL_INFORMATION_CLASS.AclSizeInformation);

                SecurityDescriptorApi.SECURITY_DESCRIPTOR sSECURITY_DESCRIPTOR = new SecurityDescriptorApi.SECURITY_DESCRIPTOR();
                sSECURITY_DESCRIPTOR = (SecurityDescriptorApi.SECURITY_DESCRIPTOR)Marshal.PtrToStructure(pSecurityDesriptorIn, typeof(SecurityDescriptorApi.SECURITY_DESCRIPTOR));

                uint totalCount = (uint)(newAces.Count - deleteAces.Count);
                int  cbNewACL   = (int)AclSize.AclBytesInUse + (int)((Marshal.SizeOf(typeof(SecurityDescriptorApi.ACCESS_ALLOWED_ACE)) - IntPtr.Size) * totalCount);

                // Create new ACL
                pNewDacl = Marshal.AllocHGlobal(cbNewACL);
                bRet     = SecurityDescriptorApi.InitializeAcl(pNewDacl, cbNewACL, acl.AclRevision);
                Console.WriteLine(Marshal.GetLastWin32Error());

                bRet = SecurityDescriptorApi.IsValidAcl(pNewDacl);
                Console.WriteLine(Marshal.GetLastWin32Error());

                SecurityDescriptorApi.ACL_REVISION_INFORMATION aclRevision = new SecurityDescriptorApi.ACL_REVISION_INFORMATION();
                aclRevision.AclRevision = acl.AclRevision;
                IntPtr pAclRevision = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityDescriptorApi.ACL_REVISION_INFORMATION)));
                Marshal.StructureToPtr(aclRevision, pAclRevision, true);

                bRet = SecurityDescriptorApi.SetAclInformation(
                    pNewDacl,
                    pAclRevision,
                    ((uint)Marshal.SizeOf(typeof(SecurityDescriptorApi.ACL_REVISION_INFORMATION))),
                    SecurityDescriptorApi.ACL_INFORMATION_CLASS.AclRevisionInformation);
                Console.WriteLine(Marshal.GetLastWin32Error());

                //Delete/Editing the Ace entry from the ACl
                for (int idx = 0; idx < AclSize.AceCount; idx++)
                {
                    IntPtr pAce; ptrSid = IntPtr.Zero;
                    string sUsername, sDomain;

                    int err = SecurityDescriptorApi.GetAce(pDaclOffset, idx, out pAce);
                    SecurityDescriptorApi.ACCESS_ALLOWED_ACE ace = (SecurityDescriptorApi.ACCESS_ALLOWED_ACE)Marshal.PtrToStructure(pAce, typeof(SecurityDescriptorApi.ACCESS_ALLOWED_ACE));

                    IntPtr iter = (IntPtr)((int)pAce + (int)Marshal.OffsetOf(typeof(SecurityDescriptorApi.ACCESS_ALLOWED_ACE), "SidStart"));

                    int    size = (int)SecurityDescriptorApi.GetLengthSid(iter);
                    byte[] bSID = new byte[size];
                    Marshal.Copy(iter, bSID, 0, size);
                    SecurityDescriptorApi.ConvertSidToStringSid(bSID, out ptrSid);
                    GetObjectLookUpName(iter, out sUsername, out sDomain);

                    if (deleteAces != null && deleteAces.Count != 0 && deleteAces.ContainsKey(sUsername))
                    {
                        continue;
                    }

                    if (editAces != null && editAces.Count != 0 && editAces.ContainsKey(sUsername))
                    {
                        List <LwAccessControlEntry> attributes = editAces[sUsername] as List <LwAccessControlEntry>;
                        if (attributes != null)
                        {
                            foreach (LwAccessControlEntry lwAce in attributes)
                            {
                                if ((int)ace.Header.AceType == lwAce.AceType)
                                {
                                    SecurityDescriptorApi.ConvertStringSidToSid(lwAce.SID, out ptrSid);
                                    bRet = SecurityDescriptorApi.AddAccessAllowedAceEx(
                                        pNewDacl,
                                        0,
                                        Convert.ToByte(ace.Header.AceFlags),
                                        Convert.ToInt32(lwAce.AccessMask),
                                        ptrSid);

                                    Console.WriteLine(Marshal.GetLastWin32Error());
                                    Logger.Log("SecurityDescriptorWrapper.ApiSetSecurityDescriptorDacl() : SecurityDescriptorApi.AddAccessAllowedAceEx return code :" + Marshal.GetLastWin32Error());
                                }
                            }
                        }
                    }
                    else
                    {
                        Logger.Log("Adding new Ace from existing one: " + sUsername, Logger.SecurityDescriptorLogLevel);
                        bRet = SecurityDescriptorApi.AddAccessAllowedAceEx(
                            pNewDacl,
                            0,
                            ace.Header.AceFlags,
                            ace.Mask,
                            iter);
                        Console.WriteLine(Marshal.GetLastWin32Error());
                    }
                    SecurityDescriptorApi.FreeSid(ptrSid);
                }

                //Adding new Aces to the Security Descriptor
                foreach (string key in newAces.Keys)
                {
                    List <LwAccessControlEntry> attributes = newAces[key] as List <LwAccessControlEntry>;
                    foreach (LwAccessControlEntry lwAce in attributes)
                    {
                        SecurityDescriptorApi.ConvertStringSidToSid(lwAce.SID, out ptrSid);
                        bRet = SecurityDescriptorApi.AddAccessAllowedAceEx(
                            pNewDacl,
                            0,
                            Convert.ToByte(lwAce.AceFlags),
                            Convert.ToInt32(lwAce.AccessMask),
                            ptrSid);

                        Console.WriteLine(Marshal.GetLastWin32Error());
                        Logger.Log("Adding new Ace : " + lwAce.Username, Logger.SecurityDescriptorLogLevel);
                        Logger.Log("SecurityDescriptorWrapper.ApiSetSecurityDescriptorDacl() : SecurityDescriptorApi.AddAccessAllowedAceEx return code :" + Marshal.GetLastWin32Error());
                    }
                }

                pNewSd = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityDescriptorApi.SECURITY_DESCRIPTOR)));
                int iSdRevision = (int)SecurityDescriptorApi.SECURITY_DESCRIPTOR_REVISION;
                bRet = SecurityDescriptorApi.InitializeSecurityDescriptor(pNewSd, (uint)iSdRevision);
                Console.WriteLine(Marshal.GetLastWin32Error());
                Logger.Log("SecurityDescriptorApi.InitializeSecurityDescriptor returns errorcode: " + errorReturn);

                bRet = SecurityDescriptorApi.IsValidSecurityDescriptor(pNewSd);
                Console.WriteLine(Marshal.GetLastWin32Error());
                Logger.Log("SecurityDescriptorApi.IsValidSecurityDescriptor returns errorcode: " + Marshal.GetLastWin32Error());

                bRet = SecurityDescriptorApi.SetSecurityDescriptorDacl(
                    pNewSd,
                    lpbDaclPresent,
                    pNewDacl,
                    lpbDaclDefaulted);
                Console.WriteLine(Marshal.GetLastWin32Error());
                Logger.Log("SecurityDescriptorApi.SetSecurityDescriptorDacl returns errorcode: " + Marshal.GetLastWin32Error());

                bRet = SecurityDescriptorApi.IsValidSecurityDescriptor(pNewSd);
                Console.WriteLine(Marshal.GetLastWin32Error());
                Logger.Log("SecurityDescriptorApi.IsValidSecurityDescriptor returns errorcode: " + Marshal.GetLastWin32Error());

                pSecurityDescriptorOut = IntPtr.Zero;
                uint lpdwBufferLength = (uint)Marshal.SizeOf(typeof(SecurityDescriptorApi.SECURITY_DESCRIPTOR));

                bRet = SecurityDescriptorApi.MakeSelfRelativeSD(pNewSd, out pSecurityDescriptorOut, ref lpdwBufferLength);
                Console.WriteLine(Marshal.GetLastWin32Error());

                bRet = SecurityDescriptorApi.MakeSelfRelativeSD(pNewSd, out pSecurityDescriptorOut, ref lpdwBufferLength);
                Console.WriteLine(Marshal.GetLastWin32Error());

                bRet = SecurityDescriptorApi.IsValidSecurityDescriptor(pNewSd);
                Console.WriteLine(Marshal.GetLastWin32Error());
                Logger.Log("SecurityDescriptorApi.IsValidSecurityDescriptor returns errorcode: " + Marshal.GetLastWin32Error());

                /*bRet = SecurityDescriptorApi.SetSecurityDescriptorGroup(
                 *             pNewSd,
                 *             sSECURITY_DESCRIPTOR.group,
                 *             false);
                 * Console.WriteLine(Marshal.GetLastWin32Error());
                 * Logger.Log("SecurityDescriptorApi.SetSecurityDescriptorGroup returns errorcode: " + Marshal.GetLastWin32Error());
                 *
                 * bRet = SecurityDescriptorApi.IsValidSecurityDescriptor(pNewSd);
                 * Console.WriteLine(Marshal.GetLastWin32Error());
                 * Logger.Log("SecurityDescriptorApi.IsValidSecurityDescriptor returns errorcode: " + Marshal.GetLastWin32Error());
                 *
                 * bRet = SecurityDescriptorApi.SetSecurityDescriptorOwner(
                 *            pNewSd,
                 *            sSECURITY_DESCRIPTOR.owner,
                 *            false);
                 * Console.WriteLine(Marshal.GetLastWin32Error());
                 * Logger.Log("SecurityDescriptorApi.SetSecurityDescriptorOwner returns errorcode: " + Marshal.GetLastWin32Error());
                 *
                 * bRet = SecurityDescriptorApi.IsValidSecurityDescriptor(pNewSd);
                 * Console.WriteLine(Marshal.GetLastWin32Error());
                 * Logger.Log("SecurityDescriptorApi.IsValidSecurityDescriptor returns errorcode: " + Marshal.GetLastWin32Error());
                 *
                 * uint pControl; uint lpdwRevision;
                 * bRet = SecurityDescriptorApi.GetSecurityDescriptorControl(
                 *           pSecurityDesriptorIn,
                 *           out pControl,
                 *           out lpdwRevision);
                 * Console.WriteLine(Marshal.GetLastWin32Error());
                 * Logger.Log("SecurityDescriptorApi.SetSecurityDescriptorControl returns errorcode: " + Marshal.GetLastWin32Error());
                 *
                 * bRet = SecurityDescriptorApi.SetSecurityDescriptorControl(
                 *           pNewSd,
                 *           pControl,
                 *           pControl);
                 * Console.WriteLine(Marshal.GetLastWin32Error());
                 * Logger.Log("SecurityDescriptorApi.SetSecurityDescriptorControl returns errorcode: " + Marshal.GetLastWin32Error());
                 *
                 * bRet = SecurityDescriptorApi.IsValidSecurityDescriptor(pNewSd);
                 * Console.WriteLine(Marshal.GetLastWin32Error());
                 * Logger.Log("SecurityDescriptorApi.IsValidSecurityDescriptor returns errorcode: " + Marshal.GetLastWin32Error());
                 *
                 * if (pNewDacl != IntPtr.Zero)
                 * {
                 *  SecurityDescriptorApi.LocalFree(pNewDacl);
                 * }
                 *
                 * uint lpdwAbsoluteSDSize = 0, lpdwDaclSize = 0, lpdwSaclSize = 0, lpdwOwnerSize = 0, lpdwPrimaryGroupSize = 0;
                 * IntPtr pAbsoluteSD, pDacl, pSacl, pOwner, pPrimaryGroup;
                 * lpdwAbsoluteSDSize = (uint)Marshal.SizeOf(typeof(SecurityDescriptorApi.SECURITY_DESCRIPTOR));
                 * bRet = SecurityDescriptorApi.MakeAbsoluteSD(pNewSd, out pAbsoluteSD,
                 *                              ref lpdwAbsoluteSDSize, out pDacl, ref lpdwDaclSize,
                 *                              out pSacl, ref lpdwSaclSize,
                 *                              out pOwner, ref lpdwOwnerSize,
                 *                              out pPrimaryGroup, ref lpdwPrimaryGroupSize);
                 * Console.WriteLine(Marshal.GetLastWin32Error());
                 * Logger.Log("SecurityDescriptorApi.MakeAbsoluteSD returns errorcode: " + Marshal.GetLastWin32Error()); */

                if (!bRet)
                {
                    pSecurityDescriptorOut = IntPtr.Zero;
                }
            }
            catch (Exception ex)
            {
                pSecurityDescriptorOut = IntPtr.Zero;
                errorReturn            = (uint)Marshal.GetLastWin32Error();
                Logger.LogException("SecurityDescriptorWrapper.ApiGetLogOnUserHandle()", ex);
            }

            return(errorReturn);
        }