Разрешения реестра в Windows 10 - PullRequest
0 голосов
/ 07 июня 2018

Приложение, работающее от имени администратора в Windows 7, имеет разрешения на чтение / запись для HKEY_LOCAL_MACHINE, но, очевидно, не для Windows 10.

Многие приложения хранят вещи в HKEY_LOCAL_MACHINE, которые обычнопредназначено для всех пользователей, и они отлично работают (как Visual Studio), не будучи запущенным от имени администратора, но не для моего приложения.

Как я могу сделать, чтобы мое собственное приложение получило доступ HKEY_LOCAL_MACHINE без необходимости запускакак администратор?

Проблема в том, что RegCreateKeyEx() и RegOpenKeyEx() возвращают 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?

Да, я могу создавать записи реестрачерез установщик, который имеет права администратора, но мое приложение все равно хотело бы обновить некоторые настройки!Нужно ли хранить это локально на диске сейчас?

Вся конфигурация в приложении должна быть применима ко всем пользователям.

1 Ответ

0 голосов
/ 07 июня 2018

Как я уже говорил в моих комментариях выше, вам нужно создать все необходимые ключи в HKLM в вашем установщике (который должен быть запущен с повышенными правами), а затем изменить защиту для них, чтобы они могли быть доступны дляприложение, работающее со стандартными разрешениями (то есть как член группы BUILTIN\Users и работающее без повышенных прав).

Вот код для «снятия защиты» с ключа реестра.Код, написанный в блокноте, поэтому может не скомпилироваться, и он, очевидно, немного хакерский.

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