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

1698 lines
54 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
opaque.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 <compress.h>
#define DBG_OPAQUE "OpaqueUnc"
//
// Strings
//
#define S_TRANSPORT_DIR TEXT("USMT2.UNC")
#define S_TRANSPORT_DAT_FILE TEXT("TRANSDB.DAT")
#define S_TRANSPORT_IMG_FILE TEXT("IMG%05X.DAT")
#define S_TRANSPORT_STATUS_FILE TEXT("status")
#define S_FILEOBJECT_NAME TEXT("File")
#define S_REGOBJECT_NAME TEXT("Registry")
#define S_DATABASEOBJECT_NAME TEXT("Database")
#define S_DETAILS_PREFIX TEXT("details-")
//
// Constants
//
#define TRFLAG_FILE 0x01
#define TRFLAG_MEMORY 0x02
#define COPY_BUFFER_SIZE 32768
#define OPAQUETR_OLDSIG1 0x55534D31 //USM1
#define OPAQUETR_OLDSIG2 0x55534D32 //USM1
#define OPAQUETR_SIG 0x55534D33 //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;
//
// Globals
//
MIG_TRANSPORTSTORAGEID g_ReliableStorageId;
PCTSTR g_TransportPath = NULL;
PCTSTR g_TransportTempPath = NULL;
PCTSTR g_TransportStatus = NULL;
HANDLE g_TransportStatusHandle = NULL;
BOOL g_OtCompressData = FALSE;
BOOL g_OtOldFormat = FALSE;
UINT g_Platform;
MIG_PROGRESSSLICEID g_PersistentSlice;
MIG_PROGRESSSLICEID g_DatabaseSlice;
UINT g_CompressedTicks;
UINT g_CompressedTicked;
MIG_PROGRESSSLICEID g_CompressedSlice;
UINT g_UncompressTicks;
UINT g_UncompressTicked;
MIG_PROGRESSSLICEID g_UncompressSlice;
LONGLONG g_TotalFiles;
LONGLONG g_FilesRead;
//
// Macro expansion list
//
// None
//
// Private function prototypes
//
BOOL
pOtSaveAllState (
IN BOOL Compressed
);
//
// Macro expansion definition
//
// None
//
// Code
//
BOOL
pSetOpaqueTransportStatus (
IN HANDLE TrJournalHandle,
IN BOOL Compressed,
IN DWORD Status
)
{
DWORD signature = OPAQUETR_SIG;
BOOL result = FALSE;
if (BfSetFilePointer (TrJournalHandle, 0)) {
result = TRUE;
result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&signature), sizeof (DWORD));
result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&Compressed), sizeof (BOOL));
result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&Status), sizeof (DWORD));
result = result && FlushFileBuffers (TrJournalHandle);
}
return result;
}
DWORD
pGetOpaqueTransportStatus (
IN PCTSTR TrJournal,
OUT PBOOL Compressed, OPTIONAL
OUT PBOOL OldStorage, OPTIONAL
IN BOOL OpenReadOnly
)
{
HANDLE trJrnHandle;
BOOL compressed = FALSE;
DWORD signature = 0;
DWORD fileSize = 0;
DWORD result = 0;
if (OldStorage) {
*OldStorage = FALSE;
}
if (TrJournal && TrJournal [0]) {
if (OpenReadOnly) {
trJrnHandle = BfOpenReadFile (TrJournal);
} else {
trJrnHandle = BfOpenFile (TrJournal);
}
if (trJrnHandle) {
if (BfSetFilePointer (trJrnHandle, 0)) {
fileSize = GetFileSize (trJrnHandle, NULL);
if (fileSize == (sizeof (BOOL) + sizeof (DWORD))) {
if (OldStorage) {
*OldStorage = TRUE;
}
if (BfReadFile (trJrnHandle, (PBYTE)(&compressed), sizeof (BOOL))) {
BfReadFile (trJrnHandle, (PBYTE)(&result), sizeof (DWORD));
}
}
if (fileSize == (sizeof (BOOL) + sizeof (DWORD) + sizeof (DWORD))) {
if (BfReadFile (trJrnHandle, (PBYTE)(&signature), sizeof (DWORD))) {
if (signature == OPAQUETR_SIG) {
if (BfReadFile (trJrnHandle, (PBYTE)(&compressed), sizeof (BOOL))) {
BfReadFile (trJrnHandle, (PBYTE)(&result), sizeof (DWORD));
}
}
if ((signature == OPAQUETR_OLDSIG1) ||
(signature == OPAQUETR_OLDSIG2)
) {
if (OldStorage) {
*OldStorage = TRUE;
}
if (BfReadFile (trJrnHandle, (PBYTE)(&compressed), sizeof (BOOL))) {
BfReadFile (trJrnHandle, (PBYTE)(&result), sizeof (DWORD));
}
}
}
}
}
CloseHandle (trJrnHandle);
} else {
if (GetLastError () == ERROR_ACCESS_DENIED) {
result = TRSTATUS_LOCKED;
}
}
}
if (Compressed) {
*Compressed = compressed;
}
return result;
}
PCTSTR
pGetOpaqueImageFile (
IN PCTSTR BasePath,
IN UINT ImageIdx
)
{
TCHAR imageFileName [13];
PCTSTR imageFile = NULL;
HANDLE imageFileHandle = NULL;
wsprintf (imageFileName, S_TRANSPORT_IMG_FILE, ImageIdx);
return JoinPaths (BasePath, imageFileName);
}
PCTSTR
pGetRealTransportPath (
VOID
)
{
return g_OtCompressData?g_TransportTempPath:g_TransportPath;
}
BOOL
WINAPI
OpaqueTransportInitialize (
IN PMIG_LOGCALLBACK LogCallback
)
{
//
// Initialize globals
//
LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
g_ReliableStorageId = IsmRegisterTransport (S_RELIABLE_STORAGE_TRANSPORT);
return TRUE;
}
VOID
WINAPI
OpaqueTransportEstimateProgressBar (
MIG_PLATFORMTYPEID PlatformTypeId
)
{
UINT ticks;
PMIG_OBJECTCOUNT objectCount;
if (PlatformTypeId == PLATFORM_SOURCE) {
//
// If saving, we know the number of ticks based on the count of the
// persistent attribute.
//
objectCount = IsmGetObjectsStatistics (PLATFORM_SOURCE);
if (objectCount) {
ticks = objectCount->PersistentObjects;
} else {
ticks = 0;
}
g_PersistentSlice = IsmRegisterProgressSlice (ticks, max (1, ticks / 5));
if (g_OtCompressData) {
g_DatabaseSlice = IsmRegisterProgressSlice (3, 1);
} else {
g_DatabaseSlice = IsmRegisterProgressSlice (1, 1);
}
} else {
if (g_OtCompressData) {
g_UncompressTicked = 0;
g_UncompressTicks = 1000;
g_UncompressSlice = IsmRegisterProgressSlice (g_UncompressTicks, 180);
} else {
//
// If restoring, we have almost no work to account for, since
// we download from the secure server file-by-file.
//
DEBUGMSG ((DBG_VERBOSE, "Assuming transport download has no progress impact"));
}
}
}
BOOL
WINAPI
OpaqueTransportQueryCapabilities (
IN MIG_TRANSPORTSTORAGEID TransportStorageId,
OUT PMIG_TRANSPORTTYPE TransportType,
OUT PMIG_TRANSPORTCAPABILITIES Capabilities,
OUT PCTSTR *FriendlyDescription
)
{
if (TransportStorageId != g_ReliableStorageId) {
return FALSE;
}
*TransportType = TRANSPORTTYPE_FULL;
*Capabilities = CAPABILITY_COMPRESSED;
*FriendlyDescription = TEXT("Local computer or another computer on the Network");
return TRUE;
}
VOID
pOtCleanUpTempDir (
VOID
)
{
if (g_TransportTempPath) {
FiRemoveAllFilesInTree (g_TransportTempPath);
}
}
PCTSTR
pOtCreateTemporaryDir (
VOID
)
{
TCHAR tempFile[MAX_PATH];
if (!IsmGetTempDirectory (tempFile, ARRAYSIZE(tempFile))) {
return NULL;
}
return DuplicatePathString (tempFile, 0);
}
BOOL
WINAPI
OpaqueTransportSetStorage (
IN MIG_PLATFORMTYPEID Platform,
IN MIG_TRANSPORTSTORAGEID TransportStorageId,
IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities,
IN PCTSTR StoragePath,
OUT PBOOL Valid,
OUT PBOOL ImageExists
)
{
PCTSTR lastDirPtr = NULL;
PCTSTR transportPath = NULL;
PCTSTR transportStatus = NULL;
HANDLE transportStatusHandle = INVALID_HANDLE_VALUE;
MIG_OBJECTSTRINGHANDLE encodedPath;
DWORD status;
BOOL result = FALSE;
if (Valid) {
*Valid = FALSE;
}
if (ImageExists) {
*ImageExists = FALSE;
}
if (TransportStorageId == g_ReliableStorageId) {
if ((!RequiredCapabilities) || (RequiredCapabilities == CAPABILITY_COMPRESSED)) {
if (RequiredCapabilities == CAPABILITY_COMPRESSED) {
g_OtCompressData = TRUE;
} else {
g_OtCompressData = FALSE;
}
// If this is the destination, let's check if the user included USMT2.UNC in
// the path by mistake. If he did (the StoragePath ends in USMT2.UNC and
// StoragePath has our transport status) we will accept it.
if (Platform == PLATFORM_DESTINATION) {
lastDirPtr = _tcsrchr (StoragePath, TEXT('\\'));
if (lastDirPtr) {
lastDirPtr = _tcsinc (lastDirPtr);
if (lastDirPtr) {
if (StringIMatch (lastDirPtr, S_TRANSPORT_DIR)) {
transportPath = DuplicatePathString (StoragePath, 0);
transportStatus = JoinPaths (transportPath, S_TRANSPORT_STATUS_FILE);
if ((!DoesFileExist (transportPath)) ||
(pGetOpaqueTransportStatus (transportStatus, NULL, NULL, TRUE) != TRSTATUS_READY)
) {
FreePathString (transportPath);
transportPath = NULL;
FreePathString (transportStatus);
transportStatus = NULL;
}
}
}
}
}
if (!transportPath) {
transportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR);
}
if (!transportStatus) {
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;
}
if ((*Valid) && (Platform == PLATFORM_SOURCE)) {
// we need to actually try to create our transport directory and the status file
// After that we will remove them but this is just the way for us to validate the
// store
*Valid = FALSE;
if (BfCreateDirectory (transportPath)) {
transportStatusHandle = BfCreateFile (transportStatus);
if (transportStatusHandle) {
*Valid = TRUE;
CloseHandle (transportStatusHandle);
}
PushError ();
FiRemoveAllFilesInTree (transportPath);
PopError ();
}
}
*ImageExists = FALSE;
} else {
// we try to open this transport status file with Read/Write. If we
// fail this is either because somebody has it opened or we don't
// have access rights. In both cases we should get back TRSTATUS_LOCKED
status = pGetOpaqueTransportStatus (transportStatus, NULL, NULL, TRUE);
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;
}
}
result = TRUE;
}
}
if (result && *Valid) {
if (g_TransportPath) {
FreePathString (g_TransportPath);
g_TransportPath = NULL;
}
if (g_TransportStatus) {
FreePathString (g_TransportStatus);
g_TransportStatus = NULL;
}
if (transportPath) {
g_TransportPath = transportPath;
} else {
g_TransportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR);
}
if (transportStatus) {
g_TransportStatus = transportStatus;
} else {
g_TransportStatus = JoinPaths (g_TransportPath, S_TRANSPORT_STATUS_FILE);
}
encodedPath = IsmCreateSimpleObjectPattern (g_TransportPath, FALSE, NULL, FALSE);
if (encodedPath) {
IsmRegisterStaticExclusion (MIG_FILE_TYPE, encodedPath);
IsmDestroyObjectHandle (encodedPath);
}
}
return result;
}
BOOL
WINAPI
OpaqueTransportSaveState (
VOID
)
{
MIG_APPINFO appInfo;
ERRUSER_EXTRADATA extraData;
DWORD status;
BOOL result = FALSE;
BOOL allowDelete = FALSE;
ZeroMemory (&extraData, sizeof (ERRUSER_EXTRADATA));
extraData.Error = ERRUSER_ERROR_UNKNOWN;
__try {
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
appInfo.Phase = MIG_TRANSPORT_PHASE;
appInfo.SubPhase = SUBPHASE_PREPARING;
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
if (!g_TransportPath) {
DEBUGMSG ((DBG_ERROR, "Transport Path is not selected"));
extraData.Error = ERRUSER_ERROR_NOTRANSPORTPATH;
__leave;
}
if (DoesFileExist (g_TransportPath)) {
status = pGetOpaqueTransportStatus (g_TransportStatus, NULL, NULL, FALSE);
switch (status) {
case TRSTATUS_LOCKED:
SetLastError (ERROR_ACCESS_DENIED);
LOG ((LOG_ERROR, (PCSTR) MSG_TRANSPORT_DIR_BUSY, g_TransportPath));
extraData.Error = ERRUSER_ERROR_TRANSPORTPATHBUSY;
__leave;
case TRSTATUS_DIRTY:
result = FiRemoveAllFilesInTree (g_TransportPath);
if (!result) {
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_EMPTY_DIR, g_TransportPath));
extraData.Error = ERRUSER_ERROR_CANTEMPTYDIR;
__leave;
}
break;
case TRSTATUS_READY:
default:
if (IsmSendMessageToApp (TRANSPORTMESSAGE_IMAGE_EXISTS, 0)) {
if (!FiRemoveAllFilesInTree (g_TransportPath)) {
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_EMPTY_DIR, g_TransportPath));
extraData.Error = ERRUSER_ERROR_CANTEMPTYDIR;
__leave;
}
} else {
LOG ((LOG_ERROR, (PCSTR) MSG_NOT_EMPTY, g_TransportPath));
SetLastError (ERROR_ALREADY_EXISTS);
extraData.Error = ERRUSER_ERROR_ALREADYEXISTS;
__leave;
}
break;
}
}
allowDelete = TRUE;
if (!BfCreateDirectory (g_TransportPath)) {
PushError ();
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_DIR, g_TransportPath));
PopError ();
extraData.Error = ERRUSER_ERROR_CANTCREATEDIR;
__leave;
}
g_TransportStatusHandle = BfCreateFile (g_TransportStatus);
if (!g_TransportStatusHandle) {
PushError ();
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_STATUS_FILE, g_TransportStatus));
PopError ();
extraData.Error = ERRUSER_ERROR_CANTCREATESTATUS;
__leave;
}
result = pSetOpaqueTransportStatus (g_TransportStatusHandle, g_OtCompressData, TRSTATUS_DIRTY);
if (!result) {
PushError ();
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_STATUS_FILE, g_TransportStatus));
PopError ();
extraData.Error = ERRUSER_ERROR_CANTCREATESTATUS;
__leave;
}
g_Platform = PLATFORM_SOURCE;
result = pOtSaveAllState (g_OtCompressData);
if (result) {
result = result && pSetOpaqueTransportStatus (g_TransportStatusHandle, g_OtCompressData, TRSTATUS_READY);
}
result = result && FlushFileBuffers (g_TransportStatusHandle);
result = result && CloseHandle (g_TransportStatusHandle);
if (result) {
g_TransportStatusHandle = NULL;
}
}
__finally {
PushError ();
if (g_TransportStatusHandle) {
// if we got here there was some error. Let's just close the handle
CloseHandle (g_TransportStatusHandle);
}
if (allowDelete && (!result)) {
FiRemoveAllFilesInTree (g_TransportPath);
}
PopError ();
}
PushError ();
if (!result) {
extraData.ErrorArea = ERRUSER_AREA_SAVE;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
}
PopError ();
return result;
}
PCTSTR
pOpaqueGetNewFileName (
IN PCTSTR FileName
)
{
PCTSTR newFileName = NULL;
PTSTR tempPtr1 = NULL;
PCTSTR endStr1 = NULL;
PCTSTR tempPtr2 = NULL;
PCTSTR endStr2 = NULL;
INT i;
// let's modify the file to extract. The file name will
// be split in 2 after the first 5 characters
newFileName = DuplicatePathString (FileName, 1);
if (!newFileName) {
return NULL;
}
tempPtr1 = (PTSTR) GetFileNameFromPath (newFileName);
if (!tempPtr1) {
FreePathString (newFileName);
return NULL;
}
endStr1 = GetEndOfString (newFileName);
if (!endStr1) {
FreePathString (newFileName);
return NULL;
}
tempPtr2 = GetFileNameFromPath (FileName);
if (!tempPtr2) {
FreePathString (newFileName);
return NULL;
}
endStr2 = GetEndOfString (FileName);
if (!endStr2) {
FreePathString (newFileName);
return NULL;
}
for (i = 0; i < 5; i ++) {
tempPtr1 = _tcsinc (tempPtr1);
tempPtr2 = _tcsinc (tempPtr2);
}
if ((tempPtr1 < endStr1) &&
(tempPtr2 < endStr2)
) {
StringCopy (tempPtr1, TEXT("\\"));
tempPtr1 = _tcsinc (tempPtr1);
StringCopy (tempPtr1, tempPtr2);
} else {
FreePathString (newFileName);
newFileName = NULL;
}
return newFileName;
}
BOOL
pOpaqueCallback (
IN PCTSTR FileToExtract,
IN LONGLONG FileSize,
OUT PBOOL ExtractFile,
IN OUT PCTSTR *NewFileName
)
{
LONGLONG numerator;
LONGLONG divisor;
LONGLONG tick;
UINT delta;
if (NewFileName) {
*NewFileName = pOpaqueGetNewFileName (FileToExtract);
}
g_FilesRead ++;
// now update the progress bar
numerator = (LONGLONG) g_FilesRead * (LONGLONG) g_UncompressTicks;
divisor = (LONGLONG) g_TotalFiles;
if (divisor) {
tick = numerator / divisor;
} else {
tick = 0;
}
delta = (UINT) tick - g_UncompressTicked;
if (delta) {
IsmTickProgressBar (g_UncompressSlice, delta);
g_UncompressTicked += delta;
}
if (ExtractFile) {
*ExtractFile = TRUE;
}
return (!IsmCheckCancel());
}
BOOL
pOtReadAllImages (
VOID
)
{
COMPRESS_HANDLE compressedHandle;
BOOL result = FALSE;
if (CompressOpenHandle (g_TransportPath, S_TRANSPORT_IMG_FILE, 1, &compressedHandle)) {
g_TotalFiles = compressedHandle.FilesStored;
if (CompressExtractAllFiles (g_TransportTempPath, &compressedHandle, pOpaqueCallback)) {
result = TRUE;
}
CompressCleanupHandle (&compressedHandle);
}
return result;
}
BOOL
WINAPI
OpaqueTransportBeginApply (
VOID
)
{
ERRUSER_EXTRADATA extraData;
DWORD status = 0;
PCTSTR memDbFile;
INT_PTR appReply;
PCTSTR newTransDbFile = NULL;
BOOL result = FALSE;
g_Platform = PLATFORM_DESTINATION;
ZeroMemory (&extraData, sizeof (ERRUSER_EXTRADATA));
extraData.Error = ERRUSER_ERROR_UNKNOWN;
__try {
if (!g_TransportPath) {
DEBUGMSG ((DBG_ERROR, "Transport Path is not selected"));
extraData.Error = ERRUSER_ERROR_NOTRANSPORTPATH;
__leave;
}
while (status != TRSTATUS_READY) {
status = pGetOpaqueTransportStatus (g_TransportStatus, &g_OtCompressData, &g_OtOldFormat, TRUE);
switch (status) {
case TRSTATUS_LOCKED:
if (!IsmSendMessageToApp (TRANSPORTMESSAGE_IMAGE_LOCKED, 0)) {
SetLastError (ERROR_ACCESS_DENIED);
LOG ((LOG_ERROR, (PCSTR) MSG_TRANSPORT_DIR_BUSY, g_TransportPath));
extraData.Error = ERRUSER_ERROR_TRANSPORTPATHBUSY;
__leave;
}
break;
case TRSTATUS_DIRTY:
SetLastError (ERROR_INVALID_DATA);
LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_IMAGE, g_TransportPath));
extraData.Error = ERRUSER_ERROR_TRANSPORTINVALIDIMAGE;
__leave;
case TRSTATUS_READY:
break;
default:
SetLastError (ERROR_INVALID_DATA);
LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_IMAGE, g_TransportPath));
extraData.Error = ERRUSER_ERROR_TRANSPORTINVALIDIMAGE;
__leave;
}
}
if (g_OtOldFormat) {
IsmSendMessageToApp (TRANSPORTMESSAGE_OLD_STORAGE, 0);
SetLastError (ERROR_INVALID_DATA);
LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_IMAGE, g_TransportPath));
extraData.Error = ERRUSER_ERROR_TRANSPORTINVALIDIMAGE;
__leave;
}
g_TransportStatusHandle = BfOpenReadFile (g_TransportStatus);
if (!g_TransportStatusHandle) {
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_STATUS_FILE, g_TransportStatus));
extraData.Error = ERRUSER_ERROR_CANTOPENSTATUS;
__leave;
}
if (g_OtCompressData) {
g_TransportTempPath = pOtCreateTemporaryDir ();
if (!g_TransportTempPath) {
CloseHandle (g_TransportStatusHandle);
g_TransportStatusHandle = NULL;
extraData.Error = ERRUSER_ERROR_CANTCREATETEMPDIR;
__leave;
}
if (!pOtReadAllImages ()) {
CloseHandle (g_TransportStatusHandle);
g_TransportStatusHandle = NULL;
extraData.Error = ERRUSER_ERROR_CANTUNPACKIMAGE;
__leave;
}
CloseHandle (g_TransportStatusHandle);
g_TransportStatusHandle = NULL;
}
newTransDbFile = pOpaqueGetNewFileName (S_TRANSPORT_DAT_FILE);
memDbFile = JoinPaths (pGetRealTransportPath (), newTransDbFile?newTransDbFile:S_TRANSPORT_DAT_FILE);
if (newTransDbFile) {
FreePathString (newTransDbFile);
newTransDbFile = NULL;
}
result = MemDbLoad (memDbFile);
if (!result) {
extraData.Error = ERRUSER_ERROR_CANTREADIMAGE;
}
FreePathString (memDbFile);
}
__finally {
}
if (!result) {
extraData.ErrorArea = ERRUSER_AREA_LOAD;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
}
return result;
}
VOID
WINAPI
OpaqueTransportEndApply (
VOID
)
{
MYASSERT (g_Platform == PLATFORM_DESTINATION);
if (g_OtCompressData) {
pOtCleanUpTempDir ();
} else {
CloseHandle (g_TransportStatusHandle);
g_TransportStatusHandle = NULL;
}
}
VOID
WINAPI
OpaqueTransportTerminate (
VOID
)
{
pOtCleanUpTempDir();
if (g_TransportTempPath) {
FreePathString (g_TransportTempPath);
g_TransportTempPath = NULL;
}
if (g_TransportStatus) {
FreePathString (g_TransportStatus);
g_TransportStatus = NULL;
}
if (g_TransportPath) {
FreePathString (g_TransportPath);
g_TransportPath = NULL;
}
}
static
VOID
pGetTempFileName (
OUT PTSTR Buffer
)
{
static fileIndex = 0;
fileIndex ++;
wsprintf (Buffer, TEXT("%08X.DAT"), fileIndex);
}
PCTSTR
pOpaqueAllocStorageFileName (
IN PCTSTR FileName OPTIONAL
)
{
TCHAR buffer[32];
if (FileName) {
StringCopy (buffer, FileName);
} else {
pGetTempFileName (buffer);
}
return JoinPaths (g_TransportPath, buffer);
}
VOID
pFreeStorageFileName (
IN PCTSTR FileName
)
{
FreePathString (FileName);
}
BOOL
pOpaqueSaveDetails (
IN PCTSTR DecoratedObject,
IN PMIG_DETAILS Details
)
{
PCTSTR key;
BOOL b = FALSE;
if ((!Details) || (!Details->DetailsSize)) {
return TRUE;
}
key = JoinText (S_DETAILS_PREFIX, DecoratedObject);
if (key) {
b = (MemDbSetUnorderedBlob (key, 0, Details->DetailsData, Details->DetailsSize) != 0);
FreeText (key);
}
return b;
}
BOOL
pOtAddFileToImage (
IN PCTSTR FileName,
IN PCTSTR StoredName,
IN OUT PCOMPRESS_HANDLE CompressedHandle
)
{
return CompressAddFileToHandle (FileName, StoredName, CompressedHandle);
}
BOOL
pOtSaveContentInFile (
IN MIG_OBJECTTYPEID ObjectTypeId,
IN PCTSTR EncodedFileName,
IN PCTSTR DecoratedObject,
IN PMIG_CONTENT Content,
IN OUT PCOMPRESS_HANDLE CompressedHandle OPTIONAL
)
{
BOOL result = FALSE;
PCTSTR destPath = NULL;
DWORD attributes = INVALID_ATTRIBUTES;
MYASSERT (Content->ContentInFile);
if (!Content->ContentInFile) {
return FALSE;
}
//
// Use the CopyFile API to move the file from local to storage.
//
__try {
if (Content && (Content->Details.DetailsSize == sizeof (WIN32_FIND_DATAW)) && Content->Details.DetailsData) {
attributes = ((PWIN32_FIND_DATAW)Content->Details.DetailsData)->dwFileAttributes;
}
if ((attributes != INVALID_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
// this must be a directory, let's just write the key
if (!MemDbSetValue (DecoratedObject, TRFLAG_FILE)) {
__leave;
}
} else {
//
// Get a temp file, assemble the src path, copy the file
//
destPath = pOpaqueAllocStorageFileName (NULL);
if (!destPath) {
__leave;
}
if (CompressedHandle) {
if (!pOtAddFileToImage (Content->FileContent.ContentPath, GetFileNameFromPath (destPath), CompressedHandle)) {
__leave;
}
} else {
if (!CopyFile (Content->FileContent.ContentPath, destPath, FALSE)) {
__leave;
}
}
//
// Keep track of where the file went
//
if (!MemDbSetValue (DecoratedObject, TRFLAG_FILE)) {
__leave;
}
if (!MemDbAddSingleLinkage (DecoratedObject, GetFileNameFromPath (destPath), 0)) {
__leave;
}
}
//
// Save details
//
result = pOpaqueSaveDetails (DecoratedObject, &(Content->Details));
}
__finally {
pFreeStorageFileName (destPath);
INVALID_POINTER (destPath);
}
return result;
}
BOOL
pOtSaveContentInMemory (
IN MIG_OBJECTTYPEID ObjectTypeId,
IN PCTSTR EncodedObjectName,
IN PCTSTR DecoratedObject,
IN PMIG_CONTENT Content
)
{
BOOL result = FALSE;
MYASSERT (!Content->ContentInFile);
if (Content->ContentInFile) {
return FALSE;
}
MemDbSetValue (DecoratedObject, TRFLAG_MEMORY);
if (Content->MemoryContent.ContentBytes && Content->MemoryContent.ContentSize) {
MemDbSetUnorderedBlob (
DecoratedObject,
0,
Content->MemoryContent.ContentBytes,
Content->MemoryContent.ContentSize
);
}
result = pOpaqueSaveDetails (DecoratedObject, &(Content->Details));
return result;
}
PCTSTR
pOpaqueBuildDecoratedObject (
IN MIG_OBJECTTYPEID ObjectTypeId,
IN ENCODEDSTRHANDLE ObjectName
)
{
TCHAR prefix[32];
wsprintf (prefix, TEXT("%u"), ObjectTypeId);
return JoinPaths (prefix, ObjectName);
}
VOID
pOtDestroyDecoratedObject (
IN PCTSTR String
)
{
FreePathString (String);
}
BOOL
pOtSaveAllState (
IN BOOL Compressed
)
{
MIG_APPINFO appInfo;
MIG_CONTENT value;
PMIG_CONTENT convValue;
ULONGLONG size;
MIG_OBJECTWITHATTRIBUTE_ENUM objEnum;
PCTSTR ourDbFile = NULL;
PCTSTR decoratedObject = NULL;
ULONGLONG bytesSaved = 0;
UINT lastTick = GetTickCount();
TCHAR text[64];
UINT fraction;
COMPRESS_HANDLE compressedHandle;
INT_PTR appReply;
BOOL okSave = FALSE;
TRANSCOPY_ERROR transCopyError;
ERRUSER_EXTRADATA extraData;
BOOL result = FALSE;
__try {
ZeroMemory (&compressedHandle, sizeof (COMPRESS_HANDLE));
if (Compressed) {
g_TransportTempPath = pOtCreateTemporaryDir ();
if (!g_TransportTempPath) {
extraData.Error = ERRUSER_ERROR_CANTCREATETEMPDIR;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = 0;
extraData.ObjectName = NULL;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
__leave;
}
if (!CompressCreateHandle (g_TransportPath, S_TRANSPORT_IMG_FILE, 1, 0, &compressedHandle)) {
extraData.Error = ERRUSER_ERROR_CANTCREATECABFILE;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = 0;
extraData.ObjectName = NULL;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
__leave;
}
}
//
// Enumerate all objects with "save" attribute
//
if (IsmEnumFirstPersistentObject (&objEnum)) {
do {
//
// For each object to be saved, do the appropriate
// data copy action
//
okSave = FALSE;
while (!okSave) {
if (!IsmAcquireObjectEx (
objEnum.ObjectTypeId,
objEnum.ObjectName,
&value,
CONTENTTYPE_ANY,
0
)) {
transCopyError.ObjectType = IsmGetObjectTypeName (objEnum.ObjectTypeId);
transCopyError.ObjectName = IsmGetNativeObjectName (objEnum.ObjectTypeId, objEnum.ObjectName);
transCopyError.Error = GetLastError ();
if (IsmIsNonCriticalObject (objEnum.ObjectTypeId, objEnum.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);
extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = objEnum.ObjectTypeId;
extraData.ObjectName = objEnum.ObjectName;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
IsmAbortPersistentObjectEnum (&objEnum);
__leave;
}
}
if (appReply == APPRESPONSE_IGNORE) {
LOG ((LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName));
IsmReleaseMemory (transCopyError.ObjectName);
extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = objEnum.ObjectTypeId;
extraData.ObjectName = objEnum.ObjectName;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYWARNING, (ULONG_PTR)(&extraData));
break;
}
IsmReleaseMemory (transCopyError.ObjectName);
continue;
}
okSave = TRUE;
}
if (okSave) {
#ifdef UNICODE
convValue = &value;
#else
// now let's convert this object content to UNICODE
convValue = IsmConvertObjectContentToUnicode (objEnum.ObjectTypeId, objEnum.ObjectName, &value);
if (!convValue) {
convValue = &value;
}
#endif
decoratedObject = pOpaqueBuildDecoratedObject (objEnum.ObjectTypeId, objEnum.ObjectName);
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
appInfo.Phase = MIG_TRANSPORT_PHASE;
appInfo.SubPhase = SUBPHASE_COMPRESSING;
appInfo.ObjectTypeId = (objEnum.ObjectTypeId & (~PLATFORM_MASK));
appInfo.ObjectName = objEnum.ObjectName;
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
if (convValue->ContentInFile) {
okSave = FALSE;
while (!okSave) {
if (!pOtSaveContentInFile (objEnum.ObjectTypeId, objEnum.ObjectName, decoratedObject, convValue, &compressedHandle)) {
if (GetLastError () == ERROR_DISK_FULL) {
// we just failed because we don't have enough space on the destination
// path. Let's tell that to the user
extraData.Error = ERRUSER_ERROR_CANTCREATECABFILE;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = 0;
extraData.ObjectName = NULL;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
__leave;
}
transCopyError.ObjectType = IsmGetObjectTypeName (objEnum.ObjectTypeId);
transCopyError.ObjectName = IsmGetNativeObjectName (objEnum.ObjectTypeId, objEnum.ObjectName);
transCopyError.Error = GetLastError ();
if (IsmIsNonCriticalObject (objEnum.ObjectTypeId, objEnum.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);
extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = objEnum.ObjectTypeId;
extraData.ObjectName = objEnum.ObjectName;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
IsmAbortPersistentObjectEnum (&objEnum);
__leave;
}
}
if (appReply == APPRESPONSE_IGNORE) {
LOG ((LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName));
IsmReleaseMemory (transCopyError.ObjectName);
extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = objEnum.ObjectTypeId;
extraData.ObjectName = objEnum.ObjectName;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYWARNING, (ULONG_PTR)(&extraData));
break;
}
IsmReleaseMemory (transCopyError.ObjectName);
continue;
}
okSave = TRUE;
}
size = convValue->FileContent.ContentSize;
} else {
okSave = FALSE;
while (!okSave) {
if (!pOtSaveContentInMemory (objEnum.ObjectTypeId, objEnum.ObjectName, decoratedObject, convValue)) {
if (GetLastError () == ERROR_DISK_FULL) {
// we just failed because we don't have enough space on the destination
// path. Let's tell that to the user
extraData.Error = ERRUSER_ERROR_CANTCREATECABFILE;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = 0;
extraData.ObjectName = NULL;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
__leave;
}
transCopyError.ObjectType = IsmGetObjectTypeName (objEnum.ObjectTypeId);
transCopyError.ObjectName = IsmGetNativeObjectName (objEnum.ObjectTypeId, objEnum.ObjectName);
transCopyError.Error = GetLastError ();
if (IsmIsNonCriticalObject (objEnum.ObjectTypeId, objEnum.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);
extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = objEnum.ObjectTypeId;
extraData.ObjectName = objEnum.ObjectName;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
IsmAbortPersistentObjectEnum (&objEnum);
__leave;
}
}
if (appReply == APPRESPONSE_IGNORE) {
LOG ((LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName));
IsmReleaseMemory (transCopyError.ObjectName);
extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = objEnum.ObjectTypeId;
extraData.ObjectName = objEnum.ObjectName;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYWARNING, (ULONG_PTR)(&extraData));
break;
}
IsmReleaseMemory (transCopyError.ObjectName);
continue;
}
okSave = TRUE;
}
size = convValue->MemoryContent.ContentSize;
}
#ifndef UNICODE
if (convValue != (&value)) {
IsmFreeConvertedObjectContent (objEnum.ObjectTypeId, convValue);
}
#endif
IsmReleaseObject (&value);
pOtDestroyDecoratedObject (decoratedObject);
decoratedObject = NULL;
}
IsmTickProgressBar (g_PersistentSlice, 1);
if (IsmCheckCancel()) {
__leave;
}
//
// Send bytes saved to app every 3 seconds
//
bytesSaved += size;
if (GetTickCount() - lastTick > 3000) {
if (bytesSaved < 1048576) {
wsprintf (text, TEXT("Saved: %u K"), (UINT) (bytesSaved / 1024));
} else if (bytesSaved < 8388608) {
fraction = (UINT) (bytesSaved / 10485);
wsprintf (text, TEXT("Saved: %u.%02u M"), fraction / 100, fraction % 100);
} else if (bytesSaved < 1073741824) {
wsprintf (text, TEXT("Saved: %u M"), (UINT) (bytesSaved / 1048576));
} else {
fraction = (UINT) (bytesSaved / 10737418);
wsprintf (text, TEXT("Saved: %u.%02u G"), fraction / 100, fraction % 100);
}
IsmSendMessageToApp (TRANSPORTMESSAGE_SIZE_SAVED, (ULONG_PTR) text);
lastTick = GetTickCount();
}
} while (IsmEnumNextPersistentObject (&objEnum));
}
if (IsmCheckCancel()) {
__leave;
}
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
appInfo.Phase = MIG_TRANSPORT_PHASE;
appInfo.SubPhase = SUBPHASE_FINISHING;
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
if (Compressed) {
ourDbFile = JoinPaths (g_TransportTempPath, S_TRANSPORT_DAT_FILE);
} else {
ourDbFile = pOpaqueAllocStorageFileName (S_TRANSPORT_DAT_FILE);
if (!ourDbFile) {
extraData.Error = ERRUSER_ERROR_CANTSAVEINTERNALDATA;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = 0;
extraData.ObjectName = NULL;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
__leave;
}
}
if (!MemDbSave (ourDbFile)) {
extraData.Error = ERRUSER_ERROR_CANTSAVEINTERNALDATA;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = 0;
extraData.ObjectName = NULL;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
__leave;
}
IsmTickProgressBar (g_DatabaseSlice, 1);
if (Compressed) {
if (IsmCheckCancel()) {
__leave;
}
if (!pOtAddFileToImage (ourDbFile, S_TRANSPORT_DAT_FILE, &compressedHandle)) {
extraData.Error = ERRUSER_ERROR_CANTSAVEINTERNALDATA;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = 0;
extraData.ObjectName = NULL;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
__leave;
}
IsmTickProgressBar (g_DatabaseSlice, 1);
if (IsmCheckCancel()) {
__leave;
}
if (!CompressFlushAndCloseHandle (&compressedHandle)) {
extraData.Error = ERRUSER_ERROR_CANTCREATECABFILE;
extraData.ErrorArea = ERRUSER_AREA_SAVE;
extraData.ObjectTypeId = 0;
extraData.ObjectName = NULL;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
__leave;
}
IsmTickProgressBar (g_DatabaseSlice, 1);
if (IsmCheckCancel()) {
__leave;
}
}
IsmSendMessageToApp (TRANSPORTMESSAGE_SIZE_SAVED, 0);
result = TRUE;
}
__finally {
PushError ();
CompressCleanupHandle (&compressedHandle);
pFreeStorageFileName (ourDbFile);
INVALID_POINTER (ourDbFile);
pOtDestroyDecoratedObject (decoratedObject);
INVALID_POINTER (decoratedObject);
if (g_OtCompressData && g_TransportTempPath) {
pOtCleanUpTempDir ();
}
PopError ();
}
return result;
}
BOOL
WINAPI
OpaqueTransportAcquireObject (
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;
PCTSTR newFileValue = NULL;
BOOL valueInFile;
KEYHANDLE keyHandle;
PALLOCSTATE allocState;
PCTSTR detailsKey = NULL;
PBYTE details;
UINT detailsSize;
PCTSTR sourceFile;
PCTSTR decoratedObject = NULL;
HANDLE fileHandle;
BOOL result = FALSE;
if (!ObjectContent) {
return FALSE;
}
MYASSERT (g_Platform == PLATFORM_DESTINATION);
MYASSERT ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE);
decoratedObject = pOpaqueBuildDecoratedObject (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);
newFileValue = pOpaqueGetNewFileName (fileValue);
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 = JoinPaths (pGetRealTransportPath (), newFileValue?newFileValue:fileValue);
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) {
sourceFile = JoinPaths (pGetRealTransportPath (), newFileValue?newFileValue:fileValue);
ObjectContent->MemoryContent.ContentSize = (UINT) BfGetFileSize (sourceFile);
ObjectContent->MemoryContent.ContentBytes = MapFileIntoMemory (
sourceFile,
&allocState->FileHandle,
&allocState->MapHandle
);
FreePathString (sourceFile);
result = (ObjectContent->MemoryContent.ContentBytes != NULL);
} else {
ObjectContent->MemoryContent.ContentSize = 0;
ObjectContent->MemoryContent.ContentBytes = NULL;
result = TRUE;
}
}
if (newFileValue) {
FreePathString (newFileValue);
newFileValue = NULL;
}
if (fileValue) {
MemDbReleaseMemory (fileValue);
fileValue = NULL;
}
} 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
OpaqueTransportReleaseObject (
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;
}