/// <summary>
        /// Gets the security descriptor of a kernel object.
        /// </summary>
        /// <param name="handle">A handle to a kernel object.</param>
        /// <param name="securityInformation">The information to retrieve.</param>
        /// <returns>A security descriptor.</returns>
        public static SecurityDescriptor GetSecurity(IntPtr handle, SecurityInformation securityInformation)
        {
            NtStatus status;
            int retLength;

            using (var data = new MemoryAlloc(0x100))
            {
                status = Win32.NtQuerySecurityObject(
                    handle,
                    securityInformation,
                    data,
                    data.Size,
                    out retLength
                    );

                if (status == NtStatus.BufferTooSmall)
                {
                    data.ResizeNew(retLength);

                    status = Win32.NtQuerySecurityObject(
                        handle,
                        securityInformation,
                        data,
                        data.Size,
                        out retLength
                        );
                }

                if (status >= NtStatus.Error)
                    Win32.Throw(status);

                return new SecurityDescriptor(data);
            }
        }
        /// <summary>
        /// Gets the security descriptor of a kernel object.
        /// </summary>
        /// <param name="handle">A handle to a kernel object.</param>
        /// <param name="securityInformation">The information to retrieve.</param>
        /// <returns>A security descriptor.</returns>
        public static SecurityDescriptor GetSecurity(IntPtr handle, SecurityInformation securityInformation)
        {
            using (MemoryAlloc data = new MemoryAlloc(0x100))
            {
                int retLength;

                NtStatus status = Win32.NtQuerySecurityObject(
                    handle,
                    securityInformation,
                    data,
                    data.Size,
                    out retLength
                    );

                if (status == NtStatus.BufferTooSmall)
                {
                    data.ResizeNew(retLength);

                    Win32.NtQuerySecurityObject(
                        handle,
                        securityInformation,
                        data,
                        data.Size,
                        out retLength
                        ).ThrowIf();
                }

                status.ThrowIf();

                return(new SecurityDescriptor(data));
            }
        }
