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.

7705 lines
210 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. ism.c
  5. Abstract:
  6. Implements routines that are common to the entire ISM.
  7. Author:
  8. Jim Schmidt (jimschm) 21-Mar-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "ism.h"
  17. #include "ismp.h"
  18. #include "modules.h"
  19. #define DBG_ISM "Ism"
  20. //
  21. // Strings
  22. //
  23. #define S_LOCK_KEY TEXT("Locks\\%X")
  24. #define S_TRANSPORT_TYPES TEXT("TransportTypes")
  25. #define S_DATABASEFILE_LITE TEXT("|MainDatabaseFile\\LITE") // pipe is to decorate for uniqueness
  26. #define S_DATABASEFILE_FULL TEXT("|MainDatabaseFile\\Full") // pipe is to decorate for uniqueness
  27. #define S_VER_OSTYPE TEXT("OsVersionType")
  28. #define S_VER_OSMAJOR TEXT("OsVersionMajor")
  29. #define S_VER_OSMINOR TEXT("OsVersionMinor")
  30. #define S_VER_OSBUILD TEXT("OsVersionBuild")
  31. //
  32. // Constants
  33. //
  34. #define ISM_TMP_SIGNATURE 0x544D5355
  35. #define OBJECT_LOCKED 0x00000001
  36. #define GROUP_ID 0x00000001
  37. #define ITEM_ID 0x00000002
  38. //
  39. // Macros
  40. //
  41. // None
  42. //
  43. // Types
  44. //
  45. typedef struct {
  46. MEMDB_ENUM MemDbEnum;
  47. DBENUM_ARGS ParsedPatterns;
  48. } OBJECTENUM_HANDLE, *POBJECTENUM_HANDLE;
  49. typedef enum {
  50. TESTATE_BEGINTRANSPORT,
  51. TESTATE_GETCAPS,
  52. TESTATE_RETURN,
  53. TESTATE_NEXTTRANSPORTTYPE,
  54. TESTATE_NEXTTRANSPORT,
  55. TESTATE_DONE
  56. } TRANSPORTENUMSTATE;
  57. typedef struct {
  58. HASHTABLE_ENUM TableEnum;
  59. MEMDB_ENUM MemDbEnum;
  60. TRANSPORTENUMSTATE State;
  61. MIG_TRANSPORTSTORAGEID DesiredStorageId;
  62. } TRANSPORTENUMHANDLE, *PTRANSPORTENUMHANDLE;
  63. typedef struct {
  64. UINT SliceSize;
  65. UINT CurrentPosition;
  66. UINT SliceSizeInSeconds;
  67. } PROGSLICE, *PPROGSLICE;
  68. //
  69. // Globals
  70. //
  71. MIG_OBJECTCOUNT g_TotalObjects;
  72. MIG_OBJECTCOUNT g_SourceObjects;
  73. MIG_OBJECTCOUNT g_DestinationObjects;
  74. HANDLE g_CancelEvent;
  75. HANDLE g_ActivityEvent;
  76. HASHTABLE g_TransportTable;
  77. HASHTABLE g_ControlFileTable;
  78. PMHANDLE g_IsmPool;
  79. PMHANDLE g_IsmUntrackedPool;
  80. HINF g_IsmInf = INVALID_HANDLE_VALUE;
  81. PCTSTR g_CurrentGroup = NULL;
  82. UINT g_IsmCurrentPlatform = PLATFORM_CURRENT;
  83. UINT g_IsmModulePlatformContext = PLATFORM_CURRENT;
  84. PRESTORE_STRUCT g_RestoreCallbacks = NULL;
  85. PCOMPARE_STRUCT g_CompareCallbacks = NULL;
  86. PMESSAGECALLBACK g_MessageCallback;
  87. PTRANSPORTDATA g_SelectedTransport;
  88. MIG_TRANSPORTSTORAGEID g_SelectedTransportId;
  89. GROWBUFFER g_SliceBuffer;
  90. MIG_PROGRESSPHASE g_CurrentPhase;
  91. PPROGRESSBARFN g_ProgressBarFn;
  92. ULONG_PTR g_ProgressBarArg;
  93. MIG_TRANSPORTTYPE g_TransportType = 0;
  94. PTEMPORARYPROFILE g_TempProfile;
  95. PMIG_LOGCALLBACK g_LogCallback;
  96. PCTSTR g_JournalDirectory = NULL;
  97. BOOL g_PreserveJournal = FALSE;
  98. HANDLE g_JournalHandle = NULL;
  99. BOOL g_RollbackMode = FALSE;
  100. BOOL g_JournalUsed = FALSE;
  101. BOOL g_ExecutionInProgress = FALSE;
  102. PCTSTR g_DelayedOperationsCommand = NULL;
  103. BOOL g_EngineInitialized;
  104. BOOL g_EngineTerminated;
  105. BOOL g_MakeProfilePermanent = FALSE;
  106. // temporary storage
  107. TCHAR g_GlobalTempDir [MAX_PATH] = TEXT("");
  108. UINT g_TempDirIndex = 0;
  109. UINT g_TempFileIndex = 0;
  110. // execute
  111. HASHTABLE g_PreProcessTable = NULL;
  112. HASHTABLE g_RefreshTable = NULL;
  113. HASHTABLE g_PostProcessTable = NULL;
  114. BOOL g_PreProcessDone = FALSE;
  115. #ifdef PRERELEASE
  116. // crash hooks
  117. MIG_OBJECTTYPEID g_CrashCountTypeId = 0;
  118. DWORD g_CrashCountType = 0;
  119. DWORD g_CrashCountObjects = 0;
  120. MIG_OBJECTTYPEID g_CrashNameTypeId = 0;
  121. PCTSTR g_CrashNameObject = NULL;
  122. #endif
  123. //
  124. // Macro expansion list
  125. //
  126. // None
  127. //
  128. // Private function prototypes
  129. //
  130. VOID
  131. pCallProgressBar (
  132. IN MIG_PROGRESSSTATE State
  133. );
  134. BOOL
  135. pEnumFirstTransportType (
  136. OUT PMEMDB_ENUM EnumPtr
  137. );
  138. BOOL
  139. pEnumNextTransportType (
  140. IN OUT PMEMDB_ENUM EnumPtr
  141. );
  142. VOID
  143. pAbortTransportTypeEnum (
  144. IN OUT PMEMDB_ENUM EnumPtr
  145. );
  146. BOOL
  147. pEnumFirstVirtualObject (
  148. OUT PMIG_OBJECT_ENUM ObjectEnum,
  149. IN MIG_OBJECTTYPEID ObjectTypeId,
  150. IN MIG_OBJECTSTRINGHANDLE ObjectPattern
  151. );
  152. BOOL
  153. pEnumNextVirtualObject (
  154. IN OUT PMIG_OBJECT_ENUM ObjectEnum
  155. );
  156. VOID
  157. pAbortVirtualObjectEnum (
  158. IN PMIG_OBJECT_ENUM ObjectEnum
  159. );
  160. BOOL
  161. pEnablePrivilege (
  162. IN PCTSTR PrivilegeName,
  163. IN BOOL Enable
  164. );
  165. VOID
  166. pFreeRestoreCallbacks (
  167. VOID
  168. );
  169. VOID
  170. pFreeCompareCallbacks (
  171. VOID
  172. );
  173. VOID
  174. pRecordUserData (
  175. IN PCTSTR UserName,
  176. IN PCTSTR UserDomain,
  177. IN PCTSTR UserStringSid,
  178. IN PCTSTR UserProfilePath,
  179. IN BOOL ProfileCreated
  180. );
  181. //
  182. // Macro expansion definition
  183. //
  184. // None
  185. //
  186. // Code
  187. //
  188. BOOL
  189. WINAPI
  190. DllMain (
  191. IN HINSTANCE hInstance,
  192. IN DWORD dwReason,
  193. IN LPVOID lpReserved
  194. )
  195. {
  196. if (dwReason == DLL_PROCESS_ATTACH) {
  197. g_hInst = hInstance;
  198. }
  199. return TRUE;
  200. }
  201. BOOL
  202. CheckCancel (
  203. VOID
  204. )
  205. {
  206. BOOL cancelled;
  207. if (g_EngineTerminated) {
  208. SetLastError (ERROR_REQUEST_ABORTED);
  209. DEBUGMSG ((DBG_ERROR, "CheckCancel called after engine was terminated"));
  210. return TRUE;
  211. }
  212. if (!g_EngineInitialized) {
  213. SetLastError (ERROR_REQUEST_ABORTED);
  214. DEBUGMSG ((DBG_WARNING, "Engine is not initialized"));
  215. return TRUE;
  216. }
  217. cancelled = (WaitForSingleObject (g_CancelEvent, 0) == WAIT_OBJECT_0);
  218. if (cancelled) {
  219. SetLastError (ERROR_CANCELLED);
  220. DEBUGMSG ((DBG_ISM, "Cancel signaled"));
  221. }
  222. return cancelled;
  223. }
  224. MIG_OBJECTTYPEID
  225. FixObjectTypeId (
  226. IN MIG_OBJECTTYPEID ObjectTypeId
  227. )
  228. {
  229. if ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_CURRENT) {
  230. return (ObjectTypeId | g_IsmCurrentPlatform);
  231. }
  232. return ObjectTypeId;
  233. }
  234. MIG_OBJECTTYPEID
  235. FixEnumerationObjectTypeId (
  236. IN MIG_OBJECTTYPEID ObjectTypeId
  237. )
  238. {
  239. if ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_CURRENT) {
  240. if (g_IsmModulePlatformContext == PLATFORM_CURRENT) {
  241. return (ObjectTypeId | g_IsmCurrentPlatform);
  242. } else {
  243. return (ObjectTypeId | g_IsmModulePlatformContext);
  244. }
  245. }
  246. return ObjectTypeId;
  247. }
  248. BOOL
  249. pEnablePrivilege (
  250. IN PCTSTR PrivilegeName,
  251. IN BOOL Enable
  252. )
  253. {
  254. HANDLE token;
  255. BOOL b;
  256. TOKEN_PRIVILEGES newPrivileges;
  257. LUID luid;
  258. if (ISWIN9X ()) {
  259. return TRUE;
  260. }
  261. if (!OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) {
  262. return FALSE;
  263. }
  264. if (!LookupPrivilegeValue (NULL, PrivilegeName, &luid)) {
  265. CloseHandle (token);
  266. return FALSE;
  267. }
  268. newPrivileges.PrivilegeCount = 1;
  269. newPrivileges.Privileges[0].Luid = luid;
  270. newPrivileges.Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0;
  271. b = AdjustTokenPrivileges(
  272. token,
  273. FALSE,
  274. &newPrivileges,
  275. 0,
  276. NULL,
  277. NULL
  278. );
  279. CloseHandle (token);
  280. return b;
  281. }
  282. #ifdef PRERELEASE
  283. VOID
  284. LoadCrashHooks (
  285. VOID
  286. )
  287. {
  288. HINF crashInf;
  289. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  290. PCTSTR typeName;
  291. PCTSTR objectName;
  292. crashInf = InfOpenInfFile (TEXT("c:\\crash.inf"));
  293. if (crashInf == INVALID_HANDLE_VALUE) {
  294. return;
  295. }
  296. if (InfFindFirstLine (crashInf, TEXT("TotalNumber"), NULL, &is)) {
  297. InfGetIntField (&is, 1, &g_CrashCountObjects);
  298. }
  299. if (InfFindFirstLine (crashInf, TEXT("TypeNumber"), NULL, &is)) {
  300. typeName = InfGetStringField (&is, 1);
  301. if (typeName) {
  302. g_CrashCountTypeId = IsmGetObjectTypeId (typeName);
  303. InfGetIntField (&is, 2, &g_CrashCountType);
  304. }
  305. }
  306. if (InfFindFirstLine (crashInf, TEXT("TypeObject"), NULL, &is)) {
  307. typeName = InfGetStringField (&is, 1);
  308. objectName = InfGetStringField (&is, 2);
  309. if (typeName && objectName) {
  310. g_CrashNameTypeId = IsmGetObjectTypeId (typeName);
  311. g_CrashNameObject = IsmGetMemory (SizeOfString (objectName));
  312. StringCopy ((PTSTR)g_CrashNameObject, objectName);
  313. }
  314. }
  315. InfCleanUpInfStruct (&is);
  316. InfCloseInfFile (crashInf);
  317. }
  318. #endif
  319. BOOL
  320. pWriteIsmSig (
  321. IN PCTSTR DirName
  322. )
  323. {
  324. TCHAR tempName [MAX_PATH];
  325. HANDLE tempHandle;
  326. DWORD tempSig = ISM_TMP_SIGNATURE;
  327. StringCopy (tempName, DirName);
  328. StringCopy (AppendWack (tempName), TEXT("USMT.TMP"));
  329. tempHandle = BfCreateFile (tempName);
  330. if (!tempHandle) {
  331. return FALSE;
  332. }
  333. if (!BfWriteFile (tempHandle, (PCBYTE)(&tempSig), sizeof (DWORD))) {
  334. CloseHandle (tempHandle);
  335. DeleteFile (tempName);
  336. return FALSE;
  337. }
  338. CloseHandle (tempHandle);
  339. return TRUE;
  340. }
  341. BOOL
  342. pReadIsmSig (
  343. IN PCTSTR DirName
  344. )
  345. {
  346. TCHAR tempName [MAX_PATH];
  347. HANDLE tempHandle;
  348. DWORD tempSig;
  349. StringCopy (tempName, DirName);
  350. StringCopy (AppendWack (tempName), TEXT("USMT.TMP"));
  351. tempHandle = BfOpenReadFile (tempName);
  352. if (!tempHandle) {
  353. return FALSE;
  354. }
  355. if (!BfReadFile (tempHandle, (PBYTE)(&tempSig), sizeof (DWORD))) {
  356. CloseHandle (tempHandle);
  357. DeleteFile (tempName);
  358. return FALSE;
  359. }
  360. if (tempSig != ISM_TMP_SIGNATURE) {
  361. CloseHandle (tempHandle);
  362. DeleteFile (tempName);
  363. return FALSE;
  364. }
  365. CloseHandle (tempHandle);
  366. return TRUE;
  367. }
  368. BOOL
  369. pCreateTempStorage (
  370. VOID
  371. )
  372. {
  373. DRIVE_ENUM driveEnum;
  374. GROWBUFFER excludedDrv = INIT_GROWBUFFER;
  375. TCHAR driveName [4] = TEXT("");
  376. DWORD sectPerClust;
  377. DWORD bytesPerSect;
  378. DWORD freeClusters;
  379. DWORD totalClusters;
  380. ULONGLONG maxFreeDiskSpace = 0;
  381. ULONGLONG freeDiskSpace = 0;
  382. UINT index = 0;
  383. PTSTR endStr = NULL;
  384. BOOL found = FALSE;
  385. BOOL hideDir = FALSE;
  386. // we are going to walk the fixed drives picking up the one
  387. // with the most available space. In the root we are going
  388. // to create a directory and mark it as ours by creating a
  389. // special file called USMT.TMP that will have a signature in it.
  390. // The directory name is normally USMT.TMP. If the directory
  391. // already exists and does not have our special file in it
  392. // we are going to pick another name (USMT%04d.TMP), otherwise
  393. // we are going to overwrite it.
  394. while (!found) {
  395. *driveName = 0;
  396. maxFreeDiskSpace = 0;
  397. if (EnumFirstDrive (&driveEnum, DRIVEENUM_FIXED)) {
  398. do {
  399. if (IsStrInMultiSz (driveEnum.DriveName, (PCTSTR)excludedDrv.Buf)) {
  400. continue;
  401. }
  402. freeDiskSpace = 0;
  403. if (GetDiskFreeSpace (driveEnum.DriveName, &sectPerClust, &bytesPerSect, &freeClusters, &totalClusters)) {
  404. freeDiskSpace = Int32x32To64 ((sectPerClust * bytesPerSect), freeClusters);
  405. }
  406. if (freeDiskSpace > maxFreeDiskSpace) {
  407. StringCopyTcharCount (driveName, driveEnum.DriveName, 4);
  408. maxFreeDiskSpace = freeDiskSpace;
  409. }
  410. } while (EnumNextDrive (&driveEnum));
  411. }
  412. while (index < 0xFFFF) {
  413. if (*driveName) {
  414. StringCopy (g_GlobalTempDir, driveName);
  415. hideDir = TRUE;
  416. } else {
  417. GetTempPath (ARRAYSIZE(g_GlobalTempDir), g_GlobalTempDir);
  418. hideDir = FALSE;
  419. }
  420. if (index) {
  421. endStr = GetEndOfString (g_GlobalTempDir);
  422. wsprintf (endStr, TEXT("USMT%04X.TMP"), index);
  423. } else {
  424. StringCat (g_GlobalTempDir, TEXT("USMT.TMP"));
  425. }
  426. if (!DoesFileExist (g_GlobalTempDir)) {
  427. if (BfCreateDirectory (g_GlobalTempDir)) {
  428. if (pWriteIsmSig (g_GlobalTempDir)) {
  429. found = TRUE;
  430. if (hideDir) {
  431. SetFileAttributes (g_GlobalTempDir, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
  432. }
  433. break;
  434. }
  435. }
  436. // If we are here, we failed to create the temp dir
  437. // on this drive. This should have succeeded so this
  438. // means that the drive is locked down somehow.
  439. if (*driveName) {
  440. // Let's bail out and add the drive to the exclude list.
  441. GbMultiSzAppend (&excludedDrv, driveName);
  442. }
  443. break;
  444. }
  445. if (pReadIsmSig (g_GlobalTempDir)) {
  446. if (FiRemoveAllFilesInTree (g_GlobalTempDir)) {
  447. if (BfCreateDirectory (g_GlobalTempDir)) {
  448. if (pWriteIsmSig (g_GlobalTempDir)) {
  449. found = TRUE;
  450. if (hideDir) {
  451. SetFileAttributes (g_GlobalTempDir, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
  452. }
  453. break;
  454. }
  455. }
  456. // If we are here, we failed to create the temp dir
  457. // on this drive. This should have succeeded so this
  458. // means that the drive is locked down somehow.
  459. if (*driveName) {
  460. // Let's bail out and add the drive to the exclude list.
  461. GbMultiSzAppend (&excludedDrv, driveName);
  462. }
  463. break;
  464. }
  465. }
  466. index ++;
  467. }
  468. if (!(*driveName)) {
  469. break;
  470. }
  471. }
  472. GbFree (&excludedDrv);
  473. return found;
  474. }
  475. BOOL
  476. IsmGetTempStorage (
  477. OUT PTSTR Path,
  478. IN UINT PathTchars
  479. )
  480. {
  481. MYASSERT (*g_GlobalTempDir);
  482. if (*g_GlobalTempDir) {
  483. StringCopyTcharCount (Path, g_GlobalTempDir, PathTchars);
  484. return TRUE;
  485. }
  486. return FALSE;
  487. }
  488. BOOL
  489. IsmGetTempDirectory (
  490. OUT PTSTR Path,
  491. IN UINT PathTchars
  492. )
  493. {
  494. PTSTR endStr = NULL;
  495. if (!IsmGetTempStorage (Path, PathTchars)) {
  496. return FALSE;
  497. }
  498. endStr = GetEndOfString (Path);
  499. while (g_TempDirIndex < 0xFFFFFFFF) {
  500. wsprintf (endStr, TEXT("\\DIR%04X.TMP"), g_TempDirIndex);
  501. if (!DoesFileExist (Path)) {
  502. if (BfCreateDirectory (Path)) {
  503. g_TempDirIndex ++;
  504. return TRUE;
  505. }
  506. }
  507. g_TempDirIndex ++;
  508. }
  509. return FALSE;
  510. }
  511. BOOL
  512. IsmGetTempFile (
  513. OUT PTSTR Path,
  514. IN UINT PathTchars
  515. )
  516. {
  517. PTSTR endStr = NULL;
  518. if (!IsmGetTempStorage (Path, PathTchars)) {
  519. return FALSE;
  520. }
  521. endStr = GetEndOfString (Path);
  522. while (g_TempFileIndex < 0xFFFFFFFF) {
  523. wsprintf (endStr, TEXT("\\FILE%04X.TMP"), g_TempFileIndex);
  524. if (!DoesFileExist (Path)) {
  525. g_TempFileIndex ++;
  526. return TRUE;
  527. }
  528. g_TempFileIndex ++;
  529. }
  530. return FALSE;
  531. }
  532. BOOL
  533. IsmInitialize (
  534. IN PCTSTR InfPath,
  535. IN PMESSAGECALLBACK MessageCallback, OPTIONAL
  536. IN PMIG_LOGCALLBACK LogCallback
  537. )
  538. {
  539. BOOL result = FALSE;
  540. BOOL logInitError = FALSE;
  541. TCHAR memdbDir[MAX_TCHAR_PATH];
  542. g_ExecutionInProgress = TRUE;
  543. __try {
  544. SetErrorMode (SEM_FAILCRITICALERRORS);
  545. //
  546. // Initialize utilities. They produce their own debug messages.
  547. //
  548. UtInitialize (NULL);
  549. LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
  550. if (!FileEnumInitialize ()) {
  551. logInitError = TRUE;
  552. __leave;
  553. }
  554. // Initialize the temporary storage
  555. if (!pCreateTempStorage ()) {
  556. logInitError = TRUE;
  557. __leave;
  558. }
  559. if (!IsmGetTempDirectory (memdbDir, ARRAYSIZE (memdbDir))) {
  560. logInitError = TRUE;
  561. __leave;
  562. }
  563. if (!MemDbInitializeEx (memdbDir)) {
  564. logInitError = TRUE;
  565. __leave;
  566. }
  567. if (!RegInitialize ()) {
  568. logInitError = TRUE;
  569. __leave;
  570. }
  571. RegInitializeCache (8);
  572. InfGlobalInit (FALSE);
  573. //
  574. // Turn on privileges
  575. //
  576. if (!pEnablePrivilege (SE_BACKUP_NAME, TRUE)) {
  577. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_BACKUP_PRIVLEDGE));
  578. __leave;
  579. }
  580. if (!pEnablePrivilege (SE_RESTORE_NAME, TRUE)) {
  581. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_RESTORE_PRIVLEDGE));
  582. __leave;
  583. }
  584. //
  585. // Initialize ISM globals
  586. //
  587. g_CancelEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
  588. if (!g_CancelEvent) {
  589. DEBUGMSG ((DBG_ERROR, "Can't create cancel event"));
  590. __leave;
  591. }
  592. g_ActivityEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
  593. if (!g_ActivityEvent) {
  594. DEBUGMSG ((DBG_ERROR, "Can't create activity event"));
  595. CloseHandle (g_CancelEvent);
  596. __leave;
  597. }
  598. g_TransportTable = HtAllocWithData (sizeof (PTRANSPORTDATA));
  599. g_ControlFileTable = HtAlloc ();
  600. g_IsmInf = InfOpenInfFile (InfPath);
  601. if (g_IsmInf == INVALID_HANDLE_VALUE) {
  602. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INVALID_ISM_INF, InfPath));
  603. SetLastError (ERROR_FILE_NOT_FOUND);
  604. __leave;
  605. }
  606. if (!g_IsmPool) {
  607. g_IsmPool = PmCreateNamedPool ("ISM Pool");
  608. }
  609. if (!g_IsmUntrackedPool) {
  610. g_IsmUntrackedPool = PmCreatePool ();
  611. PmDisableTracking (g_IsmUntrackedPool);
  612. }
  613. //
  614. // Initialize internal modules
  615. //
  616. if (!InitializeEnv ()) {
  617. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 1));
  618. __leave;
  619. }
  620. if (!InitializeFlowControl ()) {
  621. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 3));
  622. __leave;
  623. }
  624. PrepareEnumerationEnvironment (TRUE);
  625. if (!InitializeTypeMgr ()) {
  626. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 2));
  627. __leave;
  628. }
  629. if (!InitializeOperations ()) {
  630. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 4));
  631. __leave;
  632. }
  633. g_MessageCallback = MessageCallback;
  634. //
  635. // Set the journal location
  636. //
  637. IsmSetRollbackJournalType (TRUE);
  638. g_PreProcessTable = HtAllocWithData (sizeof (PCTSTR));
  639. g_RefreshTable = HtAllocWithData (sizeof (PCTSTR));
  640. g_PostProcessTable = HtAllocWithData (sizeof (PCTSTR));
  641. g_EngineInitialized = TRUE;
  642. result = TRUE;
  643. }
  644. __finally {
  645. g_ExecutionInProgress = FALSE;
  646. if (!result) {
  647. IsmTerminate();
  648. }
  649. }
  650. if (logInitError) {
  651. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_ENGINE_INIT_FAILURE));
  652. }
  653. return result;
  654. }
  655. BOOL
  656. IsmSetPlatform (
  657. IN MIG_PLATFORMTYPEID Platform
  658. )
  659. {
  660. OSVERSIONINFO versionInfo;
  661. MIG_OSVERSIONINFO migVerInfo;
  662. TCHAR tempStr [sizeof (UINT) * 2 + 3];
  663. MIG_OBJECTSTRINGHANDLE tempHandle = NULL;
  664. if (Platform == PLATFORM_SOURCE) {
  665. if (!RegisterInternalAttributes ()) {
  666. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 5));
  667. return FALSE;
  668. }
  669. }
  670. //
  671. // write the source or the destination machine version information
  672. // in the environment
  673. //
  674. ZeroMemory (&versionInfo, sizeof (OSVERSIONINFO));
  675. versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  676. ZeroMemory (&migVerInfo, sizeof (MIG_OSVERSIONINFO));
  677. if (GetVersionEx (&versionInfo)) {
  678. if (versionInfo.dwPlatformId == 1) {
  679. migVerInfo.OsType = OSTYPE_WINDOWS9X;
  680. migVerInfo.OsTypeName = OSTYPE_WINDOWS9X_STR;
  681. if (versionInfo.dwMajorVersion == 4) {
  682. if (versionInfo.dwMinorVersion == 0) {
  683. migVerInfo.OsMajorVersion = OSMAJOR_WIN95;
  684. migVerInfo.OsMajorVersionName = OSMAJOR_WIN95_STR;
  685. migVerInfo.OsMinorVersion = OSMINOR_GOLD;
  686. migVerInfo.OsMinorVersionName = OSMINOR_GOLD_STR;
  687. if (LOWORD (versionInfo.dwBuildNumber) >= 1111) {
  688. migVerInfo.OsMajorVersion = OSMAJOR_WIN95OSR2;
  689. migVerInfo.OsMajorVersionName = OSMAJOR_WIN95OSR2_STR;
  690. }
  691. } else if (versionInfo.dwMinorVersion == 10) {
  692. migVerInfo.OsMajorVersion = OSMAJOR_WIN98;
  693. migVerInfo.OsMajorVersionName = OSMAJOR_WIN98_STR;
  694. migVerInfo.OsMinorVersion = OSMINOR_GOLD;
  695. migVerInfo.OsMinorVersionName = OSMINOR_GOLD_STR;
  696. if (LOWORD (versionInfo.dwBuildNumber) >= 2222) {
  697. migVerInfo.OsMinorVersion = OSMINOR_WIN98SE;
  698. migVerInfo.OsMinorVersionName = OSMINOR_WIN98SE_STR;
  699. }
  700. } else if (versionInfo.dwMinorVersion == 90) {
  701. migVerInfo.OsMajorVersion = OSMAJOR_WINME;
  702. migVerInfo.OsMajorVersionName = OSMAJOR_WINME_STR;
  703. migVerInfo.OsMinorVersion = OSMINOR_GOLD;
  704. migVerInfo.OsMinorVersionName = OSMINOR_GOLD_STR;
  705. }
  706. }
  707. }
  708. if (versionInfo.dwPlatformId == 2) {
  709. migVerInfo.OsType = OSTYPE_WINDOWSNT;
  710. migVerInfo.OsTypeName = OSTYPE_WINDOWSNT_STR;
  711. if (versionInfo.dwMajorVersion == 4) {
  712. migVerInfo.OsMajorVersion = OSMAJOR_WINNT4;
  713. migVerInfo.OsMajorVersionName = OSMAJOR_WINNT4_STR;
  714. migVerInfo.OsMinorVersion = versionInfo.dwMinorVersion;
  715. if (migVerInfo.OsMinorVersion == OSMINOR_GOLD) {
  716. migVerInfo.OsMinorVersionName = OSMINOR_GOLD_STR;
  717. }
  718. }
  719. if (versionInfo.dwMajorVersion == 5) {
  720. migVerInfo.OsMajorVersion = OSMAJOR_WINNT5;
  721. migVerInfo.OsMajorVersionName = OSMAJOR_WINNT5_STR;
  722. migVerInfo.OsMinorVersion = versionInfo.dwMinorVersion;
  723. if (migVerInfo.OsMinorVersion == OSMINOR_GOLD) {
  724. migVerInfo.OsMinorVersionName = OSMINOR_GOLD_STR;
  725. } else if (migVerInfo.OsMinorVersion == OSMINOR_WINNT51) {
  726. migVerInfo.OsMinorVersionName = OSMINOR_WINNT51_STR;
  727. }
  728. }
  729. }
  730. wsprintf (tempStr, TEXT("0x%08X"), migVerInfo.OsType);
  731. IsmSetEnvironmentString (Platform, NULL, S_VER_OSTYPE, tempStr);
  732. wsprintf (tempStr, TEXT("0x%08X"), migVerInfo.OsMajorVersion);
  733. IsmSetEnvironmentString (Platform, NULL, S_VER_OSMAJOR, tempStr);
  734. wsprintf (tempStr, TEXT("0x%08X"), migVerInfo.OsMinorVersion);
  735. IsmSetEnvironmentString (Platform, NULL, S_VER_OSMINOR, tempStr);
  736. wsprintf (tempStr, TEXT("0x%08X"), versionInfo.dwBuildNumber);
  737. IsmSetEnvironmentString (Platform, NULL, S_VER_OSBUILD, tempStr);
  738. }
  739. if (Platform == PLATFORM_SOURCE) {
  740. // let's exclude our temporary directory
  741. tempHandle = IsmCreateObjectHandle (g_GlobalTempDir, NULL);
  742. if (tempHandle) {
  743. IsmRegisterStaticExclusion (MIG_FILE_TYPE, tempHandle);
  744. IsmDestroyObjectHandle (tempHandle);
  745. tempHandle = NULL;
  746. }
  747. }
  748. g_IsmCurrentPlatform = Platform;
  749. return TRUE;
  750. }
  751. BOOL
  752. pPrepareUserJournal (
  753. IN OUT PTEMPORARYPROFILE UserProfile
  754. )
  755. {
  756. BOOL result = FALSE;
  757. DWORD tempField;
  758. PCTSTR journalFile = NULL;
  759. if (UserProfile && UserProfile->UserProfileRoot) {
  760. __try {
  761. UserProfile->DelayedOpJrn = JoinPaths (UserProfile->UserProfileRoot, TEXT("usrusmt2.tmp"));
  762. FiRemoveAllFilesInTree (UserProfile->DelayedOpJrn);
  763. if (!BfCreateDirectory (UserProfile->DelayedOpJrn)) {
  764. __leave;
  765. }
  766. journalFile = JoinPaths (UserProfile->DelayedOpJrn, TEXT("JOURNAL.DAT"));
  767. UserProfile->DelayedOpJrnHandle = BfCreateFile (journalFile);
  768. if (UserProfile->DelayedOpJrnHandle == INVALID_HANDLE_VALUE) {
  769. __leave;
  770. }
  771. tempField = JRN_USR_SIGNATURE;
  772. BfWriteFile (UserProfile->DelayedOpJrnHandle, (PBYTE)(&tempField), sizeof (DWORD));
  773. tempField = JRN_USR_VERSION;
  774. BfWriteFile (UserProfile->DelayedOpJrnHandle, (PBYTE)(&tempField), sizeof (DWORD));
  775. tempField = JRN_USR_DIRTY;
  776. BfWriteFile (UserProfile->DelayedOpJrnHandle, (PBYTE)(&tempField), sizeof (DWORD));
  777. FlushFileBuffers (UserProfile->DelayedOpJrnHandle);
  778. FreePathString (journalFile);
  779. result = TRUE;
  780. }
  781. __finally {
  782. if (!result) {
  783. if (UserProfile->DelayedOpJrn) {
  784. FreePathString (UserProfile->DelayedOpJrn);
  785. UserProfile->DelayedOpJrn = NULL;
  786. }
  787. if (!UserProfile->DelayedOpJrnHandle || (UserProfile->DelayedOpJrnHandle == INVALID_HANDLE_VALUE)) {
  788. CloseHandle (UserProfile->DelayedOpJrnHandle);
  789. UserProfile->DelayedOpJrnHandle = NULL;
  790. }
  791. }
  792. }
  793. }
  794. return result;
  795. }
  796. BOOL
  797. pValidateUserJournal (
  798. IN PTEMPORARYPROFILE UserProfile,
  799. IN BOOL RunKeyAdded
  800. )
  801. {
  802. BOOL result = FALSE;
  803. DWORD tempField;
  804. __try {
  805. if (UserProfile->DelayedOpJrn) {
  806. if (RunKeyAdded) {
  807. if (UserProfile->DelayedOpJrnHandle && (UserProfile->DelayedOpJrnHandle != INVALID_HANDLE_VALUE)) {
  808. if (!BfSetFilePointer (UserProfile->DelayedOpJrnHandle, 2 * sizeof (DWORD))) {
  809. __leave;
  810. }
  811. tempField = JRN_USR_COMPLETE;
  812. BfWriteFile (UserProfile->DelayedOpJrnHandle, (PBYTE)(&tempField), sizeof (DWORD));
  813. FlushFileBuffers (UserProfile->DelayedOpJrnHandle);
  814. result = TRUE;
  815. }
  816. } else {
  817. // Run key command was not added, no point to
  818. // keep this journal here
  819. FiRemoveAllFilesInTree (UserProfile->DelayedOpJrn);
  820. result = TRUE;
  821. }
  822. }
  823. }
  824. __finally {
  825. if (UserProfile->DelayedOpJrnHandle && (UserProfile->DelayedOpJrnHandle != INVALID_HANDLE_VALUE)) {
  826. CloseHandle (UserProfile->DelayedOpJrnHandle);
  827. UserProfile->DelayedOpJrnHandle = NULL;
  828. }
  829. if (UserProfile->DelayedOpJrn) {
  830. FreePathString (UserProfile->DelayedOpJrn);
  831. UserProfile->DelayedOpJrn = NULL;
  832. }
  833. }
  834. return result;
  835. }
  836. BOOL
  837. pWriteDelayedOperationsCommand (
  838. IN PTEMPORARYPROFILE UserProfile
  839. )
  840. {
  841. HKEY runKeyHandle = NULL;
  842. PCTSTR runKeyStr = NULL;
  843. LONG rc;
  844. BOOL result = FALSE;
  845. __try {
  846. if (!UserProfile->MapKey) {
  847. LOG ((LOG_ERROR, (PCSTR) MSG_NO_MAPPED_USER));
  848. __leave;
  849. }
  850. runKeyStr = JoinPathsInPoolEx ((
  851. NULL,
  852. TEXT("HKEY_USERS"),
  853. UserProfile->MapKey,
  854. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"),
  855. NULL
  856. ));
  857. runKeyHandle = CreateRegKeyStr (runKeyStr);
  858. if (!runKeyHandle) {
  859. LOG ((LOG_ERROR, (PCSTR) MSG_RUN_KEY_CREATE_FAILURE));
  860. __leave;
  861. }
  862. rc = RegSetValueEx (
  863. runKeyHandle,
  864. TEXT("USMT2RUN"),
  865. 0,
  866. REG_EXPAND_SZ,
  867. (PBYTE) g_DelayedOperationsCommand,
  868. SizeOfString (g_DelayedOperationsCommand)
  869. );
  870. if (rc != ERROR_SUCCESS) {
  871. LOG ((LOG_ERROR, (PCSTR) MSG_RUN_KEY_CREATE_FAILURE));
  872. __leave;
  873. }
  874. result = TRUE;
  875. }
  876. __finally {
  877. if (runKeyHandle) {
  878. CloseRegKey (runKeyHandle);
  879. runKeyHandle = NULL;
  880. }
  881. if (runKeyStr) {
  882. FreePathString (runKeyStr);
  883. runKeyStr = NULL;
  884. }
  885. }
  886. return result;
  887. }
  888. BOOL
  889. pDeleteDelayedOperationsCommand (
  890. VOID
  891. )
  892. {
  893. HKEY runKeyHandle = NULL;
  894. LONG rc;
  895. BOOL result = FALSE;
  896. __try {
  897. runKeyHandle = OpenRegKeyStr (TEXT("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"));
  898. if (!runKeyHandle) {
  899. LOG ((LOG_ERROR, (PCSTR) MSG_RUN_KEY_DELETE_FAILURE));
  900. __leave;
  901. }
  902. rc = RegDeleteValue (
  903. runKeyHandle,
  904. TEXT("USMT2RUN")
  905. );
  906. if (rc != ERROR_SUCCESS) {
  907. LOG ((LOG_ERROR, (PCSTR) MSG_RUN_KEY_DELETE_FAILURE));
  908. __leave;
  909. }
  910. result = TRUE;
  911. }
  912. __finally {
  913. if (runKeyHandle) {
  914. CloseRegKey (runKeyHandle);
  915. runKeyHandle = NULL;
  916. }
  917. }
  918. return result;
  919. }
  920. VOID
  921. IsmTerminate (
  922. VOID
  923. )
  924. {
  925. HASHTABLE_ENUM e;
  926. BOOL runKeyAdded = FALSE;
  927. if (g_EngineTerminated) {
  928. g_EngineInitialized = FALSE;
  929. return;
  930. }
  931. // We need to try and terminate properties. In some cases the property file
  932. // remains opened.
  933. TerminateProperties (g_IsmCurrentPlatform);
  934. if (g_PreProcessTable) {
  935. if (EnumFirstHashTableString (&e, g_PreProcessTable)) {
  936. do {
  937. IsmReleaseMemory (*((PCTSTR *)e.ExtraData));
  938. } while (EnumNextHashTableString (&e));
  939. }
  940. HtFree (g_PreProcessTable);
  941. g_PreProcessTable = NULL;
  942. }
  943. if (g_RefreshTable) {
  944. if (EnumFirstHashTableString (&e, g_RefreshTable)) {
  945. do {
  946. if (!CheckCancel () && g_PreProcessDone) {
  947. IsmSendMessageToApp (ISMMESSAGE_EXECUTE_REFRESH, (ULONG_PTR) *((PCTSTR *)e.ExtraData));
  948. }
  949. IsmReleaseMemory (*((PCTSTR *)e.ExtraData));
  950. } while (EnumNextHashTableString (&e));
  951. }
  952. HtFree (g_RefreshTable);
  953. g_RefreshTable = NULL;
  954. }
  955. if (g_PostProcessTable) {
  956. if (EnumFirstHashTableString (&e, g_PostProcessTable)) {
  957. do {
  958. if (g_PreProcessDone) {
  959. IsmSendMessageToApp (ISMMESSAGE_EXECUTE_POSTPROCESS, (ULONG_PTR) *((PCTSTR *)e.ExtraData));
  960. }
  961. IsmReleaseMemory (*((PCTSTR *)e.ExtraData));
  962. } while (EnumNextHashTableString (&e));
  963. }
  964. HtFree (g_PostProcessTable);
  965. g_PostProcessTable = NULL;
  966. }
  967. g_PreProcessDone = FALSE;
  968. g_EngineInitialized = FALSE;
  969. g_ExecutionInProgress = TRUE;
  970. //
  971. // Terminate plug-in modules
  972. //
  973. TerminateProcessWideModules();
  974. //
  975. // Clean up journal
  976. //
  977. if (g_JournalDirectory && !g_PreserveJournal) {
  978. if (DoesFileExist (g_JournalDirectory)) {
  979. if (!FiRemoveAllFilesInTree (g_JournalDirectory)) {
  980. DEBUGMSG ((DBG_ERROR, "Cannot remove journal directory: %s", g_JournalDirectory));
  981. }
  982. }
  983. FreePathString (g_JournalDirectory);
  984. g_JournalDirectory = NULL;
  985. g_JournalUsed = FALSE;
  986. }
  987. if (g_TempProfile) {
  988. // let's write the Run key command line and set runKeyAdded to TRUE
  989. runKeyAdded = pWriteDelayedOperationsCommand (g_TempProfile);
  990. pValidateUserJournal (g_TempProfile, runKeyAdded);
  991. if (!CloseTemporaryProfile (g_TempProfile, g_MakeProfilePermanent)) {
  992. LOG ((
  993. LOG_MODULE_ERROR,
  994. (PCSTR) MSG_CANT_SAVE_PROFILE,
  995. g_TempProfile->UserName,
  996. GetLastError()
  997. ));
  998. CloseTemporaryProfile (g_TempProfile, FALSE);
  999. }
  1000. g_TempProfile = NULL;
  1001. }
  1002. if (g_DelayedOperationsCommand) {
  1003. FreePathString (g_DelayedOperationsCommand);
  1004. g_DelayedOperationsCommand = NULL;
  1005. }
  1006. //
  1007. // Terminate all control files
  1008. //
  1009. if (g_ControlFileTable) {
  1010. if (EnumFirstHashTableString (&e, g_ControlFileTable)) {
  1011. do {
  1012. DeleteFile (e.String);
  1013. } while (EnumNextHashTableString (&e));
  1014. }
  1015. HtFree (g_ControlFileTable);
  1016. g_ControlFileTable = NULL;
  1017. }
  1018. //
  1019. // Terminate internal modules
  1020. //
  1021. ClearEnumerationEnvironment (TRUE);
  1022. TerminateEnv ();
  1023. TerminateTypeMgr ();
  1024. TerminateFlowControl ();
  1025. TerminateOperations ();
  1026. //
  1027. // Destroy globals
  1028. //
  1029. pFreeRestoreCallbacks ();
  1030. pFreeCompareCallbacks ();
  1031. if (g_CancelEvent) {
  1032. CloseHandle (g_CancelEvent);
  1033. g_CancelEvent = NULL;
  1034. }
  1035. if (g_ActivityEvent) {
  1036. CloseHandle (g_ActivityEvent);
  1037. g_ActivityEvent = NULL;
  1038. }
  1039. GbFree (&g_SliceBuffer);
  1040. if (g_TransportTable) {
  1041. HtFree (g_TransportTable);
  1042. g_TransportTable = NULL;
  1043. }
  1044. if (g_IsmPool) {
  1045. PmDestroyPool (g_IsmPool);
  1046. g_IsmPool = NULL;
  1047. }
  1048. if (g_IsmUntrackedPool) {
  1049. PmDestroyPool (g_IsmUntrackedPool);
  1050. g_IsmUntrackedPool = NULL;
  1051. }
  1052. if (g_IsmInf != INVALID_HANDLE_VALUE) {
  1053. InfCloseInfFile (g_IsmInf);
  1054. g_IsmInf = INVALID_HANDLE_VALUE;
  1055. }
  1056. InfGlobalInit (TRUE);
  1057. MemDbTerminateEx (TRUE); // relies on fileenum
  1058. // let's remove the temporary storage, it's here because uses fileenum
  1059. if (*g_GlobalTempDir) {
  1060. if (!FiRemoveAllFilesInTree (g_GlobalTempDir)) {
  1061. DEBUGMSG ((DBG_ERROR, "Cannot remove temporary storage: %s", g_GlobalTempDir));
  1062. }
  1063. *g_GlobalTempDir = 0;
  1064. }
  1065. FileEnumTerminate ();
  1066. RegTerminate ();
  1067. UtTerminate ();
  1068. g_EngineTerminated = TRUE;
  1069. g_ExecutionInProgress = FALSE;
  1070. }
  1071. BOOL
  1072. IsmPreserveJournal (
  1073. IN BOOL Preserve
  1074. )
  1075. {
  1076. BOOL result = g_PreserveJournal;
  1077. g_PreserveJournal = Preserve;
  1078. return result;
  1079. }
  1080. BOOL
  1081. pEtmParse (
  1082. IN PVOID Reserved
  1083. )
  1084. {
  1085. HASHTABLE_ENUM e;
  1086. BOOL b = TRUE;
  1087. PETMDATA etmData;
  1088. PrepareEnumerationEnvironment (FALSE);
  1089. //
  1090. // Call the parse entry point
  1091. //
  1092. if (EnumFirstHashTableString (&e, g_EtmTable)) {
  1093. do {
  1094. etmData = *((PETMDATA *) e.ExtraData);
  1095. if (etmData->ShouldBeCalled && etmData->EtmParse) {
  1096. MYASSERT (!g_CurrentGroup);
  1097. g_CurrentGroup = etmData->Group;
  1098. b = etmData->EtmParse (Reserved);
  1099. g_CurrentGroup = NULL;
  1100. }
  1101. } while (b && EnumNextHashTableString (&e));
  1102. }
  1103. ClearEnumerationEnvironment (FALSE);
  1104. return b;
  1105. }
  1106. BOOL
  1107. pCreateComputerParse (
  1108. IN PVOID Reserved
  1109. )
  1110. {
  1111. HASHTABLE_ENUM e;
  1112. BOOL b = TRUE;
  1113. PVCMDATA vcmData;
  1114. PrepareEnumerationEnvironment (FALSE);
  1115. //
  1116. // Call the parse entry point
  1117. //
  1118. if (EnumFirstHashTableString (&e, g_VcmTable)) {
  1119. do {
  1120. vcmData = *((PVCMDATA *) e.ExtraData);
  1121. if (vcmData->ShouldBeCalled && vcmData->VcmParse) {
  1122. MYASSERT (!g_CurrentGroup);
  1123. g_CurrentGroup = vcmData->Group;
  1124. b = vcmData->VcmParse (Reserved);
  1125. g_CurrentGroup = NULL;
  1126. }
  1127. } while (b && EnumNextHashTableString (&e));
  1128. }
  1129. ClearEnumerationEnvironment (FALSE);
  1130. return b;
  1131. }
  1132. BOOL
  1133. pCreateComputerGather (
  1134. IN PVOID Reserved
  1135. )
  1136. {
  1137. HASHTABLE_ENUM e;
  1138. BOOL b = TRUE;
  1139. BOOL cancelled = FALSE;
  1140. PVCMDATA vcmData;
  1141. UINT containers;
  1142. MIG_PROGRESSSLICEID sliceId;
  1143. PrepareEnumerationEnvironment (FALSE);
  1144. //
  1145. // Queue high priority enumerations
  1146. //
  1147. if (b && EnumFirstHashTableString (&e, g_VcmTable)) {
  1148. do {
  1149. vcmData = *((PVCMDATA *) e.ExtraData);
  1150. if (vcmData->ShouldBeCalled && vcmData->VcmQueueHighPriorityEnumeration) {
  1151. MYASSERT (!g_CurrentGroup);
  1152. g_CurrentGroup = vcmData->Group;
  1153. b = vcmData->VcmQueueHighPriorityEnumeration (Reserved);
  1154. g_CurrentGroup = NULL;
  1155. }
  1156. } while (b && EnumNextHashTableString (&e));
  1157. }
  1158. g_CurrentPhase = MIG_HIGHPRIORITYGATHER_PHASE;
  1159. g_SliceBuffer.End = 0;
  1160. containers = EstimateAllObjectEnumerations (0, FALSE);
  1161. if (containers) {
  1162. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1163. } else {
  1164. sliceId = 0;
  1165. }
  1166. pCallProgressBar (MIG_BEGIN_PHASE);
  1167. //
  1168. // Run high priority enumeration queue
  1169. //
  1170. if (b) {
  1171. if (!DoAllObjectEnumerations (sliceId)) {
  1172. DEBUGMSG ((DBG_ERROR, "Internal ISM Error during high priority object enumeration."));
  1173. b = FALSE;
  1174. }
  1175. }
  1176. pCallProgressBar (MIG_END_PHASE);
  1177. ClearEnumerationEnvironment (FALSE);
  1178. PrepareEnumerationEnvironment (FALSE);
  1179. //
  1180. // Queue normal priority enumerations
  1181. //
  1182. if (b && EnumFirstHashTableString (&e, g_VcmTable)) {
  1183. do {
  1184. vcmData = *((PVCMDATA *) e.ExtraData);
  1185. if (vcmData->ShouldBeCalled) {
  1186. MYASSERT (!g_CurrentGroup);
  1187. g_CurrentGroup = vcmData->Group;
  1188. b = vcmData->VcmQueueEnumeration (Reserved);
  1189. g_CurrentGroup = NULL;
  1190. }
  1191. } while (b && EnumNextHashTableString (&e));
  1192. }
  1193. g_CurrentPhase = MIG_GATHER_PHASE;
  1194. g_SliceBuffer.End = 0;
  1195. containers = EstimateAllObjectEnumerations (0, FALSE);
  1196. if (containers) {
  1197. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1198. } else {
  1199. sliceId = 0;
  1200. }
  1201. pCallProgressBar (MIG_BEGIN_PHASE);
  1202. //
  1203. // Run normal priority enumeration queue
  1204. //
  1205. if (b) {
  1206. if (!DoAllObjectEnumerations (sliceId)) {
  1207. DEBUGMSG ((DBG_ERROR, "Internal ISM Error during object enumeration."));
  1208. b = FALSE;
  1209. }
  1210. }
  1211. ClearEnumerationEnvironment (FALSE);
  1212. pCallProgressBar (MIG_END_PHASE);
  1213. g_CurrentPhase = 0;
  1214. g_SliceBuffer.End = 0;
  1215. return b;
  1216. }
  1217. BOOL
  1218. pSourceParse (
  1219. IN PVOID Reserved
  1220. )
  1221. {
  1222. HASHTABLE_ENUM e;
  1223. BOOL b = TRUE;
  1224. PSGMDATA sgmData;
  1225. PrepareEnumerationEnvironment (FALSE);
  1226. //
  1227. // Call the parse entry point
  1228. //
  1229. if (b && EnumFirstHashTableString (&e, g_SgmTable)) {
  1230. do {
  1231. sgmData = *((PSGMDATA *) e.ExtraData);
  1232. if (sgmData->ShouldBeCalled && sgmData->SgmParse) {
  1233. MYASSERT (!g_CurrentGroup);
  1234. g_CurrentGroup = sgmData->Group;
  1235. b = sgmData->SgmParse (Reserved);
  1236. g_CurrentGroup = NULL;
  1237. }
  1238. } while (b && EnumNextHashTableString (&e));
  1239. }
  1240. ClearEnumerationEnvironment (FALSE);
  1241. return b;
  1242. }
  1243. BOOL
  1244. pSourceGather (
  1245. IN PVOID Reserved
  1246. )
  1247. {
  1248. HASHTABLE_ENUM e;
  1249. BOOL b = TRUE;
  1250. BOOL cancelled = FALSE;
  1251. PSGMDATA sgmData;
  1252. UINT containers;
  1253. MIG_PROGRESSSLICEID sliceId;
  1254. PrepareEnumerationEnvironment (FALSE);
  1255. //
  1256. // Estimate the queue high priority enumerations
  1257. //
  1258. containers = 0;
  1259. if (b && EnumFirstHashTableString (&e, g_SgmTable)) {
  1260. do {
  1261. sgmData = *((PSGMDATA *) e.ExtraData);
  1262. if (sgmData->ShouldBeCalled && sgmData->SgmQueueHighPriorityEnumeration) {
  1263. containers ++;
  1264. }
  1265. } while (b && EnumNextHashTableString (&e));
  1266. }
  1267. //
  1268. // Queue high priority enumerations
  1269. //
  1270. g_CurrentPhase = MIG_HIGHPRIORITYQUEUE_PHASE;
  1271. g_SliceBuffer.End = 0;
  1272. if (containers) {
  1273. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1274. } else {
  1275. sliceId = 0;
  1276. }
  1277. pCallProgressBar (MIG_BEGIN_PHASE);
  1278. if (b && EnumFirstHashTableString (&e, g_SgmTable)) {
  1279. do {
  1280. sgmData = *((PSGMDATA *) e.ExtraData);
  1281. if (sgmData->ShouldBeCalled && sgmData->SgmQueueHighPriorityEnumeration) {
  1282. MYASSERT (!g_CurrentGroup);
  1283. g_CurrentGroup = sgmData->Group;
  1284. b = sgmData->SgmQueueHighPriorityEnumeration (Reserved);
  1285. g_CurrentGroup = NULL;
  1286. // Call progress bar
  1287. IsmTickProgressBar (sliceId, 1);
  1288. }
  1289. } while (b && EnumNextHashTableString (&e));
  1290. }
  1291. pCallProgressBar (MIG_END_PHASE);
  1292. //
  1293. // Estimate the high priority enumerations estimate
  1294. //
  1295. containers = EstimateAllObjectEnumerations (0, TRUE);
  1296. //
  1297. // Estimate the high priority enumerations
  1298. //
  1299. g_CurrentPhase = MIG_HIGHPRIORITYESTIMATE_PHASE;
  1300. g_SliceBuffer.End = 0;
  1301. if (containers) {
  1302. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1303. } else {
  1304. sliceId = 0;
  1305. }
  1306. pCallProgressBar (MIG_BEGIN_PHASE);
  1307. containers = EstimateAllObjectEnumerations (sliceId, FALSE);
  1308. pCallProgressBar (MIG_END_PHASE);
  1309. //
  1310. // Run high priority enumeration queue
  1311. //
  1312. g_CurrentPhase = MIG_HIGHPRIORITYGATHER_PHASE;
  1313. g_SliceBuffer.End = 0;
  1314. if (containers) {
  1315. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1316. } else {
  1317. sliceId = 0;
  1318. }
  1319. pCallProgressBar (MIG_BEGIN_PHASE);
  1320. if (b) {
  1321. if (!DoAllObjectEnumerations (sliceId)) {
  1322. DEBUGMSG ((DBG_ERROR, "Internal ISM Error during high priority object enumeration."));
  1323. b = FALSE;
  1324. }
  1325. }
  1326. pCallProgressBar (MIG_END_PHASE);
  1327. ClearEnumerationEnvironment (FALSE);
  1328. PrepareEnumerationEnvironment (FALSE);
  1329. //
  1330. // Estimate the queue normal priority enumerations
  1331. //
  1332. containers = 0;
  1333. if (b && EnumFirstHashTableString (&e, g_SgmTable)) {
  1334. do {
  1335. sgmData = *((PSGMDATA *) e.ExtraData);
  1336. if (sgmData->ShouldBeCalled) {
  1337. containers ++;
  1338. }
  1339. } while (b && EnumNextHashTableString (&e));
  1340. }
  1341. //
  1342. // Queue normal priority enumerations
  1343. //
  1344. g_CurrentPhase = MIG_GATHERQUEUE_PHASE;
  1345. g_SliceBuffer.End = 0;
  1346. if (containers) {
  1347. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1348. } else {
  1349. sliceId = 0;
  1350. }
  1351. pCallProgressBar (MIG_BEGIN_PHASE);
  1352. if (b && EnumFirstHashTableString (&e, g_SgmTable)) {
  1353. do {
  1354. sgmData = *((PSGMDATA *) e.ExtraData);
  1355. if (sgmData->ShouldBeCalled) {
  1356. MYASSERT (!g_CurrentGroup);
  1357. g_CurrentGroup = sgmData->Group;
  1358. b = sgmData->SgmQueueEnumeration (Reserved);
  1359. g_CurrentGroup = NULL;
  1360. // Call progress bar
  1361. IsmTickProgressBar (sliceId, 1);
  1362. }
  1363. } while (b && EnumNextHashTableString (&e));
  1364. }
  1365. pCallProgressBar (MIG_END_PHASE);
  1366. //
  1367. // Estimate the normal priority enumerations estimate
  1368. //
  1369. containers = EstimateAllObjectEnumerations (0, TRUE);
  1370. //
  1371. // Estimate the normal priority enumerations
  1372. //
  1373. g_CurrentPhase = MIG_GATHERESTIMATE_PHASE;
  1374. g_SliceBuffer.End = 0;
  1375. if (containers) {
  1376. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1377. } else {
  1378. sliceId = 0;
  1379. }
  1380. pCallProgressBar (MIG_BEGIN_PHASE);
  1381. containers = EstimateAllObjectEnumerations (sliceId, FALSE);
  1382. pCallProgressBar (MIG_END_PHASE);
  1383. //
  1384. // Run normal priority enumeration queue
  1385. //
  1386. g_CurrentPhase = MIG_GATHER_PHASE;
  1387. g_SliceBuffer.End = 0;
  1388. if (containers) {
  1389. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1390. } else {
  1391. sliceId = 0;
  1392. }
  1393. pCallProgressBar (MIG_BEGIN_PHASE);
  1394. if (b) {
  1395. if (!DoAllObjectEnumerations (sliceId)) {
  1396. DEBUGMSG ((DBG_ERROR, "Internal ISM Error during object enumeration."));
  1397. b = FALSE;
  1398. }
  1399. }
  1400. ClearEnumerationEnvironment (FALSE);
  1401. pCallProgressBar (MIG_END_PHASE);
  1402. g_CurrentPhase = 0;
  1403. g_SliceBuffer.End = 0;
  1404. return b;
  1405. }
  1406. BOOL
  1407. pSourceAnalyze (
  1408. IN PVOID Reserved
  1409. )
  1410. {
  1411. HASHTABLE_ENUM e;
  1412. BOOL b = TRUE;
  1413. BOOL cancelled = FALSE;
  1414. PSAMDATA samData;
  1415. UINT modulesNeedingProgress = 0;
  1416. MIG_PROGRESSSLICEID sliceId = 0;
  1417. //
  1418. // Prepare a progress bar
  1419. //
  1420. g_CurrentPhase = MIG_ANALYSIS_PHASE;
  1421. g_SliceBuffer.End = 0;
  1422. if (b && EnumFirstHashTableString (&e, g_SamTable)) {
  1423. do {
  1424. samData = *((PSAMDATA *) e.ExtraData);
  1425. if (samData->ShouldBeCalled) {
  1426. if (samData->SamEstimateProgressBar) {
  1427. samData->SamEstimateProgressBar();
  1428. } else {
  1429. modulesNeedingProgress++;
  1430. }
  1431. }
  1432. } while (b && EnumNextHashTableString (&e));
  1433. }
  1434. if (modulesNeedingProgress) {
  1435. sliceId = IsmRegisterProgressSlice (
  1436. modulesNeedingProgress,
  1437. modulesNeedingProgress * 10
  1438. );
  1439. }
  1440. pCallProgressBar (MIG_BEGIN_PHASE);
  1441. //
  1442. // Run all the registered SAMs
  1443. //
  1444. if (b && EnumFirstHashTableString (&e, g_SamTable)) {
  1445. do {
  1446. samData = *((PSAMDATA *) e.ExtraData);
  1447. if (samData->ShouldBeCalled) {
  1448. MYASSERT (!g_CurrentGroup);
  1449. g_CurrentGroup = samData->Group;
  1450. b = samData->SamExecute();
  1451. g_CurrentGroup = NULL;
  1452. if (!samData->SamEstimateProgressBar) {
  1453. if (!IsmTickProgressBar (sliceId, 1)) {
  1454. b = FALSE;
  1455. }
  1456. }
  1457. }
  1458. } while (b && EnumNextHashTableString (&e));
  1459. }
  1460. pCallProgressBar (MIG_END_PHASE);
  1461. g_CurrentPhase = 0;
  1462. g_SliceBuffer.End = 0;
  1463. return b;
  1464. }
  1465. BOOL
  1466. pDestinationGather (
  1467. IN PVOID Reserved
  1468. )
  1469. {
  1470. HASHTABLE_ENUM e;
  1471. BOOL b = TRUE;
  1472. BOOL cancelled = FALSE;
  1473. PDGMDATA dgmData;
  1474. UINT containers;
  1475. MIG_PROGRESSSLICEID sliceId;
  1476. PrepareEnumerationEnvironment (FALSE);
  1477. //
  1478. // Estimate the queue high priority enumerations
  1479. //
  1480. containers = 0;
  1481. if (b && EnumFirstHashTableString (&e, g_DgmTable)) {
  1482. do {
  1483. dgmData = *((PDGMDATA *) e.ExtraData);
  1484. if (dgmData->ShouldBeCalled && dgmData->DgmQueueHighPriorityEnumeration) {
  1485. containers ++;
  1486. }
  1487. } while (b && EnumNextHashTableString (&e));
  1488. }
  1489. //
  1490. // Queue high priority enumerations
  1491. //
  1492. g_CurrentPhase = MIG_HIGHPRIORITYQUEUE_PHASE;
  1493. g_SliceBuffer.End = 0;
  1494. if (containers) {
  1495. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1496. } else {
  1497. sliceId = 0;
  1498. }
  1499. pCallProgressBar (MIG_BEGIN_PHASE);
  1500. if (b && EnumFirstHashTableString (&e, g_DgmTable)) {
  1501. do {
  1502. dgmData = *((PDGMDATA *) e.ExtraData);
  1503. if (dgmData->ShouldBeCalled && dgmData->DgmQueueHighPriorityEnumeration) {
  1504. MYASSERT (!g_CurrentGroup);
  1505. g_CurrentGroup = dgmData->Group;
  1506. b = dgmData->DgmQueueHighPriorityEnumeration (Reserved);
  1507. g_CurrentGroup = NULL;
  1508. // Call progress bar
  1509. IsmTickProgressBar (sliceId, 1);
  1510. }
  1511. } while (b && EnumNextHashTableString (&e));
  1512. }
  1513. pCallProgressBar (MIG_END_PHASE);
  1514. //
  1515. // Estimate the high priority enumerations estimate
  1516. //
  1517. containers = EstimateAllObjectEnumerations (0, TRUE);
  1518. //
  1519. // Estimate the high priority enumerations
  1520. //
  1521. g_CurrentPhase = MIG_HIGHPRIORITYESTIMATE_PHASE;
  1522. g_SliceBuffer.End = 0;
  1523. if (containers) {
  1524. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1525. } else {
  1526. sliceId = 0;
  1527. }
  1528. pCallProgressBar (MIG_BEGIN_PHASE);
  1529. containers = EstimateAllObjectEnumerations (sliceId, FALSE);
  1530. pCallProgressBar (MIG_END_PHASE);
  1531. //
  1532. // Run high priority enumeration queue
  1533. //
  1534. g_CurrentPhase = MIG_HIGHPRIORITYGATHER_PHASE;
  1535. g_SliceBuffer.End = 0;
  1536. if (containers) {
  1537. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1538. } else {
  1539. sliceId = 0;
  1540. }
  1541. pCallProgressBar (MIG_BEGIN_PHASE);
  1542. if (b) {
  1543. if (!DoAllObjectEnumerations (sliceId)) {
  1544. DEBUGMSG ((DBG_ERROR, "Internal ISM Error during high priority object enumeration."));
  1545. b = FALSE;
  1546. }
  1547. }
  1548. pCallProgressBar (MIG_END_PHASE);
  1549. ClearEnumerationEnvironment (FALSE);
  1550. PrepareEnumerationEnvironment (FALSE);
  1551. //
  1552. // Estimate the queue normal priority enumerations
  1553. //
  1554. containers = 0;
  1555. if (b && EnumFirstHashTableString (&e, g_DgmTable)) {
  1556. do {
  1557. dgmData = *((PDGMDATA *) e.ExtraData);
  1558. if (dgmData->ShouldBeCalled) {
  1559. containers ++;
  1560. }
  1561. } while (b && EnumNextHashTableString (&e));
  1562. }
  1563. //
  1564. // Queue normal priority enumerations
  1565. //
  1566. g_CurrentPhase = MIG_GATHERQUEUE_PHASE;
  1567. g_SliceBuffer.End = 0;
  1568. if (containers) {
  1569. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1570. } else {
  1571. sliceId = 0;
  1572. }
  1573. pCallProgressBar (MIG_BEGIN_PHASE);
  1574. if (b && EnumFirstHashTableString (&e, g_DgmTable)) {
  1575. do {
  1576. dgmData = *((PDGMDATA *) e.ExtraData);
  1577. if (dgmData->ShouldBeCalled) {
  1578. MYASSERT (!g_CurrentGroup);
  1579. g_CurrentGroup = dgmData->Group;
  1580. b = dgmData->DgmQueueEnumeration (Reserved);
  1581. g_CurrentGroup = NULL;
  1582. // Call progress bar
  1583. IsmTickProgressBar (sliceId, 1);
  1584. }
  1585. } while (b && EnumNextHashTableString (&e));
  1586. }
  1587. pCallProgressBar (MIG_END_PHASE);
  1588. //
  1589. // Estimate the normal priority enumerations estimate
  1590. //
  1591. containers = EstimateAllObjectEnumerations (0, TRUE);
  1592. //
  1593. // Estimate the normal priority enumerations
  1594. //
  1595. g_CurrentPhase = MIG_GATHERESTIMATE_PHASE;
  1596. g_SliceBuffer.End = 0;
  1597. if (containers) {
  1598. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1599. } else {
  1600. sliceId = 0;
  1601. }
  1602. pCallProgressBar (MIG_BEGIN_PHASE);
  1603. containers = EstimateAllObjectEnumerations (sliceId, FALSE);
  1604. pCallProgressBar (MIG_END_PHASE);
  1605. //
  1606. // Run normal priority enumeration queue
  1607. //
  1608. g_CurrentPhase = MIG_GATHER_PHASE;
  1609. g_SliceBuffer.End = 0;
  1610. if (containers) {
  1611. sliceId = IsmRegisterProgressSlice (containers, containers * 5);
  1612. } else {
  1613. sliceId = 0;
  1614. }
  1615. pCallProgressBar (MIG_BEGIN_PHASE);
  1616. if (b) {
  1617. if (!DoAllObjectEnumerations (sliceId)) {
  1618. DEBUGMSG ((DBG_ERROR, "Internal ISM Error during object enumeration."));
  1619. b = FALSE;
  1620. }
  1621. }
  1622. ClearEnumerationEnvironment (FALSE);
  1623. pCallProgressBar (MIG_END_PHASE);
  1624. g_CurrentPhase = 0;
  1625. g_SliceBuffer.End = 0;
  1626. return b;
  1627. }
  1628. BOOL
  1629. ShouldObjectBeRestored (
  1630. IN MIG_OBJECTTYPEID ObjectTypeId,
  1631. IN MIG_OBJECTID ObjectId,
  1632. IN MIG_OBJECTSTRINGHANDLE ObjectName
  1633. )
  1634. /*++
  1635. Routine Description:
  1636. ShouldObjectBeRestored determines if a specific object should be restored
  1637. at all. It first checks if the object is marked for apply, and then checks
  1638. all restore callbacks to allow them to deny the restore.
  1639. Arguments:
  1640. ObjectTypeId - Specifies the object type
  1641. ObjectId - Specifies the numeric ID of the object
  1642. ObjectName - Specifies the encoded node and leaf of the object
  1643. Return Value:
  1644. TRUE if the object should be restored, FALSE otherwise
  1645. --*/
  1646. {
  1647. BOOL result = TRUE;
  1648. MIG_RESTORECALLBACK_ENUM restoreEnum;
  1649. //
  1650. // Is object marked for apply?
  1651. //
  1652. if (!IsmIsApplyObjectId (ObjectId)) {
  1653. return FALSE;
  1654. }
  1655. //
  1656. // Call callbacks to allow them to deny restore
  1657. //
  1658. if (EnumFirstRestoreCallback (&restoreEnum)) {
  1659. do {
  1660. if (!restoreEnum.RestoreCallback (ObjectTypeId, ObjectId, ObjectName)) {
  1661. result = FALSE;
  1662. break;
  1663. }
  1664. } while (EnumNextRestoreCallback (&restoreEnum));
  1665. }
  1666. return result;
  1667. }
  1668. BOOL
  1669. pDestinationAnalyze (
  1670. IN PVOID Reserved
  1671. )
  1672. {
  1673. HASHTABLE_ENUM e;
  1674. BOOL b = TRUE;
  1675. BOOL cancelled = FALSE;
  1676. PDAMDATA damData;
  1677. PCSMDATA csmData;
  1678. UINT modulesNeedingProgress = 0;
  1679. MIG_PROGRESSSLICEID sliceId = 0;
  1680. //
  1681. // Prepare a progress bar
  1682. //
  1683. g_CurrentPhase = MIG_ANALYSIS_PHASE;
  1684. g_SliceBuffer.End = 0;
  1685. if (EnumFirstHashTableString (&e, g_DamTable)) {
  1686. do {
  1687. damData = *((PDAMDATA *) e.ExtraData);
  1688. if (damData->ShouldBeCalled) {
  1689. if (damData->DamEstimateProgressBar) {
  1690. damData->DamEstimateProgressBar();
  1691. } else {
  1692. modulesNeedingProgress++;
  1693. }
  1694. }
  1695. } while (EnumNextHashTableString (&e));
  1696. }
  1697. if (EnumFirstHashTableString (&e, g_CsmTable)) {
  1698. do {
  1699. csmData = *((PCSMDATA *) e.ExtraData);
  1700. if (csmData->ShouldBeCalled) {
  1701. if (csmData->CsmEstimateProgressBar) {
  1702. csmData->CsmEstimateProgressBar();
  1703. } else {
  1704. modulesNeedingProgress++;
  1705. }
  1706. }
  1707. } while (EnumNextHashTableString (&e));
  1708. }
  1709. if (modulesNeedingProgress) {
  1710. sliceId = IsmRegisterProgressSlice (
  1711. modulesNeedingProgress,
  1712. modulesNeedingProgress * 10
  1713. );
  1714. }
  1715. pCallProgressBar (MIG_BEGIN_PHASE);
  1716. //
  1717. // Run all the registered DAMs
  1718. //
  1719. if (EnumFirstHashTableString (&e, g_DamTable)) {
  1720. do {
  1721. damData = *((PDAMDATA *) e.ExtraData);
  1722. if (damData->ShouldBeCalled) {
  1723. MYASSERT (!g_CurrentGroup);
  1724. g_CurrentGroup = damData->Group;
  1725. b = damData->DamExecute();
  1726. g_CurrentGroup = NULL;
  1727. if (!damData->DamEstimateProgressBar) {
  1728. if (!IsmTickProgressBar (sliceId, 1)) {
  1729. b = FALSE;
  1730. }
  1731. }
  1732. }
  1733. } while (b && EnumNextHashTableString (&e));
  1734. }
  1735. //
  1736. // Run all the registered CSMs
  1737. //
  1738. if (EnumFirstHashTableString (&e, g_CsmTable)) {
  1739. do {
  1740. csmData = *((PCSMDATA *) e.ExtraData);
  1741. if (csmData->ShouldBeCalled) {
  1742. MYASSERT (!g_CurrentGroup);
  1743. g_CurrentGroup = csmData->Group;
  1744. b = csmData->CsmExecute();
  1745. g_CurrentGroup = NULL;
  1746. if (!csmData->CsmEstimateProgressBar) {
  1747. if (!IsmTickProgressBar (sliceId, 1)) {
  1748. b = FALSE;
  1749. }
  1750. }
  1751. }
  1752. } while (b && EnumNextHashTableString (&e));
  1753. }
  1754. pCallProgressBar (MIG_END_PHASE);
  1755. g_CurrentPhase = 0;
  1756. g_SliceBuffer.End = 0;
  1757. return b;
  1758. }
  1759. BOOL
  1760. pTestShortFileName (
  1761. IN PCTSTR FileName,
  1762. IN PCTSTR TempDir
  1763. )
  1764. {
  1765. PCTSTR testFileName;
  1766. HANDLE fileHandle;
  1767. WIN32_FIND_DATA fileInfo;
  1768. BOOL result = FALSE;
  1769. testFileName = JoinPaths (TempDir, FileName);
  1770. fileHandle = BfCreateFile (testFileName);
  1771. if (fileHandle) {
  1772. CloseHandle (fileHandle);
  1773. if (DoesFileExistEx (testFileName, &fileInfo)) {
  1774. result = (fileInfo.cAlternateFileName [0] == 0) ||
  1775. StringIMatch (fileInfo.cFileName, fileInfo.cAlternateFileName);
  1776. }
  1777. DeleteFile (testFileName);
  1778. }
  1779. FreePathString (testFileName);
  1780. return result;
  1781. }
  1782. BOOL
  1783. pIsShortFileName (
  1784. IN MIG_OBJECTTYPEID ObjectTypeId,
  1785. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  1786. IN PCTSTR TempDir,
  1787. IN PCTSTR FullKeyName,
  1788. IN OUT KEYHANDLE *KeyHandle
  1789. )
  1790. {
  1791. PCTSTR node, leaf;
  1792. PTSTR nodePtr;
  1793. PTSTR fullKeyName;
  1794. MEMDB_ENUM memDbEnum;
  1795. BOOL result = FALSE;
  1796. if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
  1797. if (leaf) {
  1798. result = pTestShortFileName (leaf, TempDir);
  1799. } else {
  1800. fullKeyName = DuplicatePathString (FullKeyName, 0);
  1801. nodePtr = _tcsrchr (fullKeyName, TEXT('\\'));
  1802. if (nodePtr) {
  1803. *nodePtr = 0;
  1804. nodePtr = _tcsrchr (fullKeyName, TEXT('\\'));
  1805. if (nodePtr) {
  1806. result = pTestShortFileName (nodePtr, TempDir);
  1807. if (!result && MemDbEnumFirst (&memDbEnum, fullKeyName, ENUMFLAG_ALL, ENUMLEVEL_LASTLEVEL, ENUMLEVEL_ALLLEVELS)) {
  1808. *KeyHandle = memDbEnum.KeyHandle;
  1809. MemDbAbortEnum (&memDbEnum);
  1810. } else {
  1811. result = TRUE;
  1812. }
  1813. }
  1814. }
  1815. FreePathString (fullKeyName);
  1816. }
  1817. IsmDestroyObjectString (node);
  1818. IsmDestroyObjectString (leaf);
  1819. }
  1820. return result;
  1821. }
  1822. BOOL
  1823. pFixFileEnumerationOrder (
  1824. IN MIG_PLATFORMTYPEID Platform,
  1825. IN PCTSTR TempDir
  1826. )
  1827. {
  1828. MIG_OBJECTTYPEID objectTypeId;
  1829. PCTSTR decoratedPath;
  1830. MEMDB_ENUM memDbEnum;
  1831. GROWBUFFER moveHandles = INIT_GROWBUFFER;
  1832. KEYHANDLE keyHandle;
  1833. PDWORD moveHandle = NULL;
  1834. BOOL result = FALSE;
  1835. objectTypeId = MIG_FILE_TYPE | Platform;
  1836. decoratedPath = GetDecoratedObjectPathFromName (objectTypeId, TEXT("*"), TRUE);
  1837. if (decoratedPath) {
  1838. if (MemDbEnumFirst (&memDbEnum, decoratedPath, ENUMFLAG_NORMAL, 1, ENUMLEVEL_ALLLEVELS)) {
  1839. do {
  1840. if (IsmCheckCancel()) {
  1841. return FALSE;
  1842. }
  1843. keyHandle = memDbEnum.KeyHandle;
  1844. if (!pIsShortFileName (objectTypeId, memDbEnum.KeyName, TempDir, memDbEnum.FullKeyName, &keyHandle)) {
  1845. GbAppendDword (&moveHandles, keyHandle);
  1846. }
  1847. } while (MemDbEnumNext (&memDbEnum));
  1848. }
  1849. GbAppendDword (&moveHandles, 0);
  1850. moveHandle = (PDWORD)moveHandles.Buf;
  1851. while (*moveHandle) {
  1852. if (IsmCheckCancel()) {
  1853. return FALSE;
  1854. }
  1855. MemDbMoveKeyHandleToEnd (*moveHandle);
  1856. moveHandle ++;
  1857. }
  1858. FreePathString (decoratedPath);
  1859. }
  1860. GbFree (&moveHandles);
  1861. return result;
  1862. }
  1863. BOOL
  1864. pDestinationApply (
  1865. IN PVOID Reserved
  1866. )
  1867. {
  1868. BOOL b = TRUE;
  1869. BOOL cancelled = FALSE;
  1870. MIG_OBJECTTYPEID objTypeId;
  1871. MIG_OBJECT_ENUM objectEnum;
  1872. MIG_OBJECTSTRINGHANDLE objPattern = NULL;
  1873. BOOL toProcess = FALSE;
  1874. MIG_PROGRESSSLICEID sliceId = 0;
  1875. UINT ticks;
  1876. LONG failCode;
  1877. BOOL runKeyAdded = FALSE;
  1878. MIG_OBJECTTYPEID fileTypeId;
  1879. TCHAR tempDir [MAX_PATH] = TEXT("");
  1880. BOOL deleteFailed = FALSE;
  1881. TCHAR delayedDeleteKey [] = TEXT("DelayedDelete");
  1882. KEYHANDLE delayedDeleteHandle;
  1883. MIG_OBJECTID delayedDeleteId;
  1884. PUINT delayedDeleteList;
  1885. UINT delayedDeleteListNo;
  1886. UINT delayedDeleteIndex;
  1887. MIG_OBJECTSTRINGHANDLE delayedObjectName = NULL;
  1888. MIG_OBJECTTYPEID delayedObjectTypeId;
  1889. HASHTABLE_ENUM e;
  1890. ERRUSER_EXTRADATA extraData;
  1891. MIG_OBJECTTYPEIDENUM objTypeIdEnum;
  1892. g_CurrentPhase = MIG_APPLY_PHASE;
  1893. g_SliceBuffer.End = 0;
  1894. ticks = g_DestinationObjects.TotalObjects +
  1895. g_SourceObjects.TotalObjects +
  1896. g_DestinationObjects.TotalObjects;
  1897. if (ticks) {
  1898. sliceId = IsmRegisterProgressSlice (ticks, max (1, ticks / 10));
  1899. } else {
  1900. sliceId = IsmRegisterProgressSlice (1, 30);
  1901. }
  1902. pCallProgressBar (MIG_BEGIN_PHASE);
  1903. // let's execute PreProcess functions
  1904. if (g_PreProcessTable) {
  1905. if (EnumFirstHashTableString (&e, g_PreProcessTable)) {
  1906. do {
  1907. IsmSendMessageToApp (ISMMESSAGE_EXECUTE_PREPROCESS, (ULONG_PTR) *((PCTSTR *)e.ExtraData));
  1908. } while (EnumNextHashTableString (&e));
  1909. }
  1910. }
  1911. g_PreProcessDone = TRUE;
  1912. IsmGetTempDirectory (tempDir, ARRAYSIZE(tempDir));
  1913. fileTypeId = MIG_FILE_TYPE;
  1914. //
  1915. // Special code for file type (short/long issue)
  1916. //
  1917. pFixFileEnumerationOrder (PLATFORM_SOURCE, tempDir);
  1918. pFixFileEnumerationOrder (PLATFORM_DESTINATION, tempDir);
  1919. //
  1920. // Now we are going to execute an ISM driven restore
  1921. //
  1922. objPattern = IsmCreateSimpleObjectPattern (NULL, TRUE, NULL, TRUE);
  1923. //
  1924. // Enumerate and process high priority operations for all objects on the
  1925. // right side of the tree
  1926. //
  1927. failCode = ERROR_SUCCESS;
  1928. if (IsmEnumFirstObjectTypeId (&objTypeIdEnum)) {
  1929. do {
  1930. objTypeId = objTypeIdEnum.ObjectTypeId;
  1931. objTypeId |= PLATFORM_DESTINATION;
  1932. if (CanObjectTypeBeRestored (objTypeId)) {
  1933. delayedDeleteHandle = MemDbAddKey (delayedDeleteKey);
  1934. if (pEnumFirstVirtualObject (&objectEnum, objTypeId, objPattern)) {
  1935. do {
  1936. toProcess = ShouldObjectBeRestored (
  1937. objTypeId,
  1938. objectEnum.ObjectId,
  1939. objectEnum.ObjectName
  1940. );
  1941. if (toProcess) {
  1942. if (!RestoreObject (
  1943. objTypeId,
  1944. objectEnum.ObjectName,
  1945. NULL,
  1946. OP_HIGH_PRIORITY,
  1947. &deleteFailed
  1948. )) {
  1949. failCode = GetLastError();
  1950. if (failCode != ERROR_SUCCESS) {
  1951. LOG ((
  1952. IsmIsNonCriticalObjectId (objectEnum.ObjectId)?LOG_WARNING:LOG_ERROR,
  1953. (PCSTR) MSG_CANT_RESTORE_SOURCE_OBJECT,
  1954. IsmGetObjectTypeName (objTypeId),
  1955. IsmGetNativeObjectName (objTypeId, objectEnum.ObjectName)
  1956. ));
  1957. failCode = ERROR_SUCCESS;
  1958. }
  1959. }
  1960. if (deleteFailed && delayedDeleteHandle) {
  1961. delayedDeleteId = IsmGetObjectIdFromName (objTypeId, objectEnum.ObjectName, TRUE);
  1962. if (delayedDeleteId) {
  1963. MemDbAddSingleLinkageByKeyHandle (
  1964. delayedDeleteHandle,
  1965. delayedDeleteId,
  1966. 0
  1967. );
  1968. }
  1969. }
  1970. }
  1971. if (ticks) {
  1972. if (!IsmTickProgressBar (sliceId, 1)) {
  1973. failCode = ERROR_CANCELLED;
  1974. break;
  1975. }
  1976. ticks--;
  1977. } else if (CheckCancel()) {
  1978. failCode = ERROR_CANCELLED;
  1979. break;
  1980. }
  1981. } while (pEnumNextVirtualObject (&objectEnum));
  1982. }
  1983. if (delayedDeleteHandle) {
  1984. // OK, now let's see if we have some delayed delete here
  1985. delayedDeleteList = MemDbGetSingleLinkageArrayByKeyHandle (
  1986. delayedDeleteHandle,
  1987. 0,
  1988. &delayedDeleteListNo
  1989. );
  1990. delayedDeleteListNo /= SIZEOF(KEYHANDLE);
  1991. if ((delayedDeleteList) &&
  1992. (delayedDeleteListNo > 0)) {
  1993. delayedDeleteIndex = delayedDeleteListNo;
  1994. do {
  1995. delayedDeleteIndex --;
  1996. delayedDeleteId = *(delayedDeleteList + delayedDeleteIndex);
  1997. delayedObjectName = MemDbGetKeyFromHandle ((KEYHANDLE) delayedDeleteId, 1);
  1998. if (delayedObjectName) {
  1999. if (MemDbGetValueByHandle ((KEYHANDLE) delayedDeleteId, &delayedObjectTypeId)) {
  2000. // now we have everything to retry the delete
  2001. if (!RestoreObject (
  2002. delayedObjectTypeId,
  2003. delayedObjectName,
  2004. NULL,
  2005. OP_HIGH_PRIORITY,
  2006. NULL
  2007. )) {
  2008. failCode = GetLastError();
  2009. if (failCode != ERROR_SUCCESS) {
  2010. LOG ((
  2011. IsmIsNonCriticalObject (delayedObjectTypeId, delayedObjectName)?LOG_WARNING:LOG_ERROR,
  2012. (PCSTR) MSG_CANT_RESTORE_SOURCE_OBJECT,
  2013. IsmGetObjectTypeName (objTypeId),
  2014. IsmGetNativeObjectName (objTypeId, objectEnum.ObjectName)
  2015. ));
  2016. failCode = ERROR_SUCCESS;
  2017. }
  2018. }
  2019. }
  2020. MemDbReleaseMemory (delayedObjectName);
  2021. }
  2022. } while (delayedDeleteIndex > 0);
  2023. MemDbReleaseMemory (delayedDeleteList);
  2024. }
  2025. }
  2026. MemDbDeleteKey (delayedDeleteKey);
  2027. }
  2028. if (failCode != ERROR_SUCCESS) {
  2029. IsmAbortObjectEnum (&objectEnum);
  2030. SetLastError (failCode);
  2031. if (tempDir [0]) {
  2032. FiRemoveAllFilesInTree (tempDir);
  2033. }
  2034. IsmAbortObjectTypeIdEnum (&objTypeIdEnum);
  2035. return FALSE;
  2036. }
  2037. } while (IsmEnumNextObjectTypeId (&objTypeIdEnum));
  2038. }
  2039. //
  2040. // Enumerate and process high priority and low priority operations for all objects on the
  2041. // left side of the tree
  2042. //
  2043. failCode = ERROR_SUCCESS;
  2044. if (IsmEnumFirstObjectTypeId (&objTypeIdEnum)) {
  2045. do {
  2046. objTypeId = objTypeIdEnum.ObjectTypeId;
  2047. objTypeId |= PLATFORM_SOURCE;
  2048. if (CanObjectTypeBeRestored (objTypeId)) {
  2049. if (pEnumFirstVirtualObject (&objectEnum, objTypeId, objPattern)) {
  2050. do {
  2051. toProcess = ShouldObjectBeRestored (
  2052. objTypeId,
  2053. objectEnum.ObjectId,
  2054. objectEnum.ObjectName
  2055. );
  2056. if (toProcess) {
  2057. if (!RestoreObject (
  2058. objTypeId,
  2059. objectEnum.ObjectName,
  2060. NULL,
  2061. OP_ALL_PRIORITY,
  2062. NULL
  2063. )) {
  2064. failCode = GetLastError();
  2065. if (failCode != ERROR_SUCCESS) {
  2066. LOG ((
  2067. IsmIsNonCriticalObjectId (objectEnum.ObjectId)?LOG_WARNING:LOG_ERROR,
  2068. (PCSTR) MSG_CANT_RESTORE_SOURCE_OBJECT,
  2069. IsmGetObjectTypeName (objTypeId),
  2070. IsmGetNativeObjectName (objTypeId, objectEnum.ObjectName)
  2071. ));
  2072. failCode = ERROR_SUCCESS;
  2073. extraData.Error = ERRUSER_ERROR_CANTRESTOREOBJECT;
  2074. extraData.ErrorArea = ERRUSER_AREA_RESTORE;
  2075. extraData.ObjectTypeId = objTypeId;
  2076. extraData.ObjectName = objectEnum.ObjectName;
  2077. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYWARNING, (ULONG_PTR)(&extraData));
  2078. }
  2079. }
  2080. }
  2081. if (ticks) {
  2082. if (!IsmTickProgressBar (sliceId, 1)) {
  2083. failCode = ERROR_CANCELLED;
  2084. break;
  2085. }
  2086. ticks--;
  2087. } else if (CheckCancel()) {
  2088. failCode = ERROR_CANCELLED;
  2089. break;
  2090. }
  2091. } while (pEnumNextVirtualObject (&objectEnum));
  2092. }
  2093. }
  2094. if (failCode != ERROR_SUCCESS) {
  2095. IsmAbortObjectEnum (&objectEnum);
  2096. SetLastError (failCode);
  2097. if (tempDir [0]) {
  2098. FiRemoveAllFilesInTree (tempDir);
  2099. }
  2100. IsmAbortObjectTypeIdEnum (&objTypeIdEnum);
  2101. return FALSE;
  2102. }
  2103. } while (IsmEnumNextObjectTypeId (&objTypeIdEnum));
  2104. }
  2105. //
  2106. // Enumerate and process low priority operation for all objects on the
  2107. // right side of the tree
  2108. //
  2109. failCode = ERROR_SUCCESS;
  2110. if (IsmEnumFirstObjectTypeId (&objTypeIdEnum)) {
  2111. do {
  2112. objTypeId = objTypeIdEnum.ObjectTypeId;
  2113. objTypeId |= PLATFORM_DESTINATION;
  2114. if (CanObjectTypeBeRestored (objTypeId)) {
  2115. delayedDeleteHandle = MemDbAddKey (delayedDeleteKey);
  2116. if (pEnumFirstVirtualObject (&objectEnum, objTypeId, objPattern)) {
  2117. do {
  2118. toProcess = ShouldObjectBeRestored (
  2119. objTypeId,
  2120. objectEnum.ObjectId,
  2121. objectEnum.ObjectName
  2122. );
  2123. if (toProcess) {
  2124. if (!RestoreObject (
  2125. objTypeId,
  2126. objectEnum.ObjectName,
  2127. NULL,
  2128. OP_LOW_PRIORITY,
  2129. &deleteFailed
  2130. )) {
  2131. failCode = GetLastError();
  2132. if (failCode != ERROR_SUCCESS) {
  2133. LOG ((
  2134. IsmIsNonCriticalObjectId (objectEnum.ObjectId)?LOG_WARNING:LOG_ERROR,
  2135. (PCSTR) MSG_CANT_RESTORE_SOURCE_OBJECT,
  2136. IsmGetObjectTypeName (objTypeId),
  2137. IsmGetNativeObjectName (objTypeId, objectEnum.ObjectName)
  2138. ));
  2139. failCode = ERROR_SUCCESS;
  2140. }
  2141. }
  2142. if (deleteFailed && delayedDeleteHandle) {
  2143. delayedDeleteId = IsmGetObjectIdFromName (objTypeId, objectEnum.ObjectName, TRUE);
  2144. if (delayedDeleteId) {
  2145. MemDbAddSingleLinkageByKeyHandle (
  2146. delayedDeleteHandle,
  2147. delayedDeleteId,
  2148. 0
  2149. );
  2150. }
  2151. }
  2152. }
  2153. if (ticks) {
  2154. if (!IsmTickProgressBar (sliceId, 1)) {
  2155. failCode = ERROR_CANCELLED;
  2156. break;
  2157. }
  2158. ticks--;
  2159. } else if (CheckCancel()) {
  2160. failCode = ERROR_CANCELLED;
  2161. break;
  2162. }
  2163. } while (pEnumNextVirtualObject (&objectEnum));
  2164. }
  2165. if (delayedDeleteHandle) {
  2166. // OK, now let's see if we have some delayed delete here
  2167. delayedDeleteList = MemDbGetSingleLinkageArrayByKeyHandle (
  2168. delayedDeleteHandle,
  2169. 0,
  2170. &delayedDeleteListNo
  2171. );
  2172. delayedDeleteListNo /= SIZEOF(KEYHANDLE);
  2173. if ((delayedDeleteList) &&
  2174. (delayedDeleteListNo > 0)) {
  2175. delayedDeleteIndex = delayedDeleteListNo;
  2176. do {
  2177. delayedDeleteIndex --;
  2178. delayedDeleteId = *(delayedDeleteList + delayedDeleteIndex);
  2179. delayedObjectName = MemDbGetKeyFromHandle ((KEYHANDLE) delayedDeleteId, 1);
  2180. if (delayedObjectName) {
  2181. if (MemDbGetValueByHandle ((KEYHANDLE) delayedDeleteId, &delayedObjectTypeId)) {
  2182. // now we have everything to retry the delete
  2183. if (!RestoreObject (
  2184. delayedObjectTypeId,
  2185. delayedObjectName,
  2186. NULL,
  2187. OP_LOW_PRIORITY,
  2188. NULL
  2189. )) {
  2190. failCode = GetLastError();
  2191. if (failCode != ERROR_SUCCESS) {
  2192. LOG ((
  2193. IsmIsNonCriticalObject (delayedObjectTypeId, delayedObjectName)?LOG_WARNING:LOG_ERROR,
  2194. (PCSTR) MSG_CANT_RESTORE_SOURCE_OBJECT,
  2195. IsmGetObjectTypeName (objTypeId),
  2196. IsmGetNativeObjectName (objTypeId, objectEnum.ObjectName)
  2197. ));
  2198. failCode = ERROR_SUCCESS;
  2199. }
  2200. }
  2201. }
  2202. MemDbReleaseMemory (delayedObjectName);
  2203. }
  2204. } while (delayedDeleteIndex > 0);
  2205. MemDbReleaseMemory (delayedDeleteList);
  2206. }
  2207. }
  2208. MemDbDeleteKey (delayedDeleteKey);
  2209. }
  2210. if (failCode != ERROR_SUCCESS) {
  2211. IsmAbortObjectEnum (&objectEnum);
  2212. SetLastError (failCode);
  2213. if (tempDir [0]) {
  2214. FiRemoveAllFilesInTree (tempDir);
  2215. }
  2216. return FALSE;
  2217. }
  2218. } while (IsmEnumNextObjectTypeId (&objTypeIdEnum));
  2219. }
  2220. g_MakeProfilePermanent = TRUE;
  2221. IsmDestroyObjectHandle (objPattern);
  2222. pCallProgressBar (MIG_END_PHASE);
  2223. g_CurrentPhase = 0;
  2224. g_SliceBuffer.End = 0;
  2225. if (tempDir [0]) {
  2226. FiRemoveAllFilesInTree (tempDir);
  2227. }
  2228. return b;
  2229. }
  2230. MIG_TRANSPORTSTORAGEID
  2231. IsmRegisterTransport (
  2232. IN PCTSTR TypeString
  2233. )
  2234. {
  2235. MIG_TRANSPORTSTORAGEID transportStorageId;
  2236. PCTSTR memdbKey;
  2237. memdbKey = JoinPaths (S_TRANSPORT_TYPES, TypeString);
  2238. transportStorageId = (MIG_TRANSPORTSTORAGEID) MemDbSetKey (memdbKey);
  2239. FreePathString (memdbKey);
  2240. if (!transportStorageId) {
  2241. DEBUGMSG ((DBG_ISM, "Unable to set memdb key in IsmRegisterTransport"));
  2242. EngineError ();
  2243. }
  2244. return transportStorageId;
  2245. }
  2246. BOOL
  2247. pEnumFirstTransportType (
  2248. OUT PMEMDB_ENUM EnumPtr
  2249. )
  2250. {
  2251. PCTSTR memdbPattern;
  2252. BOOL b;
  2253. memdbPattern = JoinPaths (S_TRANSPORT_TYPES, TEXT("*"));
  2254. b = MemDbEnumFirst (
  2255. EnumPtr,
  2256. memdbPattern,
  2257. ENUMFLAG_NORMAL,
  2258. ENUMLEVEL_ALLLEVELS,
  2259. ENUMLEVEL_ALLLEVELS
  2260. );
  2261. FreePathString (memdbPattern);
  2262. return b;
  2263. }
  2264. BOOL
  2265. pEnumNextTransportType (
  2266. IN OUT PMEMDB_ENUM EnumPtr
  2267. )
  2268. {
  2269. return MemDbEnumNext (EnumPtr);
  2270. }
  2271. VOID
  2272. pAbortTransportTypeEnum (
  2273. IN PMEMDB_ENUM EnumPtr
  2274. )
  2275. {
  2276. MemDbAbortEnum (EnumPtr);
  2277. }
  2278. BOOL
  2279. IsmEnumFirstTransport (
  2280. OUT PMIG_TRANSPORTENUM Enum,
  2281. IN MIG_TRANSPORTSTORAGEID DesiredStorageId OPTIONAL
  2282. )
  2283. {
  2284. PTRANSPORTENUMHANDLE handle;
  2285. BOOL b;
  2286. ZeroMemory (Enum, sizeof (MIG_TRANSPORTENUM));
  2287. Enum->Handle = MemAllocZeroed (sizeof (TRANSPORTENUMHANDLE));
  2288. handle = (PTRANSPORTENUMHANDLE) Enum->Handle;
  2289. handle->DesiredStorageId = DesiredStorageId;
  2290. b = EnumFirstHashTableString (&handle->TableEnum, g_TransportTable);
  2291. if (!b) {
  2292. IsmAbortTransportEnum (Enum);
  2293. return FALSE;
  2294. }
  2295. handle->State = TESTATE_BEGINTRANSPORT;
  2296. return IsmEnumNextTransport (Enum);
  2297. }
  2298. BOOL
  2299. IsmEnumNextTransport (
  2300. IN OUT PMIG_TRANSPORTENUM Enum
  2301. )
  2302. {
  2303. PTRANSPORTENUMHANDLE handle;
  2304. PTRANSPORTDATA transportData;
  2305. handle = (PTRANSPORTENUMHANDLE) Enum->Handle;
  2306. if (!handle) {
  2307. return FALSE;
  2308. }
  2309. for (;;) {
  2310. switch (handle->State) {
  2311. case TESTATE_BEGINTRANSPORT:
  2312. //
  2313. // Begin enumeration of all registered types
  2314. //
  2315. if (!pEnumFirstTransportType (&handle->MemDbEnum)) {
  2316. handle->State = TESTATE_NEXTTRANSPORT;
  2317. } else {
  2318. handle->State = TESTATE_GETCAPS;
  2319. }
  2320. break;
  2321. case TESTATE_GETCAPS:
  2322. transportData = *((PTRANSPORTDATA *) handle->TableEnum.ExtraData);
  2323. if (!transportData) {
  2324. handle->State = TESTATE_NEXTTRANSPORT;
  2325. } else {
  2326. MYASSERT (transportData->TransportQueryCapabilities);
  2327. if (handle->DesiredStorageId &&
  2328. handle->DesiredStorageId != (MIG_TRANSPORTSTORAGEID) handle->MemDbEnum.KeyHandle
  2329. ) {
  2330. handle->State = TESTATE_NEXTTRANSPORTTYPE;
  2331. } else {
  2332. if (!transportData->TransportQueryCapabilities (
  2333. (MIG_TRANSPORTSTORAGEID) handle->MemDbEnum.KeyHandle,
  2334. &Enum->TransportType,
  2335. &Enum->Capabilities,
  2336. &Enum->FriendlyDescription
  2337. )) {
  2338. handle->State = TESTATE_NEXTTRANSPORTTYPE;
  2339. } else {
  2340. handle->State = TESTATE_RETURN;
  2341. }
  2342. }
  2343. }
  2344. break;
  2345. case TESTATE_RETURN:
  2346. Enum->TransportId = (MIG_TRANSPORTID) handle->TableEnum.Index;
  2347. Enum->SupportedStorageId = (MIG_TRANSPORTSTORAGEID) handle->MemDbEnum.KeyHandle;
  2348. handle->State = TESTATE_NEXTTRANSPORTTYPE;
  2349. return TRUE;
  2350. case TESTATE_NEXTTRANSPORTTYPE:
  2351. if (!pEnumNextTransportType (&handle->MemDbEnum)) {
  2352. pAbortTransportTypeEnum (&handle->MemDbEnum);
  2353. handle->State = TESTATE_NEXTTRANSPORT;
  2354. } else {
  2355. handle->State = TESTATE_GETCAPS;
  2356. }
  2357. break;
  2358. case TESTATE_NEXTTRANSPORT:
  2359. if (!EnumNextHashTableString (&handle->TableEnum)) {
  2360. handle->State = TESTATE_DONE;
  2361. } else {
  2362. handle->State = TESTATE_BEGINTRANSPORT;
  2363. }
  2364. break;
  2365. case TESTATE_DONE:
  2366. IsmAbortTransportEnum (Enum);
  2367. return FALSE;
  2368. }
  2369. }
  2370. }
  2371. VOID
  2372. IsmAbortTransportEnum (
  2373. IN PMIG_TRANSPORTENUM Enum
  2374. )
  2375. {
  2376. PTRANSPORTENUMHANDLE handle = (PTRANSPORTENUMHANDLE) Enum->Handle;
  2377. if (handle) {
  2378. pAbortTransportTypeEnum (&handle->MemDbEnum);
  2379. FreeAlloc (handle);
  2380. INVALID_POINTER (handle);
  2381. }
  2382. ZeroMemory (Enum, sizeof (MIG_TRANSPORTENUM));
  2383. }
  2384. MIG_TRANSPORTID
  2385. IsmSelectTransport (
  2386. IN MIG_TRANSPORTSTORAGEID DesiredStorageId,
  2387. IN MIG_TRANSPORTTYPE TransportType,
  2388. IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities
  2389. )
  2390. {
  2391. MIG_TRANSPORTENUM e;
  2392. MIG_TRANSPORTID result = 0;
  2393. if (!DesiredStorageId) {
  2394. return 0;
  2395. }
  2396. if (IsmEnumFirstTransport (&e, DesiredStorageId)) {
  2397. do {
  2398. if (e.TransportType != TransportType) {
  2399. continue;
  2400. }
  2401. if ((e.Capabilities & RequiredCapabilities) == RequiredCapabilities) {
  2402. result = e.TransportId;
  2403. IsmAbortTransportEnum (&e);
  2404. g_TransportType = TransportType;
  2405. return result;
  2406. }
  2407. } while (IsmEnumNextTransport (&e));
  2408. }
  2409. DEBUGMSG ((DBG_ISM, "IsmSelectTransport: Requested transport type does not exist"));
  2410. return result;
  2411. }
  2412. BOOL
  2413. IsmSetTransportStorage (
  2414. IN MIG_PLATFORMTYPEID Platform,
  2415. IN MIG_TRANSPORTID TransportId,
  2416. IN MIG_TRANSPORTSTORAGEID DesiredStorageId,
  2417. IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities,
  2418. IN PCTSTR StoragePath,
  2419. OUT PBOOL StoragePathIsValid, OPTIONAL
  2420. OUT PBOOL ImageExistsInStorage OPTIONAL
  2421. )
  2422. {
  2423. PTRANSPORTDATA *ptrToTransportData;
  2424. PTRANSPORTDATA transportData;
  2425. BOOL b;
  2426. BOOL valid;
  2427. BOOL exists;
  2428. PCTSTR sanitizedPath = NULL;
  2429. if (!TransportId) {
  2430. return FALSE;
  2431. }
  2432. if (!HtGetExtraData (g_TransportTable, (HASHITEM) TransportId, (PVOID *) &ptrToTransportData)) {
  2433. return FALSE;
  2434. }
  2435. transportData = *ptrToTransportData;
  2436. if (!transportData || !transportData->ShouldBeCalled) {
  2437. return FALSE;
  2438. }
  2439. MYASSERT (transportData->TransportSetStorage);
  2440. if (Platform == PLATFORM_CURRENT) {
  2441. Platform = g_IsmCurrentPlatform;
  2442. }
  2443. if (g_SelectedTransport) {
  2444. if (g_SelectedTransport->TransportResetStorage) {
  2445. g_SelectedTransport->TransportResetStorage (g_SelectedTransportId);
  2446. }
  2447. g_SelectedTransport = NULL;
  2448. g_SelectedTransportId = 0;
  2449. }
  2450. if (StoragePath) {
  2451. sanitizedPath = SanitizePath (StoragePath);
  2452. }
  2453. b = transportData->TransportSetStorage (
  2454. Platform,
  2455. DesiredStorageId,
  2456. RequiredCapabilities,
  2457. sanitizedPath,
  2458. &valid,
  2459. &exists
  2460. );
  2461. if (sanitizedPath) {
  2462. FreePathString (sanitizedPath);
  2463. }
  2464. if (b) {
  2465. if (StoragePathIsValid) {
  2466. *StoragePathIsValid = valid;
  2467. }
  2468. if (ImageExistsInStorage) {
  2469. *ImageExistsInStorage = exists;
  2470. }
  2471. g_SelectedTransport = transportData;
  2472. g_SelectedTransportId = DesiredStorageId;
  2473. }
  2474. return b;
  2475. }
  2476. BOOL
  2477. IsmExecute (
  2478. MIG_EXECUTETYPEID ExecuteType
  2479. )
  2480. {
  2481. static BOOL srcInitCompleted = FALSE;
  2482. static BOOL destInitCompleted = FALSE;
  2483. static BOOL vcmInitCompleted = FALSE;
  2484. static BOOL srcModuleInitCompleted = FALSE;
  2485. static BOOL destModuleInitCompleted = FALSE;
  2486. static BOOL rollbackInitCompleted = FALSE;
  2487. static BOOL vcmMode = FALSE;
  2488. static BOOL normalMode = FALSE;
  2489. static BOOL parsingDone = FALSE;
  2490. static BOOL srcExecuteDone = FALSE;
  2491. static BOOL destExecuteDone = FALSE;
  2492. static BOOL delayedOperationsDone = FALSE;
  2493. BOOL needVcmInit = FALSE;
  2494. BOOL needSrcModuleInit = FALSE;
  2495. BOOL needDestModuleInit = FALSE;
  2496. BOOL needRollbackInit = FALSE;
  2497. BOOL needTerminate = FALSE;
  2498. BOOL needTransportTermination = FALSE;
  2499. BOOL needDelayedOperationsTerminate = FALSE;
  2500. BOOL parseEtm = FALSE;
  2501. BOOL parseVcm = FALSE;
  2502. BOOL processVcm = FALSE;
  2503. BOOL parseSource = FALSE;
  2504. BOOL processSource = FALSE;
  2505. BOOL processDestination = FALSE;
  2506. BOOL processDelayedOperations = FALSE;
  2507. MIG_PLATFORMTYPEID platform = PLATFORM_SOURCE;
  2508. PCTSTR journalFile;
  2509. DWORD tempField;
  2510. PCURRENT_USER_DATA currentUserData;
  2511. BOOL cleanupOnly = FALSE;
  2512. BOOL b = TRUE;
  2513. if (CheckCancel ()) {
  2514. return FALSE;
  2515. }
  2516. g_ExecutionInProgress = TRUE;
  2517. switch (ExecuteType) {
  2518. case EXECUTETYPE_VIRTUALCOMPUTER_PARSING:
  2519. if (parsingDone) {
  2520. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_VIRTUALCOMPUTER_PARSING denied, parsing already executed"));
  2521. b = FALSE;
  2522. break;
  2523. }
  2524. if (normalMode) {
  2525. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_VIRTUALCOMPUTER_PARSING denied, not in virtual computer mode"));
  2526. b = FALSE;
  2527. break;
  2528. }
  2529. needVcmInit = TRUE;
  2530. parseEtm = TRUE;
  2531. parseVcm = TRUE;
  2532. parsingDone = TRUE;
  2533. vcmMode = TRUE;
  2534. break;
  2535. case EXECUTETYPE_VIRTUALCOMPUTER:
  2536. if (srcExecuteDone) {
  2537. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_VIRTUALCOMPUTER denied, virtual computer already built"));
  2538. b = FALSE;
  2539. break;
  2540. }
  2541. if (normalMode) {
  2542. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_VIRTUALCOMPUTER denied, not in virtual computer mode"));
  2543. b = FALSE;
  2544. break;
  2545. }
  2546. needVcmInit = TRUE;
  2547. processVcm = TRUE;
  2548. needTerminate = TRUE;
  2549. parsingDone = TRUE;
  2550. vcmMode = TRUE;
  2551. srcExecuteDone = TRUE;
  2552. break;
  2553. case EXECUTETYPE_EXECUTESOURCE_PARSING:
  2554. if (vcmMode) {
  2555. DEBUGMSG ((DBG_ERROR, "PARSING denied, in virtual computer mode"));
  2556. b = FALSE;
  2557. break;
  2558. }
  2559. if (parsingDone) {
  2560. DEBUGMSG ((DBG_ERROR, "PARSING denied, it was already done"));
  2561. b = FALSE;
  2562. break;
  2563. }
  2564. needSrcModuleInit = TRUE;
  2565. parseEtm = TRUE;
  2566. parseSource = TRUE;
  2567. parsingDone = TRUE;
  2568. normalMode = TRUE;
  2569. break;
  2570. case EXECUTETYPE_EXECUTESOURCE:
  2571. if (vcmMode) {
  2572. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_EXECUTESOURCE denied, in virtual computer mode"));
  2573. b = FALSE;
  2574. break;
  2575. }
  2576. if (srcExecuteDone) {
  2577. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_EXECUTESOURCE denied, source computer already processed"));
  2578. b = FALSE;
  2579. break;
  2580. }
  2581. if (destExecuteDone) {
  2582. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_EXECUTESOURCE denied, destination computer already processed"));
  2583. b = FALSE;
  2584. break;
  2585. }
  2586. needSrcModuleInit = TRUE;
  2587. processSource = TRUE;
  2588. needTerminate = TRUE;
  2589. parsingDone = TRUE;
  2590. normalMode = TRUE;
  2591. srcExecuteDone = TRUE;
  2592. break;
  2593. case EXECUTETYPE_EXECUTEDESTINATION:
  2594. if (!g_SelectedTransport || !g_SelectedTransport->ShouldBeCalled) {
  2595. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_TRANSPORT_SELECTED));
  2596. b = FALSE;
  2597. break;
  2598. }
  2599. if (vcmMode) {
  2600. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_EXECUTEDESTINATION denied, in virtual computer mode"));
  2601. b = FALSE;
  2602. break;
  2603. }
  2604. if (destExecuteDone) {
  2605. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_EXECUTEDESTINATION denied, destination computer already processed"));
  2606. b = FALSE;
  2607. break;
  2608. }
  2609. platform = PLATFORM_DESTINATION;
  2610. needDestModuleInit = TRUE;
  2611. needRollbackInit = TRUE;
  2612. processDestination = TRUE;
  2613. needTransportTermination = TRUE;
  2614. needTerminate = TRUE;
  2615. parsingDone = TRUE;
  2616. normalMode = TRUE;
  2617. destExecuteDone = TRUE;
  2618. break;
  2619. case EXECUTETYPE_DELAYEDOPERATIONS:
  2620. case EXECUTETYPE_DELAYEDOPERATIONSCLEANUP:
  2621. if (vcmMode) {
  2622. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_DELAYEDOPERATIONS denied, in virtual computer mode"));
  2623. b = FALSE;
  2624. break;
  2625. }
  2626. if (delayedOperationsDone) {
  2627. DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_DELAYEDOPERATIONS denied, delayed operations already processed"));
  2628. b = FALSE;
  2629. break;
  2630. }
  2631. platform = PLATFORM_DESTINATION;
  2632. destInitCompleted = TRUE;
  2633. needRollbackInit = TRUE;
  2634. needDelayedOperationsTerminate = TRUE;
  2635. processDelayedOperations = TRUE;
  2636. delayedOperationsDone = TRUE;
  2637. cleanupOnly = (ExecuteType == EXECUTETYPE_DELAYEDOPERATIONSCLEANUP);
  2638. }
  2639. if (b) {
  2640. g_IsmModulePlatformContext = platform;
  2641. if (platform == PLATFORM_SOURCE) {
  2642. if (!srcInitCompleted) {
  2643. //
  2644. // Complete initialization of all ISM components
  2645. //
  2646. b = InitializeProperties (platform, vcmMode);
  2647. srcInitCompleted = TRUE;
  2648. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: src property init failed"));
  2649. }
  2650. } else {
  2651. if (!destInitCompleted) {
  2652. //
  2653. // Complete initialization of all ISM components
  2654. //
  2655. b = InitializeProperties (platform, vcmMode);
  2656. destInitCompleted = TRUE;
  2657. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: dest property init failed"));
  2658. }
  2659. }
  2660. if (needVcmInit && !vcmInitCompleted) {
  2661. //
  2662. // Initialize the modules
  2663. //
  2664. b = InitializeVcmModules (NULL);
  2665. vcmInitCompleted = TRUE;
  2666. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: VCM init failed"));
  2667. }
  2668. if (needSrcModuleInit && !srcModuleInitCompleted) {
  2669. //
  2670. // Initialize the modules
  2671. //
  2672. b = InitializeModules (platform, NULL);
  2673. srcModuleInitCompleted = TRUE;
  2674. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: src module init failed"));
  2675. }
  2676. if (needRollbackInit && !rollbackInitCompleted) {
  2677. //
  2678. // remove all journal entries, prepare for a new apply
  2679. //
  2680. if (g_JournalDirectory) {
  2681. FiRemoveAllFilesInTree (g_JournalDirectory);
  2682. BfCreateDirectory (g_JournalDirectory);
  2683. journalFile = JoinPaths (g_JournalDirectory, TEXT("JOURNAL.DAT"));
  2684. g_JournalHandle = BfCreateFile (journalFile);
  2685. if (g_JournalHandle) {
  2686. tempField = JRN_SIGNATURE;
  2687. BfWriteFile (g_JournalHandle, (PBYTE)(&tempField), sizeof (DWORD));
  2688. tempField = JRN_VERSION;
  2689. BfWriteFile (g_JournalHandle, (PBYTE)(&tempField), sizeof (DWORD));
  2690. FreePathString (journalFile);
  2691. currentUserData = GetCurrentUserData ();
  2692. if (currentUserData) {
  2693. pRecordUserData (
  2694. currentUserData->UserName,
  2695. currentUserData->UserDomain,
  2696. currentUserData->UserStringSid,
  2697. currentUserData->UserProfilePath,
  2698. FALSE
  2699. );
  2700. FreeCurrentUserData (currentUserData);
  2701. } else {
  2702. pRecordUserData (
  2703. NULL,
  2704. NULL,
  2705. NULL,
  2706. NULL,
  2707. FALSE
  2708. );
  2709. }
  2710. }
  2711. }
  2712. ELSE_DEBUGMSG ((DBG_WHOOPS, "Journal directory does not exist."));
  2713. rollbackInitCompleted = TRUE;
  2714. }
  2715. if (needDestModuleInit && !destModuleInitCompleted) {
  2716. //
  2717. // Initialize the modules
  2718. //
  2719. b = InitializeModules (platform, NULL);
  2720. destModuleInitCompleted = TRUE;
  2721. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: dest module init failed"));
  2722. }
  2723. }
  2724. if (b && parseEtm) {
  2725. //
  2726. // Execute the appropriate ETM parse functions
  2727. //
  2728. b = pEtmParse (NULL);
  2729. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: ETM parse failed"));
  2730. b = b && !CheckCancel();
  2731. }
  2732. if (b && parseVcm) {
  2733. //
  2734. // Execute the appropriate virtual computer parse functions
  2735. //
  2736. b = pCreateComputerParse (NULL);
  2737. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: VCM parse failed"));
  2738. b = b && !CheckCancel();
  2739. }
  2740. if (b && processVcm) {
  2741. //
  2742. // Execute the appropriate virtual computer gather functions
  2743. //
  2744. b = pCreateComputerGather (NULL);
  2745. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: VCM queue enumeration or gather callback failed"));
  2746. b = b && !CheckCancel();
  2747. }
  2748. if (b && parseSource) {
  2749. //
  2750. // Execute the appropriate virtual computer parse functions
  2751. //
  2752. b = pSourceParse (NULL);
  2753. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: SGM parse failed"));
  2754. b = b && !CheckCancel();
  2755. }
  2756. if (b && processSource) {
  2757. //
  2758. // Execute the appropriate source gather functions
  2759. //
  2760. b = pSourceGather (NULL);
  2761. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: SGM queue enumeration or gather callback failed"));
  2762. b = b && !CheckCancel();
  2763. if (b) {
  2764. b = pSourceAnalyze (NULL);
  2765. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: SAM failed"));
  2766. b = b && !CheckCancel();
  2767. }
  2768. }
  2769. if (b && processDestination) {
  2770. //
  2771. // Execute the appropriate destination functions
  2772. //
  2773. b = pDestinationGather (NULL);
  2774. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: DGM queue enumeration or gather callback failed"));
  2775. b = b && !CheckCancel();
  2776. if (b) {
  2777. b = pDestinationAnalyze (NULL);
  2778. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: DAM failed"));
  2779. b = b && !CheckCancel();
  2780. }
  2781. if (b) {
  2782. b = pDestinationApply (NULL);
  2783. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: dest apply failed"));
  2784. b = b && !CheckCancel();
  2785. }
  2786. }
  2787. if (b && processDelayedOperations) {
  2788. //
  2789. // Execute the appropriate delayed operations
  2790. //
  2791. b = ExecuteDelayedOperations (cleanupOnly);
  2792. DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: delayed operations failed"));
  2793. }
  2794. if (needTransportTermination) {
  2795. MYASSERT (g_SelectedTransport);
  2796. MYASSERT (g_SelectedTransport->TransportEndApply);
  2797. g_SelectedTransport->TransportEndApply ();
  2798. }
  2799. if (needTerminate) {
  2800. //
  2801. // Done -- terminate the modules
  2802. //
  2803. TerminateModules ();
  2804. TerminateProperties (platform);
  2805. }
  2806. if (needDelayedOperationsTerminate) {
  2807. pDeleteDelayedOperationsCommand ();
  2808. }
  2809. g_IsmModulePlatformContext = PLATFORM_CURRENT;
  2810. if (g_JournalHandle) {
  2811. CloseHandle (g_JournalHandle);
  2812. g_JournalHandle = NULL;
  2813. }
  2814. g_ExecutionInProgress = FALSE;
  2815. return b;
  2816. }
  2817. BOOL
  2818. IsmRegisterProgressBarCallback (
  2819. IN PPROGRESSBARFN ProgressBarFn,
  2820. IN ULONG_PTR Arg
  2821. )
  2822. {
  2823. if (CheckCancel ()) {
  2824. return FALSE;
  2825. }
  2826. if (!ProgressBarFn) {
  2827. g_ProgressBarFn = NULL;
  2828. return TRUE;
  2829. }
  2830. if (g_ProgressBarFn) {
  2831. DEBUGMSG ((DBG_ERROR, "Progress bar callback is already set"));
  2832. return FALSE;
  2833. }
  2834. g_ProgressBarFn = ProgressBarFn;
  2835. g_ProgressBarArg = Arg;
  2836. return TRUE;
  2837. }
  2838. BOOL
  2839. pSaveStatistics (
  2840. VOID
  2841. )
  2842. {
  2843. MIG_OBJECTCOUNT objectCount [3];
  2844. MYASSERT (
  2845. g_TotalObjects.TotalObjects ==
  2846. g_SourceObjects.TotalObjects +
  2847. g_DestinationObjects.TotalObjects
  2848. );
  2849. MYASSERT (
  2850. g_TotalObjects.PersistentObjects ==
  2851. g_SourceObjects.PersistentObjects +
  2852. g_DestinationObjects.PersistentObjects
  2853. );
  2854. MYASSERT (
  2855. g_TotalObjects.ApplyObjects ==
  2856. g_SourceObjects.ApplyObjects +
  2857. g_DestinationObjects.ApplyObjects
  2858. );
  2859. CopyMemory (&(objectCount [0]), &g_TotalObjects, sizeof (MIG_OBJECTCOUNT));
  2860. CopyMemory (&(objectCount [1]), &g_SourceObjects, sizeof (MIG_OBJECTCOUNT));
  2861. CopyMemory (&(objectCount [2]), &g_DestinationObjects, sizeof (MIG_OBJECTCOUNT));
  2862. if (!MemDbSetUnorderedBlob (S_OBJECTCOUNT, 0, (PCBYTE)objectCount, 3 * sizeof (MIG_OBJECTCOUNT))) {
  2863. return FALSE;
  2864. }
  2865. return SavePerObjectStatistics ();
  2866. }
  2867. BOOL
  2868. pLoadStatistics (
  2869. VOID
  2870. )
  2871. {
  2872. PMIG_OBJECTCOUNT objectCount;
  2873. DWORD size;
  2874. objectCount = (PMIG_OBJECTCOUNT) MemDbGetUnorderedBlob (S_OBJECTCOUNT, 0, &size);
  2875. if ((!objectCount) || (size != 3 * sizeof (MIG_OBJECTCOUNT))) {
  2876. if (objectCount) {
  2877. MemDbReleaseMemory (objectCount);
  2878. }
  2879. MYASSERT (FALSE);
  2880. return FALSE;
  2881. }
  2882. CopyMemory (&g_TotalObjects, objectCount, sizeof (MIG_OBJECTCOUNT));
  2883. CopyMemory (&g_SourceObjects, objectCount + 1, sizeof (MIG_OBJECTCOUNT));
  2884. CopyMemory (&g_DestinationObjects, objectCount + 2, sizeof (MIG_OBJECTCOUNT));
  2885. MemDbReleaseMemory (objectCount);
  2886. MYASSERT (
  2887. g_TotalObjects.TotalObjects ==
  2888. g_SourceObjects.TotalObjects +
  2889. g_DestinationObjects.TotalObjects
  2890. );
  2891. MYASSERT (
  2892. g_TotalObjects.PersistentObjects ==
  2893. g_SourceObjects.PersistentObjects +
  2894. g_DestinationObjects.PersistentObjects
  2895. );
  2896. MYASSERT (
  2897. g_TotalObjects.ApplyObjects ==
  2898. g_SourceObjects.ApplyObjects +
  2899. g_DestinationObjects.ApplyObjects
  2900. );
  2901. return LoadPerObjectStatistics ();
  2902. }
  2903. BOOL
  2904. pLoadLightDatabase (
  2905. IN PCTSTR FileName
  2906. )
  2907. {
  2908. HINF infHandle;
  2909. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  2910. INFSTRUCT is2 = INITINFSTRUCT_PMHANDLE;
  2911. MIG_OBJECTTYPEID objectTypeId;
  2912. GROWBUFFER buff = INIT_GROWBUFFER;
  2913. PCTSTR field;
  2914. MIG_OBJECTSTRINGHANDLE objectName;
  2915. UINT index;
  2916. PCTSTR scope;
  2917. PCTSTR name;
  2918. PCTSTR key;
  2919. PCTSTR keyData;
  2920. UINT envType;
  2921. DWORD dummy;
  2922. PCTSTR savedGroup;
  2923. ENVENTRY_STRUCT envStruct;
  2924. PTSTR decodedString = NULL;
  2925. MIG_OBJECTTYPEIDENUM objTypeIdEnum;
  2926. PCTSTR priorityStr;
  2927. UINT priority;
  2928. TYPE_REGISTER typeRegisterData;
  2929. infHandle = InfOpenInfFile (FileName);
  2930. if (infHandle == INVALID_HANDLE_VALUE) {
  2931. return FALSE;
  2932. }
  2933. // let's load transport variables
  2934. if (InfFindFirstLine (infHandle, TEXT("Data Sections"), NULL, &is)) {
  2935. do {
  2936. name = InfGetStringField (&is, 1);
  2937. if (name && InfFindFirstLine (infHandle, name, NULL, &is2)) {
  2938. do {
  2939. key = InfGetStringField (&is2, 0);
  2940. keyData = InfGetStringField (&is2, 1);
  2941. if (key && keyData) {
  2942. IsmSetTransportVariable (PLATFORM_SOURCE, name, key, keyData);
  2943. }
  2944. } while (InfFindNextLine (&is2));
  2945. }
  2946. } while (InfFindNextLine (&is));
  2947. }
  2948. // let's load source environment variables
  2949. if (InfFindFirstLine (infHandle, TEXT("Environment"), NULL, &is)) {
  2950. do {
  2951. name = InfGetStringField (&is, 1);
  2952. scope = InfGetStringField (&is, 2);
  2953. field = InfGetStringField (&is, 3);
  2954. if (scope && name && field) {
  2955. _stscanf (field, TEXT("%lx"), &envType);
  2956. buff.End = 0;
  2957. switch (envType) {
  2958. case ENVENTRY_STRING:
  2959. field = InfGetStringField (&is, 4);
  2960. if (field) {
  2961. GbCopyString (&buff, field);
  2962. }
  2963. break;
  2964. case ENVENTRY_MULTISZ:
  2965. index = 4;
  2966. for (;;) {
  2967. field = InfGetStringField (&is, index);
  2968. if (!field) {
  2969. break;
  2970. }
  2971. GbCopyString (&buff, field);
  2972. index ++;
  2973. }
  2974. if (buff.End) {
  2975. GbCopyString (&buff, TEXT(""));
  2976. }
  2977. break;
  2978. case ENVENTRY_BINARY:
  2979. index = 4;
  2980. for (;;) {
  2981. field = InfGetStringField (&is, index);
  2982. if (!field) {
  2983. break;
  2984. }
  2985. _stscanf (field, TEXT("%lx"), &dummy);
  2986. *((PBYTE)GbGrow (&buff, sizeof (BYTE))) = (BYTE)dummy;
  2987. index ++;
  2988. }
  2989. break;
  2990. default:
  2991. // don't know what to write, it's just a flag
  2992. break;
  2993. }
  2994. // now let's add the environment variable
  2995. envStruct.Type = envType;
  2996. if (buff.End) {
  2997. envStruct.EnvBinaryData = buff.Buf;
  2998. envStruct.EnvBinaryDataSize = buff.End;
  2999. } else {
  3000. envStruct.EnvBinaryData = NULL;
  3001. envStruct.EnvBinaryDataSize = 0;
  3002. }
  3003. savedGroup = g_CurrentGroup;
  3004. g_CurrentGroup = scope;
  3005. IsmSetEnvironmentValue (
  3006. PLATFORM_SOURCE,
  3007. (scope && *scope)?scope:NULL,
  3008. name,
  3009. &envStruct
  3010. );
  3011. g_CurrentGroup = savedGroup;
  3012. }
  3013. } while (InfFindNextLine (&is));
  3014. }
  3015. // let's load object types
  3016. if (InfFindFirstLine (infHandle, TEXT("Object Types"), NULL, &is)) {
  3017. do {
  3018. field = InfGetStringField (&is, 1);
  3019. priorityStr = InfGetStringField (&is, 2);
  3020. if (field && priorityStr) {
  3021. MYASSERT (IsmGetObjectTypeId (field) != 0);
  3022. if (IsmGetObjectTypeId (field) == 0) {
  3023. // we need to preregister this type
  3024. ZeroMemory (&typeRegisterData, sizeof (TYPE_REGISTER));
  3025. _stscanf (priorityStr, TEXT("%lx"), &priority);
  3026. typeRegisterData.Priority = priority;
  3027. IsmRegisterObjectType (
  3028. field,
  3029. TRUE,
  3030. FALSE,
  3031. &typeRegisterData
  3032. );
  3033. }
  3034. }
  3035. } while (InfFindNextLine (&is));
  3036. }
  3037. InfCleanUpInfStruct (&is);
  3038. if (IsmEnumFirstObjectTypeId (&objTypeIdEnum)) {
  3039. do {
  3040. objectTypeId = objTypeIdEnum.ObjectTypeId;
  3041. if (InfFindFirstLine (infHandle, IsmGetObjectTypeName (objectTypeId), NULL, &is)) {
  3042. do {
  3043. index = 1;
  3044. buff.End = 0;
  3045. for (;;) {
  3046. field = InfGetStringField (&is, index);
  3047. if (!field) {
  3048. break;
  3049. }
  3050. if (*field) {
  3051. decodedString = DuplicatePathString (field, 0);
  3052. if (DecodeRuleChars (decodedString, field) != NULL) {
  3053. GbCopyString (&buff, decodedString);
  3054. } else {
  3055. GbCopyString (&buff, field);
  3056. }
  3057. FreePathString (decodedString);
  3058. } else {
  3059. GbCopyString (&buff, TEXT("<empty>"));
  3060. }
  3061. index ++;
  3062. }
  3063. if (buff.End) {
  3064. GbCopyString (&buff, TEXT(""));
  3065. if (IsmConvertMultiSzToObject (
  3066. objectTypeId,
  3067. (PCTSTR)buff.Buf,
  3068. &objectName,
  3069. NULL
  3070. )) {
  3071. // now save the object data into our database
  3072. // for future reference
  3073. IsmMakePersistentObject (objectTypeId | PLATFORM_SOURCE, objectName);
  3074. IsmDestroyObjectHandle (objectName);
  3075. }
  3076. }
  3077. } while (InfFindNextLine (&is));
  3078. }
  3079. } while (IsmEnumNextObjectTypeId (&objTypeIdEnum));
  3080. }
  3081. InfCleanUpInfStruct (&is);
  3082. InfCleanUpInfStruct (&is2);
  3083. InfCloseInfFile (infHandle);
  3084. GbFree (&buff);
  3085. pSaveStatistics ();
  3086. return TRUE;
  3087. }
  3088. BOOL
  3089. pFinishLoad (
  3090. VOID
  3091. )
  3092. {
  3093. MIG_OBJECTSTRINGHANDLE memDbObjectName;
  3094. MIG_CONTENT memDbContent;
  3095. BOOL result = FALSE;
  3096. GROWLIST growList = INIT_GROWLIST;
  3097. __try {
  3098. switch (g_TransportType) {
  3099. case TRANSPORTTYPE_LIGHT:
  3100. if (!RegisterInternalAttributes ()) {
  3101. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 6));
  3102. __leave;
  3103. }
  3104. memDbObjectName = IsmCreateObjectHandle (S_DATABASEFILE_LITE, NULL);
  3105. if (!IsmAcquireObjectEx (MIG_DATA_TYPE | PLATFORM_SOURCE, memDbObjectName, &memDbContent, CONTENTTYPE_FILE, 0)) {
  3106. IsmDestroyObjectHandle (memDbObjectName);
  3107. DEBUGMSG ((DBG_ISM, "pFinishLoad: Failed to acquire VCM database"));
  3108. __leave;
  3109. }
  3110. if (!pLoadLightDatabase (memDbContent.FileContent.ContentPath)) {
  3111. IsmDestroyObjectHandle (memDbObjectName);
  3112. IsmReleaseObject (&memDbContent);
  3113. DEBUGMSG ((DBG_ISM, "pFinishLoad: Failed to load VCM database"));
  3114. __leave;
  3115. }
  3116. IsmDestroyObjectHandle (memDbObjectName);
  3117. IsmReleaseObject (&memDbContent);
  3118. break;
  3119. case TRANSPORTTYPE_FULL:
  3120. //
  3121. // Save environment into a grow list, because memdb is going to be reloaded
  3122. //
  3123. EnvSaveEnvironment (&growList);
  3124. memDbObjectName = IsmCreateObjectHandle (S_DATABASEFILE_FULL, NULL);
  3125. if (!IsmAcquireObjectEx (MIG_DATA_TYPE | PLATFORM_SOURCE, memDbObjectName, &memDbContent, CONTENTTYPE_FILE, 0)) {
  3126. IsmDestroyObjectHandle (memDbObjectName);
  3127. DEBUGMSG ((DBG_ISM, "pFinishLoad: Failed to acquire database"));
  3128. __leave;
  3129. }
  3130. if (!MemDbLoad (memDbContent.FileContent.ContentPath)) {
  3131. IsmDestroyObjectHandle (memDbObjectName);
  3132. IsmReleaseObject (&memDbContent);
  3133. DEBUGMSG ((DBG_ISM, "pFinishLoad: Failed to load database"));
  3134. __leave;
  3135. }
  3136. IsmDestroyObjectHandle (memDbObjectName);
  3137. IsmReleaseObject (&memDbContent);
  3138. //
  3139. // Rebuild all the things we lost because of the memdb refresh
  3140. //
  3141. if (!RegisterInternalAttributes ()) {
  3142. DEBUGMSG ((DBG_ISM, "pFinishLoad: Failed to register persistent attrib"));
  3143. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 7));
  3144. __leave;
  3145. }
  3146. EnvRestoreEnvironment (&growList);
  3147. break;
  3148. default:
  3149. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_UNKNOWN_TRANSPORT_TYPE, g_TransportType));
  3150. __leave;
  3151. }
  3152. pLoadStatistics ();
  3153. GlFree (&growList);
  3154. EnvInvalidateCallbacks ();
  3155. result = TRUE;
  3156. }
  3157. __finally {
  3158. }
  3159. return result;
  3160. }
  3161. BOOL
  3162. IsmLoad (
  3163. VOID
  3164. )
  3165. {
  3166. BOOL result = FALSE;
  3167. GROWLIST growList = INIT_GROWLIST;
  3168. if (CheckCancel ()) {
  3169. return FALSE;
  3170. }
  3171. if (!g_SelectedTransport || !g_SelectedTransport->ShouldBeCalled) {
  3172. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_TRANSPORT_SELECTED));
  3173. return FALSE;
  3174. }
  3175. g_ExecutionInProgress = TRUE;
  3176. //
  3177. // We need to invalidate operation combinations created so far
  3178. // because we might load a new memdb where all operations could
  3179. // be registered already
  3180. //
  3181. TerminateOperations ();
  3182. g_CurrentPhase = MIG_TRANSPORT_PHASE;
  3183. g_SliceBuffer.End = 0;
  3184. __try {
  3185. if (g_SelectedTransport->TransportEstimateProgressBar) {
  3186. g_SelectedTransport->TransportEstimateProgressBar (g_IsmCurrentPlatform);
  3187. }
  3188. pCallProgressBar (MIG_BEGIN_PHASE);
  3189. MYASSERT (g_SelectedTransport->TransportBeginApply);
  3190. if (!g_SelectedTransport->TransportBeginApply ()) {
  3191. DEBUGMSG ((DBG_ISM, "IsmLoad: Begin apply failed"));
  3192. __leave;
  3193. }
  3194. result = pFinishLoad ();
  3195. }
  3196. __finally {
  3197. PushError ();
  3198. pCallProgressBar (MIG_END_PHASE);
  3199. g_CurrentPhase = 0;
  3200. g_SliceBuffer.End = 0;
  3201. PopError ();
  3202. }
  3203. if (!result) {
  3204. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_LOAD_FAILURE));
  3205. } else {
  3206. InitializeOperations ();
  3207. }
  3208. g_ExecutionInProgress = FALSE;
  3209. return result;
  3210. }
  3211. BOOL
  3212. IsmResumeLoad (
  3213. VOID
  3214. )
  3215. {
  3216. BOOL result = FALSE;
  3217. GROWLIST growList = INIT_GROWLIST;
  3218. if (CheckCancel ()) {
  3219. return FALSE;
  3220. }
  3221. if (!g_SelectedTransport || !g_SelectedTransport->ShouldBeCalled) {
  3222. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_TRANSPORT_SELECTED));
  3223. return FALSE;
  3224. }
  3225. g_ExecutionInProgress = TRUE;
  3226. //
  3227. // We need to invalidate operation combinations created so far
  3228. // because we might load a new memdb where all operations could
  3229. // be registered already
  3230. //
  3231. TerminateOperations ();
  3232. g_CurrentPhase = MIG_TRANSPORT_PHASE;
  3233. g_SliceBuffer.End = 0;
  3234. __try {
  3235. if (g_SelectedTransport->TransportEstimateProgressBar) {
  3236. g_SelectedTransport->TransportEstimateProgressBar (g_IsmCurrentPlatform);
  3237. }
  3238. pCallProgressBar (MIG_BEGIN_PHASE);
  3239. if (!g_SelectedTransport->TransportResumeApply) {
  3240. __leave;
  3241. }
  3242. if (!g_SelectedTransport->TransportResumeApply ()) {
  3243. __leave;
  3244. }
  3245. result = pFinishLoad ();
  3246. }
  3247. __finally {
  3248. PushError ();
  3249. pCallProgressBar (MIG_END_PHASE);
  3250. g_CurrentPhase = 0;
  3251. g_SliceBuffer.End = 0;
  3252. PopError ();
  3253. }
  3254. if (result) {
  3255. InitializeOperations ();
  3256. }
  3257. g_ExecutionInProgress = FALSE;
  3258. return result;
  3259. }
  3260. BOOL
  3261. pSaveLightDatabase (
  3262. IN PCTSTR FileName
  3263. )
  3264. {
  3265. HANDLE fileHandle = NULL;
  3266. MIG_OBJECTTYPEID objectTypeId;
  3267. ENV_ENTRY_ENUM envEntryEnum;
  3268. MULTISZ_ENUM multiSzEnum;
  3269. UINT size;
  3270. TCHAR buffer[sizeof (DWORD) * 2 + 3];
  3271. PCTSTR start;
  3272. PCTSTR end;
  3273. TCHAR section[256];
  3274. TCHAR sectionLookahead[256];
  3275. UINT pass;
  3276. MIG_OBJECTTYPEIDENUM objTypeIdEnum;
  3277. fileHandle = BfCreateFile (FileName);
  3278. if (!fileHandle) {
  3279. return FALSE;
  3280. }
  3281. WriteFileString (fileHandle, TEXT("[Version]\r\n"));
  3282. WriteFileString (fileHandle, TEXT("signature=\"$CHICAGO$\"\r\n"));
  3283. WriteFileString (fileHandle, TEXT("Class=Upgrade\r\n\r\n\r\n"));
  3284. //
  3285. // Write sections for lite transport
  3286. //
  3287. for (pass = 0 ; pass < 2 ; pass++) {
  3288. if (EnvEnumerateFirstEntry (
  3289. &envEntryEnum,
  3290. PLATFORM_SOURCE,
  3291. TEXT("*\\") S_TRANSPORT_PREFIX TEXT("\\*")
  3292. )) {
  3293. if (pass == 0) {
  3294. WriteFileString (fileHandle, TEXT("[Data Sections]\r\n"));
  3295. }
  3296. *section = 0;
  3297. do {
  3298. if (envEntryEnum.EnvEntryType != ENVENTRY_STRING) {
  3299. continue;
  3300. }
  3301. if (!envEntryEnum.EnvEntryDataSize || !envEntryEnum.EnvEntryData) {
  3302. continue;
  3303. }
  3304. if (envEntryEnum.EnvEntryName) {
  3305. //
  3306. // Find start and end of section name
  3307. //
  3308. start = envEntryEnum.EnvEntryName;
  3309. end = _tcschr (start, TEXT('\\'));
  3310. if (!end) {
  3311. continue;
  3312. }
  3313. start = end + 1;
  3314. end = _tcschr (start, TEXT('\\'));
  3315. if (end && (end - start) < (ARRAYSIZE (sectionLookahead) - 2)) {
  3316. //
  3317. // Copy section name into lookahead buffer
  3318. //
  3319. StringCopyAB (sectionLookahead, start, end);
  3320. //
  3321. // Ignore if no keys exist
  3322. //
  3323. start = _tcsinc (end);
  3324. if (*start == 0) {
  3325. continue;
  3326. }
  3327. //
  3328. // If lookahead buffer != last section, write section name
  3329. //
  3330. if (StringICompare (section, sectionLookahead)) {
  3331. if (pass == 1 && *section) {
  3332. WriteFileString (fileHandle, TEXT("\r\n"));
  3333. }
  3334. StringCopy (section, sectionLookahead);
  3335. if (pass == 1) {
  3336. WriteFileString (fileHandle, TEXT("["));
  3337. }
  3338. WriteFileString (fileHandle, section);
  3339. if (pass == 1) {
  3340. WriteFileString (fileHandle, TEXT("]\r\n"));
  3341. } else {
  3342. WriteFileString (fileHandle, TEXT("\r\n"));
  3343. }
  3344. }
  3345. //
  3346. // If pass 1, write the key=value text
  3347. //
  3348. if (pass == 1) {
  3349. WriteFileString (fileHandle, start);
  3350. WriteFileString (fileHandle, TEXT(" = "));
  3351. WriteFileString (fileHandle, (PCTSTR)envEntryEnum.EnvEntryData);
  3352. WriteFileString (fileHandle, TEXT("\r\n"));
  3353. }
  3354. }
  3355. }
  3356. } while (EnvEnumerateNextEntry (&envEntryEnum));
  3357. AbortEnvEnumerateEntry (&envEntryEnum);
  3358. if (*section == 0) {
  3359. WriteFileString (fileHandle, TEXT("; empty\r\n\r\n"));
  3360. } else {
  3361. WriteFileString (fileHandle, TEXT("\r\n"));
  3362. }
  3363. }
  3364. }
  3365. WriteFileString (fileHandle, TEXT("[Environment]\r\n"));
  3366. if (EnvEnumerateFirstEntry (&envEntryEnum, PLATFORM_SOURCE, TEXT("*"))) {
  3367. do {
  3368. // skip v1 hack variables
  3369. if (envEntryEnum.EnvEntryName) {
  3370. if (StringIMatchCharCount (
  3371. S_TRANSPORT_PREFIX TEXT("\\"),
  3372. envEntryEnum.EnvEntryName,
  3373. ARRAYSIZE (S_TRANSPORT_PREFIX)
  3374. )) {
  3375. continue;
  3376. }
  3377. }
  3378. // write the group and the name
  3379. WriteFileString (fileHandle, TEXT("\""));
  3380. if (envEntryEnum.EnvEntryName) {
  3381. WriteFileString (fileHandle, envEntryEnum.EnvEntryName);
  3382. }
  3383. WriteFileString (fileHandle, TEXT("\",\""));
  3384. if (envEntryEnum.EnvEntryGroup) {
  3385. WriteFileString (fileHandle, envEntryEnum.EnvEntryGroup);
  3386. }
  3387. WriteFileString (fileHandle, TEXT("\","));
  3388. // now write the entry type
  3389. wsprintf (buffer, TEXT("0x%08X"), envEntryEnum.EnvEntryType);
  3390. WriteFileString (fileHandle, buffer);
  3391. switch (envEntryEnum.EnvEntryType) {
  3392. case ENVENTRY_STRING:
  3393. if (envEntryEnum.EnvEntryDataSize && envEntryEnum.EnvEntryData) {
  3394. WriteFileString (fileHandle, TEXT(",\""));
  3395. WriteFileString (fileHandle, (PCTSTR)envEntryEnum.EnvEntryData);
  3396. WriteFileString (fileHandle, TEXT("\""));
  3397. }
  3398. break;
  3399. case ENVENTRY_MULTISZ:
  3400. if (envEntryEnum.EnvEntryDataSize && envEntryEnum.EnvEntryData) {
  3401. if (EnumFirstMultiSz (&multiSzEnum, (PCTSTR)envEntryEnum.EnvEntryData)) {
  3402. do {
  3403. WriteFileString (fileHandle, TEXT(",\""));
  3404. WriteFileString (fileHandle, multiSzEnum.CurrentString);
  3405. WriteFileString (fileHandle, TEXT("\""));
  3406. } while (EnumNextMultiSz (&multiSzEnum));
  3407. }
  3408. }
  3409. break;
  3410. case ENVENTRY_BINARY:
  3411. if (envEntryEnum.EnvEntryDataSize && envEntryEnum.EnvEntryData) {
  3412. // write it in binary format
  3413. size = 0;
  3414. while (size < envEntryEnum.EnvEntryDataSize) {
  3415. wsprintf (
  3416. buffer,
  3417. TEXT("%02X"),
  3418. envEntryEnum.EnvEntryData [size]
  3419. );
  3420. WriteFileString (fileHandle, TEXT(","));
  3421. WriteFileString (fileHandle, buffer);
  3422. size ++;
  3423. }
  3424. }
  3425. break;
  3426. default:
  3427. // don't know what to write, it's just a flag
  3428. break;
  3429. }
  3430. WriteFileString (fileHandle, TEXT("\r\n"));
  3431. } while (EnvEnumerateNextEntry (&envEntryEnum));
  3432. AbortEnvEnumerateEntry (&envEntryEnum);
  3433. }
  3434. WriteFileString (fileHandle, TEXT("\r\n\r\n"));
  3435. WriteFileString (fileHandle, TEXT("[Object Types]\r\n"));
  3436. if (IsmEnumFirstObjectTypeId (&objTypeIdEnum)) {
  3437. do {
  3438. objectTypeId = objTypeIdEnum.ObjectTypeId;
  3439. WriteFileString (fileHandle, IsmGetObjectTypeName (objectTypeId));
  3440. WriteFileString (fileHandle, TEXT(", "));
  3441. wsprintf (buffer, TEXT("0x%08X"), IsmGetObjectTypePriority (objectTypeId));
  3442. WriteFileString (fileHandle, buffer);
  3443. WriteFileString (fileHandle, TEXT("\r\n"));
  3444. } while (IsmEnumNextObjectTypeId (&objTypeIdEnum));
  3445. }
  3446. WriteFileString (fileHandle, TEXT("\r\n\r\n"));
  3447. CloseHandle (fileHandle);
  3448. return TRUE;
  3449. }
  3450. BOOL
  3451. IsmSave (
  3452. VOID
  3453. )
  3454. {
  3455. MIG_OBJECTSTRINGHANDLE memDbObjectName;
  3456. TCHAR tempPath [MAX_PATH];
  3457. BOOL result = FALSE;
  3458. if (CheckCancel ()) {
  3459. return FALSE;
  3460. }
  3461. if (!g_SelectedTransport || !g_SelectedTransport->ShouldBeCalled) {
  3462. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_TRANSPORT_SELECTED));
  3463. return FALSE;
  3464. }
  3465. __try {
  3466. g_ExecutionInProgress = TRUE;
  3467. if (!IsmGetTempFile (tempPath, ARRAYSIZE(tempPath))) {
  3468. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_CANT_SAVE_MEMDB));
  3469. __leave;
  3470. }
  3471. switch (g_TransportType) {
  3472. case TRANSPORTTYPE_LIGHT:
  3473. memDbObjectName = IsmCreateObjectHandle (S_DATABASEFILE_LITE, NULL);
  3474. DataTypeAddObject (memDbObjectName, tempPath, TRUE);
  3475. IsmDestroyObjectHandle (memDbObjectName);
  3476. if (!pSaveLightDatabase (tempPath)) {
  3477. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_CANT_SAVE_MEMDB));
  3478. __leave;
  3479. }
  3480. break;
  3481. case TRANSPORTTYPE_FULL:
  3482. memDbObjectName = IsmCreateObjectHandle (S_DATABASEFILE_FULL, NULL);
  3483. DataTypeAddObject (memDbObjectName, tempPath, TRUE);
  3484. IsmDestroyObjectHandle (memDbObjectName);
  3485. pSaveStatistics ();
  3486. if (!MemDbSave (tempPath)) {
  3487. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_CANT_SAVE_MEMDB));
  3488. __leave;
  3489. }
  3490. break;
  3491. default:
  3492. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_UNKNOWN_TRANSPORT_TYPE, g_TransportType));
  3493. __leave;
  3494. }
  3495. EnvInvalidateCallbacks ();
  3496. g_CurrentPhase = MIG_TRANSPORT_PHASE;
  3497. g_SliceBuffer.End = 0;
  3498. if (g_SelectedTransport->TransportEstimateProgressBar) {
  3499. g_SelectedTransport->TransportEstimateProgressBar (g_IsmCurrentPlatform);
  3500. }
  3501. pCallProgressBar (MIG_BEGIN_PHASE);
  3502. result = g_SelectedTransport->TransportSaveState ();
  3503. if (result) {
  3504. DeleteFile (tempPath);
  3505. } else {
  3506. DEBUGMSG ((DBG_ISM, "TransportSaveState failed"));
  3507. // NTRAID#NTBUG9-168115-2000/08/23-jimschm Temp file is not cleaned up here or in resume below
  3508. }
  3509. pCallProgressBar (MIG_END_PHASE);
  3510. g_CurrentPhase = 0;
  3511. g_SliceBuffer.End = 0;
  3512. }
  3513. __finally {
  3514. g_ExecutionInProgress = FALSE;
  3515. }
  3516. if (!result) {
  3517. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_SAVE_FAILURE));
  3518. }
  3519. return result;
  3520. }
  3521. BOOL
  3522. IsmResumeSave (
  3523. VOID
  3524. )
  3525. {
  3526. BOOL result;
  3527. if (CheckCancel ()) {
  3528. return FALSE;
  3529. }
  3530. if (!g_SelectedTransport || !g_SelectedTransport->ShouldBeCalled) {
  3531. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_TRANSPORT_SELECTED));
  3532. return FALSE;
  3533. }
  3534. if (!g_SelectedTransport->TransportResumeSaveState) {
  3535. return FALSE;
  3536. }
  3537. g_ExecutionInProgress = TRUE;
  3538. EnvInvalidateCallbacks ();
  3539. g_CurrentPhase = MIG_TRANSPORT_PHASE;
  3540. g_SliceBuffer.End = 0;
  3541. if (g_SelectedTransport->TransportEstimateProgressBar) {
  3542. g_SelectedTransport->TransportEstimateProgressBar (g_IsmCurrentPlatform);
  3543. }
  3544. pCallProgressBar (MIG_BEGIN_PHASE);
  3545. result = g_SelectedTransport->TransportResumeSaveState ();
  3546. DEBUGMSG_IF ((!result, DBG_ISM, "TransportResumeSaveState failed"));
  3547. pCallProgressBar (MIG_END_PHASE);
  3548. g_CurrentPhase = 0;
  3549. g_SliceBuffer.End = 0;
  3550. g_ExecutionInProgress = FALSE;
  3551. return result;
  3552. }
  3553. PVOID
  3554. TrackedIsmGetMemory (
  3555. IN UINT Size
  3556. TRACKING_DEF
  3557. )
  3558. {
  3559. PVOID result;
  3560. TRACK_ENTER();
  3561. if (!g_IsmPool) {
  3562. g_IsmPool = PmCreateNamedPool ("ISM Pool");
  3563. }
  3564. result = PmGetMemory (g_IsmPool, Size);
  3565. TRACK_LEAVE();
  3566. return result;
  3567. }
  3568. PCTSTR
  3569. TrackedIsmDuplicateString (
  3570. IN PCTSTR String
  3571. TRACKING_DEF
  3572. )
  3573. {
  3574. PCTSTR result;
  3575. TRACK_ENTER();
  3576. if (!g_IsmPool) {
  3577. g_IsmPool = PmCreateNamedPool ("ISM Pool");
  3578. }
  3579. result = PmDuplicateString (g_IsmPool, String);
  3580. TRACK_LEAVE();
  3581. return result;
  3582. }
  3583. BOOL
  3584. IsmReleaseMemory (
  3585. IN PCVOID Memory
  3586. )
  3587. {
  3588. if (g_IsmPool && Memory) {
  3589. PmReleaseMemory (g_IsmPool, Memory);
  3590. return TRUE;
  3591. } else {
  3592. return FALSE;
  3593. }
  3594. }
  3595. MIG_OBJECTSTRINGHANDLE
  3596. TrackedIsmCreateObjectHandle (
  3597. IN PCTSTR Node,
  3598. IN PCTSTR Leaf
  3599. TRACKING_DEF
  3600. )
  3601. {
  3602. MIG_OBJECTSTRINGHANDLE result;
  3603. TRACK_ENTER();
  3604. result = ObsBuildEncodedObjectStringEx (Node, Leaf, TRUE);
  3605. TRACK_LEAVE();
  3606. return result;
  3607. }
  3608. BOOL
  3609. WINAPI
  3610. TrackedIsmCreateObjectStringsFromHandleEx (
  3611. IN MIG_OBJECTSTRINGHANDLE Handle,
  3612. OUT PCTSTR *Node, OPTIONAL
  3613. OUT PCTSTR *Leaf, OPTIONAL
  3614. IN BOOL DoNotDecode
  3615. TRACKING_DEF
  3616. )
  3617. {
  3618. BOOL result;
  3619. TRACK_ENTER();
  3620. result = ObsSplitObjectStringEx (
  3621. Handle,
  3622. Node,
  3623. Leaf,
  3624. NULL,
  3625. !DoNotDecode
  3626. );
  3627. if (!result) {
  3628. if (Node) {
  3629. *Node = NULL;
  3630. }
  3631. if (Leaf) {
  3632. *Leaf = NULL;
  3633. }
  3634. }
  3635. TRACK_LEAVE();
  3636. return result;
  3637. }
  3638. VOID
  3639. IsmDestroyObjectString (
  3640. IN PCTSTR String
  3641. )
  3642. {
  3643. ObsFree (String);
  3644. }
  3645. VOID
  3646. IsmDestroyObjectHandle (
  3647. IN MIG_OBJECTSTRINGHANDLE Handle
  3648. )
  3649. {
  3650. ObsFree (Handle);
  3651. }
  3652. BOOL
  3653. IsmIsObjectHandleNodeOnly (
  3654. IN MIG_OBJECTSTRINGHANDLE Handle
  3655. )
  3656. {
  3657. return ObsGetLeafPortionOfEncodedString (Handle) == NULL;
  3658. }
  3659. BOOL
  3660. IsmIsObjectHandleLeafOnly (
  3661. IN MIG_OBJECTSTRINGHANDLE Handle
  3662. )
  3663. {
  3664. return !ObsHasNode (Handle);
  3665. }
  3666. PCTSTR
  3667. pCreatePatternStr (
  3668. IN PMIG_SEGMENTS Segments, OPTIONAL
  3669. IN UINT Count
  3670. )
  3671. {
  3672. PTSTR result;
  3673. UINT size;
  3674. UINT u;
  3675. PTSTR p;
  3676. if (Segments == ALL_PATTERN) {
  3677. result = DuplicatePathString (TEXT("*"), 0);
  3678. } else if (Segments && Count) {
  3679. //
  3680. // Compute the buffer size needed: logchars * DBCS * escaping + nul
  3681. //
  3682. size = 1;
  3683. for (u = 0; u < Count ; u++) {
  3684. if (!Segments[u].IsPattern) {
  3685. size += TcharCount (Segments[u].Segment) * 2;
  3686. } else {
  3687. size += TcharCount (Segments[u].Segment);
  3688. }
  3689. }
  3690. #ifndef UNICODE
  3691. size *= 2; // account for dbcs expansion
  3692. #endif
  3693. result = AllocPathString (size);
  3694. p = result;
  3695. //
  3696. // Build the pattern
  3697. //
  3698. *p = 0;
  3699. for (u = 0; u < Count ; u ++) {
  3700. if (!Segments[u].IsPattern) {
  3701. ObsEncodeString (p, Segments[u].Segment);
  3702. p = GetEndOfString (p);
  3703. } else {
  3704. p = StringCat (p, Segments[u].Segment);
  3705. }
  3706. }
  3707. } else {
  3708. result = DuplicatePathString (TEXT(""), 0);
  3709. }
  3710. return result;
  3711. }
  3712. MIG_OBJECTSTRINGHANDLE
  3713. TrackedIsmCreateObjectPattern (
  3714. IN PMIG_SEGMENTS NodeSegments, OPTIONAL
  3715. IN UINT NodeSegmentsNr,
  3716. IN PMIG_SEGMENTS LeafSegments, OPTIONAL
  3717. IN UINT LeafSegmentsNr
  3718. TRACKING_DEF
  3719. )
  3720. {
  3721. PCTSTR node;
  3722. PCTSTR leaf;
  3723. ENCODEDSTRHANDLE result;
  3724. TRACK_ENTER();
  3725. if (NodeSegments == ALL_PATTERN) {
  3726. NodeSegmentsNr = 1;
  3727. }
  3728. if (LeafSegments == ALL_PATTERN) {
  3729. LeafSegmentsNr = 1;
  3730. }
  3731. node = pCreatePatternStr (NodeSegments, NodeSegmentsNr);
  3732. leaf = pCreatePatternStr (LeafSegments, LeafSegmentsNr);
  3733. result = ObsBuildEncodedObjectStringEx (NodeSegmentsNr ? node : NULL, LeafSegmentsNr ? leaf : NULL, FALSE);
  3734. FreePathString (node);
  3735. FreePathString (leaf);
  3736. TRACK_LEAVE();
  3737. return result;
  3738. }
  3739. MIG_OBJECTSTRINGHANDLE
  3740. TrackedIsmCreateSimpleObjectPattern (
  3741. IN PCTSTR BaseNode, OPTIONAL
  3742. IN BOOL EnumTree,
  3743. IN PCTSTR Leaf, OPTIONAL
  3744. IN BOOL LeafIsPattern
  3745. TRACKING_DEF
  3746. )
  3747. {
  3748. MIG_SEGMENTS nodePat[2];
  3749. MIG_SEGMENTS leafPat[1];
  3750. UINT nrSegNode = 0;
  3751. UINT nrSegLeaf = 0;
  3752. PCTSTR p;
  3753. MIG_OBJECTSTRINGHANDLE result;
  3754. TRACK_ENTER();
  3755. if (BaseNode) {
  3756. nodePat [0].Segment = BaseNode;
  3757. nodePat [0].IsPattern = FALSE;
  3758. nrSegNode ++;
  3759. }
  3760. if (EnumTree) {
  3761. if (nrSegNode) {
  3762. p = _tcsdec2 (BaseNode, GetEndOfString (BaseNode));
  3763. if (p && _tcsnextc (p) == TEXT('\\')) {
  3764. nodePat [nrSegNode].Segment = TEXT("*");
  3765. } else {
  3766. nodePat [nrSegNode].Segment = TEXT("\\*");
  3767. }
  3768. } else {
  3769. nodePat [nrSegNode].Segment = TEXT("*");
  3770. }
  3771. nodePat [nrSegNode].IsPattern = TRUE;
  3772. nrSegNode ++;
  3773. }
  3774. if (Leaf) {
  3775. leafPat [0].Segment = Leaf;
  3776. leafPat [0].IsPattern = LeafIsPattern;
  3777. nrSegLeaf ++;
  3778. } else {
  3779. if (LeafIsPattern) {
  3780. leafPat [0].Segment = TEXT("*");
  3781. leafPat [0].IsPattern = TRUE;
  3782. nrSegLeaf ++;
  3783. }
  3784. }
  3785. result = IsmCreateObjectPattern (nrSegNode?nodePat:NULL, nrSegNode, nrSegLeaf?leafPat:NULL, nrSegLeaf);
  3786. TRACK_LEAVE();
  3787. return result;
  3788. }
  3789. PTSTR
  3790. GetFirstSeg (
  3791. IN PCTSTR SrcFileName
  3792. )
  3793. {
  3794. if (_tcsnextc (SrcFileName) == TEXT('\\')) {
  3795. SrcFileName = _tcsinc (SrcFileName);
  3796. if (_tcsnextc (SrcFileName) == TEXT('\\')) {
  3797. SrcFileName = _tcsinc (SrcFileName);
  3798. }
  3799. return (_tcschr (SrcFileName, TEXT('\\')));
  3800. } else {
  3801. return (_tcschr (SrcFileName, TEXT('\\')));
  3802. }
  3803. }
  3804. BOOL
  3805. pAddShortLongInfo (
  3806. IN ENCODEDSTRHANDLE EncodedObjectName
  3807. )
  3808. {
  3809. GROWBUFFER growBuf = INIT_GROWBUFFER;
  3810. PCTSTR node = NULL;
  3811. PCTSTR leaf = NULL;
  3812. PTSTR nativeName = NULL;
  3813. PTSTR nativeNamePtr;
  3814. PTSTR beginSegPtr;
  3815. PTSTR endSegPtr;
  3816. TCHAR savedChar;
  3817. WIN32_FIND_DATA findData;
  3818. UINT savedEnd;
  3819. UINT beginBuffIdx;
  3820. BOOL result = FALSE;
  3821. KEYHANDLE kh1, kh2;
  3822. BOOL b;
  3823. if (IsmCreateObjectStringsFromHandle (EncodedObjectName, &node, &leaf)) {
  3824. MYASSERT (node);
  3825. if (node) {
  3826. if (leaf) {
  3827. nativeName = DuplicatePathString (S_SHORTLONG_TREE, SizeOfString (node) + SizeOfString (leaf));
  3828. } else {
  3829. nativeName = DuplicatePathString (S_SHORTLONG_TREE, SizeOfString (node));
  3830. }
  3831. nativeNamePtr = AppendWack (nativeName);
  3832. StringCopy (nativeNamePtr, node);
  3833. if (leaf) {
  3834. StringCopy (AppendWack (nativeNamePtr), leaf);
  3835. }
  3836. GbAppendString (&growBuf, S_SHORTLONG_TREE);
  3837. GbAppendString (&growBuf, TEXT("\\"));
  3838. beginBuffIdx = growBuf.End - 1;
  3839. beginSegPtr = GetFirstSeg (nativeNamePtr);
  3840. if (beginSegPtr) {
  3841. beginSegPtr = _tcsinc (beginSegPtr);
  3842. GbAppendStringAB (&growBuf, nativeNamePtr, beginSegPtr);
  3843. while (beginSegPtr) {
  3844. endSegPtr = _tcschr (beginSegPtr, TEXT('\\'));
  3845. if (!endSegPtr) {
  3846. endSegPtr = GetEndOfString (beginSegPtr);
  3847. MYASSERT (endSegPtr);
  3848. }
  3849. savedChar = *endSegPtr;
  3850. *endSegPtr = 0;
  3851. if (DoesFileExistEx (nativeNamePtr, &findData)) {
  3852. if (*findData.cAlternateFileName) {
  3853. savedEnd = growBuf.End - 1;
  3854. GbAppendString (&growBuf, findData.cAlternateFileName);
  3855. kh1 = MemDbAddKey (nativeName);
  3856. if (kh1) {
  3857. kh2 = MemDbAddKey ((PCTSTR) growBuf.Buf);
  3858. if (kh2) {
  3859. b = MemDbSetValueByHandle (kh1, FILENAME_LONG);
  3860. b = b && MemDbSetValueByHandle (kh2, FILENAME_SHORT);
  3861. b = b && MemDbAddDoubleLinkageByKeyHandle (kh1, kh2, 0);
  3862. } else {
  3863. b = FALSE;
  3864. }
  3865. if (!b) {
  3866. MemDbDeleteKey (nativeName);
  3867. }
  3868. }
  3869. growBuf.End = savedEnd;
  3870. }
  3871. GbAppendString (&growBuf, findData.cFileName);
  3872. } else {
  3873. GbAppendStringAB (&growBuf, beginSegPtr, endSegPtr);
  3874. }
  3875. *endSegPtr = savedChar;
  3876. if (savedChar) {
  3877. beginSegPtr = _tcsinc (endSegPtr);
  3878. GbAppendStringAB (&growBuf, endSegPtr, beginSegPtr);
  3879. } else {
  3880. beginSegPtr = NULL;
  3881. }
  3882. }
  3883. }
  3884. FreePathString (nativeName);
  3885. }
  3886. if (node) {
  3887. IsmDestroyObjectString (node);
  3888. }
  3889. if (leaf) {
  3890. IsmDestroyObjectString (leaf);
  3891. }
  3892. }
  3893. GbFree (&growBuf);
  3894. return result;
  3895. }
  3896. BOOL
  3897. pGetShortName (
  3898. IN PCTSTR Segment,
  3899. OUT WIN32_FIND_DATA *FindData
  3900. )
  3901. {
  3902. static TCHAR tempDir [MAX_PATH] = TEXT("");
  3903. PCTSTR testFileName;
  3904. HANDLE fileHandle;
  3905. BOOL result = FALSE;
  3906. if (tempDir [0] == 0) {
  3907. IsmGetTempDirectory (tempDir, ARRAYSIZE(tempDir));
  3908. }
  3909. testFileName = JoinPaths (tempDir, Segment);
  3910. fileHandle = BfCreateFile (testFileName);
  3911. if (fileHandle) {
  3912. CloseHandle (fileHandle);
  3913. if (DoesFileExistEx (testFileName, FindData)) {
  3914. result = TRUE;
  3915. }
  3916. DeleteFile (testFileName);
  3917. }
  3918. FreePathString (testFileName);
  3919. return result;
  3920. }
  3921. BOOL
  3922. pGetFullSpecShortName (
  3923. IN MIG_OBJECTTYPEID ObjectTypeId,
  3924. IN ENCODEDSTRHANDLE ObjectName,
  3925. OUT PWIN32_FIND_DATA FindData
  3926. )
  3927. {
  3928. MIG_CONTENT objectContent;
  3929. BOOL result = FALSE;
  3930. if (IsmAcquireObject (
  3931. ObjectTypeId,
  3932. ObjectName,
  3933. &objectContent
  3934. )) {
  3935. if ((objectContent.Details.DetailsSize == sizeof (WIN32_FIND_DATA)) &&
  3936. (objectContent.Details.DetailsData)
  3937. ) {
  3938. CopyMemory (FindData, objectContent.Details.DetailsData, sizeof (WIN32_FIND_DATA));
  3939. result = TRUE;
  3940. }
  3941. IsmReleaseObject (&objectContent);
  3942. }
  3943. return result;
  3944. }
  3945. BOOL
  3946. pGetStoredShortName (
  3947. IN PCTSTR ShortLongBase,
  3948. IN PCTSTR ShortLongSegment,
  3949. OUT PWIN32_FIND_DATA FindData
  3950. )
  3951. {
  3952. KEYHANDLE kh1, kh2;
  3953. DWORD value;
  3954. PCTSTR shortLongSpec;
  3955. PCTSTR lastSeg;
  3956. PCTSTR lastSegPtr;
  3957. DWORD segSize;
  3958. BOOL result = FALSE;
  3959. ZeroMemory (FindData, sizeof (WIN32_FIND_DATA));
  3960. shortLongSpec = JoinPaths (ShortLongBase, ShortLongSegment);
  3961. if (shortLongSpec) {
  3962. kh1 = MemDbGetHandleFromKey (shortLongSpec);
  3963. if (kh1) {
  3964. MemDbGetValueByHandle (kh1, &value);
  3965. if (value == FILENAME_SHORT) {
  3966. // just copy the last segment into FindData->cAlternateFileName
  3967. lastSegPtr = _tcsrchr (shortLongSpec, TEXT('\\'));
  3968. if (lastSegPtr) {
  3969. lastSegPtr = _tcsinc (lastSegPtr);
  3970. if (lastSegPtr) {
  3971. StringCopyTcharCount (
  3972. FindData->cAlternateFileName,
  3973. lastSegPtr,
  3974. ARRAYSIZE(FindData->cAlternateFileName)
  3975. );
  3976. }
  3977. }
  3978. // get the long name information
  3979. kh2 = MemDbGetDoubleLinkageByKeyHandle (kh1, 0, 0);
  3980. MYASSERT (kh2);
  3981. if (kh2) {
  3982. lastSeg = MemDbGetKeyFromHandle (kh2, MEMDB_LAST_LEVEL);
  3983. // copy lastSeg into FindData->cFileName
  3984. StringCopyTcharCount (
  3985. FindData->cFileName,
  3986. lastSeg,
  3987. ARRAYSIZE(FindData->cFileName)
  3988. );
  3989. MemDbReleaseMemory (lastSeg);
  3990. result = TRUE;
  3991. }
  3992. } else {
  3993. // just copy the last segment into FindData->cFileName
  3994. lastSegPtr = _tcsrchr (shortLongSpec, TEXT('\\'));
  3995. if (lastSegPtr) {
  3996. lastSegPtr = _tcsinc (lastSegPtr);
  3997. if (lastSegPtr) {
  3998. StringCopyTcharCount (
  3999. FindData->cFileName,
  4000. lastSegPtr,
  4001. ARRAYSIZE(FindData->cFileName)
  4002. );
  4003. }
  4004. }
  4005. // get the short name information
  4006. kh2 = MemDbGetDoubleLinkageByKeyHandle (kh1, 0, 0);
  4007. MYASSERT (kh2);
  4008. if (kh2) {
  4009. if (kh2 != kh1) {
  4010. lastSeg = MemDbGetKeyFromHandle (kh2, MEMDB_LAST_LEVEL);
  4011. // copy lastSeg into FindData->cAlternateFileName
  4012. segSize = TcharCount (lastSeg);
  4013. if (segSize < ARRAYSIZE(FindData->cAlternateFileName)) {
  4014. StringCopyTcharCount (
  4015. FindData->cAlternateFileName,
  4016. lastSeg,
  4017. ARRAYSIZE(FindData->cAlternateFileName)
  4018. );
  4019. }
  4020. MemDbReleaseMemory (lastSeg);
  4021. }
  4022. result = TRUE;
  4023. }
  4024. }
  4025. }
  4026. FreePathString (shortLongSpec);
  4027. }
  4028. return result;
  4029. }
  4030. BOOL
  4031. pAddShortLongInfoOnDest (
  4032. IN MIG_OBJECTTYPEID ObjectTypeId,
  4033. IN ENCODEDSTRHANDLE EncodedObjectName
  4034. )
  4035. {
  4036. GROWBUFFER growBuf = INIT_GROWBUFFER;
  4037. PCTSTR node = NULL;
  4038. PCTSTR leaf = NULL;
  4039. PTSTR nativeName = NULL;
  4040. PTSTR nativeNamePtr;
  4041. PTSTR beginSegPtr;
  4042. PTSTR endSegPtr;
  4043. PCTSTR shortSeg = NULL;
  4044. TCHAR savedChar;
  4045. WIN32_FIND_DATA findData;
  4046. UINT savedEnd;
  4047. UINT beginBuffIdx;
  4048. BOOL fullSpec;
  4049. BOOL result = FALSE;
  4050. KEYHANDLE kh1, kh2;
  4051. BOOL goOn;
  4052. if (IsmCreateObjectStringsFromHandle (EncodedObjectName, &node, &leaf)) {
  4053. MYASSERT (node);
  4054. if (leaf) {
  4055. nativeName = DuplicatePathString (S_SHORTLONG_TREE, SizeOfString (node) + SizeOfString (leaf));
  4056. } else {
  4057. nativeName = DuplicatePathString (S_SHORTLONG_TREE, SizeOfString (node));
  4058. }
  4059. nativeNamePtr = AppendWack (nativeName);
  4060. StringCopy (nativeNamePtr, node);
  4061. if (leaf) {
  4062. StringCopy (AppendWack (nativeNamePtr), leaf);
  4063. }
  4064. GbAppendString (&growBuf, S_SHORTLONG_TREE);
  4065. GbAppendString (&growBuf, TEXT("\\"));
  4066. beginBuffIdx = growBuf.End - sizeof (TCHAR);
  4067. beginSegPtr = GetFirstSeg (nativeNamePtr);
  4068. if (beginSegPtr) {
  4069. beginSegPtr = _tcsinc (beginSegPtr);
  4070. GbAppendStringAB (&growBuf, nativeNamePtr, beginSegPtr);
  4071. while (beginSegPtr) {
  4072. fullSpec = FALSE;
  4073. endSegPtr = _tcschr (beginSegPtr, TEXT('\\'));
  4074. if (!endSegPtr) {
  4075. endSegPtr = GetEndOfString (beginSegPtr);
  4076. MYASSERT (endSegPtr);
  4077. fullSpec = TRUE;
  4078. }
  4079. savedChar = *endSegPtr;
  4080. *endSegPtr = 0;
  4081. goOn = FALSE;
  4082. goOn = pGetStoredShortName ((PCTSTR) growBuf.Buf, beginSegPtr, &findData);
  4083. if (!goOn && fullSpec) {
  4084. goOn = pGetFullSpecShortName (ObjectTypeId, EncodedObjectName, &findData);
  4085. }
  4086. if (!goOn) {
  4087. goOn = pGetShortName (beginSegPtr, &findData);
  4088. }
  4089. if (goOn) {
  4090. // Special case for when findData.cFileName = "."
  4091. if (StringIMatch (findData.cFileName, TEXT("."))) {
  4092. StringCopyTcharCount (
  4093. findData.cFileName,
  4094. beginSegPtr,
  4095. ARRAYSIZE(findData.cFileName)
  4096. );
  4097. }
  4098. if (*findData.cAlternateFileName) {
  4099. // there is a difference between short and long file name
  4100. // for the last segment
  4101. savedEnd = growBuf.End - sizeof (TCHAR);
  4102. GbAppendString (&growBuf, findData.cAlternateFileName);
  4103. kh1 = MemDbAddKey (nativeName);
  4104. if (kh1) {
  4105. kh2 = MemDbAddKey ((PCTSTR) growBuf.Buf);
  4106. if (kh2) {
  4107. goOn = MemDbSetValueByHandle (kh1, FILENAME_LONG);
  4108. goOn = goOn && MemDbSetValueByHandle (kh2, FILENAME_SHORT);
  4109. goOn = goOn && MemDbAddDoubleLinkageByKeyHandle (kh1, kh2, 0);
  4110. } else {
  4111. goOn = FALSE;
  4112. }
  4113. if (!goOn) {
  4114. MemDbDeleteKey (nativeName);
  4115. }
  4116. }
  4117. growBuf.End = savedEnd;
  4118. } else {
  4119. // there is no difference between short and long file name
  4120. // for the last segment. Let's add it to the tree though,
  4121. // as a circular reference
  4122. savedEnd = growBuf.End - sizeof (TCHAR);
  4123. GbAppendString (&growBuf, findData.cFileName);
  4124. kh1 = MemDbAddKey (nativeName);
  4125. if (kh1) {
  4126. if (StringIMatch (nativeName, (PCTSTR) growBuf.Buf)) {
  4127. // this is a circular reference
  4128. kh2 = kh1;
  4129. } else {
  4130. kh2 = MemDbAddKey ((PCTSTR) growBuf.Buf);
  4131. }
  4132. if (kh2) {
  4133. goOn = MemDbSetValueByHandle (kh1, FILENAME_LONG);
  4134. if (kh2 != kh1) {
  4135. goOn = goOn && MemDbSetValueByHandle (kh2, FILENAME_SHORT);
  4136. }
  4137. goOn = goOn && MemDbAddDoubleLinkageByKeyHandle (kh1, kh2, 0);
  4138. } else {
  4139. goOn = FALSE;
  4140. }
  4141. if (!goOn) {
  4142. MemDbDeleteKey (nativeName);
  4143. }
  4144. }
  4145. growBuf.End = savedEnd;
  4146. }
  4147. GbAppendString (&growBuf, findData.cFileName);
  4148. } else {
  4149. GbAppendStringAB (&growBuf, beginSegPtr, endSegPtr);
  4150. }
  4151. *endSegPtr = savedChar;
  4152. if (savedChar) {
  4153. beginSegPtr = _tcsinc (endSegPtr);
  4154. GbAppendStringAB (&growBuf, endSegPtr, beginSegPtr);
  4155. } else {
  4156. beginSegPtr = NULL;
  4157. }
  4158. }
  4159. }
  4160. FreePathString (nativeName);
  4161. if (node) {
  4162. IsmDestroyObjectString (node);
  4163. }
  4164. if (leaf) {
  4165. IsmDestroyObjectString (leaf);
  4166. }
  4167. }
  4168. GbFree (&growBuf);
  4169. return result;
  4170. }
  4171. MIG_OBJECTID
  4172. IsmGetObjectIdFromName (
  4173. IN MIG_OBJECTTYPEID ObjectTypeId,
  4174. IN MIG_OBJECTSTRINGHANDLE EncodedObjectName,
  4175. IN BOOL MustExist
  4176. )
  4177. {
  4178. MIG_OBJECTID result = 0;
  4179. KEYHANDLE objectId;
  4180. PCTSTR decoratedPath;
  4181. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  4182. __try {
  4183. decoratedPath = GetDecoratedObjectPathFromName (ObjectTypeId, EncodedObjectName, FALSE);
  4184. if (!decoratedPath) {
  4185. __leave;
  4186. }
  4187. if (MustExist) {
  4188. objectId = MemDbGetHandleFromKey (decoratedPath);
  4189. } else {
  4190. objectId = MemDbSetKey (decoratedPath);
  4191. // if GetLastError = ERROR_ALREADY_EXISTS we don't have to do
  4192. // anything, the object is already in our database
  4193. if (GetLastError () == ERROR_SUCCESS) {
  4194. if (MemDbSetValueByHandle (objectId, ObjectTypeId)) {
  4195. g_TotalObjects.TotalObjects ++;
  4196. if ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE) {
  4197. g_SourceObjects.TotalObjects ++;
  4198. } else {
  4199. g_DestinationObjects.TotalObjects ++;
  4200. }
  4201. IncrementTotalObjectCount (ObjectTypeId);
  4202. if (ObjectTypeId == (MIG_FILE_TYPE|PLATFORM_SOURCE)) {
  4203. //
  4204. // fire up the short-long algorithm
  4205. //
  4206. if (g_IsmCurrentPlatform == PLATFORM_SOURCE) {
  4207. pAddShortLongInfo (EncodedObjectName);
  4208. } else {
  4209. pAddShortLongInfoOnDest (ObjectTypeId, EncodedObjectName);
  4210. }
  4211. }
  4212. } else {
  4213. objectId = 0;
  4214. }
  4215. }
  4216. if (!objectId) {
  4217. EngineError ();
  4218. __leave;
  4219. }
  4220. }
  4221. result = (MIG_OBJECTID) objectId;
  4222. }
  4223. __finally {
  4224. FreePathString (decoratedPath);
  4225. INVALID_POINTER (decoratedPath);
  4226. }
  4227. return result;
  4228. }
  4229. MIG_OBJECTID
  4230. GetObjectIdForModification (
  4231. IN MIG_OBJECTTYPEID ObjectTypeId,
  4232. IN MIG_OBJECTSTRINGHANDLE EncodedObjectName
  4233. )
  4234. {
  4235. if (!CanObjectTypeBeModified (ObjectTypeId)) {
  4236. return 0;
  4237. }
  4238. return IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, FALSE);
  4239. }
  4240. BOOL
  4241. pEnumFirstVirtualObject (
  4242. OUT PMIG_OBJECT_ENUM ObjectEnum,
  4243. IN MIG_OBJECTTYPEID ObjectTypeId,
  4244. IN MIG_OBJECTSTRINGHANDLE ObjectPattern
  4245. )
  4246. {
  4247. PCTSTR decoratedPath = NULL;
  4248. BOOL result = FALSE;
  4249. POBJECTENUM_HANDLE handle;
  4250. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  4251. ZeroMemory (ObjectEnum, sizeof (MIG_OBJECT_ENUM));
  4252. ObjectEnum->ObjectTypeId = ObjectTypeId;
  4253. ObjectEnum->Handle = MemAllocZeroed (sizeof (OBJECTENUM_HANDLE));
  4254. handle = ObjectEnum->Handle;
  4255. __try {
  4256. if (!ObsHasNode (ObjectPattern)) {
  4257. DEBUGMSG ((DBG_ERROR, "Pattern %s has nul node", ObjectPattern));
  4258. __leave;
  4259. }
  4260. decoratedPath = GetDecoratedObjectPathFromName (ObjectTypeId, ObjectPattern, TRUE);
  4261. if (!decoratedPath) {
  4262. __leave;
  4263. }
  4264. if (DbEnumFirst (
  4265. ObjectTypeId,
  4266. &handle->MemDbEnum,
  4267. decoratedPath,
  4268. &handle->ParsedPatterns
  4269. )) {
  4270. ObjectEnum->ObjectName = handle->MemDbEnum.KeyName;
  4271. ObjectEnum->ObjectId = (MIG_OBJECTID) handle->MemDbEnum.KeyHandle;
  4272. result = TRUE;
  4273. }
  4274. }
  4275. __finally {
  4276. FreePathString (decoratedPath);
  4277. INVALID_POINTER (decoratedPath);
  4278. if (!result) {
  4279. pAbortVirtualObjectEnum (ObjectEnum);
  4280. }
  4281. }
  4282. return result;
  4283. }
  4284. BOOL
  4285. pEnumNextVirtualObject (
  4286. IN OUT PMIG_OBJECT_ENUM ObjectEnum
  4287. )
  4288. {
  4289. BOOL result = FALSE;
  4290. POBJECTENUM_HANDLE handle;
  4291. handle = ObjectEnum->Handle;
  4292. if (MemDbEnumNext (&handle->MemDbEnum)) {
  4293. ObjectEnum->ObjectName = handle->MemDbEnum.KeyName;
  4294. ObjectEnum->ObjectId = (MIG_OBJECTID) handle->MemDbEnum.KeyHandle;
  4295. result = TRUE;
  4296. } else {
  4297. pAbortVirtualObjectEnum (ObjectEnum);
  4298. }
  4299. return result;
  4300. }
  4301. VOID
  4302. pAbortVirtualObjectEnum (
  4303. IN PMIG_OBJECT_ENUM ObjectEnum
  4304. )
  4305. {
  4306. POBJECTENUM_HANDLE handle;
  4307. handle = ObjectEnum->Handle;
  4308. if (handle) {
  4309. DbEnumFreeStruct (&handle->ParsedPatterns);
  4310. MemDbAbortEnum (&handle->MemDbEnum);
  4311. FreeAlloc (handle);
  4312. INVALID_POINTER (ObjectEnum->Handle);
  4313. }
  4314. ZeroMemory (ObjectEnum, sizeof (MIG_OBJECT_ENUM));
  4315. }
  4316. BOOL
  4317. IsmEnumFirstSourceObjectEx (
  4318. OUT PMIG_OBJECT_ENUM ObjectEnum,
  4319. IN MIG_OBJECTTYPEID ObjectTypeId,
  4320. IN MIG_OBJECTSTRINGHANDLE ObjectPattern,
  4321. IN BOOL EnumerateVirtualObjects
  4322. )
  4323. {
  4324. //
  4325. // First fix ObjectTypeId
  4326. //
  4327. ObjectTypeId &= (~PLATFORM_MASK);
  4328. ObjectTypeId |= PLATFORM_SOURCE;
  4329. //
  4330. // If this is the destination or we are forced, then we enumerate virtual objects
  4331. //
  4332. if (EnumerateVirtualObjects ||
  4333. (g_IsmModulePlatformContext == PLATFORM_CURRENT && g_IsmCurrentPlatform == PLATFORM_DESTINATION) ||
  4334. g_IsmModulePlatformContext == PLATFORM_DESTINATION
  4335. ) {
  4336. return pEnumFirstVirtualObject (ObjectEnum, ObjectTypeId, ObjectPattern);
  4337. }
  4338. return EnumFirstPhysicalObject (ObjectEnum, ObjectTypeId, ObjectPattern);
  4339. }
  4340. BOOL
  4341. IsmEnumNextObject (
  4342. IN OUT PMIG_OBJECT_ENUM ObjectEnum
  4343. )
  4344. {
  4345. //
  4346. // Verify enumeration has not completed
  4347. //
  4348. if (!ObjectEnum->Handle) {
  4349. return FALSE;
  4350. }
  4351. //
  4352. // If ObjectId is specified, we are enumerating the ISM
  4353. //
  4354. if (ObjectEnum->ObjectId) {
  4355. return pEnumNextVirtualObject (ObjectEnum);
  4356. }
  4357. //
  4358. // Otherwise we are enumerating physical objects
  4359. //
  4360. return EnumNextPhysicalObject (ObjectEnum);
  4361. }
  4362. VOID
  4363. IsmAbortObjectEnum (
  4364. IN PMIG_OBJECT_ENUM ObjectEnum
  4365. )
  4366. {
  4367. //
  4368. // Verify enumeration has not completed
  4369. //
  4370. if (!ObjectEnum->Handle) {
  4371. return;
  4372. }
  4373. //
  4374. // If ObjectId is specified, we are enumerating the ISM, otherwise we are
  4375. // enumerating physical objects
  4376. //
  4377. if (ObjectEnum->ObjectId) {
  4378. pAbortVirtualObjectEnum (ObjectEnum);
  4379. } else {
  4380. AbortPhysicalObjectEnum (ObjectEnum);
  4381. }
  4382. return;
  4383. }
  4384. BOOL
  4385. IsmEnumFirstDestinationObjectEx (
  4386. OUT PMIG_OBJECT_ENUM ObjectEnum,
  4387. IN MIG_OBJECTTYPEID ObjectTypeId,
  4388. IN MIG_OBJECTSTRINGHANDLE ObjectPattern,
  4389. IN BOOL EnumerateVirtualObjects
  4390. )
  4391. {
  4392. //
  4393. // First fix ObjectTypeId
  4394. //
  4395. ObjectTypeId &= (~PLATFORM_MASK);
  4396. ObjectTypeId |= PLATFORM_SOURCE;
  4397. //
  4398. // If this is the source, it's illegal
  4399. //
  4400. if (g_IsmCurrentPlatform == PLATFORM_SOURCE) {
  4401. return FALSE;
  4402. }
  4403. if (EnumerateVirtualObjects) {
  4404. return pEnumFirstVirtualObject (ObjectEnum, ObjectTypeId, ObjectPattern);
  4405. }
  4406. return EnumFirstPhysicalObject (ObjectEnum, ObjectTypeId, ObjectPattern);
  4407. }
  4408. BOOL
  4409. IsObjectLocked (
  4410. IN MIG_OBJECTID ObjectId
  4411. )
  4412. {
  4413. UINT flags;
  4414. if (!MemDbGetFlagsByHandle ((KEYHANDLE) ObjectId, &flags)) {
  4415. return FALSE;
  4416. }
  4417. return flags & OBJECT_LOCKED;
  4418. }
  4419. BOOL
  4420. IsHandleLocked (
  4421. IN MIG_OBJECTID ObjectId,
  4422. IN KEYHANDLE Handle
  4423. )
  4424. {
  4425. TCHAR lockKey[256];
  4426. wsprintf (lockKey, S_LOCK_KEY, ObjectId);
  4427. return MemDbTestSingleLinkageValue (lockKey, 0, Handle);
  4428. }
  4429. BOOL
  4430. TestLock (
  4431. IN MIG_OBJECTID ObjectId,
  4432. IN KEYHANDLE Handle
  4433. )
  4434. {
  4435. return IsObjectLocked (ObjectId) || IsHandleLocked (ObjectId, Handle);
  4436. }
  4437. VOID
  4438. pLockHandle (
  4439. IN MIG_OBJECTID ObjectId,
  4440. IN KEYHANDLE Handle
  4441. )
  4442. {
  4443. TCHAR lockKey[256];
  4444. wsprintf (lockKey, S_LOCK_KEY, ObjectId);
  4445. if (!MemDbAddSingleLinkageValue (lockKey, 0, Handle, FALSE)) {
  4446. EngineError ();
  4447. }
  4448. }
  4449. BOOL
  4450. pLockGroup (
  4451. IN KEYHANDLE ItemId,
  4452. IN BOOL FirstPass,
  4453. IN ULONG_PTR Arg
  4454. )
  4455. {
  4456. pLockHandle ((MIG_OBJECTID) Arg, (KEYHANDLE) ItemId);
  4457. return TRUE;
  4458. }
  4459. VOID
  4460. LockHandle (
  4461. IN MIG_OBJECTID ObjectId,
  4462. IN KEYHANDLE Handle
  4463. )
  4464. {
  4465. RECURSERETURN rc;
  4466. rc = RecurseForGroupItems (
  4467. Handle,
  4468. pLockGroup,
  4469. (ULONG_PTR) ObjectId,
  4470. TRUE,
  4471. FALSE
  4472. );
  4473. if (rc == RECURSE_FAIL || rc == RECURSE_SUCCESS) {
  4474. return;
  4475. }
  4476. MYASSERT (rc == RECURSE_NOT_NEEDED);
  4477. pLockHandle (ObjectId, Handle);
  4478. }
  4479. VOID
  4480. IsmLockObjectId (
  4481. IN MIG_OBJECTID ObjectId
  4482. )
  4483. {
  4484. if (!MemDbSetFlagsByHandle (ObjectId, OBJECT_LOCKED, 0)) {
  4485. EngineError ();
  4486. }
  4487. }
  4488. VOID
  4489. IsmLockObject (
  4490. IN MIG_OBJECTTYPEID ObjectTypeId,
  4491. IN MIG_OBJECTSTRINGHANDLE EncodedObjectName
  4492. )
  4493. {
  4494. MIG_OBJECTID objectId;
  4495. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  4496. objectId = GetObjectIdForModification (ObjectTypeId, EncodedObjectName);
  4497. if (objectId) {
  4498. IsmLockObjectId (objectId);
  4499. }
  4500. }
  4501. PCTSTR
  4502. GetObjectNameForDebugMsg (
  4503. IN MIG_OBJECTID ObjectId
  4504. )
  4505. {
  4506. static TCHAR buffer[256];
  4507. PCTSTR name;
  4508. name = MemDbGetKeyFromHandle ((KEYHANDLE) ObjectId, 1);
  4509. if (name) {
  4510. StackStringCopy (buffer, name);
  4511. MemDbReleaseMemory (name);
  4512. } else {
  4513. StringCopy (buffer, TEXT("<invalid object>"));
  4514. }
  4515. return name;
  4516. }
  4517. PCTSTR
  4518. pIsValidCName (
  4519. IN PCTSTR Name
  4520. )
  4521. {
  4522. UINT u;
  4523. if (!Name) {
  4524. return NULL;
  4525. }
  4526. if (!__iscsymf (_tcsnextc (Name))) {
  4527. return NULL;
  4528. }
  4529. Name = _tcsinc (Name);
  4530. u = 1;
  4531. while (*Name) {
  4532. if (!__iscsym (_tcsnextc (Name))) {
  4533. return Name;
  4534. }
  4535. Name = _tcsinc (Name);
  4536. u++;
  4537. }
  4538. if (u > 64) {
  4539. return NULL;
  4540. }
  4541. return Name;
  4542. }
  4543. BOOL
  4544. IsValidCName (
  4545. IN PCTSTR Name
  4546. )
  4547. {
  4548. PCTSTR p;
  4549. BOOL result = FALSE;
  4550. p = pIsValidCName (Name);
  4551. if (p && (!*p)) {
  4552. result = TRUE;
  4553. } else {
  4554. SetLastError (ERROR_INVALID_NAME);
  4555. }
  4556. return TRUE;
  4557. }
  4558. BOOL
  4559. IsValidCNameWithDots (
  4560. IN PCTSTR Name
  4561. )
  4562. {
  4563. PCTSTR p;
  4564. p = pIsValidCName (Name);
  4565. while (p && _tcsnextc (p) == TEXT('.')) {
  4566. p = _tcsinc (p);
  4567. p = pIsValidCName (p);
  4568. }
  4569. return p && (*p == 0);
  4570. }
  4571. BOOL
  4572. MarkGroupIds (
  4573. IN PCTSTR MemDbKey
  4574. )
  4575. {
  4576. UINT flags;
  4577. PTSTR keyCopy;
  4578. PTSTR p;
  4579. PTSTR start;
  4580. BOOL b = FALSE;
  4581. keyCopy = DuplicateText (MemDbKey);
  4582. __try {
  4583. p = (PTSTR) FindLastWack (keyCopy);
  4584. if (!p) {
  4585. __leave;
  4586. }
  4587. start = _tcschr (p + 1, TEXT('.'));
  4588. //
  4589. // Make sure all groups in the string are legal
  4590. //
  4591. p = start;
  4592. while (p) {
  4593. *p = 0;
  4594. if (MemDbGetFlags (keyCopy, &flags)) {
  4595. if (flags & ITEM_ID) {
  4596. DEBUGMSG ((DBG_ERROR, "Group already used as item. Key=%s", keyCopy));
  4597. __leave;
  4598. }
  4599. }
  4600. *p = TEXT('.');
  4601. p = _tcschr (p + 1, TEXT('.'));
  4602. }
  4603. if (MemDbGetFlags (keyCopy, &flags)) {
  4604. if (flags & GROUP_ID) {
  4605. DEBUGMSG ((DBG_ERROR, "Item already used as group. Key=%s", keyCopy));
  4606. __leave;
  4607. }
  4608. }
  4609. //
  4610. // Mark all groups
  4611. //
  4612. p = start;
  4613. while (p) {
  4614. *p = 0;
  4615. if (!MemDbSetFlags (keyCopy, GROUP_ID, 0)) {
  4616. EngineError ();
  4617. __leave;
  4618. }
  4619. *p = TEXT('.');
  4620. p = _tcschr (p + 1, TEXT('.'));
  4621. }
  4622. //
  4623. // Mark the item
  4624. //
  4625. b = MemDbSetFlags (keyCopy, ITEM_ID, 0);
  4626. if (!b) {
  4627. EngineError ();
  4628. }
  4629. }
  4630. __finally {
  4631. FreeText (keyCopy);
  4632. }
  4633. return b;
  4634. }
  4635. BOOL
  4636. IsGroupId (
  4637. IN KEYHANDLE Id
  4638. )
  4639. {
  4640. UINT flags;
  4641. if (!MemDbGetFlagsByHandle (Id, &flags)) {
  4642. return FALSE;
  4643. }
  4644. return flags & GROUP_ID;
  4645. }
  4646. BOOL
  4647. IsItemId (
  4648. IN KEYHANDLE Id
  4649. )
  4650. {
  4651. UINT flags;
  4652. if (!MemDbGetFlagsByHandle (Id, &flags)) {
  4653. return FALSE;
  4654. }
  4655. return flags & ITEM_ID;
  4656. }
  4657. KEYHANDLE
  4658. GetGroupOfId (
  4659. IN KEYHANDLE GroupOrItemId
  4660. )
  4661. {
  4662. PTSTR key;
  4663. PTSTR p;
  4664. PTSTR lastDot;
  4665. KEYHANDLE result = 0;
  4666. key = (PTSTR) MemDbGetKeyFromHandle (GroupOrItemId, 0);
  4667. if (!key) {
  4668. return 0;
  4669. }
  4670. __try {
  4671. p = (PTSTR) FindLastWack (key);
  4672. if (!p) {
  4673. __leave;
  4674. }
  4675. lastDot = NULL;
  4676. do {
  4677. p = _tcschr (p + 1, TEXT('.'));
  4678. if (p) {
  4679. lastDot = p;
  4680. }
  4681. } while (p);
  4682. if (!lastDot) {
  4683. __leave;
  4684. }
  4685. *lastDot = 0;
  4686. result = MemDbGetHandleFromKey (key);
  4687. MYASSERT (!result || IsGroupId (result));
  4688. }
  4689. __finally {
  4690. MemDbReleaseMemory (key);
  4691. }
  4692. return result;
  4693. }
  4694. BOOL
  4695. pGroupRegistrationWorker (
  4696. IN OUT PGROUPREGISTRATION_ENUM EnumPtr
  4697. )
  4698. {
  4699. EnumPtr->GroupOrItemId = EnumPtr->EnumStruct.KeyHandle;
  4700. MYASSERT (EnumPtr->EnumStruct.Flags & (GROUP_ID|ITEM_ID));
  4701. EnumPtr->ItemId = (EnumPtr->EnumStruct.Flags & ITEM_ID) != 0;
  4702. return TRUE;
  4703. }
  4704. BOOL
  4705. EnumFirstGroupRegistration (
  4706. OUT PGROUPREGISTRATION_ENUM EnumPtr,
  4707. IN KEYHANDLE GroupId
  4708. )
  4709. {
  4710. BOOL b;
  4711. PCTSTR key;
  4712. PCTSTR pattern;
  4713. if (!IsGroupId (GroupId)) {
  4714. DEBUGMSG ((DBG_ERROR, "EnumFirstGroupRegistration: GroupId is invalid"));
  4715. return FALSE;
  4716. }
  4717. key = MemDbGetKeyFromHandle (GroupId, 0);
  4718. if (!key) {
  4719. return 0;
  4720. }
  4721. pattern = JoinText (key, TEXT(".*"));
  4722. MemDbReleaseMemory (key);
  4723. INVALID_POINTER (key);
  4724. b = MemDbEnumFirst (
  4725. &EnumPtr->EnumStruct,
  4726. pattern,
  4727. ENUMFLAG_NORMAL,
  4728. ENUMLEVEL_ALLLEVELS,
  4729. ENUMLEVEL_ALLLEVELS
  4730. );
  4731. FreeText (pattern);
  4732. INVALID_POINTER (pattern);
  4733. if (!b) {
  4734. return FALSE;
  4735. }
  4736. return pGroupRegistrationWorker (EnumPtr);
  4737. }
  4738. BOOL
  4739. EnumNextGroupRegistration (
  4740. IN OUT PGROUPREGISTRATION_ENUM EnumPtr
  4741. )
  4742. {
  4743. if (!MemDbEnumNext (&EnumPtr->EnumStruct)) {
  4744. return FALSE;
  4745. }
  4746. return pGroupRegistrationWorker (EnumPtr);
  4747. }
  4748. VOID
  4749. AbortGroupRegistrationEnum (
  4750. IN PGROUPREGISTRATION_ENUM EnumPtr
  4751. )
  4752. {
  4753. MemDbAbortEnum (&EnumPtr->EnumStruct);
  4754. ZeroMemory (EnumPtr, sizeof (GROUPREGISTRATION_ENUM));
  4755. }
  4756. RECURSERETURN
  4757. RecurseForGroupItems (
  4758. IN KEYHANDLE GroupId,
  4759. IN GROUPITEM_CALLBACK Callback,
  4760. IN ULONG_PTR Arg,
  4761. IN BOOL ExecuteOnly,
  4762. IN BOOL LogicalOrOnResults
  4763. )
  4764. {
  4765. PCTSTR groupKey = NULL;
  4766. PCTSTR enumKey = NULL;
  4767. MEMDB_ENUM e;
  4768. UINT pass;
  4769. RECURSERETURN result = RECURSE_FAIL;
  4770. BOOL b;
  4771. BOOL oneSuccess = FALSE;
  4772. if (!IsGroupId (GroupId)) {
  4773. return RECURSE_NOT_NEEDED;
  4774. }
  4775. groupKey = MemDbGetKeyFromHandle (GroupId, 0);
  4776. enumKey = JoinText (groupKey, TEXT(".*"));
  4777. MemDbReleaseMemory (groupKey);
  4778. __try {
  4779. for (pass = ExecuteOnly ? 1 : 0 ; pass < 2 ; pass++) {
  4780. //
  4781. // Enumerate all attributes (skip attribute subgroups)
  4782. //
  4783. if (MemDbEnumFirst (
  4784. &e,
  4785. enumKey,
  4786. ENUMFLAG_NORMAL,
  4787. ENUMLEVEL_ALLLEVELS,
  4788. ENUMLEVEL_ALLLEVELS
  4789. )) {
  4790. do {
  4791. if (IsItemId (e.KeyHandle)) {
  4792. //
  4793. // Pass 0 is for query, pass 1 is for execute
  4794. //
  4795. b = Callback (e.KeyHandle, pass == 0, Arg);
  4796. if (LogicalOrOnResults) {
  4797. oneSuccess |= b;
  4798. } else if (!b) {
  4799. MemDbAbortEnum (&e);
  4800. __leave;
  4801. }
  4802. }
  4803. } while (MemDbEnumNext (&e));
  4804. MemDbAbortEnum (&e);
  4805. }
  4806. }
  4807. if (LogicalOrOnResults) {
  4808. if (!oneSuccess) {
  4809. __leave;
  4810. }
  4811. }
  4812. result = RECURSE_SUCCESS;
  4813. }
  4814. __finally {
  4815. FreeText (enumKey);
  4816. INVALID_POINTER (enumKey);
  4817. }
  4818. return result;
  4819. }
  4820. BOOL
  4821. DbEnumFillStruct (
  4822. IN MIG_OBJECTTYPEID ObjectTypeId,
  4823. IN PCTSTR Pattern,
  4824. OUT PDBENUM_ARGS Args
  4825. )
  4826. {
  4827. PWSTR p, q;
  4828. PWSTR plainPatternEnd = NULL;
  4829. PWSTR patternCopy;
  4830. PCWSTR node;
  4831. PCWSTR leaf;
  4832. BOOL freeNode = TRUE;
  4833. Args->ObjectTypeId = ObjectTypeId;
  4834. //
  4835. // Split the pattern into a node and leaf pattern
  4836. //
  4837. patternCopy = (PWSTR) CreateUnicode (Pattern);
  4838. ObsSplitObjectStringW (patternCopy, &node, &leaf);
  4839. if (!node) {
  4840. node = L"*";
  4841. freeNode = FALSE;
  4842. }
  4843. DestroyUnicode (patternCopy);
  4844. INVALID_POINTER (patternCopy);
  4845. //
  4846. // Find the first level in node that has a pattern. Then
  4847. // truncate the node and parse it as a "plain" pattern.
  4848. // This makes sure a node pattern such as c:\foo\* will
  4849. // match c:\foo itself.
  4850. //
  4851. patternCopy = DuplicateTextW (node);
  4852. p = patternCopy;
  4853. plainPatternEnd = patternCopy;
  4854. while (p && *p) {
  4855. MYASSERT (*plainPatternEnd);
  4856. q = (PWSTR) ObsFindNonEncodedCharInEncodedStringW (p, L'\\');
  4857. if (!q) {
  4858. p = GetEndOfStringW (p);
  4859. } else {
  4860. p = q;
  4861. *p = 0;
  4862. }
  4863. if (ObsFindNonEncodedCharInEncodedStringW (plainPatternEnd, L'*') ||
  4864. ObsFindNonEncodedCharInEncodedStringW (plainPatternEnd, L'?')
  4865. ) {
  4866. *plainPatternEnd = 0;
  4867. break;
  4868. }
  4869. plainPatternEnd = p;
  4870. if (q) {
  4871. *p = L'\\';
  4872. p++;
  4873. }
  4874. }
  4875. if (plainPatternEnd && *plainPatternEnd == 0 && *patternCopy) {
  4876. Args->PlainNodeParsedPattern = CreateParsedPatternW (patternCopy);
  4877. } else {
  4878. Args->PlainNodeParsedPattern = NULL;
  4879. }
  4880. //
  4881. // Fill the rest of the struct, clean up and exit
  4882. //
  4883. Args->NodeParsedPattern = CreateParsedPatternW (node);
  4884. if (leaf) {
  4885. Args->LeafParsedPattern = CreateParsedPatternW (leaf);
  4886. } else {
  4887. Args->LeafParsedPattern = NULL;
  4888. }
  4889. if (freeNode) {
  4890. ObsFreeW (node);
  4891. INVALID_POINTER (node);
  4892. }
  4893. ObsFreeW (leaf);
  4894. INVALID_POINTER (leaf);
  4895. FreeTextW (patternCopy);
  4896. INVALID_POINTER (patternCopy);
  4897. return TRUE;
  4898. }
  4899. VOID
  4900. DbEnumFreeStruct (
  4901. IN PDBENUM_ARGS Args
  4902. )
  4903. {
  4904. if (Args->PlainNodeParsedPattern) {
  4905. DestroyParsedPatternW (Args->PlainNodeParsedPattern);
  4906. INVALID_POINTER (Args->PlainNodeParsedPattern);
  4907. }
  4908. if (Args->NodeParsedPattern) {
  4909. DestroyParsedPatternW (Args->NodeParsedPattern);
  4910. INVALID_POINTER (Args->NodeParsedPattern);
  4911. }
  4912. if (Args->LeafParsedPattern) {
  4913. DestroyParsedPatternW (Args->LeafParsedPattern);
  4914. INVALID_POINTER (Args->LeafParsedPattern);
  4915. }
  4916. ZeroMemory (Args, sizeof (DBENUM_ARGS));
  4917. }
  4918. BOOL
  4919. DbEnumFind (
  4920. IN PCWSTR KeySegment
  4921. )
  4922. {
  4923. //
  4924. // Does KeySegment have a pattern?
  4925. //
  4926. if (ObsFindNonEncodedCharInEncodedStringW (KeySegment, L'*') ||
  4927. ObsFindNonEncodedCharInEncodedStringW (KeySegment, L'?')
  4928. ) {
  4929. return TRUE;
  4930. }
  4931. return FALSE;
  4932. }
  4933. BOOL
  4934. DbEnumMatch (
  4935. IN PCVOID InboundArgs,
  4936. IN PCWSTR CurrentKey
  4937. )
  4938. {
  4939. PDBENUM_ARGS args;
  4940. PCWSTR node;
  4941. PCWSTR leaf;
  4942. PCWSTR newLeaf;
  4943. BOOL result = FALSE;
  4944. WCHAR dummy[] = L"";
  4945. args = (PDBENUM_ARGS) InboundArgs;
  4946. CurrentKey = wcschr (CurrentKey, L'\\');
  4947. MYASSERT (CurrentKey);
  4948. if (!CurrentKey) {
  4949. return FALSE;
  4950. }
  4951. CurrentKey++;
  4952. //
  4953. // Split current key into node and leaf
  4954. //
  4955. ObsSplitObjectStringW (CurrentKey, &node, &leaf);
  4956. MYASSERT (args->NodeParsedPattern);
  4957. if (node) {
  4958. //
  4959. // Test node against parsed pattern
  4960. //
  4961. if (args->NodeParsedPattern) {
  4962. result = TestParsedPatternW (args->NodeParsedPattern, node);
  4963. if (!result && args->PlainNodeParsedPattern) {
  4964. result = TestParsedPatternW (args->PlainNodeParsedPattern, node);
  4965. }
  4966. if (result) {
  4967. if (leaf) {
  4968. result = FALSE;
  4969. if (args->LeafParsedPattern) {
  4970. result = TestParsedPatternW (args->LeafParsedPattern, leaf);
  4971. if (!result &&
  4972. ((args->ObjectTypeId & (~PLATFORM_MASK)) == MIG_FILE_TYPE) &&
  4973. (wcschr (leaf, L'.') == NULL)
  4974. ) {
  4975. newLeaf = JoinTextW (leaf, L".");
  4976. result = TestParsedPatternW (args->LeafParsedPattern, newLeaf);
  4977. FreeTextW (newLeaf);
  4978. }
  4979. }
  4980. } else {
  4981. if (args->LeafParsedPattern &&
  4982. args->PlainNodeParsedPattern &&
  4983. TestParsedPatternW (args->PlainNodeParsedPattern, node)
  4984. ) {
  4985. result = FALSE;
  4986. }
  4987. }
  4988. }
  4989. }
  4990. } else {
  4991. //
  4992. // Test empty node against parsed pattern
  4993. //
  4994. if (args->NodeParsedPattern) {
  4995. result = TestParsedPatternW (args->NodeParsedPattern, dummy);
  4996. if (!result && args->PlainNodeParsedPattern) {
  4997. result = TestParsedPatternW (args->PlainNodeParsedPattern, dummy);
  4998. }
  4999. if (result) {
  5000. if (leaf) {
  5001. result = FALSE;
  5002. if (args->LeafParsedPattern) {
  5003. result = TestParsedPatternW (args->LeafParsedPattern, leaf);
  5004. }
  5005. }
  5006. }
  5007. }
  5008. }
  5009. ObsFreeW (node);
  5010. INVALID_POINTER (node);
  5011. ObsFreeW (leaf);
  5012. INVALID_POINTER (leaf);
  5013. return result;
  5014. }
  5015. BOOL
  5016. DbEnumFirst (
  5017. IN MIG_OBJECTTYPEID ObjectTypeId,
  5018. OUT PMEMDB_ENUM EnumPtr,
  5019. IN PCTSTR PatternString,
  5020. OUT PDBENUM_ARGS ArgsStruct
  5021. )
  5022. {
  5023. MEMDB_PATTERNSTRUCTW callbacks;
  5024. PCTSTR objectPattern;
  5025. objectPattern = _tcschr (PatternString, TEXT('\\'));
  5026. if (!objectPattern) {
  5027. MYASSERT (FALSE);
  5028. return FALSE;
  5029. }
  5030. objectPattern++;
  5031. #ifdef DEBUG
  5032. {
  5033. PCTSTR p;
  5034. //
  5035. // Verify pattern string base is not a pattern. This is
  5036. // required, because we assume the first level will not
  5037. // use enumeration, but will use direct lookup.
  5038. //
  5039. p = _tcschr (PatternString, TEXT('*'));
  5040. MYASSERT (!p || p >= objectPattern);
  5041. p = _tcschr (PatternString, TEXT('?'));
  5042. MYASSERT (!p || p >= objectPattern);
  5043. }
  5044. #endif
  5045. DbEnumFillStruct (ObjectTypeId, objectPattern, ArgsStruct);
  5046. callbacks.PatternFind = DbEnumFind;
  5047. callbacks.PatternMatch = DbEnumMatch;
  5048. callbacks.Data = ArgsStruct;
  5049. return MemDbEnumFirstEx (
  5050. EnumPtr,
  5051. PatternString,
  5052. ENUMFLAG_NORMAL,
  5053. 1,
  5054. ENUMLEVEL_ALLLEVELS,
  5055. &callbacks
  5056. );
  5057. }
  5058. BOOL
  5059. IsmRegisterRestoreCallback (
  5060. IN PMIG_RESTORECALLBACK RestoreCallback
  5061. )
  5062. {
  5063. PRESTORE_STRUCT restoreStruct;
  5064. restoreStruct = (PRESTORE_STRUCT) PmGetMemory (g_IsmPool, sizeof (RESTORE_STRUCT));
  5065. restoreStruct->RestoreCallback = RestoreCallback;
  5066. restoreStruct->Next = g_RestoreCallbacks;
  5067. g_RestoreCallbacks = restoreStruct;
  5068. return TRUE;
  5069. }
  5070. BOOL
  5071. EnumFirstRestoreCallback (
  5072. OUT PMIG_RESTORECALLBACK_ENUM RestoreCallbackEnum
  5073. )
  5074. {
  5075. RestoreCallbackEnum->RestoreStruct = g_RestoreCallbacks;
  5076. if (RestoreCallbackEnum->RestoreStruct) {
  5077. RestoreCallbackEnum->RestoreCallback = RestoreCallbackEnum->RestoreStruct->RestoreCallback;
  5078. return TRUE;
  5079. }
  5080. return FALSE;
  5081. }
  5082. BOOL
  5083. EnumNextRestoreCallback (
  5084. IN OUT PMIG_RESTORECALLBACK_ENUM RestoreCallbackEnum
  5085. )
  5086. {
  5087. if (!RestoreCallbackEnum->RestoreStruct) {
  5088. return FALSE;
  5089. }
  5090. RestoreCallbackEnum->RestoreStruct = RestoreCallbackEnum->RestoreStruct->Next;
  5091. if (RestoreCallbackEnum->RestoreStruct) {
  5092. RestoreCallbackEnum->RestoreCallback = RestoreCallbackEnum->RestoreStruct->RestoreCallback;
  5093. return TRUE;
  5094. }
  5095. return FALSE;
  5096. }
  5097. VOID
  5098. pFreeRestoreCallbacks (
  5099. VOID
  5100. )
  5101. {
  5102. PRESTORE_STRUCT restoreStruct, oldStruct;
  5103. restoreStruct = g_RestoreCallbacks;
  5104. while (restoreStruct) {
  5105. oldStruct = restoreStruct;
  5106. restoreStruct = restoreStruct->Next;
  5107. PmReleaseMemory (g_IsmPool, oldStruct);
  5108. }
  5109. g_RestoreCallbacks = NULL;
  5110. }
  5111. BOOL
  5112. IsmRegisterCompareCallback (
  5113. IN MIG_OBJECTTYPEID ObjectTypeId,
  5114. IN PMIG_COMPARECALLBACK CompareCallback
  5115. )
  5116. {
  5117. PCOMPARE_STRUCT compareStruct;
  5118. compareStruct = (PCOMPARE_STRUCT) PmGetMemory (g_IsmPool, sizeof (COMPARE_STRUCT));
  5119. compareStruct->ObjectTypeId = ObjectTypeId;
  5120. compareStruct->CompareCallback = CompareCallback;
  5121. compareStruct->Next = g_CompareCallbacks;
  5122. g_CompareCallbacks = compareStruct;
  5123. return TRUE;
  5124. }
  5125. BOOL
  5126. EnumFirstCompareCallback (
  5127. OUT PMIG_COMPARECALLBACK_ENUM CompareCallbackEnum
  5128. )
  5129. {
  5130. CompareCallbackEnum->CompareStruct = g_CompareCallbacks;
  5131. if (CompareCallbackEnum->CompareStruct) {
  5132. CompareCallbackEnum->CompareCallback = CompareCallbackEnum->CompareStruct->CompareCallback;
  5133. return TRUE;
  5134. }
  5135. return FALSE;
  5136. }
  5137. BOOL
  5138. EnumNextCompareCallback (
  5139. IN OUT PMIG_COMPARECALLBACK_ENUM CompareCallbackEnum
  5140. )
  5141. {
  5142. if (!CompareCallbackEnum->CompareStruct) {
  5143. return FALSE;
  5144. }
  5145. CompareCallbackEnum->CompareStruct = CompareCallbackEnum->CompareStruct->Next;
  5146. if (CompareCallbackEnum->CompareStruct) {
  5147. CompareCallbackEnum->CompareCallback = CompareCallbackEnum->CompareStruct->CompareCallback;
  5148. return TRUE;
  5149. }
  5150. return FALSE;
  5151. }
  5152. VOID
  5153. pFreeCompareCallbacks (
  5154. VOID
  5155. )
  5156. {
  5157. PCOMPARE_STRUCT compareStruct, oldStruct;
  5158. compareStruct = g_CompareCallbacks;
  5159. while (compareStruct) {
  5160. oldStruct = compareStruct;
  5161. compareStruct = compareStruct->Next;
  5162. PmReleaseMemory (g_IsmPool, oldStruct);
  5163. }
  5164. g_CompareCallbacks = NULL;
  5165. }
  5166. BOOL
  5167. pCompareFileContent (
  5168. IN PCTSTR File1,
  5169. IN PCTSTR File2
  5170. )
  5171. {
  5172. HANDLE fileHandle1 = NULL;
  5173. HANDLE fileHandle2 = NULL;
  5174. #define BUFFER_SIZE 4096
  5175. BYTE buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
  5176. BOOL result = FALSE;
  5177. BOOL res1, res2;
  5178. DWORD read1, read2;
  5179. __try {
  5180. fileHandle1 = BfOpenReadFile (File1);
  5181. fileHandle2 = BfOpenReadFile (File2);
  5182. if (fileHandle1 && fileHandle2) {
  5183. while (TRUE) {
  5184. if (IsmCheckCancel ()) {
  5185. result = FALSE;
  5186. break;
  5187. }
  5188. res1 = ReadFile (fileHandle1, buffer1, BUFFER_SIZE, &read1, NULL);
  5189. res2 = ReadFile (fileHandle2, buffer2, BUFFER_SIZE, &read2, NULL);
  5190. if (!res1 && !res2) {
  5191. result = TRUE;
  5192. break;
  5193. }
  5194. if (res1 && res2) {
  5195. if (read1 != read2) {
  5196. break;
  5197. }
  5198. if (read1 == 0) {
  5199. result = TRUE;
  5200. break;
  5201. }
  5202. if (!TestBuffer (buffer1, buffer2, read1)) {
  5203. break;
  5204. }
  5205. } else {
  5206. break;
  5207. }
  5208. }
  5209. }
  5210. }
  5211. __finally {
  5212. if (fileHandle1) {
  5213. CloseHandle (fileHandle1);
  5214. fileHandle1 = NULL;
  5215. }
  5216. if (fileHandle2) {
  5217. CloseHandle (fileHandle2);
  5218. fileHandle2 = NULL;
  5219. }
  5220. }
  5221. return result;
  5222. }
  5223. BOOL
  5224. pDefaultCompare (
  5225. IN PMIG_CONTENT Object1,
  5226. IN PMIG_CONTENT Object2,
  5227. OUT PBOOL DifferentDetailsOnly OPTIONAL
  5228. )
  5229. {
  5230. UINT index;
  5231. PWIN32_FIND_DATAW find1, find2;
  5232. PUBINT src;
  5233. PUBINT dest;
  5234. UINT remainder;
  5235. UINT count;
  5236. DWORD allAttribs;
  5237. DWORD extendedAttribs;
  5238. BOOL result = TRUE;
  5239. *DifferentDetailsOnly = FALSE;
  5240. if (Object1->ContentInFile != Object2->ContentInFile) {
  5241. result = FALSE;
  5242. } else {
  5243. if (Object1->ContentInFile) {
  5244. if (Object1->FileContent.ContentPath && Object2->FileContent.ContentPath) {
  5245. result = pCompareFileContent (Object1->FileContent.ContentPath, Object2->FileContent.ContentPath);
  5246. } else {
  5247. result = FALSE;
  5248. }
  5249. } else {
  5250. if (Object1->MemoryContent.ContentSize == Object2->MemoryContent.ContentSize) {
  5251. if (Object1->MemoryContent.ContentBytes && Object2->MemoryContent.ContentBytes) {
  5252. result = TestBuffer (
  5253. Object1->MemoryContent.ContentBytes,
  5254. Object2->MemoryContent.ContentBytes,
  5255. Object1->MemoryContent.ContentSize
  5256. );
  5257. } else {
  5258. result = FALSE;
  5259. }
  5260. } else {
  5261. result = FALSE;
  5262. }
  5263. }
  5264. }
  5265. if (result) {
  5266. if (Object1->Details.DetailsSize == Object2->Details.DetailsSize) {
  5267. if (Object1->Details.DetailsData && Object2->Details.DetailsData) {
  5268. result = TestBuffer (
  5269. Object1->Details.DetailsData,
  5270. Object2->Details.DetailsData,
  5271. Object1->Details.DetailsSize
  5272. );
  5273. } else {
  5274. result = FALSE;
  5275. }
  5276. } else {
  5277. result = FALSE;
  5278. }
  5279. if (!result) {
  5280. if (DifferentDetailsOnly) {
  5281. *DifferentDetailsOnly = TRUE;
  5282. }
  5283. }
  5284. }
  5285. return result;
  5286. }
  5287. BOOL
  5288. IsmAreObjectsIdentical (
  5289. IN MIG_OBJECTTYPEID SrcObjectTypeId,
  5290. IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
  5291. IN PMIG_CONTENT SrcContent,
  5292. IN MIG_OBJECTTYPEID DestObjectTypeId,
  5293. IN MIG_OBJECTSTRINGHANDLE DestObjectName,
  5294. IN PMIG_CONTENT DestContent,
  5295. OUT PBOOL DifferentDetailsOnly OPTIONAL
  5296. )
  5297. /*++
  5298. Routine Description:
  5299. IsmAreObjectsIdentical determines if two objects are identical or not.
  5300. If they are of a different type they are automatically different.
  5301. The compare callbacks are all called passing them the information
  5302. that if previous callbacks already gave a resolution. If no
  5303. compare callback is found valid, a default compare (binary compare) will
  5304. be performed.
  5305. Arguments:
  5306. SrcObjectTypeId - Specifies the first object type ID
  5307. SrcObjectName - Specifies the first object name
  5308. SrcContent - Specifies the first object content
  5309. DestObjectTypeId - Specifies the second object type ID
  5310. DestObjectName - Specifies the second object name
  5311. DestContent - Specifies the second object content
  5312. DifferentDetailsOnly - If the objects are different, tells the caller
  5313. that only the details (not the actual content)
  5314. were different
  5315. Return Value:
  5316. TRUE if the objects are identical, FALSE otherwise
  5317. --*/
  5318. {
  5319. BOOL identical = FALSE;
  5320. BOOL detailsOnly = FALSE;
  5321. MIG_COMPARECALLBACK_ENUM compareEnum;
  5322. BOOL alreadyProcessed = FALSE;
  5323. //
  5324. // verify the parameters
  5325. //
  5326. if ((SrcContent == NULL) || (DestContent == NULL)) {
  5327. if (DifferentDetailsOnly) {
  5328. *DifferentDetailsOnly = FALSE;
  5329. }
  5330. return (SrcContent == DestContent);
  5331. }
  5332. //
  5333. // Are object type IDs different?
  5334. //
  5335. SrcObjectTypeId &= (~PLATFORM_MASK);
  5336. DestObjectTypeId &= (~PLATFORM_MASK);
  5337. if (SrcObjectTypeId != DestObjectTypeId) {
  5338. return FALSE;
  5339. }
  5340. //
  5341. // Call compare callbacks
  5342. //
  5343. if (EnumFirstCompareCallback (&compareEnum)) {
  5344. do {
  5345. if (compareEnum.CompareCallback (
  5346. alreadyProcessed,
  5347. SrcObjectTypeId,
  5348. SrcObjectName,
  5349. SrcContent,
  5350. DestObjectTypeId,
  5351. DestObjectName,
  5352. DestContent,
  5353. &identical,
  5354. &detailsOnly
  5355. )) {
  5356. // this callback worked
  5357. alreadyProcessed = TRUE;
  5358. }
  5359. } while (EnumNextCompareCallback (&compareEnum));
  5360. }
  5361. if (!alreadyProcessed) {
  5362. return pDefaultCompare (SrcContent, DestContent, DifferentDetailsOnly);
  5363. }
  5364. if (DifferentDetailsOnly) {
  5365. *DifferentDetailsOnly = detailsOnly;
  5366. }
  5367. return identical;
  5368. }
  5369. ULONG_PTR
  5370. IsmSendMessageToApp (
  5371. UINT Message,
  5372. ULONG_PTR Arg
  5373. )
  5374. {
  5375. if (g_MessageCallback) {
  5376. return g_MessageCallback (Message, Arg);
  5377. }
  5378. return 0;
  5379. }
  5380. MIG_PROGRESSSLICEID
  5381. IsmRegisterProgressSlice (
  5382. IN UINT Ticks,
  5383. IN UINT TimeEstimateInSeconds
  5384. )
  5385. {
  5386. PPROGSLICE slice;
  5387. MIG_PROGRESSSLICEID sliceId;
  5388. if (!TimeEstimateInSeconds || !Ticks) {
  5389. DEBUGMSG ((DBG_WARNING, "Ticks/TimeEstimateInSeconds must not be zero"));
  5390. return 0;
  5391. }
  5392. sliceId = (MIG_PROGRESSSLICEID) (g_SliceBuffer.End / sizeof (PROGSLICE) + 1);
  5393. slice = (PPROGSLICE) GbGrow (&g_SliceBuffer, sizeof (PROGSLICE));
  5394. slice->SliceSize = Ticks;
  5395. slice->CurrentPosition = 0;
  5396. slice->SliceSizeInSeconds = TimeEstimateInSeconds;
  5397. return sliceId;
  5398. }
  5399. VOID
  5400. pCallProgressBar (
  5401. IN MIG_PROGRESSSTATE State
  5402. )
  5403. {
  5404. ULONGLONG temp;
  5405. UINT u;
  5406. PPROGSLICE slice;
  5407. UINT totalTicks = 0;
  5408. UINT currentPos = 0;
  5409. MIG_APPINFO appInfo;
  5410. if (g_ProgressBarFn) {
  5411. for (u = 0 ; u < g_SliceBuffer.End ; u += sizeof (PROGSLICE)) {
  5412. slice = (PPROGSLICE) (g_SliceBuffer.Buf + u);
  5413. temp = (ULONGLONG) slice->CurrentPosition * (ULONGLONG) slice->SliceSizeInSeconds;
  5414. temp *= 10;
  5415. temp /= (ULONGLONG) slice->SliceSize;
  5416. currentPos += (UINT) temp;
  5417. temp = (ULONGLONG) slice->SliceSizeInSeconds * 10;
  5418. totalTicks += (UINT) temp;
  5419. }
  5420. if (State == MIG_END_PHASE) {
  5421. currentPos = totalTicks;
  5422. } else if (State == MIG_BEGIN_PHASE) {
  5423. currentPos = 0;
  5424. }
  5425. g_ProgressBarFn (
  5426. g_CurrentPhase,
  5427. State,
  5428. currentPos,
  5429. totalTicks,
  5430. g_ProgressBarArg
  5431. );
  5432. }
  5433. if (State == MIG_BEGIN_PHASE) {
  5434. ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
  5435. appInfo.Phase = g_CurrentPhase;
  5436. IsmSendMessageToApp (ISMMESSAGE_APP_INFO_NOW, (ULONG_PTR)(&appInfo));
  5437. }
  5438. if (State == MIG_END_PHASE) {
  5439. ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
  5440. IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
  5441. }
  5442. }
  5443. BOOL
  5444. IsmTickProgressBar (
  5445. IN MIG_PROGRESSSLICEID SliceId,
  5446. IN UINT TickDelta OPTIONAL
  5447. )
  5448. {
  5449. PPROGSLICE slice;
  5450. if (!g_CurrentPhase || !g_ProgressBarFn) {
  5451. SliceId = 0;
  5452. }
  5453. if (!TickDelta) {
  5454. TickDelta = 1;
  5455. }
  5456. if (SliceId) {
  5457. //
  5458. // Update the slice ID
  5459. //
  5460. SliceId--;
  5461. if (SliceId >= (MIG_PROGRESSSLICEID) (g_SliceBuffer.End / sizeof (PROGSLICE))) {
  5462. DEBUGMSG ((DBG_ERROR, "Invalid slice ID passed to IsmTickProgressBar"));
  5463. return FALSE;
  5464. }
  5465. slice = (PPROGSLICE) g_SliceBuffer.Buf + SliceId;
  5466. if (slice->CurrentPosition < slice->SliceSize) {
  5467. slice->CurrentPosition += TickDelta;
  5468. if (slice->CurrentPosition > slice->SliceSize) {
  5469. slice->CurrentPosition = slice->SliceSize;
  5470. }
  5471. //
  5472. // Call the application's progress callback
  5473. //
  5474. pCallProgressBar (MIG_IN_PHASE);
  5475. } else {
  5476. DEBUGMSG ((DBG_WARNING, "IsmTickProgressBar: Slice already completed"));
  5477. }
  5478. }
  5479. return !CheckCancel();
  5480. }
  5481. VOID
  5482. IsmSetCancel (
  5483. VOID
  5484. )
  5485. {
  5486. if (g_CancelEvent) {
  5487. SetEvent (g_CancelEvent);
  5488. }
  5489. }
  5490. MIG_PLATFORMTYPEID
  5491. IsmGetRealPlatform (
  5492. VOID
  5493. )
  5494. {
  5495. return g_IsmCurrentPlatform;
  5496. }
  5497. BOOL
  5498. IsmCurrentlyExecuting (
  5499. VOID
  5500. )
  5501. {
  5502. return g_ExecutionInProgress;
  5503. }
  5504. BOOL
  5505. IsmCreateUser (
  5506. IN PCTSTR UserName,
  5507. IN PCTSTR Domain
  5508. )
  5509. {
  5510. if (g_TempProfile) {
  5511. DEBUGMSG ((DBG_WHOOPS, "Cannot call IsmCreateUser more than once"));
  5512. return FALSE;
  5513. }
  5514. // record that we attempted to create the user
  5515. pRecordUserData (
  5516. UserName,
  5517. Domain,
  5518. NULL,
  5519. NULL,
  5520. TRUE
  5521. );
  5522. g_TempProfile = OpenTemporaryProfile (UserName, Domain);
  5523. if (g_TempProfile) {
  5524. // record that we created the user
  5525. pRecordUserData (
  5526. UserName,
  5527. Domain,
  5528. g_TempProfile->UserStringSid,
  5529. g_TempProfile->UserProfileRoot,
  5530. TRUE
  5531. );
  5532. // prepare the user journal
  5533. pPrepareUserJournal (g_TempProfile);
  5534. // let ETM module know this
  5535. BroadcastUserCreation (g_TempProfile);
  5536. }
  5537. return g_TempProfile != NULL;
  5538. }
  5539. MIG_PARSEDPATTERN
  5540. IsmCreateParsedPattern (
  5541. IN MIG_OBJECTSTRINGHANDLE EncodedObject
  5542. )
  5543. {
  5544. return (MIG_PARSEDPATTERN)ObsCreateParsedPattern (EncodedObject);
  5545. }
  5546. VOID
  5547. IsmDestroyParsedPattern (
  5548. IN MIG_PARSEDPATTERN ParsedPattern
  5549. )
  5550. {
  5551. ObsDestroyParsedPattern ((POBSPARSEDPATTERN)ParsedPattern);
  5552. }
  5553. BOOL
  5554. IsmParsedPatternMatchEx (
  5555. IN MIG_PARSEDPATTERN ParsedPattern,
  5556. IN MIG_OBJECTTYPEID ObjectTypeId, OPTIONAL
  5557. IN PCTSTR Node, OPTIONAL
  5558. IN PCTSTR Leaf OPTIONAL
  5559. )
  5560. {
  5561. BOOL result = TRUE;
  5562. PTSTR newLeaf;
  5563. PTSTR tempString;
  5564. POBSPARSEDPATTERN obsParsedPattern = (POBSPARSEDPATTERN) ParsedPattern;
  5565. MYASSERT (Node && obsParsedPattern->NodePattern);
  5566. if (!(Node && obsParsedPattern->NodePattern)) {
  5567. return FALSE;
  5568. }
  5569. if (((obsParsedPattern->Flags & OBSPF_NOLEAF) && Leaf) ||
  5570. ((obsParsedPattern->Flags & OBSPF_EXACTLEAF) && !Leaf)
  5571. ) {
  5572. return FALSE;
  5573. }
  5574. if (!TestParsedPattern (obsParsedPattern->NodePattern, Node)) {
  5575. //
  5576. // let's try one more time with a wack at the end
  5577. //
  5578. tempString = JoinText (Node, TEXT("\\"));
  5579. result = TestParsedPattern (obsParsedPattern->NodePattern, tempString);
  5580. FreeText (tempString);
  5581. if (!result) {
  5582. return FALSE;
  5583. }
  5584. }
  5585. if (Leaf) {
  5586. if (!obsParsedPattern->LeafPattern) {
  5587. return FALSE;
  5588. }
  5589. result = TestParsedPattern (obsParsedPattern->LeafPattern, Leaf);
  5590. if (!result &&
  5591. ((ObjectTypeId & (~PLATFORM_MASK)) == MIG_FILE_TYPE) &&
  5592. (_tcschr (Leaf, TEXT('.')) == NULL)
  5593. ) {
  5594. newLeaf = JoinText (Leaf, TEXT("."));
  5595. if (newLeaf) {
  5596. result = TestParsedPattern (obsParsedPattern->LeafPattern, newLeaf);
  5597. FreeText (newLeaf);
  5598. } else {
  5599. result = FALSE;
  5600. }
  5601. }
  5602. } else {
  5603. if (!obsParsedPattern->ExactRoot) {
  5604. result = FALSE;
  5605. }
  5606. }
  5607. return result;
  5608. }
  5609. BOOL
  5610. IsmParsedPatternMatch (
  5611. IN MIG_PARSEDPATTERN ParsedPattern,
  5612. IN MIG_OBJECTTYPEID ObjectTypeId, OPTIONAL
  5613. IN MIG_OBJECTSTRINGHANDLE ObjectName
  5614. )
  5615. {
  5616. PTSTR decodedNode;
  5617. PTSTR decodedLeaf;
  5618. BOOL b;
  5619. if (!IsmCreateObjectStringsFromHandle (ObjectName, &decodedNode, &decodedLeaf)) {
  5620. return FALSE;
  5621. }
  5622. b = IsmParsedPatternMatchEx (ParsedPattern, ObjectTypeId, decodedNode, decodedLeaf);
  5623. IsmDestroyObjectString (decodedNode);
  5624. IsmDestroyObjectString (decodedLeaf);
  5625. return b;
  5626. }
  5627. BOOL
  5628. IsmGetMappedUserData (
  5629. OUT PMIG_USERDATA UserData
  5630. )
  5631. {
  5632. if (UserData && g_TempProfile) {
  5633. ZeroMemory (UserData, sizeof (MIG_USERDATA));
  5634. UserData->UserName = g_TempProfile->UserName;
  5635. UserData->DomainName = g_TempProfile->DomainName;
  5636. UserData->AccountName = g_TempProfile->AccountName;
  5637. UserData->UserProfileRoot = g_TempProfile->UserProfileRoot;
  5638. UserData->UserSid = g_TempProfile->UserSid;
  5639. }
  5640. return (g_TempProfile != NULL);
  5641. }
  5642. BOOL
  5643. IsmAddControlFile (
  5644. IN PCTSTR ObjectName,
  5645. IN PCTSTR NativePath
  5646. )
  5647. {
  5648. MIG_OBJECTSTRINGHANDLE memDbObjectName;
  5649. TCHAR tempFile[MAX_TCHAR_PATH];
  5650. if (g_IsmCurrentPlatform == PLATFORM_CURRENT) {
  5651. DEBUGMSG ((DBG_WHOOPS, "IsmSetPlatform must be called before IsmAddControlFile"));
  5652. return FALSE;
  5653. }
  5654. // Do not start with a | special character
  5655. if (*ObjectName == TEXT('|')) {
  5656. return FALSE;
  5657. }
  5658. // INF file paths are limited to MAX_PATH in size
  5659. if (SizeOfString (NativePath) > ARRAYSIZE(tempFile)) {
  5660. return FALSE;
  5661. }
  5662. IsmGetTempFile (tempFile, ARRAYSIZE (tempFile));
  5663. if (!CopyFile (NativePath, tempFile, FALSE)) {
  5664. return FALSE;
  5665. }
  5666. // Add filename to hashtable for cleanup
  5667. HtAddString (g_ControlFileTable, tempFile);
  5668. memDbObjectName = IsmCreateObjectHandle (TEXT("External"), ObjectName);
  5669. DataTypeAddObject (memDbObjectName, tempFile, TRUE);
  5670. IsmDestroyObjectHandle (memDbObjectName);
  5671. return TRUE;
  5672. }
  5673. BOOL
  5674. IsmGetControlFile (
  5675. IN MIG_OBJECTTYPEID ObjectTypeId,
  5676. IN PCTSTR ObjectName,
  5677. IN PTSTR Buffer // Required to be MAX_PATH_PLUS_NUL in size
  5678. )
  5679. {
  5680. MIG_CONTENT content;
  5681. TCHAR tempFile[MAX_TCHAR_PATH];
  5682. BOOL result = FALSE;
  5683. if (IsmAcquireObject (ObjectTypeId, ObjectName, &content)) {
  5684. MYASSERT (content.ContentInFile);
  5685. if ((content.ContentInFile) &&
  5686. (SizeOfString (content.FileContent.ContentPath) < ARRAYSIZE(tempFile))) {
  5687. IsmGetTempFile (tempFile, ARRAYSIZE (tempFile));
  5688. if (CopyFile (content.FileContent.ContentPath, tempFile, FALSE)) {
  5689. // Return a copy of the filename
  5690. StringCopy (Buffer, tempFile);
  5691. // Add filename to hashtable for cleanup
  5692. HtAddString (g_ControlFileTable, tempFile);
  5693. result = TRUE;
  5694. }
  5695. }
  5696. }
  5697. return result;
  5698. }
  5699. BOOL
  5700. IsmSetRollbackJournalType (
  5701. IN BOOL Common
  5702. )
  5703. {
  5704. TCHAR winDir [MAX_PATH];
  5705. PCURRENT_USER_DATA currentUserData;
  5706. BOOL result = FALSE;
  5707. if (g_JournalUsed) {
  5708. return FALSE;
  5709. }
  5710. if (g_JournalDirectory) {
  5711. FreePathString (g_JournalDirectory);
  5712. }
  5713. if (Common) {
  5714. if (GetWindowsDirectory (winDir, ARRAYSIZE (winDir))) {
  5715. g_JournalDirectory = JoinPaths (winDir, TEXT("usmt2.tmp"));
  5716. result = TRUE;
  5717. }
  5718. } else {
  5719. currentUserData = GetCurrentUserData ();
  5720. if (currentUserData) {
  5721. g_JournalDirectory = JoinPaths (currentUserData->UserProfilePath, TEXT("usmt2.tmp"));
  5722. FreeCurrentUserData (currentUserData);
  5723. }
  5724. }
  5725. return TRUE;
  5726. }
  5727. BOOL
  5728. IsmCanWriteRollbackJournal (
  5729. VOID
  5730. )
  5731. {
  5732. BOOL result = TRUE;
  5733. DWORD err;
  5734. if (DoesFileExist (g_JournalDirectory)) {
  5735. FiRemoveAllFilesInTree (g_JournalDirectory);
  5736. }
  5737. if (!BfCreateDirectory (g_JournalDirectory)) {
  5738. err = GetLastError ();
  5739. if ((err == ERROR_ALREADY_EXISTS) ||
  5740. (err == ERROR_ACCESS_DENIED)
  5741. ) {
  5742. result = FALSE;
  5743. }
  5744. }
  5745. if (result) {
  5746. FiRemoveAllFilesInTree (g_JournalDirectory);
  5747. }
  5748. return result;
  5749. }
  5750. VOID
  5751. pRecordUserData (
  5752. IN PCTSTR UserName,
  5753. IN PCTSTR UserDomain,
  5754. IN PCTSTR UserStringSid,
  5755. IN PCTSTR UserProfilePath,
  5756. IN BOOL ProfileCreated
  5757. )
  5758. {
  5759. LONGLONG lastPos;
  5760. TCHAR userName [MAX_TCHAR_PATH];
  5761. TCHAR userDomain [MAX_TCHAR_PATH];
  5762. TCHAR userStringSid [MAX_TCHAR_PATH];
  5763. TCHAR userProfilePath [MAX_TCHAR_PATH];
  5764. DWORD dontCare;
  5765. if (g_RollbackMode) {
  5766. return;
  5767. }
  5768. if (!g_JournalDirectory) {
  5769. DEBUGMSG ((DBG_WHOOPS, "Journal directory does not exist."));
  5770. return;
  5771. }
  5772. if (!g_JournalHandle) {
  5773. DEBUGMSG ((DBG_WHOOPS, "Journal file is not opened."));
  5774. return;
  5775. }
  5776. // If the file position is just after the journal header we'll just write
  5777. // the info, otherwise we are going to save the current position,
  5778. // write our data and restore the file position.
  5779. if (!BfGetFilePointer (g_JournalHandle, &lastPos)) {
  5780. DEBUGMSG ((DBG_WHOOPS, "Something wrong with the Journal file."));
  5781. return;
  5782. }
  5783. if (lastPos != JOURNAL_HEADER_SIZE) {
  5784. if (!BfSetFilePointer (g_JournalHandle, JOURNAL_HEADER_SIZE)) {
  5785. DEBUGMSG ((DBG_WHOOPS, "Something wrong with the Journal file."));
  5786. return;
  5787. }
  5788. }
  5789. // now write the info
  5790. ZeroMemory (userName, MAX_TCHAR_PATH);
  5791. ZeroMemory (userDomain, MAX_TCHAR_PATH);
  5792. ZeroMemory (userStringSid, MAX_TCHAR_PATH);
  5793. ZeroMemory (userProfilePath, MAX_TCHAR_PATH);
  5794. if (UserName) {
  5795. StringCopyTcharCount (userName, UserName, MAX_TCHAR_PATH);
  5796. }
  5797. if (UserDomain) {
  5798. StringCopyTcharCount (userDomain, UserDomain, MAX_TCHAR_PATH);
  5799. }
  5800. if (UserStringSid) {
  5801. StringCopyTcharCount (userStringSid, UserStringSid, MAX_TCHAR_PATH);
  5802. }
  5803. if (UserProfilePath) {
  5804. StringCopyTcharCount (userProfilePath, UserProfilePath, MAX_TCHAR_PATH);
  5805. }
  5806. WriteFile (
  5807. g_JournalHandle,
  5808. userName,
  5809. MAX_TCHAR_PATH,
  5810. &dontCare,
  5811. NULL
  5812. );
  5813. WriteFile (
  5814. g_JournalHandle,
  5815. userDomain,
  5816. MAX_TCHAR_PATH,
  5817. &dontCare,
  5818. NULL
  5819. );
  5820. WriteFile (
  5821. g_JournalHandle,
  5822. userStringSid,
  5823. MAX_TCHAR_PATH,
  5824. &dontCare,
  5825. NULL
  5826. );
  5827. WriteFile (
  5828. g_JournalHandle,
  5829. userProfilePath,
  5830. MAX_TCHAR_PATH,
  5831. &dontCare,
  5832. NULL
  5833. );
  5834. WriteFile (
  5835. g_JournalHandle,
  5836. &ProfileCreated,
  5837. sizeof (BOOL),
  5838. &dontCare,
  5839. NULL
  5840. );
  5841. if (lastPos != JOURNAL_HEADER_SIZE) {
  5842. BfSetFilePointer (g_JournalHandle, lastPos);
  5843. }
  5844. }
  5845. VOID
  5846. IsmRecordOperation (
  5847. IN DWORD OperationType,
  5848. IN MIG_OBJECTTYPEID ObjectTypeId,
  5849. IN MIG_OBJECTSTRINGHANDLE ObjectName
  5850. )
  5851. {
  5852. #ifdef PRERELEASE
  5853. // crash hooks
  5854. #define MAX_OBJECTTYPES 20
  5855. static DWORD totalObjects = 0;
  5856. static DWORD typeObjects[MAX_OBJECTTYPES] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  5857. MIG_OBJECTTYPEID objTypeId;
  5858. PCTSTR nativeName = NULL;
  5859. BOOL doCrash = FALSE;
  5860. #endif
  5861. static GROWBUFFER buffer = INIT_GROWBUFFER;
  5862. static DWORD backupIdx = 0;
  5863. TCHAR destFile [13];
  5864. PCTSTR destFullPath;
  5865. DWORD entrySize = 0;
  5866. WIN32_FIND_DATA findData;
  5867. MIG_CONTENT objectContent;
  5868. DWORD dontCare;
  5869. if (g_RollbackMode) {
  5870. return;
  5871. }
  5872. if (!g_JournalDirectory) {
  5873. DEBUGMSG ((DBG_WHOOPS, "Journal directory does not exist."));
  5874. return;
  5875. }
  5876. if (!g_JournalHandle) {
  5877. DEBUGMSG ((DBG_WHOOPS, "Journal file is not opened."));
  5878. return;
  5879. }
  5880. ObjectTypeId &= (~PLATFORM_MASK);
  5881. buffer.End = 0;
  5882. switch (OperationType) {
  5883. case JRNOP_CREATE:
  5884. #ifdef PRERELEASE
  5885. // crash hooks
  5886. totalObjects ++;
  5887. if (g_CrashCountObjects == totalObjects) {
  5888. doCrash = TRUE;
  5889. }
  5890. objTypeId = ObjectTypeId & (~PLATFORM_MASK);
  5891. if (objTypeId && (objTypeId <= MAX_OBJECTTYPES)) {
  5892. typeObjects [objTypeId - 1]++;
  5893. if ((g_CrashCountTypeId == objTypeId) &&
  5894. (g_CrashCountType == typeObjects [objTypeId - 1])
  5895. ) {
  5896. doCrash = TRUE;
  5897. }
  5898. }
  5899. if (g_CrashNameTypeId == objTypeId) {
  5900. nativeName = IsmGetNativeObjectName (objTypeId, ObjectName);
  5901. if (StringIMatch (nativeName, g_CrashNameObject)) {
  5902. doCrash = TRUE;
  5903. }
  5904. IsmReleaseMemory (nativeName);
  5905. }
  5906. #endif
  5907. GbAppendDword (&buffer, OperationType);
  5908. CopyMemory (GbGrow (&buffer, sizeof (MIG_OBJECTTYPEID)), &ObjectTypeId, sizeof (MIG_OBJECTTYPEID));
  5909. GbAppendDword (&buffer, SizeOfString (ObjectName));
  5910. GbCopyString (&buffer, ObjectName);
  5911. entrySize = buffer.End;
  5912. break;
  5913. case JRNOP_DELETE:
  5914. if (!IsmAcquireObject (
  5915. ObjectTypeId | PLATFORM_DESTINATION,
  5916. ObjectName,
  5917. &objectContent
  5918. )) {
  5919. return;
  5920. }
  5921. GbAppendDword (&buffer, OperationType);
  5922. CopyMemory (GbGrow (&buffer, sizeof (MIG_OBJECTTYPEID)), &ObjectTypeId, sizeof (MIG_OBJECTTYPEID));
  5923. GbAppendDword (&buffer, SizeOfString (ObjectName));
  5924. GbCopyString (&buffer, ObjectName);
  5925. GbAppendDword (&buffer, sizeof (MIG_CONTENT));
  5926. CopyMemory (GbGrow (&buffer, sizeof (MIG_CONTENT)), &objectContent, sizeof (MIG_CONTENT));
  5927. if (objectContent.Details.DetailsSize && objectContent.Details.DetailsData) {
  5928. GbAppendDword (&buffer, objectContent.Details.DetailsSize);
  5929. CopyMemory (
  5930. GbGrow (&buffer, objectContent.Details.DetailsSize),
  5931. objectContent.Details.DetailsData,
  5932. objectContent.Details.DetailsSize
  5933. );
  5934. } else {
  5935. GbAppendDword (&buffer, 0);
  5936. }
  5937. if (objectContent.ContentInFile) {
  5938. if (DoesFileExistEx (objectContent.FileContent.ContentPath, &findData) &&
  5939. ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  5940. ) {
  5941. // extra data is the relative path to the backup copy of this file
  5942. backupIdx ++;
  5943. wsprintf (destFile, TEXT("%08d.BAK"), backupIdx);
  5944. destFullPath = JoinPaths (g_JournalDirectory, destFile);
  5945. BfCopyAndFlushFile (objectContent.FileContent.ContentPath, destFullPath, FALSE);
  5946. FreePathString (destFullPath);
  5947. GbAppendDword (&buffer, SizeOfString (destFile));
  5948. GbCopyString (&buffer, destFile);
  5949. } else {
  5950. GbAppendDword (&buffer, 0);
  5951. }
  5952. } else {
  5953. // extra data is the actual content
  5954. GbAppendDword (&buffer, objectContent.MemoryContent.ContentSize);
  5955. if (objectContent.MemoryContent.ContentSize) {
  5956. CopyMemory (
  5957. GbGrow (&buffer, objectContent.MemoryContent.ContentSize),
  5958. objectContent.MemoryContent.ContentBytes,
  5959. objectContent.MemoryContent.ContentSize
  5960. );
  5961. }
  5962. }
  5963. entrySize = buffer.End;
  5964. IsmReleaseObject (&objectContent);
  5965. break;
  5966. default:
  5967. DEBUGMSG ((DBG_WHOOPS, "Wrong operation type in pRecordOperation: %d", OperationType));
  5968. return;
  5969. }
  5970. WriteFile (
  5971. g_JournalHandle,
  5972. &entrySize,
  5973. sizeof (DWORD),
  5974. &dontCare,
  5975. NULL
  5976. );
  5977. WriteFile (
  5978. g_JournalHandle,
  5979. buffer.Buf,
  5980. buffer.End,
  5981. &dontCare,
  5982. NULL
  5983. );
  5984. WriteFile (
  5985. g_JournalHandle,
  5986. &entrySize,
  5987. sizeof (DWORD),
  5988. &dontCare,
  5989. NULL
  5990. );
  5991. FlushFileBuffers (g_JournalHandle);
  5992. #ifdef PRERELEASE
  5993. if (doCrash) {
  5994. DebugBreak ();
  5995. }
  5996. #endif
  5997. g_JournalUsed = TRUE;
  5998. }
  5999. BOOL
  6000. IsmSetDelayedOperationsCommand (
  6001. IN PCTSTR DelayedOperationsCommand
  6002. )
  6003. {
  6004. if (g_DelayedOperationsCommand) {
  6005. FreePathString (g_DelayedOperationsCommand);
  6006. }
  6007. g_DelayedOperationsCommand = DuplicatePathString (DelayedOperationsCommand, 0);
  6008. return TRUE;
  6009. }
  6010. VOID
  6011. IsmRecordDelayedOperation (
  6012. IN DWORD OperationType,
  6013. IN MIG_OBJECTTYPEID ObjectTypeId,
  6014. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  6015. IN PMIG_CONTENT ObjectContent
  6016. )
  6017. {
  6018. static GROWBUFFER buffer = INIT_GROWBUFFER;
  6019. static DWORD backupIdx = 0;
  6020. TCHAR destFile [13];
  6021. PCTSTR destFullPath;
  6022. DWORD entrySize = 0;
  6023. WIN32_FIND_DATA findData;
  6024. DWORD dontCare;
  6025. if (!g_TempProfile ||
  6026. !g_TempProfile->DelayedOpJrn ||
  6027. !g_TempProfile->DelayedOpJrnHandle ||
  6028. (g_TempProfile->DelayedOpJrnHandle == INVALID_HANDLE_VALUE)
  6029. ) {
  6030. DEBUGMSG ((DBG_WHOOPS, "Delayed operations Journal does not exist."));
  6031. return;
  6032. }
  6033. ObjectTypeId &= (~PLATFORM_MASK);
  6034. buffer.End = 0;
  6035. switch (OperationType) {
  6036. case JRNOP_DELETE:
  6037. GbAppendDword (&buffer, OperationType);
  6038. CopyMemory (GbGrow (&buffer, sizeof (MIG_OBJECTTYPEID)), &ObjectTypeId, sizeof (MIG_OBJECTTYPEID));
  6039. GbAppendDword (&buffer, SizeOfString (ObjectName));
  6040. GbCopyString (&buffer, ObjectName);
  6041. entrySize = buffer.End;
  6042. break;
  6043. case JRNOP_CREATE:
  6044. case JRNOP_REPLACE:
  6045. GbAppendDword (&buffer, OperationType);
  6046. CopyMemory (GbGrow (&buffer, sizeof (MIG_OBJECTTYPEID)), &ObjectTypeId, sizeof (MIG_OBJECTTYPEID));
  6047. GbAppendDword (&buffer, SizeOfString (ObjectName));
  6048. GbCopyString (&buffer, ObjectName);
  6049. GbAppendDword (&buffer, sizeof (MIG_CONTENT));
  6050. CopyMemory (GbGrow (&buffer, sizeof (MIG_CONTENT)), ObjectContent, sizeof (MIG_CONTENT));
  6051. if (ObjectContent->Details.DetailsSize && ObjectContent->Details.DetailsData) {
  6052. GbAppendDword (&buffer, ObjectContent->Details.DetailsSize);
  6053. CopyMemory (
  6054. GbGrow (&buffer, ObjectContent->Details.DetailsSize),
  6055. ObjectContent->Details.DetailsData,
  6056. ObjectContent->Details.DetailsSize
  6057. );
  6058. } else {
  6059. GbAppendDword (&buffer, 0);
  6060. }
  6061. if (ObjectContent->ContentInFile) {
  6062. if (DoesFileExistEx (ObjectContent->FileContent.ContentPath, &findData) &&
  6063. ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  6064. ) {
  6065. // extra data is the relative path to the backup copy of this file
  6066. backupIdx ++;
  6067. wsprintf (destFile, TEXT("%08d.BAK"), backupIdx);
  6068. destFullPath = JoinPaths (g_TempProfile->DelayedOpJrn, destFile);
  6069. BfCopyAndFlushFile (ObjectContent->FileContent.ContentPath, destFullPath, FALSE);
  6070. FreePathString (destFullPath);
  6071. GbAppendDword (&buffer, SizeOfString (destFile));
  6072. GbCopyString (&buffer, destFile);
  6073. } else {
  6074. GbAppendDword (&buffer, 0);
  6075. }
  6076. } else {
  6077. // extra data is the actual content
  6078. GbAppendDword (&buffer, ObjectContent->MemoryContent.ContentSize);
  6079. if (ObjectContent->MemoryContent.ContentSize) {
  6080. CopyMemory (
  6081. GbGrow (&buffer, ObjectContent->MemoryContent.ContentSize),
  6082. ObjectContent->MemoryContent.ContentBytes,
  6083. ObjectContent->MemoryContent.ContentSize
  6084. );
  6085. }
  6086. }
  6087. entrySize = buffer.End;
  6088. break;
  6089. default:
  6090. DEBUGMSG ((DBG_WHOOPS, "Wrong operation type in IsmRecordDelayedOperation: %d", OperationType));
  6091. return;
  6092. }
  6093. WriteFile (
  6094. g_TempProfile->DelayedOpJrnHandle,
  6095. &entrySize,
  6096. sizeof (DWORD),
  6097. &dontCare,
  6098. NULL
  6099. );
  6100. WriteFile (
  6101. g_TempProfile->DelayedOpJrnHandle,
  6102. buffer.Buf,
  6103. buffer.End,
  6104. &dontCare,
  6105. NULL
  6106. );
  6107. WriteFile (
  6108. g_TempProfile->DelayedOpJrnHandle,
  6109. &entrySize,
  6110. sizeof (DWORD),
  6111. &dontCare,
  6112. NULL
  6113. );
  6114. FlushFileBuffers (g_TempProfile->DelayedOpJrnHandle);
  6115. }
  6116. PMIG_OBJECTCOUNT
  6117. IsmGetObjectsStatistics (
  6118. IN MIG_OBJECTTYPEID ObjectTypeId OPTIONAL
  6119. )
  6120. {
  6121. if ((ObjectTypeId & (~PLATFORM_MASK)) == 0) {
  6122. if (ObjectTypeId & PLATFORM_SOURCE) {
  6123. return &g_SourceObjects;
  6124. } else if (ObjectTypeId & PLATFORM_DESTINATION) {
  6125. return &g_DestinationObjects;
  6126. } else {
  6127. return &g_TotalObjects;
  6128. }
  6129. } else {
  6130. return GetTypeObjectsStatistics (ObjectTypeId);
  6131. }
  6132. }
  6133. VOID
  6134. EngineError (
  6135. VOID
  6136. )
  6137. {
  6138. LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_ENGINE_FAILURE));
  6139. IsmSetCancel();
  6140. }
  6141. BOOL
  6142. IsmGetOsVersionInfo (
  6143. IN MIG_PLATFORMTYPEID Platform,
  6144. OUT PMIG_OSVERSIONINFO VersionInfo
  6145. )
  6146. {
  6147. TCHAR tempStr [sizeof (UINT) * 2 + 3];
  6148. if (!VersionInfo) {
  6149. return FALSE;
  6150. }
  6151. ZeroMemory (VersionInfo, sizeof (MIG_OSVERSIONINFO));
  6152. if (Platform == PLATFORM_CURRENT) {
  6153. Platform = g_IsmCurrentPlatform;
  6154. }
  6155. if (!IsmGetEnvironmentString (
  6156. Platform,
  6157. NULL,
  6158. S_VER_OSTYPE,
  6159. tempStr,
  6160. sizeof(tempStr),
  6161. NULL
  6162. )) {
  6163. return FALSE;
  6164. }
  6165. _stscanf (tempStr, TEXT("%lx"), &(VersionInfo->OsType));
  6166. if (!IsmGetEnvironmentString (
  6167. Platform,
  6168. NULL,
  6169. S_VER_OSMAJOR,
  6170. tempStr,
  6171. sizeof(tempStr),
  6172. NULL
  6173. )) {
  6174. return FALSE;
  6175. }
  6176. _stscanf (tempStr, TEXT("%lx"), &(VersionInfo->OsMajorVersion));
  6177. if (!IsmGetEnvironmentString (
  6178. Platform,
  6179. NULL,
  6180. S_VER_OSMINOR,
  6181. tempStr,
  6182. sizeof(tempStr),
  6183. NULL
  6184. )) {
  6185. return FALSE;
  6186. }
  6187. _stscanf (tempStr, TEXT("%lx"), &(VersionInfo->OsMinorVersion));
  6188. if (!IsmGetEnvironmentString (
  6189. Platform,
  6190. NULL,
  6191. S_VER_OSBUILD,
  6192. tempStr,
  6193. sizeof(tempStr),
  6194. NULL
  6195. )) {
  6196. return FALSE;
  6197. }
  6198. _stscanf (tempStr, TEXT("%lx"), &(VersionInfo->OsBuildNumber));
  6199. if (VersionInfo->OsType == OSTYPE_WINDOWS9X) {
  6200. VersionInfo->OsTypeName = OSTYPE_WINDOWS9X_STR;
  6201. if (VersionInfo->OsMajorVersion == OSMAJOR_WIN95) {
  6202. VersionInfo->OsMajorVersionName = OSMAJOR_WIN95_STR;
  6203. if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) {
  6204. VersionInfo->OsMinorVersion = OSMINOR_GOLD;
  6205. }
  6206. }
  6207. if (VersionInfo->OsMajorVersion == OSMAJOR_WIN95OSR2) {
  6208. VersionInfo->OsMajorVersionName = OSMAJOR_WIN95OSR2_STR;
  6209. if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) {
  6210. VersionInfo->OsMinorVersion = OSMINOR_GOLD;
  6211. }
  6212. }
  6213. if (VersionInfo->OsMajorVersion == OSMAJOR_WIN98) {
  6214. VersionInfo->OsMajorVersionName = OSMAJOR_WIN98_STR;
  6215. if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) {
  6216. VersionInfo->OsMinorVersion = OSMINOR_GOLD;
  6217. }
  6218. if (VersionInfo->OsMinorVersion == OSMINOR_WIN98SE) {
  6219. VersionInfo->OsMinorVersionName = OSMINOR_WIN98SE_STR;
  6220. }
  6221. }
  6222. if (VersionInfo->OsMajorVersion == OSMAJOR_WINME) {
  6223. VersionInfo->OsMajorVersionName = OSMAJOR_WINME_STR;
  6224. if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) {
  6225. VersionInfo->OsMinorVersion = OSMINOR_GOLD;
  6226. }
  6227. }
  6228. }
  6229. if (VersionInfo->OsType == OSTYPE_WINDOWSNT) {
  6230. VersionInfo->OsTypeName = OSTYPE_WINDOWSNT_STR;
  6231. if (VersionInfo->OsMajorVersion == OSMAJOR_WINNT4) {
  6232. VersionInfo->OsMajorVersionName = OSMAJOR_WINNT4_STR;
  6233. if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) {
  6234. VersionInfo->OsMinorVersionName = OSMINOR_GOLD_STR;
  6235. }
  6236. }
  6237. if (VersionInfo->OsMajorVersion == OSMAJOR_WINNT5) {
  6238. VersionInfo->OsMajorVersionName = OSMAJOR_WINNT5_STR;
  6239. if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) {
  6240. VersionInfo->OsMinorVersionName = OSMINOR_GOLD_STR;
  6241. }
  6242. if (VersionInfo->OsMinorVersion == OSMINOR_WINNT51) {
  6243. VersionInfo->OsMinorVersionName = OSMINOR_WINNT51_STR;
  6244. }
  6245. }
  6246. }
  6247. return TRUE;
  6248. }
  6249. BOOL
  6250. pGetFunctionData (
  6251. IN PCTSTR FunctionMultiSz,
  6252. OUT PCTSTR *FunctionId,
  6253. OUT PCTSTR *MultiSzCopy
  6254. )
  6255. {
  6256. GROWBUFFER buf = INIT_GROWBUFFER;
  6257. MULTISZ_ENUM e;
  6258. BOOL result = TRUE;
  6259. if (!FunctionMultiSz) {
  6260. return FALSE;
  6261. }
  6262. if (!FunctionId) {
  6263. return FALSE;
  6264. }
  6265. if (!MultiSzCopy) {
  6266. return FALSE;
  6267. }
  6268. *FunctionId = NULL;
  6269. *MultiSzCopy = NULL;
  6270. buf.End = 0;
  6271. if (result && EnumFirstMultiSz (&e, FunctionMultiSz)) {
  6272. do {
  6273. GbMultiSzAppend (&buf, e.CurrentString);
  6274. } while (EnumNextMultiSz (&e));
  6275. }
  6276. if (buf.End) {
  6277. *MultiSzCopy = IsmGetMemory (buf.End);
  6278. CopyMemory ((PTSTR)(*MultiSzCopy), buf.Buf, buf.End);
  6279. } else {
  6280. result = FALSE;
  6281. }
  6282. buf.End = 0;
  6283. if (result && EnumFirstMultiSz (&e, FunctionMultiSz)) {
  6284. do {
  6285. GbAppendString (&buf, e.CurrentString);
  6286. GbAppendString (&buf, TEXT(";"));
  6287. } while (EnumNextMultiSz (&e));
  6288. }
  6289. if (buf.End) {
  6290. *FunctionId = IsmGetMemory (buf.End);
  6291. CopyMemory ((PTSTR)(*FunctionId), buf.Buf, buf.End);
  6292. } else {
  6293. result = FALSE;
  6294. }
  6295. if (!result) {
  6296. if (*MultiSzCopy) {
  6297. IsmReleaseMemory (*MultiSzCopy);
  6298. *MultiSzCopy = NULL;
  6299. }
  6300. if (*FunctionId) {
  6301. IsmReleaseMemory (*FunctionId);
  6302. *FunctionId = NULL;
  6303. }
  6304. }
  6305. return result;
  6306. }
  6307. BOOL
  6308. IsmExecuteFunction (
  6309. IN UINT ExecutionPhase,
  6310. IN PCTSTR FunctionMultiSz
  6311. )
  6312. {
  6313. PCTSTR functionId;
  6314. PCTSTR functionMultiSz;
  6315. BOOL result = FALSE;
  6316. switch (ExecutionPhase) {
  6317. case MIG_EXECUTE_PREPROCESS:
  6318. if (g_PreProcessTable) {
  6319. if (pGetFunctionData (FunctionMultiSz, &functionId, &functionMultiSz)) {
  6320. HtAddStringEx (g_PreProcessTable, functionId, &functionMultiSz, FALSE);
  6321. IsmReleaseMemory (functionId);
  6322. }
  6323. }
  6324. result = TRUE;
  6325. break;
  6326. case MIG_EXECUTE_REFRESH:
  6327. if (g_RefreshTable) {
  6328. if (pGetFunctionData (FunctionMultiSz, &functionId, &functionMultiSz)) {
  6329. HtAddStringEx (g_RefreshTable, functionId, &functionMultiSz, FALSE);
  6330. IsmReleaseMemory (functionId);
  6331. }
  6332. }
  6333. result = TRUE;
  6334. break;
  6335. case MIG_EXECUTE_POSTPROCESS:
  6336. if (g_PostProcessTable) {
  6337. if (pGetFunctionData (FunctionMultiSz, &functionId, &functionMultiSz)) {
  6338. HtAddStringEx (g_PostProcessTable, functionId, &functionMultiSz, FALSE);
  6339. IsmReleaseMemory (functionId);
  6340. }
  6341. }
  6342. result = TRUE;
  6343. break;
  6344. }
  6345. return result;
  6346. }