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.

1099 lines
33 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. filescan.c
  5. Abstract:
  6. This source file deals with file scanning phase.
  7. Author:
  8. Calin Negreanu (calinn) 09-Feb-1998
  9. Revision History:
  10. ovidiut 22-May-1999 Made AddMigrationPath globally accessible through w95upg.h
  11. jimschm 23-Sep-1998 mapif.h removal,
  12. calinn 31-Mar-1998 Dir recursion limited to ENUM_MAX_LEVELS (1024)
  13. --*/
  14. #include "pch.h"
  15. #include "migappp.h"
  16. #include "migdbp.h"
  17. #define PROGBAR_DIR_LEVEL 2
  18. #define MAX_BACKUPDIRS_IN_REPORT 5
  19. GROWBUFFER g_OtherOsPaths = GROWBUF_INIT;
  20. DWORD g_ProgressBarTicks;
  21. BOOL g_OtherOsExists = FALSE;
  22. BOOL g_IsFusionDir = FALSE;
  23. HASHTABLE g_UseNtFileHashTable;
  24. #define WINNT_FLAT TEXT("WINNT.EXE")
  25. #define WIN9X_FLAT TEXT("WINSETUP.BIN")
  26. #define WIN98_FLAT TEXT("W98SETUP.BIN")
  27. #define WIN3X_FLAT_1 TEXT("KRNL386.EX_")
  28. #define WIN3X_FLAT_2 TEXT("KERNEL.EXE")
  29. #define WINNT_INSTALLATION TEXT("SYSTEM32\\NTOSKRNL.EXE")
  30. #define WIN9X_INSTALLATION TEXT("SYSTEM\\KERNEL32.DLL")
  31. #define WIN3X_INSTALLATION_1 TEXT("SYSTEM\\KRNL386.EXE")
  32. #define WIN3X_INSTALLATION_2 TEXT("SYSTEM\\KRNL386.EXE")
  33. #define WIN3X_INSTALLATION_3 TEXT("SYSTEM\\KERNEL.EXE")
  34. #define WINNT_SETUP_1 TEXT(":\\$WIN_NT$.~BT")
  35. #define WINNT_SETUP_2 TEXT(":\\$WIN_NT$.~LS")
  36. #define RECYCLE_1 TEXT(":\\RECYCLED")
  37. #define RECYCLE_2 TEXT(":\\RECYCLER")
  38. BOOL
  39. pSpecialExcludedDir (
  40. IN PCTSTR FullFileSpec
  41. )
  42. {
  43. PCTSTR testPath = NULL;
  44. BOOL Result = TRUE;
  45. __try {
  46. if (StringIMatch (g_WinDir, FullFileSpec)) {
  47. Result = FALSE;
  48. __leave;
  49. }
  50. //
  51. // let's see if it's one of our dirs.
  52. //
  53. if (((*SOURCEDIRECTORY(0))&&(StringIMatch (FullFileSpec, SOURCEDIRECTORY(0)) )) ||
  54. ((*g_TempDirWack )&&(StringIMatchCharCount (FullFileSpec, g_TempDirWack, g_TempDirWackChars-1) )) ||
  55. ((*g_PlugInDirWack )&&(StringIMatchCharCount (FullFileSpec, g_PlugInDirWack, g_PlugInDirWackChars-1) )) ||
  56. ((*g_RecycledDirWack )&&(StringIMatchCharCount (FullFileSpec, g_RecycledDirWack, g_RecycledDirWackChars-1) ))) {
  57. __leave;
  58. }
  59. //
  60. //we are trying to see if we are entering a winnt, win95 or win3.x
  61. //flat directory
  62. //
  63. testPath = JoinPaths (FullFileSpec, WINNT_FLAT);
  64. if (DoesFileExist (testPath)) {
  65. __leave;
  66. }
  67. FreePathString (testPath);
  68. testPath = JoinPaths (FullFileSpec, WIN9X_FLAT);
  69. if (DoesFileExist (testPath)) {
  70. __leave;
  71. }
  72. FreePathString (testPath);
  73. testPath = JoinPaths (FullFileSpec, WIN98_FLAT);
  74. if (DoesFileExist (testPath)) {
  75. __leave;
  76. }
  77. FreePathString (testPath);
  78. testPath = JoinPaths (FullFileSpec, WIN3X_FLAT_1);
  79. if (DoesFileExist (testPath)) {
  80. __leave;
  81. }
  82. FreePathString (testPath);
  83. testPath = JoinPaths (FullFileSpec, WIN3X_FLAT_2);
  84. if (DoesFileExist (testPath)) {
  85. __leave;
  86. }
  87. FreePathString (testPath);
  88. //
  89. //we are trying to see if we are entering a winnt installation,
  90. //win95 installation or win3.x installation
  91. //
  92. testPath = JoinPaths (FullFileSpec, WINNT_INSTALLATION);
  93. if (DoesFileExist (testPath)) {
  94. MultiSzAppend (&g_OtherOsPaths, FullFileSpec);
  95. __leave;
  96. }
  97. FreePathString (testPath);
  98. if (FullFileSpec [0]) {
  99. testPath = _tcsinc (FullFileSpec);
  100. if ((StringIMatch (testPath, WINNT_SETUP_1)) ||
  101. (StringIMatch (testPath, WINNT_SETUP_2)) ||
  102. (StringIMatch (testPath, RECYCLE_1 )) ||
  103. (StringIMatch (testPath, RECYCLE_2 ))) {
  104. testPath = NULL;
  105. __leave;
  106. }
  107. }
  108. testPath = NULL;
  109. Result = FALSE;
  110. }
  111. __finally {
  112. if (testPath) {
  113. FreePathString (testPath);
  114. testPath = NULL;
  115. }
  116. }
  117. return Result;
  118. }
  119. INT
  120. pCountDirectories (
  121. IN PCTSTR FullPath,
  122. IN PCTSTR DontCare,
  123. IN WIN32_FIND_DATA *FindData,
  124. IN DWORD EnumHandle,
  125. IN PVOID Params,
  126. PDWORD CurrentDirData
  127. )
  128. {
  129. if (pSpecialExcludedDir (FullPath)) {
  130. ExcludePath (g_ExclusionValue, FullPath);
  131. return CALLBACK_DO_NOT_RECURSE_THIS_DIRECTORY;
  132. }
  133. if (!(FindData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) {
  134. g_ProgressBarTicks += TICKS_FILESCAN_DIR_INCREMENT;
  135. }
  136. return CALLBACK_CONTINUE;
  137. }
  138. DWORD
  139. FileScan_GetProgressMax (
  140. VOID
  141. )
  142. {
  143. ACCESSIBLE_DRIVE_ENUM e;
  144. DWORD Count = 0;
  145. g_ProgressBarTicks = 0;
  146. //
  147. // Enumerate of the accessible drives. The callback routine will keep track of all
  148. // of the directories on that drive to a depth of two.
  149. //
  150. if (GetFirstAccessibleDriveEx (&e, TRUE)) {
  151. do {
  152. //
  153. // restrict file system analyze to the windows drive
  154. //
  155. if (!EnumerateTree (
  156. e->Drive,
  157. pCountDirectories,
  158. NULL, // failure-logging callback
  159. g_ExclusionValue ,
  160. NULL, // unused
  161. PROGBAR_DIR_LEVEL,
  162. NULL, // Unused exclusion structure.
  163. FILTER_DIRECTORIES
  164. )) {
  165. LOG((LOG_ERROR,"Error counting directories on drive %s.",e->Drive));
  166. }
  167. } while (GetNextAccessibleDrive(&e));
  168. }
  169. DEBUGLOGTIME (("FileScan_GetProgressMax estimation: %lu", g_ProgressBarTicks));
  170. return g_ProgressBarTicks;
  171. }
  172. INT
  173. pGetDirLevel (
  174. IN PCTSTR DirName
  175. )
  176. {
  177. INT result = 0;
  178. PCTSTR dirPtr = DirName;
  179. do {
  180. dirPtr = _tcschr (dirPtr, TEXT('\\'));
  181. if (dirPtr != NULL) {
  182. result++;
  183. dirPtr = _tcsinc (dirPtr);
  184. if (dirPtr[0] == 0) {
  185. result--;
  186. dirPtr = NULL;
  187. }
  188. }
  189. }
  190. while (dirPtr);
  191. return result;
  192. }
  193. INT
  194. pProcessFileOrDir (
  195. IN PCTSTR FullFileSpec,
  196. IN PCTSTR DontCare,
  197. IN WIN32_FIND_DATA *FindData,
  198. IN DWORD EnumHandle,
  199. IN LPVOID Params,
  200. IN OUT PDWORD CurrentDirData
  201. )
  202. {
  203. FILE_HELPER_PARAMS HelperParams;
  204. INT result = CALLBACK_CONTINUE;
  205. if (CANCELLED()) {
  206. SetLastError (ERROR_CANCELLED);
  207. return CALLBACK_FAILED;
  208. }
  209. #ifdef DEBUG
  210. {
  211. TCHAR DbgBuf[256];
  212. if (GetPrivateProfileString ("FileScan", FullFileSpec, "", DbgBuf, 256, g_DebugInfPath)) {
  213. DEBUGMSG ((DBG_NAUSEA, "%s found", FullFileSpec));
  214. }
  215. if (GetPrivateProfileString ("FileScan", "All", "", DbgBuf, 256, g_DebugInfPath)) {
  216. DEBUGMSG ((DBG_NAUSEA, "%s", FullFileSpec));
  217. }
  218. }
  219. #endif
  220. if (!SafeModeActionCrashed (SAFEMODEID_FILES, FullFileSpec)) {
  221. SafeModeRegisterAction(SAFEMODEID_FILES, FullFileSpec);
  222. __try {
  223. //
  224. //prepare structure for calling helper functions
  225. //
  226. HelperParams.FullFileSpec = FullFileSpec;
  227. HelperParams.Handled = 0;
  228. HelperParams.FindData = FindData;
  229. HelperParams.Extension = GetDotExtensionFromPath (HelperParams.FullFileSpec);
  230. HelperParams.VirtualFile = (FindData == NULL);
  231. HelperParams.CurrentDirData = CurrentDirData;
  232. if (FindData) {
  233. if ((FindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
  234. if (pGetDirLevel (FullFileSpec) <= PROGBAR_DIR_LEVEL) {
  235. // This is an increment point
  236. if (!TickProgressBarDelta (TICKS_FILESCAN_DIR_INCREMENT)) {
  237. SetLastError (ERROR_CANCELLED);
  238. result = CALLBACK_FAILED;
  239. __leave;
  240. }
  241. ProgressBar_SetSubComponent (FullFileSpec);
  242. }
  243. //
  244. // If we know that this dir has something special and we must exclude it
  245. // if you need to add code to exclude some dir plug it in pSpecialExcludedDir
  246. //
  247. if (pSpecialExcludedDir (FullFileSpec)) {
  248. result = CALLBACK_DO_NOT_RECURSE_THIS_DIRECTORY;
  249. __leave;
  250. }
  251. _tcssafecpy (HelperParams.DirSpec, FullFileSpec, MAX_TCHAR_PATH);
  252. HelperParams.IsDirectory = TRUE;
  253. }
  254. else {
  255. _tcssafecpyab (HelperParams.DirSpec, FullFileSpec, GetFileNameFromPath (FullFileSpec), MAX_TCHAR_PATH);
  256. HelperParams.IsDirectory = FALSE;
  257. }
  258. } else {
  259. HelperParams.IsDirectory = FALSE;
  260. }
  261. // calling the process helper functions
  262. if (!ProcessFileHelpers (&HelperParams)) {
  263. result = CALLBACK_FAILED;
  264. __leave;
  265. }
  266. }
  267. __finally {
  268. }
  269. SafeModeUnregisterAction();
  270. }
  271. return result;
  272. }
  273. static
  274. BOOL
  275. pExamineAccessibleDrive (
  276. IN ACCESSIBLE_DRIVE_ENUM Enum
  277. )
  278. {
  279. BOOL fRet = TRUE;
  280. //
  281. // Enumerate volume. FALSE retval ends enumeration; callback sets last error.
  282. //
  283. SetLastError (ERROR_SUCCESS);
  284. if (!(fRet = EnumerateTree (
  285. Enum -> Drive,
  286. pProcessFileOrDir,
  287. NULL, // No failure callback
  288. g_ExclusionValue,
  289. NULL, // Params - Unused.
  290. ENUM_MAX_LEVELS,
  291. NULL,
  292. FILTER_ALL
  293. ))
  294. ) {
  295. DEBUGMSG_IF ((
  296. GetLastError() != ERROR_SUCCESS &&
  297. GetLastError() != ERROR_PATH_NOT_FOUND &&
  298. GetLastError() != ERROR_CANCELLED,
  299. DBG_ERROR,
  300. "pAccessibleDrivesEnum_Callback: EnumerateTree failed."
  301. ));
  302. if (GetLastError() != ERROR_SUCCESS &&
  303. GetLastError() != ERROR_PATH_NOT_FOUND &&
  304. GetLastError() != ERROR_CANCELLED) {
  305. LOG ((
  306. LOG_ERROR,
  307. "Failure while enumerating tree. rc: %u",
  308. GetLastError()
  309. ));
  310. }
  311. }
  312. return fRet;
  313. }
  314. VOID
  315. pReportOtherOs (
  316. VOID
  317. )
  318. /*
  319. This function will report if other OS was found in the system. It will also report (with a strong message) if PATH variable points to
  320. some directories that belong to some other OSes.
  321. */
  322. {
  323. MULTISZ_ENUM enumOsPaths;
  324. PCTSTR Group;
  325. PCTSTR Message;
  326. if (g_ConfigOptions.IgnoreOtherOS) {
  327. return;
  328. }
  329. if (g_OtherOsExists) {
  330. //
  331. // Already done.
  332. //
  333. return;
  334. }
  335. if (EnumFirstMultiSz (&enumOsPaths, g_OtherOsPaths.Buf)) {
  336. g_OtherOsExists = TRUE;
  337. Group = BuildMessageGroup (MSG_BLOCKING_ITEMS_ROOT, MSG_OTHER_OS_WARNING_SUBGROUP, NULL);
  338. Message = GetStringResource (MSG_OTHER_OS_WARNING);
  339. if (Message && Group) {
  340. MsgMgr_ObjectMsg_Add (TEXT("*OtherOsFound"), Group, Message);
  341. }
  342. FreeText (Group);
  343. FreeStringResource (Message);
  344. }
  345. }
  346. VOID
  347. AddMigrationPathEx (
  348. IN PCTSTR PathLong,
  349. IN DWORD Levels,
  350. IN BOOL Win9xOsPath
  351. )
  352. /*++
  353. Routine Description:
  354. AddMigrationPath adds the specified path to MEMDB_CATEGORY_MIGRATION_PATHS,
  355. ensuring that PathLong is not a drive root; in this case Levels is set to 0
  356. Arguments:
  357. PathLong - Specifies the path to be added (long file name format)
  358. Levels - Specifies how many levels (subdirs) are valid
  359. Win9xOsPath - Specifies TRUE if the path supplied should be treated as an OS path
  360. Return Value:
  361. none
  362. --*/
  363. {
  364. TCHAR key[MEMDB_MAX];
  365. //
  366. // a drive spec is supposed to be one driveletter followed by a column (eg. l:)
  367. //
  368. if (_istalpha (PathLong[0]) && PathLong[1] == TEXT(':') &&
  369. (PathLong[2] == 0 || PathLong[2] == TEXT('\\') && PathLong[3] == 0)) {
  370. //
  371. // this is the root of a drive, so override Levels
  372. //
  373. Levels = 0;
  374. }
  375. if (StringIMatch (PathLong, g_ProgramFilesDir)) {
  376. Levels = 0;
  377. }
  378. MemDbBuildKey (key, MEMDB_CATEGORY_MIGRATION_PATHS, PathLong, NULL, NULL);
  379. MemDbSetValueAndFlags (key, Levels, Win9xOsPath ? TRUE : FALSE, 0);
  380. }
  381. VOID
  382. pAddValueEnumDirsAsMigDirs (
  383. IN PCTSTR Key,
  384. IN DWORD Levels
  385. )
  386. {
  387. HKEY key;
  388. REGVALUE_ENUM e;
  389. TCHAR pathLong[MAX_TCHAR_PATH];
  390. PTSTR Data;
  391. PCTSTR pathExp;
  392. PTSTR filePtr;
  393. key = OpenRegKeyStr (Key);
  394. if (key != NULL) {
  395. if (EnumFirstRegValue (&e, key)) {
  396. do {
  397. Data = GetRegValueString (e.KeyHandle, e.ValueName);
  398. if (Data) {
  399. ExtractArgZeroEx (Data, pathLong, NULL, FALSE);
  400. if (*pathLong) {
  401. pathExp = ExpandEnvironmentTextA(pathLong);
  402. if (pathExp) {
  403. // eliminate the file name
  404. filePtr = (PTSTR)GetFileNameFromPath (pathExp);
  405. if (filePtr) {
  406. filePtr = _tcsdec (pathExp, filePtr);
  407. if (filePtr) {
  408. *filePtr = 0;
  409. }
  410. }
  411. if (filePtr && OurGetLongPathName (pathExp, pathLong, MAX_TCHAR_PATH)) {
  412. AddMigrationPath (pathLong, Levels);
  413. }
  414. FreeText (pathExp);
  415. }
  416. }
  417. MemFree (g_hHeap, 0, Data);
  418. }
  419. }
  420. while (EnumNextRegValue (&e));
  421. }
  422. CloseRegKey (key);
  423. }
  424. }
  425. VOID
  426. pBuildMigrationPaths (
  427. VOID
  428. )
  429. /*
  430. This function will create a list with all the paths that are considered "ours". Any other path that has OS files in it is considered
  431. a backup path. If an OS file is found in a "backup" path a warning is presented to the user.
  432. */
  433. {
  434. PCTSTR pathExp = NULL;
  435. TCHAR pathLong [MAX_TCHAR_PATH];
  436. CHAR pathExpAnsi [MAX_TCHAR_PATH];
  437. PATH_ENUM pathEnum;
  438. TCHAR dirName [MAX_TCHAR_PATH];
  439. INFCONTEXT context;
  440. PCTSTR argList[]={"ProgramFiles", g_ProgramFilesDir, "SystemDrive", g_WinDrive, NULL};
  441. HKEY appPathsKey, currentAppKey;
  442. REGKEY_ENUM appPathsEnum;
  443. PCTSTR appPaths = NULL;
  444. MEMDB_ENUM eFolder;
  445. TREE_ENUM eFile;
  446. PCTSTR extPtr;
  447. TCHAR shortcutTarget [MAX_TCHAR_PATH];
  448. TCHAR shortcutArgs [MAX_TCHAR_PATH];
  449. TCHAR shortcutWorkDir [MAX_TCHAR_PATH];
  450. TCHAR shortcutIconPath [MAX_TCHAR_PATH];
  451. INT shortcutIcon;
  452. WORD shortcutHotKey;
  453. BOOL msDosMode;
  454. IShellLink *shellLink;
  455. IPersistFile *persistFile;
  456. PTSTR filePtr;
  457. HKEY sharedDllsKey;
  458. REGVALUE_ENUM sharedDllsEnum;
  459. DWORD Levels;
  460. //
  461. // First thing. Include PATH variable and root of the boot drive in our migration paths.
  462. //
  463. AddMigrationPath (g_BootDrive, 0);
  464. if (EnumFirstPath (&pathEnum, NULL, g_WinDir, g_SystemDir)) {
  465. do {
  466. pathExp = ExpandEnvironmentTextA(pathEnum.PtrCurrPath);
  467. filePtr = (PTSTR)GetFileNameFromPath (pathExp);
  468. if (*filePtr == 0) {
  469. filePtr = _tcsdec (pathExp, filePtr);
  470. if (filePtr) {
  471. *filePtr = 0;
  472. }
  473. }
  474. if (OurGetLongPathName (pathExp, pathLong, MAX_TCHAR_PATH)) {
  475. AddMigrationPathEx (pathLong, 2, TRUE);
  476. }
  477. FreeText (pathExp);
  478. }
  479. while (EnumNextPath (&pathEnum));
  480. EnumPathAbort (&pathEnum);
  481. }
  482. //
  483. // Then include temporary directory as a tree
  484. //
  485. if (GetTempPath (MAX_TCHAR_PATH, pathLong)) {
  486. // eliminate \ from the end of a path
  487. filePtr = GetEndOfString (pathLong);
  488. filePtr = _tcsdec (pathLong, filePtr);
  489. if ((filePtr) &&
  490. (*filePtr == TEXT('\\'))
  491. ) {
  492. *filePtr = 0;
  493. }
  494. AddMigrationPath (pathLong, MAX_DEEP_LEVELS);
  495. }
  496. //
  497. // Then include known directories from win95upg.inf section "MigrationDirs".
  498. //
  499. MYASSERT (g_Win95UpgInf != INVALID_HANDLE_VALUE);
  500. if (SetupFindFirstLine (g_Win95UpgInf, S_MIGRATION_DIRS, NULL, &context)) {
  501. do {
  502. if (SetupGetStringField (&context, 1, dirName, MAX_TCHAR_PATH, NULL)) {
  503. pathExp = ExpandEnvironmentTextExA(dirName, argList);
  504. if (pathExp) {
  505. filePtr = (PTSTR)GetFileNameFromPath (pathExp);
  506. if (*filePtr == 0) {
  507. filePtr = _tcsdec (pathExp, filePtr);
  508. if (filePtr) {
  509. *filePtr = 0;
  510. }
  511. }
  512. if (OurGetLongPathName (pathExp, pathLong, MAX_TCHAR_PATH)) {
  513. AddMigrationPathEx (pathLong, MAX_DEEP_LEVELS, TRUE);
  514. }
  515. //
  516. // also add the path translated to ANSI (if different)
  517. //
  518. OemToCharA (pathExp, pathExpAnsi);
  519. if (OurGetLongPathName (pathExpAnsi, pathLong, MAX_TCHAR_PATH)) {
  520. AddMigrationPathEx (pathLong, MAX_DEEP_LEVELS, TRUE);
  521. }
  522. FreeText (pathExp);
  523. }
  524. }
  525. }
  526. while (SetupFindNextLine (&context, &context));
  527. }
  528. //
  529. // Then include known OEM directories from win95upg.inf section "OemMigrationDirs".
  530. //
  531. if (SetupFindFirstLine (g_Win95UpgInf, S_OEM_MIGRATION_DIRS, NULL, &context)) {
  532. do {
  533. if (SetupGetStringField (&context, 1, dirName, MAX_TCHAR_PATH, NULL)) {
  534. pathExp = ExpandEnvironmentTextExA(dirName, argList);
  535. if (pathExp) {
  536. filePtr = (PTSTR)GetFileNameFromPath (pathExp);
  537. if (*filePtr == 0) {
  538. filePtr = _tcsdec (pathExp, filePtr);
  539. if (filePtr) {
  540. *filePtr = 0;
  541. }
  542. }
  543. if (OurGetLongPathName (pathExp, pathLong, MAX_TCHAR_PATH)) {
  544. Levels = 0;
  545. if (SetupGetStringField (&context, 2, dirName, MAX_TCHAR_PATH, NULL)) {
  546. if (_ttoi (dirName) != 0) {
  547. Levels = MAX_DEEP_LEVELS;
  548. }
  549. }
  550. AddMigrationPathEx (pathLong, Levels, TRUE);
  551. }
  552. FreeText (pathExp);
  553. }
  554. }
  555. }
  556. while (SetupFindNextLine (&context, &context));
  557. }
  558. //
  559. // Then include paths listed in SharedDlls key.
  560. //
  561. sharedDllsKey = OpenRegKeyStr (S_REG_SHARED_DLLS);
  562. if (sharedDllsKey != NULL) {
  563. if (EnumFirstRegValue (&sharedDllsEnum, sharedDllsKey)) {
  564. do {
  565. pathExp = ExpandEnvironmentTextA(sharedDllsEnum.ValueName);
  566. if (pathExp) {
  567. // eliminate the file name
  568. filePtr = (PTSTR)GetFileNameFromPath (pathExp);
  569. if (filePtr) {
  570. filePtr = _tcsdec (pathExp, filePtr);
  571. if (filePtr) {
  572. *filePtr = 0;
  573. }
  574. }
  575. if (OurGetLongPathName (pathExp, pathLong, MAX_TCHAR_PATH)) {
  576. AddMigrationPath (pathLong, 0);
  577. }
  578. FreeText (pathExp);
  579. }
  580. }
  581. while (EnumNextRegValue (&sharedDllsEnum));
  582. }
  583. CloseRegKey (sharedDllsKey);
  584. }
  585. //
  586. // Then include paths listed in AppPaths key.
  587. //
  588. appPathsKey = OpenRegKeyStr (S_SKEY_APP_PATHS);
  589. if (appPathsKey != NULL) {
  590. if (EnumFirstRegKey (&appPathsEnum, appPathsKey)) {
  591. do {
  592. currentAppKey = OpenRegKey (appPathsKey, appPathsEnum.SubKeyName);
  593. if (currentAppKey != NULL) {
  594. appPaths = GetRegValueString (currentAppKey, TEXT("Path"));
  595. if (appPaths != NULL) {
  596. if (EnumFirstPath (&pathEnum, appPaths, NULL, NULL)) {
  597. do {
  598. pathExp = ExpandEnvironmentTextA(pathEnum.PtrCurrPath);
  599. if (pathExp) {
  600. // eliminate \ from the end of a path
  601. filePtr = GetEndOfString (pathExp);
  602. filePtr = _tcsdec (pathExp, filePtr);
  603. if ((filePtr) &&
  604. (*filePtr == TEXT('\\'))
  605. ) {
  606. *filePtr = 0;
  607. }
  608. if (OurGetLongPathName (pathExp, pathLong, MAX_TCHAR_PATH)) {
  609. AddMigrationPath (pathLong, 2);
  610. }
  611. FreeText (pathExp);
  612. }
  613. }
  614. while (EnumNextPath (&pathEnum));
  615. EnumPathAbort (&pathEnum);
  616. }
  617. MemFree (g_hHeap, 0, appPaths);
  618. }
  619. CloseRegKey (currentAppKey);
  620. }
  621. }
  622. while (EnumNextRegKey (&appPathsEnum));
  623. }
  624. CloseRegKey (appPathsKey);
  625. }
  626. //
  627. // Then include paths listed in Run* keys.
  628. //
  629. pAddValueEnumDirsAsMigDirs (S_RUNKEY, 2);
  630. pAddValueEnumDirsAsMigDirs (S_RUNONCEKEY, 2);
  631. pAddValueEnumDirsAsMigDirs (S_RUNONCEEXKEY, 2);
  632. pAddValueEnumDirsAsMigDirs (S_RUNSERVICESKEY, 2);
  633. pAddValueEnumDirsAsMigDirs (S_RUNSERVICESONCEKEY, 2);
  634. pAddValueEnumDirsAsMigDirs (S_RUNKEY_USER, 2);
  635. pAddValueEnumDirsAsMigDirs (S_RUNONCEKEY_USER, 2);
  636. pAddValueEnumDirsAsMigDirs (S_RUNONCEEXKEY_USER, 2);
  637. pAddValueEnumDirsAsMigDirs (S_RUNONCEKEY_DEFAULTUSER, 2);
  638. pAddValueEnumDirsAsMigDirs (S_RUNONCEEXKEY_DEFAULTUSER, 2);
  639. pAddValueEnumDirsAsMigDirs (S_RUNKEY_DEFAULTUSER, 2);
  640. //
  641. // Finally include paths listed in all links from all user profiles.
  642. //
  643. if (InitCOMLink (&shellLink, &persistFile)) {
  644. if (MemDbEnumFirstValue (&eFolder, MEMDB_CATEGORY_NICE_PATHS"\\*", MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
  645. do {
  646. if (*eFolder.szName == 0) {
  647. continue;
  648. }
  649. // first: this directory is a migration directory
  650. AddMigrationPath (eFolder.szName, MAX_DEEP_LEVELS);
  651. //
  652. // For each shell folder we enumerate all links trying to get the path where the links are running
  653. //
  654. if (EnumFirstFileInTreeEx (&eFile, eFolder.szName, TEXT("*.*"), FALSE, FALSE, 0)) {
  655. do {
  656. if (!eFile.Directory) {
  657. extPtr = GetFileExtensionFromPath (eFile.Name);
  658. if (extPtr) {
  659. if (StringIMatch (extPtr, TEXT("LNK"))) {
  660. if (ExtractShellLinkInfo (
  661. shortcutTarget,
  662. shortcutArgs,
  663. shortcutWorkDir,
  664. shortcutIconPath,
  665. &shortcutIcon,
  666. &shortcutHotKey,
  667. NULL,
  668. eFile.FullPath,
  669. shellLink,
  670. persistFile
  671. )) {
  672. if (shortcutWorkDir [0] != 0) {
  673. AddMigrationPath (shortcutWorkDir, 2);
  674. }
  675. if (shortcutTarget [0] != 0) {
  676. filePtr = (PTSTR)GetFileNameFromPath (shortcutTarget);
  677. if (filePtr) {
  678. filePtr = _tcsdec (shortcutTarget, filePtr);
  679. if (filePtr) {
  680. *filePtr = 0;
  681. AddMigrationPath (shortcutTarget, 2);
  682. }
  683. }
  684. }
  685. }
  686. }
  687. if (StringIMatch (extPtr, TEXT("PIF"))) {
  688. if (ExtractPifInfo (
  689. shortcutTarget,
  690. shortcutArgs,
  691. shortcutWorkDir,
  692. shortcutIconPath,
  693. &shortcutIcon,
  694. &msDosMode,
  695. NULL,
  696. eFile.FullPath
  697. ) == ERROR_SUCCESS) {
  698. if (shortcutWorkDir [0] != 0) {
  699. AddMigrationPath (shortcutWorkDir, 2);
  700. }
  701. if (shortcutTarget [0] != 0) {
  702. filePtr = (PTSTR)GetFileNameFromPath (shortcutTarget);
  703. if (filePtr) {
  704. filePtr = _tcsdec (shortcutTarget, filePtr);
  705. if (filePtr) {
  706. *filePtr = 0;
  707. AddMigrationPath (shortcutTarget, 2);
  708. }
  709. }
  710. }
  711. }
  712. }
  713. }
  714. }
  715. }
  716. while (EnumNextFileInTree (&eFile));
  717. }
  718. }
  719. while (MemDbEnumNextValue (&eFolder));
  720. }
  721. FreeCOMLink (&shellLink, &persistFile);
  722. }
  723. #ifdef DEBUG
  724. if (GetPrivateProfileIntA ("Debug", "MigPaths", 0, g_DebugInfPathBufA) == 1) {
  725. if (MemDbGetValueEx (&eFolder, MEMDB_CATEGORY_MIGRATION_PATHS, NULL, NULL)) {
  726. DEBUGMSG(("Migration Paths:",""));
  727. do {
  728. DEBUGMSG(("","%s - %ld", eFolder.szName, eFolder.dwValue));
  729. }
  730. while (MemDbEnumNextValue (&eFolder));
  731. }
  732. }
  733. #endif
  734. }
  735. VOID
  736. pReportBackupDirs (
  737. )
  738. {
  739. MEMDB_ENUM e;
  740. PCTSTR BackupDirsGroup;
  741. PCTSTR Message;
  742. PCTSTR ArgArray[2];
  743. TCHAR Buffer[12];
  744. if (g_BackupDirCount <= MAX_BACKUPDIRS_IN_REPORT) {
  745. if (MemDbGetValueEx (&e, MEMDB_CATEGORY_BACKUPDIRS, NULL, NULL)) {
  746. do {
  747. BackupDirsGroup = BuildMessageGroup (
  748. MSG_INSTALL_NOTES_ROOT,
  749. MSG_BACKUP_DETECTED_LIST_SUBGROUP,
  750. e.szName
  751. );
  752. if (BackupDirsGroup) {
  753. MsgMgr_ObjectMsg_Add(
  754. e.szName,
  755. BackupDirsGroup,
  756. S_EMPTY
  757. );
  758. FreeText (BackupDirsGroup);
  759. }
  760. } while (MemDbEnumNextValue (&e));
  761. } else {
  762. MYASSERT (!g_BackupDirCount);
  763. }
  764. } else {
  765. //
  766. // just put a generic message
  767. //
  768. BackupDirsGroup = BuildMessageGroup (
  769. MSG_INSTALL_NOTES_ROOT,
  770. MSG_BACKUP_DETECTED_SUBGROUP,
  771. NULL
  772. );
  773. if (BackupDirsGroup) {
  774. ArgArray[0] = g_Win95Name;
  775. wsprintf (Buffer, TEXT("%lu"), g_BackupDirCount);
  776. ArgArray[1] = Buffer;
  777. Message = ParseMessageID (MSG_BACKUP_DETECTED, ArgArray);
  778. if (Message) {
  779. MsgMgr_ObjectMsg_Add (
  780. TEXT("*BackupDetected"),
  781. BackupDirsGroup,
  782. Message
  783. );
  784. FreeStringResource (Message);
  785. //
  786. // write all backup dirs to the log file
  787. //
  788. if (MemDbGetValueEx (&e, MEMDB_CATEGORY_BACKUPDIRS, NULL, NULL)) {
  789. do {
  790. //
  791. // write it in the log
  792. //
  793. LOG ((LOG_WARNING, (PCSTR)MSG_BACKUP_DETECTED_LOG, e.szName, g_Win95Name));
  794. } while (MemDbEnumNextValue (&e));
  795. } else {
  796. MYASSERT (FALSE);
  797. }
  798. }
  799. FreeText (BackupDirsGroup);
  800. } else {
  801. MYASSERT (FALSE);
  802. }
  803. }
  804. }
  805. BOOL
  806. pScanFileSystem (
  807. VOID
  808. )
  809. {
  810. BOOL fStatus = TRUE;
  811. BOOL fRet = TRUE;
  812. ACCESSIBLE_DRIVE_ENUM e;
  813. LONG ReturnCode = ERROR_SUCCESS;
  814. INFSTRUCT context = INITINFSTRUCT_GROWBUFFER;
  815. PCTSTR virtualFile;
  816. PCTSTR pathExp;
  817. PCTSTR argList[3]={"ProgramFiles", g_ProgramFilesDir, NULL};
  818. pReportOtherOs ();
  819. pBuildMigrationPaths ();
  820. if (!InitLinkAnnounce ()) {
  821. return FALSE;
  822. }
  823. TickProgressBar ();
  824. if (GetFirstAccessibleDriveEx (&e, TRUE)) {
  825. do {
  826. fStatus = pExamineAccessibleDrive(e);
  827. } while (fStatus && GetNextAccessibleDrive(&e));
  828. }
  829. else {
  830. fRet = FALSE;
  831. }
  832. //
  833. // Act on status
  834. //
  835. if (!fRet || !fStatus) {
  836. ReturnCode = GetLastError ();
  837. if (ReturnCode != ERROR_CANCELLED && !CANCELLED()) {
  838. ERROR_CRITICAL
  839. LOG ((LOG_ERROR, (PCSTR)MSG_ENUMDRIVES_FAILED_LOG));
  840. DEBUGMSG((DBG_ERROR,"FileScan: Error enumerating drives"));
  841. }
  842. return FALSE;
  843. }
  844. //
  845. // OK, we are now at the end of filescan. Let's enumerate virtual files
  846. //
  847. MYASSERT (g_Win95UpgInf != INVALID_HANDLE_VALUE);
  848. if (InfFindFirstLine (g_Win95UpgInf, S_VIRTUAL_FILES, NULL, &context)) {
  849. do {
  850. virtualFile = InfGetStringField (&context, 1);
  851. if (virtualFile) {
  852. pathExp = ExpandEnvironmentTextExA(virtualFile, argList);
  853. if (pathExp) {
  854. if (!DoesFileExist (pathExp)) {
  855. pProcessFileOrDir (pathExp, NULL, NULL, 0, NULL, NULL);
  856. }
  857. FreeText (pathExp);
  858. }
  859. }
  860. }
  861. while (InfFindNextLine (&context));
  862. InfCleanUpInfStruct (&context);
  863. }
  864. CleanupUseNtFilesMap ();
  865. return TRUE;
  866. }
  867. DWORD
  868. ScanFileSystem (
  869. IN DWORD Request
  870. )
  871. {
  872. DWORD Ticks;
  873. switch (Request) {
  874. case REQUEST_QUERYTICKS:
  875. return FileScan_GetProgressMax ();
  876. case REQUEST_RUN:
  877. Ticks = GetTickCount();
  878. if (!pScanFileSystem ()) {
  879. return GetLastError ();
  880. }
  881. pReportBackupDirs ();
  882. Ticks = GetTickCount() - Ticks;
  883. g_ProgressBarTime += Ticks;
  884. return ERROR_SUCCESS;
  885. default:
  886. DEBUGMSG ((DBG_ERROR, "Bad parameter in ScanFileSystem"));
  887. }
  888. return 0;
  889. }
  890. VOID
  891. InitUseNtFilesMap (
  892. VOID
  893. )
  894. {
  895. INFSTRUCT context = INITINFSTRUCT_POOLHANDLE;
  896. PTSTR name;
  897. DWORD zero = 0;
  898. g_UseNtFileHashTable = HtAllocWithData (sizeof (DWORD));
  899. if (!g_UseNtFileHashTable) {
  900. return;
  901. }
  902. if (InfFindFirstLine (g_MigDbInf, S_USENTFILES, NULL, &context)) {
  903. do {
  904. name = InfGetStringField (&context, 4);
  905. if (name) {
  906. HtAddStringAndData (g_UseNtFileHashTable, name, &zero);
  907. }
  908. } while (InfFindNextLine (&context));
  909. InfCleanUpInfStruct (&context);
  910. }
  911. }
  912. VOID
  913. CleanupUseNtFilesMap (
  914. VOID
  915. )
  916. {
  917. if (g_UseNtFileHashTable) {
  918. HtFree (g_UseNtFileHashTable);
  919. g_UseNtFileHashTable = NULL;
  920. }
  921. }