NetShareGetInfo in C# to read Share Permissions of a File System Object
NetShareGetInfo is a C++ API to read the information of a shared resource (File System Object – FSO). This blog shows how to use this API in C# to read Share Permissions of a shared FSO. For more information on NetShareGetinfo, please go through the below link
msdn.microsoft.com/en-us/library/windows/desktop/bb525388(v=vs.85).aspx
I was working with WMI class Win32_Share to read the Share Permissions of a folder in C#. The class read NTFS Permissions successfully, however I was unable to find a way to read the actual Share Permissions of the folder using this WMI class.
I used C++ NetShareGetInfo API earlier to read Share Permissions of a folder and decided to use the same NetShareGetInfo API in my C# application. I wrote C# wrap-up for this API and that successfully read the Share Permissions. A sample of C# application to read Share Permissions of a shared folder using NetShareGetInfo API is pasted below
1: using System;
2: using System.Collections.Generic;
3: using System.Text;
4: using System.Runtime.InteropServices;
5:
6: class MainConsole
7: {
8: [DllImport("Netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
9: static extern int NetShareGetInfo(
10: [MarshalAs(UnmanagedType.LPWStr)] string serverName,
11: [MarshalAs(UnmanagedType.LPWStr)] string netName,
12: Int32 level,
13: out IntPtr bufPtr);
14:
15: [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
16: [return: MarshalAs(UnmanagedType.Bool)]
17: static extern bool GetSecurityDescriptorDacl(
18: IntPtr pSecurityDescriptor,
19: [MarshalAs(UnmanagedType.Bool)] out bool bDaclPresent,
20: ref IntPtr pDacl,
21: [MarshalAs(UnmanagedType.Bool)] out bool bDaclDefaulted
22: );
23:
24: [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
25: [return: MarshalAs(UnmanagedType.Bool)]
26: static extern bool GetAclInformation(
27: IntPtr pAcl,
28: ref ACL_SIZE_INFORMATION pAclInformation,
29: uint nAclInformationLength,
30: ACL_INFORMATION_CLASS dwAclInformationClass
31: );
32:
33: [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
34: static extern int GetAce(
35: IntPtr aclPtr,
36: int aceIndex,
37: out IntPtr acePtr
38: );
39:
40: [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
41: static extern int GetLengthSid(
42: IntPtr pSID
43: );
44:
45: [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
46: [return: MarshalAs(UnmanagedType.Bool)]
47: static extern bool ConvertSidToStringSid(
48: [MarshalAs(UnmanagedType.LPArray)] byte[] pSID,
49: out IntPtr ptrSid
50: );
51:
52: [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
53: static extern int NetApiBufferFree(
54: IntPtr buffer
55: );
56:
57: enum SID_NAME_USE
58: {
59: SidTypeUser = 1,
60: SidTypeGroup,
61: SidTypeDomain,
62: SidTypeAlias,
63: SidTypeWellKnownGroup,
64: SidTypeDeletedAccount,
65: SidTypeInvalid,
66: SidTypeUnknown,
67: SidTypeComputer
68: }
69:
70: [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
71: static extern bool LookupAccountSid(
72: string lpSystemName,
73: [MarshalAs(UnmanagedType.LPArray)] byte[] Sid,
74: System.Text.StringBuilder lpName,
75: ref uint cchName,
76: System.Text.StringBuilder ReferencedDomainName,
77: ref uint cchReferencedDomainName,
78: out SID_NAME_USE peUse);
79:
80: [StructLayout(LayoutKind.Sequential)]
81: struct SHARE_INFO_502
82: {
83: [MarshalAs(UnmanagedType.LPWStr)]
84: public string shi502_netname;
85: public uint shi502_type;
86: [MarshalAs(UnmanagedType.LPWStr)]
87: public string shi502_remark;
88: public Int32 shi502_permissions;
89: public Int32 shi502_max_uses;
90: public Int32 shi502_current_uses;
91: [MarshalAs(UnmanagedType.LPWStr)]
92: public string shi502_path;
93: public IntPtr shi502_passwd;
94: public Int32 shi502_reserved;
95: public IntPtr shi502_security_descriptor;
96: }
97:
98: [StructLayout(LayoutKind.Sequential)]
99: struct ACL_SIZE_INFORMATION
100: {
101: public uint AceCount;
102: public uint AclBytesInUse;
103: public uint AclBytesFree;
104: }
105:
106: [StructLayout(LayoutKind.Sequential)]
107: public struct ACE_HEADER
108: {
109: public byte AceType;
110: public byte AceFlags;
111: public short AceSize;
112: }
113:
114: [StructLayout(LayoutKind.Sequential)]
115: struct ACCESS_ALLOWED_ACE
116: {
117: public ACE_HEADER Header;
118: public int Mask;
119: public int SidStart;
120: }
121:
122: enum ACL_INFORMATION_CLASS
123: {
124: AclRevisionInformation = 1,
125: AclSizeInformation
126: }
127:
128:
129:
130: static void Main(string[] args)
131: {
132: IntPtr bufptr = IntPtr.Zero;
133: int err = NetShareGetInfo("ServerName", "ShareName", 502, out bufptr);
134: if (0 == err)
135: {
136: SHARE_INFO_502 shareInfo = (SHARE_INFO_502)Marshal.PtrToStructure(bufptr, typeof(SHARE_INFO_502));
137:
138: bool bDaclPresent;
139: bool bDaclDefaulted;
140: IntPtr pAcl = IntPtr.Zero;
141: GetSecurityDescriptorDacl(shareInfo.shi502_security_descriptor, out bDaclPresent, ref pAcl, out bDaclDefaulted);
142: if (bDaclPresent)
143: {
144: ACL_SIZE_INFORMATION AclSize = new ACL_SIZE_INFORMATION();
145: GetAclInformation(pAcl, ref AclSize, (uint)Marshal.SizeOf(typeof(ACL_SIZE_INFORMATION)), ACL_INFORMATION_CLASS.AclSizeInformation);
146: for (int i = 0; i < AclSize.AceCount; i++)
147: {
148: IntPtr pAce;
149: err = GetAce(pAcl, i, out pAce);
150: ACCESS_ALLOWED_ACE ace = (ACCESS_ALLOWED_ACE)Marshal.PtrToStructure(pAce, typeof(ACCESS_ALLOWED_ACE));
151:
152: IntPtr iter = (IntPtr)((long)pAce + (long)Marshal.OffsetOf(typeof(ACCESS_ALLOWED_ACE), "SidStart"));
153: byte[] bSID = null;
154: int size = (int)GetLengthSid(iter);
155: bSID = new byte[size];
156: Marshal.Copy(iter, bSID, 0, size);
157: IntPtr ptrSid;
158: ConvertSidToStringSid(bSID, out ptrSid);
159: string strSID = Marshal.PtrToStringAuto(ptrSid);
160:
161: Console.WriteLine("The details of ACE number {0} are: ", i+1);
162:
163: StringBuilder name = new StringBuilder();
164: uint cchName = (uint)name.Capacity;
165: StringBuilder referencedDomainName = new StringBuilder();
166: uint cchReferencedDomainName = (uint)referencedDomainName.Capacity;
167: SID_NAME_USE sidUse;
168:
169: LookupAccountSid(null, bSID, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse);
170:
171: Console.WriteLine("Trustee Name: " + name);
172: Console.WriteLine("Domain Name: " + referencedDomainName);
173:
174: if ((ace.Mask & 0x1F01FF) == 0x1F01FF)
175: {
176: Console.WriteLine("Permission: Full Control");
177: }
178: else if ((ace.Mask & 0x1301BF) == 0x1301BF)
179: {
180: Console.WriteLine("Permission: READ and CHANGE");
181: }
182: else if ((ace.Mask & 0x1200A9) == 0x1200A9)
183: {
184: Console.WriteLine("Permission: READ only");
185: }
186: Console.WriteLine("SID: {0} \nHeader AceType: {1} \nAccess Mask: {2} \nHeader AceFlag: {3}", strSID, ace.Header.AceType.ToString(), ace.Mask.ToString(), ace.Header.AceFlags.ToString());
187: Console.WriteLine("\n");
188: }
189: }
190: err = NetApiBufferFree(bufptr);
191: }
192: }
193:
194: }
195:
196:
The first parameter of API is the server name and the second parameter is the shared resource name (folder).
Most of the work involved in writing the C# wrap-up for API and defining the structures for ACE flags and types. A sample output of the application is pasted below
The details of ACE number 1 are:
Trustee Name: UserName
Domain Name: DomainName
Permission: Full Control
SID: S-1-5-21-2146773085-903363285-719344707-359738
Header AceType: 0
Access Mask: 2032127
Header AceFlag: 0