WindowsRegistry questions

  1. Why do WindowsRegistry::deleteValue and WindowsRegistry::deleteKey not return a value or a Result?

  2. Could you add a function to delete a Key and all it’s Subkeys (see Microsoft Example)

Thanks,

Rail

Okay… Here’s what I came up with:

/** Deletes a registry value. */
static bool JUCE_CALLTYPE deleteValue (const String& regValuePath, WoW64Mode mode = WoW64_Default);

/** Deletes a registry key (which is registry-talk for 'folder'). */
static bool JUCE_CALLTYPE deleteKey (const String& regKeyPath, WoW64Mode mode = WoW64_Default);

/** Deletes a registry key and all it's subkeys. */
static bool JUCE_CALLTYPE deleteNode (const String& regKeyPath, WoW64Mode mode = WoW64_Default);

Implementation:

 bool JUCE_CALLTYPE WindowsRegistry::deleteValue (const String& regValuePath, WoW64Mode mode)
{
    const RegistryKeyWrapper key (regValuePath, true, (DWORD) mode);

    if (key.key != 0)
        if (RegDeleteValue (key.key, key.wideCharValueName) == ERROR_SUCCESS)
            return true;

    return false;
}

 bool JUCE_CALLTYPE WindowsRegistry::deleteKey (const String& regKeyPath, WoW64Mode mode)
{
    const RegistryKeyWrapper key (regKeyPath, true, (DWORD) mode);

    if (key.key != 0)
        if (RegDeleteKey (key.key, key.wideCharValueName) == ERROR_SUCCESS)
            return true;

    return false;
}

 bool JUCE_CALLTYPE WindowsRegistry:: deleteNode (const String& regKeyPath, WoW64Mode mode)
{
    // First, see if we can delete the key without having
    // to recurse.

    if (deleteKey (regKeyPath, mode))
        return true;

    {

    const RegistryKeyWrapper key (regKeyPath + "\\ZZZZZZZ_DUMMY_02122012", false, mode);    // RegistryKeyWrapper requires a value 
                                                                                            // so we make a fake one which hopefully will never exist

    if (key.key != 0)
        {
        TCHAR    szSubKey[MAX_PATH];
        DWORD    dwSize;
        FILETIME ftWrite;
        LONG     lResult;

        // Enumerate the keys

        dwSize = MAX_PATH;

        lResult = RegEnumKeyEx (key.key, 0, szSubKey, &dwSize, NULL, NULL, NULL, &ftWrite);

        if (lResult == ERROR_SUCCESS)
            {
            String mutableRegKeyPath = regKeyPath;        // need a mutable String

            do {
                mutableRegKeyPath += "\\" + String (szSubKey);

                if (! deleteNode (mutableRegKeyPath, mode))
                    break;

                mutableRegKeyPath = mutableRegKeyPath.upToLastOccurrenceOf ("\\", false, true);

                dwSize = MAX_PATH;

                lResult = RegEnumKeyEx (key.key, 0, szSubKey, &dwSize, NULL, NULL, NULL, &ftWrite);

                } while (lResult == ERROR_SUCCESS);
            }
        }

    }

    // Try again to delete the key.

    return deleteKey (regKeyPath, mode);
}

Rail

Cheers Rail - I’ll take a look at this when I get a moment.

Wow, Microsoft example code can be pretty tortuous! Here’s a version where I’ve tried to strip out all the unnecessary spam - does this still work in your use-case?

