grokgarble.com

Database, Software, and System Engineering

Network File Share in .NET C#

Well, kinda…

Using the ManagmentClass class (someone might be regretting the naming here) we can expose WMI in .NET.  Then, we can operate on methods of the Windows Managment Interface to create shares in C# code.

Like all Windows API work, this isn’t super clear throughout MSDN or the Internet.  I also find that Windows API return codes are a pain.  When I operate in that old schools space I try to take the next step and get a return code description method created.

Below, we create a security descriptor and share using .NET and WMI objects (with some return code flare).

Enjoy!

1) Figure out who you want access to your share.  This must be done with the use of of a Win32_SecurityDescriptor in WMI:

        private static ManagementBaseObject SecurityDescriptor()
        {
            NTAccount account = new NTAccount("NT Authority", "Everyone");
            SecurityIdentifier sid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
            byte[] sidArray = new byte[sid.BinaryLength];
            sid.GetBinaryForm(sidArray, 0);
            ManagementObject Trustee = new ManagementClass(new ManagementPath("Win32_Trustee"), null);
            Trustee["Domain"] = "NT Authority";
            Trustee["Name"] = "Everyone";
            Trustee["SID"] = sidArray;
            ManagementObject AdminACE = new ManagementClass(new ManagementPath("Win32_Ace"), null);
            AdminACE["AccessMask"] = 2032127;
            AdminACE["AceFlags"] = 3;
            AdminACE["AceType"] = 0;
            AdminACE["Trustee"] = Trustee;
            ManagementObject SecurityDescriptor = new ManagementClass(new ManagementPath("Win32_SecurityDescriptor"), null);
            SecurityDescriptor["ControlFlags"] = 4; //SE_DACL_PRESENT
            SecurityDescriptor["DACL"] = new object[] { AdminACE };
            return SecurityDescriptor;
        }

It’s never easy with security….

So for an explaination of the above; first, you look up your principle using NTAccount then create a Win32_Trustee from that principal.

note:  this method can *easily* be parameterized for a domain:

        private static ManagementBaseObject SecurityDescriptor(string domain, string user)
        {
            NTAccount account = new NTAccount(domain, user);
            SecurityIdentifier sid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));

[...]

Then, you estable what access controll entry (ACE) you want to grant to the principal(s) using the Win32_Ace object.  The SecurityDescriptor method above includes it all.  Side note: ACL and ACE’s are the most confusing things to code in Windows for me, bar none.  It’s not easy, play with the code to taste if you need specific access and don’t forget to review the AccessMask and AceTypes to limit down from full control as needed.  To add multiple add them as comma separated DACL’s like so:

SecurityDescriptor["DACL"] = new object[] { AdminACE, MyACE, YourACE, OurACE };

2) Finally, create your share

First, create your ManagmentClass object and parameters (using your above security principal(s)) for the “Create” method of the Win32_Share.  If anything funky happens decode the response code description.

        public static void CreateShare(string FolderPath, string ShareName, string Description)
        {
            //create a ManagementClass object
            ManagementClass managementClass = new ManagementClass("Win32_Share");

            //create ManagementBaseObjects for in and out parameters
            ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");
            ManagementBaseObject outParams;

            // Set the input parameters
            inParams["Description"] = Description;
            inParams["Name"] = ShareName;
            inParams["Path"] = FolderPath;
            inParams["Type"] = 0x0; // Disk Drive

            //invoke the method
            outParams = managementClass.InvokeMethod("Create", inParams, null);

            //check to see if the method invocation was successful
            uint rVal = (uint)(outParams.Properties["ReturnValue"].Value);
            if (rVal != 0 && rVal != 22) //ok if it already exists
            {
                throw new Exception(String.Format("Unable to share directory. \nReturn Code: {0} \nDescription: {1}", rVal, getCreateShareReturnCodeDescription(rVal)));
            }
        }

        private static string getCreateShareReturnCodeDescription(uint returnValue)
        {
            switch (returnValue)
            {
                case 0:
                    return "Success";
                case 2:
                    return "Access Denied";
                case 8:
                    return "Unknown Failure";
                case 9:
                    return "Invalid Name";
                case 10:
                    return "Invalid Level";
                case 21:
                    return "Invalid Parameter";
                case 22:
                    return "Duplicate Share";
                case 23:
                    return "Redirect Path";
                case 24:
                    return "Unknown Device or Directory";
                case 25:
                    return "Net Name Not Found";
            }
            return "Unknown";
        }

,

4 thoughts on “Network File Share in .NET C#

  • jacksonlps90@gmail.com' Jackson Lopes says:

    The following line:

    outParams = managementClass.InvokeMethod(“Create”, inParams, null);
    uint rVal = (uint)(outParams.Properties["ReturnValue"].Value);

    is returning the values 2(Access Denied.)

    I’ve been trying to solve it frm the past 48 hrs..I DESPERATELY NEED SOME HELP.

    • Jeff Murr says:

      Depending on your interface and server this can be a complicated problem to solve. If you’re using the code within a windows application, make sure you use elevated permissions on the exe. If you’re using the code within a web application, make sure the application pool is running under and identity that can access the file system you’re wanting to interact with. I’d start local before trying anything remote. Next start with external debugging techniques using processmonitor etc. to identify what is really giving you the access denied.

      Sorry for the late response Jackson. Just had a baby :).

      Jeff

      • haseenaa@gmail.com' Aruna says:

        I have tried the same from Windows Application and i have added the Security Descriptor too, not able to create a folder in my own local machine itself where i am an admin. It says “Access Denied”. Please help me with that. Thanks in Advance

  • lbj@applied-intelligence.dl' Lars Shakya Buch-Jepsen | Applied-Intelligence says:

    I know I reply on an old post but others might use it an inspiration.
    The missing part of the code is step 3 where the “SecurityDescriptor” is used on the share. The needed code is to get the share as a “ManagementObject” and on that invoke method “SetShareInfo” with your “SecurityDescriptor”.

Leave a Reply to Jeff Murr Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>