C++ 编辑/删除受保护的注册表项值

C++ 编辑/删除受保护的注册表项值,c++,winapi,registry,C++,Winapi,Registry,我的问题:当使用自定义安全描述符创建注册表项时,是否可以编辑注册表项的值?我需要用安全属性结构调用吗?如果没有,那么我需要删除密钥,然后重新创建它 我试图删除编辑器,然后重写注册表项值,但它不起作用。一些重要信息是,我使用自定义安全描述符创建了注册表项。自定义安全描述符仅设置了密钥读取 但是我甚至不能删除密钥,因为它的ACL安全描述符。这是一个问题,因为当我卸载时,我甚至不能删除注册表项。我使用自定义安全描述符创建注册表项的原因是,用户不能意外或故意更改注册表项。键告诉我我的应用程序以前是否运行

我的问题:当使用自定义安全描述符创建注册表项时,是否可以编辑注册表项的值?我需要用安全属性结构调用吗?如果没有,那么我需要删除密钥,然后重新创建它

我试图删除编辑器,然后重写注册表项值,但它不起作用。一些重要信息是,我使用自定义安全描述符创建了注册表项。自定义安全描述符仅设置了密钥读取

但是我甚至不能删除密钥,因为它的ACL安全描述符。这是一个问题,因为当我卸载时,我甚至不能删除注册表项。我使用自定义安全描述符创建注册表项的原因是,用户不能意外或故意更改注册表项。键告诉我我的应用程序以前是否运行过

有人知道我如何编辑/删除这种类型的注册表项吗

我的代码,尝试编辑我的密钥并显示我如何首先创建密钥:

// Code to change key value
LONG lResult = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software/MyApplication"), 0, KEY_READ, &hKey);
LONG setValueRes = RegSetValueEx(hKey, _T("FirstRunSignafier"), 0, REG_DWORD, (LPBYTE) &firstRunSignafierValue, 
                                 (DWORD) sizeof(firstRunSignafierValue));
// Error Value of setValueRes is 5. lResult succeeds


// Code that creates the registry key
int  recordFirstApplicationRun()
{
    tstring REG_FIRST_RUN_SIGNIFIER = _T("Software\\MyApplication");
    HKEY hKey;
    LONG lResult;
    int   res                     = 1;
    DWORD dwValue, dwType, dwSize = sizeof(dwValue);
    DWORD firstRunSignafierValue  = 1;
    DWORD keyAlreadyExists; // Two potential values: REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
    PSID pEveryoneSID             = NULL;
    PACL pACL                     = NULL;
    PSECURITY_DESCRIPTOR pSD      = NULL;
    SECURITY_ATTRIBUTES secAttr;

    createSecurityAttributes(&secAttr, pEveryoneSID, pACL, pSD);
    LONG createRes = RegCreateKeyEx(HKEY_CURRENT_USER, &REG_FIRST_RUN_SIGNIFIER[0], 0, NULL, REG_OPTION_NON_VOLATILE, 
                                    KEY_WRITE|KEY_WRITE, &secAttr, &hKey, &keyAlreadyExists);
    if (createRes != ERROR_SUCCESS) {
        //_tprintf(_T("Failed to create key: Last Error: %x, Return Val: %x\n"), GetLastError(), createRes);
        CPP_Utilities::outputLastError("Failed to create key");
        res = -1;
        goto Cleanup;
    }

    //CPP_Utilities::outputLastErrorEx( (keyAlreadyExists == REG_CREATED_NEW_KEY) ? _T("Created new registry key"):_T("Registry key already exists") );
    _tprintf( (keyAlreadyExists == REG_CREATED_NEW_KEY) ? _T("Created new registry key\n"):_T("Registry key already exists\n") );

    // To Write a DWORD to the registry
    LONG setValueRes = RegSetValueEx(hKey, _T("FirstRunSignafier"), 0, REG_DWORD, (LPBYTE) &firstRunSignafierValue, 
                                     (DWORD) sizeof(firstRunSignafierValue));
    if (setValueRes != ERROR_SUCCESS) {
        _tprintf(_T("B: %X\n"), setValueRes);
        CPP_Utilities::outputLastError("Failed to set registry value");
        res = -2;
        goto Cleanup;
    }

    Cleanup:
        if (pEveryoneSID) 
            FreeSid(pEveryoneSID);
        if (pACL) 
            LocalFree(pACL);
        if (pSD) 
            LocalFree(pSD);
        if (hKey)
            RegCloseKey(hKey);

    return res;
}

int createSecurityAttributes(SECURITY_ATTRIBUTES* secAttr, PSID pEveryoneSID, PACL pACL, PSECURITY_DESCRIPTOR pSD)
{
    // Pre: Memory release for parameters MUST be handled by caller

    EXPLICIT_ACCESS ea;
    DWORD dwRes;
    /*PSID*/ pEveryoneSID                   = NULL;
    /*PACL*/ pACL                           = NULL;
    /*PSECURITY_DESCRIPTOR*/ pSD            = NULL;
    SID_IDENTIFIER_AUTHORITY SIDAuthWorld   = SECURITY_WORLD_SID_AUTHORITY;

    // Create a well-known SID for the Everyone group.
    if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID)) {
        _tprintf(_T("AllocateAndInitializeSid Error %u\n"), GetLastError());
        CPP_Utilities::outputLastError("AllocateAndInitializeSid Error");
        return -1;
    }

    // Initialize an EXPLICIT_ACCESS structure for an ACE. The ACE will allow Everyone read access to the key.
    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = KEY_READ;
    ea.grfAccessMode        = SET_ACCESS;
    ea.grfInheritance       = NO_INHERITANCE;
    ea.Trustee.TrusteeForm  = TRUSTEE_IS_SID;
    ea.Trustee.TrusteeType  = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea.Trustee.ptstrName    = (LPTSTR) pEveryoneSID;

    // Create a new ACL that contains the new ACEs.
    dwRes = SetEntriesInAcl(1, &ea, NULL, &pACL);
    if (ERROR_SUCCESS != dwRes) {
        _tprintf(_T("SetEntriesInAcl Error %u\n"), GetLastError());
        CPP_Utilities::outputLastError("SetEntriesInAcl Error");
        return -2;
    }

    // Initialize a security descriptor.  
    pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); 
    if (NULL == pSD) { 
        _tprintf(_T("LocalAlloc Error %u\n"), GetLastError());
        CPP_Utilities::outputLastError("LocalAlloc Error");
        return -3; 
    } 

    if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {  
        _tprintf(_T("InitializeSecurityDescriptor Error %u\n"), GetLastError());
        CPP_Utilities::outputLastError("InitializeSecurityDescriptor Error");
        return -4;
    } 

    // Add the ACL to the security descriptor. 
    if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) {  
        _tprintf(_T("SetSecurityDescriptorDacl Error %u\n"), GetLastError());
        CPP_Utilities::outputLastError("SetSecurityDescriptorDacl Error");
        return -5;
    } 

    // Initialize a security attributes structure.
    secAttr->nLength                = sizeof (SECURITY_ATTRIBUTES);
    secAttr->lpSecurityDescriptor   = pSD;
    secAttr->bInheritHandle         = FALSE;

    return 1;
}

您需要更改权限,以便用户具有密钥设置值访问权限。最简单的方法是卸载程序删除安装程序添加的ACL

您只需要卸载程序来反转安装程序执行的步骤。您的安装程序运行到:

创建一个键。 将ACL添加到密钥。 因此,您的卸载程序需要:

从密钥中删除ACL。 删除密钥。
谢谢你的回答。您知道如何从注册表项中删除ACL吗?我想是使用RegSetKeySecurity