bool JUCE_CALLTYPE WindowsRegistry::deleteNode (const String& regKeyPath, WoW64Mode mode)
{
    if (deleteKey (regKeyPath, mode))
        return true;

    {
        // (RegistryKeyWrapper needs a sub-path, so use a dummy one that will be ignored)
        const RegistryKeyWrapper key (regKeyPath + "\\DUMMY_KEY_987654321X", false, mode);

        if (key.key != 0)
        {
            for (;;)
            {
                wchar_t subKey[MAX_PATH + 1] = {};
                DWORD subKeySize = MAX_PATH;

                if (RegEnumKeyEx (key.key, 0, subKey, &subKeySize, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS
                     || ! deleteNode (regKeyPath + "\\" + String (subKey), mode))
                    break;
            }
        }
    }

    return deleteKey (regKeyPath, mode);
}
1 Like

Perfect :smiley:

I was actually worried about using the dummy value… but it seemed the easiest solution.

Thanks!

Rail

Yeah, perhaps it could be even simpler if we just make sure that deleteKey is itself recursive, e.g.

bool JUCE_CALLTYPE WindowsRegistry::deleteKey (const String& regKeyPath, WoW64Mode mode)
{
    const RegistryKeyWrapper key (regKeyPath, true, (DWORD) mode);

    if (key.key == 0)
        return false;

    if (RegDeleteKey (key.key, key.wideCharValueName) == ERROR_SUCCESS)
        return true;

    for (;;)
    {
        wchar_t subKey[MAX_PATH + 1] = {};
        DWORD subKeySize = MAX_PATH;

        if (RegEnumKeyEx (key.key, 0, subKey, &subKeySize, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS
             || ! deleteKey (regKeyPath + "\\" + String (subKey), mode))
            break;
    }

    return RegDeleteKey (key.key, key.wideCharValueName) == ERROR_SUCCESS;
}

?

Tried that but RegEnumKeyEx() is failing… perhaps because we’re opening in write mode??

Yup… https://msdn.microsoft.com/en-us/library/windows/desktop/ms724878(v=vs.85).aspx

write doesn’t have the KEY_ENUMERATE_SUB_KEYS flag set.

Rail

… and even if I add the flag:

const RegistryKeyWrapper key (regKeyPath, true, (DWORD)(mode | KEY_ENUMERATE_SUB_KEYS));

without the dummy value the key structure is off.

Rail

Hmm. How about

static bool deleteKeyNonRecursive (const String& regKeyPath, WoW64Mode mode)
{
    const RegistryKeyWrapper key (regKeyPath, true, (DWORD) mode);

    return key.key != 0 && RegDeleteKey (key.key, key.wideCharValueName) == ERROR_SUCCESS;
}

bool JUCE_CALLTYPE WindowsRegistry::deleteKey (const String& regKeyPath, WoW64Mode mode)
{
    if (deleteKeyNonRecursive (regKeyPath, mode))
        return true;

    for (const RegistryKeyWrapper key (regKeyPath, false, (DWORD) mode);;)
    {
        wchar_t subKey[MAX_PATH + 1] = {};
        DWORD subKeySize = MAX_PATH;

        if (RegEnumKeyEx (key.key, 0, subKey, &subKeySize, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS
             || ! deleteKey (regKeyPath + "\\" + String (subKey), mode))
            break;
    }

    return deleteKeyNonRecursive (regKeyPath, mode);
}

I haven’t tried that… but it looks like it’ll have the same issues as the previous version where I just set the flag… where the first nested folder is off because of the “value”.

Yeah… with my test call to:

return WindowsRegistry::deleteKey (“HKEY_LOCAL_MACHINE\SOFTWARE\Platinum Samples\Accent”, WindowsRegistry::WoW64_64bit);

I get: HKEY_LOCAL_MACHINE\SOFTWARE\Platinum Samples\Accent\Accent\…

Rail

oh yes, sorry. Surely enough just to add this?

for (const RegistryKeyWrapper key (regKeyPath + "\\", false, (DWORD) mode);;)

Bingo! We have a winner. Now you can mix the KEY_WRITE and the KEY_ENUMERATE_SUB_KEYS flag if you don’t want to split it out… but that’s your call.

Thanks,

Rail

Great, thanks for your help. I’ll leave the RegCreateKeyEx flags the same if this works, and will push it shortly…

1 Like