static HRESULT DeleteEmptyRegistryKeyChildren( __in DWORD dwRoot, __in_z LPCWSTR wzSubKey ) { HRESULT hr = S_OK; HKEY hkKey = NULL; DWORD dwIndex = 0; BOOL fNoValues = FALSE; LPWSTR sczValueName = NULL; LPWSTR sczSubkeyName = NULL; LPWSTR sczSubkeyPath = NULL; DWORD dwSubKeyPathLen = 0; hr = RegOpen(ManifestConvertToRootKey(dwRoot), wzSubKey, KEY_READ, &hkKey); if (E_FILENOTFOUND == hr) { ExitFunction1(hr = S_OK); } ExitOnFailure(hr, "Failed to open regkey: %ls", wzSubKey); if (E_NOMOREITEMS == RegValueEnum(hkKey, dwIndex, &sczValueName, NULL)) { fNoValues = TRUE; } // Recurse and handle subkeys as well dwIndex = 0; while (E_NOMOREITEMS != (hr = RegKeyEnum(hkKey, dwIndex, &sczSubkeyName))) { ExitOnFailure(hr, "Failed to enumerate key %u", dwIndex); hr = StrAllocString(&sczSubkeyPath, wzSubKey, 0); ExitOnFailure(hr, "Failed to allocate copy of subkey name"); dwSubKeyPathLen = lstrlenW(sczSubkeyPath); if (0 == dwSubKeyPathLen) { hr = E_INVALIDARG; ExitOnFailure(hr, "Encountered empty keyname while enumerating subkeys under key: %ls", wzSubKey); } else if (L'\\' != sczSubkeyPath[dwSubKeyPathLen - 1]) { hr = StrAllocConcat(&sczSubkeyPath, L"\\", 1); ExitOnFailure(hr, "Failed to concatenate backslash to copy of regkey name"); } hr = StrAllocConcat(&sczSubkeyPath, sczSubkeyName, 0); ExitOnFailure(hr, "Failed to concatenate subkey name to subkey path"); hr = DeleteEmptyRegistryKeyChildren(dwRoot, sczSubkeyPath); // Increment and ignore the error if we didn't delete the subkey if (HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) == hr) { ++dwIndex; hr = S_OK; } ExitOnFailure(hr, "Failed to read regkey and write settings for root: %u, subkey: %ls", dwRoot, sczSubkeyPath); } // If there are no keys and no values under it, delete it if (fNoValues && 0 == dwIndex) { hr = RegDelete(ManifestConvertToRootKey(dwRoot), wzSubKey, REG_KEY_DEFAULT, FALSE); ExitOnFailure(hr, "Failed to delete registry key at root: %u, subkey: %ls", dwRoot, wzSubKey); ExitFunction1(hr = S_OK); } else { ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY)); } LExit: ReleaseRegKey(hkKey); ReleaseStr(sczValueName); ReleaseStr(sczSubkeyName); ReleaseStr(sczSubkeyPath); return hr; }
/******************************************************************** RegDelete - deletes a registry key (and optionally it's whole tree). *********************************************************************/ extern "C" HRESULT DAPI RegDelete( __in HKEY hkRoot, __in_z LPCWSTR wzSubKey, __in REG_KEY_BITNESS kbKeyBitness, __in BOOL fDeleteTree ) { HRESULT hr = S_OK; DWORD er = ERROR_SUCCESS; LPWSTR pszEnumeratedSubKey = NULL; LPWSTR pszRecursiveSubKey = NULL; HKEY hkKey = NULL; REGSAM samDesired = 0; if (fDeleteTree) { hr = RegOpen(hkRoot, wzSubKey, KEY_READ, &hkKey); if (E_FILENOTFOUND == hr) { ExitFunction1(hr = S_OK); } ExitOnFailure1(hr, "Failed to open this key for enumerating subkeys", wzSubKey); // Yes, keep enumerating the 0th item, because we're deleting it every time while (E_NOMOREITEMS != (hr = RegKeyEnum(hkKey, 0, &pszEnumeratedSubKey))) { ExitOnFailure(hr, "Failed to enumerate key 0"); hr = PathConcat(wzSubKey, pszEnumeratedSubKey, &pszRecursiveSubKey); ExitOnFailure2(hr, "Failed to concatenate paths while recursively deleting subkeys. Path1: %ls, Path2: %ls", wzSubKey, pszEnumeratedSubKey); hr = RegDelete(hkRoot, pszRecursiveSubKey, kbKeyBitness, fDeleteTree); ExitOnFailure1(hr, "Failed to recursively delete subkey: %ls", pszRecursiveSubKey); } hr = S_OK; } if (!vfRegInitialized && REG_KEY_DEFAULT != kbKeyBitness) { hr = E_INVALIDARG; ExitOnFailure(hr, "RegInitialize must be called first in order to RegDelete() a key with non-default bit attributes!"); } switch (kbKeyBitness) { case REG_KEY_32BIT: samDesired = KEY_WOW64_32KEY; break; case REG_KEY_64BIT: samDesired = KEY_WOW64_64KEY; break; case REG_KEY_DEFAULT: // Nothing to do break; } if (NULL != vpfnRegDeleteKeyExW) { er = vpfnRegDeleteKeyExW(hkRoot, wzSubKey, samDesired, 0); if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er)) { ExitFunction1(hr = E_FILENOTFOUND); } ExitOnWin32Error(er, hr, "Failed to delete registry key (ex)."); } else { er = vpfnRegDeleteKeyW(hkRoot, wzSubKey); if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er)) { ExitFunction1(hr = E_FILENOTFOUND); } ExitOnWin32Error(er, hr, "Failed to delete registry key."); } LExit: ReleaseRegKey(hkKey); ReleaseStr(pszEnumeratedSubKey); ReleaseStr(pszRecursiveSubKey); return hr; }
static HRESULT ReadRegKeyWriteLegacyDb( __in CFGDB_STRUCT *pcdb, __in LEGACY_SYNC_PRODUCT_SESSION *pSyncProductSession, __in LEGACY_REGISTRY_KEY *pRegKey, __in_z LPCWSTR wzSubKey ) { HRESULT hr = S_OK; HKEY hkKey = NULL; DWORD dwType = 0; DWORD dwIndex = 0; LPWSTR sczValueName = NULL; LPWSTR sczSubkeyName = NULL; LPWSTR sczSubkeyPath = NULL; hr = RegOpen(ManifestConvertToRootKey(pRegKey->dwRoot), wzSubKey, KEY_READ, &hkKey); if (E_FILENOTFOUND == hr) { ExitFunction1(hr = S_OK); } ExitOnFailure(hr, "Failed to open regkey: %ls", wzSubKey); dwIndex = 0; while (E_NOMOREITEMS != (hr = RegValueEnum(hkKey, dwIndex, &sczValueName, &dwType))) { ExitOnFailure(hr, "Failed to enumerate value %u", dwIndex); hr = ReadRegValueWriteLegacyDb(pcdb, pSyncProductSession, pRegKey, hkKey, wzSubKey, sczValueName, dwType); ExitOnFailure(hr, "Failed to write registry value setting: %ls", sczValueName); ++dwIndex; } // Recurse and handle subkeys as well dwIndex = 0; while (E_NOMOREITEMS != (hr = RegKeyEnum(hkKey, dwIndex, &sczSubkeyName))) { ExitOnFailure(hr, "Failed to enumerate key %u", dwIndex); hr = StrAllocString(&sczSubkeyPath, wzSubKey, 0); ExitOnFailure(hr, "Failed to allocate copy of subkey name"); hr = PathBackslashTerminate(&sczSubkeyPath); ExitOnFailure(hr, "Failed to ensure path is terminated with a backslash"); hr = StrAllocConcat(&sczSubkeyPath, sczSubkeyName, 0); ExitOnFailure(hr, "Failed to concatenate subkey name to subkey path"); hr = ReadRegKeyWriteLegacyDb(pcdb, pSyncProductSession, pRegKey, sczSubkeyPath); ExitOnFailure(hr, "Failed to read regkey and write settings for root: %u, subkey: %ls", pRegKey->dwRoot, sczSubkeyPath); ++dwIndex; } if (E_NOMOREITEMS == hr) { hr = S_OK; } LExit: ReleaseRegKey(hkKey); ReleaseStr(sczValueName); ReleaseStr(sczSubkeyName); ReleaseStr(sczSubkeyPath); return hr; }