Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All
Important This document may not represent best practices for current development, links to downloads and other resources may no longer be valid. Current recommended version can be found here.

How To: Update a Security Descriptor of a WMI Namespace

.NET Framework 2.0

A security descriptor identifies a securable object's owner and primary group. A functional security descriptor is in binary format, but security descriptors can also be in string format to store and transmit security descriptor information. By changing a security descriptor, you can grant a group certain rights to access a securable object. This example updates the security descriptor information for a namespace so that certain users can access and modify the namespace.

Example

The following code example grants all rights to the Power Users group for a given namespace. To change the namespace name, change the value of the namespaceName variable in the Sample class.

using System;
using System.Management;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace ManagementSample
{
    class Sample
    {
        private readonly string namespaceName = 
            "TestNamespaceSecurity";

        public void Run()
        {
            IntPtr stringSecurityDescriptorPtr = IntPtr.Zero;
            IntPtr securityDescriptorPtr = IntPtr.Zero;
            int stringSecurityDescriptorSize = 0;
            int securityDescriptorSize = 0;

            try
            {
                // Create a test namespace
                this.CreateTestNamespace();

                // Retreive SD of a namespace
                ManagementClass systemSecurity = 
                    new ManagementClass("root/" + 
                    namespaceName + ":__SystemSecurity");
                ManagementBaseObject outParams =
                    systemSecurity.InvokeMethod("GetSD",
                      null, null);
                if ((uint)outParams["ReturnValue"] != 0)
                {
                    Console.WriteLine("GetSD returns an error: " +
                        outParams["ReturnValue"]);
                    return;
                }                                

                // Convert SD to string SD
                this.ConvertSDtoStringSD((byte[])outParams["SD"],
                    out stringSecurityDescriptorPtr,
                    out stringSecurityDescriptorSize);
                string stringSecurityDescriptor =
                    Marshal.PtrToStringAuto(
                    stringSecurityDescriptorPtr);
                Console.WriteLine("Original string security " +
                    "descriptor of the {0} namespace:",
                    namespaceName);
                Console.WriteLine(stringSecurityDescriptor);
                
                // Grant all permissions to Power Users Group
                stringSecurityDescriptor +=
                    "(A;;CCDCLCSWRPWPRCWD;;;PU)";

                //Convert string SD to SD
                Console.WriteLine(
                    "\nNew String Security Descriptor:");
                Console.WriteLine(stringSecurityDescriptor); 
                this.ConvertStringSDtoSD(stringSecurityDescriptor,
                    out securityDescriptorPtr,
                    out securityDescriptorSize);
                byte[] securityDescriptor = 
                    new byte[securityDescriptorSize];
                Marshal.Copy(securityDescriptorPtr,
                    securityDescriptor, 0, securityDescriptorSize);

                //Set the new SD for the namespace
                ManagementBaseObject inParams = 
                    systemSecurity.GetMethodParameters("SetSD");                                
                inParams["SD"] = securityDescriptor;
                outParams = systemSecurity.InvokeMethod("SetSD",
                    inParams, null);
                if ((uint)outParams["ReturnValue"] != 0)
                {
                    Console.WriteLine("SetSD returns error: " +
                        outParams["ReturnValue"]);
                    return;
                }
                Console.WriteLine("\nNew string security descriptor"
                    + " is set. Press Enter to exit.");
                Console.ReadLine();
            }
            finally
            {
                // Free unmanaged memory
                if (securityDescriptorPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(securityDescriptorPtr);
                    securityDescriptorPtr = IntPtr.Zero;
                }
                if (stringSecurityDescriptorPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(stringSecurityDescriptorPtr);
                    stringSecurityDescriptorPtr = IntPtr.Zero;
                }
                this.DeleteTestNamespace();
            }
        }

        public void ConvertSDtoStringSD(byte[] securityDescriptor,
            out IntPtr stringSecurityDescriptorPtr,
            out int stringSecurityDescriptorSize)
        {
            bool result = 
                ConvertSecurityDescriptorToStringSecurityDescriptor(
                securityDescriptor,
                1,
                SecurityInformation.DACL_SECURITY_INFORMATION | 
                SecurityInformation.GROUP_SECURITY_INFORMATION |
                SecurityInformation.OWNER_SECURITY_INFORMATION |
                SecurityInformation.SACL_SECURITY_INFORMATION,
                out stringSecurityDescriptorPtr,
                out stringSecurityDescriptorSize);
            if (!result) 
            {
                Console.WriteLine( "Fail to convert" +
                    " SD to string SD:" );
                throw new Win32Exception(
                    Marshal.GetLastWin32Error());
            }
        }

        public void ConvertStringSDtoSD(
            string stringSecurityDescriptor,
            out IntPtr securityDescriptorPtr,
            out int securityDescriptorSize)
        {
            bool result =
                ConvertStringSecurityDescriptorToSecurityDescriptor(
                stringSecurityDescriptor,
                1,
                out securityDescriptorPtr,
                out securityDescriptorSize);
            if (!result) 
            {
                Console.WriteLine( 
                    "Fail to convert string SD to SD:" );
                throw new Win32Exception(
                    Marshal.GetLastWin32Error());
            }
        }

        private enum SecurityInformation : uint
        {
            OWNER_SECURITY_INFORMATION= 0x00000001,
            GROUP_SECURITY_INFORMATION= 0x00000002,
            DACL_SECURITY_INFORMATION= 0x00000004,
            SACL_SECURITY_INFORMATION= 0x00000008,
            PROTECTED_DACL_SECURITY_INFORMATION= 0x80000000,
            PROTECTED_SACL_SECURITY_INFORMATION= 0x40000000,
            UNPROTECTED_DACL_SECURITY_INFORMATION= 0x20000000,
            UNPROTECTED_SACL_SECURITY_INFORMATION= 0x10000000,
        };

        [DllImport("Advapi32.dll", CharSet=CharSet.Auto,
            SetLastError=true, ExactSpelling=false)]
        private static extern bool 
            ConvertSecurityDescriptorToStringSecurityDescriptor(
            [In] byte[] SecurityDescriptor,
            [In] int RequestedStringSDRevision,
            [In] SecurityInformation SecurityInformation,
            [Out] out IntPtr StringSecurityDescriptor,
            [Out] out int StringSecurityDescriptorLen
        );


        [DllImport("Advapi32.dll", CharSet=CharSet.Auto,
            SetLastError=true, ExactSpelling=false)]
        private static extern bool 
            ConvertStringSecurityDescriptorToSecurityDescriptor(
            [In] string StringSecurityDescriptor,
            [In] uint StringSDRevision,
            [Out] out IntPtr SecurityDescriptor,
            [Out] out int SecurityDescriptorSize
        );

        private void CreateTestNamespace()
        {
            ManagementClass rootNamespace = 
                new ManagementClass("root:__namespace");
            ManagementObject testNamespace = 
                rootNamespace.CreateInstance();
            testNamespace["Name"] = namespaceName;
            testNamespace.Put();
        }

        private void DeleteTestNamespace()
        {
            ManagementObject testNamespace = 
            new ManagementObject("root:__namespace.Name='" 
                + namespaceName + "'");
            try
            {
                testNamespace.Get();
                testNamespace.Delete();
            }
            catch (ManagementException e)
            {
                if (e.ErrorCode == ManagementStatus.NotFound)
                    return;
            }
        }

        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                new Sample().Run(); 
            }
            catch (Win32Exception e)
            {
                Console.WriteLine(e);
            }
        }
    }
}

Compiling the Code

The example requires references to the System and System.Management namespaces.

See Also

Community Additions

ADD
Show:
© 2015 Microsoft