1、文件属性概述
Windows平台下,文件的属性分为常规属性和安全属性。
当用户修改了目标文件的常规属性,密标通过GetFileAttributes()来获取文件的常规属性;通过SetFileAttributes()将原文件的常规属性再设置过来,这样保证了文件的常规属性不会丢失。
Windows-文件常规属性
当用户修改了目标文件的安全属性,密标通过核心函数GetNamedSecurityInfo()来获取文件的安全属性信息;通过核心函数SetNamedSecurityInfo()将原文件的安全属性再设置过来,这样保证了文件的安全属性不会丢失。
Windows-文件安全属性
2、Windows文件属性详解
Windows磁盘分区格式分为NTFS和FAT32两种。对于文件的常规属性,存在于NTFS和FAT32两种磁盘分区下;对于文件的安全属性,则只存在于NTFS分区下。
2.1 Windows文件-常规属性
GetFileAttributes函数的主要功能是返回指定目录或文件的文件常规属性。
函数原型:
DWORD GetFileAttributes(LPCTSTR lpFileName);
函数参数:
lpFileName:指定的文件或目录名称
注:对于ANSI版本,目录名称不能超过260个字符。
返回值:
成功时,返回值为文件或目录的属性,返回值 可以为一个或多个属性;
失败时,返回值为INVALID_FILE_ATTRIBUTES。
备注:GetFileAttributesEx 函数:
除了可以得到上面的文件属性内容外,还能够得到文件的创建日期,最后读写日期以及文件大小等信息。
SetFileAttributes函数的主要功能是设置文件或目录的常规属性。
函数原型:
BOOL SetFileAttributes(
LPCTSTR lpFileName,
DWORD dwFileAttributes);
函数参数:
lpFileName:输入参数,为需要设置文件属性的文件或目录。
dwFileAttributes:文件系统中对文件属性的表示使用了DWORD类型的数据,多个文件属性用“|”运算连在一起.
返回值:
返回BOOL值,表示是否成功。
在MSDN中,文件总共有15种属性,根据磁盘的分区格式不同,文件的属性也会不同。
Windows-文件属性返回值
橙色标记的属性为Windows系统中文件的公有属性,其中“只读”、“隐藏”、“系统”、“存档”为文件的四种基本属性。compressed,content_indexed,encrypted只存在于NTFS分区中。
2.2 Windows文件-安全属性
Windows NT里,用户被分成许多组,组和组之间都有不同的权限,当然,一个组的用户和用户之间也可以有不同的权限。下面我们来谈谈NT中常见的用户组。
Administrators:管理员组,默认情况下,Administrators中的用户对计算机/域有不受限制的完全访问权。分配给该组的默认权限允许对整个系统进行完全控制。所以,只有受信任的人员才可成为该组的成员。
Power Users:高级用户组,Power Users 可以执行除了为 Administrators 组保留的任务外的其他任何操作系统任务。分配给 Power Users 组的默认权限允许 Power Users 组的成员修改整个计算机的设置。但Power Users 不具有将自己添加到 Administrators 组的权限。在权限设置中,这个组的权限是仅次于Administrators的。
Users:普通用户组,这个组的用户无法进行有意或无意的改动。因此,用户可以运行经过验证的应用程序,但不可以运行大多数旧版应用程序。 Users 组是最安全的组,因为分配给该组的默认权限不允许成员修改操作系统的设置或用户资料。Users 组提供了一个最安全的程序运行环境。在经过 NTFS 格式化的卷上,默认安全设置旨在禁止该组的成员危及操作系统和已安装程序的完整性。用户不能修改系统注册表设置、操作系统文件或程序文件。Users 可以关闭工作站,但不能关闭服务器。Users 可以创建本地组,但只能修改自己创建的本地组。
Guests:来宾组,按默认值,来宾跟普通Users的成员有同等访问权,但来宾帐户的限制更多。
Everyone:所有的用户,这个计算机上的所有用户都属于这个组。
如下表,显示了通过Windows API函数来操作通用安全对象的安全信息。
Windows操作各种类型安全对象的信息表
2.2.1 读文件-安全属性
GetNamedSecurityInfo()函数的主要功能是获取指定目录或文件的文件安全属性。
函数原型:
DWORD GetNamedSecurityInfo(
LPTSTR pObjectName, // object name
SE_OBJECT_TYPE ObjectType, // object type
SECURITY_INFORMATION SecurityInfo, // 消息类型
PSID *ppsidOwner, // 所有者的SID
PSID *ppsidGroup, // 以前的组 SID
PACL *ppDacl, // DACL
PACL *ppSacl, // SACL
PSECURITY_DESCRIPTOR *ppSecurityDescriptor // SD
);
返回值:
返回BOOL值,表示是否成功。0:成功
==============================================================
示例:
PACL pOldDacl=NULL;
std::string file_path = “D:\dandao\1.txt”;
PACL pNewDacl=NULL;
DWORD dRet;
PSECURITY_DESCRIPTOR pSID=NULL;
dRet = GetNamedSecurityInfo((LPTSTR)UTWS(file_path),
SE_FILE_OBJECT, //文件安全属性
DACL_SECURITY_INFORMATION,//消息类型为安全类型
NULL,NULL,&pOldDacl,NULL,&pSID);//获取文件的安全属性,信息存放于pOldDacl中
if(dRet== ERROR_SUCCESS) return OK;
=============================================================
2.2.2 写文件-安全属性
SetNamedSecurityInfo()函数的主要功能是设置指定目录或文件的文件安全属性。
函数原型:
DWORD SetNamedSecurityInfo(
LPTSTR pObjectName, // object name
SE_OBJECT_TYPE ObjectType, // object type
SECURITY_INFORMATION SecurityInfo, // 消息类型
PSID *ppsidOwner, // 所有者的SID
PSID *ppsidGroup, // 以前的组 SID
PACL *ppDacl, // DACL
PACL *ppSacl, // SACL
PSECURITY_DESCRIPTOR *ppSecurityDescriptor // SD
);
返回值:
返回BOOL值,表示是否成功。0:成功
2.2.3 修改文件-安全属性
Windows API调用流程:GetNamedSecurityInfo() ->填充EXPLICIT_ACCESS ->
SetEntriesInAcl() ->SetNamedSecurityInfo()->释放DACL和SID。
==============================================================
示例:
PACL pOldDacl=NULL;
PACL pNewDacl=NULL;
DWORD dRet;
std::string file_path = “D:\dandao\1.txt”;
EXPLICIT_ACCESS eia;
PSECURITY_DESCRIPTOR pSID=NULL;
dRet = GetNamedSecurityInfo((LPTSTR)UTWS(file_path),
SE_FILE_OBJECT, //文件安全属性
DACL_SECURITY_INFORMATION,//消息类型为安全类型
NULL,NULL,&pOldDacl,NULL,&pSID);
//创建一个ACE,修改文件的安全属性,并将信息写入eia
ZeroMemory(&eia,sizeof(EXPLICIT_ACCESS));
eia.grfAccessPermissions = 0x1F01FF;
(0x1F01FF:代表完全权限; 0x1200A9:可读、可执行; 0x1701BF:可读、可写、可执行、可修改)
eia.grfAccessMode = GRANT_ACCESS; //权限模式
eia.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;//继承关系
eia.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
eia.Trustee.pstrName = L”everyone”;
// 将新的ACE加入DACL,此时PNewDacl存放的是新的安全属性信息
dRet = SetEntriesInAcl(1,&eia,pOldDacl,&pNewDacl);
if(dRet=ERROR_SUCCESS) return OK;
// 更新修改后的DACL
dRet = SetNamedSecurityInfo((LPTSTR)UTWS(file_path),
SE_FILE_OBJECT, //文件安全属性
DACL_SECURITY_INFORMATION,//消息类型为安全类型
NULL,NULL,NULL,pNewDacl, NULL);
if(dRet=ERROR_SUCCESS) return OK;
//释放DACL和SID
if(pNewDacl)LocalFree(pNewDacl);
if(pSID)LocalFree(pSID);
=================================================================