windows-nt/Source/XPSP1/NT/windows/winstate/cobra/utils/compress/compress.c
2020-09-26 16:20:57 +08:00

1711 lines
59 KiB
C

#include "pch.h"
#include "compress.h"
#include "mrcicode.h"
#define COMPRESS_SIG 0x434F4D50 //COMP
#define COMPRESS_CONT_SIG 0x434F4D43 //COMC
#define COMPRESS_NEWFILE 0x434F4D46 //COMF
#define COMPRESS_BUFFER_SIZE 0x8000 //32K
#define COMPRESS_DEFAULT_SIZE 0x7FFFFFFF //2GB
BOOL g_ErrorMode = FALSE;
unsigned
CompressData(
IN CompressionType Type,
IN PBYTE Data,
IN unsigned DataSize,
OUT PBYTE CompressedData,
IN unsigned BufferSize
)
{
unsigned u;
switch(Type) {
case CompressNone:
default:
//
// Force caller to do something intelligent, such as
// writing directly out of the uncompressed buffer.
// This avoids an extra memory move.
//
u = (unsigned)(-1);
break;
case CompressMrci1:
u = Mrci1MaxCompress(Data,DataSize,CompressedData,BufferSize);
break;
case CompressMrci2:
u = Mrci2MaxCompress(Data,DataSize,CompressedData,BufferSize);
break;
}
return(u);
}
unsigned
DecompressData(
IN CompressionType Type,
IN PBYTE CompressedData,
IN unsigned CompressedDataSize,
OUT PBYTE DecompressedData,
IN unsigned BufferSize
)
{
unsigned u;
switch(Type) {
case CompressNone:
if(BufferSize >= CompressedDataSize) {
memmove(DecompressedData,CompressedData,CompressedDataSize);
u = CompressedDataSize;
} else {
u = (unsigned)(-1);
}
break;
case CompressMrci1:
u = Mrci1Decompress(CompressedData,CompressedDataSize,DecompressedData,BufferSize);
break;
case CompressMrci2:
u = Mrci2Decompress(CompressedData,CompressedDataSize,DecompressedData,BufferSize);
break;
default:
u = (unsigned)(-1);
break;
}
return(u);
}
VOID
CompressCleanupHandleA (
IN OUT PCOMPRESS_HANDLEA CompressedHandle
)
{
if (CompressedHandle) {
if (CompressedHandle->ReadBuffer) {
MemFree (g_hHeap, 0, CompressedHandle->ReadBuffer);
}
if (CompressedHandle->ExtraBuffer) {
MemFree (g_hHeap, 0, CompressedHandle->ExtraBuffer);
}
if (CompressedHandle->CompBuffer) {
MemFree (g_hHeap, 0, CompressedHandle->CompBuffer);
}
if (CompressedHandle->StorePath) {
FreePathStringA (CompressedHandle->StorePath);
}
if (CompressedHandle->MainFilePattern) {
FreePathStringA (CompressedHandle->MainFilePattern);
}
if ((CompressedHandle->CurrFileHandle) &&
(CompressedHandle->CurrFileHandle != INVALID_HANDLE_VALUE)
) {
CloseHandle (CompressedHandle->CurrFileHandle);
}
ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEA));
}
}
VOID
CompressCleanupHandleW (
IN OUT PCOMPRESS_HANDLEW CompressedHandle
)
{
if (CompressedHandle) {
if (CompressedHandle->ReadBuffer) {
MemFree (g_hHeap, 0, CompressedHandle->ReadBuffer);
}
if (CompressedHandle->ExtraBuffer) {
MemFree (g_hHeap, 0, CompressedHandle->ExtraBuffer);
}
if (CompressedHandle->CompBuffer) {
MemFree (g_hHeap, 0, CompressedHandle->CompBuffer);
}
if (CompressedHandle->StorePath) {
FreePathStringW (CompressedHandle->StorePath);
}
if (CompressedHandle->MainFilePattern) {
FreePathStringW (CompressedHandle->MainFilePattern);
}
if ((CompressedHandle->CurrFileHandle) &&
(CompressedHandle->CurrFileHandle != INVALID_HANDLE_VALUE)
) {
CloseHandle (CompressedHandle->CurrFileHandle);
}
ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEW));
}
}
BOOL
CompressCreateHandleA (
IN PCSTR StorePath,
IN PCSTR MainFilePattern,
IN UINT StartIndex,
IN LONGLONG MaxFileSize,
OUT PCOMPRESS_HANDLEA CompressedHandle
)
{
CHAR currFile [MAX_PATH];
PCSTR currFullPath = NULL;
DWORD signature = COMPRESS_SIG;
BOOL result = FALSE;
__try {
ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEA));
if (StartIndex == 0) {
CompressedHandle->CurrFileIndex = 1;
} else {
CompressedHandle->CurrFileIndex = StartIndex;
}
CompressedHandle->FirstFileIndex = CompressedHandle->CurrFileIndex;
if (MaxFileSize == 0) {
CompressedHandle->MaxFileSize = COMPRESS_DEFAULT_SIZE;
} else {
CompressedHandle->MaxFileSize = MaxFileSize;
}
CompressedHandle->StorePath = DuplicatePathStringA (StorePath, 0);
if (!CompressedHandle->StorePath) {
__leave;
}
CompressedHandle->MainFilePattern = DuplicatePathStringA (MainFilePattern, 0);
if (!CompressedHandle->MainFilePattern) {
__leave;
}
wsprintfA (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
currFullPath = JoinPathsA (CompressedHandle->StorePath, currFile);
CompressedHandle->CurrFileHandle = BfCreateFileA (currFullPath);
if ((CompressedHandle->CurrFileHandle == NULL) ||
(CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
FreePathStringA (currFullPath);
currFullPath = NULL;
// write the signature
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
// reserve room for writing how many files we stored
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
CompressedHandle->ReadBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!CompressedHandle->ReadBuffer) {
__leave;
}
CompressedHandle->CompBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!CompressedHandle->CompBuffer) {
__leave;
}
CompressedHandle->ExtraBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!CompressedHandle->ExtraBuffer) {
__leave;
}
result = TRUE;
}
__finally {
PushError ();
if (currFullPath) {
FreePathStringA (currFullPath);
currFullPath = NULL;
}
if (!result) {
CompressCleanupHandleA (CompressedHandle);
}
PopError ();
}
return result;
}
BOOL
CompressCreateHandleW (
IN PCWSTR StorePath,
IN PCWSTR MainFilePattern,
IN UINT StartIndex,
IN LONGLONG MaxFileSize,
OUT PCOMPRESS_HANDLEW CompressedHandle
)
{
WCHAR currFile [MAX_PATH];
PCWSTR currFullPath = NULL;
DWORD signature = COMPRESS_SIG;
BOOL result = FALSE;
__try {
ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEW));
if (StartIndex == 0) {
CompressedHandle->CurrFileIndex = 1;
} else {
CompressedHandle->CurrFileIndex = StartIndex;
}
CompressedHandle->FirstFileIndex = CompressedHandle->CurrFileIndex;
if (MaxFileSize == 0) {
CompressedHandle->MaxFileSize = COMPRESS_DEFAULT_SIZE;
} else {
CompressedHandle->MaxFileSize = MaxFileSize;
}
CompressedHandle->StorePath = DuplicatePathStringW (StorePath, 0);
if (!CompressedHandle->StorePath) {
__leave;
}
CompressedHandle->MainFilePattern = DuplicatePathStringW (MainFilePattern, 0);
if (!CompressedHandle->MainFilePattern) {
__leave;
}
wsprintfW (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
currFullPath = JoinPathsW (CompressedHandle->StorePath, currFile);
CompressedHandle->CurrFileHandle = BfCreateFileW (currFullPath);
if ((CompressedHandle->CurrFileHandle == NULL) ||
(CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
FreePathStringW (currFullPath);
currFullPath = NULL;
// write the signature
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
// reserve room for writing how many files we stored
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
CompressedHandle->ReadBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!CompressedHandle->ReadBuffer) {
__leave;
}
CompressedHandle->CompBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!CompressedHandle->CompBuffer) {
__leave;
}
CompressedHandle->ExtraBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!CompressedHandle->ExtraBuffer) {
__leave;
}
result = TRUE;
}
__finally {
PushError ();
if (currFullPath) {
FreePathStringW (currFullPath);
currFullPath = NULL;
}
if (!result) {
CompressCleanupHandleW (CompressedHandle);
}
PopError ();
}
return result;
}
BOOL
pPrepareNextFileA (
IN OUT PCOMPRESS_HANDLEA CompressedHandle,
IN BOOL ReadOnly
)
{
CHAR currFile [MAX_PATH];
PCSTR currFullPath = NULL;
DWORD signature = COMPRESS_SIG;
LONGLONG contSig = COMPRESS_CONT_SIG;
BOOL result = FALSE;
__try {
if ((CompressedHandle->CurrFileHandle == NULL) ||
(CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
if (!CloseHandle (CompressedHandle->CurrFileHandle)) {
__leave;
}
CompressedHandle->CurrFileSize = 0;
CompressedHandle->CurrFileIndex ++;
wsprintfA (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
currFullPath = JoinPathsA (CompressedHandle->StorePath, currFile);
if (ReadOnly) {
CompressedHandle->CurrFileHandle = BfOpenReadFileA (currFullPath);
} else {
CompressedHandle->CurrFileHandle = BfCreateFileA (currFullPath);
}
if ((CompressedHandle->CurrFileHandle == NULL) ||
(CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
FreePathStringA (currFullPath);
currFullPath = NULL;
if (ReadOnly) {
// read the signature
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
if (signature != COMPRESS_SIG) {
SetLastError (ERROR_INVALID_DATA);
__leave;
}
// read special continuation signature
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&contSig), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
if (CompressedHandle->CurrFileIndex > 1) {
if (contSig != COMPRESS_CONT_SIG) {
SetLastError (ERROR_INVALID_DATA);
__leave;
}
}
} else {
// write the signature
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
// write special continuation signature
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&contSig), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
}
result = TRUE;
}
__finally {
PushError ();
if (currFullPath) {
FreePathStringA (currFullPath);
currFullPath = NULL;
}
PopError ();
}
return result;
}
BOOL
pPrepareNextFileW (
IN OUT PCOMPRESS_HANDLEW CompressedHandle,
IN BOOL ReadOnly
)
{
WCHAR currFile [MAX_PATH];
PCWSTR currFullPath = NULL;
DWORD signature = COMPRESS_SIG;
LONGLONG contSig = COMPRESS_CONT_SIG;
BOOL result = FALSE;
__try {
if ((CompressedHandle->CurrFileHandle == NULL) ||
(CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
if (!CloseHandle (CompressedHandle->CurrFileHandle)) {
__leave;
}
CompressedHandle->CurrFileSize = 0;
CompressedHandle->CurrFileIndex ++;
wsprintfW (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
currFullPath = JoinPathsW (CompressedHandle->StorePath, currFile);
if (ReadOnly) {
CompressedHandle->CurrFileHandle = BfOpenReadFileW (currFullPath);
} else {
CompressedHandle->CurrFileHandle = BfCreateFileW (currFullPath);
}
if ((CompressedHandle->CurrFileHandle == NULL) ||
(CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
FreePathStringW (currFullPath);
currFullPath = NULL;
if (ReadOnly) {
// read the signature
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
if (signature != COMPRESS_SIG) {
SetLastError (ERROR_INVALID_DATA);
__leave;
}
// read special continuation signature
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&contSig), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
if (CompressedHandle->CurrFileIndex > 1) {
if (contSig != COMPRESS_CONT_SIG) {
SetLastError (ERROR_INVALID_DATA);
__leave;
}
}
} else {
// write the signature
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
// write special continuation signature
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&contSig), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
}
result = TRUE;
}
__finally {
PushError ();
if (currFullPath) {
FreePathStringW (currFullPath);
currFullPath = NULL;
}
PopError ();
}
return result;
}
BOOL
pDeleteNextFilesA (
IN PCOMPRESS_HANDLEA CompressedHandle,
IN UINT SavedIndex
)
{
CHAR currFile [MAX_PATH];
PCSTR currFullPath = NULL;
while (TRUE) {
wsprintfA (currFile, CompressedHandle->MainFilePattern, SavedIndex);
currFullPath = JoinPathsA (CompressedHandle->StorePath, currFile);
if (currFullPath) {
if (DoesFileExistA (currFullPath)) {
DeleteFileA (currFullPath);
} else {
break;
}
FreePathStringA (currFullPath);
currFullPath = NULL;
}
SavedIndex ++;
}
if (currFullPath) {
FreePathStringA (currFullPath);
currFullPath = NULL;
}
return TRUE;
}
BOOL
pDeleteNextFilesW (
IN PCOMPRESS_HANDLEW CompressedHandle,
IN UINT SavedIndex
)
{
WCHAR currFile [MAX_PATH];
PCWSTR currFullPath = NULL;
while (TRUE) {
wsprintfW (currFile, CompressedHandle->MainFilePattern, SavedIndex);
currFullPath = JoinPathsW (CompressedHandle->StorePath, currFile);
if (currFullPath) {
if (DoesFileExistW (currFullPath)) {
DeleteFileW (currFullPath);
} else {
break;
}
FreePathStringW (currFullPath);
currFullPath = NULL;
}
SavedIndex ++;
}
if (currFullPath) {
FreePathStringW (currFullPath);
currFullPath = NULL;
}
return TRUE;
}
BOOL
CompressAddFileToHandleA (
IN PCSTR FileName,
IN PCSTR StoredName,
IN OUT PCOMPRESS_HANDLEA CompressedHandle
)
{
HANDLE fileHandle = INVALID_HANDLE_VALUE;
LONGLONG fileSize;
DWORD bytesRead;
DWORD bytesWritten;
DWORD bytesComp;
DWORD bytesUncomp;
DWORD signature = COMPRESS_NEWFILE;
DWORD fileNameSize;
DWORD headerSize;
USHORT compType = 0;
USHORT compSize = 0;
PCWSTR unicodeName = NULL;
UINT savedIndex = 0;
LARGE_INTEGER savedSize;
BOOL result = FALSE;
__try {
// save the state of the compress handle
savedIndex = CompressedHandle->CurrFileIndex;
savedSize.QuadPart = CompressedHandle->CurrFileSize;
fileSize = BfGetFileSizeA (FileName);
fileHandle = BfOpenReadFileA (FileName);
if ((fileHandle == NULL) ||
(fileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
// handle UNICODE files
unicodeName = ConvertAtoW (StoredName);
if (!unicodeName) {
__leave;
}
fileNameSize = SizeOfStringW (unicodeName);
headerSize = sizeof (DWORD) + sizeof (LONGLONG) + sizeof (DWORD) + fileNameSize;
if (CompressedHandle->CurrFileSize + headerSize > CompressedHandle->MaxFileSize) {
if (!pPrepareNextFileA (CompressedHandle, FALSE)) {
__leave;
}
}
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileSize), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileNameSize), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(unicodeName), fileNameSize)) {
__leave;
}
CompressedHandle->CurrFileSize += fileNameSize;
FreeConvertedStr (unicodeName);
unicodeName = NULL;
while (fileSize) {
ZeroMemory (CompressedHandle->ReadBuffer, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
ZeroMemory (CompressedHandle->CompBuffer, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!ReadFile (fileHandle, CompressedHandle->ReadBuffer + 2 * sizeof (USHORT), COMPRESS_BUFFER_SIZE, &bytesRead, NULL)) {
__leave;
}
if (bytesRead == 0)
{
// Somehow the file points is beyond the end of the file. Probably file in use.
SetLastError(ERROR_SHARING_VIOLATION);
__leave;
}
bytesComp = CompressData (
CompressMrci1,
CompressedHandle->ReadBuffer + 2 * sizeof (USHORT),
bytesRead,
CompressedHandle->CompBuffer + 2 * sizeof (USHORT),
COMPRESS_BUFFER_SIZE
);
if (bytesComp < bytesRead) {
bytesUncomp = DecompressData (
CompressMrci1,
CompressedHandle->CompBuffer + 2 * sizeof (USHORT),
bytesComp,
CompressedHandle->ExtraBuffer,
COMPRESS_BUFFER_SIZE
);
if (bytesUncomp != bytesRead) {
bytesComp = COMPRESS_BUFFER_SIZE;
} else {
if (!TestBuffer (CompressedHandle->ReadBuffer + 2 * sizeof (USHORT), CompressedHandle->ExtraBuffer, bytesRead)) {
bytesComp = COMPRESS_BUFFER_SIZE;
}
}
}
if (bytesComp >= bytesRead) {
compType = CompressNone;
compSize = (USHORT)bytesRead;
CopyMemory (CompressedHandle->ReadBuffer, &compType, sizeof (USHORT));
CopyMemory (CompressedHandle->ReadBuffer + sizeof (USHORT), &compSize, sizeof (USHORT));
compSize += (2 * sizeof (USHORT));
if (CompressedHandle->CurrFileSize + compSize > CompressedHandle->MaxFileSize) {
if (!pPrepareNextFileA (CompressedHandle, FALSE)) {
__leave;
}
}
if (!BfWriteFile (CompressedHandle->CurrFileHandle, CompressedHandle->ReadBuffer, compSize)) {
__leave;
}
CompressedHandle->CurrFileSize += compSize;
} else {
compType = CompressMrci1;
compSize = (USHORT)bytesComp;
CopyMemory (CompressedHandle->CompBuffer, &compType, sizeof (USHORT));
CopyMemory (CompressedHandle->CompBuffer + sizeof (USHORT), &compSize, sizeof (USHORT));
compSize += (2 * sizeof (USHORT));
if (CompressedHandle->CurrFileSize + compSize > CompressedHandle->MaxFileSize) {
if (!pPrepareNextFileA (CompressedHandle, FALSE)) {
__leave;
}
}
if (!BfWriteFile (CompressedHandle->CurrFileHandle, CompressedHandle->CompBuffer, compSize)) {
__leave;
}
CompressedHandle->CurrFileSize += compSize;
}
fileSize -= bytesRead;
}
CompressedHandle->FilesStored ++;
result = TRUE;
}
__finally {
PushError ();
if (unicodeName) {
FreeConvertedStr (unicodeName);
unicodeName = NULL;
}
if (fileHandle != INVALID_HANDLE_VALUE) {
CloseHandle (fileHandle);
}
if (!result) {
// let's restore the state of the compress handle
if (savedIndex == CompressedHandle->CurrFileIndex) {
if (savedSize.QuadPart != CompressedHandle->CurrFileSize) {
SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
SetEndOfFile (CompressedHandle->CurrFileHandle);
CompressedHandle->CurrFileSize = savedSize.QuadPart;
}
} else {
CompressedHandle->CurrFileIndex = savedIndex - 1;
pPrepareNextFileA (CompressedHandle, TRUE);
SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
SetEndOfFile (CompressedHandle->CurrFileHandle);
CompressedHandle->CurrFileSize = savedSize.QuadPart;
pDeleteNextFilesA (CompressedHandle, savedIndex);
}
}
PopError ();
}
return result;
}
BOOL
CompressAddFileToHandleW (
IN PCWSTR FileName,
IN PCWSTR StoredName,
IN OUT PCOMPRESS_HANDLEW CompressedHandle
)
{
HANDLE fileHandle = INVALID_HANDLE_VALUE;
LONGLONG fileSize;
DWORD bytesRead;
DWORD bytesWritten;
DWORD bytesComp;
DWORD bytesUncomp;
DWORD signature = COMPRESS_NEWFILE;
DWORD fileNameSize;
DWORD headerSize;
USHORT compType = 0;
USHORT compSize = 0;
UINT savedIndex = 0;
LARGE_INTEGER savedSize;
BOOL result = FALSE;
__try {
// save the state of the compress handle
savedIndex = CompressedHandle->CurrFileIndex;
savedSize.QuadPart = CompressedHandle->CurrFileSize;
fileSize = BfGetFileSizeW (FileName);
fileHandle = BfOpenReadFileW (FileName);
if ((fileHandle == NULL) ||
(fileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
fileNameSize = SizeOfStringW (StoredName);
headerSize = sizeof (DWORD) + sizeof (LONGLONG) + sizeof (DWORD) + fileNameSize;
if (CompressedHandle->CurrFileSize + headerSize > CompressedHandle->MaxFileSize) {
if (!pPrepareNextFileW (CompressedHandle, FALSE)) {
__leave;
}
}
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileSize), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileNameSize), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(StoredName), fileNameSize)) {
__leave;
}
CompressedHandle->CurrFileSize += fileNameSize;
while (fileSize) {
ZeroMemory (CompressedHandle->ReadBuffer, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
ZeroMemory (CompressedHandle->CompBuffer, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!ReadFile (fileHandle, CompressedHandle->ReadBuffer + 2 * sizeof (USHORT), COMPRESS_BUFFER_SIZE, &bytesRead, NULL)) {
__leave;
}
if (bytesRead == 0)
{
// Somehow the file points is beyond the end of the file. Probably file in use.
SetLastError(ERROR_SHARING_VIOLATION);
__leave;
}
bytesComp = CompressData (
CompressMrci1,
CompressedHandle->ReadBuffer + 2 * sizeof (USHORT),
bytesRead,
CompressedHandle->CompBuffer + 2 * sizeof (USHORT),
COMPRESS_BUFFER_SIZE
);
if (bytesComp < bytesRead) {
bytesUncomp = DecompressData (
CompressMrci1,
CompressedHandle->CompBuffer + 2 * sizeof (USHORT),
bytesComp,
CompressedHandle->ExtraBuffer,
COMPRESS_BUFFER_SIZE
);
if (bytesUncomp != bytesRead) {
bytesComp = COMPRESS_BUFFER_SIZE;
} else {
if (!TestBuffer (CompressedHandle->ReadBuffer + 2 * sizeof (USHORT), CompressedHandle->ExtraBuffer, bytesRead)) {
bytesComp = COMPRESS_BUFFER_SIZE;
}
}
}
if (bytesComp >= bytesRead) {
compType = CompressNone;
compSize = (USHORT)bytesRead;
CopyMemory (CompressedHandle->ReadBuffer, &compType, sizeof (USHORT));
CopyMemory (CompressedHandle->ReadBuffer + sizeof (USHORT), &compSize, sizeof (USHORT));
compSize += (2 * sizeof (USHORT));
if (CompressedHandle->CurrFileSize + compSize > CompressedHandle->MaxFileSize) {
if (!pPrepareNextFileW (CompressedHandle, FALSE)) {
__leave;
}
}
if (!BfWriteFile (CompressedHandle->CurrFileHandle, CompressedHandle->ReadBuffer, compSize)) {
__leave;
}
CompressedHandle->CurrFileSize += compSize;
} else {
compType = CompressMrci1;
compSize = (USHORT)bytesComp;
CopyMemory (CompressedHandle->CompBuffer, &compType, sizeof (USHORT));
CopyMemory (CompressedHandle->CompBuffer + sizeof (USHORT), &compSize, sizeof (USHORT));
compSize += (2 * sizeof (USHORT));
if (CompressedHandle->CurrFileSize + compSize > CompressedHandle->MaxFileSize) {
if (!pPrepareNextFileW (CompressedHandle, FALSE)) {
__leave;
}
}
if (!BfWriteFile (CompressedHandle->CurrFileHandle, CompressedHandle->CompBuffer, compSize)) {
__leave;
}
CompressedHandle->CurrFileSize += compSize;
}
fileSize -= bytesRead;
}
CompressedHandle->FilesStored ++;
result = TRUE;
}
__finally {
PushError ();
if (fileHandle != INVALID_HANDLE_VALUE) {
CloseHandle (fileHandle);
}
if (!result) {
// let's restore the state of the compress handle
if (savedIndex == CompressedHandle->CurrFileIndex) {
if (savedSize.QuadPart != CompressedHandle->CurrFileSize) {
SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
SetEndOfFile (CompressedHandle->CurrFileHandle);
CompressedHandle->CurrFileSize = savedSize.QuadPart;
}
} else {
CompressedHandle->CurrFileIndex = savedIndex - 1;
pPrepareNextFileW (CompressedHandle, TRUE);
SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
SetEndOfFile (CompressedHandle->CurrFileHandle);
CompressedHandle->CurrFileSize = savedSize.QuadPart;
pDeleteNextFilesW (CompressedHandle, savedIndex);
}
}
PopError ();
}
return result;
}
BOOL
CompressFlushAndCloseHandleA (
IN OUT PCOMPRESS_HANDLEA CompressedHandle
)
{
CHAR currFile [MAX_PATH];
PCSTR currFullPath = NULL;
DWORD signature = COMPRESS_SIG;
BOOL result = FALSE;
__try {
if ((CompressedHandle) &&
(CompressedHandle->CurrFileHandle) &&
(CompressedHandle->CurrFileHandle != INVALID_HANDLE_VALUE)
) {
result = CloseHandle (CompressedHandle->CurrFileHandle);
CompressedHandle->CurrFileHandle = NULL;
if (result) {
// write the total number of files compressed into the first file
result = FALSE;
wsprintfA (currFile, CompressedHandle->MainFilePattern, CompressedHandle->FirstFileIndex);
currFullPath = JoinPathsA (CompressedHandle->StorePath, currFile);
CompressedHandle->CurrFileHandle = BfOpenFileA (currFullPath);
if ((CompressedHandle->CurrFileHandle == NULL) ||
(CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
FreePathStringA (currFullPath);
currFullPath = NULL;
// write again the signature
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
// write number of files compressed
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
__leave;
}
result = CloseHandle (CompressedHandle->CurrFileHandle);
CompressedHandle->CurrFileHandle = NULL;
}
}
}
__finally {
PushError ();
if (currFullPath) {
FreePathStringA (currFullPath);
currFullPath = NULL;
}
CompressCleanupHandleA (CompressedHandle);
PopError ();
}
return result;
}
BOOL
CompressFlushAndCloseHandleW (
IN OUT PCOMPRESS_HANDLEW CompressedHandle
)
{
WCHAR currFile [MAX_PATH];
PCWSTR currFullPath = NULL;
DWORD signature = COMPRESS_SIG;
BOOL result = FALSE;
__try {
if ((CompressedHandle) &&
(CompressedHandle->CurrFileHandle) &&
(CompressedHandle->CurrFileHandle != INVALID_HANDLE_VALUE)
) {
result = CloseHandle (CompressedHandle->CurrFileHandle);
CompressedHandle->CurrFileHandle = NULL;
if (result) {
// write the total number of files compressed into the first file
result = FALSE;
wsprintfW (currFile, CompressedHandle->MainFilePattern, CompressedHandle->FirstFileIndex);
currFullPath = JoinPathsW (CompressedHandle->StorePath, currFile);
CompressedHandle->CurrFileHandle = BfOpenFileW (currFullPath);
if ((CompressedHandle->CurrFileHandle == NULL) ||
(CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
FreePathStringW (currFullPath);
currFullPath = NULL;
// write again the signature
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
// write number of files compressed
if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
__leave;
}
result = CloseHandle (CompressedHandle->CurrFileHandle);
CompressedHandle->CurrFileHandle = NULL;
}
}
}
__finally {
PushError ();
if (currFullPath) {
FreePathStringW (currFullPath);
currFullPath = NULL;
}
CompressCleanupHandleW (CompressedHandle);
PopError ();
}
return result;
}
BOOL
CompressOpenHandleA (
IN PCSTR StorePath,
IN PCSTR MainFilePattern,
IN UINT StartIndex,
OUT PCOMPRESS_HANDLEA CompressedHandle
)
{
CHAR currFile [MAX_PATH];
PCSTR currFullPath = NULL;
DWORD signature = 0;
BOOL result = FALSE;
__try {
ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEA));
if (StartIndex == 0) {
CompressedHandle->CurrFileIndex = 1;
} else {
CompressedHandle->CurrFileIndex = StartIndex;
}
CompressedHandle->FirstFileIndex = CompressedHandle->CurrFileIndex;
CompressedHandle->StorePath = DuplicatePathStringA (StorePath, 0);
if (!CompressedHandle->StorePath) {
__leave;
}
CompressedHandle->MainFilePattern = DuplicatePathStringA (MainFilePattern, 0);
if (!CompressedHandle->MainFilePattern) {
__leave;
}
wsprintfA (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
currFullPath = JoinPathsA (CompressedHandle->StorePath, currFile);
CompressedHandle->CurrFileHandle = BfOpenReadFileA (currFullPath);
if ((CompressedHandle->CurrFileHandle == NULL) ||
(CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
FreePathStringA (currFullPath);
currFullPath = NULL;
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
if (signature != COMPRESS_SIG) {
SetLastError (ERROR_INVALID_DATA);
__leave;
}
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
CompressedHandle->ReadBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!CompressedHandle->ReadBuffer) {
__leave;
}
CompressedHandle->CompBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!CompressedHandle->CompBuffer) {
__leave;
}
result = TRUE;
}
__finally {
PushError ();
if (currFullPath) {
FreePathStringA (currFullPath);
currFullPath = NULL;
}
if (!result) {
CompressCleanupHandleA (CompressedHandle);
}
PopError ();
}
return result;
}
BOOL
CompressOpenHandleW (
IN PCWSTR StorePath,
IN PCWSTR MainFilePattern,
IN UINT StartIndex,
OUT PCOMPRESS_HANDLEW CompressedHandle
)
{
WCHAR currFile [MAX_PATH];
PCWSTR currFullPath = NULL;
DWORD signature = 0;
BOOL result = FALSE;
__try {
ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEW));
if (StartIndex == 0) {
CompressedHandle->CurrFileIndex = 1;
} else {
CompressedHandle->CurrFileIndex = StartIndex;
}
CompressedHandle->FirstFileIndex = CompressedHandle->CurrFileIndex;
CompressedHandle->StorePath = DuplicatePathStringW (StorePath, 0);
if (!CompressedHandle->StorePath) {
__leave;
}
CompressedHandle->MainFilePattern = DuplicatePathStringW (MainFilePattern, 0);
if (!CompressedHandle->MainFilePattern) {
__leave;
}
wsprintfW (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
currFullPath = JoinPathsW (CompressedHandle->StorePath, currFile);
CompressedHandle->CurrFileHandle = BfOpenReadFileW (currFullPath);
if ((CompressedHandle->CurrFileHandle == NULL) ||
(CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
FreePathStringW (currFullPath);
currFullPath = NULL;
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
if (signature != COMPRESS_SIG) {
SetLastError (ERROR_INVALID_DATA);
__leave;
}
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
CompressedHandle->ReadBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!CompressedHandle->ReadBuffer) {
__leave;
}
CompressedHandle->CompBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
if (!CompressedHandle->CompBuffer) {
__leave;
}
result = TRUE;
}
__finally {
PushError ();
if (currFullPath) {
FreePathStringW (currFullPath);
currFullPath = NULL;
}
if (!result) {
CompressCleanupHandleW (CompressedHandle);
}
PopError ();
}
return result;
}
BOOL
CompressExtractAllFilesA (
IN PCSTR ExtractPath,
IN OUT PCOMPRESS_HANDLEA CompressedHandle,
IN PCOMPRESSNOTIFICATIONA CompressNotification OPTIONAL
)
{
DWORD signature;
LONGLONG fileSize;
LONGLONG fileSizeRead;
DWORD fileNameSize;
PCWSTR storedName = NULL;
PCSTR storedNameA = NULL;
PCSTR extractPath = NULL;
PCSTR newFileName = NULL;
BOOL extractFile = TRUE;
HANDLE extractHandle = NULL;
USHORT compType = 0;
USHORT compSize = 0;
DWORD bytesComp;
LARGE_INTEGER savedSize;
BOOL result = FALSE;
__try {
for (;;) {
// read the header for this file
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
// It is possible that we continue onto the next file, let's try that.
if (!pPrepareNextFileA (CompressedHandle, TRUE)) {
result = TRUE;
__leave;
}
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
if (signature != COMPRESS_NEWFILE) {
SetLastError (ERROR_INVALID_DATA);
__leave;
}
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileSize), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
fileSizeRead = 0;
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileNameSize), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
storedName = MemAlloc (g_hHeap, 0, fileNameSize);
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(storedName), fileNameSize)) {
__leave;
}
CompressedHandle->CurrFileSize += fileNameSize;
storedNameA = ConvertWtoA (storedName);
if (!storedNameA) {
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
__leave;
}
extractPath = JoinPathsA (ExtractPath, storedNameA);
if (!extractPath) {
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
__leave;
}
extractFile = TRUE;
newFileName = NULL;
if (CompressNotification) {
if (!CompressNotification (extractPath, fileSize, &extractFile, &newFileName)) {
__leave;
}
}
if (extractFile) {
if (newFileName) {
// let's make sure that the directory exists
BfCreateDirectoryExA (newFileName, FALSE);
}
extractHandle = BfCreateFileA (newFileName?newFileName:extractPath);
if ((extractHandle == NULL) ||
(extractHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
} else {
extractHandle = NULL;
}
if (newFileName) {
FreePathStringA (newFileName);
newFileName = NULL;
}
FreePathStringA (extractPath);
extractPath = NULL;
MemFree (g_hHeap, 0, storedName);
storedName = NULL;
FreeConvertedStr (storedNameA);
storedNameA = NULL;
if (fileSize > 0) {
if (!extractFile && g_ErrorMode) {
for (;;) {
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
// It is possible that we continue onto the next file, let's try that.
if (!pPrepareNextFileA (CompressedHandle, TRUE)) {
// we might be at the end of the compressed file, there are no other files here
result = TRUE;
__leave;
}
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
__leave;
}
}
CompressedHandle->CurrFileSize += sizeof (USHORT);
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compSize), sizeof (USHORT))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (USHORT);
// let's try to see if we just read a new file signature
*((PUSHORT)(&signature) + 0) = compType;
*((PUSHORT)(&signature) + 1) = compSize;
if (signature == COMPRESS_NEWFILE) {
// this is a new file
CompressedHandle->CurrFileSize -= sizeof (USHORT);
CompressedHandle->CurrFileSize -= sizeof (USHORT);
// rewind the file current pointer;
savedSize.QuadPart = CompressedHandle->CurrFileSize;
SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
// we are done with the current file
break;
} else {
// Let's advance the file pointer
if (SetFilePointer (CompressedHandle->CurrFileHandle, compSize, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER) {
__leave;
}
CompressedHandle->CurrFileSize += compSize;
}
}
} else {
for (;;) {
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
// It is possible that we continue onto the next file, let's try that.
if (!pPrepareNextFileA (CompressedHandle, TRUE)) {
__leave;
}
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
__leave;
}
}
CompressedHandle->CurrFileSize += sizeof (USHORT);
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compSize), sizeof (USHORT))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (USHORT);
if (!BfReadFile (CompressedHandle->CurrFileHandle, CompressedHandle->CompBuffer, compSize)) {
__leave;
}
CompressedHandle->CurrFileSize += compSize;
if (compType == CompressNone) {
if (extractFile) {
if (!BfWriteFile (extractHandle, CompressedHandle->CompBuffer, compSize)) {
__leave;
}
}
fileSizeRead += compSize;
} else {
bytesComp = DecompressData (
compType,
CompressedHandle->CompBuffer,
compSize,
CompressedHandle->ReadBuffer,
COMPRESS_BUFFER_SIZE
);
if (bytesComp > COMPRESS_BUFFER_SIZE) {
SetLastError (ERROR_INVALID_DATA);
__leave;
}
if (extractFile) {
if (!BfWriteFile (extractHandle, CompressedHandle->ReadBuffer, bytesComp)) {
__leave;
}
}
fileSizeRead += bytesComp;
}
if (fileSizeRead == fileSize) {
// this file is done, let's go to the next one
break;
}
}
}
}
if (extractHandle) {
CloseHandle (extractHandle);
extractHandle = NULL;
}
}
}
__finally {
if (storedName != NULL) {
MemFree (g_hHeap, 0, storedName);
storedName = NULL;
}
if (storedNameA != NULL) {
FreeConvertedStr (storedNameA);
storedNameA = NULL;
}
if (newFileName != NULL) {
FreePathStringA (newFileName);
newFileName = NULL;
}
if (extractPath != NULL) {
FreePathStringA (extractPath);
extractPath = NULL;
}
if ((extractHandle != NULL) &&
(extractHandle != INVALID_HANDLE_VALUE)
) {
CloseHandle (extractHandle);
extractHandle = NULL;
}
}
return result;
}
BOOL
CompressExtractAllFilesW (
IN PCWSTR ExtractPath,
IN OUT PCOMPRESS_HANDLEW CompressedHandle,
IN PCOMPRESSNOTIFICATIONW CompressNotification OPTIONAL
)
{
DWORD signature;
LONGLONG fileSize;
LONGLONG fileSizeRead;
DWORD fileNameSize;
PCWSTR storedName = NULL;
PCWSTR extractPath = NULL;
PCWSTR newFileName = NULL;
BOOL extractFile = TRUE;
HANDLE extractHandle = NULL;
USHORT compType = 0;
USHORT compSize = 0;
DWORD bytesComp;
LARGE_INTEGER savedSize;
BOOL result = FALSE;
__try {
for (;;) {
// read the header for this file
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
// It is possible that we continue onto the next file, let's try that.
if (!pPrepareNextFileW (CompressedHandle, TRUE)) {
result = TRUE;
__leave;
}
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
__leave;
}
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
if (signature != COMPRESS_NEWFILE) {
SetLastError (ERROR_INVALID_DATA);
__leave;
}
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileSize), sizeof (LONGLONG))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (LONGLONG);
fileSizeRead = 0;
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileNameSize), sizeof (DWORD))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (DWORD);
storedName = MemAlloc (g_hHeap, 0, fileNameSize);
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(storedName), fileNameSize)) {
__leave;
}
CompressedHandle->CurrFileSize += fileNameSize;
extractPath = JoinPathsW (ExtractPath, storedName);
if (!extractPath) {
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
__leave;
}
extractFile = TRUE;
newFileName = NULL;
if (CompressNotification) {
if (!CompressNotification (extractPath, fileSize, &extractFile, &newFileName)) {
__leave;
}
}
if (extractFile) {
if (newFileName) {
// let's make sure that the directory exists
BfCreateDirectoryExW (newFileName, FALSE);
}
extractHandle = BfCreateFileW (newFileName?newFileName:extractPath);
if ((extractHandle == NULL) ||
(extractHandle == INVALID_HANDLE_VALUE)
) {
__leave;
}
} else {
extractHandle = NULL;
}
if (newFileName) {
FreePathStringW (newFileName);
newFileName = NULL;
}
FreePathStringW (extractPath);
extractPath = NULL;
MemFree (g_hHeap, 0, storedName);
storedName = NULL;
if (fileSize) {
if (!extractFile && g_ErrorMode) {
for (;;) {
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
// It is possible that we continue onto the next file, let's try that.
if (!pPrepareNextFileW (CompressedHandle, TRUE)) {
// we might be at the end of the compressed file, there are no other files here
result = TRUE;
__leave;
}
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
__leave;
}
}
CompressedHandle->CurrFileSize += sizeof (USHORT);
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compSize), sizeof (USHORT))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (USHORT);
// let's try to see if we just read a new file signature
*((PUSHORT)(&signature + 0)) = compType;
*((PUSHORT)(&signature + 1)) = compSize;
if (signature == COMPRESS_NEWFILE) {
// this is a new file
CompressedHandle->CurrFileSize -= sizeof (USHORT);
CompressedHandle->CurrFileSize -= sizeof (USHORT);
// rewind the file current pointer;
savedSize.QuadPart = CompressedHandle->CurrFileSize;
SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
// we are done with the current file
break;
} else {
// Let's advance the file pointer
if (SetFilePointer (CompressedHandle->CurrFileHandle, compSize, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER) {
__leave;
}
CompressedHandle->CurrFileSize += compSize;
}
}
} else {
for (;;) {
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
// It is possible that we continue onto the next file, let's try that.
if (!pPrepareNextFileW (CompressedHandle, TRUE)) {
__leave;
}
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
__leave;
}
}
CompressedHandle->CurrFileSize += sizeof (USHORT);
if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compSize), sizeof (USHORT))) {
__leave;
}
CompressedHandle->CurrFileSize += sizeof (USHORT);
if (!BfReadFile (CompressedHandle->CurrFileHandle, CompressedHandle->CompBuffer, compSize)) {
__leave;
}
CompressedHandle->CurrFileSize += compSize;
if (compType == CompressNone) {
if (extractFile) {
if (!BfWriteFile (extractHandle, CompressedHandle->CompBuffer, compSize)) {
__leave;
}
}
fileSizeRead += compSize;
} else {
bytesComp = DecompressData (
compType,
CompressedHandle->CompBuffer,
compSize,
CompressedHandle->ReadBuffer,
COMPRESS_BUFFER_SIZE
);
if (bytesComp > COMPRESS_BUFFER_SIZE) {
SetLastError (ERROR_INVALID_DATA);
__leave;
}
if (extractFile) {
if (!BfWriteFile (extractHandle, CompressedHandle->ReadBuffer, bytesComp)) {
__leave;
}
}
fileSizeRead += bytesComp;
}
if (fileSizeRead == fileSize) {
// this file is done, let's go to the next one
break;
}
}
}
}
if (extractHandle) {
CloseHandle (extractHandle);
extractHandle = NULL;
}
}
}
__finally {
if (storedName != NULL) {
MemFree (g_hHeap, 0, storedName);
storedName = NULL;
}
if (newFileName != NULL) {
FreePathStringW (newFileName);
newFileName = NULL;
}
if (extractPath != NULL) {
FreePathStringW (extractPath);
extractPath = NULL;
}
if ((extractHandle != NULL) &&
(extractHandle != INVALID_HANDLE_VALUE)
) {
CloseHandle (extractHandle);
extractHandle = NULL;
}
}
return result;
}
BOOL
CompressSetErrorMode (
IN BOOL ErrorMode
)
{
BOOL oldErrorMode = g_ErrorMode;
g_ErrorMode = ErrorMode;
return oldErrorMode;
}