c++ - Windows 10 中的注册表权限

标签 c++ mfc windows-10 registry dac

在 Windows 7 中以非管理员身份运行的应用程序具有对 HKEY_LOCAL_MACHINE 的读/写权限,但在 Windows 10 中显然没有。

很多应用程序都将内容存储在 HKEY_LOCAL_MACHINE 中,这些内容通常适用于所有用户,并且它们在不以管理员身份运行的情况下也能正常工作(如 Visual Studio),但我的应用程序不行。

如何让我自己的应用程序访问 HKEY_LOCAL_MACHINE 而无需以管理员用户身份运行它?

问题是当我以标准用户身份运行应用程序时,RegCreateKeyEx()RegOpenKeyEx() 在 Windows 10 中返回 ERROR_ACCESS_DENIED , 但如果我以管理员用户身份运行它们,它们就可以正常工作。我不想为此以管理员身份运行应用程序。

更新

根据评论,非管理员应用程序只有对 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 中需要的任何 key (需要以提升的方式运行),然后更改对它们的保护,以便它们可以被访问以标准权限运行的应用程序(即,作为 BUILTIN\Users 组的成员,并且在非提升权限下运行)。

这是“取消保护”注册表项的代码。用记事本编写的代码可能无法完全编译,而且显然有点 hacky,抱歉。

实用函数 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(返回错误代码):

// 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;
}

现在有一个功能可以向“用户”组中的每个人授予对注册表项的访问权限。成功返回 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;
}

关于c++ - Windows 10 中的注册表权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50730569/

相关文章:

c++ - 单例类实现版本

c++ - 如何扩展库类的功能?

c++ - VS2010不理解自己文件的字符串编码

c++ - MFC——圆形按钮

python - 有没有办法在 Windows 10 中安装后更改 python 最大路径长度设置?

C++ Visual Studio 错误 : Identifier cannot be implicitly captured because no default capture mode has been specified

c++ - C++中的空嵌套初始化列表

c++ - 在 C++ 中调用作为结构数组成员的成员函数指针的语法是什么

git - 在 Windows 上的 git Git 中忽略文件名大小写更改

c# - 如何以编程方式关闭 Windows 10 应用程序上的打印 UI?