/// <summary>
        /// Create and initialize a Server Silo,
        /// </summary>
        /// <param name="root_dir_flags">Flags for root directory.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <param name="system_root">Path to the system root.</param>
        /// <param name="delete_event">Event to signal when silo deleted.</param>
        /// <param name="downlevel_container">True if a downlevel container.</param>
        /// <returns>The Job object.</returns>
        public static NtResult <NtJob> CreateServerSilo(SiloObjectRootDirectoryControlFlags root_dir_flags, string system_root, NtEvent delete_event, bool downlevel_container, bool throw_on_error)
        {
            using (var job = CreateSilo(root_dir_flags, throw_on_error))
            {
                if (!job.IsSuccess)
                {
                    return(job);
                }

                NtStatus status = job.Result.SetSiloSystemRoot(system_root, throw_on_error);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <NtJob>(throw_on_error));
                }

                var silo_dir = job.Result.QuerySiloRootDirectory(throw_on_error);
                if (!silo_dir.IsSuccess)
                {
                    return(silo_dir.Cast <NtJob>());
                }

                string device_path = $@"{silo_dir.Result}\Device";

                using (var device_dir = NtDirectory.Open(@"\Device", null, DirectoryAccessRights.MaximumAllowed, throw_on_error))
                {
                    if (!device_dir.IsSuccess)
                    {
                        return(device_dir.Cast <NtJob>());
                    }
                    using (var obja = new ObjectAttributes(device_path, AttributeFlags.CaseInsensitive | AttributeFlags.Permanent | AttributeFlags.OpenIf))
                    {
                        using (var dir = NtDirectory.Create(obja, DirectoryAccessRights.MaximumAllowed, device_dir.Result, throw_on_error))
                        {
                            if (!dir.IsSuccess)
                            {
                                return(dir.Cast <NtJob>());
                            }
                        }
                    }
                }

                status = job.Result.InitializeServerSilo(delete_event, downlevel_container, throw_on_error);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <NtJob>(throw_on_error));
                }
                return(job.Result.Duplicate().CreateResult());
            }
        }
示例#2
0
        private static NtResult <SafeStructureInOutBuffer <T> > QueryObject <T>(SafeKernelObjectHandle handle,
                                                                                ObjectInformationClass object_info, bool throw_on_error) where T : new()
        {
            SafeStructureInOutBuffer <T> ret = null;
            NtStatus status = NtStatus.STATUS_BUFFER_TOO_SMALL;

            try
            {
                status = NtSystemCalls.NtQueryObject(handle, object_info, SafeHGlobalBuffer.Null, 0, out int return_length);
                if ((status != NtStatus.STATUS_BUFFER_TOO_SMALL) && (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH))
                {
                    return(status.CreateResultFromError <SafeStructureInOutBuffer <T> >(throw_on_error));
                }

                if (return_length == 0)
                {
                    ret = new SafeStructureInOutBuffer <T>();
                }
                else
                {
                    ret = new SafeStructureInOutBuffer <T>(return_length, false);
                }
                status = NtSystemCalls.NtQueryObject(handle, object_info, ret, ret.Length, out return_length);
                return(status.CreateResult(throw_on_error, () => ret));
            }
            finally
            {
                if (ret != null && !status.IsSuccess())
                {
                    ret.Close();
                    ret = null;
                }
            }
        }