示例#3
0
        private string GetInformationUnicodeString(DriverInformationClass infoClass)
        {
            using (MemoryAlloc data = new MemoryAlloc(0x1000))
            {
                int retLength = 0;

                try
                {
                    KProcessHacker.Instance.KphQueryInformationDriver(
                        this,
                        infoClass,
                        data,
                        data.Size,
                        out retLength
                        );
                }
                catch (WindowsException)
                {
                    data.ResizeNew(retLength);

                    KProcessHacker.Instance.KphQueryInformationDriver(
                        this,
                        infoClass,
                        data,
                        data.Size,
                        out retLength
                        );
                }

                return(data.ReadStruct <UnicodeString>().Read());
            }
        }
        public string GetTarget()
        {
            NtStatus      status;
            int           retLength;
            UnicodeString str = new UnicodeString();

            using (var buffer = new MemoryAlloc(0x200))
            {
                str.Length        = 0;
                str.MaximumLength = (ushort)buffer.Size;
                str.Buffer        = buffer;

                if ((status = Win32.NtQuerySymbolicLinkObject(this, ref str, out retLength)) >= NtStatus.Error)
                {
                    buffer.ResizeNew(retLength);
                    str.MaximumLength = (ushort)retLength;
                    str.Buffer        = buffer;
                }

                if ((status = Win32.NtQuerySymbolicLinkObject(this, ref str, out retLength)) >= NtStatus.Error)
                {
                    Win32.Throw(status);
                }

                return(str.Read());
            }
        }
        public static MemoryRegion PackCredentials(CredPackFlags flags, string userName, string password)
        {
            MemoryAlloc data = new MemoryAlloc(0x100);
            int         size = data.Size;

            if (string.IsNullOrEmpty(userName))
            {
                userName = string.Empty;
            }
            if (string.IsNullOrEmpty(password))
            {
                password = string.Empty;
            }

            if (!Win32.CredPackAuthenticationBuffer(flags, userName, password, data, ref size))
            {
                data.ResizeNew(size);

                if (!Win32.CredPackAuthenticationBuffer(flags, userName, password, data, ref size))
                {
                    Win32.Throw();
                }
            }

            return(data);
        }
        public static void UnpackCredentials(
            MemoryRegion buffer,
            CredPackFlags flags,
            out string domainName,
            out string userName,
            out string password
            )
        {
            using (MemoryAlloc domainNameBuffer = new MemoryAlloc(0x100))
                using (MemoryAlloc userNameBuffer = new MemoryAlloc(0x100))
                    using (MemoryAlloc passwordBuffer = new MemoryAlloc(0x100))
                    {
                        int domainNameSize = domainNameBuffer.Size / 2 - 1;
                        int userNameSize   = userNameBuffer.Size / 2 - 1;
                        int passwordSize   = passwordBuffer.Size / 2 - 1;

                        if (!Win32.CredUnPackAuthenticationBuffer(
                                flags,
                                buffer,
                                buffer.Size,
                                userNameBuffer,
                                ref userNameSize,
                                domainNameBuffer,
                                ref domainNameSize,
                                passwordBuffer,
                                ref passwordSize
                                ))
                        {
                            domainNameBuffer.ResizeNew(domainNameSize * 2 + 2);
                            userNameBuffer.ResizeNew(userNameSize * 2 + 2);
                            passwordBuffer.ResizeNew(passwordSize * 2 + 2);

                            if (!Win32.CredUnPackAuthenticationBuffer(
                                    flags,
                                    buffer,
                                    buffer.Size,
                                    userNameBuffer,
                                    ref userNameSize,
                                    domainNameBuffer,
                                    ref domainNameSize,
                                    passwordBuffer,
                                    ref passwordSize
                                    ))
                            {
                                Win32.Throw();
                            }
                        }

                        domainName = domainNameBuffer.ReadUnicodeString(0);
                        userName   = userNameBuffer.ReadUnicodeString(0);
                        password   = passwordBuffer.ReadUnicodeString(0);
                    }
        }
