以程序的方式操纵NTFS的文件权限(下)

简介:
    // 
    // 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] ,专栏在 [url]http://haoel.blog.51cto.com/[/url] 欢迎大家和我交流。









本文转自 haoel 51CTO博客,原文链接:http://blog.51cto.com/haoel/124664,如需转载请自行联系原作者

目录
相关文章
|
4月前
|
Linux Shell
Linux中的shell外壳与权限(包含目录文件的权限,粘滞位的来龙去脉)(下)
Linux中的shell外壳与权限(包含目录文件的权限,粘滞位的来龙去脉)
|
4月前
|
Linux Shell 数据安全/隐私保护
Linux中的shell外壳与权限(包含目录文件的权限,粘滞位的来龙去脉)(上)
Linux中的shell外壳与权限(包含目录文件的权限,粘滞位的来龙去脉)
|
人工智能 Linux
如何在Linux使用 chattr 命令更改文件或目录的扩展属性?
如何在Linux使用 chattr 命令更改文件或目录的扩展属性?
138 0
|
Linux
linux第四课:改变文件的权限和属性(内含:1.修改权限命令chmod+2.临时切换用户用 sudo+3.chowm:改变文件所有者)
linux第四课:改变文件的权限和属性(内含:1.修改权限命令chmod+2.临时切换用户用 sudo+3.chowm:改变文件所有者)
259 0
linux第四课:改变文件的权限和属性(内含:1.修改权限命令chmod+2.临时切换用户用 sudo+3.chowm:改变文件所有者)
|
存储 Unix
【操纵系统】文件目录
【操纵系统】文件目录
119 0
|
Linux
【Linux】如何改变文件属性与权限
【Linux】如何改变文件属性与权限
73 0
【Linux】如何改变文件属性与权限
|
Linux
【Linux】同组只有可读权限能否进入工作
【Linux】同组只有可读权限能否进入工作
59 0
【Linux】同组只有可读权限能否进入工作
随心所欲操作 Linux 更改文件属性
Linux 文件基本属性 ls -l(查看文件基本属性) chgrp(更改文件属组) chown(更改文件属主,也可以同时更改文件属组) chmod(更改文件9个属性)
随心所欲操作 Linux 更改文件属性