示例#3
0
        /// <summary>
        /// Query the image path from a process ID.
        /// </summary>
        /// <param name="pid">The ID of the process.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The image path.</returns>
        /// <remarks>This method can be called without any permissions on the process.</remarks>
        public static NtResult <string> GetProcessIdImagePath(int pid, bool throw_on_error)
        {
            var info = new SystemProcessIdInformation()
            {
                ProcessId = new IntPtr(pid)
            };

            using (var buffer = info.ToBuffer())
            {
                NtStatus status = _system_info_object.QueryInformation(
                    SystemInformationClass.SystemProcessIdInformation,
                    buffer, out int length);
                if (status.IsSuccess())
                {
                    return(new NtResult <string>(NtStatus.STATUS_SUCCESS, string.Empty));
                }
                if (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH)
                {
                    return(status.CreateResultFromError <string>(throw_on_error));
                }

                using (var str = new UnicodeStringAllocated(buffer.Result.ImageName.MaximumLength))
                {
                    info = new SystemProcessIdInformation()
                    {
                        ProcessId = new IntPtr(pid), ImageName = str.String
                    };
                    return(Query(SystemInformationClass.SystemProcessIdInformation,
                                 info, throw_on_error).Map(r => r.ImageName.ToString()));
                }
            }
        }
示例#4
0
        /// <summary>
        /// Query memory information for a process.
        /// </summary>
        /// <param name="process">The process to query.</param>
        /// <param name="base_address">The base address.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The memory information for the region.</returns>
        /// <exception cref="NtException">Thrown on error.</exception>
        public static NtResult <MemoryInformation> QueryMemoryInformation(SafeKernelObjectHandle process, long base_address, bool throw_on_error)
        {
            MemoryBasicInformation basic_info = new MemoryBasicInformation();
            string mapped_image_path          = string.Empty;

            using (var buffer = new SafeStructureInOutBuffer <MemoryBasicInformation>())
            {
                NtStatus status = NtSystemCalls.NtQueryVirtualMemory(process,
                                                                     new IntPtr(base_address), MemoryInformationClass.MemoryBasicInformation,
                                                                     buffer, buffer.LengthIntPtr, out IntPtr ret_length);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <MemoryInformation>(throw_on_error));
                }
                basic_info = buffer.Result;
            }

            if (basic_info.Type == MemoryType.Image || basic_info.Type == MemoryType.Mapped)
            {
                var name = QuerySectionName(process, base_address, false);
                if (name.IsSuccess)
                {
                    mapped_image_path = name.Result;
                }
            }

            return(new MemoryInformation(basic_info, mapped_image_path).CreateResult());
        }
        /// <summary>
        /// Retried LSA privilege data.
        /// </summary>
        /// <param name="system_name">The system containing the LSA instance.</param>
        /// <param name="keyname">The name of the key.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The private data as bytes.</returns>
        public static NtResult <byte[]> LsaRetrievePrivateData(string system_name, string keyname, bool throw_on_error)
        {
            if (keyname is null)
            {
                throw new ArgumentNullException(nameof(keyname));
            }

            using (var policy = SafeLsaHandle.OpenPolicy(system_name, Policy.LsaPolicyAccessRights.GetPrivateInformation, throw_on_error))
            {
                if (!policy.IsSuccess)
                {
                    return(policy.Cast <byte[]>());
                }
                NtStatus status = SecurityNativeMethods.LsaRetrievePrivateData(policy.Result,
                                                                               new UnicodeString(keyname), out SafeLsaMemoryBuffer data);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <byte[]>(throw_on_error));
                }
                using (data)
                {
                    data.Initialize <UnicodeStringOut>(1);
                    return(data.Read <UnicodeStringOut>(0).ToArray().CreateResult());
                }
            }
        }
        /// <summary>
        /// Convert a DOS filename to an NT filename and get as an ObjectAttributes structure
        /// </summary>
        /// <param name="filename">The DOS filename.</param>
        /// <param name="attributes">The object attribute flags.</param>
        /// <param name="sqos">An optional security quality of service.</param>
        /// <param name="security_descriptor">An optional security descriptor.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The object attributes</returns>
        public static NtResult <ObjectAttributes> DosFileNameToObjectAttributes(string filename, AttributeFlags attributes,
                                                                                SecurityQualityOfService sqos, SecurityDescriptor security_descriptor, bool throw_on_error)
        {
            if (filename == null)
            {
                throw new ArgumentNullException("filename");
            }

            UnicodeStringOut nt_name       = new UnicodeStringOut();
            RtlRelativeName  relative_name = new RtlRelativeName();

            try
            {
                NtStatus status = NtRtl.RtlDosPathNameToRelativeNtPathName_U_WithStatus(filename, out nt_name,
                                                                                        out IntPtr short_path, relative_name);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <ObjectAttributes>(throw_on_error));
                }
                string final_name;
                SafeKernelObjectHandle root = SafeKernelObjectHandle.Null;

                if (relative_name.RelativeName.Buffer != IntPtr.Zero)
                {
                    final_name = relative_name.RelativeName.ToString();
                    root       = new SafeKernelObjectHandle(relative_name.ContainingDirectory, false);
                }
                else
                {
                    final_name = nt_name.ToString();
                }

                return(status.CreateResult(false, () =>
                                           new ObjectAttributes(final_name, attributes, root, sqos, security_descriptor)));
            }
            finally
            {
                if (nt_name.Buffer != IntPtr.Zero)
                {
                    NtRtl.RtlFreeUnicodeString(ref nt_name);
                }

                if (relative_name.RelativeName.Buffer != IntPtr.Zero)
                {
                    NtRtl.RtlReleaseRelativeName(relative_name);
                }
            }
        }
