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.

1131 lines
39 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. if (0 == GetSystemDirectory(szSystemDir, MAX_PATH))
  414. {
  415. return GetLastError();
  416. }
  417. //
  418. // Setup deletes a bunch of the files that 1.0 CMAK or IEAK5 CMAK need to function.
  419. // Since we currently don't support NT5 CMAK on WKS, we need to copy these files
  420. // to the setup provided working directory, so that we can copy them bak once
  421. // we boot into NT.
  422. //
  423. if (g_bMigrateCmak10 && (TEXT('\0') != g_szCmakPath[0]) && (TEXT('\0') != g_szWorkingDir[0]))
  424. {
  425. TCHAR szDest[MAX_PATH+1];
  426. TCHAR szSrc[MAX_PATH+1];
  427. for (int i=0; i < c_NumFiles; i++)
  428. {
  429. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s%s"), g_szCmakPath, OriginalNames[i]));
  430. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s%s"), g_szWorkingDir, TempNames[i]));
  431. if (FileExists(szSrc))
  432. {
  433. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  434. }
  435. }
  436. lReturn &= ERROR_SUCCESS;
  437. }
  438. else if (g_bMigrateCmak121 && (TEXT('\0') != szSystemDir[0]) &&
  439. (TEXT('\0') != g_szWorkingDir[0]))
  440. {
  441. TCHAR szDest[MAX_PATH+1];
  442. TCHAR szSrc[MAX_PATH+1];
  443. //
  444. // Copy w95inf16.dll to the working directory and rename it w95inf16.tmp
  445. //
  446. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), szSystemDir, c_pszW95Inf16, c_pszDll));
  447. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), g_szWorkingDir, c_pszW95Inf16, c_pszTmp));
  448. if (FileExists(szSrc))
  449. {
  450. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  451. }
  452. //
  453. // Copy w95inf32.dll to the working directory and rename it w95inf32.tmp
  454. //
  455. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), szSystemDir, c_pszW95Inf32, c_pszDll));
  456. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), g_szWorkingDir, c_pszW95Inf32, c_pszTmp));
  457. if (FileExists(szSrc))
  458. {
  459. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  460. }
  461. lReturn &= ERROR_SUCCESS;
  462. }
  463. if (g_bMigrateCm)
  464. {
  465. //
  466. // Enumerate all the installed profiles on the machine. For each profile check
  467. // for a UserInfo\<CurrentServiceNameKey>. If this key exists, then go to the next
  468. // profile or user. If it doesn't exist, then read the data from the cmp file. If
  469. // the cmp has data marked as being stored then we need to save the password. If
  470. // the password isn't in the cmp then it is in the wnet cache. We must then
  471. // retrieve it.
  472. //
  473. HKEY hKey;
  474. HKEY hTempKey;
  475. TCHAR szTemp[MAX_PATH+1];
  476. TCHAR szLongServiceName[MAX_PATH+1];
  477. TCHAR szCmpPath[MAX_PATH+1];
  478. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0, KEY_READ,
  479. &hKey))
  480. {
  481. DWORD dwIndex = 0;
  482. DWORD dwValueSize = MAX_PATH;
  483. DWORD dwDataSize = MAX_PATH;
  484. DWORD dwType;
  485. while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szLongServiceName,
  486. &dwValueSize, NULL, &dwType, (LPBYTE)szCmpPath, &dwDataSize))
  487. {
  488. if (REG_SZ == dwType)
  489. {
  490. MYDBGASSERT(TEXT('\0') != szLongServiceName[0]);
  491. MYDBGASSERT(TEXT('\0') != szCmpPath[0]);
  492. //
  493. // If the user saved their password or their Internet password,
  494. // then we must make sure that it exists in the cmp (in encrypted form)
  495. // so that when the user runs CM on the NT5 side of the migration,
  496. // CM will move the settings to the new format. Note, that if the
  497. // cmp doesn't specify that the password(s) be saved, then this
  498. // function just returns as there is no password to ensure is in the
  499. // cmp.
  500. MYVERIFY(EnsureEncryptedPasswordInCmpIfSaved(szLongServiceName, szCmpPath));
  501. }
  502. dwValueSize = MAX_PATH;
  503. dwDataSize = MAX_PATH;
  504. dwIndex++;
  505. if (dwIndex == g_dwNumValues)
  506. {
  507. break;
  508. }
  509. }
  510. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  511. }
  512. lReturn &= ERROR_SUCCESS;
  513. }
  514. return lReturn;
  515. }
  516. //+----------------------------------------------------------------------------
  517. //
  518. // Function: InitializeNT
  519. //
  520. // Synopsis: First function called on the Win2k side of the migration, used to
  521. // setup the Win2k migration. Similar to Initialize9x but on the Win2k
  522. // side. No changes to the system should be made in this function.
  523. //
  524. // Arguments: IN LPCWSTR WorkingDirectory - temporary storage, same as path given
  525. // on the Win9x side
  526. // IN LPCWSTR SourceDirectories - a multi-sz list of the Win2k source
  527. // directory or directories
  528. // LPVOID Reserved - reserved
  529. //
  530. // Returns: LONG - ERROR_SUCCESS unless an init error occurs.
  531. //
  532. // History: quintinb Created Header 8/27/98
  533. //
  534. //+----------------------------------------------------------------------------
  535. LONG
  536. CALLBACK InitializeNT(IN LPCWSTR WorkingDirectory, IN LPCWSTR SourceDirectories, LPVOID Reserved)
  537. {
  538. HKEY hKey;
  539. //
  540. // Convert the WorkingDirectory to MultiByte
  541. //
  542. MYVERIFY (0 != WideCharToMultiByte(CP_THREAD_ACP, WC_COMPOSITECHECK, WorkingDirectory, -1,
  543. g_szWorkingDir, MAX_PATH, NULL, NULL));
  544. //
  545. // Check to see if we need to Migrate CMAK
  546. //
  547. CmakVersion CmakVer;
  548. if (CmakVer.IsPresent())
  549. {
  550. if (CmakVer.GetInstallLocation(g_szCmakPath))
  551. {
  552. //
  553. // Now try to figure out what version of CMAK we have to see if we need
  554. // to run the migration DLL or not. If the CMAK.exe version is 6.00.613.0 (1.0)
  555. // then we should migrate it. If it is higher than that, 1.1 or 1.2 it is
  556. // beta and we shouldn't support the upgrade anyway (I purposely am not
  557. // going to run the migration on it). If it is IE5 IEAK CMAK, then it should
  558. // survive upgrade without a problem.
  559. //
  560. if (CmakVer.Is10Cmak())
  561. {
  562. g_bMigrateCmak10 = TRUE;
  563. }
  564. else if (CmakVer.Is121Cmak())
  565. {
  566. g_bMigrateCmak121 = TRUE;
  567. }
  568. }
  569. }
  570. //
  571. // Check to see if we need to migrate CM Profiles
  572. //
  573. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings, 0,
  574. KEY_READ, &hKey))
  575. {
  576. if ((ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
  577. &g_dwNumValues, NULL, NULL, NULL, NULL)) && (g_dwNumValues > 0))
  578. {
  579. //
  580. // Then we have mappings values, so we need to migrate them.
  581. //
  582. g_bMigrateCm = TRUE;
  583. }
  584. RegCloseKey(hKey);
  585. }
  586. if (g_bMigrateCmak10 || g_bMigrateCmak121 || g_bMigrateCm)
  587. {
  588. return ERROR_SUCCESS;
  589. }
  590. else
  591. {
  592. return ERROR_NOT_INSTALLED;
  593. }
  594. }
  595. //+----------------------------------------------------------------------------
  596. //
  597. // Function: MigrateUserNT
  598. //
  599. // Synopsis: Called once per migrated user on win2k. Used to migrated any
  600. // per user settings saved from MigrateUser9x.
  601. //
  602. // Arguments: IN HINF UnattendInfHandle - valid inf handle to unattend.txt,
  603. // for use with the setup API's
  604. // IN HKEY UserRegHandle - HKEY_CURRENT_USER of the user currently
  605. // being migrated
  606. // IN LPCWSTR UserName - username of the user currently being migrated
  607. // LPVOID Reserved - reserved
  608. //
  609. // Returns: LONG - ERROR_SUCCESS or a win32 error code (will abort migration dll
  610. // processing)
  611. //
  612. // History: quintinb Created Header 8/27/98
  613. //
  614. //+----------------------------------------------------------------------------
  615. LONG
  616. CALLBACK MigrateUserNT(IN HINF UnattendInfHandle, IN HKEY UserRegHandle,
  617. IN LPCWSTR UserName, LPVOID Reserved)
  618. {
  619. return ERROR_SUCCESS;
  620. }
  621. //+----------------------------------------------------------------------------
  622. //
  623. // Function: MigrateSystemNT
  624. //
  625. // Synopsis: Called to allow system wide migration changes to be made on the
  626. // Win2k side.
  627. //
  628. // Arguments: IN HINF UnattendInfHandle - handle to the unattend.txt file
  629. // LPVOID Reserved - reserved
  630. //
  631. // Returns: LONG - ERROR_SUCCESS or a win32 error code (will abort migration dll
  632. // processing)
  633. //
  634. // History: quintinb Created Header 8/27/98
  635. //
  636. //+----------------------------------------------------------------------------
  637. LONG
  638. CALLBACK MigrateSystemNT(IN HINF UnattendInfHandle, LPVOID Reserved)
  639. {
  640. LONG lReturn = ERROR_NOT_INSTALLED;
  641. DWORD dwDisposition;
  642. TCHAR szSystemDir[MAX_PATH+1];
  643. if (0 == GetSystemDirectory(szSystemDir, MAX_PATH))
  644. {
  645. return GetLastError();
  646. }
  647. const TCHAR* const c_pszSystemFmt = TEXT("%s\\system\\%s.inf");
  648. const TCHAR* const c_pszValueString = TEXT("Connection Manager Profiles Upgrade");
  649. const TCHAR* const c_pszRegRunKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
  650. const TCHAR* const c_pszCmdLine = TEXT("cmstp.exe /m");
  651. if (g_bMigrateCmak10 && (TEXT('\0') != g_szCmakPath[0]) && (TEXT('\0') != g_szWorkingDir[0]))
  652. {
  653. TCHAR szDest[MAX_PATH+1];
  654. TCHAR szSrc[MAX_PATH+1];
  655. for (int i=0; i < c_NumFiles; i++)
  656. {
  657. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s%s"), g_szCmakPath,
  658. OriginalNames[i]));
  659. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s%s"), g_szWorkingDir,
  660. TempNames[i]));
  661. if (FileExists(szSrc))
  662. {
  663. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  664. }
  665. }
  666. lReturn &= ERROR_SUCCESS;
  667. }
  668. else if (g_bMigrateCmak121 && (TEXT('\0') != g_szCmakPath[0]) &&
  669. (TEXT('\0') != szSystemDir[0]))
  670. {
  671. TCHAR szDest[MAX_PATH+1];
  672. TCHAR szSrc[MAX_PATH+1];
  673. //
  674. // Copy w95inf16.tmp in the working dir back to the systemdir and rename it .dll
  675. //
  676. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), g_szWorkingDir,
  677. c_pszW95Inf16, c_pszTmp));
  678. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), szSystemDir,
  679. c_pszW95Inf16, c_pszDll));
  680. if (FileExists(szSrc))
  681. {
  682. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  683. }
  684. //
  685. // Copy w95inf32.tmp in the working dir back to the systemdir and rename it .dll
  686. //
  687. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s\\%s%s"), g_szWorkingDir,
  688. c_pszW95Inf32, c_pszTmp));
  689. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s%s"), szSystemDir,
  690. c_pszW95Inf32, c_pszDll));
  691. if (FileExists(szSrc))
  692. {
  693. MYVERIFY(FALSE != CopyFile(szSrc, szDest, FALSE));
  694. }
  695. lReturn &= ERROR_SUCCESS;
  696. }
  697. if (g_bMigrateCm)
  698. {
  699. //
  700. // Enumerate all the installed profiles on the machine. For each profile check to
  701. // see if the profile inf is located in the system (that's system not system32) dir.
  702. // If it is, then we need to move it to system32 so that our code will know where to
  703. // find it.
  704. //
  705. HKEY hKey;
  706. HKEY hTempKey;
  707. TCHAR szSource[MAX_PATH+1];
  708. TCHAR szDest[MAX_PATH+1];
  709. TCHAR szLongServiceName[MAX_PATH+1];
  710. TCHAR szWindowsDir[MAX_PATH+1];
  711. TCHAR szCmpPath[MAX_PATH+1];
  712. //
  713. // Get the Windows directory and the system directory
  714. //
  715. if (0 == GetWindowsDirectory(szWindowsDir, MAX_PATH))
  716. {
  717. return GetLastError();
  718. }
  719. if (0 == GetSystemDirectory(szSystemDir, MAX_PATH))
  720. {
  721. return GetLastError();
  722. }
  723. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmMappings,
  724. 0, KEY_READ, &hKey))
  725. {
  726. DWORD dwIndex = 0;
  727. DWORD dwValueSize = MAX_PATH;
  728. DWORD dwDataSize = MAX_PATH;
  729. DWORD dwType;
  730. while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, szLongServiceName,
  731. &dwValueSize, NULL, &dwType, (LPBYTE)szCmpPath, &dwDataSize))
  732. {
  733. if (REG_SZ == dwType)
  734. {
  735. MYDBGASSERT(TEXT('\0') != szLongServiceName[0]);
  736. MYDBGASSERT(TEXT('\0') != szCmpPath[0]);
  737. CFileNameParts CmpPath(szCmpPath);
  738. MYVERIFY(CELEMS(szSource) > (UINT)wsprintf(szSource, c_pszSystemFmt, szWindowsDir, CmpPath.m_FileName));
  739. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s.inf"), szSystemDir, CmpPath.m_FileName));
  740. if (CopyFile(szSource, szDest, FALSE))
  741. {
  742. DeleteFile(szSource);
  743. }
  744. }
  745. dwValueSize = MAX_PATH;
  746. dwDataSize = MAX_PATH;
  747. dwIndex++;
  748. if (dwIndex == g_dwNumValues)
  749. {
  750. break;
  751. }
  752. }
  753. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  754. }
  755. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_pszRegRunKey, 0, NULL,
  756. REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &hKey, &dwDisposition))
  757. {
  758. RegSetValueEx(hKey, c_pszValueString, 0, REG_SZ, (CONST BYTE*)c_pszCmdLine,
  759. sizeof(TCHAR)*(lstrlen(c_pszCmdLine)+1));
  760. RegCloseKey(hKey);
  761. }
  762. lReturn &= ERROR_SUCCESS;
  763. }
  764. return lReturn;
  765. }
  766. //+----------------------------------------------------------------------------
  767. //
  768. // Function: EnsureEncryptedPasswordInCmpIfSaved
  769. //
  770. // Synopsis: This function is called on the Win9x side of the migration so
  771. // that if a password is in the Win9x password cache (which only
  772. // happens if the user has profiling enabled), it will be retrieved,
  773. // encrypted, and written to the cmp. This enables CM to populate
  774. // a users registry with the starting password whenever they first
  775. // launch the CM profile. This no functionality is lost from the
  776. // shared password feature that win9x had.
  777. //
  778. // Arguments: szLongServiceName - Service name of the profile to retrieve
  779. // the password for
  780. // szCmpPath - full path to the cmp to write the password too
  781. //
  782. // Returns: BOOL - returns TRUE if successful
  783. //
  784. // History: quintinb Created 08/27/98
  785. // nickball CmWipePassword 08/04/99
  786. //
  787. //+----------------------------------------------------------------------------
  788. BOOL EnsureEncryptedPasswordInCmpIfSaved(LPCTSTR pszLongServiceName, LPCTSTR pszCmpPath)
  789. {
  790. TCHAR szPassword[MAX_PATH+1] = TEXT("");
  791. TCHAR szCacheEntryName[MAX_PATH+1];
  792. TCHAR szEncryptedPassword[MAX_PATH+1];
  793. DWORD dwSize;
  794. DWORD dwCryptType = 0;
  795. GetCachedPassword pfnGetCachedPassword = NULL;
  796. int iTemp=0;
  797. CDynamicLibrary MprDll(TEXT("mpr.dll"));
  798. iTemp = GetPrivateProfileInt(c_pszCmSection, c_pszCmEntryRememberPwd, 0, pszCmpPath);
  799. if (iTemp)
  800. {
  801. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryPassword, TEXT(""), szPassword, MAX_PATH, pszCmpPath);
  802. if (TEXT('\0') == szPassword[0])
  803. {
  804. //
  805. // The string must be in the password cache. Build the key string
  806. // for the cache.
  807. //
  808. MYVERIFY(CELEMS(szCacheEntryName) > (UINT)wsprintf(szCacheEntryName,
  809. TEXT("%s - Sign-In (Connection Manager)"), pszLongServiceName));
  810. pfnGetCachedPassword = (GetCachedPassword)MprDll.GetProcAddress(TEXT("WNetGetCachedPassword"));
  811. if (NULL == pfnGetCachedPassword)
  812. {
  813. CmWipePassword(szPassword);
  814. return FALSE;
  815. }
  816. else
  817. {
  818. WORD wStr = (WORD)256;
  819. if (ERROR_SUCCESS == pfnGetCachedPassword(szCacheEntryName,
  820. (WORD)lstrlen(szCacheEntryName), szPassword, &wStr, 80))
  821. {
  822. //
  823. // Okay, we retrived the password, now lets encrypt it and write it
  824. // to the cmp
  825. //
  826. if (EncryptPassword(szPassword, szEncryptedPassword, &dwSize, &dwCryptType))
  827. {
  828. //
  829. // Write the encrypted password
  830. //
  831. WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPassword, szEncryptedPassword,
  832. pszCmpPath);
  833. //
  834. // Write the encryption type
  835. //
  836. wsprintf(szPassword, TEXT("%u"), dwCryptType);
  837. WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPcs, szPassword,
  838. pszCmpPath);
  839. }
  840. }
  841. }
  842. }
  843. }
  844. //
  845. // Now do the same for the Internet Password
  846. //
  847. iTemp = GetPrivateProfileInt(c_pszCmSection, c_pszCmEntryRememberInetPwd, 0, pszCmpPath);
  848. if (iTemp)
  849. {
  850. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryInetPassword, TEXT(""), szPassword, MAX_PATH, pszCmpPath);
  851. if (TEXT('\0') == szPassword[0])
  852. {
  853. //
  854. // The string must be in the password cache. Build the key string
  855. // for the cache.
  856. //
  857. MYVERIFY(CELEMS(szCacheEntryName) > (UINT)wsprintf(szCacheEntryName,
  858. TEXT("%s - Sign-In (Connection Manager)-tunnel"), pszLongServiceName));
  859. pfnGetCachedPassword = (GetCachedPassword)MprDll.GetProcAddress(TEXT("WNetGetCachedPassword"));
  860. if (NULL == pfnGetCachedPassword)
  861. {
  862. CmWipePassword(szPassword);
  863. return FALSE;
  864. }
  865. else
  866. {
  867. WORD wStr = (WORD)256;
  868. if (ERROR_SUCCESS == pfnGetCachedPassword(szCacheEntryName,
  869. (WORD)lstrlen(szCacheEntryName), szPassword, &wStr, 80))
  870. {
  871. //
  872. // Okay, we retrived the password, now lets encrypt it and write it
  873. // to the cmp
  874. //
  875. dwCryptType = 0;
  876. if (EncryptPassword(szPassword, szEncryptedPassword, &dwSize, &dwCryptType))
  877. {
  878. //
  879. // Write the encrypted password
  880. //
  881. WritePrivateProfileString(c_pszCmSection, c_pszCmEntryInetPassword, szEncryptedPassword,
  882. pszCmpPath);
  883. //
  884. // Write the encryption type
  885. //
  886. wsprintf(szPassword, TEXT("%u"), dwCryptType);
  887. WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPcs, szPassword,
  888. pszCmpPath);
  889. }
  890. }
  891. }
  892. }
  893. }
  894. CmWipePassword(szPassword);
  895. return TRUE;
  896. }
  897. //+----------------------------------------------------------------------------
  898. //
  899. // Function: EncryptPassword
  900. //
  901. // Synopsis:
  902. //
  903. // Arguments: IN LPCTSTR pszPassword -
  904. // OUT LPTSTR pszEncryptedPassword -
  905. // OUT LPDWORD lpdwBufSize -
  906. // OUT LPDWORD lpdwCryptType -
  907. //
  908. // Returns: BOOL -
  909. //
  910. // History: quintinb Created Header 8/27/98
  911. // nickball CmWipePassword 08/04/99
  912. //
  913. //+----------------------------------------------------------------------------
  914. BOOL EncryptPassword(IN LPCTSTR pszPassword, OUT LPTSTR pszEncryptedPassword, OUT LPDWORD lpdwBufSize, OUT LPDWORD lpdwCryptType)
  915. {
  916. MYDBGASSERT(pszPassword);
  917. MYDBGASSERT(pszEncryptedPassword);
  918. MYDBGASSERT(lpdwBufSize);
  919. MYDBGASSERT(lpdwCryptType);
  920. DWORD dwEncryptedBufferLen;
  921. DWORD dwSize = 0;
  922. LPTSTR pszEncryptedData = NULL;
  923. TCHAR szSourceData[PWLEN + sizeof(TCHAR)];
  924. if ((NULL == pszPassword) || (NULL == pszEncryptedPassword) || (NULL == lpdwBufSize))
  925. {
  926. return NULL;
  927. }
  928. //
  929. // Standard encryption, copy the password
  930. //
  931. lstrcpy(szSourceData, pszPassword);
  932. //
  933. // It is not safe to call InitSecure more than once
  934. //
  935. if (!g_fInitSecureCalled)
  936. {
  937. BOOL bFastEncryption = FALSE;
  938. MYVERIFY(FALSE != ReadEncryptionOption(&bFastEncryption));
  939. InitSecure(bFastEncryption);
  940. g_fInitSecureCalled = TRUE;
  941. }
  942. //
  943. // Encrypt the provided password
  944. //
  945. if (EncryptData((LPBYTE)szSourceData, (lstrlen(szSourceData)+1) * sizeof(TCHAR),
  946. (LPBYTE*)&pszEncryptedData, &dwEncryptedBufferLen, lpdwCryptType, NULL, NULL, NULL))
  947. {
  948. if (lpdwBufSize)
  949. {
  950. *lpdwBufSize = dwEncryptedBufferLen;
  951. }
  952. if (pszEncryptedData)
  953. {
  954. _tcscpy(pszEncryptedPassword, pszEncryptedData);
  955. HeapFree(GetProcessHeap(), 0, pszEncryptedData);
  956. pszEncryptedData = NULL;
  957. CmWipePassword(szSourceData);
  958. return TRUE;
  959. }
  960. }
  961. CmWipePassword(szSourceData);
  962. return FALSE;
  963. }
  964. //+----------------------------------------------------------------------------
  965. //
  966. // Function: ReadEncryptionOption
  967. //
  968. // Synopsis:
  969. //
  970. // Arguments: BOOL* pfFastEncryption - boolean to fill in with fast encryption flag
  971. //
  972. // Returns: BOOL - TRUE if successful
  973. //
  974. // History: quintinb Created Header 8/27/98
  975. // copied from the version written by Fengsun in cmdial\connect.cpp
  976. //
  977. //+----------------------------------------------------------------------------
  978. BOOL ReadEncryptionOption(BOOL* pfFastEncryption)
  979. {
  980. HKEY hKeyCm;
  981. DWORD dwType;
  982. DWORD dwSize = sizeof(DWORD);
  983. MYDBGASSERT(pfFastEncryption != NULL);
  984. *pfFastEncryption = FALSE;
  985. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmRoot, 0,
  986. KEY_QUERY_VALUE ,&hKeyCm))
  987. {
  988. RegQueryValueEx(hKeyCm, c_pszRegCmEncryptOption, NULL, &dwType,
  989. (BYTE*)pfFastEncryption, &dwSize);
  990. RegCloseKey(hKeyCm);
  991. }
  992. return TRUE;
  993. }