Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

319 lines
10 KiB

/*** fci.c - Diamond File Compression Interface library
*
* Author:
* Chuck Strouss
*
* History:
* 21-Jan-1994 chuckst basic FCI structure in place
* 09-Mar-1994 bens Add RESERVE support
* 21-Mar-1994 bens Use spruced up fci_int.h definitions
* 26-May-1994 bens Add Quantum support
*/
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <io.h>
#include <errno.h>
#include "types.h"
#include "asrt.h"
#include "fci_int.h"
#include "cabinet.h"
#include "erf.h"
#include "..\mszip\mci.h"
#include "buildcab.h"
#include "checksum.h"
/*** FCI - FCI context structure
*
*/
typedef struct { /* fci */
#ifdef ASSERT
SIGNATURE sig;
#endif
PCAB pcab;
PFOL pfol;
PERF perf;
PFNFREE pfnfree; // memory free function
void *pv; // used for passing back to callbacks
} FCI;
typedef FCI *PFCI; /* pfci */
#define PFCIfromHFCI(hfci) ((PFCI)(hfci))
#define HFCIfromPFCI(pfci) ((HFCI)(pfci))
#ifdef ASSERT
#define sigFCI MAKESIG('F','C','I','X') // FCI signature
#define AssertFCI(pfci) AssertStructure(pfci,sigFCI);
#else // !ASSERT
#define AssertFCI(pfci)
#endif // !ASSERT
/*** FCICreate -- create an FCI context (an open CAB, an open FOL)
*
* NOTE: See fci_int.h for entry/exit conditions.
*/
HFCI DIAMONDAPI FCICreate(PERF perf,
PFNFCIFILEPLACED pfnfiledest,
PFNALLOC pfnalloc,
PFNFREE pfnfree,
PFNFCIGETTEMPFILE pfntemp,
PCCAB pccab)
{
PFCI pfci;
pfci = (PFCI) pfnalloc (sizeof (FCI));
if (pfci == NULL) {
ErfSetCodes(perf,FCIERR_ALLOC_FAIL,0);
return NULL;
}
SetAssertSignature(pfci,sigFCI);
AssertFCI(pfci); // Make sure we've really set sig
pfci->pfnfree = pfnfree; // Save free function in our context
pfci->pcab = NULL; // assume cabinet not initialized yet for err exit
pfci->pfol = FolderInit(perf,
pfnalloc,
pfnfree,
pfntemp,
sizeof(CFDATA) + pccab->cbReserveCFData);
if (pfci->pfol == NULL) {
goto error;
}
#ifndef REMOVE_CHICAGO_M6_HACK
//** Save incompressible failure flag in folder, so we can test
// it after each block we attempt to compress.
pfci->pfol->fFailOnIncompressible = pccab->fFailOnIncompressible;
#endif
pfci->pcab = CreateCab("tell.cab",
perf,
pfnfiledest,
pfnalloc,
pfnfree,
pfntemp);
if (pfci->pcab == NULL) {
goto error; // error already filled in
}
pfci->pcab->ccab = *pccab; // save cabinet name structure
pfci->pcab->setID = pccab->setID; // Save cabinet set ID
pfci->pcab->iCabinet = 0; // Cabinet number starts at 0
//** Check for RESERVEd data
//BUGBUG 15-Mar-1994 bens Should we return an error if too big?
Assert(pccab->cbReserveCFHeader <= cbRESERVE_HEADER_MAX);
Assert(pccab->cbReserveCFFolder <= cbRESERVE_FOLDER_MAX);
Assert(pccab->cbReserveCFData <= cbRESERVE_DATA_MAX);
if ((pccab->cbReserveCFHeader > 0) || // If any reserved data
(pccab->cbReserveCFFolder > 0) ||
(pccab->cbReserveCFData > 0)) {
//** Need a CFRESERVE structure in the CFHEADER
pfci->pcab->cbReserveCF = sizeof(CFRESERVE) +
pccab->cbReserveCFHeader;
}
else {
pfci->pcab->cbReserveCF = 0; // No reserved areas
}
//** Compute size of structures with reserved areas
pfci->pcab->cbCFHeaderPlusReserve = sizeof(CFHEADER) +
pfci->pcab->cbReserveCF;
pfci->pcab->cbCFFolderPlusReserve = sizeof(CFFOLDER) +
pccab->cbReserveCFFolder;
pfci->pcab->cbCFDataPlusReserve = sizeof(CFDATA) +
pccab->cbReserveCFData;
//** Check for defaults
if (pfci->pcab->ccab.cb == 0) { // 0 implies MAX
pfci->pcab->ccab.cb = CB_MAX_DISK;
}
return HFCIfromPFCI(pfci); // return our handle!
error:
FCIDestroy(pfci);
return NULL;
}
/*** FCIAddFile - Add file to cabinet
*
* NOTE: See fci_int.h for entry/exit conditions.
*/
BOOL DIAMONDAPI FCIAddFile(HFCI hfci,
char *pszSourceFile,
char *pszFileName,
BOOL fExecute,
PFNFCIGETNEXTCABINET GetNextCab,
PFNFCISTATUS pfnProgress,
PFNFCIGETOPENINFO pfnOpenInfo,
TCOMP typeCompress,
void *pv)
{
PFCI pfci;
pfci = PFCIfromHFCI(hfci);
AssertFCI(pfci);
AssertCAB(pfci->pcab);
AssertFOL(pfci->pfol);
#ifndef REMOVE_CHICAGO_M6_HACK
//** Make sure state is passing around correctly
Assert(pfci->pfol->fFailOnIncompressible == pfci->pcab->ccab.fFailOnIncompressible);
#endif
//** Make sure the compressor is initialized to the type of compression
// the caller has requested.
if (typeCompress != pfci->pfol->typeCompress)
{
//** First terminate any pending compression stuff
if (!AddFolderToCabinet(pfci->pcab,
pfci->pfol,
FALSE, // Do not force GetNextCabinet
GetNextCab,
pfnProgress,
pv)) {
return FALSE;
}
if (!SetCompressionType(typeCompress,pfci->pfol)) {
return FALSE;
}
}
#ifndef REMOVE_CHICAGO_M6_HACK
//** Make sure state is passing around correctly
Assert(pfci->pfol->fFailOnIncompressible == pfci->pcab->ccab.fFailOnIncompressible);
#endif
//** Add the file to the current folder
if (!AddFileToFolder(pfci->pfol,
pszSourceFile, // filename to read from
pszFileName, // name it will have in folder
fExecute,
pfnProgress,
pfnOpenInfo, // callback for opening file, etc.
typeCompress,
pv)) {
return FALSE;
}
//** See if folder being built exceeds folder threshold, or exceeds
// maximum specified cabinet size
if ((pfci->pcab->ccab.cbFolderThresh < pfci->pfol->tf[iftfCFDATA].cb) ||
(pfci->pcab->ccab.cb <
(pfci->pcab->cbCFHeaderPlusReserve + // still need CFHEADER
pfci->pcab->cbCFFolderPlusReserve + // and one more CFFOLDER
pfci->pcab->tf[ictfCFDATA].cb +
pfci->pcab->tf[ictfCFFILE].cb +
pfci->pcab->tf[ictfCFFOLDER].cb +
pfci->pfol->tf[iftfCFDATA].cb +
pfci->pfol->tf[iftfCFFOLDER].cb))) {
//** Need to add folder to cabinet
return AddFolderToCabinet(pfci->pcab,
pfci->pfol,
FALSE, // Do not force GetNextCabinet
GetNextCab,
pfnProgress,
pv);
}
//** Success
return TRUE;
}
/*** FCIFlushCabinet - Complete the current cabinet under construction
*
* NOTE: See fci_int.h for entry/exit conditions.
*/
BOOL DIAMONDAPI FCIFlushCabinet(HFCI hfci,
BOOL fGetNextCab,
PFNFCIGETNEXTCABINET GetNextCab,
PFNFCISTATUS pfnProgress,
void *pv)
{
PFCI pfci;
unsigned long cbDone;
unsigned long cbTot;
pfci = PFCIfromHFCI(hfci);
AssertFCI(pfci);
if (!AddFolderToCabinet(pfci->pcab,
pfci->pfol,
fGetNextCab,
GetNextCab,
pfnProgress,
pv)) {
return FALSE; // error already filled in
}
//** If fGetNextCab is TRUE, then AddFolderToCabinet did the FlushCab,
// so don't do it again here!
if (fGetNextCab) {
return TRUE;
}
//** Need to flush the remainder of the cabinet
cbDone = 0;
cbTot = pfci->pcab->tf[ictfCFFILE].cb +
pfci->pcab->tf[ictfCFDATA].cb;
return FlushCab(pfci->pcab,
pfnProgress,
&cbDone,
cbTot,
pv);
}
/*** FCIFlushFolder - Complete the current folder under construction
*
* NOTE: See fci_int.h for entry/exit conditions.
*/
BOOL DIAMONDAPI FCIFlushFolder(HFCI hfci,
PFNFCIGETNEXTCABINET GetNextCab,
PFNFCISTATUS pfnProgress,
void *pv)
{
PFCI pfci;
pfci = PFCIfromHFCI(hfci);
AssertFCI(pfci);
if (!AddFolderToCabinet(pfci->pcab,
pfci->pfol,
FALSE, // Do not force GetNextCabinet
GetNextCab,
pfnProgress,
pv)) {
return FALSE; // error already filled in
}
return TRUE;
}
/*** FCIDestroy -- Destroy an FCI context
*
* NOTE: See fci_int.h for entry/exit conditions.
*/
BOOL DIAMONDAPI FCIDestroy(HFCI hfci)
{
PFCI pfci;
BOOL retcode = TRUE;
pfci = PFCIfromHFCI(hfci);
AssertFCI(pfci);
if (pfci->pfol != NULL) retcode &= FolderDestroy(pfci->pfol);
if (pfci->pcab != NULL) retcode &= CabDestroy(pfci->pcab);
ClearAssertSignature(pfci);
pfci->pfnfree(pfci);
return retcode;
}