示例#7
0
        /// <summary>
        /// Get a notification synchronously.
        /// </summary>
        /// <param name="timeout">Optional timeout for getting the notification.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The transaction notification.</returns>
        public NtResult <TransactionNotification> GetNotification(NtWaitTimeout timeout, bool throw_on_error)
        {
            NtStatus status = NtSystemCalls.NtGetNotificationResourceManager(Handle,
                                                                             SafeHGlobalBuffer.Null, 0, timeout.ToLargeInteger(), out int return_length, 0, IntPtr.Zero);

            if (status != NtStatus.STATUS_BUFFER_TOO_SMALL)
            {
                return(status.CreateResultFromError <TransactionNotification>(throw_on_error));
            }

            using (var buffer = new SafeStructureInOutBuffer <TransactionNotificationData>(return_length, false)) {
                return(NtSystemCalls.NtGetNotificationResourceManager(Handle,
                                                                      buffer, buffer.Length, timeout.ToLargeInteger(), out return_length, 0, IntPtr.Zero)
                       .CreateResult(throw_on_error, () => new TransactionNotification(buffer)));
            }
        }
示例#8
0
        /// <summary>
        /// Query a single system environment value.
        /// </summary>
        /// <param name="name">The name of the value.</param>
        /// <param name="vendor_guid">The associated vendor guid</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The system environment value.</returns>
        public static NtResult <SystemEnvironmentValue> QuerySystemEnvironmentValue(string name, Guid vendor_guid, bool throw_on_error)
        {
            UnicodeString name_string  = new UnicodeString(name);
            int           value_length = 0;
            NtStatus      status       = NtSystemCalls.NtQuerySystemEnvironmentValueEx(name_string, ref vendor_guid, null, ref value_length, 0);

            if (status != NtStatus.STATUS_BUFFER_TOO_SMALL)
            {
                return(status.CreateResultFromError <SystemEnvironmentValue>(throw_on_error));
            }

            byte[]        value      = new byte[value_length];
            OptionalInt32 attributes = new OptionalInt32();

            return(NtSystemCalls.NtQuerySystemEnvironmentValueEx(name_string, ref vendor_guid, value, ref value_length, attributes)
                   .CreateResult(throw_on_error, () => new SystemEnvironmentValue(name, value, attributes, vendor_guid)));
        }
