You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1688 lines
58 KiB
1688 lines
58 KiB
/*++
|
|
|
|
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;
|
|
}
|
|
|