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 - the ERF error structure aren't used on error
27 - no real compression yet
28 - unknown behaviour if files>4GB or cabinet >4GB
29 - incorrect status information
30 - check if the maximum size for a cabinet is too small to store any data
31 - 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 */
445 static inline cab_ULONG
fci_set_little_endian_ulong( cab_ULONG i
)
447 #ifdef WORDS_BIGENDIAN
448 return RtlUlongByteSwap( i
);
454 static inline cab_ULONG
fci_get_little_endian_ulong( cab_ULONG i
)
456 #ifdef WORDS_BIGENDIAN
457 return RtlUlongByteSwap( i
);
463 static inline cab_UWORD
fci_set_little_endian_uword( cab_UWORD i
)
465 #ifdef WORDS_BIGENDIAN
466 return RtlUshortByteSwap( i
);
472 static inline cab_UWORD
fci_get_little_endian_uword( cab_UWORD i
)
474 #ifdef WORDS_BIGENDIAN
475 return RtlUshortByteSwap( i
);
482 static BOOL
fci_flushfolder_copy_cfdata(HFCI hfci
, char* buffer
, UINT cbReserveCFData
,
483 PFNFCISTATUS pfnfcis
, int* err
, int handleCFDATA1new
,
484 cab_ULONG
* psizeFileCFDATA1new
, cab_ULONG
* payload
)
486 cab_ULONG read_result
;
487 CFDATA
* pcfdata
=(CFDATA
*)buffer
;
488 BOOL split_block
=FALSE
;
489 cab_UWORD savedUncomp
=0;
490 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
494 /* while not all CFDATAs have been copied do */
496 if( p_fci_internal
->fNextCab
) {
498 /* TODO internal error should never happen */
502 /* REUSE the variable read_result */
503 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
504 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
505 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
510 if (p_fci_internal
->fPrevCab
) {
511 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
512 strlen(p_fci_internal
->szPrevDisk
)+1;
514 /* No more CFDATA fits into the cabinet under construction */
515 /* So don't try to store more data into it */
516 if( p_fci_internal
->fNextCab
&&
517 (p_fci_internal
->oldCCAB
.cb
<= sizeof(CFDATA
) + cbReserveCFData
+
518 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
519 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
522 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
524 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
525 strlen(p_fci_internal
->pccab
->szCab
)+1 +
526 strlen(p_fci_internal
->pccab
->szDisk
)+1
528 /* This may never be run for the first time the while loop is entered.
529 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
530 split_block
=TRUE
; /* In this case split_block is abused to store */
531 /* the complete data block into the next cabinet and not into the */
532 /* current one. Originally split_block is the indicator that a */
533 /* data block has been splitted across different cabinets. */
536 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
537 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/*file handle*/
538 buffer
, /* memory buffer */
539 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
540 err
, p_fci_internal
->pv
);
541 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
542 if (read_result
==0) break; /* ALL DATA has been copied */
543 /* TODO read error */
546 /* TODO error handling of err */
548 /* REUSE buffer p_fci_internal->data_out !!! */
549 /* read data from p_fci_internal->handleCFDATA1 to */
550 /* p_fci_internal->data_out */
551 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
552 p_fci_internal
->data_out
/* memory buffer */,
553 pcfdata
->cbData
/* number of bytes to copy */,
554 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
555 /* TODO read error */
558 /* TODO error handling of err */
560 /* if cabinet size is too large */
562 /* REUSE the variable read_result */
563 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
564 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
565 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
570 if (p_fci_internal
->fPrevCab
) {
571 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
572 strlen(p_fci_internal
->szPrevDisk
)+1;
575 /* Is cabinet with new CFDATA too large? Then data block has to be split */
576 if( p_fci_internal
->fNextCab
&&
577 (p_fci_internal
->oldCCAB
.cb
< sizeof(CFDATA
) + cbReserveCFData
+
579 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
580 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
583 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
584 sizeof(CFFOLDER
) + /* size of new CFFolder entry */
585 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
586 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* name of next cabinet */
587 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* name of next disk */
589 /* REUSE read_result to save the size of the compressed data */
590 read_result
=pcfdata
->cbData
;
591 /* Modify the size of the compressed data to store only a part of the */
592 /* data block into the current cabinet. This is done to prevent */
593 /* that the maximum cabinet size will be exceeded. The remainder */
594 /* will be stored into the next following cabinet. */
596 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
597 /* Substract everything except the size of the block of data */
598 /* to get it's actual size */
599 pcfdata
->cbData
= p_fci_internal
->oldCCAB
.cb
- (
600 sizeof(CFDATA
) + cbReserveCFData
+
601 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
602 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
604 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
605 sizeof(CFFOLDER
) + /* set size of new CFFolder entry */
606 p_fci_internal
->oldCCAB
.cbReserveCFFolder
);
607 /* substract the size of special header fields */
608 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
609 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
610 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
613 if (p_fci_internal
->fPrevCab
) {
614 pcfdata
->cbData
-=strlen(p_fci_internal
->szPrevCab
)+1 +
615 strlen(p_fci_internal
->szPrevDisk
)+1;
617 pcfdata
->cbData
-=strlen(p_fci_internal
->pccab
->szCab
)+1 +
618 strlen(p_fci_internal
->pccab
->szDisk
)+1;
620 savedUncomp
= pcfdata
->cbUncomp
;
621 pcfdata
->cbUncomp
= 0; /* on splitted blocks of data this is zero */
623 /* if split_block==TRUE then the above while loop won't */
624 /* be executed again */
625 split_block
=TRUE
; /* split_block is the indicator that */
626 /* a data block has been splitted across */
627 /* diffentent cabinets.*/
630 /* This should never happen !!! */
631 if (pcfdata
->cbData
==0) {
636 /* set little endian */
637 pcfdata
->cbData
=fci_set_little_endian_uword(pcfdata
->cbData
);
638 pcfdata
->cbUncomp
=fci_set_little_endian_uword(pcfdata
->cbUncomp
);
640 /* get checksum and write to cfdata.csum */
641 pcfdata
->csum
= fci_get_checksum( &(pcfdata
->cbData
),
642 sizeof(CFDATA
)+cbReserveCFData
-
643 sizeof(pcfdata
->csum
), fci_get_checksum( p_fci_internal
->data_out
, /*buffer*/
644 pcfdata
->cbData
, 0 ) );
646 /* set little endian */
647 pcfdata
->csum
=fci_set_little_endian_ulong(pcfdata
->csum
);
649 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
650 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
651 buffer
, /* memory buffer */
652 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
653 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
654 /* TODO write error */
657 /* TODO error handling of err */
659 p_fci_internal
->sizeFileCFDATA2
+= sizeof(CFDATA
)+cbReserveCFData
;
661 /* reset little endian */
662 pcfdata
->cbData
=fci_get_little_endian_uword(pcfdata
->cbData
);
663 pcfdata
->cbUncomp
=fci_get_little_endian_uword(pcfdata
->cbUncomp
);
664 pcfdata
->csum
=fci_get_little_endian_ulong(pcfdata
->csum
);
666 /* write compressed data into p_fci_internal->handleCFDATA2 */
667 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
668 p_fci_internal
->data_out
, /* memory buffer */
669 pcfdata
->cbData
, /* number of bytes to copy */
670 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
671 /* TODO write error */
674 /* TODO error handling of err */
676 p_fci_internal
->sizeFileCFDATA2
+= pcfdata
->cbData
;
677 ++(p_fci_internal
->cDataBlocks
);
678 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
679 (*payload
)+=pcfdata
->cbUncomp
;
680 /* if cabinet size too large and data has been split */
681 /* write the remainder of the data block to the new CFDATA1 file */
682 if( split_block
) { /* This does not include the */
683 /* abused one (just search for "abused" )*/
684 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
685 if (p_fci_internal
->fNextCab
==FALSE
) {
686 /* TODO internal error */
690 /* set cbData to the size of the remainder of the data block */
691 pcfdata
->cbData
= read_result
- pcfdata
->cbData
;
692 /*recover former value of cfdata.cbData; read_result will be the offset*/
693 read_result
-= pcfdata
->cbData
;
694 pcfdata
->cbUncomp
= savedUncomp
;
696 /* reset checksum, it will be computed later */
699 /* write cfdata WITHOUT checksum to handleCFDATA1new */
700 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
701 buffer
, /* memory buffer */
702 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
703 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
704 /* TODO write error */
707 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
709 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
711 /* write compressed data into handleCFDATA1new */
712 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
713 p_fci_internal
->data_out
+ read_result
, /* memory buffer + offset */
714 /* to last part of split data */
715 pcfdata
->cbData
, /* number of bytes to copy */
716 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
717 /* TODO write error */
720 /* TODO error handling of err */
722 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
724 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
725 /* the two blocks of the split data block have been written */
726 /* don't reset split_data yet, because it is still needed see below */
729 /* report status with pfnfcis about copied size of folder */
730 if( (*pfnfcis
)(statusFolder
,
731 p_fci_internal
->statusFolderCopied
, /*cfdata.cbData(+previous ones)*/
732 p_fci_internal
->statusFolderTotal
, /* total folder size */
733 p_fci_internal
->pv
) == -1) {
734 /* TODO set error code and abort */
739 /* if cabinet size too large */
740 /* write the remaining data blocks to the new CFDATA1 file */
741 if ( split_block
) { /* This does include the */
742 /* abused one (just search for "abused" )*/
743 if (p_fci_internal
->fNextCab
==FALSE
) {
744 /* TODO internal error */
747 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
749 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
750 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/* handle */
751 buffer
, /* memory buffer */
752 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
753 err
, p_fci_internal
->pv
);
754 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
755 if (read_result
==0) break; /* ALL DATA has been copied */
756 /* TODO read error */
759 /* TODO error handling of err */
761 /* REUSE buffer p_fci_internal->data_out !!! */
762 /* read data from p_fci_internal->handleCFDATA1 to */
763 /* p_fci_internal->data_out */
764 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
765 p_fci_internal
->data_out
/* memory buffer */,
766 pcfdata
->cbData
/* number of bytes to copy */,
767 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
768 /* TODO read error */
771 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
773 /* write cfdata with checksum to handleCFDATA1new */
774 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
775 buffer
, /* memory buffer */
776 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
777 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
778 /* TODO write error */
781 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
783 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
785 /* write compressed data into handleCFDATA1new */
786 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
787 p_fci_internal
->data_out
, /* memory buffer */
788 pcfdata
->cbData
, /* number of bytes to copy */
789 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
790 /* TODO write error */
793 /* TODO error handling of err */
795 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
796 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
798 /* report status with pfnfcis about copied size of folder */
799 if( (*pfnfcis
)(statusFolder
,
800 p_fci_internal
->statusFolderCopied
,/*cfdata.cbData(+revious ones)*/
801 p_fci_internal
->statusFolderTotal
, /* total folder size */
802 p_fci_internal
->pv
) == -1) {
803 /* TODO set error code and abort */
808 break; /* jump out of the next while loop */
809 } /* end of if( split_data ) */
812 } /* end of fci_flushfolder_copy_cfdata */
818 static BOOL
fci_flushfolder_copy_cffolder(HFCI hfci
, int* err
, UINT cbReserveCFFolder
,
819 cab_ULONG sizeFileCFDATA2old
)
824 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
826 /* absolute offset cannot be set yet, because the size of cabinet header, */
827 /* the number of CFFOLDERs and the number of CFFILEs may change. */
828 /* Instead the size of all previous data blocks will be stored and */
829 /* the remainder of the offset will be added when the cabinet will be */
830 /* flushed to disk. */
831 /* This is exactly the way the original CABINET.DLL works!!! */
832 cffolder
.coffCabStart
=sizeFileCFDATA2old
;
834 /* set the number of this folder's CFDATA sections */
835 cffolder
.cCFData
=p_fci_internal
->cDataBlocks
;
836 /* TODO set compression type */
837 cffolder
.typeCompress
= tcompTYPE_NONE
;
839 /* write cffolder to p_fci_internal->handleCFFOLDER */
840 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
841 &cffolder
, /* memory buffer */
842 sizeof(cffolder
), /* number of bytes to copy */
843 err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
844 /* TODO write error */
847 /* TODO error handling of err */
849 p_fci_internal
->sizeFileCFFOLDER
+= sizeof(cffolder
);
851 /* add optional reserved area */
852 if (cbReserveCFFolder
!=0) {
853 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
854 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
855 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
856 p_fci_internal
->perf
->fError
= TRUE
;
857 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
860 for(i
=0;i
<cbReserveCFFolder
;) {
863 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
864 reserved
, /* memory buffer */
865 cbReserveCFFolder
, /* number of bytes to copy */
866 err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
867 PFCI_FREE(hfci
, reserved
);
868 /* TODO write error */
871 /* TODO error handling of err */
873 p_fci_internal
->sizeFileCFFOLDER
+= cbReserveCFFolder
;
875 PFCI_FREE(hfci
, reserved
);
878 } /* end of fci_flushfolder_copy_cffolder */
884 static BOOL
fci_flushfolder_copy_cffile(HFCI hfci
, int* err
, int handleCFFILE1new
,
885 cab_ULONG
*psizeFileCFFILE1new
, cab_ULONG payload
)
888 cab_ULONG read_result
;
890 cab_ULONG sizeOfFiles
=0, sizeOfFilesPrev
;
891 BOOL may_be_prev
=TRUE
;
892 cab_ULONG cbFileRemainer
=0;
893 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
894 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
895 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,0,SEEK_SET
,err
,
896 p_fci_internal
->pv
) !=0 ) {
897 /* TODO wrong return value */
899 /* TODO error handling of err */
901 /* while not all CFFILE structures have been copied do */
903 /* REUSE the variable read_result */
904 /* read data from p_fci_internal->handleCFFILE1 to cffile */
905 read_result
= PFCI_READ(hfci
,p_fci_internal
->handleCFFILE1
/* file handle */,
906 &cffile
, /* memory buffer */
907 sizeof(cffile
), /* number of bytes to copy */
908 err
, p_fci_internal
->pv
);
909 if( read_result
!= sizeof(cffile
) ) {
910 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
911 /* TODO read error */
914 /* TODO error handling of err */
916 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
917 /* position. I don't know why so I'll just omit it */
919 /* read the filename from p_fci_internal->handleCFFILE1 */
920 /* REUSE the variable read_result AGAIN */
921 /* REUSE the memory buffer PFCI(hfci)->data_out */
922 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFILE1
/*file handle*/,
923 p_fci_internal
->data_out
, /* memory buffer */
924 CB_MAX_FILENAME
, /* number of bytes to copy */
925 err
, p_fci_internal
->pv
) <2) {
926 /* TODO read error */
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 /* TODO set error code internal error */
938 seek
+=sizeof(cffile
) + strlen(p_fci_internal
->data_out
)+1;
940 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
941 /* i.e. seek to the next CFFILE area */
942 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,
943 seek
, /* seek position*/
946 != sizeof(cffile
)+strlen(p_fci_internal
->data_out
)+1 ) {
947 /* TODO wrong return value */
949 /* TODO error handling of err */
951 /* fnfilfnfildest: placed file on cabinet */
952 if (p_fci_internal
->fNextCab
||
953 p_fci_internal
->fGetNextCabInVain
) {
954 PFCI_FILEPLACED( hfci
, &(p_fci_internal
->oldCCAB
),
955 p_fci_internal
->data_out
, /* the file name*/
956 cffile
.cbFile
, /* file size */
957 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
961 PFCI_FILEPLACED( hfci
, p_fci_internal
->pccab
,
962 p_fci_internal
->data_out
, /* the file name*/
963 cffile
.cbFile
, /* file size */
964 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
969 /* Check special iFolder values */
970 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
971 p_fci_internal
->fPrevCab
==FALSE
) {
972 /* THIS MAY NEVER HAPPEN */
973 /* TODO set error code */
976 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
977 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
) {
978 /* THIS MAY NEVER HAPPEN */
979 /* TODO set error code */
982 if( may_be_prev
&& cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
985 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& may_be_prev
==FALSE
) {
986 /* THIS MAY NEVER HAPPEN */
987 /* TODO set error code */
990 if( cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
994 sizeOfFilesPrev
=sizeOfFiles
;
995 /* Set complete size of all processed files */
996 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
997 p_fci_internal
->cbFileRemainer
!=0
999 sizeOfFiles
+=p_fci_internal
->cbFileRemainer
;
1000 p_fci_internal
->cbFileRemainer
=0;
1002 sizeOfFiles
+=cffile
.cbFile
;
1005 /* Check if spanned file fits into this cabinet folder */
1006 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& sizeOfFiles
>payload
) {
1007 cffile
.iFolder
=cffileCONTINUED_PREV_AND_NEXT
;
1010 /* Check if file doesn't fit into this cabinet folder */
1011 if( sizeOfFiles
>payload
) {
1012 cffile
.iFolder
=cffileCONTINUED_TO_NEXT
;
1015 /* set little endian */
1016 cffile
.cbFile
=fci_set_little_endian_ulong(cffile
.cbFile
);
1017 cffile
.uoffFolderStart
=fci_set_little_endian_ulong(cffile
.uoffFolderStart
);
1018 cffile
.iFolder
=fci_set_little_endian_uword(cffile
.iFolder
);
1019 cffile
.date
=fci_set_little_endian_uword(cffile
.date
);
1020 cffile
.time
=fci_set_little_endian_uword(cffile
.time
);
1021 cffile
.attribs
=fci_set_little_endian_uword(cffile
.attribs
);
1023 /* write cffile to p_fci_internal->handleCFFILE2 */
1024 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
1025 &cffile
, /* memory buffer */
1026 sizeof(cffile
), /* number of bytes to copy */
1027 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1028 /* TODO write error */
1031 /* TODO error handling of err */
1033 p_fci_internal
->sizeFileCFFILE2
+= sizeof(cffile
);
1035 /* reset little endian */
1036 cffile
.cbFile
=fci_get_little_endian_ulong(cffile
.cbFile
);
1037 cffile
.uoffFolderStart
=fci_get_little_endian_ulong(cffile
.uoffFolderStart
);
1038 cffile
.iFolder
=fci_get_little_endian_uword(cffile
.iFolder
);
1039 cffile
.date
=fci_get_little_endian_uword(cffile
.date
);
1040 cffile
.time
=fci_get_little_endian_uword(cffile
.time
);
1041 cffile
.attribs
=fci_get_little_endian_uword(cffile
.attribs
);
1043 /* write file name to p_fci_internal->handleCFFILE2 */
1044 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
1045 p_fci_internal
->data_out
, /* memory buffer */
1046 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1047 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1048 /* TODO write error */
1051 /* TODO error handling of err */
1053 p_fci_internal
->sizeFileCFFILE2
+= strlen(p_fci_internal
->data_out
)+1;
1055 /* cFiles is used to count all files of a cabinet */
1056 ++(p_fci_internal
->cFiles
);
1058 /* This is only true for files which will be written into the */
1059 /* next cabinet of the spanning folder */
1060 if( sizeOfFiles
>payload
) {
1062 /* Files which data will be partially written into the current cabinet */
1063 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
1064 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
1066 if( sizeOfFilesPrev
<=payload
) {
1067 /* The size of the uncompressed, data of a spanning file in a */
1069 cbFileRemainer
=sizeOfFiles
-payload
;
1071 cffile
.iFolder
=cffileCONTINUED_FROM_PREV
;
1076 /* write cffile into handleCFFILE1new */
1077 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1078 &cffile
, /* memory buffer */
1079 sizeof(cffile
), /* number of bytes to copy */
1080 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1081 /* TODO write error */
1084 /* TODO error handling of err */
1086 *psizeFileCFFILE1new
+= sizeof(cffile
);
1087 /* write name of file into handleCFFILE1new */
1088 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1089 p_fci_internal
->data_out
, /* memory buffer */
1090 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1091 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1092 /* TODO write error */
1095 /* TODO error handling of err */
1097 *psizeFileCFFILE1new
+= strlen(p_fci_internal
->data_out
)+1;
1100 } /* END OF while */
1101 p_fci_internal
->cbFileRemainer
=cbFileRemainer
;
1103 } /* end of fci_flushfolder_copy_cffile */
1108 static BOOL
fci_flush_folder(
1111 PFNFCIGETNEXTCABINET pfnfcignc
,
1112 PFNFCISTATUS pfnfcis
)
1115 int handleCFDATA1new
; /* handle for new temp file */
1116 char szFileNameCFDATA1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1117 int handleCFFILE1new
; /* handle for new temp file */
1118 char szFileNameCFFILE1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1119 UINT cbReserveCFData
, cbReserveCFFolder
;
1121 cab_ULONG sizeFileCFDATA1new
=0;
1122 cab_ULONG sizeFileCFFILE1new
=0;
1123 cab_ULONG sizeFileCFDATA2old
;
1125 cab_ULONG read_result
;
1126 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1129 if (!REALLY_IS_FCI(hfci
)) {
1130 SetLastError(ERROR_INVALID_HANDLE
);
1134 if ((!pfnfcignc
) || (!pfnfcis
)) {
1135 p_fci_internal
->perf
->erfOper
= FCIERR_NONE
;
1136 p_fci_internal
->perf
->erfType
= ERROR_BAD_ARGUMENTS
;
1137 p_fci_internal
->perf
->fError
= TRUE
;
1139 SetLastError(ERROR_BAD_ARGUMENTS
);
1143 if( p_fci_internal
->fGetNextCabInVain
&&
1144 p_fci_internal
->fNextCab
){
1145 /* TODO internal error */
1149 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1150 /* this function will return TRUE */
1151 if( p_fci_internal
->sizeFileCFFILE1
== 0 ) {
1152 if ( p_fci_internal
->sizeFileCFDATA1
!= 0 ) {
1153 /* TODO error handling */
1159 if (p_fci_internal
->data_in
==NULL
|| p_fci_internal
->data_out
==NULL
) {
1160 /* TODO error handling */
1164 /* FCIFlushFolder has already been called... */
1165 if (p_fci_internal
->fSplitFolder
&& p_fci_internal
->sizeFileCFFILE2
!=0) {
1166 if (p_fci_internal
->sizeFileCFFILE2
==0) {
1167 /* TODO set error code */
1173 /* TODO check what will happen when return FALSE later */
1174 /* and p_fci_internal->fSplitFolder is set to FALSE */
1175 p_fci_internal
->fSplitFolder
=FALSE
;
1178 if( p_fci_internal
->fGetNextCabInVain
||
1179 p_fci_internal
->fNextCab
){
1180 cbReserveCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1181 cbReserveCFFolder
= p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1183 cbReserveCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1184 cbReserveCFFolder
= p_fci_internal
->pccab
->cbReserveCFFolder
;
1188 /* if there is data in p_fci_internal->data_in */
1189 if (p_fci_internal
->cdata_in
!=0) {
1191 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
1194 /* reset to get the number of data blocks of this folder which are */
1195 /* actually in this cabinet ( at least partially ) */
1196 p_fci_internal
->cDataBlocks
=0;
1198 if ( p_fci_internal
->fNextCab
||
1199 p_fci_internal
->fGetNextCabInVain
) {
1200 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
1201 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1202 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1203 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1204 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1208 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
+
1209 p_fci_internal
->pccab
->cbReserveCFFolder
;
1210 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1211 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1212 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1216 if (p_fci_internal
->fPrevCab
) {
1217 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1218 strlen(p_fci_internal
->szPrevDisk
)+1;
1220 if (p_fci_internal
->fNextCab
) {
1221 read_result
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1222 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1225 p_fci_internal
->statusFolderTotal
= sizeof(CFHEADER
)+read_result
+
1226 sizeof(CFFOLDER
) + p_fci_internal
->sizeFileCFFILE2
+
1227 p_fci_internal
->sizeFileCFDATA2
+ p_fci_internal
->sizeFileCFFILE1
+
1228 p_fci_internal
->sizeFileCFDATA1
;
1229 p_fci_internal
->statusFolderCopied
= 0;
1231 /* report status with pfnfcis about copied size of folder */
1232 if( (*pfnfcis
)(statusFolder
, p_fci_internal
->statusFolderCopied
,
1233 p_fci_internal
->statusFolderTotal
, /* TODO total folder size */
1234 p_fci_internal
->pv
) == -1) {
1235 /* TODO set error code and abort */
1239 /* get a new temp file */
1240 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFDATA1new
,CB_MAX_FILENAME
)) {
1241 /* TODO error handling */
1245 if ( strlen(szFileNameCFDATA1new
) >= CB_MAX_FILENAME
) {
1246 /* TODO set error code */
1249 handleCFDATA1new
= PFCI_OPEN(hfci
,szFileNameCFDATA1new
,34050,384,&err
,
1250 p_fci_internal
->pv
);
1252 /* get a new temp file */
1253 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFFILE1new
,CB_MAX_FILENAME
)) {
1254 /* TODO error handling */
1255 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1256 /* TODO error handling of err */
1260 if ( strlen(szFileNameCFFILE1new
) >= CB_MAX_FILENAME
) {
1261 /* TODO set error code */
1262 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1263 /* TODO error handling of err */
1266 handleCFFILE1new
= PFCI_OPEN(hfci
,szFileNameCFFILE1new
,34050,384,&err
,
1267 p_fci_internal
->pv
);
1269 /* USE the variable read_result */
1270 if ( p_fci_internal
->fNextCab
||
1271 p_fci_internal
->fGetNextCabInVain
) {
1272 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1273 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1274 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1275 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1279 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
;
1280 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1281 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1282 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1286 if (p_fci_internal
->fPrevCab
) {
1287 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1288 strlen(p_fci_internal
->szPrevDisk
)+1;
1290 read_result
+= sizeof(CFHEADER
) + p_fci_internal
->sizeFileCFDATA2
+
1291 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
;
1293 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
1294 read_result
+= sizeof(CFFOLDER
)+p_fci_internal
->pccab
->cbReserveCFFolder
;
1297 /* Check if multiple cabinets have to be created. */
1299 /* Might be too much data for the maximum allowed cabinet size.*/
1300 /* When any further data will be added later, it might not */
1301 /* be possible to flush the cabinet, because there might */
1302 /* not be enough space to store the name of the following */
1303 /* cabinet and name of the corresponding disk. */
1304 /* So take care of this and get the name of the next cabinet */
1305 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
1306 p_fci_internal
->fNextCab
==FALSE
&&
1309 p_fci_internal
->pccab
->cb
< read_result
+
1310 p_fci_internal
->sizeFileCFDATA1
+
1311 p_fci_internal
->sizeFileCFFILE1
+
1312 CB_MAX_CABINET_NAME
+ /* next cabinet name */
1313 CB_MAX_DISK_NAME
/* next disk name */
1318 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
1319 /* increment cabinet index */
1320 ++(p_fci_internal
->pccab
->iCab
);
1321 /* get name of next cabinet */
1322 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0, /* estimated size of cab */
1323 p_fci_internal
->pv
)) {
1324 /* TODO error handling */
1325 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1326 /* TODO error handling of err */
1327 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1328 /* TODO error handling of err */
1332 /* Skip a few lines of code. This is catched by the next if. */
1333 p_fci_internal
->fGetNextCabInVain
=TRUE
;
1336 /* too much data for cabinet */
1337 if( (p_fci_internal
->fGetNextCabInVain
||
1338 p_fci_internal
->fNextCab
) &&
1341 p_fci_internal
->oldCCAB
.cb
< read_result
+
1342 p_fci_internal
->sizeFileCFDATA1
+
1343 p_fci_internal
->sizeFileCFFILE1
+
1344 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1345 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1349 p_fci_internal
->fGetNextCabInVain
=FALSE
;
1350 p_fci_internal
->fNextCab
=TRUE
;
1352 /* return FALSE if there is not enough space left*/
1353 /* this should never happen */
1354 if (p_fci_internal
->oldCCAB
.cb
<=
1355 p_fci_internal
->sizeFileCFFILE1
+
1357 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1358 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1361 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1362 /* TODO error handling of err */
1363 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1364 /* TODO error handling of err */
1366 /* close and delete p_fci_internal->handleCFFILE1 */
1367 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1368 /* TODO error handling of err */
1369 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1370 /* TODO error handling of err */
1375 /* the folder will be split across cabinets */
1376 p_fci_internal
->fSplitFolder
=TRUE
;
1379 /* this should never happen */
1380 if (p_fci_internal
->fNextCab
) {
1381 /* TODO internal error */
1386 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1387 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA1
,0,SEEK_SET
,&err
,
1388 p_fci_internal
->pv
) !=0 ) {
1389 /* TODO wrong return value */
1390 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1391 /* TODO error handling of err */
1392 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1393 /* TODO error handling of err */
1396 /* TODO error handling of err */
1398 /* save size of file CFDATA2 - required for the folder's offset to data */
1399 sizeFileCFDATA2old
= p_fci_internal
->sizeFileCFDATA2
;
1401 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFData
+sizeof(CFDATA
)))) {
1402 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
1403 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1404 p_fci_internal
->perf
->fError
= TRUE
;
1405 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1406 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1407 /* TODO error handling of err */
1408 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1409 /* TODO error handling of err */
1413 if(!fci_flushfolder_copy_cfdata(hfci
, reserved
, cbReserveCFData
, pfnfcis
, &err
,
1414 handleCFDATA1new
, &sizeFileCFDATA1new
, &payload
1416 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1417 /* TODO error handling of err */
1418 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1419 /* TODO error handling of err */
1420 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1421 /* TODO error handling of err */
1422 PFCI_FREE(hfci
,reserved
);
1426 PFCI_FREE(hfci
,reserved
);
1428 if(!fci_flushfolder_copy_cffolder(hfci
, &err
, cbReserveCFFolder
,
1429 sizeFileCFDATA2old
)) {
1430 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1431 /* TODO error handling of err */
1432 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1433 /* TODO error handling of err */
1434 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1435 /* TODO error handling of err */
1439 if(!fci_flushfolder_copy_cffile(hfci
, &err
, handleCFFILE1new
,
1440 &sizeFileCFFILE1new
, payload
)) {
1441 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1442 /* TODO error handling of err */
1443 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1444 /* TODO error handling of err */
1445 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1446 /* TODO error handling of err */
1447 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1448 /* TODO error handling of err */
1452 /* close and delete p_fci_internal->handleCFDATA1 */
1453 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
1454 /* TODO error handling of err */
1455 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFDATA1
,&err
,p_fci_internal
->pv
);
1456 /* TODO error handling of err */
1458 /* put new CFDATA1 into hfci */
1459 memcpy(p_fci_internal
->szFileNameCFDATA1
,szFileNameCFDATA1new
,
1462 /* put CFDATA1 file handle */
1463 PFCI_INT(hfci
)->handleCFDATA1
= handleCFDATA1new
;
1465 PFCI_INT(hfci
)->sizeFileCFDATA1
= sizeFileCFDATA1new
;
1467 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1468 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFFILE1
,&err
,PFCI_INT(hfci
)->pv
);
1469 /* TODO error handling of err */
1470 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFFILE1
,&err
,p_fci_internal
->pv
);
1471 /* TODO error handling of err */
1473 /* put new CFFILE1 into hfci */
1474 memcpy(p_fci_internal
->szFileNameCFFILE1
,szFileNameCFFILE1new
,
1477 /* put CFFILE1 file handle */
1478 p_fci_internal
->handleCFFILE1
= handleCFFILE1new
;
1480 p_fci_internal
->sizeFileCFFILE1
= sizeFileCFFILE1new
;
1482 ++(p_fci_internal
->cFolders
);
1484 /* reset CFFolder specific information */
1485 p_fci_internal
->cDataBlocks
=0;
1486 p_fci_internal
->cCompressedBytesInFolder
=0;
1489 } /* end of fci_flush_folder */
1494 static BOOL
fci_flush_cabinet(
1497 PFNFCIGETNEXTCABINET pfnfcignc
,
1498 PFNFCISTATUS pfnfcis
)
1503 cab_UWORD cbCFHeader
;
1504 cab_UBYTE cbCFFolder
;
1508 cab_ULONG read_result
;
1509 int handleCABINET
; /* file handle for cabinet */
1510 char pszFileNameCABINET
[CB_MAX_CAB_PATH
+CB_MAX_CABINET_NAME
];/* name buffer */
1511 UINT cbReserveCFHeader
, cbReserveCFFolder
, i
;
1513 BOOL returntrue
=FALSE
;
1514 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1516 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1518 /* when FCIFlushCabinet was or FCIAddFile wasn't called */
1519 if( p_fci_internal
->sizeFileCFFILE1
==0 && fGetNextCab
) {
1523 if (!fci_flush_folder(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)){
1524 /* TODO set error */
1528 if(returntrue
) return TRUE
;
1530 if (p_fci_internal
->fSplitFolder
&& p_fci_internal
->fNextCab
==FALSE
) {
1531 /* TODO internal error */
1535 if( p_fci_internal
->fNextCab
||
1536 p_fci_internal
->fGetNextCabInVain
) {
1537 cbReserveCFFolder
=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1538 cbReserveCFHeader
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1540 if (strlen(p_fci_internal
->oldCCAB
.szCabPath
)>=CB_MAX_CAB_PATH
||
1541 strlen(p_fci_internal
->oldCCAB
.szCab
)>=CB_MAX_CABINET_NAME
) {
1542 /* TODO set error */
1545 /* get the full name of the cabinet */
1546 memcpy(pszFileNameCABINET
,p_fci_internal
->oldCCAB
.szCabPath
,
1548 memcpy(pszFileNameCABINET
+strlen(pszFileNameCABINET
),
1549 p_fci_internal
->oldCCAB
.szCab
, CB_MAX_CABINET_NAME
);
1551 cbReserveCFFolder
=p_fci_internal
->pccab
->cbReserveCFFolder
;
1552 cbReserveCFHeader
=p_fci_internal
->pccab
->cbReserveCFHeader
;
1554 if (strlen(p_fci_internal
->pccab
->szCabPath
)>=CB_MAX_CAB_PATH
||
1555 strlen(p_fci_internal
->pccab
->szCab
)>=CB_MAX_CABINET_NAME
) {
1556 /* TODO set error */
1559 /* get the full name of the cabinet */
1560 memcpy(pszFileNameCABINET
,p_fci_internal
->pccab
->szCabPath
,
1562 memcpy(pszFileNameCABINET
+strlen(pszFileNameCABINET
),
1563 p_fci_internal
->pccab
->szCab
, CB_MAX_CABINET_NAME
);
1566 /* create the cabinet */
1567 handleCABINET
= PFCI_OPEN(hfci
, pszFileNameCABINET
,
1568 33538, 384, &err
, p_fci_internal
->pv
);
1569 /* TODO check handle */
1570 /* TODO error checking of err */
1572 memcpy(cfheader
.signature
,"!CAB",4);
1573 cfheader
.reserved1
=0;
1574 cfheader
.cbCabinet
= /* size of the cabinet file in bytes */
1576 p_fci_internal
->sizeFileCFFOLDER
+
1577 p_fci_internal
->sizeFileCFFILE2
+
1578 p_fci_internal
->sizeFileCFDATA2
;
1580 if (p_fci_internal
->fPrevCab
) {
1581 cfheader
.cbCabinet
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1582 strlen(p_fci_internal
->szPrevDisk
)+1;
1584 if (p_fci_internal
->fNextCab
) {
1585 cfheader
.cbCabinet
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1586 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1588 if( p_fci_internal
->fNextCab
||
1589 p_fci_internal
->fGetNextCabInVain
) {
1590 cfheader
.cbCabinet
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1591 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1592 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1593 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1594 cfheader
.cbCabinet
+=4;
1597 cfheader
.cbCabinet
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1598 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1599 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1600 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1601 cfheader
.cbCabinet
+=4;
1605 cfheader
.reserved2
=0;
1606 cfheader
.coffFiles
= /* offset to first CFFILE section */
1607 cfheader
.cbCabinet
- p_fci_internal
->sizeFileCFFILE2
-
1608 p_fci_internal
->sizeFileCFDATA2
;
1610 cfheader
.reserved3
=0;
1611 cfheader
.versionMinor
=3;
1612 cfheader
.versionMajor
=1;
1613 /* number of CFFOLDER entries in the cabinet */
1614 cfheader
.cFolders
=p_fci_internal
->cFolders
;
1615 /* number of CFFILE entries in the cabinet */
1616 cfheader
.cFiles
=p_fci_internal
->cFiles
;
1617 cfheader
.flags
=0; /* 1=prev cab, 2=next cabinet, 4=reserved setions */
1619 if( p_fci_internal
->fPrevCab
) {
1620 cfheader
.flags
= cfheadPREV_CABINET
;
1623 if( p_fci_internal
->fNextCab
) {
1624 cfheader
.flags
|= cfheadNEXT_CABINET
;
1627 if( p_fci_internal
->fNextCab
||
1628 p_fci_internal
->fGetNextCabInVain
) {
1629 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1630 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1631 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1632 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1634 cfheader
.setID
= p_fci_internal
->oldCCAB
.setID
;
1635 cfheader
.iCabinet
= p_fci_internal
->oldCCAB
.iCab
-1;
1637 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1638 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1639 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1640 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1642 cfheader
.setID
= p_fci_internal
->pccab
->setID
;
1643 cfheader
.iCabinet
= p_fci_internal
->pccab
->iCab
-1;
1646 /* set little endian */
1647 cfheader
.reserved1
=fci_set_little_endian_ulong(cfheader
.reserved1
);
1648 cfheader
.cbCabinet
=fci_set_little_endian_ulong(cfheader
.cbCabinet
);
1649 cfheader
.reserved2
=fci_set_little_endian_ulong(cfheader
.reserved2
);
1650 cfheader
.coffFiles
=fci_set_little_endian_ulong(cfheader
.coffFiles
);
1651 cfheader
.reserved3
=fci_set_little_endian_ulong(cfheader
.reserved3
);
1652 cfheader
.cFolders
=fci_set_little_endian_uword(cfheader
.cFolders
);
1653 cfheader
.cFiles
=fci_set_little_endian_uword(cfheader
.cFiles
);
1654 cfheader
.flags
=fci_set_little_endian_uword(cfheader
.flags
);
1655 cfheader
.setID
=fci_set_little_endian_uword(cfheader
.setID
);
1656 cfheader
.iCabinet
=fci_set_little_endian_uword(cfheader
.iCabinet
);
1658 /* write CFHEADER into cabinet file */
1659 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1660 &cfheader
, /* memory buffer */
1661 sizeof(cfheader
), /* number of bytes to copy */
1662 &err
, p_fci_internal
->pv
) != sizeof(cfheader
) ) {
1663 /* TODO write error */
1666 /* TODO error handling of err */
1668 /* reset little endian */
1669 cfheader
.reserved1
=fci_get_little_endian_ulong(cfheader
.reserved1
);
1670 cfheader
.cbCabinet
=fci_get_little_endian_ulong(cfheader
.cbCabinet
);
1671 cfheader
.reserved2
=fci_get_little_endian_ulong(cfheader
.reserved2
);
1672 cfheader
.coffFiles
=fci_get_little_endian_ulong(cfheader
.coffFiles
);
1673 cfheader
.reserved3
=fci_get_little_endian_ulong(cfheader
.reserved3
);
1674 cfheader
.cFolders
=fci_get_little_endian_uword(cfheader
.cFolders
);
1675 cfheader
.cFiles
=fci_get_little_endian_uword(cfheader
.cFiles
);
1676 cfheader
.flags
=fci_get_little_endian_uword(cfheader
.flags
);
1677 cfheader
.setID
=fci_get_little_endian_uword(cfheader
.setID
);
1678 cfheader
.iCabinet
=fci_get_little_endian_uword(cfheader
.iCabinet
);
1680 if( cfheader
.flags
& cfheadRESERVE_PRESENT
) {
1681 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1682 cfreserved
.cbCFHeader
= cbReserveCFHeader
;
1683 cfreserved
.cbCFFolder
= cbReserveCFFolder
;
1684 if( p_fci_internal
->fNextCab
||
1685 p_fci_internal
->fGetNextCabInVain
) {
1686 cfreserved
.cbCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1688 cfreserved
.cbCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1691 /* set little endian */
1692 cfreserved
.cbCFHeader
=fci_set_little_endian_uword(cfreserved
.cbCFHeader
);
1694 /* write reserved info into cabinet file */
1695 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1696 &cfreserved
, /* memory buffer */
1697 sizeof(cfreserved
), /* number of bytes to copy */
1698 &err
, p_fci_internal
->pv
) != sizeof(cfreserved
) ) {
1699 /* TODO write error */
1702 /* TODO error handling of err */
1704 /* reset little endian */
1705 cfreserved
.cbCFHeader
=fci_get_little_endian_uword(cfreserved
.cbCFHeader
);
1708 /* add optional reserved area */
1709 if (cbReserveCFHeader
!=0) {
1710 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFHeader
))) {
1711 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
1712 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1713 p_fci_internal
->perf
->fError
= TRUE
;
1714 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1717 for(i
=0;i
<cbReserveCFHeader
;) {
1720 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1721 reserved
, /* memory buffer */
1722 cbReserveCFHeader
, /* number of bytes to copy */
1723 &err
, p_fci_internal
->pv
) != cbReserveCFHeader
) {
1724 PFCI_FREE(hfci
, reserved
);
1725 /* TODO write error */
1728 /* TODO error handling of err */
1729 PFCI_FREE(hfci
, reserved
);
1732 if( cfheader
.flags
& cfheadPREV_CABINET
) {
1733 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1734 p_fci_internal
->szPrevCab
, /* memory buffer */
1735 strlen(p_fci_internal
->szPrevCab
)+1, /* number of bytes to copy */
1736 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevCab
)+1 ) {
1737 /* TODO write error */
1740 /* TODO error handling of err */
1742 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1743 p_fci_internal
->szPrevDisk
, /* memory buffer */
1744 strlen(p_fci_internal
->szPrevDisk
)+1, /* number of bytes to copy */
1745 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevDisk
)+1 ) {
1746 /* TODO write error */
1749 /* TODO error handling of err */
1752 if( cfheader
.flags
& cfheadNEXT_CABINET
) {
1753 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1754 p_fci_internal
->pccab
->szCab
, /* memory buffer */
1755 strlen(p_fci_internal
->pccab
->szCab
)+1, /* number of bytes to copy */
1756 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szCab
)+1 ) {
1757 /* TODO write error */
1760 /* TODO error handling of err */
1762 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1763 p_fci_internal
->pccab
->szDisk
, /* memory buffer */
1764 strlen(p_fci_internal
->pccab
->szDisk
)+1, /* number of bytes to copy */
1765 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szDisk
)+1 ) {
1766 /* TODO write error */
1769 /* TODO error handling of err */
1772 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1773 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFOLDER
,
1774 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1775 /* TODO wrong return value */
1777 /* TODO error handling of err */
1779 /* while not all CFFOLDER structures have been copied into the cabinet do */
1781 /* use the variable read_result */
1782 /* read cffolder of p_fci_internal->handleCFFOLDER */
1783 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* handle */
1784 &cffolder
, /* memory buffer */
1785 sizeof(cffolder
), /* number of bytes to copy */
1786 &err
, p_fci_internal
->pv
);
1787 if( read_result
!= sizeof(cffolder
) ) {
1788 if( read_result
== 0 ) break; /*ALL CFFOLDER structures have been copied*/
1789 /* TODO read error */
1792 /* TODO error handling of err */
1794 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1795 cffolder
.coffCabStart
+=
1796 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
1798 if( p_fci_internal
->fNextCab
||
1799 p_fci_internal
->fGetNextCabInVain
) {
1800 cffolder
.coffCabStart
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1802 cffolder
.coffCabStart
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1805 if (p_fci_internal
->fPrevCab
) {
1806 cffolder
.coffCabStart
+= strlen(p_fci_internal
->szPrevCab
)+1 +
1807 strlen(p_fci_internal
->szPrevDisk
)+1;
1810 if (p_fci_internal
->fNextCab
) {
1811 cffolder
.coffCabStart
+= strlen(p_fci_internal
->oldCCAB
.szCab
)+1 +
1812 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1;
1815 if( p_fci_internal
->fNextCab
||
1816 p_fci_internal
->fGetNextCabInVain
) {
1817 cffolder
.coffCabStart
+= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1818 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1819 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1820 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1821 cffolder
.coffCabStart
+= 4;
1824 cffolder
.coffCabStart
+= p_fci_internal
->pccab
->cbReserveCFHeader
;
1825 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1826 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1827 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1828 cffolder
.coffCabStart
+= 4;
1832 /* set little endian */
1833 cffolder
.coffCabStart
=fci_set_little_endian_ulong(cffolder
.coffCabStart
);
1834 cffolder
.cCFData
=fci_set_little_endian_uword(cffolder
.cCFData
);
1835 cffolder
.typeCompress
=fci_set_little_endian_uword(cffolder
.typeCompress
);
1837 /* write cffolder to cabinet file */
1838 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1839 &cffolder
, /* memory buffer */
1840 sizeof(cffolder
), /* number of bytes to copy */
1841 &err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
1842 /* TODO write error */
1845 /* TODO error handling of err */
1847 /* reset little endian */
1848 cffolder
.coffCabStart
=fci_get_little_endian_ulong(cffolder
.coffCabStart
);
1849 cffolder
.cCFData
=fci_get_little_endian_uword(cffolder
.cCFData
);
1850 cffolder
.typeCompress
=fci_get_little_endian_uword(cffolder
.typeCompress
);
1852 /* add optional reserved area */
1854 /* This allocation and freeing at each CFFolder block is a bit */
1855 /* inefficent, but it's harder to forget about freeing the buffer :-). */
1856 /* Reserved areas are used seldom besides that... */
1857 if (cbReserveCFFolder
!=0) {
1858 if(!(reserved
= PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
1859 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
1860 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1861 p_fci_internal
->perf
->fError
= TRUE
;
1862 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1866 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
1867 reserved
, /* memory buffer */
1868 cbReserveCFFolder
, /* number of bytes to copy */
1869 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1870 PFCI_FREE(hfci
, reserved
);
1871 /* TODO read error */
1874 /* TODO error handling of err */
1876 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1877 reserved
, /* memory buffer */
1878 cbReserveCFFolder
, /* number of bytes to copy */
1879 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1880 PFCI_FREE(hfci
, reserved
);
1881 /* TODO read error */
1884 /* TODO error handling of err */
1886 PFCI_FREE(hfci
, reserved
);
1889 } /* END OF while */
1891 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1892 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE2
,
1893 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1894 /* TODO wrong return value */
1896 /* TODO error handling of err */
1898 /* while not all CFFILE structures have been copied to the cabinet do */
1900 /* REUSE the variable read_result */
1901 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1902 /* read a block from p_fci_internal->handleCFFILE2 */
1903 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFILE2
/* handle */,
1904 p_fci_internal
->data_out
, /* memory buffer */
1905 32768, /* number of bytes to copy */
1906 &err
, p_fci_internal
->pv
);
1907 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
1908 /* TODO error handling of err */
1910 /* write the block to the cabinet file */
1911 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1912 p_fci_internal
->data_out
, /* memory buffer */
1913 read_result
, /* number of bytes to copy */
1914 &err
, p_fci_internal
->pv
) != read_result
) {
1915 /* TODO write error */
1918 /* TODO error handling of err */
1920 if (p_fci_internal
->fSplitFolder
==FALSE
) {
1921 p_fci_internal
->statusFolderCopied
= 0;
1922 p_fci_internal
->statusFolderTotal
= p_fci_internal
->sizeFileCFDATA2
+
1923 p_fci_internal
->sizeFileCFFILE2
;
1925 p_fci_internal
->statusFolderCopied
+= read_result
;
1927 /* TODO is this correct */
1928 /* report status with pfnfcis about copied size of folder */
1929 if( (*pfnfcis
)(statusFolder
,
1930 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
1931 p_fci_internal
->statusFolderTotal
, /* total size of folder */
1932 p_fci_internal
->pv
) == -1) {
1933 /* TODO set error code and abort */
1937 } /* END OF while */
1939 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1940 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA2
,
1941 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1942 /* TODO wrong return value */
1945 /* TODO error handling of err */
1947 /* reset the number of folders for the next cabinet */
1948 p_fci_internal
->cFolders
=0;
1949 /* reset the number of files for the next cabinet */
1950 p_fci_internal
->cFiles
=0;
1952 /* while not all CFDATA structures have been copied to the cabinet do */
1954 /* REUSE the variable read_result AGAIN */
1955 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1956 /* read a block from p_fci_internal->handleCFDATA2 */
1957 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA2
/* handle */,
1958 p_fci_internal
->data_out
, /* memory buffer */
1959 32768, /* number of bytes to copy */
1960 &err
, p_fci_internal
->pv
);
1961 if( read_result
== 0 ) break; /* ALL CFDATA structures have been copied */
1962 /* TODO error handling of err */
1964 /* write the block to the cabinet file */
1965 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1966 p_fci_internal
->data_out
, /* memory buffer */
1967 read_result
, /* number of bytes to copy */
1968 &err
, p_fci_internal
->pv
) != read_result
) {
1969 /* TODO write error */
1972 /* TODO error handling of err */
1974 p_fci_internal
->statusFolderCopied
+= read_result
;
1975 /* report status with pfnfcis about copied size of folder */
1976 if( (*pfnfcis
)(statusFolder
,
1977 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
1978 p_fci_internal
->statusFolderTotal
, /* total size of folder */
1979 p_fci_internal
->pv
) == -1) {
1980 /* TODO set error code and abort */
1983 } /* END OF while */
1985 /* set seek of the cabinet file to 0 */
1986 if( PFCI_SEEK(hfci
, handleCABINET
,
1987 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1988 /* TODO wrong return value */
1990 /* TODO error handling of err */
1992 /* write the signature "MSCF" into the cabinet file */
1993 memcpy( cfheader
.signature
, "MSCF", 4 );
1994 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1995 &cfheader
, /* memory buffer */
1996 4, /* number of bytes to copy */
1997 &err
, p_fci_internal
->pv
) != 4 ) {
1998 /* TODO write error */
2001 /* TODO error handling of err */
2003 /* close the cabinet file */
2004 PFCI_CLOSE(hfci
,handleCABINET
,&err
,p_fci_internal
->pv
);
2005 /* TODO error handling of err */
2008 /* COPIED FROM FCIDestroy */
2010 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
2011 /* TODO error handling of err */
2012 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
2013 p_fci_internal
->pv
);
2014 /* TODO error handling of err */
2015 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
2016 /* TODO error handling of err */
2017 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
2018 p_fci_internal
->pv
);
2019 /* TODO error handling of err */
2020 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
2021 /* TODO error handling of err */
2022 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
2023 p_fci_internal
->pv
);
2024 /* TODO error handling of err */
2026 /* END OF copied from FCIDestroy */
2028 /* get 3 temporary files and open them */
2029 /* write names and handles to hfci */
2032 p_fci_internal
->sizeFileCFDATA2
= 0;
2033 p_fci_internal
->sizeFileCFFILE2
= 0;
2034 p_fci_internal
->sizeFileCFFOLDER
= 0;
2036 /* COPIED FROM FCICreate */
2038 /* CFDATA with checksum and ready to be copied into cabinet */
2039 if( !PFCI_GETTEMPFILE(hfci
, p_fci_internal
->szFileNameCFDATA2
,
2041 /* TODO error handling */
2045 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
2046 /* TODO set error code */
2049 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
2050 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, p_fci_internal
->pv
);
2051 /* TODO check handle */
2052 /* TODO error checking of err */
2054 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2055 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
2057 /* TODO error handling */
2061 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
2062 /* TODO set error code */
2065 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
2066 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, p_fci_internal
->pv
);
2067 /* TODO check handle */
2068 /* TODO error checking of err */
2070 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2071 if (!PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,CB_MAX_FILENAME
)) {
2072 /* TODO error handling */
2076 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
2077 /* TODO set error code */
2080 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
2081 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, p_fci_internal
->pv
);
2082 /* TODO check handle */
2083 /* TODO error checking of err */
2085 /* END OF copied from FCICreate */
2088 /* TODO close and delete new files when return FALSE */
2091 /* report status with pfnfcis about copied size of folder */
2092 if( (*pfnfcis
)(statusCabinet
, p_fci_internal
->statusFolderTotal
, /* TODO estimated cabinet file size */
2093 cfheader
.cbCabinet
, /* real cabinet file size */ p_fci_internal
->pv
) == -1) {
2094 /* TODO set error code and abort */
2098 p_fci_internal
->fPrevCab
=TRUE
;
2099 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2100 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2102 if (p_fci_internal
->fNextCab
) {
2103 p_fci_internal
->fNextCab
=FALSE
;
2105 if (p_fci_internal
->sizeFileCFFILE1
==0 && p_fci_internal
->sizeFileCFDATA1
!=0) {
2106 /* THIS CAN NEVER HAPPEN */
2107 /* TODO set error code */
2111 /* COPIED FROM FCIAddFile and modified */
2113 /* REUSE the variable read_result */
2114 if (p_fci_internal
->fGetNextCabInVain
) {
2115 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
2116 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2117 read_result
+=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2119 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2120 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2121 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2125 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
;
2126 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2127 read_result
+=p_fci_internal
->pccab
->cbReserveCFFolder
;
2129 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2130 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2131 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2135 if ( p_fci_internal
->fPrevCab
) {
2136 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2137 strlen(p_fci_internal
->szPrevDisk
)+1;
2139 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2140 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2141 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2143 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2145 if( p_fci_internal
->fNewPrevious
) {
2146 memcpy(p_fci_internal
->szPrevCab
, p_fci_internal
->oldCCAB
.szCab
,
2147 CB_MAX_CABINET_NAME
);
2148 memcpy(p_fci_internal
->szPrevDisk
, p_fci_internal
->oldCCAB
.szDisk
,
2150 p_fci_internal
->fNewPrevious
=FALSE
;
2153 /* too much data for the maximum size of a cabinet */
2154 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2155 p_fci_internal
->pccab
->cb
< read_result
) {
2156 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2159 /* Might be too much data for the maximum size of a cabinet.*/
2160 /* When any further data will be added later, it might not */
2161 /* be possible to flush the cabinet, because there might */
2162 /* not be enough space to store the name of the following */
2163 /* cabinet and name of the corresponding disk. */
2164 /* So take care of this and get the name of the next cabinet */
2165 if (p_fci_internal
->fGetNextCabInVain
==FALSE
&& (
2166 p_fci_internal
->pccab
->cb
< read_result
+
2167 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2170 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2171 /* increment cabinet index */
2172 ++(p_fci_internal
->pccab
->iCab
);
2173 /* get name of next cabinet */
2174 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0, /* estimated size of cab */
2175 p_fci_internal
->pv
)) {
2176 /* TODO error handling */
2179 /* Skip a few lines of code. This is catched by the next if. */
2180 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2183 /* too much data for cabinet */
2184 if (p_fci_internal
->fGetNextCabInVain
&& (
2185 p_fci_internal
->oldCCAB
.cb
< read_result
+
2186 strlen(p_fci_internal
->oldCCAB
.szCab
)+1+
2187 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1
2189 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2190 p_fci_internal
->fNextCab
=TRUE
;
2191 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2194 /* if the FolderThreshold has been reached flush the folder automatically */
2195 if( p_fci_internal
->fGetNextCabInVain
) {
2196 if( p_fci_internal
->cCompressedBytesInFolder
>=
2197 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2198 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2201 if( p_fci_internal
->cCompressedBytesInFolder
>=
2202 p_fci_internal
->pccab
->cbFolderThresh
) {
2203 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2207 /* END OF COPIED FROM FCIAddFile and modified */
2209 if( p_fci_internal
->sizeFileCFFILE1
>0 ) {
2210 if( !FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
) ) return FALSE
;
2211 p_fci_internal
->fNewPrevious
=TRUE
;
2214 p_fci_internal
->fNewPrevious
=FALSE
;
2215 if( p_fci_internal
->sizeFileCFFILE1
>0 || p_fci_internal
->sizeFileCFDATA1
) {
2216 /* THIS MAY NEVER HAPPEN */
2217 /* TODO set error structures */
2223 } /* end of fci_flush_cabinet */
2229 /***********************************************************************
2230 * FCIAddFile (CABINET.11)
2232 * FCIAddFile adds a file to the to be created cabinet file
2235 * hfci [I] An HFCI from FCICreate
2236 * pszSourceFile [I] A pointer to a C string which contains the name and
2237 * location of the file which will be added to the cabinet
2238 * pszFileName [I] A pointer to a C string which contains the name under
2239 * which the file will be stored in the cabinet
2240 * fExecute [I] A boolean value which indicates if the file should be
2241 * executed after extraction of self extracting
2243 * pfnfcignc [I] A pointer to a function which gets information about
2245 * pfnfcis [IO] A pointer to a function which will report status
2246 * information about the compression process
2247 * pfnfcioi [I] A pointer to a function which reports file attributes
2248 * and time and date information
2249 * typeCompress [I] Compression type
2252 * On success, returns TRUE
2253 * On failure, returns FALSE
2259 BOOL __cdecl
FCIAddFile(
2261 char *pszSourceFile
,
2264 PFNFCIGETNEXTCABINET pfnfcignc
,
2265 PFNFCISTATUS pfnfcis
,
2266 PFNFCIGETOPENINFO pfnfcigoi
,
2271 cab_ULONG read_result
;
2273 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2276 if (!REALLY_IS_FCI(hfci
)) {
2277 SetLastError(ERROR_INVALID_HANDLE
);
2281 if ((!pszSourceFile
) || (!pszFileName
) || (!pfnfcignc
) || (!pfnfcis
) ||
2282 (!pfnfcigoi
) || strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2283 p_fci_internal
->perf
->erfOper
= FCIERR_NONE
;
2284 p_fci_internal
->perf
->erfType
= ERROR_BAD_ARGUMENTS
;
2285 p_fci_internal
->perf
->fError
= TRUE
;
2287 SetLastError(ERROR_BAD_ARGUMENTS
);
2291 /* TODO check if pszSourceFile??? */
2293 if(p_fci_internal
->fGetNextCabInVain
&& p_fci_internal
->fNextCab
) {
2294 /* TODO internal error */
2298 if(p_fci_internal
->fNextCab
) {
2299 /* TODO internal error */
2303 cffile
.cbFile
=0; /* size of the to be added file*/
2304 /* offset of the uncompressed file in the folder */
2305 cffile
.uoffFolderStart
=p_fci_internal
->cDataBlocks
*CAB_BLOCKMAX
+ p_fci_internal
->cdata_in
;
2306 /* number of folder in the cabinet or special 0=first */
2307 cffile
.iFolder
= p_fci_internal
->cFolders
;
2309 /* allocation of memory */
2310 if (p_fci_internal
->data_in
==NULL
) {
2311 if (p_fci_internal
->cdata_in
!=0) {
2312 /* TODO error handling */
2315 if (p_fci_internal
->data_out
!=NULL
) {
2316 /* TODO error handling */
2319 if(!(p_fci_internal
->data_in
= (char*)PFCI_ALLOC(hfci
,CB_MAX_CHUNK
))) {
2320 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
2321 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
2322 p_fci_internal
->perf
->fError
= TRUE
;
2323 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2326 if (p_fci_internal
->data_out
==NULL
) {
2327 if(!(p_fci_internal
->data_out
= PFCI_ALLOC(hfci
, 2 * CB_MAX_CHUNK
))){
2328 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
2329 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
2330 p_fci_internal
->perf
->fError
= TRUE
;
2331 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2337 if (p_fci_internal
->data_out
==NULL
) {
2338 PFCI_FREE(hfci
,p_fci_internal
->data_in
);
2339 /* TODO error handling */
2343 /* get information about the file */
2344 file_handle
=(*pfnfcigoi
)(pszSourceFile
, &(cffile
.date
), &(cffile
.time
),
2345 &(cffile
.attribs
), &err
, p_fci_internal
->pv
);
2346 /* TODO check file_handle */
2347 /* TODO error handling of err */
2349 if (fExecute
) { cffile
.attribs
|= _A_EXEC
; }
2351 /* REUSE the variable read_result */
2352 if (p_fci_internal
->fGetNextCabInVain
) {
2353 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2354 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2355 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2356 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2357 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2361 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2362 p_fci_internal
->pccab
->cbReserveCFFolder
;
2363 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2364 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2365 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2369 if ( p_fci_internal
->fPrevCab
) {
2370 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2371 strlen(p_fci_internal
->szPrevDisk
)+1;
2373 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2374 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2375 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2378 read_result
+= sizeof(CFFILE
) + strlen(pszFileName
)+1 +
2379 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2380 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2382 sizeof(CFFOLDER
); /* size of new CFFolder entry */
2384 /* Might be too much data for the maximum size of a cabinet.*/
2385 /* When any further data will be added later, it might not */
2386 /* be possible to flush the cabinet, because there might */
2387 /* not be enough space to store the name of the following */
2388 /* cabinet and name of the corresponding disk. */
2389 /* So take care of this and get the name of the next cabinet */
2390 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2391 p_fci_internal
->fNextCab
==FALSE
&&
2392 ( p_fci_internal
->pccab
->cb
< read_result
+
2393 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2397 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2398 /* increment cabinet index */
2399 ++(p_fci_internal
->pccab
->iCab
);
2400 /* get name of next cabinet */
2401 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0,/* TODO estimated size of cab */
2402 p_fci_internal
->pv
)) {
2403 /* TODO error handling */
2406 /* Skip a few lines of code. This is catched by the next if. */
2407 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2410 if( p_fci_internal
->fGetNextCabInVain
&&
2411 p_fci_internal
->fNextCab
2413 /* THIS CAN NEVER HAPPEN */
2414 /* TODO set error code*/
2418 /* too much data for cabinet */
2419 if( p_fci_internal
->fGetNextCabInVain
&&
2421 p_fci_internal
->oldCCAB
.cb
< read_result
+
2422 strlen(p_fci_internal
->pccab
->szCab
)+1+
2423 strlen(p_fci_internal
->pccab
->szDisk
)+1
2425 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2426 p_fci_internal
->fNextCab
=TRUE
;
2427 if(!fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
)) return FALSE
;
2430 if( p_fci_internal
->fNextCab
) {
2431 /* THIS MAY NEVER HAPPEN */
2432 /* TODO set error code*/
2436 /* read the contents of the file blockwize*/
2438 if (p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2439 /* TODO internal error */
2443 read_result
= PFCI_READ(hfci
, file_handle
/* file handle */,
2444 (p_fci_internal
->data_in
+ p_fci_internal
->cdata_in
) /* memory buffer */,
2445 (CAB_BLOCKMAX
- p_fci_internal
->cdata_in
) /* number of bytes to copy */,
2446 &err
, p_fci_internal
->pv
);
2447 /* TODO error handling of err */
2449 if( read_result
==0 ) break;
2451 /* increment the block size */
2452 p_fci_internal
->cdata_in
+= read_result
;
2454 /* increment the file size */
2455 cffile
.cbFile
+= read_result
;
2458 if ( p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2459 /* TODO report internal error */
2462 /* write a whole block */
2463 if ( p_fci_internal
->cdata_in
== CAB_BLOCKMAX
) {
2465 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
2469 /* close the file from FCIAddFile */
2470 PFCI_CLOSE(hfci
,file_handle
,&err
,p_fci_internal
->pv
);
2471 /* TODO error handling of err */
2473 /* write cffile to p_fci_internal->handleCFFILE1 */
2474 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2475 &cffile
, sizeof(cffile
),&err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
2476 /* TODO write error */
2479 /* TODO error handling of err */
2481 p_fci_internal
->sizeFileCFFILE1
+= sizeof(cffile
);
2483 /* append the name of file*/
2484 if (strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2486 /* TODO set error code */
2489 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2490 pszFileName
, strlen(pszFileName
)+1, &err
, p_fci_internal
->pv
)
2491 != strlen(pszFileName
)+1 ) {
2492 /* TODO write error */
2495 /* TODO error handling of err */
2497 p_fci_internal
->sizeFileCFFILE1
+= strlen(pszFileName
)+1;
2499 /* REUSE the variable read_result */
2500 if (p_fci_internal
->fGetNextCabInVain
||
2501 p_fci_internal
->fNextCab
2503 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2504 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2505 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2506 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2507 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2511 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2512 p_fci_internal
->pccab
->cbReserveCFFolder
;
2513 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2514 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2515 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2519 if ( p_fci_internal
->fPrevCab
) {
2520 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2521 strlen(p_fci_internal
->szPrevDisk
)+1;
2523 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2524 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2525 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2527 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2528 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2529 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2531 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2533 /* too much data for the maximum size of a cabinet */
2534 /* (ignoring the unflushed data block) */
2535 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2536 p_fci_internal
->fNextCab
==FALSE
&& /* this is always the case */
2537 p_fci_internal
->pccab
->cb
< read_result
) {
2538 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2541 /* Might be too much data for the maximum size of a cabinet.*/
2542 /* When any further data will be added later, it might not */
2543 /* be possible to flush the cabinet, because there might */
2544 /* not be enough space to store the name of the following */
2545 /* cabinet and name of the corresponding disk. */
2546 /* So take care of this and get the name of the next cabinet */
2547 /* (ignoring the unflushed data block) */
2548 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2549 p_fci_internal
->fNextCab
==FALSE
&&
2550 ( p_fci_internal
->pccab
->cb
< read_result
+
2551 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2555 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2556 /* increment cabinet index */
2557 ++(p_fci_internal
->pccab
->iCab
);
2558 /* get name of next cabinet */
2559 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0,/* TODO estimated size of cab */
2560 p_fci_internal
->pv
)) {
2561 /* TODO error handling */
2564 /* Skip a few lines of code. This is catched by the next if. */
2565 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2568 if( p_fci_internal
->fGetNextCabInVain
&&
2569 p_fci_internal
->fNextCab
2571 /* THIS CAN NEVER HAPPEN */
2572 /* TODO set error code*/
2576 /* too much data for cabinet */
2577 if( (p_fci_internal
->fGetNextCabInVain
||
2578 p_fci_internal
->fNextCab
) && (
2579 p_fci_internal
->oldCCAB
.cb
< read_result
+
2580 strlen(p_fci_internal
->pccab
->szCab
)+1+
2581 strlen(p_fci_internal
->pccab
->szDisk
)+1
2584 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2585 p_fci_internal
->fNextCab
=TRUE
;
2586 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2589 if( p_fci_internal
->fNextCab
) {
2590 /* THIS MAY NEVER HAPPEN */
2591 /* TODO set error code*/
2595 /* if the FolderThreshold has been reached flush the folder automatically */
2596 if( p_fci_internal
->fGetNextCabInVain
) {
2597 if( p_fci_internal
->cCompressedBytesInFolder
>=
2598 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2599 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2602 if( p_fci_internal
->cCompressedBytesInFolder
>=
2603 p_fci_internal
->pccab
->cbFolderThresh
) {
2604 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2609 } /* end of FCIAddFile */
2615 /***********************************************************************
2616 * FCIFlushFolder (CABINET.12)
2618 * FCIFlushFolder completes the CFFolder structure under construction.
2620 * All further data which is added by FCIAddFile will be associateed to
2621 * the next CFFolder structure.
2623 * FCIFlushFolder will be called by FCIAddFile automatically if the
2624 * threshold (stored in the member cbFolderThresh of the CCAB structure
2625 * pccab passed to FCICreate) is exceeded.
2627 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2628 * any data will be written into the cabinet file.
2631 * hfci [I] An HFCI from FCICreate
2632 * pfnfcignc [I] A pointer to a function which gets information about
2634 * pfnfcis [IO] A pointer to a function which will report status
2635 * information about the compression process
2638 * On success, returns TRUE
2639 * On failure, returns FALSE
2645 BOOL __cdecl
FCIFlushFolder(
2647 PFNFCIGETNEXTCABINET pfnfcignc
,
2648 PFNFCISTATUS pfnfcis
)
2650 return fci_flush_folder(hfci
,FALSE
,pfnfcignc
,pfnfcis
);
2651 } /* end of FCIFlushFolder */
2655 /***********************************************************************
2656 * FCIFlushCabinet (CABINET.13)
2658 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2659 * into the cabinet file. If the maximum cabinet size (stored in the
2660 * member cb of the CCAB structure pccab passed to FCICreate) has been
2661 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2662 * The remaining data still has to be flushed manually by calling
2665 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2666 * NOT be called again. Then hfci has to be released by FCIDestroy.
2669 * hfci [I] An HFCI from FCICreate
2670 * fGetNextCab [I] Whether you want to add additional files to a
2671 * cabinet set (TRUE) or whether you want to
2672 * finalize it (FALSE)
2673 * pfnfcignc [I] A pointer to a function which gets information about
2675 * pfnfcis [IO] A pointer to a function which will report status
2676 * information about the compression process
2679 * On success, returns TRUE
2680 * On failure, returns FALSE
2686 BOOL __cdecl
FCIFlushCabinet(
2689 PFNFCIGETNEXTCABINET pfnfcignc
,
2690 PFNFCISTATUS pfnfcis
)
2692 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2694 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2696 while( p_fci_internal
->sizeFileCFFILE1
>0 ||
2697 p_fci_internal
->sizeFileCFFILE2
>0 ) {
2698 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2702 } /* end of FCIFlushCabinet */
2705 /***********************************************************************
2706 * FCIDestroy (CABINET.14)
2708 * Frees a handle created by FCICreate.
2709 * Only reason for failure would be an invalid handle.
2712 * hfci [I] The HFCI to free
2718 BOOL __cdecl
FCIDestroy(HFCI hfci
)
2721 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2722 if (REALLY_IS_FCI(hfci
)) {
2724 /* before hfci can be removed all temporary files must be closed */
2726 p_fci_internal
->FCI_Intmagic
= 0;
2728 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
2729 /* TODO error handling of err */
2730 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA1
, &err
,
2731 p_fci_internal
->pv
);
2732 /* TODO error handling of err */
2733 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE1
,&err
,p_fci_internal
->pv
);
2734 /* TODO error handling of err */
2735 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE1
, &err
,
2736 p_fci_internal
->pv
);
2737 /* TODO error handling of err */
2738 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
2739 /* TODO error handling of err */
2740 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
2741 p_fci_internal
->pv
);
2742 /* TODO error handling of err */
2743 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
2744 /* TODO error handling of err */
2745 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
2746 p_fci_internal
->pv
);
2747 /* TODO error handling of err */
2748 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
2749 /* TODO error handling of err */
2750 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
2751 p_fci_internal
->pv
);
2752 /* TODO error handling of err */
2754 /* data in and out buffers have to be removed */
2755 if (p_fci_internal
->data_in
!=NULL
)
2756 PFCI_FREE(hfci
, p_fci_internal
->data_in
);
2757 if (p_fci_internal
->data_out
!=NULL
)
2758 PFCI_FREE(hfci
, p_fci_internal
->data_out
);
2760 /* hfci can now be removed */
2761 PFCI_FREE(hfci
, hfci
);
2764 SetLastError(ERROR_INVALID_HANDLE
);
2768 } /* end of FCIDestroy */