示例#9
0
        /// <summary>
        /// Query a license value. While technically not directly a registry key
        /// it has many of the same properties such as using the same registry
        /// value types.
        /// </summary>
        /// <param name="name">The name of the license value.</param>
        /// <param name="throw_on_error">True to throw an exception on error</param>
        /// <returns>The license value key</returns>
        public static NtResult <NtKeyValue> QueryLicenseValue(string name, bool throw_on_error)
        {
            RegistryValueType type;
            int           ret_length;
            UnicodeString name_string = new UnicodeString(name);
            NtStatus      status      = NtSystemCalls.NtQueryLicenseValue(name_string, out type, SafeHGlobalBuffer.Null, 0, out ret_length);

            if (status != NtStatus.STATUS_BUFFER_TOO_SMALL)
            {
                return(status.CreateResultFromError <NtKeyValue>(throw_on_error));
            }

            using (var buffer = new SafeHGlobalBuffer(ret_length))
            {
                return(NtSystemCalls.NtQueryLicenseValue(name_string, out type, buffer, buffer.Length, out ret_length)
                       .CreateResult(throw_on_error, () => new NtKeyValue(name, type, buffer.ToArray(), 0)));
            }
        }
        /// <summary>
        /// Retrieve LSA privilege data.
        /// </summary>
        /// <param name="keyname">The name of the key.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The private data as bytes.</returns>
        public NtResult <byte[]> RetrievePrivateData(string keyname, bool throw_on_error)
        {
            if (keyname is null)
            {
                throw new ArgumentNullException(nameof(keyname));
            }

            NtStatus status = SecurityNativeMethods.LsaRetrievePrivateData(Handle,
                                                                           new UnicodeString(keyname), out SafeLsaMemoryBuffer data);

            if (!status.IsSuccess())
            {
                return(status.CreateResultFromError <byte[]>(throw_on_error));
            }
            using (data)
            {
                return(data.GetUnicodeString().ToArray().CreateResult());
            }
        }
示例#11
0
        /// <summary>
        /// Enumerate window handles.
        /// </summary>
        /// <param name="desktop">Desktop containing the Windows. Optional.</param>
        /// <param name="parent">The parent Window. Optional.</param>
        /// <param name="enum_children">True to enumerate child Windows.</param>
        /// <param name="hide_immersive">Hide immersive Windows.</param>
        /// <param name="thread_id">The thread ID that owns the Window.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The enumerated Window Handles.</returns>
        public static NtResult <IEnumerable <NtWindow> > GetWindows(NtDesktop desktop, NtWindow parent,
                                                                    bool enum_children, bool hide_immersive, int thread_id, bool throw_on_error)
        {
            int count = 64;

            while (true)
            {
                IntPtr[] handles = new IntPtr[count];
                NtStatus status  = NtSystemCalls.NtUserBuildHwndList(desktop.GetHandle(), parent.Handle, enum_children,
                                                                     hide_immersive, thread_id, handles.Length, handles, out int required_count);
                if (status.IsSuccess())
                {
                    return(handles.Take(required_count).Select(i => new NtWindow(i)).CreateResult());
                }
                if (status != NtStatus.STATUS_BUFFER_TOO_SMALL || count > required_count)
                {
                    return(status.CreateResultFromError <IEnumerable <NtWindow> >(throw_on_error));
                }
                count = required_count;
            }
        }
示例#12
0
        private NtResult <SafeHGlobalBuffer> CreateRelativeSecurityDescriptor(bool throw_on_error)
        {
            using (var sd_buffer = CreateAbsoluteSecurityDescriptor(throw_on_error))
            {
                if (!sd_buffer.IsSuccess)
                {
                    return(sd_buffer);
                }

                int      total_length = 0;
                NtStatus status       = NtRtl.RtlAbsoluteToSelfRelativeSD(sd_buffer.Result, SafeHGlobalBuffer.Null, ref total_length);
                if (status != NtStatus.STATUS_BUFFER_TOO_SMALL)
                {
                    return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                }

                using (var relative_sd = new SafeHGlobalBuffer(total_length))
                {
                    return(NtRtl.RtlAbsoluteToSelfRelativeSD(sd_buffer.Result, relative_sd, ref total_length)
                           .CreateResult(throw_on_error, () => relative_sd.Detach()));
                }
            }
        }
