NT4/private/utils/rdisk/diamond.c
2020-09-30 17:12:29 +02:00

477 lines
9.0 KiB
C

/*++
Module Name:
diamond.c
Abstract:
Diamond compression interface.
This module contains functions to compress a file using
the mszip compression library.
Author:
Ted Miller
Environment:
Windows
--*/
#include "precomp.h"
#pragma hdrstop
typedef struct _COMPRESS_CONTEXT {
DWORD GaugeBasePosition;
DWORD GaugeRangeForFile;
HWND GaugeWindow;
DWORD FileSize;
DWORD BytesCompressedSoFar;
} COMPRESS_CONTEXT, *PCOMPRESS_CONTEXT;
DWORD DiamondLastError;
//
// Callback functions to perform memory allocation, io, etc.
// We pass addresses of these functions to diamond.
//
int
DIAMONDAPI
fciFilePlacedCB(
OUT PCCAB Cabinet,
IN PSTR FileName,
IN LONG FileSize,
IN BOOL Continuation,
IN PVOID Context
)
/*++
Routine Description:
Callback used by diamond to indicate that a file has been
comitted to a cabinet.
No action is taken and success is returned.
Arguments:
Cabinet - cabinet structure to fill in.
FileName - name of file in cabinet
FileSize - size of file in cabinet
Continuation - TRUE if this is a partial file, continuation
of compression begun in a different cabinet.
Context - supplies context information.
Return Value:
0 (success).
--*/
{
UNREFERENCED_PARAMETER(Cabinet);
UNREFERENCED_PARAMETER(FileName);
UNREFERENCED_PARAMETER(FileSize);
UNREFERENCED_PARAMETER(Continuation);
UNREFERENCED_PARAMETER(Context);
return(0);
}
PVOID
DIAMONDAPI
fciAllocCB(
IN ULONG NumberOfBytes
)
/*++
Routine Description:
Callback used by diamond to allocate memory.
Arguments:
NumberOfBytes - supplies desired size of block.
Return Value:
Returns pointer to a block of memory or NULL
if memory cannot be allocated.
--*/
{
return((PVOID)LocalAlloc(LMEM_FIXED,NumberOfBytes));
}
VOID
DIAMONDAPI
fciFreeCB(
IN PVOID Block
)
/*++
Routine Description:
Callback used by diamond to free a memory block.
The block must have been allocated with fciAlloc().
Arguments:
Block - supplies pointer to block of memory to be freed.
Return Value:
None.
--*/
{
LocalFree((HLOCAL)Block);
}
BOOL
DIAMONDAPI
fciTempFileCB(
OUT PSTR TempFileName,
IN int TempFileNameBufferSize
)
/*++
Routine Description:
Callback used by diamond to request a tempfile name.
Arguments:
TempFileName - receives temp file name.
TempFileNameBufferSize - supplies size of memory block
pointed to by TempFileName.
Return Value:
TRUE (success).
--*/
{
UNREFERENCED_PARAMETER(TempFileNameBufferSize);
if(GetTempFileNameA(".","dc",0,TempFileName)) {
//
// GetTempFileNameA will create the file, causing
// FCI to fail when it tries to open it using _O_EXCL.
//
DeleteFileA(TempFileName);
}
return(TRUE);
}
BOOL
DIAMONDAPI
fciNextCabinetCB(
OUT PCCAB Cabinet,
IN DWORD CabinetSizeEstimate,
IN PVOID Context
)
/*++
Routine Description:
Callback used by diamond to request a new cabinet file.
This functionality is not used in our implementation as
we deal only with single-file cabinets.
Arguments:
Cabinet - cabinet structure to be filled in.
CabinetSizeEstimate - estimated size of cabinet.
Context - supplies context information.
Return Value:
FALSE (failure).
--*/
{
UNREFERENCED_PARAMETER(Cabinet);
UNREFERENCED_PARAMETER(CabinetSizeEstimate);
UNREFERENCED_PARAMETER(Context);
return(FALSE);
}
BOOL
DIAMONDAPI
fciStatusCB(
IN UINT StatusType,
IN DWORD Count1,
IN DWORD Count2,
IN PVOID Context
)
/*++
Routine Description:
Callback used by diamond to give status on file compression
and cabinet operations, etc.
This routine has no effect.
Arguments:
Status Type - supplies status type.
0 = statusFile - compressing block into a folder.
Count1 = compressed size
Count2 = uncompressed size
1 = statusFolder - performing AddFilder.
Count1 = bytes done
Count2 = total bytes
Context - supplies context info.
Return Value:
TRUE (success).
--*/
{
PCOMPRESS_CONTEXT context;
DWORD delta;
UNREFERENCED_PARAMETER(Count1);
context = (PCOMPRESS_CONTEXT)Context;
if(StatusType == statusFile) {
//
// Update number of bytes compressed so far.
//
context->BytesCompressedSoFar += Count2;
//
// Calculate the gauge offset from the base position
// for this file. We do this carefully to avoid overflow.
//
delta = (DWORD)( (LONGLONG)context->GaugeRangeForFile
* (LONGLONG)context->BytesCompressedSoFar
/ (LONGLONG)context->FileSize);
//
// Update the gas gauge.
//
SendDlgItemMessage( context->GaugeWindow,
ID_BAR,
PBM_SETPOS,
context->GaugeBasePosition + delta,
0L
);
}
return(TRUE);
}
int
DIAMONDAPI
fciOpenInfoCB(
IN PSTR FileName,
OUT WORD *DosDate,
OUT WORD *DosTime,
OUT WORD *FileAttributes,
IN PVOID Context
)
/*++
Routine Description:
Callback used by diamond to open a file and retreive information
about it.
Arguments:
FileName - supplies filename of file about which information
is desired.
DosDate - receives last write date of the file if the file exists.
DosTime - receives last write time of the file if the file exists.
FileAttributes - receives file attributes if the file exists.
Context - supplies context information.
Return Value:
C runtime handle to open file if success; -1 if file could
not be located or opened.
--*/
{
int h;
WIN32_FIND_DATAA FindData;
HANDLE FindHandle;
PCOMPRESS_CONTEXT context;
context = Context;
FindHandle = FindFirstFileA(FileName,&FindData);
if(FindHandle == INVALID_HANDLE_VALUE) {
DiamondLastError = GetLastError();
return(-1);
}
FindClose(FindHandle);
context->FileSize = FindData.nFileSizeLow;
FileTimeToDosDateTime(&FindData.ftLastWriteTime,DosDate,DosTime);
*FileAttributes = (WORD)FindData.dwFileAttributes;
h = _open(FileName,_O_RDONLY | _O_BINARY);
if(h == -1) {
DiamondLastError = GetLastError();
return(-1);
}
return(h);
}
DWORD
DiamondCompressFile(
IN PSTR SourceFile,
IN PSTR TargetFile,
IN DWORD GaugeBasePosition,
IN DWORD GaugeRangeForThisFile,
IN HWND GaugeNotifyWindow
)
{
BOOL b;
PSTR SourceFilenamePart,p;
HFCI FciContext;
ERF FciError;
CCAB ccab;
COMPRESS_CONTEXT GaugeContext;
//
// Isolate the filename part of the source file.
//
if(SourceFilenamePart = strrchr(SourceFile,'\\')) {
SourceFilenamePart++;
} else {
SourceFilenamePart = SourceFile;
}
//
// Fill in the cabinet structure.
//
ZeroMemory(&ccab,sizeof(ccab));
lstrcpyA(ccab.szCabPath,TargetFile);
if(p=strrchr(ccab.szCabPath,'\\')) {
lstrcpyA(ccab.szCab,++p);
*p = 0;
} else {
lstrcpyA(ccab.szCab,TargetFile);
ccab.szCabPath[0] = 0;
}
DiamondLastError = NO_ERROR;
GaugeContext.GaugeBasePosition = GaugeBasePosition;
GaugeContext.GaugeRangeForFile = GaugeRangeForThisFile;
GaugeContext.GaugeWindow = GaugeNotifyWindow;
GaugeContext.FileSize = 0;
GaugeContext.BytesCompressedSoFar = 0;
//
// Compress the file.
//
FciContext = FCICreate(
&FciError,
fciFilePlacedCB,
fciAllocCB,
fciFreeCB,
fciTempFileCB,
&ccab
);
if(FciContext) {
b = FCIAddFile(
FciContext,
SourceFile, // file to add to cabinet.
SourceFilenamePart, // filename part, name to store in cabinet.
FALSE, // fExecute on extract
fciNextCabinetCB, // routine for next cabinet (always fails)
fciStatusCB,
fciOpenInfoCB,
tcompTYPE_MSZIP,
&GaugeContext
);
if(b) {
b = FCIFlushCabinet(
FciContext,
FALSE,
fciNextCabinetCB,
fciStatusCB,
&GaugeContext
);
}
FCIDestroy(FciContext);
}
return(b ? NO_ERROR : ((DiamondLastError == NO_ERROR) ? ERROR_INVALID_FUNCTION : DiamondLastError));
}
#if 0
#include <stdio.h>
void __cdecl main(int argc,char *argv[])
{
if(argc == 3) {
DiamondCompressFile(argv[1],argv[2]);
} else {
printf("bad args\n");
}
}
#endif