Hello,
You can use this code to get list of users from shared folder of source path and also add users to destination path. It will also make destination folder shared.
It is useful to copy folder from one path to another with all its permissions.
You can use this code to get list of users from shared folder of source path and also add users to destination path. It will also make destination folder shared.
It is useful to copy folder from one path to another with all its permissions.
Code:
public void SetPermissions(string srcPath, string destPath)
{
string unc;
string sharedName = string.Empty;
if (TryGetLocalFromUncDirectory(srcPath, out unc, out sharedName))
{
sharedName = Path.GetFileName(unc);
if (!Directory.Exists(destPath))
{
Directory.CreateDirectory(destPath);
}
string userName = Environment.UserName;
string domainName = Environment.UserDomainName;
AddPermissions(sharedName, domainName, userName, destPath);
}
}
/// <summary>
/// Remove the share.
/// </summary>
private uint RemoveShare(string shareName)
{
try
{
using (ManagementObject o = new ManagementObject("root\\cimv2",
"Win32_Share.Name='" + shareName + "'", null))
{
ManagementBaseObject outParams = o.InvokeMethod("delete", null, null);
return (uint)(outParams.Properties["ReturnValue"].Value);
}
}
catch (Exception ex)
{
return 1;
}
}
/// <summary>
/// Creates the share.
/// </summary>
private void AddPermissions(string sharedFolderName, string domain, string userName, string destPath)
{
// Step 1 - Getting the user Account Object
ManagementObject sharedFolder = GetSharedFolderObject(sharedFolderName);
if (sharedFolder==null)
{
System.Diagnostics.Trace.WriteLine("The shared folder with given name does not exist");
return;
}
ManagementBaseObject securityDescriptorObject = sharedFolder.InvokeMethod("GetSecurityDescriptor", null, null);
if (securityDescriptorObject == null)
{
System.Diagnostics.Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "Error extracting security descriptor of the shared path {0}.", sharedFolderName));
return;
}
int returnCode = Convert.ToInt32(securityDescriptorObject.Properties["ReturnValue"].Value);
if (returnCode != 0)
{
System.Diagnostics.Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "Error extracting security descriptor of the shared path {0}. Error Code{1}.", sharedFolderName, returnCode.ToString()));
return;
}
ManagementBaseObject securityDescriptor = securityDescriptorObject.Properties["Descriptor"].Value as ManagementBaseObject;
// Step 2 -- Extract Access Control List from the security descriptor
int existingAcessControlEntriesCount = 0;
ManagementBaseObject[] accessControlList = securityDescriptor.Properties["DACL"].Value as ManagementBaseObject[];
if (accessControlList == null)
{
// If there aren't any entries in access control list or the list is empty - create one
accessControlList = new ManagementBaseObject[1];
}
else
{
// Otherwise, resize the list to allow for all new users.
existingAcessControlEntriesCount = accessControlList.Length;
Array.Resize(ref accessControlList, accessControlList.Length + 1);
}
// Step 3 - Getting the user Account Object
ManagementObject userAccountObject = GetUserAccountObject(domain, userName);
ManagementObject securityIdentfierObject = new ManagementObject(string.Format("Win32_SID.SID='{0}'", (string)userAccountObject.Properties["SID"].Value));
securityIdentfierObject.Get();
// Step 4 - Create Trustee Object
ManagementObject trusteeObject = CreateTrustee(domain, userName, securityIdentfierObject);
// Step 5 - Create Access Control Entry
ManagementObject accessControlEntry = CreateAccessControlEntry(trusteeObject, false);
// Step 6 - Add Access Control Entry to the Access Control List
accessControlList[existingAcessControlEntriesCount] = accessControlEntry;
// Step 7 - Assign access Control list to security desciptor
securityDescriptor.Properties["DACL"].Value = accessControlList;
// Step 8 - Assign access Control list to security desciptor
ManagementBaseObject parameterForSetSecurityDescriptor = sharedFolder.GetMethodParameters("SetSecurityDescriptor");
parameterForSetSecurityDescriptor["Descriptor"] = securityDescriptor;
sharedFolder.InvokeMethod("SetSecurityDescriptor", parameterForSetSecurityDescriptor, null);
// Step 9 - Remove Shared Folder
RemoveShare(sharedFolderName);
// Step 10 - Create Shared Folder
CreateSharedFolderWithUserPermissions(securityDescriptor, sharedFolderName, destPath);
}
/// <summary>
/// Gets the UNC path for a local path passed to it. empty string if folder isn't shared
///
/// </summary>
/// <param name="local">The local path</param>
/// <param name="unc">The UNC path</param>
/// <returns>True if UNC is valid, false otherwise</returns>
///
private bool TryGetLocalFromUncDirectory(string local, out string unc, out string sharedName)
{
unc = string.Empty;
sharedName = string.Empty;
if (string.IsNullOrEmpty(local))
{
throw new ArgumentNullException("local");
}
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Name FROM Win32_share WHERE path ='" + local.Replace("\\", "\\\\") + "'");
ManagementObjectCollection coll = searcher.Get();
if (coll.Count == 1)
{
foreach (ManagementObject share in searcher.Get())
{
sharedName = share["Name"] as String;
unc = "\\\\" + SystemInformation.ComputerName + "\\" + sharedName;
return true;
}
}
return false;
}
/// <summary>
/// The method returns ManagementObject object for the shared folder with given name
/// </summary>
/// <param name="sharedFolderName">string containing name of shared folder</param>
/// <returns>Object of type ManagementObject for the shared folder.</returns>
private static ManagementObject GetSharedFolderObject(string sharedFolderName)
{
ManagementObject sharedFolderObject = null;
//Creating a searcher object to search
ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * from Win32_LogicalShareSecuritySetting where Name = '" + sharedFolderName + "'");
ManagementObjectCollection resultOfSearch = searcher.Get();
if (resultOfSearch.Count > 0)
{
//The search might return a number of objects with same shared name. I assume there is just going to be one
foreach (ManagementObject sharedFolder in resultOfSearch)
{
sharedFolderObject = sharedFolder;
break;
}
}
return sharedFolderObject;
}
/// <summary>
/// The method returns ManagementObject object for the user folder with given name
/// </summary>
/// <param name="domain">string containing domain name of user </param>
/// <param name="alias">string containing the user's network name </param>
/// <returns>Object of type ManagementObject for the user folder.</returns>
private static ManagementObject GetUserAccountObject(string domain, string alias)
{
ManagementObject userAccountObject = null;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(string.Format("select * from Win32_Account where Name = '{0}' and Domain='{1}'", alias, domain));
ManagementObjectCollection resultOfSearch = searcher.Get();
if (resultOfSearch.Count > 0)
{
foreach (ManagementObject userAccount in resultOfSearch)
{
userAccountObject = userAccount;
break;
}
}
return userAccountObject;
}
/// <summary>
/// Returns the Security Identifier Sid of the given user
/// </summary>
/// <param name="userAccountObject">The user object who's Sid needs to be returned</param>
/// <returns></returns>
private static ManagementObject GetAccountSecurityIdentifier(ManagementBaseObject userAccountObject)
{
ManagementObject securityIdentfierObject = new ManagementObject(string.Format("Win32_SID.SID='{0}'", (string)userAccountObject.Properties["SID"].Value));
securityIdentfierObject.Get();
return securityIdentfierObject;
}
/// <summary>
/// Create a trustee object for the given user
/// </summary>
/// <param name="domain">name of domain</param>
/// <param name="userName">the network name of the user</param>
/// <param name="securityIdentifierOfUser">Object containing User'sid</param>
/// <returns></returns>
private static ManagementObject CreateTrustee(string domain, string userName, ManagementObject securityIdentifierOfUser)
{
ManagementObject trusteeObject = new ManagementClass("Win32_Trustee").CreateInstance();
trusteeObject.Properties["Domain"].Value = domain;
trusteeObject.Properties["Name"].Value = userName;
trusteeObject.Properties["SID"].Value = securityIdentifierOfUser.Properties["BinaryRepresentation"].Value;
trusteeObject.Properties["SidLength"].Value = securityIdentifierOfUser.Properties["SidLength"].Value;
trusteeObject.Properties["SIDString"].Value = securityIdentifierOfUser.Properties["SID"].Value;
return trusteeObject;
}
/// <summary>
/// Create an Access Control Entry object for the given user
/// </summary>
/// <param name="trustee">The user's trustee object</param>
/// <param name="deny">boolean to say if user permissions should be assigned or denied</param>
/// <returns></returns>
private static ManagementObject CreateAccessControlEntry(ManagementObject trustee, bool deny)
{
ManagementObject aceObject = new ManagementClass("Win32_ACE").CreateInstance();
aceObject.Properties["AccessMask"].Value = 0x1U | 0x2U | 0x4U | 0x8U | 0x10U | 0x20U | 0x40U | 0x80U | 0x100U | 0x10000U | 0x20000U | 0x40000U | 0x80000U | 0x100000U; // all permissions
aceObject.Properties["AceFlags"].Value = 0x0U; // no flags
aceObject.Properties["AceType"].Value = deny ? 1U : 0U; // 0 = allow, 1 = deny
aceObject.Properties["Trustee"].Value = trustee;
return aceObject;
}
/// <summary>
/// Creates the shared folder with all user permissions.
/// </summary>
private void CreateSharedFolderWithUserPermissions(ManagementBaseObject securityDescriptor, string sharedFolderName, string destPath)
{
// 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"] = "My Files Share";
inParams["Name"] = sharedFolderName;
inParams["Path"] = destPath;
inParams["Type"] = 0x0; // Disk Drive
inParams["Access"] = securityDescriptor;
// Invoke the method on the ManagementClass object
outParams = managementClass.InvokeMethod("Create", inParams, null);
// Check to see if the method invocation was successful
if ((uint)(outParams.Properties["ReturnValue"].Value) != 0)
{
throw new Exception("Unable to share directory.");
}
}