2 * File Compression Interface
4 * Copyright 2002 Patrik Stridvall
5 * Copyright 2005 Gerold Jens Wucherpfennig
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 There is still some work to be done:
26 - no real compression yet
27 - unknown behaviour if files>=2GB or cabinet >=4GB
28 - check if the maximum size for a cabinet is too small to store any data
29 - call pfnfcignc on exactly the same position as MS FCIAddFile in every case
48 #include "wine/debug.h"
51 #ifdef WORDS_BIGENDIAN
52 #define fci_endian_ulong(x) RtlUlongByteSwap(x)
53 #define fci_endian_uword(x) RtlUshortByteSwap(x)
55 #define fci_endian_ulong(x) (x)
56 #define fci_endian_uword(x) (x)
60 #define fci_set_error(A,B,C) do { \
61 p_fci_internal->perf->erfOper = A; \
62 p_fci_internal->perf->erfType = B; \
63 p_fci_internal->perf->fError = C; \
64 if (B) SetLastError(B); } while(0)
68 cab_UBYTE signature[4]; /* !CAB for unfinished cabinets else MSCF */
70 cab_ULONG cbCabinet; /* size of the cabinet file in bytes*/
72 cab_ULONG coffFiles; /* offset to first CFFILE section */
74 cab_UBYTE versionMinor; /* 3 */
75 cab_UBYTE versionMajor; /* 1 */
76 cab_UWORD cFolders; /* number of CFFOLDER entries in the cabinet*/
77 cab_UWORD cFiles; /* number of CFFILE entries in the cabinet*/
78 cab_UWORD flags; /* 1=prev cab, 2=next cabinet, 4=reserved setions*/
79 cab_UWORD setID; /* identification number of all cabinets in a set*/
80 cab_UWORD iCabinet; /* number of the cabinet in a set */
81 /* additional area if "flags" were set*/
82 } CFHEADER; /* minimum 36 bytes */
85 cab_ULONG coffCabStart; /* offset to the folder's first CFDATA section */
86 cab_UWORD cCFData; /* number of this folder's CFDATA sections */
87 cab_UWORD typeCompress; /* compression type of data in CFDATA section*/
88 /* additional area if reserve flag was set */
89 } CFFOLDER; /* minumum 8 bytes */
92 cab_ULONG cbFile; /* size of the uncompressed file in bytes */
93 cab_ULONG uoffFolderStart; /* offset of the uncompressed file in the folder */
94 cab_UWORD iFolder; /* number of folder in the cabinet 0=first */
95 /* for special values see below this structure*/
96 cab_UWORD date; /* last modification date*/
97 cab_UWORD time; /* last modification time*/
98 cab_UWORD attribs; /* DOS fat attributes and UTF indicator */
99 /* ... and a C string with the name of the file */
100 } CFFILE; /* 16 bytes + name of file */
104 cab_ULONG csum; /* checksum of this entry*/
105 cab_UWORD cbData; /* number of compressed bytes */
106 cab_UWORD cbUncomp; /* number of bytes when data is uncompressed */
107 /* optional reserved area */
108 /* compressed data */
112 /***********************************************************************
113 * FCICreate (CABINET.10)
115 * FCICreate is provided with several callbacks and
116 * returns a handle which can be used to create cabinet files.
119 * perf [IO] A pointer to an ERF structure. When FCICreate
120 * returns an error condition, error information may
121 * be found here as well as from GetLastError.
122 * pfnfiledest [I] A pointer to a function which is called when a file
123 * is placed. Only useful for subsequent cabinet files.
124 * pfnalloc [I] A pointer to a function which allocates ram. Uses
125 * the same interface as malloc.
126 * pfnfree [I] A pointer to a function which frees ram. Uses the
127 * same interface as free.
128 * pfnopen [I] A pointer to a function which opens a file. Uses
129 * the same interface as _open.
130 * pfnread [I] A pointer to a function which reads from a file into
131 * a caller-provided buffer. Uses the same interface
133 * pfnwrite [I] A pointer to a function which writes to a file from
134 * a caller-provided buffer. Uses the same interface
136 * pfnclose [I] A pointer to a function which closes a file handle.
137 * Uses the same interface as _close.
138 * pfnseek [I] A pointer to a function which seeks in a file.
139 * Uses the same interface as _lseek.
140 * pfndelete [I] A pointer to a function which deletes a file.
141 * pfnfcigtf [I] A pointer to a function which gets the name of a
143 * pccab [I] A pointer to an initialized CCAB structure.
144 * pv [I] A pointer to an application-defined notification
145 * function which will be passed to other FCI functions
149 * On success, returns an FCI handle of type HFCI.
150 * On failure, the NULL file handle is returned. Error
151 * info can be retrieved from perf.
157 HFCI __cdecl FCICreate(
159 PFNFCIFILEPLACED pfnfiledest,
160 PFNFCIALLOC pfnalloc,
164 PFNFCIWRITE pfnwrite,
165 PFNFCICLOSE pfnclose,
167 PFNFCIDELETE pfndelete,
168 PFNFCIGETTEMPFILE pfnfcigtf,
174 PFCI_Int p_fci_internal;
176 if ((!perf) || (!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||
177 (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||
178 (!pfnfcigtf) || (!pccab)) {
179 perf->erfOper = FCIERR_NONE;
180 perf->erfType = ERROR_BAD_ARGUMENTS;
183 SetLastError(ERROR_BAD_ARGUMENTS);
187 if (!((hfci = ((HFCI) (*pfnalloc)(sizeof(FCI_Int)))))) {
188 perf->erfOper = FCIERR_ALLOC_FAIL;
189 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
192 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
196 p_fci_internal=((PFCI_Int)(hfci));
197 p_fci_internal->FCI_Intmagic = FCI_INT_MAGIC;
198 p_fci_internal->perf = perf;
199 p_fci_internal->pfnfiledest = pfnfiledest;
200 p_fci_internal->pfnalloc = pfnalloc;
201 p_fci_internal->pfnfree = pfnfree;
202 p_fci_internal->pfnopen = pfnopen;
203 p_fci_internal->pfnread = pfnread;
204 p_fci_internal->pfnwrite = pfnwrite;
205 p_fci_internal->pfnclose = pfnclose;
206 p_fci_internal->pfnseek = pfnseek;
207 p_fci_internal->pfndelete = pfndelete;
208 p_fci_internal->pfnfcigtf = pfnfcigtf;
209 p_fci_internal->pccab = pccab;
210 p_fci_internal->fPrevCab = FALSE;
211 p_fci_internal->fNextCab = FALSE;
212 p_fci_internal->fSplitFolder = FALSE;
213 p_fci_internal->fGetNextCabInVain = FALSE;
214 p_fci_internal->pv = pv;
215 p_fci_internal->data_in = NULL;
216 p_fci_internal->cdata_in = 0;
217 p_fci_internal->data_out = NULL;
218 p_fci_internal->cCompressedBytesInFolder = 0;
219 p_fci_internal->cFolders = 0;
220 p_fci_internal->cFiles = 0;
221 p_fci_internal->cDataBlocks = 0;
222 p_fci_internal->sizeFileCFDATA1 = 0;
223 p_fci_internal->sizeFileCFFILE1 = 0;
224 p_fci_internal->sizeFileCFDATA2 = 0;
225 p_fci_internal->sizeFileCFFILE2 = 0;
226 p_fci_internal->sizeFileCFFOLDER = 0;
227 p_fci_internal->sizeFileCFFOLDER = 0;
228 p_fci_internal->fNewPrevious = FALSE;
229 p_fci_internal->estimatedCabinetSize = 0;
230 p_fci_internal->statusFolderTotal = 0;
232 memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
233 memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);
236 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA1,
238 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
242 if ( strlen(p_fci_internal->szFileNameCFDATA1) >= CB_MAX_FILENAME ) {
243 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
247 p_fci_internal->handleCFDATA1 = PFCI_OPEN(hfci,
248 p_fci_internal->szFileNameCFDATA1, 34050, 384, &err, pv);
249 if(p_fci_internal->handleCFDATA1==0){
250 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
253 /* TODO error checking of err */
255 /* array of all CFFILE in a folder */
256 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE1,
258 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
262 if ( strlen(p_fci_internal->szFileNameCFFILE1) >= CB_MAX_FILENAME ) {
263 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
266 p_fci_internal->handleCFFILE1 = PFCI_OPEN(hfci,
267 p_fci_internal->szFileNameCFFILE1, 34050, 384, &err, pv);
268 if(p_fci_internal->handleCFFILE1==0){
269 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
272 /* TODO error checking of err */
274 /* CFDATA with checksum and ready to be copied into cabinet */
275 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA2,
277 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE);
281 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
282 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
285 p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
286 p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, pv);
287 if(p_fci_internal->handleCFDATA2==0){
288 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
291 /* TODO error checking of err */
293 /* array of all CFFILE in a folder, ready to be copied into cabinet */
294 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
296 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
300 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
301 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
304 p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
305 p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, pv);
306 if(p_fci_internal->handleCFFILE2==0){
307 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
310 /* TODO error checking of err */
312 /* array of all CFFILE in a folder, ready to be copied into cabinet */
313 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,
315 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
319 if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
320 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
323 p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
324 p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, pv);
325 if(p_fci_internal->handleCFFOLDER==0) {
326 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
330 /* TODO close and delete new files when return FALSE */
331 /* TODO error checking of err */
334 } /* end of FCICreate */
341 static BOOL fci_flush_data_block (HFCI hfci, int* err,
342 PFNFCISTATUS pfnfcis) {
344 /* attention no hfci checks!!! */
345 /* attention no checks if there is data available!!! */
347 CFDATA* cfdata=&data;
349 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
350 UINT cbReserveCFData=p_fci_internal->pccab->cbReserveCFData;
353 /* TODO compress the data of p_fci_internal->data_in */
354 /* and write it to p_fci_internal->data_out */
355 memcpy(p_fci_internal->data_out, p_fci_internal->data_in,
356 p_fci_internal->cdata_in /* number of bytes to copy */);
358 cfdata->csum=0; /* checksum has to be set later */
359 /* TODO set realsize of compressed data */
360 cfdata->cbData = p_fci_internal->cdata_in;
361 cfdata->cbUncomp = p_fci_internal->cdata_in;
363 /* write cfdata to p_fci_internal->handleCFDATA1 */
364 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
365 cfdata, sizeof(*cfdata), err, p_fci_internal->pv)
366 != sizeof(*cfdata) ) {
367 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
370 /* TODO error handling of err */
372 p_fci_internal->sizeFileCFDATA1 += sizeof(*cfdata);
374 /* add optional reserved area */
376 /* This allocation and freeing at each CFData block is a bit */
377 /* inefficent, but it's harder to forget about freeing the buffer :-). */
378 /* Reserved areas are used seldom besides that... */
379 if (cbReserveCFData!=0) {
380 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData))) {
381 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
384 for(i=0;i<cbReserveCFData;) {
387 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
388 reserved, /* memory buffer */
389 cbReserveCFData, /* number of bytes to copy */
390 err, p_fci_internal->pv) != cbReserveCFData ) {
391 PFCI_FREE(hfci, reserved);
392 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
395 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
397 p_fci_internal->sizeFileCFDATA1 += cbReserveCFData;
398 PFCI_FREE(hfci, reserved);
401 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
402 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
403 p_fci_internal->data_out, /* memory buffer */
404 cfdata->cbData, /* number of bytes to copy */
405 err, p_fci_internal->pv) != cfdata->cbData) {
406 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
409 /* TODO error handling of err */
411 p_fci_internal->sizeFileCFDATA1 += cfdata->cbData;
413 /* reset the offset */
414 p_fci_internal->cdata_in = 0;
415 p_fci_internal->cCompressedBytesInFolder += cfdata->cbData;
417 /* report status with pfnfcis about uncompressed and compressed file data */
418 if( (*pfnfcis)(statusFile, cfdata->cbData, cfdata->cbUncomp,
419 p_fci_internal->pv) == -1) {
420 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
424 ++(p_fci_internal->cDataBlocks);
427 } /* end of fci_flush_data_block */
433 static cab_ULONG fci_get_checksum(void *pv, UINT cb, CHECKSUM seed)
444 while (cUlong-- > 0) {
446 ul |= (((cab_ULONG)(*pb++)) << 8);
447 ul |= (((cab_ULONG)(*pb++)) << 16);
448 ul |= (((cab_ULONG)(*pb++)) << 24);
456 ul |= (((ULONG)(*pb++)) << 16);
458 ul |= (((ULONG)(*pb++)) << 8);
467 } /* end of fci_get_checksum */
471 static BOOL fci_flushfolder_copy_cfdata(HFCI hfci, char* buffer, UINT cbReserveCFData,
472 PFNFCISTATUS pfnfcis, int* err, int handleCFDATA1new,
473 cab_ULONG* psizeFileCFDATA1new, cab_ULONG* payload)
475 cab_ULONG read_result;
476 CFDATA* pcfdata=(CFDATA*)buffer;
477 BOOL split_block=FALSE;
478 cab_UWORD savedUncomp=0;
479 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
483 /* while not all CFDATAs have been copied do */
485 if( p_fci_internal->fNextCab ) {
487 /* internal error should never happen */
488 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
492 /* REUSE the variable read_result */
493 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
494 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
495 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
500 if (p_fci_internal->fPrevCab) {
501 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
502 strlen(p_fci_internal->szPrevDisk)+1;
504 /* No more CFDATA fits into the cabinet under construction */
505 /* So don't try to store more data into it */
506 if( p_fci_internal->fNextCab &&
507 (p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData +
508 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
509 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
512 p_fci_internal->oldCCAB.cbReserveCFHeader +
514 p_fci_internal->oldCCAB.cbReserveCFFolder +
515 strlen(p_fci_internal->pccab->szCab)+1 +
516 strlen(p_fci_internal->pccab->szDisk)+1
518 /* This may never be run for the first time the while loop is entered.
519 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
520 split_block=TRUE; /* In this case split_block is abused to store */
521 /* the complete data block into the next cabinet and not into the */
522 /* current one. Originally split_block is the indicator that a */
523 /* data block has been splitted across different cabinets. */
526 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
527 read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/*file handle*/
528 buffer, /* memory buffer */
529 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
530 err, p_fci_internal->pv);
531 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
532 if (read_result==0) break; /* ALL DATA has been copied */
534 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
537 /* TODO error handling of err */
539 /* REUSE buffer p_fci_internal->data_out !!! */
540 /* read data from p_fci_internal->handleCFDATA1 to */
541 /* p_fci_internal->data_out */
542 if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
543 p_fci_internal->data_out /* memory buffer */,
544 pcfdata->cbData /* number of bytes to copy */,
545 err, p_fci_internal->pv) != pcfdata->cbData ) {
547 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
550 /* TODO error handling of err */
552 /* if cabinet size is too large */
554 /* REUSE the variable read_result */
555 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
556 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
557 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
562 if (p_fci_internal->fPrevCab) {
563 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
564 strlen(p_fci_internal->szPrevDisk)+1;
567 /* Is cabinet with new CFDATA too large? Then data block has to be split */
568 if( p_fci_internal->fNextCab &&
569 (p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData +
571 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
572 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
575 p_fci_internal->oldCCAB.cbReserveCFHeader +
576 sizeof(CFFOLDER) + /* size of new CFFolder entry */
577 p_fci_internal->oldCCAB.cbReserveCFFolder +
578 strlen(p_fci_internal->pccab->szCab)+1 + /* name of next cabinet */
579 strlen(p_fci_internal->pccab->szDisk)+1 /* name of next disk */
581 /* REUSE read_result to save the size of the compressed data */
582 read_result=pcfdata->cbData;
583 /* Modify the size of the compressed data to store only a part of the */
584 /* data block into the current cabinet. This is done to prevent */
585 /* that the maximum cabinet size will be exceeded. The remainder */
586 /* will be stored into the next following cabinet. */
588 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
589 /* Substract everything except the size of the block of data */
590 /* to get it's actual size */
591 pcfdata->cbData = p_fci_internal->oldCCAB.cb - (
592 sizeof(CFDATA) + cbReserveCFData +
593 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
594 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
596 p_fci_internal->oldCCAB.cbReserveCFHeader +
597 sizeof(CFFOLDER) + /* set size of new CFFolder entry */
598 p_fci_internal->oldCCAB.cbReserveCFFolder );
599 /* substract the size of special header fields */
600 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
601 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
602 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
605 if (p_fci_internal->fPrevCab) {
606 pcfdata->cbData-=strlen(p_fci_internal->szPrevCab)+1 +
607 strlen(p_fci_internal->szPrevDisk)+1;
609 pcfdata->cbData-=strlen(p_fci_internal->pccab->szCab)+1 +
610 strlen(p_fci_internal->pccab->szDisk)+1;
612 savedUncomp = pcfdata->cbUncomp;
613 pcfdata->cbUncomp = 0; /* on splitted blocks of data this is zero */
615 /* if split_block==TRUE then the above while loop won't */
616 /* be executed again */
617 split_block=TRUE; /* split_block is the indicator that */
618 /* a data block has been splitted across */
619 /* diffentent cabinets.*/
622 /* This should never happen !!! */
623 if (pcfdata->cbData==0) {
625 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
629 /* set little endian */
630 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
631 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
633 /* get checksum and write to cfdata.csum */
634 pcfdata->csum = fci_get_checksum( &(pcfdata->cbData),
635 sizeof(CFDATA)+cbReserveCFData -
636 sizeof(pcfdata->csum), fci_get_checksum( p_fci_internal->data_out, /*buffer*/
637 pcfdata->cbData, 0 ) );
639 /* set little endian */
640 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
642 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
643 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
644 buffer, /* memory buffer */
645 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
646 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
647 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
650 /* TODO error handling of err */
652 p_fci_internal->sizeFileCFDATA2 += sizeof(CFDATA)+cbReserveCFData;
654 /* reset little endian */
655 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
656 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
657 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
659 /* write compressed data into p_fci_internal->handleCFDATA2 */
660 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
661 p_fci_internal->data_out, /* memory buffer */
662 pcfdata->cbData, /* number of bytes to copy */
663 err, p_fci_internal->pv) != pcfdata->cbData) {
664 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
667 /* TODO error handling of err */
669 p_fci_internal->sizeFileCFDATA2 += pcfdata->cbData;
670 ++(p_fci_internal->cDataBlocks);
671 p_fci_internal->statusFolderCopied += pcfdata->cbData;
672 (*payload)+=pcfdata->cbUncomp;
673 /* if cabinet size too large and data has been split */
674 /* write the remainder of the data block to the new CFDATA1 file */
675 if( split_block ) { /* This does not include the */
676 /* abused one (just search for "abused" )*/
677 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
678 if (p_fci_internal->fNextCab==FALSE ) {
680 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
684 /* set cbData to the size of the remainder of the data block */
685 pcfdata->cbData = read_result - pcfdata->cbData;
686 /*recover former value of cfdata.cbData; read_result will be the offset*/
687 read_result -= pcfdata->cbData;
688 pcfdata->cbUncomp = savedUncomp;
690 /* reset checksum, it will be computed later */
693 /* write cfdata WITHOUT checksum to handleCFDATA1new */
694 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
695 buffer, /* memory buffer */
696 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
697 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
698 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
701 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
703 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
705 /* write compressed data into handleCFDATA1new */
706 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
707 p_fci_internal->data_out + read_result, /* memory buffer + offset */
708 /* to last part of split data */
709 pcfdata->cbData, /* number of bytes to copy */
710 err, p_fci_internal->pv) != pcfdata->cbData) {
711 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
714 /* TODO error handling of err */
716 p_fci_internal->statusFolderCopied += pcfdata->cbData;
718 *psizeFileCFDATA1new += pcfdata->cbData;
719 /* the two blocks of the split data block have been written */
720 /* don't reset split_data yet, because it is still needed see below */
723 /* report status with pfnfcis about copied size of folder */
724 if( (*pfnfcis)(statusFolder,
725 p_fci_internal->statusFolderCopied, /*cfdata.cbData(+previous ones)*/
726 p_fci_internal->statusFolderTotal, /* total folder size */
727 p_fci_internal->pv) == -1) {
728 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
733 /* if cabinet size too large */
734 /* write the remaining data blocks to the new CFDATA1 file */
735 if ( split_block ) { /* This does include the */
736 /* abused one (just search for "abused" )*/
737 if (p_fci_internal->fNextCab==FALSE ) {
739 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
742 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
744 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
745 read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/* handle */
746 buffer, /* memory buffer */
747 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
748 err, p_fci_internal->pv);
749 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
750 if (read_result==0) break; /* ALL DATA has been copied */
752 fci_set_error(FCIERR_NONE, ERROR_READ_FAULT, TRUE );
755 /* TODO error handling of err */
757 /* REUSE buffer p_fci_internal->data_out !!! */
758 /* read data from p_fci_internal->handleCFDATA1 to */
759 /* p_fci_internal->data_out */
760 if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
761 p_fci_internal->data_out /* memory buffer */,
762 pcfdata->cbData /* number of bytes to copy */,
763 err, p_fci_internal->pv) != pcfdata->cbData ) {
765 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE);
768 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
770 /* write cfdata with checksum to handleCFDATA1new */
771 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
772 buffer, /* memory buffer */
773 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
774 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
775 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
778 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
780 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
782 /* write compressed data into handleCFDATA1new */
783 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
784 p_fci_internal->data_out, /* memory buffer */
785 pcfdata->cbData, /* number of bytes to copy */
786 err, p_fci_internal->pv) != pcfdata->cbData) {
787 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
790 /* TODO error handling of err */
792 *psizeFileCFDATA1new += pcfdata->cbData;
793 p_fci_internal->statusFolderCopied += pcfdata->cbData;
795 /* report status with pfnfcis about copied size of folder */
796 if( (*pfnfcis)(statusFolder,
797 p_fci_internal->statusFolderCopied,/*cfdata.cbData(+revious ones)*/
798 p_fci_internal->statusFolderTotal, /* total folder size */
799 p_fci_internal->pv) == -1) {
800 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
805 break; /* jump out of the next while loop */
806 } /* end of if( split_data ) */
809 } /* end of fci_flushfolder_copy_cfdata */
815 static BOOL fci_flushfolder_copy_cffolder(HFCI hfci, int* err, UINT cbReserveCFFolder,
816 cab_ULONG sizeFileCFDATA2old)
821 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
823 /* absolute offset cannot be set yet, because the size of cabinet header, */
824 /* the number of CFFOLDERs and the number of CFFILEs may change. */
825 /* Instead the size of all previous data blocks will be stored and */
826 /* the remainder of the offset will be added when the cabinet will be */
827 /* flushed to disk. */
828 /* This is exactly the way the original CABINET.DLL works!!! */
829 cffolder.coffCabStart=sizeFileCFDATA2old;
831 /* set the number of this folder's CFDATA sections */
832 cffolder.cCFData=p_fci_internal->cDataBlocks;
833 /* TODO set compression type */
834 cffolder.typeCompress = tcompTYPE_NONE;
836 /* write cffolder to p_fci_internal->handleCFFOLDER */
837 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
838 &cffolder, /* memory buffer */
839 sizeof(cffolder), /* number of bytes to copy */
840 err, p_fci_internal->pv) != sizeof(cffolder) ) {
841 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
844 /* TODO error handling of err */
846 p_fci_internal->sizeFileCFFOLDER += sizeof(cffolder);
848 /* add optional reserved area */
849 if (cbReserveCFFolder!=0) {
850 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFFolder))) {
851 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
854 for(i=0;i<cbReserveCFFolder;) {
857 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
858 reserved, /* memory buffer */
859 cbReserveCFFolder, /* number of bytes to copy */
860 err, p_fci_internal->pv) != cbReserveCFFolder ) {
861 PFCI_FREE(hfci, reserved);
862 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
865 /* TODO error handling of err */
867 p_fci_internal->sizeFileCFFOLDER += cbReserveCFFolder;
869 PFCI_FREE(hfci, reserved);
872 } /* end of fci_flushfolder_copy_cffolder */
878 static BOOL fci_flushfolder_copy_cffile(HFCI hfci, int* err, int handleCFFILE1new,
879 cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload)
882 cab_ULONG read_result;
884 cab_ULONG sizeOfFiles=0, sizeOfFilesPrev;
885 BOOL may_be_prev=TRUE;
886 cab_ULONG cbFileRemainer=0;
887 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
888 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
889 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,0,SEEK_SET,err,
890 p_fci_internal->pv) !=0 ) {
891 /* wrong return value */
892 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
895 /* TODO error handling of err */
897 /* while not all CFFILE structures have been copied do */
899 /* REUSE the variable read_result */
900 /* read data from p_fci_internal->handleCFFILE1 to cffile */
901 read_result = PFCI_READ(hfci,p_fci_internal->handleCFFILE1/* file handle */,
902 &cffile, /* memory buffer */
903 sizeof(cffile), /* number of bytes to copy */
904 err, p_fci_internal->pv);
905 if( read_result != sizeof(cffile) ) {
906 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
908 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
911 /* TODO error handling of err */
913 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
914 /* position. I don't know why so I'll just omit it */
916 /* read the filename from p_fci_internal->handleCFFILE1 */
917 /* REUSE the variable read_result AGAIN */
918 /* REUSE the memory buffer PFCI(hfci)->data_out */
919 if( PFCI_READ(hfci, p_fci_internal->handleCFFILE1 /*file handle*/,
920 p_fci_internal->data_out, /* memory buffer */
921 CB_MAX_FILENAME, /* number of bytes to copy */
922 err, p_fci_internal->pv) <2) {
924 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
927 /* TODO maybe other checks of read_result */
928 /* TODO error handling of err */
931 if( strlen(p_fci_internal->data_out)>=CB_MAX_FILENAME ) {
932 /* set error code internal error */
933 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
937 seek+=sizeof(cffile) + strlen(p_fci_internal->data_out)+1;
939 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
940 /* i.e. seek to the next CFFILE area */
941 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,
942 seek, /* seek position*/
946 /* wrong return value */
947 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
950 /* TODO error handling of err */
952 /* fnfilfnfildest: placed file on cabinet */
953 if (p_fci_internal->fNextCab ||
954 p_fci_internal->fGetNextCabInVain) {
955 PFCI_FILEPLACED( hfci, &(p_fci_internal->oldCCAB),
956 p_fci_internal->data_out, /* the file name*/
957 cffile.cbFile, /* file size */
958 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
962 PFCI_FILEPLACED( hfci, p_fci_internal->pccab,
963 p_fci_internal->data_out, /* the file name*/
964 cffile.cbFile, /* file size */
965 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
970 /* Check special iFolder values */
971 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
972 p_fci_internal->fPrevCab==FALSE ) {
973 /* THIS MAY NEVER HAPPEN */
975 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
978 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
979 cffile.iFolder==cffileCONTINUED_TO_NEXT ) {
980 /* THIS MAY NEVER HAPPEN */
982 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
985 if( may_be_prev && cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
988 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && may_be_prev==FALSE ) {
989 /* THIS MAY NEVER HAPPEN */
991 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
994 if( cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
998 sizeOfFilesPrev=sizeOfFiles;
999 /* Set complete size of all processed files */
1000 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
1001 p_fci_internal->cbFileRemainer!=0
1003 sizeOfFiles+=p_fci_internal->cbFileRemainer;
1004 p_fci_internal->cbFileRemainer=0;
1006 sizeOfFiles+=cffile.cbFile;
1009 /* Check if spanned file fits into this cabinet folder */
1010 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && sizeOfFiles>payload ) {
1011 cffile.iFolder=cffileCONTINUED_PREV_AND_NEXT;
1014 /* Check if file doesn't fit into this cabinet folder */
1015 if( sizeOfFiles>payload ) {
1016 cffile.iFolder=cffileCONTINUED_TO_NEXT;
1019 /* set little endian */
1020 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1021 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1022 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1023 cffile.date=fci_endian_uword(cffile.date);
1024 cffile.time=fci_endian_uword(cffile.time);
1025 cffile.attribs=fci_endian_uword(cffile.attribs);
1027 /* write cffile to p_fci_internal->handleCFFILE2 */
1028 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */
1029 &cffile, /* memory buffer */
1030 sizeof(cffile), /* number of bytes to copy */
1031 err, p_fci_internal->pv) != sizeof(cffile) ) {
1032 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1035 /* TODO error handling of err */
1037 p_fci_internal->sizeFileCFFILE2 += sizeof(cffile);
1039 /* reset little endian */
1040 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1041 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1042 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1043 cffile.date=fci_endian_uword(cffile.date);
1044 cffile.time=fci_endian_uword(cffile.time);
1045 cffile.attribs=fci_endian_uword(cffile.attribs);
1047 /* write file name to p_fci_internal->handleCFFILE2 */
1048 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */
1049 p_fci_internal->data_out, /* memory buffer */
1050 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1051 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1052 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1055 /* TODO error handling of err */
1057 p_fci_internal->sizeFileCFFILE2 += strlen(p_fci_internal->data_out)+1;
1059 /* cFiles is used to count all files of a cabinet */
1060 ++(p_fci_internal->cFiles);
1062 /* This is only true for files which will be written into the */
1063 /* next cabinet of the spanning folder */
1064 if( sizeOfFiles>payload ) {
1066 /* Files which data will be partially written into the current cabinet */
1067 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
1068 cffile.iFolder==cffileCONTINUED_TO_NEXT
1070 if( sizeOfFilesPrev<=payload ) {
1071 /* The size of the uncompressed, data of a spanning file in a */
1073 cbFileRemainer=sizeOfFiles-payload;
1075 cffile.iFolder=cffileCONTINUED_FROM_PREV;
1080 /* write cffile into handleCFFILE1new */
1081 if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */
1082 &cffile, /* memory buffer */
1083 sizeof(cffile), /* number of bytes to copy */
1084 err, p_fci_internal->pv) != sizeof(cffile) ) {
1085 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1088 /* TODO error handling of err */
1090 *psizeFileCFFILE1new += sizeof(cffile);
1091 /* write name of file into handleCFFILE1new */
1092 if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */
1093 p_fci_internal->data_out, /* memory buffer */
1094 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1095 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1096 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1099 /* TODO error handling of err */
1101 *psizeFileCFFILE1new += strlen(p_fci_internal->data_out)+1;
1104 } /* END OF while */
1105 p_fci_internal->cbFileRemainer=cbFileRemainer;
1107 } /* end of fci_flushfolder_copy_cffile */
1112 static BOOL fci_flush_folder(
1115 PFNFCIGETNEXTCABINET pfnfcignc,
1116 PFNFCISTATUS pfnfcis)
1119 int handleCFDATA1new; /* handle for new temp file */
1120 char szFileNameCFDATA1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1121 int handleCFFILE1new; /* handle for new temp file */
1122 char szFileNameCFFILE1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1123 UINT cbReserveCFData, cbReserveCFFolder;
1125 cab_ULONG sizeFileCFDATA1new=0;
1126 cab_ULONG sizeFileCFFILE1new=0;
1127 cab_ULONG sizeFileCFDATA2old;
1129 cab_ULONG read_result;
1130 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
1133 if (!REALLY_IS_FCI(hfci)) {
1134 SetLastError(ERROR_INVALID_HANDLE);
1138 if ((!pfnfcignc) || (!pfnfcis)) {
1139 fci_set_error( FCIERR_NONE, ERROR_BAD_ARGUMENTS, TRUE );
1143 if( p_fci_internal->fGetNextCabInVain &&
1144 p_fci_internal->fNextCab ){
1145 /* internal error */
1146 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1150 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1151 /* this function will return TRUE */
1152 if( p_fci_internal->sizeFileCFFILE1 == 0 ) {
1153 if ( p_fci_internal->sizeFileCFDATA1 != 0 ) {
1154 /* error handling */
1155 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1161 if (p_fci_internal->data_in==NULL || p_fci_internal->data_out==NULL ) {
1162 /* error handling */
1163 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1167 /* FCIFlushFolder has already been called... */
1168 if (p_fci_internal->fSplitFolder && p_fci_internal->sizeFileCFFILE2!=0) {
1172 /* This can be set already, because it makes only a difference */
1173 /* when the current function exits with return FALSE */
1174 p_fci_internal->fSplitFolder=FALSE;
1177 if( p_fci_internal->fGetNextCabInVain ||
1178 p_fci_internal->fNextCab ){
1179 cbReserveCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1180 cbReserveCFFolder = p_fci_internal->oldCCAB.cbReserveCFFolder;
1182 cbReserveCFData = p_fci_internal->pccab->cbReserveCFData;
1183 cbReserveCFFolder = p_fci_internal->pccab->cbReserveCFFolder;
1187 /* if there is data in p_fci_internal->data_in */
1188 if (p_fci_internal->cdata_in!=0) {
1190 if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;
1193 /* reset to get the number of data blocks of this folder which are */
1194 /* actually in this cabinet ( at least partially ) */
1195 p_fci_internal->cDataBlocks=0;
1197 if ( p_fci_internal->fNextCab ||
1198 p_fci_internal->fGetNextCabInVain ) {
1199 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader+
1200 p_fci_internal->oldCCAB.cbReserveCFFolder;
1201 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1202 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1203 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1207 read_result= p_fci_internal->pccab->cbReserveCFHeader+
1208 p_fci_internal->pccab->cbReserveCFFolder;
1209 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1210 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1211 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1215 if (p_fci_internal->fPrevCab) {
1216 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1217 strlen(p_fci_internal->szPrevDisk)+1;
1219 if (p_fci_internal->fNextCab) {
1220 read_result+=strlen(p_fci_internal->pccab->szCab)+1 +
1221 strlen(p_fci_internal->pccab->szDisk)+1;
1224 p_fci_internal->statusFolderTotal = sizeof(CFHEADER)+read_result+
1225 sizeof(CFFOLDER) + p_fci_internal->sizeFileCFFILE2+
1226 p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1+
1227 p_fci_internal->sizeFileCFDATA1 + p_fci_internal->sizeFileCFFOLDER;
1228 p_fci_internal->statusFolderCopied = 0;
1230 /* report status with pfnfcis about copied size of folder */
1231 if( (*pfnfcis)(statusFolder, p_fci_internal->statusFolderCopied,
1232 p_fci_internal->statusFolderTotal, /* TODO total folder size */
1233 p_fci_internal->pv) == -1) {
1234 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
1238 /* get a new temp file */
1239 if(!PFCI_GETTEMPFILE(hfci,szFileNameCFDATA1new,CB_MAX_FILENAME)) {
1240 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1244 if ( strlen(szFileNameCFDATA1new) >= CB_MAX_FILENAME ) {
1245 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1248 handleCFDATA1new = PFCI_OPEN(hfci,szFileNameCFDATA1new,34050,384,&err,
1249 p_fci_internal->pv);
1250 if(handleCFDATA1new==0){
1251 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
1254 /* TODO error handling of err */
1258 /* get a new temp file */
1259 if(!PFCI_GETTEMPFILE(hfci,szFileNameCFFILE1new,CB_MAX_FILENAME)) {
1260 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1261 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1262 /* TODO error handling of err */
1266 if ( strlen(szFileNameCFFILE1new) >= CB_MAX_FILENAME ) {
1267 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1268 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1269 /* TODO error handling of err */
1272 handleCFFILE1new = PFCI_OPEN(hfci,szFileNameCFFILE1new,34050,384,&err,
1273 p_fci_internal->pv);
1274 if(handleCFFILE1new==0){
1275 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
1278 /* TODO error handling of err */
1280 /* USE the variable read_result */
1281 if ( p_fci_internal->fNextCab ||
1282 p_fci_internal->fGetNextCabInVain ) {
1283 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader;
1284 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1285 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1286 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1290 read_result= p_fci_internal->pccab->cbReserveCFHeader;
1291 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1292 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1293 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1297 if (p_fci_internal->fPrevCab) {
1298 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1299 strlen(p_fci_internal->szPrevDisk)+1;
1301 read_result+= sizeof(CFHEADER) + p_fci_internal->sizeFileCFDATA2 +
1302 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER;
1304 if(p_fci_internal->sizeFileCFFILE1!=0) {
1305 read_result+= sizeof(CFFOLDER)+p_fci_internal->pccab->cbReserveCFFolder;
1308 /* Check if multiple cabinets have to be created. */
1310 /* Might be too much data for the maximum allowed cabinet size.*/
1311 /* When any further data will be added later, it might not */
1312 /* be possible to flush the cabinet, because there might */
1313 /* not be enough space to store the name of the following */
1314 /* cabinet and name of the corresponding disk. */
1315 /* So take care of this and get the name of the next cabinet */
1316 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1317 p_fci_internal->fNextCab==FALSE &&
1320 p_fci_internal->pccab->cb < read_result +
1321 p_fci_internal->sizeFileCFDATA1 +
1322 p_fci_internal->sizeFileCFFILE1 +
1323 CB_MAX_CABINET_NAME + /* next cabinet name */
1324 CB_MAX_DISK_NAME /* next disk name */
1329 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
1330 /* increment cabinet index */
1331 ++(p_fci_internal->pccab->iCab);
1332 /* get name of next cabinet */
1333 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
1334 if (!(*pfnfcignc)(p_fci_internal->pccab,
1335 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
1336 p_fci_internal->pv)) {
1337 /* error handling */
1338 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1339 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1340 /* TODO error handling of err */
1341 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1342 /* TODO error handling of err */
1346 /* Skip a few lines of code. This is caught by the next if. */
1347 p_fci_internal->fGetNextCabInVain=TRUE;
1350 /* too much data for cabinet */
1351 if( (p_fci_internal->fGetNextCabInVain ||
1352 p_fci_internal->fNextCab ) &&
1355 p_fci_internal->oldCCAB.cb < read_result +
1356 p_fci_internal->sizeFileCFDATA1 +
1357 p_fci_internal->sizeFileCFFILE1 +
1358 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1359 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1363 p_fci_internal->fGetNextCabInVain=FALSE;
1364 p_fci_internal->fNextCab=TRUE;
1366 /* return FALSE if there is not enough space left*/
1367 /* this should never happen */
1368 if (p_fci_internal->oldCCAB.cb <=
1369 p_fci_internal->sizeFileCFFILE1 +
1371 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1372 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1375 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1376 /* TODO error handling of err */
1377 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1378 /* TODO error handling of err */
1380 /* close and delete p_fci_internal->handleCFFILE1 */
1381 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1382 /* TODO error handling of err */
1383 PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);
1384 /* TODO error handling of err */
1389 /* the folder will be split across cabinets */
1390 p_fci_internal->fSplitFolder=TRUE;
1393 /* this should never happen */
1394 if (p_fci_internal->fNextCab) {
1395 /* internal error */
1396 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1401 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1402 if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA1,0,SEEK_SET,&err,
1403 p_fci_internal->pv) !=0 ) {
1404 /* wrong return value */
1405 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1406 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1407 /* TODO error handling of err */
1408 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1409 /* TODO error handling of err */
1412 /* TODO error handling of err */
1414 /* save size of file CFDATA2 - required for the folder's offset to data */
1415 sizeFileCFDATA2old = p_fci_internal->sizeFileCFDATA2;
1417 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData+sizeof(CFDATA)))) {
1418 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1419 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1420 /* TODO error handling of err */
1421 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1422 /* TODO error handling of err */
1426 if(!fci_flushfolder_copy_cfdata(hfci, reserved, cbReserveCFData, pfnfcis, &err,
1427 handleCFDATA1new, &sizeFileCFDATA1new, &payload
1429 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1430 /* TODO error handling of err */
1431 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1432 /* TODO error handling of err */
1433 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1434 /* TODO error handling of err */
1435 PFCI_FREE(hfci,reserved);
1439 PFCI_FREE(hfci,reserved);
1441 if(!fci_flushfolder_copy_cffolder(hfci, &err, cbReserveCFFolder,
1442 sizeFileCFDATA2old )) {
1443 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1444 /* TODO error handling of err */
1445 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1446 /* TODO error handling of err */
1447 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1448 /* TODO error handling of err */
1452 if(!fci_flushfolder_copy_cffile(hfci, &err, handleCFFILE1new,
1453 &sizeFileCFFILE1new, payload)) {
1454 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1455 /* TODO error handling of err */
1456 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1457 /* TODO error handling of err */
1458 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1459 /* TODO error handling of err */
1460 PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);
1461 /* TODO error handling of err */
1465 /* close and delete p_fci_internal->handleCFDATA1 */
1466 PFCI_CLOSE(hfci,p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
1467 /* TODO error handling of err */
1468 PFCI_DELETE(hfci,p_fci_internal->szFileNameCFDATA1,&err,p_fci_internal->pv);
1469 /* TODO error handling of err */
1471 /* put new CFDATA1 into hfci */
1472 memcpy(p_fci_internal->szFileNameCFDATA1,szFileNameCFDATA1new,
1475 /* put CFDATA1 file handle */
1476 PFCI_INT(hfci)->handleCFDATA1 = handleCFDATA1new;
1478 PFCI_INT(hfci)->sizeFileCFDATA1 = sizeFileCFDATA1new;
1480 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1481 PFCI_CLOSE(hfci,p_fci_internal->handleCFFILE1,&err,PFCI_INT(hfci)->pv);
1482 /* TODO error handling of err */
1483 PFCI_DELETE(hfci,p_fci_internal->szFileNameCFFILE1,&err,p_fci_internal->pv);
1484 /* TODO error handling of err */
1486 /* put new CFFILE1 into hfci */
1487 memcpy(p_fci_internal->szFileNameCFFILE1,szFileNameCFFILE1new,
1490 /* put CFFILE1 file handle */
1491 p_fci_internal->handleCFFILE1 = handleCFFILE1new;
1493 p_fci_internal->sizeFileCFFILE1 = sizeFileCFFILE1new;
1495 ++(p_fci_internal->cFolders);
1497 /* reset CFFolder specific information */
1498 p_fci_internal->cDataBlocks=0;
1499 p_fci_internal->cCompressedBytesInFolder=0;
1502 } /* end of fci_flush_folder */
1507 static BOOL fci_flush_cabinet(
1510 PFNFCIGETNEXTCABINET pfnfcignc,
1511 PFNFCISTATUS pfnfcis)
1516 cab_UWORD cbCFHeader;
1517 cab_UBYTE cbCFFolder;
1521 cab_ULONG read_result=0;
1522 int handleCABINET; /* file handle for cabinet */
1523 char szFileNameCABINET[CB_MAX_CAB_PATH+CB_MAX_CABINET_NAME];/* name buffer */
1524 UINT cbReserveCFHeader, cbReserveCFFolder, i;
1526 BOOL returntrue=FALSE;
1527 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
1529 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1531 /* when FCIFlushCabinet was or FCIAddFile hasn't been called */
1532 if( p_fci_internal->sizeFileCFFILE1==0 && fGetNextCab ) {
1536 if (!fci_flush_folder(hfci,fGetNextCab,pfnfcignc,pfnfcis)){
1537 /* TODO set error */
1541 if(returntrue) return TRUE;
1543 if ( (p_fci_internal->fSplitFolder && p_fci_internal->fNextCab==FALSE)||
1544 (p_fci_internal->sizeFileCFFOLDER==0 &&
1545 (p_fci_internal->sizeFileCFFILE1!=0 ||
1546 p_fci_internal->sizeFileCFFILE2!=0 )
1550 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1554 if( p_fci_internal->fNextCab ||
1555 p_fci_internal->fGetNextCabInVain ) {
1556 cbReserveCFFolder=p_fci_internal->oldCCAB.cbReserveCFFolder;
1557 cbReserveCFHeader=p_fci_internal->oldCCAB.cbReserveCFHeader;
1559 if (strlen(p_fci_internal->oldCCAB.szCabPath)>=CB_MAX_CAB_PATH ||
1560 strlen(p_fci_internal->oldCCAB.szCab)>=CB_MAX_CABINET_NAME) {
1562 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1565 /* get the full name of the cabinet */
1566 memcpy(szFileNameCABINET,p_fci_internal->oldCCAB.szCabPath,
1568 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1569 p_fci_internal->oldCCAB.szCab, CB_MAX_CABINET_NAME);
1571 cbReserveCFFolder=p_fci_internal->pccab->cbReserveCFFolder;
1572 cbReserveCFHeader=p_fci_internal->pccab->cbReserveCFHeader;
1574 if (strlen(p_fci_internal->pccab->szCabPath)>=CB_MAX_CAB_PATH ||
1575 strlen(p_fci_internal->pccab->szCab)>=CB_MAX_CABINET_NAME) {
1577 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1580 /* get the full name of the cabinet */
1581 memcpy(szFileNameCABINET,p_fci_internal->pccab->szCabPath,
1583 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1584 p_fci_internal->pccab->szCab, CB_MAX_CABINET_NAME);
1587 memcpy(cfheader.signature,"!CAB",4);
1588 cfheader.reserved1=0;
1589 cfheader.cbCabinet= /* size of the cabinet file in bytes */
1591 p_fci_internal->sizeFileCFFOLDER +
1592 p_fci_internal->sizeFileCFFILE2 +
1593 p_fci_internal->sizeFileCFDATA2;
1595 if (p_fci_internal->fPrevCab) {
1596 cfheader.cbCabinet+=strlen(p_fci_internal->szPrevCab)+1 +
1597 strlen(p_fci_internal->szPrevDisk)+1;
1599 if (p_fci_internal->fNextCab) {
1600 cfheader.cbCabinet+=strlen(p_fci_internal->pccab->szCab)+1 +
1601 strlen(p_fci_internal->pccab->szDisk)+1;
1603 if( p_fci_internal->fNextCab ||
1604 p_fci_internal->fGetNextCabInVain ) {
1605 cfheader.cbCabinet+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1606 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1607 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1608 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1609 cfheader.cbCabinet+=4;
1612 cfheader.cbCabinet+=p_fci_internal->pccab->cbReserveCFHeader;
1613 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1614 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1615 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1616 cfheader.cbCabinet+=4;
1620 if( ( ( p_fci_internal->fNextCab ||
1621 p_fci_internal->fGetNextCabInVain ) &&
1622 cfheader.cbCabinet > p_fci_internal->oldCCAB.cb
1624 ( ( p_fci_internal->fNextCab==FALSE &&
1625 p_fci_internal->fGetNextCabInVain==FALSE ) &&
1626 cfheader.cbCabinet > p_fci_internal->pccab->cb
1630 fci_set_error( FCIERR_NONE, ERROR_MORE_DATA, TRUE );
1635 cfheader.reserved2=0;
1636 cfheader.coffFiles= /* offset to first CFFILE section */
1637 cfheader.cbCabinet - p_fci_internal->sizeFileCFFILE2 -
1638 p_fci_internal->sizeFileCFDATA2;
1640 cfheader.reserved3=0;
1641 cfheader.versionMinor=3;
1642 cfheader.versionMajor=1;
1643 /* number of CFFOLDER entries in the cabinet */
1644 cfheader.cFolders=p_fci_internal->cFolders;
1645 /* number of CFFILE entries in the cabinet */
1646 cfheader.cFiles=p_fci_internal->cFiles;
1647 cfheader.flags=0; /* 1=prev cab, 2=next cabinet, 4=reserved setions */
1649 if( p_fci_internal->fPrevCab ) {
1650 cfheader.flags = cfheadPREV_CABINET;
1653 if( p_fci_internal->fNextCab ) {
1654 cfheader.flags |= cfheadNEXT_CABINET;
1657 if( p_fci_internal->fNextCab ||
1658 p_fci_internal->fGetNextCabInVain ) {
1659 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1660 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1661 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1662 cfheader.flags |= cfheadRESERVE_PRESENT;
1664 cfheader.setID = p_fci_internal->oldCCAB.setID;
1665 cfheader.iCabinet = p_fci_internal->oldCCAB.iCab-1;
1667 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1668 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1669 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1670 cfheader.flags |= cfheadRESERVE_PRESENT;
1672 cfheader.setID = p_fci_internal->pccab->setID;
1673 cfheader.iCabinet = p_fci_internal->pccab->iCab-1;
1676 /* create the cabinet */
1677 handleCABINET = PFCI_OPEN(hfci, szFileNameCABINET,
1678 33538, 384, &err, p_fci_internal->pv );
1679 if(handleCABINET==0){
1680 fci_set_error( FCIERR_CAB_FILE, ERROR_OPEN_FAILED, TRUE );
1683 /* TODO error checking of err */
1685 /* set little endian */
1686 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1687 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1688 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1689 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1690 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1691 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1692 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1693 cfheader.flags=fci_endian_uword(cfheader.flags);
1694 cfheader.setID=fci_endian_uword(cfheader.setID);
1695 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1697 /* write CFHEADER into cabinet file */
1698 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1699 &cfheader, /* memory buffer */
1700 sizeof(cfheader), /* number of bytes to copy */
1701 &err, p_fci_internal->pv) != sizeof(cfheader) ) {
1703 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1706 /* TODO error handling of err */
1708 /* reset little endian */
1709 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1710 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1711 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1712 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1713 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1714 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1715 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1716 cfheader.flags=fci_endian_uword(cfheader.flags);
1717 cfheader.setID=fci_endian_uword(cfheader.setID);
1718 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1720 if( cfheader.flags & cfheadRESERVE_PRESENT ) {
1721 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1722 cfreserved.cbCFHeader = cbReserveCFHeader;
1723 cfreserved.cbCFFolder = cbReserveCFFolder;
1724 if( p_fci_internal->fNextCab ||
1725 p_fci_internal->fGetNextCabInVain ) {
1726 cfreserved.cbCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1728 cfreserved.cbCFData = p_fci_internal->pccab->cbReserveCFData;
1731 /* set little endian */
1732 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1734 /* write reserved info into cabinet file */
1735 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1736 &cfreserved, /* memory buffer */
1737 sizeof(cfreserved), /* number of bytes to copy */
1738 &err, p_fci_internal->pv) != sizeof(cfreserved) ) {
1740 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1743 /* TODO error handling of err */
1745 /* reset little endian */
1746 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1749 /* add optional reserved area */
1750 if (cbReserveCFHeader!=0) {
1751 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFHeader))) {
1752 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1755 for(i=0;i<cbReserveCFHeader;) {
1758 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1759 reserved, /* memory buffer */
1760 cbReserveCFHeader, /* number of bytes to copy */
1761 &err, p_fci_internal->pv) != cbReserveCFHeader ) {
1762 PFCI_FREE(hfci, reserved);
1764 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1767 /* TODO error handling of err */
1768 PFCI_FREE(hfci, reserved);
1771 if( cfheader.flags & cfheadPREV_CABINET ) {
1772 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1773 p_fci_internal->szPrevCab, /* memory buffer */
1774 strlen(p_fci_internal->szPrevCab)+1, /* number of bytes to copy */
1775 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevCab)+1 ) {
1777 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1780 /* TODO error handling of err */
1782 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1783 p_fci_internal->szPrevDisk, /* memory buffer */
1784 strlen(p_fci_internal->szPrevDisk)+1, /* number of bytes to copy */
1785 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevDisk)+1 ) {
1787 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1790 /* TODO error handling of err */
1793 if( cfheader.flags & cfheadNEXT_CABINET ) {
1794 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1795 p_fci_internal->pccab->szCab, /* memory buffer */
1796 strlen(p_fci_internal->pccab->szCab)+1, /* number of bytes to copy */
1797 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szCab)+1 ) {
1799 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1802 /* TODO error handling of err */
1804 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1805 p_fci_internal->pccab->szDisk, /* memory buffer */
1806 strlen(p_fci_internal->pccab->szDisk)+1, /* number of bytes to copy */
1807 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szDisk)+1 ) {
1809 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1812 /* TODO error handling of err */
1815 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1816 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFOLDER,
1817 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1818 /* wrong return value */
1819 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1822 /* TODO error handling of err */
1824 /* while not all CFFOLDER structures have been copied into the cabinet do */
1826 /* use the variable read_result */
1827 /* read cffolder of p_fci_internal->handleCFFOLDER */
1828 read_result = PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* handle */
1829 &cffolder, /* memory buffer */
1830 sizeof(cffolder), /* number of bytes to copy */
1831 &err, p_fci_internal->pv);
1832 if( read_result != sizeof(cffolder) ) {
1833 if( read_result == 0 ) break;/*ALL CFFOLDER structures have been copied*/
1835 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
1838 /* TODO error handling of err */
1840 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1841 cffolder.coffCabStart +=
1842 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
1844 if( p_fci_internal->fNextCab ||
1845 p_fci_internal->fGetNextCabInVain ) {
1846 cffolder.coffCabStart+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1848 cffolder.coffCabStart+=p_fci_internal->pccab->cbReserveCFHeader;
1851 if (p_fci_internal->fPrevCab) {
1852 cffolder.coffCabStart += strlen(p_fci_internal->szPrevCab)+1 +
1853 strlen(p_fci_internal->szPrevDisk)+1;
1856 if (p_fci_internal->fNextCab) {
1857 cffolder.coffCabStart += strlen(p_fci_internal->oldCCAB.szCab)+1 +
1858 strlen(p_fci_internal->oldCCAB.szDisk)+1;
1861 if( p_fci_internal->fNextCab ||
1862 p_fci_internal->fGetNextCabInVain ) {
1863 cffolder.coffCabStart += p_fci_internal->oldCCAB.cbReserveCFHeader;
1864 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1865 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1866 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1867 cffolder.coffCabStart += 4;
1870 cffolder.coffCabStart += p_fci_internal->pccab->cbReserveCFHeader;
1871 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1872 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1873 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1874 cffolder.coffCabStart += 4;
1878 /* set little endian */
1879 cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
1880 cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
1881 cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
1883 /* write cffolder to cabinet file */
1884 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1885 &cffolder, /* memory buffer */
1886 sizeof(cffolder), /* number of bytes to copy */
1887 &err, p_fci_internal->pv) != sizeof(cffolder) ) {
1889 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1892 /* TODO error handling of err */
1894 /* reset little endian */
1895 cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
1896 cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
1897 cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
1899 /* add optional reserved area */
1901 /* This allocation and freeing at each CFFolder block is a bit */
1902 /* inefficent, but it's harder to forget about freeing the buffer :-). */
1903 /* Reserved areas are used seldom besides that... */
1904 if (cbReserveCFFolder!=0) {
1905 if(!(reserved = PFCI_ALLOC(hfci, cbReserveCFFolder))) {
1906 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1910 if( PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
1911 reserved, /* memory buffer */
1912 cbReserveCFFolder, /* number of bytes to copy */
1913 &err, p_fci_internal->pv) != cbReserveCFFolder ) {
1914 PFCI_FREE(hfci, reserved);
1916 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
1919 /* TODO error handling of err */
1921 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1922 reserved, /* memory buffer */
1923 cbReserveCFFolder, /* number of bytes to copy */
1924 &err, p_fci_internal->pv) != cbReserveCFFolder ) {
1925 PFCI_FREE(hfci, reserved);
1927 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1930 /* TODO error handling of err */
1932 PFCI_FREE(hfci, reserved);
1935 } /* END OF while */
1937 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1938 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE2,
1939 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1940 /* wrong return value */
1941 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1944 /* TODO error handling of err */
1946 /* while not all CFFILE structures have been copied to the cabinet do */
1948 /* REUSE the variable read_result */
1949 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1950 /* read a block from p_fci_internal->handleCFFILE2 */
1951 read_result = PFCI_READ(hfci, p_fci_internal->handleCFFILE2 /* handle */,
1952 p_fci_internal->data_out, /* memory buffer */
1953 CB_MAX_CHUNK, /* number of bytes to copy */
1954 &err, p_fci_internal->pv);
1955 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
1956 /* TODO error handling of err */
1958 /* write the block to the cabinet file */
1959 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1960 p_fci_internal->data_out, /* memory buffer */
1961 read_result, /* number of bytes to copy */
1962 &err, p_fci_internal->pv) != read_result ) {
1964 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1967 /* TODO error handling of err */
1969 if (p_fci_internal->fSplitFolder==FALSE) {
1970 p_fci_internal->statusFolderCopied = 0;
1971 /* TODO TEST THIS further */
1972 p_fci_internal->statusFolderTotal = p_fci_internal->sizeFileCFDATA2+
1973 p_fci_internal->sizeFileCFFILE2;
1975 p_fci_internal->statusFolderCopied += read_result;
1977 /* report status with pfnfcis about copied size of folder */
1978 if( (*pfnfcis)(statusFolder,
1979 p_fci_internal->statusFolderCopied, /* length of copied blocks */
1980 p_fci_internal->statusFolderTotal, /* total size of folder */
1981 p_fci_internal->pv) == -1) {
1982 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
1986 } /* END OF while */
1988 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1989 if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA2,
1990 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1991 /* wrong return value */
1992 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1995 /* TODO error handling of err */
1997 /* reset the number of folders for the next cabinet */
1998 p_fci_internal->cFolders=0;
1999 /* reset the number of files for the next cabinet */
2000 p_fci_internal->cFiles=0;
2002 /* while not all CFDATA structures have been copied to the cabinet do */
2004 /* REUSE the variable read_result AGAIN */
2005 /* REUSE the buffer p_fci_internal->data_out AGAIN */
2006 /* read a block from p_fci_internal->handleCFDATA2 */
2007 read_result = PFCI_READ(hfci, p_fci_internal->handleCFDATA2 /* handle */,
2008 p_fci_internal->data_out, /* memory buffer */
2009 CB_MAX_CHUNK, /* number of bytes to copy */
2010 &err, p_fci_internal->pv);
2011 if( read_result == 0 ) break; /* ALL CFDATA structures have been copied */
2012 /* TODO error handling of err */
2014 /* write the block to the cabinet file */
2015 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
2016 p_fci_internal->data_out, /* memory buffer */
2017 read_result, /* number of bytes to copy */
2018 &err, p_fci_internal->pv) != read_result ) {
2020 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
2023 /* TODO error handling of err */
2025 p_fci_internal->statusFolderCopied += read_result;
2026 /* report status with pfnfcis about copied size of folder */
2027 if( (*pfnfcis)(statusFolder,
2028 p_fci_internal->statusFolderCopied, /* length of copied blocks */
2029 p_fci_internal->statusFolderTotal, /* total size of folder */
2030 p_fci_internal->pv) == -1) {
2031 /* set error code and abort */
2032 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
2035 } /* END OF while */
2037 /* set seek of the cabinet file to 0 */
2038 if( PFCI_SEEK(hfci, handleCABINET,
2039 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
2040 /* wrong return value */
2041 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
2044 /* TODO error handling of err */
2046 /* write the signature "MSCF" into the cabinet file */
2047 memcpy( cfheader.signature, "MSCF", 4 );
2048 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
2049 &cfheader, /* memory buffer */
2050 4, /* number of bytes to copy */
2051 &err, p_fci_internal->pv) != 4 ) {
2053 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
2056 /* TODO error handling of err */
2058 /* close the cabinet file */
2059 PFCI_CLOSE(hfci,handleCABINET,&err,p_fci_internal->pv);
2060 /* TODO error handling of err */
2063 /* COPIED FROM FCIDestroy */
2065 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2066 /* TODO error handling of err */
2067 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,
2068 p_fci_internal->pv);
2069 /* TODO error handling of err */
2070 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2071 /* TODO error handling of err */
2072 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,
2073 p_fci_internal->pv);
2074 /* TODO error handling of err */
2075 PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
2076 /* TODO error handling of err */
2077 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,
2078 p_fci_internal->pv);
2079 /* TODO error handling of err */
2081 /* END OF copied from FCIDestroy */
2083 /* get 3 temporary files and open them */
2084 /* write names and handles to hfci */
2087 p_fci_internal->sizeFileCFDATA2 = 0;
2088 p_fci_internal->sizeFileCFFILE2 = 0;
2089 p_fci_internal->sizeFileCFFOLDER = 0;
2091 /* COPIED FROM FCICreate */
2093 /* CFDATA with checksum and ready to be copied into cabinet */
2094 if( !PFCI_GETTEMPFILE(hfci, p_fci_internal->szFileNameCFDATA2,
2096 /* error handling */
2097 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2101 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
2102 /* set error code and abort */
2103 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2106 p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
2107 p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, p_fci_internal->pv);
2109 if(p_fci_internal->handleCFDATA2==0){
2110 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
2113 /* TODO error checking of err */
2115 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2116 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
2118 /* error handling */
2119 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2123 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
2124 /* set error code and abort */
2125 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2128 p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
2129 p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, p_fci_internal->pv);
2131 if(p_fci_internal->handleCFFILE2==0){
2132 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
2135 /* TODO error checking of err */
2137 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2138 if (!PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,CB_MAX_FILENAME)) {
2139 /* error handling */
2140 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2144 if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
2145 /* set error code and abort */
2146 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2149 p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
2150 p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, p_fci_internal->pv);
2152 if(p_fci_internal->handleCFFOLDER==0){
2153 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
2156 /* TODO error checking of err */
2158 /* END OF copied from FCICreate */
2161 /* TODO close and delete new files when return FALSE */
2164 /* report status with pfnfcis about copied size of folder */
2165 (*pfnfcis)(statusCabinet,
2166 p_fci_internal->estimatedCabinetSize, /* estimated cabinet file size */
2167 cfheader.cbCabinet /* real cabinet file size */, p_fci_internal->pv);
2169 p_fci_internal->fPrevCab=TRUE;
2170 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2171 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2173 if (p_fci_internal->fNextCab) {
2174 p_fci_internal->fNextCab=FALSE;
2176 if (p_fci_internal->sizeFileCFFILE1==0 && p_fci_internal->sizeFileCFDATA1!=0) {
2177 /* THIS CAN NEVER HAPPEN */
2178 /* set error code */
2179 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2183 /* COPIED FROM FCIAddFile and modified */
2185 /* REUSE the variable read_result */
2186 if (p_fci_internal->fGetNextCabInVain) {
2187 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader;
2188 if(p_fci_internal->sizeFileCFFILE1!=0) {
2189 read_result+=p_fci_internal->oldCCAB.cbReserveCFFolder;
2191 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2192 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2193 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2197 read_result=p_fci_internal->pccab->cbReserveCFHeader;
2198 if(p_fci_internal->sizeFileCFFILE1!=0) {
2199 read_result+=p_fci_internal->pccab->cbReserveCFFolder;
2201 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2202 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2203 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2207 if ( p_fci_internal->fPrevCab ) {
2208 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2209 strlen(p_fci_internal->szPrevDisk)+1;
2211 read_result+= p_fci_internal->sizeFileCFDATA1 +
2212 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2213 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2215 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2217 if( p_fci_internal->fNewPrevious ) {
2218 memcpy(p_fci_internal->szPrevCab, p_fci_internal->oldCCAB.szCab,
2219 CB_MAX_CABINET_NAME);
2220 memcpy(p_fci_internal->szPrevDisk, p_fci_internal->oldCCAB.szDisk,
2222 p_fci_internal->fNewPrevious=FALSE;
2225 /* too much data for the maximum size of a cabinet */
2226 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2227 p_fci_internal->pccab->cb < read_result ) {
2228 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2231 /* Might be too much data for the maximum size of a cabinet.*/
2232 /* When any further data will be added later, it might not */
2233 /* be possible to flush the cabinet, because there might */
2234 /* not be enough space to store the name of the following */
2235 /* cabinet and name of the corresponding disk. */
2236 /* So take care of this and get the name of the next cabinet */
2237 if (p_fci_internal->fGetNextCabInVain==FALSE && (
2238 p_fci_internal->pccab->cb < read_result +
2239 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2242 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2243 /* increment cabinet index */
2244 ++(p_fci_internal->pccab->iCab);
2245 /* get name of next cabinet */
2246 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2247 if (!(*pfnfcignc)(p_fci_internal->pccab,
2248 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2249 p_fci_internal->pv)) {
2250 /* error handling */
2251 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2254 /* Skip a few lines of code. This is caught by the next if. */
2255 p_fci_internal->fGetNextCabInVain=TRUE;
2258 /* too much data for cabinet */
2259 if (p_fci_internal->fGetNextCabInVain && (
2260 p_fci_internal->oldCCAB.cb < read_result +
2261 strlen(p_fci_internal->oldCCAB.szCab)+1+
2262 strlen(p_fci_internal->oldCCAB.szDisk)+1
2264 p_fci_internal->fGetNextCabInVain=FALSE;
2265 p_fci_internal->fNextCab=TRUE;
2266 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2269 /* if the FolderThreshold has been reached flush the folder automatically */
2270 if( p_fci_internal->fGetNextCabInVain ) {
2271 if( p_fci_internal->cCompressedBytesInFolder >=
2272 p_fci_internal->oldCCAB.cbFolderThresh) {
2273 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2276 if( p_fci_internal->cCompressedBytesInFolder >=
2277 p_fci_internal->pccab->cbFolderThresh) {
2278 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2282 /* END OF COPIED FROM FCIAddFile and modified */
2284 if( p_fci_internal->sizeFileCFFILE1>0 ) {
2285 if( !FCIFlushFolder(hfci, pfnfcignc, pfnfcis) ) return FALSE;
2286 p_fci_internal->fNewPrevious=TRUE;
2289 p_fci_internal->fNewPrevious=FALSE;
2290 if( p_fci_internal->sizeFileCFFILE1>0 || p_fci_internal->sizeFileCFDATA1) {
2291 /* THIS MAY NEVER HAPPEN */
2292 /* set error structures */
2293 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2299 } /* end of fci_flush_cabinet */
2305 /***********************************************************************
2306 * FCIAddFile (CABINET.11)
2308 * FCIAddFile adds a file to the to be created cabinet file
2311 * hfci [I] An HFCI from FCICreate
2312 * pszSourceFile [I] A pointer to a C string which contains the name and
2313 * location of the file which will be added to the cabinet
2314 * pszFileName [I] A pointer to a C string which contains the name under
2315 * which the file will be stored in the cabinet
2316 * fExecute [I] A boolean value which indicates if the file should be
2317 * executed after extraction of self extracting
2319 * pfnfcignc [I] A pointer to a function which gets information about
2321 * pfnfcis [IO] A pointer to a function which will report status
2322 * information about the compression process
2323 * pfnfcioi [I] A pointer to a function which reports file attributes
2324 * and time and date information
2325 * typeCompress [I] Compression type
2328 * On success, returns TRUE
2329 * On failure, returns FALSE
2335 BOOL __cdecl FCIAddFile(
2337 char *pszSourceFile,
2340 PFNFCIGETNEXTCABINET pfnfcignc,
2341 PFNFCISTATUS pfnfcis,
2342 PFNFCIGETOPENINFO pfnfcigoi,
2347 cab_ULONG read_result;
2349 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2352 if (!REALLY_IS_FCI(hfci)) {
2353 SetLastError(ERROR_INVALID_HANDLE);
2357 if ((!pszSourceFile) || (!pszFileName) || (!pfnfcignc) || (!pfnfcis) ||
2358 (!pfnfcigoi) || strlen(pszFileName)>=CB_MAX_FILENAME) {
2359 fci_set_error( FCIERR_NONE, ERROR_BAD_ARGUMENTS, TRUE );
2363 /* TODO check if pszSourceFile??? */
2365 if(p_fci_internal->fGetNextCabInVain && p_fci_internal->fNextCab) {
2366 /* internal error */
2367 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2371 if(p_fci_internal->fNextCab) {
2372 /* internal error */
2373 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2377 cffile.cbFile=0; /* size of the to be added file*/
2378 /* offset of the uncompressed file in the folder */
2379 cffile.uoffFolderStart=p_fci_internal->cDataBlocks*CAB_BLOCKMAX + p_fci_internal->cdata_in;
2380 /* number of folder in the cabinet or special 0=first */
2381 cffile.iFolder = p_fci_internal->cFolders;
2383 /* allocation of memory */
2384 if (p_fci_internal->data_in==NULL) {
2385 if (p_fci_internal->cdata_in!=0) {
2386 /* error handling */
2387 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2390 if (p_fci_internal->data_out!=NULL) {
2391 /* error handling */
2392 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2395 if(!(p_fci_internal->data_in = (char*)PFCI_ALLOC(hfci,CB_MAX_CHUNK))) {
2396 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
2399 if (p_fci_internal->data_out==NULL) {
2400 if(!(p_fci_internal->data_out = PFCI_ALLOC(hfci, 2 * CB_MAX_CHUNK))){
2401 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
2407 if (p_fci_internal->data_out==NULL) {
2408 PFCI_FREE(hfci,p_fci_internal->data_in);
2409 /* error handling */
2410 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2414 /* get information about the file */
2415 file_handle=(*pfnfcigoi)(pszSourceFile, &(cffile.date), &(cffile.time),
2416 &(cffile.attribs), &err, p_fci_internal->pv);
2417 /* check file_handle */
2419 fci_set_error( FCIERR_OPEN_SRC, ERROR_OPEN_FAILED, TRUE );
2421 /* TODO error handling of err */
2423 if (fExecute) { cffile.attribs |= _A_EXEC; }
2425 /* REUSE the variable read_result */
2426 if (p_fci_internal->fGetNextCabInVain) {
2427 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2428 p_fci_internal->oldCCAB.cbReserveCFFolder;
2429 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2430 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2431 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2435 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2436 p_fci_internal->pccab->cbReserveCFFolder;
2437 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2438 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2439 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2443 if ( p_fci_internal->fPrevCab ) {
2444 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2445 strlen(p_fci_internal->szPrevDisk)+1;
2447 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2448 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2449 strlen(p_fci_internal->pccab->szDisk)+1;
2452 read_result+= sizeof(CFFILE) + strlen(pszFileName)+1 +
2453 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2454 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2456 sizeof(CFFOLDER); /* size of new CFFolder entry */
2458 /* Might be too much data for the maximum size of a cabinet.*/
2459 /* When any further data will be added later, it might not */
2460 /* be possible to flush the cabinet, because there might */
2461 /* not be enough space to store the name of the following */
2462 /* cabinet and name of the corresponding disk. */
2463 /* So take care of this and get the name of the next cabinet */
2464 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2465 p_fci_internal->fNextCab==FALSE &&
2466 ( p_fci_internal->pccab->cb < read_result +
2467 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2471 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2472 /* increment cabinet index */
2473 ++(p_fci_internal->pccab->iCab);
2474 /* get name of next cabinet */
2475 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2476 if (!(*pfnfcignc)(p_fci_internal->pccab,
2477 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2478 p_fci_internal->pv)) {
2479 /* error handling */
2480 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2483 /* Skip a few lines of code. This is caught by the next if. */
2484 p_fci_internal->fGetNextCabInVain=TRUE;
2487 if( p_fci_internal->fGetNextCabInVain &&
2488 p_fci_internal->fNextCab
2490 /* THIS CAN NEVER HAPPEN */
2491 /* set error code */
2492 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2496 /* too much data for cabinet */
2497 if( p_fci_internal->fGetNextCabInVain &&
2499 p_fci_internal->oldCCAB.cb < read_result +
2500 strlen(p_fci_internal->pccab->szCab)+1+
2501 strlen(p_fci_internal->pccab->szDisk)+1
2503 p_fci_internal->fGetNextCabInVain=FALSE;
2504 p_fci_internal->fNextCab=TRUE;
2505 if(!fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis)) return FALSE;
2508 if( p_fci_internal->fNextCab ) {
2509 /* THIS MAY NEVER HAPPEN */
2510 /* set error code */
2511 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2515 /* read the contents of the file blockwise */
2517 if (p_fci_internal->cdata_in > CAB_BLOCKMAX) {
2518 /* internal error */
2519 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2523 read_result = PFCI_READ(hfci, file_handle /* file handle */,
2524 (p_fci_internal->data_in + p_fci_internal->cdata_in) /* memory buffer */,
2525 (CAB_BLOCKMAX - p_fci_internal->cdata_in) /* number of bytes to copy */,
2526 &err, p_fci_internal->pv);
2527 /* TODO error handling of err */
2529 if( read_result==0 ) break;
2531 /* increment the block size */
2532 p_fci_internal->cdata_in += read_result;
2534 /* increment the file size */
2535 cffile.cbFile += read_result;
2537 if ( p_fci_internal->cdata_in > CAB_BLOCKMAX ) {
2538 /* report internal error */
2539 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2542 /* write a whole block */
2543 if ( p_fci_internal->cdata_in == CAB_BLOCKMAX ) {
2545 if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;
2549 /* close the file from FCIAddFile */
2550 PFCI_CLOSE(hfci,file_handle,&err,p_fci_internal->pv);
2551 /* TODO error handling of err */
2553 /* write cffile to p_fci_internal->handleCFFILE1 */
2554 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */
2555 &cffile, sizeof(cffile),&err, p_fci_internal->pv) != sizeof(cffile) ) {
2557 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
2560 /* TODO error handling of err */
2562 p_fci_internal->sizeFileCFFILE1 += sizeof(cffile);
2564 /* append the name of file */
2565 if (strlen(pszFileName)>=CB_MAX_FILENAME) {
2567 /* set error code */
2568 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2571 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */
2572 pszFileName, strlen(pszFileName)+1, &err, p_fci_internal->pv)
2573 != strlen(pszFileName)+1 ) {
2575 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
2578 /* TODO error handling of err */
2580 p_fci_internal->sizeFileCFFILE1 += strlen(pszFileName)+1;
2582 /* REUSE the variable read_result */
2583 if (p_fci_internal->fGetNextCabInVain ||
2584 p_fci_internal->fNextCab
2586 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2587 p_fci_internal->oldCCAB.cbReserveCFFolder;
2588 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2589 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2590 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2594 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2595 p_fci_internal->pccab->cbReserveCFFolder;
2596 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2597 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2598 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2602 if ( p_fci_internal->fPrevCab ) {
2603 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2604 strlen(p_fci_internal->szPrevDisk)+1;
2606 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2607 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2608 strlen(p_fci_internal->pccab->szDisk)+1;
2610 read_result+= p_fci_internal->sizeFileCFDATA1 +
2611 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2612 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2614 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2616 /* too much data for the maximum size of a cabinet */
2617 /* (ignoring the unflushed data block) */
2618 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2619 p_fci_internal->fNextCab==FALSE && /* this is always the case */
2620 p_fci_internal->pccab->cb < read_result ) {
2621 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2624 /* Might be too much data for the maximum size of a cabinet.*/
2625 /* When any further data will be added later, it might not */
2626 /* be possible to flush the cabinet, because there might */
2627 /* not be enough space to store the name of the following */
2628 /* cabinet and name of the corresponding disk. */
2629 /* So take care of this and get the name of the next cabinet */
2630 /* (ignoring the unflushed data block) */
2631 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2632 p_fci_internal->fNextCab==FALSE &&
2633 ( p_fci_internal->pccab->cb < read_result +
2634 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2638 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2639 /* increment cabinet index */
2640 ++(p_fci_internal->pccab->iCab);
2641 /* get name of next cabinet */
2642 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2643 if (!(*pfnfcignc)(p_fci_internal->pccab,
2644 p_fci_internal->estimatedCabinetSize,/* estimated size of cab */
2645 p_fci_internal->pv)) {
2646 /* error handling */
2647 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2650 /* Skip a few lines of code. This is caught by the next if. */
2651 p_fci_internal->fGetNextCabInVain=TRUE;
2654 if( p_fci_internal->fGetNextCabInVain &&
2655 p_fci_internal->fNextCab
2657 /* THIS CAN NEVER HAPPEN */
2658 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2662 /* too much data for cabinet */
2663 if( (p_fci_internal->fGetNextCabInVain ||
2664 p_fci_internal->fNextCab) && (
2665 p_fci_internal->oldCCAB.cb < read_result +
2666 strlen(p_fci_internal->pccab->szCab)+1+
2667 strlen(p_fci_internal->pccab->szDisk)+1
2670 p_fci_internal->fGetNextCabInVain=FALSE;
2671 p_fci_internal->fNextCab=TRUE;
2672 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2675 if( p_fci_internal->fNextCab ) {
2676 /* THIS MAY NEVER HAPPEN */
2677 /* set error code */
2678 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2682 /* if the FolderThreshold has been reached flush the folder automatically */
2683 if( p_fci_internal->fGetNextCabInVain ) {
2684 if( p_fci_internal->cCompressedBytesInFolder >=
2685 p_fci_internal->oldCCAB.cbFolderThresh) {
2686 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2689 if( p_fci_internal->cCompressedBytesInFolder >=
2690 p_fci_internal->pccab->cbFolderThresh) {
2691 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2696 } /* end of FCIAddFile */
2702 /***********************************************************************
2703 * FCIFlushFolder (CABINET.12)
2705 * FCIFlushFolder completes the CFFolder structure under construction.
2707 * All further data which is added by FCIAddFile will be associateed to
2708 * the next CFFolder structure.
2710 * FCIFlushFolder will be called by FCIAddFile automatically if the
2711 * threshold (stored in the member cbFolderThresh of the CCAB structure
2712 * pccab passed to FCICreate) is exceeded.
2714 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2715 * any data will be written into the cabinet file.
2718 * hfci [I] An HFCI from FCICreate
2719 * pfnfcignc [I] A pointer to a function which gets information about
2721 * pfnfcis [IO] A pointer to a function which will report status
2722 * information about the compression process
2725 * On success, returns TRUE
2726 * On failure, returns FALSE
2732 BOOL __cdecl FCIFlushFolder(
2734 PFNFCIGETNEXTCABINET pfnfcignc,
2735 PFNFCISTATUS pfnfcis)
2737 return fci_flush_folder(hfci,FALSE,pfnfcignc,pfnfcis);
2738 } /* end of FCIFlushFolder */
2742 /***********************************************************************
2743 * FCIFlushCabinet (CABINET.13)
2745 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2746 * into the cabinet file. If the maximum cabinet size (stored in the
2747 * member cb of the CCAB structure pccab passed to FCICreate) has been
2748 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2749 * The remaining data still has to be flushed manually by calling
2752 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2753 * NOT be called again. Then hfci has to be released by FCIDestroy.
2756 * hfci [I] An HFCI from FCICreate
2757 * fGetNextCab [I] Whether you want to add additional files to a
2758 * cabinet set (TRUE) or whether you want to
2759 * finalize it (FALSE)
2760 * pfnfcignc [I] A pointer to a function which gets information about
2762 * pfnfcis [IO] A pointer to a function which will report status
2763 * information about the compression process
2766 * On success, returns TRUE
2767 * On failure, returns FALSE
2773 BOOL __cdecl FCIFlushCabinet(
2776 PFNFCIGETNEXTCABINET pfnfcignc,
2777 PFNFCISTATUS pfnfcis)
2779 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2781 if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2783 while( p_fci_internal->sizeFileCFFILE1>0 ||
2784 p_fci_internal->sizeFileCFFILE2>0 ) {
2785 if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2789 } /* end of FCIFlushCabinet */
2792 /***********************************************************************
2793 * FCIDestroy (CABINET.14)
2795 * Frees a handle created by FCICreate.
2796 * Only reason for failure would be an invalid handle.
2799 * hfci [I] The HFCI to free
2805 BOOL __cdecl FCIDestroy(HFCI hfci)
2808 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2809 if (REALLY_IS_FCI(hfci)) {
2811 /* before hfci can be removed all temporary files must be closed */
2813 p_fci_internal->FCI_Intmagic = 0;
2815 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
2816 /* TODO error handling of err */
2817 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA1, &err,
2818 p_fci_internal->pv);
2819 /* TODO error handling of err */
2820 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE1,&err,p_fci_internal->pv);
2821 /* TODO error handling of err */
2822 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE1, &err,
2823 p_fci_internal->pv);
2824 /* TODO error handling of err */
2825 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2826 /* TODO error handling of err */
2827 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,
2828 p_fci_internal->pv);
2829 /* TODO error handling of err */
2830 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2831 /* TODO error handling of err */
2832 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,
2833 p_fci_internal->pv);
2834 /* TODO error handling of err */
2835 PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
2836 /* TODO error handling of err */
2837 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,
2838 p_fci_internal->pv);
2839 /* TODO error handling of err */
2841 /* data in and out buffers have to be removed */
2842 if (p_fci_internal->data_in!=NULL)
2843 PFCI_FREE(hfci, p_fci_internal->data_in);
2844 if (p_fci_internal->data_out!=NULL)
2845 PFCI_FREE(hfci, p_fci_internal->data_out);
2847 /* hfci can now be removed */
2848 PFCI_FREE(hfci, hfci);
2851 SetLastError(ERROR_INVALID_HANDLE);
2855 } /* end of FCIDestroy */