2 * File Compression Interface
4 * Copyright 2002 Patrik Stridvall
5 * Copyright 2005 Gerold Jens Wucherpfennig
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 There is still some work to be done:
26 - no real compression yet
27 - unknown behaviour if files>=2GB or cabinet >=4GB
28 - check if the maximum size for a cabinet is too small to store any data
29 - call pfnfcignc on exactly the same position as MS FCIAddFile in every case
48 #include "wine/debug.h"
51 #ifdef WORDS_BIGENDIAN
52 #define fci_endian_ulong(x) RtlUlongByteSwap(x)
53 #define fci_endian_uword(x) RtlUshortByteSwap(x)
55 #define fci_endian_ulong(x) (x)
56 #define fci_endian_uword(x) (x)
60 #define fci_set_error(A,B,C) do { \
61 p_fci_internal->perf->erfOper = A; \
62 p_fci_internal->perf->erfType = B; \
63 p_fci_internal->perf->fError = C; \
64 if (B) SetLastError(B); } while(0)
68 cab_UBYTE signature
[4]; /* !CAB for unfinished cabinets else MSCF */
70 cab_ULONG cbCabinet
; /* size of the cabinet file in bytes*/
72 cab_ULONG coffFiles
; /* offset to first CFFILE section */
74 cab_UBYTE versionMinor
; /* 3 */
75 cab_UBYTE versionMajor
; /* 1 */
76 cab_UWORD cFolders
; /* number of CFFOLDER entries in the cabinet*/
77 cab_UWORD cFiles
; /* number of CFFILE entries in the cabinet*/
78 cab_UWORD flags
; /* 1=prev cab, 2=next cabinet, 4=reserved setions*/
79 cab_UWORD setID
; /* identification number of all cabinets in a set*/
80 cab_UWORD iCabinet
; /* number of the cabinet in a set */
81 /* additional area if "flags" were set*/
82 } CFHEADER
; /* minimum 36 bytes */
85 cab_ULONG coffCabStart
; /* offset to the folder's first CFDATA section */
86 cab_UWORD cCFData
; /* number of this folder's CFDATA sections */
87 cab_UWORD typeCompress
; /* compression type of data in CFDATA section*/
88 /* additional area if reserve flag was set */
89 } CFFOLDER
; /* minumum 8 bytes */
92 cab_ULONG cbFile
; /* size of the uncompressed file in bytes */
93 cab_ULONG uoffFolderStart
; /* offset of the uncompressed file in the folder */
94 cab_UWORD iFolder
; /* number of folder in the cabinet 0=first */
95 /* for special values see below this structure*/
96 cab_UWORD date
; /* last modification date*/
97 cab_UWORD time
; /* last modification time*/
98 cab_UWORD attribs
; /* DOS fat attributes and UTF indicator */
99 /* ... and a C string with the name of the file */
100 } CFFILE
; /* 16 bytes + name of file */
104 cab_ULONG csum
; /* checksum of this entry*/
105 cab_UWORD cbData
; /* number of compressed bytes */
106 cab_UWORD cbUncomp
; /* number of bytes when data is uncompressed */
107 /* optional reserved area */
108 /* compressed data */
112 /***********************************************************************
113 * FCICreate (CABINET.10)
115 * FCICreate is provided with several callbacks and
116 * returns a handle which can be used to create cabinet files.
119 * perf [IO] A pointer to an ERF structure. When FCICreate
120 * returns an error condition, error information may
121 * be found here as well as from GetLastError.
122 * pfnfiledest [I] A pointer to a function which is called when a file
123 * is placed. Only useful for subsequent cabinet files.
124 * pfnalloc [I] A pointer to a function which allocates ram. Uses
125 * the same interface as malloc.
126 * pfnfree [I] A pointer to a function which frees ram. Uses the
127 * same interface as free.
128 * pfnopen [I] A pointer to a function which opens a file. Uses
129 * the same interface as _open.
130 * pfnread [I] A pointer to a function which reads from a file into
131 * a caller-provided buffer. Uses the same interface
133 * pfnwrite [I] A pointer to a function which writes to a file from
134 * a caller-provided buffer. Uses the same interface
136 * pfnclose [I] A pointer to a function which closes a file handle.
137 * Uses the same interface as _close.
138 * pfnseek [I] A pointer to a function which seeks in a file.
139 * Uses the same interface as _lseek.
140 * pfndelete [I] A pointer to a function which deletes a file.
141 * pfnfcigtf [I] A pointer to a function which gets the name of a
143 * pccab [I] A pointer to an initialized CCAB structure.
144 * pv [I] A pointer to an application-defined notification
145 * function which will be passed to other FCI functions
149 * On success, returns an FCI handle of type HFCI.
150 * On failure, the NULL file handle is returned. Error
151 * info can be retrieved from perf.
157 HFCI __cdecl
FCICreate(
159 PFNFCIFILEPLACED pfnfiledest
,
160 PFNFCIALLOC pfnalloc
,
164 PFNFCIWRITE pfnwrite
,
165 PFNFCICLOSE pfnclose
,
167 PFNFCIDELETE pfndelete
,
168 PFNFCIGETTEMPFILE pfnfcigtf
,
174 PFCI_Int p_fci_internal
;
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
= ((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 memcpy(p_fci_internal
->szPrevCab
, pccab
->szCab
, CB_MAX_CABINET_NAME
);
237 memcpy(p_fci_internal
->szPrevDisk
, pccab
->szDisk
, CB_MAX_DISK_NAME
);
240 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFDATA1
,
242 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
246 if ( strlen(p_fci_internal
->szFileNameCFDATA1
) >= CB_MAX_FILENAME
) {
247 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
251 p_fci_internal
->handleCFDATA1
= PFCI_OPEN(hfci
,
252 p_fci_internal
->szFileNameCFDATA1
, 34050, 384, &err
, pv
);
253 if(p_fci_internal
->handleCFDATA1
==0){
254 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
257 /* TODO error checking of err */
259 /* array of all CFFILE in a folder */
260 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE1
,
262 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
266 if ( strlen(p_fci_internal
->szFileNameCFFILE1
) >= CB_MAX_FILENAME
) {
267 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
270 p_fci_internal
->handleCFFILE1
= PFCI_OPEN(hfci
,
271 p_fci_internal
->szFileNameCFFILE1
, 34050, 384, &err
, pv
);
272 if(p_fci_internal
->handleCFFILE1
==0){
273 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
276 /* TODO error checking of err */
278 /* CFDATA with checksum and ready to be copied into cabinet */
279 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFDATA2
,
281 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
285 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
286 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
289 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
290 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, pv
);
291 if(p_fci_internal
->handleCFDATA2
==0){
292 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
295 /* TODO error checking of err */
297 /* array of all CFFILE in a folder, ready to be copied into cabinet */
298 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
300 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
304 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
305 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
308 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
309 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, pv
);
310 if(p_fci_internal
->handleCFFILE2
==0){
311 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
314 /* TODO error checking of err */
316 /* array of all CFFILE in a folder, ready to be copied into cabinet */
317 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,
319 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
323 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
324 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
327 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
328 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, pv
);
329 if(p_fci_internal
->handleCFFOLDER
==0) {
330 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
334 /* TODO close and delete new files when return FALSE */
335 /* TODO error checking of err */
338 } /* end of FCICreate */
345 static BOOL
fci_flush_data_block (HFCI hfci
, int* err
,
346 PFNFCISTATUS pfnfcis
) {
348 /* attention no hfci checks!!! */
349 /* attention no checks if there is data available!!! */
351 CFDATA
* cfdata
=&data
;
353 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
354 UINT cbReserveCFData
=p_fci_internal
->pccab
->cbReserveCFData
;
357 /* TODO compress the data of p_fci_internal->data_in */
358 /* and write it to p_fci_internal->data_out */
359 memcpy(p_fci_internal
->data_out
, p_fci_internal
->data_in
,
360 p_fci_internal
->cdata_in
/* number of bytes to copy */);
362 cfdata
->csum
=0; /* checksum has to be set later */
363 /* TODO set realsize of compressed data */
364 cfdata
->cbData
= p_fci_internal
->cdata_in
;
365 cfdata
->cbUncomp
= p_fci_internal
->cdata_in
;
367 /* write cfdata to p_fci_internal->handleCFDATA1 */
368 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
369 cfdata
, sizeof(*cfdata
), err
, p_fci_internal
->pv
)
370 != sizeof(*cfdata
) ) {
371 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
374 /* TODO error handling of err */
376 p_fci_internal
->sizeFileCFDATA1
+= sizeof(*cfdata
);
378 /* add optional reserved area */
380 /* This allocation and freeing at each CFData block is a bit */
381 /* inefficent, but it's harder to forget about freeing the buffer :-). */
382 /* Reserved areas are used seldom besides that... */
383 if (cbReserveCFData
!=0) {
384 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFData
))) {
385 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
388 for(i
=0;i
<cbReserveCFData
;) {
391 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
392 reserved
, /* memory buffer */
393 cbReserveCFData
, /* number of bytes to copy */
394 err
, p_fci_internal
->pv
) != cbReserveCFData
) {
395 PFCI_FREE(hfci
, reserved
);
396 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
399 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
401 p_fci_internal
->sizeFileCFDATA1
+= cbReserveCFData
;
402 PFCI_FREE(hfci
, reserved
);
405 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
406 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
407 p_fci_internal
->data_out
, /* memory buffer */
408 cfdata
->cbData
, /* number of bytes to copy */
409 err
, p_fci_internal
->pv
) != cfdata
->cbData
) {
410 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
413 /* TODO error handling of err */
415 p_fci_internal
->sizeFileCFDATA1
+= cfdata
->cbData
;
417 /* reset the offset */
418 p_fci_internal
->cdata_in
= 0;
419 p_fci_internal
->cCompressedBytesInFolder
+= cfdata
->cbData
;
421 /* report status with pfnfcis about uncompressed and compressed file data */
422 if( (*pfnfcis
)(statusFile
, cfdata
->cbData
, cfdata
->cbUncomp
,
423 p_fci_internal
->pv
) == -1) {
424 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
428 ++(p_fci_internal
->cDataBlocks
);
431 } /* end of fci_flush_data_block */
437 static cab_ULONG
fci_get_checksum(const void *pv
, UINT cb
, CHECKSUM seed
)
448 while (cUlong
-- > 0) {
450 ul
|= (((cab_ULONG
)(*pb
++)) << 8);
451 ul
|= (((cab_ULONG
)(*pb
++)) << 16);
452 ul
|= (((cab_ULONG
)(*pb
++)) << 24);
460 ul
|= (((ULONG
)(*pb
++)) << 16);
462 ul
|= (((ULONG
)(*pb
++)) << 8);
471 } /* end of fci_get_checksum */
475 static BOOL
fci_flushfolder_copy_cfdata(HFCI hfci
, char* buffer
, UINT cbReserveCFData
,
476 PFNFCISTATUS pfnfcis
, int* err
, int handleCFDATA1new
,
477 cab_ULONG
* psizeFileCFDATA1new
, cab_ULONG
* payload
)
479 cab_ULONG read_result
;
480 CFDATA
* pcfdata
=(CFDATA
*)buffer
;
481 BOOL split_block
=FALSE
;
482 cab_UWORD savedUncomp
=0;
483 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
487 /* while not all CFDATAs have been copied do */
489 if( p_fci_internal
->fNextCab
) {
491 /* internal error should never happen */
492 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
496 /* REUSE the variable read_result */
497 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
498 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
499 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
504 if (p_fci_internal
->fPrevCab
) {
505 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
506 strlen(p_fci_internal
->szPrevDisk
)+1;
508 /* No more CFDATA fits into the cabinet under construction */
509 /* So don't try to store more data into it */
510 if( p_fci_internal
->fNextCab
&&
511 (p_fci_internal
->oldCCAB
.cb
<= sizeof(CFDATA
) + cbReserveCFData
+
512 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
513 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
516 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
518 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
519 strlen(p_fci_internal
->pccab
->szCab
)+1 +
520 strlen(p_fci_internal
->pccab
->szDisk
)+1
522 /* This may never be run for the first time the while loop is entered.
523 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
524 split_block
=TRUE
; /* In this case split_block is abused to store */
525 /* the complete data block into the next cabinet and not into the */
526 /* current one. Originally split_block is the indicator that a */
527 /* data block has been splitted across different cabinets. */
530 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
531 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/*file handle*/
532 buffer
, /* memory buffer */
533 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
534 err
, p_fci_internal
->pv
);
535 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
536 if (read_result
==0) break; /* ALL DATA has been copied */
538 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
541 /* TODO error handling of err */
543 /* REUSE buffer p_fci_internal->data_out !!! */
544 /* read data from p_fci_internal->handleCFDATA1 to */
545 /* p_fci_internal->data_out */
546 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
547 p_fci_internal
->data_out
/* memory buffer */,
548 pcfdata
->cbData
/* number of bytes to copy */,
549 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
551 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
554 /* TODO error handling of err */
556 /* if cabinet size is too large */
558 /* REUSE the variable read_result */
559 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
560 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
561 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
566 if (p_fci_internal
->fPrevCab
) {
567 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
568 strlen(p_fci_internal
->szPrevDisk
)+1;
571 /* Is cabinet with new CFDATA too large? Then data block has to be split */
572 if( p_fci_internal
->fNextCab
&&
573 (p_fci_internal
->oldCCAB
.cb
< sizeof(CFDATA
) + cbReserveCFData
+
575 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
576 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
579 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
580 sizeof(CFFOLDER
) + /* size of new CFFolder entry */
581 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
582 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* name of next cabinet */
583 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* name of next disk */
585 /* REUSE read_result to save the size of the compressed data */
586 read_result
=pcfdata
->cbData
;
587 /* Modify the size of the compressed data to store only a part of the */
588 /* data block into the current cabinet. This is done to prevent */
589 /* that the maximum cabinet size will be exceeded. The remainder */
590 /* will be stored into the next following cabinet. */
592 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
593 /* Substract everything except the size of the block of data */
594 /* to get it's actual size */
595 pcfdata
->cbData
= p_fci_internal
->oldCCAB
.cb
- (
596 sizeof(CFDATA
) + cbReserveCFData
+
597 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
598 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
600 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
601 sizeof(CFFOLDER
) + /* set size of new CFFolder entry */
602 p_fci_internal
->oldCCAB
.cbReserveCFFolder
);
603 /* substract the size of special header fields */
604 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
605 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
606 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
609 if (p_fci_internal
->fPrevCab
) {
610 pcfdata
->cbData
-=strlen(p_fci_internal
->szPrevCab
)+1 +
611 strlen(p_fci_internal
->szPrevDisk
)+1;
613 pcfdata
->cbData
-=strlen(p_fci_internal
->pccab
->szCab
)+1 +
614 strlen(p_fci_internal
->pccab
->szDisk
)+1;
616 savedUncomp
= pcfdata
->cbUncomp
;
617 pcfdata
->cbUncomp
= 0; /* on splitted blocks of data this is zero */
619 /* if split_block==TRUE then the above while loop won't */
620 /* be executed again */
621 split_block
=TRUE
; /* split_block is the indicator that */
622 /* a data block has been splitted across */
623 /* diffentent cabinets.*/
626 /* This should never happen !!! */
627 if (pcfdata
->cbData
==0) {
629 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
633 /* set little endian */
634 pcfdata
->cbData
=fci_endian_uword(pcfdata
->cbData
);
635 pcfdata
->cbUncomp
=fci_endian_uword(pcfdata
->cbUncomp
);
637 /* get checksum and write to cfdata.csum */
638 pcfdata
->csum
= fci_get_checksum( &(pcfdata
->cbData
),
639 sizeof(CFDATA
)+cbReserveCFData
-
640 sizeof(pcfdata
->csum
), fci_get_checksum( p_fci_internal
->data_out
, /*buffer*/
641 pcfdata
->cbData
, 0 ) );
643 /* set little endian */
644 pcfdata
->csum
=fci_endian_ulong(pcfdata
->csum
);
646 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
647 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
648 buffer
, /* memory buffer */
649 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
650 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
651 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
654 /* TODO error handling of err */
656 p_fci_internal
->sizeFileCFDATA2
+= sizeof(CFDATA
)+cbReserveCFData
;
658 /* reset little endian */
659 pcfdata
->cbData
=fci_endian_uword(pcfdata
->cbData
);
660 pcfdata
->cbUncomp
=fci_endian_uword(pcfdata
->cbUncomp
);
661 pcfdata
->csum
=fci_endian_ulong(pcfdata
->csum
);
663 /* write compressed data into p_fci_internal->handleCFDATA2 */
664 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
665 p_fci_internal
->data_out
, /* memory buffer */
666 pcfdata
->cbData
, /* number of bytes to copy */
667 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
668 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
671 /* TODO error handling of err */
673 p_fci_internal
->sizeFileCFDATA2
+= pcfdata
->cbData
;
674 ++(p_fci_internal
->cDataBlocks
);
675 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
676 (*payload
)+=pcfdata
->cbUncomp
;
677 /* if cabinet size too large and data has been split */
678 /* write the remainder of the data block to the new CFDATA1 file */
679 if( split_block
) { /* This does not include the */
680 /* abused one (just search for "abused" )*/
681 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
682 if (p_fci_internal
->fNextCab
==FALSE
) {
684 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
688 /* set cbData to the size of the remainder of the data block */
689 pcfdata
->cbData
= read_result
- pcfdata
->cbData
;
690 /*recover former value of cfdata.cbData; read_result will be the offset*/
691 read_result
-= pcfdata
->cbData
;
692 pcfdata
->cbUncomp
= savedUncomp
;
694 /* reset checksum, it will be computed later */
697 /* write cfdata WITHOUT checksum to handleCFDATA1new */
698 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
699 buffer
, /* memory buffer */
700 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
701 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
702 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
705 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
707 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
709 /* write compressed data into handleCFDATA1new */
710 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
711 p_fci_internal
->data_out
+ read_result
, /* memory buffer + offset */
712 /* to last part of split data */
713 pcfdata
->cbData
, /* number of bytes to copy */
714 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
715 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
718 /* TODO error handling of err */
720 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
722 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
723 /* the two blocks of the split data block have been written */
724 /* don't reset split_data yet, because it is still needed see below */
727 /* report status with pfnfcis about copied size of folder */
728 if( (*pfnfcis
)(statusFolder
,
729 p_fci_internal
->statusFolderCopied
, /*cfdata.cbData(+previous ones)*/
730 p_fci_internal
->statusFolderTotal
, /* total folder size */
731 p_fci_internal
->pv
) == -1) {
732 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
737 /* if cabinet size too large */
738 /* write the remaining data blocks to the new CFDATA1 file */
739 if ( split_block
) { /* This does include the */
740 /* abused one (just search for "abused" )*/
741 if (p_fci_internal
->fNextCab
==FALSE
) {
743 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
746 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
748 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
749 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/* handle */
750 buffer
, /* memory buffer */
751 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
752 err
, p_fci_internal
->pv
);
753 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
754 if (read_result
==0) break; /* ALL DATA has been copied */
756 fci_set_error(FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
759 /* TODO error handling of err */
761 /* REUSE buffer p_fci_internal->data_out !!! */
762 /* read data from p_fci_internal->handleCFDATA1 to */
763 /* p_fci_internal->data_out */
764 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
765 p_fci_internal
->data_out
/* memory buffer */,
766 pcfdata
->cbData
/* number of bytes to copy */,
767 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
769 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
772 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
774 /* write cfdata with checksum to handleCFDATA1new */
775 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
776 buffer
, /* memory buffer */
777 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
778 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
779 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
782 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
784 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
786 /* write compressed data into handleCFDATA1new */
787 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
788 p_fci_internal
->data_out
, /* memory buffer */
789 pcfdata
->cbData
, /* number of bytes to copy */
790 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
791 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
794 /* TODO error handling of err */
796 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
797 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
799 /* report status with pfnfcis about copied size of folder */
800 if( (*pfnfcis
)(statusFolder
,
801 p_fci_internal
->statusFolderCopied
,/*cfdata.cbData(+revious ones)*/
802 p_fci_internal
->statusFolderTotal
, /* total folder size */
803 p_fci_internal
->pv
) == -1) {
804 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
809 break; /* jump out of the next while loop */
810 } /* end of if( split_data ) */
813 } /* end of fci_flushfolder_copy_cfdata */
819 static BOOL
fci_flushfolder_copy_cffolder(HFCI hfci
, int* err
, UINT cbReserveCFFolder
,
820 cab_ULONG sizeFileCFDATA2old
)
825 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
827 /* absolute offset cannot be set yet, because the size of cabinet header, */
828 /* the number of CFFOLDERs and the number of CFFILEs may change. */
829 /* Instead the size of all previous data blocks will be stored and */
830 /* the remainder of the offset will be added when the cabinet will be */
831 /* flushed to disk. */
832 /* This is exactly the way the original CABINET.DLL works!!! */
833 cffolder
.coffCabStart
=sizeFileCFDATA2old
;
835 /* set the number of this folder's CFDATA sections */
836 cffolder
.cCFData
=p_fci_internal
->cDataBlocks
;
837 /* TODO set compression type */
838 cffolder
.typeCompress
= tcompTYPE_NONE
;
840 /* write cffolder to p_fci_internal->handleCFFOLDER */
841 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
842 &cffolder
, /* memory buffer */
843 sizeof(cffolder
), /* number of bytes to copy */
844 err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
845 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
848 /* TODO error handling of err */
850 p_fci_internal
->sizeFileCFFOLDER
+= sizeof(cffolder
);
852 /* add optional reserved area */
853 if (cbReserveCFFolder
!=0) {
854 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
855 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
858 for(i
=0;i
<cbReserveCFFolder
;) {
861 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
862 reserved
, /* memory buffer */
863 cbReserveCFFolder
, /* number of bytes to copy */
864 err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
865 PFCI_FREE(hfci
, reserved
);
866 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
869 /* TODO error handling of err */
871 p_fci_internal
->sizeFileCFFOLDER
+= cbReserveCFFolder
;
873 PFCI_FREE(hfci
, reserved
);
876 } /* end of fci_flushfolder_copy_cffolder */
882 static BOOL
fci_flushfolder_copy_cffile(HFCI hfci
, int* err
, int handleCFFILE1new
,
883 cab_ULONG
*psizeFileCFFILE1new
, cab_ULONG payload
)
886 cab_ULONG read_result
;
888 cab_ULONG sizeOfFiles
=0, sizeOfFilesPrev
;
889 BOOL may_be_prev
=TRUE
;
890 cab_ULONG cbFileRemainer
=0;
891 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
892 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
893 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,0,SEEK_SET
,err
,
894 p_fci_internal
->pv
) !=0 ) {
895 /* wrong return value */
896 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
899 /* TODO error handling of err */
901 /* while not all CFFILE structures have been copied do */
903 /* REUSE the variable read_result */
904 /* read data from p_fci_internal->handleCFFILE1 to cffile */
905 read_result
= PFCI_READ(hfci
,p_fci_internal
->handleCFFILE1
/* file handle */,
906 &cffile
, /* memory buffer */
907 sizeof(cffile
), /* number of bytes to copy */
908 err
, p_fci_internal
->pv
);
909 if( read_result
!= sizeof(cffile
) ) {
910 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
912 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
915 /* TODO error handling of err */
917 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
918 /* position. I don't know why so I'll just omit it */
920 /* read the filename from p_fci_internal->handleCFFILE1 */
921 /* REUSE the variable read_result AGAIN */
922 /* REUSE the memory buffer PFCI(hfci)->data_out */
923 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFILE1
/*file handle*/,
924 p_fci_internal
->data_out
, /* memory buffer */
925 CB_MAX_FILENAME
, /* number of bytes to copy */
926 err
, p_fci_internal
->pv
) <2) {
928 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
931 /* TODO maybe other checks of read_result */
932 /* TODO error handling of err */
935 if( strlen(p_fci_internal
->data_out
)>=CB_MAX_FILENAME
) {
936 /* set error code internal error */
937 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
941 seek
+=sizeof(cffile
) + strlen(p_fci_internal
->data_out
)+1;
943 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
944 /* i.e. seek to the next CFFILE area */
945 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,
946 seek
, /* seek position*/
950 /* wrong return value */
951 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
954 /* TODO error handling of err */
956 /* fnfilfnfildest: placed file on cabinet */
957 if (p_fci_internal
->fNextCab
||
958 p_fci_internal
->fGetNextCabInVain
) {
959 PFCI_FILEPLACED( hfci
, &(p_fci_internal
->oldCCAB
),
960 p_fci_internal
->data_out
, /* the file name*/
961 cffile
.cbFile
, /* file size */
962 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
966 PFCI_FILEPLACED( hfci
, p_fci_internal
->pccab
,
967 p_fci_internal
->data_out
, /* the file name*/
968 cffile
.cbFile
, /* file size */
969 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
974 /* Check special iFolder values */
975 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
976 p_fci_internal
->fPrevCab
==FALSE
) {
977 /* THIS MAY NEVER HAPPEN */
979 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
982 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
983 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
) {
984 /* THIS MAY NEVER HAPPEN */
986 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
989 if( may_be_prev
&& cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
992 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& may_be_prev
==FALSE
) {
993 /* THIS MAY NEVER HAPPEN */
995 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
998 if( cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
1002 sizeOfFilesPrev
=sizeOfFiles
;
1003 /* Set complete size of all processed files */
1004 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
1005 p_fci_internal
->cbFileRemainer
!=0
1007 sizeOfFiles
+=p_fci_internal
->cbFileRemainer
;
1008 p_fci_internal
->cbFileRemainer
=0;
1010 sizeOfFiles
+=cffile
.cbFile
;
1013 /* Check if spanned file fits into this cabinet folder */
1014 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& sizeOfFiles
>payload
) {
1015 cffile
.iFolder
=cffileCONTINUED_PREV_AND_NEXT
;
1018 /* Check if file doesn't fit into this cabinet folder */
1019 if( sizeOfFiles
>payload
) {
1020 cffile
.iFolder
=cffileCONTINUED_TO_NEXT
;
1023 /* set little endian */
1024 cffile
.cbFile
=fci_endian_ulong(cffile
.cbFile
);
1025 cffile
.uoffFolderStart
=fci_endian_ulong(cffile
.uoffFolderStart
);
1026 cffile
.iFolder
=fci_endian_uword(cffile
.iFolder
);
1027 cffile
.date
=fci_endian_uword(cffile
.date
);
1028 cffile
.time
=fci_endian_uword(cffile
.time
);
1029 cffile
.attribs
=fci_endian_uword(cffile
.attribs
);
1031 /* write cffile to p_fci_internal->handleCFFILE2 */
1032 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
1033 &cffile
, /* memory buffer */
1034 sizeof(cffile
), /* number of bytes to copy */
1035 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1036 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1039 /* TODO error handling of err */
1041 p_fci_internal
->sizeFileCFFILE2
+= sizeof(cffile
);
1043 /* reset little endian */
1044 cffile
.cbFile
=fci_endian_ulong(cffile
.cbFile
);
1045 cffile
.uoffFolderStart
=fci_endian_ulong(cffile
.uoffFolderStart
);
1046 cffile
.iFolder
=fci_endian_uword(cffile
.iFolder
);
1047 cffile
.date
=fci_endian_uword(cffile
.date
);
1048 cffile
.time
=fci_endian_uword(cffile
.time
);
1049 cffile
.attribs
=fci_endian_uword(cffile
.attribs
);
1051 /* write file name to p_fci_internal->handleCFFILE2 */
1052 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
1053 p_fci_internal
->data_out
, /* memory buffer */
1054 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1055 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1056 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1059 /* TODO error handling of err */
1061 p_fci_internal
->sizeFileCFFILE2
+= strlen(p_fci_internal
->data_out
)+1;
1063 /* cFiles is used to count all files of a cabinet */
1064 ++(p_fci_internal
->cFiles
);
1066 /* This is only true for files which will be written into the */
1067 /* next cabinet of the spanning folder */
1068 if( sizeOfFiles
>payload
) {
1070 /* Files which data will be partially written into the current cabinet */
1071 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
1072 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
1074 if( sizeOfFilesPrev
<=payload
) {
1075 /* The size of the uncompressed, data of a spanning file in a */
1077 cbFileRemainer
=sizeOfFiles
-payload
;
1079 cffile
.iFolder
=cffileCONTINUED_FROM_PREV
;
1084 /* write cffile into handleCFFILE1new */
1085 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1086 &cffile
, /* memory buffer */
1087 sizeof(cffile
), /* number of bytes to copy */
1088 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1089 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1092 /* TODO error handling of err */
1094 *psizeFileCFFILE1new
+= sizeof(cffile
);
1095 /* write name of file into handleCFFILE1new */
1096 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1097 p_fci_internal
->data_out
, /* memory buffer */
1098 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1099 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1100 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1103 /* TODO error handling of err */
1105 *psizeFileCFFILE1new
+= strlen(p_fci_internal
->data_out
)+1;
1108 } /* END OF while */
1109 p_fci_internal
->cbFileRemainer
=cbFileRemainer
;
1111 } /* end of fci_flushfolder_copy_cffile */
1116 static BOOL
fci_flush_folder(
1119 PFNFCIGETNEXTCABINET pfnfcignc
,
1120 PFNFCISTATUS pfnfcis
)
1123 int handleCFDATA1new
; /* handle for new temp file */
1124 char szFileNameCFDATA1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1125 int handleCFFILE1new
; /* handle for new temp file */
1126 char szFileNameCFFILE1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1127 UINT cbReserveCFData
, cbReserveCFFolder
;
1129 cab_ULONG sizeFileCFDATA1new
=0;
1130 cab_ULONG sizeFileCFFILE1new
=0;
1131 cab_ULONG sizeFileCFDATA2old
;
1133 cab_ULONG read_result
;
1134 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1137 if (!REALLY_IS_FCI(hfci
)) {
1138 SetLastError(ERROR_INVALID_HANDLE
);
1142 if ((!pfnfcignc
) || (!pfnfcis
)) {
1143 fci_set_error( FCIERR_NONE
, ERROR_BAD_ARGUMENTS
, TRUE
);
1147 if( p_fci_internal
->fGetNextCabInVain
&&
1148 p_fci_internal
->fNextCab
){
1149 /* internal error */
1150 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1154 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1155 /* this function will return TRUE */
1156 if( p_fci_internal
->sizeFileCFFILE1
== 0 ) {
1157 if ( p_fci_internal
->sizeFileCFDATA1
!= 0 ) {
1158 /* error handling */
1159 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1165 if (p_fci_internal
->data_in
==NULL
|| p_fci_internal
->data_out
==NULL
) {
1166 /* error handling */
1167 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1171 /* FCIFlushFolder has already been called... */
1172 if (p_fci_internal
->fSplitFolder
&& p_fci_internal
->sizeFileCFFILE2
!=0) {
1176 /* This can be set already, because it makes only a difference */
1177 /* when the current function exits with return FALSE */
1178 p_fci_internal
->fSplitFolder
=FALSE
;
1181 if( p_fci_internal
->fGetNextCabInVain
||
1182 p_fci_internal
->fNextCab
){
1183 cbReserveCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1184 cbReserveCFFolder
= p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1186 cbReserveCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1187 cbReserveCFFolder
= p_fci_internal
->pccab
->cbReserveCFFolder
;
1191 /* if there is data in p_fci_internal->data_in */
1192 if (p_fci_internal
->cdata_in
!=0) {
1194 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
1197 /* reset to get the number of data blocks of this folder which are */
1198 /* actually in this cabinet ( at least partially ) */
1199 p_fci_internal
->cDataBlocks
=0;
1201 if ( p_fci_internal
->fNextCab
||
1202 p_fci_internal
->fGetNextCabInVain
) {
1203 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
1204 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1205 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1206 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1207 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1211 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
+
1212 p_fci_internal
->pccab
->cbReserveCFFolder
;
1213 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1214 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1215 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1219 if (p_fci_internal
->fPrevCab
) {
1220 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1221 strlen(p_fci_internal
->szPrevDisk
)+1;
1223 if (p_fci_internal
->fNextCab
) {
1224 read_result
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1225 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1228 p_fci_internal
->statusFolderTotal
= sizeof(CFHEADER
)+read_result
+
1229 sizeof(CFFOLDER
) + p_fci_internal
->sizeFileCFFILE2
+
1230 p_fci_internal
->sizeFileCFDATA2
+ p_fci_internal
->sizeFileCFFILE1
+
1231 p_fci_internal
->sizeFileCFDATA1
+ p_fci_internal
->sizeFileCFFOLDER
;
1232 p_fci_internal
->statusFolderCopied
= 0;
1234 /* report status with pfnfcis about copied size of folder */
1235 if( (*pfnfcis
)(statusFolder
, p_fci_internal
->statusFolderCopied
,
1236 p_fci_internal
->statusFolderTotal
, /* TODO total folder size */
1237 p_fci_internal
->pv
) == -1) {
1238 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
1242 /* get a new temp file */
1243 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFDATA1new
,CB_MAX_FILENAME
)) {
1244 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
1248 if ( strlen(szFileNameCFDATA1new
) >= CB_MAX_FILENAME
) {
1249 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1252 handleCFDATA1new
= PFCI_OPEN(hfci
,szFileNameCFDATA1new
,34050,384,&err
,
1253 p_fci_internal
->pv
);
1254 if(handleCFDATA1new
==0){
1255 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
1258 /* TODO error handling of err */
1262 /* get a new temp file */
1263 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFFILE1new
,CB_MAX_FILENAME
)) {
1264 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
1265 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1266 /* TODO error handling of err */
1270 if ( strlen(szFileNameCFFILE1new
) >= CB_MAX_FILENAME
) {
1271 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1272 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1273 /* TODO error handling of err */
1276 handleCFFILE1new
= PFCI_OPEN(hfci
,szFileNameCFFILE1new
,34050,384,&err
,
1277 p_fci_internal
->pv
);
1278 if(handleCFFILE1new
==0){
1279 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
1282 /* TODO error handling of err */
1284 /* USE the variable read_result */
1285 if ( p_fci_internal
->fNextCab
||
1286 p_fci_internal
->fGetNextCabInVain
) {
1287 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1288 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1289 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1290 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1294 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
;
1295 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1296 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1297 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1301 if (p_fci_internal
->fPrevCab
) {
1302 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1303 strlen(p_fci_internal
->szPrevDisk
)+1;
1305 read_result
+= sizeof(CFHEADER
) + p_fci_internal
->sizeFileCFDATA2
+
1306 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
;
1308 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
1309 read_result
+= sizeof(CFFOLDER
)+p_fci_internal
->pccab
->cbReserveCFFolder
;
1312 /* Check if multiple cabinets have to be created. */
1314 /* Might be too much data for the maximum allowed cabinet size.*/
1315 /* When any further data will be added later, it might not */
1316 /* be possible to flush the cabinet, because there might */
1317 /* not be enough space to store the name of the following */
1318 /* cabinet and name of the corresponding disk. */
1319 /* So take care of this and get the name of the next cabinet */
1320 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
1321 p_fci_internal
->fNextCab
==FALSE
&&
1324 p_fci_internal
->pccab
->cb
< read_result
+
1325 p_fci_internal
->sizeFileCFDATA1
+
1326 p_fci_internal
->sizeFileCFFILE1
+
1327 CB_MAX_CABINET_NAME
+ /* next cabinet name */
1328 CB_MAX_DISK_NAME
/* next disk name */
1333 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
1334 /* increment cabinet index */
1335 ++(p_fci_internal
->pccab
->iCab
);
1336 /* get name of next cabinet */
1337 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
1338 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
1339 p_fci_internal
->estimatedCabinetSize
, /* estimated size of cab */
1340 p_fci_internal
->pv
)) {
1341 /* error handling */
1342 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
1343 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1344 /* TODO error handling of err */
1345 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1346 /* TODO error handling of err */
1350 /* Skip a few lines of code. This is caught by the next if. */
1351 p_fci_internal
->fGetNextCabInVain
=TRUE
;
1354 /* too much data for cabinet */
1355 if( (p_fci_internal
->fGetNextCabInVain
||
1356 p_fci_internal
->fNextCab
) &&
1359 p_fci_internal
->oldCCAB
.cb
< read_result
+
1360 p_fci_internal
->sizeFileCFDATA1
+
1361 p_fci_internal
->sizeFileCFFILE1
+
1362 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1363 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1367 p_fci_internal
->fGetNextCabInVain
=FALSE
;
1368 p_fci_internal
->fNextCab
=TRUE
;
1370 /* return FALSE if there is not enough space left*/
1371 /* this should never happen */
1372 if (p_fci_internal
->oldCCAB
.cb
<=
1373 p_fci_internal
->sizeFileCFFILE1
+
1375 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1376 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1379 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1380 /* TODO error handling of err */
1381 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1382 /* TODO error handling of err */
1384 /* close and delete p_fci_internal->handleCFFILE1 */
1385 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1386 /* TODO error handling of err */
1387 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1388 /* TODO error handling of err */
1393 /* the folder will be split across cabinets */
1394 p_fci_internal
->fSplitFolder
=TRUE
;
1397 /* this should never happen */
1398 if (p_fci_internal
->fNextCab
) {
1399 /* internal error */
1400 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1405 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1406 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA1
,0,SEEK_SET
,&err
,
1407 p_fci_internal
->pv
) !=0 ) {
1408 /* wrong return value */
1409 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1410 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1411 /* TODO error handling of err */
1412 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1413 /* TODO error handling of err */
1416 /* TODO error handling of err */
1418 /* save size of file CFDATA2 - required for the folder's offset to data */
1419 sizeFileCFDATA2old
= p_fci_internal
->sizeFileCFDATA2
;
1421 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFData
+sizeof(CFDATA
)))) {
1422 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
1423 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1424 /* TODO error handling of err */
1425 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1426 /* TODO error handling of err */
1430 if(!fci_flushfolder_copy_cfdata(hfci
, reserved
, cbReserveCFData
, pfnfcis
, &err
,
1431 handleCFDATA1new
, &sizeFileCFDATA1new
, &payload
1433 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1434 /* TODO error handling of err */
1435 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1436 /* TODO error handling of err */
1437 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1438 /* TODO error handling of err */
1439 PFCI_FREE(hfci
,reserved
);
1443 PFCI_FREE(hfci
,reserved
);
1445 if(!fci_flushfolder_copy_cffolder(hfci
, &err
, cbReserveCFFolder
,
1446 sizeFileCFDATA2old
)) {
1447 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1448 /* TODO error handling of err */
1449 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1450 /* TODO error handling of err */
1451 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1452 /* TODO error handling of err */
1456 if(!fci_flushfolder_copy_cffile(hfci
, &err
, handleCFFILE1new
,
1457 &sizeFileCFFILE1new
, payload
)) {
1458 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1459 /* TODO error handling of err */
1460 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1461 /* TODO error handling of err */
1462 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1463 /* TODO error handling of err */
1464 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1465 /* TODO error handling of err */
1469 /* close and delete p_fci_internal->handleCFDATA1 */
1470 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
1471 /* TODO error handling of err */
1472 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFDATA1
,&err
,p_fci_internal
->pv
);
1473 /* TODO error handling of err */
1475 /* put new CFDATA1 into hfci */
1476 memcpy(p_fci_internal
->szFileNameCFDATA1
,szFileNameCFDATA1new
,
1479 /* put CFDATA1 file handle */
1480 PFCI_INT(hfci
)->handleCFDATA1
= handleCFDATA1new
;
1482 PFCI_INT(hfci
)->sizeFileCFDATA1
= sizeFileCFDATA1new
;
1484 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1485 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFFILE1
,&err
,PFCI_INT(hfci
)->pv
);
1486 /* TODO error handling of err */
1487 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFFILE1
,&err
,p_fci_internal
->pv
);
1488 /* TODO error handling of err */
1490 /* put new CFFILE1 into hfci */
1491 memcpy(p_fci_internal
->szFileNameCFFILE1
,szFileNameCFFILE1new
,
1494 /* put CFFILE1 file handle */
1495 p_fci_internal
->handleCFFILE1
= handleCFFILE1new
;
1497 p_fci_internal
->sizeFileCFFILE1
= sizeFileCFFILE1new
;
1499 ++(p_fci_internal
->cFolders
);
1501 /* reset CFFolder specific information */
1502 p_fci_internal
->cDataBlocks
=0;
1503 p_fci_internal
->cCompressedBytesInFolder
=0;
1506 } /* end of fci_flush_folder */
1511 static BOOL
fci_flush_cabinet(
1514 PFNFCIGETNEXTCABINET pfnfcignc
,
1515 PFNFCISTATUS pfnfcis
)
1520 cab_UWORD cbCFHeader
;
1521 cab_UBYTE cbCFFolder
;
1525 cab_ULONG read_result
=0;
1526 int handleCABINET
; /* file handle for cabinet */
1527 char szFileNameCABINET
[CB_MAX_CAB_PATH
+CB_MAX_CABINET_NAME
];/* name buffer */
1528 UINT cbReserveCFHeader
, cbReserveCFFolder
, i
;
1530 BOOL returntrue
=FALSE
;
1531 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1533 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1535 /* when FCIFlushCabinet was or FCIAddFile hasn't been called */
1536 if( p_fci_internal
->sizeFileCFFILE1
==0 && fGetNextCab
) {
1540 if (!fci_flush_folder(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)){
1541 /* TODO set error */
1545 if(returntrue
) return TRUE
;
1547 if ( (p_fci_internal
->fSplitFolder
&& p_fci_internal
->fNextCab
==FALSE
)||
1548 (p_fci_internal
->sizeFileCFFOLDER
==0 &&
1549 (p_fci_internal
->sizeFileCFFILE1
!=0 ||
1550 p_fci_internal
->sizeFileCFFILE2
!=0 )
1554 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1558 if( p_fci_internal
->fNextCab
||
1559 p_fci_internal
->fGetNextCabInVain
) {
1560 cbReserveCFFolder
=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1561 cbReserveCFHeader
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1563 if (strlen(p_fci_internal
->oldCCAB
.szCabPath
)>=CB_MAX_CAB_PATH
||
1564 strlen(p_fci_internal
->oldCCAB
.szCab
)>=CB_MAX_CABINET_NAME
) {
1566 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1569 /* get the full name of the cabinet */
1570 memcpy(szFileNameCABINET
,p_fci_internal
->oldCCAB
.szCabPath
,
1572 memcpy(szFileNameCABINET
+strlen(szFileNameCABINET
),
1573 p_fci_internal
->oldCCAB
.szCab
, CB_MAX_CABINET_NAME
);
1575 cbReserveCFFolder
=p_fci_internal
->pccab
->cbReserveCFFolder
;
1576 cbReserveCFHeader
=p_fci_internal
->pccab
->cbReserveCFHeader
;
1578 if (strlen(p_fci_internal
->pccab
->szCabPath
)>=CB_MAX_CAB_PATH
||
1579 strlen(p_fci_internal
->pccab
->szCab
)>=CB_MAX_CABINET_NAME
) {
1581 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1584 /* get the full name of the cabinet */
1585 memcpy(szFileNameCABINET
,p_fci_internal
->pccab
->szCabPath
,
1587 memcpy(szFileNameCABINET
+strlen(szFileNameCABINET
),
1588 p_fci_internal
->pccab
->szCab
, CB_MAX_CABINET_NAME
);
1591 memcpy(cfheader
.signature
,"!CAB",4);
1592 cfheader
.reserved1
=0;
1593 cfheader
.cbCabinet
= /* size of the cabinet file in bytes */
1595 p_fci_internal
->sizeFileCFFOLDER
+
1596 p_fci_internal
->sizeFileCFFILE2
+
1597 p_fci_internal
->sizeFileCFDATA2
;
1599 if (p_fci_internal
->fPrevCab
) {
1600 cfheader
.cbCabinet
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1601 strlen(p_fci_internal
->szPrevDisk
)+1;
1603 if (p_fci_internal
->fNextCab
) {
1604 cfheader
.cbCabinet
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1605 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1607 if( p_fci_internal
->fNextCab
||
1608 p_fci_internal
->fGetNextCabInVain
) {
1609 cfheader
.cbCabinet
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1610 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1611 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1612 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1613 cfheader
.cbCabinet
+=4;
1616 cfheader
.cbCabinet
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1617 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1618 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1619 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1620 cfheader
.cbCabinet
+=4;
1624 if( ( ( p_fci_internal
->fNextCab
||
1625 p_fci_internal
->fGetNextCabInVain
) &&
1626 cfheader
.cbCabinet
> p_fci_internal
->oldCCAB
.cb
1628 ( ( p_fci_internal
->fNextCab
==FALSE
&&
1629 p_fci_internal
->fGetNextCabInVain
==FALSE
) &&
1630 cfheader
.cbCabinet
> p_fci_internal
->pccab
->cb
1634 fci_set_error( FCIERR_NONE
, ERROR_MORE_DATA
, TRUE
);
1639 cfheader
.reserved2
=0;
1640 cfheader
.coffFiles
= /* offset to first CFFILE section */
1641 cfheader
.cbCabinet
- p_fci_internal
->sizeFileCFFILE2
-
1642 p_fci_internal
->sizeFileCFDATA2
;
1644 cfheader
.reserved3
=0;
1645 cfheader
.versionMinor
=3;
1646 cfheader
.versionMajor
=1;
1647 /* number of CFFOLDER entries in the cabinet */
1648 cfheader
.cFolders
=p_fci_internal
->cFolders
;
1649 /* number of CFFILE entries in the cabinet */
1650 cfheader
.cFiles
=p_fci_internal
->cFiles
;
1651 cfheader
.flags
=0; /* 1=prev cab, 2=next cabinet, 4=reserved setions */
1653 if( p_fci_internal
->fPrevCab
) {
1654 cfheader
.flags
= cfheadPREV_CABINET
;
1657 if( p_fci_internal
->fNextCab
) {
1658 cfheader
.flags
|= cfheadNEXT_CABINET
;
1661 if( p_fci_internal
->fNextCab
||
1662 p_fci_internal
->fGetNextCabInVain
) {
1663 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1664 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1665 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1666 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1668 cfheader
.setID
= p_fci_internal
->oldCCAB
.setID
;
1669 cfheader
.iCabinet
= p_fci_internal
->oldCCAB
.iCab
-1;
1671 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1672 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1673 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1674 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1676 cfheader
.setID
= p_fci_internal
->pccab
->setID
;
1677 cfheader
.iCabinet
= p_fci_internal
->pccab
->iCab
-1;
1680 /* create the cabinet */
1681 handleCABINET
= PFCI_OPEN(hfci
, szFileNameCABINET
,
1682 33538, 384, &err
, p_fci_internal
->pv
);
1683 if(handleCABINET
==0){
1684 fci_set_error( FCIERR_CAB_FILE
, ERROR_OPEN_FAILED
, TRUE
);
1687 /* TODO error checking of err */
1689 /* set little endian */
1690 cfheader
.reserved1
=fci_endian_ulong(cfheader
.reserved1
);
1691 cfheader
.cbCabinet
=fci_endian_ulong(cfheader
.cbCabinet
);
1692 cfheader
.reserved2
=fci_endian_ulong(cfheader
.reserved2
);
1693 cfheader
.coffFiles
=fci_endian_ulong(cfheader
.coffFiles
);
1694 cfheader
.reserved3
=fci_endian_ulong(cfheader
.reserved3
);
1695 cfheader
.cFolders
=fci_endian_uword(cfheader
.cFolders
);
1696 cfheader
.cFiles
=fci_endian_uword(cfheader
.cFiles
);
1697 cfheader
.flags
=fci_endian_uword(cfheader
.flags
);
1698 cfheader
.setID
=fci_endian_uword(cfheader
.setID
);
1699 cfheader
.iCabinet
=fci_endian_uword(cfheader
.iCabinet
);
1701 /* write CFHEADER into cabinet file */
1702 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1703 &cfheader
, /* memory buffer */
1704 sizeof(cfheader
), /* number of bytes to copy */
1705 &err
, p_fci_internal
->pv
) != sizeof(cfheader
) ) {
1707 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1710 /* TODO error handling of err */
1712 /* reset little endian */
1713 cfheader
.reserved1
=fci_endian_ulong(cfheader
.reserved1
);
1714 cfheader
.cbCabinet
=fci_endian_ulong(cfheader
.cbCabinet
);
1715 cfheader
.reserved2
=fci_endian_ulong(cfheader
.reserved2
);
1716 cfheader
.coffFiles
=fci_endian_ulong(cfheader
.coffFiles
);
1717 cfheader
.reserved3
=fci_endian_ulong(cfheader
.reserved3
);
1718 cfheader
.cFolders
=fci_endian_uword(cfheader
.cFolders
);
1719 cfheader
.cFiles
=fci_endian_uword(cfheader
.cFiles
);
1720 cfheader
.flags
=fci_endian_uword(cfheader
.flags
);
1721 cfheader
.setID
=fci_endian_uword(cfheader
.setID
);
1722 cfheader
.iCabinet
=fci_endian_uword(cfheader
.iCabinet
);
1724 if( cfheader
.flags
& cfheadRESERVE_PRESENT
) {
1725 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1726 cfreserved
.cbCFHeader
= cbReserveCFHeader
;
1727 cfreserved
.cbCFFolder
= cbReserveCFFolder
;
1728 if( p_fci_internal
->fNextCab
||
1729 p_fci_internal
->fGetNextCabInVain
) {
1730 cfreserved
.cbCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1732 cfreserved
.cbCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1735 /* set little endian */
1736 cfreserved
.cbCFHeader
=fci_endian_uword(cfreserved
.cbCFHeader
);
1738 /* write reserved info into cabinet file */
1739 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1740 &cfreserved
, /* memory buffer */
1741 sizeof(cfreserved
), /* number of bytes to copy */
1742 &err
, p_fci_internal
->pv
) != sizeof(cfreserved
) ) {
1744 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1747 /* TODO error handling of err */
1749 /* reset little endian */
1750 cfreserved
.cbCFHeader
=fci_endian_uword(cfreserved
.cbCFHeader
);
1753 /* add optional reserved area */
1754 if (cbReserveCFHeader
!=0) {
1755 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFHeader
))) {
1756 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
1759 for(i
=0;i
<cbReserveCFHeader
;) {
1762 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1763 reserved
, /* memory buffer */
1764 cbReserveCFHeader
, /* number of bytes to copy */
1765 &err
, p_fci_internal
->pv
) != cbReserveCFHeader
) {
1766 PFCI_FREE(hfci
, reserved
);
1768 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1771 /* TODO error handling of err */
1772 PFCI_FREE(hfci
, reserved
);
1775 if( cfheader
.flags
& cfheadPREV_CABINET
) {
1776 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1777 p_fci_internal
->szPrevCab
, /* memory buffer */
1778 strlen(p_fci_internal
->szPrevCab
)+1, /* number of bytes to copy */
1779 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevCab
)+1 ) {
1781 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1784 /* TODO error handling of err */
1786 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1787 p_fci_internal
->szPrevDisk
, /* memory buffer */
1788 strlen(p_fci_internal
->szPrevDisk
)+1, /* number of bytes to copy */
1789 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevDisk
)+1 ) {
1791 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1794 /* TODO error handling of err */
1797 if( cfheader
.flags
& cfheadNEXT_CABINET
) {
1798 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1799 p_fci_internal
->pccab
->szCab
, /* memory buffer */
1800 strlen(p_fci_internal
->pccab
->szCab
)+1, /* number of bytes to copy */
1801 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szCab
)+1 ) {
1803 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1806 /* TODO error handling of err */
1808 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1809 p_fci_internal
->pccab
->szDisk
, /* memory buffer */
1810 strlen(p_fci_internal
->pccab
->szDisk
)+1, /* number of bytes to copy */
1811 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szDisk
)+1 ) {
1813 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1816 /* TODO error handling of err */
1819 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1820 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFOLDER
,
1821 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1822 /* wrong return value */
1823 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1826 /* TODO error handling of err */
1828 /* while not all CFFOLDER structures have been copied into the cabinet do */
1830 /* use the variable read_result */
1831 /* read cffolder of p_fci_internal->handleCFFOLDER */
1832 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* handle */
1833 &cffolder
, /* memory buffer */
1834 sizeof(cffolder
), /* number of bytes to copy */
1835 &err
, p_fci_internal
->pv
);
1836 if( read_result
!= sizeof(cffolder
) ) {
1837 if( read_result
== 0 ) break;/*ALL CFFOLDER structures have been copied*/
1839 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
1842 /* TODO error handling of err */
1844 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1845 cffolder
.coffCabStart
+=
1846 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
1848 if( p_fci_internal
->fNextCab
||
1849 p_fci_internal
->fGetNextCabInVain
) {
1850 cffolder
.coffCabStart
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1852 cffolder
.coffCabStart
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1855 if (p_fci_internal
->fPrevCab
) {
1856 cffolder
.coffCabStart
+= strlen(p_fci_internal
->szPrevCab
)+1 +
1857 strlen(p_fci_internal
->szPrevDisk
)+1;
1860 if (p_fci_internal
->fNextCab
) {
1861 cffolder
.coffCabStart
+= strlen(p_fci_internal
->oldCCAB
.szCab
)+1 +
1862 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1;
1865 if( p_fci_internal
->fNextCab
||
1866 p_fci_internal
->fGetNextCabInVain
) {
1867 cffolder
.coffCabStart
+= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1868 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1869 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1870 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1871 cffolder
.coffCabStart
+= 4;
1874 cffolder
.coffCabStart
+= p_fci_internal
->pccab
->cbReserveCFHeader
;
1875 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1876 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1877 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1878 cffolder
.coffCabStart
+= 4;
1882 /* set little endian */
1883 cffolder
.coffCabStart
=fci_endian_ulong(cffolder
.coffCabStart
);
1884 cffolder
.cCFData
=fci_endian_uword(cffolder
.cCFData
);
1885 cffolder
.typeCompress
=fci_endian_uword(cffolder
.typeCompress
);
1887 /* write cffolder to cabinet file */
1888 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1889 &cffolder
, /* memory buffer */
1890 sizeof(cffolder
), /* number of bytes to copy */
1891 &err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
1893 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1896 /* TODO error handling of err */
1898 /* reset little endian */
1899 cffolder
.coffCabStart
=fci_endian_ulong(cffolder
.coffCabStart
);
1900 cffolder
.cCFData
=fci_endian_uword(cffolder
.cCFData
);
1901 cffolder
.typeCompress
=fci_endian_uword(cffolder
.typeCompress
);
1903 /* add optional reserved area */
1905 /* This allocation and freeing at each CFFolder block is a bit */
1906 /* inefficent, but it's harder to forget about freeing the buffer :-). */
1907 /* Reserved areas are used seldom besides that... */
1908 if (cbReserveCFFolder
!=0) {
1909 if(!(reserved
= PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
1910 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
1914 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
1915 reserved
, /* memory buffer */
1916 cbReserveCFFolder
, /* number of bytes to copy */
1917 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1918 PFCI_FREE(hfci
, reserved
);
1920 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
1923 /* TODO error handling of err */
1925 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1926 reserved
, /* memory buffer */
1927 cbReserveCFFolder
, /* number of bytes to copy */
1928 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1929 PFCI_FREE(hfci
, reserved
);
1931 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1934 /* TODO error handling of err */
1936 PFCI_FREE(hfci
, reserved
);
1939 } /* END OF while */
1941 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1942 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE2
,
1943 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1944 /* wrong return value */
1945 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1948 /* TODO error handling of err */
1950 /* while not all CFFILE structures have been copied to the cabinet do */
1952 /* REUSE the variable read_result */
1953 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1954 /* read a block from p_fci_internal->handleCFFILE2 */
1955 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFILE2
/* handle */,
1956 p_fci_internal
->data_out
, /* memory buffer */
1957 CB_MAX_CHUNK
, /* number of bytes to copy */
1958 &err
, p_fci_internal
->pv
);
1959 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
1960 /* TODO error handling of err */
1962 /* write the block to the cabinet file */
1963 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1964 p_fci_internal
->data_out
, /* memory buffer */
1965 read_result
, /* number of bytes to copy */
1966 &err
, p_fci_internal
->pv
) != read_result
) {
1968 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1971 /* TODO error handling of err */
1973 if (p_fci_internal
->fSplitFolder
==FALSE
) {
1974 p_fci_internal
->statusFolderCopied
= 0;
1975 /* TODO TEST THIS further */
1976 p_fci_internal
->statusFolderTotal
= p_fci_internal
->sizeFileCFDATA2
+
1977 p_fci_internal
->sizeFileCFFILE2
;
1979 p_fci_internal
->statusFolderCopied
+= read_result
;
1981 /* report status with pfnfcis about copied size of folder */
1982 if( (*pfnfcis
)(statusFolder
,
1983 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
1984 p_fci_internal
->statusFolderTotal
, /* total size of folder */
1985 p_fci_internal
->pv
) == -1) {
1986 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
1990 } /* END OF while */
1992 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1993 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA2
,
1994 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1995 /* wrong return value */
1996 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1999 /* TODO error handling of err */
2001 /* reset the number of folders for the next cabinet */
2002 p_fci_internal
->cFolders
=0;
2003 /* reset the number of files for the next cabinet */
2004 p_fci_internal
->cFiles
=0;
2006 /* while not all CFDATA structures have been copied to the cabinet do */
2008 /* REUSE the variable read_result AGAIN */
2009 /* REUSE the buffer p_fci_internal->data_out AGAIN */
2010 /* read a block from p_fci_internal->handleCFDATA2 */
2011 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA2
/* handle */,
2012 p_fci_internal
->data_out
, /* memory buffer */
2013 CB_MAX_CHUNK
, /* number of bytes to copy */
2014 &err
, p_fci_internal
->pv
);
2015 if( read_result
== 0 ) break; /* ALL CFDATA structures have been copied */
2016 /* TODO error handling of err */
2018 /* write the block to the cabinet file */
2019 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
2020 p_fci_internal
->data_out
, /* memory buffer */
2021 read_result
, /* number of bytes to copy */
2022 &err
, p_fci_internal
->pv
) != read_result
) {
2024 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2027 /* TODO error handling of err */
2029 p_fci_internal
->statusFolderCopied
+= read_result
;
2030 /* report status with pfnfcis about copied size of folder */
2031 if( (*pfnfcis
)(statusFolder
,
2032 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
2033 p_fci_internal
->statusFolderTotal
, /* total size of folder */
2034 p_fci_internal
->pv
) == -1) {
2035 /* set error code and abort */
2036 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
2039 } /* END OF while */
2041 /* set seek of the cabinet file to 0 */
2042 if( PFCI_SEEK(hfci
, handleCABINET
,
2043 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
2044 /* wrong return value */
2045 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
2048 /* TODO error handling of err */
2050 /* write the signature "MSCF" into the cabinet file */
2051 memcpy( cfheader
.signature
, "MSCF", 4 );
2052 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
2053 &cfheader
, /* memory buffer */
2054 4, /* number of bytes to copy */
2055 &err
, p_fci_internal
->pv
) != 4 ) {
2057 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2060 /* TODO error handling of err */
2062 /* close the cabinet file */
2063 PFCI_CLOSE(hfci
,handleCABINET
,&err
,p_fci_internal
->pv
);
2064 /* TODO error handling of err */
2067 /* COPIED FROM FCIDestroy */
2069 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
2070 /* TODO error handling of err */
2071 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
2072 p_fci_internal
->pv
);
2073 /* TODO error handling of err */
2074 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
2075 /* TODO error handling of err */
2076 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
2077 p_fci_internal
->pv
);
2078 /* TODO error handling of err */
2079 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
2080 /* TODO error handling of err */
2081 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
2082 p_fci_internal
->pv
);
2083 /* TODO error handling of err */
2085 /* END OF copied from FCIDestroy */
2087 /* get 3 temporary files and open them */
2088 /* write names and handles to hfci */
2091 p_fci_internal
->sizeFileCFDATA2
= 0;
2092 p_fci_internal
->sizeFileCFFILE2
= 0;
2093 p_fci_internal
->sizeFileCFFOLDER
= 0;
2095 /* COPIED FROM FCICreate */
2097 /* CFDATA with checksum and ready to be copied into cabinet */
2098 if( !PFCI_GETTEMPFILE(hfci
, p_fci_internal
->szFileNameCFDATA2
,
2100 /* error handling */
2101 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2105 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
2106 /* set error code and abort */
2107 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2110 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
2111 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, p_fci_internal
->pv
);
2113 if(p_fci_internal
->handleCFDATA2
==0){
2114 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
2117 /* TODO error checking of err */
2119 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2120 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
2122 /* error handling */
2123 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2127 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
2128 /* set error code and abort */
2129 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2132 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
2133 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, p_fci_internal
->pv
);
2135 if(p_fci_internal
->handleCFFILE2
==0){
2136 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
2139 /* TODO error checking of err */
2141 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2142 if (!PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,CB_MAX_FILENAME
)) {
2143 /* error handling */
2144 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2148 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
2149 /* set error code and abort */
2150 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2153 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
2154 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, p_fci_internal
->pv
);
2156 if(p_fci_internal
->handleCFFOLDER
==0){
2157 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
2160 /* TODO error checking of err */
2162 /* END OF copied from FCICreate */
2165 /* TODO close and delete new files when return FALSE */
2168 /* report status with pfnfcis about copied size of folder */
2169 (*pfnfcis
)(statusCabinet
,
2170 p_fci_internal
->estimatedCabinetSize
, /* estimated cabinet file size */
2171 cfheader
.cbCabinet
/* real cabinet file size */, p_fci_internal
->pv
);
2173 p_fci_internal
->fPrevCab
=TRUE
;
2174 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2175 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2177 if (p_fci_internal
->fNextCab
) {
2178 p_fci_internal
->fNextCab
=FALSE
;
2180 if (p_fci_internal
->sizeFileCFFILE1
==0 && p_fci_internal
->sizeFileCFDATA1
!=0) {
2181 /* THIS CAN NEVER HAPPEN */
2182 /* set error code */
2183 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2187 /* COPIED FROM FCIAddFile and modified */
2189 /* REUSE the variable read_result */
2190 if (p_fci_internal
->fGetNextCabInVain
) {
2191 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
2192 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2193 read_result
+=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2195 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2196 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2197 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2201 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
;
2202 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2203 read_result
+=p_fci_internal
->pccab
->cbReserveCFFolder
;
2205 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2206 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2207 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2211 if ( p_fci_internal
->fPrevCab
) {
2212 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2213 strlen(p_fci_internal
->szPrevDisk
)+1;
2215 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2216 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2217 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2219 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2221 if( p_fci_internal
->fNewPrevious
) {
2222 memcpy(p_fci_internal
->szPrevCab
, p_fci_internal
->oldCCAB
.szCab
,
2223 CB_MAX_CABINET_NAME
);
2224 memcpy(p_fci_internal
->szPrevDisk
, p_fci_internal
->oldCCAB
.szDisk
,
2226 p_fci_internal
->fNewPrevious
=FALSE
;
2229 /* too much data for the maximum size of a cabinet */
2230 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2231 p_fci_internal
->pccab
->cb
< read_result
) {
2232 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2235 /* Might be too much data for the maximum size of a cabinet.*/
2236 /* When any further data will be added later, it might not */
2237 /* be possible to flush the cabinet, because there might */
2238 /* not be enough space to store the name of the following */
2239 /* cabinet and name of the corresponding disk. */
2240 /* So take care of this and get the name of the next cabinet */
2241 if (p_fci_internal
->fGetNextCabInVain
==FALSE
&& (
2242 p_fci_internal
->pccab
->cb
< read_result
+
2243 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2246 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2247 /* increment cabinet index */
2248 ++(p_fci_internal
->pccab
->iCab
);
2249 /* get name of next cabinet */
2250 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
2251 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
2252 p_fci_internal
->estimatedCabinetSize
, /* estimated size of cab */
2253 p_fci_internal
->pv
)) {
2254 /* error handling */
2255 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2258 /* Skip a few lines of code. This is caught by the next if. */
2259 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2262 /* too much data for cabinet */
2263 if (p_fci_internal
->fGetNextCabInVain
&& (
2264 p_fci_internal
->oldCCAB
.cb
< read_result
+
2265 strlen(p_fci_internal
->oldCCAB
.szCab
)+1+
2266 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1
2268 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2269 p_fci_internal
->fNextCab
=TRUE
;
2270 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2273 /* if the FolderThreshold has been reached flush the folder automatically */
2274 if( p_fci_internal
->fGetNextCabInVain
) {
2275 if( p_fci_internal
->cCompressedBytesInFolder
>=
2276 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2277 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2280 if( p_fci_internal
->cCompressedBytesInFolder
>=
2281 p_fci_internal
->pccab
->cbFolderThresh
) {
2282 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2286 /* END OF COPIED FROM FCIAddFile and modified */
2288 if( p_fci_internal
->sizeFileCFFILE1
>0 ) {
2289 if( !FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
) ) return FALSE
;
2290 p_fci_internal
->fNewPrevious
=TRUE
;
2293 p_fci_internal
->fNewPrevious
=FALSE
;
2294 if( p_fci_internal
->sizeFileCFFILE1
>0 || p_fci_internal
->sizeFileCFDATA1
) {
2295 /* THIS MAY NEVER HAPPEN */
2296 /* set error structures */
2297 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2303 } /* end of fci_flush_cabinet */
2309 /***********************************************************************
2310 * FCIAddFile (CABINET.11)
2312 * FCIAddFile adds a file to the to be created cabinet file
2315 * hfci [I] An HFCI from FCICreate
2316 * pszSourceFile [I] A pointer to a C string which contains the name and
2317 * location of the file which will be added to the cabinet
2318 * pszFileName [I] A pointer to a C string which contains the name under
2319 * which the file will be stored in the cabinet
2320 * fExecute [I] A boolean value which indicates if the file should be
2321 * executed after extraction of self extracting
2323 * pfnfcignc [I] A pointer to a function which gets information about
2325 * pfnfcis [IO] A pointer to a function which will report status
2326 * information about the compression process
2327 * pfnfcioi [I] A pointer to a function which reports file attributes
2328 * and time and date information
2329 * typeCompress [I] Compression type
2332 * On success, returns TRUE
2333 * On failure, returns FALSE
2339 BOOL __cdecl
FCIAddFile(
2341 char *pszSourceFile
,
2344 PFNFCIGETNEXTCABINET pfnfcignc
,
2345 PFNFCISTATUS pfnfcis
,
2346 PFNFCIGETOPENINFO pfnfcigoi
,
2351 cab_ULONG read_result
;
2353 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2356 if (!REALLY_IS_FCI(hfci
)) {
2357 SetLastError(ERROR_INVALID_HANDLE
);
2361 if ((!pszSourceFile
) || (!pszFileName
) || (!pfnfcignc
) || (!pfnfcis
) ||
2362 (!pfnfcigoi
) || strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2363 fci_set_error( FCIERR_NONE
, ERROR_BAD_ARGUMENTS
, TRUE
);
2367 /* TODO check if pszSourceFile??? */
2369 if(p_fci_internal
->fGetNextCabInVain
&& p_fci_internal
->fNextCab
) {
2370 /* internal error */
2371 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2375 if(p_fci_internal
->fNextCab
) {
2376 /* internal error */
2377 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2381 cffile
.cbFile
=0; /* size of the to be added file*/
2382 /* offset of the uncompressed file in the folder */
2383 cffile
.uoffFolderStart
=p_fci_internal
->cDataBlocks
*CAB_BLOCKMAX
+ p_fci_internal
->cdata_in
;
2384 /* number of folder in the cabinet or special 0=first */
2385 cffile
.iFolder
= p_fci_internal
->cFolders
;
2387 /* allocation of memory */
2388 if (p_fci_internal
->data_in
==NULL
) {
2389 if (p_fci_internal
->cdata_in
!=0) {
2390 /* error handling */
2391 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2394 if (p_fci_internal
->data_out
!=NULL
) {
2395 /* error handling */
2396 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2399 if(!(p_fci_internal
->data_in
= (char*)PFCI_ALLOC(hfci
,CB_MAX_CHUNK
))) {
2400 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
2403 if (p_fci_internal
->data_out
==NULL
) {
2404 if(!(p_fci_internal
->data_out
= PFCI_ALLOC(hfci
, 2 * CB_MAX_CHUNK
))){
2405 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
2411 if (p_fci_internal
->data_out
==NULL
) {
2412 PFCI_FREE(hfci
,p_fci_internal
->data_in
);
2413 /* error handling */
2414 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2418 /* get information about the file */
2419 file_handle
=(*pfnfcigoi
)(pszSourceFile
, &(cffile
.date
), &(cffile
.time
),
2420 &(cffile
.attribs
), &err
, p_fci_internal
->pv
);
2421 /* check file_handle */
2423 fci_set_error( FCIERR_OPEN_SRC
, ERROR_OPEN_FAILED
, TRUE
);
2425 /* TODO error handling of err */
2427 if (fExecute
) { cffile
.attribs
|= _A_EXEC
; }
2429 /* REUSE the variable read_result */
2430 if (p_fci_internal
->fGetNextCabInVain
) {
2431 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2432 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2433 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2434 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2435 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2439 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2440 p_fci_internal
->pccab
->cbReserveCFFolder
;
2441 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2442 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2443 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2447 if ( p_fci_internal
->fPrevCab
) {
2448 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2449 strlen(p_fci_internal
->szPrevDisk
)+1;
2451 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2452 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2453 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2456 read_result
+= sizeof(CFFILE
) + strlen(pszFileName
)+1 +
2457 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2458 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2460 sizeof(CFFOLDER
); /* size of new CFFolder entry */
2462 /* Might be too much data for the maximum size of a cabinet.*/
2463 /* When any further data will be added later, it might not */
2464 /* be possible to flush the cabinet, because there might */
2465 /* not be enough space to store the name of the following */
2466 /* cabinet and name of the corresponding disk. */
2467 /* So take care of this and get the name of the next cabinet */
2468 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2469 p_fci_internal
->fNextCab
==FALSE
&&
2470 ( p_fci_internal
->pccab
->cb
< read_result
+
2471 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2475 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2476 /* increment cabinet index */
2477 ++(p_fci_internal
->pccab
->iCab
);
2478 /* get name of next cabinet */
2479 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
2480 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
2481 p_fci_internal
->estimatedCabinetSize
, /* estimated size of cab */
2482 p_fci_internal
->pv
)) {
2483 /* error handling */
2484 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2487 /* Skip a few lines of code. This is caught by the next if. */
2488 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2491 if( p_fci_internal
->fGetNextCabInVain
&&
2492 p_fci_internal
->fNextCab
2494 /* THIS CAN NEVER HAPPEN */
2495 /* set error code */
2496 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2500 /* too much data for cabinet */
2501 if( p_fci_internal
->fGetNextCabInVain
&&
2503 p_fci_internal
->oldCCAB
.cb
< read_result
+
2504 strlen(p_fci_internal
->pccab
->szCab
)+1+
2505 strlen(p_fci_internal
->pccab
->szDisk
)+1
2507 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2508 p_fci_internal
->fNextCab
=TRUE
;
2509 if(!fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
)) return FALSE
;
2512 if( p_fci_internal
->fNextCab
) {
2513 /* THIS MAY NEVER HAPPEN */
2514 /* set error code */
2515 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2519 /* read the contents of the file blockwise */
2521 if (p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2522 /* internal error */
2523 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2527 read_result
= PFCI_READ(hfci
, file_handle
/* file handle */,
2528 (p_fci_internal
->data_in
+ p_fci_internal
->cdata_in
) /* memory buffer */,
2529 (CAB_BLOCKMAX
- p_fci_internal
->cdata_in
) /* number of bytes to copy */,
2530 &err
, p_fci_internal
->pv
);
2531 /* TODO error handling of err */
2533 if( read_result
==0 ) break;
2535 /* increment the block size */
2536 p_fci_internal
->cdata_in
+= read_result
;
2538 /* increment the file size */
2539 cffile
.cbFile
+= read_result
;
2541 if ( p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2542 /* report internal error */
2543 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2546 /* write a whole block */
2547 if ( p_fci_internal
->cdata_in
== CAB_BLOCKMAX
) {
2549 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
2553 /* close the file from FCIAddFile */
2554 PFCI_CLOSE(hfci
,file_handle
,&err
,p_fci_internal
->pv
);
2555 /* TODO error handling of err */
2557 /* write cffile to p_fci_internal->handleCFFILE1 */
2558 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2559 &cffile
, sizeof(cffile
),&err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
2561 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2564 /* TODO error handling of err */
2566 p_fci_internal
->sizeFileCFFILE1
+= sizeof(cffile
);
2568 /* append the name of file */
2569 if (strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2571 /* set error code */
2572 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2575 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2576 pszFileName
, strlen(pszFileName
)+1, &err
, p_fci_internal
->pv
)
2577 != strlen(pszFileName
)+1 ) {
2579 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2582 /* TODO error handling of err */
2584 p_fci_internal
->sizeFileCFFILE1
+= strlen(pszFileName
)+1;
2586 /* REUSE the variable read_result */
2587 if (p_fci_internal
->fGetNextCabInVain
||
2588 p_fci_internal
->fNextCab
2590 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2591 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2592 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2593 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2594 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2598 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2599 p_fci_internal
->pccab
->cbReserveCFFolder
;
2600 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2601 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2602 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2606 if ( p_fci_internal
->fPrevCab
) {
2607 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2608 strlen(p_fci_internal
->szPrevDisk
)+1;
2610 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2611 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2612 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2614 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2615 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2616 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2618 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2620 /* too much data for the maximum size of a cabinet */
2621 /* (ignoring the unflushed data block) */
2622 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2623 p_fci_internal
->fNextCab
==FALSE
&& /* this is always the case */
2624 p_fci_internal
->pccab
->cb
< read_result
) {
2625 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2628 /* Might be too much data for the maximum size of a cabinet.*/
2629 /* When any further data will be added later, it might not */
2630 /* be possible to flush the cabinet, because there might */
2631 /* not be enough space to store the name of the following */
2632 /* cabinet and name of the corresponding disk. */
2633 /* So take care of this and get the name of the next cabinet */
2634 /* (ignoring the unflushed data block) */
2635 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2636 p_fci_internal
->fNextCab
==FALSE
&&
2637 ( p_fci_internal
->pccab
->cb
< read_result
+
2638 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2642 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2643 /* increment cabinet index */
2644 ++(p_fci_internal
->pccab
->iCab
);
2645 /* get name of next cabinet */
2646 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
2647 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
2648 p_fci_internal
->estimatedCabinetSize
,/* estimated size of cab */
2649 p_fci_internal
->pv
)) {
2650 /* error handling */
2651 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2654 /* Skip a few lines of code. This is caught by the next if. */
2655 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2658 if( p_fci_internal
->fGetNextCabInVain
&&
2659 p_fci_internal
->fNextCab
2661 /* THIS CAN NEVER HAPPEN */
2662 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2666 /* too much data for cabinet */
2667 if( (p_fci_internal
->fGetNextCabInVain
||
2668 p_fci_internal
->fNextCab
) && (
2669 p_fci_internal
->oldCCAB
.cb
< read_result
+
2670 strlen(p_fci_internal
->pccab
->szCab
)+1+
2671 strlen(p_fci_internal
->pccab
->szDisk
)+1
2674 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2675 p_fci_internal
->fNextCab
=TRUE
;
2676 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2679 if( p_fci_internal
->fNextCab
) {
2680 /* THIS MAY NEVER HAPPEN */
2681 /* set error code */
2682 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2686 /* if the FolderThreshold has been reached flush the folder automatically */
2687 if( p_fci_internal
->fGetNextCabInVain
) {
2688 if( p_fci_internal
->cCompressedBytesInFolder
>=
2689 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2690 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2693 if( p_fci_internal
->cCompressedBytesInFolder
>=
2694 p_fci_internal
->pccab
->cbFolderThresh
) {
2695 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2700 } /* end of FCIAddFile */
2706 /***********************************************************************
2707 * FCIFlushFolder (CABINET.12)
2709 * FCIFlushFolder completes the CFFolder structure under construction.
2711 * All further data which is added by FCIAddFile will be associateed to
2712 * the next CFFolder structure.
2714 * FCIFlushFolder will be called by FCIAddFile automatically if the
2715 * threshold (stored in the member cbFolderThresh of the CCAB structure
2716 * pccab passed to FCICreate) is exceeded.
2718 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2719 * any data will be written into the cabinet file.
2722 * hfci [I] An HFCI from FCICreate
2723 * pfnfcignc [I] A pointer to a function which gets information about
2725 * pfnfcis [IO] A pointer to a function which will report status
2726 * information about the compression process
2729 * On success, returns TRUE
2730 * On failure, returns FALSE
2736 BOOL __cdecl
FCIFlushFolder(
2738 PFNFCIGETNEXTCABINET pfnfcignc
,
2739 PFNFCISTATUS pfnfcis
)
2741 return fci_flush_folder(hfci
,FALSE
,pfnfcignc
,pfnfcis
);
2742 } /* end of FCIFlushFolder */
2746 /***********************************************************************
2747 * FCIFlushCabinet (CABINET.13)
2749 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2750 * into the cabinet file. If the maximum cabinet size (stored in the
2751 * member cb of the CCAB structure pccab passed to FCICreate) has been
2752 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2753 * The remaining data still has to be flushed manually by calling
2756 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2757 * NOT be called again. Then hfci has to be released by FCIDestroy.
2760 * hfci [I] An HFCI from FCICreate
2761 * fGetNextCab [I] Whether you want to add additional files to a
2762 * cabinet set (TRUE) or whether you want to
2763 * finalize it (FALSE)
2764 * pfnfcignc [I] A pointer to a function which gets information about
2766 * pfnfcis [IO] A pointer to a function which will report status
2767 * information about the compression process
2770 * On success, returns TRUE
2771 * On failure, returns FALSE
2777 BOOL __cdecl
FCIFlushCabinet(
2780 PFNFCIGETNEXTCABINET pfnfcignc
,
2781 PFNFCISTATUS pfnfcis
)
2783 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2785 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2787 while( p_fci_internal
->sizeFileCFFILE1
>0 ||
2788 p_fci_internal
->sizeFileCFFILE2
>0 ) {
2789 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2793 } /* end of FCIFlushCabinet */
2796 /***********************************************************************
2797 * FCIDestroy (CABINET.14)
2799 * Frees a handle created by FCICreate.
2800 * Only reason for failure would be an invalid handle.
2803 * hfci [I] The HFCI to free
2809 BOOL __cdecl
FCIDestroy(HFCI hfci
)
2812 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2813 if (REALLY_IS_FCI(hfci
)) {
2815 /* before hfci can be removed all temporary files must be closed */
2817 p_fci_internal
->FCI_Intmagic
= 0;
2819 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
2820 /* TODO error handling of err */
2821 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA1
, &err
,
2822 p_fci_internal
->pv
);
2823 /* TODO error handling of err */
2824 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE1
,&err
,p_fci_internal
->pv
);
2825 /* TODO error handling of err */
2826 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE1
, &err
,
2827 p_fci_internal
->pv
);
2828 /* TODO error handling of err */
2829 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
2830 /* TODO error handling of err */
2831 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
2832 p_fci_internal
->pv
);
2833 /* TODO error handling of err */
2834 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
2835 /* TODO error handling of err */
2836 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
2837 p_fci_internal
->pv
);
2838 /* TODO error handling of err */
2839 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
2840 /* TODO error handling of err */
2841 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
2842 p_fci_internal
->pv
);
2843 /* TODO error handling of err */
2845 /* data in and out buffers have to be removed */
2846 if (p_fci_internal
->data_in
!=NULL
)
2847 PFCI_FREE(hfci
, p_fci_internal
->data_in
);
2848 if (p_fci_internal
->data_out
!=NULL
)
2849 PFCI_FREE(hfci
, p_fci_internal
->data_out
);
2851 /* hfci can now be removed */
2852 PFCI_FREE(hfci
, hfci
);
2855 SetLastError(ERROR_INVALID_HANDLE
);
2859 } /* end of FCIDestroy */