示例#7
0
        public static void UnpackCredentials(
            MemoryRegion buffer,
            CredPackFlags flags,
            out string domainName,
            out string userName,
            out string password
            )
        {
            using (var domainNameBuffer = new MemoryAlloc(0x100))
            using (var userNameBuffer = new MemoryAlloc(0x100))
            using (var passwordBuffer = new MemoryAlloc(0x100))
            {
                int domainNameSize = domainNameBuffer.Size / 2 - 1;
                int userNameSize = userNameBuffer.Size / 2 - 1;
                int passwordSize = passwordBuffer.Size / 2 - 1;

                if (!Win32.CredUnPackAuthenticationBuffer(
                    flags,
                    buffer,
                    buffer.Size,
                    userNameBuffer,
                    ref userNameSize,
                    domainNameBuffer,
                    ref domainNameSize,
                    passwordBuffer,
                    ref passwordSize
                    ))
                {
                    domainNameBuffer.ResizeNew(domainNameSize * 2 + 2);
                    userNameBuffer.ResizeNew(userNameSize * 2 + 2);
                    passwordBuffer.ResizeNew(passwordSize * 2 + 2);

                    if (!Win32.CredUnPackAuthenticationBuffer(
                        flags,
                        buffer,
                        buffer.Size,
                        userNameBuffer,
                        ref userNameSize,
                        domainNameBuffer,
                        ref domainNameSize,
                        passwordBuffer,
                        ref passwordSize
                        ))
                        Win32.Throw();
                }

                domainName = domainNameBuffer.ReadUnicodeString(0);
                userName = userNameBuffer.ReadUnicodeString(0);
                password = passwordBuffer.ReadUnicodeString(0);
            }
        }
        public string GetVariable(string name)
        {
            NtStatus      status;
            UnicodeString nameStr;
            UnicodeString valueStr;

            nameStr = new UnicodeString(name);

            try
            {
                using (var data = new MemoryAlloc(100))
                {
                    valueStr               = new UnicodeString();
                    valueStr.Buffer        = data;
                    valueStr.MaximumLength = (ushort)data.Size;

                    status = Win32.RtlQueryEnvironmentVariable_U(
                        this,
                        ref nameStr,
                        ref valueStr
                        );

                    if (status == NtStatus.BufferTooSmall)
                    {
                        // Resize and try again (+2 for the null terminator).
                        data.ResizeNew(valueStr.Length + 2);
                        valueStr.Buffer        = data;
                        valueStr.MaximumLength = (ushort)(valueStr.Length + 2);

                        status = Win32.RtlQueryEnvironmentVariable_U(
                            this,
                            ref nameStr,
                            ref valueStr
                            );
                    }

                    if (status >= NtStatus.Error)
                    {
                        Win32.Throw(status);
                    }

                    return(valueStr.Read());
                }
            }
            finally
            {
                nameStr.Dispose();
            }
        }
        public string GetVariable(string name)
        {
            UnicodeString nameStr = new UnicodeString(name);

            try
            {
                using (MemoryAlloc data = new MemoryAlloc(100))
                {
                    UnicodeString valueStr = new UnicodeString
                    {
                        Buffer        = data,
                        MaximumLength = (ushort)data.Size
                    };

                    NtStatus status = Win32.RtlQueryEnvironmentVariable_U(
                        this,
                        ref nameStr,
                        ref valueStr
                        );

                    if (status == NtStatus.BufferTooSmall)
                    {
                        // Resize and try again (+2 for the null terminator).
                        data.ResizeNew(valueStr.Length + 2);
                        valueStr.Buffer        = data;
                        valueStr.MaximumLength = (ushort)(valueStr.Length + 2);

                        status = Win32.RtlQueryEnvironmentVariable_U(
                            this,
                            ref nameStr,
                            ref valueStr
                            );
                    }

                    status.ThrowIf();

                    return(valueStr.Text);
                }
            }
            finally
            {
                nameStr.Dispose();
            }
        }
        /// <summary>
        /// Creates a copy of the security descriptor in self-relative form.
        /// </summary>
        /// <returns>A new self-relative security descriptor.</returns>
        public SecurityDescriptor ToSelfRelative()
        {
            using (MemoryAlloc data = new MemoryAlloc(Win32.SecurityDescriptorMinLength))
            {
                int retLength = data.Size;

                NtStatus status = Win32.RtlMakeSelfRelativeSD(this, data, ref retLength);

                if (status == NtStatus.BufferTooSmall)
                {
                    data.ResizeNew(retLength);
                    status = Win32.RtlMakeSelfRelativeSD(this, data, ref retLength);
                }

                status.ThrowIf();

                return(new SecurityDescriptor(data));
            }
        }
示例#11
0
        private T QueryStruct <T>(JobObjectInformationClass informationClass)
            where T : struct
        {
            int retLength;

            using (MemoryAlloc data = new MemoryAlloc(Marshal.SizeOf(typeof(T))))
            {
                if (!Win32.QueryInformationJobObject(this, informationClass, data, data.Size, out retLength))
                {
                    data.ResizeNew(retLength);

                    if (!Win32.QueryInformationJobObject(this, informationClass, data, data.Size, out retLength))
                    {
                        Win32.Throw();
                    }
                }

                return(data.ReadStruct <T>());
            }
        }
示例#12
0
        public static MemoryRegion PackCredentials(CredPackFlags flags, string userName, string password)
        {
            MemoryAlloc data = new MemoryAlloc(0x100);
            int size = data.Size;

            if (userName == null)
                userName = "";
            if (password == null)
                password = "";

            if (!Win32.CredPackAuthenticationBuffer(flags, userName, password, data, ref size))
            {
                data.ResizeNew(size);

                if (!Win32.CredPackAuthenticationBuffer(flags, userName, password, data, ref size))
                    Win32.Throw();
            }

            return data;
        }
