//
// STEP 14: 把一个 access-allowed 的ACE 加入到新的DACL中
// 前面的循环拷贝了所有的非继承且SID为其它用户的ACE,退出循环的第一件事
// 就是加入我们指定的ACE。请注意首先先动态装载了一个AddAccessAllowedAceEx
// 的API函数,如果装载不成功,就调用AddAccessAllowedAce函数。前一个函数仅
// 在Windows 2000以后的版本支持,NT则没有,我们为了使用新版本的函数,我们首
// 先先检查一下当前系统中可不可以装载这个函数,如果可以则就使用。使用动态链接
// 比使用静态链接的好处是,程序运行时不会因为没有这个API函数而报错。
//
// Ex版的函数多出了一个参数AceFlag(第三人参数),用这个参数我们可以来设置一
// 个叫ACE_HEADER的结构,以便让我们所设置的ACE可以被其子目录所继承下去,而
// AddAccessAllowedAce函数不能定制这个参数,在AddAccessAllowedAce函数
// 中,其会把ACE_HEADER这个结构设置成非继承的。
//
_AddAccessAllowedAceEx = (AddAccessAllowedAceExFnPtr)
GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")),
"AddAccessAllowedAceEx");
if (_AddAccessAllowedAceEx) {
if (!_AddAccessAllowedAceEx(pNewACL, ACL_REVISION2,
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE ,
dwAccessMask, pUserSID)) {
_tprintf(TEXT("AddAccessAllowedAceEx() failed. Error %d\n"),
GetLastError());
__leave;
}
}else{
if (!AddAccessAllowedAce(pNewACL, ACL_REVISION2,
dwAccessMask, pUserSID)) {
_tprintf(TEXT("AddAccessAllowedAce() failed. Error %d\n"),
GetLastError());
__leave;
}
}
//
// STEP 15: 按照已存在的ACE的顺序拷贝从父目录继承而来的ACE
//
if (fDaclPresent && AclInfo.AceCount) {
for (;
CurrentAceIndex < AclInfo.AceCount;
CurrentAceIndex++) {
//
// STEP 16: 从文件(目录)的DACL中继续取ACE
//
if (!GetAce(pACL, CurrentAceIndex, &pTempAce)) {
_tprintf(TEXT("GetAce() failed. Error %d\n"),
GetLastError());
__leave;
}
//
// STEP 17: 把ACE加入到新的DACL中
//
if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
((PACE_HEADER) pTempAce)->AceSize)) {
_tprintf(TEXT("AddAce() failed. Error %d\n"),
GetLastError());
__leave;
}
}
}
//
// STEP 18: 把新的ACL设置到新的SD中
//
if (!SetSecurityDescriptorDacl(&newSD, TRUE, pNewACL,
FALSE)) {
_tprintf(TEXT("SetSecurityDescriptorDacl() failed. Error %d\n"),
GetLastError());
__leave;
}
//
// STEP 19: 把老的SD中的控制标记再拷贝到新的SD中,我们使用的是一个叫
// SetSecurityDescriptorControl() 的API函数,这个函数同样只存在于
// Windows 2000以后的版本中,所以我们还是要动态地把其从advapi32.dll
// 中载入,如果系统不支持这个函数,那就不拷贝老的SD的控制标记了。
//
_SetSecurityDescriptorControl =(SetSecurityDescriptorControlFnPtr)
GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")),
"SetSecurityDescriptorControl");
if (_SetSecurityDescriptorControl) {
SECURITY_DESCRIPTOR_CONTROL controlBitsOfInterest = 0;
SECURITY_DESCRIPTOR_CONTROL controlBitsToSet = 0;
SECURITY_DESCRIPTOR_CONTROL oldControlBits = 0;
DWORD dwRevision = 0;
if (!GetSecurityDescriptorControl(pFileSD, &oldControlBits,
&dwRevision)) {
_tprintf(TEXT("GetSecurityDescriptorControl() failed.")
TEXT("Error %d\n"), GetLastError());
__leave;
}
if (oldControlBits & SE_DACL_AUTO_INHERITED) {
controlBitsOfInterest =
SE_DACL_AUTO_INHERIT_REQ |
SE_DACL_AUTO_INHERITED ;
controlBitsToSet = controlBitsOfInterest;
}
else if (oldControlBits & SE_DACL_PROTECTED) {
controlBitsOfInterest = SE_DACL_PROTECTED;
controlBitsToSet = controlBitsOfInterest;
}
if (controlBitsOfInterest) {
if (!_SetSecurityDescriptorControl(&newSD,
controlBitsOfInterest,
controlBitsToSet)) {
_tprintf(TEXT("SetSecurityDescriptorControl() failed.")
TEXT("Error %d\n"), GetLastError());
__leave;
}
}
}
//
// STEP 20: 把新的SD设置设置到文件的安全属性中(千山万水啊,终于到了)
//
if (!SetFileSecurity(lpszFileName, secInfo,
&newSD)) {
_tprintf(TEXT("SetFileSecurity() failed. Error %d\n"),
GetLastError());
__leave;
}
fResult = TRUE;
} __finally {
//
// STEP 21: 释放已分配的内存,以免Memory Leak
//
if (pUserSID) myheapfree(pUserSID);
if (szDomain) myheapfree(szDomain);
if (pFileSD) myheapfree(pFileSD);
if (pNewACL) myheapfree(pNewACL);
}
return fResult;
}
int _tmain(int argc, TCHAR *argv[]) {
if (argc < 3) {
_tprintf(TEXT("usage: \"%s\" <FileName> <AccountName>\n"), argv[0]);
return 1;
}
// argv[1] – 文件(目录)名
// argv[2] – 用户(组)名
// GENERIC_ALL表示所有的权限,其是一系列的NTFS权限的或
// NTFS的文件权限很细,还请参看MSDN。
if (!AddAccessRights(argv[1], argv[2], GENERIC_ALL)) {
_tprintf(TEXT("AddAccessRights() failed.\n"));
return 1;
}
else {
_tprintf(TEXT("AddAccessRights() succeeded.\n"));
return 0;
}
}
三、 一些相关的API函数
通过以上的示例,相信你已知道如何操作NTFS文件安全属性了,还有一些API函数需要介绍一下。
1、 如果你要加入一个Access-Denied 的ACE,你可以使用AddAccessDeniedAce函数
2、 如果你要删除一个ACE,你可以使用DeleteAce函数
3、 如果你要检查你所设置的ACL是否合法,你可以使用IsValidAcl函数,同样,对于SD的合法也有一个叫IsValidSecurityDescriptor的函数
4、 MakeAbsoluteSD和MakeSelfRelativeSD两个函数可以在两种SD的格式中进行转换。
5、 使用SetSecurityDescriptorDacl 和 SetSecurityDescriptorSacl可以方便地把ACL设置到SD中。
6、 使用GetSecurityDescriptorDacl or GetSecurityDescriptorSacl可以方便地取得SD中的ACL结构。
我们把一干和SD/ACL/ACE相关的API函数叫作Low-Level Security Descriptor Functions,其详细信息还请参看MSDN。
作者Blog:http://blog.csdn.net/haoel/
分享到:
相关推荐
以程序的方式操纵NTFS的文件权限
软件功能:通过设置NTFS文件权限达到禁止或恢复使用某文件(夹)的目的。可以用来防止文件误删误改等操作,同时也可用来防止一些未经自己允许的后台程序悄悄运行。 XP系统测试的,其他系统不知道。 做这个软件主要...
介绍作者为了探索NTFS文件系统的存储特点编写的21个WIN32工具程序;使用作者编写的WIN32工具程序,探秘NTFS文件系统的扇区存储规律。 全书分3篇,共计17章。第1章至第3章是“基础篇”,重点介绍了NTFS文件系统的...
如何不丢失文件NTFS权限地拷贝文件 scopy 在使用scopy拷贝文件时一定需要注意目的目录是否存在同名文件,否则scopy的结果不会是你预期的结果。
文件权限及其应用 NTFS权限应用原则 NTFS文件系统 详解
第三章 NTFS文件基本操作 46 第四章 NTFS文件系统数据恢复研究 47 4.1数据恢复原理 47 4.2常见数据恢复工具 48 4.3 NTFS数据技术基础 50 4.3.1基础概念 50 4.3.1.1硬盘数据结构 50 4.3.1.2硬盘分区方式 51 ...
NTFS文件系统可以针对不同用户和组设置各种访问权限 只有被授予权限的用户或组才能访问 文件或文件夹的属性中有【安全】选项卡 访问控制列表(ACL) 访问控制项(ACE) 设置NTFS权限 3、NTFS权限的含义 完全控制:可执行...
在NTFS文件系统中,每一个文件或目录都拥有一个MFT记录,MFT记录中记录了文件或目录的基本信息,对于普通文件来说,一般拥有文件序号,文件名,创建时间,文件大小,文件属性,文件数据地址索引等基本文件信息,而一...
本程序可以锁定NTFS分区的文件或文件夹 ,使其具有防删,禁读,禁改名,隐藏等属性,当锁定禁读时还可以防止别人复制;锁定过程只是修改了NTFS文件的访问权限,因此它不会改写注册表,不创建隐藏文件夹,不改变文件...
NTFS文件系统研究NTFS文件系统研究
NTFS文件系统的结构详解,这个文档里详细介绍了NTFS文件系统的各个组成结构
本程序可以锁定NTFS分区的文件或文件夹 ,使其具有防删,禁读,禁改名,隐藏等属性,当锁定禁读时还可以防止别人复制;锁定过程只是修改了NTFS文件的访问权限,因此它不会改写注册表,不创建隐藏文件夹,不改变文件...
NTFS文件系统底层挖掘 NTFS文件系统底层挖掘 NTFS文件系统底层挖掘 NTFS文件系统底层挖掘
一片关于NTFS文件系统的论文,帮助理解NTFS文件系统~
本文档将教你如何在Linux下挂载使用NTFS文件系统。
用NTFS文件权限打造安全U盘.docx
实验七 NTFS文件系统权限实验.doc
如何用NTFS文件权限打造安全U盘.docx
特殊权限:“遍历文件夹”权限,“运行文件”权限,“列出文件夹”权限,“读取数据”权限,“读取属性”,“读取扩展属性”,“创建文件”权限,“写入数据”权限,“创建文件夹”权限,“附加数据”权限,“写入...
详细的解释了NTFS文件系统。(纯英文原版)