/*++ Copyright (c) 1999 Microsoft Corporation Module Name: ism.c Abstract: Implements routines that are common to the entire ISM. Author: Jim Schmidt (jimschm) 21-Mar-2000 Revision History: --*/ // // Includes // #include "pch.h" #include "ism.h" #include "ismp.h" #include "modules.h" #define DBG_ISM "Ism" // // Strings // #define S_LOCK_KEY TEXT("Locks\\%X") #define S_TRANSPORT_TYPES TEXT("TransportTypes") #define S_DATABASEFILE_LITE TEXT("|MainDatabaseFile\\LITE") // pipe is to decorate for uniqueness #define S_DATABASEFILE_FULL TEXT("|MainDatabaseFile\\Full") // pipe is to decorate for uniqueness #define S_VER_OSTYPE TEXT("OsVersionType") #define S_VER_OSMAJOR TEXT("OsVersionMajor") #define S_VER_OSMINOR TEXT("OsVersionMinor") #define S_VER_OSBUILD TEXT("OsVersionBuild") // // Constants // #define ISM_TMP_SIGNATURE 0x544D5355 #define OBJECT_LOCKED 0x00000001 #define GROUP_ID 0x00000001 #define ITEM_ID 0x00000002 // // Macros // // None // // Types // typedef struct { MEMDB_ENUM MemDbEnum; DBENUM_ARGS ParsedPatterns; } OBJECTENUM_HANDLE, *POBJECTENUM_HANDLE; typedef enum { TESTATE_BEGINTRANSPORT, TESTATE_GETCAPS, TESTATE_RETURN, TESTATE_NEXTTRANSPORTTYPE, TESTATE_NEXTTRANSPORT, TESTATE_DONE } TRANSPORTENUMSTATE; typedef struct { HASHTABLE_ENUM TableEnum; MEMDB_ENUM MemDbEnum; TRANSPORTENUMSTATE State; MIG_TRANSPORTSTORAGEID DesiredStorageId; } TRANSPORTENUMHANDLE, *PTRANSPORTENUMHANDLE; typedef struct { UINT SliceSize; UINT CurrentPosition; UINT SliceSizeInSeconds; } PROGSLICE, *PPROGSLICE; // // Globals // MIG_OBJECTCOUNT g_TotalObjects; MIG_OBJECTCOUNT g_SourceObjects; MIG_OBJECTCOUNT g_DestinationObjects; HANDLE g_CancelEvent; HANDLE g_ActivityEvent; HASHTABLE g_TransportTable; HASHTABLE g_ControlFileTable; PMHANDLE g_IsmPool; PMHANDLE g_IsmUntrackedPool; HINF g_IsmInf = INVALID_HANDLE_VALUE; PCTSTR g_CurrentGroup = NULL; UINT g_IsmCurrentPlatform = PLATFORM_CURRENT; UINT g_IsmModulePlatformContext = PLATFORM_CURRENT; PRESTORE_STRUCT g_RestoreCallbacks = NULL; PMESSAGECALLBACK g_MessageCallback; PTRANSPORTDATA g_SelectedTransport; MIG_TRANSPORTSTORAGEID g_SelectedTransportId; GROWBUFFER g_SliceBuffer; MIG_PROGRESSPHASE g_CurrentPhase; PPROGRESSBARFN g_ProgressBarFn; ULONG_PTR g_ProgressBarArg; MIG_TRANSPORTTYPE g_TransportType = 0; PTEMPORARYPROFILE g_TempProfile; PMIG_LOGCALLBACK g_LogCallback; PCTSTR g_JournalDirectory = NULL; BOOL g_PreserveJournal = FALSE; HANDLE g_JournalHandle = NULL; BOOL g_RollbackMode = FALSE; BOOL g_JournalUsed = FALSE; BOOL g_ExecutionInProgress = FALSE; PCTSTR g_DelayedOperationsCommand = NULL; BOOL g_EngineInitialized; BOOL g_EngineTerminated; BOOL g_MakeProfilePermanent = FALSE; // temporary storage TCHAR g_GlobalTempDir [MAX_PATH] = TEXT(""); UINT g_TempDirIndex = 0; UINT g_TempFileIndex = 0; // execute HASHTABLE g_PreProcessTable = NULL; HASHTABLE g_RefreshTable = NULL; HASHTABLE g_PostProcessTable = NULL; BOOL g_PreProcessDone = FALSE; #ifdef PRERELEASE // crash hooks MIG_OBJECTTYPEID g_CrashCountTypeId = 0; DWORD g_CrashCountType = 0; DWORD g_CrashCountObjects = 0; MIG_OBJECTTYPEID g_CrashNameTypeId = 0; PCTSTR g_CrashNameObject = NULL; #endif // // Macro expansion list // // None // // Private function prototypes // VOID pCallProgressBar ( IN MIG_PROGRESSSTATE State ); BOOL pEnumFirstTransportType ( OUT PMEMDB_ENUM EnumPtr ); BOOL pEnumNextTransportType ( IN OUT PMEMDB_ENUM EnumPtr ); VOID pAbortTransportTypeEnum ( IN OUT PMEMDB_ENUM EnumPtr ); BOOL pEnumFirstVirtualObject ( OUT PMIG_OBJECT_ENUM ObjectEnum, IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE ObjectPattern ); BOOL pEnumNextVirtualObject ( IN OUT PMIG_OBJECT_ENUM ObjectEnum ); VOID pAbortVirtualObjectEnum ( IN PMIG_OBJECT_ENUM ObjectEnum ); BOOL pEnablePrivilege ( IN PCTSTR PrivilegeName, IN BOOL Enable ); VOID pFreeRestoreCallbacks ( VOID ); VOID pRecordUserData ( IN PCTSTR UserName, IN PCTSTR UserDomain, IN PCTSTR UserStringSid, IN PCTSTR UserProfilePath, IN BOOL ProfileCreated ); // // Macro expansion definition // // None // // Code // BOOL WINAPI DllMain ( IN HINSTANCE hInstance, IN DWORD dwReason, IN LPVOID lpReserved ) { if (dwReason == DLL_PROCESS_ATTACH) { g_hInst = hInstance; } return TRUE; } BOOL CheckCancel ( VOID ) { BOOL cancelled; if (g_EngineTerminated) { SetLastError (ERROR_REQUEST_ABORTED); DEBUGMSG ((DBG_ERROR, "CheckCancel called after engine was terminated")); return TRUE; } if (!g_EngineInitialized) { SetLastError (ERROR_REQUEST_ABORTED); DEBUGMSG ((DBG_WARNING, "Engine is not initialized")); return TRUE; } cancelled = (WaitForSingleObject (g_CancelEvent, 0) == WAIT_OBJECT_0); if (cancelled) { SetLastError (ERROR_CANCELLED); DEBUGMSG ((DBG_ISM, "Cancel signaled")); } return cancelled; } MIG_OBJECTTYPEID FixObjectTypeId ( IN MIG_OBJECTTYPEID ObjectTypeId ) { if ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_CURRENT) { return (ObjectTypeId | g_IsmCurrentPlatform); } return ObjectTypeId; } MIG_OBJECTTYPEID FixEnumerationObjectTypeId ( IN MIG_OBJECTTYPEID ObjectTypeId ) { if ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_CURRENT) { if (g_IsmModulePlatformContext == PLATFORM_CURRENT) { return (ObjectTypeId | g_IsmCurrentPlatform); } else { return (ObjectTypeId | g_IsmModulePlatformContext); } } return ObjectTypeId; } BOOL pEnablePrivilege ( IN PCTSTR PrivilegeName, IN BOOL Enable ) { HANDLE token; BOOL b; TOKEN_PRIVILEGES newPrivileges; LUID luid; if (ISWIN9X ()) { return TRUE; } if (!OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) { return FALSE; } if (!LookupPrivilegeValue (NULL, PrivilegeName, &luid)) { CloseHandle (token); return FALSE; } newPrivileges.PrivilegeCount = 1; newPrivileges.Privileges[0].Luid = luid; newPrivileges.Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0; b = AdjustTokenPrivileges( token, FALSE, &newPrivileges, 0, NULL, NULL ); CloseHandle (token); return b; } #ifdef PRERELEASE VOID LoadCrashHooks ( VOID ) { HINF crashInf; INFSTRUCT is = INITINFSTRUCT_PMHANDLE; PCTSTR typeName; PCTSTR objectName; crashInf = InfOpenInfFile (TEXT("c:\\crash.inf")); if (crashInf == INVALID_HANDLE_VALUE) { return; } if (InfFindFirstLine (crashInf, TEXT("TotalNumber"), NULL, &is)) { InfGetIntField (&is, 1, &g_CrashCountObjects); } if (InfFindFirstLine (crashInf, TEXT("TypeNumber"), NULL, &is)) { typeName = InfGetStringField (&is, 1); if (typeName) { g_CrashCountTypeId = IsmGetObjectTypeId (typeName); InfGetIntField (&is, 2, &g_CrashCountType); } } if (InfFindFirstLine (crashInf, TEXT("TypeObject"), NULL, &is)) { typeName = InfGetStringField (&is, 1); objectName = InfGetStringField (&is, 2); if (typeName && objectName) { g_CrashNameTypeId = IsmGetObjectTypeId (typeName); g_CrashNameObject = IsmGetMemory (SizeOfString (objectName)); StringCopy ((PTSTR)g_CrashNameObject, objectName); } } InfCleanUpInfStruct (&is); InfCloseInfFile (crashInf); } #endif BOOL pWriteIsmSig ( IN PCTSTR DirName ) { TCHAR tempName [MAX_PATH]; HANDLE tempHandle; DWORD tempSig = ISM_TMP_SIGNATURE; StringCopy (tempName, DirName); StringCopy (AppendWack (tempName), TEXT("USMT.TMP")); tempHandle = BfCreateFile (tempName); if (!tempHandle) { return FALSE; } if (!BfWriteFile (tempHandle, (PCBYTE)(&tempSig), sizeof (DWORD))) { CloseHandle (tempHandle); DeleteFile (tempName); return FALSE; } CloseHandle (tempHandle); return TRUE; } BOOL pReadIsmSig ( IN PCTSTR DirName ) { TCHAR tempName [MAX_PATH]; HANDLE tempHandle; DWORD tempSig; StringCopy (tempName, DirName); StringCopy (AppendWack (tempName), TEXT("USMT.TMP")); tempHandle = BfOpenReadFile (tempName); if (!tempHandle) { return FALSE; } if (!BfReadFile (tempHandle, (PBYTE)(&tempSig), sizeof (DWORD))) { CloseHandle (tempHandle); DeleteFile (tempName); return FALSE; } if (tempSig != ISM_TMP_SIGNATURE) { CloseHandle (tempHandle); DeleteFile (tempName); return FALSE; } CloseHandle (tempHandle); return TRUE; } BOOL pCreateTempStorage ( VOID ) { DRIVE_ENUM driveEnum; GROWBUFFER excludedDrv = INIT_GROWBUFFER; TCHAR driveName [4] = TEXT(""); DWORD sectPerClust; DWORD bytesPerSect; DWORD freeClusters; DWORD totalClusters; ULONGLONG maxFreeDiskSpace = 0; ULONGLONG freeDiskSpace = 0; UINT index = 0; PTSTR endStr = NULL; BOOL found = FALSE; BOOL hideDir = FALSE; // we are going to walk the fixed drives picking up the one // with the most available space. In the root we are going // to create a directory and mark it as ours by creating a // special file called USMT.TMP that will have a signature in it. // The directory name is normally USMT.TMP. If the directory // already exists and does not have our special file in it // we are going to pick another name (USMT%04d.TMP), otherwise // we are going to overwrite it. while (!found) { *driveName = 0; maxFreeDiskSpace = 0; if (EnumFirstDrive (&driveEnum, DRIVEENUM_FIXED)) { do { if (IsStrInMultiSz (driveEnum.DriveName, (PCTSTR)excludedDrv.Buf)) { continue; } freeDiskSpace = 0; if (GetDiskFreeSpace (driveEnum.DriveName, §PerClust, &bytesPerSect, &freeClusters, &totalClusters)) { freeDiskSpace = Int32x32To64 ((sectPerClust * bytesPerSect), freeClusters); } if (freeDiskSpace > maxFreeDiskSpace) { StringCopyTcharCount (driveName, driveEnum.DriveName, 4); maxFreeDiskSpace = freeDiskSpace; } } while (EnumNextDrive (&driveEnum)); } while (index < 0xFFFF) { if (*driveName) { StringCopy (g_GlobalTempDir, driveName); hideDir = TRUE; } else { GetTempPath (ARRAYSIZE(g_GlobalTempDir), g_GlobalTempDir); hideDir = FALSE; } if (index) { endStr = GetEndOfString (g_GlobalTempDir); wsprintf (endStr, TEXT("USMT%04X.TMP"), index); } else { StringCat (g_GlobalTempDir, TEXT("USMT.TMP")); } if (!DoesFileExist (g_GlobalTempDir)) { if (BfCreateDirectory (g_GlobalTempDir)) { if (pWriteIsmSig (g_GlobalTempDir)) { found = TRUE; if (hideDir) { SetFileAttributes (g_GlobalTempDir, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); } break; } } // If we are here, we failed to create the temp dir // on this drive. This should have succeeded so this // means that the drive is locked down somehow. if (*driveName) { // Let's bail out and add the drive to the exclude list. GbMultiSzAppend (&excludedDrv, driveName); } break; } if (pReadIsmSig (g_GlobalTempDir)) { if (FiRemoveAllFilesInTree (g_GlobalTempDir)) { if (BfCreateDirectory (g_GlobalTempDir)) { if (pWriteIsmSig (g_GlobalTempDir)) { found = TRUE; if (hideDir) { SetFileAttributes (g_GlobalTempDir, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); } break; } } // If we are here, we failed to create the temp dir // on this drive. This should have succeeded so this // means that the drive is locked down somehow. if (*driveName) { // Let's bail out and add the drive to the exclude list. GbMultiSzAppend (&excludedDrv, driveName); } break; } } index ++; } if (!(*driveName)) { break; } } GbFree (&excludedDrv); return found; } BOOL IsmGetTempStorage ( OUT PTSTR Path, IN UINT PathTchars ) { MYASSERT (*g_GlobalTempDir); if (*g_GlobalTempDir) { StringCopyTcharCount (Path, g_GlobalTempDir, PathTchars); return TRUE; } return FALSE; } BOOL IsmGetTempDirectory ( OUT PTSTR Path, IN UINT PathTchars ) { PTSTR endStr = NULL; if (!IsmGetTempStorage (Path, PathTchars)) { return FALSE; } endStr = GetEndOfString (Path); while (g_TempDirIndex < 0xFFFFFFFF) { wsprintf (endStr, TEXT("\\DIR%04X.TMP"), g_TempDirIndex); if (!DoesFileExist (Path)) { if (BfCreateDirectory (Path)) { g_TempDirIndex ++; return TRUE; } } g_TempDirIndex ++; } return FALSE; } BOOL IsmGetTempFile ( OUT PTSTR Path, IN UINT PathTchars ) { PTSTR endStr = NULL; if (!IsmGetTempStorage (Path, PathTchars)) { return FALSE; } endStr = GetEndOfString (Path); while (g_TempFileIndex < 0xFFFFFFFF) { wsprintf (endStr, TEXT("\\FILE%04X.TMP"), g_TempFileIndex); if (!DoesFileExist (Path)) { g_TempFileIndex ++; return TRUE; } g_TempFileIndex ++; } return FALSE; } BOOL IsmInitialize ( IN PCTSTR InfPath, IN PMESSAGECALLBACK MessageCallback, OPTIONAL IN PMIG_LOGCALLBACK LogCallback ) { BOOL result = FALSE; BOOL logInitError = FALSE; TCHAR memdbDir[MAX_TCHAR_PATH]; g_ExecutionInProgress = TRUE; __try { SetErrorMode (SEM_FAILCRITICALERRORS); // // Initialize utilities. They produce their own debug messages. // UtInitialize (NULL); LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback); if (!FileEnumInitialize ()) { logInitError = TRUE; __leave; } // Initialize the temporary storage if (!pCreateTempStorage ()) { logInitError = TRUE; __leave; } if (!IsmGetTempDirectory (memdbDir, ARRAYSIZE (memdbDir))) { logInitError = TRUE; __leave; } if (!MemDbInitializeEx (memdbDir)) { logInitError = TRUE; __leave; } if (!RegInitialize ()) { logInitError = TRUE; __leave; } RegInitializeCache (8); InfGlobalInit (FALSE); // // Turn on privileges // if (!pEnablePrivilege (SE_BACKUP_NAME, TRUE)) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_BACKUP_PRIVLEDGE)); __leave; } if (!pEnablePrivilege (SE_RESTORE_NAME, TRUE)) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_RESTORE_PRIVLEDGE)); __leave; } // // Initialize ISM globals // g_CancelEvent = CreateEvent (NULL, TRUE, FALSE, NULL); if (!g_CancelEvent) { DEBUGMSG ((DBG_ERROR, "Can't create cancel event")); __leave; } g_ActivityEvent = CreateEvent (NULL, TRUE, FALSE, NULL); if (!g_ActivityEvent) { DEBUGMSG ((DBG_ERROR, "Can't create activity event")); CloseHandle (g_CancelEvent); __leave; } g_TransportTable = HtAllocWithData (sizeof (PTRANSPORTDATA)); g_ControlFileTable = HtAlloc (); g_IsmInf = InfOpenInfFile (InfPath); if (g_IsmInf == INVALID_HANDLE_VALUE) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INVALID_ISM_INF, InfPath)); SetLastError (ERROR_FILE_NOT_FOUND); __leave; } if (!g_IsmPool) { g_IsmPool = PmCreateNamedPool ("ISM Pool"); } if (!g_IsmUntrackedPool) { g_IsmUntrackedPool = PmCreatePool (); PmDisableTracking (g_IsmUntrackedPool); } // // Initialize internal modules // if (!InitializeEnv ()) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 1)); __leave; } if (!InitializeFlowControl ()) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 3)); __leave; } PrepareEnumerationEnvironment (TRUE); if (!InitializeTypeMgr ()) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 2)); __leave; } if (!InitializeOperations ()) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 4)); __leave; } g_MessageCallback = MessageCallback; // // Set the journal location // IsmSetRollbackJournalType (TRUE); g_PreProcessTable = HtAllocWithData (sizeof (PCTSTR)); g_RefreshTable = HtAllocWithData (sizeof (PCTSTR)); g_PostProcessTable = HtAllocWithData (sizeof (PCTSTR)); g_EngineInitialized = TRUE; result = TRUE; } __finally { g_ExecutionInProgress = FALSE; if (!result) { IsmTerminate(); } } if (logInitError) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_ENGINE_INIT_FAILURE)); } return result; } BOOL IsmSetPlatform ( IN MIG_PLATFORMTYPEID Platform ) { OSVERSIONINFO versionInfo; MIG_OSVERSIONINFO migVerInfo; TCHAR tempStr [sizeof (UINT) * 2 + 3]; MIG_OBJECTSTRINGHANDLE tempHandle = NULL; if (Platform == PLATFORM_SOURCE) { if (!RegisterInternalAttributes ()) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 5)); return FALSE; } } // // write the source or the destination machine version information // in the environment // ZeroMemory (&versionInfo, sizeof (OSVERSIONINFO)); versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); ZeroMemory (&migVerInfo, sizeof (MIG_OSVERSIONINFO)); if (GetVersionEx (&versionInfo)) { if (versionInfo.dwPlatformId == 1) { migVerInfo.OsType = OSTYPE_WINDOWS9X; migVerInfo.OsTypeName = OSTYPE_WINDOWS9X_STR; if (versionInfo.dwMajorVersion == 4) { if (versionInfo.dwMinorVersion == 0) { migVerInfo.OsMajorVersion = OSMAJOR_WIN95; migVerInfo.OsMajorVersionName = OSMAJOR_WIN95_STR; migVerInfo.OsMinorVersion = OSMINOR_GOLD; migVerInfo.OsMinorVersionName = OSMINOR_GOLD_STR; if (LOWORD (versionInfo.dwBuildNumber) >= 1111) { migVerInfo.OsMajorVersion = OSMAJOR_WIN95OSR2; migVerInfo.OsMajorVersionName = OSMAJOR_WIN95OSR2_STR; } } else if (versionInfo.dwMinorVersion == 10) { migVerInfo.OsMajorVersion = OSMAJOR_WIN98; migVerInfo.OsMajorVersionName = OSMAJOR_WIN98_STR; migVerInfo.OsMinorVersion = OSMINOR_GOLD; migVerInfo.OsMinorVersionName = OSMINOR_GOLD_STR; if (LOWORD (versionInfo.dwBuildNumber) >= 2222) { migVerInfo.OsMinorVersion = OSMINOR_WIN98SE; migVerInfo.OsMinorVersionName = OSMINOR_WIN98SE_STR; } } else if (versionInfo.dwMinorVersion == 90) { migVerInfo.OsMajorVersion = OSMAJOR_WINME; migVerInfo.OsMajorVersionName = OSMAJOR_WINME_STR; migVerInfo.OsMinorVersion = OSMINOR_GOLD; migVerInfo.OsMinorVersionName = OSMINOR_GOLD_STR; } } } if (versionInfo.dwPlatformId == 2) { migVerInfo.OsType = OSTYPE_WINDOWSNT; migVerInfo.OsTypeName = OSTYPE_WINDOWSNT_STR; if (versionInfo.dwMajorVersion == 4) { migVerInfo.OsMajorVersion = OSMAJOR_WINNT4; migVerInfo.OsMajorVersionName = OSMAJOR_WINNT4_STR; migVerInfo.OsMinorVersion = versionInfo.dwMinorVersion; if (migVerInfo.OsMinorVersion == OSMINOR_GOLD) { migVerInfo.OsMinorVersionName = OSMINOR_GOLD_STR; } } if (versionInfo.dwMajorVersion == 5) { migVerInfo.OsMajorVersion = OSMAJOR_WINNT5; migVerInfo.OsMajorVersionName = OSMAJOR_WINNT5_STR; migVerInfo.OsMinorVersion = versionInfo.dwMinorVersion; if (migVerInfo.OsMinorVersion == OSMINOR_GOLD) { migVerInfo.OsMinorVersionName = OSMINOR_GOLD_STR; } else if (migVerInfo.OsMinorVersion == OSMINOR_WINNT51) { migVerInfo.OsMinorVersionName = OSMINOR_WINNT51_STR; } } } wsprintf (tempStr, TEXT("0x%08X"), migVerInfo.OsType); IsmSetEnvironmentString (Platform, NULL, S_VER_OSTYPE, tempStr); wsprintf (tempStr, TEXT("0x%08X"), migVerInfo.OsMajorVersion); IsmSetEnvironmentString (Platform, NULL, S_VER_OSMAJOR, tempStr); wsprintf (tempStr, TEXT("0x%08X"), migVerInfo.OsMinorVersion); IsmSetEnvironmentString (Platform, NULL, S_VER_OSMINOR, tempStr); wsprintf (tempStr, TEXT("0x%08X"), versionInfo.dwBuildNumber); IsmSetEnvironmentString (Platform, NULL, S_VER_OSBUILD, tempStr); } if (Platform == PLATFORM_SOURCE) { // let's exclude our temporary directory tempHandle = IsmCreateObjectHandle (g_GlobalTempDir, NULL); if (tempHandle) { IsmRegisterStaticExclusion (MIG_FILE_TYPE, tempHandle); IsmDestroyObjectHandle (tempHandle); tempHandle = NULL; } } g_IsmCurrentPlatform = Platform; return TRUE; } BOOL pPrepareUserJournal ( IN OUT PTEMPORARYPROFILE UserProfile ) { BOOL result = FALSE; DWORD tempField; PCTSTR journalFile = NULL; if (UserProfile && UserProfile->UserProfileRoot) { __try { UserProfile->DelayedOpJrn = JoinPaths (UserProfile->UserProfileRoot, TEXT("usrusmt2.tmp")); FiRemoveAllFilesInTree (UserProfile->DelayedOpJrn); if (!BfCreateDirectory (UserProfile->DelayedOpJrn)) { __leave; } journalFile = JoinPaths (UserProfile->DelayedOpJrn, TEXT("JOURNAL.DAT")); UserProfile->DelayedOpJrnHandle = BfCreateFile (journalFile); if (UserProfile->DelayedOpJrnHandle == INVALID_HANDLE_VALUE) { __leave; } tempField = JRN_USR_SIGNATURE; BfWriteFile (UserProfile->DelayedOpJrnHandle, (PBYTE)(&tempField), sizeof (DWORD)); tempField = JRN_USR_VERSION; BfWriteFile (UserProfile->DelayedOpJrnHandle, (PBYTE)(&tempField), sizeof (DWORD)); tempField = JRN_USR_DIRTY; BfWriteFile (UserProfile->DelayedOpJrnHandle, (PBYTE)(&tempField), sizeof (DWORD)); FlushFileBuffers (UserProfile->DelayedOpJrnHandle); FreePathString (journalFile); result = TRUE; } __finally { if (!result) { if (UserProfile->DelayedOpJrn) { FreePathString (UserProfile->DelayedOpJrn); UserProfile->DelayedOpJrn = NULL; } if (!UserProfile->DelayedOpJrnHandle || (UserProfile->DelayedOpJrnHandle == INVALID_HANDLE_VALUE)) { CloseHandle (UserProfile->DelayedOpJrnHandle); UserProfile->DelayedOpJrnHandle = NULL; } } } } return result; } BOOL pValidateUserJournal ( IN PTEMPORARYPROFILE UserProfile, IN BOOL RunKeyAdded ) { BOOL result = FALSE; DWORD tempField; __try { if (UserProfile->DelayedOpJrn) { if (RunKeyAdded) { if (UserProfile->DelayedOpJrnHandle && (UserProfile->DelayedOpJrnHandle != INVALID_HANDLE_VALUE)) { if (!BfSetFilePointer (UserProfile->DelayedOpJrnHandle, 2 * sizeof (DWORD))) { __leave; } tempField = JRN_USR_COMPLETE; BfWriteFile (UserProfile->DelayedOpJrnHandle, (PBYTE)(&tempField), sizeof (DWORD)); FlushFileBuffers (UserProfile->DelayedOpJrnHandle); result = TRUE; } } else { // Run key command was not added, no point to // keep this journal here FiRemoveAllFilesInTree (UserProfile->DelayedOpJrn); result = TRUE; } } } __finally { if (UserProfile->DelayedOpJrnHandle && (UserProfile->DelayedOpJrnHandle != INVALID_HANDLE_VALUE)) { CloseHandle (UserProfile->DelayedOpJrnHandle); UserProfile->DelayedOpJrnHandle = NULL; } if (UserProfile->DelayedOpJrn) { FreePathString (UserProfile->DelayedOpJrn); UserProfile->DelayedOpJrn = NULL; } } return result; } BOOL pWriteDelayedOperationsCommand ( IN PTEMPORARYPROFILE UserProfile ) { HKEY runKeyHandle = NULL; PCTSTR runKeyStr = NULL; LONG rc; BOOL result = FALSE; __try { if (!UserProfile->MapKey) { LOG ((LOG_ERROR, (PCSTR) MSG_NO_MAPPED_USER)); __leave; } runKeyStr = JoinPathsInPoolEx (( NULL, TEXT("HKEY_USERS"), UserProfile->MapKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), NULL )); runKeyHandle = CreateRegKeyStr (runKeyStr); if (!runKeyHandle) { LOG ((LOG_ERROR, (PCSTR) MSG_RUN_KEY_CREATE_FAILURE)); __leave; } rc = RegSetValueEx ( runKeyHandle, TEXT("USMT2RUN"), 0, REG_EXPAND_SZ, (PBYTE) g_DelayedOperationsCommand, SizeOfString (g_DelayedOperationsCommand) ); if (rc != ERROR_SUCCESS) { LOG ((LOG_ERROR, (PCSTR) MSG_RUN_KEY_CREATE_FAILURE)); __leave; } result = TRUE; } __finally { if (runKeyHandle) { CloseRegKey (runKeyHandle); runKeyHandle = NULL; } if (runKeyStr) { FreePathString (runKeyStr); runKeyStr = NULL; } } return result; } BOOL pDeleteDelayedOperationsCommand ( VOID ) { HKEY runKeyHandle = NULL; LONG rc; BOOL result = FALSE; __try { runKeyHandle = OpenRegKeyStr (TEXT("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run")); if (!runKeyHandle) { LOG ((LOG_ERROR, (PCSTR) MSG_RUN_KEY_DELETE_FAILURE)); __leave; } rc = RegDeleteValue ( runKeyHandle, TEXT("USMT2RUN") ); if (rc != ERROR_SUCCESS) { LOG ((LOG_ERROR, (PCSTR) MSG_RUN_KEY_DELETE_FAILURE)); __leave; } result = TRUE; } __finally { if (runKeyHandle) { CloseRegKey (runKeyHandle); runKeyHandle = NULL; } } return result; } VOID IsmTerminate ( VOID ) { HASHTABLE_ENUM e; BOOL runKeyAdded = FALSE; if (g_EngineTerminated) { g_EngineInitialized = FALSE; return; } // We need to try and terminate properties. In some cases the property file // remains opened. TerminateProperties (g_IsmCurrentPlatform); if (g_PreProcessTable) { if (EnumFirstHashTableString (&e, g_PreProcessTable)) { do { IsmReleaseMemory (*((PCTSTR *)e.ExtraData)); } while (EnumNextHashTableString (&e)); } HtFree (g_PreProcessTable); g_PreProcessTable = NULL; } if (g_RefreshTable) { if (EnumFirstHashTableString (&e, g_RefreshTable)) { do { if (!CheckCancel () && g_PreProcessDone) { IsmSendMessageToApp (ISMMESSAGE_EXECUTE_REFRESH, (ULONG_PTR) *((PCTSTR *)e.ExtraData)); } IsmReleaseMemory (*((PCTSTR *)e.ExtraData)); } while (EnumNextHashTableString (&e)); } HtFree (g_RefreshTable); g_RefreshTable = NULL; } if (g_PostProcessTable) { if (EnumFirstHashTableString (&e, g_PostProcessTable)) { do { if (g_PreProcessDone) { IsmSendMessageToApp (ISMMESSAGE_EXECUTE_POSTPROCESS, (ULONG_PTR) *((PCTSTR *)e.ExtraData)); } IsmReleaseMemory (*((PCTSTR *)e.ExtraData)); } while (EnumNextHashTableString (&e)); } HtFree (g_PostProcessTable); g_PostProcessTable = NULL; } g_PreProcessDone = FALSE; g_EngineInitialized = FALSE; g_ExecutionInProgress = TRUE; // // Terminate plug-in modules // TerminateProcessWideModules(); // // Clean up journal // if (g_JournalDirectory && !g_PreserveJournal) { if (DoesFileExist (g_JournalDirectory)) { if (!FiRemoveAllFilesInTree (g_JournalDirectory)) { DEBUGMSG ((DBG_ERROR, "Cannot remove journal directory: %s", g_JournalDirectory)); } } FreePathString (g_JournalDirectory); g_JournalDirectory = NULL; g_JournalUsed = FALSE; } if (g_TempProfile) { // let's write the Run key command line and set runKeyAdded to TRUE runKeyAdded = pWriteDelayedOperationsCommand (g_TempProfile); pValidateUserJournal (g_TempProfile, runKeyAdded); if (!CloseTemporaryProfile (g_TempProfile, g_MakeProfilePermanent)) { LOG (( LOG_MODULE_ERROR, (PCSTR) MSG_CANT_SAVE_PROFILE, g_TempProfile->UserName, GetLastError() )); CloseTemporaryProfile (g_TempProfile, FALSE); } g_TempProfile = NULL; } if (g_DelayedOperationsCommand) { FreePathString (g_DelayedOperationsCommand); g_DelayedOperationsCommand = NULL; } // // Terminate all control files // if (g_ControlFileTable) { if (EnumFirstHashTableString (&e, g_ControlFileTable)) { do { DeleteFile (e.String); } while (EnumNextHashTableString (&e)); } HtFree (g_ControlFileTable); g_ControlFileTable = NULL; } // // Terminate internal modules // ClearEnumerationEnvironment (TRUE); TerminateEnv (); TerminateTypeMgr (); TerminateFlowControl (); TerminateOperations (); // // Destroy globals // pFreeRestoreCallbacks (); if (g_CancelEvent) { CloseHandle (g_CancelEvent); g_CancelEvent = NULL; } if (g_ActivityEvent) { CloseHandle (g_ActivityEvent); g_ActivityEvent = NULL; } GbFree (&g_SliceBuffer); if (g_TransportTable) { HtFree (g_TransportTable); g_TransportTable = NULL; } if (g_IsmPool) { PmDestroyPool (g_IsmPool); g_IsmPool = NULL; } if (g_IsmUntrackedPool) { PmDestroyPool (g_IsmUntrackedPool); g_IsmUntrackedPool = NULL; } if (g_IsmInf != INVALID_HANDLE_VALUE) { InfCloseInfFile (g_IsmInf); g_IsmInf = INVALID_HANDLE_VALUE; } InfGlobalInit (TRUE); MemDbTerminateEx (TRUE); // relies on fileenum // let's remove the temporary storage, it's here because uses fileenum if (*g_GlobalTempDir) { if (!FiRemoveAllFilesInTree (g_GlobalTempDir)) { DEBUGMSG ((DBG_ERROR, "Cannot remove temporary storage: %s", g_GlobalTempDir)); } *g_GlobalTempDir = 0; } FileEnumTerminate (); RegTerminate (); UtTerminate (); g_EngineTerminated = TRUE; g_ExecutionInProgress = FALSE; } BOOL IsmPreserveJournal ( IN BOOL Preserve ) { BOOL result = g_PreserveJournal; g_PreserveJournal = Preserve; return result; } BOOL pEtmParse ( IN PVOID Reserved ) { HASHTABLE_ENUM e; BOOL b = TRUE; PETMDATA etmData; PrepareEnumerationEnvironment (FALSE); // // Call the parse entry point // if (EnumFirstHashTableString (&e, g_EtmTable)) { do { etmData = *((PETMDATA *) e.ExtraData); if (etmData->ShouldBeCalled && etmData->EtmParse) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = etmData->Group; b = etmData->EtmParse (Reserved); g_CurrentGroup = NULL; } } while (b && EnumNextHashTableString (&e)); } ClearEnumerationEnvironment (FALSE); return b; } BOOL pCreateComputerParse ( IN PVOID Reserved ) { HASHTABLE_ENUM e; BOOL b = TRUE; PVCMDATA vcmData; PrepareEnumerationEnvironment (FALSE); // // Call the parse entry point // if (EnumFirstHashTableString (&e, g_VcmTable)) { do { vcmData = *((PVCMDATA *) e.ExtraData); if (vcmData->ShouldBeCalled && vcmData->VcmParse) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = vcmData->Group; b = vcmData->VcmParse (Reserved); g_CurrentGroup = NULL; } } while (b && EnumNextHashTableString (&e)); } ClearEnumerationEnvironment (FALSE); return b; } BOOL pCreateComputerGather ( IN PVOID Reserved ) { HASHTABLE_ENUM e; BOOL b = TRUE; BOOL cancelled = FALSE; PVCMDATA vcmData; UINT containers; MIG_PROGRESSSLICEID sliceId; PrepareEnumerationEnvironment (FALSE); // // Queue high priority enumerations // if (b && EnumFirstHashTableString (&e, g_VcmTable)) { do { vcmData = *((PVCMDATA *) e.ExtraData); if (vcmData->ShouldBeCalled && vcmData->VcmQueueHighPriorityEnumeration) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = vcmData->Group; b = vcmData->VcmQueueHighPriorityEnumeration (Reserved); g_CurrentGroup = NULL; } } while (b && EnumNextHashTableString (&e)); } g_CurrentPhase = MIG_HIGHPRIORITYGATHER_PHASE; g_SliceBuffer.End = 0; containers = EstimateAllObjectEnumerations (0, FALSE); if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); // // Run high priority enumeration queue // if (b) { if (!DoAllObjectEnumerations (sliceId)) { DEBUGMSG ((DBG_ERROR, "Internal ISM Error during high priority object enumeration.")); b = FALSE; } } pCallProgressBar (MIG_END_PHASE); ClearEnumerationEnvironment (FALSE); PrepareEnumerationEnvironment (FALSE); // // Queue normal priority enumerations // if (b && EnumFirstHashTableString (&e, g_VcmTable)) { do { vcmData = *((PVCMDATA *) e.ExtraData); if (vcmData->ShouldBeCalled) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = vcmData->Group; b = vcmData->VcmQueueEnumeration (Reserved); g_CurrentGroup = NULL; } } while (b && EnumNextHashTableString (&e)); } g_CurrentPhase = MIG_GATHER_PHASE; g_SliceBuffer.End = 0; containers = EstimateAllObjectEnumerations (0, FALSE); if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); // // Run normal priority enumeration queue // if (b) { if (!DoAllObjectEnumerations (sliceId)) { DEBUGMSG ((DBG_ERROR, "Internal ISM Error during object enumeration.")); b = FALSE; } } ClearEnumerationEnvironment (FALSE); pCallProgressBar (MIG_END_PHASE); g_CurrentPhase = 0; g_SliceBuffer.End = 0; return b; } BOOL pSourceParse ( IN PVOID Reserved ) { HASHTABLE_ENUM e; BOOL b = TRUE; PSGMDATA sgmData; PrepareEnumerationEnvironment (FALSE); // // Call the parse entry point // if (b && EnumFirstHashTableString (&e, g_SgmTable)) { do { sgmData = *((PSGMDATA *) e.ExtraData); if (sgmData->ShouldBeCalled && sgmData->SgmParse) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = sgmData->Group; b = sgmData->SgmParse (Reserved); g_CurrentGroup = NULL; } } while (b && EnumNextHashTableString (&e)); } ClearEnumerationEnvironment (FALSE); return b; } BOOL pSourceGather ( IN PVOID Reserved ) { HASHTABLE_ENUM e; BOOL b = TRUE; BOOL cancelled = FALSE; PSGMDATA sgmData; UINT containers; MIG_PROGRESSSLICEID sliceId; PrepareEnumerationEnvironment (FALSE); // // Estimate the queue high priority enumerations // containers = 0; if (b && EnumFirstHashTableString (&e, g_SgmTable)) { do { sgmData = *((PSGMDATA *) e.ExtraData); if (sgmData->ShouldBeCalled && sgmData->SgmQueueHighPriorityEnumeration) { containers ++; } } while (b && EnumNextHashTableString (&e)); } // // Queue high priority enumerations // g_CurrentPhase = MIG_HIGHPRIORITYQUEUE_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); if (b && EnumFirstHashTableString (&e, g_SgmTable)) { do { sgmData = *((PSGMDATA *) e.ExtraData); if (sgmData->ShouldBeCalled && sgmData->SgmQueueHighPriorityEnumeration) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = sgmData->Group; b = sgmData->SgmQueueHighPriorityEnumeration (Reserved); g_CurrentGroup = NULL; // Call progress bar IsmTickProgressBar (sliceId, 1); } } while (b && EnumNextHashTableString (&e)); } pCallProgressBar (MIG_END_PHASE); // // Estimate the high priority enumerations estimate // containers = EstimateAllObjectEnumerations (0, TRUE); // // Estimate the high priority enumerations // g_CurrentPhase = MIG_HIGHPRIORITYESTIMATE_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); containers = EstimateAllObjectEnumerations (sliceId, FALSE); pCallProgressBar (MIG_END_PHASE); // // Run high priority enumeration queue // g_CurrentPhase = MIG_HIGHPRIORITYGATHER_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); if (b) { if (!DoAllObjectEnumerations (sliceId)) { DEBUGMSG ((DBG_ERROR, "Internal ISM Error during high priority object enumeration.")); b = FALSE; } } pCallProgressBar (MIG_END_PHASE); ClearEnumerationEnvironment (FALSE); PrepareEnumerationEnvironment (FALSE); // // Estimate the queue normal priority enumerations // containers = 0; if (b && EnumFirstHashTableString (&e, g_SgmTable)) { do { sgmData = *((PSGMDATA *) e.ExtraData); if (sgmData->ShouldBeCalled) { containers ++; } } while (b && EnumNextHashTableString (&e)); } // // Queue normal priority enumerations // g_CurrentPhase = MIG_GATHERQUEUE_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); if (b && EnumFirstHashTableString (&e, g_SgmTable)) { do { sgmData = *((PSGMDATA *) e.ExtraData); if (sgmData->ShouldBeCalled) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = sgmData->Group; b = sgmData->SgmQueueEnumeration (Reserved); g_CurrentGroup = NULL; // Call progress bar IsmTickProgressBar (sliceId, 1); } } while (b && EnumNextHashTableString (&e)); } pCallProgressBar (MIG_END_PHASE); // // Estimate the normal priority enumerations estimate // containers = EstimateAllObjectEnumerations (0, TRUE); // // Estimate the normal priority enumerations // g_CurrentPhase = MIG_GATHERESTIMATE_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); containers = EstimateAllObjectEnumerations (sliceId, FALSE); pCallProgressBar (MIG_END_PHASE); // // Run normal priority enumeration queue // g_CurrentPhase = MIG_GATHER_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); if (b) { if (!DoAllObjectEnumerations (sliceId)) { DEBUGMSG ((DBG_ERROR, "Internal ISM Error during object enumeration.")); b = FALSE; } } ClearEnumerationEnvironment (FALSE); pCallProgressBar (MIG_END_PHASE); g_CurrentPhase = 0; g_SliceBuffer.End = 0; return b; } BOOL pSourceAnalyze ( IN PVOID Reserved ) { HASHTABLE_ENUM e; BOOL b = TRUE; BOOL cancelled = FALSE; PSAMDATA samData; UINT modulesNeedingProgress = 0; MIG_PROGRESSSLICEID sliceId = 0; // // Prepare a progress bar // g_CurrentPhase = MIG_ANALYSIS_PHASE; g_SliceBuffer.End = 0; if (b && EnumFirstHashTableString (&e, g_SamTable)) { do { samData = *((PSAMDATA *) e.ExtraData); if (samData->ShouldBeCalled) { if (samData->SamEstimateProgressBar) { samData->SamEstimateProgressBar(); } else { modulesNeedingProgress++; } } } while (b && EnumNextHashTableString (&e)); } if (modulesNeedingProgress) { sliceId = IsmRegisterProgressSlice ( modulesNeedingProgress, modulesNeedingProgress * 10 ); } pCallProgressBar (MIG_BEGIN_PHASE); // // Run all the registered SAMs // if (b && EnumFirstHashTableString (&e, g_SamTable)) { do { samData = *((PSAMDATA *) e.ExtraData); if (samData->ShouldBeCalled) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = samData->Group; b = samData->SamExecute(); g_CurrentGroup = NULL; if (!samData->SamEstimateProgressBar) { if (!IsmTickProgressBar (sliceId, 1)) { b = FALSE; } } } } while (b && EnumNextHashTableString (&e)); } pCallProgressBar (MIG_END_PHASE); g_CurrentPhase = 0; g_SliceBuffer.End = 0; return b; } BOOL pDestinationGather ( IN PVOID Reserved ) { HASHTABLE_ENUM e; BOOL b = TRUE; BOOL cancelled = FALSE; PDGMDATA dgmData; UINT containers; MIG_PROGRESSSLICEID sliceId; PrepareEnumerationEnvironment (FALSE); // // Estimate the queue high priority enumerations // containers = 0; if (b && EnumFirstHashTableString (&e, g_DgmTable)) { do { dgmData = *((PDGMDATA *) e.ExtraData); if (dgmData->ShouldBeCalled && dgmData->DgmQueueHighPriorityEnumeration) { containers ++; } } while (b && EnumNextHashTableString (&e)); } // // Queue high priority enumerations // g_CurrentPhase = MIG_HIGHPRIORITYQUEUE_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); if (b && EnumFirstHashTableString (&e, g_DgmTable)) { do { dgmData = *((PDGMDATA *) e.ExtraData); if (dgmData->ShouldBeCalled && dgmData->DgmQueueHighPriorityEnumeration) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = dgmData->Group; b = dgmData->DgmQueueHighPriorityEnumeration (Reserved); g_CurrentGroup = NULL; // Call progress bar IsmTickProgressBar (sliceId, 1); } } while (b && EnumNextHashTableString (&e)); } pCallProgressBar (MIG_END_PHASE); // // Estimate the high priority enumerations estimate // containers = EstimateAllObjectEnumerations (0, TRUE); // // Estimate the high priority enumerations // g_CurrentPhase = MIG_HIGHPRIORITYESTIMATE_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); containers = EstimateAllObjectEnumerations (sliceId, FALSE); pCallProgressBar (MIG_END_PHASE); // // Run high priority enumeration queue // g_CurrentPhase = MIG_HIGHPRIORITYGATHER_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); if (b) { if (!DoAllObjectEnumerations (sliceId)) { DEBUGMSG ((DBG_ERROR, "Internal ISM Error during high priority object enumeration.")); b = FALSE; } } pCallProgressBar (MIG_END_PHASE); ClearEnumerationEnvironment (FALSE); PrepareEnumerationEnvironment (FALSE); // // Estimate the queue normal priority enumerations // containers = 0; if (b && EnumFirstHashTableString (&e, g_DgmTable)) { do { dgmData = *((PDGMDATA *) e.ExtraData); if (dgmData->ShouldBeCalled) { containers ++; } } while (b && EnumNextHashTableString (&e)); } // // Queue normal priority enumerations // g_CurrentPhase = MIG_GATHERQUEUE_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); if (b && EnumFirstHashTableString (&e, g_DgmTable)) { do { dgmData = *((PDGMDATA *) e.ExtraData); if (dgmData->ShouldBeCalled) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = dgmData->Group; b = dgmData->DgmQueueEnumeration (Reserved); g_CurrentGroup = NULL; // Call progress bar IsmTickProgressBar (sliceId, 1); } } while (b && EnumNextHashTableString (&e)); } pCallProgressBar (MIG_END_PHASE); // // Estimate the normal priority enumerations estimate // containers = EstimateAllObjectEnumerations (0, TRUE); // // Estimate the normal priority enumerations // g_CurrentPhase = MIG_GATHERESTIMATE_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); containers = EstimateAllObjectEnumerations (sliceId, FALSE); pCallProgressBar (MIG_END_PHASE); // // Run normal priority enumeration queue // g_CurrentPhase = MIG_GATHER_PHASE; g_SliceBuffer.End = 0; if (containers) { sliceId = IsmRegisterProgressSlice (containers, containers * 5); } else { sliceId = 0; } pCallProgressBar (MIG_BEGIN_PHASE); if (b) { if (!DoAllObjectEnumerations (sliceId)) { DEBUGMSG ((DBG_ERROR, "Internal ISM Error during object enumeration.")); b = FALSE; } } ClearEnumerationEnvironment (FALSE); pCallProgressBar (MIG_END_PHASE); g_CurrentPhase = 0; g_SliceBuffer.End = 0; return b; } BOOL ShouldObjectBeRestored ( IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTID ObjectId, IN MIG_OBJECTSTRINGHANDLE ObjectName ) /*++ Routine Description: ShouldObjectBeRestored determines if a specific object should be restored at all. It first checks if the object is marked for apply, and then checks all restore callbacks to allow them to deny the restore. Arguments: ObjectTypeId - Specifies the object type ObjectId - Specifies the numeric ID of the object ObjectName - Specifies the encoded node and leaf of the object Return Value: TRUE if the object should be restored, FALSE otherwise --*/ { BOOL result = TRUE; MIG_RESTORECALLBACK_ENUM restoreEnum; // // Is object marked for apply? // if (!IsmIsApplyObjectId (ObjectId)) { return FALSE; } // // Call callbacks to allow them to deny restore // if (EnumFirstRestoreCallback (&restoreEnum)) { do { if (!restoreEnum.RestoreCallback (ObjectTypeId, ObjectId, ObjectName)) { result = FALSE; break; } } while (EnumNextRestoreCallback (&restoreEnum)); } return result; } BOOL pDestinationAnalyze ( IN PVOID Reserved ) { HASHTABLE_ENUM e; BOOL b = TRUE; BOOL cancelled = FALSE; PDAMDATA damData; PCSMDATA csmData; UINT modulesNeedingProgress = 0; MIG_PROGRESSSLICEID sliceId = 0; // // Prepare a progress bar // g_CurrentPhase = MIG_ANALYSIS_PHASE; g_SliceBuffer.End = 0; if (EnumFirstHashTableString (&e, g_DamTable)) { do { damData = *((PDAMDATA *) e.ExtraData); if (damData->ShouldBeCalled) { if (damData->DamEstimateProgressBar) { damData->DamEstimateProgressBar(); } else { modulesNeedingProgress++; } } } while (EnumNextHashTableString (&e)); } if (EnumFirstHashTableString (&e, g_CsmTable)) { do { csmData = *((PCSMDATA *) e.ExtraData); if (csmData->ShouldBeCalled) { if (csmData->CsmEstimateProgressBar) { csmData->CsmEstimateProgressBar(); } else { modulesNeedingProgress++; } } } while (EnumNextHashTableString (&e)); } if (modulesNeedingProgress) { sliceId = IsmRegisterProgressSlice ( modulesNeedingProgress, modulesNeedingProgress * 10 ); } pCallProgressBar (MIG_BEGIN_PHASE); // // Run all the registered DAMs // if (EnumFirstHashTableString (&e, g_DamTable)) { do { damData = *((PDAMDATA *) e.ExtraData); if (damData->ShouldBeCalled) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = damData->Group; b = damData->DamExecute(); g_CurrentGroup = NULL; if (!damData->DamEstimateProgressBar) { if (!IsmTickProgressBar (sliceId, 1)) { b = FALSE; } } } } while (b && EnumNextHashTableString (&e)); } // // Run all the registered CSMs // if (EnumFirstHashTableString (&e, g_CsmTable)) { do { csmData = *((PCSMDATA *) e.ExtraData); if (csmData->ShouldBeCalled) { MYASSERT (!g_CurrentGroup); g_CurrentGroup = csmData->Group; b = csmData->CsmExecute(); g_CurrentGroup = NULL; if (!csmData->CsmEstimateProgressBar) { if (!IsmTickProgressBar (sliceId, 1)) { b = FALSE; } } } } while (b && EnumNextHashTableString (&e)); } pCallProgressBar (MIG_END_PHASE); g_CurrentPhase = 0; g_SliceBuffer.End = 0; return b; } BOOL pTestShortFileName ( IN PCTSTR FileName, IN PCTSTR TempDir ) { PCTSTR testFileName; HANDLE fileHandle; WIN32_FIND_DATA fileInfo; BOOL result = FALSE; testFileName = JoinPaths (TempDir, FileName); fileHandle = BfCreateFile (testFileName); if (fileHandle) { CloseHandle (fileHandle); if (DoesFileExistEx (testFileName, &fileInfo)) { result = (fileInfo.cAlternateFileName [0] == 0) || StringIMatch (fileInfo.cFileName, fileInfo.cAlternateFileName); } DeleteFile (testFileName); } FreePathString (testFileName); return result; } BOOL pIsShortFileName ( IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE ObjectName, IN PCTSTR TempDir, IN PCTSTR FullKeyName, IN OUT KEYHANDLE *KeyHandle ) { PCTSTR node, leaf; PTSTR nodePtr; PTSTR fullKeyName; MEMDB_ENUM memDbEnum; BOOL result = FALSE; if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) { if (leaf) { result = pTestShortFileName (leaf, TempDir); } else { fullKeyName = DuplicatePathString (FullKeyName, 0); nodePtr = _tcsrchr (fullKeyName, TEXT('\\')); if (nodePtr) { *nodePtr = 0; nodePtr = _tcsrchr (fullKeyName, TEXT('\\')); if (nodePtr) { result = pTestShortFileName (nodePtr, TempDir); if (!result && MemDbEnumFirst (&memDbEnum, fullKeyName, ENUMFLAG_ALL, ENUMLEVEL_LASTLEVEL, ENUMLEVEL_ALLLEVELS)) { *KeyHandle = memDbEnum.KeyHandle; MemDbAbortEnum (&memDbEnum); } else { result = TRUE; } } } FreePathString (fullKeyName); } IsmDestroyObjectString (node); IsmDestroyObjectString (leaf); } return result; } BOOL pFixFileEnumerationOrder ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR TempDir ) { MIG_OBJECTTYPEID objectTypeId; PCTSTR decoratedPath; MEMDB_ENUM memDbEnum; GROWBUFFER moveHandles = INIT_GROWBUFFER; KEYHANDLE keyHandle; PDWORD moveHandle = NULL; BOOL result = FALSE; objectTypeId = MIG_FILE_TYPE | Platform; decoratedPath = GetDecoratedObjectPathFromName (objectTypeId, TEXT("*"), TRUE); if (decoratedPath) { if (MemDbEnumFirst (&memDbEnum, decoratedPath, ENUMFLAG_NORMAL, 1, ENUMLEVEL_ALLLEVELS)) { do { if (IsmCheckCancel()) { return FALSE; } keyHandle = memDbEnum.KeyHandle; if (!pIsShortFileName (objectTypeId, memDbEnum.KeyName, TempDir, memDbEnum.FullKeyName, &keyHandle)) { GbAppendDword (&moveHandles, keyHandle); } } while (MemDbEnumNext (&memDbEnum)); } GbAppendDword (&moveHandles, 0); moveHandle = (PDWORD)moveHandles.Buf; while (*moveHandle) { if (IsmCheckCancel()) { return FALSE; } MemDbMoveKeyHandleToEnd (*moveHandle); moveHandle ++; } FreePathString (decoratedPath); } GbFree (&moveHandles); return result; } BOOL pDestinationApply ( IN PVOID Reserved ) { BOOL b = TRUE; BOOL cancelled = FALSE; MIG_OBJECTTYPEID objTypeId; MIG_OBJECT_ENUM objectEnum; MIG_OBJECTSTRINGHANDLE objPattern = NULL; BOOL toProcess = FALSE; MIG_PROGRESSSLICEID sliceId = 0; UINT ticks; LONG failCode; BOOL runKeyAdded = FALSE; MIG_OBJECTTYPEID fileTypeId; TCHAR tempDir [MAX_PATH] = TEXT(""); BOOL deleteFailed = FALSE; TCHAR delayedDeleteKey [] = TEXT("DelayedDelete"); KEYHANDLE delayedDeleteHandle; MIG_OBJECTID delayedDeleteId; PUINT delayedDeleteList; UINT delayedDeleteListNo; UINT delayedDeleteIndex; MIG_OBJECTSTRINGHANDLE delayedObjectName = NULL; MIG_OBJECTTYPEID delayedObjectTypeId; HASHTABLE_ENUM e; ERRUSER_EXTRADATA extraData; g_CurrentPhase = MIG_APPLY_PHASE; g_SliceBuffer.End = 0; ticks = g_DestinationObjects.TotalObjects + g_SourceObjects.TotalObjects + g_DestinationObjects.TotalObjects; if (ticks) { sliceId = IsmRegisterProgressSlice (ticks, max (1, ticks / 10)); } else { sliceId = IsmRegisterProgressSlice (1, 30); } pCallProgressBar (MIG_BEGIN_PHASE); // let's execute PreProcess functions if (g_PreProcessTable) { if (EnumFirstHashTableString (&e, g_PreProcessTable)) { do { IsmSendMessageToApp (ISMMESSAGE_EXECUTE_PREPROCESS, (ULONG_PTR) *((PCTSTR *)e.ExtraData)); } while (EnumNextHashTableString (&e)); } } g_PreProcessDone = TRUE; IsmGetTempDirectory (tempDir, ARRAYSIZE(tempDir)); fileTypeId = MIG_FILE_TYPE; // // Special code for file type (short/long issue) // pFixFileEnumerationOrder (PLATFORM_SOURCE, tempDir); pFixFileEnumerationOrder (PLATFORM_DESTINATION, tempDir); // // Now we are going to execute an ISM driven restore // objPattern = IsmCreateSimpleObjectPattern (NULL, TRUE, NULL, TRUE); // // Enumerate and process high priority operations for all objects on the // right side of the tree // failCode = ERROR_SUCCESS; objTypeId = IsmGetFirstObjectTypeId (); while (objTypeId) { objTypeId |= PLATFORM_DESTINATION; if (CanObjectTypeBeRestored (objTypeId)) { delayedDeleteHandle = MemDbAddKey (delayedDeleteKey); if (pEnumFirstVirtualObject (&objectEnum, objTypeId, objPattern)) { do { toProcess = ShouldObjectBeRestored ( objTypeId, objectEnum.ObjectId, objectEnum.ObjectName ); if (toProcess) { if (!RestoreObject ( objTypeId, objectEnum.ObjectName, NULL, OP_HIGH_PRIORITY, &deleteFailed )) { failCode = GetLastError(); if (failCode != ERROR_SUCCESS) { LOG (( IsmIsNonCriticalObjectId (objectEnum.ObjectId)?LOG_WARNING:LOG_ERROR, (PCSTR) MSG_CANT_RESTORE_SOURCE_OBJECT, IsmGetObjectTypeName (objTypeId), IsmGetNativeObjectName (objTypeId, objectEnum.ObjectName) )); failCode = ERROR_SUCCESS; } } if (deleteFailed && delayedDeleteHandle) { delayedDeleteId = IsmGetObjectIdFromName (objTypeId, objectEnum.ObjectName, TRUE); if (delayedDeleteId) { MemDbAddSingleLinkageByKeyHandle ( delayedDeleteHandle, delayedDeleteId, 0 ); } } } if (ticks) { if (!IsmTickProgressBar (sliceId, 1)) { failCode = ERROR_CANCELLED; break; } ticks--; } else if (CheckCancel()) { failCode = ERROR_CANCELLED; break; } } while (pEnumNextVirtualObject (&objectEnum)); } if (delayedDeleteHandle) { // OK, now let's see if we have some delayed delete here delayedDeleteList = MemDbGetSingleLinkageArrayByKeyHandle ( delayedDeleteHandle, 0, &delayedDeleteListNo ); delayedDeleteListNo /= SIZEOF(KEYHANDLE); if ((delayedDeleteList) && (delayedDeleteListNo > 0)) { delayedDeleteIndex = delayedDeleteListNo; do { delayedDeleteIndex --; delayedDeleteId = *(delayedDeleteList + delayedDeleteIndex); delayedObjectName = MemDbGetKeyFromHandle ((KEYHANDLE) delayedDeleteId, 1); if (delayedObjectName) { if (MemDbGetValueByHandle ((KEYHANDLE) delayedDeleteId, &delayedObjectTypeId)) { // now we have everything to retry the delete if (!RestoreObject ( delayedObjectTypeId, delayedObjectName, NULL, OP_HIGH_PRIORITY, NULL )) { failCode = GetLastError(); if (failCode != ERROR_SUCCESS) { LOG (( IsmIsNonCriticalObject (delayedObjectTypeId, delayedObjectName)?LOG_WARNING:LOG_ERROR, (PCSTR) MSG_CANT_RESTORE_SOURCE_OBJECT, IsmGetObjectTypeName (objTypeId), IsmGetNativeObjectName (objTypeId, objectEnum.ObjectName) )); failCode = ERROR_SUCCESS; } } } MemDbReleaseMemory (delayedObjectName); } } while (delayedDeleteIndex > 0); MemDbReleaseMemory (delayedDeleteList); } } MemDbDeleteKey (delayedDeleteKey); } if (failCode != ERROR_SUCCESS) { IsmAbortObjectEnum (&objectEnum); SetLastError (failCode); if (tempDir [0]) { FiRemoveAllFilesInTree (tempDir); } return FALSE; } objTypeId &= (~PLATFORM_MASK); objTypeId = IsmGetNextObjectTypeId (objTypeId); } // // Enumerate and process high priority and low priority operations for all objects on the // left side of the tree // failCode = ERROR_SUCCESS; objTypeId = IsmGetFirstObjectTypeId (); while (objTypeId) { objTypeId |= PLATFORM_SOURCE; if (CanObjectTypeBeRestored (objTypeId)) { if (pEnumFirstVirtualObject (&objectEnum, objTypeId, objPattern)) { do { toProcess = ShouldObjectBeRestored ( objTypeId, objectEnum.ObjectId, objectEnum.ObjectName ); if (toProcess) { if (!RestoreObject ( objTypeId, objectEnum.ObjectName, NULL, OP_ALL_PRIORITY, NULL )) { failCode = GetLastError(); if (failCode != ERROR_SUCCESS) { LOG (( IsmIsNonCriticalObjectId (objectEnum.ObjectId)?LOG_WARNING:LOG_ERROR, (PCSTR) MSG_CANT_RESTORE_SOURCE_OBJECT, IsmGetObjectTypeName (objTypeId), IsmGetNativeObjectName (objTypeId, objectEnum.ObjectName) )); failCode = ERROR_SUCCESS; extraData.Error = ERRUSER_ERROR_CANTRESTOREOBJECT; extraData.ErrorArea = ERRUSER_AREA_RESTORE; extraData.ObjectTypeId = objTypeId; extraData.ObjectName = objectEnum.ObjectName; IsmSendMessageToApp (MODULEMESSAGE_DISPLAYWARNING, (ULONG_PTR)(&extraData)); } } } if (ticks) { if (!IsmTickProgressBar (sliceId, 1)) { failCode = ERROR_CANCELLED; break; } ticks--; } else if (CheckCancel()) { failCode = ERROR_CANCELLED; break; } } while (pEnumNextVirtualObject (&objectEnum)); } } if (failCode != ERROR_SUCCESS) { IsmAbortObjectEnum (&objectEnum); SetLastError (failCode); if (tempDir [0]) { FiRemoveAllFilesInTree (tempDir); } return FALSE; } objTypeId &= (~PLATFORM_MASK); objTypeId = IsmGetNextObjectTypeId (objTypeId); } // // Enumerate and process low priority operation for all objects on the // right side of the tree // failCode = ERROR_SUCCESS; objTypeId = IsmGetFirstObjectTypeId (); while (objTypeId) { objTypeId |= PLATFORM_DESTINATION; if (CanObjectTypeBeRestored (objTypeId)) { delayedDeleteHandle = MemDbAddKey (delayedDeleteKey); if (pEnumFirstVirtualObject (&objectEnum, objTypeId, objPattern)) { do { toProcess = ShouldObjectBeRestored ( objTypeId, objectEnum.ObjectId, objectEnum.ObjectName ); if (toProcess) { if (!RestoreObject ( objTypeId, objectEnum.ObjectName, NULL, OP_LOW_PRIORITY, &deleteFailed )) { failCode = GetLastError(); if (failCode != ERROR_SUCCESS) { LOG (( IsmIsNonCriticalObjectId (objectEnum.ObjectId)?LOG_WARNING:LOG_ERROR, (PCSTR) MSG_CANT_RESTORE_SOURCE_OBJECT, IsmGetObjectTypeName (objTypeId), IsmGetNativeObjectName (objTypeId, objectEnum.ObjectName) )); failCode = ERROR_SUCCESS; } } if (deleteFailed && delayedDeleteHandle) { delayedDeleteId = IsmGetObjectIdFromName (objTypeId, objectEnum.ObjectName, TRUE); if (delayedDeleteId) { MemDbAddSingleLinkageByKeyHandle ( delayedDeleteHandle, delayedDeleteId, 0 ); } } } if (ticks) { if (!IsmTickProgressBar (sliceId, 1)) { failCode = ERROR_CANCELLED; break; } ticks--; } else if (CheckCancel()) { failCode = ERROR_CANCELLED; break; } } while (pEnumNextVirtualObject (&objectEnum)); } if (delayedDeleteHandle) { // OK, now let's see if we have some delayed delete here delayedDeleteList = MemDbGetSingleLinkageArrayByKeyHandle ( delayedDeleteHandle, 0, &delayedDeleteListNo ); delayedDeleteListNo /= SIZEOF(KEYHANDLE); if ((delayedDeleteList) && (delayedDeleteListNo > 0)) { delayedDeleteIndex = delayedDeleteListNo; do { delayedDeleteIndex --; delayedDeleteId = *(delayedDeleteList + delayedDeleteIndex); delayedObjectName = MemDbGetKeyFromHandle ((KEYHANDLE) delayedDeleteId, 1); if (delayedObjectName) { if (MemDbGetValueByHandle ((KEYHANDLE) delayedDeleteId, &delayedObjectTypeId)) { // now we have everything to retry the delete if (!RestoreObject ( delayedObjectTypeId, delayedObjectName, NULL, OP_LOW_PRIORITY, NULL )) { failCode = GetLastError(); if (failCode != ERROR_SUCCESS) { LOG (( IsmIsNonCriticalObject (delayedObjectTypeId, delayedObjectName)?LOG_WARNING:LOG_ERROR, (PCSTR) MSG_CANT_RESTORE_SOURCE_OBJECT, IsmGetObjectTypeName (objTypeId), IsmGetNativeObjectName (objTypeId, objectEnum.ObjectName) )); failCode = ERROR_SUCCESS; } } } MemDbReleaseMemory (delayedObjectName); } } while (delayedDeleteIndex > 0); MemDbReleaseMemory (delayedDeleteList); } } MemDbDeleteKey (delayedDeleteKey); } if (failCode != ERROR_SUCCESS) { IsmAbortObjectEnum (&objectEnum); SetLastError (failCode); if (tempDir [0]) { FiRemoveAllFilesInTree (tempDir); } return FALSE; } objTypeId &= (~PLATFORM_MASK); objTypeId = IsmGetNextObjectTypeId (objTypeId); } g_MakeProfilePermanent = TRUE; IsmDestroyObjectHandle (objPattern); pCallProgressBar (MIG_END_PHASE); g_CurrentPhase = 0; g_SliceBuffer.End = 0; if (tempDir [0]) { FiRemoveAllFilesInTree (tempDir); } return b; } MIG_TRANSPORTSTORAGEID IsmRegisterTransport ( IN PCTSTR TypeString ) { MIG_TRANSPORTSTORAGEID transportStorageId; PCTSTR memdbKey; memdbKey = JoinPaths (S_TRANSPORT_TYPES, TypeString); transportStorageId = (MIG_TRANSPORTSTORAGEID) MemDbSetKey (memdbKey); FreePathString (memdbKey); if (!transportStorageId) { DEBUGMSG ((DBG_ISM, "Unable to set memdb key in IsmRegisterTransport")); EngineError (); } return transportStorageId; } BOOL pEnumFirstTransportType ( OUT PMEMDB_ENUM EnumPtr ) { PCTSTR memdbPattern; BOOL b; memdbPattern = JoinPaths (S_TRANSPORT_TYPES, TEXT("*")); b = MemDbEnumFirst ( EnumPtr, memdbPattern, ENUMFLAG_NORMAL, ENUMLEVEL_ALLLEVELS, ENUMLEVEL_ALLLEVELS ); FreePathString (memdbPattern); return b; } BOOL pEnumNextTransportType ( IN OUT PMEMDB_ENUM EnumPtr ) { return MemDbEnumNext (EnumPtr); } VOID pAbortTransportTypeEnum ( IN PMEMDB_ENUM EnumPtr ) { MemDbAbortEnum (EnumPtr); } BOOL IsmEnumFirstTransport ( OUT PMIG_TRANSPORTENUM Enum, IN MIG_TRANSPORTSTORAGEID DesiredStorageId OPTIONAL ) { PTRANSPORTENUMHANDLE handle; BOOL b; ZeroMemory (Enum, sizeof (MIG_TRANSPORTENUM)); Enum->Handle = MemAllocZeroed (sizeof (TRANSPORTENUMHANDLE)); handle = (PTRANSPORTENUMHANDLE) Enum->Handle; handle->DesiredStorageId = DesiredStorageId; b = EnumFirstHashTableString (&handle->TableEnum, g_TransportTable); if (!b) { IsmAbortTransportEnum (Enum); return FALSE; } handle->State = TESTATE_BEGINTRANSPORT; return IsmEnumNextTransport (Enum); } BOOL IsmEnumNextTransport ( IN OUT PMIG_TRANSPORTENUM Enum ) { PTRANSPORTENUMHANDLE handle; PTRANSPORTDATA transportData; handle = (PTRANSPORTENUMHANDLE) Enum->Handle; if (!handle) { return FALSE; } for (;;) { switch (handle->State) { case TESTATE_BEGINTRANSPORT: // // Begin enumeration of all registered types // if (!pEnumFirstTransportType (&handle->MemDbEnum)) { handle->State = TESTATE_NEXTTRANSPORT; } else { handle->State = TESTATE_GETCAPS; } break; case TESTATE_GETCAPS: transportData = *((PTRANSPORTDATA *) handle->TableEnum.ExtraData); if (!transportData) { handle->State = TESTATE_NEXTTRANSPORT; } else { MYASSERT (transportData->TransportQueryCapabilities); if (handle->DesiredStorageId && handle->DesiredStorageId != (MIG_TRANSPORTSTORAGEID) handle->MemDbEnum.KeyHandle ) { handle->State = TESTATE_NEXTTRANSPORTTYPE; } else { if (!transportData->TransportQueryCapabilities ( (MIG_TRANSPORTSTORAGEID) handle->MemDbEnum.KeyHandle, &Enum->TransportType, &Enum->Capabilities, &Enum->FriendlyDescription )) { handle->State = TESTATE_NEXTTRANSPORTTYPE; } else { handle->State = TESTATE_RETURN; } } } break; case TESTATE_RETURN: Enum->TransportId = (MIG_TRANSPORTID) handle->TableEnum.Index; Enum->SupportedStorageId = (MIG_TRANSPORTSTORAGEID) handle->MemDbEnum.KeyHandle; handle->State = TESTATE_NEXTTRANSPORTTYPE; return TRUE; case TESTATE_NEXTTRANSPORTTYPE: if (!pEnumNextTransportType (&handle->MemDbEnum)) { pAbortTransportTypeEnum (&handle->MemDbEnum); handle->State = TESTATE_NEXTTRANSPORT; } else { handle->State = TESTATE_GETCAPS; } break; case TESTATE_NEXTTRANSPORT: if (!EnumNextHashTableString (&handle->TableEnum)) { handle->State = TESTATE_DONE; } else { handle->State = TESTATE_BEGINTRANSPORT; } break; case TESTATE_DONE: IsmAbortTransportEnum (Enum); return FALSE; } } } VOID IsmAbortTransportEnum ( IN PMIG_TRANSPORTENUM Enum ) { PTRANSPORTENUMHANDLE handle = (PTRANSPORTENUMHANDLE) Enum->Handle; if (handle) { pAbortTransportTypeEnum (&handle->MemDbEnum); FreeAlloc (handle); INVALID_POINTER (handle); } ZeroMemory (Enum, sizeof (MIG_TRANSPORTENUM)); } MIG_TRANSPORTID IsmSelectTransport ( IN MIG_TRANSPORTSTORAGEID DesiredStorageId, IN MIG_TRANSPORTTYPE TransportType, IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities ) { MIG_TRANSPORTENUM e; MIG_TRANSPORTID result = 0; if (!DesiredStorageId) { return 0; } if (IsmEnumFirstTransport (&e, DesiredStorageId)) { do { if (e.TransportType != TransportType) { continue; } if ((e.Capabilities & RequiredCapabilities) == RequiredCapabilities) { result = e.TransportId; IsmAbortTransportEnum (&e); g_TransportType = TransportType; return result; } } while (IsmEnumNextTransport (&e)); } DEBUGMSG ((DBG_ISM, "IsmSelectTransport: Requested transport type does not exist")); return result; } BOOL IsmSetTransportStorage ( IN MIG_PLATFORMTYPEID Platform, IN MIG_TRANSPORTID TransportId, IN MIG_TRANSPORTSTORAGEID DesiredStorageId, IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities, IN PCTSTR StoragePath, OUT PBOOL StoragePathIsValid, OPTIONAL OUT PBOOL ImageExistsInStorage OPTIONAL ) { PTRANSPORTDATA *ptrToTransportData; PTRANSPORTDATA transportData; BOOL b; BOOL valid; BOOL exists; PCTSTR sanitizedPath = NULL; if (!TransportId) { return FALSE; } if (!HtGetExtraData (g_TransportTable, (HASHITEM) TransportId, (PVOID *) &ptrToTransportData)) { return FALSE; } transportData = *ptrToTransportData; if (!transportData || !transportData->ShouldBeCalled) { return FALSE; } MYASSERT (transportData->TransportSetStorage); if (Platform == PLATFORM_CURRENT) { Platform = g_IsmCurrentPlatform; } if (g_SelectedTransport) { if (g_SelectedTransport->TransportResetStorage) { g_SelectedTransport->TransportResetStorage (g_SelectedTransportId); } g_SelectedTransport = NULL; g_SelectedTransportId = 0; } if (StoragePath) { sanitizedPath = SanitizePath (StoragePath); } b = transportData->TransportSetStorage ( Platform, DesiredStorageId, RequiredCapabilities, sanitizedPath, &valid, &exists ); if (sanitizedPath) { FreePathString (sanitizedPath); } if (b) { if (StoragePathIsValid) { *StoragePathIsValid = valid; } if (ImageExistsInStorage) { *ImageExistsInStorage = exists; } g_SelectedTransport = transportData; g_SelectedTransportId = DesiredStorageId; } return b; } BOOL IsmExecute ( MIG_EXECUTETYPEID ExecuteType ) { static BOOL srcInitCompleted = FALSE; static BOOL destInitCompleted = FALSE; static BOOL vcmInitCompleted = FALSE; static BOOL srcModuleInitCompleted = FALSE; static BOOL destModuleInitCompleted = FALSE; static BOOL rollbackInitCompleted = FALSE; static BOOL vcmMode = FALSE; static BOOL normalMode = FALSE; static BOOL parsingDone = FALSE; static BOOL srcExecuteDone = FALSE; static BOOL destExecuteDone = FALSE; static BOOL delayedOperationsDone = FALSE; BOOL needVcmInit = FALSE; BOOL needSrcModuleInit = FALSE; BOOL needDestModuleInit = FALSE; BOOL needRollbackInit = FALSE; BOOL needTerminate = FALSE; BOOL needTransportTermination = FALSE; BOOL needDelayedOperationsTerminate = FALSE; BOOL parseEtm = FALSE; BOOL parseVcm = FALSE; BOOL processVcm = FALSE; BOOL parseSource = FALSE; BOOL processSource = FALSE; BOOL processDestination = FALSE; BOOL processDelayedOperations = FALSE; MIG_PLATFORMTYPEID platform = PLATFORM_SOURCE; PCTSTR journalFile; DWORD tempField; PCURRENT_USER_DATA currentUserData; BOOL cleanupOnly = FALSE; BOOL b = TRUE; if (CheckCancel ()) { return FALSE; } g_ExecutionInProgress = TRUE; switch (ExecuteType) { case EXECUTETYPE_VIRTUALCOMPUTER_PARSING: if (parsingDone) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_VIRTUALCOMPUTER_PARSING denied, parsing already executed")); b = FALSE; break; } if (normalMode) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_VIRTUALCOMPUTER_PARSING denied, not in virtual computer mode")); b = FALSE; break; } needVcmInit = TRUE; parseEtm = TRUE; parseVcm = TRUE; parsingDone = TRUE; vcmMode = TRUE; break; case EXECUTETYPE_VIRTUALCOMPUTER: if (srcExecuteDone) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_VIRTUALCOMPUTER denied, virtual computer already built")); b = FALSE; break; } if (normalMode) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_VIRTUALCOMPUTER denied, not in virtual computer mode")); b = FALSE; break; } needVcmInit = TRUE; processVcm = TRUE; needTerminate = TRUE; parsingDone = TRUE; vcmMode = TRUE; srcExecuteDone = TRUE; break; case EXECUTETYPE_EXECUTESOURCE_PARSING: if (vcmMode) { DEBUGMSG ((DBG_ERROR, "PARSING denied, in virtual computer mode")); b = FALSE; break; } if (parsingDone) { DEBUGMSG ((DBG_ERROR, "PARSING denied, it was already done")); b = FALSE; break; } needSrcModuleInit = TRUE; parseEtm = TRUE; parseSource = TRUE; parsingDone = TRUE; normalMode = TRUE; break; case EXECUTETYPE_EXECUTESOURCE: if (vcmMode) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_EXECUTESOURCE denied, in virtual computer mode")); b = FALSE; break; } if (srcExecuteDone) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_EXECUTESOURCE denied, source computer already processed")); b = FALSE; break; } if (destExecuteDone) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_EXECUTESOURCE denied, destination computer already processed")); b = FALSE; break; } needSrcModuleInit = TRUE; processSource = TRUE; needTerminate = TRUE; parsingDone = TRUE; normalMode = TRUE; srcExecuteDone = TRUE; break; case EXECUTETYPE_EXECUTEDESTINATION: if (!g_SelectedTransport || !g_SelectedTransport->ShouldBeCalled) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_TRANSPORT_SELECTED)); b = FALSE; break; } if (vcmMode) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_EXECUTEDESTINATION denied, in virtual computer mode")); b = FALSE; break; } if (destExecuteDone) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_EXECUTEDESTINATION denied, destination computer already processed")); b = FALSE; break; } platform = PLATFORM_DESTINATION; needDestModuleInit = TRUE; needRollbackInit = TRUE; processDestination = TRUE; needTransportTermination = TRUE; needTerminate = TRUE; parsingDone = TRUE; normalMode = TRUE; destExecuteDone = TRUE; break; case EXECUTETYPE_DELAYEDOPERATIONS: case EXECUTETYPE_DELAYEDOPERATIONSCLEANUP: if (vcmMode) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_DELAYEDOPERATIONS denied, in virtual computer mode")); b = FALSE; break; } if (delayedOperationsDone) { DEBUGMSG ((DBG_ERROR, "EXECUTETYPE_DELAYEDOPERATIONS denied, delayed operations already processed")); b = FALSE; break; } platform = PLATFORM_DESTINATION; destInitCompleted = TRUE; needRollbackInit = TRUE; needDelayedOperationsTerminate = TRUE; processDelayedOperations = TRUE; delayedOperationsDone = TRUE; cleanupOnly = (ExecuteType == EXECUTETYPE_DELAYEDOPERATIONSCLEANUP); } if (b) { g_IsmModulePlatformContext = platform; if (platform == PLATFORM_SOURCE) { if (!srcInitCompleted) { // // Complete initialization of all ISM components // b = InitializeProperties (platform, vcmMode); srcInitCompleted = TRUE; DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: src property init failed")); } } else { if (!destInitCompleted) { // // Complete initialization of all ISM components // b = InitializeProperties (platform, vcmMode); destInitCompleted = TRUE; DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: dest property init failed")); } } if (needVcmInit && !vcmInitCompleted) { // // Initialize the modules // b = InitializeVcmModules (NULL); vcmInitCompleted = TRUE; DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: VCM init failed")); } if (needSrcModuleInit && !srcModuleInitCompleted) { // // Initialize the modules // b = InitializeModules (platform, NULL); srcModuleInitCompleted = TRUE; DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: src module init failed")); } if (needRollbackInit && !rollbackInitCompleted) { // // remove all journal entries, prepare for a new apply // if (g_JournalDirectory) { FiRemoveAllFilesInTree (g_JournalDirectory); BfCreateDirectory (g_JournalDirectory); journalFile = JoinPaths (g_JournalDirectory, TEXT("JOURNAL.DAT")); g_JournalHandle = BfCreateFile (journalFile); if (g_JournalHandle) { tempField = JRN_SIGNATURE; BfWriteFile (g_JournalHandle, (PBYTE)(&tempField), sizeof (DWORD)); tempField = JRN_VERSION; BfWriteFile (g_JournalHandle, (PBYTE)(&tempField), sizeof (DWORD)); FreePathString (journalFile); currentUserData = GetCurrentUserData (); if (currentUserData) { pRecordUserData ( currentUserData->UserName, currentUserData->UserDomain, currentUserData->UserStringSid, currentUserData->UserProfilePath, FALSE ); FreeCurrentUserData (currentUserData); } else { pRecordUserData ( NULL, NULL, NULL, NULL, FALSE ); } } } ELSE_DEBUGMSG ((DBG_WHOOPS, "Journal directory does not exist.")); rollbackInitCompleted = TRUE; } if (needDestModuleInit && !destModuleInitCompleted) { // // Initialize the modules // b = InitializeModules (platform, NULL); destModuleInitCompleted = TRUE; DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: dest module init failed")); } } if (b && parseEtm) { // // Execute the appropriate ETM parse functions // b = pEtmParse (NULL); DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: ETM parse failed")); b = b && !CheckCancel(); } if (b && parseVcm) { // // Execute the appropriate virtual computer parse functions // b = pCreateComputerParse (NULL); DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: VCM parse failed")); b = b && !CheckCancel(); } if (b && processVcm) { // // Execute the appropriate virtual computer gather functions // b = pCreateComputerGather (NULL); DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: VCM queue enumeration or gather callback failed")); b = b && !CheckCancel(); } if (b && parseSource) { // // Execute the appropriate virtual computer parse functions // b = pSourceParse (NULL); DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: SGM parse failed")); b = b && !CheckCancel(); } if (b && processSource) { // // Execute the appropriate source gather functions // b = pSourceGather (NULL); DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: SGM queue enumeration or gather callback failed")); b = b && !CheckCancel(); if (b) { b = pSourceAnalyze (NULL); DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: SAM failed")); b = b && !CheckCancel(); } } if (b && processDestination) { // // Execute the appropriate destination functions // b = pDestinationGather (NULL); DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: DGM queue enumeration or gather callback failed")); b = b && !CheckCancel(); if (b) { b = pDestinationAnalyze (NULL); DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: DAM failed")); b = b && !CheckCancel(); } if (b) { b = pDestinationApply (NULL); DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: dest apply failed")); b = b && !CheckCancel(); } } if (b && processDelayedOperations) { // // Execute the appropriate delayed operations // b = ExecuteDelayedOperations (cleanupOnly); DEBUGMSG_IF ((!b, DBG_ISM, "IsmExecute: delayed operations failed")); } if (needTransportTermination) { MYASSERT (g_SelectedTransport); MYASSERT (g_SelectedTransport->TransportEndApply); g_SelectedTransport->TransportEndApply (); } if (needTerminate) { // // Done -- terminate the modules // TerminateModules (); TerminateProperties (platform); } if (needDelayedOperationsTerminate) { pDeleteDelayedOperationsCommand (); } g_IsmModulePlatformContext = PLATFORM_CURRENT; if (g_JournalHandle) { CloseHandle (g_JournalHandle); g_JournalHandle = NULL; } g_ExecutionInProgress = FALSE; return b; } BOOL IsmRegisterProgressBarCallback ( IN PPROGRESSBARFN ProgressBarFn, IN ULONG_PTR Arg ) { if (CheckCancel ()) { return FALSE; } if (!ProgressBarFn) { g_ProgressBarFn = NULL; return TRUE; } if (g_ProgressBarFn) { DEBUGMSG ((DBG_ERROR, "Progress bar callback is already set")); return FALSE; } g_ProgressBarFn = ProgressBarFn; g_ProgressBarArg = Arg; return TRUE; } BOOL pSaveStatistics ( VOID ) { MIG_OBJECTCOUNT objectCount [3]; MYASSERT ( g_TotalObjects.TotalObjects == g_SourceObjects.TotalObjects + g_DestinationObjects.TotalObjects ); MYASSERT ( g_TotalObjects.PersistentObjects == g_SourceObjects.PersistentObjects + g_DestinationObjects.PersistentObjects ); MYASSERT ( g_TotalObjects.ApplyObjects == g_SourceObjects.ApplyObjects + g_DestinationObjects.ApplyObjects ); CopyMemory (&(objectCount [0]), &g_TotalObjects, sizeof (MIG_OBJECTCOUNT)); CopyMemory (&(objectCount [1]), &g_SourceObjects, sizeof (MIG_OBJECTCOUNT)); CopyMemory (&(objectCount [2]), &g_DestinationObjects, sizeof (MIG_OBJECTCOUNT)); if (!MemDbSetUnorderedBlob (S_OBJECTCOUNT, 0, (PCBYTE)objectCount, 3 * sizeof (MIG_OBJECTCOUNT))) { return FALSE; } return SavePerObjectStatistics (); } BOOL pLoadStatistics ( VOID ) { PMIG_OBJECTCOUNT objectCount; DWORD size; objectCount = (PMIG_OBJECTCOUNT) MemDbGetUnorderedBlob (S_OBJECTCOUNT, 0, &size); if ((!objectCount) || (size != 3 * sizeof (MIG_OBJECTCOUNT))) { if (objectCount) { MemDbReleaseMemory (objectCount); } MYASSERT (FALSE); return FALSE; } CopyMemory (&g_TotalObjects, objectCount, sizeof (MIG_OBJECTCOUNT)); CopyMemory (&g_SourceObjects, objectCount + 1, sizeof (MIG_OBJECTCOUNT)); CopyMemory (&g_DestinationObjects, objectCount + 2, sizeof (MIG_OBJECTCOUNT)); MemDbReleaseMemory (objectCount); MYASSERT ( g_TotalObjects.TotalObjects == g_SourceObjects.TotalObjects + g_DestinationObjects.TotalObjects ); MYASSERT ( g_TotalObjects.PersistentObjects == g_SourceObjects.PersistentObjects + g_DestinationObjects.PersistentObjects ); MYASSERT ( g_TotalObjects.ApplyObjects == g_SourceObjects.ApplyObjects + g_DestinationObjects.ApplyObjects ); return LoadPerObjectStatistics (); } BOOL pLoadLightDatabase ( IN PCTSTR FileName ) { HINF infHandle; INFSTRUCT is = INITINFSTRUCT_PMHANDLE; INFSTRUCT is2 = INITINFSTRUCT_PMHANDLE; MIG_OBJECTTYPEID objectTypeId; GROWBUFFER buff = INIT_GROWBUFFER; PCTSTR field; MIG_OBJECTSTRINGHANDLE objectName; UINT index; PCTSTR scope; PCTSTR name; PCTSTR key; PCTSTR keyData; UINT envType; DWORD dummy; PCTSTR savedGroup; ENVENTRY_STRUCT envStruct; PTSTR decodedString = NULL; infHandle = InfOpenInfFile (FileName); if (infHandle == INVALID_HANDLE_VALUE) { return FALSE; } // let's load transport variables if (InfFindFirstLine (infHandle, TEXT("Data Sections"), NULL, &is)) { do { name = InfGetStringField (&is, 1); if (name && InfFindFirstLine (infHandle, name, NULL, &is2)) { do { key = InfGetStringField (&is2, 0); keyData = InfGetStringField (&is2, 1); if (key && keyData) { IsmSetTransportVariable (PLATFORM_SOURCE, name, key, keyData); } } while (InfFindNextLine (&is2)); } } while (InfFindNextLine (&is)); } // let's load source environment variables if (InfFindFirstLine (infHandle, TEXT("Environment"), NULL, &is)) { do { name = InfGetStringField (&is, 1); scope = InfGetStringField (&is, 2); field = InfGetStringField (&is, 3); if (scope && name && field) { _stscanf (field, TEXT("%lx"), &envType); buff.End = 0; switch (envType) { case ENVENTRY_STRING: field = InfGetStringField (&is, 4); if (field) { GbCopyString (&buff, field); } break; case ENVENTRY_MULTISZ: index = 4; for (;;) { field = InfGetStringField (&is, index); if (!field) { break; } GbCopyString (&buff, field); index ++; } if (buff.End) { GbCopyString (&buff, TEXT("")); } break; case ENVENTRY_BINARY: index = 4; for (;;) { field = InfGetStringField (&is, index); if (!field) { break; } _stscanf (field, TEXT("%lx"), &dummy); *((PBYTE)GbGrow (&buff, sizeof (BYTE))) = (BYTE)dummy; index ++; } break; default: // don't know what to write, it's just a flag break; } // now let's add the environment variable envStruct.Type = envType; if (buff.End) { envStruct.EnvBinaryData = buff.Buf; envStruct.EnvBinaryDataSize = buff.End; } else { envStruct.EnvBinaryData = NULL; envStruct.EnvBinaryDataSize = 0; } savedGroup = g_CurrentGroup; g_CurrentGroup = scope; IsmSetEnvironmentValue ( PLATFORM_SOURCE, (scope && *scope)?scope:NULL, name, &envStruct ); g_CurrentGroup = savedGroup; } } while (InfFindNextLine (&is)); } // let's load object types if (InfFindFirstLine (infHandle, TEXT("Object Types"), NULL, &is)) { do { field = InfGetStringField (&is, 1); if (field) { MYASSERT (IsmGetObjectTypeId (field) != 0); if (IsmGetObjectTypeId (field) == 0) { // we need to preregister this type IsmRegisterObjectType ( field, TRUE, FALSE, NULL ); } } } while (InfFindNextLine (&is)); } InfCleanUpInfStruct (&is); TypeMgrRescanTypes (); objectTypeId = IsmGetFirstObjectTypeId (); while (objectTypeId) { if (InfFindFirstLine (infHandle, IsmGetObjectTypeName (objectTypeId), NULL, &is)) { do { index = 1; buff.End = 0; for (;;) { field = InfGetStringField (&is, index); if (!field) { break; } if (*field) { decodedString = DuplicatePathString (field, 0); if (DecodeRuleChars (decodedString, field) != NULL) { GbCopyString (&buff, decodedString); } else { GbCopyString (&buff, field); } FreePathString (decodedString); } else { GbCopyString (&buff, TEXT("")); } index ++; } if (buff.End) { GbCopyString (&buff, TEXT("")); if (IsmConvertMultiSzToObject ( objectTypeId, (PCTSTR)buff.Buf, &objectName, NULL )) { // now save the object data into our database // for future reference IsmMakePersistentObject (objectTypeId | PLATFORM_SOURCE, objectName); IsmDestroyObjectHandle (objectName); } } } while (InfFindNextLine (&is)); } objectTypeId = IsmGetNextObjectTypeId (objectTypeId); } InfCleanUpInfStruct (&is); InfCleanUpInfStruct (&is2); InfCloseInfFile (infHandle); GbFree (&buff); pSaveStatistics (); return TRUE; } BOOL pFinishLoad ( VOID ) { MIG_OBJECTSTRINGHANDLE memDbObjectName; MIG_CONTENT memDbContent; BOOL result = FALSE; GROWLIST growList = INIT_GROWLIST; __try { switch (g_TransportType) { case TRANSPORTTYPE_LIGHT: if (!RegisterInternalAttributes ()) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 6)); __leave; } memDbObjectName = IsmCreateObjectHandle (S_DATABASEFILE_LITE, NULL); if (!IsmAcquireObjectEx (MIG_DATA_TYPE | PLATFORM_SOURCE, memDbObjectName, &memDbContent, CONTENTTYPE_FILE, 0)) { IsmDestroyObjectHandle (memDbObjectName); DEBUGMSG ((DBG_ISM, "pFinishLoad: Failed to acquire VCM database")); __leave; } if (!pLoadLightDatabase (memDbContent.FileContent.ContentPath)) { IsmDestroyObjectHandle (memDbObjectName); IsmReleaseObject (&memDbContent); DEBUGMSG ((DBG_ISM, "pFinishLoad: Failed to load VCM database")); __leave; } IsmDestroyObjectHandle (memDbObjectName); IsmReleaseObject (&memDbContent); break; case TRANSPORTTYPE_FULL: // // Save environment into a grow list, because memdb is going to be reloaded // EnvSaveEnvironment (&growList); memDbObjectName = IsmCreateObjectHandle (S_DATABASEFILE_FULL, NULL); if (!IsmAcquireObjectEx (MIG_DATA_TYPE | PLATFORM_SOURCE, memDbObjectName, &memDbContent, CONTENTTYPE_FILE, 0)) { IsmDestroyObjectHandle (memDbObjectName); DEBUGMSG ((DBG_ISM, "pFinishLoad: Failed to acquire database")); __leave; } if (!MemDbLoad (memDbContent.FileContent.ContentPath)) { IsmDestroyObjectHandle (memDbObjectName); IsmReleaseObject (&memDbContent); DEBUGMSG ((DBG_ISM, "pFinishLoad: Failed to load database")); __leave; } IsmDestroyObjectHandle (memDbObjectName); IsmReleaseObject (&memDbContent); // // Rebuild all the things we lost because of the memdb refresh // TypeMgrRescanTypes (); if (!RegisterInternalAttributes ()) { DEBUGMSG ((DBG_ISM, "pFinishLoad: Failed to register persistent attrib")); LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_INIT_FAILURE, 7)); __leave; } EnvRestoreEnvironment (&growList); break; default: LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_UNKNOWN_TRANSPORT_TYPE, g_TransportType)); __leave; } pLoadStatistics (); GlFree (&growList); EnvInvalidateCallbacks (); result = TRUE; } __finally { } return result; } BOOL IsmLoad ( VOID ) { BOOL result = FALSE; GROWLIST growList = INIT_GROWLIST; if (CheckCancel ()) { return FALSE; } if (!g_SelectedTransport || !g_SelectedTransport->ShouldBeCalled) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_TRANSPORT_SELECTED)); return FALSE; } g_ExecutionInProgress = TRUE; // // We need to invalidate operation combinations created so far // because we might load a new memdb where all operations could // be registered already // TerminateOperations (); g_CurrentPhase = MIG_TRANSPORT_PHASE; g_SliceBuffer.End = 0; __try { if (g_SelectedTransport->TransportEstimateProgressBar) { g_SelectedTransport->TransportEstimateProgressBar (g_IsmCurrentPlatform); } pCallProgressBar (MIG_BEGIN_PHASE); MYASSERT (g_SelectedTransport->TransportBeginApply); if (!g_SelectedTransport->TransportBeginApply ()) { DEBUGMSG ((DBG_ISM, "IsmLoad: Begin apply failed")); __leave; } result = pFinishLoad (); } __finally { PushError (); pCallProgressBar (MIG_END_PHASE); g_CurrentPhase = 0; g_SliceBuffer.End = 0; PopError (); } if (!result) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_LOAD_FAILURE)); } InitializeOperations (); g_ExecutionInProgress = FALSE; return result; } BOOL IsmResumeLoad ( VOID ) { BOOL result = FALSE; GROWLIST growList = INIT_GROWLIST; if (CheckCancel ()) { return FALSE; } if (!g_SelectedTransport || !g_SelectedTransport->ShouldBeCalled) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_TRANSPORT_SELECTED)); return FALSE; } g_ExecutionInProgress = TRUE; // // We need to invalidate operation combinations created so far // because we might load a new memdb where all operations could // be registered already // TerminateOperations (); g_CurrentPhase = MIG_TRANSPORT_PHASE; g_SliceBuffer.End = 0; __try { if (g_SelectedTransport->TransportEstimateProgressBar) { g_SelectedTransport->TransportEstimateProgressBar (g_IsmCurrentPlatform); } pCallProgressBar (MIG_BEGIN_PHASE); if (!g_SelectedTransport->TransportResumeApply) { __leave; } if (!g_SelectedTransport->TransportResumeApply ()) { __leave; } result = pFinishLoad (); } __finally { pCallProgressBar (MIG_END_PHASE); g_CurrentPhase = 0; g_SliceBuffer.End = 0; } InitializeOperations (); g_ExecutionInProgress = FALSE; return result; } BOOL pSaveLightDatabase ( IN PCTSTR FileName ) { HANDLE fileHandle = NULL; MIG_OBJECTTYPEID objectTypeId; ENV_ENTRY_ENUM envEntryEnum; MULTISZ_ENUM multiSzEnum; UINT size; TCHAR buffer[sizeof (DWORD) * 2 + 3]; PCTSTR start; PCTSTR end; TCHAR section[256]; TCHAR sectionLookahead[256]; UINT pass; fileHandle = BfCreateFile (FileName); if (!fileHandle) { return FALSE; } WriteFileString (fileHandle, TEXT("[Version]\r\n")); WriteFileString (fileHandle, TEXT("signature=\"$CHICAGO$\"\r\n")); WriteFileString (fileHandle, TEXT("Class=Upgrade\r\n\r\n\r\n")); // // Write sections for lite transport // for (pass = 0 ; pass < 2 ; pass++) { if (EnvEnumerateFirstEntry ( &envEntryEnum, PLATFORM_SOURCE, TEXT("*\\") S_TRANSPORT_PREFIX TEXT("\\*") )) { if (pass == 0) { WriteFileString (fileHandle, TEXT("[Data Sections]\r\n")); } *section = 0; do { if (envEntryEnum.EnvEntryType != ENVENTRY_STRING) { continue; } if (!envEntryEnum.EnvEntryDataSize || !envEntryEnum.EnvEntryData) { continue; } if (envEntryEnum.EnvEntryName) { // // Find start and end of section name // start = envEntryEnum.EnvEntryName; end = _tcschr (start, TEXT('\\')); if (!end) { continue; } start = end + 1; end = _tcschr (start, TEXT('\\')); if (end && (end - start) < (ARRAYSIZE (sectionLookahead) - 2)) { // // Copy section name into lookahead buffer // StringCopyAB (sectionLookahead, start, end); // // Ignore if no keys exist // start = _tcsinc (end); if (*start == 0) { continue; } // // If lookahead buffer != last section, write section name // if (StringICompare (section, sectionLookahead)) { if (pass == 1 && *section) { WriteFileString (fileHandle, TEXT("\r\n")); } StringCopy (section, sectionLookahead); if (pass == 1) { WriteFileString (fileHandle, TEXT("[")); } WriteFileString (fileHandle, section); if (pass == 1) { WriteFileString (fileHandle, TEXT("]\r\n")); } else { WriteFileString (fileHandle, TEXT("\r\n")); } } // // If pass 1, write the key=value text // if (pass == 1) { WriteFileString (fileHandle, start); WriteFileString (fileHandle, TEXT(" = ")); WriteFileString (fileHandle, (PCTSTR)envEntryEnum.EnvEntryData); WriteFileString (fileHandle, TEXT("\r\n")); } } } } while (EnvEnumerateNextEntry (&envEntryEnum)); AbortEnvEnumerateEntry (&envEntryEnum); if (*section == 0) { WriteFileString (fileHandle, TEXT("; empty\r\n\r\n")); } else { WriteFileString (fileHandle, TEXT("\r\n")); } } } WriteFileString (fileHandle, TEXT("[Environment]\r\n")); if (EnvEnumerateFirstEntry (&envEntryEnum, PLATFORM_SOURCE, TEXT("*"))) { do { // skip v1 hack variables if (envEntryEnum.EnvEntryName) { if (StringIMatchCharCount ( S_TRANSPORT_PREFIX TEXT("\\"), envEntryEnum.EnvEntryName, ARRAYSIZE (S_TRANSPORT_PREFIX) )) { continue; } } // write the group and the name WriteFileString (fileHandle, TEXT("\"")); if (envEntryEnum.EnvEntryName) { WriteFileString (fileHandle, envEntryEnum.EnvEntryName); } WriteFileString (fileHandle, TEXT("\",\"")); if (envEntryEnum.EnvEntryGroup) { WriteFileString (fileHandle, envEntryEnum.EnvEntryGroup); } WriteFileString (fileHandle, TEXT("\",")); // now write the entry type wsprintf (buffer, TEXT("0x%08X"), envEntryEnum.EnvEntryType); WriteFileString (fileHandle, buffer); switch (envEntryEnum.EnvEntryType) { case ENVENTRY_STRING: if (envEntryEnum.EnvEntryDataSize && envEntryEnum.EnvEntryData) { WriteFileString (fileHandle, TEXT(",\"")); WriteFileString (fileHandle, (PCTSTR)envEntryEnum.EnvEntryData); WriteFileString (fileHandle, TEXT("\"")); } break; case ENVENTRY_MULTISZ: if (envEntryEnum.EnvEntryDataSize && envEntryEnum.EnvEntryData) { if (EnumFirstMultiSz (&multiSzEnum, (PCTSTR)envEntryEnum.EnvEntryData)) { do { WriteFileString (fileHandle, TEXT(",\"")); WriteFileString (fileHandle, multiSzEnum.CurrentString); WriteFileString (fileHandle, TEXT("\"")); } while (EnumNextMultiSz (&multiSzEnum)); } } break; case ENVENTRY_BINARY: if (envEntryEnum.EnvEntryDataSize && envEntryEnum.EnvEntryData) { // write it in binary format size = 0; while (size < envEntryEnum.EnvEntryDataSize) { wsprintf ( buffer, TEXT("%02X"), envEntryEnum.EnvEntryData [size] ); WriteFileString (fileHandle, TEXT(",")); WriteFileString (fileHandle, buffer); size ++; } } break; default: // don't know what to write, it's just a flag break; } WriteFileString (fileHandle, TEXT("\r\n")); } while (EnvEnumerateNextEntry (&envEntryEnum)); AbortEnvEnumerateEntry (&envEntryEnum); } WriteFileString (fileHandle, TEXT("\r\n\r\n")); WriteFileString (fileHandle, TEXT("[Object Types]\r\n")); objectTypeId = IsmGetFirstObjectTypeId (); while (objectTypeId) { WriteFileString (fileHandle, IsmGetObjectTypeName (objectTypeId)); WriteFileString (fileHandle, TEXT("\r\n")); objectTypeId = IsmGetNextObjectTypeId (objectTypeId); } WriteFileString (fileHandle, TEXT("\r\n\r\n")); CloseHandle (fileHandle); return TRUE; } BOOL IsmSave ( VOID ) { MIG_OBJECTSTRINGHANDLE memDbObjectName; TCHAR tempPath [MAX_PATH]; BOOL result = FALSE; if (CheckCancel ()) { return FALSE; } if (!g_SelectedTransport || !g_SelectedTransport->ShouldBeCalled) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_TRANSPORT_SELECTED)); return FALSE; } __try { g_ExecutionInProgress = TRUE; if (!IsmGetTempFile (tempPath, ARRAYSIZE(tempPath))) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_CANT_SAVE_MEMDB)); __leave; } switch (g_TransportType) { case TRANSPORTTYPE_LIGHT: memDbObjectName = IsmCreateObjectHandle (S_DATABASEFILE_LITE, NULL); DataTypeAddObject (memDbObjectName, tempPath, TRUE); IsmDestroyObjectHandle (memDbObjectName); if (!pSaveLightDatabase (tempPath)) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_CANT_SAVE_MEMDB)); __leave; } break; case TRANSPORTTYPE_FULL: memDbObjectName = IsmCreateObjectHandle (S_DATABASEFILE_FULL, NULL); DataTypeAddObject (memDbObjectName, tempPath, TRUE); IsmDestroyObjectHandle (memDbObjectName); pSaveStatistics (); if (!MemDbSave (tempPath)) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_CANT_SAVE_MEMDB)); __leave; } break; default: LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_UNKNOWN_TRANSPORT_TYPE, g_TransportType)); __leave; } EnvInvalidateCallbacks (); g_CurrentPhase = MIG_TRANSPORT_PHASE; g_SliceBuffer.End = 0; if (g_SelectedTransport->TransportEstimateProgressBar) { g_SelectedTransport->TransportEstimateProgressBar (g_IsmCurrentPlatform); } pCallProgressBar (MIG_BEGIN_PHASE); result = g_SelectedTransport->TransportSaveState (); if (result) { DeleteFile (tempPath); } else { DEBUGMSG ((DBG_ISM, "TransportSaveState failed")); // NTRAID#NTBUG9-168115-2000/08/23-jimschm Temp file is not cleaned up here or in resume below } pCallProgressBar (MIG_END_PHASE); g_CurrentPhase = 0; g_SliceBuffer.End = 0; } __finally { g_ExecutionInProgress = FALSE; } if (!result) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_SAVE_FAILURE)); } return result; } BOOL IsmResumeSave ( VOID ) { BOOL result; if (CheckCancel ()) { return FALSE; } if (!g_SelectedTransport || !g_SelectedTransport->ShouldBeCalled) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_NO_TRANSPORT_SELECTED)); return FALSE; } if (!g_SelectedTransport->TransportResumeSaveState) { return FALSE; } g_ExecutionInProgress = TRUE; EnvInvalidateCallbacks (); g_CurrentPhase = MIG_TRANSPORT_PHASE; g_SliceBuffer.End = 0; if (g_SelectedTransport->TransportEstimateProgressBar) { g_SelectedTransport->TransportEstimateProgressBar (g_IsmCurrentPlatform); } pCallProgressBar (MIG_BEGIN_PHASE); result = g_SelectedTransport->TransportResumeSaveState (); DEBUGMSG_IF ((!result, DBG_ISM, "TransportResumeSaveState failed")); pCallProgressBar (MIG_END_PHASE); g_CurrentPhase = 0; g_SliceBuffer.End = 0; g_ExecutionInProgress = FALSE; return result; } PVOID TrackedIsmGetMemory ( IN UINT Size TRACKING_DEF ) { PVOID result; TRACK_ENTER(); if (!g_IsmPool) { g_IsmPool = PmCreateNamedPool ("ISM Pool"); } result = PmGetMemory (g_IsmPool, Size); TRACK_LEAVE(); return result; } PCTSTR TrackedIsmDuplicateString ( IN PCTSTR String TRACKING_DEF ) { PCTSTR result; TRACK_ENTER(); if (!g_IsmPool) { g_IsmPool = PmCreateNamedPool ("ISM Pool"); } result = PmDuplicateString (g_IsmPool, String); TRACK_LEAVE(); return result; } BOOL IsmReleaseMemory ( IN PCVOID Memory ) { if (g_IsmPool && Memory) { PmReleaseMemory (g_IsmPool, Memory); return TRUE; } else { return FALSE; } } MIG_OBJECTSTRINGHANDLE TrackedIsmCreateObjectHandle ( IN PCTSTR Node, IN PCTSTR Leaf TRACKING_DEF ) { MIG_OBJECTSTRINGHANDLE result; TRACK_ENTER(); result = ObsBuildEncodedObjectStringEx (Node, Leaf, TRUE); TRACK_LEAVE(); return result; } BOOL WINAPI TrackedIsmCreateObjectStringsFromHandleEx ( IN MIG_OBJECTSTRINGHANDLE Handle, OUT PCTSTR *Node, OPTIONAL OUT PCTSTR *Leaf, OPTIONAL IN BOOL DoNotDecode TRACKING_DEF ) { BOOL result; TRACK_ENTER(); result = ObsSplitObjectStringEx ( Handle, Node, Leaf, NULL, !DoNotDecode ); if (!result) { if (Node) { *Node = NULL; } if (Leaf) { *Leaf = NULL; } } TRACK_LEAVE(); return result; } VOID IsmDestroyObjectString ( IN PCTSTR String ) { ObsFree (String); } VOID IsmDestroyObjectHandle ( IN MIG_OBJECTSTRINGHANDLE Handle ) { ObsFree (Handle); } BOOL IsmIsObjectHandleNodeOnly ( IN MIG_OBJECTSTRINGHANDLE Handle ) { return ObsGetLeafPortionOfEncodedString (Handle) == NULL; } BOOL IsmIsObjectHandleLeafOnly ( IN MIG_OBJECTSTRINGHANDLE Handle ) { return !ObsHasNode (Handle); } PCTSTR pCreatePatternStr ( IN PMIG_SEGMENTS Segments, OPTIONAL IN UINT Count ) { PTSTR result; UINT size; UINT u; PTSTR p; if (Segments == ALL_PATTERN) { result = DuplicatePathString (TEXT("*"), 0); } else if (Segments && Count) { // // Compute the buffer size needed: logchars * DBCS * escaping + nul // size = 1; for (u = 0; u < Count ; u++) { if (!Segments[u].IsPattern) { size += TcharCount (Segments[u].Segment) * 2; } else { size += TcharCount (Segments[u].Segment); } } #ifndef UNICODE size *= 2; // account for dbcs expansion #endif result = AllocPathString (size); p = result; // // Build the pattern // *p = 0; for (u = 0; u < Count ; u ++) { if (!Segments[u].IsPattern) { ObsEncodeString (p, Segments[u].Segment); p = GetEndOfString (p); } else { p = StringCat (p, Segments[u].Segment); } } } else { result = DuplicatePathString (TEXT(""), 0); } return result; } MIG_OBJECTSTRINGHANDLE TrackedIsmCreateObjectPattern ( IN PMIG_SEGMENTS NodeSegments, OPTIONAL IN UINT NodeSegmentsNr, IN PMIG_SEGMENTS LeafSegments, OPTIONAL IN UINT LeafSegmentsNr TRACKING_DEF ) { PCTSTR node; PCTSTR leaf; ENCODEDSTRHANDLE result; TRACK_ENTER(); if (NodeSegments == ALL_PATTERN) { NodeSegmentsNr = 1; } if (LeafSegments == ALL_PATTERN) { LeafSegmentsNr = 1; } node = pCreatePatternStr (NodeSegments, NodeSegmentsNr); leaf = pCreatePatternStr (LeafSegments, LeafSegmentsNr); result = ObsBuildEncodedObjectStringEx (NodeSegmentsNr ? node : NULL, LeafSegmentsNr ? leaf : NULL, FALSE); FreePathString (node); FreePathString (leaf); TRACK_LEAVE(); return result; } MIG_OBJECTSTRINGHANDLE TrackedIsmCreateSimpleObjectPattern ( IN PCTSTR BaseNode, OPTIONAL IN BOOL EnumTree, IN PCTSTR Leaf, OPTIONAL IN BOOL LeafIsPattern TRACKING_DEF ) { MIG_SEGMENTS nodePat[2]; MIG_SEGMENTS leafPat[1]; UINT nrSegNode = 0; UINT nrSegLeaf = 0; PCTSTR p; MIG_OBJECTSTRINGHANDLE result; TRACK_ENTER(); if (BaseNode) { nodePat [0].Segment = BaseNode; nodePat [0].IsPattern = FALSE; nrSegNode ++; } if (EnumTree) { if (nrSegNode) { p = _tcsdec2 (BaseNode, GetEndOfString (BaseNode)); if (p && _tcsnextc (p) == TEXT('\\')) { nodePat [nrSegNode].Segment = TEXT("*"); } else { nodePat [nrSegNode].Segment = TEXT("\\*"); } } else { nodePat [nrSegNode].Segment = TEXT("*"); } nodePat [nrSegNode].IsPattern = TRUE; nrSegNode ++; } if (Leaf) { leafPat [0].Segment = Leaf; leafPat [0].IsPattern = LeafIsPattern; nrSegLeaf ++; } else { if (LeafIsPattern) { leafPat [0].Segment = TEXT("*"); leafPat [0].IsPattern = TRUE; nrSegLeaf ++; } } result = IsmCreateObjectPattern (nrSegNode?nodePat:NULL, nrSegNode, nrSegLeaf?leafPat:NULL, nrSegLeaf); TRACK_LEAVE(); return result; } PTSTR GetFirstSeg ( IN PCTSTR SrcFileName ) { if (_tcsnextc (SrcFileName) == TEXT('\\')) { SrcFileName = _tcsinc (SrcFileName); if (_tcsnextc (SrcFileName) == TEXT('\\')) { SrcFileName = _tcsinc (SrcFileName); } return (_tcschr (SrcFileName, TEXT('\\'))); } else { return (_tcschr (SrcFileName, TEXT('\\'))); } } BOOL pAddShortLongInfo ( IN ENCODEDSTRHANDLE EncodedObjectName ) { GROWBUFFER growBuf = INIT_GROWBUFFER; PCTSTR node = NULL; PCTSTR leaf = NULL; PTSTR nativeName = NULL; PTSTR nativeNamePtr; PTSTR beginSegPtr; PTSTR endSegPtr; TCHAR savedChar; WIN32_FIND_DATA findData; UINT savedEnd; UINT beginBuffIdx; BOOL result = FALSE; KEYHANDLE kh1, kh2; BOOL b; if (IsmCreateObjectStringsFromHandle (EncodedObjectName, &node, &leaf)) { MYASSERT (node); if (leaf) { nativeName = DuplicatePathString (S_SHORTLONG_TREE, SizeOfString (node) + SizeOfString (leaf)); } else { nativeName = DuplicatePathString (S_SHORTLONG_TREE, SizeOfString (node)); } nativeNamePtr = AppendWack (nativeName); StringCopy (nativeNamePtr, node); if (leaf) { StringCopy (AppendWack (nativeNamePtr), leaf); } GbAppendString (&growBuf, S_SHORTLONG_TREE); GbAppendString (&growBuf, TEXT("\\")); beginBuffIdx = growBuf.End - 1; beginSegPtr = GetFirstSeg (nativeNamePtr); if (beginSegPtr) { beginSegPtr = _tcsinc (beginSegPtr); GbAppendStringAB (&growBuf, nativeNamePtr, beginSegPtr); while (beginSegPtr) { endSegPtr = _tcschr (beginSegPtr, TEXT('\\')); if (!endSegPtr) { endSegPtr = GetEndOfString (beginSegPtr); MYASSERT (endSegPtr); } savedChar = *endSegPtr; *endSegPtr = 0; if (DoesFileExistEx (nativeNamePtr, &findData)) { if (*findData.cAlternateFileName) { savedEnd = growBuf.End - 1; GbAppendString (&growBuf, findData.cAlternateFileName); kh1 = MemDbAddKey (nativeName); if (kh1) { kh2 = MemDbAddKey ((PCTSTR) growBuf.Buf); if (kh2) { b = MemDbSetValueByHandle (kh1, FILENAME_LONG); b = b && MemDbSetValueByHandle (kh2, FILENAME_SHORT); b = b && MemDbAddDoubleLinkageByKeyHandle (kh1, kh2, 0); } else { b = FALSE; } if (!b) { MemDbDeleteKey (nativeName); } } growBuf.End = savedEnd; } GbAppendString (&growBuf, findData.cFileName); } else { GbAppendStringAB (&growBuf, beginSegPtr, endSegPtr); } *endSegPtr = savedChar; if (savedChar) { beginSegPtr = _tcsinc (endSegPtr); GbAppendStringAB (&growBuf, endSegPtr, beginSegPtr); } else { beginSegPtr = NULL; } } } FreePathString (nativeName); if (node) { IsmDestroyObjectString (node); } if (leaf) { IsmDestroyObjectString (leaf); } } GbFree (&growBuf); return result; } BOOL pGetShortName ( IN PCTSTR Segment, OUT WIN32_FIND_DATA *FindData ) { static TCHAR tempDir [MAX_PATH] = TEXT(""); PCTSTR testFileName; HANDLE fileHandle; BOOL result = FALSE; if (tempDir [0] == 0) { IsmGetTempDirectory (tempDir, ARRAYSIZE(tempDir)); } testFileName = JoinPaths (tempDir, Segment); fileHandle = BfCreateFile (testFileName); if (fileHandle) { CloseHandle (fileHandle); if (DoesFileExistEx (testFileName, FindData)) { result = TRUE; } DeleteFile (testFileName); } FreePathString (testFileName); return result; } BOOL pAddShortLongInfoOnDest ( IN ENCODEDSTRHANDLE EncodedObjectName ) { GROWBUFFER growBuf = INIT_GROWBUFFER; PCTSTR node = NULL; PCTSTR leaf = NULL; PTSTR nativeName = NULL; PTSTR nativeNamePtr; PTSTR beginSegPtr; PTSTR endSegPtr; PCTSTR shortSeg = NULL; TCHAR savedChar; WIN32_FIND_DATA findData; UINT savedEnd; UINT beginBuffIdx; BOOL result = FALSE; KEYHANDLE kh1, kh2; BOOL b; if (IsmCreateObjectStringsFromHandle (EncodedObjectName, &node, &leaf)) { MYASSERT (node); if (leaf) { nativeName = DuplicatePathString (S_SHORTLONG_TREE, SizeOfString (node) + SizeOfString (leaf)); } else { nativeName = DuplicatePathString (S_SHORTLONG_TREE, SizeOfString (node)); } nativeNamePtr = AppendWack (nativeName); StringCopy (nativeNamePtr, node); if (leaf) { StringCopy (AppendWack (nativeNamePtr), leaf); } GbAppendString (&growBuf, S_SHORTLONG_TREE); GbAppendString (&growBuf, TEXT("\\")); beginBuffIdx = growBuf.End - 1; beginSegPtr = GetFirstSeg (nativeNamePtr); if (beginSegPtr) { beginSegPtr = _tcsinc (beginSegPtr); GbAppendStringAB (&growBuf, nativeNamePtr, beginSegPtr); while (beginSegPtr) { endSegPtr = _tcschr (beginSegPtr, TEXT('\\')); if (!endSegPtr) { endSegPtr = GetEndOfString (beginSegPtr); MYASSERT (endSegPtr); } savedChar = *endSegPtr; *endSegPtr = 0; if (pGetShortName (beginSegPtr, &findData)) { if (*findData.cAlternateFileName) { savedEnd = growBuf.End - 1; GbAppendString (&growBuf, findData.cAlternateFileName); kh1 = MemDbAddKey (nativeName); if (kh1) { kh2 = MemDbAddKey ((PCTSTR) growBuf.Buf); if (kh2) { b = MemDbSetValueByHandle (kh1, FILENAME_LONG); b = b && MemDbSetValueByHandle (kh2, FILENAME_SHORT); b = b && MemDbAddDoubleLinkageByKeyHandle (kh1, kh2, 0); } else { b = FALSE; } if (!b) { MemDbDeleteKey (nativeName); } } growBuf.End = savedEnd; } GbAppendString (&growBuf, findData.cFileName); } else { GbAppendStringAB (&growBuf, beginSegPtr, endSegPtr); } *endSegPtr = savedChar; if (savedChar) { beginSegPtr = _tcsinc (endSegPtr); GbAppendStringAB (&growBuf, endSegPtr, beginSegPtr); } else { beginSegPtr = NULL; } } } FreePathString (nativeName); if (node) { IsmDestroyObjectString (node); } if (leaf) { IsmDestroyObjectString (leaf); } } GbFree (&growBuf); return result; } MIG_OBJECTID IsmGetObjectIdFromName ( IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE EncodedObjectName, IN BOOL MustExist ) { MIG_OBJECTID result = 0; KEYHANDLE objectId; PCTSTR decoratedPath; ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId); __try { decoratedPath = GetDecoratedObjectPathFromName (ObjectTypeId, EncodedObjectName, FALSE); if (!decoratedPath) { __leave; } if (MustExist) { objectId = MemDbGetHandleFromKey (decoratedPath); } else { objectId = MemDbSetKey (decoratedPath); // if GetLastError = ERROR_ALREADY_EXISTS we don't have to do // anything, the object is already in our database if (GetLastError () == ERROR_SUCCESS) { if (MemDbSetValueByHandle (objectId, ObjectTypeId)) { g_TotalObjects.TotalObjects ++; if ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE) { g_SourceObjects.TotalObjects ++; } else { g_DestinationObjects.TotalObjects ++; } IncrementTotalObjectCount (ObjectTypeId); if (ObjectTypeId == (MIG_FILE_TYPE|PLATFORM_SOURCE)) { // // fire up the short-long algorithm // if (g_IsmCurrentPlatform == PLATFORM_SOURCE) { pAddShortLongInfo (EncodedObjectName); } else { pAddShortLongInfoOnDest (EncodedObjectName); } } } else { objectId = 0; } } if (!objectId) { EngineError (); __leave; } } result = (MIG_OBJECTID) objectId; } __finally { FreePathString (decoratedPath); INVALID_POINTER (decoratedPath); } return result; } MIG_OBJECTID GetObjectIdForModification ( IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE EncodedObjectName ) { if (!CanObjectTypeBeModified (ObjectTypeId)) { return 0; } return IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, FALSE); } BOOL pEnumFirstVirtualObject ( OUT PMIG_OBJECT_ENUM ObjectEnum, IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE ObjectPattern ) { PCTSTR decoratedPath = NULL; BOOL result = FALSE; POBJECTENUM_HANDLE handle; ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId); ZeroMemory (ObjectEnum, sizeof (MIG_OBJECT_ENUM)); ObjectEnum->ObjectTypeId = ObjectTypeId; ObjectEnum->Handle = MemAllocZeroed (sizeof (OBJECTENUM_HANDLE)); handle = ObjectEnum->Handle; __try { if (!ObsHasNode (ObjectPattern)) { DEBUGMSG ((DBG_ERROR, "Pattern %s has nul node", ObjectPattern)); __leave; } decoratedPath = GetDecoratedObjectPathFromName (ObjectTypeId, ObjectPattern, TRUE); if (!decoratedPath) { __leave; } if (DbEnumFirst ( ObjectTypeId, &handle->MemDbEnum, decoratedPath, &handle->ParsedPatterns )) { ObjectEnum->ObjectName = handle->MemDbEnum.KeyName; ObjectEnum->ObjectId = (MIG_OBJECTID) handle->MemDbEnum.KeyHandle; result = TRUE; } } __finally { FreePathString (decoratedPath); INVALID_POINTER (decoratedPath); if (!result) { pAbortVirtualObjectEnum (ObjectEnum); } } return result; } BOOL pEnumNextVirtualObject ( IN OUT PMIG_OBJECT_ENUM ObjectEnum ) { BOOL result = FALSE; POBJECTENUM_HANDLE handle; handle = ObjectEnum->Handle; if (MemDbEnumNext (&handle->MemDbEnum)) { ObjectEnum->ObjectName = handle->MemDbEnum.KeyName; ObjectEnum->ObjectId = (MIG_OBJECTID) handle->MemDbEnum.KeyHandle; result = TRUE; } else { pAbortVirtualObjectEnum (ObjectEnum); } return result; } VOID pAbortVirtualObjectEnum ( IN PMIG_OBJECT_ENUM ObjectEnum ) { POBJECTENUM_HANDLE handle; handle = ObjectEnum->Handle; if (handle) { DbEnumFreeStruct (&handle->ParsedPatterns); MemDbAbortEnum (&handle->MemDbEnum); FreeAlloc (handle); INVALID_POINTER (ObjectEnum->Handle); } ZeroMemory (ObjectEnum, sizeof (MIG_OBJECT_ENUM)); } BOOL IsmEnumFirstSourceObjectEx ( OUT PMIG_OBJECT_ENUM ObjectEnum, IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE ObjectPattern, IN BOOL EnumerateVirtualObjects ) { // // First fix ObjectTypeId // ObjectTypeId &= (~PLATFORM_MASK); ObjectTypeId |= PLATFORM_SOURCE; // // If this is the destination or we are forced, then we enumerate virtual objects // if (EnumerateVirtualObjects || (g_IsmModulePlatformContext == PLATFORM_CURRENT && g_IsmCurrentPlatform == PLATFORM_DESTINATION) || g_IsmModulePlatformContext == PLATFORM_DESTINATION ) { return pEnumFirstVirtualObject (ObjectEnum, ObjectTypeId, ObjectPattern); } return EnumFirstPhysicalObject (ObjectEnum, ObjectTypeId, ObjectPattern); } BOOL IsmEnumNextObject ( IN OUT PMIG_OBJECT_ENUM ObjectEnum ) { // // Verify enumeration has not completed // if (!ObjectEnum->Handle) { return FALSE; } // // If ObjectId is specified, we are enumerating the ISM // if (ObjectEnum->ObjectId) { return pEnumNextVirtualObject (ObjectEnum); } // // Otherwise we are enumerating physical objects // return EnumNextPhysicalObject (ObjectEnum); } VOID IsmAbortObjectEnum ( IN PMIG_OBJECT_ENUM ObjectEnum ) { // // Verify enumeration has not completed // if (!ObjectEnum->Handle) { return; } // // If ObjectId is specified, we are enumerating the ISM, otherwise we are // enumerating physical objects // if (ObjectEnum->ObjectId) { pAbortVirtualObjectEnum (ObjectEnum); } else { AbortPhysicalObjectEnum (ObjectEnum); } return; } BOOL IsmEnumFirstDestinationObjectEx ( OUT PMIG_OBJECT_ENUM ObjectEnum, IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE ObjectPattern, IN BOOL EnumerateVirtualObjects ) { // // First fix ObjectTypeId // ObjectTypeId &= (~PLATFORM_MASK); ObjectTypeId |= PLATFORM_SOURCE; // // If this is the source, it's illegal // if (g_IsmCurrentPlatform == PLATFORM_SOURCE) { return FALSE; } if (EnumerateVirtualObjects) { return pEnumFirstVirtualObject (ObjectEnum, ObjectTypeId, ObjectPattern); } return EnumFirstPhysicalObject (ObjectEnum, ObjectTypeId, ObjectPattern); } BOOL IsObjectLocked ( IN MIG_OBJECTID ObjectId ) { UINT flags; if (!MemDbGetFlagsByHandle ((KEYHANDLE) ObjectId, &flags)) { return FALSE; } return flags & OBJECT_LOCKED; } BOOL IsHandleLocked ( IN MIG_OBJECTID ObjectId, IN KEYHANDLE Handle ) { TCHAR lockKey[256]; wsprintf (lockKey, S_LOCK_KEY, ObjectId); return MemDbTestSingleLinkageValue (lockKey, 0, Handle); } BOOL TestLock ( IN MIG_OBJECTID ObjectId, IN KEYHANDLE Handle ) { return IsObjectLocked (ObjectId) || IsHandleLocked (ObjectId, Handle); } VOID pLockHandle ( IN MIG_OBJECTID ObjectId, IN KEYHANDLE Handle ) { TCHAR lockKey[256]; wsprintf (lockKey, S_LOCK_KEY, ObjectId); if (!MemDbAddSingleLinkageValue (lockKey, 0, Handle, FALSE)) { EngineError (); } } BOOL pLockGroup ( IN KEYHANDLE ItemId, IN BOOL FirstPass, IN ULONG_PTR Arg ) { pLockHandle ((MIG_OBJECTID) Arg, (KEYHANDLE) ItemId); return TRUE; } VOID LockHandle ( IN MIG_OBJECTID ObjectId, IN KEYHANDLE Handle ) { RECURSERETURN rc; rc = RecurseForGroupItems ( Handle, pLockGroup, (ULONG_PTR) ObjectId, TRUE, FALSE ); if (rc == RECURSE_FAIL || rc == RECURSE_SUCCESS) { return; } MYASSERT (rc == RECURSE_NOT_NEEDED); pLockHandle (ObjectId, Handle); } VOID IsmLockObjectId ( IN MIG_OBJECTID ObjectId ) { if (!MemDbSetFlagsByHandle (ObjectId, OBJECT_LOCKED, 0)) { EngineError (); } } VOID IsmLockObject ( IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE EncodedObjectName ) { MIG_OBJECTID objectId; ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId); objectId = GetObjectIdForModification (ObjectTypeId, EncodedObjectName); if (objectId) { IsmLockObjectId (objectId); } } PCTSTR GetObjectNameForDebugMsg ( IN MIG_OBJECTID ObjectId ) { static TCHAR buffer[256]; PCTSTR name; name = MemDbGetKeyFromHandle ((KEYHANDLE) ObjectId, 1); if (name) { StackStringCopy (buffer, name); MemDbReleaseMemory (name); } else { StringCopy (buffer, TEXT("")); } return name; } PCTSTR pIsValidCName ( IN PCTSTR Name ) { UINT u; if (!Name) { return NULL; } if (!__iscsymf (_tcsnextc (Name))) { return NULL; } Name = _tcsinc (Name); u = 1; while (*Name) { if (!__iscsym (_tcsnextc (Name))) { return Name; } Name = _tcsinc (Name); u++; } if (u > 64) { return NULL; } return Name; } BOOL IsValidCName ( IN PCTSTR Name ) { PCTSTR p; BOOL result = FALSE; p = pIsValidCName (Name); if (p && (!*p)) { result = TRUE; } else { SetLastError (ERROR_INVALID_NAME); } return TRUE; } BOOL IsValidCNameWithDots ( IN PCTSTR Name ) { PCTSTR p; p = pIsValidCName (Name); while (p && _tcsnextc (p) == TEXT('.')) { p = _tcsinc (p); p = pIsValidCName (p); } return p && (*p == 0); } BOOL MarkGroupIds ( IN PCTSTR MemDbKey ) { UINT flags; PTSTR keyCopy; PTSTR p; PTSTR start; BOOL b = FALSE; keyCopy = DuplicateText (MemDbKey); __try { p = (PTSTR) FindLastWack (keyCopy); if (!p) { __leave; } start = _tcschr (p + 1, TEXT('.')); // // Make sure all groups in the string are legal // p = start; while (p) { *p = 0; if (MemDbGetFlags (keyCopy, &flags)) { if (flags & ITEM_ID) { DEBUGMSG ((DBG_ERROR, "Group already used as item. Key=%s", keyCopy)); __leave; } } *p = TEXT('.'); p = _tcschr (p + 1, TEXT('.')); } if (MemDbGetFlags (keyCopy, &flags)) { if (flags & GROUP_ID) { DEBUGMSG ((DBG_ERROR, "Item already used as group. Key=%s", keyCopy)); __leave; } } // // Mark all groups // p = start; while (p) { *p = 0; if (!MemDbSetFlags (keyCopy, GROUP_ID, 0)) { EngineError (); __leave; } *p = TEXT('.'); p = _tcschr (p + 1, TEXT('.')); } // // Mark the item // b = MemDbSetFlags (keyCopy, ITEM_ID, 0); if (!b) { EngineError (); } } __finally { FreeText (keyCopy); } return b; } BOOL IsGroupId ( IN KEYHANDLE Id ) { UINT flags; if (!MemDbGetFlagsByHandle (Id, &flags)) { return FALSE; } return flags & GROUP_ID; } BOOL IsItemId ( IN KEYHANDLE Id ) { UINT flags; if (!MemDbGetFlagsByHandle (Id, &flags)) { return FALSE; } return flags & ITEM_ID; } KEYHANDLE GetGroupOfId ( IN KEYHANDLE GroupOrItemId ) { PTSTR key; PTSTR p; PTSTR lastDot; KEYHANDLE result = 0; key = (PTSTR) MemDbGetKeyFromHandle (GroupOrItemId, 0); if (!key) { return 0; } __try { p = (PTSTR) FindLastWack (key); if (!p) { __leave; } lastDot = NULL; do { p = _tcschr (p + 1, TEXT('.')); if (p) { lastDot = p; } } while (p); if (!lastDot) { __leave; } *lastDot = 0; result = MemDbGetHandleFromKey (key); MYASSERT (!result || IsGroupId (result)); } __finally { MemDbReleaseMemory (key); } return result; } BOOL pGroupRegistrationWorker ( IN OUT PGROUPREGISTRATION_ENUM EnumPtr ) { EnumPtr->GroupOrItemId = EnumPtr->EnumStruct.KeyHandle; MYASSERT (EnumPtr->EnumStruct.Flags & (GROUP_ID|ITEM_ID)); EnumPtr->ItemId = (EnumPtr->EnumStruct.Flags & ITEM_ID) != 0; return TRUE; } BOOL EnumFirstGroupRegistration ( OUT PGROUPREGISTRATION_ENUM EnumPtr, IN KEYHANDLE GroupId ) { BOOL b; PCTSTR key; PCTSTR pattern; if (!IsGroupId (GroupId)) { DEBUGMSG ((DBG_ERROR, "EnumFirstGroupRegistration: GroupId is invalid")); return FALSE; } key = MemDbGetKeyFromHandle (GroupId, 0); if (!key) { return 0; } pattern = JoinText (key, TEXT(".*")); MemDbReleaseMemory (key); INVALID_POINTER (key); b = MemDbEnumFirst ( &EnumPtr->EnumStruct, pattern, ENUMFLAG_NORMAL, ENUMLEVEL_ALLLEVELS, ENUMLEVEL_ALLLEVELS ); FreeText (pattern); INVALID_POINTER (pattern); if (!b) { return FALSE; } return pGroupRegistrationWorker (EnumPtr); } BOOL EnumNextGroupRegistration ( IN OUT PGROUPREGISTRATION_ENUM EnumPtr ) { if (!MemDbEnumNext (&EnumPtr->EnumStruct)) { return FALSE; } return pGroupRegistrationWorker (EnumPtr); } VOID AbortGroupRegistrationEnum ( IN PGROUPREGISTRATION_ENUM EnumPtr ) { MemDbAbortEnum (&EnumPtr->EnumStruct); ZeroMemory (EnumPtr, sizeof (GROUPREGISTRATION_ENUM)); } RECURSERETURN RecurseForGroupItems ( IN KEYHANDLE GroupId, IN GROUPITEM_CALLBACK Callback, IN ULONG_PTR Arg, IN BOOL ExecuteOnly, IN BOOL LogicalOrOnResults ) { PCTSTR groupKey = NULL; PCTSTR enumKey = NULL; MEMDB_ENUM e; UINT pass; RECURSERETURN result = RECURSE_FAIL; BOOL b; BOOL oneSuccess = FALSE; if (!IsGroupId (GroupId)) { return RECURSE_NOT_NEEDED; } groupKey = MemDbGetKeyFromHandle (GroupId, 0); enumKey = JoinText (groupKey, TEXT(".*")); MemDbReleaseMemory (groupKey); __try { for (pass = ExecuteOnly ? 1 : 0 ; pass < 2 ; pass++) { // // Enumerate all attributes (skip attribute subgroups) // if (MemDbEnumFirst ( &e, enumKey, ENUMFLAG_NORMAL, ENUMLEVEL_ALLLEVELS, ENUMLEVEL_ALLLEVELS )) { do { if (IsItemId (e.KeyHandle)) { // // Pass 0 is for query, pass 1 is for execute // b = Callback (e.KeyHandle, pass == 0, Arg); if (LogicalOrOnResults) { oneSuccess |= b; } else if (!b) { MemDbAbortEnum (&e); __leave; } } } while (MemDbEnumNext (&e)); MemDbAbortEnum (&e); } } if (LogicalOrOnResults) { if (!oneSuccess) { __leave; } } result = RECURSE_SUCCESS; } __finally { FreeText (enumKey); INVALID_POINTER (enumKey); } return result; } BOOL DbEnumFillStruct ( IN MIG_OBJECTTYPEID ObjectTypeId, IN PCTSTR Pattern, OUT PDBENUM_ARGS Args ) { PWSTR p, q; PWSTR plainPatternEnd = NULL; PWSTR patternCopy; PCWSTR node; PCWSTR leaf; BOOL freeNode = TRUE; Args->ObjectTypeId = ObjectTypeId; // // Split the pattern into a node and leaf pattern // patternCopy = (PWSTR) CreateUnicode (Pattern); ObsSplitObjectStringW (patternCopy, &node, &leaf); if (!node) { node = L"*"; freeNode = FALSE; } DestroyUnicode (patternCopy); INVALID_POINTER (patternCopy); // // Find the first level in node that has a pattern. Then // truncate the node and parse it as a "plain" pattern. // This makes sure a node pattern such as c:\foo\* will // match c:\foo itself. // patternCopy = DuplicateTextW (node); p = patternCopy; plainPatternEnd = patternCopy; while (p && *p) { MYASSERT (*plainPatternEnd); q = (PWSTR) ObsFindNonEncodedCharInEncodedStringW (p, L'\\'); if (!q) { p = GetEndOfStringW (p); } else { p = q; *p = 0; } if (ObsFindNonEncodedCharInEncodedStringW (plainPatternEnd, L'*') || ObsFindNonEncodedCharInEncodedStringW (plainPatternEnd, L'?') ) { *plainPatternEnd = 0; break; } plainPatternEnd = p; if (q) { *p = L'\\'; p++; } } if (plainPatternEnd && *plainPatternEnd == 0 && *patternCopy) { Args->PlainNodeParsedPattern = CreateParsedPatternW (patternCopy); } else { Args->PlainNodeParsedPattern = NULL; } // // Fill the rest of the struct, clean up and exit // Args->NodeParsedPattern = CreateParsedPatternW (node); if (leaf) { Args->LeafParsedPattern = CreateParsedPatternW (leaf); } else { Args->LeafParsedPattern = NULL; } if (freeNode) { ObsFreeW (node); INVALID_POINTER (node); } ObsFreeW (leaf); INVALID_POINTER (leaf); FreeTextW (patternCopy); INVALID_POINTER (patternCopy); return TRUE; } VOID DbEnumFreeStruct ( IN PDBENUM_ARGS Args ) { if (Args->PlainNodeParsedPattern) { DestroyParsedPatternW (Args->PlainNodeParsedPattern); INVALID_POINTER (Args->PlainNodeParsedPattern); } if (Args->NodeParsedPattern) { DestroyParsedPatternW (Args->NodeParsedPattern); INVALID_POINTER (Args->NodeParsedPattern); } if (Args->LeafParsedPattern) { DestroyParsedPatternW (Args->LeafParsedPattern); INVALID_POINTER (Args->LeafParsedPattern); } ZeroMemory (Args, sizeof (DBENUM_ARGS)); } BOOL DbEnumFind ( IN PCWSTR KeySegment ) { // // Does KeySegment have a pattern? // if (ObsFindNonEncodedCharInEncodedStringW (KeySegment, L'*') || ObsFindNonEncodedCharInEncodedStringW (KeySegment, L'?') ) { return TRUE; } return FALSE; } BOOL DbEnumMatch ( IN PCVOID InboundArgs, IN PCWSTR CurrentKey ) { PDBENUM_ARGS args; PCWSTR node; PCWSTR leaf; PCWSTR newLeaf; BOOL result = FALSE; WCHAR dummy[] = L""; args = (PDBENUM_ARGS) InboundArgs; CurrentKey = wcschr (CurrentKey, L'\\'); MYASSERT (CurrentKey); if (!CurrentKey) { return FALSE; } CurrentKey++; // // Split current key into node and leaf // ObsSplitObjectStringW (CurrentKey, &node, &leaf); MYASSERT (args->NodeParsedPattern); if (node) { // // Test node against parsed pattern // if (args->NodeParsedPattern) { result = TestParsedPatternW (args->NodeParsedPattern, node); if (!result && args->PlainNodeParsedPattern) { result = TestParsedPatternW (args->PlainNodeParsedPattern, node); } if (result) { if (leaf) { result = FALSE; if (args->LeafParsedPattern) { result = TestParsedPatternW (args->LeafParsedPattern, leaf); if (!result && ((args->ObjectTypeId & (~PLATFORM_MASK)) == MIG_FILE_TYPE) && (wcschr (leaf, L'.') == NULL) ) { newLeaf = JoinTextW (leaf, L"."); result = TestParsedPatternW (args->LeafParsedPattern, newLeaf); FreeTextW (newLeaf); } } } else { if (args->LeafParsedPattern && args->PlainNodeParsedPattern && TestParsedPatternW (args->PlainNodeParsedPattern, node) ) { result = FALSE; } } } } } else { // // Test empty node against parsed pattern // if (args->NodeParsedPattern) { result = TestParsedPatternW (args->NodeParsedPattern, dummy); if (!result && args->PlainNodeParsedPattern) { result = TestParsedPatternW (args->PlainNodeParsedPattern, dummy); } if (result) { if (leaf) { result = FALSE; if (args->LeafParsedPattern) { result = TestParsedPatternW (args->LeafParsedPattern, leaf); } } } } } ObsFreeW (node); INVALID_POINTER (node); ObsFreeW (leaf); INVALID_POINTER (leaf); return result; } BOOL DbEnumFirst ( IN MIG_OBJECTTYPEID ObjectTypeId, OUT PMEMDB_ENUM EnumPtr, IN PCTSTR PatternString, OUT PDBENUM_ARGS ArgsStruct ) { MEMDB_PATTERNSTRUCTW callbacks; PCTSTR objectPattern; objectPattern = _tcschr (PatternString, TEXT('\\')); if (!objectPattern) { MYASSERT (FALSE); return FALSE; } objectPattern++; #ifdef DEBUG { PCTSTR p; // // Verify pattern string base is not a pattern. This is // required, because we assume the first level will not // use enumeration, but will use direct lookup. // p = _tcschr (PatternString, TEXT('*')); MYASSERT (!p || p >= objectPattern); p = _tcschr (PatternString, TEXT('?')); MYASSERT (!p || p >= objectPattern); } #endif DbEnumFillStruct (ObjectTypeId, objectPattern, ArgsStruct); callbacks.PatternFind = DbEnumFind; callbacks.PatternMatch = DbEnumMatch; callbacks.Data = ArgsStruct; return MemDbEnumFirstEx ( EnumPtr, PatternString, ENUMFLAG_NORMAL, 1, ENUMLEVEL_ALLLEVELS, &callbacks ); } BOOL IsmRegisterRestoreCallback ( IN PMIG_RESTORECALLBACK RestoreCallback ) { PRESTORE_STRUCT restoreStruct; restoreStruct = (PRESTORE_STRUCT) PmGetMemory (g_IsmPool, sizeof (RESTORE_STRUCT)); restoreStruct->RestoreCallback = RestoreCallback; restoreStruct->Next = g_RestoreCallbacks; g_RestoreCallbacks = restoreStruct; return TRUE; } BOOL EnumFirstRestoreCallback ( OUT PMIG_RESTORECALLBACK_ENUM RestoreCallbackEnum ) { RestoreCallbackEnum->RestoreStruct = g_RestoreCallbacks; if (RestoreCallbackEnum->RestoreStruct) { RestoreCallbackEnum->RestoreCallback = RestoreCallbackEnum->RestoreStruct->RestoreCallback; return TRUE; } return FALSE; } BOOL EnumNextRestoreCallback ( IN OUT PMIG_RESTORECALLBACK_ENUM RestoreCallbackEnum ) { if (!RestoreCallbackEnum->RestoreStruct) { return FALSE; } RestoreCallbackEnum->RestoreStruct = RestoreCallbackEnum->RestoreStruct->Next; if (RestoreCallbackEnum->RestoreStruct) { RestoreCallbackEnum->RestoreCallback = RestoreCallbackEnum->RestoreStruct->RestoreCallback; return TRUE; } return FALSE; } VOID pFreeRestoreCallbacks ( VOID ) { PRESTORE_STRUCT restoreStruct, oldStruct; restoreStruct = g_RestoreCallbacks; while (restoreStruct) { oldStruct = restoreStruct; restoreStruct = restoreStruct->Next; PmReleaseMemory (g_IsmPool, oldStruct); } g_RestoreCallbacks = NULL; } ULONG_PTR IsmSendMessageToApp ( UINT Message, ULONG_PTR Arg ) { if (g_MessageCallback) { return g_MessageCallback (Message, Arg); } return 0; } MIG_PROGRESSSLICEID IsmRegisterProgressSlice ( IN UINT Ticks, IN UINT TimeEstimateInSeconds ) { PPROGSLICE slice; MIG_PROGRESSSLICEID sliceId; if (!TimeEstimateInSeconds || !Ticks) { DEBUGMSG ((DBG_WARNING, "Ticks/TimeEstimateInSeconds must not be zero")); return 0; } sliceId = (MIG_PROGRESSSLICEID) (g_SliceBuffer.End / sizeof (PROGSLICE) + 1); slice = (PPROGSLICE) GbGrow (&g_SliceBuffer, sizeof (PROGSLICE)); slice->SliceSize = Ticks; slice->CurrentPosition = 0; slice->SliceSizeInSeconds = TimeEstimateInSeconds; return sliceId; } VOID pCallProgressBar ( IN MIG_PROGRESSSTATE State ) { ULONGLONG temp; UINT u; PPROGSLICE slice; UINT totalTicks = 0; UINT currentPos = 0; MIG_APPINFO appInfo; if (g_ProgressBarFn) { for (u = 0 ; u < g_SliceBuffer.End ; u += sizeof (PROGSLICE)) { slice = (PPROGSLICE) (g_SliceBuffer.Buf + u); temp = (ULONGLONG) slice->CurrentPosition * (ULONGLONG) slice->SliceSizeInSeconds; temp *= 10; temp /= (ULONGLONG) slice->SliceSize; currentPos += (UINT) temp; temp = (ULONGLONG) slice->SliceSizeInSeconds * 10; totalTicks += (UINT) temp; } if (State == MIG_END_PHASE) { currentPos = totalTicks; } else if (State == MIG_BEGIN_PHASE) { currentPos = 0; } g_ProgressBarFn ( g_CurrentPhase, State, currentPos, totalTicks, g_ProgressBarArg ); } if (State == MIG_BEGIN_PHASE) { ZeroMemory (&appInfo, sizeof (MIG_APPINFO)); appInfo.Phase = g_CurrentPhase; IsmSendMessageToApp (ISMMESSAGE_APP_INFO_NOW, (ULONG_PTR)(&appInfo)); } if (State == MIG_END_PHASE) { ZeroMemory (&appInfo, sizeof (MIG_APPINFO)); IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo)); } } BOOL IsmTickProgressBar ( IN MIG_PROGRESSSLICEID SliceId, IN UINT TickDelta OPTIONAL ) { PPROGSLICE slice; if (!g_CurrentPhase || !g_ProgressBarFn) { SliceId = 0; } if (!TickDelta) { TickDelta = 1; } if (SliceId) { // // Update the slice ID // SliceId--; if (SliceId >= (MIG_PROGRESSSLICEID) (g_SliceBuffer.End / sizeof (PROGSLICE))) { DEBUGMSG ((DBG_ERROR, "Invalid slice ID passed to IsmTickProgressBar")); return FALSE; } slice = (PPROGSLICE) g_SliceBuffer.Buf + SliceId; if (slice->CurrentPosition < slice->SliceSize) { slice->CurrentPosition += TickDelta; if (slice->CurrentPosition > slice->SliceSize) { slice->CurrentPosition = slice->SliceSize; } // // Call the application's progress callback // pCallProgressBar (MIG_IN_PHASE); } else { DEBUGMSG ((DBG_WARNING, "IsmTickProgressBar: Slice already completed")); } } return !CheckCancel(); } VOID IsmSetCancel ( VOID ) { if (g_CancelEvent) { SetEvent (g_CancelEvent); } } MIG_PLATFORMTYPEID IsmGetRealPlatform ( VOID ) { return g_IsmCurrentPlatform; } BOOL IsmCurrentlyExecuting ( VOID ) { return g_ExecutionInProgress; } BOOL IsmCreateUser ( IN PCTSTR UserName, IN PCTSTR Domain ) { if (g_TempProfile) { DEBUGMSG ((DBG_WHOOPS, "Cannot call IsmCreateUser more than once")); return FALSE; } // record that we attempted to create the user pRecordUserData ( UserName, Domain, NULL, NULL, TRUE ); g_TempProfile = OpenTemporaryProfile (UserName, Domain); if (g_TempProfile) { // record that we created the user pRecordUserData ( UserName, Domain, g_TempProfile->UserStringSid, g_TempProfile->UserProfileRoot, TRUE ); // prepare the user journal pPrepareUserJournal (g_TempProfile); // let ETM module know this BroadcastUserCreation (g_TempProfile); } return g_TempProfile != NULL; } MIG_PARSEDPATTERN IsmCreateParsedPattern ( IN MIG_OBJECTSTRINGHANDLE EncodedObject ) { return (MIG_PARSEDPATTERN)ObsCreateParsedPattern (EncodedObject); } VOID IsmDestroyParsedPattern ( IN MIG_PARSEDPATTERN ParsedPattern ) { ObsDestroyParsedPattern ((POBSPARSEDPATTERN)ParsedPattern); } BOOL IsmParsedPatternMatchEx ( IN MIG_PARSEDPATTERN ParsedPattern, IN MIG_OBJECTTYPEID ObjectTypeId, OPTIONAL IN PCTSTR Node, OPTIONAL IN PCTSTR Leaf OPTIONAL ) { BOOL result = TRUE; PTSTR newLeaf; PTSTR tempString; POBSPARSEDPATTERN obsParsedPattern = (POBSPARSEDPATTERN) ParsedPattern; MYASSERT (Node && obsParsedPattern->NodePattern); if (!(Node && obsParsedPattern->NodePattern)) { return FALSE; } if (((obsParsedPattern->Flags & OBSPF_NOLEAF) && Leaf) || ((obsParsedPattern->Flags & OBSPF_EXACTLEAF) && !Leaf) ) { return FALSE; } if (!TestParsedPattern (obsParsedPattern->NodePattern, Node)) { // // let's try one more time with a wack at the end // tempString = JoinText (Node, TEXT("\\")); result = TestParsedPattern (obsParsedPattern->NodePattern, tempString); FreeText (tempString); if (!result) { return FALSE; } } if (Leaf) { if (!obsParsedPattern->LeafPattern) { return FALSE; } result = TestParsedPattern (obsParsedPattern->LeafPattern, Leaf); if (!result && ((ObjectTypeId & (~PLATFORM_MASK)) == MIG_FILE_TYPE) && (_tcschr (Leaf, TEXT('.')) == NULL) ) { newLeaf = JoinText (Leaf, TEXT(".")); if (newLeaf) { result = TestParsedPattern (obsParsedPattern->LeafPattern, newLeaf); FreeText (newLeaf); } else { result = FALSE; } } } else { if (!obsParsedPattern->ExactRoot) { result = FALSE; } } return result; } BOOL IsmParsedPatternMatch ( IN MIG_PARSEDPATTERN ParsedPattern, IN MIG_OBJECTTYPEID ObjectTypeId, OPTIONAL IN MIG_OBJECTSTRINGHANDLE ObjectName ) { PTSTR decodedNode; PTSTR decodedLeaf; BOOL b; if (!IsmCreateObjectStringsFromHandle (ObjectName, &decodedNode, &decodedLeaf)) { return FALSE; } b = IsmParsedPatternMatchEx (ParsedPattern, ObjectTypeId, decodedNode, decodedLeaf); IsmDestroyObjectString (decodedNode); IsmDestroyObjectString (decodedLeaf); return b; } BOOL IsmGetMappedUserData ( OUT PMIG_USERDATA UserData ) { if (UserData && g_TempProfile) { ZeroMemory (UserData, sizeof (MIG_USERDATA)); UserData->UserName = g_TempProfile->UserName; UserData->DomainName = g_TempProfile->DomainName; UserData->AccountName = g_TempProfile->AccountName; UserData->UserProfileRoot = g_TempProfile->UserProfileRoot; UserData->UserSid = g_TempProfile->UserSid; } return (g_TempProfile != NULL); } BOOL IsmAddControlFile ( IN PCTSTR ObjectName, IN PCTSTR NativePath ) { MIG_OBJECTSTRINGHANDLE memDbObjectName; TCHAR tempFile[MAX_TCHAR_PATH]; if (g_IsmCurrentPlatform == PLATFORM_CURRENT) { DEBUGMSG ((DBG_WHOOPS, "IsmSetPlatform must be called before IsmAddControlFile")); return FALSE; } // Do not start with a | special character if (*ObjectName == TEXT('|')) { return FALSE; } // INF file paths are limited to MAX_PATH in size if (SizeOfString (NativePath) > ARRAYSIZE(tempFile)) { return FALSE; } IsmGetTempFile (tempFile, ARRAYSIZE (tempFile)); if (!CopyFile (NativePath, tempFile, FALSE)) { return FALSE; } // Add filename to hashtable for cleanup HtAddString (g_ControlFileTable, tempFile); memDbObjectName = IsmCreateObjectHandle (TEXT("External"), ObjectName); DataTypeAddObject (memDbObjectName, tempFile, TRUE); IsmDestroyObjectHandle (memDbObjectName); return TRUE; } BOOL IsmGetControlFile ( IN MIG_OBJECTTYPEID ObjectTypeId, IN PCTSTR ObjectName, IN PTSTR Buffer // Required to be MAX_PATH_PLUS_NUL in size ) { MIG_CONTENT content; TCHAR tempFile[MAX_TCHAR_PATH]; BOOL result = FALSE; if (IsmAcquireObject (ObjectTypeId, ObjectName, &content)) { MYASSERT (content.ContentInFile); if ((content.ContentInFile) && (SizeOfString (content.FileContent.ContentPath) < ARRAYSIZE(tempFile))) { IsmGetTempFile (tempFile, ARRAYSIZE (tempFile)); if (CopyFile (content.FileContent.ContentPath, tempFile, FALSE)) { // Return a copy of the filename StringCopy (Buffer, tempFile); // Add filename to hashtable for cleanup HtAddString (g_ControlFileTable, tempFile); result = TRUE; } } } return result; } BOOL IsmSetRollbackJournalType ( IN BOOL Common ) { TCHAR winDir [MAX_PATH]; PCURRENT_USER_DATA currentUserData; BOOL result = FALSE; if (g_JournalUsed) { return FALSE; } if (g_JournalDirectory) { FreePathString (g_JournalDirectory); } if (Common) { if (GetWindowsDirectory (winDir, ARRAYSIZE (winDir))) { g_JournalDirectory = JoinPaths (winDir, TEXT("usmt2.tmp")); result = TRUE; } } else { currentUserData = GetCurrentUserData (); if (currentUserData) { g_JournalDirectory = JoinPaths (currentUserData->UserProfilePath, TEXT("usmt2.tmp")); FreeCurrentUserData (currentUserData); } } return TRUE; } BOOL IsmCanWriteRollbackJournal ( VOID ) { BOOL result = TRUE; DWORD err; if (DoesFileExist (g_JournalDirectory)) { FiRemoveAllFilesInTree (g_JournalDirectory); } if (!BfCreateDirectory (g_JournalDirectory)) { err = GetLastError (); if ((err == ERROR_ALREADY_EXISTS) || (err == ERROR_ACCESS_DENIED) ) { result = FALSE; } } if (result) { FiRemoveAllFilesInTree (g_JournalDirectory); } return result; } VOID pRecordUserData ( IN PCTSTR UserName, IN PCTSTR UserDomain, IN PCTSTR UserStringSid, IN PCTSTR UserProfilePath, IN BOOL ProfileCreated ) { LONGLONG lastPos; TCHAR userName [MAX_TCHAR_PATH]; TCHAR userDomain [MAX_TCHAR_PATH]; TCHAR userStringSid [MAX_TCHAR_PATH]; TCHAR userProfilePath [MAX_TCHAR_PATH]; DWORD dontCare; if (g_RollbackMode) { return; } if (!g_JournalDirectory) { DEBUGMSG ((DBG_WHOOPS, "Journal directory does not exist.")); return; } if (!g_JournalHandle) { DEBUGMSG ((DBG_WHOOPS, "Journal file is not opened.")); return; } // If the file position is just after the journal header we'll just write // the info, otherwise we are going to save the current position, // write our data and restore the file position. if (!BfGetFilePointer (g_JournalHandle, &lastPos)) { DEBUGMSG ((DBG_WHOOPS, "Something wrong with the Journal file.")); return; } if (lastPos != JOURNAL_HEADER_SIZE) { if (!BfSetFilePointer (g_JournalHandle, JOURNAL_HEADER_SIZE)) { DEBUGMSG ((DBG_WHOOPS, "Something wrong with the Journal file.")); return; } } // now write the info ZeroMemory (userName, MAX_TCHAR_PATH); ZeroMemory (userDomain, MAX_TCHAR_PATH); ZeroMemory (userStringSid, MAX_TCHAR_PATH); ZeroMemory (userProfilePath, MAX_TCHAR_PATH); if (UserName) { StringCopyTcharCount (userName, UserName, MAX_TCHAR_PATH); } if (UserDomain) { StringCopyTcharCount (userDomain, UserDomain, MAX_TCHAR_PATH); } if (UserStringSid) { StringCopyTcharCount (userStringSid, UserStringSid, MAX_TCHAR_PATH); } if (UserProfilePath) { StringCopyTcharCount (userProfilePath, UserProfilePath, MAX_TCHAR_PATH); } WriteFile ( g_JournalHandle, userName, MAX_TCHAR_PATH, &dontCare, NULL ); WriteFile ( g_JournalHandle, userDomain, MAX_TCHAR_PATH, &dontCare, NULL ); WriteFile ( g_JournalHandle, userStringSid, MAX_TCHAR_PATH, &dontCare, NULL ); WriteFile ( g_JournalHandle, userProfilePath, MAX_TCHAR_PATH, &dontCare, NULL ); WriteFile ( g_JournalHandle, &ProfileCreated, sizeof (BOOL), &dontCare, NULL ); if (lastPos != JOURNAL_HEADER_SIZE) { BfSetFilePointer (g_JournalHandle, lastPos); } } VOID IsmRecordOperation ( IN DWORD OperationType, IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE ObjectName ) { #ifdef PRERELEASE // crash hooks #define MAX_OBJECTTYPES 20 static DWORD totalObjects = 0; 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}; MIG_OBJECTTYPEID objTypeId; PCTSTR nativeName = NULL; BOOL doCrash = FALSE; #endif static GROWBUFFER buffer = INIT_GROWBUFFER; static DWORD backupIdx = 0; TCHAR destFile [13]; PCTSTR destFullPath; DWORD entrySize = 0; WIN32_FIND_DATA findData; MIG_CONTENT objectContent; DWORD dontCare; if (g_RollbackMode) { return; } if (!g_JournalDirectory) { DEBUGMSG ((DBG_WHOOPS, "Journal directory does not exist.")); return; } if (!g_JournalHandle) { DEBUGMSG ((DBG_WHOOPS, "Journal file is not opened.")); return; } ObjectTypeId &= (~PLATFORM_MASK); buffer.End = 0; switch (OperationType) { case JRNOP_CREATE: #ifdef PRERELEASE // crash hooks totalObjects ++; if (g_CrashCountObjects == totalObjects) { doCrash = TRUE; } objTypeId = ObjectTypeId & (~PLATFORM_MASK); if (objTypeId && (objTypeId <= MAX_OBJECTTYPES)) { typeObjects [objTypeId - 1]++; if ((g_CrashCountTypeId == objTypeId) && (g_CrashCountType == typeObjects [objTypeId - 1]) ) { doCrash = TRUE; } } if (g_CrashNameTypeId == objTypeId) { nativeName = IsmGetNativeObjectName (objTypeId, ObjectName); if (StringIMatch (nativeName, g_CrashNameObject)) { doCrash = TRUE; } IsmReleaseMemory (nativeName); } #endif GbAppendDword (&buffer, OperationType); CopyMemory (GbGrow (&buffer, sizeof (MIG_OBJECTTYPEID)), &ObjectTypeId, sizeof (MIG_OBJECTTYPEID)); GbAppendDword (&buffer, SizeOfString (ObjectName)); GbCopyString (&buffer, ObjectName); entrySize = buffer.End; break; case JRNOP_DELETE: if (!IsmAcquireObject ( ObjectTypeId | PLATFORM_DESTINATION, ObjectName, &objectContent )) { return; } GbAppendDword (&buffer, OperationType); CopyMemory (GbGrow (&buffer, sizeof (MIG_OBJECTTYPEID)), &ObjectTypeId, sizeof (MIG_OBJECTTYPEID)); GbAppendDword (&buffer, SizeOfString (ObjectName)); GbCopyString (&buffer, ObjectName); GbAppendDword (&buffer, sizeof (MIG_CONTENT)); CopyMemory (GbGrow (&buffer, sizeof (MIG_CONTENT)), &objectContent, sizeof (MIG_CONTENT)); if (objectContent.Details.DetailsSize && objectContent.Details.DetailsData) { GbAppendDword (&buffer, objectContent.Details.DetailsSize); CopyMemory ( GbGrow (&buffer, objectContent.Details.DetailsSize), objectContent.Details.DetailsData, objectContent.Details.DetailsSize ); } else { GbAppendDword (&buffer, 0); } if (objectContent.ContentInFile) { if (DoesFileExistEx (objectContent.FileContent.ContentPath, &findData) && ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) ) { // extra data is the relative path to the backup copy of this file backupIdx ++; wsprintf (destFile, TEXT("%08d.BAK"), backupIdx); destFullPath = JoinPaths (g_JournalDirectory, destFile); BfCopyAndFlushFile (objectContent.FileContent.ContentPath, destFullPath, FALSE); FreePathString (destFullPath); GbAppendDword (&buffer, SizeOfString (destFile)); GbCopyString (&buffer, destFile); } else { GbAppendDword (&buffer, 0); } } else { // extra data is the actual content GbAppendDword (&buffer, objectContent.MemoryContent.ContentSize); if (objectContent.MemoryContent.ContentSize) { CopyMemory ( GbGrow (&buffer, objectContent.MemoryContent.ContentSize), objectContent.MemoryContent.ContentBytes, objectContent.MemoryContent.ContentSize ); } } entrySize = buffer.End; IsmReleaseObject (&objectContent); break; default: DEBUGMSG ((DBG_WHOOPS, "Wrong operation type in pRecordOperation: %d", OperationType)); return; } WriteFile ( g_JournalHandle, &entrySize, sizeof (DWORD), &dontCare, NULL ); WriteFile ( g_JournalHandle, buffer.Buf, buffer.End, &dontCare, NULL ); WriteFile ( g_JournalHandle, &entrySize, sizeof (DWORD), &dontCare, NULL ); FlushFileBuffers (g_JournalHandle); #ifdef PRERELEASE if (doCrash) { DebugBreak (); } #endif g_JournalUsed = TRUE; } BOOL IsmSetDelayedOperationsCommand ( IN PCTSTR DelayedOperationsCommand ) { if (g_DelayedOperationsCommand) { FreePathString (g_DelayedOperationsCommand); } g_DelayedOperationsCommand = DuplicatePathString (DelayedOperationsCommand, 0); return TRUE; } VOID IsmRecordDelayedOperation ( IN DWORD OperationType, IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE ObjectName, IN PMIG_CONTENT ObjectContent ) { static GROWBUFFER buffer = INIT_GROWBUFFER; static DWORD backupIdx = 0; TCHAR destFile [13]; PCTSTR destFullPath; DWORD entrySize = 0; WIN32_FIND_DATA findData; DWORD dontCare; if (!g_TempProfile || !g_TempProfile->DelayedOpJrn || !g_TempProfile->DelayedOpJrnHandle || (g_TempProfile->DelayedOpJrnHandle == INVALID_HANDLE_VALUE) ) { DEBUGMSG ((DBG_WHOOPS, "Delayed operations Journal does not exist.")); return; } ObjectTypeId &= (~PLATFORM_MASK); buffer.End = 0; switch (OperationType) { case JRNOP_DELETE: GbAppendDword (&buffer, OperationType); CopyMemory (GbGrow (&buffer, sizeof (MIG_OBJECTTYPEID)), &ObjectTypeId, sizeof (MIG_OBJECTTYPEID)); GbAppendDword (&buffer, SizeOfString (ObjectName)); GbCopyString (&buffer, ObjectName); entrySize = buffer.End; break; case JRNOP_CREATE: case JRNOP_REPLACE: GbAppendDword (&buffer, OperationType); CopyMemory (GbGrow (&buffer, sizeof (MIG_OBJECTTYPEID)), &ObjectTypeId, sizeof (MIG_OBJECTTYPEID)); GbAppendDword (&buffer, SizeOfString (ObjectName)); GbCopyString (&buffer, ObjectName); GbAppendDword (&buffer, sizeof (MIG_CONTENT)); CopyMemory (GbGrow (&buffer, sizeof (MIG_CONTENT)), ObjectContent, sizeof (MIG_CONTENT)); if (ObjectContent->Details.DetailsSize && ObjectContent->Details.DetailsData) { GbAppendDword (&buffer, ObjectContent->Details.DetailsSize); CopyMemory ( GbGrow (&buffer, ObjectContent->Details.DetailsSize), ObjectContent->Details.DetailsData, ObjectContent->Details.DetailsSize ); } else { GbAppendDword (&buffer, 0); } if (ObjectContent->ContentInFile) { if (DoesFileExistEx (ObjectContent->FileContent.ContentPath, &findData) && ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) ) { // extra data is the relative path to the backup copy of this file backupIdx ++; wsprintf (destFile, TEXT("%08d.BAK"), backupIdx); destFullPath = JoinPaths (g_TempProfile->DelayedOpJrn, destFile); BfCopyAndFlushFile (ObjectContent->FileContent.ContentPath, destFullPath, FALSE); FreePathString (destFullPath); GbAppendDword (&buffer, SizeOfString (destFile)); GbCopyString (&buffer, destFile); } else { GbAppendDword (&buffer, 0); } } else { // extra data is the actual content GbAppendDword (&buffer, ObjectContent->MemoryContent.ContentSize); if (ObjectContent->MemoryContent.ContentSize) { CopyMemory ( GbGrow (&buffer, ObjectContent->MemoryContent.ContentSize), ObjectContent->MemoryContent.ContentBytes, ObjectContent->MemoryContent.ContentSize ); } } entrySize = buffer.End; break; default: DEBUGMSG ((DBG_WHOOPS, "Wrong operation type in IsmRecordDelayedOperation: %d", OperationType)); return; } WriteFile ( g_TempProfile->DelayedOpJrnHandle, &entrySize, sizeof (DWORD), &dontCare, NULL ); WriteFile ( g_TempProfile->DelayedOpJrnHandle, buffer.Buf, buffer.End, &dontCare, NULL ); WriteFile ( g_TempProfile->DelayedOpJrnHandle, &entrySize, sizeof (DWORD), &dontCare, NULL ); FlushFileBuffers (g_TempProfile->DelayedOpJrnHandle); } PMIG_OBJECTCOUNT IsmGetObjectsStatistics ( IN MIG_OBJECTTYPEID ObjectTypeId OPTIONAL ) { if ((ObjectTypeId & (~PLATFORM_MASK)) == 0) { if (ObjectTypeId & PLATFORM_SOURCE) { return &g_SourceObjects; } else if (ObjectTypeId & PLATFORM_DESTINATION) { return &g_DestinationObjects; } else { return &g_TotalObjects; } } else { return GetTypeObjectsStatistics (ObjectTypeId); } } VOID EngineError ( VOID ) { LOG ((LOG_MODULE_ERROR, (PCSTR) MSG_ENGINE_FAILURE)); IsmSetCancel(); } BOOL IsmGetOsVersionInfo ( IN MIG_PLATFORMTYPEID Platform, OUT PMIG_OSVERSIONINFO VersionInfo ) { TCHAR tempStr [sizeof (UINT) * 2 + 3]; if (!VersionInfo) { return FALSE; } ZeroMemory (VersionInfo, sizeof (MIG_OSVERSIONINFO)); if (Platform == PLATFORM_CURRENT) { Platform = g_IsmCurrentPlatform; } if (!IsmGetEnvironmentString ( Platform, NULL, S_VER_OSTYPE, tempStr, sizeof(tempStr), NULL )) { return FALSE; } _stscanf (tempStr, TEXT("%lx"), &(VersionInfo->OsType)); if (!IsmGetEnvironmentString ( Platform, NULL, S_VER_OSMAJOR, tempStr, sizeof(tempStr), NULL )) { return FALSE; } _stscanf (tempStr, TEXT("%lx"), &(VersionInfo->OsMajorVersion)); if (!IsmGetEnvironmentString ( Platform, NULL, S_VER_OSMINOR, tempStr, sizeof(tempStr), NULL )) { return FALSE; } _stscanf (tempStr, TEXT("%lx"), &(VersionInfo->OsMinorVersion)); if (!IsmGetEnvironmentString ( Platform, NULL, S_VER_OSBUILD, tempStr, sizeof(tempStr), NULL )) { return FALSE; } _stscanf (tempStr, TEXT("%lx"), &(VersionInfo->OsBuildNumber)); if (VersionInfo->OsType == OSTYPE_WINDOWS9X) { VersionInfo->OsTypeName = OSTYPE_WINDOWS9X_STR; if (VersionInfo->OsMajorVersion == OSMAJOR_WIN95) { VersionInfo->OsMajorVersionName = OSMAJOR_WIN95_STR; if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) { VersionInfo->OsMinorVersion = OSMINOR_GOLD; } } if (VersionInfo->OsMajorVersion == OSMAJOR_WIN95OSR2) { VersionInfo->OsMajorVersionName = OSMAJOR_WIN95OSR2_STR; if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) { VersionInfo->OsMinorVersion = OSMINOR_GOLD; } } if (VersionInfo->OsMajorVersion == OSMAJOR_WIN98) { VersionInfo->OsMajorVersionName = OSMAJOR_WIN98_STR; if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) { VersionInfo->OsMinorVersion = OSMINOR_GOLD; } if (VersionInfo->OsMinorVersion == OSMINOR_WIN98SE) { VersionInfo->OsMinorVersionName = OSMINOR_WIN98SE_STR; } } if (VersionInfo->OsMajorVersion == OSMAJOR_WINME) { VersionInfo->OsMajorVersionName = OSMAJOR_WINME_STR; if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) { VersionInfo->OsMinorVersion = OSMINOR_GOLD; } } } if (VersionInfo->OsType == OSTYPE_WINDOWSNT) { VersionInfo->OsTypeName = OSTYPE_WINDOWSNT_STR; if (VersionInfo->OsMajorVersion == OSMAJOR_WINNT4) { VersionInfo->OsMajorVersionName = OSMAJOR_WINNT4_STR; if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) { VersionInfo->OsMinorVersionName = OSMINOR_GOLD_STR; } } if (VersionInfo->OsMajorVersion == OSMAJOR_WINNT5) { VersionInfo->OsMajorVersionName = OSMAJOR_WINNT5_STR; if (VersionInfo->OsMinorVersion == OSMINOR_GOLD) { VersionInfo->OsMinorVersionName = OSMINOR_GOLD_STR; } if (VersionInfo->OsMinorVersion == OSMINOR_WINNT51) { VersionInfo->OsMinorVersionName = OSMINOR_WINNT51_STR; } } } return TRUE; } BOOL pGetFunctionData ( IN PCTSTR FunctionMultiSz, OUT PCTSTR *FunctionId, OUT PCTSTR *MultiSzCopy ) { GROWBUFFER buf = INIT_GROWBUFFER; MULTISZ_ENUM e; BOOL result = TRUE; if (!FunctionMultiSz) { return FALSE; } if (!FunctionId) { return FALSE; } if (!MultiSzCopy) { return FALSE; } *FunctionId = NULL; *MultiSzCopy = NULL; buf.End = 0; if (result && EnumFirstMultiSz (&e, FunctionMultiSz)) { do { GbMultiSzAppend (&buf, e.CurrentString); } while (EnumNextMultiSz (&e)); } if (buf.End) { *MultiSzCopy = IsmGetMemory (buf.End); CopyMemory ((PTSTR)(*MultiSzCopy), buf.Buf, buf.End); } else { result = FALSE; } buf.End = 0; if (result && EnumFirstMultiSz (&e, FunctionMultiSz)) { do { GbAppendString (&buf, e.CurrentString); GbAppendString (&buf, TEXT(";")); } while (EnumNextMultiSz (&e)); } if (buf.End) { *FunctionId = IsmGetMemory (buf.End); CopyMemory ((PTSTR)(*FunctionId), buf.Buf, buf.End); } else { result = FALSE; } if (!result) { if (*MultiSzCopy) { IsmReleaseMemory (*MultiSzCopy); *MultiSzCopy = NULL; } if (*FunctionId) { IsmReleaseMemory (*FunctionId); *FunctionId = NULL; } } return result; } BOOL IsmExecuteFunction ( IN UINT ExecutionPhase, IN PCTSTR FunctionMultiSz ) { PCTSTR functionId; PCTSTR functionMultiSz; BOOL result = FALSE; switch (ExecutionPhase) { case MIG_EXECUTE_PREPROCESS: if (g_PreProcessTable) { if (pGetFunctionData (FunctionMultiSz, &functionId, &functionMultiSz)) { HtAddStringEx (g_PreProcessTable, functionId, &functionMultiSz, FALSE); IsmReleaseMemory (functionId); } } result = TRUE; break; case MIG_EXECUTE_REFRESH: if (g_RefreshTable) { if (pGetFunctionData (FunctionMultiSz, &functionId, &functionMultiSz)) { HtAddStringEx (g_RefreshTable, functionId, &functionMultiSz, FALSE); IsmReleaseMemory (functionId); } } result = TRUE; break; case MIG_EXECUTE_POSTPROCESS: if (g_PostProcessTable) { if (pGetFunctionData (FunctionMultiSz, &functionId, &functionMultiSz)) { HtAddStringEx (g_PostProcessTable, functionId, &functionMultiSz, FALSE); IsmReleaseMemory (functionId); } } result = TRUE; break; } return result; }