Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

572 lines
11 KiB

/*++
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 <windows.h>
#include <stdio.h>
#include "lz_common.h"
#include "lz_buffers.h"
#include "lz_header.h"
#include <io.h>
#include <fcntl.h>
#include <errno.h>
#include "main.h"
#include <diamondc.h>
#include "mydiam.h"
typedef struct _DIAMOND_INFO {
DWORD SourceFileSize;
DWORD CompressedSize;
FILETIME SourceFileCreationTime;
FILETIME SourceFileModifiedTime;
FILETIME SourceFileAccessedTime;
} DIAMOND_INFO, *PDIAMOND_INFO;
//
// 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);
}
FNFCIGETTEMPFILE(fciTempFileCB)
{
CHAR TempPath[MAX_PATH];
DWORD cchTemp;
cchTemp = GetTempPath(sizeof(TempPath), TempPath);
if ((cchTemp == 0) || (cchTemp >= sizeof(TempPath))) {
TempPath[0] = '.';
TempPath[1] = '\0';
}
if(GetTempFileNameA(TempPath,"dc",0,pszTempName)) {
DeleteFileA(pszTempName);
}
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.
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).
--*/
{
PDIAMOND_INFO context;
UNREFERENCED_PARAMETER(Count2);
context = (PDIAMOND_INFO)Context;
if(StatusType == statusFile) {
//
// Track compressed size.
//
context->CompressedSize += Count1;
}
return(TRUE);
}
FNFCIGETOPENINFO(fciOpenInfoCB)
{
int h;
WIN32_FIND_DATAA FindData;
HANDLE FindHandle;
PDIAMOND_INFO context;
FILETIME ftLocal;
context = pv;
FindHandle = FindFirstFileA(pszName,&FindData);
if(FindHandle == INVALID_HANDLE_VALUE) {
return(-1);
}
FindClose(FindHandle);
context->SourceFileSize = FindData.nFileSizeLow;
context->SourceFileCreationTime = FindData.ftCreationTime;
context->SourceFileModifiedTime = FindData.ftLastWriteTime;
context->SourceFileAccessedTime = FindData.ftLastAccessTime;
FileTimeToLocalFileTime(&FindData.ftLastWriteTime, &ftLocal);
FileTimeToDosDateTime(&ftLocal, pdate, ptime);
*pattribs = (WORD)(FindData.dwFileAttributes &
( FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE ));
h = _open(pszName,_O_RDONLY | _O_BINARY);
if(h == -1) {
return(-1);
}
return(h);
}
FNFCIOPEN(fciOpen)
{
int result;
result = _open(pszFile, oflag, pmode);
if (result == -1) {
*err = errno;
}
return(result);
}
FNFCIREAD(fciRead)
{
UINT result;
result = (UINT) _read((HFILE)hf, memory, cb);
if (result != cb) {
*err = errno;
}
return(result);
}
FNFCIWRITE(fciWrite)
{
UINT result;
result = (UINT) _write((HFILE)hf, memory, cb);
if (result != cb) {
*err = errno;
}
return(result);
}
FNFCICLOSE(fciClose)
{
int result;
result = _close((HFILE)hf);
if (result == -1) {
*err = errno;
}
return(result);
}
FNFCISEEK(fciSeek)
{
long result;
result = _lseek((HFILE)hf, dist, seektype);
if (result == -1) {
*err = errno;
}
return(result);
}
FNFCIDELETE(fciDelete)
{
int result;
result = _unlink(pszFile);
if (result == -1) {
*err = errno;
}
return(result);
}
INT
DiamondCompressFile(
IN NOTIFYPROC CompressNotify,
IN PSTR SourceFile,
IN PSTR TargetFile,
IN BOOL Rename,
OUT PLZINFO pLZI
)
{
BOOL b;
PSTR SourceFilenamePart,p;
HFCI FciContext;
ERF FciError;
CCAB ccab;
CHAR targetFile[MAX_PATH];
DIAMOND_INFO Context;
INT Status;
__try {
//
// Isolate the filename part of the source file.
//
if(SourceFilenamePart = strrchr(SourceFile,'\\')) {
SourceFilenamePart++;
} else {
SourceFilenamePart = SourceFile;
}
//
// Form the actual name of the target file.
//
lstrcpy(targetFile,TargetFile);
if(Rename) {
MakeCompressedName(targetFile);
}
//
// 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;
}
//
// Call the notification function to see whether we are really
// supposed to compress this file.
//
if(!CompressNotify(SourceFile,targetFile,NOTIFY_START_COMPRESS)) {
Status = BLANK_ERROR;
__leave;
}
ZeroMemory(&Context,sizeof(Context));
//
// Compress the file.
//
FciContext = FCICreate(
&FciError,
fciFilePlacedCB,
fciAllocCB,
fciFreeCB,
fciOpen,
fciRead,
fciWrite,
fciClose,
fciSeek,
fciDelete,
fciTempFileCB,
&ccab,
&Context
);
if(FciContext) {
b = FCIAddFile(
FciContext,
SourceFile, // file to add to cabinet.
SourceFilenamePart, // filename part, name to store in cabinet.
FALSE,
fciNextCabinetCB, // routine for next cabinet (always fails)
fciStatusCB,
fciOpenInfoCB,
DiamondCompressionType
);
if(b) {
b = FCIFlushCabinet(
FciContext,
FALSE,
fciNextCabinetCB,
fciStatusCB
);
if(b) {
HANDLE FindHandle;
WIN32_FIND_DATA FindData;
//
// Context.CompressedSize does not include headers
// and any other file overhead.
//
FindHandle = FindFirstFile(targetFile,&FindData);
if(FindHandle == INVALID_HANDLE_VALUE) {
pLZI->cblOutSize = (LONG)Context.CompressedSize;
} else {
pLZI->cblOutSize = (LONG)FindData.nFileSizeLow;
FindClose(FindHandle);
}
pLZI->cblInSize = (LONG)Context.SourceFileSize;
FindHandle = CreateFile(targetFile,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (FindHandle != INVALID_HANDLE_VALUE)
{
SetFileTime(FindHandle,
&Context.SourceFileCreationTime,
&Context.SourceFileAccessedTime,
&Context.SourceFileModifiedTime);
CloseHandle(FindHandle);
}
}
}
if(b) {
Status = TRUE;
} else {
switch(FciError.erfOper) {
case FCIERR_OPEN_SRC:
Status = LZERROR_BADINHANDLE;
break;
case FCIERR_READ_SRC:
Status = LZERROR_READ;
break;
case FCIERR_CAB_FILE:
Status = LZERROR_WRITE;
break;
case FCIERR_ALLOC_FAIL:
Status = LZERROR_GLOBALLOC;
break;
case FCIERR_TEMP_FILE:
case FCIERR_BAD_COMPR_TYPE:
case FCIERR_USER_ABORT:
case FCIERR_MCI_FAIL:
default:
Status = FALSE;
}
}
FCIDestroy(FciContext);
} else {
Status = LZERROR_GLOBALLOC;
}
} __except(EXCEPTION_EXECUTE_HANDLER) {
Status = GetLastError();
}
return(Status);
}