博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
以程序的方式操纵NTFS的文件权限(下)
阅读量:6859 次
发布时间:2019-06-26

本文共 4585 字,大约阅读时间需要 15 分钟。

    // 
    // 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
我的 MSN
[email]haoel@hotmail.com[/email]
,专栏在
欢迎大家和我交流。
本文转自 haoel 51CTO博客,原文链接:http://blog.51cto.com/haoel/124664,如需转载请自行联系原作者
你可能感兴趣的文章
网站建设前要注意这些网站设计误区可能会毁了网站
查看>>
《乐高EV3机器人搭建与编程》一1.2 LEGO系列产品
查看>>
《HTML、CSS、JavaScript 网页制作从入门到精通》——6.3 表格的边框
查看>>
《Spring攻略(第2版)》——1.9 用依赖检查属性
查看>>
并发集合(七)创建并发随机数
查看>>
论文导读:面向卷积神经网络的卷积核冗余消除策略
查看>>
当下流行架构中的一些技术思考
查看>>
Hadoop学习第四天之hadoop命令操作(上)
查看>>
走进阿里云:做云数据、大计算的No.1
查看>>
Gradle 基础
查看>>
listview优化(中)
查看>>
当安全遇上AI 阿里聚安全算法挑战赛完美收官
查看>>
怪”博士闵万里:用人工智能,解决吃饭出行问题
查看>>
ES6 + Webpack + React + Babel 如何在低版本浏览器上愉快的玩耍(下)
查看>>
日志服务(原SLS)新功能发布(8)--日志服务Web Tracking功能
查看>>
kvm虚拟化学习笔记(十三)之kvm虚拟机磁盘文件读取小结
查看>>
kvm虚拟化学习笔记(四)之kvm虚拟机日常管理与配置
查看>>
SlideView 图片滑动(扩展/收缩)展示效果
查看>>
iOS开发之即时通讯之Socket(AsyncSocket)
查看>>
算法设计
查看>>