* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
*/\r
\r
+/*\r
+\r
+There is still some work to be done:\r
+\r
+- currently no support for big-endian machines\r
+- the ERF error structure aren't used on error\r
+- no real compression yet\r
+- unknown behaviour if files>4GB or cabinet >4GB\r
+- incorrect status information\r
+- check if the maximum size for a cabinet is too small to store any data\r
+- call pfnfcignc on exactly the same position as MS FCIAddFile in every case\r
+\r
+*/\r
+\r
+\r
+\r
#include "config.h"\r
\r
#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
\r
#include "windef.h"\r
#include "winbase.h"\r
\r
WINE_DEFAULT_DEBUG_CHANNEL(cabinet);\r
\r
+typedef struct {\r
+ cab_UBYTE signature[4]; /* !CAB for unfinished cabinets else MSCF */\r
+ cab_ULONG reserved1;\r
+ cab_ULONG cbCabinet; /* size of the cabinet file in bytes*/\r
+ cab_ULONG reserved2;\r
+ cab_ULONG coffFiles; /* offset to first CFFILE section */\r
+ cab_ULONG reserved3;\r
+ cab_UBYTE versionMinor; /* 3 */\r
+ cab_UBYTE versionMajor; /* 1 */\r
+ cab_UWORD cFolders; /* number of CFFOLDER entries in the cabinet*/\r
+ cab_UWORD cFiles; /* number of CFFILE entries in the cabinet*/\r
+ cab_UWORD flags; /* 1=prev cab, 2=next cabinet, 4=reserved setions*/\r
+ cab_UWORD setID; /* identification number of all cabinets in a set*/\r
+ cab_UWORD iCabinet; /* number of the cabinet in a set */\r
+ /* additional area if "flags" were set*/\r
+} CFHEADER; /* minimum 36 bytes */\r
+\r
+typedef struct {\r
+ cab_ULONG coffCabStart; /* offset to the folder's first CFDATA section */\r
+ cab_UWORD cCFData; /* number of this folder's CFDATA sections */\r
+ cab_UWORD typeCompress; /* compression type of data in CFDATA section*/\r
+ /* additional area if reserve flag was set */\r
+} CFFOLDER; /* minumum 8 bytes */\r
+\r
+typedef struct {\r
+ cab_ULONG cbFile; /* size of the uncompressed file in bytes */\r
+ cab_ULONG uoffFolderStart; /* offset of the uncompressed file in the folder */\r
+ cab_UWORD iFolder; /* number of folder in the cabinet 0=first */\r
+ /* for special values see below this structure*/\r
+ cab_UWORD date; /* last modification date*/\r
+ cab_UWORD time; /* last modification time*/\r
+ cab_UWORD attribs; /* DOS fat attributes and UTF indicator */\r
+ /* ... and a C string with the name of the file */\r
+} CFFILE; /* 16 bytes + name of file */\r
+\r
+\r
+typedef struct {\r
+ cab_ULONG csum; /* checksum of this entry*/\r
+ cab_UWORD cbData; /* number of compressed bytes */\r
+ cab_UWORD cbUncomp; /* number of bytes when data is uncompressed */\r
+ /* optional reserved area */\r
+ /* compressed data */\r
+} CFDATA;\r
+\r
+\r
/***********************************************************************\r
* FCICreate (CABINET.10)\r
*\r
- * Provided with several callbacks,\r
- * returns a handle which can be used to perform operations\r
- * on cabinet files.\r
+ * FCICreate is provided with several callbacks and\r
+ * returns a handle which can be used to create cabinet files.\r
*\r
* PARAMS\r
* perf [IO] A pointer to an ERF structure. When FCICreate\r
* the same interface as _open.\r
* pfnread [I] A pointer to a function which reads from a file into\r
* a caller-provided buffer. Uses the same interface\r
- * as _read\r
+ * as _read.\r
* pfnwrite [I] A pointer to a function which writes to a file from\r
* a caller-provided buffer. Uses the same interface\r
* as _write.\r
* Uses the same interface as _lseek.\r
* pfndelete [I] A pointer to a function which deletes a file.\r
* pfnfcigtf [I] A pointer to a function which gets the name of a\r
- * temporary file; ignored in wine\r
- * pccab [I] A pointer to an initialized CCAB structure\r
+ * temporary file.\r
+ * pccab [I] A pointer to an initialized CCAB structure.\r
* pv [I] A pointer to an application-defined notification\r
* function which will be passed to other FCI functions\r
* as a parameter.\r
PCCAB pccab,\r
void *pv)\r
{\r
- HFCI rv;\r
+ HFCI hfci;\r
+ int err;\r
+ PFCI_Int p_fci_internal;\r
\r
- if ((!pfnalloc) || (!pfnfree)) {\r
+ if ((!perf) || (!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||\r
+ (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||\r
+ (!pfnfcigtf) || (!pccab)) {\r
perf->erfOper = FCIERR_NONE;\r
perf->erfType = ERROR_BAD_ARGUMENTS;\r
perf->fError = TRUE;\r
return NULL;\r
}\r
\r
- if (!(rv = (HFCI) (*pfnalloc)(sizeof(FCI_Int)))) {\r
+ if (!((hfci = ((HFCI) (*pfnalloc)(sizeof(FCI_Int)))))) {\r
perf->erfOper = FCIERR_ALLOC_FAIL;\r
perf->erfType = ERROR_NOT_ENOUGH_MEMORY;\r
perf->fError = TRUE;\r
return NULL;\r
}\r
\r
- PFCI_INT(rv)->FCI_Intmagic = FCI_INT_MAGIC;\r
- PFCI_INT(rv)->perf = perf;\r
- PFCI_INT(rv)->pfnfiledest = pfnfiledest;\r
- PFCI_INT(rv)->pfnalloc = pfnalloc;\r
- PFCI_INT(rv)->pfnfree = pfnfree;\r
- PFCI_INT(rv)->pfnopen = pfnopen;\r
- PFCI_INT(rv)->pfnread = pfnread;\r
- PFCI_INT(rv)->pfnwrite = pfnwrite;\r
- PFCI_INT(rv)->pfnclose = pfnclose;\r
- PFCI_INT(rv)->pfnseek = pfnseek;\r
- PFCI_INT(rv)->pfndelete = pfndelete;\r
- PFCI_INT(rv)->pfnfcigtf = pfnfcigtf;\r
- PFCI_INT(rv)->pccab = pccab;\r
- PFCI_INT(rv)->pv = pv;\r
+ p_fci_internal=((PFCI_Int)(hfci));\r
+ p_fci_internal->FCI_Intmagic = FCI_INT_MAGIC;\r
+ p_fci_internal->perf = perf;\r
+ p_fci_internal->pfnfiledest = pfnfiledest;\r
+ p_fci_internal->pfnalloc = pfnalloc;\r
+ p_fci_internal->pfnfree = pfnfree;\r
+ p_fci_internal->pfnopen = pfnopen;\r
+ p_fci_internal->pfnread = pfnread;\r
+ p_fci_internal->pfnwrite = pfnwrite;\r
+ p_fci_internal->pfnclose = pfnclose;\r
+ p_fci_internal->pfnseek = pfnseek;\r
+ p_fci_internal->pfndelete = pfndelete;\r
+ p_fci_internal->pfnfcigtf = pfnfcigtf;\r
+ p_fci_internal->pccab = pccab;\r
+ p_fci_internal->fPrevCab = FALSE;\r
+ p_fci_internal->fNextCab = FALSE;\r
+ p_fci_internal->fSplitFolder = FALSE;\r
+ p_fci_internal->fGetNextCabInVain = FALSE;\r
+ p_fci_internal->pv = pv;\r
+ p_fci_internal->data_in = NULL;\r
+ p_fci_internal->cdata_in = 0;\r
+ p_fci_internal->data_out = NULL;\r
+ p_fci_internal->cCompressedBytesInFolder = 0;\r
+ p_fci_internal->cFolders = 0;\r
+ p_fci_internal->cFiles = 0;\r
+ p_fci_internal->cDataBlocks = 0;\r
+ p_fci_internal->sizeFileCFDATA1 = 0;\r
+ p_fci_internal->sizeFileCFFILE1 = 0;\r
+ p_fci_internal->sizeFileCFDATA2 = 0;\r
+ p_fci_internal->sizeFileCFFILE2 = 0;\r
+ p_fci_internal->sizeFileCFFOLDER = 0;\r
+ p_fci_internal->sizeFileCFFOLDER = 0;\r
+ p_fci_internal->fNewPrevious = FALSE;\r
\r
- /* Still mark as incomplete, because of other missing FCI* APIs */\r
+ memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);\r
+ memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);\r
\r
- PFCI_INT(rv)->FCI_Intmagic = 0;\r
- PFDI_FREE(rv, rv);\r
- FIXME("(%p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p): stub\n",\r
- perf, pfnfiledest, pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose,\r
- pfnseek, pfndelete, pfnfcigtf, pccab, pv);\r
+ /* CFDATA */\r
+ if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA1,\r
+ CB_MAX_FILENAME)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* safety */\r
+ if ( strlen(p_fci_internal->szFileNameCFDATA1) >= CB_MAX_FILENAME ) {\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
\r
- perf->erfOper = FCIERR_NONE;\r
- perf->erfType = 0;\r
- perf->fError = TRUE;\r
+ p_fci_internal->handleCFDATA1 = PFCI_OPEN(hfci,\r
+ p_fci_internal->szFileNameCFDATA1, 34050, 384, &err, pv);\r
+ /* TODO check handle */\r
+ /* TODO error checking of err */\r
\r
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\r
+ /* array of all CFFILE in a folder */\r
+ if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE1,\r
+ CB_MAX_FILENAME)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* safety */\r
+ if ( strlen(p_fci_internal->szFileNameCFFILE1) >= CB_MAX_FILENAME ) {\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ p_fci_internal->handleCFFILE1 = PFCI_OPEN(hfci,\r
+ p_fci_internal->szFileNameCFFILE1, 34050, 384, &err, pv);\r
+ /* TODO check handle */\r
+ /* TODO error checking of err */\r
\r
- return NULL;\r
+ /* CFDATA with checksum and ready to be copied into cabinet */\r
+ if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA2,\r
+ CB_MAX_FILENAME)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* safety */\r
+ if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,\r
+ p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, pv);\r
+ /* TODO check handle */\r
+ /* TODO error checking of err */\r
\r
-}\r
+ /* array of all CFFILE in a folder, ready to be copied into cabinet */\r
+ if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,\r
+ CB_MAX_FILENAME)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* safety */\r
+ if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,\r
+ p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, pv);\r
+ /* TODO check handle */\r
+ /* TODO error checking of err */\r
\r
-/***********************************************************************\r
- * FCIAddFile (CABINET.11)\r
- */\r
-BOOL __cdecl FCIAddFile(\r
- HFCI hfci,\r
- char *pszSourceFile,\r
- char *pszFileName,\r
- BOOL fExecute,\r
- PFNFCIGETNEXTCABINET pfnfcignc,\r
- PFNFCISTATUS pfnfcis,\r
- PFNFCIGETOPENINFO pfnfcigoi,\r
- TCOMP typeCompress)\r
+ /* array of all CFFILE in a folder, ready to be copied into cabinet */\r
+ if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,\r
+ CB_MAX_FILENAME)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* safety */\r
+ if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,\r
+ p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, pv);\r
+\r
+\r
+ /* TODO close and delete new files when return FALSE */\r
+\r
+ /* TODO check handle */\r
+ /* TODO error checking of err */\r
+\r
+ return hfci;\r
+} /* end of FCICreate */\r
+\r
+\r
+\r
+\r
+\r
+\r
+static BOOL fci_flush_data_block (HFCI hfci, int* err,\r
+ PFNFCISTATUS pfnfcis) {\r
+\r
+ /* attention no hfci checks!!! */\r
+ /* attention no checks if there is data available!!! */\r
+ CFDATA data;\r
+ CFDATA* cfdata=&data;\r
+ char* reserved;\r
+ PFCI_Int p_fci_internal=((PFCI_Int)(hfci));\r
+ UINT cbReserveCFData=p_fci_internal->pccab->cbReserveCFData;\r
+ UINT i;\r
+\r
+ /* TODO compress the data of p_fci_internal->data_in */\r
+ /* and write it to p_fci_internal->data_out */\r
+ memcpy(p_fci_internal->data_out, p_fci_internal->data_in,\r
+ p_fci_internal->cdata_in /* number of bytes to copy */);\r
+\r
+ cfdata->csum=0; /* checksum has to be set later */\r
+ /* TODO set realsize of compressed data */\r
+ cfdata->cbData = p_fci_internal->cdata_in;\r
+ cfdata->cbUncomp = p_fci_internal->cdata_in;\r
+\r
+ /* write cfdata to p_fci_internal->handleCFDATA1 */\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */\r
+ cfdata, sizeof(*cfdata), err, p_fci_internal->pv)\r
+ != sizeof(*cfdata) ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->sizeFileCFDATA1 += sizeof(*cfdata);\r
+\r
+ /* add optional reserved area */\r
+\r
+ /* This allocation and freeing at each CFData block is a bit */\r
+ /* inefficent, but it's harder to forget about freeing the buffer :-). */\r
+ /* Reserved areas are used seldom besides that... */\r
+ if (cbReserveCFData!=0) {\r
+ if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData))) {\r
+ p_fci_internal->perf->erfOper = FCIERR_ALLOC_FAIL;\r
+ p_fci_internal->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;\r
+ p_fci_internal->perf->fError = TRUE;\r
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);\r
+ return FALSE;\r
+ }\r
+ for(i=0;i<cbReserveCFData;) {\r
+ reserved[i++]='\0';\r
+ }\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */\r
+ reserved, /* memory buffer */\r
+ cbReserveCFData, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != cbReserveCFData ) {\r
+ PFCI_FREE(hfci, reserved);\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err PFCI_FREE(hfci, reserved)*/\r
+\r
+ p_fci_internal->sizeFileCFDATA1 += cbReserveCFData;\r
+ PFCI_FREE(hfci, reserved);\r
+ }\r
+\r
+ /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */\r
+ p_fci_internal->data_out, /* memory buffer */\r
+ cfdata->cbData, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != cfdata->cbData) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->sizeFileCFDATA1 += cfdata->cbData;\r
+\r
+ /* reset the offset */\r
+ p_fci_internal->cdata_in = 0;\r
+ p_fci_internal->cCompressedBytesInFolder += cfdata->cbData;\r
+\r
+ /* report status with pfnfcis about uncompressed and compressed file data */\r
+ if( (*pfnfcis)(statusFile, cfdata->cbData, cfdata->cbUncomp,\r
+ p_fci_internal->pv) == -1) {\r
+ /* TODO set error code and abort */\r
+ return FALSE;\r
+ }\r
+\r
+ ++(p_fci_internal->cDataBlocks);\r
+\r
+ return TRUE;\r
+} /* end of fci_flush_data_block */\r
+\r
+\r
+\r
+\r
+\r
+static cab_ULONG fci_get_checksum(void *pv, UINT cb, CHECKSUM seed)\r
+{\r
+ cab_ULONG csum;\r
+ cab_ULONG ul;\r
+ int cUlong;\r
+ BYTE *pb;\r
+\r
+ csum = seed;\r
+ cUlong = cb / 4;\r
+ pb = pv;\r
+\r
+ while (cUlong-- > 0) {\r
+ ul = *pb++;\r
+ ul |= (((cab_ULONG)(*pb++)) << 8);\r
+ ul |= (((cab_ULONG)(*pb++)) << 16);\r
+ ul |= (((cab_ULONG)(*pb++)) << 24);\r
+\r
+ csum ^= ul;\r
+ }\r
+\r
+ ul = 0;\r
+ switch (cb % 4) {\r
+ case 3:\r
+ ul |= (((ULONG)(*pb++)) << 16);\r
+ case 2:\r
+ ul |= (((ULONG)(*pb++)) << 8);\r
+ case 1:\r
+ ul |= *pb++;\r
+ default:\r
+ break;\r
+ }\r
+ csum ^= ul;\r
+\r
+ return csum;\r
+} /* end of fci_get_checksum */\r
+\r
+\r
+\r
+\r
+\r
+static BOOL fci_flushfolder_copy_cfdata(HFCI hfci, char* buffer, UINT cbReserveCFData,\r
+ PFNFCISTATUS pfnfcis, int* err, int handleCFDATA1new,\r
+ cab_ULONG* psizeFileCFDATA1new, cab_ULONG* payload)\r
+{\r
+ cab_ULONG read_result;\r
+ CFDATA* pcfdata=(CFDATA*)buffer;\r
+ BOOL split_block=FALSE;\r
+ cab_UWORD savedUncomp=0;\r
+ PFCI_Int p_fci_internal=((PFCI_Int)(hfci));\r
+\r
+ *payload=0;\r
+\r
+ /* while not all CFDATAs have been copied do */\r
+ while(!FALSE) {\r
+ if( p_fci_internal->fNextCab ) {\r
+ if( split_block ) {\r
+ /* TODO internal error should never happen */\r
+ return FALSE;\r
+ }\r
+ }\r
+ /* REUSE the variable read_result */\r
+ if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ read_result=4;\r
+ } else {\r
+ read_result=0;\r
+ }\r
+ if (p_fci_internal->fPrevCab) {\r
+ read_result+=strlen(p_fci_internal->szPrevCab)+1 +\r
+ strlen(p_fci_internal->szPrevDisk)+1;\r
+ }\r
+ /* No more CFDATA fits into the cabinet under construction */\r
+ /* So don't try to store more data into it */\r
+ if( p_fci_internal->fNextCab &&\r
+ (p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData +\r
+ p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +\r
+ p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +\r
+ sizeof(CFHEADER) +\r
+ read_result +\r
+ p_fci_internal->oldCCAB.cbReserveCFHeader +\r
+ sizeof(CFFOLDER) +\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder +\r
+ strlen(p_fci_internal->pccab->szCab)+1 +\r
+ strlen(p_fci_internal->pccab->szDisk)+1\r
+ )) {\r
+ /* This may never be run for the first time the while loop is entered.\r
+ Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/\r
+ split_block=TRUE; /* In this case split_block is abused to store */\r
+ /* the complete data block into the next cabinet and not into the */\r
+ /* current one. Originally split_block is the indicator that a */\r
+ /* data block has been splitted across different cabinets. */\r
+ } else {\r
+\r
+ /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/\r
+ read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/*file handle*/\r
+ buffer, /* memory buffer */\r
+ sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */\r
+ err, p_fci_internal->pv);\r
+ if (read_result!=sizeof(CFDATA)+cbReserveCFData) {\r
+ if (read_result==0) break; /* ALL DATA has been copied */\r
+ /* TODO read error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* REUSE buffer p_fci_internal->data_out !!! */\r
+ /* read data from p_fci_internal->handleCFDATA1 to */\r
+ /* p_fci_internal->data_out */\r
+ if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,\r
+ p_fci_internal->data_out /* memory buffer */,\r
+ pcfdata->cbData /* number of bytes to copy */,\r
+ err, p_fci_internal->pv) != pcfdata->cbData ) {\r
+ /* TODO read error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* if cabinet size is too large */\r
+\r
+ /* REUSE the variable read_result */\r
+ if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ read_result=4;\r
+ } else {\r
+ read_result=0;\r
+ }\r
+ if (p_fci_internal->fPrevCab) {\r
+ read_result+=strlen(p_fci_internal->szPrevCab)+1 +\r
+ strlen(p_fci_internal->szPrevDisk)+1;\r
+ }\r
+\r
+ /* Is cabinet with new CFDATA too large? Then data block has to be split */\r
+ if( p_fci_internal->fNextCab &&\r
+ (p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData +\r
+ pcfdata->cbData +\r
+ p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +\r
+ p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +\r
+ sizeof(CFHEADER) +\r
+ read_result +\r
+ p_fci_internal->oldCCAB.cbReserveCFHeader +\r
+ sizeof(CFFOLDER) + /* size of new CFFolder entry */\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder +\r
+ strlen(p_fci_internal->pccab->szCab)+1 + /* name of next cabinet */\r
+ strlen(p_fci_internal->pccab->szDisk)+1 /* name of next disk */\r
+ )) {\r
+ /* REUSE read_result to save the size of the compressed data */\r
+ read_result=pcfdata->cbData;\r
+ /* Modify the size of the compressed data to store only a part of the */\r
+ /* data block into the current cabinet. This is done to prevent */\r
+ /* that the maximum cabinet size will be exceeded. The remainer */\r
+ /* will be stored into the next following cabinet. */\r
+\r
+ /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */\r
+ /* Substract everything except the size of the block of data */\r
+ /* to get it's actual size */\r
+ pcfdata->cbData = p_fci_internal->oldCCAB.cb - (\r
+ sizeof(CFDATA) + cbReserveCFData +\r
+ p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +\r
+ p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +\r
+ sizeof(CFHEADER) +\r
+ p_fci_internal->oldCCAB.cbReserveCFHeader +\r
+ sizeof(CFFOLDER) + /* set size of new CFFolder entry */\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder );\r
+ /* substract the size of special header fields */\r
+ if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ pcfdata->cbData-=4;\r
+ }\r
+ if (p_fci_internal->fPrevCab) {\r
+ pcfdata->cbData-=strlen(p_fci_internal->szPrevCab)+1 +\r
+ strlen(p_fci_internal->szPrevDisk)+1;\r
+ }\r
+ pcfdata->cbData-=strlen(p_fci_internal->pccab->szCab)+1 +\r
+ strlen(p_fci_internal->pccab->szDisk)+1;\r
+\r
+ savedUncomp = pcfdata->cbUncomp;\r
+ pcfdata->cbUncomp = 0; /* on splitted blocks of data this is zero */\r
+\r
+ /* if split_block==TRUE then the above while loop won't */\r
+ /* be executed again */\r
+ split_block=TRUE; /* split_block is the indicator that */\r
+ /* a data block has been splitted across */\r
+ /* diffentent cabinets.*/\r
+ }\r
+\r
+ /* This should never happen !!! */\r
+ if (pcfdata->cbData==0) {\r
+ /* TODO set error */\r
+ return FALSE;\r
+ }\r
+\r
+ /* get checksum and write to cfdata.csum */\r
+ pcfdata->csum = fci_get_checksum( &(pcfdata->cbData),\r
+ sizeof(CFDATA)+cbReserveCFData -\r
+ sizeof(pcfdata->csum), fci_get_checksum( p_fci_internal->data_out, /*buffer*/\r
+ pcfdata->cbData, 0 ) );\r
+\r
+ /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */\r
+ buffer, /* memory buffer */\r
+ sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->sizeFileCFDATA2 += sizeof(CFDATA)+cbReserveCFData;\r
+\r
+ /* write compressed data into p_fci_internal->handleCFDATA2 */\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */\r
+ p_fci_internal->data_out, /* memory buffer */\r
+ pcfdata->cbData, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != pcfdata->cbData) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->sizeFileCFDATA2 += pcfdata->cbData;\r
+ ++(p_fci_internal->cDataBlocks);\r
+ p_fci_internal->statusFolderCopied += pcfdata->cbData;\r
+ (*payload)+=pcfdata->cbUncomp;\r
+ /* if cabinet size too large and data has been split */\r
+ /* write the remainer of the data block to the new CFDATA1 file */\r
+ if( split_block ) { /* This does not include the */\r
+ /* abused one (just search for "abused" )*/\r
+ /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */\r
+ if (p_fci_internal->fNextCab==FALSE ) {\r
+ /* TODO internal error */\r
+ return FALSE;\r
+ }\r
+\r
+ /* set cbData the size of the remainer of the data block */\r
+ pcfdata->cbData = read_result - pcfdata->cbData;\r
+ /*recover former value of cfdata.cbData; read_result will be the offset*/\r
+ read_result -= pcfdata->cbData;\r
+ pcfdata->cbUncomp = savedUncomp;\r
+\r
+ /* reset checksum, it will be computed later */\r
+ pcfdata->csum=0;\r
+ /* write cfdata WITHOUT checksum to handleCFDATA1new */\r
+ if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */\r
+ buffer, /* memory buffer */\r
+ sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */\r
+\r
+ *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;\r
+\r
+ /* write compressed data into handleCFDATA1new */\r
+ if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */\r
+ p_fci_internal->data_out + read_result, /* memory buffer + offset */\r
+ /* to last part of split data */\r
+ pcfdata->cbData, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != pcfdata->cbData) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->statusFolderCopied += pcfdata->cbData;\r
+\r
+ *psizeFileCFDATA1new += pcfdata->cbData;\r
+ /* the two blocks of the split data block have been written */\r
+ /* dont reset split_data yet, because it is still needed see below */\r
+ }\r
+\r
+ /* report status with pfnfcis about copied size of folder */\r
+ if( (*pfnfcis)(statusFolder,\r
+ p_fci_internal->statusFolderCopied, /*cfdata.cbData(+previous ones)*/\r
+ p_fci_internal->statusFolderTotal, /* total folder size */\r
+ p_fci_internal->pv) == -1) {\r
+ /* TODO set error code and abort */\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ /* if cabinet size too large */\r
+ /* write the remaining data blocks to the new CFDATA1 file */\r
+ if ( split_block ) { /* This does include the */\r
+ /* abused one (just search for "abused" )*/\r
+ if (p_fci_internal->fNextCab==FALSE ) {\r
+ /* TODO internal error */\r
+ return FALSE;\r
+ }\r
+ /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */\r
+ while(!FALSE) {\r
+ /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/\r
+ read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/* handle */\r
+ buffer, /* memory buffer */\r
+ sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */\r
+ err, p_fci_internal->pv);\r
+ if (read_result!=sizeof(CFDATA)+cbReserveCFData) {\r
+ if (read_result==0) break; /* ALL DATA has been copied */\r
+ /* TODO read error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* REUSE buffer p_fci_internal->data_out !!! */\r
+ /* read data from p_fci_internal->handleCFDATA1 to */\r
+ /* p_fci_internal->data_out */\r
+ if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,\r
+ p_fci_internal->data_out /* memory buffer */,\r
+ pcfdata->cbData /* number of bytes to copy */,\r
+ err, p_fci_internal->pv) != pcfdata->cbData ) {\r
+ /* TODO read error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */\r
+\r
+ /* write cfdata with checksum to handleCFDATA1new */\r
+ if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */\r
+ buffer, /* memory buffer */\r
+ sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */\r
+\r
+ *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;\r
+\r
+ /* write compressed data into handleCFDATA1new */\r
+ if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */\r
+ p_fci_internal->data_out, /* memory buffer */\r
+ pcfdata->cbData, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != pcfdata->cbData) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ *psizeFileCFDATA1new += pcfdata->cbData;\r
+ p_fci_internal->statusFolderCopied += pcfdata->cbData;\r
+\r
+ /* report status with pfnfcis about copied size of folder */\r
+ if( (*pfnfcis)(statusFolder,\r
+ p_fci_internal->statusFolderCopied,/*cfdata.cbData(+revious ones)*/\r
+ p_fci_internal->statusFolderTotal, /* total folder size */\r
+ p_fci_internal->pv) == -1) {\r
+ /* TODO set error code and abort */\r
+ return FALSE;\r
+ }\r
+\r
+ } /* end of WHILE */\r
+ break; /* jump out of the next while loop */\r
+ } /* end of if( split_data ) */\r
+ } /* end of WHILE */\r
+ return TRUE;\r
+} /* end of fci_flushfolder_copy_cfdata */\r
+\r
+\r
+\r
+\r
+\r
+static BOOL fci_flushfolder_copy_cffolder(HFCI hfci, int* err, UINT cbReserveCFFolder,\r
+ cab_ULONG sizeFileCFDATA2old)\r
{\r
- FIXME("(%p, %p, %p, %d, %p, %p, %p, %hu): stub\n", hfci, pszSourceFile,\r
- pszFileName, fExecute, pfnfcignc, pfnfcis, pfnfcigoi, typeCompress);\r
+ CFFOLDER cffolder;\r
+ UINT i;\r
+ char* reserved;\r
+ PFCI_Int p_fci_internal=((PFCI_Int)(hfci));\r
+\r
+ /* absolute offset cannot be set yet, because the size of cabinet header, */\r
+ /* the number of CFFOLDERs and the number of CFFILEs may change. */\r
+ /* Instead the size of all previous data blocks will be stored and */\r
+ /* the remainer of the offset will be added when the cabinet will be */\r
+ /* flushed to disk. */\r
+ /* This is exactly the way the original CABINET.DLL works!!! */\r
+ cffolder.coffCabStart=sizeFileCFDATA2old;\r
\r
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\r
+ /* set the number of this folder's CFDATA sections */\r
+ cffolder.cCFData=p_fci_internal->cDataBlocks;\r
+ /* TODO set compression type */\r
+ cffolder.typeCompress = tcompTYPE_NONE;\r
\r
+ /* write cffolder to p_fci_internal->handleCFFOLDER */\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */\r
+ &cffolder, /* memory buffer */\r
+ sizeof(cffolder), /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != sizeof(cffolder) ) {\r
+ /* TODO write error */\r
return FALSE;\r
-}\r
+ }\r
+ /* TODO error handling of err */\r
\r
-/***********************************************************************\r
- * FCIFlushCabinet (CABINET.13)\r
- */\r
-BOOL __cdecl FCIFlushCabinet(\r
+ p_fci_internal->sizeFileCFFOLDER += sizeof(cffolder);\r
+\r
+ /* add optional reserved area */\r
+ if (cbReserveCFFolder!=0) {\r
+ if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFFolder))) {\r
+ p_fci_internal->perf->erfOper = FCIERR_ALLOC_FAIL;\r
+ p_fci_internal->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;\r
+ p_fci_internal->perf->fError = TRUE;\r
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);\r
+ return FALSE;\r
+ }\r
+ for(i=0;i<cbReserveCFFolder;) {\r
+ reserved[i++]='\0';\r
+ }\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */\r
+ reserved, /* memory buffer */\r
+ cbReserveCFFolder, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != cbReserveCFFolder ) {\r
+ PFCI_FREE(hfci, reserved);\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->sizeFileCFFOLDER += cbReserveCFFolder;\r
+\r
+ PFCI_FREE(hfci, reserved);\r
+ }\r
+ return TRUE;\r
+} /* end of fci_flushfolder_copy_cffolder */\r
+\r
+\r
+\r
+\r
+\r
+static BOOL fci_flushfolder_copy_cffile(HFCI hfci, int* err, int handleCFFILE1new,\r
+ cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload)\r
+{\r
+ CFFILE cffile;\r
+ cab_ULONG read_result;\r
+ cab_ULONG seek=0;\r
+ cab_ULONG sizeOfFiles=0, sizeOfFilesPrev;\r
+ BOOL may_be_prev=TRUE;\r
+ cab_ULONG cbFileRemainer=0;\r
+ PFCI_Int p_fci_internal=((PFCI_Int)(hfci));\r
+ /* set seek of p_fci_internal->handleCFFILE1 to 0 */\r
+ if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,0,SEEK_SET,err,\r
+ p_fci_internal->pv) !=0 ) {\r
+ /* TODO wrong return value */\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* while not all CFFILE structures have been copied do */\r
+ while(!FALSE) {\r
+ /* REUSE the variable read_result */\r
+ /* read data from p_fci_internal->handleCFFILE1 to cffile */\r
+ read_result = PFCI_READ(hfci,p_fci_internal->handleCFFILE1/* file handle */,\r
+ &cffile, /* memory buffer */\r
+ sizeof(cffile), /* number of bytes to copy */\r
+ err, p_fci_internal->pv);\r
+ if( read_result != sizeof(cffile) ) {\r
+ if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */\r
+ /* TODO read error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* Microsoft's(R) CABINET.DLL would do a seek to the current! */\r
+ /* position. I don't know why so I'll just omit it */\r
+\r
+ /* read the filename from p_fci_internal->handleCFFILE1 */\r
+ /* REUSE the variable read_result AGAIN */\r
+ /* REUSE the memory buffer PFCI(hfci)->data_out */\r
+ if( PFCI_READ(hfci, p_fci_internal->handleCFFILE1 /*file handle*/,\r
+ p_fci_internal->data_out, /* memory buffer */\r
+ CB_MAX_FILENAME, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) <2) {\r
+ /* TODO read error */\r
+ return FALSE;\r
+ }\r
+ /* TODO maybe other checks of read_result */\r
+ /* TODO error handling of err */\r
+\r
+ /* safety */\r
+ if( strlen(p_fci_internal->data_out)>=CB_MAX_FILENAME ) {\r
+ /* TODO set error code internal error */\r
+ return FALSE;\r
+ }\r
+\r
+ seek+=sizeof(cffile) + strlen(p_fci_internal->data_out)+1;\r
+\r
+ /* set seek of p_fci_internal->handleCFFILE1 to end of file name */\r
+ /* i.e. seek to the next CFFILE area */\r
+ if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,\r
+ seek, /* seek position*/\r
+ SEEK_SET ,err,\r
+ p_fci_internal->pv)\r
+ != sizeof(cffile)+strlen(p_fci_internal->data_out)+1 ) {\r
+ /* TODO wrong return value */\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* fnfilfnfildest: placed file on cabinet */\r
+ if (p_fci_internal->fNextCab ||\r
+ p_fci_internal->fGetNextCabInVain) {\r
+ PFCI_FILEPLACED( hfci, &(p_fci_internal->oldCCAB),\r
+ p_fci_internal->data_out, /* the file name*/\r
+ cffile.cbFile, /* file size */\r
+ (cffile.iFolder==cffileCONTINUED_FROM_PREV),\r
+ p_fci_internal->pv\r
+ );\r
+ } else {\r
+ PFCI_FILEPLACED( hfci, p_fci_internal->pccab,\r
+ p_fci_internal->data_out, /* the file name*/\r
+ cffile.cbFile, /* file size */\r
+ (cffile.iFolder==cffileCONTINUED_FROM_PREV),\r
+ p_fci_internal->pv\r
+ );\r
+ }\r
+\r
+ /* Check special iFolder values */\r
+ if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&\r
+ p_fci_internal->fPrevCab==FALSE ) {\r
+ /* THIS MAY NEVER HAPPEN */\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||\r
+ cffile.iFolder==cffileCONTINUED_TO_NEXT ) {\r
+ /* THIS MAY NEVER HAPPEN */\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ if( may_be_prev && cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {\r
+ may_be_prev=FALSE;\r
+ }\r
+ if( cffile.iFolder==cffileCONTINUED_FROM_PREV && may_be_prev==FALSE ) {\r
+ /* THIS MAY NEVER HAPPEN */\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ if( cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {\r
+ may_be_prev=FALSE;\r
+ }\r
+\r
+ sizeOfFilesPrev=sizeOfFiles;\r
+ /* Set complete size of all processed files */\r
+ if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&\r
+ p_fci_internal->cbFileRemainer!=0\r
+ ) {\r
+ sizeOfFiles+=p_fci_internal->cbFileRemainer;\r
+ p_fci_internal->cbFileRemainer=0;\r
+ } else {\r
+ sizeOfFiles+=cffile.cbFile;\r
+ }\r
+\r
+ /* Check if spanned file fits into this cabinet folder */\r
+ if( cffile.iFolder==cffileCONTINUED_FROM_PREV && sizeOfFiles>payload ) {\r
+ cffile.iFolder=cffileCONTINUED_PREV_AND_NEXT;\r
+ } else\r
+\r
+ /* Check if file doesn't fit into this cabinet folder */\r
+ if( sizeOfFiles>payload ) {\r
+ cffile.iFolder=cffileCONTINUED_TO_NEXT;\r
+ }\r
+\r
+ /* write cffile to p_fci_internal->handleCFFILE2 */\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */\r
+ &cffile, /* memory buffer */\r
+ sizeof(cffile), /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != sizeof(cffile) ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->sizeFileCFFILE2 += sizeof(cffile);\r
+\r
+ /* write file name to p_fci_internal->handleCFFILE2 */\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */\r
+ p_fci_internal->data_out, /* memory buffer */\r
+ strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->sizeFileCFFILE2 += strlen(p_fci_internal->data_out)+1;\r
+\r
+ /* cFiles is used to count all files of a cabinet */\r
+ ++(p_fci_internal->cFiles);\r
+\r
+ /* This is only true for files which will be written into the */\r
+ /* next cabinet of the spanning folder */\r
+ if( sizeOfFiles>payload ) {\r
+\r
+ /* Files which data will be partially written into the current cabinet */\r
+ if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||\r
+ cffile.iFolder==cffileCONTINUED_TO_NEXT\r
+ ) {\r
+ if( sizeOfFilesPrev<=payload ) {\r
+ /* The size of the uncompressed, data of a spanning file in a */\r
+ /* spanning data */\r
+ cbFileRemainer=sizeOfFiles-payload;\r
+ }\r
+ cffile.iFolder=cffileCONTINUED_FROM_PREV;\r
+ } else {\r
+ cffile.iFolder=0;\r
+ }\r
+\r
+ /* write cffile into handleCFFILE1new */\r
+ if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */\r
+ &cffile, /* memory buffer */\r
+ sizeof(cffile), /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != sizeof(cffile) ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ *psizeFileCFFILE1new += sizeof(cffile);\r
+ /* write name of file into handleCFFILE1new */\r
+ if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */\r
+ p_fci_internal->data_out, /* memory buffer */\r
+ strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */\r
+ err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ *psizeFileCFFILE1new += strlen(p_fci_internal->data_out)+1;\r
+ }\r
+\r
+ } /* END OF while */\r
+ p_fci_internal->cbFileRemainer=cbFileRemainer;\r
+ return TRUE;\r
+} /* end of fci_flushfolder_copy_cffile */\r
+\r
+\r
+\r
+\r
+static BOOL fci_flush_folder(\r
HFCI hfci,\r
BOOL fGetNextCab,\r
PFNFCIGETNEXTCABINET pfnfcignc,\r
PFNFCISTATUS pfnfcis)\r
{\r
- FIXME("(%p, %d, %p, %p): stub\n", hfci, fGetNextCab, pfnfcignc, pfnfcis);\r
+ int err;\r
+ int handleCFDATA1new; /* handle for new temp file */\r
+ char szFileNameCFDATA1new[CB_MAX_FILENAME]; /* name buffer for temp file */\r
+ int handleCFFILE1new; /* handle for new temp file */\r
+ char szFileNameCFFILE1new[CB_MAX_FILENAME]; /* name buffer for temp file */\r
+ UINT cbReserveCFData, cbReserveCFFolder;\r
+ char* reserved;\r
+ cab_ULONG sizeFileCFDATA1new=0;\r
+ cab_ULONG sizeFileCFFILE1new=0;\r
+ cab_ULONG sizeFileCFDATA2old;\r
+ cab_ULONG payload;\r
+ cab_ULONG read_result;\r
+ PFCI_Int p_fci_internal=((PFCI_Int)(hfci));\r
+\r
+ /* test hfci */\r
+ if (!REALLY_IS_FCI(hfci)) {\r
+ SetLastError(ERROR_INVALID_HANDLE);\r
+ return FALSE;\r
+ }\r
\r
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\r
+ if ((!pfnfcignc) || (!pfnfcis)) {\r
+ p_fci_internal->perf->erfOper = FCIERR_NONE;\r
+ p_fci_internal->perf->erfType = ERROR_BAD_ARGUMENTS;\r
+ p_fci_internal->perf->fError = TRUE;\r
\r
+ SetLastError(ERROR_BAD_ARGUMENTS);\r
return FALSE;\r
-}\r
+ }\r
\r
-/***********************************************************************\r
- * FCIFlushFolder (CABINET.12)\r
- */\r
-BOOL __cdecl FCIFlushFolder(\r
- HFCI hfci,\r
- PFNFCIGETNEXTCABINET pfnfcignc,\r
- PFNFCISTATUS pfnfcis)\r
-{\r
- FIXME("(%p, %p, %p): stub\n", hfci, pfnfcignc, pfnfcis);\r
+ if( p_fci_internal->fGetNextCabInVain &&\r
+ p_fci_internal->fNextCab ){\r
+ /* TODO internal error */\r
+ return FALSE;\r
+ }\r
+\r
+ /* If there was no FCIAddFile or FCIFlushFolder has already been called */\r
+ /* this function will return TRUE */\r
+ if( p_fci_internal->sizeFileCFFILE1 == 0 ) {\r
+ if ( p_fci_internal->sizeFileCFDATA1 != 0 ) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ return TRUE;\r
+ }\r
\r
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\r
+ if (p_fci_internal->data_in==NULL || p_fci_internal->data_out==NULL ) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+\r
+ /* FCIFlushFolder has already been called... */\r
+ if (p_fci_internal->fSplitFolder && p_fci_internal->sizeFileCFFILE2!=0) {\r
+ if (p_fci_internal->sizeFileCFFILE2==0) {\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ return TRUE;\r
+ }\r
+\r
+ /* TODO check what will happen when return FALSE later */\r
+ /* and p_fci_internal->fSplitFolder is set to FALSE */\r
+ p_fci_internal->fSplitFolder=FALSE;\r
+\r
+\r
+ if( p_fci_internal->fGetNextCabInVain ||\r
+ p_fci_internal->fNextCab ){\r
+ cbReserveCFData = p_fci_internal->oldCCAB.cbReserveCFData;\r
+ cbReserveCFFolder = p_fci_internal->oldCCAB.cbReserveCFFolder;\r
+ } else {\r
+ cbReserveCFData = p_fci_internal->pccab->cbReserveCFData;\r
+ cbReserveCFFolder = p_fci_internal->pccab->cbReserveCFFolder;\r
+ }\r
+\r
+ /* START of COPY */\r
+ /* if there is data in p_fci_internal->data_in */\r
+ if (p_fci_internal->cdata_in!=0) {\r
+\r
+ if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;\r
+\r
+ }\r
+ /* reset to get the number of data blocks of this folder which are */\r
+ /* actually in this cabinet ( at least partially ) */\r
+ p_fci_internal->cDataBlocks=0;\r
+\r
+ if ( p_fci_internal->fNextCab ||\r
+ p_fci_internal->fGetNextCabInVain ) {\r
+ read_result= p_fci_internal->oldCCAB.cbReserveCFHeader+\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder;\r
+ if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ read_result+=4;\r
+ }\r
+ } else {\r
+ read_result= p_fci_internal->pccab->cbReserveCFHeader+\r
+ p_fci_internal->pccab->cbReserveCFFolder;\r
+ if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFFolder != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFData != 0 ) {\r
+ read_result+=4;\r
+ }\r
+ }\r
+ if (p_fci_internal->fPrevCab) {\r
+ read_result+=strlen(p_fci_internal->szPrevCab)+1 +\r
+ strlen(p_fci_internal->szPrevDisk)+1;\r
+ }\r
+ if (p_fci_internal->fNextCab) {\r
+ read_result+=strlen(p_fci_internal->pccab->szCab)+1 +\r
+ strlen(p_fci_internal->pccab->szDisk)+1;\r
+ }\r
\r
+ p_fci_internal->statusFolderTotal = sizeof(CFHEADER)+read_result+\r
+ sizeof(CFFOLDER) + p_fci_internal->sizeFileCFFILE2+\r
+ p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1+\r
+ p_fci_internal->sizeFileCFDATA1;\r
+ p_fci_internal->statusFolderCopied = 0;\r
+\r
+ /* report status with pfnfcis about copied size of folder */\r
+ if( (*pfnfcis)(statusFolder, p_fci_internal->statusFolderCopied,\r
+ p_fci_internal->statusFolderTotal, /* TODO total folder size */\r
+ p_fci_internal->pv) == -1) {\r
+ /* TODO set error code and abort */\r
return FALSE;\r
-}\r
+ }\r
\r
-/***********************************************************************\r
- * FCIDestroy (CABINET.14)\r
- *\r
- * Frees a handle created by FCICreate.\r
- * Only reason for failure would be an invalid handle.\r
- *\r
- * PARAMS\r
- * hfci [I] The HFCI to free\r
- *\r
- * RETURNS\r
- * TRUE for success\r
- * FALSE for failure\r
- */\r
-BOOL __cdecl FCIDestroy(HFCI hfci)\r
-{\r
- if (REALLY_IS_FCI(hfci)) {\r
- PFCI_INT(hfci)->FCI_Intmagic = 0;\r
- PFDI_FREE(hfci, hfci);\r
- /*return TRUE; */\r
+ /* get a new temp file */\r
+ if(!PFCI_GETTEMPFILE(hfci,szFileNameCFDATA1new,CB_MAX_FILENAME)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* safety */\r
+ if ( strlen(szFileNameCFDATA1new) >= CB_MAX_FILENAME ) {\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ handleCFDATA1new = PFCI_OPEN(hfci,szFileNameCFDATA1new,34050,384,&err,\r
+ p_fci_internal->pv);\r
+\r
+ /* get a new temp file */\r
+ if(!PFCI_GETTEMPFILE(hfci,szFileNameCFFILE1new,CB_MAX_FILENAME)) {\r
+ /* TODO error handling */\r
+ PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ return FALSE;\r
+ }\r
+ /* safety */\r
+ if ( strlen(szFileNameCFFILE1new) >= CB_MAX_FILENAME ) {\r
+ /* TODO set error code */\r
+ PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ return FALSE;\r
+ }\r
+ handleCFFILE1new = PFCI_OPEN(hfci,szFileNameCFFILE1new,34050,384,&err,\r
+ p_fci_internal->pv);\r
+\r
+ /* USE the variable read_result */\r
+ if ( p_fci_internal->fNextCab ||\r
+ p_fci_internal->fGetNextCabInVain ) {\r
+ read_result= p_fci_internal->oldCCAB.cbReserveCFHeader;\r
+ if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ read_result+=4;\r
+ }\r
+ } else {\r
+ read_result= p_fci_internal->pccab->cbReserveCFHeader;\r
+ if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFFolder != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFData != 0 ) {\r
+ read_result+=4;\r
+ }\r
+ }\r
+ if (p_fci_internal->fPrevCab) {\r
+ read_result+=strlen(p_fci_internal->szPrevCab)+1 +\r
+ strlen(p_fci_internal->szPrevDisk)+1;\r
+ }\r
+ read_result+= sizeof(CFHEADER) + p_fci_internal->sizeFileCFDATA2 +\r
+ p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER;\r
+\r
+ if(p_fci_internal->sizeFileCFFILE1!=0) {\r
+ read_result+= sizeof(CFFOLDER)+p_fci_internal->pccab->cbReserveCFFolder;\r
+ }\r
+\r
+ /* Check if multiple cabinets have to be created. */\r
+\r
+ /* Might be too much data for the maximum allowed cabinet size.*/\r
+ /* When any further data will be added later, it might not */\r
+ /* be possible to flush the cabinet, because there might */\r
+ /* not be enough space to store the name of the following */\r
+ /* cabinet and name of the corresponding disk. */\r
+ /* So take care of this and get the name of the next cabinet */\r
+ if( p_fci_internal->fGetNextCabInVain==FALSE &&\r
+ p_fci_internal->fNextCab==FALSE &&\r
+ (\r
+ (\r
+ p_fci_internal->pccab->cb < read_result +\r
+ p_fci_internal->sizeFileCFDATA1 +\r
+ p_fci_internal->sizeFileCFFILE1 +\r
+ CB_MAX_CABINET_NAME + /* next cabinet name */\r
+ CB_MAX_DISK_NAME /* next disk name */\r
+ ) || fGetNextCab\r
+ )\r
+ ) {\r
+ /* save CCAB */\r
+ memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));\r
+ /* increment cabinet index */\r
+ ++(p_fci_internal->pccab->iCab);\r
+ /* get name of next cabinet */\r
+ if (!(*pfnfcignc)(p_fci_internal->pccab, 0, /* estimated size of cab */\r
+ p_fci_internal->pv)) {\r
+ /* TODO error handling */\r
+ PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ return FALSE;\r
+ }\r
+\r
+ /* Skip a few lines of code. This is catched by the next if. */\r
+ p_fci_internal->fGetNextCabInVain=TRUE;\r
+ }\r
+\r
+ /* too much data for cabinet */\r
+ if( (p_fci_internal->fGetNextCabInVain ||\r
+ p_fci_internal->fNextCab ) &&\r
+ (\r
+ (\r
+ p_fci_internal->oldCCAB.cb < read_result +\r
+ p_fci_internal->sizeFileCFDATA1 +\r
+ p_fci_internal->sizeFileCFFILE1 +\r
+ strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */\r
+ strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */\r
+ ) || fGetNextCab\r
+ )\r
+ ) {\r
+ p_fci_internal->fGetNextCabInVain=FALSE;\r
+ p_fci_internal->fNextCab=TRUE;\r
+\r
+ /* return FALSE if there is not enough space left*/\r
+ /* this should never happen */\r
+ if (p_fci_internal->oldCCAB.cb <=\r
+ p_fci_internal->sizeFileCFFILE1 +\r
+ read_result +\r
+ strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */\r
+ strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */\r
+ ) {\r
+\r
+ PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+\r
+ /* close and delete p_fci_internal->handleCFFILE1 */\r
+ PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+\r
+ return FALSE;\r
+ }\r
+\r
+ /* the folder will be split across cabinets */\r
+ p_fci_internal->fSplitFolder=TRUE;\r
+\r
+ } else {\r
+ /* this should never happen */\r
+ if (p_fci_internal->fNextCab) {\r
+ /* TODO internal error */\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ /* set seek of p_fci_internal->handleCFDATA1 to 0 */\r
+ if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA1,0,SEEK_SET,&err,\r
+ p_fci_internal->pv) !=0 ) {\r
+ /* TODO wrong return value */\r
+ PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* save size of file CFDATA2 - required for the folder's offset to data */\r
+ sizeFileCFDATA2old = p_fci_internal->sizeFileCFDATA2;\r
+\r
+ if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData+sizeof(CFDATA)))) {\r
+ p_fci_internal->perf->erfOper = FCIERR_ALLOC_FAIL;\r
+ p_fci_internal->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;\r
+ p_fci_internal->perf->fError = TRUE;\r
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);\r
+ PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ return FALSE;\r
+ }\r
+\r
+ if(!fci_flushfolder_copy_cfdata(hfci, reserved, cbReserveCFData, pfnfcis, &err,\r
+ handleCFDATA1new, &sizeFileCFDATA1new, &payload\r
+ )) {\r
+ PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_FREE(hfci,reserved);\r
+ return FALSE;\r
+ }\r
+\r
+ PFCI_FREE(hfci,reserved);\r
+\r
+ if(!fci_flushfolder_copy_cffolder(hfci, &err, cbReserveCFFolder,\r
+ sizeFileCFDATA2old )) {\r
+ PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ return FALSE;\r
+ }\r
+\r
+ if(!fci_flushfolder_copy_cffile(hfci, &err, handleCFFILE1new,\r
+ &sizeFileCFFILE1new, payload)) {\r
+ PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ return FALSE;\r
+ }\r
+\r
+ /* close and delete p_fci_internal->handleCFDATA1 */\r
+ PFCI_CLOSE(hfci,p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci,p_fci_internal->szFileNameCFDATA1,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+\r
+ /* put new CFDATA1 into hfci */\r
+ memcpy(p_fci_internal->szFileNameCFDATA1,szFileNameCFDATA1new,\r
+ CB_MAX_FILENAME);\r
+\r
+ /* put CFDATA1 file handle */\r
+ PFCI_INT(hfci)->handleCFDATA1 = handleCFDATA1new;\r
+ /* set file size */\r
+ PFCI_INT(hfci)->sizeFileCFDATA1 = sizeFileCFDATA1new;\r
+\r
+ /* close and delete PFCI_INT(hfci)->handleCFFILE1 */\r
+ PFCI_CLOSE(hfci,p_fci_internal->handleCFFILE1,&err,PFCI_INT(hfci)->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci,p_fci_internal->szFileNameCFFILE1,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+\r
+ /* put new CFFILE1 into hfci */\r
+ memcpy(p_fci_internal->szFileNameCFFILE1,szFileNameCFFILE1new,\r
+ CB_MAX_FILENAME);\r
+\r
+ /* put CFFILE1 file handle */\r
+ p_fci_internal->handleCFFILE1 = handleCFFILE1new;\r
+ /* set file size */\r
+ p_fci_internal->sizeFileCFFILE1 = sizeFileCFFILE1new;\r
+\r
+ ++(p_fci_internal->cFolders);\r
+\r
+ /* reset CFFolder specific information */\r
+ p_fci_internal->cDataBlocks=0;\r
+ p_fci_internal->cCompressedBytesInFolder=0;\r
+\r
+ return TRUE;\r
+} /* end of fci_flush_folder */\r
+\r
+\r
+\r
+\r
+static BOOL fci_flush_cabinet(\r
+ HFCI hfci,\r
+ BOOL fGetNextCab,\r
+ PFNFCIGETNEXTCABINET pfnfcignc,\r
+ PFNFCISTATUS pfnfcis)\r
+{\r
+ int err;\r
+ CFHEADER cfheader;\r
+ struct {\r
+ cab_UWORD cbCFHeader;\r
+ cab_UBYTE cbCFFolder;\r
+ cab_UBYTE cbCFData;\r
+ } cfreserved;\r
+ CFFOLDER cffolder;\r
+ cab_ULONG read_result;\r
+ int handleCABINET; /* file handle for cabinet */\r
+ char pszFileNameCABINET[CB_MAX_CAB_PATH+CB_MAX_CABINET_NAME];/* name buffer */\r
+ UINT cbReserveCFHeader, cbReserveCFFolder, i;\r
+ char* reserved;\r
+ BOOL returntrue=FALSE;\r
+ PFCI_Int p_fci_internal=((PFCI_Int)(hfci));\r
+\r
+ /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */\r
+\r
+ /* when FCIFlushCabinet was or FCIAddFile wasn't called */\r
+ if( p_fci_internal->sizeFileCFFILE1==0 && fGetNextCab ) {\r
+ returntrue=TRUE;\r
+ }\r
+\r
+ if (!fci_flush_folder(hfci,fGetNextCab,pfnfcignc,pfnfcis)){\r
+ /* TODO set error */\r
+ return FALSE;\r
+ }\r
+\r
+ if(returntrue) return TRUE;\r
+\r
+ if (p_fci_internal->fSplitFolder && p_fci_internal->fNextCab==FALSE) {\r
+ /* TODO internal error */\r
+ return FALSE;\r
+ }\r
+\r
+ if( p_fci_internal->fNextCab ||\r
+ p_fci_internal->fGetNextCabInVain ) {\r
+ cbReserveCFFolder=p_fci_internal->oldCCAB.cbReserveCFFolder;\r
+ cbReserveCFHeader=p_fci_internal->oldCCAB.cbReserveCFHeader;\r
+ /* safety */\r
+ if (strlen(p_fci_internal->oldCCAB.szCabPath)>=CB_MAX_CAB_PATH ||\r
+ strlen(p_fci_internal->oldCCAB.szCab)>=CB_MAX_CABINET_NAME) {\r
+ /* TODO set error */\r
+ return FALSE;\r
+ }\r
+ /* get the full name of the cabinet */\r
+ memcpy(pszFileNameCABINET,p_fci_internal->oldCCAB.szCabPath,\r
+ CB_MAX_CAB_PATH);\r
+ memcpy(pszFileNameCABINET+strlen(pszFileNameCABINET),\r
+ p_fci_internal->oldCCAB.szCab, CB_MAX_CABINET_NAME);\r
+ } else {\r
+ cbReserveCFFolder=p_fci_internal->pccab->cbReserveCFFolder;\r
+ cbReserveCFHeader=p_fci_internal->pccab->cbReserveCFHeader;\r
+ /* safety */\r
+ if (strlen(p_fci_internal->pccab->szCabPath)>=CB_MAX_CAB_PATH ||\r
+ strlen(p_fci_internal->pccab->szCab)>=CB_MAX_CABINET_NAME) {\r
+ /* TODO set error */\r
+ return FALSE;\r
+ }\r
+ /* get the full name of the cabinet */\r
+ memcpy(pszFileNameCABINET,p_fci_internal->pccab->szCabPath,\r
+ CB_MAX_CAB_PATH);\r
+ memcpy(pszFileNameCABINET+strlen(pszFileNameCABINET),\r
+ p_fci_internal->pccab->szCab, CB_MAX_CABINET_NAME);\r
+ }\r
+\r
+ /* create the cabinet */\r
+ handleCABINET = PFCI_OPEN(hfci, pszFileNameCABINET,\r
+ 33538, 384, &err, p_fci_internal->pv );\r
+ /* TODO check handle */\r
+ /* TODO error checking of err */\r
+\r
+ memcpy(cfheader.signature,"!CAB",4);\r
+ cfheader.reserved1=0;\r
+ cfheader.cbCabinet= /* size of the cabinet file in bytes */\r
+ sizeof(CFHEADER) +\r
+ p_fci_internal->sizeFileCFFOLDER +\r
+ p_fci_internal->sizeFileCFFILE2 +\r
+ p_fci_internal->sizeFileCFDATA2;\r
+\r
+ if (p_fci_internal->fPrevCab) {\r
+ cfheader.cbCabinet+=strlen(p_fci_internal->szPrevCab)+1 +\r
+ strlen(p_fci_internal->szPrevDisk)+1;\r
+ }\r
+ if (p_fci_internal->fNextCab) {\r
+ cfheader.cbCabinet+=strlen(p_fci_internal->pccab->szCab)+1 +\r
+ strlen(p_fci_internal->pccab->szDisk)+1;\r
+ }\r
+ if( p_fci_internal->fNextCab ||\r
+ p_fci_internal->fGetNextCabInVain ) {\r
+ cfheader.cbCabinet+=p_fci_internal->oldCCAB.cbReserveCFHeader;\r
+ if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ cfheader.cbCabinet+=4;\r
+ }\r
+ } else {\r
+ cfheader.cbCabinet+=p_fci_internal->pccab->cbReserveCFHeader;\r
+ if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFFolder != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFData != 0 ) {\r
+ cfheader.cbCabinet+=4;\r
+ }\r
+ }\r
+\r
+ cfheader.reserved2=0;\r
+ cfheader.coffFiles= /* offset to first CFFILE section */\r
+ cfheader.cbCabinet - p_fci_internal->sizeFileCFFILE2 -\r
+ p_fci_internal->sizeFileCFDATA2;\r
+\r
+ cfheader.reserved3=0;\r
+ cfheader.versionMinor=3;\r
+ cfheader.versionMajor=1;\r
+ /* number of CFFOLDER entries in the cabinet */\r
+ cfheader.cFolders=p_fci_internal->cFolders;\r
+ /* number of CFFILE entries in the cabinet */\r
+ cfheader.cFiles=p_fci_internal->cFiles;\r
+ cfheader.flags=0; /* 1=prev cab, 2=next cabinet, 4=reserved setions */\r
+\r
+ if( p_fci_internal->fPrevCab ) {\r
+ cfheader.flags = cfheadPREV_CABINET;\r
+ }\r
+\r
+ if( p_fci_internal->fNextCab ) {\r
+ cfheader.flags |= cfheadNEXT_CABINET;\r
+ }\r
+\r
+ if( p_fci_internal->fNextCab ||\r
+ p_fci_internal->fGetNextCabInVain ) {\r
+ if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ cfheader.flags |= cfheadRESERVE_PRESENT;\r
+ }\r
+ cfheader.setID = p_fci_internal->oldCCAB.setID;\r
+ cfheader.iCabinet = p_fci_internal->oldCCAB.iCab-1;\r
+ } else {\r
+ if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFFolder != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFData != 0 ) {\r
+ cfheader.flags |= cfheadRESERVE_PRESENT;\r
+ }\r
+ cfheader.setID = p_fci_internal->pccab->setID;\r
+ cfheader.iCabinet = p_fci_internal->pccab->iCab-1;\r
+ }\r
+\r
+ /* write CFHEADER into cabinet file */\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ &cfheader, /* memory buffer */\r
+ sizeof(cfheader), /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != sizeof(cfheader) ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ if( cfheader.flags & cfheadRESERVE_PRESENT ) {\r
+ /* NOTE: No checks for maximum value overflows as designed by MS!!! */\r
+ cfreserved.cbCFHeader = cbReserveCFHeader;\r
+ cfreserved.cbCFFolder = cbReserveCFFolder;\r
+ if( p_fci_internal->fNextCab ||\r
+ p_fci_internal->fGetNextCabInVain ) {\r
+ cfreserved.cbCFData = p_fci_internal->oldCCAB.cbReserveCFData;\r
+ } else {\r
+ cfreserved.cbCFData = p_fci_internal->pccab->cbReserveCFData;\r
+ }\r
+ /* write reserved info into cabinet file */\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ &cfreserved, /* memory buffer */\r
+ sizeof(cfreserved), /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != sizeof(cfreserved) ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+ }\r
+\r
+ /* add optional reserved area */\r
+ if (cbReserveCFHeader!=0) {\r
+ if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFHeader))) {\r
+ p_fci_internal->perf->erfOper = FCIERR_ALLOC_FAIL;\r
+ p_fci_internal->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;\r
+ p_fci_internal->perf->fError = TRUE;\r
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);\r
+ return FALSE;\r
+ }\r
+ for(i=0;i<cbReserveCFHeader;) {\r
+ reserved[i++]='\0';\r
+ }\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ reserved, /* memory buffer */\r
+ cbReserveCFHeader, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != cbReserveCFHeader ) {\r
+ PFCI_FREE(hfci, reserved);\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+ PFCI_FREE(hfci, reserved);\r
+ }\r
+\r
+ if( cfheader.flags & cfheadPREV_CABINET ) {\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ p_fci_internal->szPrevCab, /* memory buffer */\r
+ strlen(p_fci_internal->szPrevCab)+1, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevCab)+1 ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ p_fci_internal->szPrevDisk, /* memory buffer */\r
+ strlen(p_fci_internal->szPrevDisk)+1, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevDisk)+1 ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+ }\r
+\r
+ if( cfheader.flags & cfheadNEXT_CABINET ) {\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ p_fci_internal->pccab->szCab, /* memory buffer */\r
+ strlen(p_fci_internal->pccab->szCab)+1, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szCab)+1 ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ p_fci_internal->pccab->szDisk, /* memory buffer */\r
+ strlen(p_fci_internal->pccab->szDisk)+1, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szDisk)+1 ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+ }\r
+\r
+ /* set seek of p_fci_internal->handleCFFOLDER to 0 */\r
+ if( PFCI_SEEK(hfci,p_fci_internal->handleCFFOLDER,\r
+ 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {\r
+ /* TODO wrong return value */\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* while not all CFFOLDER structures have been copied into the cabinet do */\r
+ while(!FALSE) {\r
+ /* use the variable read_result */\r
+ /* read cffolder of p_fci_internal->handleCFFOLDER */\r
+ read_result = PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* handle */\r
+ &cffolder, /* memory buffer */\r
+ sizeof(cffolder), /* number of bytes to copy */\r
+ &err, p_fci_internal->pv);\r
+ if( read_result != sizeof(cffolder) ) {\r
+ if( read_result == 0 ) break; /*ALL CFFOLDER structures have been copied*/\r
+ /* TODO read error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* add size of header size of all CFFOLDERs and size of all CFFILEs */\r
+ cffolder.coffCabStart +=\r
+ p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +\r
+ sizeof(CFHEADER);\r
+ if( p_fci_internal->fNextCab ||\r
+ p_fci_internal->fGetNextCabInVain ) {\r
+ cffolder.coffCabStart+=p_fci_internal->oldCCAB.cbReserveCFHeader;\r
+ } else {\r
+ cffolder.coffCabStart+=p_fci_internal->pccab->cbReserveCFHeader;\r
+ }\r
+\r
+ if (p_fci_internal->fPrevCab) {\r
+ cffolder.coffCabStart += strlen(p_fci_internal->szPrevCab)+1 +\r
+ strlen(p_fci_internal->szPrevDisk)+1;\r
+ }\r
+\r
+ if (p_fci_internal->fNextCab) {\r
+ cffolder.coffCabStart += strlen(p_fci_internal->oldCCAB.szCab)+1 +\r
+ strlen(p_fci_internal->oldCCAB.szDisk)+1;\r
+ }\r
+\r
+ if( p_fci_internal->fNextCab ||\r
+ p_fci_internal->fGetNextCabInVain ) {\r
+ cffolder.coffCabStart += p_fci_internal->oldCCAB.cbReserveCFHeader;\r
+ if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ cffolder.coffCabStart += 4;\r
+ }\r
+ } else {\r
+ cffolder.coffCabStart += p_fci_internal->pccab->cbReserveCFHeader;\r
+ if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFFolder != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFData != 0 ) {\r
+ cffolder.coffCabStart += 4;\r
+ }\r
+ }\r
+\r
+ /* write cffolder to cabinet file */\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ &cffolder, /* memory buffer */\r
+ sizeof(cffolder), /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != sizeof(cffolder) ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* add optional reserved area */\r
+\r
+ /* This allocation and freeing at each CFFolder block is a bit */\r
+ /* inefficent, but it's harder to forget about freeing the buffer :-). */\r
+ /* Reserved areas are used seldom besides that... */\r
+ if (cbReserveCFFolder!=0) {\r
+ if(!(reserved = PFCI_ALLOC(hfci, cbReserveCFFolder))) {\r
+ p_fci_internal->perf->erfOper = FCIERR_ALLOC_FAIL;\r
+ p_fci_internal->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;\r
+ p_fci_internal->perf->fError = TRUE;\r
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);\r
+ return FALSE;\r
+ }\r
+\r
+ if( PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* file handle */\r
+ reserved, /* memory buffer */\r
+ cbReserveCFFolder, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != cbReserveCFFolder ) {\r
+ PFCI_FREE(hfci, reserved);\r
+ /* TODO read error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ reserved, /* memory buffer */\r
+ cbReserveCFFolder, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != cbReserveCFFolder ) {\r
+ PFCI_FREE(hfci, reserved);\r
+ /* TODO read error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ PFCI_FREE(hfci, reserved);\r
+ }\r
+\r
+ } /* END OF while */\r
+\r
+ /* set seek of p_fci_internal->handleCFFILE2 to 0 */\r
+ if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE2,\r
+ 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {\r
+ /* TODO wrong return value */\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* while not all CFFILE structures have been copied to the cabinet do */\r
+ while(!FALSE) {\r
+ /* REUSE the variable read_result */\r
+ /* REUSE the buffer p_fci_internal->data_out AGAIN */\r
+ /* read a block from p_fci_internal->handleCFFILE2 */\r
+ read_result = PFCI_READ(hfci, p_fci_internal->handleCFFILE2 /* handle */,\r
+ p_fci_internal->data_out, /* memory buffer */\r
+ 32768, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv);\r
+ if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */\r
+ /* TODO error handling of err */\r
+\r
+ /* write the block to the cabinet file */\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ p_fci_internal->data_out, /* memory buffer */\r
+ read_result, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != read_result ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ if (p_fci_internal->fSplitFolder==FALSE) {\r
+ p_fci_internal->statusFolderCopied = 0;\r
+ p_fci_internal->statusFolderTotal = p_fci_internal->sizeFileCFDATA2+\r
+ p_fci_internal->sizeFileCFFILE2;\r
+ }\r
+ p_fci_internal->statusFolderCopied += read_result;\r
+\r
+/* TODO is this correct */\r
+ /* report status with pfnfcis about copied size of folder */\r
+ if( (*pfnfcis)(statusFolder,\r
+ p_fci_internal->statusFolderCopied, /* length of copied blocks */\r
+ p_fci_internal->statusFolderTotal, /* total size of folder */\r
+ p_fci_internal->pv) == -1) {\r
+ /* TODO set error code and abort */\r
+ return FALSE;\r
+ }\r
+\r
+ } /* END OF while */\r
+\r
+ /* set seek of p_fci_internal->handleCFDATA2 to 0 */\r
+ if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA2,\r
+ 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {\r
+ /* TODO wrong return value */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* reset the number of folders for the next cabinet */\r
+ p_fci_internal->cFolders=0;\r
+ /* reset the number of files for the next cabinet */\r
+ p_fci_internal->cFiles=0;\r
+\r
+ /* while not all CFDATA structures have been copied to the cabinet do */\r
+ while(!FALSE) {\r
+ /* REUSE the variable read_result AGAIN */\r
+ /* REUSE the buffer p_fci_internal->data_out AGAIN */\r
+ /* read a block from p_fci_internal->handleCFDATA2 */\r
+ read_result = PFCI_READ(hfci, p_fci_internal->handleCFDATA2 /* handle */,\r
+ p_fci_internal->data_out, /* memory buffer */\r
+ 32768, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv);\r
+ if( read_result == 0 ) break; /* ALL CFDATA structures have been copied */\r
+ /* TODO error handling of err */\r
+\r
+ /* write the block to the cabinet file */\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ p_fci_internal->data_out, /* memory buffer */\r
+ read_result, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != read_result ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->statusFolderCopied += read_result;\r
+ /* report status with pfnfcis about copied size of folder */\r
+ if( (*pfnfcis)(statusFolder,\r
+ p_fci_internal->statusFolderCopied, /* length of copied blocks */\r
+ p_fci_internal->statusFolderTotal, /* total size of folder */\r
+ p_fci_internal->pv) == -1) {\r
+ /* TODO set error code and abort */\r
+ return FALSE;\r
+ }\r
+ } /* END OF while */\r
+\r
+ /* set seek of the cabinet file to 0 */\r
+ if( PFCI_SEEK(hfci, handleCABINET,\r
+ 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {\r
+ /* TODO wrong return value */\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* write the signature "MSCF" into the cabinet file */\r
+ memcpy( cfheader.signature, "MSCF", 4 );\r
+ if( PFCI_WRITE(hfci, handleCABINET, /* file handle */\r
+ &cfheader, /* memory buffer */\r
+ 4, /* number of bytes to copy */\r
+ &err, p_fci_internal->pv) != 4 ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ /* close the cabinet file */\r
+ PFCI_CLOSE(hfci,handleCABINET,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+\r
+\r
+/* COPIED FROM FCIDestroy */\r
+\r
+ PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,\r
+ p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,\r
+ p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,\r
+ p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+\r
+/* END OF copied from FCIDestroy */\r
+\r
+ /* get 3 temporary files and open them */\r
+ /* write names and handles to hfci */\r
+\r
+\r
+ p_fci_internal->sizeFileCFDATA2 = 0;\r
+ p_fci_internal->sizeFileCFFILE2 = 0;\r
+ p_fci_internal->sizeFileCFFOLDER = 0;\r
+\r
+/* COPIED FROM FCICreate */\r
+\r
+ /* CFDATA with checksum and ready to be copied into cabinet */\r
+ if( !PFCI_GETTEMPFILE(hfci, p_fci_internal->szFileNameCFDATA2,\r
+ CB_MAX_FILENAME)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* safety */\r
+ if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,\r
+ p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, p_fci_internal->pv);\r
+ /* TODO check handle */\r
+ /* TODO error checking of err */\r
+\r
+ /* array of all CFFILE in a folder, ready to be copied into cabinet */\r
+ if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,\r
+ CB_MAX_FILENAME)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* safety */\r
+ if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,\r
+ p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, p_fci_internal->pv);\r
+ /* TODO check handle */\r
+ /* TODO error checking of err */\r
+\r
+ /* array of all CFFILE in a folder, ready to be copied into cabinet */\r
+ if (!PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,CB_MAX_FILENAME)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* safety */\r
+ if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,\r
+ p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, p_fci_internal->pv);\r
+ /* TODO check handle */\r
+ /* TODO error checking of err */\r
+\r
+/* END OF copied from FCICreate */\r
+\r
+\r
+ /* TODO close and delete new files when return FALSE */\r
+\r
+\r
+ /* report status with pfnfcis about copied size of folder */\r
+ if( (*pfnfcis)(statusCabinet, p_fci_internal->statusFolderTotal, /* TODO estimated cabinet file size */\r
+ cfheader.cbCabinet, /* real cabinet file size */ p_fci_internal->pv) == -1) {\r
+ /* TODO set error code and abort */\r
+ return FALSE;\r
+ }\r
+\r
+ p_fci_internal->fPrevCab=TRUE;\r
+ /* The sections szPrevCab and szPrevDisk are not being updated, because */\r
+ /* MS CABINET.DLL always puts the first cabinet name and disk into them */\r
+\r
+ if (p_fci_internal->fNextCab) {\r
+ p_fci_internal->fNextCab=FALSE;\r
+\r
+ if (p_fci_internal->sizeFileCFFILE1==0 && p_fci_internal->sizeFileCFDATA1!=0) {\r
+ /* THIS CAN NEVER HAPPEN */\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+\r
+/* COPIED FROM FCIAddFile and modified */\r
+\r
+ /* REUSE the variable read_result */\r
+ if (p_fci_internal->fGetNextCabInVain) {\r
+ read_result=p_fci_internal->oldCCAB.cbReserveCFHeader;\r
+ if(p_fci_internal->sizeFileCFFILE1!=0) {\r
+ read_result+=p_fci_internal->oldCCAB.cbReserveCFFolder;\r
+ }\r
+ if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ read_result+=4;\r
+ }\r
+ } else {\r
+ read_result=p_fci_internal->pccab->cbReserveCFHeader;\r
+ if(p_fci_internal->sizeFileCFFILE1!=0) {\r
+ read_result+=p_fci_internal->pccab->cbReserveCFFolder;\r
+ }\r
+ if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFFolder != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFData != 0 ) {\r
+ read_result+=4;\r
+ }\r
+ }\r
+ if ( p_fci_internal->fPrevCab ) {\r
+ read_result+= strlen(p_fci_internal->szPrevCab)+1+\r
+ strlen(p_fci_internal->szPrevDisk)+1;\r
+ }\r
+ read_result+= p_fci_internal->sizeFileCFDATA1 +\r
+ p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +\r
+ p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +\r
+ sizeof(CFHEADER) +\r
+ sizeof(CFFOLDER); /* set size of new CFFolder entry */\r
+\r
+ if( p_fci_internal->fNewPrevious ) {\r
+ memcpy(p_fci_internal->szPrevCab, p_fci_internal->oldCCAB.szCab,\r
+ CB_MAX_CABINET_NAME);\r
+ memcpy(p_fci_internal->szPrevDisk, p_fci_internal->oldCCAB.szDisk,\r
+ CB_MAX_DISK_NAME);\r
+ p_fci_internal->fNewPrevious=FALSE;\r
+ }\r
+\r
+ /* too much data for the maximum size of a cabinet */\r
+ if( p_fci_internal->fGetNextCabInVain==FALSE &&\r
+ p_fci_internal->pccab->cb < read_result ) {\r
+ return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);\r
+ }\r
+\r
+ /* Might be too much data for the maximum size of a cabinet.*/\r
+ /* When any further data will be added later, it might not */\r
+ /* be possible to flush the cabinet, because there might */\r
+ /* not be enough space to store the name of the following */\r
+ /* cabinet and name of the corresponding disk. */\r
+ /* So take care of this and get the name of the next cabinet */\r
+ if (p_fci_internal->fGetNextCabInVain==FALSE && (\r
+ p_fci_internal->pccab->cb < read_result +\r
+ CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME\r
+ )) {\r
+ /* save CCAB */\r
+ memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));\r
+ /* increment cabinet index */\r
+ ++(p_fci_internal->pccab->iCab);\r
+ /* get name of next cabinet */\r
+ if (!(*pfnfcignc)(p_fci_internal->pccab, 0, /* estimated size of cab */\r
+ p_fci_internal->pv)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* Skip a few lines of code. This is catched by the next if. */\r
+ p_fci_internal->fGetNextCabInVain=TRUE;\r
+ }\r
+\r
+ /* too much data for cabinet */\r
+ if (p_fci_internal->fGetNextCabInVain && (\r
+ p_fci_internal->oldCCAB.cb < read_result +\r
+ strlen(p_fci_internal->oldCCAB.szCab)+1+\r
+ strlen(p_fci_internal->oldCCAB.szDisk)+1\r
+ )) {\r
+ p_fci_internal->fGetNextCabInVain=FALSE;\r
+ p_fci_internal->fNextCab=TRUE;\r
+ return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);\r
+ }\r
+\r
+ /* if the FolderThreshold has been reached flush the folder automatically */\r
+ if( p_fci_internal->fGetNextCabInVain ) {\r
+ if( p_fci_internal->cCompressedBytesInFolder >=\r
+ p_fci_internal->oldCCAB.cbFolderThresh) {\r
+ return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);\r
+ }\r
+ } else {\r
+ if( p_fci_internal->cCompressedBytesInFolder >=\r
+ p_fci_internal->pccab->cbFolderThresh) {\r
+ return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);\r
+ }\r
+ }\r
+\r
+/* END OF COPIED FROM FCIAddFile and modified */\r
+\r
+ if( p_fci_internal->sizeFileCFFILE1>0 ) {\r
+ if( !FCIFlushFolder(hfci, pfnfcignc, pfnfcis) ) return FALSE;\r
+ p_fci_internal->fNewPrevious=TRUE;\r
+ }\r
+ } else {\r
+ p_fci_internal->fNewPrevious=FALSE;\r
+ if( p_fci_internal->sizeFileCFFILE1>0 || p_fci_internal->sizeFileCFDATA1) {\r
+ /* THIS MAY NEVER HAPPEN */\r
+ /* TODO set error structures */\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+} /* end of fci_flush_cabinet */\r
+\r
+\r
+\r
+\r
+\r
+/***********************************************************************\r
+ * FCIAddFile (CABINET.11)\r
+ *\r
+ * FCIAddFile adds a file to the to be created cabinet file\r
+ *\r
+ * PARAMS\r
+ * hfci [I] An HFCI from FCICreate\r
+ * pszSourceFile [I] A pointer to a C string which contains the name and\r
+ * location of the file which will be added to the cabinet\r
+ * pszFileName [I] A pointer to a C string which contains the name under\r
+ * which the file will be stored in the cabinet\r
+ * fExecute [I] A boolean value which indicates if the file should be\r
+ * executed after extraction of self extracting\r
+ * executables\r
+ * pfnfcignc [I] A pointer to a function which gets information about\r
+ * the next cabinet\r
+ * pfnfcis [IO] A pointer to a function which will report status\r
+ * information about the compression process\r
+ * pfnfcioi [I] A pointer to a function which reports file attributes\r
+ * and time and date information\r
+ * typeCompress [I] Compression type\r
+ *\r
+ * RETURNS\r
+ * On success, returns TRUE\r
+ * On failure, returns FALSE\r
+ *\r
+ * INCLUDES\r
+ * fci.h\r
+ *\r
+ */\r
+BOOL __cdecl FCIAddFile(\r
+ HFCI hfci,\r
+ char *pszSourceFile,\r
+ char *pszFileName,\r
+ BOOL fExecute,\r
+ PFNFCIGETNEXTCABINET pfnfcignc,\r
+ PFNFCISTATUS pfnfcis,\r
+ PFNFCIGETOPENINFO pfnfcigoi,\r
+ TCOMP typeCompress)\r
+{\r
+ int err;\r
+ CFFILE cffile;\r
+ cab_ULONG read_result;\r
+ int file_handle;\r
+ PFCI_Int p_fci_internal=((PFCI_Int)(hfci));\r
+\r
+ /* test hfci */\r
+ if (!REALLY_IS_FCI(hfci)) {\r
+ SetLastError(ERROR_INVALID_HANDLE);\r
+ return FALSE;\r
+ }\r
+\r
+ if ((!pszSourceFile) || (!pszFileName) || (!pfnfcignc) || (!pfnfcis) ||\r
+ (!pfnfcigoi) || strlen(pszFileName)>=CB_MAX_FILENAME) {\r
+ p_fci_internal->perf->erfOper = FCIERR_NONE;\r
+ p_fci_internal->perf->erfType = ERROR_BAD_ARGUMENTS;\r
+ p_fci_internal->perf->fError = TRUE;\r
+\r
+ SetLastError(ERROR_BAD_ARGUMENTS);\r
+ return FALSE;\r
+ }\r
+\r
+ /* TODO check if pszSourceFile??? */\r
+\r
+ if(p_fci_internal->fGetNextCabInVain && p_fci_internal->fNextCab) {\r
+ /* TODO internal error */\r
+ return FALSE;\r
+ }\r
+\r
+ if(p_fci_internal->fNextCab) {\r
+ /* TODO internal error */\r
+ return FALSE;\r
+ }\r
+\r
+ cffile.cbFile=0; /* size of the to be added file*/\r
+ /* offset of the uncompressed file in the folder */\r
+ cffile.uoffFolderStart=p_fci_internal->cDataBlocks*CAB_BLOCKMAX + p_fci_internal->cdata_in;\r
+ /* number of folder in the cabinet or special 0=first */\r
+ cffile.iFolder = p_fci_internal->cFolders;\r
+\r
+ /* allocation of memory */\r
+ if (p_fci_internal->data_in==NULL) {\r
+ if (p_fci_internal->cdata_in!=0) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ if (p_fci_internal->data_out!=NULL) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ if(!(p_fci_internal->data_in = (char*)PFCI_ALLOC(hfci,CB_MAX_CHUNK))) {\r
+ p_fci_internal->perf->erfOper = FCIERR_ALLOC_FAIL;\r
+ p_fci_internal->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;\r
+ p_fci_internal->perf->fError = TRUE;\r
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);\r
+ return FALSE;\r
+ }\r
+ if (p_fci_internal->data_out==NULL) {\r
+ if(!(p_fci_internal->data_out = PFCI_ALLOC(hfci, 2 * CB_MAX_CHUNK))){\r
+ p_fci_internal->perf->erfOper = FCIERR_ALLOC_FAIL;\r
+ p_fci_internal->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;\r
+ p_fci_internal->perf->fError = TRUE;\r
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);\r
+ return FALSE;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (p_fci_internal->data_out==NULL) {\r
+ PFCI_FREE(hfci,p_fci_internal->data_in);\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+\r
+ /* get information about the file */\r
+ file_handle=(*pfnfcigoi)(pszSourceFile, &(cffile.date), &(cffile.time),\r
+ &(cffile.attribs), &err, p_fci_internal->pv);\r
+ /* TODO check file_handle */\r
+ /* TODO error handling of err */\r
+\r
+ if (fExecute) { cffile.attribs |= _A_EXEC; }\r
+\r
+ /* REUSE the variable read_result */\r
+ if (p_fci_internal->fGetNextCabInVain) {\r
+ read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder;\r
+ if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ read_result+=4;\r
+ }\r
+ } else {\r
+ read_result=p_fci_internal->pccab->cbReserveCFHeader +\r
+ p_fci_internal->pccab->cbReserveCFFolder;\r
+ if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFFolder != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFData != 0 ) {\r
+ read_result+=4;\r
+ }\r
+ }\r
+ if ( p_fci_internal->fPrevCab ) {\r
+ read_result+= strlen(p_fci_internal->szPrevCab)+1+\r
+ strlen(p_fci_internal->szPrevDisk)+1;\r
+ }\r
+ if ( p_fci_internal->fNextCab ) { /* this is never the case */\r
+ read_result+= strlen(p_fci_internal->pccab->szCab)+1+\r
+ strlen(p_fci_internal->pccab->szDisk)+1;\r
+ }\r
+\r
+ read_result+= sizeof(CFFILE) + strlen(pszFileName)+1 +\r
+ p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +\r
+ p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +\r
+ sizeof(CFHEADER) +\r
+ sizeof(CFFOLDER); /* size of new CFFolder entry */\r
+\r
+ /* Might be too much data for the maximum size of a cabinet.*/\r
+ /* When any further data will be added later, it might not */\r
+ /* be possible to flush the cabinet, because there might */\r
+ /* not be enough space to store the name of the following */\r
+ /* cabinet and name of the corresponding disk. */\r
+ /* So take care of this and get the name of the next cabinet */\r
+ if( p_fci_internal->fGetNextCabInVain==FALSE &&\r
+ p_fci_internal->fNextCab==FALSE &&\r
+ ( p_fci_internal->pccab->cb < read_result +\r
+ CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME\r
+ )\r
+ ) {\r
+ /* save CCAB */\r
+ memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));\r
+ /* increment cabinet index */\r
+ ++(p_fci_internal->pccab->iCab);\r
+ /* get name of next cabinet */\r
+ if (!(*pfnfcignc)(p_fci_internal->pccab, 0,/* TODO estimated size of cab */\r
+ p_fci_internal->pv)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* Skip a few lines of code. This is catched by the next if. */\r
+ p_fci_internal->fGetNextCabInVain=TRUE;\r
+ }\r
+\r
+ if( p_fci_internal->fGetNextCabInVain &&\r
+ p_fci_internal->fNextCab\r
+ ) {\r
+ /* THIS CAN NEVER HAPPEN */\r
+ /* TODO set error code*/\r
+ return FALSE;\r
+ }\r
+\r
+ /* too much data for cabinet */\r
+ if( p_fci_internal->fGetNextCabInVain &&\r
+ (\r
+ p_fci_internal->oldCCAB.cb < read_result +\r
+ strlen(p_fci_internal->pccab->szCab)+1+\r
+ strlen(p_fci_internal->pccab->szDisk)+1\r
+ )) {\r
+ p_fci_internal->fGetNextCabInVain=FALSE;\r
+ p_fci_internal->fNextCab=TRUE;\r
+ if(!fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis)) return FALSE;\r
+ }\r
+\r
+ if( p_fci_internal->fNextCab ) {\r
+ /* THIS MAY NEVER HAPPEN */\r
+ /* TODO set error code*/\r
+ return FALSE;\r
+ }\r
+\r
+ /* read the contents of the file blockwize*/\r
+ while (!FALSE) {\r
+ if (p_fci_internal->cdata_in > CAB_BLOCKMAX) {\r
+ /* TODO internal error */\r
+ return FALSE;\r
+ }\r
+\r
+ read_result = PFCI_READ(hfci, file_handle /* file handle */,\r
+ (p_fci_internal->data_in + p_fci_internal->cdata_in) /* memory buffer */,\r
+ (CAB_BLOCKMAX - p_fci_internal->cdata_in) /* number of bytes to copy */,\r
+ &err, p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+\r
+ if( read_result==0 ) break;\r
+\r
+ /* increment the block size */\r
+ p_fci_internal->cdata_in += read_result;\r
+\r
+ /* increment the file size */\r
+ cffile.cbFile += read_result;\r
+\r
+\r
+ if ( p_fci_internal->cdata_in > CAB_BLOCKMAX ) {\r
+ /* TODO report internal error */\r
+ return FALSE;\r
+ }\r
+ /* write a whole block */\r
+ if ( p_fci_internal->cdata_in == CAB_BLOCKMAX ) {\r
+\r
+ if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;\r
+ }\r
+ }\r
+\r
+ /* close the file from FCIAddFile */\r
+ PFCI_CLOSE(hfci,file_handle,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+\r
+ /* write cffile to p_fci_internal->handleCFFILE1 */\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */\r
+ &cffile, sizeof(cffile),&err, p_fci_internal->pv) != sizeof(cffile) ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->sizeFileCFFILE1 += sizeof(cffile);\r
+\r
+ /* append the name of file*/\r
+ if (strlen(pszFileName)>=CB_MAX_FILENAME) {\r
+ /* IMPOSSIBLE */\r
+ /* TODO set error code */\r
+ return FALSE;\r
+ }\r
+ if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */\r
+ pszFileName, strlen(pszFileName)+1, &err, p_fci_internal->pv)\r
+ != strlen(pszFileName)+1 ) {\r
+ /* TODO write error */\r
+ return FALSE;\r
+ }\r
+ /* TODO error handling of err */\r
+\r
+ p_fci_internal->sizeFileCFFILE1 += strlen(pszFileName)+1;\r
+\r
+ /* REUSE the variable read_result */\r
+ if (p_fci_internal->fGetNextCabInVain ||\r
+ p_fci_internal->fNextCab\r
+ ) {\r
+ read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder;\r
+ if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||\r
+ p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {\r
+ read_result+=4;\r
+ }\r
+ } else {\r
+ read_result=p_fci_internal->pccab->cbReserveCFHeader +\r
+ p_fci_internal->pccab->cbReserveCFFolder;\r
+ if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFFolder != 0 ||\r
+ p_fci_internal->pccab->cbReserveCFData != 0 ) {\r
+ read_result+=4;\r
+ }\r
+ }\r
+ if ( p_fci_internal->fPrevCab ) {\r
+ read_result+= strlen(p_fci_internal->szPrevCab)+1+\r
+ strlen(p_fci_internal->szPrevDisk)+1;\r
+ }\r
+ if ( p_fci_internal->fNextCab ) { /* this is never the case */\r
+ read_result+= strlen(p_fci_internal->pccab->szCab)+1+\r
+ strlen(p_fci_internal->pccab->szDisk)+1;\r
+ }\r
+ read_result+= p_fci_internal->sizeFileCFDATA1 +\r
+ p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +\r
+ p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +\r
+ sizeof(CFHEADER) +\r
+ sizeof(CFFOLDER); /* set size of new CFFolder entry */\r
+\r
+ /* too much data for the maximum size of a cabinet */\r
+ /* (ignoring the unflushed data block) */\r
+ if( p_fci_internal->fGetNextCabInVain==FALSE &&\r
+ p_fci_internal->fNextCab==FALSE && /* this is always the case */\r
+ p_fci_internal->pccab->cb < read_result ) {\r
+ return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);\r
+ }\r
+\r
+ /* Might be too much data for the maximum size of a cabinet.*/\r
+ /* When any further data will be added later, it might not */\r
+ /* be possible to flush the cabinet, because there might */\r
+ /* not be enough space to store the name of the following */\r
+ /* cabinet and name of the corresponding disk. */\r
+ /* So take care of this and get the name of the next cabinet */\r
+ /* (ignoring the unflushed data block) */\r
+ if( p_fci_internal->fGetNextCabInVain==FALSE &&\r
+ p_fci_internal->fNextCab==FALSE &&\r
+ ( p_fci_internal->pccab->cb < read_result +\r
+ CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME\r
+ )\r
+ ) {\r
+ /* save CCAB */\r
+ memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));\r
+ /* increment cabinet index */\r
+ ++(p_fci_internal->pccab->iCab);\r
+ /* get name of next cabinet */\r
+ if (!(*pfnfcignc)(p_fci_internal->pccab, 0,/* TODO estimated size of cab */\r
+ p_fci_internal->pv)) {\r
+ /* TODO error handling */\r
+ return FALSE;\r
+ }\r
+ /* Skip a few lines of code. This is catched by the next if. */\r
+ p_fci_internal->fGetNextCabInVain=TRUE;\r
+ }\r
+\r
+ if( p_fci_internal->fGetNextCabInVain &&\r
+ p_fci_internal->fNextCab\r
+ ) {\r
+ /* THIS CAN NEVER HAPPEN */\r
+ /* TODO set error code*/\r
+ return FALSE;\r
+ }\r
+\r
+ /* too much data for cabinet */\r
+ if( (p_fci_internal->fGetNextCabInVain ||\r
+ p_fci_internal->fNextCab) && (\r
+ p_fci_internal->oldCCAB.cb < read_result +\r
+ strlen(p_fci_internal->pccab->szCab)+1+\r
+ strlen(p_fci_internal->pccab->szDisk)+1\r
+ )) {\r
+\r
+ p_fci_internal->fGetNextCabInVain=FALSE;\r
+ p_fci_internal->fNextCab=TRUE;\r
+ return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);\r
+ }\r
+\r
+ if( p_fci_internal->fNextCab ) {\r
+ /* THIS MAY NEVER HAPPEN */\r
+ /* TODO set error code*/\r
+ return FALSE;\r
+ }\r
+\r
+ /* if the FolderThreshold has been reached flush the folder automatically */\r
+ if( p_fci_internal->fGetNextCabInVain ) {\r
+ if( p_fci_internal->cCompressedBytesInFolder >=\r
+ p_fci_internal->oldCCAB.cbFolderThresh) {\r
+ return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);\r
+ }\r
+ } else {\r
+ if( p_fci_internal->cCompressedBytesInFolder >=\r
+ p_fci_internal->pccab->cbFolderThresh) {\r
+ return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+} /* end of FCIAddFile */\r
+\r
+\r
+\r
+\r
+\r
+/***********************************************************************\r
+ * FCIFlushFolder (CABINET.12)\r
+ *\r
+ * FCIFlushFolder completes the CFFolder structure under construction.\r
+ *\r
+ * All further data which is added by FCIAddFile will be associateed to\r
+ * the next CFFolder structure.\r
+ *\r
+ * FCIFlushFolder will be called by FCIAddFile automatically if the\r
+ * threshold (stored in the member cbFolderThresh of the CCAB structure\r
+ * pccab passed to FCICreate) is exceeded.\r
+ *\r
+ * FCIFlushFolder will be called by FCIFlushFolder automatically before\r
+ * any data will be written into the cabinet file.\r
+ *\r
+ * PARAMS\r
+ * hfci [I] An HFCI from FCICreate\r
+ * pfnfcignc [I] A pointer to a function which gets information about\r
+ * the next cabinet\r
+ * pfnfcis [IO] A pointer to a function which will report status\r
+ * information about the compression process\r
+ *\r
+ * RETURNS\r
+ * On success, returns TRUE\r
+ * On failure, returns FALSE\r
+ *\r
+ * INCLUDES\r
+ * fci.h\r
+ *\r
+ */\r
+BOOL __cdecl FCIFlushFolder(\r
+ HFCI hfci,\r
+ PFNFCIGETNEXTCABINET pfnfcignc,\r
+ PFNFCISTATUS pfnfcis)\r
+{\r
+ return fci_flush_folder(hfci,FALSE,pfnfcignc,pfnfcis);\r
+} /* end of FCIFlushFolder */\r
+\r
+\r
+\r
+/***********************************************************************\r
+ * FCIFlushCabinet (CABINET.13)\r
+ *\r
+ * FCIFlushCabinet stores the data which has been added by FCIAddFile\r
+ * into the cabinet file. If the maximum cabinet size (stored in the\r
+ * member cb of the CCAB structure pccab passed to FCICreate) has been\r
+ * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.\r
+ * The remaining data still has to be flushed manually by calling\r
+ * FCIFlushCabinet.\r
+ *\r
+ * After FCIFlushCabinet has been called (manually) FCIAddFile must\r
+ * NOT be called again. Then hfci has to be released by FCIDestroy.\r
+ *\r
+ * PARAMS\r
+ * hfci [I] An HFCI from FCICreate\r
+ * fGetNextCab [I] Whether you want to add additional files to a\r
+ * cabinet set (TRUE) or whether you want to\r
+ * finalize it (FALSE)\r
+ * pfnfcignc [I] A pointer to a function which gets information about\r
+ * the next cabinet\r
+ * pfnfcis [IO] A pointer to a function which will report status\r
+ * information about the compression process\r
+ *\r
+ * RETURNS\r
+ * On success, returns TRUE\r
+ * On failure, returns FALSE\r
+ *\r
+ * INCLUDES\r
+ * fci.h\r
+ *\r
+ */\r
+BOOL __cdecl FCIFlushCabinet(\r
+ HFCI hfci,\r
+ BOOL fGetNextCab,\r
+ PFNFCIGETNEXTCABINET pfnfcignc,\r
+ PFNFCISTATUS pfnfcis)\r
+{\r
+ PFCI_Int p_fci_internal=((PFCI_Int)(hfci));\r
+\r
+ if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;\r
+\r
+ while( p_fci_internal->sizeFileCFFILE1>0 ||\r
+ p_fci_internal->sizeFileCFFILE2>0 ) {\r
+ if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+} /* end of FCIFlushCabinet */\r
+\r
+\r
+/***********************************************************************\r
+ * FCIDestroy (CABINET.14)\r
+ *\r
+ * Frees a handle created by FCICreate.\r
+ * Only reason for failure would be an invalid handle.\r
+ *\r
+ * PARAMS\r
+ * hfci [I] The HFCI to free\r
+ *\r
+ * RETURNS\r
+ * TRUE for success\r
+ * FALSE for failure\r
+ */\r
+BOOL __cdecl FCIDestroy(HFCI hfci)\r
+{\r
+ int err;\r
+ PFCI_Int p_fci_internal=((PFCI_Int)(hfci));\r
+ if (REALLY_IS_FCI(hfci)) {\r
+\r
+ /* before hfci can be removed all temporary files must be closed */\r
+ /* and deleted */\r
+ p_fci_internal->FCI_Intmagic = 0;\r
+\r
+ PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA1, &err,\r
+ p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE1,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE1, &err,\r
+ p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,\r
+ p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,\r
+ p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+ PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,\r
+ p_fci_internal->pv);\r
+ /* TODO error handling of err */\r
+\r
+ /* data in and out buffers have to be removed */\r
+ if (p_fci_internal->data_in!=NULL)\r
+ PFCI_FREE(hfci, p_fci_internal->data_in);\r
+ if (p_fci_internal->data_out!=NULL)\r
+ PFCI_FREE(hfci, p_fci_internal->data_out);\r
+\r
+ /* hfci can now be removed */\r
+ PFCI_FREE(hfci, hfci);\r
+ return TRUE;\r
} else {\r
SetLastError(ERROR_INVALID_HANDLE);\r
return FALSE;\r
}\r
\r
- /* Still mark as incomplete, because of other missing FCI* APIs */\r
- FIXME("(%p): stub\n", hfci);\r
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\r
- return FALSE;\r
-}\r
+} /* end of FCIDestroy */\r