/*++ 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 #include #include "lz_common.h" #include "lz_buffers.h" #include "lz_header.h" #include #include #include #include "main.h" #include #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); }