示例#13
0
        public string GetLogFileName()
        {
            NtStatus status;
            int      retLength;

            using (var data = new MemoryAlloc(0x1000))
            {
                status = Win32.NtQueryInformationTransactionManager(
                    this,
                    TmInformationClass.TransactionManagerLogPathInformation,
                    data,
                    data.Size,
                    out retLength
                    );

                if (status == NtStatus.BufferTooSmall)
                {
                    // Resize the buffer and try again.
                    data.ResizeNew(retLength);

                    status = Win32.NtQueryInformationTransactionManager(
                        this,
                        TmInformationClass.TransactionManagerLogPathInformation,
                        data,
                        data.Size,
                        out retLength
                        );
                }

                if (status >= NtStatus.Error)
                {
                    Win32.Throw(status);
                }

                TmLogPathInformation logPathInfo = data.ReadStruct <TmLogPathInformation>();

                return(data.ReadUnicodeString(TmLogPathInformation.LogPathOffset, logPathInfo.LogPathLength));
            }
        }
        private T QueryStruct <T>(JobObjectInformationClass informationClass, int size) where T : struct
        {
            int retLength;

            using (MemoryAlloc data = new MemoryAlloc(size))
            {
                bool ret = Win32.QueryInformationJobObject(this, informationClass, data, data.Size, out retLength);
                int  res = System.Runtime.InteropServices.Marshal.GetLastWin32Error();

                if (!Win32.QueryInformationJobObject(this, informationClass, data, data.Size, out retLength))
                {
                    data.ResizeNew(retLength);

                    if (!Win32.QueryInformationJobObject(this, informationClass, data, data.Size, out retLength))
                    {
                        Win32.Throw();
                    }
                }

                return(data.ReadStruct <T>());
            }
        }
        private MemoryAlloc GetPropertiesInformation()
        {
            NtStatus status;
            int      retLength;

            var data = new MemoryAlloc(0x1000);

            status = Win32.NtQueryInformationTransaction(
                this,
                TransactionInformationClass.TransactionPropertiesInformation,
                data,
                data.Size,
                out retLength
                );

            if (status == NtStatus.BufferTooSmall)
            {
                // Resize the buffer and try again.
                data.ResizeNew(retLength);

                status = Win32.NtQueryInformationTransaction(
                    this,
                    TransactionInformationClass.TransactionPropertiesInformation,
                    data,
                    data.Size,
                    out retLength
                    );
            }

            if (status >= NtStatus.Error)
            {
                data.Dispose();
                Win32.Throw(status);
            }

            return(data);
        }
示例#16
0
        private MemoryAlloc GetBasicInformation()
        {
            NtStatus status;
            int      retLength;

            var data = new MemoryAlloc(0x1000);

            status = Win32.NtQueryInformationResourceManager(
                this,
                ResourceManagerInformationClass.ResourceManagerBasicInformation,
                data,
                data.Size,
                out retLength
                );

            if (status == NtStatus.BufferTooSmall)
            {
                // Resize the buffer and try again.
                data.ResizeNew(retLength);

                status = Win32.NtQueryInformationResourceManager(
                    this,
                    ResourceManagerInformationClass.ResourceManagerBasicInformation,
                    data,
                    data.Size,
                    out retLength
                    );
            }

            if (status >= NtStatus.Error)
            {
                data.Dispose();
                Win32.Throw(status);
            }

            return(data);
        }
