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)
67 WINE_DEFAULT_DEBUG_CHANNEL(cabinet
);
70 cab_UBYTE signature
[4]; /* !CAB for unfinished cabinets else MSCF */
72 cab_ULONG cbCabinet
; /* size of the cabinet file in bytes*/
74 cab_ULONG coffFiles
; /* offset to first CFFILE section */
76 cab_UBYTE versionMinor
; /* 3 */
77 cab_UBYTE versionMajor
; /* 1 */
78 cab_UWORD cFolders
; /* number of CFFOLDER entries in the cabinet*/
79 cab_UWORD cFiles
; /* number of CFFILE entries in the cabinet*/
80 cab_UWORD flags
; /* 1=prev cab, 2=next cabinet, 4=reserved setions*/
81 cab_UWORD setID
; /* identification number of all cabinets in a set*/
82 cab_UWORD iCabinet
; /* number of the cabinet in a set */
83 /* additional area if "flags" were set*/
84 } CFHEADER
; /* minimum 36 bytes */
87 cab_ULONG coffCabStart
; /* offset to the folder's first CFDATA section */
88 cab_UWORD cCFData
; /* number of this folder's CFDATA sections */
89 cab_UWORD typeCompress
; /* compression type of data in CFDATA section*/
90 /* additional area if reserve flag was set */
91 } CFFOLDER
; /* minumum 8 bytes */
94 cab_ULONG cbFile
; /* size of the uncompressed file in bytes */
95 cab_ULONG uoffFolderStart
; /* offset of the uncompressed file in the folder */
96 cab_UWORD iFolder
; /* number of folder in the cabinet 0=first */
97 /* for special values see below this structure*/
98 cab_UWORD date
; /* last modification date*/
99 cab_UWORD time
; /* last modification time*/
100 cab_UWORD attribs
; /* DOS fat attributes and UTF indicator */
101 /* ... and a C string with the name of the file */
102 } CFFILE
; /* 16 bytes + name of file */
106 cab_ULONG csum
; /* checksum of this entry*/
107 cab_UWORD cbData
; /* number of compressed bytes */
108 cab_UWORD cbUncomp
; /* number of bytes when data is uncompressed */
109 /* optional reserved area */
110 /* compressed data */
114 /***********************************************************************
115 * FCICreate (CABINET.10)
117 * FCICreate is provided with several callbacks and
118 * returns a handle which can be used to create cabinet files.
121 * perf [IO] A pointer to an ERF structure. When FCICreate
122 * returns an error condition, error information may
123 * be found here as well as from GetLastError.
124 * pfnfiledest [I] A pointer to a function which is called when a file
125 * is placed. Only useful for subsequent cabinet files.
126 * pfnalloc [I] A pointer to a function which allocates ram. Uses
127 * the same interface as malloc.
128 * pfnfree [I] A pointer to a function which frees ram. Uses the
129 * same interface as free.
130 * pfnopen [I] A pointer to a function which opens a file. Uses
131 * the same interface as _open.
132 * pfnread [I] A pointer to a function which reads from a file into
133 * a caller-provided buffer. Uses the same interface
135 * pfnwrite [I] A pointer to a function which writes to a file from
136 * a caller-provided buffer. Uses the same interface
138 * pfnclose [I] A pointer to a function which closes a file handle.
139 * Uses the same interface as _close.
140 * pfnseek [I] A pointer to a function which seeks in a file.
141 * Uses the same interface as _lseek.
142 * pfndelete [I] A pointer to a function which deletes a file.
143 * pfnfcigtf [I] A pointer to a function which gets the name of a
145 * pccab [I] A pointer to an initialized CCAB structure.
146 * pv [I] A pointer to an application-defined notification
147 * function which will be passed to other FCI functions
151 * On success, returns an FCI handle of type HFCI.
152 * On failure, the NULL file handle is returned. Error
153 * info can be retrieved from perf.
159 HFCI __cdecl
FCICreate(
161 PFNFCIFILEPLACED pfnfiledest
,
162 PFNFCIALLOC pfnalloc
,
166 PFNFCIWRITE pfnwrite
,
167 PFNFCICLOSE pfnclose
,
169 PFNFCIDELETE pfndelete
,
170 PFNFCIGETTEMPFILE pfnfcigtf
,
176 PFCI_Int p_fci_internal
;
178 if ((!perf
) || (!pfnalloc
) || (!pfnfree
) || (!pfnopen
) || (!pfnread
) ||
179 (!pfnwrite
) || (!pfnclose
) || (!pfnseek
) || (!pfndelete
) ||
180 (!pfnfcigtf
) || (!pccab
)) {
181 perf
->erfOper
= FCIERR_NONE
;
182 perf
->erfType
= ERROR_BAD_ARGUMENTS
;
185 SetLastError(ERROR_BAD_ARGUMENTS
);
189 if (!((hfci
= ((HFCI
) (*pfnalloc
)(sizeof(FCI_Int
)))))) {
190 perf
->erfOper
= FCIERR_ALLOC_FAIL
;
191 perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
194 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
198 p_fci_internal
=((PFCI_Int
)(hfci
));
199 p_fci_internal
->FCI_Intmagic
= FCI_INT_MAGIC
;
200 p_fci_internal
->perf
= perf
;
201 p_fci_internal
->pfnfiledest
= pfnfiledest
;
202 p_fci_internal
->pfnalloc
= pfnalloc
;
203 p_fci_internal
->pfnfree
= pfnfree
;
204 p_fci_internal
->pfnopen
= pfnopen
;
205 p_fci_internal
->pfnread
= pfnread
;
206 p_fci_internal
->pfnwrite
= pfnwrite
;
207 p_fci_internal
->pfnclose
= pfnclose
;
208 p_fci_internal
->pfnseek
= pfnseek
;
209 p_fci_internal
->pfndelete
= pfndelete
;
210 p_fci_internal
->pfnfcigtf
= pfnfcigtf
;
211 p_fci_internal
->pccab
= pccab
;
212 p_fci_internal
->fPrevCab
= FALSE
;
213 p_fci_internal
->fNextCab
= FALSE
;
214 p_fci_internal
->fSplitFolder
= FALSE
;
215 p_fci_internal
->fGetNextCabInVain
= FALSE
;
216 p_fci_internal
->pv
= pv
;
217 p_fci_internal
->data_in
= NULL
;
218 p_fci_internal
->cdata_in
= 0;
219 p_fci_internal
->data_out
= NULL
;
220 p_fci_internal
->cCompressedBytesInFolder
= 0;
221 p_fci_internal
->cFolders
= 0;
222 p_fci_internal
->cFiles
= 0;
223 p_fci_internal
->cDataBlocks
= 0;
224 p_fci_internal
->sizeFileCFDATA1
= 0;
225 p_fci_internal
->sizeFileCFFILE1
= 0;
226 p_fci_internal
->sizeFileCFDATA2
= 0;
227 p_fci_internal
->sizeFileCFFILE2
= 0;
228 p_fci_internal
->sizeFileCFFOLDER
= 0;
229 p_fci_internal
->sizeFileCFFOLDER
= 0;
230 p_fci_internal
->fNewPrevious
= FALSE
;
231 p_fci_internal
->estimatedCabinetSize
= 0;
232 p_fci_internal
->statusFolderTotal
= 0;
234 memcpy(p_fci_internal
->szPrevCab
, pccab
->szCab
, CB_MAX_CABINET_NAME
);
235 memcpy(p_fci_internal
->szPrevDisk
, pccab
->szDisk
, CB_MAX_DISK_NAME
);
238 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFDATA1
,
240 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
244 if ( strlen(p_fci_internal
->szFileNameCFDATA1
) >= CB_MAX_FILENAME
) {
245 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
249 p_fci_internal
->handleCFDATA1
= PFCI_OPEN(hfci
,
250 p_fci_internal
->szFileNameCFDATA1
, 34050, 384, &err
, pv
);
251 if(p_fci_internal
->handleCFDATA1
==0){
252 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
255 /* TODO error checking of err */
257 /* array of all CFFILE in a folder */
258 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE1
,
260 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
264 if ( strlen(p_fci_internal
->szFileNameCFFILE1
) >= CB_MAX_FILENAME
) {
265 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
268 p_fci_internal
->handleCFFILE1
= PFCI_OPEN(hfci
,
269 p_fci_internal
->szFileNameCFFILE1
, 34050, 384, &err
, pv
);
270 if(p_fci_internal
->handleCFFILE1
==0){
271 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
274 /* TODO error checking of err */
276 /* CFDATA with checksum and ready to be copied into cabinet */
277 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFDATA2
,
279 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
283 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
284 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
287 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
288 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, pv
);
289 if(p_fci_internal
->handleCFDATA2
==0){
290 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
293 /* TODO error checking of err */
295 /* array of all CFFILE in a folder, ready to be copied into cabinet */
296 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
298 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
302 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
303 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
306 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
307 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, pv
);
308 if(p_fci_internal
->handleCFFILE2
==0){
309 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
312 /* TODO error checking of err */
314 /* array of all CFFILE in a folder, ready to be copied into cabinet */
315 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,
317 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
321 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
322 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
325 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
326 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, pv
);
327 if(p_fci_internal
->handleCFFOLDER
==0) {
328 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
332 /* TODO close and delete new files when return FALSE */
333 /* TODO error checking of err */
336 } /* end of FCICreate */
343 static BOOL
fci_flush_data_block (HFCI hfci
, int* err
,
344 PFNFCISTATUS pfnfcis
) {
346 /* attention no hfci checks!!! */
347 /* attention no checks if there is data available!!! */
349 CFDATA
* cfdata
=&data
;
351 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
352 UINT cbReserveCFData
=p_fci_internal
->pccab
->cbReserveCFData
;
355 /* TODO compress the data of p_fci_internal->data_in */
356 /* and write it to p_fci_internal->data_out */
357 memcpy(p_fci_internal
->data_out
, p_fci_internal
->data_in
,
358 p_fci_internal
->cdata_in
/* number of bytes to copy */);
360 cfdata
->csum
=0; /* checksum has to be set later */
361 /* TODO set realsize of compressed data */
362 cfdata
->cbData
= p_fci_internal
->cdata_in
;
363 cfdata
->cbUncomp
= p_fci_internal
->cdata_in
;
365 /* write cfdata to p_fci_internal->handleCFDATA1 */
366 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
367 cfdata
, sizeof(*cfdata
), err
, p_fci_internal
->pv
)
368 != sizeof(*cfdata
) ) {
369 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
372 /* TODO error handling of err */
374 p_fci_internal
->sizeFileCFDATA1
+= sizeof(*cfdata
);
376 /* add optional reserved area */
378 /* This allocation and freeing at each CFData block is a bit */
379 /* inefficent, but it's harder to forget about freeing the buffer :-). */
380 /* Reserved areas are used seldom besides that... */
381 if (cbReserveCFData
!=0) {
382 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFData
))) {
383 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
386 for(i
=0;i
<cbReserveCFData
;) {
389 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
390 reserved
, /* memory buffer */
391 cbReserveCFData
, /* number of bytes to copy */
392 err
, p_fci_internal
->pv
) != cbReserveCFData
) {
393 PFCI_FREE(hfci
, reserved
);
394 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
397 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
399 p_fci_internal
->sizeFileCFDATA1
+= cbReserveCFData
;
400 PFCI_FREE(hfci
, reserved
);
403 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
404 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
405 p_fci_internal
->data_out
, /* memory buffer */
406 cfdata
->cbData
, /* number of bytes to copy */
407 err
, p_fci_internal
->pv
) != cfdata
->cbData
) {
408 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
411 /* TODO error handling of err */
413 p_fci_internal
->sizeFileCFDATA1
+= cfdata
->cbData
;
415 /* reset the offset */
416 p_fci_internal
->cdata_in
= 0;
417 p_fci_internal
->cCompressedBytesInFolder
+= cfdata
->cbData
;
419 /* report status with pfnfcis about uncompressed and compressed file data */
420 if( (*pfnfcis
)(statusFile
, cfdata
->cbData
, cfdata
->cbUncomp
,
421 p_fci_internal
->pv
) == -1) {
422 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
426 ++(p_fci_internal
->cDataBlocks
);
429 } /* end of fci_flush_data_block */
435 static cab_ULONG
fci_get_checksum(void *pv
, UINT cb
, CHECKSUM seed
)
446 while (cUlong
-- > 0) {
448 ul
|= (((cab_ULONG
)(*pb
++)) << 8);
449 ul
|= (((cab_ULONG
)(*pb
++)) << 16);
450 ul
|= (((cab_ULONG
)(*pb
++)) << 24);
458 ul
|= (((ULONG
)(*pb
++)) << 16);
460 ul
|= (((ULONG
)(*pb
++)) << 8);
469 } /* end of fci_get_checksum */
473 static BOOL
fci_flushfolder_copy_cfdata(HFCI hfci
, char* buffer
, UINT cbReserveCFData
,
474 PFNFCISTATUS pfnfcis
, int* err
, int handleCFDATA1new
,
475 cab_ULONG
* psizeFileCFDATA1new
, cab_ULONG
* payload
)
477 cab_ULONG read_result
;
478 CFDATA
* pcfdata
=(CFDATA
*)buffer
;
479 BOOL split_block
=FALSE
;
480 cab_UWORD savedUncomp
=0;
481 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
485 /* while not all CFDATAs have been copied do */
487 if( p_fci_internal
->fNextCab
) {
489 /* internal error should never happen */
490 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
494 /* REUSE the variable read_result */
495 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
496 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
497 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
502 if (p_fci_internal
->fPrevCab
) {
503 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
504 strlen(p_fci_internal
->szPrevDisk
)+1;
506 /* No more CFDATA fits into the cabinet under construction */
507 /* So don't try to store more data into it */
508 if( p_fci_internal
->fNextCab
&&
509 (p_fci_internal
->oldCCAB
.cb
<= sizeof(CFDATA
) + cbReserveCFData
+
510 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
511 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
514 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
516 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
517 strlen(p_fci_internal
->pccab
->szCab
)+1 +
518 strlen(p_fci_internal
->pccab
->szDisk
)+1
520 /* This may never be run for the first time the while loop is entered.
521 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
522 split_block
=TRUE
; /* In this case split_block is abused to store */
523 /* the complete data block into the next cabinet and not into the */
524 /* current one. Originally split_block is the indicator that a */
525 /* data block has been splitted across different cabinets. */
528 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
529 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/*file handle*/
530 buffer
, /* memory buffer */
531 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
532 err
, p_fci_internal
->pv
);
533 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
534 if (read_result
==0) break; /* ALL DATA has been copied */
536 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
539 /* TODO error handling of err */
541 /* REUSE buffer p_fci_internal->data_out !!! */
542 /* read data from p_fci_internal->handleCFDATA1 to */
543 /* p_fci_internal->data_out */
544 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
545 p_fci_internal
->data_out
/* memory buffer */,
546 pcfdata
->cbData
/* number of bytes to copy */,
547 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
549 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
552 /* TODO error handling of err */
554 /* if cabinet size is too large */
556 /* REUSE the variable read_result */
557 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
558 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
559 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
564 if (p_fci_internal
->fPrevCab
) {
565 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
566 strlen(p_fci_internal
->szPrevDisk
)+1;
569 /* Is cabinet with new CFDATA too large? Then data block has to be split */
570 if( p_fci_internal
->fNextCab
&&
571 (p_fci_internal
->oldCCAB
.cb
< sizeof(CFDATA
) + cbReserveCFData
+
573 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
574 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
577 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
578 sizeof(CFFOLDER
) + /* size of new CFFolder entry */
579 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
580 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* name of next cabinet */
581 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* name of next disk */
583 /* REUSE read_result to save the size of the compressed data */
584 read_result
=pcfdata
->cbData
;
585 /* Modify the size of the compressed data to store only a part of the */
586 /* data block into the current cabinet. This is done to prevent */
587 /* that the maximum cabinet size will be exceeded. The remainder */
588 /* will be stored into the next following cabinet. */
590 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
591 /* Substract everything except the size of the block of data */
592 /* to get it's actual size */
593 pcfdata
->cbData
= p_fci_internal
->oldCCAB
.cb
- (
594 sizeof(CFDATA
) + cbReserveCFData
+
595 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
596 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
598 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
599 sizeof(CFFOLDER
) + /* set size of new CFFolder entry */
600 p_fci_internal
->oldCCAB
.cbReserveCFFolder
);
601 /* substract the size of special header fields */
602 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
603 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
604 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
607 if (p_fci_internal
->fPrevCab
) {
608 pcfdata
->cbData
-=strlen(p_fci_internal
->szPrevCab
)+1 +
609 strlen(p_fci_internal
->szPrevDisk
)+1;
611 pcfdata
->cbData
-=strlen(p_fci_internal
->pccab
->szCab
)+1 +
612 strlen(p_fci_internal
->pccab
->szDisk
)+1;
614 savedUncomp
= pcfdata
->cbUncomp
;
615 pcfdata
->cbUncomp
= 0; /* on splitted blocks of data this is zero */
617 /* if split_block==TRUE then the above while loop won't */
618 /* be executed again */
619 split_block
=TRUE
; /* split_block is the indicator that */
620 /* a data block has been splitted across */
621 /* diffentent cabinets.*/
624 /* This should never happen !!! */
625 if (pcfdata
->cbData
==0) {
627 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
631 /* set little endian */
632 pcfdata
->cbData
=fci_endian_uword(pcfdata
->cbData
);
633 pcfdata
->cbUncomp
=fci_endian_uword(pcfdata
->cbUncomp
);
635 /* get checksum and write to cfdata.csum */
636 pcfdata
->csum
= fci_get_checksum( &(pcfdata
->cbData
),
637 sizeof(CFDATA
)+cbReserveCFData
-
638 sizeof(pcfdata
->csum
), fci_get_checksum( p_fci_internal
->data_out
, /*buffer*/
639 pcfdata
->cbData
, 0 ) );
641 /* set little endian */
642 pcfdata
->csum
=fci_endian_ulong(pcfdata
->csum
);
644 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
645 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
646 buffer
, /* memory buffer */
647 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
648 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
649 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
652 /* TODO error handling of err */
654 p_fci_internal
->sizeFileCFDATA2
+= sizeof(CFDATA
)+cbReserveCFData
;
656 /* reset little endian */
657 pcfdata
->cbData
=fci_endian_uword(pcfdata
->cbData
);
658 pcfdata
->cbUncomp
=fci_endian_uword(pcfdata
->cbUncomp
);
659 pcfdata
->csum
=fci_endian_ulong(pcfdata
->csum
);
661 /* write compressed data into p_fci_internal->handleCFDATA2 */
662 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
663 p_fci_internal
->data_out
, /* memory buffer */
664 pcfdata
->cbData
, /* number of bytes to copy */
665 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
666 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
669 /* TODO error handling of err */
671 p_fci_internal
->sizeFileCFDATA2
+= pcfdata
->cbData
;
672 ++(p_fci_internal
->cDataBlocks
);
673 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
674 (*payload
)+=pcfdata
->cbUncomp
;
675 /* if cabinet size too large and data has been split */
676 /* write the remainder of the data block to the new CFDATA1 file */
677 if( split_block
) { /* This does not include the */
678 /* abused one (just search for "abused" )*/
679 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
680 if (p_fci_internal
->fNextCab
==FALSE
) {
682 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
686 /* set cbData to the size of the remainder of the data block */
687 pcfdata
->cbData
= read_result
- pcfdata
->cbData
;
688 /*recover former value of cfdata.cbData; read_result will be the offset*/
689 read_result
-= pcfdata
->cbData
;
690 pcfdata
->cbUncomp
= savedUncomp
;
692 /* reset checksum, it will be computed later */
695 /* write cfdata WITHOUT checksum to handleCFDATA1new */
696 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
697 buffer
, /* memory buffer */
698 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
699 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
700 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
703 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
705 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
707 /* write compressed data into handleCFDATA1new */
708 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
709 p_fci_internal
->data_out
+ read_result
, /* memory buffer + offset */
710 /* to last part of split data */
711 pcfdata
->cbData
, /* number of bytes to copy */
712 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
713 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
716 /* TODO error handling of err */
718 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
720 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
721 /* the two blocks of the split data block have been written */
722 /* don't reset split_data yet, because it is still needed see below */
725 /* report status with pfnfcis about copied size of folder */
726 if( (*pfnfcis
)(statusFolder
,
727 p_fci_internal
->statusFolderCopied
, /*cfdata.cbData(+previous ones)*/
728 p_fci_internal
->statusFolderTotal
, /* total folder size */
729 p_fci_internal
->pv
) == -1) {
730 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
735 /* if cabinet size too large */
736 /* write the remaining data blocks to the new CFDATA1 file */
737 if ( split_block
) { /* This does include the */
738 /* abused one (just search for "abused" )*/
739 if (p_fci_internal
->fNextCab
==FALSE
) {
741 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
744 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
746 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
747 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/* handle */
748 buffer
, /* memory buffer */
749 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
750 err
, p_fci_internal
->pv
);
751 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
752 if (read_result
==0) break; /* ALL DATA has been copied */
754 fci_set_error(FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
757 /* TODO error handling of err */
759 /* REUSE buffer p_fci_internal->data_out !!! */
760 /* read data from p_fci_internal->handleCFDATA1 to */
761 /* p_fci_internal->data_out */
762 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
763 p_fci_internal
->data_out
/* memory buffer */,
764 pcfdata
->cbData
/* number of bytes to copy */,
765 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
767 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
770 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
772 /* write cfdata with checksum to handleCFDATA1new */
773 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
774 buffer
, /* memory buffer */
775 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
776 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
777 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
780 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
782 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
784 /* write compressed data into handleCFDATA1new */
785 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
786 p_fci_internal
->data_out
, /* memory buffer */
787 pcfdata
->cbData
, /* number of bytes to copy */
788 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
789 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
792 /* TODO error handling of err */
794 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
795 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
797 /* report status with pfnfcis about copied size of folder */
798 if( (*pfnfcis
)(statusFolder
,
799 p_fci_internal
->statusFolderCopied
,/*cfdata.cbData(+revious ones)*/
800 p_fci_internal
->statusFolderTotal
, /* total folder size */
801 p_fci_internal
->pv
) == -1) {
802 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
807 break; /* jump out of the next while loop */
808 } /* end of if( split_data ) */
811 } /* end of fci_flushfolder_copy_cfdata */
817 static BOOL
fci_flushfolder_copy_cffolder(HFCI hfci
, int* err
, UINT cbReserveCFFolder
,
818 cab_ULONG sizeFileCFDATA2old
)
823 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
825 /* absolute offset cannot be set yet, because the size of cabinet header, */
826 /* the number of CFFOLDERs and the number of CFFILEs may change. */
827 /* Instead the size of all previous data blocks will be stored and */
828 /* the remainder of the offset will be added when the cabinet will be */
829 /* flushed to disk. */
830 /* This is exactly the way the original CABINET.DLL works!!! */
831 cffolder
.coffCabStart
=sizeFileCFDATA2old
;
833 /* set the number of this folder's CFDATA sections */
834 cffolder
.cCFData
=p_fci_internal
->cDataBlocks
;
835 /* TODO set compression type */
836 cffolder
.typeCompress
= tcompTYPE_NONE
;
838 /* write cffolder to p_fci_internal->handleCFFOLDER */
839 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
840 &cffolder
, /* memory buffer */
841 sizeof(cffolder
), /* number of bytes to copy */
842 err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
843 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
846 /* TODO error handling of err */
848 p_fci_internal
->sizeFileCFFOLDER
+= sizeof(cffolder
);
850 /* add optional reserved area */
851 if (cbReserveCFFolder
!=0) {
852 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
853 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
856 for(i
=0;i
<cbReserveCFFolder
;) {
859 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
860 reserved
, /* memory buffer */
861 cbReserveCFFolder
, /* number of bytes to copy */
862 err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
863 PFCI_FREE(hfci
, reserved
);
864 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
867 /* TODO error handling of err */
869 p_fci_internal
->sizeFileCFFOLDER
+= cbReserveCFFolder
;
871 PFCI_FREE(hfci
, reserved
);
874 } /* end of fci_flushfolder_copy_cffolder */
880 static BOOL
fci_flushfolder_copy_cffile(HFCI hfci
, int* err
, int handleCFFILE1new
,
881 cab_ULONG
*psizeFileCFFILE1new
, cab_ULONG payload
)
884 cab_ULONG read_result
;
886 cab_ULONG sizeOfFiles
=0, sizeOfFilesPrev
;
887 BOOL may_be_prev
=TRUE
;
888 cab_ULONG cbFileRemainer
=0;
889 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
890 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
891 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,0,SEEK_SET
,err
,
892 p_fci_internal
->pv
) !=0 ) {
893 /* wrong return value */
894 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
897 /* TODO error handling of err */
899 /* while not all CFFILE structures have been copied do */
901 /* REUSE the variable read_result */
902 /* read data from p_fci_internal->handleCFFILE1 to cffile */
903 read_result
= PFCI_READ(hfci
,p_fci_internal
->handleCFFILE1
/* file handle */,
904 &cffile
, /* memory buffer */
905 sizeof(cffile
), /* number of bytes to copy */
906 err
, p_fci_internal
->pv
);
907 if( read_result
!= sizeof(cffile
) ) {
908 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
910 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
913 /* TODO error handling of err */
915 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
916 /* position. I don't know why so I'll just omit it */
918 /* read the filename from p_fci_internal->handleCFFILE1 */
919 /* REUSE the variable read_result AGAIN */
920 /* REUSE the memory buffer PFCI(hfci)->data_out */
921 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFILE1
/*file handle*/,
922 p_fci_internal
->data_out
, /* memory buffer */
923 CB_MAX_FILENAME
, /* number of bytes to copy */
924 err
, p_fci_internal
->pv
) <2) {
926 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
929 /* TODO maybe other checks of read_result */
930 /* TODO error handling of err */
933 if( strlen(p_fci_internal
->data_out
)>=CB_MAX_FILENAME
) {
934 /* set error code internal error */
935 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
939 seek
+=sizeof(cffile
) + strlen(p_fci_internal
->data_out
)+1;
941 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
942 /* i.e. seek to the next CFFILE area */
943 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,
944 seek
, /* seek position*/
948 /* wrong return value */
949 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
952 /* TODO error handling of err */
954 /* fnfilfnfildest: placed file on cabinet */
955 if (p_fci_internal
->fNextCab
||
956 p_fci_internal
->fGetNextCabInVain
) {
957 PFCI_FILEPLACED( hfci
, &(p_fci_internal
->oldCCAB
),
958 p_fci_internal
->data_out
, /* the file name*/
959 cffile
.cbFile
, /* file size */
960 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
964 PFCI_FILEPLACED( hfci
, p_fci_internal
->pccab
,
965 p_fci_internal
->data_out
, /* the file name*/
966 cffile
.cbFile
, /* file size */
967 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
972 /* Check special iFolder values */
973 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
974 p_fci_internal
->fPrevCab
==FALSE
) {
975 /* THIS MAY NEVER HAPPEN */
977 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
980 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
981 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
) {
982 /* THIS MAY NEVER HAPPEN */
984 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
987 if( may_be_prev
&& cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
990 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& may_be_prev
==FALSE
) {
991 /* THIS MAY NEVER HAPPEN */
993 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
996 if( cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
1000 sizeOfFilesPrev
=sizeOfFiles
;
1001 /* Set complete size of all processed files */
1002 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
1003 p_fci_internal
->cbFileRemainer
!=0
1005 sizeOfFiles
+=p_fci_internal
->cbFileRemainer
;
1006 p_fci_internal
->cbFileRemainer
=0;
1008 sizeOfFiles
+=cffile
.cbFile
;
1011 /* Check if spanned file fits into this cabinet folder */
1012 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& sizeOfFiles
>payload
) {
1013 cffile
.iFolder
=cffileCONTINUED_PREV_AND_NEXT
;
1016 /* Check if file doesn't fit into this cabinet folder */
1017 if( sizeOfFiles
>payload
) {
1018 cffile
.iFolder
=cffileCONTINUED_TO_NEXT
;
1021 /* set little endian */
1022 cffile
.cbFile
=fci_endian_ulong(cffile
.cbFile
);
1023 cffile
.uoffFolderStart
=fci_endian_ulong(cffile
.uoffFolderStart
);
1024 cffile
.iFolder
=fci_endian_uword(cffile
.iFolder
);
1025 cffile
.date
=fci_endian_uword(cffile
.date
);
1026 cffile
.time
=fci_endian_uword(cffile
.time
);
1027 cffile
.attribs
=fci_endian_uword(cffile
.attribs
);
1029 /* write cffile to p_fci_internal->handleCFFILE2 */
1030 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
1031 &cffile
, /* memory buffer */
1032 sizeof(cffile
), /* number of bytes to copy */
1033 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1034 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1037 /* TODO error handling of err */
1039 p_fci_internal
->sizeFileCFFILE2
+= sizeof(cffile
);
1041 /* reset little endian */
1042 cffile
.cbFile
=fci_endian_ulong(cffile
.cbFile
);
1043 cffile
.uoffFolderStart
=fci_endian_ulong(cffile
.uoffFolderStart
);
1044 cffile
.iFolder
=fci_endian_uword(cffile
.iFolder
);
1045 cffile
.date
=fci_endian_uword(cffile
.date
);
1046 cffile
.time
=fci_endian_uword(cffile
.time
);
1047 cffile
.attribs
=fci_endian_uword(cffile
.attribs
);
1049 /* write file name to p_fci_internal->handleCFFILE2 */
1050 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
1051 p_fci_internal
->data_out
, /* memory buffer */
1052 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1053 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1054 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1057 /* TODO error handling of err */
1059 p_fci_internal
->sizeFileCFFILE2
+= strlen(p_fci_internal
->data_out
)+1;
1061 /* cFiles is used to count all files of a cabinet */
1062 ++(p_fci_internal
->cFiles
);
1064 /* This is only true for files which will be written into the */
1065 /* next cabinet of the spanning folder */
1066 if( sizeOfFiles
>payload
) {
1068 /* Files which data will be partially written into the current cabinet */
1069 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
1070 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
1072 if( sizeOfFilesPrev
<=payload
) {
1073 /* The size of the uncompressed, data of a spanning file in a */
1075 cbFileRemainer
=sizeOfFiles
-payload
;
1077 cffile
.iFolder
=cffileCONTINUED_FROM_PREV
;
1082 /* write cffile into handleCFFILE1new */
1083 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1084 &cffile
, /* memory buffer */
1085 sizeof(cffile
), /* number of bytes to copy */
1086 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1087 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1090 /* TODO error handling of err */
1092 *psizeFileCFFILE1new
+= sizeof(cffile
);
1093 /* write name of file into handleCFFILE1new */
1094 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1095 p_fci_internal
->data_out
, /* memory buffer */
1096 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1097 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1098 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1101 /* TODO error handling of err */
1103 *psizeFileCFFILE1new
+= strlen(p_fci_internal
->data_out
)+1;
1106 } /* END OF while */
1107 p_fci_internal
->cbFileRemainer
=cbFileRemainer
;
1109 } /* end of fci_flushfolder_copy_cffile */
1114 static BOOL
fci_flush_folder(
1117 PFNFCIGETNEXTCABINET pfnfcignc
,
1118 PFNFCISTATUS pfnfcis
)
1121 int handleCFDATA1new
; /* handle for new temp file */
1122 char szFileNameCFDATA1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1123 int handleCFFILE1new
; /* handle for new temp file */
1124 char szFileNameCFFILE1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1125 UINT cbReserveCFData
, cbReserveCFFolder
;
1127 cab_ULONG sizeFileCFDATA1new
=0;
1128 cab_ULONG sizeFileCFFILE1new
=0;
1129 cab_ULONG sizeFileCFDATA2old
;
1131 cab_ULONG read_result
;
1132 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1135 if (!REALLY_IS_FCI(hfci
)) {
1136 SetLastError(ERROR_INVALID_HANDLE
);
1140 if ((!pfnfcignc
) || (!pfnfcis
)) {
1141 fci_set_error( FCIERR_NONE
, ERROR_BAD_ARGUMENTS
, TRUE
);
1145 if( p_fci_internal
->fGetNextCabInVain
&&
1146 p_fci_internal
->fNextCab
){
1147 /* internal error */
1148 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1152 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1153 /* this function will return TRUE */
1154 if( p_fci_internal
->sizeFileCFFILE1
== 0 ) {
1155 if ( p_fci_internal
->sizeFileCFDATA1
!= 0 ) {
1156 /* error handling */
1157 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1163 if (p_fci_internal
->data_in
==NULL
|| p_fci_internal
->data_out
==NULL
) {
1164 /* error handling */
1165 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1169 /* FCIFlushFolder has already been called... */
1170 if (p_fci_internal
->fSplitFolder
&& p_fci_internal
->sizeFileCFFILE2
!=0) {
1174 /* This can be set already, because it makes only a difference */
1175 /* when the current function exits with return FALSE */
1176 p_fci_internal
->fSplitFolder
=FALSE
;
1179 if( p_fci_internal
->fGetNextCabInVain
||
1180 p_fci_internal
->fNextCab
){
1181 cbReserveCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1182 cbReserveCFFolder
= p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1184 cbReserveCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1185 cbReserveCFFolder
= p_fci_internal
->pccab
->cbReserveCFFolder
;
1189 /* if there is data in p_fci_internal->data_in */
1190 if (p_fci_internal
->cdata_in
!=0) {
1192 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
1195 /* reset to get the number of data blocks of this folder which are */
1196 /* actually in this cabinet ( at least partially ) */
1197 p_fci_internal
->cDataBlocks
=0;
1199 if ( p_fci_internal
->fNextCab
||
1200 p_fci_internal
->fGetNextCabInVain
) {
1201 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
1202 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1203 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1204 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1205 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1209 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
+
1210 p_fci_internal
->pccab
->cbReserveCFFolder
;
1211 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1212 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1213 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1217 if (p_fci_internal
->fPrevCab
) {
1218 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1219 strlen(p_fci_internal
->szPrevDisk
)+1;
1221 if (p_fci_internal
->fNextCab
) {
1222 read_result
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1223 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1226 p_fci_internal
->statusFolderTotal
= sizeof(CFHEADER
)+read_result
+
1227 sizeof(CFFOLDER
) + p_fci_internal
->sizeFileCFFILE2
+
1228 p_fci_internal
->sizeFileCFDATA2
+ p_fci_internal
->sizeFileCFFILE1
+
1229 p_fci_internal
->sizeFileCFDATA1
+ p_fci_internal
->sizeFileCFFOLDER
;
1230 p_fci_internal
->statusFolderCopied
= 0;
1232 /* report status with pfnfcis about copied size of folder */
1233 if( (*pfnfcis
)(statusFolder
, p_fci_internal
->statusFolderCopied
,
1234 p_fci_internal
->statusFolderTotal
, /* TODO total folder size */
1235 p_fci_internal
->pv
) == -1) {
1236 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
1240 /* get a new temp file */
1241 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFDATA1new
,CB_MAX_FILENAME
)) {
1242 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
1246 if ( strlen(szFileNameCFDATA1new
) >= CB_MAX_FILENAME
) {
1247 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1250 handleCFDATA1new
= PFCI_OPEN(hfci
,szFileNameCFDATA1new
,34050,384,&err
,
1251 p_fci_internal
->pv
);
1252 if(handleCFDATA1new
==0){
1253 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
1256 /* TODO error handling of err */
1260 /* get a new temp file */
1261 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFFILE1new
,CB_MAX_FILENAME
)) {
1262 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
1263 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1264 /* TODO error handling of err */
1268 if ( strlen(szFileNameCFFILE1new
) >= CB_MAX_FILENAME
) {
1269 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1270 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1271 /* TODO error handling of err */
1274 handleCFFILE1new
= PFCI_OPEN(hfci
,szFileNameCFFILE1new
,34050,384,&err
,
1275 p_fci_internal
->pv
);
1276 if(handleCFFILE1new
==0){
1277 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
1280 /* TODO error handling of err */
1282 /* USE the variable read_result */
1283 if ( p_fci_internal
->fNextCab
||
1284 p_fci_internal
->fGetNextCabInVain
) {
1285 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1286 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1287 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1288 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1292 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
;
1293 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1294 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1295 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1299 if (p_fci_internal
->fPrevCab
) {
1300 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1301 strlen(p_fci_internal
->szPrevDisk
)+1;
1303 read_result
+= sizeof(CFHEADER
) + p_fci_internal
->sizeFileCFDATA2
+
1304 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
;
1306 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
1307 read_result
+= sizeof(CFFOLDER
)+p_fci_internal
->pccab
->cbReserveCFFolder
;
1310 /* Check if multiple cabinets have to be created. */
1312 /* Might be too much data for the maximum allowed cabinet size.*/
1313 /* When any further data will be added later, it might not */
1314 /* be possible to flush the cabinet, because there might */
1315 /* not be enough space to store the name of the following */
1316 /* cabinet and name of the corresponding disk. */
1317 /* So take care of this and get the name of the next cabinet */
1318 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
1319 p_fci_internal
->fNextCab
==FALSE
&&
1322 p_fci_internal
->pccab
->cb
< read_result
+
1323 p_fci_internal
->sizeFileCFDATA1
+
1324 p_fci_internal
->sizeFileCFFILE1
+
1325 CB_MAX_CABINET_NAME
+ /* next cabinet name */
1326 CB_MAX_DISK_NAME
/* next disk name */
1331 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
1332 /* increment cabinet index */
1333 ++(p_fci_internal
->pccab
->iCab
);
1334 /* get name of next cabinet */
1335 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
1336 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
1337 p_fci_internal
->estimatedCabinetSize
, /* estimated size of cab */
1338 p_fci_internal
->pv
)) {
1339 /* error handling */
1340 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
1341 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1342 /* TODO error handling of err */
1343 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1344 /* TODO error handling of err */
1348 /* Skip a few lines of code. This is catched by the next if. */
1349 p_fci_internal
->fGetNextCabInVain
=TRUE
;
1352 /* too much data for cabinet */
1353 if( (p_fci_internal
->fGetNextCabInVain
||
1354 p_fci_internal
->fNextCab
) &&
1357 p_fci_internal
->oldCCAB
.cb
< read_result
+
1358 p_fci_internal
->sizeFileCFDATA1
+
1359 p_fci_internal
->sizeFileCFFILE1
+
1360 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1361 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1365 p_fci_internal
->fGetNextCabInVain
=FALSE
;
1366 p_fci_internal
->fNextCab
=TRUE
;
1368 /* return FALSE if there is not enough space left*/
1369 /* this should never happen */
1370 if (p_fci_internal
->oldCCAB
.cb
<=
1371 p_fci_internal
->sizeFileCFFILE1
+
1373 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1374 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1377 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1378 /* TODO error handling of err */
1379 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1380 /* TODO error handling of err */
1382 /* close and delete p_fci_internal->handleCFFILE1 */
1383 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1384 /* TODO error handling of err */
1385 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1386 /* TODO error handling of err */
1391 /* the folder will be split across cabinets */
1392 p_fci_internal
->fSplitFolder
=TRUE
;
1395 /* this should never happen */
1396 if (p_fci_internal
->fNextCab
) {
1397 /* internal error */
1398 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1403 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1404 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA1
,0,SEEK_SET
,&err
,
1405 p_fci_internal
->pv
) !=0 ) {
1406 /* wrong return value */
1407 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1408 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1409 /* TODO error handling of err */
1410 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1411 /* TODO error handling of err */
1414 /* TODO error handling of err */
1416 /* save size of file CFDATA2 - required for the folder's offset to data */
1417 sizeFileCFDATA2old
= p_fci_internal
->sizeFileCFDATA2
;
1419 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFData
+sizeof(CFDATA
)))) {
1420 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
1421 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1422 /* TODO error handling of err */
1423 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1424 /* TODO error handling of err */
1428 if(!fci_flushfolder_copy_cfdata(hfci
, reserved
, cbReserveCFData
, pfnfcis
, &err
,
1429 handleCFDATA1new
, &sizeFileCFDATA1new
, &payload
1431 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1432 /* TODO error handling of err */
1433 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1434 /* TODO error handling of err */
1435 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1436 /* TODO error handling of err */
1437 PFCI_FREE(hfci
,reserved
);
1441 PFCI_FREE(hfci
,reserved
);
1443 if(!fci_flushfolder_copy_cffolder(hfci
, &err
, cbReserveCFFolder
,
1444 sizeFileCFDATA2old
)) {
1445 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1446 /* TODO error handling of err */
1447 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1448 /* TODO error handling of err */
1449 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1450 /* TODO error handling of err */
1454 if(!fci_flushfolder_copy_cffile(hfci
, &err
, handleCFFILE1new
,
1455 &sizeFileCFFILE1new
, payload
)) {
1456 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1457 /* TODO error handling of err */
1458 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1459 /* TODO error handling of err */
1460 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1461 /* TODO error handling of err */
1462 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1463 /* TODO error handling of err */
1467 /* close and delete p_fci_internal->handleCFDATA1 */
1468 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
1469 /* TODO error handling of err */
1470 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFDATA1
,&err
,p_fci_internal
->pv
);
1471 /* TODO error handling of err */
1473 /* put new CFDATA1 into hfci */
1474 memcpy(p_fci_internal
->szFileNameCFDATA1
,szFileNameCFDATA1new
,
1477 /* put CFDATA1 file handle */
1478 PFCI_INT(hfci
)->handleCFDATA1
= handleCFDATA1new
;
1480 PFCI_INT(hfci
)->sizeFileCFDATA1
= sizeFileCFDATA1new
;
1482 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1483 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFFILE1
,&err
,PFCI_INT(hfci
)->pv
);
1484 /* TODO error handling of err */
1485 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFFILE1
,&err
,p_fci_internal
->pv
);
1486 /* TODO error handling of err */
1488 /* put new CFFILE1 into hfci */
1489 memcpy(p_fci_internal
->szFileNameCFFILE1
,szFileNameCFFILE1new
,
1492 /* put CFFILE1 file handle */
1493 p_fci_internal
->handleCFFILE1
= handleCFFILE1new
;
1495 p_fci_internal
->sizeFileCFFILE1
= sizeFileCFFILE1new
;
1497 ++(p_fci_internal
->cFolders
);
1499 /* reset CFFolder specific information */
1500 p_fci_internal
->cDataBlocks
=0;
1501 p_fci_internal
->cCompressedBytesInFolder
=0;
1504 } /* end of fci_flush_folder */
1509 static BOOL
fci_flush_cabinet(
1512 PFNFCIGETNEXTCABINET pfnfcignc
,
1513 PFNFCISTATUS pfnfcis
)
1518 cab_UWORD cbCFHeader
;
1519 cab_UBYTE cbCFFolder
;
1523 cab_ULONG read_result
=0;
1524 int handleCABINET
; /* file handle for cabinet */
1525 char szFileNameCABINET
[CB_MAX_CAB_PATH
+CB_MAX_CABINET_NAME
];/* name buffer */
1526 UINT cbReserveCFHeader
, cbReserveCFFolder
, i
;
1528 BOOL returntrue
=FALSE
;
1529 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1531 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1533 /* when FCIFlushCabinet was or FCIAddFile hasn't been called */
1534 if( p_fci_internal
->sizeFileCFFILE1
==0 && fGetNextCab
) {
1538 if (!fci_flush_folder(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)){
1539 /* TODO set error */
1543 if(returntrue
) return TRUE
;
1545 if ( (p_fci_internal
->fSplitFolder
&& p_fci_internal
->fNextCab
==FALSE
)||
1546 (p_fci_internal
->sizeFileCFFOLDER
==0 &&
1547 (p_fci_internal
->sizeFileCFFILE1
!=0 ||
1548 p_fci_internal
->sizeFileCFFILE2
!=0 )
1552 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
1556 if( p_fci_internal
->fNextCab
||
1557 p_fci_internal
->fGetNextCabInVain
) {
1558 cbReserveCFFolder
=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1559 cbReserveCFHeader
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1561 if (strlen(p_fci_internal
->oldCCAB
.szCabPath
)>=CB_MAX_CAB_PATH
||
1562 strlen(p_fci_internal
->oldCCAB
.szCab
)>=CB_MAX_CABINET_NAME
) {
1564 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1567 /* get the full name of the cabinet */
1568 memcpy(szFileNameCABINET
,p_fci_internal
->oldCCAB
.szCabPath
,
1570 memcpy(szFileNameCABINET
+strlen(szFileNameCABINET
),
1571 p_fci_internal
->oldCCAB
.szCab
, CB_MAX_CABINET_NAME
);
1573 cbReserveCFFolder
=p_fci_internal
->pccab
->cbReserveCFFolder
;
1574 cbReserveCFHeader
=p_fci_internal
->pccab
->cbReserveCFHeader
;
1576 if (strlen(p_fci_internal
->pccab
->szCabPath
)>=CB_MAX_CAB_PATH
||
1577 strlen(p_fci_internal
->pccab
->szCab
)>=CB_MAX_CABINET_NAME
) {
1579 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
1582 /* get the full name of the cabinet */
1583 memcpy(szFileNameCABINET
,p_fci_internal
->pccab
->szCabPath
,
1585 memcpy(szFileNameCABINET
+strlen(szFileNameCABINET
),
1586 p_fci_internal
->pccab
->szCab
, CB_MAX_CABINET_NAME
);
1589 memcpy(cfheader
.signature
,"!CAB",4);
1590 cfheader
.reserved1
=0;
1591 cfheader
.cbCabinet
= /* size of the cabinet file in bytes */
1593 p_fci_internal
->sizeFileCFFOLDER
+
1594 p_fci_internal
->sizeFileCFFILE2
+
1595 p_fci_internal
->sizeFileCFDATA2
;
1597 if (p_fci_internal
->fPrevCab
) {
1598 cfheader
.cbCabinet
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1599 strlen(p_fci_internal
->szPrevDisk
)+1;
1601 if (p_fci_internal
->fNextCab
) {
1602 cfheader
.cbCabinet
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1603 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1605 if( p_fci_internal
->fNextCab
||
1606 p_fci_internal
->fGetNextCabInVain
) {
1607 cfheader
.cbCabinet
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1608 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1609 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1610 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1611 cfheader
.cbCabinet
+=4;
1614 cfheader
.cbCabinet
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1615 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1616 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1617 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1618 cfheader
.cbCabinet
+=4;
1622 if( ( ( p_fci_internal
->fNextCab
||
1623 p_fci_internal
->fGetNextCabInVain
) &&
1624 cfheader
.cbCabinet
> p_fci_internal
->oldCCAB
.cb
1626 ( ( p_fci_internal
->fNextCab
==FALSE
&&
1627 p_fci_internal
->fGetNextCabInVain
==FALSE
) &&
1628 cfheader
.cbCabinet
> p_fci_internal
->pccab
->cb
1632 fci_set_error( FCIERR_NONE
, ERROR_MORE_DATA
, TRUE
);
1637 cfheader
.reserved2
=0;
1638 cfheader
.coffFiles
= /* offset to first CFFILE section */
1639 cfheader
.cbCabinet
- p_fci_internal
->sizeFileCFFILE2
-
1640 p_fci_internal
->sizeFileCFDATA2
;
1642 cfheader
.reserved3
=0;
1643 cfheader
.versionMinor
=3;
1644 cfheader
.versionMajor
=1;
1645 /* number of CFFOLDER entries in the cabinet */
1646 cfheader
.cFolders
=p_fci_internal
->cFolders
;
1647 /* number of CFFILE entries in the cabinet */
1648 cfheader
.cFiles
=p_fci_internal
->cFiles
;
1649 cfheader
.flags
=0; /* 1=prev cab, 2=next cabinet, 4=reserved setions */
1651 if( p_fci_internal
->fPrevCab
) {
1652 cfheader
.flags
= cfheadPREV_CABINET
;
1655 if( p_fci_internal
->fNextCab
) {
1656 cfheader
.flags
|= cfheadNEXT_CABINET
;
1659 if( p_fci_internal
->fNextCab
||
1660 p_fci_internal
->fGetNextCabInVain
) {
1661 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1662 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1663 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1664 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1666 cfheader
.setID
= p_fci_internal
->oldCCAB
.setID
;
1667 cfheader
.iCabinet
= p_fci_internal
->oldCCAB
.iCab
-1;
1669 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1670 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1671 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1672 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1674 cfheader
.setID
= p_fci_internal
->pccab
->setID
;
1675 cfheader
.iCabinet
= p_fci_internal
->pccab
->iCab
-1;
1678 /* create the cabinet */
1679 handleCABINET
= PFCI_OPEN(hfci
, szFileNameCABINET
,
1680 33538, 384, &err
, p_fci_internal
->pv
);
1681 if(handleCABINET
==0){
1682 fci_set_error( FCIERR_CAB_FILE
, ERROR_OPEN_FAILED
, TRUE
);
1685 /* TODO error checking of err */
1687 /* set little endian */
1688 cfheader
.reserved1
=fci_endian_ulong(cfheader
.reserved1
);
1689 cfheader
.cbCabinet
=fci_endian_ulong(cfheader
.cbCabinet
);
1690 cfheader
.reserved2
=fci_endian_ulong(cfheader
.reserved2
);
1691 cfheader
.coffFiles
=fci_endian_ulong(cfheader
.coffFiles
);
1692 cfheader
.reserved3
=fci_endian_ulong(cfheader
.reserved3
);
1693 cfheader
.cFolders
=fci_endian_uword(cfheader
.cFolders
);
1694 cfheader
.cFiles
=fci_endian_uword(cfheader
.cFiles
);
1695 cfheader
.flags
=fci_endian_uword(cfheader
.flags
);
1696 cfheader
.setID
=fci_endian_uword(cfheader
.setID
);
1697 cfheader
.iCabinet
=fci_endian_uword(cfheader
.iCabinet
);
1699 /* write CFHEADER into cabinet file */
1700 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1701 &cfheader
, /* memory buffer */
1702 sizeof(cfheader
), /* number of bytes to copy */
1703 &err
, p_fci_internal
->pv
) != sizeof(cfheader
) ) {
1705 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1708 /* TODO error handling of err */
1710 /* reset little endian */
1711 cfheader
.reserved1
=fci_endian_ulong(cfheader
.reserved1
);
1712 cfheader
.cbCabinet
=fci_endian_ulong(cfheader
.cbCabinet
);
1713 cfheader
.reserved2
=fci_endian_ulong(cfheader
.reserved2
);
1714 cfheader
.coffFiles
=fci_endian_ulong(cfheader
.coffFiles
);
1715 cfheader
.reserved3
=fci_endian_ulong(cfheader
.reserved3
);
1716 cfheader
.cFolders
=fci_endian_uword(cfheader
.cFolders
);
1717 cfheader
.cFiles
=fci_endian_uword(cfheader
.cFiles
);
1718 cfheader
.flags
=fci_endian_uword(cfheader
.flags
);
1719 cfheader
.setID
=fci_endian_uword(cfheader
.setID
);
1720 cfheader
.iCabinet
=fci_endian_uword(cfheader
.iCabinet
);
1722 if( cfheader
.flags
& cfheadRESERVE_PRESENT
) {
1723 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1724 cfreserved
.cbCFHeader
= cbReserveCFHeader
;
1725 cfreserved
.cbCFFolder
= cbReserveCFFolder
;
1726 if( p_fci_internal
->fNextCab
||
1727 p_fci_internal
->fGetNextCabInVain
) {
1728 cfreserved
.cbCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1730 cfreserved
.cbCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1733 /* set little endian */
1734 cfreserved
.cbCFHeader
=fci_endian_uword(cfreserved
.cbCFHeader
);
1736 /* write reserved info into cabinet file */
1737 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1738 &cfreserved
, /* memory buffer */
1739 sizeof(cfreserved
), /* number of bytes to copy */
1740 &err
, p_fci_internal
->pv
) != sizeof(cfreserved
) ) {
1742 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1745 /* TODO error handling of err */
1747 /* reset little endian */
1748 cfreserved
.cbCFHeader
=fci_endian_uword(cfreserved
.cbCFHeader
);
1751 /* add optional reserved area */
1752 if (cbReserveCFHeader
!=0) {
1753 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFHeader
))) {
1754 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
1757 for(i
=0;i
<cbReserveCFHeader
;) {
1760 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1761 reserved
, /* memory buffer */
1762 cbReserveCFHeader
, /* number of bytes to copy */
1763 &err
, p_fci_internal
->pv
) != cbReserveCFHeader
) {
1764 PFCI_FREE(hfci
, reserved
);
1766 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1769 /* TODO error handling of err */
1770 PFCI_FREE(hfci
, reserved
);
1773 if( cfheader
.flags
& cfheadPREV_CABINET
) {
1774 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1775 p_fci_internal
->szPrevCab
, /* memory buffer */
1776 strlen(p_fci_internal
->szPrevCab
)+1, /* number of bytes to copy */
1777 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevCab
)+1 ) {
1779 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1782 /* TODO error handling of err */
1784 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1785 p_fci_internal
->szPrevDisk
, /* memory buffer */
1786 strlen(p_fci_internal
->szPrevDisk
)+1, /* number of bytes to copy */
1787 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevDisk
)+1 ) {
1789 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1792 /* TODO error handling of err */
1795 if( cfheader
.flags
& cfheadNEXT_CABINET
) {
1796 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1797 p_fci_internal
->pccab
->szCab
, /* memory buffer */
1798 strlen(p_fci_internal
->pccab
->szCab
)+1, /* number of bytes to copy */
1799 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szCab
)+1 ) {
1801 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1804 /* TODO error handling of err */
1806 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1807 p_fci_internal
->pccab
->szDisk
, /* memory buffer */
1808 strlen(p_fci_internal
->pccab
->szDisk
)+1, /* number of bytes to copy */
1809 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szDisk
)+1 ) {
1811 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1814 /* TODO error handling of err */
1817 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1818 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFOLDER
,
1819 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1820 /* wrong return value */
1821 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1824 /* TODO error handling of err */
1826 /* while not all CFFOLDER structures have been copied into the cabinet do */
1828 /* use the variable read_result */
1829 /* read cffolder of p_fci_internal->handleCFFOLDER */
1830 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* handle */
1831 &cffolder
, /* memory buffer */
1832 sizeof(cffolder
), /* number of bytes to copy */
1833 &err
, p_fci_internal
->pv
);
1834 if( read_result
!= sizeof(cffolder
) ) {
1835 if( read_result
== 0 ) break;/*ALL CFFOLDER structures have been copied*/
1837 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
1840 /* TODO error handling of err */
1842 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1843 cffolder
.coffCabStart
+=
1844 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
1846 if( p_fci_internal
->fNextCab
||
1847 p_fci_internal
->fGetNextCabInVain
) {
1848 cffolder
.coffCabStart
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1850 cffolder
.coffCabStart
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1853 if (p_fci_internal
->fPrevCab
) {
1854 cffolder
.coffCabStart
+= strlen(p_fci_internal
->szPrevCab
)+1 +
1855 strlen(p_fci_internal
->szPrevDisk
)+1;
1858 if (p_fci_internal
->fNextCab
) {
1859 cffolder
.coffCabStart
+= strlen(p_fci_internal
->oldCCAB
.szCab
)+1 +
1860 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1;
1863 if( p_fci_internal
->fNextCab
||
1864 p_fci_internal
->fGetNextCabInVain
) {
1865 cffolder
.coffCabStart
+= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1866 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1867 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1868 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1869 cffolder
.coffCabStart
+= 4;
1872 cffolder
.coffCabStart
+= p_fci_internal
->pccab
->cbReserveCFHeader
;
1873 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1874 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1875 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1876 cffolder
.coffCabStart
+= 4;
1880 /* set little endian */
1881 cffolder
.coffCabStart
=fci_endian_ulong(cffolder
.coffCabStart
);
1882 cffolder
.cCFData
=fci_endian_uword(cffolder
.cCFData
);
1883 cffolder
.typeCompress
=fci_endian_uword(cffolder
.typeCompress
);
1885 /* write cffolder to cabinet file */
1886 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1887 &cffolder
, /* memory buffer */
1888 sizeof(cffolder
), /* number of bytes to copy */
1889 &err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
1891 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1894 /* TODO error handling of err */
1896 /* reset little endian */
1897 cffolder
.coffCabStart
=fci_endian_ulong(cffolder
.coffCabStart
);
1898 cffolder
.cCFData
=fci_endian_uword(cffolder
.cCFData
);
1899 cffolder
.typeCompress
=fci_endian_uword(cffolder
.typeCompress
);
1901 /* add optional reserved area */
1903 /* This allocation and freeing at each CFFolder block is a bit */
1904 /* inefficent, but it's harder to forget about freeing the buffer :-). */
1905 /* Reserved areas are used seldom besides that... */
1906 if (cbReserveCFFolder
!=0) {
1907 if(!(reserved
= PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
1908 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
1912 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
1913 reserved
, /* memory buffer */
1914 cbReserveCFFolder
, /* number of bytes to copy */
1915 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1916 PFCI_FREE(hfci
, reserved
);
1918 fci_set_error( FCIERR_NONE
, ERROR_READ_FAULT
, TRUE
);
1921 /* TODO error handling of err */
1923 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1924 reserved
, /* memory buffer */
1925 cbReserveCFFolder
, /* number of bytes to copy */
1926 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1927 PFCI_FREE(hfci
, reserved
);
1929 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1932 /* TODO error handling of err */
1934 PFCI_FREE(hfci
, reserved
);
1937 } /* END OF while */
1939 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1940 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE2
,
1941 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1942 /* wrong return value */
1943 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1946 /* TODO error handling of err */
1948 /* while not all CFFILE structures have been copied to the cabinet do */
1950 /* REUSE the variable read_result */
1951 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1952 /* read a block from p_fci_internal->handleCFFILE2 */
1953 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFILE2
/* handle */,
1954 p_fci_internal
->data_out
, /* memory buffer */
1955 CB_MAX_CHUNK
, /* number of bytes to copy */
1956 &err
, p_fci_internal
->pv
);
1957 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
1958 /* TODO error handling of err */
1960 /* write the block to the cabinet file */
1961 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1962 p_fci_internal
->data_out
, /* memory buffer */
1963 read_result
, /* number of bytes to copy */
1964 &err
, p_fci_internal
->pv
) != read_result
) {
1966 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
1969 /* TODO error handling of err */
1971 if (p_fci_internal
->fSplitFolder
==FALSE
) {
1972 p_fci_internal
->statusFolderCopied
= 0;
1973 /* TODO TEST THIS further */
1974 p_fci_internal
->statusFolderTotal
= p_fci_internal
->sizeFileCFDATA2
+
1975 p_fci_internal
->sizeFileCFFILE2
;
1977 p_fci_internal
->statusFolderCopied
+= read_result
;
1979 /* report status with pfnfcis about copied size of folder */
1980 if( (*pfnfcis
)(statusFolder
,
1981 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
1982 p_fci_internal
->statusFolderTotal
, /* total size of folder */
1983 p_fci_internal
->pv
) == -1) {
1984 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
1988 } /* END OF while */
1990 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1991 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA2
,
1992 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1993 /* wrong return value */
1994 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
1997 /* TODO error handling of err */
1999 /* reset the number of folders for the next cabinet */
2000 p_fci_internal
->cFolders
=0;
2001 /* reset the number of files for the next cabinet */
2002 p_fci_internal
->cFiles
=0;
2004 /* while not all CFDATA structures have been copied to the cabinet do */
2006 /* REUSE the variable read_result AGAIN */
2007 /* REUSE the buffer p_fci_internal->data_out AGAIN */
2008 /* read a block from p_fci_internal->handleCFDATA2 */
2009 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA2
/* handle */,
2010 p_fci_internal
->data_out
, /* memory buffer */
2011 CB_MAX_CHUNK
, /* number of bytes to copy */
2012 &err
, p_fci_internal
->pv
);
2013 if( read_result
== 0 ) break; /* ALL CFDATA structures have been copied */
2014 /* TODO error handling of err */
2016 /* write the block to the cabinet file */
2017 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
2018 p_fci_internal
->data_out
, /* memory buffer */
2019 read_result
, /* number of bytes to copy */
2020 &err
, p_fci_internal
->pv
) != read_result
) {
2022 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2025 /* TODO error handling of err */
2027 p_fci_internal
->statusFolderCopied
+= read_result
;
2028 /* report status with pfnfcis about copied size of folder */
2029 if( (*pfnfcis
)(statusFolder
,
2030 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
2031 p_fci_internal
->statusFolderTotal
, /* total size of folder */
2032 p_fci_internal
->pv
) == -1) {
2033 /* set error code and abort */
2034 fci_set_error( FCIERR_USER_ABORT
, 0, TRUE
);
2037 } /* END OF while */
2039 /* set seek of the cabinet file to 0 */
2040 if( PFCI_SEEK(hfci
, handleCABINET
,
2041 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
2042 /* wrong return value */
2043 fci_set_error( FCIERR_NONE
, ERROR_SEEK
, TRUE
);
2046 /* TODO error handling of err */
2048 /* write the signature "MSCF" into the cabinet file */
2049 memcpy( cfheader
.signature
, "MSCF", 4 );
2050 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
2051 &cfheader
, /* memory buffer */
2052 4, /* number of bytes to copy */
2053 &err
, p_fci_internal
->pv
) != 4 ) {
2055 fci_set_error( FCIERR_CAB_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2058 /* TODO error handling of err */
2060 /* close the cabinet file */
2061 PFCI_CLOSE(hfci
,handleCABINET
,&err
,p_fci_internal
->pv
);
2062 /* TODO error handling of err */
2065 /* COPIED FROM FCIDestroy */
2067 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
2068 /* TODO error handling of err */
2069 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
2070 p_fci_internal
->pv
);
2071 /* TODO error handling of err */
2072 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
2073 /* TODO error handling of err */
2074 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
2075 p_fci_internal
->pv
);
2076 /* TODO error handling of err */
2077 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
2078 /* TODO error handling of err */
2079 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
2080 p_fci_internal
->pv
);
2081 /* TODO error handling of err */
2083 /* END OF copied from FCIDestroy */
2085 /* get 3 temporary files and open them */
2086 /* write names and handles to hfci */
2089 p_fci_internal
->sizeFileCFDATA2
= 0;
2090 p_fci_internal
->sizeFileCFFILE2
= 0;
2091 p_fci_internal
->sizeFileCFFOLDER
= 0;
2093 /* COPIED FROM FCICreate */
2095 /* CFDATA with checksum and ready to be copied into cabinet */
2096 if( !PFCI_GETTEMPFILE(hfci
, p_fci_internal
->szFileNameCFDATA2
,
2098 /* error handling */
2099 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2103 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
2104 /* set error code and abort */
2105 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2108 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
2109 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, p_fci_internal
->pv
);
2111 if(p_fci_internal
->handleCFDATA2
==0){
2112 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
2115 /* TODO error checking of err */
2117 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2118 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
2120 /* error handling */
2121 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2125 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
2126 /* set error code and abort */
2127 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2130 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
2131 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, p_fci_internal
->pv
);
2133 if(p_fci_internal
->handleCFFILE2
==0){
2134 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
2137 /* TODO error checking of err */
2139 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2140 if (!PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,CB_MAX_FILENAME
)) {
2141 /* error handling */
2142 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2146 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
2147 /* set error code and abort */
2148 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2151 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
2152 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, p_fci_internal
->pv
);
2154 if(p_fci_internal
->handleCFFOLDER
==0){
2155 fci_set_error( FCIERR_TEMP_FILE
, ERROR_OPEN_FAILED
, TRUE
);
2158 /* TODO error checking of err */
2160 /* END OF copied from FCICreate */
2163 /* TODO close and delete new files when return FALSE */
2166 /* report status with pfnfcis about copied size of folder */
2167 (*pfnfcis
)(statusCabinet
,
2168 p_fci_internal
->estimatedCabinetSize
, /* estimated cabinet file size */
2169 cfheader
.cbCabinet
/* real cabinet file size */, p_fci_internal
->pv
);
2171 p_fci_internal
->fPrevCab
=TRUE
;
2172 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2173 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2175 if (p_fci_internal
->fNextCab
) {
2176 p_fci_internal
->fNextCab
=FALSE
;
2178 if (p_fci_internal
->sizeFileCFFILE1
==0 && p_fci_internal
->sizeFileCFDATA1
!=0) {
2179 /* THIS CAN NEVER HAPPEN */
2180 /* set error code */
2181 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2185 /* COPIED FROM FCIAddFile and modified */
2187 /* REUSE the variable read_result */
2188 if (p_fci_internal
->fGetNextCabInVain
) {
2189 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
2190 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2191 read_result
+=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2193 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2194 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2195 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2199 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
;
2200 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2201 read_result
+=p_fci_internal
->pccab
->cbReserveCFFolder
;
2203 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2204 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2205 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2209 if ( p_fci_internal
->fPrevCab
) {
2210 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2211 strlen(p_fci_internal
->szPrevDisk
)+1;
2213 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2214 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2215 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2217 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2219 if( p_fci_internal
->fNewPrevious
) {
2220 memcpy(p_fci_internal
->szPrevCab
, p_fci_internal
->oldCCAB
.szCab
,
2221 CB_MAX_CABINET_NAME
);
2222 memcpy(p_fci_internal
->szPrevDisk
, p_fci_internal
->oldCCAB
.szDisk
,
2224 p_fci_internal
->fNewPrevious
=FALSE
;
2227 /* too much data for the maximum size of a cabinet */
2228 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2229 p_fci_internal
->pccab
->cb
< read_result
) {
2230 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2233 /* Might be too much data for the maximum size of a cabinet.*/
2234 /* When any further data will be added later, it might not */
2235 /* be possible to flush the cabinet, because there might */
2236 /* not be enough space to store the name of the following */
2237 /* cabinet and name of the corresponding disk. */
2238 /* So take care of this and get the name of the next cabinet */
2239 if (p_fci_internal
->fGetNextCabInVain
==FALSE
&& (
2240 p_fci_internal
->pccab
->cb
< read_result
+
2241 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2244 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2245 /* increment cabinet index */
2246 ++(p_fci_internal
->pccab
->iCab
);
2247 /* get name of next cabinet */
2248 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
2249 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
2250 p_fci_internal
->estimatedCabinetSize
, /* estimated size of cab */
2251 p_fci_internal
->pv
)) {
2252 /* error handling */
2253 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2256 /* Skip a few lines of code. This is catched by the next if. */
2257 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2260 /* too much data for cabinet */
2261 if (p_fci_internal
->fGetNextCabInVain
&& (
2262 p_fci_internal
->oldCCAB
.cb
< read_result
+
2263 strlen(p_fci_internal
->oldCCAB
.szCab
)+1+
2264 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1
2266 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2267 p_fci_internal
->fNextCab
=TRUE
;
2268 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2271 /* if the FolderThreshold has been reached flush the folder automatically */
2272 if( p_fci_internal
->fGetNextCabInVain
) {
2273 if( p_fci_internal
->cCompressedBytesInFolder
>=
2274 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2275 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2278 if( p_fci_internal
->cCompressedBytesInFolder
>=
2279 p_fci_internal
->pccab
->cbFolderThresh
) {
2280 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2284 /* END OF COPIED FROM FCIAddFile and modified */
2286 if( p_fci_internal
->sizeFileCFFILE1
>0 ) {
2287 if( !FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
) ) return FALSE
;
2288 p_fci_internal
->fNewPrevious
=TRUE
;
2291 p_fci_internal
->fNewPrevious
=FALSE
;
2292 if( p_fci_internal
->sizeFileCFFILE1
>0 || p_fci_internal
->sizeFileCFDATA1
) {
2293 /* THIS MAY NEVER HAPPEN */
2294 /* set error structures */
2295 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2301 } /* end of fci_flush_cabinet */
2307 /***********************************************************************
2308 * FCIAddFile (CABINET.11)
2310 * FCIAddFile adds a file to the to be created cabinet file
2313 * hfci [I] An HFCI from FCICreate
2314 * pszSourceFile [I] A pointer to a C string which contains the name and
2315 * location of the file which will be added to the cabinet
2316 * pszFileName [I] A pointer to a C string which contains the name under
2317 * which the file will be stored in the cabinet
2318 * fExecute [I] A boolean value which indicates if the file should be
2319 * executed after extraction of self extracting
2321 * pfnfcignc [I] A pointer to a function which gets information about
2323 * pfnfcis [IO] A pointer to a function which will report status
2324 * information about the compression process
2325 * pfnfcioi [I] A pointer to a function which reports file attributes
2326 * and time and date information
2327 * typeCompress [I] Compression type
2330 * On success, returns TRUE
2331 * On failure, returns FALSE
2337 BOOL __cdecl
FCIAddFile(
2339 char *pszSourceFile
,
2342 PFNFCIGETNEXTCABINET pfnfcignc
,
2343 PFNFCISTATUS pfnfcis
,
2344 PFNFCIGETOPENINFO pfnfcigoi
,
2349 cab_ULONG read_result
;
2351 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2354 if (!REALLY_IS_FCI(hfci
)) {
2355 SetLastError(ERROR_INVALID_HANDLE
);
2359 if ((!pszSourceFile
) || (!pszFileName
) || (!pfnfcignc
) || (!pfnfcis
) ||
2360 (!pfnfcigoi
) || strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2361 fci_set_error( FCIERR_NONE
, ERROR_BAD_ARGUMENTS
, TRUE
);
2365 /* TODO check if pszSourceFile??? */
2367 if(p_fci_internal
->fGetNextCabInVain
&& p_fci_internal
->fNextCab
) {
2368 /* internal error */
2369 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2373 if(p_fci_internal
->fNextCab
) {
2374 /* internal error */
2375 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2379 cffile
.cbFile
=0; /* size of the to be added file*/
2380 /* offset of the uncompressed file in the folder */
2381 cffile
.uoffFolderStart
=p_fci_internal
->cDataBlocks
*CAB_BLOCKMAX
+ p_fci_internal
->cdata_in
;
2382 /* number of folder in the cabinet or special 0=first */
2383 cffile
.iFolder
= p_fci_internal
->cFolders
;
2385 /* allocation of memory */
2386 if (p_fci_internal
->data_in
==NULL
) {
2387 if (p_fci_internal
->cdata_in
!=0) {
2388 /* error handling */
2389 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2392 if (p_fci_internal
->data_out
!=NULL
) {
2393 /* error handling */
2394 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2397 if(!(p_fci_internal
->data_in
= (char*)PFCI_ALLOC(hfci
,CB_MAX_CHUNK
))) {
2398 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
2401 if (p_fci_internal
->data_out
==NULL
) {
2402 if(!(p_fci_internal
->data_out
= PFCI_ALLOC(hfci
, 2 * CB_MAX_CHUNK
))){
2403 fci_set_error( FCIERR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
, TRUE
);
2409 if (p_fci_internal
->data_out
==NULL
) {
2410 PFCI_FREE(hfci
,p_fci_internal
->data_in
);
2411 /* error handling */
2412 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2416 /* get information about the file */
2417 file_handle
=(*pfnfcigoi
)(pszSourceFile
, &(cffile
.date
), &(cffile
.time
),
2418 &(cffile
.attribs
), &err
, p_fci_internal
->pv
);
2419 /* check file_handle */
2421 fci_set_error( FCIERR_OPEN_SRC
, ERROR_OPEN_FAILED
, TRUE
);
2423 /* TODO error handling of err */
2425 if (fExecute
) { cffile
.attribs
|= _A_EXEC
; }
2427 /* REUSE the variable read_result */
2428 if (p_fci_internal
->fGetNextCabInVain
) {
2429 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2430 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2431 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2432 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2433 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2437 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2438 p_fci_internal
->pccab
->cbReserveCFFolder
;
2439 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2440 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2441 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2445 if ( p_fci_internal
->fPrevCab
) {
2446 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2447 strlen(p_fci_internal
->szPrevDisk
)+1;
2449 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2450 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2451 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2454 read_result
+= sizeof(CFFILE
) + strlen(pszFileName
)+1 +
2455 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2456 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2458 sizeof(CFFOLDER
); /* size of new CFFolder entry */
2460 /* Might be too much data for the maximum size of a cabinet.*/
2461 /* When any further data will be added later, it might not */
2462 /* be possible to flush the cabinet, because there might */
2463 /* not be enough space to store the name of the following */
2464 /* cabinet and name of the corresponding disk. */
2465 /* So take care of this and get the name of the next cabinet */
2466 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2467 p_fci_internal
->fNextCab
==FALSE
&&
2468 ( p_fci_internal
->pccab
->cb
< read_result
+
2469 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2473 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2474 /* increment cabinet index */
2475 ++(p_fci_internal
->pccab
->iCab
);
2476 /* get name of next cabinet */
2477 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
2478 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
2479 p_fci_internal
->estimatedCabinetSize
, /* estimated size of cab */
2480 p_fci_internal
->pv
)) {
2481 /* error handling */
2482 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2485 /* Skip a few lines of code. This is catched by the next if. */
2486 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2489 if( p_fci_internal
->fGetNextCabInVain
&&
2490 p_fci_internal
->fNextCab
2492 /* THIS CAN NEVER HAPPEN */
2493 /* set error code */
2494 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2498 /* too much data for cabinet */
2499 if( p_fci_internal
->fGetNextCabInVain
&&
2501 p_fci_internal
->oldCCAB
.cb
< read_result
+
2502 strlen(p_fci_internal
->pccab
->szCab
)+1+
2503 strlen(p_fci_internal
->pccab
->szDisk
)+1
2505 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2506 p_fci_internal
->fNextCab
=TRUE
;
2507 if(!fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
)) return FALSE
;
2510 if( p_fci_internal
->fNextCab
) {
2511 /* THIS MAY NEVER HAPPEN */
2512 /* set error code */
2513 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2517 /* read the contents of the file blockwise */
2519 if (p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2520 /* internal error */
2521 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2525 read_result
= PFCI_READ(hfci
, file_handle
/* file handle */,
2526 (p_fci_internal
->data_in
+ p_fci_internal
->cdata_in
) /* memory buffer */,
2527 (CAB_BLOCKMAX
- p_fci_internal
->cdata_in
) /* number of bytes to copy */,
2528 &err
, p_fci_internal
->pv
);
2529 /* TODO error handling of err */
2531 if( read_result
==0 ) break;
2533 /* increment the block size */
2534 p_fci_internal
->cdata_in
+= read_result
;
2536 /* increment the file size */
2537 cffile
.cbFile
+= read_result
;
2539 if ( p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2540 /* report internal error */
2541 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2544 /* write a whole block */
2545 if ( p_fci_internal
->cdata_in
== CAB_BLOCKMAX
) {
2547 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
2551 /* close the file from FCIAddFile */
2552 PFCI_CLOSE(hfci
,file_handle
,&err
,p_fci_internal
->pv
);
2553 /* TODO error handling of err */
2555 /* write cffile to p_fci_internal->handleCFFILE1 */
2556 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2557 &cffile
, sizeof(cffile
),&err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
2559 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2562 /* TODO error handling of err */
2564 p_fci_internal
->sizeFileCFFILE1
+= sizeof(cffile
);
2566 /* append the name of file */
2567 if (strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2569 /* set error code */
2570 fci_set_error( FCIERR_NONE
, ERROR_INVALID_DATA
, TRUE
);
2573 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2574 pszFileName
, strlen(pszFileName
)+1, &err
, p_fci_internal
->pv
)
2575 != strlen(pszFileName
)+1 ) {
2577 fci_set_error( FCIERR_TEMP_FILE
, ERROR_WRITE_FAULT
, TRUE
);
2580 /* TODO error handling of err */
2582 p_fci_internal
->sizeFileCFFILE1
+= strlen(pszFileName
)+1;
2584 /* REUSE the variable read_result */
2585 if (p_fci_internal
->fGetNextCabInVain
||
2586 p_fci_internal
->fNextCab
2588 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2589 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2590 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2591 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2592 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2596 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2597 p_fci_internal
->pccab
->cbReserveCFFolder
;
2598 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2599 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2600 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2604 if ( p_fci_internal
->fPrevCab
) {
2605 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2606 strlen(p_fci_internal
->szPrevDisk
)+1;
2608 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2609 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2610 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2612 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2613 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2614 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2616 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2618 /* too much data for the maximum size of a cabinet */
2619 /* (ignoring the unflushed data block) */
2620 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2621 p_fci_internal
->fNextCab
==FALSE
&& /* this is always the case */
2622 p_fci_internal
->pccab
->cb
< read_result
) {
2623 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2626 /* Might be too much data for the maximum size of a cabinet.*/
2627 /* When any further data will be added later, it might not */
2628 /* be possible to flush the cabinet, because there might */
2629 /* not be enough space to store the name of the following */
2630 /* cabinet and name of the corresponding disk. */
2631 /* So take care of this and get the name of the next cabinet */
2632 /* (ignoring the unflushed data block) */
2633 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2634 p_fci_internal
->fNextCab
==FALSE
&&
2635 ( p_fci_internal
->pccab
->cb
< read_result
+
2636 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2640 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2641 /* increment cabinet index */
2642 ++(p_fci_internal
->pccab
->iCab
);
2643 /* get name of next cabinet */
2644 p_fci_internal
->estimatedCabinetSize
=p_fci_internal
->statusFolderTotal
;
2645 if (!(*pfnfcignc
)(p_fci_internal
->pccab
,
2646 p_fci_internal
->estimatedCabinetSize
,/* estimated size of cab */
2647 p_fci_internal
->pv
)) {
2648 /* error handling */
2649 fci_set_error( FCIERR_NONE
, ERROR_FUNCTION_FAILED
, TRUE
);
2652 /* Skip a few lines of code. This is catched by the next if. */
2653 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2656 if( p_fci_internal
->fGetNextCabInVain
&&
2657 p_fci_internal
->fNextCab
2659 /* THIS CAN NEVER HAPPEN */
2660 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2664 /* too much data for cabinet */
2665 if( (p_fci_internal
->fGetNextCabInVain
||
2666 p_fci_internal
->fNextCab
) && (
2667 p_fci_internal
->oldCCAB
.cb
< read_result
+
2668 strlen(p_fci_internal
->pccab
->szCab
)+1+
2669 strlen(p_fci_internal
->pccab
->szDisk
)+1
2672 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2673 p_fci_internal
->fNextCab
=TRUE
;
2674 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2677 if( p_fci_internal
->fNextCab
) {
2678 /* THIS MAY NEVER HAPPEN */
2679 /* set error code */
2680 fci_set_error( FCIERR_NONE
, ERROR_GEN_FAILURE
, TRUE
);
2684 /* if the FolderThreshold has been reached flush the folder automatically */
2685 if( p_fci_internal
->fGetNextCabInVain
) {
2686 if( p_fci_internal
->cCompressedBytesInFolder
>=
2687 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2688 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2691 if( p_fci_internal
->cCompressedBytesInFolder
>=
2692 p_fci_internal
->pccab
->cbFolderThresh
) {
2693 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2698 } /* end of FCIAddFile */
2704 /***********************************************************************
2705 * FCIFlushFolder (CABINET.12)
2707 * FCIFlushFolder completes the CFFolder structure under construction.
2709 * All further data which is added by FCIAddFile will be associateed to
2710 * the next CFFolder structure.
2712 * FCIFlushFolder will be called by FCIAddFile automatically if the
2713 * threshold (stored in the member cbFolderThresh of the CCAB structure
2714 * pccab passed to FCICreate) is exceeded.
2716 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2717 * any data will be written into the cabinet file.
2720 * hfci [I] An HFCI from FCICreate
2721 * pfnfcignc [I] A pointer to a function which gets information about
2723 * pfnfcis [IO] A pointer to a function which will report status
2724 * information about the compression process
2727 * On success, returns TRUE
2728 * On failure, returns FALSE
2734 BOOL __cdecl
FCIFlushFolder(
2736 PFNFCIGETNEXTCABINET pfnfcignc
,
2737 PFNFCISTATUS pfnfcis
)
2739 return fci_flush_folder(hfci
,FALSE
,pfnfcignc
,pfnfcis
);
2740 } /* end of FCIFlushFolder */
2744 /***********************************************************************
2745 * FCIFlushCabinet (CABINET.13)
2747 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2748 * into the cabinet file. If the maximum cabinet size (stored in the
2749 * member cb of the CCAB structure pccab passed to FCICreate) has been
2750 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2751 * The remaining data still has to be flushed manually by calling
2754 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2755 * NOT be called again. Then hfci has to be released by FCIDestroy.
2758 * hfci [I] An HFCI from FCICreate
2759 * fGetNextCab [I] Whether you want to add additional files to a
2760 * cabinet set (TRUE) or whether you want to
2761 * finalize it (FALSE)
2762 * pfnfcignc [I] A pointer to a function which gets information about
2764 * pfnfcis [IO] A pointer to a function which will report status
2765 * information about the compression process
2768 * On success, returns TRUE
2769 * On failure, returns FALSE
2775 BOOL __cdecl
FCIFlushCabinet(
2778 PFNFCIGETNEXTCABINET pfnfcignc
,
2779 PFNFCISTATUS pfnfcis
)
2781 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2783 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2785 while( p_fci_internal
->sizeFileCFFILE1
>0 ||
2786 p_fci_internal
->sizeFileCFFILE2
>0 ) {
2787 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2791 } /* end of FCIFlushCabinet */
2794 /***********************************************************************
2795 * FCIDestroy (CABINET.14)
2797 * Frees a handle created by FCICreate.
2798 * Only reason for failure would be an invalid handle.
2801 * hfci [I] The HFCI to free
2807 BOOL __cdecl
FCIDestroy(HFCI hfci
)
2810 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2811 if (REALLY_IS_FCI(hfci
)) {
2813 /* before hfci can be removed all temporary files must be closed */
2815 p_fci_internal
->FCI_Intmagic
= 0;
2817 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
2818 /* TODO error handling of err */
2819 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA1
, &err
,
2820 p_fci_internal
->pv
);
2821 /* TODO error handling of err */
2822 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE1
,&err
,p_fci_internal
->pv
);
2823 /* TODO error handling of err */
2824 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE1
, &err
,
2825 p_fci_internal
->pv
);
2826 /* TODO error handling of err */
2827 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
2828 /* TODO error handling of err */
2829 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
2830 p_fci_internal
->pv
);
2831 /* TODO error handling of err */
2832 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
2833 /* TODO error handling of err */
2834 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
2835 p_fci_internal
->pv
);
2836 /* TODO error handling of err */
2837 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
2838 /* TODO error handling of err */
2839 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
2840 p_fci_internal
->pv
);
2841 /* TODO error handling of err */
2843 /* data in and out buffers have to be removed */
2844 if (p_fci_internal
->data_in
!=NULL
)
2845 PFCI_FREE(hfci
, p_fci_internal
->data_in
);
2846 if (p_fci_internal
->data_out
!=NULL
)
2847 PFCI_FREE(hfci
, p_fci_internal
->data_out
);
2849 /* hfci can now be removed */
2850 PFCI_FREE(hfci
, hfci
);
2853 SetLastError(ERROR_INVALID_HANDLE
);
2857 } /* end of FCIDestroy */