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.

1831 lines
55 KiB

  1. #include "pch.h"
  2. #include <advpub.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <wchar.h>
  6. #include <tchar.h>
  7. #include <locale.h>
  8. #include <winnt32p.h>
  9. #include <init9x.h>
  10. #include <migdb.h>
  11. #include <sysmig.h>
  12. #include "..\..\w95upg\migapp\migdbp.h"
  13. typedef BOOL (WINAPI INITROUTINE_PROTOTYPE)(HINSTANCE, DWORD, LPVOID);
  14. INITROUTINE_PROTOTYPE MigUtil_Entry;
  15. INITROUTINE_PROTOTYPE MemDb_Entry;
  16. INITROUTINE_PROTOTYPE MigApp_Entry;
  17. INITROUTINE_PROTOTYPE FileEnum_Entry;
  18. HINSTANCE g_hInst;
  19. HANDLE g_hHeap;
  20. BOOL g_CancelFlag = FALSE;
  21. #define ATTR_FILESIZE 0x1
  22. #define ATTR_CHECKSUM 0x2
  23. #define ATTR_COMPNAME 0x4
  24. #define ATTR_FILEDESC 0x8
  25. #define ATTR_FILEVER 0x10
  26. #define ATTR_INTNAME 0x20
  27. #define ATTR_LEGAL 0x40
  28. #define ATTR_ORIGNAME 0x80
  29. #define ATTR_PRODNAME 0x100
  30. #define ATTR_PRODVER 0x200
  31. #define ATTR_EXETYPE 0x400
  32. #define ATTR_DESCR16 0x800
  33. #ifdef DEBUG
  34. extern BOOL g_DoLog;
  35. #endif
  36. extern POOLHANDLE g_MigDbPool;
  37. extern PMIGDB_CONTEXT g_ContextList;
  38. extern VOID *g_FileTable;
  39. extern BOOL *g_CancelFlagPtr = &g_CancelFlag;
  40. extern POOLHANDLE g_PathsPool;
  41. extern PMIGDB_HOOK_PROTOTYPE g_MigDbHook;
  42. typedef struct _PATTERN_FILE {
  43. PCTSTR Pattern;
  44. PMIGDB_ATTRIB PatternAttr;
  45. struct _PATTERN_FILE *Next;
  46. } PATTERN_FILE, *PPATTERN_FILE;
  47. PPATTERN_FILE g_AttrPatterns = NULL;
  48. BOOL
  49. pScanForFile (
  50. IN PINFCONTEXT Context,
  51. IN DWORD FieldIndex
  52. );
  53. PMIGDB_ATTRIB
  54. pLoadAttribData (
  55. IN PCSTR MultiSzStr
  56. );
  57. BOOL
  58. CallAttribute (
  59. IN PMIGDB_ATTRIB MigDbAttrib,
  60. IN PDBATTRIB_PARAMS AttribParams
  61. );
  62. BOOL
  63. pWorkerFn (
  64. VOID
  65. );
  66. BOOL
  67. pLoadGoodFiles (
  68. IN HINF ConfigHandle
  69. );
  70. BOOL
  71. pLoadAttributes (
  72. IN HINF ConfigHandle
  73. );
  74. BOOL
  75. pLoadPatterns (
  76. IN HINF ConfigHandle
  77. );
  78. BOOL
  79. pHandleSection (
  80. IN PCTSTR SectionName,
  81. IN HINF ConfigHandle
  82. );
  83. BOOL
  84. pWriteMemdbSection (
  85. IN PCTSTR FileName,
  86. IN PCTSTR MemDbCategory,
  87. IN PCTSTR SectName,
  88. IN BOOL WriteByValue
  89. );
  90. BOOL
  91. pArrangeMigDbFile (
  92. IN PCTSTR SrcFile,
  93. IN PCTSTR DestFile
  94. );
  95. VOID
  96. pUsage (
  97. VOID
  98. )
  99. {
  100. _tprintf (TEXT ("\nCommand line syntax:\n\n"
  101. "migfiles [/B:BaseDir] [/T:TempDir] [/F[:SectionName]]\n\n"
  102. "/B Specifies the base directory where all migdb files are\n"
  103. " located. (migdb.inx, migdb.cfg)\n"
  104. "/L Specifies full path to FILELIST.DAT\n"
  105. "/T Specifies the temporary directory used for unpacking\n"
  106. " cabinet files\n"
  107. "/F Forces rescanning a particular section or all sections\n"));
  108. }
  109. PTSTR g_ConfigFile = NULL;
  110. PTSTR g_TempDir = NULL;
  111. PTSTR g_BaseDir = NULL;
  112. PTSTR g_MessageFile= NULL;
  113. PTSTR g_MigdbSrc = NULL;
  114. PTSTR g_MigdbDest = NULL;
  115. PTSTR g_MigdbDump = NULL;
  116. PTSTR g_HistoryFile= NULL;
  117. PTSTR g_RescanSect = NULL;
  118. BOOL g_RescanFlag = FALSE;
  119. extern HINF g_MigDbInf;
  120. GROWBUFFER g_SectFiles = GROWBUF_INIT;
  121. PTSTR g_FileListName = NULL;
  122. #define MEMDB_CATEGORY_SECTFILES TEXT("SectFiles")
  123. #define MEMDB_CATEGORY_GOODFILES TEXT("GoodFiles")
  124. #define MEMDB_CATEGORY_WARNFILES TEXT("WarnFiles")
  125. #define MEMDB_CATEGORY_DUPLFILES TEXT("DuplFiles")
  126. #define MEMDB_CATEGORY_ACTION TEXT("Action")
  127. #define MEMDB_CATEGORY_ATTRIBUTES TEXT("Attributes")
  128. #define MEMDB_CATEGORY_RENAME_SRC TEXT("RenameSrc")
  129. #define MEMDB_CATEGORY_RENAME_DEST TEXT("RenameDest")
  130. #define MEMDB_CATEGORY_REQFILES TEXT("RequiredFiles")
  131. void
  132. __cdecl
  133. main (
  134. int argc,
  135. CHAR *argv[]
  136. )
  137. {
  138. INT argidx, index;
  139. INT nextArg = 0;
  140. LONG rc;
  141. #ifdef DEBUG
  142. g_DoLog = TRUE;
  143. #endif
  144. g_hInst = GetModuleHandle (NULL);
  145. g_hHeap = GetProcessHeap();
  146. if (!MigUtil_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) {
  147. _tprintf (TEXT("MigUtil failed initializing\n"));
  148. exit (1);
  149. }
  150. if (!MemDb_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) {
  151. _tprintf (TEXT("MemDb failed initializing\n"));
  152. exit(1);
  153. }
  154. if (!MigApp_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) {
  155. _tprintf (TEXT("MigApp failed initializing\n"));
  156. exit (1);
  157. }
  158. for (argidx = 1; argidx < argc; argidx++) {
  159. if ((argv[argidx][0] != '-') &&
  160. (argv[argidx][0] != '/')
  161. ) {
  162. if (nextArg == 0) {
  163. pUsage ();
  164. exit (1);
  165. }
  166. switch (nextArg) {
  167. case 1:
  168. index = 0;
  169. goto label1;
  170. case 2:
  171. index = 0;
  172. goto label2;
  173. case 3:
  174. index = 0;
  175. goto label3;
  176. case 4:
  177. index = 0;
  178. goto label4;
  179. }
  180. }
  181. switch (toupper(argv[argidx][1])) {
  182. case 'B':
  183. if (argv[argidx][2] == 0) {
  184. nextArg = 1;
  185. }
  186. else {
  187. if (argv[argidx][2] != ':') {
  188. index = 2;
  189. }
  190. else {
  191. index = 3;
  192. }
  193. label1:
  194. nextArg = 0;
  195. g_BaseDir = AllocPathString (MAX_TCHAR_PATH);
  196. #ifdef UNICODE
  197. MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_BaseDir, MAX_TCHAR_PATH);
  198. #else
  199. _tcsncpy (g_BaseDir, argv[argidx]+index, MAX_TCHAR_PATH);
  200. #endif
  201. }
  202. break;
  203. case 'T':
  204. if (argv[argidx][2] == 0) {
  205. nextArg = 2;
  206. }
  207. else {
  208. if (argv[argidx][2] != ':') {
  209. index = 2;
  210. }
  211. else {
  212. index = 3;
  213. }
  214. label2:
  215. nextArg = 0;
  216. g_TempDir = AllocPathString (MAX_TCHAR_PATH);
  217. #ifdef UNICODE
  218. MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_TempDir, MAX_TCHAR_PATH);
  219. #else
  220. _tcsncpy (g_TempDir, argv[argidx]+index, MAX_TCHAR_PATH);
  221. #endif
  222. }
  223. break;
  224. case 'F':
  225. g_RescanFlag = TRUE;
  226. if (argv[argidx][2] == 0) {
  227. nextArg = 3;
  228. }
  229. else {
  230. if (argv[argidx][2] != ':') {
  231. index = 2;
  232. }
  233. else {
  234. index = 3;
  235. }
  236. label3:
  237. nextArg = 0;
  238. g_RescanSect = AllocPathString (MAX_TCHAR_PATH);
  239. #ifdef UNICODE
  240. MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_RescanSect, MAX_TCHAR_PATH);
  241. #else
  242. _tcsncpy (g_RescanSect, argv[argidx]+index, MAX_TCHAR_PATH);
  243. #endif
  244. }
  245. break;
  246. case 'L':
  247. if (argv[argidx][2] == 0) {
  248. nextArg = 4;
  249. }
  250. else {
  251. if (argv[argidx][2] != ':') {
  252. index = 2;
  253. }
  254. else {
  255. index = 3;
  256. }
  257. label4:
  258. nextArg = 0;
  259. g_FileListName = AllocPathString (MAX_TCHAR_PATH);
  260. #ifdef UNICODE
  261. MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_FileListName, MAX_TCHAR_PATH);
  262. #else
  263. _tcsncpy (g_FileListName, argv[argidx]+index, MAX_TCHAR_PATH);
  264. #endif
  265. }
  266. break;
  267. default:
  268. pUsage ();
  269. exit (1);
  270. }
  271. }
  272. if (g_BaseDir == NULL) {
  273. g_BaseDir = AllocPathString (MAX_TCHAR_PATH);
  274. _tcsncpy (g_BaseDir, TEXT(".\\"), MAX_TCHAR_PATH);
  275. }
  276. if (g_TempDir == NULL) {
  277. g_TempDir = AllocPathString (MAX_TCHAR_PATH);
  278. if (GetEnvironmentVariable (TEXT("TEMP"), g_TempDir, MAX_TCHAR_PATH) == 0) {
  279. GetTempPath (MAX_TCHAR_PATH, g_TempDir);
  280. }
  281. }
  282. g_ConfigFile = JoinPaths (g_BaseDir, TEXT("migdb.cfg"));
  283. g_MessageFile = JoinPaths (g_BaseDir, TEXT("migdb.msg"));
  284. g_HistoryFile = JoinPaths (g_BaseDir, TEXT("migdb.hst"));
  285. g_MigdbSrc = JoinPaths (g_BaseDir, TEXT("migdb.inx"));
  286. g_MigdbDest = JoinPaths (g_BaseDir, TEXT("migdb.tmp"));
  287. g_MigdbDump = JoinPaths (g_BaseDir, TEXT("migdb.dmp"));
  288. if (!DoesFileExist (g_FileListName)) {
  289. _tprintf (TEXT("\nNT file list file not found. Exiting.\n"));
  290. exit (1);
  291. }
  292. if (!DoesFileExist (g_MigdbSrc)) {
  293. _tprintf (TEXT("\nSource file not found. Exiting.\n"));
  294. exit (1);
  295. }
  296. if (!DoesFileExist (g_ConfigFile)) {
  297. _tprintf (TEXT("\nConfiguration file not found. Exiting.\n"));
  298. exit (1);
  299. }
  300. if (SearchPath (NULL, TEXT("extract.exe"), NULL, 0, NULL, NULL) == 0) {
  301. _tprintf (TEXT("\nCannot find extract.exe. Exiting.\n"));
  302. exit (1);
  303. }
  304. CopyFile (g_MigdbSrc, g_MigdbDest, FALSE);
  305. DeleteFile (g_MessageFile);
  306. DeleteFile (g_MigdbDump);
  307. DISABLETRACKCOMMENT();
  308. g_InAnyDir = TRUE;
  309. _tprintf (TEXT("\nReading NT file list: %s"), g_FileListName);
  310. if (!ReadNtFilesEx (g_FileListName, FALSE)) {
  311. rc = GetLastError();
  312. printf ("Could not read %s. Win32 Error Code: %x\n", g_FileListName, rc);
  313. exit (1);
  314. }
  315. _tprintf (TEXT("\nReading configuration files..."));
  316. if (!InitMigDbEx (g_MigdbSrc)) {
  317. rc = GetLastError();
  318. printf ("Could not read %s. Win32 Error Code: %x\n", g_MigdbSrc, rc);
  319. exit (1);
  320. }
  321. DEBUGMSG ((DBG_ERROR , "TEST"));
  322. DEBUGMSG ((DBG_WHOOPS, "TEST"));
  323. pWorkerFn ();
  324. if (g_MigDbInf != INVALID_HANDLE_VALUE) {
  325. SetupCloseInfFile (g_MigDbInf);
  326. }
  327. pWriteMemdbSection (g_MessageFile, MEMDB_CATEGORY_GOODFILES, TEXT("KNOWN GOOD - FILES FOUND"), FALSE);
  328. pWriteMemdbSection (g_MessageFile, MEMDB_CATEGORY_WARNFILES, TEXT("KNOWN GOOD - NAME COLLISIONS"), FALSE);
  329. pWriteMemdbSection (g_MessageFile, MEMDB_CATEGORY_DUPLFILES, TEXT("DUPLICATE FILES"), FALSE);
  330. // we need now to arrange a little bit the MIGDB.INX file
  331. pArrangeMigDbFile (g_MigdbDest, g_MigdbSrc);
  332. DeleteFile (g_MigdbDest);
  333. if (g_FileTable != NULL) {
  334. HtFree (g_FileTable);
  335. }
  336. if (g_MigDbPool != NULL) {
  337. PoolMemDestroyPool (g_MigDbPool);
  338. }
  339. FreePathString (g_ConfigFile);
  340. FreePathString (g_TempDir);
  341. FreePathString (g_BaseDir);
  342. FreePathString (g_MessageFile);
  343. FreePathString (g_MigdbSrc);
  344. FreePathString (g_MigdbDest);
  345. FreePathString (g_MigdbDump);
  346. FreePathString (g_HistoryFile);
  347. g_InAnyDir = FALSE;
  348. ENABLETRACKCOMMENT();
  349. if (!MigApp_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) {
  350. _tprintf (TEXT("MigApp failed initializing\n"));
  351. exit(1);
  352. }
  353. if (!MemDb_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) {
  354. _tprintf (TEXT("MemDb failed initializing\n"));
  355. exit(1);
  356. }
  357. if (!MigUtil_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) {
  358. _tprintf (TEXT("MigUtil failed initializing\n"));
  359. exit (1);
  360. }
  361. }
  362. UINT CALLBACK
  363. pCabinetCallback (
  364. IN PVOID Context, //context used by the callback routine
  365. IN UINT Notification, //notification sent to callback routine
  366. IN UINT Param1, //additional notification information
  367. IN UINT Param2 //additional notification information );
  368. )
  369. {
  370. PCTSTR tempDir = Context;
  371. PCTSTR fileName = (PCTSTR)Param2 ;
  372. PFILE_IN_CABINET_INFO fileInfo = (PFILE_IN_CABINET_INFO)Param1;
  373. PCTSTR fromPtr, toPtr;
  374. TCHAR tempStr [MEMDB_MAX];
  375. if (Notification == SPFILENOTIFY_FILEINCABINET) {
  376. if (toPtr = _tcschr (fileInfo->NameInCabinet, TEXT('\\'))) {
  377. _tcscpy (fileInfo->FullTargetName, tempDir);
  378. fromPtr = fileInfo->NameInCabinet;
  379. while (toPtr) {
  380. StringCopyAB (tempStr, fromPtr, toPtr);
  381. _tcscat (fileInfo->FullTargetName, TEXT("\\"));
  382. _tcscat (fileInfo->FullTargetName, tempStr);
  383. CreateDirectory (fileInfo->FullTargetName, NULL);
  384. toPtr = _tcsinc (toPtr);
  385. fromPtr = toPtr;
  386. toPtr = _tcschr (toPtr, TEXT('\\'));
  387. }
  388. }
  389. _stprintf (fileInfo->FullTargetName, TEXT("%s\\%s"), tempDir, fileInfo->NameInCabinet);
  390. return FILEOP_DOIT;
  391. }
  392. return NO_ERROR;
  393. }
  394. BOOL
  395. pWorkerFn (
  396. VOID
  397. )
  398. {
  399. HINF configHandle = INVALID_HANDLE_VALUE;
  400. INFCONTEXT context;
  401. TCHAR fileName [MAX_TCHAR_PATH] = "";
  402. TCHAR sectName [MAX_TCHAR_PATH];
  403. PTSTR dontCare;
  404. configHandle = SetupOpenInfFile (g_ConfigFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
  405. if (configHandle == INVALID_HANDLE_VALUE) {
  406. SearchPath (NULL, g_ConfigFile, NULL, MAX_TCHAR_PATH, fileName, &dontCare);
  407. configHandle = SetupOpenInfFile (fileName, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
  408. if (configHandle == INVALID_HANDLE_VALUE) {
  409. _tprintf (TEXT("\nCannot open configuration file %s. Exiting.\n"), g_ConfigFile);
  410. return FALSE;
  411. }
  412. }
  413. g_ContextList = (PMIGDB_CONTEXT) PoolMemGetMemory (g_MigDbPool, sizeof (MIGDB_CONTEXT));
  414. if (g_ContextList == NULL) {
  415. DEBUGMSG ((DBG_ERROR, "Unable to create empty context"));
  416. return FALSE;
  417. }
  418. ZeroMemory (g_ContextList, sizeof (MIGDB_CONTEXT));
  419. if (!pLoadGoodFiles (configHandle)) {
  420. _tprintf (TEXT("\nUnable to load good files section. Exiting.\n"));
  421. return FALSE;
  422. }
  423. if (!pLoadAttributes (configHandle)) {
  424. _tprintf (TEXT("\nUnable to load attributes section.\n"));
  425. }
  426. if (!pLoadPatterns (configHandle)) {
  427. _tprintf (TEXT("\nUnable to load patterns section.\n"));
  428. }
  429. else {
  430. _tprintf (TEXT("done\n\n"));
  431. }
  432. if (SetupFindFirstLine (configHandle, TEXT("sections"), NULL, &context)) {
  433. do {
  434. if (!SetupGetStringField (&context, 1, sectName, MAX_TCHAR_PATH, NULL)) {
  435. _tprintf (TEXT("\nBad section [SECTIONS] in %s. Exiting.\n"), g_ConfigFile);
  436. return FALSE;
  437. }
  438. if (!pHandleSection (sectName, configHandle)) {
  439. return FALSE;
  440. }
  441. }
  442. while (SetupFindNextLine (&context, &context));
  443. }
  444. return TRUE;
  445. }
  446. BOOL
  447. pLoadGoodFiles (
  448. IN HINF ConfigHandle
  449. )
  450. {
  451. INFCONTEXT context;
  452. if (SetupFindFirstLine (ConfigHandle, TEXT("good files"), NULL, &context)) {
  453. do {
  454. if (!pScanForFile (&context, 1)) {
  455. DEBUGMSG ((DBG_WARNING, "Scan for file failed:%d", GetLastError()));
  456. return FALSE;
  457. }
  458. }
  459. while (SetupFindNextLine (&context, &context));
  460. }
  461. return TRUE;
  462. }
  463. BOOL
  464. pLoadAttributes (
  465. IN HINF ConfigHandle
  466. )
  467. {
  468. TCHAR fileName [MEMDB_MAX];
  469. TCHAR attribStr [MEMDB_MAX];
  470. PCTSTR currAttr;
  471. DWORD attributes;
  472. DWORD dontCare;
  473. INFCONTEXT context;
  474. if (SetupFindFirstLine (ConfigHandle, TEXT("Attributes"), NULL, &context)) {
  475. do {
  476. if (SetupGetStringField (&context, 1, fileName, MAX_TCHAR_PATH, NULL)) {
  477. if (!SetupGetStringField (&context, 2, attribStr, MAX_TCHAR_PATH, NULL)) {
  478. attribStr [0] = 0;
  479. }
  480. currAttr = attribStr;
  481. attributes = 0;
  482. while (*currAttr) {
  483. switch (toupper(*currAttr)) {
  484. case 'S':
  485. attributes |= ATTR_FILESIZE;
  486. break;
  487. case 'C':
  488. attributes |= ATTR_CHECKSUM;
  489. break;
  490. case 'N':
  491. attributes |= ATTR_COMPNAME;
  492. break;
  493. case 'F':
  494. attributes |= ATTR_FILEDESC;
  495. break;
  496. case 'V':
  497. attributes |= ATTR_FILEVER;
  498. break;
  499. case 'I':
  500. attributes |= ATTR_INTNAME;
  501. break;
  502. case 'L':
  503. attributes |= ATTR_LEGAL;
  504. break;
  505. case 'O':
  506. attributes |= ATTR_ORIGNAME;
  507. break;
  508. case 'P':
  509. attributes |= ATTR_PRODNAME;
  510. break;
  511. case 'E':
  512. attributes |= ATTR_PRODVER;
  513. break;
  514. case 'T':
  515. attributes |= ATTR_EXETYPE;
  516. break;
  517. case 'D':
  518. attributes |= ATTR_DESCR16;
  519. break;
  520. default:
  521. _tprintf (TEXT("\nInvalid attributes:%s\n"), currAttr);
  522. }
  523. currAttr = _tcsinc (currAttr);
  524. }
  525. MemDbSetValueEx (
  526. MEMDB_CATEGORY_ATTRIBUTES,
  527. fileName,
  528. NULL,
  529. NULL,
  530. attributes,
  531. &dontCare
  532. );
  533. }
  534. }
  535. while (SetupFindNextLine (&context, &context));
  536. }
  537. return TRUE;
  538. }
  539. BOOL
  540. pLoadPatterns (
  541. IN HINF ConfigHandle
  542. )
  543. {
  544. TCHAR patternFile [MEMDB_MAX];
  545. TCHAR patternStr [MEMDB_MAX];
  546. INFCONTEXT context;
  547. PPATTERN_FILE fileStruct;
  548. if (SetupFindFirstLine (ConfigHandle, TEXT("Patterns"), NULL, &context)) {
  549. do {
  550. if (SetupGetStringField (&context, 1, patternFile, MAX_TCHAR_PATH, NULL) &&
  551. SetupGetMultiSzField (&context, 2, patternStr, MAX_TCHAR_PATH, NULL)
  552. ) {
  553. fileStruct = (PPATTERN_FILE) PoolMemGetMemory (g_MigDbPool, sizeof (PATTERN_FILE));
  554. fileStruct->Pattern = PoolMemDuplicateString (g_MigDbPool, patternFile);
  555. fileStruct->PatternAttr = pLoadAttribData (patternStr);
  556. fileStruct->Next = g_AttrPatterns;
  557. g_AttrPatterns = fileStruct;
  558. }
  559. }
  560. while (SetupFindNextLine (&context, &context));
  561. }
  562. return TRUE;
  563. }
  564. BOOL
  565. pDeleteAllFiles (
  566. IN PCTSTR DirPath
  567. )
  568. {
  569. TREE_ENUM e;
  570. BOOL dirsFirst = FALSE;
  571. if (EnumFirstFileInTree (&e, DirPath, TEXT("*"), dirsFirst)) {
  572. do {
  573. if (e.Directory) {
  574. pDeleteAllFiles (e.FullPath);
  575. SetFileAttributes (e.FullPath, FILE_ATTRIBUTE_NORMAL);
  576. RemoveDirectory (e.FullPath);
  577. }
  578. else {
  579. SetFileAttributes (e.FullPath, FILE_ATTRIBUTE_NORMAL);
  580. DeleteFile (e.FullPath);
  581. }
  582. } while (EnumNextFileInTree (&e));
  583. }
  584. return TRUE;
  585. }
  586. BOOL
  587. pSelected (
  588. IN PCTSTR FileName
  589. )
  590. {
  591. MULTISZ_ENUM patternEnum;
  592. if (EnumFirstMultiSz (&patternEnum, g_SectFiles.Buf)) {
  593. do {
  594. if (IsPatternMatch (patternEnum.CurrentString, FileName)) {
  595. return TRUE;
  596. }
  597. }
  598. while (EnumNextMultiSz (&patternEnum));
  599. }
  600. return FALSE;
  601. }
  602. BOOL
  603. pSpecialSelected (
  604. IN PCTSTR FileName,
  605. OUT PTSTR NewName
  606. )
  607. {
  608. MULTISZ_ENUM patternEnum;
  609. PTSTR endPtr, endPtr1;
  610. TCHAR savedVal;
  611. if (EnumFirstMultiSz (&patternEnum, g_SectFiles.Buf)) {
  612. do {
  613. endPtr = _tcsdec (patternEnum.CurrentString, GetEndOfString (patternEnum.CurrentString));
  614. savedVal = *endPtr;
  615. *endPtr = TEXT('_');
  616. if (IsPatternMatch (patternEnum.CurrentString, FileName)) {
  617. StringCopy (NewName, FileName);
  618. endPtr1 = _tcsdec (NewName, GetEndOfString (NewName));
  619. *endPtr1 = savedVal;
  620. *endPtr = savedVal;
  621. return TRUE;
  622. }
  623. *endPtr = savedVal;
  624. }
  625. while (EnumNextMultiSz (&patternEnum));
  626. }
  627. StringCopy (NewName, FileName);
  628. endPtr = _tcsdec (NewName, GetEndOfString (NewName));
  629. *endPtr = TEXT('-');
  630. return FALSE;
  631. }
  632. DWORD g_DirSequencer = 0;
  633. DWORD g_FileSequencer = 0;
  634. BOOL
  635. pCabinetFile (
  636. IN PCTSTR FileName
  637. )
  638. {
  639. PCTSTR extPtr;
  640. extPtr = GetFileExtensionFromPath (FileName);
  641. if ((extPtr != NULL) &&
  642. StringIMatch (extPtr, TEXT("CAB"))
  643. ) {
  644. return TRUE;
  645. }
  646. return FALSE;
  647. }
  648. #define ATTR_FILESIZE 0x1
  649. #define ATTR_CHECKSUM 0x2
  650. #define ATTR_COMPNAME 0x4
  651. #define ATTR_FILEDESC 0x8
  652. #define ATTR_FILEVER 0x10
  653. #define ATTR_INTNAME 0x20
  654. #define ATTR_LEGAL 0x40
  655. #define ATTR_ORIGNAME 0x80
  656. #define ATTR_PRODNAME 0x100
  657. #define ATTR_PRODVER 0x200
  658. #define ATTR_EXETYPE 0x400
  659. #define ATTR_DESCR16 0x800
  660. typedef struct _VERSION_DATA {
  661. PCSTR versionValue;
  662. PCSTR versionName;
  663. DWORD attrib;
  664. } VERSION_DATA, *PVERSION_DATA;
  665. VERSION_DATA verData [] = {{NULL, "COMPANYNAME", ATTR_COMPNAME},
  666. {NULL, "FILEDESCRIPTION", ATTR_FILEDESC},
  667. {NULL, "FILEVERSION", ATTR_FILEVER},
  668. {NULL, "INTERNALNAME", ATTR_INTNAME},
  669. {NULL, "LEGALCOPYRIGHT", ATTR_LEGAL},
  670. {NULL, "ORIGINALFILENAME", ATTR_ORIGNAME},
  671. {NULL, "PRODUCTNAME", ATTR_PRODNAME},
  672. {NULL, "PRODUCTVERSION", ATTR_PRODVER},
  673. {NULL, NULL, 0}};
  674. extern PSTR g_ExeTypes[4];
  675. BOOL
  676. pCheckForPattern (
  677. IN PCTSTR FileName,
  678. PFILE_HELPER_PARAMS Params,
  679. OUT PTSTR FileAttr,
  680. IN OUT PGROWBUFFER AttrList
  681. )
  682. {
  683. PPATTERN_FILE patternFile;
  684. PMIGDB_ATTRIB migDbAttrib;
  685. DBATTRIB_PARAMS attribParams;
  686. BOOL fileSelected;
  687. BOOL found;
  688. TCHAR temp [MEMDB_MAX];
  689. MULTISZ_ENUMA multiSzEnum;
  690. BOOL first;
  691. patternFile = g_AttrPatterns;
  692. found = FALSE;
  693. while (patternFile) {
  694. if (IsPatternMatch (patternFile->Pattern, FileName)) {
  695. fileSelected = TRUE;
  696. migDbAttrib = patternFile->PatternAttr;
  697. while (migDbAttrib) {
  698. attribParams.FileParams = Params;
  699. attribParams.ExtraData = NULL;
  700. if (!CallAttribute (migDbAttrib, &attribParams)) {
  701. fileSelected = FALSE;
  702. break;
  703. }
  704. migDbAttrib = migDbAttrib->Next;
  705. }
  706. if (fileSelected) {
  707. found = TRUE;
  708. break;
  709. }
  710. }
  711. patternFile = patternFile->Next;
  712. }
  713. if (found) {
  714. migDbAttrib = patternFile->PatternAttr;
  715. while (migDbAttrib) {
  716. _tcscpy (temp, MigDb_GetAttributeName (migDbAttrib->AttribIndex));
  717. first = TRUE;
  718. if (EnumFirstMultiSz (&multiSzEnum, migDbAttrib->Arguments)) {
  719. _tcscat (temp, TEXT("("));
  720. do {
  721. if (!first) {
  722. _tcscat (FileAttr, TEXT(","));
  723. _tcscat (FileAttr, temp);
  724. if (AttrList) {
  725. MultiSzAppend (AttrList, temp);
  726. }
  727. *temp = 0;
  728. }
  729. first = FALSE;
  730. _tcscat (temp, TEXT("\""));
  731. _tcscat (temp, multiSzEnum.CurrentString);
  732. _tcscat (temp, TEXT("\""));
  733. }
  734. while (EnumNextMultiSz (&multiSzEnum));
  735. _tcscat (temp, TEXT(")"));
  736. }
  737. _tcscat (FileAttr, TEXT(","));
  738. _tcscat (FileAttr, temp);
  739. if (AttrList) {
  740. MultiSzAppend (AttrList, temp);
  741. }
  742. migDbAttrib = migDbAttrib->Next;
  743. }
  744. return TRUE;
  745. }
  746. return FALSE;
  747. }
  748. PSTR
  749. MyQueryVersionEntry (
  750. IN PCSTR FileName,
  751. IN PCSTR VersionEntry
  752. )
  753. {
  754. VERSION_STRUCTW Version;
  755. PCWSTR CurrentStr;
  756. PSTR ConvCurrentStr = NULL;
  757. PSTR result = NULL;
  758. PCWSTR ConvFileName = NULL;
  759. PCWSTR ConvVerEntry = NULL;
  760. MYASSERT (VersionEntry);
  761. ConvFileName = ConvertAtoW (FileName);
  762. ConvVerEntry = ConvertAtoW (VersionEntry);
  763. if (CreateVersionStructW (&Version, ConvFileName)) {
  764. __try {
  765. CurrentStr = EnumFirstVersionValueW (&Version, ConvVerEntry);
  766. if (CurrentStr) {
  767. CurrentStr = SkipSpaceW (CurrentStr);
  768. ConvCurrentStr = UnicodeToCcs (CurrentStr);
  769. TruncateTrailingSpace ((PSTR) ConvCurrentStr);
  770. result = ConvCurrentStr;
  771. }
  772. else {
  773. __leave;
  774. }
  775. }
  776. __finally {
  777. DestroyVersionStructW (&Version);
  778. }
  779. }
  780. if (ConvVerEntry) {
  781. FreeConvertedStr (ConvVerEntry);
  782. }
  783. if (ConvFileName) {
  784. FreeConvertedStr (ConvFileName);
  785. }
  786. return result;
  787. }
  788. BOOL
  789. pPrintLine (
  790. IN PTREE_ENUM e,
  791. OUT PTSTR FileAttr,
  792. IN OUT PGROWBUFFER AttrList
  793. )
  794. {
  795. FILE_HELPER_PARAMS Params;
  796. UINT checkSum;
  797. DWORD exeType;
  798. PCSTR fileDesc16;
  799. INT numAttribs;
  800. DWORD listedAttr;
  801. TCHAR ekey [MEMDB_MAX];
  802. TCHAR temp [MEMDB_MAX];
  803. PVERSION_DATA p;
  804. Params.Handled = 0;
  805. Params.FullFileSpec = e->FullPath;
  806. _tcsncpy (Params.DirSpec, e->RootPath, MAX_TCHAR_PATH);
  807. Params.IsDirectory = FALSE;
  808. Params.Extension = GetFileExtensionFromPath (e->Name);
  809. Params.FindData = e->FindData;
  810. Params.VirtualFile = FALSE;
  811. Params.CurrentDirData = NULL;
  812. FileAttr [0] = 0;
  813. if (!StringIMatch (e->Name, TEXT("kernel32.dll"))) {
  814. if (pCheckForPattern (e->Name, &Params, FileAttr, AttrList)) {
  815. return TRUE;
  816. }
  817. }
  818. numAttribs = 0;
  819. MemDbBuildKey (ekey, MEMDB_CATEGORY_ATTRIBUTES, e->Name, NULL, NULL);
  820. if (!MemDbGetPatternValue (ekey, &listedAttr)) {
  821. listedAttr = ATTR_COMPNAME | ATTR_PRODVER;
  822. }
  823. if (listedAttr & ATTR_FILESIZE) {
  824. _stprintf (
  825. temp,
  826. TEXT(",FILESIZE(0x%08lX)"),
  827. e->FindData->nFileSizeLow);
  828. _tcscat (FileAttr, temp);
  829. if (AttrList) {
  830. _stprintf (
  831. temp,
  832. TEXT("FILESIZE(0x%08lX)"),
  833. e->FindData->nFileSizeLow);
  834. MultiSzAppend (AttrList, temp);
  835. }
  836. numAttribs ++;
  837. }
  838. if (listedAttr & ATTR_CHECKSUM) {
  839. checkSum = ComputeCheckSum (&Params);
  840. _stprintf (
  841. temp,
  842. TEXT(",CHECKSUM(0x%08lX)"),
  843. checkSum);
  844. _tcscat (FileAttr, temp);
  845. if (AttrList) {
  846. _stprintf (
  847. temp,
  848. TEXT("CHECKSUM(0x%08lX)"),
  849. checkSum);
  850. MultiSzAppend (AttrList, temp);
  851. }
  852. numAttribs ++;
  853. }
  854. if (listedAttr & ATTR_EXETYPE) {
  855. exeType = GetModuleType (e->FullPath);
  856. _stprintf (
  857. temp,
  858. TEXT(",EXETYPE(\"%s\")"),
  859. g_ExeTypes[exeType]);
  860. _tcscat (FileAttr, temp);
  861. if (AttrList) {
  862. _stprintf (
  863. temp,
  864. TEXT("EXETYPE(%s)"),
  865. g_ExeTypes[exeType]);
  866. MultiSzAppend (AttrList, temp);
  867. }
  868. numAttribs ++;
  869. }
  870. if (listedAttr & ATTR_DESCR16) {
  871. fileDesc16 = Get16ModuleDescription (e->FullPath);
  872. if (fileDesc16 != NULL) {
  873. _stprintf (
  874. temp,
  875. TEXT(",DESCRIPTION(\"%s\")"),
  876. fileDesc16);
  877. _tcscat (FileAttr, temp);
  878. if (AttrList) {
  879. _stprintf (
  880. temp,
  881. TEXT("DESCRIPTION(%s)"),
  882. fileDesc16);
  883. MultiSzAppend (AttrList, temp);
  884. }
  885. numAttribs ++;
  886. FreePathString (fileDesc16);
  887. }
  888. }
  889. p = verData;
  890. while (p->versionName) {
  891. if (listedAttr & p->attrib) {
  892. p->versionValue = MyQueryVersionEntry (e->FullPath, p->versionName);
  893. }
  894. p++;
  895. }
  896. p = verData;
  897. while (p->versionName) {
  898. if ((listedAttr & p->attrib) && (p->versionValue)) {
  899. _stprintf (
  900. temp,
  901. TEXT(",%s(\"%s\")"),
  902. p->versionName,
  903. p->versionValue);
  904. _tcscat (FileAttr, temp);
  905. if (AttrList) {
  906. _stprintf (
  907. temp,
  908. TEXT("%s(%s)"),
  909. p->versionName,
  910. p->versionValue);
  911. MultiSzAppend (AttrList, temp);
  912. }
  913. FreePathString (p->versionValue);
  914. numAttribs ++;
  915. }
  916. p++;
  917. }
  918. if (numAttribs == 0) {
  919. checkSum = ComputeCheckSum (&Params);
  920. _stprintf (
  921. temp,
  922. TEXT(",FC(%ld,%lX)"),
  923. e->FindData->nFileSizeLow,
  924. checkSum
  925. );
  926. _tcscat (FileAttr, temp);
  927. if (AttrList) {
  928. _stprintf (
  929. temp,
  930. TEXT("FC(%ld"),
  931. e->FindData->nFileSizeLow
  932. );
  933. MultiSzAppend (AttrList, temp);
  934. _stprintf (
  935. temp,
  936. TEXT("%lX)"),
  937. checkSum
  938. );
  939. MultiSzAppend (AttrList, temp);
  940. }
  941. }
  942. return TRUE;
  943. }
  944. BOOL
  945. pHandleAppFile (
  946. IN PTREE_ENUM e,
  947. IN PCTSTR Action,
  948. IN PCTSTR Section,
  949. IN PCTSTR Message,
  950. IN PCTSTR SrcPath
  951. )
  952. {
  953. TCHAR msgStr [MEMDB_MAX] = "";
  954. FILE_HELPER_PARAMS Params;
  955. TCHAR line [MEMDB_MAX];
  956. TCHAR key [MEMDB_MAX] = "";
  957. DWORD offset;
  958. Params.Handled = 0;
  959. Params.FullFileSpec = e->FullPath;
  960. _tcsncpy (Params.DirSpec, SrcPath, MAX_TCHAR_PATH);
  961. Params.IsDirectory = FALSE;
  962. Params.Extension = GetFileExtensionFromPath (e->Name);
  963. Params.FindData = e->FindData;
  964. Params.VirtualFile = FALSE;
  965. Params.CurrentDirData = NULL;
  966. pPrintLine (e, line, NULL);
  967. MemDbBuildKey (key, MEMDB_CATEGORY_RENAME_SRC, e->Name, NULL, NULL);
  968. if (MemDbGetValue (key, &offset)) {
  969. if (!MemDbBuildKeyFromOffset (offset, key, 1, NULL)) {
  970. *key = 0;
  971. }
  972. } else {
  973. *key = 0;
  974. }
  975. _stprintf (
  976. msgStr,
  977. TEXT("%s\\%s%s)"),
  978. MEMDB_CATEGORY_SECTFILES,
  979. *key?key:e->Name,
  980. line);
  981. MemDbSetValue (msgStr, 0);
  982. return TRUE;
  983. }
  984. BOOL
  985. pHandleSysFile (
  986. IN PTREE_ENUM e,
  987. IN PCTSTR Action,
  988. IN PCTSTR Section,
  989. IN PCTSTR Message,
  990. IN PCTSTR SrcPath
  991. )
  992. {
  993. TCHAR msgStr [MEMDB_MAX] = "";
  994. FILE_HELPER_PARAMS Params;
  995. HASHITEM stringId;
  996. PMIGDB_FILE migDbFile;
  997. FILE_LIST_STRUCT fileList;
  998. PMIGDB_ATTRIB migDbAttrib;
  999. DBATTRIB_PARAMS attribParams;
  1000. BOOL fileSelected = FALSE;
  1001. PCTSTR actionTmp;
  1002. TCHAR line [MEMDB_MAX];
  1003. TCHAR key [MEMDB_MAX] = "";
  1004. DWORD offset;
  1005. GROWBUFFER attrList = GROWBUF_INIT;
  1006. // this is not a cabinet file, let's do something with it.
  1007. Params.Handled = 0;
  1008. Params.FullFileSpec = e->FullPath;
  1009. _tcsncpy (Params.DirSpec, SrcPath, MAX_TCHAR_PATH);
  1010. Params.IsDirectory = FALSE;
  1011. Params.Extension = GetFileExtensionFromPath (e->Name);
  1012. Params.FindData = e->FindData;
  1013. Params.VirtualFile = FALSE;
  1014. Params.CurrentDirData = NULL;
  1015. pPrintLine (e, line, &attrList);
  1016. if (StringIMatch (e->Name, TEXT("kernel32.dll"))) {
  1017. _stprintf (
  1018. msgStr,
  1019. TEXT("%s\\%s%s"),
  1020. MEMDB_CATEGORY_REQFILES,
  1021. e->Name,
  1022. line);
  1023. MemDbSetValue (msgStr, fileSelected);
  1024. };
  1025. // first check if this file is in "known good" list or is already listed in migdb.inx
  1026. // with same action
  1027. stringId = HtFindString (g_FileTable, e->Name);
  1028. if (stringId) {
  1029. //The string table has extra data (a pointer to a FILE_LIST_STRUCT node)
  1030. HtCopyStringData (g_FileTable, stringId, &fileList);
  1031. migDbFile = fileList.First;
  1032. while (migDbFile) {
  1033. //check all attributes for this file
  1034. migDbAttrib = migDbFile->Attributes;
  1035. fileSelected = TRUE;
  1036. while (migDbAttrib != NULL) {
  1037. attribParams.FileParams = &Params;
  1038. attribParams.ExtraData = NULL;
  1039. if (!CallAttribute (migDbAttrib, &attribParams)) {
  1040. fileSelected = FALSE;
  1041. break;
  1042. }
  1043. migDbAttrib = migDbAttrib->Next;
  1044. }
  1045. if ((!fileSelected) &&
  1046. (migDbFile->Section == NULL)
  1047. ) {
  1048. // there was a name collision with a "known good" file. We will send a message
  1049. _stprintf (msgStr, TEXT("%s\\%s"), MEMDB_CATEGORY_WARNFILES, e->Name);
  1050. MemDbSetValue (msgStr, 0);
  1051. }
  1052. if ((fileSelected) &&
  1053. (migDbFile->Section == NULL)
  1054. ) {
  1055. // this file is "known good". We will send a message
  1056. _stprintf (msgStr, TEXT("%s\\%s"), MEMDB_CATEGORY_GOODFILES, e->Name);
  1057. MemDbSetValue (msgStr, 0);
  1058. break;
  1059. }
  1060. if ((fileSelected) && (!StringIMatch (Section, migDbFile->Section->Context->SectName))){
  1061. actionTmp = MigDb_GetActionName (migDbFile->Section->Context->ActionIndex);
  1062. if ((actionTmp != NULL) && StringIMatch (actionTmp, Action)) {
  1063. // this file was already listed in migdb.inx with the same action
  1064. _stprintf (
  1065. msgStr,
  1066. TEXT("%s\\%s\\%-14s%s"),
  1067. MEMDB_CATEGORY_DUPLFILES,
  1068. Action,
  1069. e->Name,
  1070. line);
  1071. MemDbSetValue (msgStr, 0);
  1072. break;
  1073. }
  1074. }
  1075. fileSelected = FALSE;
  1076. migDbFile = migDbFile->Next;
  1077. }
  1078. }
  1079. if (!fileSelected) {
  1080. // one more check. If this file is in FILELIST.DAT (but not in the EXCEPTED section)
  1081. // and COMPANYNAME attribute has Microsoft somewhere inside we'll put it in a different
  1082. // place
  1083. MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES, e->Name, NULL, NULL);
  1084. if (MemDbGetValue (key, NULL)) {
  1085. MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES_EXCEPT, e->Name, NULL, NULL);
  1086. if (!MemDbGetValue (key, NULL)) {
  1087. if (GlobalVersionCheck (e->FullPath, "COMPANYNAME", "*MICROSOFT*")) {
  1088. fileSelected = TRUE;
  1089. }
  1090. }
  1091. }
  1092. // this file is not in the list or attributes do not match
  1093. // we will add in incompatibility list.
  1094. //creating MIGDB_FILE structure for current file
  1095. migDbFile = (PMIGDB_FILE) PoolMemGetMemory (g_MigDbPool, sizeof (MIGDB_FILE));
  1096. if (migDbFile != NULL) {
  1097. ZeroMemory (migDbFile, sizeof (MIGDB_FILE));
  1098. migDbFile->Section = g_ContextList->Sections;
  1099. migDbFile->Attributes = pLoadAttribData (attrList.Buf);
  1100. if (g_MigDbHook != NULL) {
  1101. migDbAttrib = migDbFile->Attributes;
  1102. while (migDbAttrib) {
  1103. g_MigDbHook (e->Name, g_ContextList, g_ContextList->Sections, migDbFile, migDbAttrib);
  1104. migDbAttrib = migDbAttrib->Next;
  1105. }
  1106. }
  1107. //adding this file into string table and create a MIGDB_FILE node. If file
  1108. //already exists in string table then just create another MIGDB_FILE node
  1109. //chained with already existing ones.
  1110. stringId = HtFindString (g_FileTable, e->Name);
  1111. if (stringId) {
  1112. HtCopyStringData (g_FileTable, stringId, &fileList);
  1113. fileList.Last->Next = migDbFile;
  1114. fileList.Last = migDbFile;
  1115. HtSetStringData (g_FileTable, stringId, &fileList);
  1116. }
  1117. else {
  1118. fileList.First = fileList.Last = migDbFile;
  1119. HtAddStringAndData (g_FileTable, e->Name, &fileList);
  1120. }
  1121. }
  1122. else {
  1123. DEBUGMSG ((DBG_ERROR, "Unable to allocate file node for %s", e->Name));
  1124. }
  1125. MemDbBuildKey (key, MEMDB_CATEGORY_RENAME_SRC, e->Name, NULL, NULL);
  1126. if (MemDbGetValue (key, &offset)) {
  1127. if (!MemDbBuildKeyFromOffset (offset, key, 1, NULL)) {
  1128. *key = 0;
  1129. }
  1130. } else {
  1131. *key = 0;
  1132. }
  1133. _stprintf (
  1134. msgStr,
  1135. TEXT("%s\\%s%s"),
  1136. MEMDB_CATEGORY_SECTFILES,
  1137. *key?key:e->Name,
  1138. line);
  1139. MemDbSetValue (msgStr, fileSelected);
  1140. }
  1141. FreeGrowBuffer (&attrList);
  1142. return TRUE;
  1143. }
  1144. BOOL
  1145. pCompressedFile (
  1146. IN PTREE_ENUM e
  1147. )
  1148. {
  1149. PCTSTR extPtr;
  1150. extPtr = GetFileExtensionFromPath (e->FullPath);
  1151. if (extPtr == NULL) {
  1152. return FALSE;
  1153. }
  1154. if (_tcslen (extPtr) != 3) {
  1155. return FALSE;
  1156. }
  1157. return (extPtr [2] == TEXT('_'));
  1158. }
  1159. BOOL
  1160. pExeFile (
  1161. IN PTREE_ENUM e
  1162. )
  1163. {
  1164. PCTSTR extPtr;
  1165. extPtr = GetFileExtensionFromPath (e->FullPath);
  1166. if ((extPtr != NULL) &&
  1167. (StringIMatch (extPtr, TEXT("EXE")))
  1168. ) {
  1169. return TRUE;
  1170. }
  1171. return FALSE;
  1172. }
  1173. BOOL
  1174. pCopyAndHandleCabResource (
  1175. IN PVOID Source,
  1176. IN DWORD Size,
  1177. IN PCTSTR DirName
  1178. )
  1179. {
  1180. TCHAR cabDir [MAX_TCHAR_PATH] = "";
  1181. HANDLE hFile;
  1182. DWORD dontCare;
  1183. if (Size < 4) {
  1184. return TRUE;
  1185. }
  1186. if (*((PDWORD)Source) != 0x4643534D) {
  1187. return TRUE;
  1188. }
  1189. g_FileSequencer ++;
  1190. _stprintf (cabDir, TEXT("%s\\MIGDB%03u.CAB"), DirName, g_FileSequencer);
  1191. hFile = CreateFile (cabDir, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1192. if (hFile == INVALID_HANDLE_VALUE) {
  1193. DEBUGMSG ((DBG_ERROR, "Cannot create file %s", cabDir));
  1194. return FALSE;
  1195. }
  1196. if (!WriteFile (hFile, Source, Size, &dontCare, NULL)) {
  1197. DEBUGMSG ((DBG_ERROR, "Cannot write to file %s", cabDir));
  1198. return FALSE;
  1199. }
  1200. CloseHandle (hFile);
  1201. return TRUE;
  1202. }
  1203. BOOL CALLBACK
  1204. EnumResNameProc (
  1205. IN HANDLE hModule, // module handle
  1206. IN LPCTSTR lpszType, // pointer to resource type
  1207. IN LPTSTR lpszName, // pointer to resource name
  1208. IN LONG lParam // application-defined parameter
  1209. )
  1210. {
  1211. HRSRC hResource;
  1212. DWORD size;
  1213. HGLOBAL hGlobal;
  1214. PVOID srcBytes;
  1215. hResource = FindResource (hModule, lpszName, lpszType);
  1216. if (hResource) {
  1217. size = SizeofResource (hModule, hResource);
  1218. if (size) {
  1219. hGlobal = LoadResource (hModule, hResource);
  1220. if (hGlobal) {
  1221. srcBytes = LockResource (hGlobal);
  1222. if (srcBytes) {
  1223. pCopyAndHandleCabResource (srcBytes, size, (PCTSTR)lParam);
  1224. }
  1225. }
  1226. }
  1227. }
  1228. return TRUE;
  1229. }
  1230. BOOL CALLBACK
  1231. EnumResTypeProc (
  1232. IN HANDLE hModule, // resource-module handle
  1233. IN LPTSTR lpszType, // pointer to resource type
  1234. IN LONG lParam // application-defined parameter
  1235. )
  1236. {
  1237. if ((lpszType != RT_ACCELERATOR ) &&
  1238. (lpszType != RT_ANICURSOR ) &&
  1239. (lpszType != RT_ANIICON ) &&
  1240. (lpszType != RT_BITMAP ) &&
  1241. (lpszType != RT_CURSOR ) &&
  1242. (lpszType != RT_DIALOG ) &&
  1243. (lpszType != RT_FONT ) &&
  1244. (lpszType != RT_FONTDIR ) &&
  1245. (lpszType != RT_GROUP_CURSOR ) &&
  1246. (lpszType != RT_GROUP_ICON ) &&
  1247. (lpszType != RT_HTML ) &&
  1248. (lpszType != RT_ICON ) &&
  1249. (lpszType != RT_MENU ) &&
  1250. (lpszType != RT_MESSAGETABLE ) &&
  1251. (lpszType != RT_PLUGPLAY ) &&
  1252. (lpszType != RT_STRING ) &&
  1253. (lpszType != RT_VERSION ) &&
  1254. (lpszType != RT_VXD ) &&
  1255. (lpszType != RT_HTML )
  1256. ) {
  1257. // we found an unknown type. Let's enumerate all resources of this type
  1258. if (EnumResourceNames (hModule, lpszType, EnumResNameProc, lParam) == 0) {
  1259. DEBUGMSG ((DBG_ERROR, "Error enumerating names:%ld", GetLastError ()));
  1260. }
  1261. }
  1262. return TRUE;
  1263. }
  1264. BOOL
  1265. pHandleAllFiles (
  1266. IN BOOL AppMode,
  1267. IN PCTSTR Action,
  1268. IN PCTSTR Section,
  1269. IN PCTSTR Message,
  1270. IN PCTSTR SrcPath
  1271. )
  1272. {
  1273. TCHAR tempDir [MAX_TCHAR_PATH] = "";
  1274. TCHAR cmdLine [MAX_TCHAR_PATH] = "";
  1275. TCHAR newName [MAX_TCHAR_PATH] = "";
  1276. TREE_ENUM e;
  1277. DWORD error;
  1278. HMODULE exeModule;
  1279. PROCESS_INFORMATION processInfo;
  1280. STARTUPINFO startupInfo;
  1281. if (EnumFirstFileInTree (&e, SrcPath, TEXT("*"), FALSE)) {
  1282. do {
  1283. if (!e.Directory) {
  1284. if (pCabinetFile (e.Name)) {
  1285. if ((AppMode) ||
  1286. (!pSelected (e.Name))
  1287. ) {
  1288. // cabinet file
  1289. g_DirSequencer++;
  1290. _stprintf (tempDir, TEXT("%s\\MIGDB%03u"), g_TempDir, g_DirSequencer);
  1291. if (CreateDirectory (tempDir, NULL) == 0) {
  1292. error = GetLastError ();
  1293. if (error == ERROR_ALREADY_EXISTS) {
  1294. pDeleteAllFiles (tempDir);
  1295. }
  1296. ELSE_DEBUGMSG ((DBG_ERROR, "Cannot create directory %s", tempDir));
  1297. }
  1298. _tprintf (TEXT(" Extracting cabinet file ... %s"), e.Name);
  1299. // we need to expand the cabinet file
  1300. SetLastError (0);
  1301. if (!SetupIterateCabinet (e.FullPath, 0, pCabinetCallback, tempDir)) {
  1302. _tprintf (TEXT("...error %ld\n"), GetLastError());
  1303. DEBUGMSG((DBG_ERROR, "Could not iterate cabinet file:%s\nError:%ld", e.FullPath, GetLastError ()));
  1304. }
  1305. else {
  1306. _tprintf (TEXT("...done\n"));
  1307. }
  1308. if (!pHandleAllFiles (AppMode, Action, Section, Message, tempDir)) {
  1309. return FALSE;
  1310. }
  1311. pDeleteAllFiles (tempDir);
  1312. RemoveDirectory (tempDir);
  1313. g_DirSequencer--;
  1314. }
  1315. }
  1316. else if (pCompressedFile (&e)) {
  1317. if (AppMode) {
  1318. if (!pSpecialSelected (e.Name, newName)) {
  1319. continue;
  1320. }
  1321. }
  1322. else {
  1323. if (pSpecialSelected (e.Name, newName)) {
  1324. continue;
  1325. }
  1326. }
  1327. // compressed file
  1328. g_DirSequencer++;
  1329. _stprintf (tempDir, TEXT("%s\\MIGDB%03u"), g_TempDir, g_DirSequencer);
  1330. if (CreateDirectory (tempDir, NULL) == 0) {
  1331. error = GetLastError ();
  1332. if (error == ERROR_ALREADY_EXISTS) {
  1333. pDeleteAllFiles (tempDir);
  1334. }
  1335. ELSE_DEBUGMSG ((DBG_ERROR, "Cannot create directory %s", tempDir));
  1336. }
  1337. _stprintf (cmdLine, TEXT("expand /r %s %s"), e.FullPath, tempDir);
  1338. ZeroMemory (&startupInfo, sizeof (STARTUPINFO));
  1339. startupInfo.cb = sizeof (STARTUPINFO);
  1340. if (CreateProcess (NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo)) {
  1341. WaitForSingleObject (processInfo.hProcess, INFINITE);
  1342. CloseHandle (processInfo.hProcess);
  1343. CloseHandle (processInfo.hThread);
  1344. if (!pHandleAllFiles (AppMode, Action, Section, Message, tempDir)) {
  1345. return FALSE;
  1346. }
  1347. pDeleteAllFiles (tempDir);
  1348. }
  1349. else {
  1350. DEBUGMSG ((DBG_ERROR, "Could not decompress:%s, Error:%ld", e.Name, GetLastError()));
  1351. }
  1352. RemoveDirectory (tempDir);
  1353. g_DirSequencer--;
  1354. }
  1355. else {
  1356. if (pExeFile (&e)) {
  1357. g_FileSequencer = 0;
  1358. g_DirSequencer++;
  1359. _stprintf (tempDir, TEXT("%s\\MIGDB%03u"), g_TempDir, g_DirSequencer);
  1360. if (CreateDirectory (tempDir, NULL) == 0) {
  1361. error = GetLastError ();
  1362. if (error == ERROR_ALREADY_EXISTS) {
  1363. pDeleteAllFiles (tempDir);
  1364. }
  1365. ELSE_DEBUGMSG ((DBG_ERROR, "Cannot create directory %s", tempDir));
  1366. }
  1367. exeModule = LoadLibraryEx (e.FullPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1368. EnumResourceTypes (exeModule, EnumResTypeProc, (LONG)tempDir);
  1369. FreeLibrary (exeModule);
  1370. if (!pHandleAllFiles (AppMode, Action, Section, Message, tempDir)) {
  1371. return FALSE;
  1372. }
  1373. pDeleteAllFiles (tempDir);
  1374. RemoveDirectory (tempDir);
  1375. g_DirSequencer--;
  1376. }
  1377. if (AppMode) {
  1378. if (pSelected (e.Name)) {
  1379. if (!pHandleAppFile (&e, Action, Section, Message, SrcPath)) {
  1380. return FALSE;
  1381. }
  1382. }
  1383. }
  1384. else {
  1385. if (!pSelected (e.Name)) {
  1386. if (!pHandleSysFile (&e, Action, Section, Message, SrcPath)) {
  1387. return FALSE;
  1388. }
  1389. }
  1390. }
  1391. }
  1392. }
  1393. } while (EnumNextFileInTree (&e));
  1394. }
  1395. return TRUE;
  1396. }
  1397. BOOL
  1398. pHandleSection (
  1399. IN PCTSTR SectionName,
  1400. IN HINF ConfigHandle
  1401. )
  1402. {
  1403. PMIGDB_CONTEXT migDbContext = NULL;
  1404. INFCONTEXT context;
  1405. TCHAR action [MAX_TCHAR_PATH] = "";
  1406. TCHAR section [MAX_TCHAR_PATH] = "";
  1407. TCHAR message [MAX_TCHAR_PATH] = "";
  1408. TCHAR srcPath [MAX_TCHAR_PATH] = "";
  1409. TCHAR msgStr [MAX_TCHAR_PATH] = "";
  1410. TCHAR sectTmp [MAX_TCHAR_PATH] = "";
  1411. TCHAR renSect [MAX_TCHAR_PATH] = "";
  1412. TCHAR srcFile [MAX_TCHAR_PATH] = "";
  1413. TCHAR destFile[MAX_TCHAR_PATH] = "";
  1414. BOOL forced = FALSE;
  1415. INT field;
  1416. TCHAR excludePattern [MAX_TCHAR_PATH] = "";
  1417. BOOL appMode = FALSE;
  1418. TCHAR sectPatterns [MAX_TCHAR_PATH] = "";
  1419. DWORD offset;
  1420. _tprintf (TEXT("Processing section : %s ... "), SectionName);
  1421. if (!SetupFindFirstLine (ConfigHandle, SectionName, TEXT("action"), &context)) {
  1422. _tprintf (TEXT("\nCannot find Action= line in %s.\n"), SectionName);
  1423. return FALSE;
  1424. }
  1425. if (!SetupGetStringField (&context, 1, action, MAX_TCHAR_PATH, NULL)) {
  1426. _tprintf (TEXT("\nCannot read action name in %s.\n"), SectionName);
  1427. return FALSE;
  1428. }
  1429. if (!SetupFindFirstLine (ConfigHandle, SectionName, TEXT("section"), &context)) {
  1430. _tprintf (TEXT("\nCannot find Section= line in %s.\n"), SectionName);
  1431. return FALSE;
  1432. }
  1433. if (!SetupGetStringField (&context, 1, section, MAX_TCHAR_PATH, NULL)) {
  1434. _tprintf (TEXT("\nCannot read section name in %s.\n"), SectionName);
  1435. return FALSE;
  1436. }
  1437. if (!SetupFindFirstLine (ConfigHandle, SectionName, TEXT("sourcepath"), &context)) {
  1438. _tprintf (TEXT("\nCannot find SourcePath= line in %s.\n"), SectionName);
  1439. return FALSE;
  1440. }
  1441. if (!SetupGetStringField (&context, 1, srcPath, MAX_TCHAR_PATH, NULL)) {
  1442. _tprintf (TEXT("\nCannot read source path name in %s.\n"), SectionName);
  1443. return FALSE;
  1444. }
  1445. if (SetupFindFirstLine (ConfigHandle, SectionName, TEXT("message"), &context)) {
  1446. SetupGetStringField (&context, 1, message, MAX_TCHAR_PATH, NULL);
  1447. }
  1448. if (SetupFindFirstLine (ConfigHandle, SectionName, TEXT("RenameSection"), &context)) {
  1449. SetupGetStringField (&context, 1, renSect, MAX_TCHAR_PATH, NULL);
  1450. }
  1451. g_SectFiles.Buf = NULL;
  1452. g_SectFiles.Size = 0;
  1453. g_SectFiles.End = 0;
  1454. g_SectFiles.GrowSize = 0;
  1455. g_SectFiles.UserIndex = 0;
  1456. if (SetupFindFirstLine (ConfigHandle, SectionName, TEXT("ExcludeFiles"), &context)) {
  1457. field = 1;
  1458. while (SetupGetStringField (&context, field, excludePattern, MAX_TCHAR_PATH, NULL)) {
  1459. MultiSzAppend (&g_SectFiles, excludePattern);
  1460. field ++;
  1461. }
  1462. appMode = FALSE;
  1463. }
  1464. if (SetupFindFirstLine (ConfigHandle, SectionName, TEXT("SpecifiedFiles"), &context)) {
  1465. field = 1;
  1466. while (SetupGetStringField (&context, field, excludePattern, MAX_TCHAR_PATH, NULL)) {
  1467. MultiSzAppend (&g_SectFiles, excludePattern);
  1468. field ++;
  1469. }
  1470. appMode = TRUE;
  1471. }
  1472. // let's try to find if this section was already processed in migdb.inx
  1473. if (SetupFindFirstLine (g_MigDbInf, action, NULL, &context)) {
  1474. do {
  1475. if (SetupGetStringField (&context, 1, sectTmp, MAX_TCHAR_PATH, NULL) &&
  1476. (StringIMatch (section, sectTmp))
  1477. ) {
  1478. if ((!g_RescanFlag) ||
  1479. ((g_RescanSect != NULL) && (!StringIMatch (g_RescanSect, section)))
  1480. ) {
  1481. _tprintf (TEXT("skipped\n"));
  1482. return TRUE;
  1483. }
  1484. WritePrivateProfileString (section, NULL, NULL, g_MigdbDest);
  1485. WritePrivateProfileString (NULL, NULL, NULL, g_MigdbDest);
  1486. _tprintf (TEXT("forced ..."));
  1487. forced = TRUE;
  1488. }
  1489. }
  1490. while (SetupFindNextLine (&context, &context));
  1491. }
  1492. if (SetupFindFirstLine (ConfigHandle, renSect, NULL, &context)) {
  1493. do {
  1494. if (SetupGetStringField (&context, 0, srcFile, MAX_TCHAR_PATH, NULL) &&
  1495. SetupGetStringField (&context, 1, destFile, MAX_TCHAR_PATH, NULL)
  1496. ) {
  1497. MemDbSetValueEx (MEMDB_CATEGORY_RENAME_DEST, destFile, NULL, NULL, 0, &offset);
  1498. MemDbSetValueEx (MEMDB_CATEGORY_RENAME_SRC, srcFile, NULL, NULL, offset, NULL);
  1499. }
  1500. } while (SetupFindNextLine (&context, &context));
  1501. }
  1502. _tprintf (TEXT("\n"));
  1503. migDbContext = (PMIGDB_CONTEXT) PoolMemGetMemory (g_MigDbPool, sizeof (MIGDB_CONTEXT));
  1504. if (migDbContext == NULL) {
  1505. DEBUGMSG ((DBG_ERROR, "Unable to create context for %s", action));
  1506. return FALSE;
  1507. }
  1508. ZeroMemory (migDbContext, sizeof (MIGDB_CONTEXT));
  1509. migDbContext->Next = g_ContextList;
  1510. g_ContextList = migDbContext;
  1511. // update ActionIndex with known value
  1512. migDbContext->ActionIndex = MigDb_GetActionIdx (action);
  1513. DEBUGMSG_IF(((migDbContext->ActionIndex == -1), DBG_ERROR, "Unable to identify action index for %s", action));
  1514. // update SectName field
  1515. migDbContext->SectName = PoolMemDuplicateString (g_MigDbPool, section);
  1516. if (!pHandleAllFiles (appMode, action, section, message, srcPath)) {
  1517. return FALSE;
  1518. }
  1519. FreeGrowBuffer (&g_SectFiles);
  1520. if (!forced) {
  1521. // now let's add the action section and the line within it
  1522. _stprintf (msgStr, TEXT("%s\\%s,%s"),
  1523. MEMDB_CATEGORY_ACTION,
  1524. section,
  1525. message);
  1526. MemDbSetValue (msgStr, 0);
  1527. pWriteMemdbSection (g_MigdbDest, MEMDB_CATEGORY_ACTION, action, FALSE);
  1528. }
  1529. pWriteMemdbSection (g_MigdbDest, MEMDB_CATEGORY_SECTFILES, section, TRUE);
  1530. pWriteMemdbSection (g_MigdbDest, MEMDB_CATEGORY_REQFILES, TEXT("Windows 9x Required Files"), TRUE);
  1531. MemDbDeleteTree (MEMDB_CATEGORY_SECTFILES);
  1532. MemDbDeleteTree (MEMDB_CATEGORY_ACTION);
  1533. MemDbDeleteTree (MEMDB_CATEGORY_RENAME_SRC);
  1534. MemDbDeleteTree (MEMDB_CATEGORY_RENAME_DEST);
  1535. MemDbDeleteTree (MEMDB_CATEGORY_REQFILES);
  1536. return TRUE;
  1537. }
  1538. BOOL
  1539. pWriteMemdbSection (
  1540. IN PCTSTR FileName,
  1541. IN PCTSTR MemDbCategory,
  1542. IN PCTSTR SectName,
  1543. IN BOOL WriteByValue
  1544. )
  1545. {
  1546. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  1547. TCHAR line [MAX_TCHAR_PATH] = "";
  1548. DWORD dontCare;
  1549. MEMDB_ENUM e;
  1550. PCTSTR pattern;
  1551. fileHandle = CreateFile (FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
  1552. if (fileHandle == INVALID_HANDLE_VALUE) {
  1553. _tprintf (TEXT("\nCannot open %s.\n"), FileName);
  1554. return FALSE;
  1555. }
  1556. SetFilePointer (fileHandle, 0, 0, FILE_END);
  1557. _stprintf (line, TEXT("[%s]\r\n"), SectName);
  1558. WriteFile (fileHandle, line, GetEndOfString (line) - line, &dontCare, NULL);
  1559. pattern = JoinPaths (MemDbCategory, TEXT("\\*"));
  1560. if (MemDbEnumFirstValue (&e, pattern, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
  1561. do {
  1562. if (!WriteByValue || !e.dwValue) {
  1563. _stprintf (line, TEXT("%s\r\n"), e.szName);
  1564. if (!WriteFile (fileHandle, line, GetEndOfString (line) - line, &dontCare, NULL)) {
  1565. DEBUGMSG ((DBG_ERROR, "Error while writing information."));
  1566. }
  1567. }
  1568. }
  1569. while (MemDbEnumNextValue (&e));
  1570. }
  1571. _stprintf (line, TEXT("\r\n\r\n"), SectName);
  1572. WriteFile (fileHandle, line, GetEndOfString (line) - line, &dontCare, NULL);
  1573. if (!CloseHandle (fileHandle)) {
  1574. DEBUGMSG ((DBG_ERROR, "Error while closing file %s.", FileName));
  1575. }
  1576. if (WriteByValue) {
  1577. fileHandle = CreateFile (g_MigdbDump, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
  1578. if (fileHandle == INVALID_HANDLE_VALUE) {
  1579. _tprintf (TEXT("\nCannot open %s.\n"), g_MigdbDump);
  1580. return FALSE;
  1581. }
  1582. SetFilePointer (fileHandle, 0, 0, FILE_END);
  1583. _stprintf (line, TEXT("[\n%s.obsolete]\r\n"), SectName);
  1584. WriteFile (fileHandle, line, GetEndOfString (line) - line, &dontCare, NULL);
  1585. if (MemDbEnumFirstValue (&e, pattern, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
  1586. do {
  1587. if (e.dwValue) {
  1588. _stprintf (line, TEXT("%s\r\n"), e.szName);
  1589. if (!WriteFile (fileHandle, line, GetEndOfString (line) - line, &dontCare, NULL)) {
  1590. DEBUGMSG ((DBG_ERROR, "Error while writing information."));
  1591. }
  1592. }
  1593. }
  1594. while (MemDbEnumNextValue (&e));
  1595. }
  1596. if (!CloseHandle (fileHandle)) {
  1597. DEBUGMSG ((DBG_ERROR, "Error while closing file %s.", FileName));
  1598. }
  1599. }
  1600. FreePathString (pattern);
  1601. return TRUE;
  1602. }
  1603. BOOL
  1604. pArrangeMigDbFile (
  1605. IN PCTSTR SrcFile,
  1606. IN PCTSTR DestFile
  1607. )
  1608. {
  1609. return CopyFile (SrcFile, DestFile, FALSE);
  1610. }