Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

875 lines
29 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: migrate.cpp
  4. //
  5. // Module: CMSTP.EXE
  6. //
  7. // Synopsis: This source file contains most of the code necessary for
  8. // the migration of CM profiles. This code handles both migrating
  9. // a user when a CM1.2 profile is installed on a machine with
  10. // existing 1.0 profiles and if the user upgrades their OS to NT5.
  11. //
  12. // Copyright (c) 1997-1999 Microsoft Corporation
  13. //
  14. // Author: quintinb Created 07/14/98
  15. //
  16. //+----------------------------------------------------------------------------
  17. #include "cmmaster.h"
  18. //
  19. // For ProfileNeedsMigration
  20. //
  21. #include "needsmig.cpp"
  22. //+----------------------------------------------------------------------------
  23. //
  24. // Function: CreateRegAndValue
  25. //
  26. // Synopsis: This function is a wrapper to Create a Reg Key and then add a defualt
  27. // value to that same key.
  28. //
  29. // Arguments: HKEY hBaseKey - Relative starting point for the new subkey
  30. // LPTSTR szSubKey - SubKey path
  31. // LPTSTR szValue - String to put in the Keys default value.
  32. //
  33. // Returns: BOOL - TRUE if the key and value were successfully created
  34. //
  35. // History: quintinb Created Header 5/5/98
  36. //
  37. //+----------------------------------------------------------------------------
  38. BOOL CreateRegAndValue(HKEY hBaseKey, LPCTSTR szSubKey, LPCTSTR szValue)
  39. {
  40. DWORD dwDisp;
  41. BOOL bReturn = FALSE;
  42. HKEY hKey;
  43. if (ERROR_SUCCESS == RegCreateKeyEx(hBaseKey, szSubKey, 0, NULL,
  44. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisp))
  45. {
  46. bReturn = (ERROR_SUCCESS == RegSetValueEx(hKey, NULL, 0, REG_SZ,
  47. (BYTE*)szValue, (lstrlen(szValue)+1)));
  48. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  49. }
  50. return bReturn;
  51. }
  52. // Note: I added this function because I needed to get the following CFileNameParts
  53. // off the stack of UpdateProfileLegacyGUIDs so that I didn't need a
  54. // stack checking function. Not the greatest workaround but it sufficed.
  55. BOOL IsDefaultIcon(LPCTSTR szIconPath)
  56. {
  57. BOOL bReturn = TRUE;
  58. CFileNameParts IconPath(szIconPath);
  59. if (0 != lstrcmpi(IconPath.m_FileName, TEXT("cmmgr32")))
  60. {
  61. //
  62. // Then the icon path is something else besides cmmgr32.exe, we must not
  63. // update it.
  64. //
  65. bReturn = FALSE;
  66. }
  67. return bReturn;
  68. }
  69. //+----------------------------------------------------------------------------
  70. //
  71. // Function: UpdateProfileLegacyGUIDs
  72. //
  73. // Synopsis: This function upgrades GUIDs on a Legacy OS install to make sure
  74. // that older profile still function. This is necessary because CM
  75. // 1.0/1.1 profiles expected the CM bits to be in the same directory as
  76. // the cmp file. Thus only the cmp filename was given. In CM 1.2 we need
  77. // the full path to the CMP file since the cm bits are now located in
  78. // system32. The GUIDs are also updated to have a delete option and
  79. // the attributes were changed to not allow renaming.
  80. //
  81. // Arguments: LPTSTR szCmpFile - Full path to the cmp file of the profile to update
  82. //
  83. // Returns: BOOL - returns TRUE if the profile was successfully updated
  84. //
  85. // History: quintinb Created Header 5/5/98
  86. //
  87. //+----------------------------------------------------------------------------
  88. BOOL UpdateProfileLegacyGUIDs(LPCTSTR szCmpFile)
  89. {
  90. TCHAR szInfFile[MAX_PATH+1];
  91. TCHAR szGUID[MAX_PATH+1];
  92. TCHAR szTemp[MAX_PATH+1];
  93. TCHAR szSubKey[MAX_PATH+1];
  94. TCHAR szCommandStr[2*MAX_PATH+1];
  95. BOOL bReturn = TRUE;
  96. HKEY hKey;
  97. UINT nNumChars;
  98. MYDBGASSERT(NULL != szCmpFile);
  99. MYDBGASSERT(TEXT('\0') != szCmpFile[0]);
  100. //
  101. // Now split the path
  102. //
  103. CFileNameParts FileParts(szCmpFile);
  104. //
  105. // Now construct the path to the INF file (1.0 and 1.1 profiles kept the infs in
  106. // the system dir)
  107. //
  108. MYVERIFY(0 != GetSystemDirectory(szTemp, MAX_PATH));
  109. nNumChars = (UINT)wsprintf(szInfFile, TEXT("%s\\%s%s"), szTemp, FileParts.m_FileName, TEXT(".inf"));
  110. MYDBGASSERT(CELEMS(szInfFile) > nNumChars);
  111. //
  112. // Get the GUID from the inf file.
  113. //
  114. ZeroMemory(szGUID, sizeof(szGUID));
  115. GetPrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid, TEXT(""), szGUID,
  116. MAX_PATH, szInfFile);
  117. if (0 != szGUID[0])
  118. {
  119. //
  120. // Update the DefaultIcon Value if it points to cmmgr32.exe
  121. //
  122. BOOL bUpdateIconPath = TRUE;
  123. nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\DefaultIcon"), szGUID);
  124. MYDBGASSERT(CELEMS(szSubKey) > nNumChars);
  125. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szSubKey, 0, KEY_READ | KEY_WRITE, &hKey))
  126. {
  127. DWORD dwSize = CELEMS(szTemp);
  128. DWORD dwType = REG_SZ;
  129. if (ERROR_SUCCESS == RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)szTemp, &dwSize))
  130. {
  131. bUpdateIconPath = IsDefaultIcon(szTemp);
  132. }
  133. RegCloseKey(hKey);
  134. }
  135. if (bUpdateIconPath)
  136. {
  137. if (GetSystemDirectory(szTemp, CELEMS(szTemp)))
  138. {
  139. nNumChars = (UINT)wsprintf(szCommandStr, TEXT("%s\\cmmgr32.exe,0"), szTemp);
  140. MYDBGASSERT(CELEMS(szCommandStr) > nNumChars);
  141. bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr);
  142. }
  143. }
  144. //
  145. // Update Settings to Properties on the desktop icon menu
  146. //
  147. nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Settings..."), szGUID);
  148. MYDBGASSERT(CELEMS(szSubKey) > nNumChars);
  149. nNumChars = (UINT)wsprintf(szCommandStr, TEXT("P&roperties"));
  150. MYDBGASSERT(CELEMS(szCommandStr) > nNumChars);
  151. bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr);
  152. //
  153. // Now change the underlying command to give the full
  154. // path to the cmp file.
  155. //
  156. nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Settings...\\Command"), szGUID);
  157. MYDBGASSERT(CELEMS(szSubKey) > nNumChars);
  158. nNumChars = (UINT)wsprintf(szCommandStr, TEXT("cmmgr32.exe /settings \"%s\""), szCmpFile);
  159. MYDBGASSERT(CELEMS(szCommandStr) > nNumChars);
  160. bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr);
  161. //
  162. // Update Open to Connect on the desktop icon menu
  163. //
  164. nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Open"), szGUID);
  165. MYDBGASSERT(CELEMS(szSubKey) > nNumChars);
  166. nNumChars = (UINT)wsprintf(szCommandStr, TEXT("C&onnect"));
  167. MYDBGASSERT(CELEMS(szCommandStr) > nNumChars);
  168. bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr);
  169. //
  170. // Now change the underlying command string to use the full path to the cmp file.
  171. //
  172. nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Open\\Command"), szGUID);
  173. MYDBGASSERT(CELEMS(szSubKey) > nNumChars);
  174. nNumChars = (UINT)wsprintf(szCommandStr, TEXT("cmmgr32.exe \"%s\""), szCmpFile);
  175. MYDBGASSERT(CELEMS(szCommandStr) > nNumChars);
  176. bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr);
  177. //
  178. // Remove the showicon command from the inf.
  179. //
  180. // RemoveShowIconFromRunPostSetupCommands(szInfFile);
  181. //
  182. // Add the delete menu option
  183. //
  184. nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Delete"), szGUID);
  185. MYDBGASSERT(CELEMS(szSubKey) > nNumChars);
  186. nNumChars = (UINT)wsprintf(szCommandStr, TEXT("&Delete"));
  187. MYDBGASSERT(CELEMS(szSubKey) > nNumChars);
  188. bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szCommandStr);
  189. //
  190. // Create the uninstall command
  191. //
  192. lstrcpy(szTemp, TEXT("cmstp.exe /u \""));
  193. lstrcat(szTemp, szInfFile);
  194. lstrcat(szTemp, TEXT("\""));
  195. nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\Shell\\Delete\\Command"), szGUID);
  196. MYDBGASSERT(CELEMS(szSubKey) > nNumChars);
  197. bReturn &= CreateRegAndValue(HKEY_CLASSES_ROOT, szSubKey, szTemp);
  198. //
  199. // Remove the Add/Remove Programs entry, making sure to leave the uninstall dir
  200. // value.
  201. //
  202. nNumChars = (UINT)wsprintf(szSubKey, TEXT("%s\\%s"), c_pszRegUninstall,
  203. FileParts.m_FileName);
  204. MYDBGASSERT(CELEMS(szSubKey) > nNumChars);
  205. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  206. szSubKey, 0, KEY_ALL_ACCESS, &hKey))
  207. {
  208. RegDeleteValue(hKey, TEXT("UninstallString"));
  209. RegDeleteValue(hKey, TEXT("DisplayName"));
  210. RegCloseKey(hKey);
  211. }
  212. //
  213. // Change the attributes to not allow rename
  214. //
  215. nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s\\ShellFolder"), szGUID);
  216. MYDBGASSERT(CELEMS(szSubKey) > nNumChars);
  217. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT,
  218. szSubKey, 0, KEY_ALL_ACCESS, &hKey))
  219. {
  220. DWORD dwZero = 0;
  221. bReturn &= (ERROR_SUCCESS == RegSetValueEx(hKey, TEXT("Attributes"),
  222. 0, REG_DWORD, (BYTE*)&dwZero, sizeof(DWORD))); //lint !e514 this is desired behavior
  223. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  224. }
  225. else
  226. {
  227. bReturn = FALSE;
  228. }
  229. }
  230. else
  231. {
  232. bReturn = FALSE;
  233. }
  234. return bReturn;
  235. }
  236. //+----------------------------------------------------------------------------
  237. //
  238. // Function: UpdateProfileDesktopIconsOnNT5
  239. //
  240. // Synopsis: This function is meant to be called in an upgrade scenario of NT5.
  241. // Thus if the user has Connection Manager installed on a legacy platform
  242. // and then upgrades to NT5, this code would be called. Basically the code
  243. // removes the users existing Desktop GUID and replaces it with a Desktop
  244. // icon that is a shortcut to the connection object in the connections folder.
  245. // This code assumes the new NT5 pbk entry is written and that the connections folder
  246. // is uptodate.
  247. //
  248. // Arguments: LPTSTR szCmpFilePath - path to the cmp file for the profile
  249. // LPTSTR szLongServiceName - Long Service Name of the profile
  250. //
  251. // Returns: BOOL - TRUE if the profile is successfully updated
  252. //
  253. // History: quintinb Created Header 5/5/98
  254. //
  255. //+----------------------------------------------------------------------------
  256. BOOL UpdateProfileDesktopIconsOnNT5(HINSTANCE hInstance, LPCTSTR szCmpFilePath, LPCTSTR szLongServiceName)
  257. {
  258. TCHAR szInfFile[MAX_PATH+1];
  259. TCHAR szGUID[MAX_PATH+1];
  260. TCHAR szTemp[MAX_PATH+1];
  261. TCHAR szSubKey[MAX_PATH+1];
  262. BOOL bReturn = TRUE;
  263. HKEY hKey;
  264. HRESULT hr;
  265. UINT nNumChars;
  266. //
  267. // Now split the path
  268. //
  269. CFileNameParts FileParts(szCmpFilePath);
  270. //
  271. // Now construct the path to the 1.2 inf file location
  272. //
  273. nNumChars = (UINT)wsprintf(szInfFile, TEXT("%s%s%s\\%s%s"), FileParts.m_Drive,
  274. FileParts.m_Dir, FileParts.m_FileName, FileParts.m_FileName, TEXT(".inf"));
  275. MYDBGASSERT(nNumChars < CELEMS(szInfFile));
  276. if (!FileExists(szInfFile))
  277. {
  278. //
  279. // Now construct the path to the INF file (1.0 and 1.1 profiles kept the infs in
  280. // the system dir)
  281. //
  282. MYVERIFY(0 != GetSystemDirectory(szTemp, MAX_PATH));
  283. nNumChars = (UINT)wsprintf(szInfFile, TEXT("%s\\%s%s"), szTemp, FileParts.m_FileName, TEXT(".inf"));
  284. MYDBGASSERT(nNumChars < CELEMS(szInfFile));
  285. if (!FileExists(szInfFile))
  286. {
  287. return FALSE;
  288. }
  289. //else
  290. //{
  291. //
  292. // Remove ShowIcon from the Inf File so that the user won't get an error if they
  293. // try to uninstall it.
  294. //
  295. // RemoveShowIconFromRunPostSetupCommands(szInfFile);
  296. //}
  297. }
  298. //
  299. // Get the GUID from the inf file.
  300. //
  301. ZeroMemory(szGUID, sizeof(szGUID));
  302. MYVERIFY(0 != GetPrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid, TEXT(""), szGUID,
  303. MAX_PATH, szInfFile));
  304. if (0 != szGUID[0])
  305. {
  306. //
  307. // Delete the Explorer\Desktop entry
  308. //
  309. nNumChars = (UINT)wsprintf(szSubKey, TEXT("%s\\%s"), c_pszRegNameSpace, szGUID);
  310. if (CELEMS(szSubKey) > nNumChars)
  311. {
  312. hr = HrRegDeleteKeyTree (HKEY_LOCAL_MACHINE, szSubKey);
  313. bReturn &= SUCCEEDED(hr); //lint !e514 intended use, quintinb
  314. }
  315. //
  316. // Delete the GUID
  317. //
  318. nNumChars = (UINT)wsprintf(szSubKey, TEXT("CLSID\\%s"), szGUID);
  319. if (CELEMS(szSubKey) > nNumChars)
  320. {
  321. hr = HrRegDeleteKeyTree (HKEY_CLASSES_ROOT, szSubKey);
  322. bReturn &= SUCCEEDED(hr);//lint !e514 intended use, quintinb
  323. }
  324. //
  325. // Delete the uninstall strings
  326. //
  327. nNumChars = (UINT)wsprintf(szSubKey, TEXT("%s\\%s"), c_pszRegUninstall, FileParts.m_FileName);
  328. if (CELEMS(szSubKey) > nNumChars)
  329. {
  330. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  331. szSubKey, 0, KEY_ALL_ACCESS, &hKey))
  332. {
  333. //
  334. // Leave the UninstallDir value but delete the other two. We still use
  335. // UninstallDir to know where to uninstall from.
  336. //
  337. bReturn &= (ERROR_SUCCESS == RegDeleteValue(hKey,
  338. TEXT("DisplayName"))); //lint !e514 intended use, quintinb
  339. bReturn &= (ERROR_SUCCESS ==RegDeleteValue(hKey,
  340. TEXT("UninstallString"))); //lint !e514 intended use, quintinb
  341. }
  342. }
  343. //
  344. // Construct the InstallDir path to get the phonebook path to
  345. // pass to CreateShortcut
  346. //
  347. szTemp[0] = TEXT('\0');
  348. if (GetAllUsersCmDir(szTemp, hInstance))
  349. {
  350. LPTSTR pszPhoneBook = NULL;
  351. //
  352. // Assuming that legacy platform was All-Users thus we use TRUE
  353. //
  354. if (GetPhoneBookPath(szTemp, &pszPhoneBook, TRUE))
  355. {
  356. //
  357. // Create a desktop shortcut
  358. //
  359. DeleteNT5ShortcutFromPathAndName(hInstance, szLongServiceName, CSIDL_COMMON_DESKTOPDIRECTORY);
  360. hr = CreateNT5ProfileShortcut(szLongServiceName, pszPhoneBook, TRUE); // bAllUsers == TRUE
  361. bReturn &= SUCCEEDED(hr); //lint !e514 intended use, quintinb
  362. }
  363. CmFree(pszPhoneBook);
  364. }
  365. }
  366. return bReturn;
  367. }
  368. //+----------------------------------------------------------------------------
  369. //
  370. // Function: RemoveOldCmInstalls
  371. //
  372. // Synopsis: This function tries to remove old Connection Manager installs by
  373. // using the instcm.inf file.
  374. //
  375. // Arguments: LPTSTR szCmpFile - Path to a cmp file (gives the directory of
  376. // the CM install to delete)
  377. //
  378. // Returns: BOOL - returns TRUE if instcm.inf was successfully launched or
  379. // if the cmp was in winsys, in which case we don't want to
  380. // launch.
  381. //
  382. // History: quintinb Created Header 5/5/98
  383. //
  384. //+----------------------------------------------------------------------------
  385. BOOL RemoveOldCmInstalls(HINSTANCE hInstance, LPCTSTR szCmpFile, LPCTSTR szCurrentDir)
  386. {
  387. TCHAR szDest[MAX_PATH+1];
  388. TCHAR szSource[MAX_PATH+1];
  389. TCHAR szCmDir[MAX_PATH+1];
  390. TCHAR szSystemDir[MAX_PATH+1];
  391. TCHAR szTemp[MAX_PATH+1];
  392. UINT nNumChars;
  393. BOOL bReturn = FALSE;
  394. HKEY hKey;
  395. //
  396. // Check the input
  397. //
  398. if ((szCmpFile == NULL) || (TEXT('\0') == szCmpFile[0]))
  399. {
  400. return FALSE;
  401. }
  402. //
  403. // Next make a copy of instcm.inf
  404. //
  405. const TCHAR* const c_pszInstCmInfFmt = TEXT("%sinstcm.inf");
  406. const TCHAR* const c_pszRemoveCmInfFmt = TEXT("%sremovecm.inf");
  407. if (0 == GetSystemDirectory(szSystemDir, MAX_PATH))
  408. {
  409. return FALSE;
  410. }
  411. lstrcat(szSystemDir, TEXT("\\"));
  412. nNumChars = (UINT)wsprintf(szSource, c_pszInstCmInfFmt, szSystemDir);
  413. MYDBGASSERT(CELEMS(szSource) > nNumChars);
  414. nNumChars = (UINT)wsprintf(szDest, c_pszRemoveCmInfFmt, szSystemDir);
  415. MYDBGASSERT(CELEMS(szDest) > nNumChars);
  416. if (!FileExists(szSource))
  417. {
  418. //
  419. // We probably haven't installed instcm.inf yet, check in the current dir.
  420. //
  421. nNumChars = (UINT)wsprintf(szSource, c_pszInstCmInfFmt, szCurrentDir);
  422. MYDBGASSERT(CELEMS(szSource) > nNumChars);
  423. nNumChars = (UINT)wsprintf(szDest, c_pszRemoveCmInfFmt, szCurrentDir);
  424. MYDBGASSERT(CELEMS(szDest) > nNumChars);
  425. }
  426. if (CopyFile(szSource, szDest, FALSE))
  427. {
  428. //
  429. // Now construct the directory that the old cm bits could be in.
  430. //
  431. CFileNameParts FileParts(szCmpFile);
  432. nNumChars = (UINT)wsprintf(szCmDir, TEXT("%s%s"), FileParts.m_Drive, FileParts.m_Dir);
  433. MYDBGASSERT(CELEMS(szCmDir) > nNumChars);
  434. //
  435. // Make sure that we are not uninstalling CM from system32 (the new 1.2 location)
  436. //
  437. if (0 == lstrcmpi(szSystemDir, szCmDir))
  438. {
  439. //
  440. // Then the cmp file is in winsys, so don't remove the new cm bits
  441. //
  442. return TRUE;
  443. }
  444. // Next put the path to the CM bits in the OldPath Value of the CMMGR32.EXE
  445. // App Paths Key
  446. nNumChars = (UINT)wsprintf(szTemp, c_pszRegCmAppPaths);
  447. MYDBGASSERT(CELEMS(szTemp) > nNumChars);
  448. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  449. szTemp, 0, KEY_ALL_ACCESS, &hKey))
  450. {
  451. if (ERROR_SUCCESS == RegSetValueEx(hKey, TEXT("OldPath"), 0, REG_SZ,
  452. (BYTE*)szCmDir, (lstrlen(szCmDir) + sizeof(TCHAR)))) // must include size of NULL char
  453. {
  454. //
  455. // Finally launch the inf file to uninstall CM
  456. //
  457. TCHAR szTitle[MAX_PATH+1] = {TEXT("")};
  458. MYVERIFY(0 != LoadString(hInstance, IDS_CMSTP_TITLE, szTitle, MAX_PATH));
  459. MYDBGASSERT(TEXT('\0') != szTitle[0]);
  460. MYVERIFY(SUCCEEDED(LaunchInfSection(szDest, TEXT("Remove"), szTitle, TRUE))); // bQuiet = TRUE
  461. RegDeleteValue(hKey, TEXT("OldPath")); //lint !e534 if CM app path is removed so is this
  462. bReturn = TRUE;
  463. }
  464. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  465. }
  466. }
  467. return bReturn;
  468. }
  469. //+----------------------------------------------------------------------------
  470. //
  471. // Function: MigratePhonebookEntry
  472. //
  473. // Synopsis: This function migrates an old phonebook entry to the new
  474. //
  475. // Arguments: HINSTANCE hInstance - Module instance handle so that resources can be accessed
  476. // LPCTSTR pszCmpFile - full path to the cmp file
  477. // LPCTSTR pszLongServiceName - Long service name of the profile
  478. //
  479. // Returns: BOOL - returns TRUE on success
  480. //
  481. // History: quintinb Created for NTRAID 227444 9/30/98
  482. // quintinb modified to delete from ras\rasphone.pbk
  483. // as well on NT5 (NTRAID 280738) 2/1/99
  484. //
  485. //+----------------------------------------------------------------------------
  486. BOOL MigratePhonebookEntry(HINSTANCE hInstance, LPCTSTR pszCmpFile, LPCTSTR pszLongServiceName)
  487. {
  488. TCHAR szCmsFile[MAX_PATH+1];
  489. TCHAR szInstallDir[MAX_PATH+1];
  490. TCHAR szTemp[MAX_PATH+1];
  491. LPTSTR pszPhonebook = NULL;
  492. CPlatform plat;
  493. //
  494. // First try to delete the phonebook entry from the old phonebook location,
  495. // namely %windir%\system32\ras\rasphone.pbk
  496. //
  497. if (plat.IsAtLeastNT5() && GetSystemDirectory(szTemp, CELEMS(szTemp)))
  498. {
  499. pszPhonebook = (LPTSTR)CmMalloc(1 + lstrlen(c_pszRasDirRas) +
  500. lstrlen(c_pszRasPhonePbk) +
  501. lstrlen (szTemp));
  502. if (NULL != pszPhonebook)
  503. {
  504. wsprintf(pszPhonebook, TEXT("%s%s%s"), szTemp, c_pszRasDirRas, c_pszRasPhonePbk);
  505. CMTRACE2(TEXT("MigratePhonebookEntry -- Calling RemovePhonebookEntry on %s in phone book %s"), pszLongServiceName, MYDBGSTR(pszPhonebook));
  506. RemovePhonebookEntry(pszLongServiceName, pszPhonebook, TRUE);
  507. CmFree(pszPhonebook);
  508. }
  509. }
  510. //
  511. // Next try to delete the phonebook entry from the new location, namely
  512. // C:\Documents and Settings\All Users\Application Data\Microsoft\Network\Connections\PBK\rasphone.pbk
  513. //
  514. if (!GetAllUsersCmDir(szInstallDir, hInstance))
  515. {
  516. return FALSE;
  517. }
  518. //
  519. // Construct the cms file
  520. //
  521. CFileNameParts CmpFileParts(pszCmpFile);
  522. MYVERIFY(CELEMS(szCmsFile) > (UINT)wsprintf(szCmsFile, TEXT("%s%s\\%s.cms"),
  523. szInstallDir, CmpFileParts.m_FileName, CmpFileParts.m_FileName));
  524. //
  525. // Get the new phonebook path.
  526. // Assuming that legacy platform was All-Users thus we use TRUE
  527. //
  528. if (!GetPhoneBookPath(szInstallDir, &pszPhonebook, TRUE))
  529. {
  530. return FALSE;
  531. }
  532. CMTRACE2(TEXT("MigratePhonebookEntry -- Calling RemovePhonebookEntry on %s in phone book %s"), pszLongServiceName, MYDBGSTR(pszPhonebook));
  533. MYVERIFY(FALSE != RemovePhonebookEntry(pszLongServiceName, pszPhonebook, TRUE));
  534. //
  535. // Finally write the new pbk entry.
  536. //
  537. BOOL bReturn = WriteCmPhonebookEntry(pszLongServiceName, pszPhonebook, szCmsFile);
  538. CmFree(pszPhonebook);
  539. return bReturn;
  540. }
  541. //+----------------------------------------------------------------------------
  542. //
  543. // Function: MigrateOldCmProfileForProfileInstall
  544. //
  545. // Synopsis: This function is used to migrate Old cm profiles when a 1.2 profile
  546. // is installed. This ensures that old profiles will still work but
  547. // that already migrated profiles won't be migrated over and over again.
  548. // This function should only be called when a 1.2 profile is installed
  549. // and not on OS migration, call MigrateCmProfilesForWin2kUpgrade for
  550. // that. Migration of the profile consists of deleting the old connectoids
  551. // and creating new style connectoids. Ensuring that the desktop guid
  552. // is up to date or is replaced by a shortcut on NT5. It also removes
  553. // old installs of CM as neccessary.
  554. //
  555. // Arguments: HINSTANCE hInstance - Instance handle to load resources as necessary
  556. //
  557. // Returns: HRESULT -- Standard COM Error Codes
  558. //
  559. // History: quintinb Created 11/18/98
  560. //
  561. //+----------------------------------------------------------------------------
  562. HRESULT MigrateOldCmProfilesForProfileInstall(HINSTANCE hInstance, LPCTSTR szCurrentDir)
  563. {
  564. HKEY hKey;
  565. DWORD dwValueSize;
  566. DWORD dwType;
  567. DWORD dwDataSize;
  568. TCHAR szCurrentValue[MAX_PATH+1];
  569. TCHAR szCurrentData[MAX_PATH+1];
  570. BOOL bReturn = TRUE;
  571. CPlatform plat;
  572. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0, KEY_ALL_ACCESS, &hKey))
  573. {
  574. DWORD dwIndex = 0;
  575. dwValueSize = MAX_PATH;
  576. dwDataSize = MAX_PATH;
  577. while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szCurrentValue, &dwValueSize, NULL, &dwType,
  578. (LPBYTE)szCurrentData, &dwDataSize))
  579. {
  580. if (REG_SZ == dwType)
  581. {
  582. MYDBGASSERT(0 != szCurrentValue[0]);
  583. MYDBGASSERT(0 != szCurrentData[0]);
  584. if (ProfileNeedsMigration(szCurrentValue, szCurrentData))
  585. {
  586. //
  587. // Update the phonebook entries
  588. //
  589. bReturn &= MigratePhonebookEntry(hInstance, szCurrentData, szCurrentValue);
  590. if (plat.IsAtLeastNT5())
  591. {
  592. //
  593. // when we are moving a machine to NT5 we need to remove the profiles
  594. // old pbk entries and create new ones. Then we need to remove the
  595. // profile GUIDS and replace them with desktop shortcuts.
  596. //
  597. bReturn &= UpdateProfileDesktopIconsOnNT5(hInstance, szCurrentData,
  598. szCurrentValue);
  599. }
  600. else
  601. {
  602. //
  603. // Fix up the users desktop GUIDs so they work with the new
  604. // command line format.
  605. //
  606. bReturn &= UpdateProfileLegacyGUIDs(szCurrentData);
  607. }
  608. //
  609. // Always try to remove old CM installs
  610. //
  611. bReturn &= RemoveOldCmInstalls(hInstance, szCurrentData, szCurrentDir);
  612. }
  613. }
  614. dwValueSize = MAX_PATH;
  615. dwDataSize = MAX_PATH;
  616. dwIndex++;
  617. }
  618. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  619. }
  620. else
  621. {
  622. CMTRACE(TEXT("No CM mappings key to migrate."));
  623. }
  624. RefreshDesktop();
  625. return (bReturn ? S_OK : E_FAIL);
  626. }
  627. //+----------------------------------------------------------------------------
  628. //
  629. // Function: MigrateCmProfilesForWin2kUpgrade
  630. //
  631. // Synopsis:
  632. //
  633. // This function opens the HKLM Mappings key and enumerates all the profiles that are
  634. // listed there. This function is used when a legacy machine is upgraded to Win2K and
  635. // CM is installed. In this case we have 1.0/1.1/1.2 profiles that need to be migrated to use
  636. // the NT5 connections folder. Thus they need to have their connectoids upgraded to the new
  637. // NT 5 style and they need to have their Desktop Guids replaced by shortcuts to the connections
  638. // folder. We should always attempt to remove any old installations of connection manager
  639. // that are discovered in the old cmp directories.
  640. //
  641. // Arguments: hInstance - Instance handle for string resources
  642. //
  643. // Returns: HRESULT -- Standard COM Error codes
  644. //
  645. // History: quintinb created 5/2/98
  646. //
  647. //+----------------------------------------------------------------------------
  648. HRESULT MigrateCmProfilesForWin2kUpgrade(HINSTANCE hInstance)
  649. {
  650. HKEY hKey;
  651. DWORD dwValueSize;
  652. DWORD dwType;
  653. DWORD dwDataSize;
  654. TCHAR szCurrentDir[MAX_PATH+1];
  655. TCHAR szCurrentValue[MAX_PATH+1];
  656. TCHAR szCurrentData[MAX_PATH+1];
  657. CPlatform plat;
  658. if (0 == GetCurrentDirectory(MAX_PATH, szCurrentDir))
  659. {
  660. return E_FAIL;
  661. }
  662. lstrcat(szCurrentDir, TEXT("\\"));
  663. if (!(plat.IsAtLeastNT5()))
  664. {
  665. CMASSERTMSG(FALSE, TEXT("MigrateCmProfilesForWin2kUpgrade - This function is supposed to be NT5 only"));
  666. return E_FAIL;
  667. }
  668. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0, KEY_ALL_ACCESS, &hKey))
  669. {
  670. DWORD dwIndex = 0;
  671. dwValueSize = MAX_PATH;
  672. dwDataSize = MAX_PATH;
  673. while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szCurrentValue, &dwValueSize, NULL, &dwType,
  674. (LPBYTE)szCurrentData, &dwDataSize))
  675. {
  676. if (REG_SZ == dwType)
  677. {
  678. MYDBGASSERT(0 != szCurrentValue[0]);
  679. MYDBGASSERT(0 != szCurrentData[0]);
  680. //
  681. // Update the phonebook entries
  682. //
  683. BOOL bReturn = MigratePhonebookEntry(hInstance, szCurrentData, szCurrentValue);
  684. if (!bReturn)
  685. {
  686. CMTRACE2(TEXT("MigrateCmProfilesForWin2kUpgrade -- MigratePhonebookEntry for profile %s failed. Cmp path is %s"), szCurrentValue, szCurrentData);
  687. }
  688. //
  689. // when we are moving a machine to NT5 we need to remove the profiles
  690. // old pbk entries and create new ones. Then we need to remove the
  691. // profile GUIDS and replace them with desktop shortcuts.
  692. //
  693. bReturn = UpdateProfileDesktopIconsOnNT5(hInstance, szCurrentData, szCurrentValue);
  694. if (!bReturn)
  695. {
  696. CMTRACE2(TEXT("MigrateCmProfilesForWin2kUpgrade -- UpdateProfileDesktopIconsOnNT5 for profile %s failed. Cmp path is %s"), szCurrentValue, szCurrentData);
  697. }
  698. //
  699. // Always try to remove old CM installs
  700. //
  701. bReturn = RemoveOldCmInstalls(hInstance, szCurrentData, szCurrentDir);
  702. if (!bReturn)
  703. {
  704. CMTRACE2(TEXT("MigrateCmProfilesForWin2kUpgrade -- RemoveOldCmInstalls for profile %s failed. Cmp path is %s"), szCurrentValue, szCurrentData);
  705. }
  706. }
  707. dwValueSize = MAX_PATH;
  708. dwDataSize = MAX_PATH;
  709. dwIndex++;
  710. }
  711. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  712. }
  713. else
  714. {
  715. CMTRACE(TEXT("No CM mappings key to migrate."));
  716. }
  717. RefreshDesktop();
  718. static const TCHAR c_ValueString[] = TEXT("Connection Manager Profiles Upgrade");
  719. LONG lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  720. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"),
  721. 0,
  722. KEY_SET_VALUE,
  723. &hKey);
  724. HRESULT hr = HRESULT_FROM_WIN32 (lr);
  725. if (SUCCEEDED(hr))
  726. {
  727. RegDeleteValue(hKey, c_ValueString); //lint !e534 this value may not exist
  728. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  729. }
  730. return S_OK;
  731. }