Sync to Wine-20050628: Thomas Weidenmueller wine-patches@reactsoft.com - Removed local variables only used in TRACE statements. Gerold Jens Wucherpfennig gjwucherpfennig@gmx.net - Some FCI work. Modified: trunk/reactos/lib/cabinet/cabextract.c Modified: trunk/reactos/lib/cabinet/cabinet.h Modified: trunk/reactos/lib/cabinet/cabinet_main.c Modified: trunk/reactos/lib/cabinet/fci.c _____
Modified: trunk/reactos/lib/cabinet/cabextract.c --- trunk/reactos/lib/cabinet/cabextract.c 2005-07-06 22:16:28 UTC (rev 16470) +++ trunk/reactos/lib/cabinet/cabextract.c 2005-07-06 22:24:04 UTC (rev 16471) @@ -31,6 +31,7 @@
#include <stdarg.h> #include <stdio.h> #include <stdlib.h> +#include <ctype.h>
#include "windef.h" #include "winbase.h" @@ -2523,13 +2524,8 @@ * print_fileinfo (internal) */ void print_fileinfo(struct cab_file *fi) { - int d; - int t; char *fname = NULL;
- d = fi->date; - t = fi->time; - if (fi->attribs & cffile_A_NAME_IS_UTF) { fname = malloc(strlen(fi->filename) + 1); if (fname) { @@ -2540,8 +2536,8 @@
TRACE("%9u | %02d.%02d.%04d %02d:%02d:%02d | %s\n", fi->length, - d & 0x1f, (d>>5) & 0xf, (d>>9) + 1980, - t >> 11, (t>>5) & 0x3f, (t << 1) & 0x3e, + fi->date & 0x1f, (fi->date>>5) & 0xf, (fi->date>>9) + 1980, + fi->time >> 11, (fi->time>>5) & 0x3f, (fi->time << 1) & 0x3e, fname ? fname : fi->filename );
_____
Modified: trunk/reactos/lib/cabinet/cabinet.h --- trunk/reactos/lib/cabinet/cabinet.h 2005-07-06 22:16:28 UTC (rev 16470) +++ trunk/reactos/lib/cabinet/cabinet.h 2005-07-06 22:24:04 UTC (rev 16471) @@ -305,7 +305,41 @@
PFNFCIDELETE pfndelete; PFNFCIGETTEMPFILE pfnfcigtf; PCCAB pccab; - void *pv; + BOOL fPrevCab; + BOOL fNextCab; + BOOL fSplitFolder; + cab_ULONG statusFolderCopied; + cab_ULONG statusFolderTotal; + BOOL fGetNextCabInVain; + void *pv; + char szPrevCab[CB_MAX_CABINET_NAME]; /* previous cabinet name */ + char szPrevDisk[CB_MAX_DISK_NAME]; /* disk name of previous cabinet */ + CCAB oldCCAB; + char* data_in; /* uncompressed data blocks */ + cab_UWORD cdata_in; + char* data_out; /* compressed data blocks */ + ULONG cCompressedBytesInFolder; + cab_UWORD cFolders; + cab_UWORD cFiles; + cab_ULONG cDataBlocks; + cab_ULONG cbFileRemainer; /* uncompressed, yet to be written data */ + /* of spanned file of a spanning folder of a spanning cabinet */ + cab_UBYTE szFileNameCFDATA1[CB_MAX_FILENAME]; + int handleCFDATA1; + cab_UBYTE szFileNameCFFILE1[CB_MAX_FILENAME]; + int handleCFFILE1; + cab_UBYTE szFileNameCFDATA2[CB_MAX_FILENAME]; + int handleCFDATA2; + cab_UBYTE szFileNameCFFILE2[CB_MAX_FILENAME]; + int handleCFFILE2; + cab_UBYTE szFileNameCFFOLDER[CB_MAX_FILENAME]; + int handleCFFOLDER; + cab_ULONG sizeFileCFDATA1; + cab_ULONG sizeFileCFFILE1; + cab_ULONG sizeFileCFDATA2; + cab_ULONG sizeFileCFFILE2; + cab_ULONG sizeFileCFFOLDER; + BOOL fNewPrevious; } FCI_Int, *PFCI_Int;
typedef struct { @@ -326,6 +360,18 @@ /* cast an HFDI into a PFDI_Int */ #define PFDI_INT(hfdi) ((PFDI_Int)(hfdi))
+/* quick pfci method invokers */ +#define PFCI_ALLOC(hfdi, size) ((*PFCI_INT(hfdi)->pfnalloc) (size)) +#define PFCI_FREE(hfdi, ptr) ((*PFCI_INT(hfdi)->pfnfree) (ptr)) +#define PFCI_GETTEMPFILE(hfci,name,length) ((*PFCI_INT(hfci)->pfnfcigtf)(name,length,PFCI_INT(hfci)->pv)) +#define PFCI_DELETE(hfci,name,err,pv) ((*PFCI_INT(hfci)->pfndelete)(name,err,pv)) +#define PFCI_OPEN(hfci,name,oflag,pmode,err,pv) ((*PFCI_INT(hfci)->pfnopen)(name,oflag,pmode,err,pv)) +#define PFCI_READ(hfci,hf,memory,cb,err,pv)((*PFCI_INT(hfci)->pfnread)(hf,memory ,cb,err,pv)) +#define PFCI_WRITE(hfci,hf,memory,cb,err,pv) ((*PFCI_INT(hfci)->pfnwrite)(hf,memory,cb,err,pv)) +#define PFCI_CLOSE(hfci,hf,err,pv) ((*PFCI_INT(hfci)->pfnclose)(hf,err,pv)) +#define PFCI_SEEK(hfci,hf,dist,seektype,err,pv)((*PFCI_INT(hfci)->pfnseek)(hf,di st,seektype,err,pv)) +#define PFCI_FILEPLACED(hfci,pccab,name,cb,cont,pv)((*PFCI_INT(hfci)->pfnfiledes t)(pccab,name,cb,cont,pv)) + /* quickie pfdi method invokers */ #define PFDI_ALLOC(hfdi, size) ((*PFDI_INT(hfdi)->pfnalloc) (size)) #define PFDI_FREE(hfdi, ptr) ((*PFDI_INT(hfdi)->pfnfree) (ptr)) _____
Modified: trunk/reactos/lib/cabinet/cabinet_main.c --- trunk/reactos/lib/cabinet/cabinet_main.c 2005-07-06 22:16:28 UTC (rev 16470) +++ trunk/reactos/lib/cabinet/cabinet_main.c 2005-07-06 22:24:04 UTC (rev 16471) @@ -89,15 +89,14 @@
HRESULT WINAPI Extract(EXTRACTdest *dest, LPCSTR what) { #define DUMPC(idx) idx >= sizeof(EXTRACTdest) ? ' ' : \ - ptr[idx] >= 0x20 ? ptr[idx] : '.' + ((unsigned char*) dest)[idx] >= 0x20 ? \ + ((unsigned char*) dest)[idx] : '.'
-#define DUMPH(idx) idx >= sizeof(EXTRACTdest) ? 0x55 : ptr[idx] +#define DUMPH(idx) idx >= sizeof(EXTRACTdest) ? 0x55 : ((unsigned char*) dest)[idx]
LPSTR dir; - unsigned char *ptr; unsigned int i;
- ptr = ((unsigned char*) dest); TRACE("(dest == %0lx, what == %s)\n", (long) dest, debugstr_a(what));
if (!dest) { _____
Modified: trunk/reactos/lib/cabinet/fci.c --- trunk/reactos/lib/cabinet/fci.c 2005-07-06 22:16:28 UTC (rev 16470) +++ trunk/reactos/lib/cabinet/fci.c 2005-07-06 22:24:04 UTC (rev 16471) @@ -19,9 +19,27 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* + +There is still some work to be done: + +- currently no support for big-endian machines +- the ERF error structure aren't used on error +- no real compression yet +- unknown behaviour if files>4GB or cabinet >4GB +- incorrect status information +- check if the maximum size for a cabinet is too small to store any data +- call pfnfcignc on exactly the same position as MS FCIAddFile in every case + +*/ + + + #include "config.h"
#include <stdarg.h> +#include <stdio.h> +#include <string.h>
#include "windef.h" #include "winbase.h" @@ -33,12 +51,56 @@
WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
+typedef struct { + cab_UBYTE signature[4]; /* !CAB for unfinished cabinets else MSCF */ + cab_ULONG reserved1; + cab_ULONG cbCabinet; /* size of the cabinet file in bytes*/ + cab_ULONG reserved2; + cab_ULONG coffFiles; /* offset to first CFFILE section */ + cab_ULONG reserved3; + cab_UBYTE versionMinor; /* 3 */ + cab_UBYTE versionMajor; /* 1 */ + cab_UWORD cFolders; /* number of CFFOLDER entries in the cabinet*/ + cab_UWORD cFiles; /* number of CFFILE entries in the cabinet*/ + cab_UWORD flags; /* 1=prev cab, 2=next cabinet, 4=reserved setions*/ + cab_UWORD setID; /* identification number of all cabinets in a set*/ + cab_UWORD iCabinet; /* number of the cabinet in a set */ + /* additional area if "flags" were set*/ +} CFHEADER; /* minimum 36 bytes */ + +typedef struct { + cab_ULONG coffCabStart; /* offset to the folder's first CFDATA section */ + cab_UWORD cCFData; /* number of this folder's CFDATA sections */ + cab_UWORD typeCompress; /* compression type of data in CFDATA section*/ + /* additional area if reserve flag was set */ +} CFFOLDER; /* minumum 8 bytes */ + +typedef struct { + cab_ULONG cbFile; /* size of the uncompressed file in bytes */ + cab_ULONG uoffFolderStart; /* offset of the uncompressed file in the folder */ + cab_UWORD iFolder; /* number of folder in the cabinet 0=first */ + /* for special values see below this structure*/ + cab_UWORD date; /* last modification date*/ + cab_UWORD time; /* last modification time*/ + cab_UWORD attribs; /* DOS fat attributes and UTF indicator */ + /* ... and a C string with the name of the file */ +} CFFILE; /* 16 bytes + name of file */ + + +typedef struct { + cab_ULONG csum; /* checksum of this entry*/ + cab_UWORD cbData; /* number of compressed bytes */ + cab_UWORD cbUncomp; /* number of bytes when data is uncompressed */ + /* optional reserved area */ + /* compressed data */ +} CFDATA; + +
/*********************************************************************** * FCICreate (CABINET.10) * - * Provided with several callbacks, - * returns a handle which can be used to perform operations - * on cabinet files. + * FCICreate is provided with several callbacks and + * returns a handle which can be used to create cabinet files. * * PARAMS * perf [IO] A pointer to an ERF structure. When FCICreate @@ -54,7 +116,7 @@ * the same interface as _open. * pfnread [I] A pointer to a function which reads from a file into * a caller-provided buffer. Uses the same interface - * as _read + * as _read. * pfnwrite [I] A pointer to a function which writes to a file from * a caller-provided buffer. Uses the same interface * as _write. @@ -64,8 +126,8 @@ * Uses the same interface as _lseek. * pfndelete [I] A pointer to a function which deletes a file. * pfnfcigtf [I] A pointer to a function which gets the name of a - * temporary file; ignored in wine - * pccab [I] A pointer to an initialized CCAB structure + * temporary file. + * pccab [I] A pointer to an initialized CCAB structure. * pv [I] A pointer to an application-defined notification * function which will be passed to other FCI functions * as a parameter. @@ -94,9 +156,13 @@ PCCAB pccab, void *pv) { - HFCI rv; + HFCI hfci; + int err; + PFCI_Int p_fci_internal;
- if ((!pfnalloc) || (!pfnfree)) { + if ((!perf) || (!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) || + (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) || + (!pfnfcigtf) || (!pccab)) { perf->erfOper = FCIERR_NONE; perf->erfType = ERROR_BAD_ARGUMENTS; perf->fError = TRUE; @@ -105,7 +171,7 @@ return NULL; }
- if (!(rv = (HFCI) (*pfnalloc)(sizeof(FCI_Int)))) { + if (!((hfci = ((HFCI) (*pfnalloc)(sizeof(FCI_Int)))))) { perf->erfOper = FCIERR_ALLOC_FAIL; perf->erfType = ERROR_NOT_ENOUGH_MEMORY; perf->fError = TRUE; @@ -114,41 +180,1977 @@ return NULL; }
- PFCI_INT(rv)->FCI_Intmagic = FCI_INT_MAGIC; - PFCI_INT(rv)->perf = perf; - PFCI_INT(rv)->pfnfiledest = pfnfiledest; - PFCI_INT(rv)->pfnalloc = pfnalloc; - PFCI_INT(rv)->pfnfree = pfnfree; - PFCI_INT(rv)->pfnopen = pfnopen; - PFCI_INT(rv)->pfnread = pfnread; - PFCI_INT(rv)->pfnwrite = pfnwrite; - PFCI_INT(rv)->pfnclose = pfnclose; - PFCI_INT(rv)->pfnseek = pfnseek; - PFCI_INT(rv)->pfndelete = pfndelete; - PFCI_INT(rv)->pfnfcigtf = pfnfcigtf; - PFCI_INT(rv)->pccab = pccab; - PFCI_INT(rv)->pv = pv; + p_fci_internal=((PFCI_Int)(hfci)); + p_fci_internal->FCI_Intmagic = FCI_INT_MAGIC; + p_fci_internal->perf = perf; + p_fci_internal->pfnfiledest = pfnfiledest; + p_fci_internal->pfnalloc = pfnalloc; + p_fci_internal->pfnfree = pfnfree; + p_fci_internal->pfnopen = pfnopen; + p_fci_internal->pfnread = pfnread; + p_fci_internal->pfnwrite = pfnwrite; + p_fci_internal->pfnclose = pfnclose; + p_fci_internal->pfnseek = pfnseek; + p_fci_internal->pfndelete = pfndelete; + p_fci_internal->pfnfcigtf = pfnfcigtf; + p_fci_internal->pccab = pccab; + p_fci_internal->fPrevCab = FALSE; + p_fci_internal->fNextCab = FALSE; + p_fci_internal->fSplitFolder = FALSE; + p_fci_internal->fGetNextCabInVain = FALSE; + p_fci_internal->pv = pv; + p_fci_internal->data_in = NULL; + p_fci_internal->cdata_in = 0; + p_fci_internal->data_out = NULL; + p_fci_internal->cCompressedBytesInFolder = 0; + p_fci_internal->cFolders = 0; + p_fci_internal->cFiles = 0; + p_fci_internal->cDataBlocks = 0; + p_fci_internal->sizeFileCFDATA1 = 0; + p_fci_internal->sizeFileCFFILE1 = 0; + p_fci_internal->sizeFileCFDATA2 = 0; + p_fci_internal->sizeFileCFFILE2 = 0; + p_fci_internal->sizeFileCFFOLDER = 0; + p_fci_internal->sizeFileCFFOLDER = 0; + p_fci_internal->fNewPrevious = FALSE;
- /* Still mark as incomplete, because of other missing FCI* APIs */ + memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME); + memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);
- PFCI_INT(rv)->FCI_Intmagic = 0; - PFDI_FREE(rv, rv); - FIXME("(%p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p): stub\n", - perf, pfnfiledest, pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, - pfnseek, pfndelete, pfnfcigtf, pccab, pv); + /* CFDATA */ + if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA1, + CB_MAX_FILENAME)) { + /* TODO error handling */ + return FALSE; + } + /* safety */ + if ( strlen(p_fci_internal->szFileNameCFDATA1) >= CB_MAX_FILENAME ) { + /* TODO set error code */ + return FALSE; + }
- perf->erfOper = FCIERR_NONE; - perf->erfType = 0; - perf->fError = TRUE; + p_fci_internal->handleCFDATA1 = PFCI_OPEN(hfci, + p_fci_internal->szFileNameCFDATA1, 34050, 384, &err, pv); + /* TODO check handle */ + /* TODO error checking of err */
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + /* array of all CFFILE in a folder */ + if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE1, + CB_MAX_FILENAME)) { + /* TODO error handling */ + return FALSE; + } + /* safety */ + if ( strlen(p_fci_internal->szFileNameCFFILE1) >= CB_MAX_FILENAME ) { + /* TODO set error code */ + return FALSE; + } + p_fci_internal->handleCFFILE1 = PFCI_OPEN(hfci, + p_fci_internal->szFileNameCFFILE1, 34050, 384, &err, pv); + /* TODO check handle */ + /* TODO error checking of err */
- return NULL; + /* CFDATA with checksum and ready to be copied into cabinet */ + if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA2, + CB_MAX_FILENAME)) { + /* TODO error handling */ + return FALSE; + } + /* safety */ + if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) { + /* TODO set error code */ + return FALSE; + } + p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci, + p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, pv); + /* TODO check handle */ + /* TODO error checking of err */
-} + /* array of all CFFILE in a folder, ready to be copied into cabinet */ + if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2, + CB_MAX_FILENAME)) { + /* TODO error handling */ + return FALSE; + } + /* safety */ + if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) { + /* TODO set error code */ + return FALSE; + } + p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci, + p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, pv); + /* TODO check handle */ + /* TODO error checking of err */
+ /* array of all CFFILE in a folder, ready to be copied into cabinet */ + if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER, + CB_MAX_FILENAME)) { + /* TODO error handling */ + return FALSE; + } + /* safety */ + if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) { + /* TODO set error code */ + return FALSE; + } + p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci, + p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, pv); + + + /* TODO close and delete new files when return FALSE */ + + /* TODO check handle */ + /* TODO error checking of err */ + + return hfci; +} /* end of FCICreate */ + + + + + + +static BOOL fci_flush_data_block (HFCI hfci, int* err, + PFNFCISTATUS pfnfcis) { + + /* attention no hfci checks!!! */ + /* attention no checks if there is data available!!! */ + CFDATA data; + CFDATA* cfdata=&data; + char* reserved; + PFCI_Int p_fci_internal=((PFCI_Int)(hfci)); + UINT cbReserveCFData=p_fci_internal->pccab->cbReserveCFData; + UINT i; + + /* TODO compress the data of p_fci_internal->data_in */ + /* and write it to p_fci_internal->data_out */ + memcpy(p_fci_internal->data_out, p_fci_internal->data_in, + p_fci_internal->cdata_in /* number of bytes to copy */); + + cfdata->csum=0; /* checksum has to be set later */ + /* TODO set realsize of compressed data */ + cfdata->cbData = p_fci_internal->cdata_in; + cfdata->cbUncomp = p_fci_internal->cdata_in; + + /* write cfdata to p_fci_internal->handleCFDATA1 */ + if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */ + cfdata, sizeof(*cfdata), err, p_fci_internal->pv) + != sizeof(*cfdata) ) { + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err */ + + p_fci_internal->sizeFileCFDATA1 += sizeof(*cfdata); + + /* add optional reserved area */ + + /* This allocation and freeing at each CFData block is a bit */ + /* inefficent, but it's harder to forget about freeing the buffer :-). */ + /* Reserved areas are used seldom besides that... */ + if (cbReserveCFData!=0) { + if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData))) { + p_fci_internal->perf->erfOper = FCIERR_ALLOC_FAIL; + p_fci_internal->perf->erfType = ERROR_NOT_ENOUGH_MEMORY; + p_fci_internal->perf->fError = TRUE; + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + for(i=0;i<cbReserveCFData;) { + reserved[i++]='\0'; + } + if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */ + reserved, /* memory buffer */ + cbReserveCFData, /* number of bytes to copy */ + err, p_fci_internal->pv) != cbReserveCFData ) { + PFCI_FREE(hfci, reserved); + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err PFCI_FREE(hfci, reserved)*/ + + p_fci_internal->sizeFileCFDATA1 += cbReserveCFData; + PFCI_FREE(hfci, reserved); + } + + /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */ + if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */ + p_fci_internal->data_out, /* memory buffer */ + cfdata->cbData, /* number of bytes to copy */ + err, p_fci_internal->pv) != cfdata->cbData) { + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err */ + + p_fci_internal->sizeFileCFDATA1 += cfdata->cbData; + + /* reset the offset */ + p_fci_internal->cdata_in = 0; + p_fci_internal->cCompressedBytesInFolder += cfdata->cbData; + + /* report status with pfnfcis about uncompressed and compressed file data */ + if( (*pfnfcis)(statusFile, cfdata->cbData, cfdata->cbUncomp, + p_fci_internal->pv) == -1) { + /* TODO set error code and abort */ + return FALSE; + } + + ++(p_fci_internal->cDataBlocks); + + return TRUE; +} /* end of fci_flush_data_block */ + + + + + +static cab_ULONG fci_get_checksum(void *pv, UINT cb, CHECKSUM seed) +{ + cab_ULONG csum; + cab_ULONG ul; + int cUlong; + BYTE *pb; + + csum = seed; + cUlong = cb / 4; + pb = pv; + + while (cUlong-- > 0) { + ul = *pb++; + ul |= (((cab_ULONG)(*pb++)) << 8); + ul |= (((cab_ULONG)(*pb++)) << 16); + ul |= (((cab_ULONG)(*pb++)) << 24); + + csum ^= ul; + } + + ul = 0; + switch (cb % 4) { + case 3: + ul |= (((ULONG)(*pb++)) << 16); + case 2: + ul |= (((ULONG)(*pb++)) << 8); + case 1: + ul |= *pb++; + default: + break; + } + csum ^= ul; + + return csum; +} /* end of fci_get_checksum */ + + + + + +static BOOL fci_flushfolder_copy_cfdata(HFCI hfci, char* buffer, UINT cbReserveCFData, + PFNFCISTATUS pfnfcis, int* err, int handleCFDATA1new, + cab_ULONG* psizeFileCFDATA1new, cab_ULONG* payload) +{ + cab_ULONG read_result; + CFDATA* pcfdata=(CFDATA*)buffer; + BOOL split_block=FALSE; + cab_UWORD savedUncomp=0; + PFCI_Int p_fci_internal=((PFCI_Int)(hfci)); + + *payload=0; + + /* while not all CFDATAs have been copied do */ + while(!FALSE) { + if( p_fci_internal->fNextCab ) { + if( split_block ) { + /* TODO internal error should never happen */ + return FALSE; + } + } + /* REUSE the variable read_result */ + if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 || + p_fci_internal->oldCCAB.cbReserveCFFolder != 0 || + p_fci_internal->oldCCAB.cbReserveCFData != 0 ) { + read_result=4; + } else { + read_result=0; + } + if (p_fci_internal->fPrevCab) { + read_result+=strlen(p_fci_internal->szPrevCab)+1 + + strlen(p_fci_internal->szPrevDisk)+1; + } + /* No more CFDATA fits into the cabinet under construction */ + /* So don't try to store more data into it */ + if( p_fci_internal->fNextCab && + (p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData + + p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 + + p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER + + sizeof(CFHEADER) + + read_result + + p_fci_internal->oldCCAB.cbReserveCFHeader + + sizeof(CFFOLDER) + + p_fci_internal->oldCCAB.cbReserveCFFolder + + strlen(p_fci_internal->pccab->szCab)+1 + + strlen(p_fci_internal->pccab->szDisk)+1 + )) { + /* This may never be run for the first time the while loop is entered. + Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/ + split_block=TRUE; /* In this case split_block is abused to store */ + /* the complete data block into the next cabinet and not into the */ + /* current one. Originally split_block is the indicator that a */ + /* data block has been splitted across different cabinets. */ + } else { + + /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/ + read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/*file handle*/ + buffer, /* memory buffer */ + sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */ + err, p_fci_internal->pv); + if (read_result!=sizeof(CFDATA)+cbReserveCFData) { + if (read_result==0) break; /* ALL DATA has been copied */ + /* TODO read error */ + return FALSE; + } + /* TODO error handling of err */ + + /* REUSE buffer p_fci_internal->data_out !!! */ + /* read data from p_fci_internal->handleCFDATA1 to */ + /* p_fci_internal->data_out */ + if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */, + p_fci_internal->data_out /* memory buffer */, + pcfdata->cbData /* number of bytes to copy */, + err, p_fci_internal->pv) != pcfdata->cbData ) { + /* TODO read error */ + return FALSE; + } + /* TODO error handling of err */ + + /* if cabinet size is too large */ + + /* REUSE the variable read_result */ + if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 || + p_fci_internal->oldCCAB.cbReserveCFFolder != 0 || + p_fci_internal->oldCCAB.cbReserveCFData != 0 ) { + read_result=4; + } else { + read_result=0; + } + if (p_fci_internal->fPrevCab) { + read_result+=strlen(p_fci_internal->szPrevCab)+1 + + strlen(p_fci_internal->szPrevDisk)+1; + } + + /* Is cabinet with new CFDATA too large? Then data block has to be split */ + if( p_fci_internal->fNextCab && + (p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData + + pcfdata->cbData + + p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 + + p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER + + sizeof(CFHEADER) + + read_result + + p_fci_internal->oldCCAB.cbReserveCFHeader + + sizeof(CFFOLDER) + /* size of new CFFolder entry */ + p_fci_internal->oldCCAB.cbReserveCFFolder + + strlen(p_fci_internal->pccab->szCab)+1 + /* name of next cabinet */ + strlen(p_fci_internal->pccab->szDisk)+1 /* name of next disk */ + )) { + /* REUSE read_result to save the size of the compressed data */ + read_result=pcfdata->cbData; + /* Modify the size of the compressed data to store only a part of the */ + /* data block into the current cabinet. This is done to prevent */ + /* that the maximum cabinet size will be exceeded. The remainer */ + /* will be stored into the next following cabinet. */ + + /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */ + /* Substract everything except the size of the block of data */ + /* to get it's actual size */ + pcfdata->cbData = p_fci_internal->oldCCAB.cb - ( + sizeof(CFDATA) + cbReserveCFData + + p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 + + p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER + + sizeof(CFHEADER) + + p_fci_internal->oldCCAB.cbReserveCFHeader + + sizeof(CFFOLDER) + /* set size of new CFFolder entry */ + p_fci_internal->oldCCAB.cbReserveCFFolder ); + /* substract the size of special header fields */ + if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 || + p_fci_internal->oldCCAB.cbReserveCFFolder != 0 || + p_fci_internal->oldCCAB.cbReserveCFData != 0 ) { + pcfdata->cbData-=4; + } + if (p_fci_internal->fPrevCab) { + pcfdata->cbData-=strlen(p_fci_internal->szPrevCab)+1 + + strlen(p_fci_internal->szPrevDisk)+1; + } + pcfdata->cbData-=strlen(p_fci_internal->pccab->szCab)+1 + + strlen(p_fci_internal->pccab->szDisk)+1; + + savedUncomp = pcfdata->cbUncomp; + pcfdata->cbUncomp = 0; /* on splitted blocks of data this is zero */ + + /* if split_block==TRUE then the above while loop won't */ + /* be executed again */ + split_block=TRUE; /* split_block is the indicator that */ + /* a data block has been splitted across */ + /* diffentent cabinets.*/ + } + + /* This should never happen !!! */ + if (pcfdata->cbData==0) { + /* TODO set error */ + return FALSE; + } + + /* get checksum and write to cfdata.csum */ + pcfdata->csum = fci_get_checksum( &(pcfdata->cbData), + sizeof(CFDATA)+cbReserveCFData - + sizeof(pcfdata->csum), fci_get_checksum( p_fci_internal->data_out, /*buffer*/ + pcfdata->cbData, 0 ) ); + + /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */ + if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */ + buffer, /* memory buffer */ + sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */ + err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) { + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err */ + + p_fci_internal->sizeFileCFDATA2 += sizeof(CFDATA)+cbReserveCFData; + + /* write compressed data into p_fci_internal->handleCFDATA2 */ + if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */ + p_fci_internal->data_out, /* memory buffer */ + pcfdata->cbData, /* number of bytes to copy */ + err, p_fci_internal->pv) != pcfdata->cbData) { + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err */ + + p_fci_internal->sizeFileCFDATA2 += pcfdata->cbData; + ++(p_fci_internal->cDataBlocks); + p_fci_internal->statusFolderCopied += pcfdata->cbData; + (*payload)+=pcfdata->cbUncomp; + /* if cabinet size too large and data has been split */ + /* write the remainer of the data block to the new CFDATA1 file */ + if( split_block ) { /* This does not include the */ + /* abused one (just search for "abused" )*/ + /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */ + if (p_fci_internal->fNextCab==FALSE ) { + /* TODO internal error */ + return FALSE; + } + + /* set cbData the size of the remainer of the data block */ + pcfdata->cbData = read_result - pcfdata->cbData; + /*recover former value of cfdata.cbData; read_result will be the offset*/ + read_result -= pcfdata->cbData; + pcfdata->cbUncomp = savedUncomp; + + /* reset checksum, it will be computed later */ + pcfdata->csum=0; + /* write cfdata WITHOUT checksum to handleCFDATA1new */ + if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */ + buffer, /* memory buffer */ + sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */ + err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) { + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */ + + *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData; + + /* write compressed data into handleCFDATA1new */ + if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */ + p_fci_internal->data_out + read_result, /* memory buffer + offset */ + /* to last part of split data */ + pcfdata->cbData, /* number of bytes to copy */ + err, p_fci_internal->pv) != pcfdata->cbData) { + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err */ + + p_fci_internal->statusFolderCopied += pcfdata->cbData; + + *psizeFileCFDATA1new += pcfdata->cbData; + /* the two blocks of the split data block have been written */ + /* dont reset split_data yet, because it is still needed see below */ + } + + /* report status with pfnfcis about copied size of folder */ + if( (*pfnfcis)(statusFolder, + p_fci_internal->statusFolderCopied, /*cfdata.cbData(+previous ones)*/ + p_fci_internal->statusFolderTotal, /* total folder size */ + p_fci_internal->pv) == -1) { + /* TODO set error code and abort */ + return FALSE; + } + } + + /* if cabinet size too large */ + /* write the remaining data blocks to the new CFDATA1 file */ + if ( split_block ) { /* This does include the */ + /* abused one (just search for "abused" )*/ + if (p_fci_internal->fNextCab==FALSE ) { + /* TODO internal error */ + return FALSE; + } + /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */ + while(!FALSE) { + /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/ + read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/* handle */ + buffer, /* memory buffer */ + sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */ + err, p_fci_internal->pv); + if (read_result!=sizeof(CFDATA)+cbReserveCFData) { + if (read_result==0) break; /* ALL DATA has been copied */ + /* TODO read error */ + return FALSE; + } + /* TODO error handling of err */ + + /* REUSE buffer p_fci_internal->data_out !!! */ + /* read data from p_fci_internal->handleCFDATA1 to */ + /* p_fci_internal->data_out */ + if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */, + p_fci_internal->data_out /* memory buffer */, + pcfdata->cbData /* number of bytes to copy */, + err, p_fci_internal->pv) != pcfdata->cbData ) { + /* TODO read error */ + return FALSE; + } + /* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */ + + /* write cfdata with checksum to handleCFDATA1new */ + if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */ + buffer, /* memory buffer */ + sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */ + err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) { + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */ + + *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData; + + /* write compressed data into handleCFDATA1new */ + if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */ + p_fci_internal->data_out, /* memory buffer */ + pcfdata->cbData, /* number of bytes to copy */ + err, p_fci_internal->pv) != pcfdata->cbData) { + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err */ + + *psizeFileCFDATA1new += pcfdata->cbData; + p_fci_internal->statusFolderCopied += pcfdata->cbData; + + /* report status with pfnfcis about copied size of folder */ + if( (*pfnfcis)(statusFolder, + p_fci_internal->statusFolderCopied,/*cfdata.cbData(+revious ones)*/ + p_fci_internal->statusFolderTotal, /* total folder size */ + p_fci_internal->pv) == -1) { + /* TODO set error code and abort */ + return FALSE; + } + + } /* end of WHILE */ + break; /* jump out of the next while loop */ + } /* end of if( split_data ) */ + } /* end of WHILE */ + return TRUE; +} /* end of fci_flushfolder_copy_cfdata */ + + + + + +static BOOL fci_flushfolder_copy_cffolder(HFCI hfci, int* err, UINT cbReserveCFFolder, + cab_ULONG sizeFileCFDATA2old) +{ + CFFOLDER cffolder; + UINT i; + char* reserved; + PFCI_Int p_fci_internal=((PFCI_Int)(hfci)); + + /* absolute offset cannot be set yet, because the size of cabinet header, */ + /* the number of CFFOLDERs and the number of CFFILEs may change. */ + /* Instead the size of all previous data blocks will be stored and */ + /* the remainer of the offset will be added when the cabinet will be */ + /* flushed to disk. */ + /* This is exactly the way the original CABINET.DLL works!!! */ + cffolder.coffCabStart=sizeFileCFDATA2old; + + /* set the number of this folder's CFDATA sections */ + cffolder.cCFData=p_fci_internal->cDataBlocks; + /* TODO set compression type */ + cffolder.typeCompress = tcompTYPE_NONE; + + /* write cffolder to p_fci_internal->handleCFFOLDER */ + if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */ + &cffolder, /* memory buffer */ + sizeof(cffolder), /* number of bytes to copy */ + err, p_fci_internal->pv) != sizeof(cffolder) ) { + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err */ + + p_fci_internal->sizeFileCFFOLDER += sizeof(cffolder); + + /* add optional reserved area */ + if (cbReserveCFFolder!=0) { + if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFFolder))) { + p_fci_internal->perf->erfOper = FCIERR_ALLOC_FAIL; + p_fci_internal->perf->erfType = ERROR_NOT_ENOUGH_MEMORY; + p_fci_internal->perf->fError = TRUE; + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + for(i=0;i<cbReserveCFFolder;) { + reserved[i++]='\0'; + } + if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */ + reserved, /* memory buffer */ + cbReserveCFFolder, /* number of bytes to copy */ + err, p_fci_internal->pv) != cbReserveCFFolder ) { + PFCI_FREE(hfci, reserved); + /* TODO write error */ + return FALSE; + } + /* TODO error handling of err */ + + p_fci_internal->sizeFileCFFOLDER += cbReserveCFFolder; + + PFCI_FREE(hfci, reserved); + } + return TRUE; +} /* end of fci_flushfolder_copy_cffolder */ + + + + + +static BOOL fci_flushfolder_copy_cffile(HFCI hfci, int* err, int handleCFFILE1new, + cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload) +{ + CFFILE cffile; + cab_ULONG read_result; + cab_ULONG seek=0; + cab_ULONG sizeOfFiles=0, sizeOfFilesPrev; + BOOL may_be_prev=TRUE; + cab_ULONG cbFileRemainer=0; + PFCI_Int p_fci_internal=((PFCI_Int)(hfci)); + /* set seek of p_fci_internal->handleCFFILE1 to 0 */ + if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,0,SEEK_SET,err, + p_fci_internal->pv) !=0 ) { + /* TODO wrong return value */ + } + /* TODO error handling of err */ + + /* while not all CFFILE structures have been copied do */ + while(!FALSE) { + /* REUSE the variable read_result */ + /* read data from p_fci_internal->handleCFFILE1 to cffile */ + read_result = PFCI_READ(hfci,p_fci_internal->handleCFFILE1/* file handle */, + &cffile, /* memory buffer */ + sizeof(cffile), /* number of bytes to copy */ + err, p_fci_internal->pv); + if( read_result != sizeof(cffile) ) { + if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */ + /* TODO read error */ + return FALSE; + } + /* TODO error handling of err */ + + /* Microsoft's(R) CABINET.DLL would do a seek to the current! */ + /* position. I don't know why so I'll just omit it */ + + /* read the filename from p_fci_internal->handleCFFILE1 */ + /* REUSE the variable read_result AGAIN */ + /* REUSE the memory buffer PFCI(hfci)->data_out */ + if( PFCI_READ(hfci, p_fci_internal->handleCFFILE1 /*file handle*/, + p_fci_internal->data_out, /* memory buffer */ + CB_MAX_FILENAME, /* number of bytes to copy */ + err, p_fci_internal->pv) <2) { + /* TODO read error */ + return FALSE; + } + /* TODO maybe other checks of read_result */ + /* TODO error handling of err */ + + /* safety */ + if( strlen(p_fci_internal->data_out)>=CB_MAX_FILENAME ) { + /* TODO set error code internal error */ + return FALSE; + } [truncated at 1000 lines; 1788 more skipped]