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.

1104 lines
34 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 )&&(StringIMatchTcharCount (FullFileSpec, g_TempDirWack, g_TempDirWackChars-1) )) ||
  55. ((*g_PlugInDirWack )&&(StringIMatchTcharCount (FullFileSpec, g_PlugInDirWack, g_PlugInDirWackChars-1) )) ||
  56. ((*g_RecycledDirWack )&&(StringIMatchTcharCount (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 [MEMDB_MAX];
  448. TCHAR shortcutArgs [MEMDB_MAX];
  449. TCHAR shortcutWorkDir [MEMDB_MAX];
  450. TCHAR shortcutIconPath [MEMDB_MAX];
  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. if (TcharCountA (pathExp) < ARRAYSIZE(pathExpAnsi)) {
  519. #pragma prefast(suppress:56, "OemToCharBuffA unsupported on Win9x")
  520. OemToCharA (pathExp, pathExpAnsi);
  521. if (OurGetLongPathName (pathExpAnsi, pathLong, MAX_TCHAR_PATH)) {
  522. AddMigrationPathEx (pathLong, MAX_DEEP_LEVELS, TRUE);
  523. }
  524. }
  525. FreeText (pathExp);
  526. }
  527. }
  528. }
  529. while (SetupFindNextLine (&context, &context));
  530. }
  531. //
  532. // Then include known OEM directories from win95upg.inf section "OemMigrationDirs".
  533. //
  534. if (SetupFindFirstLine (g_Win95UpgInf, S_OEM_MIGRATION_DIRS, NULL, &context)) {
  535. do {
  536. if (SetupGetStringField (&context, 1, dirName, MAX_TCHAR_PATH, NULL)) {
  537. pathExp = ExpandEnvironmentTextExA(dirName, argList);
  538. if (pathExp) {
  539. filePtr = (PTSTR)GetFileNameFromPath (pathExp);
  540. if (*filePtr == 0) {
  541. filePtr = _tcsdec (pathExp, filePtr);
  542. if (filePtr) {
  543. *filePtr = 0;
  544. }
  545. }
  546. if (OurGetLongPathName (pathExp, pathLong, MAX_TCHAR_PATH)) {
  547. Levels = 0;
  548. if (SetupGetStringField (&context, 2, dirName, MAX_TCHAR_PATH, NULL)) {
  549. if (_ttoi (dirName) != 0) {
  550. Levels = MAX_DEEP_LEVELS;
  551. }
  552. }
  553. AddMigrationPathEx (pathLong, Levels, TRUE);
  554. }
  555. FreeText (pathExp);
  556. }
  557. }
  558. }
  559. while (SetupFindNextLine (&context, &context));
  560. }
  561. //
  562. // Then include paths listed in SharedDlls key.
  563. //
  564. sharedDllsKey = OpenRegKeyStr (S_REG_SHARED_DLLS);
  565. if (sharedDllsKey != NULL) {
  566. if (EnumFirstRegValue (&sharedDllsEnum, sharedDllsKey)) {
  567. do {
  568. pathExp = ExpandEnvironmentTextA(sharedDllsEnum.ValueName);
  569. if (pathExp) {
  570. // eliminate the file name
  571. filePtr = (PTSTR)GetFileNameFromPath (pathExp);
  572. if (filePtr) {
  573. filePtr = _tcsdec (pathExp, filePtr);
  574. if (filePtr) {
  575. *filePtr = 0;
  576. }
  577. }
  578. if (OurGetLongPathName (pathExp, pathLong, MAX_TCHAR_PATH)) {
  579. AddMigrationPath (pathLong, 0);
  580. }
  581. FreeText (pathExp);
  582. }
  583. }
  584. while (EnumNextRegValue (&sharedDllsEnum));
  585. }
  586. CloseRegKey (sharedDllsKey);
  587. }
  588. //
  589. // Then include paths listed in AppPaths key.
  590. //
  591. appPathsKey = OpenRegKeyStr (S_SKEY_APP_PATHS);
  592. if (appPathsKey != NULL) {
  593. if (EnumFirstRegKey (&appPathsEnum, appPathsKey)) {
  594. do {
  595. currentAppKey = OpenRegKey (appPathsKey, appPathsEnum.SubKeyName);
  596. if (currentAppKey != NULL) {
  597. appPaths = GetRegValueString (currentAppKey, TEXT("Path"));
  598. if (appPaths != NULL) {
  599. if (EnumFirstPath (&pathEnum, appPaths, NULL, NULL)) {
  600. do {
  601. pathExp = ExpandEnvironmentTextA(pathEnum.PtrCurrPath);
  602. if (pathExp) {
  603. // eliminate \ from the end of a path
  604. filePtr = GetEndOfString (pathExp);
  605. filePtr = _tcsdec (pathExp, filePtr);
  606. if ((filePtr) &&
  607. (*filePtr == TEXT('\\'))
  608. ) {
  609. *filePtr = 0;
  610. }
  611. if (OurGetLongPathName (pathExp, pathLong, MAX_TCHAR_PATH)) {
  612. AddMigrationPath (pathLong, 2);
  613. }
  614. FreeText (pathExp);
  615. }
  616. }
  617. while (EnumNextPath (&pathEnum));
  618. EnumPathAbort (&pathEnum);
  619. }
  620. MemFree (g_hHeap, 0, appPaths);
  621. }
  622. CloseRegKey (currentAppKey);
  623. }
  624. }
  625. while (EnumNextRegKey (&appPathsEnum));
  626. }
  627. CloseRegKey (appPathsKey);
  628. }
  629. //
  630. // Then include paths listed in Run* keys.
  631. //
  632. pAddValueEnumDirsAsMigDirs (S_RUNKEY, 2);
  633. pAddValueEnumDirsAsMigDirs (S_RUNONCEKEY, 2);
  634. pAddValueEnumDirsAsMigDirs (S_RUNONCEEXKEY, 2);
  635. pAddValueEnumDirsAsMigDirs (S_RUNSERVICESKEY, 2);
  636. pAddValueEnumDirsAsMigDirs (S_RUNSERVICESONCEKEY, 2);
  637. pAddValueEnumDirsAsMigDirs (S_RUNKEY_USER, 2);
  638. pAddValueEnumDirsAsMigDirs (S_RUNONCEKEY_USER, 2);
  639. pAddValueEnumDirsAsMigDirs (S_RUNONCEEXKEY_USER, 2);
  640. pAddValueEnumDirsAsMigDirs (S_RUNONCEKEY_DEFAULTUSER, 2);
  641. pAddValueEnumDirsAsMigDirs (S_RUNONCEEXKEY_DEFAULTUSER, 2);
  642. pAddValueEnumDirsAsMigDirs (S_RUNKEY_DEFAULTUSER, 2);
  643. //
  644. // Finally include paths listed in all links from all user profiles.
  645. //
  646. if (InitCOMLink (&shellLink, &persistFile)) {
  647. if (MemDbEnumFirstValue (&eFolder, MEMDB_CATEGORY_NICE_PATHS"\\*", MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
  648. do {
  649. if (*eFolder.szName == 0) {
  650. continue;
  651. }
  652. // first: this directory is a migration directory
  653. AddMigrationPath (eFolder.szName, MAX_DEEP_LEVELS);
  654. //
  655. // For each shell folder we enumerate all links trying to get the path where the links are running
  656. //
  657. if (EnumFirstFileInTreeEx (&eFile, eFolder.szName, TEXT("*.*"), FALSE, FALSE, 0)) {
  658. do {
  659. if (!eFile.Directory) {
  660. extPtr = GetFileExtensionFromPath (eFile.Name);
  661. if (extPtr) {
  662. if (StringIMatch (extPtr, TEXT("LNK"))) {
  663. if (ExtractShellLinkInfo (
  664. shortcutTarget,
  665. shortcutArgs,
  666. shortcutWorkDir,
  667. shortcutIconPath,
  668. &shortcutIcon,
  669. &shortcutHotKey,
  670. NULL,
  671. eFile.FullPath,
  672. shellLink,
  673. persistFile
  674. )) {
  675. if (shortcutWorkDir [0] != 0) {
  676. AddMigrationPath (shortcutWorkDir, 2);
  677. }
  678. if (shortcutTarget [0] != 0) {
  679. filePtr = (PTSTR)GetFileNameFromPath (shortcutTarget);
  680. if (filePtr) {
  681. filePtr = _tcsdec (shortcutTarget, filePtr);
  682. if (filePtr) {
  683. *filePtr = 0;
  684. AddMigrationPath (shortcutTarget, 2);
  685. }
  686. }
  687. }
  688. }
  689. }
  690. if (StringIMatch (extPtr, TEXT("PIF"))) {
  691. if (ExtractPifInfo (
  692. shortcutTarget,
  693. shortcutArgs,
  694. shortcutWorkDir,
  695. shortcutIconPath,
  696. &shortcutIcon,
  697. &msDosMode,
  698. NULL,
  699. eFile.FullPath
  700. ) == ERROR_SUCCESS) {
  701. if (shortcutWorkDir [0] != 0) {
  702. AddMigrationPath (shortcutWorkDir, 2);
  703. }
  704. if (shortcutTarget [0] != 0) {
  705. filePtr = (PTSTR)GetFileNameFromPath (shortcutTarget);
  706. if (filePtr) {
  707. filePtr = _tcsdec (shortcutTarget, filePtr);
  708. if (filePtr) {
  709. *filePtr = 0;
  710. AddMigrationPath (shortcutTarget, 2);
  711. }
  712. }
  713. }
  714. }
  715. }
  716. }
  717. }
  718. }
  719. while (EnumNextFileInTree (&eFile));
  720. }
  721. }
  722. while (MemDbEnumNextValue (&eFolder));
  723. }
  724. FreeCOMLink (&shellLink, &persistFile);
  725. }
  726. #ifdef DEBUG
  727. if (GetPrivateProfileIntA ("Debug", "MigPaths", 0, g_DebugInfPathBufA) == 1) {
  728. if (MemDbGetValueEx (&eFolder, MEMDB_CATEGORY_MIGRATION_PATHS, NULL, NULL)) {
  729. DEBUGMSG(("Migration Paths:",""));
  730. do {
  731. DEBUGMSG(("","%s - %ld", eFolder.szName, eFolder.dwValue));
  732. }
  733. while (MemDbEnumNextValue (&eFolder));
  734. }
  735. }
  736. #endif
  737. }
  738. VOID
  739. pReportBackupDirs (
  740. )
  741. {
  742. MEMDB_ENUM e;
  743. PCTSTR BackupDirsGroup;
  744. PCTSTR Message;
  745. PCTSTR ArgArray[2];
  746. TCHAR Buffer[12];
  747. if (g_BackupDirCount <= MAX_BACKUPDIRS_IN_REPORT) {
  748. if (MemDbGetValueEx (&e, MEMDB_CATEGORY_BACKUPDIRS, NULL, NULL)) {
  749. do {
  750. BackupDirsGroup = BuildMessageGroup (
  751. MSG_INSTALL_NOTES_ROOT,
  752. MSG_BACKUP_DETECTED_LIST_SUBGROUP,
  753. e.szName
  754. );
  755. if (BackupDirsGroup) {
  756. MsgMgr_ObjectMsg_Add(
  757. e.szName,
  758. BackupDirsGroup,
  759. S_EMPTY
  760. );
  761. FreeText (BackupDirsGroup);
  762. }
  763. } while (MemDbEnumNextValue (&e));
  764. } else {
  765. MYASSERT (!g_BackupDirCount);
  766. }
  767. } else {
  768. //
  769. // just put a generic message
  770. //
  771. BackupDirsGroup = BuildMessageGroup (
  772. MSG_INSTALL_NOTES_ROOT,
  773. MSG_BACKUP_DETECTED_SUBGROUP,
  774. NULL
  775. );
  776. if (BackupDirsGroup) {
  777. ArgArray[0] = g_Win95Name;
  778. wsprintf (Buffer, TEXT("%lu"), g_BackupDirCount);
  779. ArgArray[1] = Buffer;
  780. Message = ParseMessageID (MSG_BACKUP_DETECTED, ArgArray);
  781. if (Message) {
  782. MsgMgr_ObjectMsg_Add (
  783. TEXT("*BackupDetected"),
  784. BackupDirsGroup,
  785. Message
  786. );
  787. FreeStringResource (Message);
  788. //
  789. // write all backup dirs to the log file
  790. //
  791. if (MemDbGetValueEx (&e, MEMDB_CATEGORY_BACKUPDIRS, NULL, NULL)) {
  792. do {
  793. //
  794. // write it in the log
  795. //
  796. LOG ((LOG_WARNING, (PCSTR)MSG_BACKUP_DETECTED_LOG, e.szName, g_Win95Name));
  797. } while (MemDbEnumNextValue (&e));
  798. } else {
  799. MYASSERT (FALSE);
  800. }
  801. }
  802. FreeText (BackupDirsGroup);
  803. } else {
  804. MYASSERT (FALSE);
  805. }
  806. }
  807. }
  808. BOOL
  809. pScanFileSystem (
  810. VOID
  811. )
  812. {
  813. BOOL fStatus = TRUE;
  814. BOOL fRet = TRUE;
  815. ACCESSIBLE_DRIVE_ENUM e;
  816. LONG ReturnCode = ERROR_SUCCESS;
  817. INFSTRUCT context = INITINFSTRUCT_GROWBUFFER;
  818. PCTSTR virtualFile;
  819. PCTSTR pathExp;
  820. PCTSTR argList[3]={"ProgramFiles", g_ProgramFilesDir, NULL};
  821. pReportOtherOs ();
  822. pBuildMigrationPaths ();
  823. if (!InitLinkAnnounce ()) {
  824. return FALSE;
  825. }
  826. TickProgressBar ();
  827. if (GetFirstAccessibleDriveEx (&e, TRUE)) {
  828. do {
  829. fStatus = pExamineAccessibleDrive(e);
  830. } while (fStatus && GetNextAccessibleDrive(&e));
  831. }
  832. else {
  833. fRet = FALSE;
  834. }
  835. //
  836. // Act on status
  837. //
  838. if (!fRet || !fStatus) {
  839. ReturnCode = GetLastError ();
  840. if (ReturnCode != ERROR_CANCELLED && !CANCELLED()) {
  841. ERROR_CRITICAL
  842. LOG ((LOG_ERROR, (PCSTR)MSG_ENUMDRIVES_FAILED_LOG));
  843. DEBUGMSG((DBG_ERROR,"FileScan: Error enumerating drives"));
  844. }
  845. return FALSE;
  846. }
  847. //
  848. // OK, we are now at the end of filescan. Let's enumerate virtual files
  849. //
  850. MYASSERT (g_Win95UpgInf != INVALID_HANDLE_VALUE);
  851. if (InfFindFirstLine (g_Win95UpgInf, S_VIRTUAL_FILES, NULL, &context)) {
  852. do {
  853. virtualFile = InfGetStringField (&context, 1);
  854. if (virtualFile) {
  855. pathExp = ExpandEnvironmentTextExA(virtualFile, argList);
  856. if (pathExp) {
  857. if (!DoesFileExist (pathExp)) {
  858. pProcessFileOrDir (pathExp, NULL, NULL, 0, NULL, NULL);
  859. }
  860. FreeText (pathExp);
  861. }
  862. }
  863. }
  864. while (InfFindNextLine (&context));
  865. InfCleanUpInfStruct (&context);
  866. }
  867. CleanupUseNtFilesMap ();
  868. return TRUE;
  869. }
  870. DWORD
  871. ScanFileSystem (
  872. IN DWORD Request
  873. )
  874. {
  875. DWORD Ticks;
  876. switch (Request) {
  877. case REQUEST_QUERYTICKS:
  878. return FileScan_GetProgressMax ();
  879. case REQUEST_RUN:
  880. Ticks = GetTickCount();
  881. if (!pScanFileSystem ()) {
  882. return GetLastError ();
  883. }
  884. pReportBackupDirs ();
  885. Ticks = GetTickCount() - Ticks;
  886. g_ProgressBarTime += Ticks;
  887. return ERROR_SUCCESS;
  888. default:
  889. DEBUGMSG ((DBG_ERROR, "Bad parameter in ScanFileSystem"));
  890. }
  891. return 0;
  892. }
  893. VOID
  894. InitUseNtFilesMap (
  895. VOID
  896. )
  897. {
  898. INFSTRUCT context = INITINFSTRUCT_POOLHANDLE;
  899. PTSTR name;
  900. DWORD zero = 0;
  901. g_UseNtFileHashTable = HtAllocWithData (sizeof (DWORD));
  902. if (!g_UseNtFileHashTable) {
  903. return;
  904. }
  905. if (InfFindFirstLine (g_MigDbInf, S_USENTFILES, NULL, &context)) {
  906. do {
  907. name = InfGetStringField (&context, 4);
  908. if (name) {
  909. HtAddStringAndData (g_UseNtFileHashTable, name, &zero);
  910. }
  911. } while (InfFindNextLine (&context));
  912. InfCleanUpInfStruct (&context);
  913. }
  914. }
  915. VOID
  916. CleanupUseNtFilesMap (
  917. VOID
  918. )
  919. {
  920. if (g_UseNtFileHashTable) {
  921. HtFree (g_UseNtFileHashTable);
  922. g_UseNtFileHashTable = NULL;
  923. }
  924. }