//
// 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,
_tprintf(TEXT("AddAccessAllowedAce() failed. Error %d\n"),
}
//
// 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"),
}
// 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)
"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());
// STEP 20: 把新的SD設定設定到檔案的安全屬性中(千山萬水啊,終于到了)
if (!SetFileSecurity(lpszFileName, secInfo,
&newSD)) {
_tprintf(TEXT("SetFileSecurity() failed. Error %d\n"),
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"));
else {
_tprintf(TEXT("AddAccessRights() succeeded.\n"));
return 0;
通過以上的示例,相信你已知道如何操作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。
本文轉自 haoel 51CTO部落格,原文連結:http://blog.51cto.com/haoel/124664,如需轉載請自行聯系原作者