diff options
Diffstat (limited to 'private/utils/rdisk/diamond.c')
-rw-r--r-- | private/utils/rdisk/diamond.c | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/private/utils/rdisk/diamond.c b/private/utils/rdisk/diamond.c new file mode 100644 index 000000000..4e77dae2d --- /dev/null +++ b/private/utils/rdisk/diamond.c @@ -0,0 +1,476 @@ +/*++ + +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 |