Search code examples
c++winapiregistry

RegCreateKeyEx and RegOpenKeyEx succeeds but RegSetValueEx fails to set value


I am trying to set value for a test key under HKCR. RegCreateKeyEx successfully creates the test key and RegOpenKeyEx successfully open the key. RegSetValueEx output ERROR_SUCCESS but doesn't actually write any values. I have been through all similar questions previously asked and the suggestion was that the key would get created under HKLM\SOFTWARE\Wow6432Node. I am on 64-bit win 10 and testkey is under HKCR; there is nothing similar under HKLM\SOFTWARE\Wow6432Node. I tried two different RegSetValueEx and neither works. What am I doing wrong?

HKEY hKey;
LONG lResult;
lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, "testKey", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL );
if(lResult == ERROR_SUCCESS)
    cout<<"Success! Key Created!"<<endl;

lResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, "testKey", 0, KEY_ALL_ACCESS, &hKey);
if(lResult == ERROR_SUCCESS){
    cout<<"Success! Key Opened!"<<endl;
    const char info[] = "URL:URITest Link\0";
    lResult = RegSetValueEx(HKEY_CLASSES_ROOT,"",0,REG_SZ,(BYTE*) info,strlen(info));
    //lResult = RegSetValueEx(HKEY_CLASSES_ROOT,"URL Protocol",0,REG_NONE,NULL,0);
    if(lResult == ERROR_SUCCESS)
        cout<<"Success! Value Set!"<<endl;
    else
        cout<<lResult<<endl;

}

EDIT: See @Remy Lebeau answer below to see where my code was wrong.


Solution

  • I am trying to set value for a test key under HKCR. RegCreateKeyEx successfully creates the test key and RegOpenKeyEx successfully open the key. RegSetValueEx output ERROR_SUCCESS but doesn't actually write any values.

    You are not passing the HKEY handle returned by RegOpenKeyEx() to RegSetValueEx(). You need to replace the hard-coded HKEY_CLASSES_ROOT with the hKey variable in the first parameter:

    lResult = RegSetValueEx(hKey, "URL Protocol", 0, REG_NONE, NULL,0);
    

    But, in order for that to work, you also need to change your RegOpenKeyEx() call to request KEY_WRITE (or at least KEY_SET_VALUE) permission. You are opening the key with KEY_READ permission instead. You cannot write to a read-only key:

    lResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, "testKey", 0, KEY_SET_VALUE, &hKey);
    

    That being said, you shouldn't be writing to KEY_CLASSES_ROOT directly to begin with. HKEY_CLASSES_ROOT is not an actual key of its own, it is actually a merged view of the HKEY_LOCAL_MACHINE\Software\Classes and HKEY_CURRENT_USER\Software\Classes keys:

    HKEY_CLASSES_ROOT Key

    Merged View of HKEY_CLASSES_ROOT.aspx

    If you write keys to a key under HKEY_CLASSES_ROOT, the system stores the information under HKEY_LOCAL_MACHINE\Software\Classes. If you write values to a key under HKEY_CLASSES_ROOT, and the key already exists under HKEY_CURRENT_USER\Software\Classes, the system will store the information there instead of under HKEY_LOCAL_MACHINE\Software\Classes.

    If you want to register a URI scheme that is accessible to only the current user, save it in HKEY_CURRENT_USER\Software\Classes\testKey:

    HKEY hKey;
    LONG lResult;
    
    lResult = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes\\testKey", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
    if (lResult == ERROR_SUCCESS)
    {
        cout << "Success! Key Created!" << endl;
    
        const char info[] = "URL:URITest Link\0";
        lResult = RegSetValueEx(hKey, "" , 0, REG_SZ, (BYTE*) info, sizeof(info));
        if (lResult == ERROR_SUCCESS)
            lResult = RegSetValueEx(hKey, "URL Protocol", 0, REG_NONE, NULL, 0);
        if (lResult == ERROR_SUCCESS)
            cout << "Success! Value Set!" << endl;
        else
            cout << lResult << endl;
    
        RegCloseKey(hKey);
    }
    

    If you want the URI scheme to be accessible to all users, save it in HKEY_LOCAL_MACHINE\Software\Classes\testKey:

    HKEY hKey;
    LONG lResult;
    
    lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Classes\\testKey", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
    if (lResult == ERROR_SUCCESS)
    {
        cout << "Success! Key Created!" << endl;
    
        const char info[] = "URL:URITest Link\0";
        lResult = RegSetValueEx(hKey, "" , 0, REG_SZ, (BYTE*) info, sizeof(info));
        if (lResult == ERROR_SUCCESS)
            lResult = RegSetValueEx(hKey, "URL Protocol", 0, REG_NONE, NULL, 0);
        if (lResult == ERROR_SUCCESS)
            cout << "Success! Value Set!" << endl;
        else
            cout << lResult << endl;
    
        RegCloseKey(hKey);
    }