示例#17
0
        /// <summary>
        /// Creates a copy of the security descriptor in self-relative form.
        /// </summary>
        /// <returns>A new self-relative security descriptor.</returns>
        public SecurityDescriptor ToSelfRelative()
        {
            NtStatus status;
            int      retLength;

            using (var data = new MemoryAlloc(Win32.SecurityDescriptorMinLength))
            {
                retLength = data.Size;
                status    = Win32.RtlMakeSelfRelativeSD(this, data, ref retLength);

                if (status == NtStatus.BufferTooSmall)
                {
                    data.ResizeNew(retLength);
                    status = Win32.RtlMakeSelfRelativeSD(this, data, ref retLength);
                }

                if (status >= NtStatus.Error)
                {
                    Win32.Throw(status);
                }

                return(new SecurityDescriptor(data));
            }
        }
示例#18
0
        /// <summary>
        /// Gets the security descriptor of a kernel object.
        /// </summary>
        /// <param name="handle">A handle to a kernel object.</param>
        /// <param name="securityInformation">The information to retrieve.</param>
        /// <returns>A security descriptor.</returns>
        public static SecurityDescriptor GetSecurity(IntPtr handle, SecurityInformation securityInformation)
        {
            NtStatus status;
            int      retLength;

            using (var data = new MemoryAlloc(0x100))
            {
                status = Win32.NtQuerySecurityObject(
                    handle,
                    securityInformation,
                    data,
                    data.Size,
                    out retLength
                    );

                if (status == NtStatus.BufferTooSmall)
                {
                    data.ResizeNew(retLength);

                    status = Win32.NtQuerySecurityObject(
                        handle,
                        securityInformation,
                        data,
                        data.Size,
                        out retLength
                        );
                }

                if (status >= NtStatus.Error)
                {
                    Win32.Throw(status);
                }

                return(new SecurityDescriptor(data));
            }
        }
示例#19
0
        public static string GetVolumeName(string deviceName)
        {
            using (MemoryAlloc data = new MemoryAlloc(MountMgrMountPoint.SizeOf + deviceName.Length * 2))
            {
                MountMgrMountPoint mountPoint = new MountMgrMountPoint
                {
                    DeviceNameLength = (ushort)(deviceName.Length * 2),
                    DeviceNameOffset = MountMgrMountPoint.SizeOf
                };

                data.WriteStruct(mountPoint);
                data.WriteUnicodeString(mountPoint.DeviceNameOffset, deviceName);

                using (var fhandle = OpenMountManager((FileAccess)StandardRights.Synchronize))
                {
                    NtStatus status;
                    int      retLength;

                    using (MemoryAlloc outData = new MemoryAlloc(0x100))
                    {
                        while (true)
                        {
                            status = fhandle.IoControl(
                                IoCtlQueryPoints,
                                data.Memory,
                                data.Size,
                                outData.Memory,
                                outData.Size,
                                out retLength
                                );

                            if (status == NtStatus.BufferOverflow)
                            {
                                outData.ResizeNew(Marshal.ReadInt32(outData.Memory)); // read Size field
                                continue;
                            }
                            else
                            {
                                break;
                            }
                        }

                        status.ThrowIf();

                        MountMgrMountPoints mountPoints = outData.ReadStruct <MountMgrMountPoints>();

                        // Go through the mount points given and return the first symbolic link that seems
                        // to be a volume name.
                        for (int i = 0; i < mountPoints.NumberOfMountPoints; i++)
                        {
                            MountMgrMountPoint mp = outData.ReadStruct <MountMgrMountPoint>(
                                MountMgrMountPoints.MountPointsOffset,
                                MountMgrMountPoint.SizeOf,
                                i
                                );

                            string symLinkName = Marshal.PtrToStringUni(
                                outData.Memory.Increment(mp.SymbolicLinkNameOffset),
                                mp.SymbolicLinkNameLength / 2
                                );

                            if (IsVolumePath(symLinkName))
                            {
                                return(symLinkName);
                            }
                        }

                        return(null);
                    }
                }
            }
        }
        /// <summary>
        /// Creates a copy of the security descriptor in self-relative form.
        /// </summary>
        /// <returns>A new self-relative security descriptor.</returns>
        public SecurityDescriptor ToSelfRelative()
        {
            using (MemoryAlloc data = new MemoryAlloc(Win32.SecurityDescriptorMinLength))
            {
                int retLength = data.Size;

                NtStatus status = Win32.RtlMakeSelfRelativeSD(this, data, ref retLength);

                if (status == NtStatus.BufferTooSmall)
                {
                    data.ResizeNew(retLength);
                    status = Win32.RtlMakeSelfRelativeSD(this, data, ref retLength);
                }

                status.ThrowIf();

                return new SecurityDescriptor(data);
            }
        }
