├── .gitignore
├── Directory.Build.Props
├── Program.cs
├── README.md
├── Sharelord.csproj
├── Sharelord.sln
├── bin
└── Release
│ └── net4.8
│ └── publish
│ └── Sharelord.exe
└── starlord-dance.gif
/.gitignore:
--------------------------------------------------------------------------------
1 | obj/
2 | bin/
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Directory.Build.Props:
--------------------------------------------------------------------------------
1 |
2 |
3 | false
4 | false
5 |
6 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using System.Security.AccessControl;
4 | using System.Security.Principal;
5 | using System.IO;
6 |
7 | class Program
8 | {
9 | // P/Invoke declarations
10 | [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)]
11 | static extern int NetShareAdd(string servername, int level, ref SHARE_INFO_2 buf, out int parm_err);
12 |
13 | [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)]
14 | static extern int NetShareSetInfo(string servername, string netname, int level, IntPtr buf, out int parm_err);
15 |
16 | [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)]
17 | static extern int NetShareDel(string servername, string netname, int reserved);
18 |
19 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
20 | struct SHARE_INFO_2
21 | {
22 | [MarshalAs(UnmanagedType.LPWStr)] public string shi2_netname;
23 | public uint shi2_type;
24 | [MarshalAs(UnmanagedType.LPWStr)] public string shi2_remark;
25 | public uint shi2_permissions;
26 | public uint shi2_max_uses;
27 | public uint shi2_current_uses;
28 | [MarshalAs(UnmanagedType.LPWStr)] public string shi2_path;
29 | [MarshalAs(UnmanagedType.LPWStr)] public string shi2_passwd;
30 | }
31 |
32 | [StructLayout(LayoutKind.Sequential)]
33 | struct SHARE_INFO_502
34 | {
35 | [MarshalAs(UnmanagedType.LPWStr)] public string shi502_netname;
36 | public uint shi502_type;
37 | [MarshalAs(UnmanagedType.LPWStr)] public string shi502_remark;
38 | public uint shi502_permissions;
39 | public uint shi502_max_uses;
40 | public uint shi502_current_uses;
41 | [MarshalAs(UnmanagedType.LPWStr)] public string shi502_path;
42 | [MarshalAs(UnmanagedType.LPWStr)] public string shi502_passwd;
43 | public uint shi502_reserved;
44 | public IntPtr shi502_security_descriptor;
45 | }
46 |
47 | static void Main(string[] args)
48 | {
49 | if (args.Length == 0 || args[0].ToLower() == "help" || args[0].ToLower() == "--help" || args[0].ToLower() == "-h")
50 | {
51 | ShowDetailedHelp();
52 | return;
53 | }
54 |
55 | try
56 | {
57 | switch (args[0].ToLower())
58 | {
59 | case "create":
60 | HandleCreateCommand(args);
61 | break;
62 | case "setace":
63 | if (args.Length != 5) throw new ArgumentException("Invalid number of arguments for setace command.");
64 | SetAce(args[1], args[2], args[3], args[4]);
65 | break;
66 | case "setshareperms":
67 | if (args.Length != 5) throw new ArgumentException("Invalid number of arguments for setshareperms command.");
68 | SetSharePermissions(args[1], args[2], args[3], args[4]);
69 | break;
70 | case "delete":
71 | if (args.Length != 2) throw new ArgumentException("Invalid number of arguments for delete command.");
72 | DeleteShare(args[1]);
73 | break;
74 | default:
75 | throw new ArgumentException("Invalid command.");
76 | }
77 | }
78 | catch (Exception ex)
79 | {
80 | Console.WriteLine($"Error: {ex.Message}");
81 | PrintUsage();
82 | }
83 | }
84 |
85 | static void PrintUsage()
86 | {
87 | Console.WriteLine("Usage:");
88 | Console.WriteLine(" Sharelord.exe [arguments]");
89 | Console.WriteLine("\nCommands:");
90 | Console.WriteLine(" create [-r ]");
91 | Console.WriteLine(" setace ");
92 | Console.WriteLine(" setshareperms ");
93 | Console.WriteLine(" delete ");
94 | Console.WriteLine(" help Show detailed help and list of available permissions");
95 | Console.WriteLine("\nUse 'Sharelord.exe help' for more detailed information.");
96 | }
97 |
98 | static void ShowDetailedHelp()
99 | {
100 | Console.WriteLine("Sharelord - Detailed Help");
101 | Console.WriteLine("\nAvailable commands:");
102 | Console.WriteLine(" create [-r ]");
103 | Console.WriteLine(" setace ");
104 | Console.WriteLine(" setshareperms ");
105 | Console.WriteLine(" delete ");
106 | Console.WriteLine(" help");
107 |
108 | Console.WriteLine("\nFile System Rights (for setace command):");
109 | foreach (FileSystemRights right in Enum.GetValues(typeof(FileSystemRights)))
110 | {
111 | Console.WriteLine($" {right}");
112 | }
113 |
114 | Console.WriteLine("\nAccess Control Types:");
115 | Console.WriteLine(" Allow");
116 | Console.WriteLine(" Deny");
117 |
118 | Console.WriteLine("\nShare Permissions (for setshareperms command):");
119 | Console.WriteLine(" Read - Users can view file and subfolder names, read data, and run programs");
120 | Console.WriteLine(" Change - Users have Read permissions plus the ability to create, change, and delete files and subfolders");
121 | Console.WriteLine(" FullControl - Users have Change permissions plus the ability to change permissions and take ownership");
122 |
123 | Console.WriteLine("\nExamples:");
124 | Console.WriteLine(" Sharelord.exe create C:\\SharedFolder MyShare -r \"Shared folder for team\"");
125 | Console.WriteLine(" Sharelord.exe setace C:\\SharedFolder Domain\\User Modify Allow");
126 | Console.WriteLine(" Sharelord.exe setshareperms MyShare Domain\\User Change Allow");
127 | Console.WriteLine(" Sharelord.exe delete MyShare");
128 | }
129 |
130 | static void HandleCreateCommand(string[] args)
131 | {
132 | if (args.Length < 3)
133 | {
134 | throw new ArgumentException("Invalid number of arguments for create command.");
135 | }
136 |
137 | string directory = args[1];
138 | string shareName = args[2];
139 | string remark = null;
140 |
141 | // Check for optional remark flag
142 | for (int i = 3; i < args.Length; i++)
143 | {
144 | if (args[i] == "-r" && i + 1 < args.Length)
145 | {
146 | remark = args[i + 1];
147 | break;
148 | }
149 | }
150 |
151 | CreateShare(directory, shareName, remark);
152 | }
153 |
154 | static void CreateShare(string directory, string shareName, string remark)
155 | {
156 | if (!Directory.Exists(directory))
157 | {
158 | throw new DirectoryNotFoundException($"The directory '{directory}' does not exist.");
159 | }
160 |
161 | SHARE_INFO_2 shareInfo = new SHARE_INFO_2
162 | {
163 | shi2_netname = shareName,
164 | shi2_type = 0, // Disk share
165 | shi2_remark = remark,
166 | shi2_permissions = 0, // Use NT security
167 | shi2_max_uses = unchecked((uint)-1), // Maximum allowed
168 | shi2_current_uses = 0,
169 | shi2_path = directory,
170 | shi2_passwd = null
171 | };
172 |
173 | int parmErr = 0;
174 | int result = NetShareAdd(null, 2, ref shareInfo, out parmErr);
175 |
176 | if (result != 0)
177 | {
178 | throw new Exception($"Failed to create share. Error code: {result}, Parameter Error: {parmErr}");
179 | }
180 |
181 | Console.WriteLine($"Share '{shareName}' created successfully for directory '{directory}'.");
182 | if (!string.IsNullOrEmpty(remark))
183 | {
184 | Console.WriteLine($"Remark: {remark}");
185 | }
186 | }
187 |
188 | static void SetAce(string directory, string username, string rights, string type)
189 | {
190 | FileSystemRights fsr = (FileSystemRights)Enum.Parse(typeof(FileSystemRights), rights);
191 | AccessControlType act = (AccessControlType)Enum.Parse(typeof(AccessControlType), type);
192 |
193 | DirectoryInfo dirInfo = new DirectoryInfo(directory);
194 | DirectorySecurity dirSecurity = dirInfo.GetAccessControl();
195 |
196 | dirSecurity.AddAccessRule(new FileSystemAccessRule(username, fsr,
197 | InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
198 | PropagationFlags.None, act));
199 |
200 | dirInfo.SetAccessControl(dirSecurity);
201 |
202 | Console.WriteLine($"ACE set for {username} on {directory}");
203 | }
204 |
205 | static void SetSharePermissions(string shareName, string username, string permissions, string type)
206 | {
207 | NTAccount account = new NTAccount(username);
208 | SecurityIdentifier sid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
209 |
210 | uint permissionsMask = (uint)Enum.Parse(typeof(FileSystemRights), permissions);
211 | string sdString = $"D:(A;;{permissionsMask:X};;;{sid.Value})";
212 |
213 | RawSecurityDescriptor rsd = new RawSecurityDescriptor(sdString);
214 | byte[] binarySD = new byte[rsd.BinaryLength];
215 | rsd.GetBinaryForm(binarySD, 0);
216 |
217 | IntPtr securityDescriptor = Marshal.AllocHGlobal(binarySD.Length);
218 | Marshal.Copy(binarySD, 0, securityDescriptor, binarySD.Length);
219 |
220 | SHARE_INFO_502 shareInfo = new SHARE_INFO_502
221 | {
222 | shi502_netname = shareName,
223 | shi502_type = 0,
224 | shi502_remark = null,
225 | shi502_permissions = 0,
226 | shi502_max_uses = unchecked((uint)-1),
227 | shi502_current_uses = 0,
228 | shi502_path = null,
229 | shi502_passwd = null,
230 | shi502_reserved = 0,
231 | shi502_security_descriptor = securityDescriptor
232 | };
233 |
234 | IntPtr pShareInfo = Marshal.AllocHGlobal(Marshal.SizeOf(shareInfo));
235 | Marshal.StructureToPtr(shareInfo, pShareInfo, false);
236 |
237 | try
238 | {
239 | int parmErr = 0;
240 | int result = NetShareSetInfo(null, shareName, 502, pShareInfo, out parmErr);
241 | if (result != 0)
242 | {
243 | throw new Exception($"Failed to set share permissions. Error code: {result}");
244 | }
245 |
246 | Console.WriteLine($"Share permissions set for {username} on {shareName}");
247 | }
248 | finally
249 | {
250 | Marshal.FreeHGlobal(securityDescriptor);
251 | Marshal.FreeHGlobal(pShareInfo);
252 | }
253 | }
254 |
255 | static void DeleteShare(string shareName)
256 | {
257 | int result = NetShareDel(null, shareName, 0);
258 | if (result == 0)
259 | {
260 | Console.WriteLine($"Share '{shareName}' deleted successfully.");
261 | }
262 | else
263 | {
264 | throw new Exception($"Failed to delete share. Error code: {result}");
265 | }
266 | }
267 | }
268 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sharelord (lowercase l)
2 | 
3 |
4 | .NET Assembly to learn how to interact with Win32 APIs to create network shares, delete shares, and set share perms. It uses .NET methods to set ACE. Will eventually switch all to more directly use Win32 APIs. Currently using PInvoke. I hope to switch to DInvoke soon when I figure out an memory access violation i'm running into. Help with DInvoke would be greatly appreciated.
5 | ---
6 | Sharelord is a command-line tool for managing Windows shared folders and their permissions.
7 |
8 | ## Features
9 |
10 | - Create and delete shared folders
11 | - Set file system access control entries (ACEs)
12 | - Set share-level permissions
13 |
14 | ## Usage
15 |
16 | Run `Sharelord.exe --help` for detailed information on available commands and options.
17 |
18 | Basic syntax:
19 |
20 | ```
21 | Sharelord.exe [options]
22 | ```
23 |
24 | ## Examples
25 |
26 | Create a shared folder:
27 | ```
28 | Sharelord.exe create C:\SharedFolder MyShare -r "Shared folder for team"
29 | ```
30 |
31 | Set file system permissions:
32 | ```
33 | Sharelord.exe setace C:\SharedFolder Domain\User Modify Allow
34 | ```
35 |
36 | Set share-level permissions:
37 | ```
38 | Sharelord.exe setshareperms MyShare Domain\User Change Allow
39 | ```
40 |
41 | Delete a share:
42 | ```
43 | Sharelord.exe delete MyShare
44 | ```
45 |
46 | ## Note
47 |
48 | For a full list of commands, options, and permissions, refer to the built-in help menu by running `Sharelord.exe --help`.
49 |
50 | ## Build Instructions
51 |
52 | This project is a .NET application targeting .NET Framework 4.8.
53 |
54 | ### Prerequisites
55 |
56 | To build and run this project, you'll need:
57 |
58 | - [Visual Studio Code](https://code.visualstudio.com/)
59 | - [.NET Framework 4.8 Developer Pack](https://dotnet.microsoft.com/download/dotnet-framework/net48)
60 | - [C# extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp)
61 |
62 | ### Dependencies
63 |
64 | The project has the following dependencies:
65 |
66 | - System.IO.FileSystem.AccessControl (5.0.0)
67 | - System.Security.AccessControl (6.0.1)
68 | - System.Security.Principal.Windows (5.0.0)
69 |
70 |
71 | ### Building the Project
72 |
73 | 1. Open the project folder in Visual Studio Code.
74 | 2. Open the integrated terminal in VS Code (View > Terminal).
75 | 3. Run the following command to build the project:
76 |
77 | ```
78 | dotnet build
79 | ```
80 |
81 | 4. If you want to create a release build, use:
82 |
83 | ```
84 | dotnet build -c Release
85 | ```
86 |
87 | ### Notes
88 |
89 | - The project is configured to use the latest C# language version.
90 | - Unsafe blocks are allowed in the code.
91 | - In Release configuration, debug symbols are not generated.
92 |
93 | For more detailed information about the project structure and configuration, refer to the `.csproj` file.
94 |
95 | ## References
96 | - https://github.com/TheWover/DInvoke
97 | - https://github.com/rasta-mouse/DInvoke
98 | - https://www.pinvoke.net/default.aspx/netapi32/_ContentBaseDefinition.html
99 | - https://learn.microsoft.com/en-us/windows/win32/api/lmshare/nf-lmshare-netshareadd
100 | - https://learn.microsoft.com/en-us/windows/win32/api/lmshare/nf-lmshare-netsharedel
101 | - https://learn.microsoft.com/en-us/windows/win32/api/lmshare/nf-lmshare-netsharesetinfo
102 | - https://learn.microsoft.com/en-us/windows/win32/api/lmshare/ns-lmshare-share_info_2
103 | - https://learn.microsoft.com/en-us/windows/win32/api/lmshare/ns-lmshare-share_info_502
104 |
--------------------------------------------------------------------------------
/Sharelord.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | net4.8
11 | Exe
12 | latest
13 | true
14 | false
15 | annotations
16 | true
17 | false
18 |
19 |
20 |
21 | none
22 | false
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Sharelord.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.5.002.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sharelord", "Sharelord.csproj", "{0D00E441-BE4C-47DF-A57E-522102531FC0}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {0D00E441-BE4C-47DF-A57E-522102531FC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {0D00E441-BE4C-47DF-A57E-522102531FC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {0D00E441-BE4C-47DF-A57E-522102531FC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {0D00E441-BE4C-47DF-A57E-522102531FC0}.Release|Any CPU.Build.0 = Release|Any CPU
18 | {D8387AAA-678F-4814-A6D4-F95319814BC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {D8387AAA-678F-4814-A6D4-F95319814BC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {D8387AAA-678F-4814-A6D4-F95319814BC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {D8387AAA-678F-4814-A6D4-F95319814BC0}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {2B484232-9B5E-43C5-A4F9-9B3E652EAD3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {2B484232-9B5E-43C5-A4F9-9B3E652EAD3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {2B484232-9B5E-43C5-A4F9-9B3E652EAD3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {2B484232-9B5E-43C5-A4F9-9B3E652EAD3D}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {321AAE29-29C3-4FF0-9159-313584A8E1D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {321AAE29-29C3-4FF0-9159-313584A8E1D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {321AAE29-29C3-4FF0-9159-313584A8E1D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {321AAE29-29C3-4FF0-9159-313584A8E1D7}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {73B18981-8F02-4FDD-B21F-D41182516ECB}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/bin/Release/net4.8/publish/Sharelord.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NocteDefensor/Sharelord/7272c55a945e9b9cce5734b0c14ea36e3a3bf7a5/bin/Release/net4.8/publish/Sharelord.exe
--------------------------------------------------------------------------------
/starlord-dance.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NocteDefensor/Sharelord/7272c55a945e9b9cce5734b0c14ea36e3a3bf7a5/starlord-dance.gif
--------------------------------------------------------------------------------