我需要在产品安装过程中通过编程的方式修改已知注册表键的访问描述符。 我希望它按照以下方式工作:
- 以管理员模式运行安装程序。
- 创建注册表键。
- 一个函数(我需要的函数)从该键查询ACL。
- 如果该函数发现‘Users’组已经具有写访问权限,则不应执行任何操作。
- 如果没有,则应添加新的允许‘Users’组写访问的权限。
- 将权限保存为注册表键的权限。
这个问题类似于使用.NET设置注册表键写入权限,但是我需要C++ / Win32实现。
提前致谢
我需要在产品安装过程中通过编程的方式修改已知注册表键的访问描述符。 我希望它按照以下方式工作:
这个问题类似于使用.NET设置注册表键写入权限,但是我需要C++ / Win32实现。
提前致谢
获取和设置键的ACL需要使用RegGetKeySecurity和RegSetKeySecurity。然后,您需要遍历ACE,并检查适用于“Users”组SID的任何条目。接下来,您将修改/删除现有条目并/或添加新条目。请注意,在普通的Win32 C中处理ACL可能很麻烦。
最简单的授权访问代码包含3个API调用。它为所有经过身份验证的用户和管理员提供对给定hkey
的完全访问权限。
此片段不包含适当的错误处理和报告。请勿将其复制/粘贴到生产代码中。
PSECURITY_DESCRIPTOR sd = nullptr;
ULONG sd_size = 0;
TCHAR* rights = TEXT( "D:" ) // Discretionary ACL
TEXT( "(A;OICI;GA;;;AU)" ) // Allow full control to all authenticated users
TEXT( "(A;OICI;GA;;;BA)" ); // Allow full control to administrators
ConvertStringSecurityDescriptorToSecurityDescriptor( rights, SDDL_REVISION_1, &sd, &sd_size );
RegSetKeySecurity( hkey, DACL_SECURITY_INFORMATION, sd );
LocalFree( sd );
检测“用户”是否具有对密钥的写访问权限可能比预期更困难。我最终编写了一个测试值到注册表中并检查写入结果的方法。
翻译后的内容为:
检测用户是否有对密钥的写入访问权限可能比预期的要更加困难。我的解决方法是将一个测试值写入注册表,然后检查写入的结果。
其中,“Original Answer”翻译成“最初的回答”。
bool RegistryGrantAll(HKEY hKey)
{
bool bResult = false;
PSECURITY_DESCRIPTOR sd = nullptr;
const TCHAR* szSD =
TEXT("D:") // Discretionary ACL
TEXT("(D;OICI;KA;;;BG)") // Deny access to built-in guests
TEXT("(D;OICI;KA;;;AN)") // Deny access to anonymous logon
TEXT("(A;OICI;KRKW;;;AU)") // Allow KEY_READ and KEY_WRITE to authenticated users ("AU")
TEXT("(A;OICI;KA;;;BA)"); // Allow KEY_ALL_ACCESS to administrators ("BA" = Built-in Administrators)
if (ConvertStringSecurityDescriptorToSecurityDescriptor((LPCTSTR)szSD, SDDL_REVISION_1, &sd, 0))
{
auto result = RegSetKeySecurity(hKey, DACL_SECURITY_INFORMATION, sd);
if (ERROR_SUCCESS == result)
bResult = true;
else
SetLastError(result);
// Free the memory allocated for the SECURITY_DESCRIPTOR.
LocalFree(sd);
}
return bResult;
}
https://learn.microsoft.com/en-us/windows/win32/secbp/creating-a-dacl
https://learn.microsoft.com/en-us/windows/win32/secauthz/ace-strings
RegGetKeySecurity
或手动组合ACL。甚至不需要RegOpenKeyEx
。有关更多信息,请查看this MS doc.。
更新:当然需要管理员权限才能执行。// sk - alloced string / path to needed key
// common look: MACHINE\\Software\\... where MACHINE == HKEY_LOCAL_MACHINE
// google for more address abbrevations
PSECURITY_DESCRIPTOR pSD = 0;
EXPLICIT_ACCESS ea;
PACL pOldDACL = 0, pNewDACL = 0;
if (ERROR_SUCCESS == GetNamedSecurityInfo(sk, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, 0, 0, &pOldDACL, 0, &pSD)) {
memset(&ea, 0, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = KEY_ALL_ACCESS;
ea.grfAccessMode = GRANT_ACCESS;
ea.grfInheritance = NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.ptstrName = <USERNAME HERE>; //DOMAIN\\USERNAME
if (ERROR_SUCCESS == SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL)) {
if (ERROR_SUCCESS == SetNamedSecurityInfo(sk, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, 0, 0, pNewDACL, 0)) {
if (pSD != 0) LocalFree((HLOCAL)pSD);
if (pNewDACL != 0) LocalFree((HLOCAL)pNewDACL);
SAFE_FREE(sk);
// WE'RE GOOD!
return ... ;
} else {
if (pSD) LocalFree((HLOCAL)pSD);
if (pNewDACL) LocalFree((HLOCAL)pNewDACL);
SAFE_FREE(sk);
// SetNamedSecurityInfo failed
return ... ;
}
} else {
if (pSD) LocalFree((HLOCAL)pSD);
if (pNewDACL) LocalFree((HLOCAL)pNewDACL);
SAFE_FREE(sk);
// SetEntriesInAcl failed
return ... ;
}
} else {
if (pSD) LocalFree((HLOCAL)pSD);
SAFE_FREE(sk);
// GetNamedSecurityInfo failed
return ... ;
}
HKLM\Software\KO Software\Approach
。所以我需要使这个键可写。 - Kerido