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.

1162 lines
30 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. helpers.c
  5. Abstract:
  6. Implements a set of functions that are called for every
  7. file or directory (before and after the AppDb processing).
  8. Author:
  9. Calin Negreanu (calinn) 21-Nov-1997
  10. Revision History:
  11. ovidiut 14-Feb-2000 Added support for fusion
  12. ovidiut 10-May-1999 Added GatherIniFiles (support for INI actions)
  13. jimschm 07-Jan-1999 CPLs are now known-good migration
  14. jimschm 23-Sep-1998 Cleanup for new fileops
  15. --*/
  16. #include "pch.h"
  17. #include "migdbp.h"
  18. #include "migappp.h"
  19. /*++
  20. Macro Expansion List Description:
  21. HELPER_FUNCTIONS contains a list of functions called for each file and directory
  22. during file scanning.
  23. Line Syntax:
  24. DEFMAC(HelperName, HelperId)
  25. Arguments:
  26. HelperName - this is the helper function. You must implement a function with this
  27. name and required parameters.
  28. HelperId - this is the helper id. If your function handles the file it should
  29. update that in Params structure.
  30. CanHandleVirtualFiles - this is for enumerating some files that might not be on the
  31. system but we want them to be processed as if they were. A good example
  32. is backup.exe which must be replaced by ntbackup.exe. If the file is not
  33. on the system, all registry settings pointing to it will not be changed.
  34. Variables Generated From List:
  35. g_HelperFunctionList - defined in helpers.c
  36. --*/
  37. #define HELPER_FUNCTIONS \
  38. DEFMAC(IsFusionDir, IS_FUSION_DIR, FALSE) \
  39. DEFMAC(MigDbTestFile, MIGDB_TEST_FILE, TRUE ) \
  40. DEFMAC(CheckOsFiles, CHECK_OS_FILES, FALSE) \
  41. DEFMAC(pStoreCPLs, STORE_CPL, FALSE) \
  42. DEFMAC(pCheckCpl, CHECK_CPL, FALSE) \
  43. DEFMAC(pSetupTableFileHelper, SETUP_TABLE_FILE, FALSE) \
  44. DEFMAC(ProcessHelpFile, TEST_HELP_FILES, FALSE) \
  45. DEFMAC(SaveExeFiles, SAVE_EXE_FILES, FALSE) \
  46. DEFMAC(SaveLinkFiles, SAVE_LNK_FILES, FALSE) \
  47. DEFMAC(pGatherDunFiles, GATHER_DUN_FILES, FALSE) \
  48. DEFMAC(pMigrationDllNotify, MIGRATION_DLL, FALSE) \
  49. DEFMAC(GatherBriefcases, GATHER_BRIEFCASES, FALSE) \
  50. DEFMAC(GatherIniFiles, GATHER_INI_FILES, FALSE) \
  51. DEFMAC(TestNtFileName, TEST_NT_FILE_NAME, FALSE) \
  52. DEFMAC(BackUpIsuFiles, BACKUP_ISU_FILES, FALSE) \
  53. DEFMAC(EditHtmlFiles, EDIT_HTML_FILES, FALSE) \
  54. #if 0
  55. //
  56. // the appcompat team doesn't support "APPMIG.INF" any longer
  57. // and they requested us to no longer depend on it
  58. //
  59. DEFMAC(AppCompatTestFile, APPCOMPAT_TEST_FILE,FALSE) \
  60. #endif
  61. #define DEFMAC(fn,id,can) id,
  62. typedef enum {
  63. START_OF_LIST,
  64. HELPER_FUNCTIONS
  65. END_OF_LIST
  66. } HELPER_FUNCTIONS_ID;
  67. #undef DEFMAC
  68. //
  69. // Declare a global array of function pointers
  70. //
  71. typedef BOOL (HELPER_PROTOTYPE) (PFILE_HELPER_PARAMS p);
  72. typedef HELPER_PROTOTYPE *PHELPER_PROTOTYPE;
  73. /*
  74. Declare the helper functions
  75. */
  76. #define DEFMAC(fn,id,can) HELPER_PROTOTYPE fn;
  77. HELPER_FUNCTIONS
  78. #undef DEFMAC
  79. /*
  80. This is the structure used for handling helper functions
  81. */
  82. typedef struct {
  83. PCSTR HelperName;
  84. PHELPER_PROTOTYPE HelperFunction;
  85. BOOL CanHandleVirtualFiles;
  86. } HELPER_STRUCT, *PHELPER_STRUCT;
  87. /*
  88. Declare a global array of functions and name identifiers for helper functions
  89. */
  90. #define DEFMAC(fn,id,can) {#id, fn, can},
  91. static HELPER_STRUCT g_HelperFunctions[] = {
  92. HELPER_FUNCTIONS
  93. {NULL, NULL, FALSE}
  94. };
  95. #undef DEFMAC
  96. extern BOOL g_IsFusionDir;
  97. BOOL
  98. ProcessFileHelpers (
  99. IN OUT PFILE_HELPER_PARAMS Params
  100. )
  101. /*++
  102. Routine Description:
  103. Calls every helper function listed in the macro expansion list.
  104. If a helper function returns FALSE, this function returns FALSE.
  105. Arguments:
  106. Params - Specifies the parameters for the current object
  107. Return Value:
  108. TRUE if success, FALSE if failure.
  109. --*/
  110. {
  111. PHELPER_STRUCT currentHelper = g_HelperFunctions;
  112. #ifdef DEBUG
  113. BOOL InterestingFile;
  114. TCHAR DbgBuf[32];
  115. //
  116. // Check if this file is in [FilesToTrack] inside debug.inf
  117. //
  118. GetPrivateProfileString ("FilesToTrack", Params->FullFileSpec, "", DbgBuf, ARRAYSIZE(DbgBuf), g_DebugInfPath);
  119. if (!(*DbgBuf) && Params->FindData) {
  120. GetPrivateProfileString ("FilesToTrack", Params->FindData->cFileName, "", DbgBuf, ARRAYSIZE(DbgBuf), g_DebugInfPath);
  121. }
  122. InterestingFile = (*DbgBuf != 0);
  123. #endif
  124. while (currentHelper->HelperFunction) {
  125. if ((!Params->VirtualFile) ||
  126. (currentHelper->CanHandleVirtualFiles)
  127. ) {
  128. #ifdef DEBUG
  129. if (InterestingFile) {
  130. DEBUGMSG ((
  131. DBG_TRACK,
  132. "Calling %s for %s",
  133. currentHelper->HelperName,
  134. Params->FullFileSpec
  135. ));
  136. }
  137. #endif
  138. if (!currentHelper->HelperFunction (Params)) {
  139. #ifdef DEBUG
  140. if (InterestingFile) {
  141. DEBUGMSG ((
  142. DBG_TRACK,
  143. "%s failed for %s",
  144. currentHelper->HelperName,
  145. Params->FullFileSpec
  146. ));
  147. }
  148. #endif
  149. return FALSE;
  150. }
  151. #ifdef DEBUG
  152. if (InterestingFile) {
  153. DEBUGMSG ((
  154. DBG_TRACK,
  155. "%s returned, Handled = %u (0x%08X)",
  156. currentHelper->HelperName,
  157. Params->Handled
  158. ));
  159. }
  160. #endif
  161. }
  162. currentHelper++;
  163. }
  164. return TRUE;
  165. }
  166. BOOL
  167. pGatherDunFiles (
  168. IN OUT PFILE_HELPER_PARAMS Params
  169. )
  170. /*++
  171. Routine Description:
  172. pGatherDunFiles adds a memdb entry for any file that has an extension
  173. of .DUN, and then sets the HandledBy type to GATHER_DUN_FILES.
  174. Arguments:
  175. Params - Specifies the file enumeration parameters
  176. Return Value:
  177. TRUE if success, FALSE if failure.
  178. --*/
  179. {
  180. if (StringIMatch (Params->Extension, TEXT(".DUN"))) {
  181. MemDbSetValueEx (MEMDB_CATEGORY_DUN_FILES, Params->FullFileSpec, NULL, NULL, 0, NULL);
  182. Params->Handled = GATHER_DUN_FILES;
  183. }
  184. return TRUE;
  185. }
  186. BOOL
  187. pSetupTableFileHelper (
  188. IN OUT PFILE_HELPER_PARAMS Params
  189. )
  190. /*++
  191. Routine Description:
  192. pSetupTableFileHelper adds a memdb entry for any file that has an extension
  193. of .STF, and then sets the HandledBy type to SETUP_TABLE_FILE.
  194. Arguments:
  195. Params - Specifies the file enumeration parameters
  196. Return Value:
  197. TRUE if success, FALSE if failure.
  198. --*/
  199. {
  200. if (StringIMatch (Params->Extension, TEXT(".STF"))) {
  201. MemDbSetValueEx (MEMDB_CATEGORY_STF, Params->FullFileSpec, NULL, NULL, 0, NULL);
  202. Params->Handled = SETUP_TABLE_FILE;
  203. MarkFileForBackup (Params->FullFileSpec);
  204. }
  205. return TRUE;
  206. }
  207. BOOL
  208. pMigrationDllNotify (
  209. IN OUT PFILE_HELPER_PARAMS Params
  210. )
  211. /*++
  212. Routine Description:
  213. pMigrationDllNotify calls the migration DLL code to update any DLL that
  214. wants to know where a particular file is on the system.
  215. Arguments:
  216. Params - Specifies the file enumeration parameters
  217. Return Value:
  218. TRUE if success, FALSE if failure.
  219. --*/
  220. {
  221. if (!Params->VirtualFile) {
  222. MYASSERT (Params->FindData);
  223. if (!(Params->IsDirectory)) {
  224. if (!UpdateFileSearch (Params->FullFileSpec, Params->FindData->cFileName)) {
  225. DEBUGMSG ((DBG_WARNING, "UpdateFileSearch returned FALSE"));
  226. return FALSE;
  227. }
  228. }
  229. }
  230. return TRUE;
  231. }
  232. BOOL
  233. pStoreCPLs (
  234. IN OUT PFILE_HELPER_PARAMS Params
  235. )
  236. {
  237. PCTSTR ModuleExt;
  238. ModuleExt = GetFileExtensionFromPath (Params->FullFileSpec);
  239. if ((ModuleExt) && (StringIMatch (ModuleExt, TEXT("CPL")))) {
  240. MemDbSetValueEx (
  241. MEMDB_CATEGORY_CPLS,
  242. Params->FullFileSpec,
  243. NULL,
  244. NULL,
  245. 0,
  246. NULL
  247. );
  248. }
  249. return TRUE;
  250. }
  251. BOOL
  252. pCheckCpl (
  253. IN OUT PFILE_HELPER_PARAMS Params
  254. )
  255. {
  256. DWORD Status;
  257. PCTSTR ModuleExt;
  258. if (Params->Handled == 0) {
  259. ModuleExt = GetFileExtensionFromPath (Params->FullFileSpec);
  260. if ((ModuleExt) && (StringIMatch (ModuleExt, TEXT("CPL")))) {
  261. if (!IsFileMarkedAsKnownGood (Params->FullFileSpec)) {
  262. //
  263. // Delete the file if it is displayable
  264. //
  265. if (IsDisplayableCPL (Params->FullFileSpec) &&
  266. !TreatAsGood (Params->FullFileSpec)
  267. ) {
  268. DisableFile (Params->FullFileSpec);
  269. Status = GetFileStatusOnNt (Params->FullFileSpec);
  270. if (!(Status & FILESTATUS_REPLACED)) {
  271. //
  272. // Announce this CPL as bad because:
  273. //
  274. // - It is not known good
  275. // - NT does not replace it
  276. //
  277. ReportControlPanelApplet (
  278. Params->FullFileSpec,
  279. NULL,
  280. ACT_INCOMPATIBLE
  281. );
  282. }
  283. }
  284. }
  285. }
  286. }
  287. return TRUE;
  288. }
  289. BOOL
  290. CheckOsFiles (
  291. IN OUT PFILE_HELPER_PARAMS Params
  292. )
  293. {
  294. TCHAR key[MEMDB_MAX];
  295. PCTSTR filePtr;
  296. DWORD fileStatus;
  297. PCTSTR newFileName;
  298. BOOL bIsWin9xOsPath;
  299. if (Params->Handled == 0) {
  300. filePtr = GetFileNameFromPath (Params->FullFileSpec);
  301. if (filePtr) {
  302. MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES, filePtr, NULL, NULL);
  303. if (MemDbGetValue (key, NULL)) {
  304. MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES_EXCEPT, filePtr, NULL, NULL);
  305. if (!MemDbGetValue (key, NULL)) {
  306. //
  307. // only do this for files in a MigrationDir
  308. //
  309. if (IsMigrationPathEx (Params->DirSpec, &bIsWin9xOsPath) && bIsWin9xOsPath) {
  310. if (GlobalVersionCheck (Params->FullFileSpec, "COMPANYNAME", "*MICROSOFT*")) {
  311. MYASSERT (Params->CurrentDirData);
  312. if (!g_IsFusionDir || !IsNtCompatibleModule (Params->FullFileSpec)) {
  313. //
  314. // If this file is marked with any MOVE operations, remove those operations.
  315. // we want this deletion to take precedence.
  316. //
  317. RemoveOperationsFromPath (
  318. Params->FullFileSpec,
  319. ALL_MOVE_OPERATIONS
  320. );
  321. DeleteFileWithWarning (Params->FullFileSpec);
  322. MarkFileAsOsFile (Params->FullFileSpec);
  323. fileStatus = GetFileStatusOnNt (Params->FullFileSpec);
  324. if ((fileStatus & FILESTATUS_REPLACED) != 0) {
  325. newFileName = GetPathStringOnNt (Params->FullFileSpec);
  326. if (StringIMatch (newFileName, Params->FullFileSpec)) {
  327. MarkFileForCreation (newFileName);
  328. } else {
  329. MarkFileForMoveByNt (Params->FullFileSpec, newFileName);
  330. }
  331. FreePathString (newFileName);
  332. }
  333. Params->Handled = CHECK_OS_FILES;
  334. }
  335. }
  336. }
  337. }
  338. }
  339. }
  340. }
  341. return TRUE;
  342. }
  343. BOOL
  344. GatherIniFiles (
  345. IN PFILE_HELPER_PARAMS Params
  346. )
  347. /*++
  348. Routine Description:
  349. GatherIniFiles marks in memdb all INI files that have associated actions on NT.
  350. Arguments:
  351. Params - Specifies the file enumeration parameters
  352. Return Value:
  353. TRUE if success, FALSE if failure.
  354. --*/
  355. {
  356. MEMDB_ENUM e;
  357. PTSTR NtPath;
  358. BOOL TempMove;
  359. BOOL DoIniAct;
  360. BOOL Success;
  361. DWORD Operations;
  362. if (Params->IsDirectory) {
  363. return TRUE;
  364. }
  365. if (Params->Handled) {
  366. return TRUE;
  367. }
  368. if (!StringIMatch(Params->Extension, TEXT(".INI"))) {
  369. return TRUE;
  370. }
  371. DoIniAct = FALSE;
  372. Params->Handled = GATHER_INI_FILES;
  373. TempMove = FALSE;
  374. //
  375. // Save selected INI filenames to memdb to perform actions on NT
  376. //
  377. if (MemDbGetValueEx (&e, MEMDB_CATEGORY_INIFILES_ACT_FIRST, NULL, NULL)) {
  378. do {
  379. //
  380. // if this dir name is matched, add this file to memdb and return
  381. //
  382. if (IsPatternMatch (e.szName, Params->FullFileSpec)) {
  383. //
  384. // move file in temp location
  385. //
  386. NtPath = GetPathStringOnNt (Params->FullFileSpec);
  387. if (!NtPath) {
  388. //
  389. // can't get path on NT!
  390. //
  391. DEBUGMSG ((
  392. DBG_ERROR,
  393. "GetPathStringOnNt (%s) returned NULL",
  394. Params->FullFileSpec
  395. ));
  396. return FALSE;
  397. }
  398. Operations = GetOperationsOnPath (Params->FullFileSpec);
  399. if (Operations & OPERATION_FILE_MOVE_SHELL_FOLDER) {
  400. DEBUGMSG ((
  401. DBG_WARNING,
  402. "Replacing operation OPERATION_FILE_MOVE_SHELL_FOLDER with OPERATION_TEMP_PATH for file %s",
  403. Params->FullFileSpec
  404. ));
  405. RemoveOperationsFromPath (
  406. Params->FullFileSpec,
  407. OPERATION_FILE_MOVE_SHELL_FOLDER
  408. );
  409. }
  410. Success = MarkFileForTemporaryMove (Params->FullFileSpec, NtPath, g_TempDir);
  411. FreePathString (NtPath);
  412. if (!Success) {
  413. DEBUGMSG ((
  414. DBG_ERROR,
  415. "MarkFileForTemporaryMove (source=%s) returned FALSE",
  416. Params->FullFileSpec
  417. ));
  418. return FALSE;
  419. }
  420. NtPath = GetPathStringOnNt (Params->DirSpec);
  421. Success = MarkDirectoryAsPreserved (NtPath);
  422. if (!Success) {
  423. DEBUGMSG ((
  424. DBG_ERROR,
  425. "MarkDirectoryAsPreserved (%s) returned FALSE",
  426. Params->DirSpec
  427. ));
  428. }
  429. FreePathString (NtPath);
  430. TempMove = TRUE;
  431. MemDbSetValueEx (
  432. MEMDB_CATEGORY_INIACT_FIRST,
  433. Params->FullFileSpec,
  434. NULL,
  435. NULL,
  436. 0,
  437. NULL
  438. );
  439. DoIniAct = TRUE;
  440. break;
  441. }
  442. } while (MemDbEnumNextValue (&e));
  443. }
  444. if (MemDbGetValueEx (&e, MEMDB_CATEGORY_INIFILES_ACT_LAST, NULL, NULL)) {
  445. do {
  446. //
  447. // if this dir name is matched, add this file to memdb and return
  448. //
  449. if (IsPatternMatch (e.szName, Params->FullFileSpec)) {
  450. if (!TempMove) {
  451. //
  452. // move file in temp location
  453. //
  454. NtPath = GetPathStringOnNt (Params->FullFileSpec);
  455. if (!NtPath) {
  456. //
  457. // can't get path on NT!
  458. //
  459. DEBUGMSG ((
  460. DBG_ERROR,
  461. "GetPathStringOnNt (%s) returned NULL",
  462. Params->FullFileSpec
  463. ));
  464. return FALSE;
  465. }
  466. Operations = GetOperationsOnPath (Params->FullFileSpec);
  467. if (Operations & OPERATION_FILE_MOVE_SHELL_FOLDER) {
  468. DEBUGMSG ((
  469. DBG_WARNING,
  470. "Replacing operation OPERATION_FILE_MOVE_SHELL_FOLDER with OPERATION_TEMP_PATH for file %s",
  471. Params->FullFileSpec
  472. ));
  473. RemoveOperationsFromPath (
  474. Params->FullFileSpec,
  475. OPERATION_FILE_MOVE_SHELL_FOLDER
  476. );
  477. }
  478. Success = MarkFileForTemporaryMove (Params->FullFileSpec, NtPath, g_TempDir);
  479. FreePathString (NtPath);
  480. if (!Success) {
  481. DEBUGMSG ((
  482. DBG_ERROR,
  483. "MarkFileForTemporaryMove (source=%s) returned FALSE",
  484. Params->FullFileSpec
  485. ));
  486. return FALSE;
  487. }
  488. NtPath = GetPathStringOnNt (Params->DirSpec);
  489. Success = MarkDirectoryAsPreserved (NtPath);
  490. if (!Success) {
  491. DEBUGMSG ((
  492. DBG_ERROR,
  493. "MarkDirectoryAsPreserved (%s) returned FALSE",
  494. Params->DirSpec
  495. ));
  496. }
  497. FreePathString (NtPath);
  498. TempMove = TRUE;
  499. }
  500. MemDbSetValueEx (
  501. MEMDB_CATEGORY_INIACT_LAST,
  502. Params->FullFileSpec,
  503. NULL,
  504. NULL,
  505. 0,
  506. NULL
  507. );
  508. DoIniAct = TRUE;
  509. break;
  510. }
  511. } while (MemDbEnumNextValue (&e));
  512. }
  513. if (!DoIniAct) {
  514. //
  515. // ini files in %windir% are treated separately
  516. //
  517. if (!StringIMatch (Params->DirSpec, g_WinDirWack)) {
  518. //
  519. // Save all other INI filenames to memdb to convert them later on NT
  520. //
  521. MemDbSetValueEx (
  522. MEMDB_CATEGORY_INIFILES_CONVERT,
  523. Params->FullFileSpec,
  524. NULL,
  525. NULL,
  526. 0,
  527. NULL
  528. );
  529. MarkFileForBackup (Params->FullFileSpec);
  530. }
  531. }
  532. return TRUE;
  533. }
  534. BOOL
  535. GatherBriefcases (
  536. IN PFILE_HELPER_PARAMS Params
  537. )
  538. /*++
  539. Routine Description:
  540. GatherBriefcases stores in memdb all Windows Briefcase Databases
  541. Arguments:
  542. Params - Specifies the file enumeration parameters
  543. Return Value:
  544. TRUE if success, FALSE if failure.
  545. --*/
  546. {
  547. if (!*Params->Extension && !Params->IsDirectory) {
  548. MYASSERT (Params->FindData);
  549. if (StringIMatch (
  550. GetFileNameFromPath (Params->FindData->cFileName),
  551. TEXT("Briefcase Database")
  552. )) {
  553. MemDbSetValueEx (
  554. MEMDB_CATEGORY_BRIEFCASES,
  555. Params->FullFileSpec,
  556. NULL,
  557. NULL,
  558. 0,
  559. NULL
  560. );
  561. MarkFileForBackup (Params->FullFileSpec);
  562. }
  563. }
  564. return TRUE;
  565. }
  566. BOOL
  567. pIsDirInPath (
  568. IN PCTSTR FullDirSpec
  569. )
  570. {
  571. PATH_ENUMA e;
  572. if (EnumFirstPathExA (&e, NULL, NULL, NULL, TRUE)) {
  573. do {
  574. if (StringIMatch (FullDirSpec, e.PtrCurrPath)) {
  575. return TRUE;
  576. }
  577. } while (EnumNextPath (&e));
  578. }
  579. return FALSE;
  580. }
  581. BOOL
  582. pIsFusionDir (
  583. IN PCTSTR FullDirSpec
  584. )
  585. {
  586. HANDLE h;
  587. WIN32_FIND_DATA fd, fd2;
  588. TCHAR FileSpec[2 * MAX_TCHAR_PATH];
  589. TCHAR ExeName[2 * MAX_TCHAR_PATH];
  590. INT length;
  591. DWORD type;
  592. BOOL b = FALSE;
  593. MYASSERT (FullDirSpec);
  594. //
  595. // a fusion dir is never the root of a local drive or in windir or in path
  596. //
  597. if (SizeOfString (FullDirSpec) <= 4 ||
  598. StringIMatch (FullDirSpec, g_WinDir) ||
  599. StringIMatchCharCount (FullDirSpec, g_WinDirWack, g_WinDirWackChars) ||
  600. pIsDirInPath (FullDirSpec)
  601. ) {
  602. return FALSE;
  603. }
  604. length = wsprintf (FileSpec, TEXT("%s\\%s"), FullDirSpec, TEXT("*.local"));
  605. if (length <= MAX_PATH) {
  606. h = FindFirstFile (FileSpec, &fd);
  607. if (h != INVALID_HANDLE_VALUE) {
  608. do {
  609. length = wsprintf (ExeName, TEXT("%s%s"), FullDirSpec, fd.cFileName);
  610. //
  611. // cut the .local and check if this file exists
  612. //
  613. MYASSERT (ExeName[length - 6] == TEXT('.'));
  614. ExeName[length - 6] = 0;
  615. if (DoesFileExistEx (ExeName, &fd2) &&
  616. !(fd2.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  617. ) {
  618. type = GetExeType (ExeName);
  619. b = (type == EXE_WIN32_APP) || (type == EXE_WIN16_APP);
  620. }
  621. } while (!b && FindNextFile (h, &fd));
  622. FindClose (h);
  623. }
  624. }
  625. return b;
  626. }
  627. BOOL
  628. IsFusionDir (
  629. IN PFILE_HELPER_PARAMS Params
  630. )
  631. /*++
  632. Routine Description:
  633. IsFusionDir tests if the current dir is a fusion directory;
  634. it will set the MIGAPP_DIRDATA_FUSION_DIR bit in *Params->CurrentDirData
  635. Arguments:
  636. Params - Specifies the file enumeration parameters
  637. Return Value:
  638. TRUE if success, FALSE if failure.
  639. --*/
  640. {
  641. //
  642. // this helper should be called before action functions (first ID is MIGDB_TEST_FILE)
  643. //
  644. MYASSERT (IS_FUSION_DIR < MIGDB_TEST_FILE);
  645. //
  646. // the caller must provide the storage space
  647. //
  648. MYASSERT (Params->CurrentDirData);
  649. if (!Params->CurrentDirData) {
  650. return FALSE;
  651. }
  652. if (!Params->IsDirectory) {
  653. if ((*Params->CurrentDirData & MIGAPP_DIRDATA_FUSION_DIR_DETERMINED) == 0) {
  654. if (pIsFusionDir (Params->DirSpec)) {
  655. *Params->CurrentDirData |= MIGAPP_DIRDATA_IS_FUSION_DIR;
  656. }
  657. *Params->CurrentDirData |= MIGAPP_DIRDATA_FUSION_DIR_DETERMINED;
  658. }
  659. g_IsFusionDir = (*Params->CurrentDirData & MIGAPP_DIRDATA_IS_FUSION_DIR) != 0;
  660. } else {
  661. g_IsFusionDir = FALSE;
  662. }
  663. return TRUE;
  664. }
  665. BOOL
  666. TestNtFileName (
  667. IN PFILE_HELPER_PARAMS Params
  668. )
  669. /*++
  670. Routine Description:
  671. TestNtFileName tests if the current file has the same name as one in [UseNtFiles];
  672. if it does, then renaming of this file on NT side is infibited, to ensure we don't
  673. change files that are not ours.
  674. Arguments:
  675. Params - Specifies the file enumeration parameters
  676. Return Value:
  677. Always TRUE.
  678. --*/
  679. {
  680. HASHITEM result;
  681. DWORD set;
  682. TCHAR key [MEMDB_MAX];
  683. MEMDB_ENUM e;
  684. PCTSTR name;
  685. if (!Params->IsDirectory && !Params->Handled) {
  686. name = GetFileNameFromPath (Params->FullFileSpec);
  687. if (g_UseNtFileHashTable) {
  688. result = HtFindStringAndData (g_UseNtFileHashTable, name, NULL);
  689. if (result) {
  690. DEBUGMSG ((
  691. DBG_VERBOSE,
  692. "Found unhandled [UseNtFiles] file %s; it's name will not be replaced",
  693. name
  694. ));
  695. //
  696. // remove this mapping from memdb
  697. //
  698. MemDbBuildKey (
  699. key,
  700. MEMDB_CATEGORY_USE_NT_FILES,
  701. name,
  702. NULL,
  703. NULL
  704. );
  705. MemDbDeleteTree (key);
  706. MYASSERT (!MemDbGetValueEx (&e, key, NULL, NULL));
  707. //
  708. // mark this file with data so that we know a file with this name
  709. // not handled by MigDb was found
  710. //
  711. set = 1;
  712. if (!HtSetStringData (g_UseNtFileHashTable, result, &set)) {
  713. MYASSERT (FALSE);
  714. }
  715. }
  716. }
  717. }
  718. return TRUE;
  719. }
  720. BOOL
  721. BackUpIsuFiles (
  722. IN PFILE_HELPER_PARAMS Params
  723. )
  724. /*++
  725. Routine Description:
  726. BackUpIsuFiles collect all of the InstallShield files, so that they
  727. can be edited during GUI mode using code provided by InstallShield.
  728. Arguments:
  729. Params - Specifies the file enumeration parameters
  730. Return Value:
  731. TRUE if success, FALSE if failure.
  732. --*/
  733. {
  734. MEMDB_ENUM e;
  735. PTSTR NtPath;
  736. BOOL TempMove;
  737. BOOL DoIniAct;
  738. BOOL Success;
  739. DWORD Operations;
  740. if (Params->IsDirectory) {
  741. return TRUE;
  742. }
  743. if (Params->Handled) {
  744. return TRUE;
  745. }
  746. if (!StringIMatch(Params->Extension, TEXT(".ISU"))) {
  747. return TRUE;
  748. }
  749. Params->Handled = BACKUP_ISU_FILES;
  750. MarkFileForBackup (Params->FullFileSpec);
  751. return TRUE;
  752. }
  753. BOOL
  754. EditHtmlFiles (
  755. IN PFILE_HELPER_PARAMS Params
  756. )
  757. /*++
  758. Routine Description:
  759. EditHtmlFiles examines all *.HTM? files and looks for the text FILE:. If it
  760. is found, then the file is added to the FileEdit group, so that references to
  761. local paths can be updated. The file is also marked for backup.
  762. Arguments:
  763. Params - Specifies the file enumeration parameters
  764. Return Value:
  765. TRUE if success, FALSE if failure.
  766. --*/
  767. {
  768. HANDLE file;
  769. HANDLE map;
  770. PBYTE image;
  771. PCSTR pos;
  772. PCSTR end;
  773. BOOL found = FALSE;
  774. TCHAR pathCopy[MAX_TCHAR_PATH];
  775. GROWBUFFER tokenArgBuf = GROWBUF_INIT;
  776. GROWBUFFER tokenSetBuf = GROWBUF_INIT;
  777. GROWBUFFER dataBuf = GROWBUF_INIT;
  778. PTOKENARG tokenArg;
  779. PTOKENSET tokenSet;
  780. TCHAR node[MEMDB_MAX];
  781. if (Params->IsDirectory) {
  782. return TRUE;
  783. }
  784. if (Params->Handled) {
  785. return TRUE;
  786. }
  787. if (!StringIMatch (Params->Extension, TEXT(".HTM")) &&
  788. !IsPatternMatch (Params->Extension, TEXT(".HTM?"))
  789. ) {
  790. return TRUE;
  791. }
  792. //
  793. // Exclude OS files
  794. //
  795. if (IsFileMarkedAsOsFile (Params->FullFileSpec)) {
  796. DEBUGMSG ((DBG_WARNING, "%s is an OS file; skipping file: ref update", Params->FullFileSpec));
  797. return TRUE;
  798. }
  799. //
  800. // Exclude Temporary Internet Files
  801. //
  802. StringCopy (pathCopy, Params->FullFileSpec);
  803. if (MappingSearchAndReplace (g_CacheShellFolders, pathCopy, sizeof (pathCopy))) {
  804. DEBUGMSG ((DBG_WARNING, "%s is in a Cache shell folder; skipping file: ref update", Params->FullFileSpec));
  805. return TRUE;
  806. }
  807. DEBUGMSG ((DBG_NAUSEA, "Checking %s for local references", Params->FullFileSpec));
  808. //
  809. // Already processed?
  810. //
  811. MemDbBuildKey (node, MEMDB_CATEGORY_FILEEDIT, Params->FullFileSpec, NULL, NULL);
  812. if (MemDbGetValue (node, NULL)) {
  813. DEBUGMSG ((DBG_NAUSEA, "%s is already processed; skipping", Params->FullFileSpec));
  814. return TRUE;
  815. }
  816. //
  817. // Scan file for text "FILE:"
  818. //
  819. image = (PBYTE) MapFileIntoMemory (Params->FullFileSpec, &file, &map);
  820. if (!image) {
  821. DEBUGMSG ((DBG_WARNING, "Can't map %s into memory; skipping", Params->FullFileSpec));
  822. return TRUE;
  823. }
  824. pos = (PCSTR) image;
  825. end = (PCSTR) ((PBYTE) pos + GetFileSize (file, NULL));
  826. if (end > pos + 1 && !(pos[0] == 0xFF && pos[1] == 0xFE)) {
  827. while (pos < end) {
  828. if (!isspace (*pos) && *pos != '\r' && *pos != '\n') {
  829. if (*pos < 32) {
  830. DEBUGMSG ((DBG_VERBOSE, "File %s looks like it is binary; skipping", Params->FullFileSpec));
  831. break;
  832. }
  833. if (*pos == 'F' || *pos == 'f') {
  834. if (StringIPrefix (pos, TEXT("FILE:"))) {
  835. found = TRUE;
  836. DEBUGMSG ((DBG_VERBOSE, "File %s has FILE: in it; processing it as HTML", Params->FullFileSpec));
  837. break;
  838. }
  839. }
  840. }
  841. pos++;
  842. }
  843. }
  844. ELSE_DEBUGMSG ((DBG_WARNING, "File %s is not an ANSI file; skipping", Params->FullFileSpec));
  845. UnmapFile (image, map, file);
  846. //
  847. // Text found -- mark for edit & backup
  848. //
  849. if (found) {
  850. Params->Handled = EDIT_HTML_FILES;
  851. MarkFileForBackup (Params->FullFileSpec);
  852. //
  853. // Create an argument that has a detect pattern of * and UpdatePath
  854. // set to TRUE. We fill every member of TOKENARG here.
  855. //
  856. tokenArg = (PTOKENARG) GrowBuffer (&tokenArgBuf, sizeof (TOKENARG));
  857. tokenArg->DetectPattern = (PCSTR) (dataBuf.End + TOKEN_BASE_OFFSET);
  858. GrowBufCopyString (&dataBuf, TEXT("*"));
  859. tokenArg->SearchList = NULL;
  860. tokenArg->ReplaceWith = NULL;
  861. tokenArg->UpdatePath = TRUE;
  862. //
  863. // Create a token set of just one token argument. We fill every member
  864. // of TOKENSET here.
  865. //
  866. tokenSet = (PTOKENSET) GrowBuffer (
  867. &tokenSetBuf,
  868. sizeof (TOKENSET) +
  869. tokenArgBuf.End +
  870. dataBuf.End
  871. );
  872. tokenSet->ArgCount = 1;
  873. tokenSet->SelfRelative = TRUE;
  874. tokenSet->UrlMode = TRUE;
  875. tokenSet->CharsToIgnore = NULL;
  876. CopyMemory (tokenSet->Args, tokenArgBuf.Buf, tokenArgBuf.End);
  877. CopyMemory (
  878. (PBYTE) (tokenSet->Args) + tokenArgBuf.End,
  879. dataBuf.Buf,
  880. dataBuf.End
  881. );
  882. //
  883. // Save completed tokenSet to FileEdit category of memdb
  884. //
  885. MemDbSetBinaryValueEx (
  886. MEMDB_CATEGORY_FILEEDIT,
  887. Params->FullFileSpec,
  888. NULL,
  889. tokenSetBuf.Buf,
  890. tokenSetBuf.End,
  891. NULL
  892. );
  893. }
  894. ELSE_DEBUGMSG ((DBG_NAUSEA, "File %s does not have FILE: in it; skipping", Params->FullFileSpec));
  895. FreeGrowBuffer (&tokenArgBuf);
  896. FreeGrowBuffer (&tokenSetBuf);
  897. FreeGrowBuffer (&dataBuf);
  898. return TRUE;
  899. }