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.

1119 lines
37 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: main.cpp
  4. //
  5. // Module: MIGRATE.DLL
  6. //
  7. // Synopsis: Main entry point for Migrate.DLL
  8. //
  9. // Copyright (c) 1998-1999 Microsoft Corporation
  10. //
  11. // Author: quintinb created 08/21/98
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "migrate.h"
  15. #include "linkdll.h" // LinkToDll and BindLinkage for cmsecure.lib
  16. #include "linkdll.cpp" // LinkToDll and BindLinkage for cmsecure.lib
  17. const int c_NumFiles = 28;
  18. char OriginalNames[c_NumFiles][MAX_PATH+1] = {
  19. "\\showicon.exe",
  20. "\\swflash.ocx",
  21. "\\urlmon.dll",
  22. "\\iexpress.exe",
  23. "\\oleaut32.dll",
  24. "\\wextract.exe",
  25. "\\cm32\\enu\\advapi32.dll",
  26. "\\cm32\\enu\\advpack.dll",
  27. "\\cm32\\enu\\cmdial32.dll",
  28. "\\cm32\\enu\\cmdl32.exe",
  29. "\\cm32\\enu\\cmmgr32.exe",
  30. "\\cm32\\enu\\cmmgr32.hlp",
  31. "\\cm32\\enu\\cmpbk32.dll",
  32. "\\cm32\\enu\\cmstats.dll",
  33. "\\cm32\\enu\\comctl32.dll",
  34. "\\cm32\\enu\\ccfg95.dll",
  35. "\\cm32\\enu\\ccfgnt.dll",
  36. "\\cm32\\enu\\icwscrpt.exe",
  37. "\\cm32\\enu\\cnet16.dll",
  38. "\\cm32\\enu\\cnetcfg.dll",
  39. "\\cm32\\enu\\mbslgn32.dll",
  40. "\\cm32\\enu\\readme.txt",
  41. "\\cm32\\enu\\rnaph.dll",
  42. "\\cm32\\enu\\w95inf16.dll",
  43. "\\cm32\\enu\\w95inf32.dll",
  44. "\\cm32\\enu\\wininet.dll",
  45. "\\cm32\\enu\\wintrust.dll",
  46. "\\cm32\\enu\\cmcfg32.dll",
  47. };
  48. char TempNames[c_NumFiles][MAX_PATH+1] = {
  49. "\\showicon.tmp",
  50. "\\swflash.tmp",
  51. "\\urlmon.tmp",
  52. "\\iexpress.tmp",
  53. "\\oleaut32.tmp",
  54. "\\wextract.tmp",
  55. "\\advapi32.tmp",
  56. "\\advpack.tmp",
  57. "\\cmdial32.tmp",
  58. "\\cmdl32.tmp",
  59. "\\cmmgr32.001",
  60. "\\cmmgr32.002",
  61. "\\cmpbk32.tmp",
  62. "\\cmstats.tmp",
  63. "\\comctl32.tmp",
  64. "\\ccfg95.tmp",
  65. "\\ccfgnt.tmp",
  66. "\\icwscrpt.tmp",
  67. "\\cnet16.tmp",
  68. "\\cnetcfg.tmp",
  69. "\\mbslgn32.tmp",
  70. "\\readme.tmp",
  71. "\\rnaph.tmp",
  72. "\\w95inf16.tmp",
  73. "\\w95inf32.tmp",
  74. "\\wininet.tmp",
  75. "\\wintrust.tmp",
  76. "\\cmcfg32.tmp",
  77. };
  78. //
  79. // Global Vars
  80. //
  81. BOOL g_bMigrateCmak10;
  82. BOOL g_bMigrateCmak121;
  83. BOOL g_bMigrateCm;
  84. BOOL g_fInitSecureCalled;
  85. DWORD g_dwNumValues;
  86. DWORD g_dwTlsIndex; // thread local storage index
  87. HINSTANCE g_hInstance;
  88. TCHAR g_szWorkingDir[MAX_PATH+1];
  89. TCHAR g_szCmakPath[MAX_PATH+1];
  90. VENDORINFO g_VendorInfo;
  91. //+---------------------------------------------------------------------------
  92. //
  93. // Function: DllMain
  94. //
  95. // Synopsis: Main initialization function for this dll. Called whenever
  96. // a new instance of this dll is loaded or a new thread created.
  97. //
  98. // Arguments: HINSTANCE hinstDLL - handle to DLL module
  99. // DWORD fdwReason - reason for calling function
  100. // LPVOID lpvReserved - reserved
  101. //
  102. // Returns: BOOL - TRUE if initialization was successful, FALSE otherwise
  103. //
  104. // History: quintinb Created Header 01/13/2000
  105. //
  106. //----------------------------------------------------------------------------
  107. extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
  108. {
  109. if (fdwReason == DLL_PROCESS_ATTACH)
  110. {
  111. //
  112. // Init Globals
  113. //
  114. g_hInstance = hinstDLL;
  115. g_fInitSecureCalled = FALSE;
  116. g_bMigrateCmak10 = FALSE;
  117. g_bMigrateCmak121 = FALSE;
  118. ZeroMemory(g_szCmakPath, sizeof(g_szCmakPath));
  119. //
  120. // alloc tls index
  121. //
  122. g_dwTlsIndex = TlsAlloc();
  123. if (g_dwTlsIndex == TLS_OUT_OF_INDEXES)
  124. {
  125. return FALSE;
  126. }
  127. MYVERIFY(DisableThreadLibraryCalls(hinstDLL));
  128. }
  129. else if (fdwReason == DLL_PROCESS_DETACH)
  130. {
  131. //
  132. // free the tls index
  133. //
  134. if (g_dwTlsIndex != TLS_OUT_OF_INDEXES)
  135. {
  136. TlsFree(g_dwTlsIndex);
  137. }
  138. }
  139. return TRUE;
  140. }
  141. //+----------------------------------------------------------------------------
  142. //
  143. // Function: QueryVersion
  144. //
  145. // Synopsis: Supplies the Dll's version and identification information.
  146. //
  147. // Arguments: OUT LPCSTR *ProductID - buffer to hold a string that uniquely
  148. // identifies the migration dll
  149. // OUT LPUINT DllVersion - Pointer to an Integer to hold the version
  150. // number of the migration DLL
  151. // OUT LPINT *CodePageArray - pointer to an array of code pages that
  152. // the migration dll supports
  153. // OUT LPCSTR *ExeNamesBuf - a pointer to a multi-sz string. The
  154. // buffer contains a null separated list
  155. // of executable file names that the
  156. // migration engine should search for.
  157. // Full paths to all occurences of these
  158. // executables will be copied to the
  159. // [Migration Paths] section of migrate.inf.
  160. // OUT PVENDORINFO *VendorInfo - pointer to a VENDORINFO structure
  161. //
  162. // Returns: LONG - ERROR_NOT_INSTALLED if the component that this dll is to
  163. // migrate isn't installed. The migration dll won't be called
  164. // in any of the other stages if this is the return value.
  165. // ERROR_SUCCESS if the component that this dll is to migrate
  166. // is installed and requires migration. This will allow the
  167. // migration dll to be called again for further migration.
  168. //
  169. // History: quintinb Created Header 8/27/98
  170. //
  171. //+----------------------------------------------------------------------------
  172. LONG CALLBACK QueryVersion(OUT LPCSTR *ProductID, OUT LPUINT DllVersion,
  173. OUT LPINT *CodePageArray, OUT LPCSTR *ExeNamesBuf,
  174. OUT PVENDORINFO *VendorInfo)
  175. {
  176. //
  177. // Record our version information.
  178. //
  179. if (NULL != ProductID)
  180. {
  181. *ProductID = c_pszProductIdString;
  182. }
  183. if (NULL != DllVersion)
  184. {
  185. *DllVersion = uCmMigrationVersion;
  186. }
  187. if (NULL != CodePageArray)
  188. {
  189. *CodePageArray = NULL; // no code page dependencies, language neutral
  190. }
  191. if (NULL != ExeNamesBuf)
  192. {
  193. *ExeNamesBuf = NULL; //
  194. }
  195. if (NULL != VendorInfo)
  196. {
  197. *VendorInfo= &g_VendorInfo;
  198. ZeroMemory(&g_VendorInfo, sizeof(VENDORINFO));
  199. //
  200. // Use the standard MS vendor info from vendinfo.mc
  201. //
  202. FormatMessage(
  203. FORMAT_MESSAGE_FROM_HMODULE,
  204. g_hInstance,
  205. MSG_VI_COMPANY_NAME,
  206. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  207. &g_VendorInfo.CompanyName[0],
  208. sizeof(g_VendorInfo.CompanyName),
  209. NULL
  210. );
  211. FormatMessage(
  212. FORMAT_MESSAGE_FROM_HMODULE,
  213. g_hInstance,
  214. MSG_VI_SUPPORT_NUMBER,
  215. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  216. &g_VendorInfo.SupportNumber[0],
  217. sizeof(g_VendorInfo.SupportNumber),
  218. NULL
  219. );
  220. FormatMessage(
  221. FORMAT_MESSAGE_FROM_HMODULE,
  222. g_hInstance,
  223. MSG_VI_SUPPORT_URL,
  224. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  225. &g_VendorInfo.SupportUrl[0],
  226. sizeof(g_VendorInfo.SupportUrl),
  227. NULL
  228. );
  229. FormatMessage(
  230. FORMAT_MESSAGE_FROM_HMODULE,
  231. g_hInstance,
  232. MSG_VI_INSTRUCTIONS,
  233. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  234. &g_VendorInfo.InstructionsToUser[0],
  235. sizeof(g_VendorInfo.InstructionsToUser),
  236. NULL
  237. );
  238. }
  239. //
  240. // Now try to detect if CMAK or CM are installed. If they are and the versions
  241. // are such that they need to be migrated, then return ERROR_SUCCESS. Otherwise
  242. // we don't need to do any migration, so return ERROR_NOT_INSTALLED.
  243. //
  244. LONG lReturnValue = ERROR_NOT_INSTALLED;
  245. CmVersion CmVer;
  246. if (CmVer.IsPresent())
  247. {
  248. lReturnValue = ERROR_SUCCESS;
  249. }
  250. else
  251. {
  252. CmakVersion CmakVer;
  253. //
  254. // Okay, CM wasn't installed so look for CMAK.
  255. //
  256. if (CmakVer.IsPresent())
  257. {
  258. //
  259. // Okay, CMAK exists
  260. //
  261. lReturnValue = ERROR_SUCCESS;
  262. }
  263. }
  264. return lReturnValue;
  265. }
  266. //+----------------------------------------------------------------------------
  267. //
  268. // Function: Initialize9x
  269. //
  270. // Synopsis: This function is called so that the migration dll can initialize
  271. // itself on the Win9x side of the migration. The migration dll
  272. // should not make any modifications to the system in this call, as
  273. // it is only for initialization and searching to see if your component
  274. // is installed.
  275. //
  276. // Arguments: IN LPCSTR WorkingDirectory - path of the temporary storage dir for
  277. // the migration dll.
  278. // IN LPCSTR SourceDirectories - a multi-sz list of the Win2k source
  279. // directory or directories
  280. // IN LPCSTR MediaDirectory - specifies the path to the original media
  281. // directory
  282. //
  283. // Returns: LONG - ERROR_NOT_INSTALLED if the component that this dll is to
  284. // migrate isn't installed. The migration dll won't be called
  285. // in any of the other stages if this is the return value.
  286. // ERROR_SUCCESS if the component that this dll is to migrate
  287. // is installed and requires migration. This will allow the
  288. // migration dll to be called again for further migration.
  289. //
  290. // History: quintinb Created Header 8/27/98
  291. //
  292. //+----------------------------------------------------------------------------
  293. LONG CALLBACK Initialize9x(IN LPCSTR WorkingDirectory, IN LPCSTR SourceDirectories,
  294. IN LPCSTR MediaDirectory)
  295. {
  296. HKEY hKey;
  297. //
  298. // Check to see if we need to Migrate CMAK
  299. //
  300. CmakVersion CmakVer;
  301. lstrcpy(g_szWorkingDir, WorkingDirectory);
  302. if (CmakVer.IsPresent())
  303. {
  304. if (CmakVer.GetInstallLocation(g_szCmakPath))
  305. {
  306. //
  307. // Then we have a CMAK path. Write this to the handled key so that
  308. // they won't mess with our files.
  309. //
  310. TCHAR szTemp[MAX_PATH+1];
  311. wsprintf(szTemp, "%s\\migrate.inf", WorkingDirectory);
  312. MYVERIFY(0 != WritePrivateProfileString(c_pszSectionHandled, g_szCmakPath,
  313. c_pszDirectory, szTemp));
  314. //
  315. // Now try to figure out what version of CMAK we have to see if we need
  316. // to run the migration DLL or not. If the CMAK.exe version is 6.00.613.0 (1.0)
  317. // then we should migrate it. If it is higher than that, 1.1 or 1.2 it is
  318. // beta and we shouldn't support the upgrade anyway (I purposely am not
  319. // going to run the migration on it). If it is IE5 IEAK CMAK, then it should
  320. // survive upgrade without a problem.
  321. //
  322. if (CmakVer.Is10Cmak())
  323. {
  324. g_bMigrateCmak10 = TRUE;
  325. }
  326. else if (CmakVer.Is121Cmak())
  327. {
  328. g_bMigrateCmak121 = TRUE;
  329. }
  330. }
  331. }
  332. //
  333. // Check to see if we need to migrate CM Profiles
  334. //
  335. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0,
  336. KEY_READ, &hKey))
  337. {
  338. if ((ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
  339. &g_dwNumValues, NULL, NULL, NULL, NULL)) && (g_dwNumValues > 0))
  340. {
  341. //
  342. // Then we have mappings values, so we need to migrate them.
  343. //
  344. g_bMigrateCm = TRUE;
  345. }
  346. RegCloseKey(hKey);
  347. }
  348. if (g_bMigrateCmak10 || g_bMigrateCmak121 || g_bMigrateCm)
  349. {
  350. return ERROR_SUCCESS;
  351. }
  352. else
  353. {
  354. return ERROR_NOT_INSTALLED;
  355. }
  356. }
  357. //+----------------------------------------------------------------------------
  358. //
  359. // Function: MigrateUser9x
  360. //
  361. // Synopsis: Called once for each Win9x user being migrated. Its purpose is to
  362. // allow migration of per user settings.
  363. //
  364. // Arguments: IN HWND ParentWnd - Window handle of the parent window, used if
  365. // the migration dll needs to display UI. If NULL,
  366. // running in unattended mode and no UI should be
  367. // displayed.
  368. // IN LPCSTR AnswerFile - Supplies the path to the answer file.
  369. // IN HKEY UserRegKey - reg key for the HKEY_CURRENT_USER key of the
  370. // user currently being migrated.
  371. // IN LPCSTR UserName - username of the user being migrated
  372. // LPVOID Reserved - reserved
  373. //
  374. // Returns: LONG - ERROR_NOT_INSTALLED - if no per user processing is required.
  375. // ERROR_CANCELLED - if the user wants to exit setup
  376. // ERROR_SUCCESS - the migration dll processed this user successfully
  377. //
  378. // History: quintinb Created Header 8/27/98
  379. //
  380. //+----------------------------------------------------------------------------
  381. LONG
  382. CALLBACK MigrateUser9x(IN HWND ParentWnd, IN LPCSTR AnswerFile,
  383. IN HKEY UserRegKey, IN LPCSTR UserName, LPVOID Reserved)
  384. {
  385. return ERROR_NOT_INSTALLED;
  386. }
  387. //+----------------------------------------------------------------------------
  388. //
  389. // Function: MigrateSystem9x
  390. //
  391. // Synopsis: Allows migration of system wide settings on the Windows 9x side.
  392. //
  393. // Arguments: IN HWND ParentWnd - parent window handle for the display of UI,
  394. // NULL if in unattended mode
  395. // IN LPCSTR AnswerFile - full path to the answer file
  396. // LPVOID Reserved - reserved
  397. //
  398. // Returns: LONG - ERROR_NOT_INSTALLED if the component that this dll is to
  399. // migrate isn't installed. The migration dll won't be called
  400. // in any of the other stages if this is the return value.
  401. // ERROR_SUCCESS if the component that this dll is to migrate
  402. // is installed and requires migration. This will allow the
  403. // migration dll to be called again for further migration.
  404. //
  405. // History: quintinb Created Header 8/27/98
  406. //
  407. //+----------------------------------------------------------------------------
  408. LONG
  409. CALLBACK MigrateSystem9x(IN HWND ParentWnd, IN LPCSTR AnswerFile, LPVOID Reserved)
  410. {
  411. LONG lReturn = ERROR_NOT_INSTALLED;
  412. TCHAR szSystemDir[MAX_PATH+1];
  413. GetSystemDirectory(szSystemDir, MAX_PATH);
  414. //
  415. // Setup deletes a bunch of the files that 1.0 CMAK or IEAK5 CMAK need to function.
  416. // Since we currently don't support NT5 CMAK on WKS, we need to copy these files
  417. // to the setup provided working directory, so that we can copy them bak once
  418. // we boot into NT.
  419. //
  420. if (g_bMigrateCmak10 && (TEXT('\0') != g_szCmakPath[0]) && (TEXT('\0') != g_szWorkingDir[0]))
  421. {
  422. TCHAR szDest[MAX_PATH+1];
  423. TCHAR szSrc[MAX_PATH+1];
  424. for (int i=0; i < c_NumFiles; i++)
  425. {
  426. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s%s"), g_szCmakPath, OriginalNames[i]));
  427. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s%s"), g_szWorkingDir, TempNames[i]));
  428. if (FileExists(szSrc))
  429. {
  430. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  431. }
  432. }
  433. lReturn &= ERROR_SUCCESS;
  434. }
  435. else if (g_bMigrateCmak121 && (TEXT('\0') != szSystemDir[0]) &&
  436. (TEXT('\0') != g_szWorkingDir[0]))
  437. {
  438. TCHAR szDest[MAX_PATH+1];
  439. TCHAR szSrc[MAX_PATH+1];
  440. //
  441. // Copy w95inf16.dll to the working directory and rename it w95inf16.tmp
  442. //
  443. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), szSystemDir, c_pszW95Inf16, c_pszDll));
  444. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), g_szWorkingDir, c_pszW95Inf16, c_pszTmp));
  445. if (FileExists(szSrc))
  446. {
  447. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  448. }
  449. //
  450. // Copy w95inf32.dll to the working directory and rename it w95inf32.tmp
  451. //
  452. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), szSystemDir, c_pszW95Inf32, c_pszDll));
  453. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), g_szWorkingDir, c_pszW95Inf32, c_pszTmp));
  454. if (FileExists(szSrc))
  455. {
  456. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  457. }
  458. lReturn &= ERROR_SUCCESS;
  459. }
  460. if (g_bMigrateCm)
  461. {
  462. //
  463. // Enumerate all the installed profiles on the machine. For each profile check
  464. // for a UserInfo\<CurrentServiceNameKey>. If this key exists, then go to the next
  465. // profile or user. If it doesn't exist, then read the data from the cmp file. If
  466. // the cmp has data marked as being stored then we need to save the password. If
  467. // the password isn't in the cmp then it is in the wnet cache. We must then
  468. // retrieve it.
  469. //
  470. HKEY hKey;
  471. HKEY hTempKey;
  472. TCHAR szTemp[MAX_PATH+1];
  473. TCHAR szLongServiceName[MAX_PATH+1];
  474. TCHAR szCmpPath[MAX_PATH+1];
  475. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0, KEY_READ,
  476. &hKey))
  477. {
  478. DWORD dwIndex = 0;
  479. DWORD dwValueSize = MAX_PATH;
  480. DWORD dwDataSize = MAX_PATH;
  481. DWORD dwType;
  482. while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szLongServiceName,
  483. &dwValueSize, NULL, &dwType, (LPBYTE)szCmpPath, &dwDataSize))
  484. {
  485. if (REG_SZ == dwType)
  486. {
  487. MYDBGASSERT(TEXT('\0') != szLongServiceName[0]);
  488. MYDBGASSERT(TEXT('\0') != szCmpPath[0]);
  489. //
  490. // If the user saved their password or their Internet password,
  491. // then we must make sure that it exists in the cmp (in encrypted form)
  492. // so that when the user runs CM on the NT5 side of the migration,
  493. // CM will move the settings to the new format. Note, that if the
  494. // cmp doesn't specify that the password(s) be saved, then this
  495. // function just returns as there is no password to ensure is in the
  496. // cmp.
  497. MYVERIFY(EnsureEncryptedPasswordInCmpIfSaved(szLongServiceName, szCmpPath));
  498. }
  499. dwValueSize = MAX_PATH;
  500. dwDataSize = MAX_PATH;
  501. dwIndex++;
  502. if (dwIndex == g_dwNumValues)
  503. {
  504. break;
  505. }
  506. }
  507. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  508. }
  509. lReturn &= ERROR_SUCCESS;
  510. }
  511. return lReturn;
  512. }
  513. //+----------------------------------------------------------------------------
  514. //
  515. // Function: InitializeNT
  516. //
  517. // Synopsis: First function called on the Win2k side of the migration, used to
  518. // setup the Win2k migration. Similar to Initialize9x but on the Win2k
  519. // side. No changes to the system should be made in this function.
  520. //
  521. // Arguments: IN LPCWSTR WorkingDirectory - temporary storage, same as path given
  522. // on the Win9x side
  523. // IN LPCWSTR SourceDirectories - a multi-sz list of the Win2k source
  524. // directory or directories
  525. // LPVOID Reserved - reserved
  526. //
  527. // Returns: LONG - ERROR_SUCCESS unless an init error occurs.
  528. //
  529. // History: quintinb Created Header 8/27/98
  530. //
  531. //+----------------------------------------------------------------------------
  532. LONG
  533. CALLBACK InitializeNT(IN LPCWSTR WorkingDirectory, IN LPCWSTR SourceDirectories, LPVOID Reserved)
  534. {
  535. HKEY hKey;
  536. //
  537. // Convert the WorkingDirectory to MultiByte
  538. //
  539. MYVERIFY (0 != WideCharToMultiByte(CP_THREAD_ACP, WC_COMPOSITECHECK, WorkingDirectory, -1,
  540. g_szWorkingDir, MAX_PATH, NULL, NULL));
  541. //
  542. // Check to see if we need to Migrate CMAK
  543. //
  544. CmakVersion CmakVer;
  545. if (CmakVer.IsPresent())
  546. {
  547. if (CmakVer.GetInstallLocation(g_szCmakPath))
  548. {
  549. //
  550. // Now try to figure out what version of CMAK we have to see if we need
  551. // to run the migration DLL or not. If the CMAK.exe version is 6.00.613.0 (1.0)
  552. // then we should migrate it. If it is higher than that, 1.1 or 1.2 it is
  553. // beta and we shouldn't support the upgrade anyway (I purposely am not
  554. // going to run the migration on it). If it is IE5 IEAK CMAK, then it should
  555. // survive upgrade without a problem.
  556. //
  557. if (CmakVer.Is10Cmak())
  558. {
  559. g_bMigrateCmak10 = TRUE;
  560. }
  561. else if (CmakVer.Is121Cmak())
  562. {
  563. g_bMigrateCmak121 = TRUE;
  564. }
  565. }
  566. }
  567. //
  568. // Check to see if we need to migrate CM Profiles
  569. //
  570. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0,
  571. KEY_READ, &hKey))
  572. {
  573. if ((ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
  574. &g_dwNumValues, NULL, NULL, NULL, NULL)) && (g_dwNumValues > 0))
  575. {
  576. //
  577. // Then we have mappings values, so we need to migrate them.
  578. //
  579. g_bMigrateCm = TRUE;
  580. }
  581. RegCloseKey(hKey);
  582. }
  583. if (g_bMigrateCmak10 || g_bMigrateCmak121 || g_bMigrateCm)
  584. {
  585. return ERROR_SUCCESS;
  586. }
  587. else
  588. {
  589. return ERROR_NOT_INSTALLED;
  590. }
  591. }
  592. //+----------------------------------------------------------------------------
  593. //
  594. // Function: MigrateUserNT
  595. //
  596. // Synopsis: Called once per migrated user on win2k. Used to migrated any
  597. // per user settings saved from MigrateUser9x.
  598. //
  599. // Arguments: IN HINF UnattendInfHandle - valid inf handle to unattend.txt,
  600. // for use with the setup API's
  601. // IN HKEY UserRegHandle - HKEY_CURRENT_USER of the user currently
  602. // being migrated
  603. // IN LPCWSTR UserName - username of the user currently being migrated
  604. // LPVOID Reserved - reserved
  605. //
  606. // Returns: LONG - ERROR_SUCCESS or a win32 error code (will abort migration dll
  607. // processing)
  608. //
  609. // History: quintinb Created Header 8/27/98
  610. //
  611. //+----------------------------------------------------------------------------
  612. LONG
  613. CALLBACK MigrateUserNT(IN HINF UnattendInfHandle, IN HKEY UserRegHandle,
  614. IN LPCWSTR UserName, LPVOID Reserved)
  615. {
  616. return ERROR_SUCCESS;
  617. }
  618. //+----------------------------------------------------------------------------
  619. //
  620. // Function: MigrateSystemNT
  621. //
  622. // Synopsis: Called to allow system wide migration changes to be made on the
  623. // Win2k side.
  624. //
  625. // Arguments: IN HINF UnattendInfHandle - handle to the unattend.txt file
  626. // LPVOID Reserved - reserved
  627. //
  628. // Returns: LONG - ERROR_SUCCESS or a win32 error code (will abort migration dll
  629. // processing)
  630. //
  631. // History: quintinb Created Header 8/27/98
  632. //
  633. //+----------------------------------------------------------------------------
  634. LONG
  635. CALLBACK MigrateSystemNT(IN HINF UnattendInfHandle, LPVOID Reserved)
  636. {
  637. LONG lReturn = ERROR_NOT_INSTALLED;
  638. DWORD dwDisposition;
  639. TCHAR szSystemDir[MAX_PATH+1];
  640. GetSystemDirectory(szSystemDir, MAX_PATH);
  641. const TCHAR* const c_pszSystemFmt = TEXT("%s\\system\\%s.inf");
  642. const TCHAR* const c_pszValueString = TEXT("Connection Manager Profiles Upgrade");
  643. const TCHAR* const c_pszRegRunKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
  644. const TCHAR* const c_pszCmdLine = TEXT("cmstp.exe /m");
  645. if (g_bMigrateCmak10 && (TEXT('\0') != g_szCmakPath[0]) && (TEXT('\0') != g_szWorkingDir[0]))
  646. {
  647. TCHAR szDest[MAX_PATH+1];
  648. TCHAR szSrc[MAX_PATH+1];
  649. for (int i=0; i < c_NumFiles; i++)
  650. {
  651. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s%s"), g_szCmakPath,
  652. OriginalNames[i]));
  653. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s%s"), g_szWorkingDir,
  654. TempNames[i]));
  655. if (FileExists(szSrc))
  656. {
  657. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  658. }
  659. }
  660. lReturn &= ERROR_SUCCESS;
  661. }
  662. else if (g_bMigrateCmak121 && (TEXT('\0') != g_szCmakPath[0]) &&
  663. (TEXT('\0') != szSystemDir[0]))
  664. {
  665. TCHAR szDest[MAX_PATH+1];
  666. TCHAR szSrc[MAX_PATH+1];
  667. //
  668. // Copy w95inf16.tmp in the working dir back to the systemdir and rename it .dll
  669. //
  670. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), g_szWorkingDir,
  671. c_pszW95Inf16, c_pszTmp));
  672. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), szSystemDir,
  673. c_pszW95Inf16, c_pszDll));
  674. if (FileExists(szSrc))
  675. {
  676. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  677. }
  678. //
  679. // Copy w95inf32.tmp in the working dir back to the systemdir and rename it .dll
  680. //
  681. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), g_szWorkingDir,
  682. c_pszW95Inf32, c_pszTmp));
  683. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), szSystemDir,
  684. c_pszW95Inf32, c_pszDll));
  685. if (FileExists(szSrc))
  686. {
  687. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  688. }
  689. lReturn &= ERROR_SUCCESS;
  690. }
  691. if (g_bMigrateCm)
  692. {
  693. //
  694. // Enumerate all the installed profiles on the machine. For each profile check to
  695. // see if the profile inf is located in the system (that's system not system32) dir.
  696. // If it is, then we need to move it to system32 so that our code will know where to
  697. // find it.
  698. //
  699. HKEY hKey;
  700. HKEY hTempKey;
  701. TCHAR szSource[MAX_PATH+1];
  702. TCHAR szDest[MAX_PATH+1];
  703. TCHAR szLongServiceName[MAX_PATH+1];
  704. TCHAR szWindowsDir[MAX_PATH+1];
  705. TCHAR szSystemDir[MAX_PATH+1];
  706. TCHAR szCmpPath[MAX_PATH+1];
  707. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings,
  708. 0, KEY_READ, &hKey))
  709. {
  710. DWORD dwIndex = 0;
  711. DWORD dwValueSize = MAX_PATH;
  712. DWORD dwDataSize = MAX_PATH;
  713. DWORD dwType;
  714. while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szLongServiceName,
  715. &dwValueSize, NULL, &dwType, (LPBYTE)szCmpPath, &dwDataSize))
  716. {
  717. if (REG_SZ == dwType)
  718. {
  719. MYDBGASSERT(TEXT('\0') != szLongServiceName[0]);
  720. MYDBGASSERT(TEXT('\0') != szCmpPath[0]);
  721. CFileNameParts CmpPath(szCmpPath);
  722. GetWindowsDirectory(szWindowsDir, MAX_PATH);
  723. MYDBGASSERT(TEXT('\0') != szWindowsDir[0]);
  724. GetSystemDirectory(szSystemDir, MAX_PATH);
  725. MYDBGASSERT(TEXT('\0') != szSystemDir[0]);
  726. MYVERIFY(CELEMS(szSource) > (UINT)wsprintf(szSource, c_pszSystemFmt, szWindowsDir, CmpPath.m_FileName));
  727. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s.inf"), szSystemDir, CmpPath.m_FileName));
  728. if (CopyFile(szSource, szDest, FALSE))
  729. {
  730. DeleteFile(szSource);
  731. }
  732. }
  733. dwValueSize = MAX_PATH;
  734. dwDataSize = MAX_PATH;
  735. dwIndex++;
  736. if (dwIndex == g_dwNumValues)
  737. {
  738. break;
  739. }
  740. }
  741. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  742. }
  743. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_pszRegRunKey, 0, NULL,
  744. REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &hKey, &dwDisposition))
  745. {
  746. RegSetValueEx(hKey, c_pszValueString, 0, REG_SZ, (CONST BYTE*)c_pszCmdLine,
  747. sizeof(TCHAR)*(lstrlen(c_pszCmdLine)+1));
  748. RegCloseKey(hKey);
  749. }
  750. lReturn &= ERROR_SUCCESS;
  751. }
  752. return lReturn;
  753. }
  754. //+----------------------------------------------------------------------------
  755. //
  756. // Function: EnsureEncryptedPasswordInCmpIfSaved
  757. //
  758. // Synopsis: This function is called on the Win9x side of the migration so
  759. // that if a password is in the Win9x password cache (which only
  760. // happens if the user has profiling enabled), it will be retrieved,
  761. // encrypted, and written to the cmp. This enables CM to populate
  762. // a users registry with the starting password whenever they first
  763. // launch the CM profile. This no functionality is lost from the
  764. // shared password feature that win9x had.
  765. //
  766. // Arguments: szLongServiceName - Service name of the profile to retrieve
  767. // the password for
  768. // szCmpPath - full path to the cmp to write the password too
  769. //
  770. // Returns: BOOL - returns TRUE if successful
  771. //
  772. // History: quintinb Created 08/27/98
  773. // nickball CmWipePassword 08/04/99
  774. //
  775. //+----------------------------------------------------------------------------
  776. BOOL EnsureEncryptedPasswordInCmpIfSaved(LPCTSTR pszLongServiceName, LPCTSTR pszCmpPath)
  777. {
  778. TCHAR szPassword[MAX_PATH+1] = TEXT("");
  779. TCHAR szCacheEntryName[MAX_PATH+1];
  780. TCHAR szEncryptedPassword[MAX_PATH+1];
  781. DWORD dwSize;
  782. DWORD dwCryptType = 0;
  783. GetCachedPassword pfnGetCachedPassword = NULL;
  784. int iTemp=0;
  785. CDynamicLibrary MprDll(TEXT("mpr.dll"));
  786. iTemp = GetPrivateProfileInt(c_pszCmSection, c_pszCmEntryRememberPwd, 0, pszCmpPath);
  787. if (iTemp)
  788. {
  789. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryPassword, TEXT(""), szPassword, MAX_PATH, pszCmpPath);
  790. if (TEXT('\0') == szPassword[0])
  791. {
  792. //
  793. // The string must be in the password cache. Build the key string
  794. // for the cache.
  795. //
  796. MYVERIFY(CELEMS(szCacheEntryName) > (UINT)wsprintf(szCacheEntryName,
  797. TEXT("%s - Sign-In (Connection Manager)"), pszLongServiceName));
  798. pfnGetCachedPassword = (GetCachedPassword)MprDll.GetProcAddress(TEXT("WNetGetCachedPassword"));
  799. if (NULL == pfnGetCachedPassword)
  800. {
  801. CmWipePassword(szPassword);
  802. return FALSE;
  803. }
  804. else
  805. {
  806. WORD wStr = (WORD)256;
  807. if (ERROR_SUCCESS == pfnGetCachedPassword(szCacheEntryName,
  808. (WORD)lstrlen(szCacheEntryName), szPassword, &wStr, 80))
  809. {
  810. //
  811. // Okay, we retrived the password, now lets encrypt it and write it
  812. // to the cmp
  813. //
  814. if (EncryptPassword(szPassword, szEncryptedPassword, &dwSize, &dwCryptType))
  815. {
  816. //
  817. // Write the encrypted password
  818. //
  819. WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPassword, szEncryptedPassword,
  820. pszCmpPath);
  821. //
  822. // Write the encryption type
  823. //
  824. wsprintf(szPassword, TEXT("%u"), dwCryptType);
  825. WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPcs, szPassword,
  826. pszCmpPath);
  827. }
  828. }
  829. }
  830. }
  831. }
  832. //
  833. // Now do the same for the Internet Password
  834. //
  835. iTemp = GetPrivateProfileInt(c_pszCmSection, c_pszCmEntryRememberInetPwd, 0, pszCmpPath);
  836. if (iTemp)
  837. {
  838. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryInetPassword, TEXT(""), szPassword, MAX_PATH, pszCmpPath);
  839. if (TEXT('\0') == szPassword[0])
  840. {
  841. //
  842. // The string must be in the password cache. Build the key string
  843. // for the cache.
  844. //
  845. MYVERIFY(CELEMS(szCacheEntryName) > (UINT)wsprintf(szCacheEntryName,
  846. TEXT("%s - Sign-In (Connection Manager)-tunnel"), pszLongServiceName));
  847. pfnGetCachedPassword = (GetCachedPassword)MprDll.GetProcAddress(TEXT("WNetGetCachedPassword"));
  848. if (NULL == pfnGetCachedPassword)
  849. {
  850. CmWipePassword(szPassword);
  851. return FALSE;
  852. }
  853. else
  854. {
  855. WORD wStr = (WORD)256;
  856. if (ERROR_SUCCESS == pfnGetCachedPassword(szCacheEntryName,
  857. (WORD)lstrlen(szCacheEntryName), szPassword, &wStr, 80))
  858. {
  859. //
  860. // Okay, we retrived the password, now lets encrypt it and write it
  861. // to the cmp
  862. //
  863. dwCryptType = 0;
  864. if (EncryptPassword(szPassword, szEncryptedPassword, &dwSize, &dwCryptType))
  865. {
  866. //
  867. // Write the encrypted password
  868. //
  869. WritePrivateProfileString(c_pszCmSection, c_pszCmEntryInetPassword, szEncryptedPassword,
  870. pszCmpPath);
  871. //
  872. // Write the encryption type
  873. //
  874. wsprintf(szPassword, TEXT("%u"), dwCryptType);
  875. WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPcs, szPassword,
  876. pszCmpPath);
  877. }
  878. }
  879. }
  880. }
  881. }
  882. CmWipePassword(szPassword);
  883. return TRUE;
  884. }
  885. //+----------------------------------------------------------------------------
  886. //
  887. // Function: EncryptPassword
  888. //
  889. // Synopsis:
  890. //
  891. // Arguments: IN LPCTSTR pszPassword -
  892. // OUT LPTSTR pszEncryptedPassword -
  893. // OUT LPDWORD lpdwBufSize -
  894. // OUT LPDWORD lpdwCryptType -
  895. //
  896. // Returns: BOOL -
  897. //
  898. // History: quintinb Created Header 8/27/98
  899. // nickball CmWipePassword 08/04/99
  900. //
  901. //+----------------------------------------------------------------------------
  902. BOOL EncryptPassword(IN LPCTSTR pszPassword, OUT LPTSTR pszEncryptedPassword, OUT LPDWORD lpdwBufSize, OUT LPDWORD lpdwCryptType)
  903. {
  904. MYDBGASSERT(pszPassword);
  905. MYDBGASSERT(pszEncryptedPassword);
  906. MYDBGASSERT(lpdwBufSize);
  907. MYDBGASSERT(lpdwCryptType);
  908. DWORD dwEncryptedBufferLen;
  909. DWORD dwSize = 0;
  910. LPTSTR pszEncryptedData = NULL;
  911. TCHAR szSourceData[PWLEN + sizeof(TCHAR)];
  912. if ((NULL == pszPassword) || (NULL == pszEncryptedPassword) || (NULL == lpdwBufSize))
  913. {
  914. return NULL;
  915. }
  916. //
  917. // Standard encryption, copy the password
  918. //
  919. lstrcpy(szSourceData, pszPassword);
  920. //
  921. // It is not safe to call InitSecure more than once
  922. //
  923. if (!g_fInitSecureCalled)
  924. {
  925. BOOL bFastEncryption = FALSE;
  926. MYVERIFY(FALSE != ReadEncryptionOption(&bFastEncryption));
  927. InitSecure(bFastEncryption);
  928. g_fInitSecureCalled = TRUE;
  929. }
  930. //
  931. // Encrypt the provided password
  932. //
  933. if (EncryptData((LPBYTE)szSourceData, (lstrlen(szSourceData)+1) * sizeof(TCHAR),
  934. (LPBYTE*)&pszEncryptedData, &dwEncryptedBufferLen, lpdwCryptType, NULL, NULL, NULL))
  935. {
  936. if (lpdwBufSize)
  937. {
  938. *lpdwBufSize = dwEncryptedBufferLen;
  939. }
  940. if (pszEncryptedData)
  941. {
  942. _tcscpy(pszEncryptedPassword, pszEncryptedData);
  943. HeapFree(GetProcessHeap(), 0, pszEncryptedData);
  944. pszEncryptedData = NULL;
  945. CmWipePassword(szSourceData);
  946. return TRUE;
  947. }
  948. }
  949. CmWipePassword(szSourceData);
  950. return FALSE;
  951. }
  952. //+----------------------------------------------------------------------------
  953. //
  954. // Function: ReadEncryptionOption
  955. //
  956. // Synopsis:
  957. //
  958. // Arguments: BOOL* pfFastEncryption - boolean to fill in with fast encryption flag
  959. //
  960. // Returns: BOOL - TRUE if successful
  961. //
  962. // History: quintinb Created Header 8/27/98
  963. // copied from the version written by Fengsun in cmdial\connect.cpp
  964. //
  965. //+----------------------------------------------------------------------------
  966. BOOL ReadEncryptionOption(BOOL* pfFastEncryption)
  967. {
  968. HKEY hKeyCm;
  969. DWORD dwType;
  970. DWORD dwSize = sizeof(DWORD);
  971. MYDBGASSERT(pfFastEncryption != NULL);
  972. *pfFastEncryption = FALSE;
  973. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmRoot, 0,
  974. KEY_QUERY_VALUE ,&hKeyCm))
  975. {
  976. RegQueryValueEx(hKeyCm, c_pszRegCmEncryptOption, NULL, &dwType,
  977. (BYTE*)pfFastEncryption, &dwSize);
  978. RegCloseKey(hKeyCm);
  979. }
  980. return TRUE;
  981. }