`
wanjianfei
  • 浏览: 305136 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多

还是请看例程,这个程序比较长,来源于MSDN,我做了一点点修改,并把自己的理解加在注释中,所以,请注意代码中的注释:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

//使用WindowsHeapAlloc函数进行动态内存分配
#define myheapalloc(x) (HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, x))
#define myheapfree(x) (HeapFree(GetProcessHeap(), 0, x))

typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)(
IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet);

typedef BOOL (WINAPI *AddAccessAllowedAceExFnPtr)(
PACL pAcl,
DWORD dwAceRevision,
DWORD AceFlags,
DWORD AccessMask,
PSID pSid
);

BOOL AddAccessRights(TCHAR *lpszFileName, TCHAR *lpszAccountName,
DWORD dwAccessMask) {

// 声明SID变量
SID_NAME_USE snuType;

// 声明和LookupAccountName相关的变量(注意,全为0,要在程序中动态分配)
TCHAR * szDomain = NULL;
DWORD cbDomain = 0;
LPVOID pUserSID = NULL;
DWORD cbUserSID = 0;

// 和文件相关的安全描述符 SD 的变量
PSECURITY_DESCRIPTOR pFileSD = NULL; // 结构变量
DWORD cbFileSD = 0;// SDsize

// 一个新的SD的变量,用于构造新的ACL(把已有的ACL和需要新加的ACL整合起来)
SECURITY_DESCRIPTOR newSD;

// ACL 相关的变量
PACL pACL = NULL;
BOOL fDaclPresent;
BOOL fDaclDefaulted;
ACL_SIZE_INFORMATION AclInfo;

// 一个新的 ACL 变量
PACL pNewACL = NULL; //结构指针变量
DWORD cbNewACL = 0; //ACLsize

// 一个临时使用的 ACE 变量
LPVOID pTempAce = NULL;
UINT CurrentAceIndex = 0; //ACEACL中的位置

UINT newAceIndex = 0; //新添的ACEACL中的位置

//API函数的返回值,假设所有的函数都返回失败。
BOOL fResult;
BOOL fAPISuccess;

SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;

// 下面的两个函数是新的API函数,仅在Windows 2000以上版本的操作系统支持。
// 在此将从Advapi32.dll文件中动态载入。如果你使用VC++ 6.0编译程序,而且你想
// 使用这两个函数的静态链接。则请为你的编译加上:/D_WIN32_WINNT=0x0500
// 的编译参数。并且确保你的SDK的头文件和lib文件是最新的。
SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl = NULL;
AddAccessAllowedAceExFnPtr _AddAccessAllowedAceEx = NULL;

__try {

//
// STEP 1: 通过用户名取得SID
// 在这一步中LookupAccountName函数被调用了两次,第一次是取出所需要
// 的内存的大小,然后,进行内存分配。第二次调用才是取得了用户的帐户信息。
// LookupAccountName同样可以取得域用户或是用户组的信息。(请参看MSDN
//

fAPISuccess = LookupAccountName(NULL, lpszAccountName,
pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType);

// 以上调用API会失败,失败原因是内存不足。并把所需要的内存大小传出。
// 下面是处理非内存不足的错误。

if (fAPISuccess)
__leave;
else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
_tprintf(TEXT("LookupAccountName() failed. Error %d\n"),
GetLastError());
__leave;
}

pUserSID = myheapalloc(cbUserSID);
if (!pUserSID) {
_tprintf(TEXT("HeapAlloc() failed. Error %d\n"), GetLastError());
__leave;
}

szDomain = (TCHAR *) myheapalloc(cbDomain * sizeof(TCHAR));
if (!szDomain) {
_tprintf(TEXT("HeapAlloc() failed. Error %d\n"), GetLastError());
__leave;
}

fAPISuccess = LookupAccountName(NULL, lpszAccountName,
pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType);
if (!fAPISuccess) {
_tprintf(TEXT("LookupAccountName() failed. Error %d\n"),
GetLastError());
__leave;
}

//
// STEP 2: 取得文件(目录)相关的安全描述符SD
// 使用GetFileSecurity函数取得一份文件SD的拷贝,同样,这个函数也
// 是被调用两次,第一次同样是取SD的内存长度。注意,SD有两种格式:自相关的
// self-relative)和 完全的(absolute),GetFileSecurity只能取到“自
// 相关的”,而SetFileSecurity则需要完全的。这就是为什么需要一个新的SD
// 而不是直接在GetFileSecurity返回的SD上进行修改。因为“自相关的”信息
// 是不完整的。

fAPISuccess = GetFileSecurity(lpszFileName,
secInfo, pFileSD, 0, &cbFileSD);

// 以上调用API会失败,失败原因是内存不足。并把所需要的内存大小传出。
// 下面是处理非内存不足的错误。
if (fAPISuccess)
__leave;
else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
_tprintf(TEXT("GetFileSecurity() failed. Error %d\n"),
GetLastError());
__leave;
}

pFileSD = myheapalloc(cbFileSD);
if (!pFileSD) {
_tprintf(TEXT("HeapAlloc() failed. Error %d\n"), GetLastError());
__leave;
}

fAPISuccess = GetFileSecurity(lpszFileName,
secInfo, pFileSD, cbFileSD, &cbFileSD);
if (!fAPISuccess) {
_tprintf(TEXT("GetFileSecurity() failed. Error %d\n"),
GetLastError());
__leave;
}

//
// STEP 3: 初始化一个新的SD
//
if (!InitializeSecurityDescriptor(&newSD,
SECURITY_DESCRIPTOR_REVISION)) {
_tprintf(TEXT("InitializeSecurityDescriptor() failed.")
TEXT("Error %d\n"), GetLastError());
__leave;
}

//
// STEP 4: GetFileSecurity 返回的SD中取DACL
//
if (!GetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,
&fDaclDefaulted)) {
_tprintf(TEXT("GetSecurityDescriptorDacl() failed. Error %d\n"),
GetLastError());
__leave;
}

//
// STEP 5: DACL的内存size
// GetAclInformation可以提供DACL的内存大小。只传入一个类型为
// ACL_SIZE_INFORMATIONstructure的参数,需DACL的信息,是为了
// 方便我们遍历其中的ACE
AclInfo.AceCount = 0; // Assume NULL DACL.
AclInfo.AclBytesFree = 0;
AclInfo.AclBytesInUse = sizeof(ACL);

if (pACL == NULL)
fDaclPresent = FALSE;

// 如果DACL不为空,则取其信息。(大多数情况下“自关联”的DACL为空)
if (fDaclPresent) {
if (!GetAclInformation(pACL, &AclInfo,
sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) {
_tprintf(TEXT("GetAclInformation() failed. Error %d\n"),
GetLastError());
__leave;
}
}

//
// STEP 6: 计算新的ACLsize
// 计算的公式是:原有的DACLsize加上需要添加的一个ACEsize,以
// 及加上一个和ACE相关的SIDsize,最后减去两个字节以获得精确的大小。
cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE)
+ GetLengthSid(pUserSID) - sizeof(DWORD);

//
// STEP 7: 为新的ACL分配内存
//
pNewACL = (PACL) myheapalloc(cbNewACL);
if (!pNewACL) {
_tprintf(TEXT("HeapAlloc() failed. Error %d\n"), GetLastError());
__leave;
}

//
// STEP 8: 初始化新的ACL结构
//
if (!InitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) {
_tprintf(TEXT("InitializeAcl() failed. Error %d\n"),
GetLastError());
__leave;
}

(程序未完,请看下篇)

//
// STEP 9 如果文件(目录) DACL 有数据,拷贝其中的ACE到新的DACL
//
// 下面的代码假设首先检查指定文件(目录)是否存在的DACL,如果有的话,
// 那么就拷贝所有的ACE到新的DACL结构中,我们可以看到其遍历的方法是采用
// ACL_SIZE_INFORMATION结构中的AceCount成员来完成的。在这个循环中,
// 会按照默认的ACE的顺序来进行拷贝(ACEACL中的顺序是很关键的),在拷
// 贝过程中,先拷贝非继承的ACE(我们知道ACE会从上层目录中继承下来)
//

newAceIndex = 0;

if (fDaclPresent && AclInfo.AceCount) {

for (CurrentAceIndex = 0;
CurrentAceIndex < AclInfo.AceCount;
CurrentAceIndex++) {

//
// STEP 10: DACL中取ACE
//
if (!GetAce(pACL, CurrentAceIndex, &pTempAce)) {
_tprintf(TEXT("GetAce() failed. Error %d\n"),
GetLastError());
__leave;
}

//
// STEP 11: 检查是否是非继承的ACE
// 如果当前的ACE是一个从父目录继承来的ACE,那么就退出循环。
// 因为,继承的ACE总是在非继承的ACE之后,而我们所要添加的ACE
// 应该在已有的非继承的ACE之后,所有的继承的ACE之前。退出循环
// 正是为了要添加一个新的ACE到新的DACL中,这后,我们再把继承的
// ACE拷贝到新的DACL中。
//
if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags
& INHERITED_ACE)
break;

//
// STEP 12: 检查要拷贝的ACESID是否和需要加入的ACESID一样
// 如果一样,那么就应该废掉已存在的ACE,也就是说,同一个用户的存取
// 权限的设置的ACE,在DACL中应该唯一。这在里,跳过对同一用户已设置
// 了的ACE,仅是拷贝其它用户的ACE
//
if (EqualSid(pUserSID,
&(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart)))
continue;

//
// STEP 13: ACE加入到新的DACL
// 下面的代码中,注意 AddAce 函数的第三个参数,这个参数的意思是
// ACL中的索引值,意为要把ACE加到某索引位置之后,参数MAXDWORD
// 意思是确保当前的ACE是被加入到最后的位置。
//
if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
((PACE_HEADER) pTempAce)->AceSize)) {
_tprintf(TEXT("AddAce() failed. Error %d\n"),
GetLastError());
__leave;
}

newAceIndex++;
}
}

分享到:
评论

相关推荐

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

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

    NTFS文件权限设置软件 V2.0

    软件功能:通过设置NTFS文件权限达到禁止或恢复使用某文件(夹)的目的。可以用来防止文件误删误改等操作,同时也可用来防止一些未经自己允许的后台程序悄悄运行。 XP系统测试的,其他系统不知道。 做这个软件主要...

    NTFS文件系统扇区存储探秘_扫描完整版

    介绍作者为了探索NTFS文件系统的存储特点编写的21个WIN32工具程序;使用作者编写的WIN32工具程序,探秘NTFS文件系统的扇区存储规律。  全书分3篇,共计17章。第1章至第3章是“基础篇”,重点介绍了NTFS文件系统的...

    如何不丢失文件NTFS权限地拷贝文件

    如何不丢失文件NTFS权限地拷贝文件 scopy 在使用scopy拷贝文件时一定需要注意目的目录是否存在同名文件,否则scopy的结果不会是你预期的结果。

    NTFS 文件系统及NTFS权限应用原则

    文件权限及其应用 NTFS权限应用原则 NTFS文件系统 详解

    NTFS文件系统若干技术

    第二章 NTFS相关概念理论 14 2.1 RAID 简介 14 2.2 NTFS文件系统分区 14 2.2.1 基本分区 14 2.2.2 动态分区 14 2.3 NTFS参数结构介绍 14 2.3.1 NTFS的DBR 15 2.3.2 NTFS文件空间分配 16 2.3.3 NTFS元文件 17...

    操作系统安全:设置NTFS权限.pptx

    NTFS文件系统可以针对不同用户和组设置各种访问权限 只有被授予权限的用户或组才能访问 文件或文件夹的属性中有【安全】选项卡 访问控制列表(ACL) 访问控制项(ACE) 设置NTFS权限 3、NTFS权限的含义 完全控制:可执行...

    NTFS文件系统中创建一个文件的基本步骤

    在NTFS文件系统中,每一个文件或目录都拥有一个MFT记录,MFT记录中记录了文件或目录的基本信息,对于普通文件来说,一般拥有文件序号,文件名,创建时间,文件大小,文件属性,文件数据地址索引等基本文件信息,而一...

    NTFS文件锁定程序.exe

    本程序可以锁定NTFS分区的文件或文件夹 ,使其具有防删,禁读,禁改名,隐藏等属性,当锁定禁读时还可以防止别人复制;锁定过程只是修改了NTFS文件的访问权限,因此它不会改写注册表,不创建隐藏文件夹,不改变文件...

    NTFS文件系统研究

    NTFS文件系统研究NTFS文件系统研究

    NTFS文件系统结构详解

    NTFS文件系统的结构详解,这个文档里详细介绍了NTFS文件系统的各个组成结构

    NTFS文件锁定程序

    本程序可以锁定NTFS分区的文件或文件夹 ,使其具有防删,禁读,禁改名,隐藏等属性,当锁定禁读时还可以防止别人复制;锁定过程只是修改了NTFS文件的访问权限,因此它不会改写注册表,不创建隐藏文件夹,不改变文件...

    NTFS文件系统底层挖掘

    NTFS文件系统底层挖掘 NTFS文件系统底层挖掘 NTFS文件系统底层挖掘 NTFS文件系统底层挖掘

    NTFS文件系统解析

    一片关于NTFS文件系统的论文,帮助理解NTFS文件系统~

    Linux下挂载使用NTFS文件系统

    本文档将教你如何在Linux下挂载使用NTFS文件系统。

    用NTFS文件权限打造安全U盘.docx

    用NTFS文件权限打造安全U盘.docx

    实验七 NTFS文件系统权限实验.doc

    实验七 NTFS文件系统权限实验.doc

    如何用NTFS文件权限打造安全U盘.docx

    如何用NTFS文件权限打造安全U盘.docx

    NTFS权限设置

    特殊权限:“遍历文件夹”权限,“运行文件”权限,“列出文件夹”权限,“读取数据”权限,“读取属性”,“读取扩展属性”,“创建文件”权限,“写入数据”权限,“创建文件夹”权限,“附加数据”权限,“写入...

    NTFS文件系统详解

    详细的解释了NTFS文件系统。(纯英文原版)

Global site tag (gtag.js) - Google Analytics