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 sections*/
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
; /* minimum 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
;
177 SetLastError(ERROR_BAD_ARGUMENTS
);
180 if ((!pfnalloc
) || (!pfnfree
) || (!pfnopen
) || (!pfnread
) ||
181 (!pfnwrite
) || (!pfnclose
) || (!pfnseek
) || (!pfndelete
) ||
182 (!pfnfcigtf
) || (!pccab
)) {
183 perf
->erfOper
= FCIERR_NONE
;
184 perf
->erfType
= ERROR_BAD_ARGUMENTS
;
187 SetLastError(ERROR_BAD_ARGUMENTS
);
191 if (!((hfci
= (*pfnalloc
)(sizeof(FCI_Int
))))) {
192 perf
->erfOper
= FCIERR_ALLOC_FAIL
;
193 perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
196 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
200 p_fci_internal
=((PFCI_Int
)(hfci
));
201 p_fci_internal
->FCI_Intmagic
= FCI_INT_MAGIC
;
202 p_fci_internal
->perf
= perf
;
203 p_fci_internal
->pfnfiledest
= pfnfiledest
;
204 p_fci_internal
->pfnalloc
= pfnalloc
;
205 p_fci_internal
->pfnfree
= pfnfree
;
206 p_fci_internal
->pfnopen
= pfnopen
;
207 p_fci_internal
->pfnread
= pfnread
;
208 p_fci_internal
->pfnwrite
= pfnwrite
;
209 p_fci_internal
->pfnclose
= pfnclose
;
210 p_fci_internal
->pfnseek
= pfnseek
;
211 p_fci_internal
->pfndelete
= pfndelete
;
212 p_fci_internal
->pfnfcigtf
= pfnfcigtf
;
213 p_fci_internal
->pccab
= pccab
;
214 p_fci_internal
->fPrevCab
= FALSE
;
215 p_fci_internal
->fNextCab
= FALSE
;
216 p_fci_internal
->fSplitFolder
= FALSE
;
217 p_fci_internal
->fGetNextCabInVain
= FALSE
;
218 p_fci_internal
->pv
= pv
;
219 p_fci_internal
->data_in
= NULL
;
220 p_fci_internal
->cdata_in
= 0;
221 p_fci_internal
->data_out
= NULL
;
222 p_fci_internal
->cCompressedBytesInFolder
= 0;
223 p_fci_internal
->cFolders
= 0;
224 p_fci_internal
->cFiles
= 0;
225 p_fci_internal
->cDataBlocks
= 0;
226 p_fci_internal
->sizeFileCFDATA1
= 0;
227 p_fci_internal
->sizeFileCFFILE1
= 0;
228 p_fci_internal
->sizeFileCFDATA2
= 0;
229 p_fci_internal
->sizeFileCFFILE2
= 0;
230 p_fci_internal
->sizeFileCFFOLDER
= 0;
231 p_fci_internal
->sizeFileCFFOLDER
= 0;
232 p_fci_internal
->fNewPrevious
= FALSE
;
233 p_fci_internal
->estimatedCabinetSize
= 0;
234 p_fci_internal
->statusFolderTotal
= 0;
236 memset(&p_fci_internal
->oldCCAB
, 0, sizeof(CCAB
));
237 memcpy(p_fci_internal
->szPrevCab
, pccab
->szCab
, CB_MAX_CABINET_NAME
);
238 memcpy(p_fci_internal
->szPrevDisk
, pccab
->szDisk
, CB_MAX_DISK_NAME
);
241 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFDATA1
,
243 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
247 if ( strlen(p_fci_internal
->szFileNameCFDATA1
) >= CB_MAX_FILENAME
) {
248 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
252 p_fci_internal
->handleCFDATA1
= PFCI_OPEN(hfci
,
253 p_fci_internal
->szFileNameCFDATA1
, 34050, 384, &err
, pv
);
254 if(p_fci_internal
->handleCFDATA1
==0){
255 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
258 /* TODO error checking of err */
260 /* array of all CFFILE in a folder */
261 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE1
,
263 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
267 if ( strlen(p_fci_internal
->szFileNameCFFILE1
) >= CB_MAX_FILENAME
) {
268 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
271 p_fci_internal
->handleCFFILE1
= PFCI_OPEN(hfci
,
272 p_fci_internal
->szFileNameCFFILE1
, 34050, 384, &err
, pv
);
273 if(p_fci_internal
->handleCFFILE1
==0){
274 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
277 /* TODO error checking of err */
279 /* CFDATA with checksum and ready to be copied into cabinet */
280 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFDATA2
,
282 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
286 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
287 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
290 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
291 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, pv
);
292 if(p_fci_internal
->handleCFDATA2
==0){
293 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
296 /* TODO error checking of err */
298 /* array of all CFFILE in a folder, ready to be copied into cabinet */
299 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
301 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
305 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
306 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
309 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
310 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, pv
);
311 if(p_fci_internal
->handleCFFILE2
==0){
312 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
315 /* TODO error checking of err */
317 /* array of all CFFILE in a folder, ready to be copied into cabinet */
318 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,
320 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
324 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
325 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
328 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
329 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, pv
);
330 if(p_fci_internal
->handleCFFOLDER
==0) {
331 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
335 /* TODO close and delete new files when return FALSE */
336 /* TODO error checking of err */
339 } /* end of FCICreate */
346 static BOOL
fci_flush_data_block (HFCI hfci
, int* err
,
347 PFNFCISTATUS pfnfcis
) {
349 /* attention no hfci checks!!! */
350 /* attention no checks if there is data available!!! */
352 CFDATA
* cfdata
=&data
;
354 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
355 UINT cbReserveCFData
=p_fci_internal
->pccab
->cbReserveCFData
;
358 /* TODO compress the data of p_fci_internal->data_in */
359 /* and write it to p_fci_internal->data_out */
360 memcpy(p_fci_internal
->data_out
, p_fci_internal
->data_in
,
361 p_fci_internal
->cdata_in
/* number of bytes to copy */);
363 cfdata
->csum
=0; /* checksum has to be set later */
364 /* TODO set realsize of compressed data */
365 cfdata
->cbData
= p_fci_internal
->cdata_in
;
366 cfdata
->cbUncomp
= p_fci_internal
->cdata_in
;
368 /* write cfdata to p_fci_internal->handleCFDATA1 */
369 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
370 cfdata
, sizeof(*cfdata
), err
, p_fci_internal
->pv
)
371 != sizeof(*cfdata
) ) {
372 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
375 /* TODO error handling of err */
377 p_fci_internal
->sizeFileCFDATA1
+= sizeof(*cfdata
);
379 /* add optional reserved area */
381 /* This allocation and freeing at each CFData block is a bit */
382 /* inefficient, but it's harder to forget about freeing the buffer :-). */
383 /* Reserved areas are used seldom besides that... */
384 if (cbReserveCFData
!=0) {
385 if(!(reserved
= PFCI_ALLOC(hfci
, cbReserveCFData
))) {
386 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
389 for(i
=0;i
<cbReserveCFData
;) {
392 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
393 reserved
, /* memory buffer */
394 cbReserveCFData
, /* number of bytes to copy */
395 err
, p_fci_internal
->pv
) != cbReserveCFData
) {
396 PFCI_FREE(hfci
, reserved
);
397 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
400 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
402 p_fci_internal
->sizeFileCFDATA1
+= cbReserveCFData
;
403 PFCI_FREE(hfci
, reserved
);
406 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
407 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
408 p_fci_internal
->data_out
, /* memory buffer */
409 cfdata
->cbData
, /* number of bytes to copy */
410 err
, p_fci_internal
->pv
) != cfdata
->cbData
) {
411 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
414 /* TODO error handling of err */
416 p_fci_internal
->sizeFileCFDATA1
+= cfdata
->cbData
;
418 /* reset the offset */
419 p_fci_internal
->cdata_in
= 0;
420 p_fci_internal
->cCompressedBytesInFolder
+= cfdata
->cbData
;
422 /* report status with pfnfcis about uncompressed and compressed file data */
423 if( (*pfnfcis
)(statusFile
, cfdata
->cbData
, cfdata
->cbUncomp
,
424 p_fci_internal
->pv
) == -1) {
425 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
429 ++(p_fci_internal
->cDataBlocks
);
432 } /* end of fci_flush_data_block */
438 static cab_ULONG
fci_get_checksum(const void *pv
, UINT cb
, CHECKSUM seed
)
449 while (cUlong
-- > 0) {
451 ul
|= (((cab_ULONG
)(*pb
++)) << 8);
452 ul
|= (((cab_ULONG
)(*pb
++)) << 16);
453 ul
|= (((cab_ULONG
)(*pb
++)) << 24);
461 ul
|= (((ULONG
)(*pb
++)) << 16);
463 ul
|= (((ULONG
)(*pb
++)) << 8);
472 } /* end of fci_get_checksum */
476 static BOOL
fci_flushfolder_copy_cfdata(HFCI hfci
, char* buffer
, UINT cbReserveCFData
,
477 PFNFCISTATUS pfnfcis
, int* err
, int handleCFDATA1new
,
478 cab_ULONG
* psizeFileCFDATA1new
, cab_ULONG
* payload
)
480 cab_ULONG read_result
;
481 CFDATA
* pcfdata
=(CFDATA
*)buffer
;
482 BOOL split_block
=FALSE
;
483 cab_UWORD savedUncomp
=0;
484 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
488 /* while not all CFDATAs have been copied do */
490 if( p_fci_internal
->fNextCab
) {
492 /* internal error should never happen */
493 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
497 /* REUSE the variable read_result */
498 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
499 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
500 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
505 if (p_fci_internal
->fPrevCab
) {
506 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
507 strlen(p_fci_internal
->szPrevDisk
)+1;
509 /* No more CFDATA fits into the cabinet under construction */
510 /* So don't try to store more data into it */
511 if( p_fci_internal
->fNextCab
&&
512 (p_fci_internal
->oldCCAB
.cb
<= sizeof(CFDATA
) + cbReserveCFData
+
513 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
514 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
517 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
519 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
520 strlen(p_fci_internal
->pccab
->szCab
)+1 +
521 strlen(p_fci_internal
->pccab
->szDisk
)+1
523 /* This may never be run for the first time the while loop is entered.
524 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
525 split_block
=TRUE
; /* In this case split_block is abused to store */
526 /* the complete data block into the next cabinet and not into the */
527 /* current one. Originally split_block is the indicator that a */
528 /* data block has been split across different cabinets. */
531 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
532 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/*file handle*/
533 buffer
, /* memory buffer */
534 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
535 err
, p_fci_internal
->pv
);
536 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
537 if (read_result
==0) break; /* ALL DATA has been copied */
539 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
542 /* TODO error handling of err */
544 /* REUSE buffer p_fci_internal->data_out !!! */
545 /* read data from p_fci_internal->handleCFDATA1 to */
546 /* p_fci_internal->data_out */
547 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
548 p_fci_internal
->data_out
/* memory buffer */,
549 pcfdata
->cbData
/* number of bytes to copy */,
550 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
552 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
555 /* TODO error handling of err */
557 /* if cabinet size is too large */
559 /* REUSE the variable read_result */
560 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
561 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
562 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
567 if (p_fci_internal
->fPrevCab
) {
568 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
569 strlen(p_fci_internal
->szPrevDisk
)+1;
572 /* Is cabinet with new CFDATA too large? Then data block has to be split */
573 if( p_fci_internal
->fNextCab
&&
574 (p_fci_internal
->oldCCAB
.cb
< sizeof(CFDATA
) + cbReserveCFData
+
576 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
577 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
580 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
581 sizeof(CFFOLDER
) + /* size of new CFFolder entry */
582 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
583 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* name of next cabinet */
584 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* name of next disk */
586 /* REUSE read_result to save the size of the compressed data */
587 read_result
=pcfdata
->cbData
;
588 /* Modify the size of the compressed data to store only a part of the */
589 /* data block into the current cabinet. This is done to prevent */
590 /* that the maximum cabinet size will be exceeded. The remainder */
591 /* will be stored into the next following cabinet. */
593 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
594 /* Substract everything except the size of the block of data */
595 /* to get it's actual size */
596 pcfdata
->cbData
= p_fci_internal
->oldCCAB
.cb
- (
597 sizeof(CFDATA
) + cbReserveCFData
+
598 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
599 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
601 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
602 sizeof(CFFOLDER
) + /* set size of new CFFolder entry */
603 p_fci_internal
->oldCCAB
.cbReserveCFFolder
);
604 /* substract the size of special header fields */
605 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
606 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
607 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
610 if (p_fci_internal
->fPrevCab
) {
611 pcfdata
->cbData
-=strlen(p_fci_internal
->szPrevCab
)+1 +
612 strlen(p_fci_internal
->szPrevDisk
)+1;
614 pcfdata
->cbData
-=strlen(p_fci_internal
->pccab
->szCab
)+1 +
615 strlen(p_fci_internal
->pccab
->szDisk
)+1;
617 savedUncomp
= pcfdata
->cbUncomp
;
618 pcfdata
->cbUncomp
= 0; /* on split blocks of data this is zero */
620 /* if split_block==TRUE then the above while loop won't */
621 /* be executed again */
622 split_block
=TRUE
; /* split_block is the indicator that */
623 /* a data block has been split across */
624 /* different cabinets.*/
627 /* This should never happen !!! */
628 if (pcfdata
->cbData
==0) {
630 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
634 /* set little endian */
635 pcfdata
->cbData
=fci_endian_uword(pcfdata
->cbData
);
636 pcfdata
->cbUncomp
=fci_endian_uword(pcfdata
->cbUncomp
);
638 /* get checksum and write to cfdata.csum */
639 pcfdata
->csum
= fci_get_checksum( &(pcfdata
->cbData
),
640 sizeof(CFDATA
)+cbReserveCFData
-
641 sizeof(pcfdata
->csum
), fci_get_checksum( p_fci_internal
->data_out
, /*buffer*/
642 pcfdata
->cbData
, 0 ) );
644 /* set little endian */
645 pcfdata
->csum
=fci_endian_ulong(pcfdata
->csum
);
647 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
648 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
649 buffer
, /* memory buffer */
650 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
651 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
652 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
655 /* TODO error handling of err */
657 p_fci_internal
->sizeFileCFDATA2
+= sizeof(CFDATA
)+cbReserveCFData
;
659 /* reset little endian */
660 pcfdata
->cbData
=fci_endian_uword(pcfdata
->cbData
);
661 pcfdata
->cbUncomp
=fci_endian_uword(pcfdata
->cbUncomp
);
662 pcfdata
->csum
=fci_endian_ulong(pcfdata
->csum
);
664 /* write compressed data into p_fci_internal->handleCFDATA2 */
665 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
666 p_fci_internal
->data_out
, /* memory buffer */
667 pcfdata
->cbData
, /* number of bytes to copy */
668 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
669 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
672 /* TODO error handling of err */
674 p_fci_internal
->sizeFileCFDATA2
+= pcfdata
->cbData
;
675 ++(p_fci_internal
->cDataBlocks
);
676 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
677 (*payload
)+=pcfdata
->cbUncomp
;
678 /* if cabinet size too large and data has been split */
679 /* write the remainder of the data block to the new CFDATA1 file */
680 if( split_block
) { /* This does not include the */
681 /* abused one (just search for "abused" )*/
682 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
683 if (p_fci_internal
->fNextCab
==FALSE
) {
685 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
689 /* set cbData to the size of the remainder of the data block */
690 pcfdata
->cbData
= read_result
- pcfdata
->cbData
;
691 /*recover former value of cfdata.cbData; read_result will be the offset*/
692 read_result
-= pcfdata
->cbData
;
693 pcfdata
->cbUncomp
= savedUncomp
;
695 /* reset checksum, it will be computed later */
698 /* write cfdata WITHOUT checksum to handleCFDATA1new */
699 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
700 buffer
, /* memory buffer */
701 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
702 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
703 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
706 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
708 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
710 /* write compressed data into handleCFDATA1new */
711 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
712 p_fci_internal
->data_out
+ read_result
, /* memory buffer + offset */
713 /* to last part of split data */
714 pcfdata
->cbData
, /* number of bytes to copy */
715 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
716 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
719 /* TODO error handling of err */
721 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
723 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
724 /* the two blocks of the split data block have been written */
725 /* don't reset split_data yet, because it is still needed see below */
728 /* report status with pfnfcis about copied size of folder */
729 if( (*pfnfcis
)(statusFolder
,
730 p_fci_internal
->statusFolderCopied
, /*cfdata.cbData(+previous ones)*/
731 p_fci_internal
->statusFolderTotal
, /* total folder size */
732 p_fci_internal
->pv
) == -1) {
733 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
738 /* if cabinet size too large */
739 /* write the remaining data blocks to the new CFDATA1 file */
740 if ( split_block
) { /* This does include the */
741 /* abused one (just search for "abused" )*/
742 if (p_fci_internal
->fNextCab
==FALSE
) {
744 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
747 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
749 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
750 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/* handle */
751 buffer
, /* memory buffer */
752 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
753 err
, p_fci_internal
->pv
);
754 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
755 if (read_result
==0) break; /* ALL DATA has been copied */
757 fci_set_error(FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
760 /* TODO error handling of err */
762 /* REUSE buffer p_fci_internal->data_out !!! */
763 /* read data from p_fci_internal->handleCFDATA1 to */
764 /* p_fci_internal->data_out */
765 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
766 p_fci_internal
->data_out
/* memory buffer */,
767 pcfdata
->cbData
/* number of bytes to copy */,
768 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
770 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
773 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
775 /* write cfdata with checksum to handleCFDATA1new */
776 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
777 buffer
, /* memory buffer */
778 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
779 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
780 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
783 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
785 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
787 /* write compressed data into handleCFDATA1new */
788 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
789 p_fci_internal
->data_out
, /* memory buffer */
790 pcfdata
->cbData
, /* number of bytes to copy */
791 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
792 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
795 /* TODO error handling of err */
797 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
798 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
800 /* report status with pfnfcis about copied size of folder */
801 if( (*pfnfcis
)(statusFolder
,
802 p_fci_internal
->statusFolderCopied
,/*cfdata.cbData(+previous ones)*/
803 p_fci_internal
->statusFolderTotal
, /* total folder size */
804 p_fci_internal
->pv
) == -1) {
805 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
810 break; /* jump out of the next while loop */
811 } /* end of if( split_data ) */
814 } /* end of fci_flushfolder_copy_cfdata */
820 static BOOL
fci_flushfolder_copy_cffolder(HFCI hfci
, int* err
, UINT cbReserveCFFolder
,
821 cab_ULONG sizeFileCFDATA2old
)
826 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
828 /* absolute offset cannot be set yet, because the size of cabinet header, */
829 /* the number of CFFOLDERs and the number of CFFILEs may change. */
830 /* Instead the size of all previous data blocks will be stored and */
831 /* the remainder of the offset will be added when the cabinet will be */
832 /* flushed to disk. */
833 /* This is exactly the way the original CABINET.DLL works!!! */
834 cffolder
.coffCabStart
=sizeFileCFDATA2old
;
836 /* set the number of this folder's CFDATA sections */
837 cffolder
.cCFData
=p_fci_internal
->cDataBlocks
;
838 /* TODO set compression type */
839 cffolder
.typeCompress
= tcompTYPE_NONE
;
841 /* write cffolder to p_fci_internal->handleCFFOLDER */
842 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
843 &cffolder
, /* memory buffer */
844 sizeof(cffolder
), /* number of bytes to copy */
845 err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
846 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
849 /* TODO error handling of err */
851 p_fci_internal
->sizeFileCFFOLDER
+= sizeof(cffolder
);
853 /* add optional reserved area */
854 if (cbReserveCFFolder
!=0) {
855 if(!(reserved
= PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
856 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
859 for(i
=0;i
<cbReserveCFFolder
;) {
862 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
863 reserved
, /* memory buffer */
864 cbReserveCFFolder
, /* number of bytes to copy */
865 err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
866 PFCI_FREE(hfci
, reserved
);
867 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
870 /* TODO error handling of err */
872 p_fci_internal
->sizeFileCFFOLDER
+= cbReserveCFFolder
;
874 PFCI_FREE(hfci
, reserved
);
877 } /* end of fci_flushfolder_copy_cffolder */
883 static BOOL
fci_flushfolder_copy_cffile(HFCI hfci
, int* err
, int handleCFFILE1new
,
884 cab_ULONG
*psizeFileCFFILE1new
, cab_ULONG payload
)
887 cab_ULONG read_result
;
889 cab_ULONG sizeOfFiles
=0, sizeOfFilesPrev
;
890 BOOL may_be_prev
=TRUE
;
891 cab_ULONG cbFileRemainer
=0;
892 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
893 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
894 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,0,SEEK_SET
,err
,
895 p_fci_internal
->pv
) !=0 ) {
896 /* wrong return value */
897 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
900 /* TODO error handling of err */
902 /* while not all CFFILE structures have been copied do */
904 /* REUSE the variable read_result */
905 /* read data from p_fci_internal->handleCFFILE1 to cffile */
906 read_result
= PFCI_READ(hfci
,p_fci_internal
->handleCFFILE1
/* file handle */,
907 &cffile
, /* memory buffer */
908 sizeof(cffile
), /* number of bytes to copy */
909 err
, p_fci_internal
->pv
);
910 if( read_result
!= sizeof(cffile
) ) {
911 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
913 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
916 /* TODO error handling of err */
918 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
919 /* position. I don't know why so I'll just omit it */
921 /* read the filename from p_fci_internal->handleCFFILE1 */
922 /* REUSE the variable read_result AGAIN */
923 /* REUSE the memory buffer PFCI(hfci)->data_out */
924 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFILE1
/*file handle*/,
925 p_fci_internal
->data_out
, /* memory buffer */
926 CB_MAX_FILENAME
, /* number of bytes to copy */
927 err
, p_fci_internal
->pv
) <2) {
929 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
932 /* TODO maybe other checks of read_result */
933 /* TODO error handling of err */
936 if( strlen(p_fci_internal
->data_out
)>=CB_MAX_FILENAME
) {
937 /* set error code internal error */
938 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
942 seek
+=sizeof(cffile
) + strlen(p_fci_internal
->data_out
)+1;
944 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
945 /* i.e. seek to the next CFFILE area */
946 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,
947 seek
, /* seek position*/
951 /* wrong return value */
952 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
955 /* TODO error handling of err */
957 /* fnfilfnfildest: placed file on cabinet */
958 if (p_fci_internal
->fNextCab
||
959 p_fci_internal
->fGetNextCabInVain
) {
960 PFCI_FILEPLACED( hfci
, &(p_fci_internal
->oldCCAB
),
961 p_fci_internal
->data_out
, /* the file name*/
962 cffile
.cbFile
, /* file size */
963 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
967 PFCI_FILEPLACED( hfci
, p_fci_internal
->pccab
,
968 p_fci_internal
->data_out
, /* the file name*/
969 cffile
.cbFile
, /* file size */
970 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
975 /* Check special iFolder values */
976 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
977 p_fci_internal
->fPrevCab
==FALSE
) {
978 /* THIS MAY NEVER HAPPEN */
980 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
983 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
984 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
) {
985 /* THIS MAY NEVER HAPPEN */
987 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
990 if( may_be_prev
&& cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
993 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& may_be_prev
==FALSE
) {
994 /* THIS MAY NEVER HAPPEN */
996 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
999 if( cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
1003 sizeOfFilesPrev
=sizeOfFiles
;
1004 /* Set complete size of all processed files */
1005 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
1006 p_fci_internal
->cbFileRemainer
!=0
1008 sizeOfFiles
+=p_fci_internal
->cbFileRemainer
;
1009 p_fci_internal
->cbFileRemainer
=0;
1011 sizeOfFiles
+=cffile
.cbFile
;
1014 /* Check if spanned file fits into this cabinet folder */
1015 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& sizeOfFiles
>payload
) {
1016 cffile
.iFolder
=cffileCONTINUED_PREV_AND_NEXT
;
1019 /* Check if file doesn't fit into this cabinet folder */
1020 if( sizeOfFiles
>payload
) {
1021 cffile
.iFolder
=cffileCONTINUED_TO_NEXT
;
1024 /* set little endian */
1025 cffile
.cbFile
=fci_endian_ulong(cffile
.cbFile
);
1026 cffile
.uoffFolderStart
=fci_endian_ulong(cffile
.uoffFolderStart
);
1027 cffile
.iFolder
=fci_endian_uword(cffile
.iFolder
);
1028 cffile
.date
=fci_endian_uword(cffile
.date
);
1029 cffile
.time
=fci_endian_uword(cffile
.time
);
1030 cffile
.attribs
=fci_endian_uword(cffile
.attribs
);
1032 /* write cffile to p_fci_internal->handleCFFILE2 */
1033 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
1034 &cffile
, /* memory buffer */
1035 sizeof(cffile
), /* number of bytes to copy */
1036 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1037 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1040 /* TODO error handling of err */
1042 p_fci_internal
->sizeFileCFFILE2
+= sizeof(cffile
);
1044 /* reset little endian */
1045 cffile
.cbFile
=fci_endian_ulong(cffile
.cbFile
);
1046 cffile
.uoffFolderStart
=fci_endian_ulong(cffile
.uoffFolderStart
);
1047 cffile
.iFolder
=fci_endian_uword(cffile
.iFolder
);
1048 cffile
.date
=fci_endian_uword(cffile
.date
);
1049 cffile
.time
=fci_endian_uword(cffile
.time
);
1050 cffile
.attribs
=fci_endian_uword(cffile
.attribs
);
1052 /* write file name to p_fci_internal->handleCFFILE2 */
1053 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
1054 p_fci_internal
->data_out
, /* memory buffer */
1055 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1056 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1057 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1060 /* TODO error handling of err */
1062 p_fci_internal
->sizeFileCFFILE2
+= strlen(p_fci_internal
->data_out
)+1;
1064 /* cFiles is used to count all files of a cabinet */
1065 ++(p_fci_internal
->cFiles
);
1067 /* This is only true for files which will be written into the */
1068 /* next cabinet of the spanning folder */
1069 if( sizeOfFiles
>payload
) {
1071 /* Files which data will be partially written into the current cabinet */
1072 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
1073 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
1075 if( sizeOfFilesPrev
<=payload
) {
1076 /* The size of the uncompressed, data of a spanning file in a */
1078 cbFileRemainer
=sizeOfFiles
-payload
;
1080 cffile
.iFolder
=cffileCONTINUED_FROM_PREV
;
1085 /* write cffile into handleCFFILE1new */
1086 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1087 &cffile
, /* memory buffer */
1088 sizeof(cffile
), /* number of bytes to copy */
1089 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1090 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1093 /* TODO error handling of err */
1095 *psizeFileCFFILE1new
+= sizeof(cffile
);
1096 /* write name of file into handleCFFILE1new */
1097 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1098 p_fci_internal
->data_out
, /* memory buffer */
1099 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1100 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1101 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1104 /* TODO error handling of err */
1106 *psizeFileCFFILE1new
+= strlen(p_fci_internal
->data_out
)+1;
1109 } /* END OF while */
1110 p_fci_internal
->cbFileRemainer
=cbFileRemainer
;
1112 } /* end of fci_flushfolder_copy_cffile */
1117 static BOOL
fci_flush_folder(
1120 PFNFCIGETNEXTCABINET pfnfcignc
,
1121 PFNFCISTATUS pfnfcis
)
1124 int handleCFDATA1new
; /* handle for new temp file */
1125 char szFileNameCFDATA1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1126 int handleCFFILE1new
; /* handle for new temp file */
1127 char szFileNameCFFILE1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1128 UINT cbReserveCFData
, cbReserveCFFolder
;
1130 cab_ULONG sizeFileCFDATA1new
=0;
1131 cab_ULONG sizeFileCFFILE1new
=0;
1132 cab_ULONG sizeFileCFDATA2old
;
1134 cab_ULONG read_result
;
1135 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1138 if (!REALLY_IS_FCI(hfci
)) {
1139 SetLastError(ERROR_INVALID_HANDLE
);
1143 if ((!pfnfcignc
) || (!pfnfcis
)) {
1144 fci_set_error( FCIERR_NONE
, ERROR_BAD_ARGUMENTS
, TRUE
);
1148 if( p_fci_internal
->fGetNextCabInVain
&&
1149 p_fci_internal
->fNextCab
){
1150 /* internal error */
1151 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1155 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1156 /* this function will return TRUE */
1157 if( p_fci_internal
->sizeFileCFFILE1
== 0 ) {
1158 if ( p_fci_internal
->sizeFileCFDATA1
!= 0 ) {
1159 /* error handling */
1160 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1166 if (p_fci_internal
->data_in
==NULL
|| p_fci_internal
->data_out
==NULL
) {
1167 /* error handling */
1168 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1172 /* FCIFlushFolder has already been called... */
1173 if (p_fci_internal
->fSplitFolder
&& p_fci_internal
->sizeFileCFFILE2
!=0) {
1177 /* This can be set already, because it makes only a difference */
1178 /* when the current function exits with return FALSE */
1179 p_fci_internal
->fSplitFolder
=FALSE
;
1182 if( p_fci_internal
->fGetNextCabInVain
||
1183 p_fci_internal
->fNextCab
){
1184 cbReserveCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1185 cbReserveCFFolder
= p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1187 cbReserveCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1188 cbReserveCFFolder
= p_fci_internal
->pccab
->cbReserveCFFolder
;
1192 /* if there is data in p_fci_internal->data_in */
1193 if (p_fci_internal
->cdata_in
!=0) {
1195 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
1198 /* reset to get the number of data blocks of this folder which are */
1199 /* actually in this cabinet ( at least partially ) */
1200 p_fci_internal
->cDataBlocks
=0;
1202 if ( p_fci_internal
->fNextCab
||
1203 p_fci_internal
->fGetNextCabInVain
) {
1204 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
1205 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1206 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1207 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1208 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1212 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
+
1213 p_fci_internal
->pccab
->cbReserveCFFolder
;
1214 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1215 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1216 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1220 if (p_fci_internal
->fPrevCab
) {
1221 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1222 strlen(p_fci_internal
->szPrevDisk
)+1;
1224 if (p_fci_internal
->fNextCab
) {
1225 read_result
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1226 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1229 p_fci_internal
->statusFolderTotal
= sizeof(CFHEADER
)+read_result
+
1230 sizeof(CFFOLDER
) + p_fci_internal
->sizeFileCFFILE2
+
1231 p_fci_internal
->sizeFileCFDATA2
+ p_fci_internal
->sizeFileCFFILE1
+
1232 p_fci_internal
->sizeFileCFDATA1
+ p_fci_internal
->sizeFileCFFOLDER
;
1233 p_fci_internal
->statusFolderCopied
= 0;
1235 /* report status with pfnfcis about copied size of folder */
1236 if( (*pfnfcis
)(statusFolder
, p_fci_internal
->statusFolderCopied
,
1237 p_fci_internal
->statusFolderTotal
, /* TODO total folder size */
1238 p_fci_internal
->pv
) == -1) {
1239 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
1243 /* get a new temp file */
1244 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFDATA1new
,CB_MAX_FILENAME
)) {
1245 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
1249 if ( strlen(szFileNameCFDATA1new
) >= CB_MAX_FILENAME
) {
1250 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1253 handleCFDATA1new
= PFCI_OPEN(hfci
,szFileNameCFDATA1new
,34050,384,&err
,
1254 p_fci_internal
->pv
);
1255 if(handleCFDATA1new
==0){
1256 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
1259 /* TODO error handling of err */
1263 /* get a new temp file */
1264 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFFILE1new
,CB_MAX_FILENAME
)) {
1265 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
1266 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1267 /* TODO error handling of err */
1271 if ( strlen(szFileNameCFFILE1new
) >= CB_MAX_FILENAME
) {
1272 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1273 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1274 /* TODO error handling of err */
1277 handleCFFILE1new
= PFCI_OPEN(hfci
,szFileNameCFFILE1new
,34050,384,&err
,
1278 p_fci_internal
->pv
);
1279 if(handleCFFILE1new
==0){
1280 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
1283 /* TODO error handling of err */
1285 /* USE the variable read_result */
1286 if ( p_fci_internal
->fNextCab
||
1287 p_fci_internal
->fGetNextCabInVain
) {
1288 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1289 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1290 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1291 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1295 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
;
1296 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1297 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1298 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1302 if (p_fci_internal
->fPrevCab
) {
1303 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1304 strlen(p_fci_internal
->szPrevDisk
)+1;
1306 read_result
+= sizeof(CFHEADER
) + p_fci_internal
->sizeFileCFDATA2
+
1307 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
;
1309 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
1310 read_result
+= sizeof(CFFOLDER
)+p_fci_internal
->pccab
->cbReserveCFFolder
;
1313 /* Check if multiple cabinets have to be created. */
1315 /* Might be too much data for the maximum allowed cabinet size.*/
1316 /* When any further data will be added later, it might not */
1317 /* be possible to flush the cabinet, because there might */
1318 /* not be enough space to store the name of the following */
1319 /* cabinet and name of the corresponding disk. */
1320 /* So take care of this and get the name of the next cabinet */
1321 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
1322 p_fci_internal
->fNextCab
==FALSE
&&
1325 p_fci_internal
->pccab
->cb
< read_result
+
1326 p_fci_internal
->sizeFileCFDATA1
+
1327 p_fci_internal
->sizeFileCFFILE1
+
1328 CB_MAX_CABINET_NAME
+ /* next cabinet name */
1329 CB_MAX_DISK_NAME
/* next disk name */
1334 p_fci_internal
->oldCCAB
= *p_fci_internal
->pccab
;
1335 /* increment cabinet index */
1336 ++(p_fci_internal
->pccab
->iCab
);
1337 /* get name of next cabinet */
1338 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
1339 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
1340 p_fci_internal
->estimatedCabinetSize
, /* estimated size of cab */
1341 p_fci_internal
->pv
)) {
1342 /* error handling */
1343 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
1344 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1345 /* TODO error handling of err */
1346 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1347 /* TODO error handling of err */
1351 /* Skip a few lines of code. This is caught by the next if. */
1352 p_fci_internal
->fGetNextCabInVain
=TRUE
;
1355 /* too much data for cabinet */
1356 if( (p_fci_internal
->fGetNextCabInVain
||
1357 p_fci_internal
->fNextCab
) &&
1360 p_fci_internal
->oldCCAB
.cb
< read_result
+
1361 p_fci_internal
->sizeFileCFDATA1
+
1362 p_fci_internal
->sizeFileCFFILE1
+
1363 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1364 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1368 p_fci_internal
->fGetNextCabInVain
=FALSE
;
1369 p_fci_internal
->fNextCab
=TRUE
;
1371 /* return FALSE if there is not enough space left*/
1372 /* this should never happen */
1373 if (p_fci_internal
->oldCCAB
.cb
<=
1374 p_fci_internal
->sizeFileCFFILE1
+
1376 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1377 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1380 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1381 /* TODO error handling of err */
1382 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1383 /* TODO error handling of err */
1385 /* close and delete p_fci_internal->handleCFFILE1 */
1386 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1387 /* TODO error handling of err */
1388 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1389 /* TODO error handling of err */
1394 /* the folder will be split across cabinets */
1395 p_fci_internal
->fSplitFolder
=TRUE
;
1398 /* this should never happen */
1399 if (p_fci_internal
->fNextCab
) {
1400 /* internal error */
1401 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1406 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1407 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA1
,0,SEEK_SET
,&err
,
1408 p_fci_internal
->pv
) !=0 ) {
1409 /* wrong return value */
1410 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1411 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1412 /* TODO error handling of err */
1413 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1414 /* TODO error handling of err */
1417 /* TODO error handling of err */
1419 /* save size of file CFDATA2 - required for the folder's offset to data */
1420 sizeFileCFDATA2old
= p_fci_internal
->sizeFileCFDATA2
;
1422 if(!(reserved
= PFCI_ALLOC(hfci
, cbReserveCFData
+sizeof(CFDATA
)))) {
1423 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
1424 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1425 /* TODO error handling of err */
1426 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1427 /* TODO error handling of err */
1431 if(!fci_flushfolder_copy_cfdata(hfci
, reserved
, cbReserveCFData
, pfnfcis
, &err
,
1432 handleCFDATA1new
, &sizeFileCFDATA1new
, &payload
1434 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1435 /* TODO error handling of err */
1436 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1437 /* TODO error handling of err */
1438 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1439 /* TODO error handling of err */
1440 PFCI_FREE(hfci
,reserved
);
1444 PFCI_FREE(hfci
,reserved
);
1446 if(!fci_flushfolder_copy_cffolder(hfci
, &err
, cbReserveCFFolder
,
1447 sizeFileCFDATA2old
)) {
1448 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1449 /* TODO error handling of err */
1450 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1451 /* TODO error handling of err */
1452 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1453 /* TODO error handling of err */
1457 if(!fci_flushfolder_copy_cffile(hfci
, &err
, handleCFFILE1new
,
1458 &sizeFileCFFILE1new
, payload
)) {
1459 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1460 /* TODO error handling of err */
1461 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1462 /* TODO error handling of err */
1463 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1464 /* TODO error handling of err */
1465 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1466 /* TODO error handling of err */
1470 /* close and delete p_fci_internal->handleCFDATA1 */
1471 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
1472 /* TODO error handling of err */
1473 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFDATA1
,&err
,p_fci_internal
->pv
);
1474 /* TODO error handling of err */
1476 /* put new CFDATA1 into hfci */
1477 memcpy(p_fci_internal
->szFileNameCFDATA1
,szFileNameCFDATA1new
,
1480 /* put CFDATA1 file handle */
1481 PFCI_INT(hfci
)->handleCFDATA1
= handleCFDATA1new
;
1483 PFCI_INT(hfci
)->sizeFileCFDATA1
= sizeFileCFDATA1new
;
1485 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1486 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFFILE1
,&err
,PFCI_INT(hfci
)->pv
);
1487 /* TODO error handling of err */
1488 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFFILE1
,&err
,p_fci_internal
->pv
);
1489 /* TODO error handling of err */
1491 /* put new CFFILE1 into hfci */
1492 memcpy(p_fci_internal
->szFileNameCFFILE1
,szFileNameCFFILE1new
,
1495 /* put CFFILE1 file handle */
1496 p_fci_internal
->handleCFFILE1
= handleCFFILE1new
;
1498 p_fci_internal
->sizeFileCFFILE1
= sizeFileCFFILE1new
;
1500 ++(p_fci_internal
->cFolders
);
1502 /* reset CFFolder specific information */
1503 p_fci_internal
->cDataBlocks
=0;
1504 p_fci_internal
->cCompressedBytesInFolder
=0;
1507 } /* end of fci_flush_folder */
1512 static BOOL
fci_flush_cabinet(
1515 PFNFCIGETNEXTCABINET pfnfcignc
,
1516 PFNFCISTATUS pfnfcis
)
1521 cab_UWORD cbCFHeader
;
1522 cab_UBYTE cbCFFolder
;
1526 cab_ULONG read_result
=0;
1527 int handleCABINET
; /* file handle for cabinet */
1528 char szFileNameCABINET
[CB_MAX_CAB_PATH
+CB_MAX_CABINET_NAME
];/* name buffer */
1529 UINT cbReserveCFHeader
, cbReserveCFFolder
, i
;
1531 BOOL returntrue
=FALSE
;
1532 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1534 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1536 /* when FCIFlushCabinet was or FCIAddFile hasn't been called */
1537 if( p_fci_internal
->sizeFileCFFILE1
==0 && fGetNextCab
) {
1541 if (!fci_flush_folder(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)){
1542 /* TODO set error */
1546 if(returntrue
) return TRUE
;
1548 if ( (p_fci_internal
->fSplitFolder
&& p_fci_internal
->fNextCab
==FALSE
)||
1549 (p_fci_internal
->sizeFileCFFOLDER
==0 &&
1550 (p_fci_internal
->sizeFileCFFILE1
!=0 ||
1551 p_fci_internal
->sizeFileCFFILE2
!=0 )
1555 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1559 if( p_fci_internal
->fNextCab
||
1560 p_fci_internal
->fGetNextCabInVain
) {
1561 cbReserveCFFolder
=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1562 cbReserveCFHeader
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1564 if (strlen(p_fci_internal
->oldCCAB
.szCabPath
)>=CB_MAX_CAB_PATH
||
1565 strlen(p_fci_internal
->oldCCAB
.szCab
)>=CB_MAX_CABINET_NAME
) {
1567 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1570 /* get the full name of the cabinet */
1571 memcpy(szFileNameCABINET
,p_fci_internal
->oldCCAB
.szCabPath
,
1573 memcpy(szFileNameCABINET
+strlen(szFileNameCABINET
),
1574 p_fci_internal
->oldCCAB
.szCab
, CB_MAX_CABINET_NAME
);
1576 cbReserveCFFolder
=p_fci_internal
->pccab
->cbReserveCFFolder
;
1577 cbReserveCFHeader
=p_fci_internal
->pccab
->cbReserveCFHeader
;
1579 if (strlen(p_fci_internal
->pccab
->szCabPath
)>=CB_MAX_CAB_PATH
||
1580 strlen(p_fci_internal
->pccab
->szCab
)>=CB_MAX_CABINET_NAME
) {
1582 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1585 /* get the full name of the cabinet */
1586 memcpy(szFileNameCABINET
,p_fci_internal
->pccab
->szCabPath
,
1588 memcpy(szFileNameCABINET
+strlen(szFileNameCABINET
),
1589 p_fci_internal
->pccab
->szCab
, CB_MAX_CABINET_NAME
);
1592 memcpy(cfheader
.signature
,"!CAB",4);
1593 cfheader
.reserved1
=0;
1594 cfheader
.cbCabinet
= /* size of the cabinet file in bytes */
1596 p_fci_internal
->sizeFileCFFOLDER
+
1597 p_fci_internal
->sizeFileCFFILE2
+
1598 p_fci_internal
->sizeFileCFDATA2
;
1600 if (p_fci_internal
->fPrevCab
) {
1601 cfheader
.cbCabinet
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1602 strlen(p_fci_internal
->szPrevDisk
)+1;
1604 if (p_fci_internal
->fNextCab
) {
1605 cfheader
.cbCabinet
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1606 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1608 if( p_fci_internal
->fNextCab
||
1609 p_fci_internal
->fGetNextCabInVain
) {
1610 cfheader
.cbCabinet
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1611 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1612 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1613 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1614 cfheader
.cbCabinet
+=4;
1617 cfheader
.cbCabinet
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1618 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1619 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1620 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1621 cfheader
.cbCabinet
+=4;
1625 if( ( ( p_fci_internal
->fNextCab
||
1626 p_fci_internal
->fGetNextCabInVain
) &&
1627 cfheader
.cbCabinet
> p_fci_internal
->oldCCAB
.cb
1629 ( ( p_fci_internal
->fNextCab
==FALSE
&&
1630 p_fci_internal
->fGetNextCabInVain
==FALSE
) &&
1631 cfheader
.cbCabinet
> p_fci_internal
->pccab
->cb
1635 fci_set_error( FCIERR_NONE
, ERROR_MORE_DATA
, TRUE
);
1640 cfheader
.reserved2
=0;
1641 cfheader
.coffFiles
= /* offset to first CFFILE section */
1642 cfheader
.cbCabinet
- p_fci_internal
->sizeFileCFFILE2
-
1643 p_fci_internal
->sizeFileCFDATA2
;
1645 cfheader
.reserved3
=0;
1646 cfheader
.versionMinor
=3;
1647 cfheader
.versionMajor
=1;
1648 /* number of CFFOLDER entries in the cabinet */
1649 cfheader
.cFolders
=p_fci_internal
->cFolders
;
1650 /* number of CFFILE entries in the cabinet */
1651 cfheader
.cFiles
=p_fci_internal
->cFiles
;
1652 cfheader
.flags
=0; /* 1=prev cab, 2=next cabinet, 4=reserved sections */
1654 if( p_fci_internal
->fPrevCab
) {
1655 cfheader
.flags
= cfheadPREV_CABINET
;
1658 if( p_fci_internal
->fNextCab
) {
1659 cfheader
.flags
|= cfheadNEXT_CABINET
;
1662 if( p_fci_internal
->fNextCab
||
1663 p_fci_internal
->fGetNextCabInVain
) {
1664 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1665 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1666 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1667 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1669 cfheader
.setID
= p_fci_internal
->oldCCAB
.setID
;
1670 cfheader
.iCabinet
= p_fci_internal
->oldCCAB
.iCab
-1;
1672 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1673 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1674 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1675 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1677 cfheader
.setID
= p_fci_internal
->pccab
->setID
;
1678 cfheader
.iCabinet
= p_fci_internal
->pccab
->iCab
-1;
1681 /* create the cabinet */
1682 handleCABINET
= PFCI_OPEN(hfci
, szFileNameCABINET
,
1683 33538, 384, &err
, p_fci_internal
->pv
);
1684 if(handleCABINET
==0){
1685 fci_set_error( FCIERR_CAB_FILE
, ERROR_OPEN_FAILED
, TRUE
);
1688 /* TODO error checking of err */
1690 /* set little endian */
1691 cfheader
.reserved1
=fci_endian_ulong(cfheader
.reserved1
);
1692 cfheader
.cbCabinet
=fci_endian_ulong(cfheader
.cbCabinet
);
1693 cfheader
.reserved2
=fci_endian_ulong(cfheader
.reserved2
);
1694 cfheader
.coffFiles
=fci_endian_ulong(cfheader
.coffFiles
);
1695 cfheader
.reserved3
=fci_endian_ulong(cfheader
.reserved3
);
1696 cfheader
.cFolders
=fci_endian_uword(cfheader
.cFolders
);
1697 cfheader
.cFiles
=fci_endian_uword(cfheader
.cFiles
);
1698 cfheader
.flags
=fci_endian_uword(cfheader
.flags
);
1699 cfheader
.setID
=fci_endian_uword(cfheader
.setID
);
1700 cfheader
.iCabinet
=fci_endian_uword(cfheader
.iCabinet
);
1702 /* write CFHEADER into cabinet file */
1703 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1704 &cfheader
, /* memory buffer */
1705 sizeof(cfheader
), /* number of bytes to copy */
1706 &err
, p_fci_internal
->pv
) != sizeof(cfheader
) ) {
1708 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1711 /* TODO error handling of err */
1713 /* reset little endian */
1714 cfheader
.reserved1
=fci_endian_ulong(cfheader
.reserved1
);
1715 cfheader
.cbCabinet
=fci_endian_ulong(cfheader
.cbCabinet
);
1716 cfheader
.reserved2
=fci_endian_ulong(cfheader
.reserved2
);
1717 cfheader
.coffFiles
=fci_endian_ulong(cfheader
.coffFiles
);
1718 cfheader
.reserved3
=fci_endian_ulong(cfheader
.reserved3
);
1719 cfheader
.cFolders
=fci_endian_uword(cfheader
.cFolders
);
1720 cfheader
.cFiles
=fci_endian_uword(cfheader
.cFiles
);
1721 cfheader
.flags
=fci_endian_uword(cfheader
.flags
);
1722 cfheader
.setID
=fci_endian_uword(cfheader
.setID
);
1723 cfheader
.iCabinet
=fci_endian_uword(cfheader
.iCabinet
);
1725 if( cfheader
.flags
& cfheadRESERVE_PRESENT
) {
1726 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1727 cfreserved
.cbCFHeader
= cbReserveCFHeader
;
1728 cfreserved
.cbCFFolder
= cbReserveCFFolder
;
1729 if( p_fci_internal
->fNextCab
||
1730 p_fci_internal
->fGetNextCabInVain
) {
1731 cfreserved
.cbCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1733 cfreserved
.cbCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1736 /* set little endian */
1737 cfreserved
.cbCFHeader
=fci_endian_uword(cfreserved
.cbCFHeader
);
1739 /* write reserved info into cabinet file */
1740 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1741 &cfreserved
, /* memory buffer */
1742 sizeof(cfreserved
), /* number of bytes to copy */
1743 &err
, p_fci_internal
->pv
) != sizeof(cfreserved
) ) {
1745 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1748 /* TODO error handling of err */
1750 /* reset little endian */
1751 cfreserved
.cbCFHeader
=fci_endian_uword(cfreserved
.cbCFHeader
);
1754 /* add optional reserved area */
1755 if (cbReserveCFHeader
!=0) {
1756 if(!(reserved
= PFCI_ALLOC(hfci
, cbReserveCFHeader
))) {
1757 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
1760 for(i
=0;i
<cbReserveCFHeader
;) {
1763 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1764 reserved
, /* memory buffer */
1765 cbReserveCFHeader
, /* number of bytes to copy */
1766 &err
, p_fci_internal
->pv
) != cbReserveCFHeader
) {
1767 PFCI_FREE(hfci
, reserved
);
1769 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1772 /* TODO error handling of err */
1773 PFCI_FREE(hfci
, reserved
);
1776 if( cfheader
.flags
& cfheadPREV_CABINET
) {
1777 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1778 p_fci_internal
->szPrevCab
, /* memory buffer */
1779 strlen(p_fci_internal
->szPrevCab
)+1, /* number of bytes to copy */
1780 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevCab
)+1 ) {
1782 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1785 /* TODO error handling of err */
1787 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1788 p_fci_internal
->szPrevDisk
, /* memory buffer */
1789 strlen(p_fci_internal
->szPrevDisk
)+1, /* number of bytes to copy */
1790 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevDisk
)+1 ) {
1792 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1795 /* TODO error handling of err */
1798 if( cfheader
.flags
& cfheadNEXT_CABINET
) {
1799 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1800 p_fci_internal
->pccab
->szCab
, /* memory buffer */
1801 strlen(p_fci_internal
->pccab
->szCab
)+1, /* number of bytes to copy */
1802 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szCab
)+1 ) {
1804 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1807 /* TODO error handling of err */
1809 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1810 p_fci_internal
->pccab
->szDisk
, /* memory buffer */
1811 strlen(p_fci_internal
->pccab
->szDisk
)+1, /* number of bytes to copy */
1812 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szDisk
)+1 ) {
1814 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1817 /* TODO error handling of err */
1820 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1821 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFOLDER
,
1822 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1823 /* wrong return value */
1824 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1827 /* TODO error handling of err */
1829 /* while not all CFFOLDER structures have been copied into the cabinet do */
1831 /* use the variable read_result */
1832 /* read cffolder of p_fci_internal->handleCFFOLDER */
1833 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* handle */
1834 &cffolder
, /* memory buffer */
1835 sizeof(cffolder
), /* number of bytes to copy */
1836 &err
, p_fci_internal
->pv
);
1837 if( read_result
!= sizeof(cffolder
) ) {
1838 if( read_result
== 0 ) break;/*ALL CFFOLDER structures have been copied*/
1840 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
1843 /* TODO error handling of err */
1845 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1846 cffolder
.coffCabStart
+=
1847 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
1849 if( p_fci_internal
->fNextCab
||
1850 p_fci_internal
->fGetNextCabInVain
) {
1851 cffolder
.coffCabStart
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1853 cffolder
.coffCabStart
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1856 if (p_fci_internal
->fPrevCab
) {
1857 cffolder
.coffCabStart
+= strlen(p_fci_internal
->szPrevCab
)+1 +
1858 strlen(p_fci_internal
->szPrevDisk
)+1;
1861 if (p_fci_internal
->fNextCab
) {
1862 cffolder
.coffCabStart
+= strlen(p_fci_internal
->oldCCAB
.szCab
)+1 +
1863 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1;
1866 if( p_fci_internal
->fNextCab
||
1867 p_fci_internal
->fGetNextCabInVain
) {
1868 cffolder
.coffCabStart
+= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1869 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1870 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1871 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1872 cffolder
.coffCabStart
+= 4;
1875 cffolder
.coffCabStart
+= p_fci_internal
->pccab
->cbReserveCFHeader
;
1876 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1877 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1878 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1879 cffolder
.coffCabStart
+= 4;
1883 /* set little endian */
1884 cffolder
.coffCabStart
=fci_endian_ulong(cffolder
.coffCabStart
);
1885 cffolder
.cCFData
=fci_endian_uword(cffolder
.cCFData
);
1886 cffolder
.typeCompress
=fci_endian_uword(cffolder
.typeCompress
);
1888 /* write cffolder to cabinet file */
1889 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1890 &cffolder
, /* memory buffer */
1891 sizeof(cffolder
), /* number of bytes to copy */
1892 &err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
1894 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1897 /* TODO error handling of err */
1899 /* reset little endian */
1900 cffolder
.coffCabStart
=fci_endian_ulong(cffolder
.coffCabStart
);
1901 cffolder
.cCFData
=fci_endian_uword(cffolder
.cCFData
);
1902 cffolder
.typeCompress
=fci_endian_uword(cffolder
.typeCompress
);
1904 /* add optional reserved area */
1906 /* This allocation and freeing at each CFFolder block is a bit */
1907 /* inefficient, but it's harder to forget about freeing the buffer :-). */
1908 /* Reserved areas are used seldom besides that... */
1909 if (cbReserveCFFolder
!=0) {
1910 if(!(reserved
= PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
1911 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
1915 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
1916 reserved
, /* memory buffer */
1917 cbReserveCFFolder
, /* number of bytes to copy */
1918 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1919 PFCI_FREE(hfci
, reserved
);
1921 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
1924 /* TODO error handling of err */
1926 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1927 reserved
, /* memory buffer */
1928 cbReserveCFFolder
, /* number of bytes to copy */
1929 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1930 PFCI_FREE(hfci
, reserved
);
1932 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1935 /* TODO error handling of err */
1937 PFCI_FREE(hfci
, reserved
);
1940 } /* END OF while */
1942 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1943 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE2
,
1944 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1945 /* wrong return value */
1946 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1949 /* TODO error handling of err */
1951 /* while not all CFFILE structures have been copied to the cabinet do */
1952 if (p_fci_internal
->data_out
) while(!FALSE
) {
1953 /* REUSE the variable read_result */
1954 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1955 /* read a block from p_fci_internal->handleCFFILE2 */
1956 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFILE2
/* handle */,
1957 p_fci_internal
->data_out
, /* memory buffer */
1958 CB_MAX_CHUNK
, /* number of bytes to copy */
1959 &err
, p_fci_internal
->pv
);
1960 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
1961 /* TODO error handling of err */
1963 /* write the block to the cabinet file */
1964 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1965 p_fci_internal
->data_out
, /* memory buffer */
1966 read_result
, /* number of bytes to copy */
1967 &err
, p_fci_internal
->pv
) != read_result
) {
1969 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1972 /* TODO error handling of err */
1974 if (p_fci_internal
->fSplitFolder
==FALSE
) {
1975 p_fci_internal
->statusFolderCopied
= 0;
1976 /* TODO TEST THIS further */
1977 p_fci_internal
->statusFolderTotal
= p_fci_internal
->sizeFileCFDATA2
+
1978 p_fci_internal
->sizeFileCFFILE2
;
1980 p_fci_internal
->statusFolderCopied
+= read_result
;
1982 /* report status with pfnfcis about copied size of folder */
1983 if( (*pfnfcis
)(statusFolder
,
1984 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
1985 p_fci_internal
->statusFolderTotal
, /* total size of folder */
1986 p_fci_internal
->pv
) == -1) {
1987 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
1991 } /* END OF while */
1993 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1994 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA2
,
1995 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1996 /* wrong return value */
1997 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
2000 /* TODO error handling of err */
2002 /* reset the number of folders for the next cabinet */
2003 p_fci_internal
->cFolders
=0;
2004 /* reset the number of files for the next cabinet */
2005 p_fci_internal
->cFiles
=0;
2007 /* while not all CFDATA structures have been copied to the cabinet do */
2008 if (p_fci_internal
->data_out
) while(!FALSE
) {
2009 /* REUSE the variable read_result AGAIN */
2010 /* REUSE the buffer p_fci_internal->data_out AGAIN */
2011 /* read a block from p_fci_internal->handleCFDATA2 */
2012 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA2
/* handle */,
2013 p_fci_internal
->data_out
, /* memory buffer */
2014 CB_MAX_CHUNK
, /* number of bytes to copy */
2015 &err
, p_fci_internal
->pv
);
2016 if( read_result
== 0 ) break; /* ALL CFDATA structures have been copied */
2017 /* TODO error handling of err */
2019 /* write the block to the cabinet file */
2020 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
2021 p_fci_internal
->data_out
, /* memory buffer */
2022 read_result
, /* number of bytes to copy */
2023 &err
, p_fci_internal
->pv
) != read_result
) {
2025 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2028 /* TODO error handling of err */
2030 p_fci_internal
->statusFolderCopied
+= read_result
;
2031 /* report status with pfnfcis about copied size of folder */
2032 if( (*pfnfcis
)(statusFolder
,
2033 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
2034 p_fci_internal
->statusFolderTotal
, /* total size of folder */
2035 p_fci_internal
->pv
) == -1) {
2036 /* set error code and abort */
2037 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
2040 } /* END OF while */
2042 /* set seek of the cabinet file to 0 */
2043 if( PFCI_SEEK(hfci
, handleCABINET
,
2044 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
2045 /* wrong return value */
2046 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
2049 /* TODO error handling of err */
2051 /* write the signature "MSCF" into the cabinet file */
2052 memcpy( cfheader
.signature
, "MSCF", 4 );
2053 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
2054 &cfheader
, /* memory buffer */
2055 4, /* number of bytes to copy */
2056 &err
, p_fci_internal
->pv
) != 4 ) {
2058 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2061 /* TODO error handling of err */
2063 /* close the cabinet file */
2064 PFCI_CLOSE(hfci
,handleCABINET
,&err
,p_fci_internal
->pv
);
2065 /* TODO error handling of err */
2068 /* COPIED FROM FCIDestroy */
2070 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
2071 /* TODO error handling of err */
2072 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
2073 p_fci_internal
->pv
);
2074 /* TODO error handling of err */
2075 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
2076 /* TODO error handling of err */
2077 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
2078 p_fci_internal
->pv
);
2079 /* TODO error handling of err */
2080 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
2081 /* TODO error handling of err */
2082 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
2083 p_fci_internal
->pv
);
2084 /* TODO error handling of err */
2086 /* END OF copied from FCIDestroy */
2088 /* get 3 temporary files and open them */
2089 /* write names and handles to hfci */
2092 p_fci_internal
->sizeFileCFDATA2
= 0;
2093 p_fci_internal
->sizeFileCFFILE2
= 0;
2094 p_fci_internal
->sizeFileCFFOLDER
= 0;
2096 /* COPIED FROM FCICreate */
2098 /* CFDATA with checksum and ready to be copied into cabinet */
2099 if( !PFCI_GETTEMPFILE(hfci
, p_fci_internal
->szFileNameCFDATA2
,
2101 /* error handling */
2102 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2106 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
2107 /* set error code and abort */
2108 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2111 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
2112 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, p_fci_internal
->pv
);
2114 if(p_fci_internal
->handleCFDATA2
==0){
2115 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
2118 /* TODO error checking of err */
2120 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2121 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
2123 /* error handling */
2124 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2128 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
2129 /* set error code and abort */
2130 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2133 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
2134 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, p_fci_internal
->pv
);
2136 if(p_fci_internal
->handleCFFILE2
==0){
2137 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
2140 /* TODO error checking of err */
2142 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2143 if (!PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,CB_MAX_FILENAME
)) {
2144 /* error handling */
2145 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2149 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
2150 /* set error code and abort */
2151 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2154 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
2155 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, p_fci_internal
->pv
);
2157 if(p_fci_internal
->handleCFFOLDER
==0){
2158 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
2161 /* TODO error checking of err */
2163 /* END OF copied from FCICreate */
2166 /* TODO close and delete new files when return FALSE */
2169 /* report status with pfnfcis about copied size of folder */
2170 (*pfnfcis
)(statusCabinet
,
2171 p_fci_internal
->estimatedCabinetSize
, /* estimated cabinet file size */
2172 cfheader
.cbCabinet
/* real cabinet file size */, p_fci_internal
->pv
);
2174 p_fci_internal
->fPrevCab
=TRUE
;
2175 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2176 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2178 if (p_fci_internal
->fNextCab
) {
2179 p_fci_internal
->fNextCab
=FALSE
;
2181 if (p_fci_internal
->sizeFileCFFILE1
==0 && p_fci_internal
->sizeFileCFDATA1
!=0) {
2182 /* THIS CAN NEVER HAPPEN */
2183 /* set error code */
2184 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2188 /* COPIED FROM FCIAddFile and modified */
2190 /* REUSE the variable read_result */
2191 if (p_fci_internal
->fGetNextCabInVain
) {
2192 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
2193 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2194 read_result
+=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2196 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2197 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2198 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2202 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
;
2203 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2204 read_result
+=p_fci_internal
->pccab
->cbReserveCFFolder
;
2206 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2207 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2208 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2212 if ( p_fci_internal
->fPrevCab
) {
2213 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2214 strlen(p_fci_internal
->szPrevDisk
)+1;
2216 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2217 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2218 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2220 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2222 if( p_fci_internal
->fNewPrevious
) {
2223 memcpy(p_fci_internal
->szPrevCab
, p_fci_internal
->oldCCAB
.szCab
,
2224 CB_MAX_CABINET_NAME
);
2225 memcpy(p_fci_internal
->szPrevDisk
, p_fci_internal
->oldCCAB
.szDisk
,
2227 p_fci_internal
->fNewPrevious
=FALSE
;
2230 /* too much data for the maximum size of a cabinet */
2231 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2232 p_fci_internal
->pccab
->cb
< read_result
) {
2233 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2236 /* Might be too much data for the maximum size of a cabinet.*/
2237 /* When any further data will be added later, it might not */
2238 /* be possible to flush the cabinet, because there might */
2239 /* not be enough space to store the name of the following */
2240 /* cabinet and name of the corresponding disk. */
2241 /* So take care of this and get the name of the next cabinet */
2242 if (p_fci_internal
->fGetNextCabInVain
==FALSE
&& (
2243 p_fci_internal
->pccab
->cb
< read_result
+
2244 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2247 p_fci_internal
->oldCCAB
= *p_fci_internal
->pccab
;
2248 /* increment cabinet index */
2249 ++(p_fci_internal
->pccab
->iCab
);
2250 /* get name of next cabinet */
2251 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
2252 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
2253 p_fci_internal
->estimatedCabinetSize
, /* estimated size of cab */
2254 p_fci_internal
->pv
)) {
2255 /* error handling */
2256 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2259 /* Skip a few lines of code. This is caught by the next if. */
2260 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2263 /* too much data for cabinet */
2264 if (p_fci_internal
->fGetNextCabInVain
&& (
2265 p_fci_internal
->oldCCAB
.cb
< read_result
+
2266 strlen(p_fci_internal
->oldCCAB
.szCab
)+1+
2267 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1
2269 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2270 p_fci_internal
->fNextCab
=TRUE
;
2271 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2274 /* if the FolderThreshold has been reached flush the folder automatically */
2275 if( p_fci_internal
->fGetNextCabInVain
) {
2276 if( p_fci_internal
->cCompressedBytesInFolder
>=
2277 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2278 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2281 if( p_fci_internal
->cCompressedBytesInFolder
>=
2282 p_fci_internal
->pccab
->cbFolderThresh
) {
2283 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2287 /* END OF COPIED FROM FCIAddFile and modified */
2289 if( p_fci_internal
->sizeFileCFFILE1
>0 ) {
2290 if( !FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
) ) return FALSE
;
2291 p_fci_internal
->fNewPrevious
=TRUE
;
2294 p_fci_internal
->fNewPrevious
=FALSE
;
2295 if( p_fci_internal
->sizeFileCFFILE1
>0 || p_fci_internal
->sizeFileCFDATA1
) {
2296 /* THIS MAY NEVER HAPPEN */
2297 /* set error structures */
2298 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2304 } /* end of fci_flush_cabinet */
2310 /***********************************************************************
2311 * FCIAddFile (CABINET.11)
2313 * FCIAddFile adds a file to the to be created cabinet file
2316 * hfci [I] An HFCI from FCICreate
2317 * pszSourceFile [I] A pointer to a C string which contains the name and
2318 * location of the file which will be added to the cabinet
2319 * pszFileName [I] A pointer to a C string which contains the name under
2320 * which the file will be stored in the cabinet
2321 * fExecute [I] A boolean value which indicates if the file should be
2322 * executed after extraction of self extracting
2324 * pfnfcignc [I] A pointer to a function which gets information about
2326 * pfnfcis [IO] A pointer to a function which will report status
2327 * information about the compression process
2328 * pfnfcioi [I] A pointer to a function which reports file attributes
2329 * and time and date information
2330 * typeCompress [I] Compression type
2333 * On success, returns TRUE
2334 * On failure, returns FALSE
2340 BOOL __cdecl
FCIAddFile(
2342 char *pszSourceFile
,
2345 PFNFCIGETNEXTCABINET pfnfcignc
,
2346 PFNFCISTATUS pfnfcis
,
2347 PFNFCIGETOPENINFO pfnfcigoi
,
2352 cab_ULONG read_result
;
2354 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2357 if (!REALLY_IS_FCI(hfci
)) {
2358 SetLastError(ERROR_INVALID_HANDLE
);
2362 if ((!pszSourceFile
) || (!pszFileName
) || (!pfnfcignc
) || (!pfnfcis
) ||
2363 (!pfnfcigoi
) || strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2364 fci_set_error( FCIERR_NONE
, ERROR_BAD_ARGUMENTS
, TRUE
);
2368 /* TODO check if pszSourceFile??? */
2370 if(p_fci_internal
->fGetNextCabInVain
&& p_fci_internal
->fNextCab
) {
2371 /* internal error */
2372 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2376 if(p_fci_internal
->fNextCab
) {
2377 /* internal error */
2378 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2382 cffile
.cbFile
=0; /* size of the to be added file*/
2383 /* offset of the uncompressed file in the folder */
2384 cffile
.uoffFolderStart
=p_fci_internal
->cDataBlocks
*CAB_BLOCKMAX
+ p_fci_internal
->cdata_in
;
2385 /* number of folder in the cabinet or special 0=first */
2386 cffile
.iFolder
= p_fci_internal
->cFolders
;
2388 /* allocation of memory */
2389 if (p_fci_internal
->data_in
==NULL
) {
2390 if (p_fci_internal
->cdata_in
!=0) {
2391 /* error handling */
2392 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2395 if (p_fci_internal
->data_out
!=NULL
) {
2396 /* error handling */
2397 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2400 if(!(p_fci_internal
->data_in
= PFCI_ALLOC(hfci
,CB_MAX_CHUNK
))) {
2401 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
2404 if (p_fci_internal
->data_out
==NULL
) {
2405 if(!(p_fci_internal
->data_out
= PFCI_ALLOC(hfci
, 2 * CB_MAX_CHUNK
))){
2406 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
2412 if (p_fci_internal
->data_out
==NULL
) {
2413 PFCI_FREE(hfci
,p_fci_internal
->data_in
);
2414 /* error handling */
2415 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2419 /* get information about the file */
2420 /* set defaults in case callback doesn't set one or more fields */
2424 file_handle
=(*pfnfcigoi
)(pszSourceFile
, &(cffile
.date
), &(cffile
.time
),
2425 &(cffile
.attribs
), &err
, p_fci_internal
->pv
);
2426 /* check file_handle */
2428 fci_set_error( FCIERR_OPEN_SRC
, ERROR_OPEN_FAILED
, TRUE
);
2430 /* TODO error handling of err */
2432 if (fExecute
) { cffile
.attribs
|= _A_EXEC
; }
2434 /* REUSE the variable read_result */
2435 if (p_fci_internal
->fGetNextCabInVain
) {
2436 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2437 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2438 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2439 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2440 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2444 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2445 p_fci_internal
->pccab
->cbReserveCFFolder
;
2446 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2447 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2448 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2452 if ( p_fci_internal
->fPrevCab
) {
2453 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2454 strlen(p_fci_internal
->szPrevDisk
)+1;
2456 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2457 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2458 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2461 read_result
+= sizeof(CFFILE
) + strlen(pszFileName
)+1 +
2462 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2463 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2465 sizeof(CFFOLDER
); /* size of new CFFolder entry */
2467 /* Might be too much data for the maximum size of a cabinet.*/
2468 /* When any further data will be added later, it might not */
2469 /* be possible to flush the cabinet, because there might */
2470 /* not be enough space to store the name of the following */
2471 /* cabinet and name of the corresponding disk. */
2472 /* So take care of this and get the name of the next cabinet */
2473 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2474 p_fci_internal
->fNextCab
==FALSE
&&
2475 ( p_fci_internal
->pccab
->cb
< read_result
+
2476 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2480 p_fci_internal
->oldCCAB
= *p_fci_internal
->pccab
;
2481 /* increment cabinet index */
2482 ++(p_fci_internal
->pccab
->iCab
);
2483 /* get name of next cabinet */
2484 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
2485 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
2486 p_fci_internal
->estimatedCabinetSize
, /* estimated size of cab */
2487 p_fci_internal
->pv
)) {
2488 /* error handling */
2489 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2492 /* Skip a few lines of code. This is caught by the next if. */
2493 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2496 if( p_fci_internal
->fGetNextCabInVain
&&
2497 p_fci_internal
->fNextCab
2499 /* THIS CAN NEVER HAPPEN */
2500 /* set error code */
2501 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2505 /* too much data for cabinet */
2506 if( p_fci_internal
->fGetNextCabInVain
&&
2508 p_fci_internal
->oldCCAB
.cb
< read_result
+
2509 strlen(p_fci_internal
->pccab
->szCab
)+1+
2510 strlen(p_fci_internal
->pccab
->szDisk
)+1
2512 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2513 p_fci_internal
->fNextCab
=TRUE
;
2514 if(!fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
)) return FALSE
;
2517 if( p_fci_internal
->fNextCab
) {
2518 /* THIS MAY NEVER HAPPEN */
2519 /* set error code */
2520 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2524 /* read the contents of the file blockwise */
2526 if (p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2527 /* internal error */
2528 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2532 read_result
= PFCI_READ(hfci
, file_handle
/* file handle */,
2533 (p_fci_internal
->data_in
+ p_fci_internal
->cdata_in
) /* memory buffer */,
2534 (CAB_BLOCKMAX
- p_fci_internal
->cdata_in
) /* number of bytes to copy */,
2535 &err
, p_fci_internal
->pv
);
2536 /* TODO error handling of err */
2538 if( read_result
==0 ) break;
2540 /* increment the block size */
2541 p_fci_internal
->cdata_in
+= read_result
;
2543 /* increment the file size */
2544 cffile
.cbFile
+= read_result
;
2546 if ( p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2547 /* report internal error */
2548 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2551 /* write a whole block */
2552 if ( p_fci_internal
->cdata_in
== CAB_BLOCKMAX
) {
2554 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
2558 /* close the file from FCIAddFile */
2559 PFCI_CLOSE(hfci
,file_handle
,&err
,p_fci_internal
->pv
);
2560 /* TODO error handling of err */
2562 /* write cffile to p_fci_internal->handleCFFILE1 */
2563 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2564 &cffile
, sizeof(cffile
),&err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
2566 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2569 /* TODO error handling of err */
2571 p_fci_internal
->sizeFileCFFILE1
+= sizeof(cffile
);
2573 /* append the name of file */
2574 if (strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2576 /* set error code */
2577 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2580 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2581 pszFileName
, strlen(pszFileName
)+1, &err
, p_fci_internal
->pv
)
2582 != strlen(pszFileName
)+1 ) {
2584 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2587 /* TODO error handling of err */
2589 p_fci_internal
->sizeFileCFFILE1
+= strlen(pszFileName
)+1;
2591 /* REUSE the variable read_result */
2592 if (p_fci_internal
->fGetNextCabInVain
||
2593 p_fci_internal
->fNextCab
2595 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2596 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2597 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2598 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2599 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2603 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2604 p_fci_internal
->pccab
->cbReserveCFFolder
;
2605 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2606 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2607 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2611 if ( p_fci_internal
->fPrevCab
) {
2612 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2613 strlen(p_fci_internal
->szPrevDisk
)+1;
2615 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2616 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2617 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2619 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2620 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2621 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2623 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2625 /* too much data for the maximum size of a cabinet */
2626 /* (ignoring the unflushed data block) */
2627 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2628 p_fci_internal
->fNextCab
==FALSE
&& /* this is always the case */
2629 p_fci_internal
->pccab
->cb
< read_result
) {
2630 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2633 /* Might be too much data for the maximum size of a cabinet.*/
2634 /* When any further data will be added later, it might not */
2635 /* be possible to flush the cabinet, because there might */
2636 /* not be enough space to store the name of the following */
2637 /* cabinet and name of the corresponding disk. */
2638 /* So take care of this and get the name of the next cabinet */
2639 /* (ignoring the unflushed data block) */
2640 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2641 p_fci_internal
->fNextCab
==FALSE
&&
2642 ( p_fci_internal
->pccab
->cb
< read_result
+
2643 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2647 p_fci_internal
->oldCCAB
= *p_fci_internal
->pccab
;
2648 /* increment cabinet index */
2649 ++(p_fci_internal
->pccab
->iCab
);
2650 /* get name of next cabinet */
2651 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
2652 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
2653 p_fci_internal
->estimatedCabinetSize
,/* estimated size of cab */
2654 p_fci_internal
->pv
)) {
2655 /* error handling */
2656 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2659 /* Skip a few lines of code. This is caught by the next if. */
2660 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2663 if( p_fci_internal
->fGetNextCabInVain
&&
2664 p_fci_internal
->fNextCab
2666 /* THIS CAN NEVER HAPPEN */
2667 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2671 /* too much data for cabinet */
2672 if( (p_fci_internal
->fGetNextCabInVain
||
2673 p_fci_internal
->fNextCab
) && (
2674 p_fci_internal
->oldCCAB
.cb
< read_result
+
2675 strlen(p_fci_internal
->pccab
->szCab
)+1+
2676 strlen(p_fci_internal
->pccab
->szDisk
)+1
2679 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2680 p_fci_internal
->fNextCab
=TRUE
;
2681 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2684 if( p_fci_internal
->fNextCab
) {
2685 /* THIS MAY NEVER HAPPEN */
2686 /* set error code */
2687 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2691 /* if the FolderThreshold has been reached flush the folder automatically */
2692 if( p_fci_internal
->fGetNextCabInVain
) {
2693 if( p_fci_internal
->cCompressedBytesInFolder
>=
2694 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2695 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2698 if( p_fci_internal
->cCompressedBytesInFolder
>=
2699 p_fci_internal
->pccab
->cbFolderThresh
) {
2700 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2705 } /* end of FCIAddFile */
2711 /***********************************************************************
2712 * FCIFlushFolder (CABINET.12)
2714 * FCIFlushFolder completes the CFFolder structure under construction.
2716 * All further data which is added by FCIAddFile will be associated to
2717 * the next CFFolder structure.
2719 * FCIFlushFolder will be called by FCIAddFile automatically if the
2720 * threshold (stored in the member cbFolderThresh of the CCAB structure
2721 * pccab passed to FCICreate) is exceeded.
2723 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2724 * any data will be written into the cabinet file.
2727 * hfci [I] An HFCI from FCICreate
2728 * pfnfcignc [I] A pointer to a function which gets information about
2730 * pfnfcis [IO] A pointer to a function which will report status
2731 * information about the compression process
2734 * On success, returns TRUE
2735 * On failure, returns FALSE
2741 BOOL __cdecl
FCIFlushFolder(
2743 PFNFCIGETNEXTCABINET pfnfcignc
,
2744 PFNFCISTATUS pfnfcis
)
2746 return fci_flush_folder(hfci
,FALSE
,pfnfcignc
,pfnfcis
);
2747 } /* end of FCIFlushFolder */
2751 /***********************************************************************
2752 * FCIFlushCabinet (CABINET.13)
2754 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2755 * into the cabinet file. If the maximum cabinet size (stored in the
2756 * member cb of the CCAB structure pccab passed to FCICreate) has been
2757 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2758 * The remaining data still has to be flushed manually by calling
2761 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2762 * NOT be called again. Then hfci has to be released by FCIDestroy.
2765 * hfci [I] An HFCI from FCICreate
2766 * fGetNextCab [I] Whether you want to add additional files to a
2767 * cabinet set (TRUE) or whether you want to
2768 * finalize it (FALSE)
2769 * pfnfcignc [I] A pointer to a function which gets information about
2771 * pfnfcis [IO] A pointer to a function which will report status
2772 * information about the compression process
2775 * On success, returns TRUE
2776 * On failure, returns FALSE
2782 BOOL __cdecl
FCIFlushCabinet(
2785 PFNFCIGETNEXTCABINET pfnfcignc
,
2786 PFNFCISTATUS pfnfcis
)
2788 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2790 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2792 while( p_fci_internal
->sizeFileCFFILE1
>0 ||
2793 p_fci_internal
->sizeFileCFFILE2
>0 ) {
2794 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2798 } /* end of FCIFlushCabinet */
2801 /***********************************************************************
2802 * FCIDestroy (CABINET.14)
2804 * Frees a handle created by FCICreate.
2805 * Only reason for failure would be an invalid handle.
2808 * hfci [I] The HFCI to free
2814 BOOL __cdecl
FCIDestroy(HFCI hfci
)
2817 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2818 if (REALLY_IS_FCI(hfci
)) {
2820 /* before hfci can be removed all temporary files must be closed */
2822 p_fci_internal
->FCI_Intmagic
= 0;
2824 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
2825 /* TODO error handling of err */
2826 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA1
, &err
,
2827 p_fci_internal
->pv
);
2828 /* TODO error handling of err */
2829 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE1
,&err
,p_fci_internal
->pv
);
2830 /* TODO error handling of err */
2831 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE1
, &err
,
2832 p_fci_internal
->pv
);
2833 /* TODO error handling of err */
2834 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
2835 /* TODO error handling of err */
2836 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
2837 p_fci_internal
->pv
);
2838 /* TODO error handling of err */
2839 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
2840 /* TODO error handling of err */
2841 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
2842 p_fci_internal
->pv
);
2843 /* TODO error handling of err */
2844 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
2845 /* TODO error handling of err */
2846 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
2847 p_fci_internal
->pv
);
2848 /* TODO error handling of err */
2850 /* data in and out buffers have to be removed */
2851 if (p_fci_internal
->data_in
!=NULL
)
2852 PFCI_FREE(hfci
, p_fci_internal
->data_in
);
2853 if (p_fci_internal
->data_out
!=NULL
)
2854 PFCI_FREE(hfci
, p_fci_internal
->data_out
);
2856 /* hfci can now be removed */
2857 PFCI_FREE(hfci
, hfci
);
2860 SetLastError(ERROR_INVALID_HANDLE
);
2864 } /* end of FCIDestroy */