//+---------------------------------------------------------------------------- // // File: migrate.cpp // // Module: CMSTP.EXE // // Synopsis: This source file contains most of the code necessary for // the migration of CM profiles. This code handles both migrating // a user when a CM1.2 profile is installed on a machine with // existing 1.0 profiles and if the user upgrades their OS to NT5. // // Copyright (c) 1997-1999 Microsoft Corporation // // Author: quintinb Created 07/14/98 // //+---------------------------------------------------------------------------- #include "cmmaster.h" // // For ProfileNeedsMigration // #include "needsmig.cpp" //+---------------------------------------------------------------------------- // // Function: CreateRegAndValue // // Synopsis: This function is a wrapper to Create a Reg Key and then add a defualt // value to that same key. // // Arguments: HKEY hBaseKey - Relative starting point for the new subkey // LPTSTR szSubKey - SubKey path // LPTSTR szValue - String to put in the Keys default value. // // Returns: BOOL - TRUE if the key and value were successfully created // // History: quintinb Created Header 5/5/98 // //+---------------------------------------------------------------------------- BOOL CreateRegAndValue(HKEY hBaseKey, LPCTSTR szSubKey, LPCTSTR szValue) { DWORD dwDisp; BOOL bReturn = FALSE; HKEY hKey; if (ERROR_SUCCESS == RegCreateKeyEx(hBaseKey, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisp)) { bReturn = (ERROR_SUCCESS == RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE*)szValue, (lstrlen(szValue)+1))); MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey)); } return bReturn; } // Note: I added this function because I needed to get the following CFileNameParts // off the stack of UpdateProfileLegacyGUIDs so that I didn't need a // stack checking function. Not the greatest workaround but it sufficed. BOOL IsDefaultIcon(LPCTSTR szIconPath) { BOOL bReturn = TRUE; CFileNameParts IconPath(szIconPath); DWORD Lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); if (CSTR_EQUAL != CompareString(Lcid, NORM_IGNORECASE, IconPath.m_FileName, -1, TEXT("cmmgr32"), -1)) { // // Then the icon path is something else besides cmmgr32.exe, we must not // update it. // bReturn = FALSE; } return bReturn; } //+---------------------------------------------------------------------------- // // Function: UpdateProfileLegacyGUIDs // // Synopsis: This function upgrades GUIDs on a Legacy OS install to make sure // that older profile still function. This is necessary because CM // 1.0/1.1 profiles expected the CM bits to be in the same directory as // the cmp file. Thus only the cmp filename was given. In CM 1.2 we need // the full path to the CMP file since the cm bits are now located in // system32. The GUIDs are also updated to have a delete option and // the attributes were changed to not allow renaming. // // Arguments: LPTSTR szCmpFile - Full path to the cmp file of the profile to update // // Returns: BOOL - returns TRUE if the profile was successfully updated // // History: quintinb Created Header 5/5/98 // //+---------------------------------------------------------------------------- BOOL UpdateProfileLegacyGUIDs(LPCTSTR szCmpFile) { TCHAR szInfFile[MAX_PATH+1]; TCHAR szGUID[MAX_PATH+1]; TCHAR szTemp[MAX_PATH+1]; TCHAR szSubKey[MAX_PATH+1]; TCHAR szCommandStr[2*MAX_PATH+1]; BOOL bReturn = TRUE; HKEY hKey; UINT nNumChars; MYDBGASSERT(NULL != szCmpFile); MYDBGASSERT(TEXT('\0') != szCmpFile[0]); // // Now split the path // CFileNameParts FileParts(szCmpFile); // // Now construct the path to the INF file (1.0 and 1.1 profiles kept the infs in // the system dir) // MYVERIFY(0 != GetSystemDirectory(szTemp, MAX_PATH)); nNumChars = (UINT)wsprintf(szInfFile, TEXT("%s\\%s%s"), szTemp, FileParts.m_FileName, TEXT(".inf")); MYDBGASSERT(CELEMS(szInfFile) > nNumChars); // // Get the GUID from the inf file. // ZeroMemory(szGUID, sizeof(szGUID)); GetPrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid, TEXT(""), szGUID, MAX_PATH, szInfFile); if (0 != szGUID[0]) { // // Update the DefaultIcon Value if it points to cmmgr32.exe // BOOL bUpdateIconPath = TRUE; nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\DefaultIcon"), szGUID); MYDBGASSERT(CELEMS(szSubKey) > nNumChars); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szSubKey, 0, KEY_READ | KEY_WRITE, &hKey)) { DWORD dwSize = CELEMS(szTemp); DWORD dwType = REG_SZ; if (ERROR_SUCCESS == RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)szTemp, &dwSize)) { bUpdateIconPath = IsDefaultIcon(szTemp); } RegCloseKey(hKey); } if (bUpdateIconPath) { if (GetSystemDirectory(szTemp, CELEMS(szTemp))) { nNumChars = (UINT)wsprintf(szCommandStr, TEXT("%s\\cmmgr32.exe,0"), szTemp); MYDBGASSERT(CELEMS(szCommandStr) > nNumChars); bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr); } } // // Update Settings to Properties on the desktop icon menu // nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Settings..."), szGUID); MYDBGASSERT(CELEMS(szSubKey) > nNumChars); nNumChars = (UINT)wsprintf(szCommandStr, TEXT("P&roperties")); MYDBGASSERT(CELEMS(szCommandStr) > nNumChars); bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr); // // Now change the underlying command to give the full // path to the cmp file. // nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Settings...\\Command"), szGUID); MYDBGASSERT(CELEMS(szSubKey) > nNumChars); nNumChars = (UINT)wsprintf(szCommandStr, TEXT("cmmgr32.exe /settings \"%s\""), szCmpFile); MYDBGASSERT(CELEMS(szCommandStr) > nNumChars); bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr); // // Update Open to Connect on the desktop icon menu // nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Open"), szGUID); MYDBGASSERT(CELEMS(szSubKey) > nNumChars); nNumChars = (UINT)wsprintf(szCommandStr, TEXT("C&onnect")); MYDBGASSERT(CELEMS(szCommandStr) > nNumChars); bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr); // // Now change the underlying command string to use the full path to the cmp file. // nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Open\\Command"), szGUID); MYDBGASSERT(CELEMS(szSubKey) > nNumChars); nNumChars = (UINT)wsprintf(szCommandStr, TEXT("cmmgr32.exe \"%s\""), szCmpFile); MYDBGASSERT(CELEMS(szCommandStr) > nNumChars); bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr); // // Remove the showicon command from the inf. // // RemoveShowIconFromRunPostSetupCommands(szInfFile); // // Add the delete menu option // nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Delete"), szGUID); MYDBGASSERT(CELEMS(szSubKey) > nNumChars); nNumChars = (UINT)wsprintf(szCommandStr, TEXT("&Delete")); MYDBGASSERT(CELEMS(szSubKey) > nNumChars); bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr); // // Create the uninstall command // lstrcpy(szTemp, TEXT("cmstp.exe /u \"")); lstrcat(szTemp, szInfFile); lstrcat(szTemp, TEXT("\"")); nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Delete\\Command"), szGUID); MYDBGASSERT(CELEMS(szSubKey) > nNumChars); bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szTemp); // // Remove the Add/Remove Programs entry, making sure to leave the uninstall dir // value. // nNumChars = (UINT)wsprintf(szSubKey, TEXT("%s\\%s"), c_pszRegUninstall, FileParts.m_FileName); MYDBGASSERT(CELEMS(szSubKey) > nNumChars); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_ALL_ACCESS, &hKey)) { RegDeleteValue(hKey, TEXT("UninstallString")); RegDeleteValue(hKey, TEXT("DisplayName")); RegCloseKey(hKey); } // // Change the attributes to not allow rename // nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\ShellFolder"), szGUID); MYDBGASSERT(CELEMS(szSubKey) > nNumChars); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szSubKey, 0, KEY_ALL_ACCESS, &hKey)) { DWORD dwZero = 0; bReturn &= (ERROR_SUCCESS == RegSetValueEx(hKey, TEXT("Attributes"), 0, REG_DWORD, (BYTE*)&dwZero, sizeof(DWORD))); //lint !e514 this is desired behavior MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey)); } else { bReturn = FALSE; } } else { bReturn = FALSE; } return bReturn; } //+---------------------------------------------------------------------------- // // Function: UpdateProfileDesktopIconsOnNT5 // // Synopsis: This function is meant to be called in an upgrade scenario of NT5. // Thus if the user has Connection Manager installed on a legacy platform // and then upgrades to NT5, this code would be called. Basically the code // removes the users existing Desktop GUID and replaces it with a Desktop // icon that is a shortcut to the connection object in the connections folder. // This code assumes the new NT5 pbk entry is written and that the connections folder // is uptodate. // // Arguments: LPTSTR szCmpFilePath - path to the cmp file for the profile // LPTSTR szLongServiceName - Long Service Name of the profile // // Returns: BOOL - TRUE if the profile is successfully updated // // History: quintinb Created Header 5/5/98 // //+---------------------------------------------------------------------------- BOOL UpdateProfileDesktopIconsOnNT5(HINSTANCE hInstance, LPCTSTR szCmpFilePath, LPCTSTR szLongServiceName) { TCHAR szInfFile[MAX_PATH+1]; TCHAR szGUID[MAX_PATH+1]; TCHAR szTemp[MAX_PATH+1]; TCHAR szSubKey[MAX_PATH+1]; BOOL bReturn = TRUE; HKEY hKey; HRESULT hr; UINT nNumChars; // // Now split the path // CFileNameParts FileParts(szCmpFilePath); // // Now construct the path to the 1.2 inf file location // nNumChars = (UINT)wsprintf(szInfFile, TEXT("%s%s%s\\%s%s"), FileParts.m_Drive, FileParts.m_Dir, FileParts.m_FileName, FileParts.m_FileName, TEXT(".inf")); MYDBGASSERT(nNumChars < CELEMS(szInfFile)); if (!FileExists(szInfFile)) { // // Now construct the path to the INF file (1.0 and 1.1 profiles kept the infs in // the system dir) // MYVERIFY(0 != GetSystemDirectory(szTemp, MAX_PATH)); nNumChars = (UINT)wsprintf(szInfFile, TEXT("%s\\%s%s"), szTemp, FileParts.m_FileName, TEXT(".inf")); MYDBGASSERT(nNumChars < CELEMS(szInfFile)); if (!FileExists(szInfFile)) { return FALSE; } //else //{ // // Remove ShowIcon from the Inf File so that the user won't get an error if they // try to uninstall it. // // RemoveShowIconFromRunPostSetupCommands(szInfFile); //} } // // Get the GUID from the inf file. // ZeroMemory(szGUID, sizeof(szGUID)); MYVERIFY(0 != GetPrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid, TEXT(""), szGUID, MAX_PATH, szInfFile)); if (0 != szGUID[0]) { // // Delete the Explorer\Desktop entry // nNumChars = (UINT)wsprintf(szSubKey, TEXT("%s\\%s"), c_pszRegNameSpace, szGUID); if (CELEMS(szSubKey) > nNumChars) { hr = HrRegDeleteKeyTree (HKEY_LOCAL_MACHINE, szSubKey); bReturn &= SUCCEEDED(hr); //lint !e514 intended use, quintinb } // // Delete the GUID // nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s"), szGUID); if (CELEMS(szSubKey) > nNumChars) { hr = HrRegDeleteKeyTree (HKEY_CLASSES_ROOT, szSubKey); bReturn &= SUCCEEDED(hr);//lint !e514 intended use, quintinb } // // Delete the uninstall strings // nNumChars = (UINT)wsprintf(szSubKey, TEXT("%s\\%s"), c_pszRegUninstall, FileParts.m_FileName); if (CELEMS(szSubKey) > nNumChars) { if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_ALL_ACCESS, &hKey)) { // // Leave the UninstallDir value but delete the other two. We still use // UninstallDir to know where to uninstall from. // bReturn &= (ERROR_SUCCESS == RegDeleteValue(hKey, TEXT("DisplayName"))); //lint !e514 intended use, quintinb bReturn &= (ERROR_SUCCESS ==RegDeleteValue(hKey, TEXT("UninstallString"))); //lint !e514 intended use, quintinb (VOID)RegCloseKey(hKey); hKey = NULL; } } // // Construct the InstallDir path to get the phonebook path to // pass to CreateShortcut // szTemp[0] = TEXT('\0'); if (GetAllUsersCmDir(szTemp, hInstance)) { LPTSTR pszPhoneBook = NULL; // // Assuming that legacy platform was All-Users thus we use TRUE // if (GetPhoneBookPath(szTemp, &pszPhoneBook, TRUE)) { // // Create a desktop shortcut // DeleteNT5ShortcutFromPathAndName(hInstance, szLongServiceName, CSIDL_COMMON_DESKTOPDIRECTORY); hr = CreateNT5ProfileShortcut(szLongServiceName, pszPhoneBook, TRUE); // bAllUsers == TRUE bReturn &= SUCCEEDED(hr); //lint !e514 intended use, quintinb } CmFree(pszPhoneBook); } } return bReturn; } //+---------------------------------------------------------------------------- // // Function: RemoveOldCmInstalls // // Synopsis: This function tries to remove old Connection Manager installs by // using the instcm.inf file. // // Arguments: LPTSTR szCmpFile - Path to a cmp file (gives the directory of // the CM install to delete) // // Returns: BOOL - returns TRUE if instcm.inf was successfully launched or // if the cmp was in winsys, in which case we don't want to // launch. // // History: quintinb Created Header 5/5/98 // //+---------------------------------------------------------------------------- BOOL RemoveOldCmInstalls(HINSTANCE hInstance, LPCTSTR szCmpFile, LPCTSTR szCurrentDir) { TCHAR szDest[MAX_PATH+1]; TCHAR szSource[MAX_PATH+1]; TCHAR szCmDir[MAX_PATH+1]; TCHAR szSystemDir[MAX_PATH+1]; TCHAR szTemp[MAX_PATH+1]; UINT nNumChars; BOOL bReturn = FALSE; HKEY hKey; // // Check the input // if ((szCmpFile == NULL) || (TEXT('\0') == szCmpFile[0])) { return FALSE; } // // Next make a copy of instcm.inf // const TCHAR* const c_pszInstCmInfFmt = TEXT("%sinstcm.inf"); const TCHAR* const c_pszRemoveCmInfFmt = TEXT("%sremovecm.inf"); if (0 == GetSystemDirectory(szSystemDir, MAX_PATH)) { return FALSE; } lstrcat(szSystemDir, TEXT("\\")); nNumChars = (UINT)wsprintf(szSource, c_pszInstCmInfFmt, szSystemDir); MYDBGASSERT(CELEMS(szSource) > nNumChars); nNumChars = (UINT)wsprintf(szDest, c_pszRemoveCmInfFmt, szSystemDir); MYDBGASSERT(CELEMS(szDest) > nNumChars); if (!FileExists(szSource)) { // // We probably haven't installed instcm.inf yet, check in the current dir. // nNumChars = (UINT)wsprintf(szSource, c_pszInstCmInfFmt, szCurrentDir); MYDBGASSERT(CELEMS(szSource) > nNumChars); nNumChars = (UINT)wsprintf(szDest, c_pszRemoveCmInfFmt, szCurrentDir); MYDBGASSERT(CELEMS(szDest) > nNumChars); } if (CopyFile(szSource, szDest, FALSE)) { // // Now construct the directory that the old cm bits could be in. // CFileNameParts FileParts(szCmpFile); nNumChars = (UINT)wsprintf(szCmDir, TEXT("%s%s"), FileParts.m_Drive, FileParts.m_Dir); MYDBGASSERT(CELEMS(szCmDir) > nNumChars); // // Make sure that we are not uninstalling CM from system32 (the new 1.2 location) // if (0 == lstrcmpi(szSystemDir, szCmDir)) { // // Then the cmp file is in winsys, so don't remove the new cm bits // return TRUE; } // Next put the path to the CM bits in the OldPath Value of the CMMGR32.EXE // App Paths Key lstrcpyn(szTemp, c_pszRegCmAppPaths, CELEMS(szTemp)); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTemp, 0, KEY_ALL_ACCESS, &hKey)) { if (ERROR_SUCCESS == RegSetValueEx(hKey, TEXT("OldPath"), 0, REG_SZ, (BYTE*)szCmDir, (lstrlen(szCmDir) + sizeof(TCHAR)))) // must include size of NULL char { // // Finally launch the inf file to uninstall CM // TCHAR szTitle[MAX_PATH+1] = {TEXT("")}; MYVERIFY(0 != LoadString(hInstance, IDS_CMSTP_TITLE, szTitle, MAX_PATH)); MYDBGASSERT(TEXT('\0') != szTitle[0]); MYVERIFY(SUCCEEDED(LaunchInfSection(szDest, TEXT("Remove"), szTitle, TRUE))); // bQuiet = TRUE RegDeleteValue(hKey, TEXT("OldPath")); //lint !e534 if CM app path is removed so is this bReturn = TRUE; } MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey)); } } return bReturn; } //+---------------------------------------------------------------------------- // // Function: MigratePhonebookEntry // // Synopsis: This function migrates an old phonebook entry to the new // // Arguments: HINSTANCE hInstance - Module instance handle so that resources can be accessed // LPCTSTR pszCmpFile - full path to the cmp file // LPCTSTR pszLongServiceName - Long service name of the profile // // Returns: BOOL - returns TRUE on success // // History: quintinb Created for NTRAID 227444 9/30/98 // quintinb modified to delete from ras\rasphone.pbk // as well on NT5 (NTRAID 280738) 2/1/99 // //+---------------------------------------------------------------------------- BOOL MigratePhonebookEntry(HINSTANCE hInstance, LPCTSTR pszCmpFile, LPCTSTR pszLongServiceName) { TCHAR szCmsFile[MAX_PATH+1]={0}; TCHAR szInstallDir[MAX_PATH+1]={0}; TCHAR szTemp[MAX_PATH+1]={0}; LPTSTR pszPhonebook = NULL; CPlatform plat; // // First try to delete the phonebook entry from the old phonebook location, // namely %windir%\system32\ras\rasphone.pbk // if (plat.IsAtLeastNT5() && GetSystemDirectory(szTemp, CELEMS(szTemp))) { pszPhonebook = (LPTSTR)CmMalloc(1 + lstrlen(c_pszRasDirRas) + lstrlen(c_pszRasPhonePbk) + lstrlen (szTemp)); if (NULL != pszPhonebook) { wsprintf(pszPhonebook, TEXT("%s%s%s"), szTemp, c_pszRasDirRas, c_pszRasPhonePbk); CMTRACE2(TEXT("MigratePhonebookEntry -- Calling RemovePhonebookEntry on %s in phone book %s"), pszLongServiceName, MYDBGSTR(pszPhonebook)); RemovePhonebookEntry(pszLongServiceName, pszPhonebook, TRUE); CmFree(pszPhonebook); } } // // Next try to delete the phonebook entry from the new location, namely // C:\Documents and Settings\All Users\Application Data\Microsoft\Network\Connections\PBK\rasphone.pbk // if (!GetAllUsersCmDir(szInstallDir, hInstance)) { return FALSE; } // // Construct the cms file // CFileNameParts CmpFileParts(pszCmpFile); MYVERIFY(CELEMS(szCmsFile) > (UINT)wsprintf(szCmsFile, TEXT("%s%s\\%s.cms"), szInstallDir, CmpFileParts.m_FileName, CmpFileParts.m_FileName)); // // Get the new phonebook path. // Assuming that legacy platform was All-Users thus we use TRUE // if (!GetPhoneBookPath(szInstallDir, &pszPhonebook, TRUE)) { return FALSE; } CMTRACE2(TEXT("MigratePhonebookEntry -- Calling RemovePhonebookEntry on %s in phone book %s"), pszLongServiceName, MYDBGSTR(pszPhonebook)); MYVERIFY(FALSE != RemovePhonebookEntry(pszLongServiceName, pszPhonebook, TRUE)); // // Finally write the new pbk entry. // BOOL bReturn = WriteCmPhonebookEntry(pszLongServiceName, pszPhonebook, szCmsFile); CmFree(pszPhonebook); return bReturn; } //+---------------------------------------------------------------------------- // // Function: MigrateOldCmProfileForProfileInstall // // Synopsis: This function is used to migrate Old cm profiles when a 1.2 profile // is installed. This ensures that old profiles will still work but // that already migrated profiles won't be migrated over and over again. // This function should only be called when a 1.2 profile is installed // and not on OS migration, call MigrateCmProfilesForWin2kUpgrade for // that. Migration of the profile consists of deleting the old connectoids // and creating new style connectoids. Ensuring that the desktop guid // is up to date or is replaced by a shortcut on NT5. It also removes // old installs of CM as neccessary. // // Arguments: HINSTANCE hInstance - Instance handle to load resources as necessary // // Returns: HRESULT -- Standard COM Error Codes // // History: quintinb Created 11/18/98 // //+---------------------------------------------------------------------------- HRESULT MigrateOldCmProfilesForProfileInstall(HINSTANCE hInstance, LPCTSTR szCurrentDir) { HKEY hKey; DWORD dwValueSize; DWORD dwType; DWORD dwDataSize; TCHAR szCurrentValue[MAX_PATH+1]; TCHAR szCurrentData[MAX_PATH+1]; BOOL bReturn = TRUE; CPlatform plat; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0, KEY_ALL_ACCESS, &hKey)) { DWORD dwIndex = 0; dwValueSize = MAX_PATH; dwDataSize = MAX_PATH; while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szCurrentValue, &dwValueSize, NULL, &dwType, (LPBYTE)szCurrentData, &dwDataSize)) { if (REG_SZ == dwType) { MYDBGASSERT(0 != szCurrentValue[0]); MYDBGASSERT(0 != szCurrentData[0]); if (ProfileNeedsMigration(szCurrentValue, szCurrentData)) { // // Update the phonebook entries // bReturn &= MigratePhonebookEntry(hInstance, szCurrentData, szCurrentValue); if (plat.IsAtLeastNT5()) { // // when we are moving a machine to NT5 we need to remove the profiles // old pbk entries and create new ones. Then we need to remove the // profile GUIDS and replace them with desktop shortcuts. // bReturn &= UpdateProfileDesktopIconsOnNT5(hInstance, szCurrentData, szCurrentValue); } else { // // Fix up the users desktop GUIDs so they work with the new // command line format. // bReturn &= UpdateProfileLegacyGUIDs(szCurrentData); } // // Always try to remove old CM installs // bReturn &= RemoveOldCmInstalls(hInstance, szCurrentData, szCurrentDir); } } dwValueSize = MAX_PATH; dwDataSize = MAX_PATH; dwIndex++; } MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey)); } else { CMTRACE(TEXT("No CM mappings key to migrate.")); } RefreshDesktop(); return (bReturn ? S_OK : E_FAIL); } //+---------------------------------------------------------------------------- // // Function: MigrateCmProfilesForWin2kUpgrade // // Synopsis: // // This function opens the HKLM Mappings key and enumerates all the profiles that are // listed there. This function is used when a legacy machine is upgraded to Win2K and // CM is installed. In this case we have 1.0/1.1/1.2 profiles that need to be migrated to use // the NT5 connections folder. Thus they need to have their connectoids upgraded to the new // NT 5 style and they need to have their Desktop Guids replaced by shortcuts to the connections // folder. We should always attempt to remove any old installations of connection manager // that are discovered in the old cmp directories. // // Arguments: hInstance - Instance handle for string resources // // Returns: HRESULT -- Standard COM Error codes // // History: quintinb created 5/2/98 // //+---------------------------------------------------------------------------- HRESULT MigrateCmProfilesForWin2kUpgrade(HINSTANCE hInstance) { HKEY hKey; DWORD dwValueSize; DWORD dwType; DWORD dwDataSize; TCHAR szCurrentDir[MAX_PATH+1]; TCHAR szCurrentValue[MAX_PATH+1]; TCHAR szCurrentData[MAX_PATH+1]; CPlatform plat; if (0 == GetCurrentDirectory(MAX_PATH, szCurrentDir)) { return E_FAIL; } lstrcat(szCurrentDir, TEXT("\\")); if (!(plat.IsAtLeastNT5())) { CMASSERTMSG(FALSE, TEXT("MigrateCmProfilesForWin2kUpgrade - This function is supposed to be NT5 only")); return E_FAIL; } if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0, KEY_ALL_ACCESS, &hKey)) { DWORD dwIndex = 0; dwValueSize = MAX_PATH; dwDataSize = MAX_PATH; while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szCurrentValue, &dwValueSize, NULL, &dwType, (LPBYTE)szCurrentData, &dwDataSize)) { if (REG_SZ == dwType) { MYDBGASSERT(0 != szCurrentValue[0]); MYDBGASSERT(0 != szCurrentData[0]); // // Update the phonebook entries // BOOL bReturn = MigratePhonebookEntry(hInstance, szCurrentData, szCurrentValue); if (!bReturn) { CMTRACE2(TEXT("MigrateCmProfilesForWin2kUpgrade -- MigratePhonebookEntry for profile %s failed. Cmp path is %s"), szCurrentValue, szCurrentData); } // // when we are moving a machine to NT5 we need to remove the profiles // old pbk entries and create new ones. Then we need to remove the // profile GUIDS and replace them with desktop shortcuts. // bReturn = UpdateProfileDesktopIconsOnNT5(hInstance, szCurrentData, szCurrentValue); if (!bReturn) { CMTRACE2(TEXT("MigrateCmProfilesForWin2kUpgrade -- UpdateProfileDesktopIconsOnNT5 for profile %s failed. Cmp path is %s"), szCurrentValue, szCurrentData); } // // Always try to remove old CM installs // bReturn = RemoveOldCmInstalls(hInstance, szCurrentData, szCurrentDir); if (!bReturn) { CMTRACE2(TEXT("MigrateCmProfilesForWin2kUpgrade -- RemoveOldCmInstalls for profile %s failed. Cmp path is %s"), szCurrentValue, szCurrentData); } } dwValueSize = MAX_PATH; dwDataSize = MAX_PATH; dwIndex++; } MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey)); } else { CMTRACE(TEXT("No CM mappings key to migrate.")); } RefreshDesktop(); static const TCHAR c_ValueString[] = TEXT("Connection Manager Profiles Upgrade"); LONG lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), 0, KEY_SET_VALUE, &hKey); HRESULT hr = HRESULT_FROM_WIN32 (lr); if (SUCCEEDED(hr)) { RegDeleteValue(hKey, c_ValueString); //lint !e534 this value may not exist MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey)); } return S_OK; }