#include <windows.h> #include <tchar.h> #include <stdio.h>
//使用Windows的HeapAlloc函数进行动态内存分配 #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;// SD的size
// 一个新的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; //ACL的size
// 一个临时使用的 ACE 变量 LPVOID pTempAce = NULL; UINT CurrentAceIndex = 0; //ACE在ACL中的位置
UINT newAceIndex = 0; //新添的ACE在ACL中的位置
//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_INFORMATION的structure的参数,需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: 计算新的ACL的size // 计算的公式是:原有的DACL的size加上需要添加的一个ACE的size,以 // 及加上一个和ACE相关的SID的size,最后减去两个字节以获得精确的大小。 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的顺序来进行拷贝(ACE在ACL中的顺序是很关键的),在拷 // 贝过程中,先拷贝非继承的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: 检查要拷贝的ACE的SID是否和需要加入的ACE的SID一样, // 如果一样,那么就应该废掉已存在的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文件权限之前,我们首先需要理解几个关键概念。 ##### 安全描述符 (Security Descriptors) 在Windows NT/...
软件功能:通过设置NTFS文件权限达到禁止或恢复使用某文件(夹)的目的。可以用来防止文件误删误改等操作,同时也可用来防止一些未经自己允许的后台程序悄悄运行。 XP系统测试的,其他系统不知道。 做这个软件主要...
NTFS 文件系统权限管理可以通过以下方式实现: 1. 权限继承:NTFS 文件系统权限可以继承自父文件夹的权限。 2. 权限赋予:可以对文件和文件夹进行权限赋予,例如读取、写入、执行等权限。 3. 权限撤销:可以对文件...
介绍作者为了探索NTFS文件系统的存储特点编写的21个WIN32工具程序;使用作者编写的WIN32工具程序,探秘NTFS文件系统的扇区存储规律。 全书分3篇,共计17章。第1章至第3章是“基础篇”,重点介绍了NTFS文件系统的...
2. **文件权限优于文件夹权限**:如果用户对文件的权限高于文件所在的文件夹,那么以文件权限为准。 3. **拒绝权限优先**:如果明确拒绝了某个用户访问,即使其他权限允许,用户也无法访问。 NTFS权限还支持**继承*...
### 如何不丢失文件NTFS权限地拷贝文件 在Windows操作系统中,NTFS(New Technology File System)是一种被广泛使用的文件系统格式。它不仅提供了高级功能如文件压缩、加密等,还支持权限管理,这对于保护文件的...
3. 执行权限(Execute):允许用户执行文件或文件夹中的程序。 4. 删除权限(Delete):允许用户删除文件或文件夹。 5. 修改权限(Modify):允许用户修改文件或文件夹的属性。 NTFS 权限设置的应用 NTFS 权限设置...
1. **权限问题**:由于Linux和Windows对文件权限的处理方式不同,可能需要调整权限设置,以确保Linux用户能够正确读写NTFS分区上的文件。 2. **性能优化**:挂载选项如`noatime`和`nodiratime`可以提高读取性能,但...
NTFS 文件系统广泛应用于 Windows 操作系统中,主要用于存储操作系统文件和应用程序文件。同时,NTFS 文件系统也应用于其他领域,如数据存储、数据保护和云存储等。 NTFS 文件系统技术研究是计算机技术中一个重要的...
NTFS文件系统可以通过基本分区和动态分区两种方式进行创建。基本分区是最常见的分区类型,而动态分区则提供了更多的灵活性,如扩展卷、跨区卷等。 #### NTFS参数结构介绍 - **DBR(DOS Boot Record)**:这是NTFS...
- 压缩和稀疏文件:NTFS支持文件压缩,以节省磁盘空间,并可处理稀疏文件(大部分为零值的数据)。 - 空间回收:通过删除不再使用的文件和清理临时文件,可以优化磁盘空间。 这些书籍和文档将帮助读者全面掌握...
#### 二、NTFS文件系统概述 NTFS是微软开发的一种高性能文件系统,首次出现在Windows NT操作系统中,并在后续的Windows版本中得到广泛应用。相比于传统的FAT文件系统,NTFS提供了更多的功能和更好的安全性支持,如...
3. **安全特性**:NTFS支持权限控制列表(ACLs),可以为每个文件和目录设置不同的访问权限。源码揭示了如何在非Windows环境中实现这些安全机制。 4. **事务处理**:NTFS支持事务,即使在系统崩溃或异常情况下,也...
1. **高级安全性**: NTFS提供了强大的权限管理功能,能够确保文件的安全性和隐私。 2. **稳定性**: 支持日志记录和事务处理机制,可以自动恢复文件系统的损坏部分。 3. **压缩和加密**: 内置了压缩功能和EFS...
4. **文件权限和安全描述符**:NTFS支持ACL(Access Control List),备份程序应保存文件和目录的权限信息,以便在恢复时能正确还原。 5. **卷和分区信息**:除了文件和目录,备份还应包括卷标、卷序列号、引导扇区...
7. **文件权限和安全**:NTFS支持细粒度的权限控制,每个文件和目录都可以设置用户或用户组的访问权限。此外,NTFS还支持文件加密(EFS,Encrypting File System),保证数据的安全性。 8. **硬链接和符号链接**:...
### 部署文件服务器NTFS共享权限设置详细分析 #### 深度解析与案例研究 在IT领域,文件服务器的角色至关重要,尤其是在企业环境中,它承载着数据存储、共享和保护的重要职责。Windows Server 2003及后续版本提供了...
其次,NTFS支持安全特性,如权限控制和文件加密。通过ACL(Access Control List),用户可以为文件和目录设置特定的访问权限,限制不同用户对资源的访问。EFS(Encrypting File System)则是NTFS中的一个内置功能,...