Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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