示例#13
0
        private static NtResult <NtToken> LsaLogonUser(SecurityLogonType type, string auth_package, string origin_name,
                                                       SafeBuffer buffer, IEnumerable <UserGroup> local_groups, bool throw_on_error)
        {
            using (var list = new DisposableList())
            {
                var hlsa = list.AddResource(SafeLsaLogonHandle.Connect(throw_on_error));
                if (!hlsa.IsSuccess)
                {
                    return(hlsa.Cast <NtToken>());
                }
                NtStatus status = SecurityNativeMethods.LsaLookupAuthenticationPackage(
                    hlsa.Result, new LsaString(auth_package), out uint auth_pkg);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <NtToken>(throw_on_error));
                }

                var groups = local_groups == null ? SafeTokenGroupsBuffer.Null
                    : list.AddResource(SafeTokenGroupsBuffer.Create(local_groups));

                TOKEN_SOURCE tokenSource = new TOKEN_SOURCE("NT.NET");
                SecurityNativeMethods.AllocateLocallyUniqueId(out tokenSource.SourceIdentifier);
                QUOTA_LIMITS quota_limits = new QUOTA_LIMITS();
                return(SecurityNativeMethods.LsaLogonUser(hlsa.Result, new LsaString(origin_name),
                                                          type, auth_pkg, buffer, buffer.GetLength(), groups,
                                                          tokenSource, out SafeLsaReturnBufferHandle profile,
                                                          out int cbProfile, out Luid logon_id, out SafeKernelObjectHandle token_handle,
                                                          quota_limits, out NtStatus subStatus).CreateResult(throw_on_error, () =>
                {
                    using (profile)
                    {
                        return NtToken.FromHandle(token_handle);
                    }
                }));
            }
        }
示例#14
0
        private NtResult <SafeHGlobalBuffer> CreateAbsoluteSecurityDescriptor(bool throw_on_error)
        {
            byte[] dacl       = Dacl?.ToByteArray();
            byte[] sacl       = Sacl?.ToByteArray();
            byte[] owner      = Owner?.Sid.ToArray();
            byte[] group      = Group?.Sid.ToArray();
            int    total_size = GetLength(dacl) + GetLength(sacl) + GetLength(owner) + GetLength(group);

            using (var sd_buffer = new SafeStructureInOutBuffer <SecurityDescriptorStructure>(total_size, true))
            {
                NtStatus status = NtRtl.RtlCreateSecurityDescriptor(sd_buffer, Revision);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                }

                SecurityDescriptorControl control = Control & SecurityDescriptorControl.ValidControlSetMask;
                status = NtRtl.RtlSetControlSecurityDescriptor(sd_buffer, control, control);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                }

                int current_ofs = 0;
                if (Dacl != null)
                {
                    IntPtr ptr = UpdateBuffer(sd_buffer, Dacl.NullAcl ? null : dacl, ref current_ofs);
                    status = NtRtl.RtlSetDaclSecurityDescriptor(sd_buffer, true, ptr, Dacl.Defaulted);
                    if (!status.IsSuccess())
                    {
                        return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                    }
                }

                if (Sacl != null)
                {
                    IntPtr ptr = UpdateBuffer(sd_buffer, Sacl.NullAcl ? null : sacl, ref current_ofs);
                    status = NtRtl.RtlSetSaclSecurityDescriptor(sd_buffer, true, ptr, Sacl.Defaulted);
                    if (!status.IsSuccess())
                    {
                        return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                    }
                }

                if (Owner != null)
                {
                    IntPtr ptr = UpdateBuffer(sd_buffer, owner, ref current_ofs);
                    status = NtRtl.RtlSetOwnerSecurityDescriptor(sd_buffer, ptr, Owner.Defaulted);
                    if (!status.IsSuccess())
                    {
                        return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                    }
                }

                if (Group != null)
                {
                    IntPtr ptr = UpdateBuffer(sd_buffer, group, ref current_ofs);
                    status = NtRtl.RtlSetGroupSecurityDescriptor(sd_buffer, ptr, Group.Defaulted);
                    if (!status.IsSuccess())
                    {
                        return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                    }
                }

                return(status.CreateResult <SafeHGlobalBuffer>(throw_on_error, () => sd_buffer.Detach()));
            }
        }
