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.
2208 lines
70 KiB
2208 lines
70 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
direct.c
|
|
|
|
Abstract:
|
|
|
|
Implements a transport module that works with serial and parallel ports
|
|
|
|
Author:
|
|
|
|
Calin Negreanu (calinn) 14-Apr-2001
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include "logmsg.h"
|
|
#include <compress.h>
|
|
|
|
#define DBG_DIRECT "DIRECT"
|
|
|
|
//
|
|
// Strings
|
|
//
|
|
|
|
#define S_TRANSPORT_DAT_FILE TEXT("TRANSDB.DAT")
|
|
#define S_TRANSPORT_DEST_FILE TEXT("USMT2IMG.DAT")
|
|
#define S_TRANSPORT_IMG_FILE TEXT("IMG%05X.DAT")
|
|
#define S_UNCOMPRESSED_FILE TEXT("TEMPFILE.DAT")
|
|
#define S_DETAILS_PREFIX TEXT("details-")
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
#define TRFLAG_FILE 0x01
|
|
#define TRFLAG_MEMORY 0x02
|
|
#define COPY_BUFFER_SIZE 32768
|
|
#define DIRECTTR_CONVSIG 0x55534D33 //USM3
|
|
#define DIRECTTR_SIG 0x55534D34 //USM4
|
|
#define DIRECT_BUFFER_SIZE 1024
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
typedef struct {
|
|
TCHAR TempFile [MAX_PATH];
|
|
PCVOID AllocPtr;
|
|
PCVOID DetailsPtr;
|
|
HANDLE FileHandle;
|
|
HANDLE MapHandle;
|
|
} ALLOCSTATE, *PALLOCSTATE;
|
|
|
|
typedef struct {
|
|
DWORD Signature;
|
|
DWORD NumberOfFiles;
|
|
LONGLONG TotalImageSize;
|
|
} HEADER1, *PHEADER1;
|
|
|
|
typedef struct {
|
|
DWORD FileNumber;
|
|
LONGLONG FileSize;
|
|
} HEADER2, *PHEADER2;
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
MIG_TRANSPORTSTORAGEID g_DirectCableId;
|
|
UINT g_DirectCablePlatform;
|
|
PCTSTR g_DirectCablePath = NULL;
|
|
PCTSTR g_DirectCableTempPath = NULL;
|
|
DWORD g_DirectCableBaudRate = 0;
|
|
MIG_PROGRESSSLICEID g_PersistentSlice;
|
|
MIG_PROGRESSSLICEID g_DatabaseSlice;
|
|
UINT g_CompressedTicks;
|
|
UINT g_CompressedTicked;
|
|
MIG_PROGRESSSLICEID g_CompressedSlice;
|
|
UINT g_DownloadTicks;
|
|
UINT g_DownloadTicked;
|
|
MIG_PROGRESSSLICEID g_DownloadSlice;
|
|
UINT g_UncompressTicks;
|
|
UINT g_UncompressTicked;
|
|
MIG_PROGRESSSLICEID g_UncompressSlice;
|
|
LONGLONG g_TotalFiles;
|
|
LONGLONG g_FilesRead;
|
|
DWORD g_BaudRate [] = {CBR_256000,
|
|
CBR_128000,
|
|
CBR_115200,
|
|
CBR_57600,
|
|
CBR_56000,
|
|
CBR_38400,
|
|
CBR_19200,
|
|
CBR_14400,
|
|
CBR_9600,
|
|
CBR_4800,
|
|
CBR_2400,
|
|
CBR_1200,
|
|
CBR_600,
|
|
CBR_300,
|
|
CBR_110,
|
|
0};
|
|
|
|
DWORD g_StartTicks = 0;
|
|
|
|
//
|
|
// Macro expansion list
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
VOID
|
|
pDCCleanupTempDir (
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Macro expansion definition
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Code
|
|
//
|
|
|
|
BOOL
|
|
WINAPI
|
|
DirectCableTransportInitialize (
|
|
PMIG_LOGCALLBACK LogCallback
|
|
)
|
|
{
|
|
//
|
|
// Initialize globals
|
|
//
|
|
|
|
LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
|
|
g_DirectCableId = IsmRegisterTransport (S_DIRECT_CABLE_TRANSPORT);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
DirectCableTransportTerminate (
|
|
VOID
|
|
)
|
|
{
|
|
pDCCleanupTempDir ();
|
|
|
|
if (g_DirectCableTempPath) {
|
|
FreePathString (g_DirectCableTempPath);
|
|
g_DirectCableTempPath = NULL;
|
|
}
|
|
if (g_DirectCablePath) {
|
|
FreePathString (g_DirectCablePath);
|
|
g_DirectCablePath = NULL;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
DirectCableTransportEstimateProgressBar (
|
|
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));
|
|
|
|
g_DatabaseSlice = IsmRegisterProgressSlice (3, 1);
|
|
|
|
g_CompressedTicks = ticks;
|
|
|
|
g_CompressedSlice = IsmRegisterProgressSlice (g_CompressedTicks, max (1, g_CompressedTicks / 5));
|
|
} else {
|
|
g_DownloadTicked = 0;
|
|
g_DownloadTicks = 1000;
|
|
g_DownloadSlice = IsmRegisterProgressSlice (g_DownloadTicks, 180);
|
|
g_UncompressTicked = 0;
|
|
g_UncompressTicks = 1000;
|
|
g_UncompressSlice = IsmRegisterProgressSlice (g_UncompressTicks, 180);
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DirectCableTransportQueryCapabilities (
|
|
IN MIG_TRANSPORTSTORAGEID TransportStorageId,
|
|
OUT PMIG_TRANSPORTTYPE TransportType,
|
|
OUT PMIG_TRANSPORTCAPABILITIES Capabilities,
|
|
OUT PCTSTR *FriendlyDescription
|
|
)
|
|
{
|
|
if (TransportStorageId != g_DirectCableId) {
|
|
return FALSE;
|
|
}
|
|
|
|
*TransportType = TRANSPORTTYPE_FULL;
|
|
*Capabilities = CAPABILITY_COMPRESSED;
|
|
*FriendlyDescription = TEXT("Direct Cable");
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
pDCCleanupTempDir (
|
|
VOID
|
|
)
|
|
{
|
|
if (g_DirectCableTempPath) {
|
|
FiRemoveAllFilesInTree (g_DirectCableTempPath);
|
|
}
|
|
}
|
|
|
|
PCTSTR
|
|
pDCCreateTemporaryDir (
|
|
VOID
|
|
)
|
|
{
|
|
TCHAR tempFile[MAX_PATH];
|
|
|
|
if (!IsmGetTempDirectory (tempFile, ARRAYSIZE(tempFile))) {
|
|
return NULL;
|
|
}
|
|
return DuplicatePathString (tempFile, 0);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DirectCableTransportSetStorage (
|
|
IN MIG_PLATFORMTYPEID Platform,
|
|
IN MIG_TRANSPORTSTORAGEID TransportStorageId,
|
|
IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities,
|
|
IN PCTSTR StoragePath,
|
|
OUT PBOOL Valid,
|
|
OUT PBOOL ImageExists
|
|
)
|
|
{
|
|
BOOL result = FALSE;
|
|
PTSTR baudRatePtr = NULL;
|
|
|
|
if (Valid) {
|
|
*Valid = FALSE;
|
|
}
|
|
if (ImageExists) {
|
|
*ImageExists = FALSE;
|
|
}
|
|
|
|
if (TransportStorageId == g_DirectCableId) {
|
|
|
|
if ((!RequiredCapabilities) || (RequiredCapabilities == CAPABILITY_COMPRESSED)) {
|
|
|
|
if (g_DirectCablePath) {
|
|
FreePathString (g_DirectCablePath);
|
|
g_DirectCablePath = NULL;
|
|
}
|
|
g_DirectCablePath = DuplicatePathString (StoragePath, 0);
|
|
baudRatePtr = _tcschr (g_DirectCablePath, TEXT(':'));
|
|
if (baudRatePtr) {
|
|
*baudRatePtr = 0;
|
|
baudRatePtr ++;
|
|
g_DirectCableBaudRate = _ttoi (baudRatePtr);
|
|
}
|
|
|
|
if (Valid) {
|
|
*Valid = TRUE;
|
|
}
|
|
|
|
if (ImageExists) {
|
|
if (Platform == PLATFORM_SOURCE) {
|
|
*ImageExists = FALSE;
|
|
} else {
|
|
*ImageExists = TRUE;
|
|
}
|
|
}
|
|
|
|
result = TRUE;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
PCTSTR
|
|
pDCBuildDecoratedObject (
|
|
IN MIG_OBJECTTYPEID ObjectTypeId,
|
|
IN ENCODEDSTRHANDLE ObjectName
|
|
)
|
|
{
|
|
PCTSTR typeStr;
|
|
|
|
typeStr = IsmGetObjectTypeName (ObjectTypeId);
|
|
if (!typeStr) {
|
|
return NULL;
|
|
}
|
|
|
|
return JoinPaths (typeStr, ObjectName);
|
|
}
|
|
|
|
VOID
|
|
pDCDestroyDecoratedObject (
|
|
IN PCTSTR String
|
|
)
|
|
{
|
|
FreePathString (String);
|
|
}
|
|
|
|
BOOL
|
|
pDCSaveDetails (
|
|
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
|
|
pDCAllocStorageFileName (
|
|
VOID
|
|
)
|
|
{
|
|
static UINT fileIndex = 0;
|
|
TCHAR buffer [32];
|
|
|
|
fileIndex ++;
|
|
wsprintf (buffer, TEXT("%08X.DAT"), fileIndex);
|
|
|
|
return DuplicatePathString (buffer, 0);
|
|
}
|
|
|
|
BOOL
|
|
pDCSaveContentInMemory (
|
|
IN MIG_OBJECTTYPEID ObjectTypeId,
|
|
IN ENCODEDSTRHANDLE ObjectName,
|
|
IN PCTSTR DecoratedObject,
|
|
IN PMIG_CONTENT ObjectValue
|
|
)
|
|
{
|
|
BOOL result = FALSE;
|
|
|
|
MemDbSetValue (DecoratedObject, TRFLAG_MEMORY);
|
|
|
|
if (ObjectValue->MemoryContent.ContentBytes && ObjectValue->MemoryContent.ContentSize) {
|
|
|
|
MemDbSetUnorderedBlob (
|
|
DecoratedObject,
|
|
0,
|
|
ObjectValue->MemoryContent.ContentBytes,
|
|
ObjectValue->MemoryContent.ContentSize
|
|
);
|
|
}
|
|
|
|
result = pDCSaveDetails (DecoratedObject, &ObjectValue->Details);
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pDCAddFileToImage (
|
|
IN PCTSTR FileName,
|
|
IN PCTSTR StoredName,
|
|
IN OUT PCOMPRESS_HANDLE CompressedHandle
|
|
)
|
|
{
|
|
return CompressAddFileToHandle (FileName, StoredName, CompressedHandle);
|
|
}
|
|
|
|
BOOL
|
|
pDCSaveContentInFile (
|
|
IN MIG_OBJECTTYPEID ObjectTypeId,
|
|
IN PCTSTR EncodedFileName,
|
|
IN PCTSTR DecoratedObject,
|
|
IN PMIG_CONTENT Content,
|
|
IN OUT PCOMPRESS_HANDLE CompressedHandle
|
|
)
|
|
{
|
|
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;
|
|
}
|
|
result = TRUE;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Get a temp file, assemble the src path, copy the file
|
|
//
|
|
|
|
destPath = pDCAllocStorageFileName ();
|
|
if (!destPath) {
|
|
__leave;
|
|
}
|
|
|
|
if (!pDCAddFileToImage (Content->FileContent.ContentPath, destPath, CompressedHandle)) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Keep track of where the file went
|
|
//
|
|
|
|
if (!MemDbSetValue (DecoratedObject, TRFLAG_FILE)) {
|
|
__leave;
|
|
}
|
|
|
|
if (!MemDbAddSingleLinkage (DecoratedObject, destPath, 0)) {
|
|
__leave;
|
|
}
|
|
|
|
FreePathString (destPath);
|
|
destPath = NULL;
|
|
}
|
|
|
|
//
|
|
// Save details
|
|
//
|
|
|
|
result = pDCSaveDetails (DecoratedObject, &(Content->Details));
|
|
}
|
|
__finally {
|
|
if (destPath) {
|
|
FreePathString (destPath);
|
|
destPath = NULL;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
PCTSTR
|
|
pDCGetImageFile (
|
|
IN UINT ImageIdx
|
|
)
|
|
{
|
|
TCHAR imageFileName [13];
|
|
PCTSTR imageFile = NULL;
|
|
HANDLE imageFileHandle = NULL;
|
|
|
|
wsprintf (imageFileName, S_TRANSPORT_IMG_FILE, ImageIdx);
|
|
return JoinPaths (g_DirectCableTempPath, imageFileName);
|
|
}
|
|
|
|
HANDLE
|
|
pDCOpenAndSetPort (
|
|
IN PCTSTR ComPort
|
|
)
|
|
{
|
|
HANDLE result = INVALID_HANDLE_VALUE;
|
|
COMMTIMEOUTS commTimeouts;
|
|
DCB dcb;
|
|
|
|
// let's open the port. If we can't we just exit with error;
|
|
result = CreateFile (ComPort, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
if (result == INVALID_HANDLE_VALUE) {
|
|
return result;
|
|
}
|
|
|
|
// we want 3 sec timeout for both read and write
|
|
commTimeouts.ReadIntervalTimeout = 0;
|
|
commTimeouts.ReadTotalTimeoutMultiplier = 0;
|
|
commTimeouts.ReadTotalTimeoutConstant = 3000;
|
|
commTimeouts.WriteTotalTimeoutMultiplier = 0;
|
|
commTimeouts.WriteTotalTimeoutConstant = 3000;
|
|
SetCommTimeouts (result, &commTimeouts);
|
|
|
|
// let's set some comm state data
|
|
if (GetCommState (result, &dcb)) {
|
|
dcb.fBinary = 1;
|
|
dcb.fParity = 1;
|
|
dcb.ByteSize = 8;
|
|
dcb.fOutxCtsFlow = 1;
|
|
dcb.fTXContinueOnXoff = 1;
|
|
dcb.fRtsControl = 2;
|
|
dcb.fAbortOnError = 1;
|
|
dcb.Parity = 0;
|
|
dcb.BaudRate = g_DirectCableBaudRate?g_DirectCableBaudRate:CBR_115200;
|
|
if (!SetCommState (result, &dcb)) {
|
|
CloseHandle (result);
|
|
result = INVALID_HANDLE_VALUE;
|
|
return result;
|
|
}
|
|
} else {
|
|
CloseHandle (result);
|
|
result = INVALID_HANDLE_VALUE;
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
#define ACK 0x16
|
|
#define NAK 0x15
|
|
#define SOH 0x01
|
|
#define EOT 0x04
|
|
#define BLOCKSIZE 1024
|
|
|
|
BOOL
|
|
pDCSendFileToHandle (
|
|
IN HANDLE DeviceHandle,
|
|
IN PCTSTR FileName,
|
|
IN OUT ULONGLONG *TotalImageWritten,
|
|
IN ULONGLONG TotalImageSize
|
|
)
|
|
{
|
|
HANDLE fileHandle = NULL;
|
|
BOOL result = TRUE;
|
|
BYTE buffer [4 + BLOCKSIZE];
|
|
BYTE signal;
|
|
BYTE currBlock = 0;
|
|
DWORD numRead;
|
|
DWORD numWritten;
|
|
BOOL repeat = FALSE;
|
|
UINT index;
|
|
LONGLONG numerator;
|
|
LONGLONG divisor;
|
|
LONGLONG tick;
|
|
UINT delta;
|
|
UINT elapsedTicks;
|
|
UINT estimatedTime;
|
|
UINT percent, percent100;
|
|
UINT hour, minute, second;
|
|
MIG_APPINFO appInfo;
|
|
PCTSTR statusMsg;
|
|
PCTSTR argArray[5];
|
|
|
|
fileHandle = BfOpenReadFile (FileName);
|
|
if (!fileHandle) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!g_StartTicks) {
|
|
g_StartTicks = GetTickCount ();
|
|
}
|
|
|
|
// finally let's start the protocol
|
|
|
|
// We are going to listen for the NAK(15h) signal.
|
|
// As soon as we get it we are going to send a 4 + BLOCKSIZE bytes block having:
|
|
// 1 byte - SOH (01H)
|
|
// 1 byte - block number
|
|
// 1 byte - FF - block number
|
|
// BLOCKSIZE bytes of data
|
|
// 1 byte - checksum - sum of all BLOCKSIZE bytes of data
|
|
// After the block is sent, we are going to wait for ACK(16h). If we don't get
|
|
// it after timeout or if we get something else we are going to send the block again.
|
|
|
|
// wait for NAK
|
|
while ((!ReadFile (DeviceHandle, &signal, sizeof (signal), &numRead, NULL) ||
|
|
(numRead != 1) ||
|
|
(signal != NAK)
|
|
) &&
|
|
(!IsmCheckCancel ())
|
|
);
|
|
|
|
repeat = FALSE;
|
|
while (TRUE) {
|
|
|
|
if (IsmCheckCancel ()) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (!repeat) {
|
|
// prepare the next block
|
|
currBlock ++;
|
|
if (currBlock == 0) {
|
|
result = TRUE;
|
|
}
|
|
buffer [0] = SOH;
|
|
buffer [1] = currBlock;
|
|
buffer [2] = 0xFF - currBlock;
|
|
if (!ReadFile (fileHandle, buffer + 3, BLOCKSIZE, &numRead, NULL) ||
|
|
(numRead == 0)
|
|
) {
|
|
// we are done with data, send the EOT signal
|
|
signal = EOT;
|
|
WriteFile (DeviceHandle, &signal, sizeof (signal), &numWritten, NULL);
|
|
break;
|
|
}
|
|
|
|
if (TotalImageWritten) {
|
|
*TotalImageWritten += numRead;
|
|
}
|
|
// compute the checksum
|
|
buffer [sizeof (buffer) - 1] = 0;
|
|
signal = 0;
|
|
for (index = 0; index < sizeof (buffer) - 1; index ++) {
|
|
signal += buffer [index];
|
|
}
|
|
buffer [sizeof (buffer) - 1] = signal;
|
|
}
|
|
|
|
// now send the block to the other side
|
|
if (!WriteFile (DeviceHandle, buffer, sizeof (buffer), &numWritten, NULL) ||
|
|
(numWritten != sizeof (buffer))
|
|
) {
|
|
repeat = TRUE;
|
|
} else {
|
|
repeat = FALSE;
|
|
}
|
|
|
|
if (IsmCheckCancel ()) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (repeat) {
|
|
// we could not send the data last time
|
|
// let's just wait for a NAK for 10 sec and then send it again
|
|
ReadFile (DeviceHandle, &signal, sizeof (signal), &numRead, NULL);
|
|
} else {
|
|
// we sent it OK. We need to wait for an ACK to come. If we timeout
|
|
// or we get something else, we will repeat the block.
|
|
if (!ReadFile (DeviceHandle, &signal, sizeof (signal), &numRead, NULL) ||
|
|
(numRead != sizeof (signal)) ||
|
|
(signal != ACK)
|
|
) {
|
|
repeat = TRUE;
|
|
}
|
|
if (!repeat) {
|
|
if (TotalImageWritten) {
|
|
// now update the progress bar
|
|
numerator = (LONGLONG) (*TotalImageWritten) * (LONGLONG) g_CompressedTicks;
|
|
divisor = (LONGLONG) TotalImageSize;
|
|
if (divisor) {
|
|
tick = numerator / divisor;
|
|
} else {
|
|
tick = 0;
|
|
}
|
|
delta = (UINT) tick - g_CompressedTicked;
|
|
if (delta) {
|
|
IsmTickProgressBar (g_CompressedSlice, delta);
|
|
g_CompressedTicked += delta;
|
|
}
|
|
// now update the estimated time and %
|
|
elapsedTicks = GetTickCount () - g_StartTicks;
|
|
estimatedTime = (UINT)(TotalImageSize * elapsedTicks / (*TotalImageWritten)) - elapsedTicks;
|
|
percent100 = (UINT)((*TotalImageWritten) * 10000 / TotalImageSize);
|
|
percent = percent100 / 100;
|
|
percent100 = percent100 - (percent * 100);
|
|
if (elapsedTicks > 45000) { // after about 45 seconds
|
|
// let's send the message to the app
|
|
hour = estimatedTime / 3600000;
|
|
minute = estimatedTime / 60000 - hour * 60;
|
|
second = estimatedTime / 1000 - hour * 3600 - minute * 60;
|
|
|
|
argArray[0] = (PCTSTR) (UINT_PTR) (percent);
|
|
argArray[1] = (PCTSTR) (UINT_PTR) (percent100);
|
|
argArray[2] = (PCTSTR) (UINT_PTR) (hour);
|
|
argArray[3] = (PCTSTR) (UINT_PTR) (minute);
|
|
argArray[4] = (PCTSTR) (UINT_PTR) (second);
|
|
statusMsg = ParseMessageID (MSG_TRANSFER_INFO, argArray);
|
|
|
|
if (statusMsg) {
|
|
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
|
|
appInfo.Phase = MIG_TRANSPORT_PHASE;
|
|
appInfo.SubPhase = SUBPHASE_CABLETRANS;
|
|
appInfo.Text = statusMsg;
|
|
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
|
|
FreeStringResource (statusMsg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result) {
|
|
// we are done here. However, let's listen one more timeout for a
|
|
// potential NAK. If we get it, we'll repeat the EOT signal
|
|
while (ReadFile (DeviceHandle, &signal, sizeof (signal), &numRead, NULL) &&
|
|
(numRead == 1)
|
|
) {
|
|
if (signal == NAK) {
|
|
signal = EOT;
|
|
WriteFile (DeviceHandle, &signal, sizeof (signal), &numWritten, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseHandle (fileHandle);
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pDCSendFile (
|
|
IN PCTSTR ComPort,
|
|
IN PCTSTR FileName,
|
|
IN OUT ULONGLONG *TotalImageWritten,
|
|
IN ULONGLONG TotalImageSize
|
|
)
|
|
{
|
|
HANDLE deviceHandle = INVALID_HANDLE_VALUE;
|
|
BOOL result = FALSE;
|
|
|
|
deviceHandle = pDCOpenAndSetPort (ComPort);
|
|
if ((!deviceHandle) || (deviceHandle == INVALID_HANDLE_VALUE)) {
|
|
return result;
|
|
}
|
|
|
|
result = pDCSendFileToHandle (deviceHandle, FileName, TotalImageWritten, TotalImageSize);
|
|
|
|
CloseHandle (deviceHandle);
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pDCSendBlockToHandle (
|
|
IN HANDLE DeviceHandle,
|
|
IN PCBYTE Buffer
|
|
)
|
|
{
|
|
BOOL result = TRUE;
|
|
BYTE buffer [4 + BLOCKSIZE];
|
|
BYTE signal;
|
|
BYTE currBlock = 0;
|
|
DWORD numRead;
|
|
DWORD numWritten;
|
|
BOOL repeat = FALSE;
|
|
UINT index;
|
|
|
|
// let's start the protocol
|
|
|
|
// We are going to listen for the NAK(15h) signal.
|
|
// As soon as we get it we are going to send a 4 + BLOCKSIZE bytes block having:
|
|
// 1 byte - SOH (01H)
|
|
// 1 byte - block number
|
|
// 1 byte - FF - block number
|
|
// BLOCKSIZE bytes of data
|
|
// 1 byte - checksum - sum of all BLOCKSIZE bytes of data
|
|
// After the block is sent, we are going to wait for ACK(16h). If we don't get
|
|
// it after timeout or if we get something else we are going to send the block again.
|
|
|
|
// wait for NAK
|
|
while ((!ReadFile (DeviceHandle, &signal, sizeof (signal), &numRead, NULL) ||
|
|
(numRead != 1) ||
|
|
(signal != NAK)
|
|
) &&
|
|
(!IsmCheckCancel ())
|
|
);
|
|
|
|
repeat = FALSE;
|
|
while (TRUE) {
|
|
|
|
if (IsmCheckCancel ()) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (!repeat) {
|
|
// prepare the next block
|
|
currBlock ++;
|
|
if (currBlock == 0) {
|
|
result = TRUE;
|
|
}
|
|
buffer [0] = SOH;
|
|
buffer [1] = currBlock;
|
|
buffer [2] = 0xFF - currBlock;
|
|
CopyMemory (buffer + 3, Buffer, BLOCKSIZE);
|
|
|
|
// compute the checksum
|
|
buffer [sizeof (buffer) - 1] = 0;
|
|
signal = 0;
|
|
for (index = 0; index < sizeof (buffer) - 1; index ++) {
|
|
signal += buffer [index];
|
|
}
|
|
buffer [sizeof (buffer) - 1] = signal;
|
|
}
|
|
|
|
// now send the block to the other side
|
|
if (!WriteFile (DeviceHandle, buffer, sizeof (buffer), &numWritten, NULL) ||
|
|
(numWritten != sizeof (buffer))
|
|
) {
|
|
repeat = TRUE;
|
|
} else {
|
|
repeat = FALSE;
|
|
}
|
|
|
|
if (IsmCheckCancel ()) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (repeat) {
|
|
// we could not send the data last time
|
|
// let's just wait for a NAK for 10 sec and then send it again
|
|
ReadFile (DeviceHandle, &signal, sizeof (signal), &numRead, NULL);
|
|
} else {
|
|
// we sent it OK. We need to wait for an ACK to come. If we timeout
|
|
// or we get something else, we will repeat the block.
|
|
if (!ReadFile (DeviceHandle, &signal, sizeof (signal), &numRead, NULL) ||
|
|
(numRead != sizeof (signal)) ||
|
|
(signal != ACK)
|
|
) {
|
|
repeat = TRUE;
|
|
} else {
|
|
// we are done with data, send the EOT signal
|
|
signal = EOT;
|
|
WriteFile (DeviceHandle, &signal, sizeof (signal), &numWritten, NULL);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result) {
|
|
// we are done here. However, let's listen one more timeout for a
|
|
// potential NAK. If we get it, we'll repeat the EOT signal
|
|
while (ReadFile (DeviceHandle, &signal, sizeof (signal), &numRead, NULL) &&
|
|
(numRead == 1)
|
|
) {
|
|
if (signal == NAK) {
|
|
signal = EOT;
|
|
WriteFile (DeviceHandle, &signal, sizeof (signal), &numWritten, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pDCSendBlock (
|
|
IN PCTSTR ComPort,
|
|
IN PCBYTE Buffer
|
|
)
|
|
{
|
|
HANDLE deviceHandle = INVALID_HANDLE_VALUE;
|
|
BOOL result = FALSE;
|
|
|
|
// Buffer must have BLOCKSIZE size
|
|
|
|
deviceHandle = pDCOpenAndSetPort (ComPort);
|
|
if ((!deviceHandle) || (deviceHandle == INVALID_HANDLE_VALUE)) {
|
|
return result;
|
|
}
|
|
|
|
result = pDCSendBlockToHandle (deviceHandle, Buffer);
|
|
|
|
CloseHandle (deviceHandle);
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pDCReceiveFileFromHandle (
|
|
IN HANDLE DeviceHandle,
|
|
IN PCTSTR FileName,
|
|
IN LONGLONG FileSize,
|
|
IN OUT ULONGLONG *TotalImageRead,
|
|
IN ULONGLONG TotalImageSize
|
|
)
|
|
{
|
|
HANDLE fileHandle = NULL;
|
|
BOOL result = TRUE;
|
|
BYTE buffer [4 + BLOCKSIZE];
|
|
BYTE signal;
|
|
BYTE currBlock = 1;
|
|
DWORD numRead;
|
|
DWORD numWritten;
|
|
BOOL repeat = TRUE;
|
|
UINT index;
|
|
LONGLONG numerator;
|
|
LONGLONG divisor;
|
|
LONGLONG tick;
|
|
UINT delta;
|
|
UINT elapsedTicks;
|
|
UINT estimatedTime;
|
|
UINT percent, percent100;
|
|
UINT hour, minute, second;
|
|
MIG_APPINFO appInfo;
|
|
PCTSTR statusMsg;
|
|
PCTSTR argArray[5];
|
|
|
|
fileHandle = BfCreateFile (FileName);
|
|
if (!fileHandle) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!g_StartTicks) {
|
|
g_StartTicks = GetTickCount ();
|
|
}
|
|
|
|
// finally let's start the protocol
|
|
|
|
// We are going to send an NAK(15h) signal.
|
|
// After that we are going to listen for a block.
|
|
// If we don't get the block in time, or the block is wrong size
|
|
// or it has a wrong checksum we are going to send a NAK signal,
|
|
// otherwise we are going to send an ACK signal
|
|
// One exception. If the block size is 1 and the block is actually the
|
|
// EOT signal it means we are done.
|
|
|
|
while (TRUE) {
|
|
|
|
if (IsmCheckCancel ()) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (repeat) {
|
|
// send the NAK
|
|
signal = NAK;
|
|
WriteFile (DeviceHandle, &signal, sizeof (signal), &numWritten, NULL);
|
|
} else {
|
|
// send the ACK
|
|
signal = ACK;
|
|
WriteFile (DeviceHandle, &signal, sizeof (signal), &numWritten, NULL);
|
|
}
|
|
|
|
if (IsmCheckCancel ()) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
repeat = TRUE;
|
|
// let's read the data block
|
|
if (ReadFile (DeviceHandle, buffer, sizeof (buffer), &numRead, NULL)) {
|
|
if ((numRead == 1) &&
|
|
(buffer [0] == EOT)
|
|
) {
|
|
// we are done
|
|
break;
|
|
}
|
|
if (numRead == sizeof (buffer)) {
|
|
// compute the checksum
|
|
signal = 0;
|
|
for (index = 0; index < sizeof (buffer) - 1; index ++) {
|
|
signal += buffer [index];
|
|
}
|
|
if (buffer [sizeof (buffer) - 1] == signal) {
|
|
repeat = FALSE;
|
|
// checksum is correct, let's see if this is the right block
|
|
if (currBlock < buffer [1]) {
|
|
// this is a major error, the sender is ahead of us,
|
|
// we have to fail
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
if (currBlock == buffer [1]) {
|
|
if (FileSize > BLOCKSIZE) {
|
|
if ((!WriteFile (fileHandle, buffer + 3, BLOCKSIZE, &numWritten, NULL)) ||
|
|
(numWritten != BLOCKSIZE)
|
|
) {
|
|
// Write failed. Let's get out of here
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
if (TotalImageRead) {
|
|
*TotalImageRead += BLOCKSIZE;
|
|
}
|
|
FileSize -= BLOCKSIZE;
|
|
} else {
|
|
if ((!WriteFile (fileHandle, buffer + 3, (DWORD)FileSize, &numWritten, NULL)) ||
|
|
(numWritten != FileSize)
|
|
) {
|
|
// Write failed. Let's get out of here
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
if (TotalImageRead) {
|
|
*TotalImageRead += FileSize;
|
|
}
|
|
FileSize = 0;
|
|
}
|
|
if (TotalImageRead) {
|
|
// now update the progress bar
|
|
numerator = (LONGLONG) (*TotalImageRead) * (LONGLONG) g_DownloadTicks;
|
|
divisor = (LONGLONG) TotalImageSize;
|
|
if (divisor) {
|
|
tick = numerator / divisor;
|
|
} else {
|
|
tick = 0;
|
|
}
|
|
delta = (UINT) tick - g_DownloadTicked;
|
|
if (delta) {
|
|
IsmTickProgressBar (g_DownloadSlice, delta);
|
|
g_DownloadTicked += delta;
|
|
}
|
|
// now update the estimated time and %
|
|
elapsedTicks = GetTickCount () - g_StartTicks;
|
|
estimatedTime = (UINT)(TotalImageSize * elapsedTicks / (*TotalImageRead)) - elapsedTicks;
|
|
percent100 = (UINT)((*TotalImageRead) * 10000 / TotalImageSize);
|
|
percent = percent100 / 100;
|
|
percent100 = percent100 - (percent * 100);
|
|
if (elapsedTicks > 45000) { // after about 45 seconds
|
|
// let's send the message to the app
|
|
hour = estimatedTime / 3600000;
|
|
minute = estimatedTime / 60000 - hour * 60;
|
|
second = estimatedTime / 1000 - hour * 3600 - minute * 60;
|
|
|
|
argArray[0] = (PCTSTR) (UINT_PTR) (percent);
|
|
argArray[1] = (PCTSTR) (UINT_PTR) (percent100);
|
|
argArray[2] = (PCTSTR) (UINT_PTR) (hour);
|
|
argArray[3] = (PCTSTR) (UINT_PTR) (minute);
|
|
argArray[4] = (PCTSTR) (UINT_PTR) (second);
|
|
statusMsg = ParseMessageID (MSG_TRANSFER_INFO, argArray);
|
|
|
|
if (statusMsg) {
|
|
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
|
|
appInfo.Phase = MIG_TRANSPORT_PHASE;
|
|
appInfo.SubPhase = SUBPHASE_CABLETRANS;
|
|
appInfo.Text = statusMsg;
|
|
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
|
|
FreeStringResource (statusMsg);
|
|
}
|
|
}
|
|
}
|
|
currBlock ++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseHandle (fileHandle);
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pDCReceiveFile (
|
|
IN PCTSTR ComPort,
|
|
IN PCTSTR FileName,
|
|
IN LONGLONG FileSize,
|
|
IN OUT ULONGLONG *TotalImageRead,
|
|
IN ULONGLONG TotalImageSize
|
|
)
|
|
{
|
|
HANDLE deviceHandle = INVALID_HANDLE_VALUE;
|
|
BOOL result = FALSE;
|
|
|
|
deviceHandle = pDCOpenAndSetPort (ComPort);
|
|
if ((!deviceHandle) || (deviceHandle == INVALID_HANDLE_VALUE)) {
|
|
return result;
|
|
}
|
|
|
|
result = pDCReceiveFileFromHandle (deviceHandle, FileName, FileSize, TotalImageRead, TotalImageSize);
|
|
|
|
CloseHandle (deviceHandle);
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pDCReceiveBlockFromHandle (
|
|
IN HANDLE DeviceHandle,
|
|
OUT PBYTE Buffer
|
|
)
|
|
{
|
|
BOOL result = TRUE;
|
|
BYTE buffer [4 + BLOCKSIZE];
|
|
BYTE signal;
|
|
BYTE currBlock = 1;
|
|
DWORD numRead;
|
|
DWORD numWritten;
|
|
BOOL repeat = TRUE;
|
|
UINT index;
|
|
|
|
// finally let's start the protocol
|
|
|
|
// We are going to send an NAK(15h) signal.
|
|
// After that we are going to listen for a block.
|
|
// If we don't get the block in time, or the block is wrong size
|
|
// or it has a wrong checksum we are going to send a NAK signal,
|
|
// otherwise we are going to send an ACK signal
|
|
// One exception. If the block size is 1 and the block is actually the
|
|
// EOT signal it means we are done.
|
|
|
|
ZeroMemory (Buffer, BLOCKSIZE);
|
|
|
|
while (TRUE) {
|
|
|
|
if (IsmCheckCancel ()) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (repeat) {
|
|
// send the NAK
|
|
signal = NAK;
|
|
WriteFile (DeviceHandle, &signal, sizeof (signal), &numWritten, NULL);
|
|
} else {
|
|
// send the ACK
|
|
signal = ACK;
|
|
WriteFile (DeviceHandle, &signal, sizeof (signal), &numWritten, NULL);
|
|
}
|
|
|
|
if (IsmCheckCancel ()) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
repeat = TRUE;
|
|
// let's read the data block
|
|
if (ReadFile (DeviceHandle, buffer, sizeof (buffer), &numRead, NULL)) {
|
|
if ((numRead == 1) &&
|
|
(buffer [0] == EOT)
|
|
) {
|
|
// we are done
|
|
break;
|
|
}
|
|
if (numRead == sizeof (buffer)) {
|
|
// compute the checksum
|
|
signal = 0;
|
|
for (index = 0; index < sizeof (buffer) - 1; index ++) {
|
|
signal += buffer [index];
|
|
}
|
|
if (buffer [sizeof (buffer) - 1] == signal) {
|
|
repeat = FALSE;
|
|
// checksum is correct, let's see if this is the right block
|
|
if (currBlock < buffer [1]) {
|
|
// this is a major error, the sender is ahead of us,
|
|
// we have to fail
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
if (currBlock == buffer [1]) {
|
|
CopyMemory (Buffer, buffer + 3, BLOCKSIZE);
|
|
currBlock ++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pDCReceiveBlock (
|
|
IN PCTSTR ComPort,
|
|
OUT PBYTE Buffer
|
|
)
|
|
{
|
|
HANDLE deviceHandle = INVALID_HANDLE_VALUE;
|
|
BOOL result = FALSE;
|
|
|
|
// Buffer must have BLOCKSIZE size
|
|
|
|
deviceHandle = pDCOpenAndSetPort (ComPort);
|
|
if ((!deviceHandle) || (deviceHandle == INVALID_HANDLE_VALUE)) {
|
|
return result;
|
|
}
|
|
|
|
result = pDCReceiveBlockFromHandle (deviceHandle, Buffer);
|
|
|
|
CloseHandle (deviceHandle);
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pDCWriteAllImages (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_APPINFO appInfo;
|
|
PHEADER1 header1;
|
|
PHEADER2 header2;
|
|
BYTE buffer [BLOCKSIZE];
|
|
ULONGLONG totalImageWritten = 0;
|
|
ULONGLONG totalImageSize = 0;
|
|
UINT numberOfFiles = 0;
|
|
UINT imageIdx = 1;
|
|
ULONGLONG imageSize = 0;
|
|
PCTSTR imageFile;
|
|
|
|
// let's get the total image size and the total number of bytes
|
|
imageIdx = 1;
|
|
while (TRUE) {
|
|
imageFile = pDCGetImageFile (imageIdx);
|
|
imageSize = BfGetFileSize (imageFile);
|
|
if (imageSize == 0) {
|
|
FreePathString (imageFile);
|
|
break;
|
|
}
|
|
numberOfFiles ++;
|
|
totalImageSize += imageSize;
|
|
FreePathString (imageFile);
|
|
imageIdx ++;
|
|
}
|
|
|
|
// let's prepare the initial header
|
|
ZeroMemory (buffer, sizeof (buffer));
|
|
header1 = (PHEADER1) buffer;
|
|
header1->Signature = DIRECTTR_SIG;
|
|
header1->NumberOfFiles = numberOfFiles;
|
|
header1->TotalImageSize = totalImageSize;
|
|
|
|
if (!pDCSendBlock (g_DirectCablePath, buffer)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_DESTINATION));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!pDCReceiveBlock (g_DirectCablePath, buffer)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_DESTINATION));
|
|
return FALSE;
|
|
}
|
|
|
|
if (header1->Signature != DIRECTTR_SIG) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_DESTINATION));
|
|
return FALSE;
|
|
}
|
|
|
|
if (header1->NumberOfFiles != numberOfFiles) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_DESTINATION));
|
|
return FALSE;
|
|
}
|
|
|
|
if (header1->TotalImageSize != totalImageSize) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_DESTINATION));
|
|
return FALSE;
|
|
}
|
|
|
|
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
|
|
appInfo.Phase = MIG_TRANSPORT_PHASE;
|
|
appInfo.SubPhase = SUBPHASE_NETPREPARING;
|
|
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
|
|
|
|
imageIdx = 1;
|
|
while (TRUE) {
|
|
imageFile = pDCGetImageFile (imageIdx);
|
|
imageSize = BfGetFileSize (imageFile);
|
|
if (imageSize == 0) {
|
|
FreePathString (imageFile);
|
|
break;
|
|
}
|
|
// send info about the current file
|
|
ZeroMemory (buffer, sizeof (buffer));
|
|
header2 = (PHEADER2) buffer;
|
|
header2->FileNumber = imageIdx;
|
|
header2->FileSize = imageSize;
|
|
|
|
if (!pDCSendBlock (g_DirectCablePath, buffer)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_DESTINATION));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!pDCReceiveBlock (g_DirectCablePath, buffer)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_DESTINATION));
|
|
return FALSE;
|
|
}
|
|
|
|
if (header2->FileNumber != imageIdx) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_DESTINATION));
|
|
return FALSE;
|
|
}
|
|
|
|
if (header2->FileSize != imageSize) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_DESTINATION));
|
|
return FALSE;
|
|
}
|
|
|
|
// send the actual file
|
|
if (!pDCSendFile (g_DirectCablePath, imageFile, &totalImageWritten, totalImageSize)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_DESTINATION));
|
|
return FALSE;
|
|
}
|
|
|
|
FreePathString (imageFile);
|
|
imageIdx ++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DirectCableTransportSaveState (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_APPINFO appInfo;
|
|
ERRUSER_EXTRADATA extraData;
|
|
MIG_OBJECTWITHATTRIBUTE_ENUM objEnum;
|
|
PCTSTR databaseFile = NULL;
|
|
PCTSTR decoratedObject = NULL;
|
|
MIG_CONTENT value;
|
|
PMIG_CONTENT convValue;
|
|
COMPRESS_HANDLE compressedHandle;
|
|
INT_PTR appReply;
|
|
BOOL okSave = FALSE;
|
|
TRANSCOPY_ERROR transCopyError;
|
|
#ifdef DEBUG
|
|
PCTSTR nativeObjectName;
|
|
#endif
|
|
BOOL result = FALSE;
|
|
|
|
g_DirectCablePlatform = PLATFORM_SOURCE;
|
|
|
|
__try {
|
|
|
|
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
|
|
appInfo.Phase = MIG_TRANSPORT_PHASE;
|
|
appInfo.SubPhase = SUBPHASE_PREPARING;
|
|
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
|
|
|
|
ZeroMemory (&compressedHandle, sizeof (COMPRESS_HANDLE));
|
|
|
|
g_DirectCableTempPath = pDCCreateTemporaryDir ();
|
|
|
|
if (!g_DirectCableTempPath) {
|
|
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_DirectCableTempPath, 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 persistent objects
|
|
//
|
|
|
|
if (IsmEnumFirstPersistentObject (&objEnum)) {
|
|
do {
|
|
//
|
|
// For each object to be saved, do the appropriate
|
|
// data copy action
|
|
//
|
|
|
|
if (IsmCheckCancel()) {
|
|
__leave;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
nativeObjectName = IsmGetNativeObjectName (objEnum.ObjectTypeId, objEnum.ObjectName);
|
|
DEBUGMSG ((DBG_DIRECT, "Transporting: %s", nativeObjectName));
|
|
IsmReleaseMemory (nativeObjectName);
|
|
#endif
|
|
|
|
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 = pDCBuildDecoratedObject (objEnum.ObjectTypeId, objEnum.ObjectName);
|
|
|
|
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 (!pDCSaveContentInFile (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;
|
|
}
|
|
} else {
|
|
okSave = FALSE;
|
|
while (!okSave) {
|
|
if (!pDCSaveContentInMemory (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;
|
|
}
|
|
}
|
|
|
|
#ifndef UNICODE
|
|
if (convValue != (&value)) {
|
|
IsmFreeConvertedObjectContent (objEnum.ObjectTypeId, convValue);
|
|
}
|
|
#endif
|
|
IsmReleaseObject (&value);
|
|
|
|
pDCDestroyDecoratedObject (decoratedObject);
|
|
decoratedObject = NULL;
|
|
}
|
|
|
|
IsmTickProgressBar (g_PersistentSlice, 1);
|
|
|
|
if (IsmCheckCancel()) {
|
|
__leave;
|
|
}
|
|
|
|
} while (IsmEnumNextPersistentObject (&objEnum));
|
|
|
|
IsmAbortPersistentObjectEnum (&objEnum);
|
|
}
|
|
|
|
if (IsmCheckCancel()) {
|
|
__leave;
|
|
}
|
|
|
|
databaseFile = JoinPaths (g_DirectCableTempPath, S_TRANSPORT_DAT_FILE);
|
|
|
|
if (!MemDbSave (databaseFile)) {
|
|
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 (!pDCAddFileToImage (databaseFile, 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);
|
|
|
|
FreePathString (databaseFile);
|
|
databaseFile = NULL;
|
|
|
|
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;
|
|
}
|
|
|
|
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
|
|
appInfo.Phase = MIG_TRANSPORT_PHASE;
|
|
appInfo.SubPhase = SUBPHASE_CONNECTING1;
|
|
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
|
|
|
|
if (!pDCWriteAllImages ()) {
|
|
extraData.Error = ERRUSER_ERROR_CANTFINDDESTINATION;
|
|
extraData.ErrorArea = ERRUSER_AREA_SAVE;
|
|
extraData.ObjectTypeId = 0;
|
|
extraData.ObjectName = NULL;
|
|
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
|
|
__leave;
|
|
}
|
|
|
|
result = TRUE;
|
|
|
|
}
|
|
__finally {
|
|
|
|
PushError ();
|
|
|
|
CompressCleanupHandle (&compressedHandle);
|
|
|
|
if (databaseFile) {
|
|
FreePathString (databaseFile);
|
|
databaseFile = NULL;
|
|
}
|
|
|
|
PopError ();
|
|
}
|
|
|
|
PushError ();
|
|
|
|
pDCCleanupTempDir ();
|
|
|
|
PopError ();
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pDCReadAllImages (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_APPINFO appInfo;
|
|
PHEADER1 header1;
|
|
PHEADER2 header2;
|
|
BYTE buffer [BLOCKSIZE];
|
|
ULONGLONG totalImageSize = 0;
|
|
ULONGLONG totalImageRead = 0;
|
|
UINT numberOfFiles = 0;
|
|
UINT imageIdx = 1;
|
|
ULONGLONG imageSize = 0;
|
|
PCTSTR imageFile;
|
|
BOOL wrongVer = FALSE;
|
|
|
|
// Let's get the initial header
|
|
ZeroMemory (buffer, sizeof (buffer));
|
|
if (!pDCReceiveBlock (g_DirectCablePath, buffer)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
|
|
return FALSE;
|
|
}
|
|
|
|
header1 = (PHEADER1) buffer;
|
|
if (header1->Signature != DIRECTTR_SIG) {
|
|
wrongVer = TRUE;
|
|
}
|
|
|
|
header1->Signature = DIRECTTR_SIG;
|
|
if (!pDCSendBlock (g_DirectCablePath, buffer)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
|
|
return FALSE;
|
|
}
|
|
|
|
if (wrongVer) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
|
|
return FALSE;
|
|
}
|
|
|
|
numberOfFiles = header1->NumberOfFiles;
|
|
totalImageSize = header1->TotalImageSize;
|
|
|
|
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
|
|
appInfo.Phase = MIG_TRANSPORT_PHASE;
|
|
appInfo.SubPhase = SUBPHASE_NETPREPARING;
|
|
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
|
|
|
|
imageIdx = 1;
|
|
while (imageIdx <= numberOfFiles) {
|
|
imageFile = pDCGetImageFile (imageIdx);
|
|
|
|
// receive info about the current file
|
|
ZeroMemory (buffer, sizeof (buffer));
|
|
header2 = (PHEADER2) buffer;
|
|
|
|
if (!pDCReceiveBlock (g_DirectCablePath, buffer)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
|
|
return FALSE;
|
|
}
|
|
|
|
if (header2->FileNumber != imageIdx) {
|
|
wrongVer = TRUE;
|
|
}
|
|
|
|
header2->FileNumber = imageIdx;
|
|
if (!pDCSendBlock (g_DirectCablePath, buffer)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
|
|
return FALSE;
|
|
}
|
|
|
|
if (wrongVer) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
|
|
return FALSE;
|
|
}
|
|
|
|
// receive the actual file
|
|
if (!pDCReceiveFile (g_DirectCablePath, imageFile, header2->FileSize, &totalImageRead, totalImageSize)) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
|
|
return FALSE;
|
|
}
|
|
|
|
FreePathString (imageFile);
|
|
imageIdx ++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
PCTSTR
|
|
pDCGetNewFileName (
|
|
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
|
|
pDirectCableCallback (
|
|
IN PCTSTR FileToExtract,
|
|
IN LONGLONG FileSize,
|
|
OUT PBOOL ExtractFile,
|
|
IN OUT PCTSTR *NewFileName
|
|
)
|
|
{
|
|
LONGLONG numerator;
|
|
LONGLONG divisor;
|
|
LONGLONG tick;
|
|
UINT delta;
|
|
|
|
if (NewFileName) {
|
|
*NewFileName = pDCGetNewFileName (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
|
|
pDCUnpackAllFiles (
|
|
VOID
|
|
)
|
|
{
|
|
COMPRESS_HANDLE compressedHandle;
|
|
BOOL result = FALSE;
|
|
|
|
if (CompressOpenHandle (g_DirectCableTempPath, S_TRANSPORT_IMG_FILE, 1, &compressedHandle)) {
|
|
g_TotalFiles = compressedHandle.FilesStored;
|
|
if (CompressExtractAllFiles (g_DirectCableTempPath, &compressedHandle, pDirectCableCallback)) {
|
|
result = TRUE;
|
|
}
|
|
CompressCleanupHandle (&compressedHandle);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DirectCableTransportBeginApply (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_APPINFO appInfo;
|
|
ERRUSER_EXTRADATA extraData;
|
|
PCTSTR imageFile = NULL;
|
|
PCTSTR newImageFile = NULL;
|
|
BOOL result = FALSE;
|
|
|
|
g_DirectCablePlatform = PLATFORM_DESTINATION;
|
|
|
|
ZeroMemory (&extraData, sizeof (ERRUSER_EXTRADATA));
|
|
extraData.Error = ERRUSER_ERROR_UNKNOWN;
|
|
|
|
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
|
|
appInfo.Phase = MIG_TRANSPORT_PHASE;
|
|
appInfo.SubPhase = SUBPHASE_CONNECTING2;
|
|
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
|
|
|
|
__try {
|
|
|
|
g_DirectCableTempPath = pDCCreateTemporaryDir ();
|
|
|
|
if (!g_DirectCableTempPath) {
|
|
extraData.Error = ERRUSER_ERROR_CANTCREATETEMPDIR;
|
|
__leave;
|
|
}
|
|
|
|
if (!pDCReadAllImages ()) {
|
|
if (GetLastError () == ERROR_DISK_FULL) {
|
|
extraData.Error = ERRUSER_ERROR_DISKSPACE;
|
|
} else {
|
|
extraData.Error = ERRUSER_ERROR_CANTREADIMAGE;
|
|
}
|
|
__leave;
|
|
}
|
|
|
|
ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
|
|
appInfo.Phase = MIG_TRANSPORT_PHASE;
|
|
appInfo.SubPhase = SUBPHASE_UNCOMPRESSING;
|
|
IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
|
|
|
|
if (!pDCUnpackAllFiles ()) {
|
|
extraData.Error = ERRUSER_ERROR_CANTUNPACKIMAGE;
|
|
__leave;
|
|
}
|
|
|
|
newImageFile = pDCGetNewFileName (S_TRANSPORT_DAT_FILE);
|
|
|
|
imageFile = JoinPaths (g_DirectCableTempPath, newImageFile?newImageFile:S_TRANSPORT_DAT_FILE);
|
|
|
|
if (newImageFile) {
|
|
FreePathString (newImageFile);
|
|
newImageFile = NULL;
|
|
}
|
|
|
|
if (!MemDbLoad (imageFile)) {
|
|
extraData.Error = ERRUSER_ERROR_CANTREADIMAGE;
|
|
__leave;
|
|
}
|
|
|
|
result = TRUE;
|
|
}
|
|
__finally {
|
|
if (imageFile) {
|
|
FreePathString (imageFile);
|
|
imageFile = NULL;
|
|
}
|
|
}
|
|
|
|
if (!result) {
|
|
extraData.ErrorArea = ERRUSER_AREA_LOAD;
|
|
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
DirectCableTransportEndApply (
|
|
VOID
|
|
)
|
|
{
|
|
MYASSERT (g_DirectCablePlatform == PLATFORM_DESTINATION);
|
|
|
|
pDCCleanupTempDir ();
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DirectCableTransportAcquireObject (
|
|
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_DirectCablePlatform == PLATFORM_DESTINATION);
|
|
MYASSERT ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE);
|
|
|
|
decoratedObject = pDCBuildDecoratedObject (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 = pDCGetNewFileName (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 (g_DirectCableTempPath, 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 (g_DirectCableTempPath, 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
|
|
DirectCableTransportReleaseObject (
|
|
IN OUT PMIG_CONTENT ObjectContent
|
|
)
|
|
{
|
|
PALLOCSTATE allocState;
|
|
|
|
MYASSERT (g_DirectCablePlatform == 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;
|
|
}
|
|
|