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(const 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 */