示例#21
0
        public static string GetVolumeName(string deviceName)
        {
            using (MemoryAlloc data = new MemoryAlloc(MountMgrMountPoint.SizeOf + deviceName.Length * 2))
            {
                MountMgrMountPoint mountPoint = new MountMgrMountPoint
                {
                    DeviceNameLength = (ushort)(deviceName.Length*2), 
                    DeviceNameOffset = MountMgrMountPoint.SizeOf
                };

                data.WriteStruct(mountPoint);
                data.WriteUnicodeString(mountPoint.DeviceNameOffset, deviceName);

                using (var fhandle = OpenMountManager((FileAccess)StandardRights.Synchronize))
                {
                    NtStatus status;
                    int retLength;

                    using (MemoryAlloc outData = new MemoryAlloc(0x100))
                    {
                        while (true)
                        {
                            status = fhandle.IoControl(
                                IoCtlQueryPoints,
                                data.Memory,
                                data.Size,
                                outData.Memory,
                                outData.Size,
                                out retLength
                                );

                            if (status == NtStatus.BufferOverflow)
                            {
                                outData.ResizeNew(Marshal.ReadInt32(outData.Memory)); // read Size field
                                continue;
                            }
                            else
                            {
                                break;
                            }
                        }

                        status.ThrowIf();

                        MountMgrMountPoints mountPoints = outData.ReadStruct<MountMgrMountPoints>();

                        // Go through the mount points given and return the first symbolic link that seems 
                        // to be a volume name.
                        for (int i = 0; i < mountPoints.NumberOfMountPoints; i++)
                        {
                            MountMgrMountPoint mp = outData.ReadStruct<MountMgrMountPoint>(
                                MountMgrMountPoints.MountPointsOffset,
                                MountMgrMountPoint.SizeOf,
                                i
                                );

                            string symLinkName = Marshal.PtrToStringUni(
                                outData.Memory.Increment(mp.SymbolicLinkNameOffset),
                                mp.SymbolicLinkNameLength / 2
                                );

                            if (IsVolumePath(symLinkName))
                                return symLinkName;
                        }

                        return null;
                    }
                }
            }
        }
示例#22
0
        public string GetVariable(string name)
        {
            NtStatus status;
            UnicodeString nameStr;
            UnicodeString valueStr;

            nameStr = new UnicodeString(name);

            try
            {
                using (var data = new MemoryAlloc(100))
                {
                    valueStr = new UnicodeString();
                    valueStr.Buffer = data;
                    valueStr.MaximumLength = (ushort)data.Size;

                    status = Win32.RtlQueryEnvironmentVariable_U(
                        this,
                        ref nameStr,
                        ref valueStr
                        );

                    if (status == NtStatus.BufferTooSmall)
                    {
                        // Resize and try again (+2 for the null terminator).
                        data.ResizeNew(valueStr.Length + 2);
                        valueStr.Buffer = data;
                        valueStr.MaximumLength = (ushort)(valueStr.Length + 2);

                        status = Win32.RtlQueryEnvironmentVariable_U(
                            this,
                            ref nameStr,
                            ref valueStr
                            );
                    }

                    if (status >= NtStatus.Error)
                        Win32.Throw(status);

                    return valueStr.Read();
                }
            }
            finally
            {
                nameStr.Dispose();
            }
        }
