【问题标题】:How to replicate the file/directory permissions with P/Invoke?如何使用 P/Invoke 复制文件/目录权限?
【发布时间】:2011-10-03 00:39:08
【问题描述】:

我花了几个小时寻找解决方案,但文档很少,我找不到我需要的东西。

如果我有一个文件或一个目录,我如何在 C# 中使用 P/Invoke 将权限(即所有者和 SID 及其权限)从一个文件复制到另一个文件或从一个目录复制到另一个,假设这些文件和目录要么在同一台机器上,要么在同一 Active Directory 服务器控制的网络上?

【问题讨论】:

  • 为什么需要pinvoke? System.IO.File.SetAccessControl("dest_file", System.IO.File.GetAccessControl("src_file")); 没有做你想做的事吗?
  • System.IO.File 方法仅限于 259 个字符的路径,因此它们不能用于我必须处理非常长的路径的特定情况。
  • 你不能用 \\ 开启长路径吗?\
  • 虽然我没有尝试过也不能肯定地说,但从阅读this help doc 看来,.NET 根本不支持长路径。看起来它需要 Win32 调用和长路径说明符。

标签: c# security pinvoke file-permissions


【解决方案1】:

这是一个使用 GetNamedSecurityInfoSetNamedSecurityInfo.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.AccessControl;

namespace PermissionsExample
{
    class Program
    {
        static void Main(string[] args)
        {
            string source = "C:\\source.txt";
            string dest = "C:\\dest.txt";

            string result = CopyPermissions(source, dest);
            if (!string.IsNullOrEmpty(result)) { Console.WriteLine(result); }
            else { Console.WriteLine("SUCCESS"); }
        }

        public static string CopyPermissions(string source_file, string dest_file)
        {
            string errmsg = string.Empty;
            IntPtr sidOwner = IntPtr.Zero;
            IntPtr sidOwnerDescriptor = IntPtr.Zero;
            IntPtr sidGroup = IntPtr.Zero;
            IntPtr sidGroupDescriptor = IntPtr.Zero;
            IntPtr dacl = IntPtr.Zero;
            IntPtr daclDescriptor = IntPtr.Zero;
            IntPtr sacl = IntPtr.Zero;
            try
            {
                int result = GetNamedSecurityInfo(source_file, SE_OBJECT_TYPE.SE_FILE_OBJECT, SecurityInfos.DiscretionaryAcl, out sidOwner, out sidGroup, out dacl, out sacl, out daclDescriptor);
                if (result != 0)
                {
                    Win32Exception e = new Win32Exception(result);
                    errmsg = "ERROR: " + e.Message;
                    return errmsg;
                }
                result = GetNamedSecurityInfo(source_file, SE_OBJECT_TYPE.SE_FILE_OBJECT, SecurityInfos.Owner, out sidOwner, out sidGroup, out dacl, out sacl, out sidGroupDescriptor);
                if (result != 0)
                {
                    Win32Exception e = new Win32Exception(result);
                    errmsg = "ERROR: " + e.Message;
                    return errmsg;
                }

                result = GetNamedSecurityInfo(source_file, SE_OBJECT_TYPE.SE_FILE_OBJECT, SecurityInfos.Group, out sidOwner, out sidGroup, out dacl, out sacl, out sidGroupDescriptor);
                if (result != 0)
                {
                    Win32Exception e = new Win32Exception(result);
                    errmsg = "ERROR: " + e.Message;
                    return errmsg;
                }

                SecurityInfos info = SecurityInfos.DiscretionaryAcl | SecurityInfos.Group | SecurityInfos.Owner;
                result = SetNamedSecurityInfo(dest_file, SE_OBJECT_TYPE.SE_FILE_OBJECT, info, sidOwner, sidGroup, dacl, sacl);
                if (result != 0)
                {
                    Win32Exception e = new Win32Exception(result);
                    errmsg = "ERROR: " + e.Message;
                    return errmsg;
                }
            }
            finally
            {
                if (sidOwnerDescriptor != IntPtr.Zero && LocalFree(sidOwnerDescriptor) != IntPtr.Zero)
                {
                    int err = Marshal.GetLastWin32Error();
                    Win32Exception e = new Win32Exception(err);
                    errmsg += "ERROR: " + e.Message;
                }
                if (sidGroupDescriptor != IntPtr.Zero && LocalFree(sidGroupDescriptor) != IntPtr.Zero)
                {
                    int err = Marshal.GetLastWin32Error();
                    Win32Exception e = new Win32Exception(err);
                    errmsg += "ERROR: " + e.Message;
                }
                if (daclDescriptor != IntPtr.Zero && LocalFree(daclDescriptor) != IntPtr.Zero)
                {
                    int err = Marshal.GetLastWin32Error();
                    Win32Exception e = new Win32Exception(err);
                    errmsg += "ERROR: " + e.Message;
                }
            }

            return errmsg;
        }

        public enum SE_OBJECT_TYPE
        {
            SE_UNKNOWN_OBJECT_TYPE = 0,
            SE_FILE_OBJECT,
            SE_SERVICE,
            SE_PRINTER,
            SE_REGISTRY_KEY,
            SE_LMSHARE,
            SE_KERNEL_OBJECT,
            SE_WINDOW_OBJECT,
            SE_DS_OBJECT,
            SE_DS_OBJECT_ALL,
            SE_PROVIDER_DEFINED_OBJECT,
            SE_WMIGUID_OBJECT,
            SE_REGISTRY_WOW64_32KEY
        }

        [DllImport("advapi32.dll", EntryPoint = "GetNamedSecurityInfoW", ExactSpelling = true, CharSet = CharSet.Unicode)]
        private static extern int GetNamedSecurityInfo(string objectName, SE_OBJECT_TYPE objectType,
            System.Security.AccessControl.SecurityInfos securityInfo, out IntPtr sidOwner,
            out IntPtr sidGroup, out IntPtr dacl, out IntPtr sacl, out IntPtr securityDescriptor);

        [DllImport("advapi32.dll", EntryPoint = "SetNamedSecurityInfoW", ExactSpelling = true, CharSet = CharSet.Unicode)]
        private static extern int SetNamedSecurityInfo(string objectName, SE_OBJECT_TYPE objectType,
            System.Security.AccessControl.SecurityInfos securityInfo, IntPtr sidOwner,
            IntPtr sidGroup, IntPtr dacl, IntPtr sacl);

        [DllImport("kernel32.dll", EntryPoint = "LocalFree", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern IntPtr LocalFree(IntPtr hMem);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 2016-03-23
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    相关资源
    最近更新 更多