Leaked source code of windows server 2003
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.

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