|
|
/*++
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; }
|