示例#23
0
        public void EnumObjects(EnumObjectsDelegate callback)
        {
            NtStatus status;
            int      context   = 0;
            bool     firstTime = true;
            int      retLength;

            using (var data = new MemoryAlloc(0x200))
            {
                while (true)
                {
                    while ((status = Win32.NtQueryDirectoryObject(
                                this,
                                data,
                                data.Size,
                                false,
                                firstTime,
                                ref context,
                                out retLength
                                )) == NtStatus.MoreEntries)
                    {
                        // Check if we have at least one entry. If not,
                        // we need to double the buffer size and try again.
                        if (data.ReadStruct <ObjectDirectoryInformation>(0, ObjectDirectoryInformation.SizeOf, 0).Name.Buffer != IntPtr.Zero)
                        {
                            break;
                        }

                        if (data.Size > 16 * 1024 * 1024)
                        {
                            Win32.Throw(status);
                        }

                        data.ResizeNew(data.Size * 2);
                    }

                    status.ThrowIf();

                    int i = 0;

                    while (true)
                    {
                        ObjectDirectoryInformation info = data.ReadStruct <ObjectDirectoryInformation>(0, ObjectDirectoryInformation.SizeOf, i);

                        if (info.Name.Buffer == IntPtr.Zero)
                        {
                            break;
                        }

                        if (!callback(new ObjectEntry(info.Name.Text, info.TypeName.Text)))
                        {
                            return;
                        }

                        i++;
                    }

                    if (status != NtStatus.MoreEntries)
                    {
                        break;
                    }

                    firstTime = false;
                }
            }
        }
示例#24
0
        private string GetInformationUnicodeString(DriverInformationClass infoClass)
        {
            using (MemoryAlloc data = new MemoryAlloc(0x1000))
            {
                int retLength = 0;

                try
                {
                    KProcessHacker.Instance.KphQueryInformationDriver(
                        this,
                        infoClass,
                        data,
                        data.Size,
                        out retLength
                        );
                }
                catch (WindowsException)
                {
                    data.ResizeNew(retLength);

                    KProcessHacker.Instance.KphQueryInformationDriver(
                        this,
                        infoClass,
                        data,
                        data.Size,
                        out retLength
                        );
                }

                return data.ReadStruct<UnicodeString>().Read();
            }
        }
        /// <summary>
        /// Creates a copy of the security descriptor in self-relative form.
        /// </summary>
        /// <returns>A new self-relative security descriptor.</returns>
        public SecurityDescriptor ToSelfRelative()
        {
            NtStatus status;
            int retLength;

            using (var data = new MemoryAlloc(Win32.SecurityDescriptorMinLength))
            {
                retLength = data.Size;
                status = Win32.RtlMakeSelfRelativeSD(this, data, ref retLength);

                if (status == NtStatus.BufferTooSmall)
                {
                    data.ResizeNew(retLength);
                    status = Win32.RtlMakeSelfRelativeSD(this, data, ref retLength);
                }

                if (status >= NtStatus.Error)
                    Win32.Throw(status);

                return new SecurityDescriptor(data);
            }
        }
        /// <summary>
        /// Gets the security descriptor of a kernel object.
        /// </summary>
        /// <param name="handle">A handle to a kernel object.</param>
        /// <param name="securityInformation">The information to retrieve.</param>
        /// <returns>A security descriptor.</returns>
        public static SecurityDescriptor GetSecurity(IntPtr handle, SecurityInformation securityInformation)
        {
            using (MemoryAlloc data = new MemoryAlloc(0x100))
            {
                int retLength;

                NtStatus status = Win32.NtQuerySecurityObject(
                    handle,
                    securityInformation,
                    data,
                    data.Size,
                    out retLength
                    );

                if (status == NtStatus.BufferTooSmall)
                {
                    data.ResizeNew(retLength);

                    Win32.NtQuerySecurityObject(
                        handle,
                        securityInformation,
                        data,
                        data.Size,
                        out retLength
                        ).ThrowIf();
                }

                status.ThrowIf();

                return new SecurityDescriptor(data);
            }
        }