Windows 10 中的注册表权限
Registry permissions in Windows 10
运行在 Windows 7 中作为非管理员的应用程序对 HKEY_LOCAL_MACHINE
具有 read/write 权限,但在 Windows 10 中显然没有。
许多应用程序将内容存储在 HKEY_LOCAL_MACHINE
中,这些内容通常适用于所有用户,并且它们可以正常工作(如 Visual studio)而无需 运行 作为管理员,但不是我的申请。
如何让我自己的应用程序访问 HKEY_LOCAL_MACHINE
而无需以管理员用户身份 运行 它?
问题是 RegCreateKeyEx()
和 RegOpenKeyEx()
return ERROR_ACCESS_DENIED
在 Windows 10,当我 运行 应用程序作为标准用户,但如果我 运行 作为管理员用户,它们工作正常。我不想 运行 只是为了这个应用程序作为管理员。
更新
根据评论,非管理员应用程序只有对 HKLM 的读取权限,我确认调用应用程序只有 READ 写入并且它们可以读取,但注意到 windows 7 也没有'没有写入权限,但我的测试应用程序在 Windows 7 中运行良好。这是代码
void CRegistryPermissionsView::OnBnClickedButtonRegkey()
{
CRegKey regKey;
LRESULT ret = 0;
CString strKey = _T("Software\ATestApp\TestAppNode");
ret = regKey.Open(HKEY_LOCAL_MACHINE, strKey, KEY_ALL_ACCESS);
if (ret == ERROR_FILE_NOT_FOUND)
ret = regKey.Create(HKEY_LOCAL_MACHINE, strKey);
if (ret == ERROR_SUCCESS)
{
ret = regKey.SetStringValue(_T("Entry"), _T("EntryValue"));
if (ret == ERROR_SUCCESS)
{
AfxMessageBox(_T("Success"));
}
}
}
我不知道为什么以上在 Windows 7 中有效,但我的主要问题是我们应该在哪里存储适用于 Windows 10 中所有用户的全局设置?
是的,我可以通过具有管理员权限的安装程序创建注册表项,但我的应用程序仍需要更新某些设置!我们现在必须将其存储在本地驱动器上吗?
应用程序中的所有配置都需要适用于所有用户。
正如我在上面的评论中所说,您在这里必须做的是在您的安装程序中创建您在 HKLM 中需要的任何密钥(需要 运行 提升),然后更改对它们的保护它们可以通过应用程序 运行 标准权限访问(即,作为组 BUILTIN\Users
的成员,并且 运行ning 未提升)。
这是 'unprotect' 注册表项的代码。用记事本编写的代码可能无法完全编译,而且显然有点老套,抱歉。
实用函数 BuildAce(最初缺少,对此感到抱歉):
// Build an access allowed, access denied, system alarm or system audit ACE. Caller must free.
ACE_HEADER * BuildACE (PSID sid, int ace_type, int ace_flags, ACCESS_MASK ace_mask)
{
int sid_len = GetLengthSid (sid);
int ace_len = sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) + sid_len;
ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE *) malloc (ace_len);
memset (ace, 0, ace_len);
ace->Header.AceType = ace_type;
ace->Header.AceFlags = ace_flags;
ace->Header.AceSize = ace_len;
ace->Mask = ace_mask;
memcpy (&ace->SidStart, sid, sid_len);
return (ACE_HEADER *) ace;
}
实用函数 AddOrRemoveACE:
// Add or remove an ACE to/from an ACL
// Returns a copy of the original ACL with the relevant changes made; caller must free
// Sequence of ACE's must be:
// not inherited, denied
// not inherited, allowed
// inherited, denied
// inherited, allowed
ACL *AddOrRemoveACE (ACL *acl, ACE_HEADER *new_ace, bool add)
{
int acl_size = acl->AclSize;
if (add)
acl_size += new_ace->AceSize;
ACL *new_acl = (ACL *) malloc (acl_size);
BOOL ok = InitializeAcl (new_acl, acl_size, ACL_REVISION);
assert (ok);
// Add new denied ACE at start of list
if (add && new_ace->AceType == ACCESS_DENIED_ACE_TYPE)
{
ok = AddAce (new_acl, ACL_REVISION, MAXDWORD, new_ace, new_ace->AceSize);
assert (ok);
}
// Copy all non-inherited ACE's, removing anything matching new_ace
for (int i = 0; ; ++i)
{
ACE_HEADER *old_ace;
if (!GetAce (acl, i, (VOID **) &old_ace))
break;
if ((old_ace->AceFlags & INHERITED_ACE) == 0 &&
(old_ace->AceSize != new_ace->AceSize ||
memcmp (old_ace, new_ace, old_ace->AceSize) != 0))
{
ok = AddAce (new_acl, ACL_REVISION, MAXDWORD, old_ace, old_ace->AceSize);
assert (ok);
}
}
// Add new allowed ACE at end of list
if (add && new_ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
{
ok = AddAce (new_acl, ACL_REVISION, MAXDWORD, new_ace, new_ace->AceSize);
assert (ok);
}
// Copy all inherited ACE's
for (int j = 0; ; ++j)
{
ACE_HEADER *old_ace;
if (!GetAce (acl, j, (VOID **) &old_ace))
break;
if (old_ace->AceFlags & INHERITED_ACE)
{
ok = AddAce (new_acl, ACL_REVISION, MAXDWORD, old_ace, old_ace->AceSize);
assert (ok);
}
}
// Store the actual size of the acl data (not reversible)
ACL_SIZE_INFORMATION asi;
ok = GetAclInformation (new_acl, &asi, sizeof (asi), AclSizeInformation);
assert (ok);
new_acl->AclSize = (WORD) asi.AclBytesInUse;
return new_acl;
}
实用函数 AddOrRemoveRegKeyACE(returns 错误代码):
// Add or remove a registry key ACE. hKey must have WRITE_DAC access
DWORD AddOrRemoveRegKeyACE
(HKEY hKey, bool add, int ace_type, PSID sid, ACCESS_MASK access_mask)
{
LONG err;
PSECURITY_DESCRIPTOR psd;
DWORD buflen = 1024;
// Read current security information
for ( ; ; )
{
psd = malloc (buflen);
err = RegGetKeySecurity (hKey, DACL_SECURITY_INFORMATION, psd, &buflen);
if (err == 0)
break;
free (psd);
if (err == ERROR_INSUFFICIENT_BUFFER)
continue;
return err;
}
SECURITY_DESCRIPTOR_RELATIVE *sdr = (SECURITY_DESCRIPTOR_RELATIVE *) psd;
ACL *pdacl = (ACL *) ((BYTE *) sdr + sdr->Dacl);
ACE_HEADER *ace = BuildACE (sid, ace_type, CONTAINER_INHERIT_ACE, access_mask);
ACL *new_acl = AddOrRemoveACE (pdacl, ace, add);
free (ace);
free (psd);
SECURITY_DESCRIPTOR sd;
BOOL ok = InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
assert (ok);
ok = SetSecurityDescriptorControl (&sd,
SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED,
SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED);
assert (ok);
ok = SetSecurityDescriptorDacl (&sd, TRUE, new_acl, FALSE);
assert (ok);
// apply the security descriptor to the registry key
err = RegSetKeySecurity (hKey, DACL_SECURITY_INFORMATION, &sd);
free (new_acl);
return err;
}
现在有一个功能可以向组 'Users' 中的每个人授予对注册表项的访问权限。 Returns TRUE 成功:
BOOL grant_access_to_registry_key (HKEY hKey)
{
// Give the Users group access to hKey
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
PSID pUsersSid;
BOOL ok = AllocateAndInitializeSid (&sia, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS,
0, 0, 0, 0, 0, 0, &pUsersSid);
if (!ok)
return FALSE;
ok = AddOrRemoveRegKeyACE (hKey, true, ACCESS_ALLOWED_ACE_TYPE,
pUsersSid, KEY_ALL_ACCESS) == 0;
FreeSid (pUsersSid);
return ok;
}
运行在 Windows 7 中作为非管理员的应用程序对 HKEY_LOCAL_MACHINE
具有 read/write 权限,但在 Windows 10 中显然没有。
许多应用程序将内容存储在 HKEY_LOCAL_MACHINE
中,这些内容通常适用于所有用户,并且它们可以正常工作(如 Visual studio)而无需 运行 作为管理员,但不是我的申请。
如何让我自己的应用程序访问 HKEY_LOCAL_MACHINE
而无需以管理员用户身份 运行 它?
问题是 RegCreateKeyEx()
和 RegOpenKeyEx()
return ERROR_ACCESS_DENIED
在 Windows 10,当我 运行 应用程序作为标准用户,但如果我 运行 作为管理员用户,它们工作正常。我不想 运行 只是为了这个应用程序作为管理员。
更新
根据评论,非管理员应用程序只有对 HKLM 的读取权限,我确认调用应用程序只有 READ 写入并且它们可以读取,但注意到 windows 7 也没有'没有写入权限,但我的测试应用程序在 Windows 7 中运行良好。这是代码
void CRegistryPermissionsView::OnBnClickedButtonRegkey()
{
CRegKey regKey;
LRESULT ret = 0;
CString strKey = _T("Software\ATestApp\TestAppNode");
ret = regKey.Open(HKEY_LOCAL_MACHINE, strKey, KEY_ALL_ACCESS);
if (ret == ERROR_FILE_NOT_FOUND)
ret = regKey.Create(HKEY_LOCAL_MACHINE, strKey);
if (ret == ERROR_SUCCESS)
{
ret = regKey.SetStringValue(_T("Entry"), _T("EntryValue"));
if (ret == ERROR_SUCCESS)
{
AfxMessageBox(_T("Success"));
}
}
}
我不知道为什么以上在 Windows 7 中有效,但我的主要问题是我们应该在哪里存储适用于 Windows 10 中所有用户的全局设置?
是的,我可以通过具有管理员权限的安装程序创建注册表项,但我的应用程序仍需要更新某些设置!我们现在必须将其存储在本地驱动器上吗?
应用程序中的所有配置都需要适用于所有用户。
正如我在上面的评论中所说,您在这里必须做的是在您的安装程序中创建您在 HKLM 中需要的任何密钥(需要 运行 提升),然后更改对它们的保护它们可以通过应用程序 运行 标准权限访问(即,作为组 BUILTIN\Users
的成员,并且 运行ning 未提升)。
这是 'unprotect' 注册表项的代码。用记事本编写的代码可能无法完全编译,而且显然有点老套,抱歉。
实用函数 BuildAce(最初缺少,对此感到抱歉):
// Build an access allowed, access denied, system alarm or system audit ACE. Caller must free.
ACE_HEADER * BuildACE (PSID sid, int ace_type, int ace_flags, ACCESS_MASK ace_mask)
{
int sid_len = GetLengthSid (sid);
int ace_len = sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) + sid_len;
ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE *) malloc (ace_len);
memset (ace, 0, ace_len);
ace->Header.AceType = ace_type;
ace->Header.AceFlags = ace_flags;
ace->Header.AceSize = ace_len;
ace->Mask = ace_mask;
memcpy (&ace->SidStart, sid, sid_len);
return (ACE_HEADER *) ace;
}
实用函数 AddOrRemoveACE:
// Add or remove an ACE to/from an ACL
// Returns a copy of the original ACL with the relevant changes made; caller must free
// Sequence of ACE's must be:
// not inherited, denied
// not inherited, allowed
// inherited, denied
// inherited, allowed
ACL *AddOrRemoveACE (ACL *acl, ACE_HEADER *new_ace, bool add)
{
int acl_size = acl->AclSize;
if (add)
acl_size += new_ace->AceSize;
ACL *new_acl = (ACL *) malloc (acl_size);
BOOL ok = InitializeAcl (new_acl, acl_size, ACL_REVISION);
assert (ok);
// Add new denied ACE at start of list
if (add && new_ace->AceType == ACCESS_DENIED_ACE_TYPE)
{
ok = AddAce (new_acl, ACL_REVISION, MAXDWORD, new_ace, new_ace->AceSize);
assert (ok);
}
// Copy all non-inherited ACE's, removing anything matching new_ace
for (int i = 0; ; ++i)
{
ACE_HEADER *old_ace;
if (!GetAce (acl, i, (VOID **) &old_ace))
break;
if ((old_ace->AceFlags & INHERITED_ACE) == 0 &&
(old_ace->AceSize != new_ace->AceSize ||
memcmp (old_ace, new_ace, old_ace->AceSize) != 0))
{
ok = AddAce (new_acl, ACL_REVISION, MAXDWORD, old_ace, old_ace->AceSize);
assert (ok);
}
}
// Add new allowed ACE at end of list
if (add && new_ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
{
ok = AddAce (new_acl, ACL_REVISION, MAXDWORD, new_ace, new_ace->AceSize);
assert (ok);
}
// Copy all inherited ACE's
for (int j = 0; ; ++j)
{
ACE_HEADER *old_ace;
if (!GetAce (acl, j, (VOID **) &old_ace))
break;
if (old_ace->AceFlags & INHERITED_ACE)
{
ok = AddAce (new_acl, ACL_REVISION, MAXDWORD, old_ace, old_ace->AceSize);
assert (ok);
}
}
// Store the actual size of the acl data (not reversible)
ACL_SIZE_INFORMATION asi;
ok = GetAclInformation (new_acl, &asi, sizeof (asi), AclSizeInformation);
assert (ok);
new_acl->AclSize = (WORD) asi.AclBytesInUse;
return new_acl;
}
实用函数 AddOrRemoveRegKeyACE(returns 错误代码):
// Add or remove a registry key ACE. hKey must have WRITE_DAC access
DWORD AddOrRemoveRegKeyACE
(HKEY hKey, bool add, int ace_type, PSID sid, ACCESS_MASK access_mask)
{
LONG err;
PSECURITY_DESCRIPTOR psd;
DWORD buflen = 1024;
// Read current security information
for ( ; ; )
{
psd = malloc (buflen);
err = RegGetKeySecurity (hKey, DACL_SECURITY_INFORMATION, psd, &buflen);
if (err == 0)
break;
free (psd);
if (err == ERROR_INSUFFICIENT_BUFFER)
continue;
return err;
}
SECURITY_DESCRIPTOR_RELATIVE *sdr = (SECURITY_DESCRIPTOR_RELATIVE *) psd;
ACL *pdacl = (ACL *) ((BYTE *) sdr + sdr->Dacl);
ACE_HEADER *ace = BuildACE (sid, ace_type, CONTAINER_INHERIT_ACE, access_mask);
ACL *new_acl = AddOrRemoveACE (pdacl, ace, add);
free (ace);
free (psd);
SECURITY_DESCRIPTOR sd;
BOOL ok = InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
assert (ok);
ok = SetSecurityDescriptorControl (&sd,
SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED,
SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED);
assert (ok);
ok = SetSecurityDescriptorDacl (&sd, TRUE, new_acl, FALSE);
assert (ok);
// apply the security descriptor to the registry key
err = RegSetKeySecurity (hKey, DACL_SECURITY_INFORMATION, &sd);
free (new_acl);
return err;
}
现在有一个功能可以向组 'Users' 中的每个人授予对注册表项的访问权限。 Returns TRUE 成功:
BOOL grant_access_to_registry_key (HKEY hKey)
{
// Give the Users group access to hKey
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
PSID pUsersSid;
BOOL ok = AllocateAndInitializeSid (&sia, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS,
0, 0, 0, 0, 0, 0, &pUsersSid);
if (!ok)
return FALSE;
ok = AddOrRemoveRegKeyACE (hKey, true, ACCESS_ALLOWED_ACE_TYPE,
pUsersSid, KEY_ALL_ACCESS) == 0;
FreeSid (pUsersSid);
return ok;
}