/*++ Module Name: diamond.c Abstract: Diamond compression routines. This module contains functions to create a cabinet with files compressed using the mszip compression library. Author: Ovidiu Temereanca (ovidiut) 26-Oct-2000 --*/ #include "precomp.h" #include #include #include static DWORD g_DiamondLastError; static PCSTR g_TempDir = NULL; HFCI (DIAMONDAPI* g_FCICreate) ( PERF perf, PFNFCIFILEPLACED pfnfcifp, PFNFCIALLOC pfna, PFNFCIFREE pfnf, PFNFCIOPEN pfnopen, PFNFCIREAD pfnread, PFNFCIWRITE pfnwrite, PFNFCICLOSE pfnclose, PFNFCISEEK pfnseek, PFNFCIDELETE pfndelete, PFNFCIGETTEMPFILE pfnfcigtf, PCCAB pccab, void FAR * pv ); BOOL (DIAMONDAPI* g_FCIAddFile) ( HFCI hfci, char *pszSourceFile, char *pszFileName, BOOL fExecute, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis, PFNFCIGETOPENINFO pfnfcigoi, TCOMP typeCompress ); /* BOOL (DIAMONDAPI* g_FCIFlushFolder) ( HFCI hfci, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis ); */ BOOL (DIAMONDAPI* g_FCIFlushCabinet) ( HFCI hfci, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis ); BOOL (DIAMONDAPI* g_FCIDestroy) ( HFCI hfci ); // // 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). --*/ { 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) { if (!GetTempFileNameA (g_TempDir ? g_TempDir : ".", "dc" ,0 , pszTempName)) { return FALSE; } 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. Arguments: Cabinet - cabinet structure to be filled in. CabinetSizeEstimate - estimated size of cabinet. Context - supplies context information. Return Value: FALSE (failure). --*/ { 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). --*/ { return(TRUE); } FNFCIGETOPENINFO(fciOpenInfoCB) /*++ Routine Description: Callback used by diamond to open a file and retreive information about it. Arguments: pszName - supplies filename of file about which information is desired. pdate - receives last write date of the file if the file exists. ptime - receives last write time of the file if the file exists. pattribs - receives file attributes if the file exists. pv - 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; FindHandle = FindFirstFileA(pszName,&FindData); if(FindHandle == INVALID_HANDLE_VALUE) { g_DiamondLastError = GetLastError(); return(-1); } FindClose(FindHandle); FileTimeToDosDateTime(&FindData.ftLastWriteTime,pdate,ptime); *pattribs = (WORD)FindData.dwFileAttributes; h = _open(pszName,_O_RDONLY | _O_BINARY); if(h == -1) { g_DiamondLastError = GetLastError(); 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((int)hf, memory, cb); if (result != cb) { *err = errno; } return(result); } FNFCIWRITE(fciWrite) { UINT result; result = (UINT) _write((int)hf, memory, cb); if (result != cb) { *err = errno; } return(result); } FNFCICLOSE(fciClose) { int result; result = _close((int)hf); if (result == -1) { *err = errno; } return(result); } FNFCISEEK(fciSeek) { long result; result = _lseek((int)hf, dist, seektype); if (result == -1) { *err = errno; } return(result); } FNFCIDELETE(fciDelete) { int result; result = _unlink(pszFile); if (result == -1) { *err = errno; } return(result); } HANDLE DiamondInitialize ( IN PCTSTR TempDir ) { HMODULE hCabinetDll; hCabinetDll = LoadLibrary (TEXT("cabinet.dll")); if (!hCabinetDll) { return FALSE; } (FARPROC)g_FCICreate = GetProcAddress (hCabinetDll, "FCICreate"); (FARPROC)g_FCIAddFile = GetProcAddress (hCabinetDll, "FCIAddFile"); (FARPROC)g_FCIFlushCabinet = GetProcAddress (hCabinetDll, "FCIFlushCabinet"); (FARPROC)g_FCIDestroy = GetProcAddress (hCabinetDll, "FCIDestroy"); if (!g_FCICreate || !g_FCIAddFile || !g_FCIFlushCabinet || !g_FCIDestroy) { DiamondTerminate (hCabinetDll); return NULL; } if (TempDir && !g_TempDir) { #ifdef UNICODE g_TempDir = UnicodeToAnsi (TempDir); #else g_TempDir = DupString (TempDir); #endif } return hCabinetDll; } VOID DiamondTerminate ( IN HANDLE Handle ) { FreeLibrary (Handle); g_FCICreate = NULL; g_FCIAddFile = NULL; g_FCIFlushCabinet = NULL; g_FCIDestroy = NULL; if (g_TempDir) { FREE ((PVOID)g_TempDir); g_TempDir = NULL; } } HANDLE DiamondStartNewCabinet ( IN PCTSTR CabinetFilePath ) { CCAB ccab; ERF FciError; HFCI FciContext; PSTR p; // // Fill in the cabinet structure. // ZeroMemory (&ccab, sizeof(ccab)); #ifdef UNICODE if (!WideCharToMultiByte ( CP_ACP, 0, CabinetFilePath, -1, ccab.szCabPath, sizeof (ccab.szCabPath) / sizeof (ccab.szCabPath[0]), NULL, NULL )) { return NULL; } #else lstrcpyA (ccab.szCabPath, CabinetFilePath); #endif p = strrchr (ccab.szCabPath, '\\'); if(!p) { SetLastError (ERROR_INVALID_PARAMETER); return NULL; } lstrcpyA (ccab.szCab, ++p); *p = 0; g_DiamondLastError = NO_ERROR; FciContext = g_FCICreate( &FciError, fciFilePlacedCB, fciAllocCB, fciFreeCB, fciOpen, fciRead, fciWrite, fciClose, fciSeek, fciDelete, fciTempFileCB, &ccab, NULL ); return (HANDLE)FciContext; } BOOL DiamondAddFileToCabinet ( IN HANDLE CabinetContext, IN PCTSTR SourceFile, IN PCTSTR NameInCabinet ) { HFCI FciContext = (HFCI)CabinetContext; BOOL b; CHAR AnsiSourceFile[MAX_PATH]; CHAR AnsiNameInCabinet[MAX_PATH]; #ifdef UNICODE if (!WideCharToMultiByte ( CP_ACP, 0, SourceFile, -1, AnsiSourceFile, sizeof (AnsiSourceFile) / sizeof (AnsiSourceFile[0]), NULL, NULL ) || !WideCharToMultiByte ( CP_ACP, 0, NameInCabinet, -1, AnsiNameInCabinet, sizeof (AnsiNameInCabinet) / sizeof (AnsiNameInCabinet[0]), NULL, NULL )) { return FALSE; } #else lstrcpyA (AnsiSourceFile, SourceFile); lstrcpyA (AnsiNameInCabinet, NameInCabinet); #endif b = g_FCIAddFile ( FciContext, AnsiSourceFile, // file to add to cabinet. AnsiNameInCabinet, // filename part, name to store in cabinet. FALSE, // fExecute on extract fciNextCabinetCB, // routine for next cabinet (always fails) fciStatusCB, fciOpenInfoCB, tcompTYPE_MSZIP ); if (!b) { SetLastError (g_DiamondLastError == NO_ERROR ? ERROR_INVALID_FUNCTION : g_DiamondLastError); } return b; } BOOL DiamondTerminateCabinet ( IN HANDLE CabinetContext ) { HFCI FciContext = (HFCI)CabinetContext; BOOL b; b = g_FCIFlushCabinet ( FciContext, FALSE, fciNextCabinetCB, fciStatusCB ); g_FCIDestroy (FciContext); if (!b) { SetLastError (g_DiamondLastError == NO_ERROR ? ERROR_INVALID_FUNCTION : g_DiamondLastError); } return b; }