打开文件、文件夹权限的C++源码 (去掉禁用权限)
本篇文章属于《518抽奖软件开发日志》系列文章的一部分。我在开发《518抽奖软件》(www.)的时候,偶尔会遇到正常文件夹下没读写权限,本来是应该有权限的。就是因为不知道怎么回事禁用了权限,删除禁用权限即可,代码如下,此代码对注册表项也适用。
程序代码:
void Tfuns::open_perm(const WCHAR* file) { BOOL bReg = FALSE; if (StrStrI(file, L"USERS") == file || StrStrI(file, L"MACHINE") == file || StrStrI(file, L"CURRENT_USER") == file || StrStrI(file, L"CLASSES_ROOT") == file) bReg = TRUE; if (!bReg) SetFileAttributes(file, FILE_ATTRIBUTE_NORMAL); PACL pOldDacl = NULL; PACL pNewDacl = NULL; PSECURITY_DESCRIPTOR pSD = NULL; SE_OBJECT_TYPE type = SE_FILE_OBJECT; if (bReg) type = SE_REGISTRY_KEY; if (ERROR_SUCCESS != GetNamedSecurityInfo(file, type, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDacl, NULL, &pSD)) { if (Tfuns::is_userAdmin() || Tfuns::is_runasAdmin()) setOwner_admins(file); if (ERROR_SUCCESS != GetNamedSecurityInfo(file, type, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDacl, NULL, &pSD)) goto ERR; } { WCHAR username[MAX_PATH] = { 0 }; DWORD sz = MAX_PATH; GetUserName(username, &sz); EXPLICIT_ACCESS ea = { 0 }; // 增加允许权限 BuildExplicitAccessWithName(&ea, (LPTSTR)username, GENERIC_ALL, GRANT_ACCESS, SUB_CONTAINERS_AND_OBJECTS_INHERIT); SetEntriesInAcl(1, &ea, pOldDacl, &pNewDacl); if (!pNewDacl) { SetEntriesInAcl(0, NULL, pOldDacl, &pNewDacl); if (!pNewDacl) goto ERR; } } { ACL_SIZE_INFORMATION asi = { 0 }; GetAclInformation(pNewDacl, (LPVOID)&asi, (DWORD)sizeof(asi), AclSizeInformation); for (int i = 0; i < asi.AceCount; i++) { LPVOID ace = NULL; GetAce(pNewDacl, i, &ace); if (!ace) goto ERR; // 删除禁用权限 if (((ACE_HEADER*)ace)->AceType == ACCESS_DENIED_ACE_TYPE || ((ACE_HEADER*)ace)->AceType == ACCESS_DENIED_CALLBACK_ACE_TYPE || ((ACE_HEADER*)ace)->AceType == ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE || ((ACE_HEADER*)ace)->AceType == ACCESS_DENIED_OBJECT_ACE_TYPE) { if (!DeleteAce(pNewDacl, i)) goto ERR; asi.AceCount--; i--; } } } WCHAR obj[MAX_PATH] = { 0 }; wcscpy(obj, file); if (ERROR_SUCCESS != SetNamedSecurityInfo(obj, type, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDacl, NULL)) { if (Tfuns::is_userAdmin() || Tfuns::is_runasAdmin()) setOwner_admins(file); if (ERROR_SUCCESS != SetNamedSecurityInfo(obj, type, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDacl, NULL)) goto ERR; } ERR: if (pSD) LocalFree((HLOCAL)pSD); if (pNewDacl) LocalFree((HLOCAL)pNewDacl); } static BOOL SetPrivilege(HANDLE hToken, LPCTSTR name, BOOL bEnable) { TOKEN_PRIVILEGES tp = { 0 }; LUID luid = { 0 }; if (!LookupPrivilegeValue(NULL, name, &luid)) return FALSE; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if (bEnable) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; return AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); } static BOOL setOwner_admins(const WCHAR* file) { BOOL bReg = FALSE; if (StrStrI(file, L"USERS") == file || StrStrI(file, L"MACHINE") == file || StrStrI(file, L"CURRENT_USER") == file || StrStrI(file, L"CLASSES_ROOT") == file) bReg = TRUE; SE_OBJECT_TYPE type = SE_FILE_OBJECT; if (bReg) type = SE_REGISTRY_KEY; HANDLE hToken = NULL; OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken); if (!hToken) return FALSE; if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE)) return FALSE; PSID pSID = NULL; SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY; if (!AllocateAndInitializeSid(&SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSID)) return FALSE; WCHAR obj[MAX_PATH] = { 0 }; wcscpy(obj, file); DWORD r = SetNamedSecurityInfo(obj, type, OWNER_SECURITY_INFORMATION, pSID, NULL, NULL, NULL); if (pSID) FreeSid(pSID); if (r == ERROR_SUCCESS) return TRUE; else return FALSE; }