|
|
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
inftrans.c
Abstract:
Implements a basic secure server transport module
Author:
Jim Schmidt (jimschm) 08-Mar-2000
Revision History:
<alias> <date> <comments>
--*/
//
// Includes
//
#include "pch.h"
#include "logmsg.h"
#include <conio.h>
#define DBG_INFTRANS "InfTrans"
//
// Strings
//
#define S_TRANSPORT_DIR TEXT("USMT2I.UNC")
#define S_TRANSPORT_DIR_E TEXT("USMT2E.UNC")
#define S_TRANSPORT_INF_FILE TEXT("migration.inf")
#define S_TRANSPORT_STATUS_FILE TEXT("status")
#define S_TRANSPORT_ESTIMATE_FILE TEXT("USMTSIZE.TXT")
#define S_DETAILS_PREFIX TEXT("details")
#define S_DATABASEFILE_LITE TEXT("|MainDatabaseFile\\LITE") // pipe is to decorate for uniqueness
//
// Constants
//
#define TRFLAG_FILE 0x01
#define TRFLAG_MEMORY 0x02
#define INFTR_SIG 0x55534D32 //USM2
#define TRSTATUS_DIRTY 0x00000001
#define TRSTATUS_READY 0x00000002
#define TRSTATUS_LOCKED 0x00000003
//
// Macros
//
// None
//
// Types
//
typedef struct { TCHAR TempFile [MAX_PATH]; PCVOID AllocPtr; PCVOID DetailsPtr; HANDLE FileHandle; HANDLE MapHandle; } ALLOCSTATE, *PALLOCSTATE;
typedef struct { UINT ClusterSize; ULONGLONG StoreSize; } ESTIMATE_SIZE, *PESTIMATE_SIZE;
//
// Globals
//
BOOL g_EstimateSizeOnly = FALSE; MIG_TRANSPORTSTORAGEID g_ReliableStorageId; PCTSTR g_InfTransStoragePath = NULL; PCTSTR g_InfTransTransportPath = NULL; PCTSTR g_InfTransTransportStatus = NULL; HANDLE g_InfTransTransportStatusHandle = NULL; UINT g_Platform; MIG_PROGRESSSLICEID g_DatabaseSlice; MIG_PROGRESSSLICEID g_PersistentSlice; ESTIMATE_SIZE g_EstimateSize [] = { {512, 0}, {1024, 0}, {2048, 0}, {4096, 0}, {8192, 0}, {16384, 0}, {32768, 0}, {65536, 0}, {131072, 0}, {262144, 0}, {524288, 0}, {1048576, 0}, {0, 0} };
//
// Macro expansion list
//
// None
//
// Private function prototypes
//
// see unctrans.h
//
// Macro expansion definition
//
// None
//
// Code
//
BOOL pSetInfTransStatus ( IN HANDLE TrJournalHandle, IN DWORD Status ) { DWORD signature = INFTR_SIG; BOOL result = FALSE;
if (BfSetFilePointer (TrJournalHandle, 0)) { result = TRUE; result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&signature), sizeof (DWORD)); result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&Status), sizeof (DWORD)); result = result && FlushFileBuffers (TrJournalHandle); } return TRUE; }
DWORD pGetInfTransStatus ( IN PCTSTR TrJournal ) { HANDLE trJrnHandle; DWORD signature = 0; DWORD error; DWORD result = 0;
if (TrJournal && TrJournal [0]) { trJrnHandle = BfOpenReadFile (TrJournal); if (trJrnHandle) { if (BfSetFilePointer (trJrnHandle, 0)) { if (BfReadFile (trJrnHandle, (PBYTE)(&signature), sizeof (DWORD))) { if (signature == INFTR_SIG) { if (!BfReadFile (trJrnHandle, (PBYTE)(&result), sizeof (DWORD))) { result = 0; } } } } CloseHandle (trJrnHandle); } else { error = GetLastError (); if ((error == ERROR_ACCESS_DENIED) || (error == ERROR_SHARING_VIOLATION) ) { result = TRSTATUS_LOCKED; } } } return result; }
BOOL WINAPI InfTransTransportInitialize ( IN PMIG_LOGCALLBACK LogCallback ) { //
// Initialize globals
//
LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback); g_ReliableStorageId = IsmRegisterTransport (S_RELIABLE_STORAGE_TRANSPORT);
return TRUE; }
VOID WINAPI InfTransTransportEstimateProgressBar ( MIG_PLATFORMTYPEID PlatformTypeId ) { DEBUGMSG ((DBG_VERBOSE, "Assuming transport download has no progress impact")); }
BOOL WINAPI InfTransTransportQueryCapabilities ( IN MIG_TRANSPORTSTORAGEID TransportStorageId, OUT PMIG_TRANSPORTTYPE TransportType, OUT PMIG_TRANSPORTCAPABILITIES Capabilities, OUT PCTSTR *FriendlyDescription ) { if (TransportStorageId != g_ReliableStorageId) { return FALSE; }
*TransportType = TRANSPORTTYPE_LIGHT; *Capabilities = CAPABILITY_SPACEESTIMATE; *FriendlyDescription = TEXT("Another Computer on the Network"); return TRUE; }
BOOL WINAPI InfTransTransportSetStorage ( IN MIG_PLATFORMTYPEID Platform, IN MIG_TRANSPORTSTORAGEID TransportStorageId, IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities, IN PCTSTR StoragePath, OUT PBOOL Valid, OUT PBOOL ImageExists ) { PCTSTR transportPath; PCTSTR transportStatus; MIG_OBJECTSTRINGHANDLE encodedPath; DWORD status; BOOL result = FALSE;
if (Valid) { *Valid = FALSE; } if (ImageExists) { *ImageExists = FALSE; }
if (TransportStorageId == g_ReliableStorageId) {
if (!RequiredCapabilities || (RequiredCapabilities & CAPABILITY_SPACEESTIMATE) ) {
if (RequiredCapabilities & CAPABILITY_SPACEESTIMATE) { g_EstimateSizeOnly = TRUE; }
if (g_EstimateSizeOnly) { transportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR_E); } else { transportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR); } transportStatus = JoinPaths (transportPath, S_TRANSPORT_STATUS_FILE);
if (!DoesFileExist (transportPath)) {
// we require UNC path or a full path (like c:\...)
if (transportPath[0] == '\\' && transportPath[1] == '\\') { // this is a UNC path
*Valid = TRUE; } else if (transportPath[1] == ':') { // this is a normal full path
*Valid = TRUE; } else { *Valid = FALSE; }
*ImageExists = FALSE;
} else {
status = pGetInfTransStatus (transportStatus);
switch (status) { case TRSTATUS_LOCKED: *ImageExists = TRUE; *Valid = FALSE; break; case TRSTATUS_READY: *ImageExists = TRUE; *Valid = TRUE; break; case TRSTATUS_DIRTY: *ImageExists = FALSE; *Valid = TRUE; break; default: *ImageExists = FALSE; *Valid = TRUE; } }
FreePathString (transportStatus); FreePathString (transportPath); result = TRUE; } }
if (result && *Valid) {
if (g_InfTransStoragePath) { FreePathString (g_InfTransStoragePath); g_InfTransStoragePath = NULL; }
if (g_InfTransTransportPath) { FreePathString (g_InfTransTransportPath); g_InfTransTransportPath = NULL; }
g_InfTransStoragePath = DuplicatePathString (StoragePath, 0); if (g_EstimateSizeOnly) { g_InfTransTransportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR_E); } else { g_InfTransTransportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR); } g_InfTransTransportStatus = JoinPaths (g_InfTransTransportPath, S_TRANSPORT_STATUS_FILE);
encodedPath = IsmCreateSimpleObjectPattern (g_InfTransTransportPath, FALSE, NULL, FALSE); if (encodedPath) { IsmRegisterStaticExclusion (MIG_FILE_TYPE, encodedPath); IsmDestroyObjectHandle (encodedPath); } }
return result; }
BOOL pInfTransSaveDetails ( IN PCTSTR DecoratedObject, IN PMIG_DETAILS Details ) { PCTSTR key; BOOL b;
if ((!Details) || (!Details->DetailsSize)) { return TRUE; }
key = JoinText (S_DETAILS_PREFIX, DecoratedObject);
b = (MemDbSetUnorderedBlob (key, 0, Details->DetailsData, Details->DetailsSize) != 0);
FreeText (key);
return b; }
PCTSTR pInfTransBuildDecoratedObject ( IN MIG_OBJECTTYPEID ObjectTypeId, IN ENCODEDSTRHANDLE ObjectName ) { TCHAR prefix[32];
wsprintf (prefix, TEXT("%u"), ObjectTypeId & (~PLATFORM_MASK));
return JoinPaths (prefix, ObjectName); }
VOID pInfTransDestroyDecoratedObject ( IN PCTSTR String ) { FreePathString (String); }
BOOL pObjectNameToFileName ( IN MIG_OBJECTSTRINGHANDLE ObjectName, OUT PCTSTR *FileName, OUT PCTSTR *DirName OPTIONAL ) { PCTSTR node, leaf; PCTSTR newNode, dirName; BOOL result = FALSE;
if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) { newNode = StringSearchAndReplace (node, TEXT(":"), TEXT("")); if (newNode) { result = TRUE; if (leaf) { dirName = JoinPaths (g_InfTransTransportPath, newNode); *FileName = JoinPaths (dirName, leaf); if (!DirName) { FreePathString (dirName); } else { *DirName = dirName; } FreePathString (newNode); } else { *FileName = JoinPaths (g_InfTransTransportPath, newNode); if (DirName) { *DirName = *FileName; } FreePathString (newNode); } } else { dirName = JoinPaths (g_InfTransTransportPath, node); *FileName = JoinPaths (dirName, leaf); FreePathString (dirName); if (DirName) { *DirName = JoinPaths (g_InfTransTransportPath, node); } result = TRUE; } IsmDestroyObjectString (node); IsmDestroyObjectString (leaf); } return result; }
BOOL pIsShortFileName ( IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE ObjectName, IN PCTSTR TempDir ) { PCTSTR nativeFileName; PCTSTR fileNamePtr; PCTSTR testFileName; HANDLE fileHandle; WIN32_FIND_DATA fileInfo; BOOL result = FALSE;
nativeFileName = IsmGetNativeObjectName (ObjectTypeId, ObjectName); if (nativeFileName) { fileNamePtr = GetFileNameFromPath (nativeFileName); if (fileNamePtr) { testFileName = JoinPaths (TempDir, fileNamePtr); fileHandle = BfCreateFile (testFileName); if (fileHandle) { CloseHandle (fileHandle); if (DoesFileExistEx (testFileName, &fileInfo)) { result = (fileInfo.cAlternateFileName [0] == 0) || StringIMatch (fileInfo.cFileName, fileInfo.cAlternateFileName); } DeleteFile (testFileName); } } IsmReleaseMemory (nativeFileName); } return result; }
UINT pGetClusterSize ( IN PCTSTR Path ) { PTSTR drivePath = NULL; PTSTR wackPtr; DWORD sectPerClust = 0; DWORD bytesPerSect = 0; DWORD freeClust = 0; DWORD totalClust = 0; UINT result = 0; DWORD err = 0;
if (!Path) { return result; }
// if this is a UNC drive
if (Path [0] && (Path [0] == TEXT('\\')) && (Path [1] == TEXT('\\'))) { // we need to leave exactly 2 segments (like \\server\share) and
// add a wack at the end
drivePath = DuplicatePathString (Path, 1); // we know the first two characters are wacks. Wack is a single byte
// character so the next call is safe
wackPtr = _tcschr (drivePath + 2, TEXT('\\')); if (wackPtr) { wackPtr = _tcsinc (wackPtr); if (wackPtr) { wackPtr = _tcschr (wackPtr, TEXT('\\')); if (wackPtr) { // there are more than two segments here
// wack is a single byte char so this is safe
*wackPtr = 0; } AppendWack (drivePath); } else { // something is wrong, we could not advance one character?
FreePathString (drivePath); drivePath = NULL; } } else { // something is wrong, we don't even have one segment
FreePathString (drivePath); drivePath = NULL; } } else { if (Path [0] && (Path [1] == TEXT (':')) && (Path [2] == TEXT ('\\'))) { drivePath = DuplicatePathString (Path, 0); drivePath [3] = 0; } }
if (drivePath) { if (GetDiskFreeSpace (drivePath, §PerClust, &bytesPerSect, &freeClust, &totalClust)) { result = bytesPerSect * sectPerClust; } else { LOG ((LOG_WARNING, (PCSTR) MSG_CLUSTER_SIZE_ERROR, GetLastError ())); } FreePathString (drivePath); drivePath = NULL; }
return result; }
BOOL pStoreStatusOK ( IN PCTSTR StorePath, IN PCTSTR StoreStatusPath ) { DWORD status; BOOL result = FALSE;
if (DoesFileExist (StorePath)) {
status = pGetInfTransStatus (StoreStatusPath);
switch (status) { case TRSTATUS_LOCKED: SetLastError (ERROR_ACCESS_DENIED); LOG ((LOG_ERROR, (PCSTR) MSG_TRANSPORT_DIR_BUSY, StorePath)); return FALSE; case TRSTATUS_DIRTY: result = FiRemoveAllFilesInTree (StorePath); if (!result) { PushError (); SetLastError (ERROR_ACCESS_DENIED); LOG ((LOG_ERROR, (PCSTR) MSG_TRANSPORT_DIR_BUSY, StorePath)); PopError (); return FALSE; } break; case TRSTATUS_READY: default: if (IsmSendMessageToApp (TRANSPORTMESSAGE_IMAGE_EXISTS, 0)) { result = FiRemoveAllFilesInTree (StorePath); if (!result) { PushError (); LOG ((LOG_ERROR, (PCSTR) MSG_CANT_EMPTY_DIR , StorePath)); PopError (); return FALSE; } } else { SetLastError (ERROR_ALREADY_EXISTS); LOG ((LOG_ERROR, (PCSTR) MSG_NOT_EMPTY, StorePath)); return FALSE; } break; } }
if (!BfCreateDirectory (StorePath)) { PushError (); LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_DIR, StorePath)); PopError (); return FALSE; }
g_InfTransTransportStatusHandle = BfCreateFile (StoreStatusPath); if (!g_InfTransTransportStatusHandle) { PushError (); LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_STATUS_FILE, StoreStatusPath)); PopError (); return FALSE; }
pSetInfTransStatus (g_InfTransTransportStatusHandle, TRSTATUS_DIRTY);
return TRUE; }
BOOL pWriteEstimateFile ( VOID ) { PCTSTR infFile = NULL; HANDLE infFileHandle = NULL; PCTSTR estimateFile = NULL; HANDLE estimateFileHandle = NULL; UINT index = 0; LONGLONG fileSize = 0; UINT currClusterSize = 0; ULONGLONG currStoreSize = 0; TCHAR estimateBuff1 [MAX_PATH]; TCHAR estimateBuff2 [MAX_PATH]; BOOL result = TRUE;
// now it's a good time to add all other files that we used to
// the estimate, delete them and then write the estimate file
// in the root of the transport directory (g_InfTransStoragePath)
// let's add the status file to the estimate
if (g_InfTransTransportStatus) { fileSize = BfGetFileSize (g_InfTransTransportStatus); if (fileSize) { index = 0; while (TRUE) { if (g_EstimateSize [index].ClusterSize == 0) { break; } g_EstimateSize [index].StoreSize += ((fileSize / g_EstimateSize [index].ClusterSize) + 1) * g_EstimateSize [index].ClusterSize; index ++; } } }
// OK, now let's add the migration.inf file to the estimate
infFile = JoinPaths (g_InfTransTransportPath, S_TRANSPORT_INF_FILE); if (infFile) { fileSize = BfGetFileSize (infFile); if (fileSize) { index = 0; while (TRUE) { if (g_EstimateSize [index].ClusterSize == 0) { break; } g_EstimateSize [index].StoreSize += ((fileSize / g_EstimateSize [index].ClusterSize) + 1) * g_EstimateSize [index].ClusterSize; index ++; } } FreePathString (infFile); infFile = NULL; } else { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_FIND_ISM_INF)); result = FALSE; }
if (result) {
// Now, let's delete the USMT2E.UNC directory
FiRemoveAllFilesInTree (g_InfTransTransportPath);
// Finally, let's write the estimate file
estimateFile = JoinPaths (g_InfTransStoragePath, S_TRANSPORT_ESTIMATE_FILE); if (estimateFile) { if (DoesFileExist (estimateFile)) { if (IsmSendMessageToApp (TRANSPORTMESSAGE_IMAGE_EXISTS, 0)) { result = DeleteFile (estimateFile); } else { SetLastError (ERROR_ALREADY_EXISTS); LOG ((LOG_ERROR, (PCSTR) MSG_NOT_EMPTY, estimateFile)); result = FALSE; } } if (result) { estimateFileHandle = BfCreateFile (estimateFile); if (estimateFileHandle && (estimateFileHandle != INVALID_HANDLE_VALUE)) { // finally, let's write the stuff
// first write the requirement for current cluster size
currClusterSize = pGetClusterSize (g_InfTransStoragePath); if (currClusterSize) { currStoreSize = 0; index = 0; while (TRUE) { if (g_EstimateSize [index].ClusterSize == 0) { break; } if (g_EstimateSize [index].ClusterSize == currClusterSize) { currStoreSize = g_EstimateSize [index].StoreSize; break; } index ++; } } _ui64tot ( currStoreSize, estimateBuff2, 10 ); wsprintf ( estimateBuff1, TEXT("%u\t%s\r\n"), currClusterSize, estimateBuff2 ); WriteFileString (estimateFileHandle, estimateBuff1);
// then write all cluster sizes
index = 0; while (TRUE) { if (g_EstimateSize [index].ClusterSize == 0) { break; } _ui64tot ( g_EstimateSize [index].StoreSize, estimateBuff2, 10 ); wsprintf ( estimateBuff1, TEXT("%u\t%s\r\n"), g_EstimateSize [index].ClusterSize, estimateBuff2 ); WriteFileString (estimateFileHandle, estimateBuff1); index ++; } CloseHandle (estimateFileHandle); } else { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_ESTIMATE_FILE)); result = FALSE; } } else { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_ESTIMATE_FILE)); } } else { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_ESTIMATE_FILE)); result = FALSE; } }
return result; }
BOOL pAddFileSize ( IN PCTSTR FileName ) { UINT index = 0; LONGLONG fileSize = 0;
fileSize = BfGetFileSize (FileName); if (fileSize) { index = 0; while (TRUE) { if (g_EstimateSize [index].ClusterSize == 0) { break; } g_EstimateSize [index].StoreSize += ((fileSize / g_EstimateSize [index].ClusterSize) + 1) * g_EstimateSize [index].ClusterSize; index ++; } } return TRUE; }
BOOL pAddOneCluster ( VOID ) { UINT index = 0; LONGLONG fileSize = 0;
index = 0; while (TRUE) { if (g_EstimateSize [index].ClusterSize == 0) { break; } g_EstimateSize [index].StoreSize += g_EstimateSize [index].ClusterSize; index ++; } return TRUE; }
BOOL pSaveObject ( IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE ObjectName, IN BOOL ForceNoncritical, IN OUT PGROWBUFFER Buffer ) { MIG_CONTENT objectContent; TRANSCOPY_ERROR transCopyError; INT_PTR appReply; PCTSTR objMultiSz; MULTISZ_ENUM multiSzEnum; BOOL firstMultiSz; PTSTR encodedString = NULL; PCTSTR fileName; PCTSTR dirName; PCTSTR nativeObjectName; BOOL okSave = FALSE; BOOL forceLogError = FALSE;
okSave = FALSE; while (!okSave) {
if (!IsmAcquireObjectEx ( ObjectTypeId, ObjectName, &objectContent, CONTENTTYPE_ANY, 0 )) {
transCopyError.ObjectType = IsmGetObjectTypeName (ObjectTypeId); transCopyError.ObjectName = IsmGetNativeObjectName (ObjectTypeId, ObjectName); transCopyError.Error = GetLastError ();
if (ForceNoncritical || IsmIsNonCriticalObject (ObjectTypeId, ObjectName)) { appReply = APPRESPONSE_IGNORE; } else { appReply = IsmSendMessageToApp (TRANSPORTMESSAGE_SRC_COPY_ERROR, (ULONG_PTR)&transCopyError); if ((appReply == APPRESPONSE_NONE) || (appReply == APPRESPONSE_FAIL) ) { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_COPYSOURCE, transCopyError.ObjectName)); IsmReleaseMemory (transCopyError.ObjectName); return FALSE; } } if (appReply == APPRESPONSE_IGNORE) { LOG (( LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName, GetLastError (), GetLastError () )); IsmReleaseMemory (transCopyError.ObjectName); break; } IsmReleaseMemory (transCopyError.ObjectName); continue; } okSave = TRUE; }
if (okSave) {
// we have an object let's write it to the migration.inf
objMultiSz = IsmConvertObjectToMultiSz ( ObjectName, &objectContent ); if (objMultiSz) { if (EnumFirstMultiSz (&multiSzEnum, objMultiSz)) { firstMultiSz = TRUE; do { if (firstMultiSz) { firstMultiSz = FALSE; } else { GbAppendString (Buffer, TEXT(",")); } encodedString = AllocPathString (SizeOfString (multiSzEnum.CurrentString) * 6); if (EncodeRuleCharsEx (encodedString, multiSzEnum.CurrentString, TEXT("~\r\n%")) != NULL) { GbAppendString (Buffer, encodedString); } else { GbAppendString (Buffer, multiSzEnum.CurrentString); } FreePathString (encodedString); } while (EnumNextMultiSz (&multiSzEnum)); GbAppendString (Buffer, TEXT("\r\n")); } IsmReleaseMemory (objMultiSz); if (objectContent.ContentInFile) { if (objectContent.FileContent.ContentPath) { // Let's see if we only want to estimate the size
if (g_EstimateSizeOnly) {
if (pObjectNameToFileName (ObjectName, &fileName, &dirName)) { // let's add info about directory. The rule is: every new full
// directory is considered to take one cluster
if (!DoesFileExist (dirName)) { pAddOneCluster (); } if (dirName != fileName) { FreePathString (dirName); } FreePathString (fileName); } pAddFileSize (objectContent.FileContent.ContentPath);
} else {
// transform the object name into a file name and copy the
// content file there
if (!pObjectNameToFileName (ObjectName, &fileName, &dirName)) { SetLastError (ERROR_INVALID_DATA); LOG ((LOG_ERROR, (PCSTR) MSG_CANT_COPYSOURCE, objectContent.FileContent.ContentPath)); return FALSE; } if (!BfCreateDirectory (dirName)) {
LOG (( LOG_ERROR, (PCSTR) MSG_CREATE_FAILURE, dirName, objectContent.FileContent.ContentPath ));
if (GetLastError () == ERROR_FILENAME_EXCED_RANGE) { // now we want to see if the app wants us to continue or just quit the transport
transCopyError.ObjectType = IsmGetObjectTypeName (ObjectTypeId); transCopyError.ObjectName = dirName; transCopyError.Error = GetLastError ();
appReply = IsmSendMessageToApp (TRANSPORTMESSAGE_SRC_COPY_ERROR, (ULONG_PTR)&transCopyError); if (appReply == APPRESPONSE_IGNORE) { return TRUE; } }
return FALSE; } okSave = FALSE; while (!okSave) { if (!CopyFile (objectContent.FileContent.ContentPath, fileName, TRUE)) {
if ((TcharCount (fileName) >= MAX_PATH) && (GetLastError () == ERROR_PATH_NOT_FOUND)) { // we tried to copy a file to a location that was bigger than MAX_PATH
// Normally this should return the error 206 (ERROR_FILENAME_EXCED_RANGE).
// However, in my tests this returns error 3 (ERROR_PATH_NOT_FOUND).
// Let's just guard for this case:
SetLastError (ERROR_FILENAME_EXCED_RANGE); }
transCopyError.ObjectType = IsmGetObjectTypeName (ObjectTypeId); transCopyError.ObjectName = IsmGetNativeObjectName (ObjectTypeId, ObjectName); transCopyError.Error = GetLastError ();
forceLogError = FALSE;
if (ForceNoncritical || IsmIsNonCriticalObject (ObjectTypeId, ObjectName)) { appReply = APPRESPONSE_IGNORE; } else { appReply = IsmSendMessageToApp (TRANSPORTMESSAGE_SRC_COPY_ERROR, (ULONG_PTR)&transCopyError); if ((appReply == APPRESPONSE_NONE) || (appReply == APPRESPONSE_FAIL) ) { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_COPYSOURCE, transCopyError.ObjectName)); IsmReleaseMemory (transCopyError.ObjectName); return FALSE; } if (GetLastError () == ERROR_FILENAME_EXCED_RANGE) { forceLogError = TRUE; } } if (appReply == APPRESPONSE_IGNORE) { if (forceLogError) { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_COPYSOURCE, transCopyError.ObjectName)); } else { LOG (( LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName, GetLastError (), GetLastError () )); } IsmReleaseMemory (transCopyError.ObjectName); break; } IsmReleaseMemory (transCopyError.ObjectName); continue; } okSave = TRUE; } if (dirName != fileName) { FreePathString (dirName); } FreePathString (fileName); } } else { // this is just a directory. Let's record that we saved this
nativeObjectName = IsmGetNativeObjectName (ObjectTypeId, ObjectName); MemDbSetValue (nativeObjectName, TRFLAG_FILE); IsmReleaseMemory (nativeObjectName); } } } else { GbAppendString (Buffer, TEXT("\r\n")); } IsmReleaseObject (&objectContent); } return TRUE; }
BOOL WINAPI InfTransTransportSaveState ( VOID ) { MIG_OBJECTTYPEID objectTypeId; MIG_OBJECT_ENUM objEnum; MIG_OBJECTSTRINGHANDLE objectPattern = NULL; MIG_OBJECTSTRINGHANDLE objectName = NULL; MIG_OBJECTSTRINGHANDLE tempObjectName = NULL; MIG_CONTENT objectContent; PCTSTR infFile = NULL; HANDLE infFileHandle = NULL; MIG_OBJECTTYPEID dataTypeId; MIG_OBJECTTYPEID fileTypeId; TCHAR tempDir [MAX_PATH] = TEXT(""); BOOL firstPass = TRUE; BOOL process = TRUE; GROWBUFFER writeBuffer = INIT_GROWBUFFER; MIG_OBJECTTYPEIDENUM objTypeIdEnum; PCTSTR node, leaf; PTSTR nodePtr; TCHAR savedNode; DWORD value; BOOL result = FALSE;
if (!pStoreStatusOK (g_InfTransTransportPath, g_InfTransTransportStatus)) { return FALSE; }
__try {
IsmGetTempDirectory (tempDir, MAX_PATH);
g_Platform = PLATFORM_SOURCE;
objectName = IsmCreateObjectHandle (S_DATABASEFILE_LITE, NULL); if (IsmAcquireObjectEx ( MIG_DATA_TYPE | PLATFORM_SOURCE, objectName, &objectContent, CONTENTTYPE_FILE, 0 )) { // we have the database file, we assume it's an INF file
// and we copy it to our transport location with the
// migration.inf name.
infFile = JoinPaths (g_InfTransTransportPath, S_TRANSPORT_INF_FILE); if (!CopyFile (objectContent.FileContent.ContentPath, infFile, FALSE)) { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_SAVE_ISM_INF)); __leave; } IsmReleaseObject (&objectContent); } else { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_FIND_ISM_INF)); __leave; }
infFileHandle = BfOpenFile (infFile); if (!infFileHandle) { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_FIND_ISM_INF)); __leave; } BfGoToEndOfFile (infFileHandle, 0);
objectPattern = IsmCreateSimpleObjectPattern (NULL, TRUE, NULL, TRUE);
dataTypeId = MIG_DATA_TYPE; fileTypeId = MIG_FILE_TYPE;
if (IsmEnumFirstObjectTypeId (&objTypeIdEnum)) { do {
objectTypeId = objTypeIdEnum.ObjectTypeId;
if (firstPass) { WriteFileString (infFileHandle, TEXT("[")); WriteFileString (infFileHandle, IsmGetObjectTypeName (objectTypeId)); WriteFileString (infFileHandle, TEXT("]\r\n")); }
if (IsmEnumFirstSourceObjectEx (&objEnum, objectTypeId, objectPattern, TRUE)) { do {
writeBuffer.End = 0;
if (IsmCheckCancel()) { IsmAbortObjectTypeIdEnum (&objTypeIdEnum); IsmAbortObjectEnum (&objEnum); __leave; }
if (objectTypeId == dataTypeId && StringIMatch(objEnum.ObjectName, objectName)) { continue; } if (IsmIsPersistentObject (objEnum.ObjectTypeId, objEnum.ObjectName)) {
process = TRUE; if (objectTypeId == fileTypeId) { if (firstPass) { process = pIsShortFileName (objectTypeId, objEnum.ObjectName, tempDir); } else { process = !pIsShortFileName (objectTypeId, objEnum.ObjectName, tempDir); } }
if (process) {
if (objectTypeId == fileTypeId) { // for files and folders we want to save all parent folders in this INF.
// The reason why we do this, is to be able to reconstruct the short-long
// information from this source machine once we get on the destination
// machine
// extract the directory information from ObjectName
if (IsmCreateObjectStringsFromHandle (objEnum.ObjectName, &node, &leaf)) { // Let's walk the node and see if we saved it already.
// If not, save it.
nodePtr = (PTSTR)node; while (nodePtr) { nodePtr = _tcschr (nodePtr, TEXT('\\')); if (nodePtr) { savedNode = *nodePtr; *nodePtr = 0; } if (IsValidFileSpec (node)) { // let's check to see if we already added this directory
value = 0; if (!MemDbGetValue (node, &value) || (value != TRFLAG_FILE)) { tempObjectName = IsmCreateObjectHandle (node, NULL); if (tempObjectName) { writeBuffer.End = 0; if (!pSaveObject ( fileTypeId|PLATFORM_SOURCE, tempObjectName, TRUE, &writeBuffer )) { IsmAbortObjectTypeIdEnum (&objTypeIdEnum); IsmAbortObjectEnum (&objEnum); __leave; } if (writeBuffer.End) { WriteFileString (infFileHandle, (PTSTR) writeBuffer.Buf); } IsmDestroyObjectHandle (tempObjectName); } } } if (nodePtr) { *nodePtr = savedNode; nodePtr = _tcsinc (nodePtr); } }; IsmDestroyObjectString (node); IsmDestroyObjectString (leaf); } // if it's node only it was already saved above, so save only leaf ones
if (leaf) { writeBuffer.End = 0; if (!pSaveObject ( objEnum.ObjectTypeId, objEnum.ObjectName, FALSE, &writeBuffer )) { IsmAbortObjectTypeIdEnum (&objTypeIdEnum); IsmAbortObjectEnum (&objEnum); __leave; } if (writeBuffer.End) { WriteFileString (infFileHandle, (PTSTR) writeBuffer.Buf); } } } else { writeBuffer.End = 0; if (!pSaveObject ( objEnum.ObjectTypeId, objEnum.ObjectName, FALSE, &writeBuffer )) { IsmAbortObjectTypeIdEnum (&objTypeIdEnum); IsmAbortObjectEnum (&objEnum); __leave; } if (writeBuffer.End) { WriteFileString (infFileHandle, (PTSTR) writeBuffer.Buf); } } } } } while (IsmEnumNextObject (&objEnum)); } if (!firstPass || objectTypeId != fileTypeId) { WriteFileString (infFileHandle, TEXT("\r\n\r\n")); }
if ((objectTypeId == fileTypeId) && firstPass) { firstPass = FALSE; } else { if (!IsmEnumNextObjectTypeId (&objTypeIdEnum)) { break; } firstPass = TRUE; } } while (TRUE); }
result = TRUE; } __finally { PushError (); if (tempDir [0]) { FiRemoveAllFilesInTree (tempDir); } IsmDestroyObjectHandle (objectName); if (infFileHandle != NULL) { CloseHandle (infFileHandle); } IsmDestroyObjectHandle (objectPattern); FreePathString (infFile); infFile = NULL; PopError (); }
PushError ();
if (result) { pSetInfTransStatus (g_InfTransTransportStatusHandle, TRSTATUS_READY); } CloseHandle (g_InfTransTransportStatusHandle); g_InfTransTransportStatusHandle = NULL;
GbFree (&writeBuffer);
if (result && g_EstimateSizeOnly) { result = pWriteEstimateFile (); }
if (!result) { FiRemoveAllFilesInTree (g_InfTransTransportPath); }
PopError ();
return result; }
BOOL pSaveObjectContent ( IN MIG_OBJECTTYPEID ObjectTypeId, IN PCTSTR ObjectName, IN PCTSTR DecoratedObject, IN PMIG_CONTENT ObjectContent ) { PCTSTR fileName; BOOL result = FALSE;
if (ObjectContent->ContentInFile) { MemDbSetValue (DecoratedObject, TRFLAG_FILE); if (pObjectNameToFileName (ObjectName, &fileName, NULL)) { if (DoesFileExist (fileName)) { MemDbAddSingleLinkage (DecoratedObject, fileName, 0); } FreePathString (fileName); } } else { MemDbSetValue (DecoratedObject, TRFLAG_MEMORY); if (ObjectContent->MemoryContent.ContentSize && ObjectContent->MemoryContent.ContentBytes ) {
MemDbSetUnorderedBlob ( DecoratedObject, 0, ObjectContent->MemoryContent.ContentBytes, ObjectContent->MemoryContent.ContentSize ); } }
result = pInfTransSaveDetails (DecoratedObject, &(ObjectContent->Details));
return result; }
BOOL WINAPI InfTransTransportBeginApply ( VOID ) { PCTSTR infFile; HINF infHandle; INFSTRUCT is = INITINFSTRUCT_PMHANDLE; MIG_OBJECTTYPEID objectTypeId; GROWBUFFER buff = INIT_GROWBUFFER; PCTSTR field; MIG_CONTENT objectContent; MIG_OBJECTSTRINGHANDLE objectName; UINT index; PCTSTR decoratedObject = NULL; DWORD status = 0; PTSTR decodedString = NULL; MIG_OBJECTTYPEIDENUM objTypeIdEnum; DWORD error;
g_Platform = PLATFORM_DESTINATION;
while (status != TRSTATUS_READY) {
status = pGetInfTransStatus (g_InfTransTransportStatus);
switch (status) { case TRSTATUS_LOCKED: if (!IsmSendMessageToApp (TRANSPORTMESSAGE_IMAGE_LOCKED, 0)) { LOG ((LOG_ERROR, (PCSTR) MSG_TRANSPORT_DIR_BUSY , g_InfTransTransportPath)); error = GetLastError (); if ((error != ERROR_ACCESS_DENIED) && (error != ERROR_SHARING_VIOLATION) ) { SetLastError (ERROR_ACCESS_DENIED); } return FALSE; } break; case TRSTATUS_DIRTY: SetLastError (ERROR_ACCESS_DENIED); LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_IMAGE, g_InfTransTransportPath)); return FALSE; case TRSTATUS_READY: break; default: SetLastError (ERROR_INVALID_DATA); LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_IMAGE, g_InfTransTransportPath)); return FALSE; } }
g_InfTransTransportStatusHandle = BfOpenReadFile (g_InfTransTransportStatus); if (!g_InfTransTransportStatusHandle) { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_STATUS_FILE, g_InfTransTransportStatus)); return FALSE; }
infFile = JoinPaths (g_InfTransTransportPath, S_TRANSPORT_INF_FILE);
// add the database file in memdb so we can serve AcquireObject from the ISM
objectName = IsmCreateObjectHandle (S_DATABASEFILE_LITE, NULL); decoratedObject = pInfTransBuildDecoratedObject (MIG_DATA_TYPE | PLATFORM_SOURCE, objectName); MemDbSetValue (decoratedObject, TRFLAG_FILE); MemDbAddSingleLinkage (decoratedObject, infFile, 0); pInfTransDestroyDecoratedObject (decoratedObject); IsmDestroyObjectHandle (objectName);
infHandle = InfOpenInfFile (infFile);
if (infHandle == INVALID_HANDLE_VALUE) { LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_ISM_INF, infFile)); FreePathString (infFile); return FALSE; }
if (IsmEnumFirstObjectTypeId (&objTypeIdEnum)) { do {
objectTypeId = objTypeIdEnum.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("<empty>")); } index ++; } if (buff.End) { GbCopyString (&buff, TEXT("")); if (IsmConvertMultiSzToObject ( objectTypeId, (PCTSTR)buff.Buf, &objectName, &objectContent )) { // now save the object data into our database
// for future reference
decoratedObject = pInfTransBuildDecoratedObject (objectTypeId | PLATFORM_SOURCE, objectName); pSaveObjectContent (objectTypeId | g_Platform, objectName, decoratedObject, &objectContent); pInfTransDestroyDecoratedObject (decoratedObject);
IsmDestroyObjectHandle (objectName); if ((objectContent.Details.DetailsSize) && (objectContent.Details.DetailsData) ) { IsmReleaseMemory (objectContent.Details.DetailsData); } if (objectContent.ContentInFile) { if (objectContent.FileContent.ContentPath) { IsmReleaseMemory (objectContent.FileContent.ContentPath); } } else { if ((objectContent.MemoryContent.ContentSize) && (objectContent.MemoryContent.ContentBytes) ) { IsmReleaseMemory (objectContent.MemoryContent.ContentBytes); } } } }
} while (InfFindNextLine (&is)); } } while (IsmEnumNextObjectTypeId (&objTypeIdEnum)); }
GbFree (&buff);
InfCleanUpInfStruct (&is);
InfCloseInfFile (infHandle);
FreePathString (infFile);
return TRUE; }
VOID WINAPI InfTransTransportEndApply ( VOID ) { MYASSERT (g_Platform == PLATFORM_DESTINATION);
CloseHandle (g_InfTransTransportStatusHandle); g_InfTransTransportStatusHandle = NULL; }
VOID WINAPI InfTransTransportTerminate ( VOID ) { if (g_InfTransStoragePath) { FreePathString (g_InfTransStoragePath); g_InfTransStoragePath = NULL; } if (g_InfTransTransportPath) { FreePathString (g_InfTransTransportPath); g_InfTransTransportPath = NULL; } if (g_InfTransTransportStatus) { FreePathString (g_InfTransTransportStatus); g_InfTransTransportStatus = NULL; } }
BOOL WINAPI InfTransTransportAcquireObject ( IN MIG_OBJECTTYPEID ObjectTypeId, IN MIG_OBJECTSTRINGHANDLE ObjectName, OUT PMIG_CONTENT ObjectContent, CALLER_INITIALIZED IN MIG_CONTENTTYPE ContentType, IN UINT MemoryContentLimit ) { UINT value; PCBYTE memValue; UINT memValueSize; PCTSTR fileValue = NULL; BOOL valueInFile; KEYHANDLE keyHandle; PALLOCSTATE allocState; PCTSTR detailsKey = NULL; PBYTE details; UINT detailsSize; PCTSTR decoratedObject = NULL; HANDLE fileHandle; BOOL result = FALSE;
if (!ObjectContent) { return FALSE; }
MYASSERT (g_Platform == PLATFORM_DESTINATION); MYASSERT ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE);
decoratedObject = pInfTransBuildDecoratedObject (ObjectTypeId, ObjectName);
allocState = (PALLOCSTATE) MemAllocZeroed (sizeof (ALLOCSTATE));
if (MemDbGetValue (decoratedObject, &value)) { if (value == TRFLAG_FILE) { valueInFile = TRUE; keyHandle = MemDbGetSingleLinkage (decoratedObject, 0, 0); if (keyHandle) { fileValue = MemDbGetKeyFromHandle (keyHandle, 0); result = fileValue != NULL; } else { fileValue = NULL; result = TRUE; } } else if (value == TRFLAG_MEMORY) { valueInFile = FALSE; memValueSize = 0; memValue = MemDbGetUnorderedBlob (decoratedObject, 0, &memValueSize); result = TRUE; } else { LOG ((LOG_ERROR, (PCSTR) MSG_UNSUPPORTED_DATA, value)); SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND); } if (result) { result = FALSE;
if (valueInFile) { if ((ContentType == CONTENTTYPE_ANY) || (ContentType == CONTENTTYPE_FILE) || (ContentType == CONTENTTYPE_DETAILS_ONLY) ) { // this is stored as a file and it's wanted as a file
ObjectContent->ObjectTypeId = ObjectTypeId; ObjectContent->ContentInFile = TRUE; if (fileValue) { ObjectContent->FileContent.ContentPath = DuplicatePathString (fileValue, 0); ObjectContent->FileContent.ContentSize = BfGetFileSize (ObjectContent->FileContent.ContentPath); } else { ObjectContent->FileContent.ContentSize = 0; ObjectContent->FileContent.ContentPath = NULL; } result = TRUE; } else { // this is stored as a file and it's wanted as memory
ObjectContent->ObjectTypeId = ObjectTypeId; ObjectContent->ContentInFile = FALSE; if (fileValue) { ObjectContent->MemoryContent.ContentSize = (UINT) BfGetFileSize (fileValue); ObjectContent->MemoryContent.ContentBytes = MapFileIntoMemory ( fileValue, &allocState->FileHandle, &allocState->MapHandle ); result = (ObjectContent->MemoryContent.ContentBytes != NULL); } else { ObjectContent->MemoryContent.ContentSize = 0; ObjectContent->MemoryContent.ContentBytes = NULL; result = TRUE; } } MemDbReleaseMemory (fileValue); } else { if ((ContentType == CONTENTTYPE_ANY) || (ContentType == CONTENTTYPE_MEMORY) || (ContentType == CONTENTTYPE_DETAILS_ONLY) ) { // this is stored as memory and it's wanted as memory
ObjectContent->ObjectTypeId = ObjectTypeId; ObjectContent->ContentInFile = FALSE; ObjectContent->MemoryContent.ContentSize = memValueSize; ObjectContent->MemoryContent.ContentBytes = memValue; result = TRUE; } else { // this is stored as memory and it's wanted as a file
if (memValue) { if (IsmGetTempFile (allocState->TempFile, ARRAYSIZE(allocState->TempFile))) { fileHandle = BfCreateFile (allocState->TempFile); if (fileHandle) { if (BfWriteFile (fileHandle, memValue, memValueSize)) { ObjectContent->ObjectTypeId = ObjectTypeId; ObjectContent->ContentInFile = TRUE; ObjectContent->FileContent.ContentSize = memValueSize; ObjectContent->FileContent.ContentPath = DuplicatePathString (allocState->TempFile, 0); result = TRUE; } CloseHandle (fileHandle); } } MemDbReleaseMemory (memValue); } else { ObjectContent->ObjectTypeId = ObjectTypeId; ObjectContent->ContentInFile = TRUE; ObjectContent->FileContent.ContentSize = 0; ObjectContent->FileContent.ContentPath = NULL; } } } } } else { SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND); }
if (result) { //
// Fill the details
//
detailsKey = JoinText (S_DETAILS_PREFIX, decoratedObject);
details = MemDbGetUnorderedBlob (detailsKey, 0, &detailsSize);
if (!details) { detailsSize = 0; }
allocState->DetailsPtr = details;
ObjectContent->Details.DetailsSize = detailsSize; ObjectContent->Details.DetailsData = details;
FreeText (detailsKey);
ObjectContent->TransHandle = allocState; }
if (!result) { FreeAlloc (allocState); }
FreePathString (decoratedObject);
return result; }
BOOL WINAPI InfTransTransportReleaseObject ( IN OUT PMIG_CONTENT ObjectContent ) { PALLOCSTATE allocState;
MYASSERT (g_Platform == PLATFORM_DESTINATION);
allocState = (PALLOCSTATE) ObjectContent->TransHandle;
if (ObjectContent->ContentInFile) { FreePathString (ObjectContent->FileContent.ContentPath); if (allocState && allocState->TempFile[0]) { DeleteFile (allocState->TempFile); } } else { if (allocState && allocState->FileHandle && allocState->MapHandle) { UnmapFile ( ObjectContent->MemoryContent.ContentBytes, allocState->MapHandle, allocState->FileHandle ); } else { MemDbReleaseMemory (ObjectContent->MemoryContent.ContentBytes); } }
if (allocState && allocState->DetailsPtr) { MemDbReleaseMemory (allocState->DetailsPtr); }
FreeAlloc (allocState);
return TRUE; }
|