Win32桌面编程:ACLUI.DLL,EditSecurity(IntPtr hwndOwner, ISecurityInformation psi)
在Windows编程中,我们通常需要借助通用对话框的力量,今天我们就聊一下“安全属性表”通用对话框的使用心得。
当我们调用EditSecurity函数时:
1.EditSecurity将调用ISecurityInformation中的GetObjectInformation函数
在编写 ISecurityInformation.GetObjectInformation(out SI_OBJECT_INFO pObjectInfo)时
我们需要将结构返还给函数,GetObjectInformation用于初始化属性表的样式
看一下结构:
public struct SI_OBJECT_INFO
{
public uint dwFlags;
public IntPtr hInstance;
public string pszServerName;
public string pszObjectName;
public string pszPageTitle;
public Guid guidObjectType;
}
解释一下:dwFlags为属性表样式的标志SI_OBJECT_INFO 结构
pszObjectName为属性表的标题
pszPageTitle为属性页的标题
2.接着EditSecurity将调用ISecurityInformation中的GetSecurity函数
GetSecurity(uint RequestedInformation, out IntPtr ppSecurityDescriptor, bool fDefault)
其他我们不需要过于处理,专注于“ppSecurityDescriptor”,一个句柄,
例如:
public string _filePath;
public void GetSecurity(uint RequestedInformation, out IntPtr ppSecurityDescriptor, bool fDefault)
{
ppSecurityDescriptor = IntPtr.Zero;
// 获取文件的安全描述符
var fileSecurity = File.GetAccessControl(_filePath);
var rawSecurityDescriptor = fileSecurity.GetSecurityDescriptorBinaryForm();
// 将安全描述符复制到非托管内存
ppSecurityDescriptor = Marshal.AllocHGlobal(rawSecurityDescriptor.Length);
Marshal.Copy(rawSecurityDescriptor, 0, ppSecurityDescriptor, rawSecurityDescriptor.Length);
}
3.当我们将这两个函数处理好以后基本就可以弹出这个对话框了
如下(Powershell+C#):
Add-Type -TypeDefinition @"
using System;
using System.IO;
using System.Runtime.InteropServices;
// 定义必要的结构和接口
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SI_OBJECT_INFO
{
public uint dwFlags;
public IntPtr hInstance;
public string pszServerName;
public string pszObjectName;
public string pszPageTitle;
public Guid guidObjectType;
}
[ComImport, Guid("965FC360-16FF-11d0-91CB-00AA00BBB723"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISecurityInformation
{
void GetObjectInformation(out SI_OBJECT_INFO pObjectInfo);
void GetSecurity(uint RequestedInformation, out IntPtr ppSecurityDescriptor, [MarshalAs(UnmanagedType.Bool)] bool fDefault);
void SetSecurity(uint SecurityInformation, IntPtr pSecurityDescriptor);
void GetAccessRights(ref Guid pguidObjectType, uint dwFlags, out IntPtr ppAccess, out uint pcAccesses, out uint piDefaultAccess);
void MapGeneric(ref Guid pguidObjectType, ref byte pAceFlags, ref uint pMask);
void GetInheritTypes(out IntPtr ppInheritTypes, out uint pcInheritTypes);
void PropertySheetPageCallback(IntPtr hwnd, uint uMsg, uint uPage);
}
public class FileSecurityInfo : ISecurityInformation
{
public FileSecurityInfo()
{
}
public const uint SI_PAGE_TITLE = 0x00000800;
public const uint SI_EDIT_ALL = 0x00000003;
// 实现接口方法
public void GetObjectInformation(out SI_OBJECT_INFO pObjectInfo)
{
pObjectInfo = new SI_OBJECT_INFO()
{
dwFlags = Flags, // SI_EDIT_PERMS
pszObjectName = ObjectName,
pszServerName = null,
pszPageTitle = PageTitle,
guidObjectType = Guid.Empty
};
}
public string PageTitle;
public string ObjectName;
public string _filePath;
public uint Flags = SI_PAGE_TITLE | SI_EDIT_ALL;
public void GetSecurity(uint RequestedInformation, out IntPtr ppSecurityDescriptor, bool fDefault)
{
ppSecurityDescriptor = IntPtr.Zero;
// 获取文件的安全描述符
var fileSecurity = File.GetAccessControl(_filePath);
var rawSecurityDescriptor = fileSecurity.GetSecurityDescriptorBinaryForm();
// 将安全描述符复制到非托管内存
ppSecurityDescriptor = Marshal.AllocHGlobal(rawSecurityDescriptor.Length);
Marshal.Copy(rawSecurityDescriptor, 0, ppSecurityDescriptor, rawSecurityDescriptor.Length);
}
public void SetSecurity(uint SecurityInformation, IntPtr pSecurityDescriptor)
{
//if (!SetFileSecurity(_filePath, SecurityInformation, pSecurityDescriptor))
//{
// throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
//}
}
// 其他接口方法留空(需根据需求实现)
public void GetAccessRights(ref Guid pguidObjectType, uint dwFlags, out IntPtr ppAccess, out uint pcAccesses, out uint piDefaultAccess)
{
ppAccess = IntPtr.Zero;
pcAccesses = 0;
piDefaultAccess = 0;
}
public void MapGeneric(ref Guid pguidObjectType, ref byte pAceFlags, ref uint pMask) { }
public void GetInheritTypes(out IntPtr ppInheritTypes, out uint pcInheritTypes)
{
ppInheritTypes = IntPtr.Zero;
pcInheritTypes = 0;
}
public void PropertySheetPageCallback(IntPtr hwnd, uint uMsg, uint uPage) { }
[DllImport("aclui.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EditSecurity(IntPtr hwndOwner, ISecurityInformation psi);
}
"@
# 使用示例
# 创建安全信息对象
$securityInfo = New-Object FileSecurityInfo
$securityInfo.PageTitle = "于子轩的安全属性对话框"
$securityInfo.Flags = 0x00000010L #高级选项
$securityInfo.Flags += 0x00000080L #高级选项
$securityInfo.Flags += 0x00000001l #高级选项-所有者
$securityInfo.Flags += 0x00000800L #PageTitle属性作为标题
#$securityInfo.Flags += 0x00000008l #禁止修改
$securityInfo.Flags += 0x00000020L #高级选项-还原默认所有者
$securityInfo.Flags += 0x00040000L #高级选项-还原默认值按钮
$securityInfo.Flags += 0x08000000L #高级选项-还原默认值按钮
$securityInfo.ObjectName = "AclUI.h";
#$securityInfo.Flags += 0x00200000l #隐藏“高级安全设置”页面上的“特殊权限”选项卡
#$securityInfo.Flags = 0x02000000L #所有者
$securityInfo._filePath = "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.22621.0\\um\\AclUI.h";
[FileSecurityInfo]::EditSecurity([IntPtr]::Zero, $securityInfo)