#include #include #include #include #include #include #include "RegistryHelper.h" #include "BkupRstr.hpp" #include "folders.h" #include using namespace nsFolders; using namespace std; //---------------------------------------------------------------------------- // Function: CopyRegistryKey // // Synopsis: Copies a source registry key and all its subkeys to a target registry key. // Note: the target registry key has to exist already. No roll back. // // Arguments: // // sourceKey the handle for source registry key // targetKey the handle for target registry key // fSetSD whether to set the security descriptor // // Returns: ERROR_SUCCESS if successful; otherwise an error code // // Modifies: Modifies the target registry key. // //---------------------------------------------------------------------------- DWORD CopyRegistryKey(HKEY sourceKey, HKEY targetKey, BOOL fSetSD) { WCHAR className[MAX_PATH] = L""; // buffer for class name DWORD classNameLen = sizeof(className)/sizeof(className[0]); // length of class string DWORD numOfSubKeys; // number of subkeys DWORD maxSubKeySize; // longest subkey size DWORD maxClassSize; // longest class string DWORD numOfValues; // number of values for key DWORD maxValueSize; // longest value name DWORD maxValueDataSize; // longest value data DWORD securityDescriptorSize; // size of security descriptor FILETIME lastWriteTime; DWORD i, j; DWORD retValue = ERROR_SUCCESS; // Get the class name and the value count. retValue = RegQueryInfoKey(sourceKey, // key handle className, // buffer for class name &classNameLen, // length of class string NULL, // reserved &numOfSubKeys, // number of subkeys &maxSubKeySize, // longest subkey size &maxClassSize, // longest class string &numOfValues, // number of values for this key &maxValueSize, // longest value name &maxValueDataSize, // longest value data &securityDescriptorSize, // security descriptor &lastWriteTime); // last write time // fix up the security attributes for the target key if (retValue == ERROR_SUCCESS && fSetSD) { PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR) new BYTE[securityDescriptorSize]; if (pSD != NULL) { SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION; retValue = RegGetKeySecurity(sourceKey, secInfo, pSD, &securityDescriptorSize); if (retValue == ERROR_SUCCESS) retValue = RegSetKeySecurity(targetKey, secInfo, pSD); delete[] pSD; } else retValue = E_OUTOFMEMORY; } // subkeys and values related variables auto_ptr subKeyName; DWORD subKeyNameSize; auto_ptr subKeyClassName; DWORD subKeyClassNameSize; auto_ptr valueName; DWORD valueNameSize; DWORD valueType; auto_ptr valueData; DWORD valueDataSize; // copy registry values if (retValue == ERROR_SUCCESS && numOfValues > 0) { valueName = auto_ptr(new WCHAR[maxValueSize + 1]); valueData = auto_ptr(new BYTE[maxValueDataSize]); if (valueName.get() != NULL && valueData.get() != NULL) { // copy all values from source key to target key for (i = 0; i < numOfValues; i++) { valueNameSize = maxValueSize + 1; valueDataSize = maxValueDataSize; retValue = RegEnumValue(sourceKey, i, valueName.get(), &valueNameSize, NULL, &valueType, valueData.get(), &valueDataSize); if (retValue == ERROR_SUCCESS) retValue = RegSetValueEx(targetKey, valueName.get(), NULL, valueType, valueData.get(), valueDataSize); if (retValue != ERROR_SUCCESS) break; } } else retValue = E_OUTOFMEMORY; } // copy registry subkeys if (retValue == ERROR_SUCCESS && numOfSubKeys > 0) { subKeyName = auto_ptr(new WCHAR[maxSubKeySize + 1]); subKeyClassName = auto_ptr(new WCHAR[maxClassSize + 1]); if (subKeyName.get() != NULL && subKeyClassName.get() != NULL) { // process all subkeys for (i = 0; i < numOfSubKeys; i++) { subKeyNameSize = maxSubKeySize + 1; subKeyClassNameSize = maxClassSize + 1; HKEY sourceSubKey; retValue = RegEnumKeyEx(sourceKey, i, subKeyName.get(), &subKeyNameSize, NULL, subKeyClassName.get(), &subKeyClassNameSize, &lastWriteTime); if (retValue == ERROR_SUCCESS) retValue = RegOpenKeyEx(sourceKey, subKeyName.get(), NULL, KEY_ALL_ACCESS|READ_CONTROL|ACCESS_SYSTEM_SECURITY, &sourceSubKey); if (retValue == ERROR_SUCCESS) { BOOL created = FALSE; HKEY newSubKey; retValue = RegOpenKeyEx(targetKey, subKeyName.get(), 0, KEY_ALL_ACCESS|READ_CONTROL |ACCESS_SYSTEM_SECURITY, &newSubKey); if (retValue == ERROR_FILE_NOT_FOUND) { created = TRUE; retValue = RegCreateKeyEx(targetKey, subKeyName.get(), NULL, subKeyClassName.get(), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS|ACCESS_SYSTEM_SECURITY, NULL, &newSubKey, NULL); } if (retValue == ERROR_SUCCESS) { retValue = CopyRegistryKey(sourceSubKey, newSubKey, created); RegCloseKey(newSubKey); } RegCloseKey(sourceSubKey); } if (retValue != ERROR_SUCCESS) break; } } else retValue = E_FAIL; } return retValue; } //---------------------------------------------------------------------------- // Function: DeleteRegistryKey // // Synopsis: Deletes a registry key and all its subkeys. // // Arguments: // // hKey the handle for the registry key to be deleted // lpSubKey the name string for the key to be deleted // // Returns: ERROR_SUCCESS if successful; otherwise an error code // // Modifies: Modifies the subkey. // //---------------------------------------------------------------------------- DWORD DeleteRegistryKey(HKEY hKey, LPCTSTR lpSubKey) { DWORD retValue = ERROR_SUCCESS; _TCHAR subKeyName[MAX_PATH]; DWORD subKeyNameSize = MAX_PATH; // open the key HKEY hKeyToDelete; BOOL bKeyOpened = FALSE; retValue = RegOpenKeyEx(hKey, lpSubKey, 0, KEY_ALL_ACCESS, &hKeyToDelete); // delete subkeys if (retValue == ERROR_SUCCESS) { bKeyOpened = TRUE; do { retValue = RegEnumKey(hKeyToDelete, 0, subKeyName, subKeyNameSize); if (retValue == ERROR_SUCCESS) { retValue = DeleteRegistryKey(hKeyToDelete, subKeyName); } else if (retValue == ERROR_NO_MORE_ITEMS) { retValue = ERROR_SUCCESS; break; } } while (retValue == ERROR_SUCCESS); } // close key if (bKeyOpened == TRUE) RegCloseKey(hKeyToDelete); if (retValue == ERROR_SUCCESS) { retValue = RegDeleteKey(hKey, lpSubKey); } return retValue; } //---------------------------------------------------------------------------- // Function: MoveRegistryFromSourceToTarget // // Synopsis: Moves registry key from a source to a taget // // Arguments: // hSrcParent: the handle to source parent registry key // sSrcKey: the name of source registry key // hTgtParent: the handle to target parent registry key // sTgtKey: the name of target registry key // bTgtKeyCreated: indicate whether the target key is created or not // bTgtKeyUpdated: indicate whether the target key is updated or not // // Returns: ERROR_SUCCESS if successful; otherwise, returns an error code // // Modifies: Create and/or modify the target registry key // //---------------------------------------------------------------------------- DWORD MoveRegFromSourceToTarget(HKEY hSrcParent, const _TCHAR* sSrcKey, HKEY hTgtParent, const _TCHAR* sTgtKey, BOOL* bTgtKeyCreated) { HKEY hSrcKey, hTgtKey; DWORD lret; *bTgtKeyCreated = FALSE; //open the source Registry key, if it exists lret = RegOpenKeyEx(hSrcParent, sSrcKey, 0, KEY_ALL_ACCESS|READ_CONTROL|ACCESS_SYSTEM_SECURITY, &hSrcKey); if (lret == ERROR_SUCCESS) { // // copy over the registry from source key to target key // // open the target key lret = RegOpenKeyEx(hTgtParent, sTgtKey, 0, KEY_ALL_ACCESS|READ_CONTROL |ACCESS_SYSTEM_SECURITY, &hTgtKey); // if cannot open it, create it if (lret == ERROR_FILE_NOT_FOUND) { lret = RegCreateKeyEx(hTgtParent, sTgtKey, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS|ACCESS_SYSTEM_SECURITY, NULL, &hTgtKey, NULL); if (lret == ERROR_SUCCESS) *bTgtKeyCreated = TRUE; } // time to copy registry if (lret == ERROR_SUCCESS) { lret = CopyRegistryKey(hSrcKey, hTgtKey, *bTgtKeyCreated); RegCloseKey(hTgtKey); } RegCloseKey(hSrcKey); // we need to close Mission Critical Software registry key anyway } else if (lret == ERROR_FILE_NOT_FOUND) { // if the source key is not found, assume it is a success lret = ERROR_SUCCESS; } return lret; } //---------------------------------------------------------------------------- // Function: MoveRegistry // // Synopsis: Moves registry key from Mission Critical Software\DomainAdmin to Microsoft\ADMT. // // Arguments: // // Returns: ERROR_SUCCESS if successful; otherwise retuns an error code // // Modifies: Deletes the old Mission Critical Software key and creates new Microsoft\ADMT key. // //---------------------------------------------------------------------------- DWORD MoveRegistry() { DWORD lret = ERROR_SUCCESS; // some key names HKEY hMcsADMTKey; // Mission Critical Software ADMT registry key HKEY hMSADMTKey; // Microsoft ADMT registry key HKEY hMcsHKCUKey; // Mission Critical Software HKCU registry key HKEY hMSHKCUKey; // Microsoft HKCU registry key const _TCHAR* sMcsADMTKey = REGKEY_MCSADMT; const _TCHAR* sMSADMTKey = REGKEY_MSADMT; const _TCHAR* sMcsHKCUKey = REGKEY_MCSHKCU; const _TCHAR* sMSHKCUKey = REGKEY_MSHKCU; // check whether we need to move the registry key from Mission Critical Software to Microsoft\ADMT or not // this information is recorded in a REG_DWORD value in Microsoft\ADMT key lret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sMSADMTKey, 0, KEY_READ, &hMSADMTKey); if (lret == ERROR_SUCCESS) { DWORD type; DWORD value; DWORD valueSize = sizeof(value); lret = RegQueryValueEx(hMSADMTKey, REGVAL_REGISTRYUPDATED, NULL, &type, (LPBYTE)&value, &valueSize); if (lret == ERROR_SUCCESS && type == REG_DWORD && value == 1) { // if RegistryUpdated is REG_DWORD and 1, we don't need to move registry key RegCloseKey(hMSADMTKey); return ERROR_SUCCESS; } else if (lret == ERROR_FILE_NOT_FOUND) lret = ERROR_SUCCESS; RegCloseKey(hMSADMTKey); } else if (lret == ERROR_FILE_NOT_FOUND) { // if the key does not exist, we should go ahead and move the registry lret = ERROR_SUCCESS; } // check whether MCS ADMT is available or not if (lret == ERROR_SUCCESS) { lret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sMcsADMTKey, 0, KEY_READ, &hMcsADMTKey); if (lret == ERROR_SUCCESS) { // if RegistryUpdated is REG_DWORD and 1, we don't need to move registry key RegCloseKey(hMcsADMTKey); } else if (lret == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; } // get backup/restore and system security privileges BOOL fBkupRstrPrivOn = FALSE, fSystemSecurityPrivOn = FALSE; if (lret == ERROR_SUCCESS) { fBkupRstrPrivOn = GetBkupRstrPriv(NULL, TRUE); if (fBkupRstrPrivOn == FALSE) lret = GetLastError(); } if (lret == ERROR_SUCCESS) { fSystemSecurityPrivOn = GetPrivilege(NULL, SE_SECURITY_NAME, TRUE); if (fSystemSecurityPrivOn == FALSE) lret = GetLastError(); } // these two flags are used to keep track of whether two registry keys are created/updated or not BOOL fMSADMTKeyCreated = FALSE; BOOL fMSHKCUKeyCreated = FALSE; if (lret == ERROR_SUCCESS) { lret = MoveRegFromSourceToTarget(HKEY_LOCAL_MACHINE, sMcsADMTKey, HKEY_LOCAL_MACHINE, sMSADMTKey, &fMSADMTKeyCreated); } if (lret == ERROR_SUCCESS) { lret = MoveRegFromSourceToTarget(HKEY_CURRENT_USER, sMcsHKCUKey, HKEY_CURRENT_USER, sMSHKCUKey, &fMSHKCUKeyCreated); } // // delete keys that we do not need // if (lret != ERROR_SUCCESS) { if (fMSADMTKeyCreated) DeleteRegistryKey(HKEY_LOCAL_MACHINE, sMSADMTKey); if (fMSHKCUKeyCreated) DeleteRegistryKey(HKEY_CURRENT_USER, sMSHKCUKey); } // we have successfully created and copied two registry keys, we delete the old Mission Critical Software keys // and mark RegistryUpdated registry value else { // set RegistryUpdated registry value to 1 lret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sMSADMTKey, 0, KEY_ALL_ACCESS, &hMSADMTKey); if (lret == ERROR_SUCCESS) { DWORD type = REG_DWORD; DWORD value = 1; lret = RegSetValueEx(hMSADMTKey, REGVAL_REGISTRYUPDATED, NULL, type, (BYTE*)&value, sizeof(value)); RegCloseKey(hMSADMTKey); } // if we successfully set RegistryUpdated to 1, delete both old keys if (lret == ERROR_SUCCESS) { DeleteRegistryKey(HKEY_LOCAL_MACHINE, sMcsADMTKey); DeleteRegistryKey(HKEY_CURRENT_USER, sMcsHKCUKey); } } // // release privileges // if (fBkupRstrPrivOn) GetBkupRstrPriv(NULL, FALSE); if (fSystemSecurityPrivOn) GetPrivilege(NULL, SE_SECURITY_NAME, FALSE); return lret; }