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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 There is still some work to be done:
26 - currently no support for big-endian machines
27 - the ERF error structure aren't used on error
28 - no real compression yet
29 - unknown behaviour if files>4GB or cabinet >4GB
30 - incorrect status information
31 - check if the maximum size for a cabinet is too small to store any data
32 - call pfnfcignc on exactly the same position as MS FCIAddFile in every case
50 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(cabinet
);
55 cab_UBYTE signature
[4]; /* !CAB for unfinished cabinets else MSCF */
57 cab_ULONG cbCabinet
; /* size of the cabinet file in bytes*/
59 cab_ULONG coffFiles
; /* offset to first CFFILE section */
61 cab_UBYTE versionMinor
; /* 3 */
62 cab_UBYTE versionMajor
; /* 1 */
63 cab_UWORD cFolders
; /* number of CFFOLDER entries in the cabinet*/
64 cab_UWORD cFiles
; /* number of CFFILE entries in the cabinet*/
65 cab_UWORD flags
; /* 1=prev cab, 2=next cabinet, 4=reserved setions*/
66 cab_UWORD setID
; /* identification number of all cabinets in a set*/
67 cab_UWORD iCabinet
; /* number of the cabinet in a set */
68 /* additional area if "flags" were set*/
69 } CFHEADER
; /* minimum 36 bytes */
72 cab_ULONG coffCabStart
; /* offset to the folder's first CFDATA section */
73 cab_UWORD cCFData
; /* number of this folder's CFDATA sections */
74 cab_UWORD typeCompress
; /* compression type of data in CFDATA section*/
75 /* additional area if reserve flag was set */
76 } CFFOLDER
; /* minumum 8 bytes */
79 cab_ULONG cbFile
; /* size of the uncompressed file in bytes */
80 cab_ULONG uoffFolderStart
; /* offset of the uncompressed file in the folder */
81 cab_UWORD iFolder
; /* number of folder in the cabinet 0=first */
82 /* for special values see below this structure*/
83 cab_UWORD date
; /* last modification date*/
84 cab_UWORD time
; /* last modification time*/
85 cab_UWORD attribs
; /* DOS fat attributes and UTF indicator */
86 /* ... and a C string with the name of the file */
87 } CFFILE
; /* 16 bytes + name of file */
91 cab_ULONG csum
; /* checksum of this entry*/
92 cab_UWORD cbData
; /* number of compressed bytes */
93 cab_UWORD cbUncomp
; /* number of bytes when data is uncompressed */
94 /* optional reserved area */
99 /***********************************************************************
100 * FCICreate (CABINET.10)
102 * FCICreate is provided with several callbacks and
103 * returns a handle which can be used to create cabinet files.
106 * perf [IO] A pointer to an ERF structure. When FCICreate
107 * returns an error condition, error information may
108 * be found here as well as from GetLastError.
109 * pfnfiledest [I] A pointer to a function which is called when a file
110 * is placed. Only useful for subsequent cabinet files.
111 * pfnalloc [I] A pointer to a function which allocates ram. Uses
112 * the same interface as malloc.
113 * pfnfree [I] A pointer to a function which frees ram. Uses the
114 * same interface as free.
115 * pfnopen [I] A pointer to a function which opens a file. Uses
116 * the same interface as _open.
117 * pfnread [I] A pointer to a function which reads from a file into
118 * a caller-provided buffer. Uses the same interface
120 * pfnwrite [I] A pointer to a function which writes to a file from
121 * a caller-provided buffer. Uses the same interface
123 * pfnclose [I] A pointer to a function which closes a file handle.
124 * Uses the same interface as _close.
125 * pfnseek [I] A pointer to a function which seeks in a file.
126 * Uses the same interface as _lseek.
127 * pfndelete [I] A pointer to a function which deletes a file.
128 * pfnfcigtf [I] A pointer to a function which gets the name of a
130 * pccab [I] A pointer to an initialized CCAB structure.
131 * pv [I] A pointer to an application-defined notification
132 * function which will be passed to other FCI functions
136 * On success, returns an FCI handle of type HFCI.
137 * On failure, the NULL file handle is returned. Error
138 * info can be retrieved from perf.
144 HFCI __cdecl
FCICreate(
146 PFNFCIFILEPLACED pfnfiledest
,
147 PFNFCIALLOC pfnalloc
,
151 PFNFCIWRITE pfnwrite
,
152 PFNFCICLOSE pfnclose
,
154 PFNFCIDELETE pfndelete
,
155 PFNFCIGETTEMPFILE pfnfcigtf
,
161 PFCI_Int p_fci_internal
;
163 if ((!perf
) || (!pfnalloc
) || (!pfnfree
) || (!pfnopen
) || (!pfnread
) ||
164 (!pfnwrite
) || (!pfnclose
) || (!pfnseek
) || (!pfndelete
) ||
165 (!pfnfcigtf
) || (!pccab
)) {
166 perf
->erfOper
= FCIERR_NONE
;
167 perf
->erfType
= ERROR_BAD_ARGUMENTS
;
170 SetLastError(ERROR_BAD_ARGUMENTS
);
174 if (!((hfci
= ((HFCI
) (*pfnalloc
)(sizeof(FCI_Int
)))))) {
175 perf
->erfOper
= FCIERR_ALLOC_FAIL
;
176 perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
179 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
183 p_fci_internal
=((PFCI_Int
)(hfci
));
184 p_fci_internal
->FCI_Intmagic
= FCI_INT_MAGIC
;
185 p_fci_internal
->perf
= perf
;
186 p_fci_internal
->pfnfiledest
= pfnfiledest
;
187 p_fci_internal
->pfnalloc
= pfnalloc
;
188 p_fci_internal
->pfnfree
= pfnfree
;
189 p_fci_internal
->pfnopen
= pfnopen
;
190 p_fci_internal
->pfnread
= pfnread
;
191 p_fci_internal
->pfnwrite
= pfnwrite
;
192 p_fci_internal
->pfnclose
= pfnclose
;
193 p_fci_internal
->pfnseek
= pfnseek
;
194 p_fci_internal
->pfndelete
= pfndelete
;
195 p_fci_internal
->pfnfcigtf
= pfnfcigtf
;
196 p_fci_internal
->pccab
= pccab
;
197 p_fci_internal
->fPrevCab
= FALSE
;
198 p_fci_internal
->fNextCab
= FALSE
;
199 p_fci_internal
->fSplitFolder
= FALSE
;
200 p_fci_internal
->fGetNextCabInVain
= FALSE
;
201 p_fci_internal
->pv
= pv
;
202 p_fci_internal
->data_in
= NULL
;
203 p_fci_internal
->cdata_in
= 0;
204 p_fci_internal
->data_out
= NULL
;
205 p_fci_internal
->cCompressedBytesInFolder
= 0;
206 p_fci_internal
->cFolders
= 0;
207 p_fci_internal
->cFiles
= 0;
208 p_fci_internal
->cDataBlocks
= 0;
209 p_fci_internal
->sizeFileCFDATA1
= 0;
210 p_fci_internal
->sizeFileCFFILE1
= 0;
211 p_fci_internal
->sizeFileCFDATA2
= 0;
212 p_fci_internal
->sizeFileCFFILE2
= 0;
213 p_fci_internal
->sizeFileCFFOLDER
= 0;
214 p_fci_internal
->sizeFileCFFOLDER
= 0;
215 p_fci_internal
->fNewPrevious
= FALSE
;
217 memcpy(p_fci_internal
->szPrevCab
, pccab
->szCab
, CB_MAX_CABINET_NAME
);
218 memcpy(p_fci_internal
->szPrevDisk
, pccab
->szDisk
, CB_MAX_DISK_NAME
);
221 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFDATA1
,
223 /* TODO error handling */
227 if ( strlen(p_fci_internal
->szFileNameCFDATA1
) >= CB_MAX_FILENAME
) {
228 /* TODO set error code */
232 p_fci_internal
->handleCFDATA1
= PFCI_OPEN(hfci
,
233 p_fci_internal
->szFileNameCFDATA1
, 34050, 384, &err
, pv
);
234 /* TODO check handle */
235 /* TODO error checking of err */
237 /* array of all CFFILE in a folder */
238 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE1
,
240 /* TODO error handling */
244 if ( strlen(p_fci_internal
->szFileNameCFFILE1
) >= CB_MAX_FILENAME
) {
245 /* TODO set error code */
248 p_fci_internal
->handleCFFILE1
= PFCI_OPEN(hfci
,
249 p_fci_internal
->szFileNameCFFILE1
, 34050, 384, &err
, pv
);
250 /* TODO check handle */
251 /* TODO error checking of err */
253 /* CFDATA with checksum and ready to be copied into cabinet */
254 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFDATA2
,
256 /* TODO error handling */
260 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
261 /* TODO set error code */
264 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
265 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, pv
);
266 /* TODO check handle */
267 /* TODO error checking of err */
269 /* array of all CFFILE in a folder, ready to be copied into cabinet */
270 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
272 /* TODO error handling */
276 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
277 /* TODO set error code */
280 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
281 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, pv
);
282 /* TODO check handle */
283 /* TODO error checking of err */
285 /* array of all CFFILE in a folder, ready to be copied into cabinet */
286 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,
288 /* TODO error handling */
292 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
293 /* TODO set error code */
296 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
297 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, pv
);
300 /* TODO close and delete new files when return FALSE */
302 /* TODO check handle */
303 /* TODO error checking of err */
306 } /* end of FCICreate */
313 static BOOL
fci_flush_data_block (HFCI hfci
, int* err
,
314 PFNFCISTATUS pfnfcis
) {
316 /* attention no hfci checks!!! */
317 /* attention no checks if there is data available!!! */
319 CFDATA
* cfdata
=&data
;
321 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
322 UINT cbReserveCFData
=p_fci_internal
->pccab
->cbReserveCFData
;
325 /* TODO compress the data of p_fci_internal->data_in */
326 /* and write it to p_fci_internal->data_out */
327 memcpy(p_fci_internal
->data_out
, p_fci_internal
->data_in
,
328 p_fci_internal
->cdata_in
/* number of bytes to copy */);
330 cfdata
->csum
=0; /* checksum has to be set later */
331 /* TODO set realsize of compressed data */
332 cfdata
->cbData
= p_fci_internal
->cdata_in
;
333 cfdata
->cbUncomp
= p_fci_internal
->cdata_in
;
335 /* write cfdata to p_fci_internal->handleCFDATA1 */
336 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
337 cfdata
, sizeof(*cfdata
), err
, p_fci_internal
->pv
)
338 != sizeof(*cfdata
) ) {
339 /* TODO write error */
342 /* TODO error handling of err */
344 p_fci_internal
->sizeFileCFDATA1
+= sizeof(*cfdata
);
346 /* add optional reserved area */
348 /* This allocation and freeing at each CFData block is a bit */
349 /* inefficent, but it's harder to forget about freeing the buffer :-). */
350 /* Reserved areas are used seldom besides that... */
351 if (cbReserveCFData
!=0) {
352 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFData
))) {
353 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
354 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
355 p_fci_internal
->perf
->fError
= TRUE
;
356 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
359 for(i
=0;i
<cbReserveCFData
;) {
362 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
363 reserved
, /* memory buffer */
364 cbReserveCFData
, /* number of bytes to copy */
365 err
, p_fci_internal
->pv
) != cbReserveCFData
) {
366 PFCI_FREE(hfci
, reserved
);
367 /* TODO write error */
370 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
372 p_fci_internal
->sizeFileCFDATA1
+= cbReserveCFData
;
373 PFCI_FREE(hfci
, reserved
);
376 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
377 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
378 p_fci_internal
->data_out
, /* memory buffer */
379 cfdata
->cbData
, /* number of bytes to copy */
380 err
, p_fci_internal
->pv
) != cfdata
->cbData
) {
381 /* TODO write error */
384 /* TODO error handling of err */
386 p_fci_internal
->sizeFileCFDATA1
+= cfdata
->cbData
;
388 /* reset the offset */
389 p_fci_internal
->cdata_in
= 0;
390 p_fci_internal
->cCompressedBytesInFolder
+= cfdata
->cbData
;
392 /* report status with pfnfcis about uncompressed and compressed file data */
393 if( (*pfnfcis
)(statusFile
, cfdata
->cbData
, cfdata
->cbUncomp
,
394 p_fci_internal
->pv
) == -1) {
395 /* TODO set error code and abort */
399 ++(p_fci_internal
->cDataBlocks
);
402 } /* end of fci_flush_data_block */
408 static cab_ULONG
fci_get_checksum(void *pv
, UINT cb
, CHECKSUM seed
)
419 while (cUlong
-- > 0) {
421 ul
|= (((cab_ULONG
)(*pb
++)) << 8);
422 ul
|= (((cab_ULONG
)(*pb
++)) << 16);
423 ul
|= (((cab_ULONG
)(*pb
++)) << 24);
431 ul
|= (((ULONG
)(*pb
++)) << 16);
433 ul
|= (((ULONG
)(*pb
++)) << 8);
442 } /* end of fci_get_checksum */
448 static BOOL
fci_flushfolder_copy_cfdata(HFCI hfci
, char* buffer
, UINT cbReserveCFData
,
449 PFNFCISTATUS pfnfcis
, int* err
, int handleCFDATA1new
,
450 cab_ULONG
* psizeFileCFDATA1new
, cab_ULONG
* payload
)
452 cab_ULONG read_result
;
453 CFDATA
* pcfdata
=(CFDATA
*)buffer
;
454 BOOL split_block
=FALSE
;
455 cab_UWORD savedUncomp
=0;
456 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
460 /* while not all CFDATAs have been copied do */
462 if( p_fci_internal
->fNextCab
) {
464 /* TODO internal error should never happen */
468 /* REUSE the variable read_result */
469 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
470 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
471 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
476 if (p_fci_internal
->fPrevCab
) {
477 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
478 strlen(p_fci_internal
->szPrevDisk
)+1;
480 /* No more CFDATA fits into the cabinet under construction */
481 /* So don't try to store more data into it */
482 if( p_fci_internal
->fNextCab
&&
483 (p_fci_internal
->oldCCAB
.cb
<= sizeof(CFDATA
) + cbReserveCFData
+
484 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
485 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
488 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
490 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
491 strlen(p_fci_internal
->pccab
->szCab
)+1 +
492 strlen(p_fci_internal
->pccab
->szDisk
)+1
494 /* This may never be run for the first time the while loop is entered.
495 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
496 split_block
=TRUE
; /* In this case split_block is abused to store */
497 /* the complete data block into the next cabinet and not into the */
498 /* current one. Originally split_block is the indicator that a */
499 /* data block has been splitted across different cabinets. */
502 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
503 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/*file handle*/
504 buffer
, /* memory buffer */
505 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
506 err
, p_fci_internal
->pv
);
507 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
508 if (read_result
==0) break; /* ALL DATA has been copied */
509 /* TODO read error */
512 /* TODO error handling of err */
514 /* REUSE buffer p_fci_internal->data_out !!! */
515 /* read data from p_fci_internal->handleCFDATA1 to */
516 /* p_fci_internal->data_out */
517 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
518 p_fci_internal
->data_out
/* memory buffer */,
519 pcfdata
->cbData
/* number of bytes to copy */,
520 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
521 /* TODO read error */
524 /* TODO error handling of err */
526 /* if cabinet size is too large */
528 /* REUSE the variable read_result */
529 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
530 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
531 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
536 if (p_fci_internal
->fPrevCab
) {
537 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
538 strlen(p_fci_internal
->szPrevDisk
)+1;
541 /* Is cabinet with new CFDATA too large? Then data block has to be split */
542 if( p_fci_internal
->fNextCab
&&
543 (p_fci_internal
->oldCCAB
.cb
< sizeof(CFDATA
) + cbReserveCFData
+
545 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
546 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
549 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
550 sizeof(CFFOLDER
) + /* size of new CFFolder entry */
551 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
552 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* name of next cabinet */
553 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* name of next disk */
555 /* REUSE read_result to save the size of the compressed data */
556 read_result
=pcfdata
->cbData
;
557 /* Modify the size of the compressed data to store only a part of the */
558 /* data block into the current cabinet. This is done to prevent */
559 /* that the maximum cabinet size will be exceeded. The remainer */
560 /* will be stored into the next following cabinet. */
562 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
563 /* Substract everything except the size of the block of data */
564 /* to get it's actual size */
565 pcfdata
->cbData
= p_fci_internal
->oldCCAB
.cb
- (
566 sizeof(CFDATA
) + cbReserveCFData
+
567 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
568 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
570 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
571 sizeof(CFFOLDER
) + /* set size of new CFFolder entry */
572 p_fci_internal
->oldCCAB
.cbReserveCFFolder
);
573 /* substract the size of special header fields */
574 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
575 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
576 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
579 if (p_fci_internal
->fPrevCab
) {
580 pcfdata
->cbData
-=strlen(p_fci_internal
->szPrevCab
)+1 +
581 strlen(p_fci_internal
->szPrevDisk
)+1;
583 pcfdata
->cbData
-=strlen(p_fci_internal
->pccab
->szCab
)+1 +
584 strlen(p_fci_internal
->pccab
->szDisk
)+1;
586 savedUncomp
= pcfdata
->cbUncomp
;
587 pcfdata
->cbUncomp
= 0; /* on splitted blocks of data this is zero */
589 /* if split_block==TRUE then the above while loop won't */
590 /* be executed again */
591 split_block
=TRUE
; /* split_block is the indicator that */
592 /* a data block has been splitted across */
593 /* diffentent cabinets.*/
596 /* This should never happen !!! */
597 if (pcfdata
->cbData
==0) {
602 /* get checksum and write to cfdata.csum */
603 pcfdata
->csum
= fci_get_checksum( &(pcfdata
->cbData
),
604 sizeof(CFDATA
)+cbReserveCFData
-
605 sizeof(pcfdata
->csum
), fci_get_checksum( p_fci_internal
->data_out
, /*buffer*/
606 pcfdata
->cbData
, 0 ) );
608 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
609 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
610 buffer
, /* memory buffer */
611 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
612 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
613 /* TODO write error */
616 /* TODO error handling of err */
618 p_fci_internal
->sizeFileCFDATA2
+= sizeof(CFDATA
)+cbReserveCFData
;
620 /* write compressed data into p_fci_internal->handleCFDATA2 */
621 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
622 p_fci_internal
->data_out
, /* memory buffer */
623 pcfdata
->cbData
, /* number of bytes to copy */
624 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
625 /* TODO write error */
628 /* TODO error handling of err */
630 p_fci_internal
->sizeFileCFDATA2
+= pcfdata
->cbData
;
631 ++(p_fci_internal
->cDataBlocks
);
632 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
633 (*payload
)+=pcfdata
->cbUncomp
;
634 /* if cabinet size too large and data has been split */
635 /* write the remainer of the data block to the new CFDATA1 file */
636 if( split_block
) { /* This does not include the */
637 /* abused one (just search for "abused" )*/
638 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
639 if (p_fci_internal
->fNextCab
==FALSE
) {
640 /* TODO internal error */
644 /* set cbData the size of the remainer of the data block */
645 pcfdata
->cbData
= read_result
- pcfdata
->cbData
;
646 /*recover former value of cfdata.cbData; read_result will be the offset*/
647 read_result
-= pcfdata
->cbData
;
648 pcfdata
->cbUncomp
= savedUncomp
;
650 /* reset checksum, it will be computed later */
652 /* write cfdata WITHOUT checksum to handleCFDATA1new */
653 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
654 buffer
, /* memory buffer */
655 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
656 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
657 /* TODO write error */
660 /* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */
662 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
664 /* write compressed data into handleCFDATA1new */
665 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
666 p_fci_internal
->data_out
+ read_result
, /* memory buffer + offset */
667 /* to last part of split data */
668 pcfdata
->cbData
, /* number of bytes to copy */
669 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
670 /* TODO write error */
673 /* TODO error handling of err */
675 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
677 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
678 /* the two blocks of the split data block have been written */
679 /* dont reset split_data yet, because it is still needed see below */
682 /* report status with pfnfcis about copied size of folder */
683 if( (*pfnfcis
)(statusFolder
,
684 p_fci_internal
->statusFolderCopied
, /*cfdata.cbData(+previous ones)*/
685 p_fci_internal
->statusFolderTotal
, /* total folder size */
686 p_fci_internal
->pv
) == -1) {
687 /* TODO set error code and abort */
692 /* if cabinet size too large */
693 /* write the remaining data blocks to the new CFDATA1 file */
694 if ( split_block
) { /* This does include the */
695 /* abused one (just search for "abused" )*/
696 if (p_fci_internal
->fNextCab
==FALSE
) {
697 /* TODO internal error */
700 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
702 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
703 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/* handle */
704 buffer
, /* memory buffer */
705 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
706 err
, p_fci_internal
->pv
);
707 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
708 if (read_result
==0) break; /* ALL DATA has been copied */
709 /* TODO read error */
712 /* TODO error handling of err */
714 /* REUSE buffer p_fci_internal->data_out !!! */
715 /* read data from p_fci_internal->handleCFDATA1 to */
716 /* p_fci_internal->data_out */
717 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
718 p_fci_internal
->data_out
/* memory buffer */,
719 pcfdata
->cbData
/* number of bytes to copy */,
720 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
721 /* TODO read error */
724 /* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */
726 /* write cfdata with checksum to handleCFDATA1new */
727 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
728 buffer
, /* memory buffer */
729 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
730 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
731 /* TODO write error */
734 /* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */
736 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
738 /* write compressed data into handleCFDATA1new */
739 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
740 p_fci_internal
->data_out
, /* memory buffer */
741 pcfdata
->cbData
, /* number of bytes to copy */
742 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
743 /* TODO write error */
746 /* TODO error handling of err */
748 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
749 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
751 /* report status with pfnfcis about copied size of folder */
752 if( (*pfnfcis
)(statusFolder
,
753 p_fci_internal
->statusFolderCopied
,/*cfdata.cbData(+revious ones)*/
754 p_fci_internal
->statusFolderTotal
, /* total folder size */
755 p_fci_internal
->pv
) == -1) {
756 /* TODO set error code and abort */
761 break; /* jump out of the next while loop */
762 } /* end of if( split_data ) */
765 } /* end of fci_flushfolder_copy_cfdata */
771 static BOOL
fci_flushfolder_copy_cffolder(HFCI hfci
, int* err
, UINT cbReserveCFFolder
,
772 cab_ULONG sizeFileCFDATA2old
)
777 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
779 /* absolute offset cannot be set yet, because the size of cabinet header, */
780 /* the number of CFFOLDERs and the number of CFFILEs may change. */
781 /* Instead the size of all previous data blocks will be stored and */
782 /* the remainer of the offset will be added when the cabinet will be */
783 /* flushed to disk. */
784 /* This is exactly the way the original CABINET.DLL works!!! */
785 cffolder
.coffCabStart
=sizeFileCFDATA2old
;
787 /* set the number of this folder's CFDATA sections */
788 cffolder
.cCFData
=p_fci_internal
->cDataBlocks
;
789 /* TODO set compression type */
790 cffolder
.typeCompress
= tcompTYPE_NONE
;
792 /* write cffolder to p_fci_internal->handleCFFOLDER */
793 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
794 &cffolder
, /* memory buffer */
795 sizeof(cffolder
), /* number of bytes to copy */
796 err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
797 /* TODO write error */
800 /* TODO error handling of err */
802 p_fci_internal
->sizeFileCFFOLDER
+= sizeof(cffolder
);
804 /* add optional reserved area */
805 if (cbReserveCFFolder
!=0) {
806 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
807 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
808 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
809 p_fci_internal
->perf
->fError
= TRUE
;
810 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
813 for(i
=0;i
<cbReserveCFFolder
;) {
816 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
817 reserved
, /* memory buffer */
818 cbReserveCFFolder
, /* number of bytes to copy */
819 err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
820 PFCI_FREE(hfci
, reserved
);
821 /* TODO write error */
824 /* TODO error handling of err */
826 p_fci_internal
->sizeFileCFFOLDER
+= cbReserveCFFolder
;
828 PFCI_FREE(hfci
, reserved
);
831 } /* end of fci_flushfolder_copy_cffolder */
837 static BOOL
fci_flushfolder_copy_cffile(HFCI hfci
, int* err
, int handleCFFILE1new
,
838 cab_ULONG
*psizeFileCFFILE1new
, cab_ULONG payload
)
841 cab_ULONG read_result
;
843 cab_ULONG sizeOfFiles
=0, sizeOfFilesPrev
;
844 BOOL may_be_prev
=TRUE
;
845 cab_ULONG cbFileRemainer
=0;
846 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
847 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
848 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,0,SEEK_SET
,err
,
849 p_fci_internal
->pv
) !=0 ) {
850 /* TODO wrong return value */
852 /* TODO error handling of err */
854 /* while not all CFFILE structures have been copied do */
856 /* REUSE the variable read_result */
857 /* read data from p_fci_internal->handleCFFILE1 to cffile */
858 read_result
= PFCI_READ(hfci
,p_fci_internal
->handleCFFILE1
/* file handle */,
859 &cffile
, /* memory buffer */
860 sizeof(cffile
), /* number of bytes to copy */
861 err
, p_fci_internal
->pv
);
862 if( read_result
!= sizeof(cffile
) ) {
863 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
864 /* TODO read error */
867 /* TODO error handling of err */
869 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
870 /* position. I don't know why so I'll just omit it */
872 /* read the filename from p_fci_internal->handleCFFILE1 */
873 /* REUSE the variable read_result AGAIN */
874 /* REUSE the memory buffer PFCI(hfci)->data_out */
875 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFILE1
/*file handle*/,
876 p_fci_internal
->data_out
, /* memory buffer */
877 CB_MAX_FILENAME
, /* number of bytes to copy */
878 err
, p_fci_internal
->pv
) <2) {
879 /* TODO read error */
882 /* TODO maybe other checks of read_result */
883 /* TODO error handling of err */
886 if( strlen(p_fci_internal
->data_out
)>=CB_MAX_FILENAME
) {
887 /* TODO set error code internal error */
891 seek
+=sizeof(cffile
) + strlen(p_fci_internal
->data_out
)+1;
893 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
894 /* i.e. seek to the next CFFILE area */
895 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,
896 seek
, /* seek position*/
899 != sizeof(cffile
)+strlen(p_fci_internal
->data_out
)+1 ) {
900 /* TODO wrong return value */
902 /* TODO error handling of err */
904 /* fnfilfnfildest: placed file on cabinet */
905 if (p_fci_internal
->fNextCab
||
906 p_fci_internal
->fGetNextCabInVain
) {
907 PFCI_FILEPLACED( hfci
, &(p_fci_internal
->oldCCAB
),
908 p_fci_internal
->data_out
, /* the file name*/
909 cffile
.cbFile
, /* file size */
910 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
914 PFCI_FILEPLACED( hfci
, p_fci_internal
->pccab
,
915 p_fci_internal
->data_out
, /* the file name*/
916 cffile
.cbFile
, /* file size */
917 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
922 /* Check special iFolder values */
923 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
924 p_fci_internal
->fPrevCab
==FALSE
) {
925 /* THIS MAY NEVER HAPPEN */
926 /* TODO set error code */
929 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
930 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
) {
931 /* THIS MAY NEVER HAPPEN */
932 /* TODO set error code */
935 if( may_be_prev
&& cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
938 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& may_be_prev
==FALSE
) {
939 /* THIS MAY NEVER HAPPEN */
940 /* TODO set error code */
943 if( cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
947 sizeOfFilesPrev
=sizeOfFiles
;
948 /* Set complete size of all processed files */
949 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
950 p_fci_internal
->cbFileRemainer
!=0
952 sizeOfFiles
+=p_fci_internal
->cbFileRemainer
;
953 p_fci_internal
->cbFileRemainer
=0;
955 sizeOfFiles
+=cffile
.cbFile
;
958 /* Check if spanned file fits into this cabinet folder */
959 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& sizeOfFiles
>payload
) {
960 cffile
.iFolder
=cffileCONTINUED_PREV_AND_NEXT
;
963 /* Check if file doesn't fit into this cabinet folder */
964 if( sizeOfFiles
>payload
) {
965 cffile
.iFolder
=cffileCONTINUED_TO_NEXT
;
968 /* write cffile to p_fci_internal->handleCFFILE2 */
969 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
970 &cffile
, /* memory buffer */
971 sizeof(cffile
), /* number of bytes to copy */
972 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
973 /* TODO write error */
976 /* TODO error handling of err */
978 p_fci_internal
->sizeFileCFFILE2
+= sizeof(cffile
);
980 /* write file name to p_fci_internal->handleCFFILE2 */
981 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
982 p_fci_internal
->data_out
, /* memory buffer */
983 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
984 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
985 /* TODO write error */
988 /* TODO error handling of err */
990 p_fci_internal
->sizeFileCFFILE2
+= strlen(p_fci_internal
->data_out
)+1;
992 /* cFiles is used to count all files of a cabinet */
993 ++(p_fci_internal
->cFiles
);
995 /* This is only true for files which will be written into the */
996 /* next cabinet of the spanning folder */
997 if( sizeOfFiles
>payload
) {
999 /* Files which data will be partially written into the current cabinet */
1000 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
1001 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
1003 if( sizeOfFilesPrev
<=payload
) {
1004 /* The size of the uncompressed, data of a spanning file in a */
1006 cbFileRemainer
=sizeOfFiles
-payload
;
1008 cffile
.iFolder
=cffileCONTINUED_FROM_PREV
;
1013 /* write cffile into handleCFFILE1new */
1014 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1015 &cffile
, /* memory buffer */
1016 sizeof(cffile
), /* number of bytes to copy */
1017 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1018 /* TODO write error */
1021 /* TODO error handling of err */
1023 *psizeFileCFFILE1new
+= sizeof(cffile
);
1024 /* write name of file into handleCFFILE1new */
1025 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1026 p_fci_internal
->data_out
, /* memory buffer */
1027 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1028 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1029 /* TODO write error */
1032 /* TODO error handling of err */
1034 *psizeFileCFFILE1new
+= strlen(p_fci_internal
->data_out
)+1;
1037 } /* END OF while */
1038 p_fci_internal
->cbFileRemainer
=cbFileRemainer
;
1040 } /* end of fci_flushfolder_copy_cffile */
1045 static BOOL
fci_flush_folder(
1048 PFNFCIGETNEXTCABINET pfnfcignc
,
1049 PFNFCISTATUS pfnfcis
)
1052 int handleCFDATA1new
; /* handle for new temp file */
1053 char szFileNameCFDATA1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1054 int handleCFFILE1new
; /* handle for new temp file */
1055 char szFileNameCFFILE1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1056 UINT cbReserveCFData
, cbReserveCFFolder
;
1058 cab_ULONG sizeFileCFDATA1new
=0;
1059 cab_ULONG sizeFileCFFILE1new
=0;
1060 cab_ULONG sizeFileCFDATA2old
;
1062 cab_ULONG read_result
;
1063 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1066 if (!REALLY_IS_FCI(hfci
)) {
1067 SetLastError(ERROR_INVALID_HANDLE
);
1071 if ((!pfnfcignc
) || (!pfnfcis
)) {
1072 p_fci_internal
->perf
->erfOper
= FCIERR_NONE
;
1073 p_fci_internal
->perf
->erfType
= ERROR_BAD_ARGUMENTS
;
1074 p_fci_internal
->perf
->fError
= TRUE
;
1076 SetLastError(ERROR_BAD_ARGUMENTS
);
1080 if( p_fci_internal
->fGetNextCabInVain
&&
1081 p_fci_internal
->fNextCab
){
1082 /* TODO internal error */
1086 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1087 /* this function will return TRUE */
1088 if( p_fci_internal
->sizeFileCFFILE1
== 0 ) {
1089 if ( p_fci_internal
->sizeFileCFDATA1
!= 0 ) {
1090 /* TODO error handling */
1096 if (p_fci_internal
->data_in
==NULL
|| p_fci_internal
->data_out
==NULL
) {
1097 /* TODO error handling */
1101 /* FCIFlushFolder has already been called... */
1102 if (p_fci_internal
->fSplitFolder
&& p_fci_internal
->sizeFileCFFILE2
!=0) {
1103 if (p_fci_internal
->sizeFileCFFILE2
==0) {
1104 /* TODO set error code */
1110 /* TODO check what will happen when return FALSE later */
1111 /* and p_fci_internal->fSplitFolder is set to FALSE */
1112 p_fci_internal
->fSplitFolder
=FALSE
;
1115 if( p_fci_internal
->fGetNextCabInVain
||
1116 p_fci_internal
->fNextCab
){
1117 cbReserveCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1118 cbReserveCFFolder
= p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1120 cbReserveCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1121 cbReserveCFFolder
= p_fci_internal
->pccab
->cbReserveCFFolder
;
1125 /* if there is data in p_fci_internal->data_in */
1126 if (p_fci_internal
->cdata_in
!=0) {
1128 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
1131 /* reset to get the number of data blocks of this folder which are */
1132 /* actually in this cabinet ( at least partially ) */
1133 p_fci_internal
->cDataBlocks
=0;
1135 if ( p_fci_internal
->fNextCab
||
1136 p_fci_internal
->fGetNextCabInVain
) {
1137 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
1138 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1139 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1140 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1141 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1145 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
+
1146 p_fci_internal
->pccab
->cbReserveCFFolder
;
1147 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1148 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1149 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1153 if (p_fci_internal
->fPrevCab
) {
1154 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1155 strlen(p_fci_internal
->szPrevDisk
)+1;
1157 if (p_fci_internal
->fNextCab
) {
1158 read_result
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1159 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1162 p_fci_internal
->statusFolderTotal
= sizeof(CFHEADER
)+read_result
+
1163 sizeof(CFFOLDER
) + p_fci_internal
->sizeFileCFFILE2
+
1164 p_fci_internal
->sizeFileCFDATA2
+ p_fci_internal
->sizeFileCFFILE1
+
1165 p_fci_internal
->sizeFileCFDATA1
;
1166 p_fci_internal
->statusFolderCopied
= 0;
1168 /* report status with pfnfcis about copied size of folder */
1169 if( (*pfnfcis
)(statusFolder
, p_fci_internal
->statusFolderCopied
,
1170 p_fci_internal
->statusFolderTotal
, /* TODO total folder size */
1171 p_fci_internal
->pv
) == -1) {
1172 /* TODO set error code and abort */
1176 /* get a new temp file */
1177 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFDATA1new
,CB_MAX_FILENAME
)) {
1178 /* TODO error handling */
1182 if ( strlen(szFileNameCFDATA1new
) >= CB_MAX_FILENAME
) {
1183 /* TODO set error code */
1186 handleCFDATA1new
= PFCI_OPEN(hfci
,szFileNameCFDATA1new
,34050,384,&err
,
1187 p_fci_internal
->pv
);
1189 /* get a new temp file */
1190 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFFILE1new
,CB_MAX_FILENAME
)) {
1191 /* TODO error handling */
1192 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1193 /* TODO error handling of err */
1197 if ( strlen(szFileNameCFFILE1new
) >= CB_MAX_FILENAME
) {
1198 /* TODO set error code */
1199 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1200 /* TODO error handling of err */
1203 handleCFFILE1new
= PFCI_OPEN(hfci
,szFileNameCFFILE1new
,34050,384,&err
,
1204 p_fci_internal
->pv
);
1206 /* USE the variable read_result */
1207 if ( p_fci_internal
->fNextCab
||
1208 p_fci_internal
->fGetNextCabInVain
) {
1209 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1210 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1211 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1212 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1216 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
;
1217 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1218 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1219 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1223 if (p_fci_internal
->fPrevCab
) {
1224 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1225 strlen(p_fci_internal
->szPrevDisk
)+1;
1227 read_result
+= sizeof(CFHEADER
) + p_fci_internal
->sizeFileCFDATA2
+
1228 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
;
1230 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
1231 read_result
+= sizeof(CFFOLDER
)+p_fci_internal
->pccab
->cbReserveCFFolder
;
1234 /* Check if multiple cabinets have to be created. */
1236 /* Might be too much data for the maximum allowed cabinet size.*/
1237 /* When any further data will be added later, it might not */
1238 /* be possible to flush the cabinet, because there might */
1239 /* not be enough space to store the name of the following */
1240 /* cabinet and name of the corresponding disk. */
1241 /* So take care of this and get the name of the next cabinet */
1242 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
1243 p_fci_internal
->fNextCab
==FALSE
&&
1246 p_fci_internal
->pccab
->cb
< read_result
+
1247 p_fci_internal
->sizeFileCFDATA1
+
1248 p_fci_internal
->sizeFileCFFILE1
+
1249 CB_MAX_CABINET_NAME
+ /* next cabinet name */
1250 CB_MAX_DISK_NAME
/* next disk name */
1255 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
1256 /* increment cabinet index */
1257 ++(p_fci_internal
->pccab
->iCab
);
1258 /* get name of next cabinet */
1259 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0, /* estimated size of cab */
1260 p_fci_internal
->pv
)) {
1261 /* TODO error handling */
1262 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1263 /* TODO error handling of err */
1264 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1265 /* TODO error handling of err */
1269 /* Skip a few lines of code. This is catched by the next if. */
1270 p_fci_internal
->fGetNextCabInVain
=TRUE
;
1273 /* too much data for cabinet */
1274 if( (p_fci_internal
->fGetNextCabInVain
||
1275 p_fci_internal
->fNextCab
) &&
1278 p_fci_internal
->oldCCAB
.cb
< read_result
+
1279 p_fci_internal
->sizeFileCFDATA1
+
1280 p_fci_internal
->sizeFileCFFILE1
+
1281 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1282 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1286 p_fci_internal
->fGetNextCabInVain
=FALSE
;
1287 p_fci_internal
->fNextCab
=TRUE
;
1289 /* return FALSE if there is not enough space left*/
1290 /* this should never happen */
1291 if (p_fci_internal
->oldCCAB
.cb
<=
1292 p_fci_internal
->sizeFileCFFILE1
+
1294 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1295 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1298 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1299 /* TODO error handling of err */
1300 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1301 /* TODO error handling of err */
1303 /* close and delete p_fci_internal->handleCFFILE1 */
1304 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1305 /* TODO error handling of err */
1306 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1307 /* TODO error handling of err */
1312 /* the folder will be split across cabinets */
1313 p_fci_internal
->fSplitFolder
=TRUE
;
1316 /* this should never happen */
1317 if (p_fci_internal
->fNextCab
) {
1318 /* TODO internal error */
1323 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1324 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA1
,0,SEEK_SET
,&err
,
1325 p_fci_internal
->pv
) !=0 ) {
1326 /* TODO wrong return value */
1327 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1328 /* TODO error handling of err */
1329 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1330 /* TODO error handling of err */
1333 /* TODO error handling of err */
1335 /* save size of file CFDATA2 - required for the folder's offset to data */
1336 sizeFileCFDATA2old
= p_fci_internal
->sizeFileCFDATA2
;
1338 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFData
+sizeof(CFDATA
)))) {
1339 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
1340 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1341 p_fci_internal
->perf
->fError
= TRUE
;
1342 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1343 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1344 /* TODO error handling of err */
1345 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1346 /* TODO error handling of err */
1350 if(!fci_flushfolder_copy_cfdata(hfci
, reserved
, cbReserveCFData
, pfnfcis
, &err
,
1351 handleCFDATA1new
, &sizeFileCFDATA1new
, &payload
1353 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1354 /* TODO error handling of err */
1355 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1356 /* TODO error handling of err */
1357 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1358 /* TODO error handling of err */
1359 PFCI_FREE(hfci
,reserved
);
1363 PFCI_FREE(hfci
,reserved
);
1365 if(!fci_flushfolder_copy_cffolder(hfci
, &err
, cbReserveCFFolder
,
1366 sizeFileCFDATA2old
)) {
1367 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1368 /* TODO error handling of err */
1369 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1370 /* TODO error handling of err */
1371 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1372 /* TODO error handling of err */
1376 if(!fci_flushfolder_copy_cffile(hfci
, &err
, handleCFFILE1new
,
1377 &sizeFileCFFILE1new
, payload
)) {
1378 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1379 /* TODO error handling of err */
1380 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1381 /* TODO error handling of err */
1382 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1383 /* TODO error handling of err */
1384 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1385 /* TODO error handling of err */
1389 /* close and delete p_fci_internal->handleCFDATA1 */
1390 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
1391 /* TODO error handling of err */
1392 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFDATA1
,&err
,p_fci_internal
->pv
);
1393 /* TODO error handling of err */
1395 /* put new CFDATA1 into hfci */
1396 memcpy(p_fci_internal
->szFileNameCFDATA1
,szFileNameCFDATA1new
,
1399 /* put CFDATA1 file handle */
1400 PFCI_INT(hfci
)->handleCFDATA1
= handleCFDATA1new
;
1402 PFCI_INT(hfci
)->sizeFileCFDATA1
= sizeFileCFDATA1new
;
1404 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1405 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFFILE1
,&err
,PFCI_INT(hfci
)->pv
);
1406 /* TODO error handling of err */
1407 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFFILE1
,&err
,p_fci_internal
->pv
);
1408 /* TODO error handling of err */
1410 /* put new CFFILE1 into hfci */
1411 memcpy(p_fci_internal
->szFileNameCFFILE1
,szFileNameCFFILE1new
,
1414 /* put CFFILE1 file handle */
1415 p_fci_internal
->handleCFFILE1
= handleCFFILE1new
;
1417 p_fci_internal
->sizeFileCFFILE1
= sizeFileCFFILE1new
;
1419 ++(p_fci_internal
->cFolders
);
1421 /* reset CFFolder specific information */
1422 p_fci_internal
->cDataBlocks
=0;
1423 p_fci_internal
->cCompressedBytesInFolder
=0;
1426 } /* end of fci_flush_folder */
1431 static BOOL
fci_flush_cabinet(
1434 PFNFCIGETNEXTCABINET pfnfcignc
,
1435 PFNFCISTATUS pfnfcis
)
1440 cab_UWORD cbCFHeader
;
1441 cab_UBYTE cbCFFolder
;
1445 cab_ULONG read_result
;
1446 int handleCABINET
; /* file handle for cabinet */
1447 char pszFileNameCABINET
[CB_MAX_CAB_PATH
+CB_MAX_CABINET_NAME
];/* name buffer */
1448 UINT cbReserveCFHeader
, cbReserveCFFolder
, i
;
1450 BOOL returntrue
=FALSE
;
1451 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1453 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1455 /* when FCIFlushCabinet was or FCIAddFile wasn't called */
1456 if( p_fci_internal
->sizeFileCFFILE1
==0 && fGetNextCab
) {
1460 if (!fci_flush_folder(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)){
1461 /* TODO set error */
1465 if(returntrue
) return TRUE
;
1467 if (p_fci_internal
->fSplitFolder
&& p_fci_internal
->fNextCab
==FALSE
) {
1468 /* TODO internal error */
1472 if( p_fci_internal
->fNextCab
||
1473 p_fci_internal
->fGetNextCabInVain
) {
1474 cbReserveCFFolder
=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1475 cbReserveCFHeader
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1477 if (strlen(p_fci_internal
->oldCCAB
.szCabPath
)>=CB_MAX_CAB_PATH
||
1478 strlen(p_fci_internal
->oldCCAB
.szCab
)>=CB_MAX_CABINET_NAME
) {
1479 /* TODO set error */
1482 /* get the full name of the cabinet */
1483 memcpy(pszFileNameCABINET
,p_fci_internal
->oldCCAB
.szCabPath
,
1485 memcpy(pszFileNameCABINET
+strlen(pszFileNameCABINET
),
1486 p_fci_internal
->oldCCAB
.szCab
, CB_MAX_CABINET_NAME
);
1488 cbReserveCFFolder
=p_fci_internal
->pccab
->cbReserveCFFolder
;
1489 cbReserveCFHeader
=p_fci_internal
->pccab
->cbReserveCFHeader
;
1491 if (strlen(p_fci_internal
->pccab
->szCabPath
)>=CB_MAX_CAB_PATH
||
1492 strlen(p_fci_internal
->pccab
->szCab
)>=CB_MAX_CABINET_NAME
) {
1493 /* TODO set error */
1496 /* get the full name of the cabinet */
1497 memcpy(pszFileNameCABINET
,p_fci_internal
->pccab
->szCabPath
,
1499 memcpy(pszFileNameCABINET
+strlen(pszFileNameCABINET
),
1500 p_fci_internal
->pccab
->szCab
, CB_MAX_CABINET_NAME
);
1503 /* create the cabinet */
1504 handleCABINET
= PFCI_OPEN(hfci
, pszFileNameCABINET
,
1505 33538, 384, &err
, p_fci_internal
->pv
);
1506 /* TODO check handle */
1507 /* TODO error checking of err */
1509 memcpy(cfheader
.signature
,"!CAB",4);
1510 cfheader
.reserved1
=0;
1511 cfheader
.cbCabinet
= /* size of the cabinet file in bytes */
1513 p_fci_internal
->sizeFileCFFOLDER
+
1514 p_fci_internal
->sizeFileCFFILE2
+
1515 p_fci_internal
->sizeFileCFDATA2
;
1517 if (p_fci_internal
->fPrevCab
) {
1518 cfheader
.cbCabinet
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1519 strlen(p_fci_internal
->szPrevDisk
)+1;
1521 if (p_fci_internal
->fNextCab
) {
1522 cfheader
.cbCabinet
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1523 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1525 if( p_fci_internal
->fNextCab
||
1526 p_fci_internal
->fGetNextCabInVain
) {
1527 cfheader
.cbCabinet
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1528 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1529 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1530 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1531 cfheader
.cbCabinet
+=4;
1534 cfheader
.cbCabinet
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1535 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1536 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1537 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1538 cfheader
.cbCabinet
+=4;
1542 cfheader
.reserved2
=0;
1543 cfheader
.coffFiles
= /* offset to first CFFILE section */
1544 cfheader
.cbCabinet
- p_fci_internal
->sizeFileCFFILE2
-
1545 p_fci_internal
->sizeFileCFDATA2
;
1547 cfheader
.reserved3
=0;
1548 cfheader
.versionMinor
=3;
1549 cfheader
.versionMajor
=1;
1550 /* number of CFFOLDER entries in the cabinet */
1551 cfheader
.cFolders
=p_fci_internal
->cFolders
;
1552 /* number of CFFILE entries in the cabinet */
1553 cfheader
.cFiles
=p_fci_internal
->cFiles
;
1554 cfheader
.flags
=0; /* 1=prev cab, 2=next cabinet, 4=reserved setions */
1556 if( p_fci_internal
->fPrevCab
) {
1557 cfheader
.flags
= cfheadPREV_CABINET
;
1560 if( p_fci_internal
->fNextCab
) {
1561 cfheader
.flags
|= cfheadNEXT_CABINET
;
1564 if( p_fci_internal
->fNextCab
||
1565 p_fci_internal
->fGetNextCabInVain
) {
1566 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1567 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1568 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1569 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1571 cfheader
.setID
= p_fci_internal
->oldCCAB
.setID
;
1572 cfheader
.iCabinet
= p_fci_internal
->oldCCAB
.iCab
-1;
1574 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1575 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1576 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1577 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1579 cfheader
.setID
= p_fci_internal
->pccab
->setID
;
1580 cfheader
.iCabinet
= p_fci_internal
->pccab
->iCab
-1;
1583 /* write CFHEADER into cabinet file */
1584 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1585 &cfheader
, /* memory buffer */
1586 sizeof(cfheader
), /* number of bytes to copy */
1587 &err
, p_fci_internal
->pv
) != sizeof(cfheader
) ) {
1588 /* TODO write error */
1591 /* TODO error handling of err */
1593 if( cfheader
.flags
& cfheadRESERVE_PRESENT
) {
1594 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1595 cfreserved
.cbCFHeader
= cbReserveCFHeader
;
1596 cfreserved
.cbCFFolder
= cbReserveCFFolder
;
1597 if( p_fci_internal
->fNextCab
||
1598 p_fci_internal
->fGetNextCabInVain
) {
1599 cfreserved
.cbCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1601 cfreserved
.cbCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1603 /* write reserved info into cabinet file */
1604 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1605 &cfreserved
, /* memory buffer */
1606 sizeof(cfreserved
), /* number of bytes to copy */
1607 &err
, p_fci_internal
->pv
) != sizeof(cfreserved
) ) {
1608 /* TODO write error */
1611 /* TODO error handling of err */
1614 /* add optional reserved area */
1615 if (cbReserveCFHeader
!=0) {
1616 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFHeader
))) {
1617 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
1618 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1619 p_fci_internal
->perf
->fError
= TRUE
;
1620 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1623 for(i
=0;i
<cbReserveCFHeader
;) {
1626 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1627 reserved
, /* memory buffer */
1628 cbReserveCFHeader
, /* number of bytes to copy */
1629 &err
, p_fci_internal
->pv
) != cbReserveCFHeader
) {
1630 PFCI_FREE(hfci
, reserved
);
1631 /* TODO write error */
1634 /* TODO error handling of err */
1635 PFCI_FREE(hfci
, reserved
);
1638 if( cfheader
.flags
& cfheadPREV_CABINET
) {
1639 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1640 p_fci_internal
->szPrevCab
, /* memory buffer */
1641 strlen(p_fci_internal
->szPrevCab
)+1, /* number of bytes to copy */
1642 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevCab
)+1 ) {
1643 /* TODO write error */
1646 /* TODO error handling of err */
1648 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1649 p_fci_internal
->szPrevDisk
, /* memory buffer */
1650 strlen(p_fci_internal
->szPrevDisk
)+1, /* number of bytes to copy */
1651 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevDisk
)+1 ) {
1652 /* TODO write error */
1655 /* TODO error handling of err */
1658 if( cfheader
.flags
& cfheadNEXT_CABINET
) {
1659 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1660 p_fci_internal
->pccab
->szCab
, /* memory buffer */
1661 strlen(p_fci_internal
->pccab
->szCab
)+1, /* number of bytes to copy */
1662 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szCab
)+1 ) {
1663 /* TODO write error */
1666 /* TODO error handling of err */
1668 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1669 p_fci_internal
->pccab
->szDisk
, /* memory buffer */
1670 strlen(p_fci_internal
->pccab
->szDisk
)+1, /* number of bytes to copy */
1671 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szDisk
)+1 ) {
1672 /* TODO write error */
1675 /* TODO error handling of err */
1678 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1679 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFOLDER
,
1680 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1681 /* TODO wrong return value */
1683 /* TODO error handling of err */
1685 /* while not all CFFOLDER structures have been copied into the cabinet do */
1687 /* use the variable read_result */
1688 /* read cffolder of p_fci_internal->handleCFFOLDER */
1689 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* handle */
1690 &cffolder
, /* memory buffer */
1691 sizeof(cffolder
), /* number of bytes to copy */
1692 &err
, p_fci_internal
->pv
);
1693 if( read_result
!= sizeof(cffolder
) ) {
1694 if( read_result
== 0 ) break; /*ALL CFFOLDER structures have been copied*/
1695 /* TODO read error */
1698 /* TODO error handling of err */
1700 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1701 cffolder
.coffCabStart
+=
1702 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
1704 if( p_fci_internal
->fNextCab
||
1705 p_fci_internal
->fGetNextCabInVain
) {
1706 cffolder
.coffCabStart
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1708 cffolder
.coffCabStart
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1711 if (p_fci_internal
->fPrevCab
) {
1712 cffolder
.coffCabStart
+= strlen(p_fci_internal
->szPrevCab
)+1 +
1713 strlen(p_fci_internal
->szPrevDisk
)+1;
1716 if (p_fci_internal
->fNextCab
) {
1717 cffolder
.coffCabStart
+= strlen(p_fci_internal
->oldCCAB
.szCab
)+1 +
1718 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1;
1721 if( p_fci_internal
->fNextCab
||
1722 p_fci_internal
->fGetNextCabInVain
) {
1723 cffolder
.coffCabStart
+= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1724 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1725 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1726 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1727 cffolder
.coffCabStart
+= 4;
1730 cffolder
.coffCabStart
+= p_fci_internal
->pccab
->cbReserveCFHeader
;
1731 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1732 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1733 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1734 cffolder
.coffCabStart
+= 4;
1738 /* write cffolder to cabinet file */
1739 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1740 &cffolder
, /* memory buffer */
1741 sizeof(cffolder
), /* number of bytes to copy */
1742 &err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
1743 /* TODO write error */
1746 /* TODO error handling of err */
1748 /* add optional reserved area */
1750 /* This allocation and freeing at each CFFolder block is a bit */
1751 /* inefficent, but it's harder to forget about freeing the buffer :-). */
1752 /* Reserved areas are used seldom besides that... */
1753 if (cbReserveCFFolder
!=0) {
1754 if(!(reserved
= PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
1755 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
1756 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1757 p_fci_internal
->perf
->fError
= TRUE
;
1758 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1762 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
1763 reserved
, /* memory buffer */
1764 cbReserveCFFolder
, /* number of bytes to copy */
1765 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1766 PFCI_FREE(hfci
, reserved
);
1767 /* TODO read error */
1770 /* TODO error handling of err */
1772 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1773 reserved
, /* memory buffer */
1774 cbReserveCFFolder
, /* number of bytes to copy */
1775 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1776 PFCI_FREE(hfci
, reserved
);
1777 /* TODO read error */
1780 /* TODO error handling of err */
1782 PFCI_FREE(hfci
, reserved
);
1785 } /* END OF while */
1787 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1788 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE2
,
1789 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1790 /* TODO wrong return value */
1792 /* TODO error handling of err */
1794 /* while not all CFFILE structures have been copied to the cabinet do */
1796 /* REUSE the variable read_result */
1797 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1798 /* read a block from p_fci_internal->handleCFFILE2 */
1799 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFILE2
/* handle */,
1800 p_fci_internal
->data_out
, /* memory buffer */
1801 32768, /* number of bytes to copy */
1802 &err
, p_fci_internal
->pv
);
1803 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
1804 /* TODO error handling of err */
1806 /* write the block to the cabinet file */
1807 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1808 p_fci_internal
->data_out
, /* memory buffer */
1809 read_result
, /* number of bytes to copy */
1810 &err
, p_fci_internal
->pv
) != read_result
) {
1811 /* TODO write error */
1814 /* TODO error handling of err */
1816 if (p_fci_internal
->fSplitFolder
==FALSE
) {
1817 p_fci_internal
->statusFolderCopied
= 0;
1818 p_fci_internal
->statusFolderTotal
= p_fci_internal
->sizeFileCFDATA2
+
1819 p_fci_internal
->sizeFileCFFILE2
;
1821 p_fci_internal
->statusFolderCopied
+= read_result
;
1823 /* TODO is this correct */
1824 /* report status with pfnfcis about copied size of folder */
1825 if( (*pfnfcis
)(statusFolder
,
1826 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
1827 p_fci_internal
->statusFolderTotal
, /* total size of folder */
1828 p_fci_internal
->pv
) == -1) {
1829 /* TODO set error code and abort */
1833 } /* END OF while */
1835 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1836 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA2
,
1837 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1838 /* TODO wrong return value */
1841 /* TODO error handling of err */
1843 /* reset the number of folders for the next cabinet */
1844 p_fci_internal
->cFolders
=0;
1845 /* reset the number of files for the next cabinet */
1846 p_fci_internal
->cFiles
=0;
1848 /* while not all CFDATA structures have been copied to the cabinet do */
1850 /* REUSE the variable read_result AGAIN */
1851 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1852 /* read a block from p_fci_internal->handleCFDATA2 */
1853 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA2
/* handle */,
1854 p_fci_internal
->data_out
, /* memory buffer */
1855 32768, /* number of bytes to copy */
1856 &err
, p_fci_internal
->pv
);
1857 if( read_result
== 0 ) break; /* ALL CFDATA structures have been copied */
1858 /* TODO error handling of err */
1860 /* write the block to the cabinet file */
1861 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1862 p_fci_internal
->data_out
, /* memory buffer */
1863 read_result
, /* number of bytes to copy */
1864 &err
, p_fci_internal
->pv
) != read_result
) {
1865 /* TODO write error */
1868 /* TODO error handling of err */
1870 p_fci_internal
->statusFolderCopied
+= read_result
;
1871 /* report status with pfnfcis about copied size of folder */
1872 if( (*pfnfcis
)(statusFolder
,
1873 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
1874 p_fci_internal
->statusFolderTotal
, /* total size of folder */
1875 p_fci_internal
->pv
) == -1) {
1876 /* TODO set error code and abort */
1879 } /* END OF while */
1881 /* set seek of the cabinet file to 0 */
1882 if( PFCI_SEEK(hfci
, handleCABINET
,
1883 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1884 /* TODO wrong return value */
1886 /* TODO error handling of err */
1888 /* write the signature "MSCF" into the cabinet file */
1889 memcpy( cfheader
.signature
, "MSCF", 4 );
1890 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1891 &cfheader
, /* memory buffer */
1892 4, /* number of bytes to copy */
1893 &err
, p_fci_internal
->pv
) != 4 ) {
1894 /* TODO write error */
1897 /* TODO error handling of err */
1899 /* close the cabinet file */
1900 PFCI_CLOSE(hfci
,handleCABINET
,&err
,p_fci_internal
->pv
);
1901 /* TODO error handling of err */
1904 /* COPIED FROM FCIDestroy */
1906 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
1907 /* TODO error handling of err */
1908 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
1909 p_fci_internal
->pv
);
1910 /* TODO error handling of err */
1911 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
1912 /* TODO error handling of err */
1913 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
1914 p_fci_internal
->pv
);
1915 /* TODO error handling of err */
1916 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
1917 /* TODO error handling of err */
1918 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
1919 p_fci_internal
->pv
);
1920 /* TODO error handling of err */
1922 /* END OF copied from FCIDestroy */
1924 /* get 3 temporary files and open them */
1925 /* write names and handles to hfci */
1928 p_fci_internal
->sizeFileCFDATA2
= 0;
1929 p_fci_internal
->sizeFileCFFILE2
= 0;
1930 p_fci_internal
->sizeFileCFFOLDER
= 0;
1932 /* COPIED FROM FCICreate */
1934 /* CFDATA with checksum and ready to be copied into cabinet */
1935 if( !PFCI_GETTEMPFILE(hfci
, p_fci_internal
->szFileNameCFDATA2
,
1937 /* TODO error handling */
1941 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
1942 /* TODO set error code */
1945 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
1946 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, p_fci_internal
->pv
);
1947 /* TODO check handle */
1948 /* TODO error checking of err */
1950 /* array of all CFFILE in a folder, ready to be copied into cabinet */
1951 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
1953 /* TODO error handling */
1957 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
1958 /* TODO set error code */
1961 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
1962 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, p_fci_internal
->pv
);
1963 /* TODO check handle */
1964 /* TODO error checking of err */
1966 /* array of all CFFILE in a folder, ready to be copied into cabinet */
1967 if (!PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,CB_MAX_FILENAME
)) {
1968 /* TODO error handling */
1972 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
1973 /* TODO set error code */
1976 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
1977 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, p_fci_internal
->pv
);
1978 /* TODO check handle */
1979 /* TODO error checking of err */
1981 /* END OF copied from FCICreate */
1984 /* TODO close and delete new files when return FALSE */
1987 /* report status with pfnfcis about copied size of folder */
1988 if( (*pfnfcis
)(statusCabinet
, p_fci_internal
->statusFolderTotal
, /* TODO estimated cabinet file size */
1989 cfheader
.cbCabinet
, /* real cabinet file size */ p_fci_internal
->pv
) == -1) {
1990 /* TODO set error code and abort */
1994 p_fci_internal
->fPrevCab
=TRUE
;
1995 /* The sections szPrevCab and szPrevDisk are not being updated, because */
1996 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
1998 if (p_fci_internal
->fNextCab
) {
1999 p_fci_internal
->fNextCab
=FALSE
;
2001 if (p_fci_internal
->sizeFileCFFILE1
==0 && p_fci_internal
->sizeFileCFDATA1
!=0) {
2002 /* THIS CAN NEVER HAPPEN */
2003 /* TODO set error code */
2007 /* COPIED FROM FCIAddFile and modified */
2009 /* REUSE the variable read_result */
2010 if (p_fci_internal
->fGetNextCabInVain
) {
2011 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
2012 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2013 read_result
+=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2015 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2016 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2017 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2021 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
;
2022 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2023 read_result
+=p_fci_internal
->pccab
->cbReserveCFFolder
;
2025 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2026 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2027 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2031 if ( p_fci_internal
->fPrevCab
) {
2032 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2033 strlen(p_fci_internal
->szPrevDisk
)+1;
2035 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2036 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2037 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2039 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2041 if( p_fci_internal
->fNewPrevious
) {
2042 memcpy(p_fci_internal
->szPrevCab
, p_fci_internal
->oldCCAB
.szCab
,
2043 CB_MAX_CABINET_NAME
);
2044 memcpy(p_fci_internal
->szPrevDisk
, p_fci_internal
->oldCCAB
.szDisk
,
2046 p_fci_internal
->fNewPrevious
=FALSE
;
2049 /* too much data for the maximum size of a cabinet */
2050 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2051 p_fci_internal
->pccab
->cb
< read_result
) {
2052 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2055 /* Might be too much data for the maximum size of a cabinet.*/
2056 /* When any further data will be added later, it might not */
2057 /* be possible to flush the cabinet, because there might */
2058 /* not be enough space to store the name of the following */
2059 /* cabinet and name of the corresponding disk. */
2060 /* So take care of this and get the name of the next cabinet */
2061 if (p_fci_internal
->fGetNextCabInVain
==FALSE
&& (
2062 p_fci_internal
->pccab
->cb
< read_result
+
2063 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2066 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2067 /* increment cabinet index */
2068 ++(p_fci_internal
->pccab
->iCab
);
2069 /* get name of next cabinet */
2070 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0, /* estimated size of cab */
2071 p_fci_internal
->pv
)) {
2072 /* TODO error handling */
2075 /* Skip a few lines of code. This is catched by the next if. */
2076 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2079 /* too much data for cabinet */
2080 if (p_fci_internal
->fGetNextCabInVain
&& (
2081 p_fci_internal
->oldCCAB
.cb
< read_result
+
2082 strlen(p_fci_internal
->oldCCAB
.szCab
)+1+
2083 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1
2085 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2086 p_fci_internal
->fNextCab
=TRUE
;
2087 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2090 /* if the FolderThreshold has been reached flush the folder automatically */
2091 if( p_fci_internal
->fGetNextCabInVain
) {
2092 if( p_fci_internal
->cCompressedBytesInFolder
>=
2093 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2094 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2097 if( p_fci_internal
->cCompressedBytesInFolder
>=
2098 p_fci_internal
->pccab
->cbFolderThresh
) {
2099 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2103 /* END OF COPIED FROM FCIAddFile and modified */
2105 if( p_fci_internal
->sizeFileCFFILE1
>0 ) {
2106 if( !FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
) ) return FALSE
;
2107 p_fci_internal
->fNewPrevious
=TRUE
;
2110 p_fci_internal
->fNewPrevious
=FALSE
;
2111 if( p_fci_internal
->sizeFileCFFILE1
>0 || p_fci_internal
->sizeFileCFDATA1
) {
2112 /* THIS MAY NEVER HAPPEN */
2113 /* TODO set error structures */
2119 } /* end of fci_flush_cabinet */
2125 /***********************************************************************
2126 * FCIAddFile (CABINET.11)
2128 * FCIAddFile adds a file to the to be created cabinet file
2131 * hfci [I] An HFCI from FCICreate
2132 * pszSourceFile [I] A pointer to a C string which contains the name and
2133 * location of the file which will be added to the cabinet
2134 * pszFileName [I] A pointer to a C string which contains the name under
2135 * which the file will be stored in the cabinet
2136 * fExecute [I] A boolean value which indicates if the file should be
2137 * executed after extraction of self extracting
2139 * pfnfcignc [I] A pointer to a function which gets information about
2141 * pfnfcis [IO] A pointer to a function which will report status
2142 * information about the compression process
2143 * pfnfcioi [I] A pointer to a function which reports file attributes
2144 * and time and date information
2145 * typeCompress [I] Compression type
2148 * On success, returns TRUE
2149 * On failure, returns FALSE
2155 BOOL __cdecl
FCIAddFile(
2157 char *pszSourceFile
,
2160 PFNFCIGETNEXTCABINET pfnfcignc
,
2161 PFNFCISTATUS pfnfcis
,
2162 PFNFCIGETOPENINFO pfnfcigoi
,
2167 cab_ULONG read_result
;
2169 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2172 if (!REALLY_IS_FCI(hfci
)) {
2173 SetLastError(ERROR_INVALID_HANDLE
);
2177 if ((!pszSourceFile
) || (!pszFileName
) || (!pfnfcignc
) || (!pfnfcis
) ||
2178 (!pfnfcigoi
) || strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2179 p_fci_internal
->perf
->erfOper
= FCIERR_NONE
;
2180 p_fci_internal
->perf
->erfType
= ERROR_BAD_ARGUMENTS
;
2181 p_fci_internal
->perf
->fError
= TRUE
;
2183 SetLastError(ERROR_BAD_ARGUMENTS
);
2187 /* TODO check if pszSourceFile??? */
2189 if(p_fci_internal
->fGetNextCabInVain
&& p_fci_internal
->fNextCab
) {
2190 /* TODO internal error */
2194 if(p_fci_internal
->fNextCab
) {
2195 /* TODO internal error */
2199 cffile
.cbFile
=0; /* size of the to be added file*/
2200 /* offset of the uncompressed file in the folder */
2201 cffile
.uoffFolderStart
=p_fci_internal
->cDataBlocks
*CAB_BLOCKMAX
+ p_fci_internal
->cdata_in
;
2202 /* number of folder in the cabinet or special 0=first */
2203 cffile
.iFolder
= p_fci_internal
->cFolders
;
2205 /* allocation of memory */
2206 if (p_fci_internal
->data_in
==NULL
) {
2207 if (p_fci_internal
->cdata_in
!=0) {
2208 /* TODO error handling */
2211 if (p_fci_internal
->data_out
!=NULL
) {
2212 /* TODO error handling */
2215 if(!(p_fci_internal
->data_in
= (char*)PFCI_ALLOC(hfci
,CB_MAX_CHUNK
))) {
2216 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
2217 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
2218 p_fci_internal
->perf
->fError
= TRUE
;
2219 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2222 if (p_fci_internal
->data_out
==NULL
) {
2223 if(!(p_fci_internal
->data_out
= PFCI_ALLOC(hfci
, 2 * CB_MAX_CHUNK
))){
2224 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
2225 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
2226 p_fci_internal
->perf
->fError
= TRUE
;
2227 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2233 if (p_fci_internal
->data_out
==NULL
) {
2234 PFCI_FREE(hfci
,p_fci_internal
->data_in
);
2235 /* TODO error handling */
2239 /* get information about the file */
2240 file_handle
=(*pfnfcigoi
)(pszSourceFile
, &(cffile
.date
), &(cffile
.time
),
2241 &(cffile
.attribs
), &err
, p_fci_internal
->pv
);
2242 /* TODO check file_handle */
2243 /* TODO error handling of err */
2245 if (fExecute
) { cffile
.attribs
|= _A_EXEC
; }
2247 /* REUSE the variable read_result */
2248 if (p_fci_internal
->fGetNextCabInVain
) {
2249 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2250 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2251 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2252 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2253 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2257 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2258 p_fci_internal
->pccab
->cbReserveCFFolder
;
2259 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2260 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2261 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2265 if ( p_fci_internal
->fPrevCab
) {
2266 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2267 strlen(p_fci_internal
->szPrevDisk
)+1;
2269 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2270 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2271 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2274 read_result
+= sizeof(CFFILE
) + strlen(pszFileName
)+1 +
2275 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2276 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2278 sizeof(CFFOLDER
); /* size of new CFFolder entry */
2280 /* Might be too much data for the maximum size of a cabinet.*/
2281 /* When any further data will be added later, it might not */
2282 /* be possible to flush the cabinet, because there might */
2283 /* not be enough space to store the name of the following */
2284 /* cabinet and name of the corresponding disk. */
2285 /* So take care of this and get the name of the next cabinet */
2286 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2287 p_fci_internal
->fNextCab
==FALSE
&&
2288 ( p_fci_internal
->pccab
->cb
< read_result
+
2289 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2293 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2294 /* increment cabinet index */
2295 ++(p_fci_internal
->pccab
->iCab
);
2296 /* get name of next cabinet */
2297 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0,/* TODO estimated size of cab */
2298 p_fci_internal
->pv
)) {
2299 /* TODO error handling */
2302 /* Skip a few lines of code. This is catched by the next if. */
2303 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2306 if( p_fci_internal
->fGetNextCabInVain
&&
2307 p_fci_internal
->fNextCab
2309 /* THIS CAN NEVER HAPPEN */
2310 /* TODO set error code*/
2314 /* too much data for cabinet */
2315 if( p_fci_internal
->fGetNextCabInVain
&&
2317 p_fci_internal
->oldCCAB
.cb
< read_result
+
2318 strlen(p_fci_internal
->pccab
->szCab
)+1+
2319 strlen(p_fci_internal
->pccab
->szDisk
)+1
2321 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2322 p_fci_internal
->fNextCab
=TRUE
;
2323 if(!fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
)) return FALSE
;
2326 if( p_fci_internal
->fNextCab
) {
2327 /* THIS MAY NEVER HAPPEN */
2328 /* TODO set error code*/
2332 /* read the contents of the file blockwize*/
2334 if (p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2335 /* TODO internal error */
2339 read_result
= PFCI_READ(hfci
, file_handle
/* file handle */,
2340 (p_fci_internal
->data_in
+ p_fci_internal
->cdata_in
) /* memory buffer */,
2341 (CAB_BLOCKMAX
- p_fci_internal
->cdata_in
) /* number of bytes to copy */,
2342 &err
, p_fci_internal
->pv
);
2343 /* TODO error handling of err */
2345 if( read_result
==0 ) break;
2347 /* increment the block size */
2348 p_fci_internal
->cdata_in
+= read_result
;
2350 /* increment the file size */
2351 cffile
.cbFile
+= read_result
;
2354 if ( p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2355 /* TODO report internal error */
2358 /* write a whole block */
2359 if ( p_fci_internal
->cdata_in
== CAB_BLOCKMAX
) {
2361 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
2365 /* close the file from FCIAddFile */
2366 PFCI_CLOSE(hfci
,file_handle
,&err
,p_fci_internal
->pv
);
2367 /* TODO error handling of err */
2369 /* write cffile to p_fci_internal->handleCFFILE1 */
2370 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2371 &cffile
, sizeof(cffile
),&err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
2372 /* TODO write error */
2375 /* TODO error handling of err */
2377 p_fci_internal
->sizeFileCFFILE1
+= sizeof(cffile
);
2379 /* append the name of file*/
2380 if (strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2382 /* TODO set error code */
2385 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2386 pszFileName
, strlen(pszFileName
)+1, &err
, p_fci_internal
->pv
)
2387 != strlen(pszFileName
)+1 ) {
2388 /* TODO write error */
2391 /* TODO error handling of err */
2393 p_fci_internal
->sizeFileCFFILE1
+= strlen(pszFileName
)+1;
2395 /* REUSE the variable read_result */
2396 if (p_fci_internal
->fGetNextCabInVain
||
2397 p_fci_internal
->fNextCab
2399 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2400 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2401 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2402 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2403 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2407 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2408 p_fci_internal
->pccab
->cbReserveCFFolder
;
2409 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2410 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2411 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2415 if ( p_fci_internal
->fPrevCab
) {
2416 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2417 strlen(p_fci_internal
->szPrevDisk
)+1;
2419 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2420 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2421 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2423 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2424 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2425 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2427 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2429 /* too much data for the maximum size of a cabinet */
2430 /* (ignoring the unflushed data block) */
2431 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2432 p_fci_internal
->fNextCab
==FALSE
&& /* this is always the case */
2433 p_fci_internal
->pccab
->cb
< read_result
) {
2434 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2437 /* Might be too much data for the maximum size of a cabinet.*/
2438 /* When any further data will be added later, it might not */
2439 /* be possible to flush the cabinet, because there might */
2440 /* not be enough space to store the name of the following */
2441 /* cabinet and name of the corresponding disk. */
2442 /* So take care of this and get the name of the next cabinet */
2443 /* (ignoring the unflushed data block) */
2444 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2445 p_fci_internal
->fNextCab
==FALSE
&&
2446 ( p_fci_internal
->pccab
->cb
< read_result
+
2447 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2451 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2452 /* increment cabinet index */
2453 ++(p_fci_internal
->pccab
->iCab
);
2454 /* get name of next cabinet */
2455 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0,/* TODO estimated size of cab */
2456 p_fci_internal
->pv
)) {
2457 /* TODO error handling */
2460 /* Skip a few lines of code. This is catched by the next if. */
2461 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2464 if( p_fci_internal
->fGetNextCabInVain
&&
2465 p_fci_internal
->fNextCab
2467 /* THIS CAN NEVER HAPPEN */
2468 /* TODO set error code*/
2472 /* too much data for cabinet */
2473 if( (p_fci_internal
->fGetNextCabInVain
||
2474 p_fci_internal
->fNextCab
) && (
2475 p_fci_internal
->oldCCAB
.cb
< read_result
+
2476 strlen(p_fci_internal
->pccab
->szCab
)+1+
2477 strlen(p_fci_internal
->pccab
->szDisk
)+1
2480 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2481 p_fci_internal
->fNextCab
=TRUE
;
2482 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2485 if( p_fci_internal
->fNextCab
) {
2486 /* THIS MAY NEVER HAPPEN */
2487 /* TODO set error code*/
2491 /* if the FolderThreshold has been reached flush the folder automatically */
2492 if( p_fci_internal
->fGetNextCabInVain
) {
2493 if( p_fci_internal
->cCompressedBytesInFolder
>=
2494 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2495 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2498 if( p_fci_internal
->cCompressedBytesInFolder
>=
2499 p_fci_internal
->pccab
->cbFolderThresh
) {
2500 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2505 } /* end of FCIAddFile */
2511 /***********************************************************************
2512 * FCIFlushFolder (CABINET.12)
2514 * FCIFlushFolder completes the CFFolder structure under construction.
2516 * All further data which is added by FCIAddFile will be associateed to
2517 * the next CFFolder structure.
2519 * FCIFlushFolder will be called by FCIAddFile automatically if the
2520 * threshold (stored in the member cbFolderThresh of the CCAB structure
2521 * pccab passed to FCICreate) is exceeded.
2523 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2524 * any data will be written into the cabinet file.
2527 * hfci [I] An HFCI from FCICreate
2528 * pfnfcignc [I] A pointer to a function which gets information about
2530 * pfnfcis [IO] A pointer to a function which will report status
2531 * information about the compression process
2534 * On success, returns TRUE
2535 * On failure, returns FALSE
2541 BOOL __cdecl
FCIFlushFolder(
2543 PFNFCIGETNEXTCABINET pfnfcignc
,
2544 PFNFCISTATUS pfnfcis
)
2546 return fci_flush_folder(hfci
,FALSE
,pfnfcignc
,pfnfcis
);
2547 } /* end of FCIFlushFolder */
2551 /***********************************************************************
2552 * FCIFlushCabinet (CABINET.13)
2554 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2555 * into the cabinet file. If the maximum cabinet size (stored in the
2556 * member cb of the CCAB structure pccab passed to FCICreate) has been
2557 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2558 * The remaining data still has to be flushed manually by calling
2561 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2562 * NOT be called again. Then hfci has to be released by FCIDestroy.
2565 * hfci [I] An HFCI from FCICreate
2566 * fGetNextCab [I] Whether you want to add additional files to a
2567 * cabinet set (TRUE) or whether you want to
2568 * finalize it (FALSE)
2569 * pfnfcignc [I] A pointer to a function which gets information about
2571 * pfnfcis [IO] A pointer to a function which will report status
2572 * information about the compression process
2575 * On success, returns TRUE
2576 * On failure, returns FALSE
2582 BOOL __cdecl
FCIFlushCabinet(
2585 PFNFCIGETNEXTCABINET pfnfcignc
,
2586 PFNFCISTATUS pfnfcis
)
2588 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2590 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2592 while( p_fci_internal
->sizeFileCFFILE1
>0 ||
2593 p_fci_internal
->sizeFileCFFILE2
>0 ) {
2594 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2598 } /* end of FCIFlushCabinet */
2601 /***********************************************************************
2602 * FCIDestroy (CABINET.14)
2604 * Frees a handle created by FCICreate.
2605 * Only reason for failure would be an invalid handle.
2608 * hfci [I] The HFCI to free
2614 BOOL __cdecl
FCIDestroy(HFCI hfci
)
2617 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2618 if (REALLY_IS_FCI(hfci
)) {
2620 /* before hfci can be removed all temporary files must be closed */
2622 p_fci_internal
->FCI_Intmagic
= 0;
2624 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
2625 /* TODO error handling of err */
2626 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA1
, &err
,
2627 p_fci_internal
->pv
);
2628 /* TODO error handling of err */
2629 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE1
,&err
,p_fci_internal
->pv
);
2630 /* TODO error handling of err */
2631 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE1
, &err
,
2632 p_fci_internal
->pv
);
2633 /* TODO error handling of err */
2634 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
2635 /* TODO error handling of err */
2636 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
2637 p_fci_internal
->pv
);
2638 /* TODO error handling of err */
2639 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
2640 /* TODO error handling of err */
2641 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
2642 p_fci_internal
->pv
);
2643 /* TODO error handling of err */
2644 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
2645 /* TODO error handling of err */
2646 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
2647 p_fci_internal
->pv
);
2648 /* TODO error handling of err */
2650 /* data in and out buffers have to be removed */
2651 if (p_fci_internal
->data_in
!=NULL
)
2652 PFCI_FREE(hfci
, p_fci_internal
->data_in
);
2653 if (p_fci_internal
->data_out
!=NULL
)
2654 PFCI_FREE(hfci
, p_fci_internal
->data_out
);
2656 /* hfci can now be removed */
2657 PFCI_FREE(hfci
, hfci
);
2660 SetLastError(ERROR_INVALID_HANDLE
);
2664 } /* end of FCIDestroy */