示例#15
0
        /// <summary>
        /// Parse the policy from the Local Security Authority.
        /// </summary>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The list of Central Access Policies.</returns>
        public static NtResult <CentralAccessPolicy[]> ParseFromLsa(bool throw_on_error)
        {
            NtStatus status = SecurityNativeMethods.LsaGetAppliedCAPIDs(null, out SafeLsaMemoryBuffer capids, out int capid_count);

            if (!status.IsSuccess())
            {
                return(status.CreateResultFromError <CentralAccessPolicy[]>(throw_on_error));
            }
            List <CentralAccessPolicy> ret = new List <CentralAccessPolicy>();

            using (capids) {
                status = SecurityNativeMethods.LsaQueryCAPs(capids.DangerousGetHandle(), capid_count, out SafeLsaMemoryBuffer caps, out uint cap_count);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <CentralAccessPolicy[]>(throw_on_error));
                }
                caps.Initialize <CENTRAL_ACCESS_POLICY>(cap_count);
                CENTRAL_ACCESS_POLICY[] policies = new CENTRAL_ACCESS_POLICY[cap_count];
                caps.ReadArray(0, policies, 0, policies.Length);
                foreach (var policy in policies)
                {
                    SafeHGlobalBuffer buffer       = new SafeHGlobalBuffer(policy.CAPEs, policy.CAPECount * IntPtr.Size, false);
                    IntPtr[]          rule_entries = new IntPtr[policy.CAPECount];
                    buffer.ReadArray(0, rule_entries, 0, policy.CAPECount);
                    List <CentralAccessRule> rules = new List <CentralAccessRule>();
                    foreach (var ptr in rule_entries)
                    {
                        var entry                     = new SafeStructureInOutBuffer <CENTRAL_ACCESS_POLICY_ENTRY>(ptr, Marshal.SizeOf(typeof(CENTRAL_ACCESS_POLICY_ENTRY)), false);
                        var r                         = entry.Result;
                        SecurityDescriptor sd         = null;
                        SecurityDescriptor staged_sd  = null;
                        string             applies_to = string.Empty;
                        if (r.LengthSD > 0)
                        {
                            var result = SecurityDescriptor.Parse(r.SD, throw_on_error);
                            if (!result.IsSuccess)
                            {
                                return(result.Cast <CentralAccessPolicy[]>());
                            }
                            sd = result.Result;
                        }
                        if (r.LengthStagedSD > 0)
                        {
                            var result = SecurityDescriptor.Parse(r.StagedSD, throw_on_error);
                            if (!result.IsSuccess)
                            {
                                return(result.Cast <CentralAccessPolicy[]>());
                            }
                            staged_sd = result.Result;
                        }
                        if (r.LengthAppliesTo > 0)
                        {
                            byte[] condition = new byte[r.LengthAppliesTo];
                            Marshal.Copy(r.AppliesTo, condition, 0, r.LengthAppliesTo);
                            var result = NtSecurity.ConditionalAceToString(condition, throw_on_error);
                            if (!result.IsSuccess)
                            {
                                return(result.Cast <CentralAccessPolicy[]>());
                            }
                            applies_to = result.Result;
                        }

                        rules.Add(new CentralAccessRule(r.Name.ToString(), r.Description.ToString(),
                                                        sd, staged_sd, applies_to, r.ChangeId.ToString(), r.Flags));
                    }
                    var capid = Sid.Parse(policy.CAPID, throw_on_error);
                    if (!capid.IsSuccess)
                    {
                        return(capid.Cast <CentralAccessPolicy[]>());
                    }
                    ret.Add(new CentralAccessPolicy(capid.Result, policy.Flags, policy.Name.ToString(),
                                                    policy.Description.ToString(), policy.ChangeId.ToString(), rules));
                }
            }
            return(ret.ToArray().CreateResult());
        }