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"
53 #ifdef WORDS_BIGENDIAN
54 #define fci_endian_ulong(x) RtlUlongByteSwap(x)
55 #define fci_endian_uword(x) RtlUshortByteSwap(x)
57 #define fci_endian_ulong(x) (x)
58 #define fci_endian_uword(x) (x)
62 WINE_DEFAULT_DEBUG_CHANNEL(cabinet
);
65 cab_UBYTE signature
[4]; /* !CAB for unfinished cabinets else MSCF */
67 cab_ULONG cbCabinet
; /* size of the cabinet file in bytes*/
69 cab_ULONG coffFiles
; /* offset to first CFFILE section */
71 cab_UBYTE versionMinor
; /* 3 */
72 cab_UBYTE versionMajor
; /* 1 */
73 cab_UWORD cFolders
; /* number of CFFOLDER entries in the cabinet*/
74 cab_UWORD cFiles
; /* number of CFFILE entries in the cabinet*/
75 cab_UWORD flags
; /* 1=prev cab, 2=next cabinet, 4=reserved setions*/
76 cab_UWORD setID
; /* identification number of all cabinets in a set*/
77 cab_UWORD iCabinet
; /* number of the cabinet in a set */
78 /* additional area if "flags" were set*/
79 } CFHEADER
; /* minimum 36 bytes */
82 cab_ULONG coffCabStart
; /* offset to the folder's first CFDATA section */
83 cab_UWORD cCFData
; /* number of this folder's CFDATA sections */
84 cab_UWORD typeCompress
; /* compression type of data in CFDATA section*/
85 /* additional area if reserve flag was set */
86 } CFFOLDER
; /* minumum 8 bytes */
89 cab_ULONG cbFile
; /* size of the uncompressed file in bytes */
90 cab_ULONG uoffFolderStart
; /* offset of the uncompressed file in the folder */
91 cab_UWORD iFolder
; /* number of folder in the cabinet 0=first */
92 /* for special values see below this structure*/
93 cab_UWORD date
; /* last modification date*/
94 cab_UWORD time
; /* last modification time*/
95 cab_UWORD attribs
; /* DOS fat attributes and UTF indicator */
96 /* ... and a C string with the name of the file */
97 } CFFILE
; /* 16 bytes + name of file */
101 cab_ULONG csum
; /* checksum of this entry*/
102 cab_UWORD cbData
; /* number of compressed bytes */
103 cab_UWORD cbUncomp
; /* number of bytes when data is uncompressed */
104 /* optional reserved area */
105 /* compressed data */
109 /***********************************************************************
110 * FCICreate (CABINET.10)
112 * FCICreate is provided with several callbacks and
113 * returns a handle which can be used to create cabinet files.
116 * perf [IO] A pointer to an ERF structure. When FCICreate
117 * returns an error condition, error information may
118 * be found here as well as from GetLastError.
119 * pfnfiledest [I] A pointer to a function which is called when a file
120 * is placed. Only useful for subsequent cabinet files.
121 * pfnalloc [I] A pointer to a function which allocates ram. Uses
122 * the same interface as malloc.
123 * pfnfree [I] A pointer to a function which frees ram. Uses the
124 * same interface as free.
125 * pfnopen [I] A pointer to a function which opens a file. Uses
126 * the same interface as _open.
127 * pfnread [I] A pointer to a function which reads from a file into
128 * a caller-provided buffer. Uses the same interface
130 * pfnwrite [I] A pointer to a function which writes to a file from
131 * a caller-provided buffer. Uses the same interface
133 * pfnclose [I] A pointer to a function which closes a file handle.
134 * Uses the same interface as _close.
135 * pfnseek [I] A pointer to a function which seeks in a file.
136 * Uses the same interface as _lseek.
137 * pfndelete [I] A pointer to a function which deletes a file.
138 * pfnfcigtf [I] A pointer to a function which gets the name of a
140 * pccab [I] A pointer to an initialized CCAB structure.
141 * pv [I] A pointer to an application-defined notification
142 * function which will be passed to other FCI functions
146 * On success, returns an FCI handle of type HFCI.
147 * On failure, the NULL file handle is returned. Error
148 * info can be retrieved from perf.
154 HFCI __cdecl
FCICreate(
156 PFNFCIFILEPLACED pfnfiledest
,
157 PFNFCIALLOC pfnalloc
,
161 PFNFCIWRITE pfnwrite
,
162 PFNFCICLOSE pfnclose
,
164 PFNFCIDELETE pfndelete
,
165 PFNFCIGETTEMPFILE pfnfcigtf
,
171 PFCI_Int p_fci_internal
;
173 if ((!perf
) || (!pfnalloc
) || (!pfnfree
) || (!pfnopen
) || (!pfnread
) ||
174 (!pfnwrite
) || (!pfnclose
) || (!pfnseek
) || (!pfndelete
) ||
175 (!pfnfcigtf
) || (!pccab
)) {
176 perf
->erfOper
= FCIERR_NONE
;
177 perf
->erfType
= ERROR_BAD_ARGUMENTS
;
180 SetLastError(ERROR_BAD_ARGUMENTS
);
184 if (!((hfci
= ((HFCI
) (*pfnalloc
)(sizeof(FCI_Int
)))))) {
185 perf
->erfOper
= FCIERR_ALLOC_FAIL
;
186 perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
189 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
193 p_fci_internal
=((PFCI_Int
)(hfci
));
194 p_fci_internal
->FCI_Intmagic
= FCI_INT_MAGIC
;
195 p_fci_internal
->perf
= perf
;
196 p_fci_internal
->pfnfiledest
= pfnfiledest
;
197 p_fci_internal
->pfnalloc
= pfnalloc
;
198 p_fci_internal
->pfnfree
= pfnfree
;
199 p_fci_internal
->pfnopen
= pfnopen
;
200 p_fci_internal
->pfnread
= pfnread
;
201 p_fci_internal
->pfnwrite
= pfnwrite
;
202 p_fci_internal
->pfnclose
= pfnclose
;
203 p_fci_internal
->pfnseek
= pfnseek
;
204 p_fci_internal
->pfndelete
= pfndelete
;
205 p_fci_internal
->pfnfcigtf
= pfnfcigtf
;
206 p_fci_internal
->pccab
= pccab
;
207 p_fci_internal
->fPrevCab
= FALSE
;
208 p_fci_internal
->fNextCab
= FALSE
;
209 p_fci_internal
->fSplitFolder
= FALSE
;
210 p_fci_internal
->fGetNextCabInVain
= FALSE
;
211 p_fci_internal
->pv
= pv
;
212 p_fci_internal
->data_in
= NULL
;
213 p_fci_internal
->cdata_in
= 0;
214 p_fci_internal
->data_out
= NULL
;
215 p_fci_internal
->cCompressedBytesInFolder
= 0;
216 p_fci_internal
->cFolders
= 0;
217 p_fci_internal
->cFiles
= 0;
218 p_fci_internal
->cDataBlocks
= 0;
219 p_fci_internal
->sizeFileCFDATA1
= 0;
220 p_fci_internal
->sizeFileCFFILE1
= 0;
221 p_fci_internal
->sizeFileCFDATA2
= 0;
222 p_fci_internal
->sizeFileCFFILE2
= 0;
223 p_fci_internal
->sizeFileCFFOLDER
= 0;
224 p_fci_internal
->sizeFileCFFOLDER
= 0;
225 p_fci_internal
->fNewPrevious
= FALSE
;
227 memcpy(p_fci_internal
->szPrevCab
, pccab
->szCab
, CB_MAX_CABINET_NAME
);
228 memcpy(p_fci_internal
->szPrevDisk
, pccab
->szDisk
, CB_MAX_DISK_NAME
);
231 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFDATA1
,
233 /* TODO error handling */
237 if ( strlen(p_fci_internal
->szFileNameCFDATA1
) >= CB_MAX_FILENAME
) {
238 /* TODO set error code */
242 p_fci_internal
->handleCFDATA1
= PFCI_OPEN(hfci
,
243 p_fci_internal
->szFileNameCFDATA1
, 34050, 384, &err
, pv
);
244 /* TODO check handle */
245 /* TODO error checking of err */
247 /* array of all CFFILE in a folder */
248 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE1
,
250 /* TODO error handling */
254 if ( strlen(p_fci_internal
->szFileNameCFFILE1
) >= CB_MAX_FILENAME
) {
255 /* TODO set error code */
258 p_fci_internal
->handleCFFILE1
= PFCI_OPEN(hfci
,
259 p_fci_internal
->szFileNameCFFILE1
, 34050, 384, &err
, pv
);
260 /* TODO check handle */
261 /* TODO error checking of err */
263 /* CFDATA with checksum and ready to be copied into cabinet */
264 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFDATA2
,
266 /* TODO error handling */
270 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
271 /* TODO set error code */
274 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
275 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, pv
);
276 /* TODO check handle */
277 /* TODO error checking of err */
279 /* array of all CFFILE in a folder, ready to be copied into cabinet */
280 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
282 /* TODO error handling */
286 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
287 /* TODO set error code */
290 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
291 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, pv
);
292 /* TODO check handle */
293 /* TODO error checking of err */
295 /* array of all CFFILE in a folder, ready to be copied into cabinet */
296 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,
298 /* TODO error handling */
302 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
303 /* TODO set error code */
306 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
307 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, pv
);
310 /* TODO close and delete new files when return FALSE */
312 /* TODO check handle */
313 /* TODO error checking of err */
316 } /* end of FCICreate */
323 static BOOL
fci_flush_data_block (HFCI hfci
, int* err
,
324 PFNFCISTATUS pfnfcis
) {
326 /* attention no hfci checks!!! */
327 /* attention no checks if there is data available!!! */
329 CFDATA
* cfdata
=&data
;
331 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
332 UINT cbReserveCFData
=p_fci_internal
->pccab
->cbReserveCFData
;
335 /* TODO compress the data of p_fci_internal->data_in */
336 /* and write it to p_fci_internal->data_out */
337 memcpy(p_fci_internal
->data_out
, p_fci_internal
->data_in
,
338 p_fci_internal
->cdata_in
/* number of bytes to copy */);
340 cfdata
->csum
=0; /* checksum has to be set later */
341 /* TODO set realsize of compressed data */
342 cfdata
->cbData
= p_fci_internal
->cdata_in
;
343 cfdata
->cbUncomp
= p_fci_internal
->cdata_in
;
345 /* write cfdata to p_fci_internal->handleCFDATA1 */
346 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
347 cfdata
, sizeof(*cfdata
), err
, p_fci_internal
->pv
)
348 != sizeof(*cfdata
) ) {
349 /* TODO write error */
352 /* TODO error handling of err */
354 p_fci_internal
->sizeFileCFDATA1
+= sizeof(*cfdata
);
356 /* add optional reserved area */
358 /* This allocation and freeing at each CFData block is a bit */
359 /* inefficent, but it's harder to forget about freeing the buffer :-). */
360 /* Reserved areas are used seldom besides that... */
361 if (cbReserveCFData
!=0) {
362 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFData
))) {
363 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
364 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
365 p_fci_internal
->perf
->fError
= TRUE
;
366 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
369 for(i
=0;i
<cbReserveCFData
;) {
372 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
373 reserved
, /* memory buffer */
374 cbReserveCFData
, /* number of bytes to copy */
375 err
, p_fci_internal
->pv
) != cbReserveCFData
) {
376 PFCI_FREE(hfci
, reserved
);
377 /* TODO write error */
380 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
382 p_fci_internal
->sizeFileCFDATA1
+= cbReserveCFData
;
383 PFCI_FREE(hfci
, reserved
);
386 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
387 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA1
, /* file handle */
388 p_fci_internal
->data_out
, /* memory buffer */
389 cfdata
->cbData
, /* number of bytes to copy */
390 err
, p_fci_internal
->pv
) != cfdata
->cbData
) {
391 /* TODO write error */
394 /* TODO error handling of err */
396 p_fci_internal
->sizeFileCFDATA1
+= cfdata
->cbData
;
398 /* reset the offset */
399 p_fci_internal
->cdata_in
= 0;
400 p_fci_internal
->cCompressedBytesInFolder
+= cfdata
->cbData
;
402 /* report status with pfnfcis about uncompressed and compressed file data */
403 if( (*pfnfcis
)(statusFile
, cfdata
->cbData
, cfdata
->cbUncomp
,
404 p_fci_internal
->pv
) == -1) {
405 /* TODO set error code and abort */
409 ++(p_fci_internal
->cDataBlocks
);
412 } /* end of fci_flush_data_block */
418 static cab_ULONG
fci_get_checksum(void *pv
, UINT cb
, CHECKSUM seed
)
429 while (cUlong
-- > 0) {
431 ul
|= (((cab_ULONG
)(*pb
++)) << 8);
432 ul
|= (((cab_ULONG
)(*pb
++)) << 16);
433 ul
|= (((cab_ULONG
)(*pb
++)) << 24);
441 ul
|= (((ULONG
)(*pb
++)) << 16);
443 ul
|= (((ULONG
)(*pb
++)) << 8);
452 } /* end of fci_get_checksum */
458 static BOOL
fci_flushfolder_copy_cfdata(HFCI hfci
, char* buffer
, UINT cbReserveCFData
,
459 PFNFCISTATUS pfnfcis
, int* err
, int handleCFDATA1new
,
460 cab_ULONG
* psizeFileCFDATA1new
, cab_ULONG
* payload
)
462 cab_ULONG read_result
;
463 CFDATA
* pcfdata
=(CFDATA
*)buffer
;
464 BOOL split_block
=FALSE
;
465 cab_UWORD savedUncomp
=0;
466 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
470 /* while not all CFDATAs have been copied do */
472 if( p_fci_internal
->fNextCab
) {
474 /* TODO internal error should never happen */
478 /* REUSE the variable read_result */
479 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
480 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
481 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
486 if (p_fci_internal
->fPrevCab
) {
487 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
488 strlen(p_fci_internal
->szPrevDisk
)+1;
490 /* No more CFDATA fits into the cabinet under construction */
491 /* So don't try to store more data into it */
492 if( p_fci_internal
->fNextCab
&&
493 (p_fci_internal
->oldCCAB
.cb
<= sizeof(CFDATA
) + cbReserveCFData
+
494 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
495 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
498 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
500 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
501 strlen(p_fci_internal
->pccab
->szCab
)+1 +
502 strlen(p_fci_internal
->pccab
->szDisk
)+1
504 /* This may never be run for the first time the while loop is entered.
505 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
506 split_block
=TRUE
; /* In this case split_block is abused to store */
507 /* the complete data block into the next cabinet and not into the */
508 /* current one. Originally split_block is the indicator that a */
509 /* data block has been splitted across different cabinets. */
512 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
513 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/*file handle*/
514 buffer
, /* memory buffer */
515 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
516 err
, p_fci_internal
->pv
);
517 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
518 if (read_result
==0) break; /* ALL DATA has been copied */
519 /* TODO read error */
522 /* TODO error handling of err */
524 /* REUSE buffer p_fci_internal->data_out !!! */
525 /* read data from p_fci_internal->handleCFDATA1 to */
526 /* p_fci_internal->data_out */
527 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
528 p_fci_internal
->data_out
/* memory buffer */,
529 pcfdata
->cbData
/* number of bytes to copy */,
530 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
531 /* TODO read error */
534 /* TODO error handling of err */
536 /* if cabinet size is too large */
538 /* REUSE the variable read_result */
539 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
540 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
541 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
546 if (p_fci_internal
->fPrevCab
) {
547 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
548 strlen(p_fci_internal
->szPrevDisk
)+1;
551 /* Is cabinet with new CFDATA too large? Then data block has to be split */
552 if( p_fci_internal
->fNextCab
&&
553 (p_fci_internal
->oldCCAB
.cb
< sizeof(CFDATA
) + cbReserveCFData
+
555 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
556 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
559 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
560 sizeof(CFFOLDER
) + /* size of new CFFolder entry */
561 p_fci_internal
->oldCCAB
.cbReserveCFFolder
+
562 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* name of next cabinet */
563 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* name of next disk */
565 /* REUSE read_result to save the size of the compressed data */
566 read_result
=pcfdata
->cbData
;
567 /* Modify the size of the compressed data to store only a part of the */
568 /* data block into the current cabinet. This is done to prevent */
569 /* that the maximum cabinet size will be exceeded. The remainder */
570 /* will be stored into the next following cabinet. */
572 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
573 /* Substract everything except the size of the block of data */
574 /* to get it's actual size */
575 pcfdata
->cbData
= p_fci_internal
->oldCCAB
.cb
- (
576 sizeof(CFDATA
) + cbReserveCFData
+
577 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
578 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
580 p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
581 sizeof(CFFOLDER
) + /* set size of new CFFolder entry */
582 p_fci_internal
->oldCCAB
.cbReserveCFFolder
);
583 /* substract the size of special header fields */
584 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
585 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
586 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
589 if (p_fci_internal
->fPrevCab
) {
590 pcfdata
->cbData
-=strlen(p_fci_internal
->szPrevCab
)+1 +
591 strlen(p_fci_internal
->szPrevDisk
)+1;
593 pcfdata
->cbData
-=strlen(p_fci_internal
->pccab
->szCab
)+1 +
594 strlen(p_fci_internal
->pccab
->szDisk
)+1;
596 savedUncomp
= pcfdata
->cbUncomp
;
597 pcfdata
->cbUncomp
= 0; /* on splitted blocks of data this is zero */
599 /* if split_block==TRUE then the above while loop won't */
600 /* be executed again */
601 split_block
=TRUE
; /* split_block is the indicator that */
602 /* a data block has been splitted across */
603 /* diffentent cabinets.*/
606 /* This should never happen !!! */
607 if (pcfdata
->cbData
==0) {
612 /* set little endian */
613 pcfdata
->cbData
=fci_endian_uword(pcfdata
->cbData
);
614 pcfdata
->cbUncomp
=fci_endian_uword(pcfdata
->cbUncomp
);
616 /* get checksum and write to cfdata.csum */
617 pcfdata
->csum
= fci_get_checksum( &(pcfdata
->cbData
),
618 sizeof(CFDATA
)+cbReserveCFData
-
619 sizeof(pcfdata
->csum
), fci_get_checksum( p_fci_internal
->data_out
, /*buffer*/
620 pcfdata
->cbData
, 0 ) );
622 /* set little endian */
623 pcfdata
->csum
=fci_endian_ulong(pcfdata
->csum
);
625 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
626 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
627 buffer
, /* memory buffer */
628 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
629 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
630 /* TODO write error */
633 /* TODO error handling of err */
635 p_fci_internal
->sizeFileCFDATA2
+= sizeof(CFDATA
)+cbReserveCFData
;
637 /* reset little endian */
638 pcfdata
->cbData
=fci_endian_uword(pcfdata
->cbData
);
639 pcfdata
->cbUncomp
=fci_endian_uword(pcfdata
->cbUncomp
);
640 pcfdata
->csum
=fci_endian_ulong(pcfdata
->csum
);
642 /* write compressed data into p_fci_internal->handleCFDATA2 */
643 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFDATA2
, /* file handle */
644 p_fci_internal
->data_out
, /* memory buffer */
645 pcfdata
->cbData
, /* number of bytes to copy */
646 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
647 /* TODO write error */
650 /* TODO error handling of err */
652 p_fci_internal
->sizeFileCFDATA2
+= pcfdata
->cbData
;
653 ++(p_fci_internal
->cDataBlocks
);
654 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
655 (*payload
)+=pcfdata
->cbUncomp
;
656 /* if cabinet size too large and data has been split */
657 /* write the remainder of the data block to the new CFDATA1 file */
658 if( split_block
) { /* This does not include the */
659 /* abused one (just search for "abused" )*/
660 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
661 if (p_fci_internal
->fNextCab
==FALSE
) {
662 /* TODO internal error */
666 /* set cbData to the size of the remainder of the data block */
667 pcfdata
->cbData
= read_result
- pcfdata
->cbData
;
668 /*recover former value of cfdata.cbData; read_result will be the offset*/
669 read_result
-= pcfdata
->cbData
;
670 pcfdata
->cbUncomp
= savedUncomp
;
672 /* reset checksum, it will be computed later */
675 /* write cfdata WITHOUT checksum to handleCFDATA1new */
676 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
677 buffer
, /* memory buffer */
678 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
679 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
680 /* TODO write error */
683 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
685 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
687 /* write compressed data into handleCFDATA1new */
688 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
689 p_fci_internal
->data_out
+ read_result
, /* memory buffer + offset */
690 /* to last part of split data */
691 pcfdata
->cbData
, /* number of bytes to copy */
692 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
693 /* TODO write error */
696 /* TODO error handling of err */
698 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
700 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
701 /* the two blocks of the split data block have been written */
702 /* don't reset split_data yet, because it is still needed see below */
705 /* report status with pfnfcis about copied size of folder */
706 if( (*pfnfcis
)(statusFolder
,
707 p_fci_internal
->statusFolderCopied
, /*cfdata.cbData(+previous ones)*/
708 p_fci_internal
->statusFolderTotal
, /* total folder size */
709 p_fci_internal
->pv
) == -1) {
710 /* TODO set error code and abort */
715 /* if cabinet size too large */
716 /* write the remaining data blocks to the new CFDATA1 file */
717 if ( split_block
) { /* This does include the */
718 /* abused one (just search for "abused" )*/
719 if (p_fci_internal
->fNextCab
==FALSE
) {
720 /* TODO internal error */
723 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
725 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
726 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
,/* handle */
727 buffer
, /* memory buffer */
728 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
729 err
, p_fci_internal
->pv
);
730 if (read_result
!=sizeof(CFDATA
)+cbReserveCFData
) {
731 if (read_result
==0) break; /* ALL DATA has been copied */
732 /* TODO read error */
735 /* TODO error handling of err */
737 /* REUSE buffer p_fci_internal->data_out !!! */
738 /* read data from p_fci_internal->handleCFDATA1 to */
739 /* p_fci_internal->data_out */
740 if( PFCI_READ(hfci
, p_fci_internal
->handleCFDATA1
/* file handle */,
741 p_fci_internal
->data_out
/* memory buffer */,
742 pcfdata
->cbData
/* number of bytes to copy */,
743 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
744 /* TODO read error */
747 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
749 /* write cfdata with checksum to handleCFDATA1new */
750 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
751 buffer
, /* memory buffer */
752 sizeof(CFDATA
)+cbReserveCFData
, /* number of bytes to copy */
753 err
, p_fci_internal
->pv
) != sizeof(CFDATA
)+cbReserveCFData
) {
754 /* TODO write error */
757 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
759 *psizeFileCFDATA1new
+= sizeof(CFDATA
)+cbReserveCFData
;
761 /* write compressed data into handleCFDATA1new */
762 if( PFCI_WRITE(hfci
, handleCFDATA1new
, /* file handle */
763 p_fci_internal
->data_out
, /* memory buffer */
764 pcfdata
->cbData
, /* number of bytes to copy */
765 err
, p_fci_internal
->pv
) != pcfdata
->cbData
) {
766 /* TODO write error */
769 /* TODO error handling of err */
771 *psizeFileCFDATA1new
+= pcfdata
->cbData
;
772 p_fci_internal
->statusFolderCopied
+= pcfdata
->cbData
;
774 /* report status with pfnfcis about copied size of folder */
775 if( (*pfnfcis
)(statusFolder
,
776 p_fci_internal
->statusFolderCopied
,/*cfdata.cbData(+revious ones)*/
777 p_fci_internal
->statusFolderTotal
, /* total folder size */
778 p_fci_internal
->pv
) == -1) {
779 /* TODO set error code and abort */
784 break; /* jump out of the next while loop */
785 } /* end of if( split_data ) */
788 } /* end of fci_flushfolder_copy_cfdata */
794 static BOOL
fci_flushfolder_copy_cffolder(HFCI hfci
, int* err
, UINT cbReserveCFFolder
,
795 cab_ULONG sizeFileCFDATA2old
)
800 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
802 /* absolute offset cannot be set yet, because the size of cabinet header, */
803 /* the number of CFFOLDERs and the number of CFFILEs may change. */
804 /* Instead the size of all previous data blocks will be stored and */
805 /* the remainder of the offset will be added when the cabinet will be */
806 /* flushed to disk. */
807 /* This is exactly the way the original CABINET.DLL works!!! */
808 cffolder
.coffCabStart
=sizeFileCFDATA2old
;
810 /* set the number of this folder's CFDATA sections */
811 cffolder
.cCFData
=p_fci_internal
->cDataBlocks
;
812 /* TODO set compression type */
813 cffolder
.typeCompress
= tcompTYPE_NONE
;
815 /* write cffolder to p_fci_internal->handleCFFOLDER */
816 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
817 &cffolder
, /* memory buffer */
818 sizeof(cffolder
), /* number of bytes to copy */
819 err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
820 /* TODO write error */
823 /* TODO error handling of err */
825 p_fci_internal
->sizeFileCFFOLDER
+= sizeof(cffolder
);
827 /* add optional reserved area */
828 if (cbReserveCFFolder
!=0) {
829 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
830 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
831 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
832 p_fci_internal
->perf
->fError
= TRUE
;
833 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
836 for(i
=0;i
<cbReserveCFFolder
;) {
839 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
840 reserved
, /* memory buffer */
841 cbReserveCFFolder
, /* number of bytes to copy */
842 err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
843 PFCI_FREE(hfci
, reserved
);
844 /* TODO write error */
847 /* TODO error handling of err */
849 p_fci_internal
->sizeFileCFFOLDER
+= cbReserveCFFolder
;
851 PFCI_FREE(hfci
, reserved
);
854 } /* end of fci_flushfolder_copy_cffolder */
860 static BOOL
fci_flushfolder_copy_cffile(HFCI hfci
, int* err
, int handleCFFILE1new
,
861 cab_ULONG
*psizeFileCFFILE1new
, cab_ULONG payload
)
864 cab_ULONG read_result
;
866 cab_ULONG sizeOfFiles
=0, sizeOfFilesPrev
;
867 BOOL may_be_prev
=TRUE
;
868 cab_ULONG cbFileRemainer
=0;
869 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
870 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
871 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,0,SEEK_SET
,err
,
872 p_fci_internal
->pv
) !=0 ) {
873 /* TODO wrong return value */
875 /* TODO error handling of err */
877 /* while not all CFFILE structures have been copied do */
879 /* REUSE the variable read_result */
880 /* read data from p_fci_internal->handleCFFILE1 to cffile */
881 read_result
= PFCI_READ(hfci
,p_fci_internal
->handleCFFILE1
/* file handle */,
882 &cffile
, /* memory buffer */
883 sizeof(cffile
), /* number of bytes to copy */
884 err
, p_fci_internal
->pv
);
885 if( read_result
!= sizeof(cffile
) ) {
886 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
887 /* TODO read error */
890 /* TODO error handling of err */
892 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
893 /* position. I don't know why so I'll just omit it */
895 /* read the filename from p_fci_internal->handleCFFILE1 */
896 /* REUSE the variable read_result AGAIN */
897 /* REUSE the memory buffer PFCI(hfci)->data_out */
898 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFILE1
/*file handle*/,
899 p_fci_internal
->data_out
, /* memory buffer */
900 CB_MAX_FILENAME
, /* number of bytes to copy */
901 err
, p_fci_internal
->pv
) <2) {
902 /* TODO read error */
905 /* TODO maybe other checks of read_result */
906 /* TODO error handling of err */
909 if( strlen(p_fci_internal
->data_out
)>=CB_MAX_FILENAME
) {
910 /* TODO set error code internal error */
914 seek
+=sizeof(cffile
) + strlen(p_fci_internal
->data_out
)+1;
916 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
917 /* i.e. seek to the next CFFILE area */
918 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE1
,
919 seek
, /* seek position*/
922 != sizeof(cffile
)+strlen(p_fci_internal
->data_out
)+1 ) {
923 /* TODO wrong return value */
925 /* TODO error handling of err */
927 /* fnfilfnfildest: placed file on cabinet */
928 if (p_fci_internal
->fNextCab
||
929 p_fci_internal
->fGetNextCabInVain
) {
930 PFCI_FILEPLACED( hfci
, &(p_fci_internal
->oldCCAB
),
931 p_fci_internal
->data_out
, /* the file name*/
932 cffile
.cbFile
, /* file size */
933 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
937 PFCI_FILEPLACED( hfci
, p_fci_internal
->pccab
,
938 p_fci_internal
->data_out
, /* the file name*/
939 cffile
.cbFile
, /* file size */
940 (cffile
.iFolder
==cffileCONTINUED_FROM_PREV
),
945 /* Check special iFolder values */
946 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
947 p_fci_internal
->fPrevCab
==FALSE
) {
948 /* THIS MAY NEVER HAPPEN */
949 /* TODO set error code */
952 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
953 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
) {
954 /* THIS MAY NEVER HAPPEN */
955 /* TODO set error code */
958 if( may_be_prev
&& cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
961 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& may_be_prev
==FALSE
) {
962 /* THIS MAY NEVER HAPPEN */
963 /* TODO set error code */
966 if( cffile
.iFolder
!=cffileCONTINUED_FROM_PREV
) {
970 sizeOfFilesPrev
=sizeOfFiles
;
971 /* Set complete size of all processed files */
972 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&&
973 p_fci_internal
->cbFileRemainer
!=0
975 sizeOfFiles
+=p_fci_internal
->cbFileRemainer
;
976 p_fci_internal
->cbFileRemainer
=0;
978 sizeOfFiles
+=cffile
.cbFile
;
981 /* Check if spanned file fits into this cabinet folder */
982 if( cffile
.iFolder
==cffileCONTINUED_FROM_PREV
&& sizeOfFiles
>payload
) {
983 cffile
.iFolder
=cffileCONTINUED_PREV_AND_NEXT
;
986 /* Check if file doesn't fit into this cabinet folder */
987 if( sizeOfFiles
>payload
) {
988 cffile
.iFolder
=cffileCONTINUED_TO_NEXT
;
991 /* set little endian */
992 cffile
.cbFile
=fci_endian_ulong(cffile
.cbFile
);
993 cffile
.uoffFolderStart
=fci_endian_ulong(cffile
.uoffFolderStart
);
994 cffile
.iFolder
=fci_endian_uword(cffile
.iFolder
);
995 cffile
.date
=fci_endian_uword(cffile
.date
);
996 cffile
.time
=fci_endian_uword(cffile
.time
);
997 cffile
.attribs
=fci_endian_uword(cffile
.attribs
);
999 /* write cffile to p_fci_internal->handleCFFILE2 */
1000 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
1001 &cffile
, /* memory buffer */
1002 sizeof(cffile
), /* number of bytes to copy */
1003 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1004 /* TODO write error */
1007 /* TODO error handling of err */
1009 p_fci_internal
->sizeFileCFFILE2
+= sizeof(cffile
);
1011 /* reset little endian */
1012 cffile
.cbFile
=fci_endian_ulong(cffile
.cbFile
);
1013 cffile
.uoffFolderStart
=fci_endian_ulong(cffile
.uoffFolderStart
);
1014 cffile
.iFolder
=fci_endian_uword(cffile
.iFolder
);
1015 cffile
.date
=fci_endian_uword(cffile
.date
);
1016 cffile
.time
=fci_endian_uword(cffile
.time
);
1017 cffile
.attribs
=fci_endian_uword(cffile
.attribs
);
1019 /* write file name to p_fci_internal->handleCFFILE2 */
1020 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE2
, /* file handle */
1021 p_fci_internal
->data_out
, /* memory buffer */
1022 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1023 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1024 /* TODO write error */
1027 /* TODO error handling of err */
1029 p_fci_internal
->sizeFileCFFILE2
+= strlen(p_fci_internal
->data_out
)+1;
1031 /* cFiles is used to count all files of a cabinet */
1032 ++(p_fci_internal
->cFiles
);
1034 /* This is only true for files which will be written into the */
1035 /* next cabinet of the spanning folder */
1036 if( sizeOfFiles
>payload
) {
1038 /* Files which data will be partially written into the current cabinet */
1039 if( cffile
.iFolder
==cffileCONTINUED_PREV_AND_NEXT
||
1040 cffile
.iFolder
==cffileCONTINUED_TO_NEXT
1042 if( sizeOfFilesPrev
<=payload
) {
1043 /* The size of the uncompressed, data of a spanning file in a */
1045 cbFileRemainer
=sizeOfFiles
-payload
;
1047 cffile
.iFolder
=cffileCONTINUED_FROM_PREV
;
1052 /* write cffile into handleCFFILE1new */
1053 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1054 &cffile
, /* memory buffer */
1055 sizeof(cffile
), /* number of bytes to copy */
1056 err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
1057 /* TODO write error */
1060 /* TODO error handling of err */
1062 *psizeFileCFFILE1new
+= sizeof(cffile
);
1063 /* write name of file into handleCFFILE1new */
1064 if( PFCI_WRITE(hfci
, handleCFFILE1new
, /* file handle */
1065 p_fci_internal
->data_out
, /* memory buffer */
1066 strlen(p_fci_internal
->data_out
)+1, /* number of bytes to copy */
1067 err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->data_out
)+1 ) {
1068 /* TODO write error */
1071 /* TODO error handling of err */
1073 *psizeFileCFFILE1new
+= strlen(p_fci_internal
->data_out
)+1;
1076 } /* END OF while */
1077 p_fci_internal
->cbFileRemainer
=cbFileRemainer
;
1079 } /* end of fci_flushfolder_copy_cffile */
1084 static BOOL
fci_flush_folder(
1087 PFNFCIGETNEXTCABINET pfnfcignc
,
1088 PFNFCISTATUS pfnfcis
)
1091 int handleCFDATA1new
; /* handle for new temp file */
1092 char szFileNameCFDATA1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1093 int handleCFFILE1new
; /* handle for new temp file */
1094 char szFileNameCFFILE1new
[CB_MAX_FILENAME
]; /* name buffer for temp file */
1095 UINT cbReserveCFData
, cbReserveCFFolder
;
1097 cab_ULONG sizeFileCFDATA1new
=0;
1098 cab_ULONG sizeFileCFFILE1new
=0;
1099 cab_ULONG sizeFileCFDATA2old
;
1101 cab_ULONG read_result
;
1102 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1105 if (!REALLY_IS_FCI(hfci
)) {
1106 SetLastError(ERROR_INVALID_HANDLE
);
1110 if ((!pfnfcignc
) || (!pfnfcis
)) {
1111 p_fci_internal
->perf
->erfOper
= FCIERR_NONE
;
1112 p_fci_internal
->perf
->erfType
= ERROR_BAD_ARGUMENTS
;
1113 p_fci_internal
->perf
->fError
= TRUE
;
1115 SetLastError(ERROR_BAD_ARGUMENTS
);
1119 if( p_fci_internal
->fGetNextCabInVain
&&
1120 p_fci_internal
->fNextCab
){
1121 /* TODO internal error */
1125 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1126 /* this function will return TRUE */
1127 if( p_fci_internal
->sizeFileCFFILE1
== 0 ) {
1128 if ( p_fci_internal
->sizeFileCFDATA1
!= 0 ) {
1129 /* TODO error handling */
1135 if (p_fci_internal
->data_in
==NULL
|| p_fci_internal
->data_out
==NULL
) {
1136 /* TODO error handling */
1140 /* FCIFlushFolder has already been called... */
1141 if (p_fci_internal
->fSplitFolder
&& p_fci_internal
->sizeFileCFFILE2
!=0) {
1142 if (p_fci_internal
->sizeFileCFFILE2
==0) {
1143 /* TODO set error code */
1149 /* TODO check what will happen when return FALSE later */
1150 /* and p_fci_internal->fSplitFolder is set to FALSE */
1151 p_fci_internal
->fSplitFolder
=FALSE
;
1154 if( p_fci_internal
->fGetNextCabInVain
||
1155 p_fci_internal
->fNextCab
){
1156 cbReserveCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1157 cbReserveCFFolder
= p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1159 cbReserveCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1160 cbReserveCFFolder
= p_fci_internal
->pccab
->cbReserveCFFolder
;
1164 /* if there is data in p_fci_internal->data_in */
1165 if (p_fci_internal
->cdata_in
!=0) {
1167 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
1170 /* reset to get the number of data blocks of this folder which are */
1171 /* actually in this cabinet ( at least partially ) */
1172 p_fci_internal
->cDataBlocks
=0;
1174 if ( p_fci_internal
->fNextCab
||
1175 p_fci_internal
->fGetNextCabInVain
) {
1176 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
1177 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1178 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1179 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1180 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1184 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
+
1185 p_fci_internal
->pccab
->cbReserveCFFolder
;
1186 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1187 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1188 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1192 if (p_fci_internal
->fPrevCab
) {
1193 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1194 strlen(p_fci_internal
->szPrevDisk
)+1;
1196 if (p_fci_internal
->fNextCab
) {
1197 read_result
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1198 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1201 p_fci_internal
->statusFolderTotal
= sizeof(CFHEADER
)+read_result
+
1202 sizeof(CFFOLDER
) + p_fci_internal
->sizeFileCFFILE2
+
1203 p_fci_internal
->sizeFileCFDATA2
+ p_fci_internal
->sizeFileCFFILE1
+
1204 p_fci_internal
->sizeFileCFDATA1
;
1205 p_fci_internal
->statusFolderCopied
= 0;
1207 /* report status with pfnfcis about copied size of folder */
1208 if( (*pfnfcis
)(statusFolder
, p_fci_internal
->statusFolderCopied
,
1209 p_fci_internal
->statusFolderTotal
, /* TODO total folder size */
1210 p_fci_internal
->pv
) == -1) {
1211 /* TODO set error code and abort */
1215 /* get a new temp file */
1216 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFDATA1new
,CB_MAX_FILENAME
)) {
1217 /* TODO error handling */
1221 if ( strlen(szFileNameCFDATA1new
) >= CB_MAX_FILENAME
) {
1222 /* TODO set error code */
1225 handleCFDATA1new
= PFCI_OPEN(hfci
,szFileNameCFDATA1new
,34050,384,&err
,
1226 p_fci_internal
->pv
);
1228 /* get a new temp file */
1229 if(!PFCI_GETTEMPFILE(hfci
,szFileNameCFFILE1new
,CB_MAX_FILENAME
)) {
1230 /* TODO error handling */
1231 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1232 /* TODO error handling of err */
1236 if ( strlen(szFileNameCFFILE1new
) >= CB_MAX_FILENAME
) {
1237 /* TODO set error code */
1238 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1239 /* TODO error handling of err */
1242 handleCFFILE1new
= PFCI_OPEN(hfci
,szFileNameCFFILE1new
,34050,384,&err
,
1243 p_fci_internal
->pv
);
1245 /* USE the variable read_result */
1246 if ( p_fci_internal
->fNextCab
||
1247 p_fci_internal
->fGetNextCabInVain
) {
1248 read_result
= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1249 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1250 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1251 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1255 read_result
= p_fci_internal
->pccab
->cbReserveCFHeader
;
1256 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1257 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1258 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1262 if (p_fci_internal
->fPrevCab
) {
1263 read_result
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1264 strlen(p_fci_internal
->szPrevDisk
)+1;
1266 read_result
+= sizeof(CFHEADER
) + p_fci_internal
->sizeFileCFDATA2
+
1267 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
;
1269 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
1270 read_result
+= sizeof(CFFOLDER
)+p_fci_internal
->pccab
->cbReserveCFFolder
;
1273 /* Check if multiple cabinets have to be created. */
1275 /* Might be too much data for the maximum allowed cabinet size.*/
1276 /* When any further data will be added later, it might not */
1277 /* be possible to flush the cabinet, because there might */
1278 /* not be enough space to store the name of the following */
1279 /* cabinet and name of the corresponding disk. */
1280 /* So take care of this and get the name of the next cabinet */
1281 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
1282 p_fci_internal
->fNextCab
==FALSE
&&
1285 p_fci_internal
->pccab
->cb
< read_result
+
1286 p_fci_internal
->sizeFileCFDATA1
+
1287 p_fci_internal
->sizeFileCFFILE1
+
1288 CB_MAX_CABINET_NAME
+ /* next cabinet name */
1289 CB_MAX_DISK_NAME
/* next disk name */
1294 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
1295 /* increment cabinet index */
1296 ++(p_fci_internal
->pccab
->iCab
);
1297 /* get name of next cabinet */
1298 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0, /* estimated size of cab */
1299 p_fci_internal
->pv
)) {
1300 /* TODO error handling */
1301 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1302 /* TODO error handling of err */
1303 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1304 /* TODO error handling of err */
1308 /* Skip a few lines of code. This is catched by the next if. */
1309 p_fci_internal
->fGetNextCabInVain
=TRUE
;
1312 /* too much data for cabinet */
1313 if( (p_fci_internal
->fGetNextCabInVain
||
1314 p_fci_internal
->fNextCab
) &&
1317 p_fci_internal
->oldCCAB
.cb
< read_result
+
1318 p_fci_internal
->sizeFileCFDATA1
+
1319 p_fci_internal
->sizeFileCFFILE1
+
1320 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1321 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1325 p_fci_internal
->fGetNextCabInVain
=FALSE
;
1326 p_fci_internal
->fNextCab
=TRUE
;
1328 /* return FALSE if there is not enough space left*/
1329 /* this should never happen */
1330 if (p_fci_internal
->oldCCAB
.cb
<=
1331 p_fci_internal
->sizeFileCFFILE1
+
1333 strlen(p_fci_internal
->pccab
->szCab
)+1 + /* next cabinet name */
1334 strlen(p_fci_internal
->pccab
->szDisk
)+1 /* next disk name */
1337 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1338 /* TODO error handling of err */
1339 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1340 /* TODO error handling of err */
1342 /* close and delete p_fci_internal->handleCFFILE1 */
1343 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1344 /* TODO error handling of err */
1345 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1346 /* TODO error handling of err */
1351 /* the folder will be split across cabinets */
1352 p_fci_internal
->fSplitFolder
=TRUE
;
1355 /* this should never happen */
1356 if (p_fci_internal
->fNextCab
) {
1357 /* TODO internal error */
1362 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1363 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA1
,0,SEEK_SET
,&err
,
1364 p_fci_internal
->pv
) !=0 ) {
1365 /* TODO wrong return value */
1366 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1367 /* TODO error handling of err */
1368 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1369 /* TODO error handling of err */
1372 /* TODO error handling of err */
1374 /* save size of file CFDATA2 - required for the folder's offset to data */
1375 sizeFileCFDATA2old
= p_fci_internal
->sizeFileCFDATA2
;
1377 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFData
+sizeof(CFDATA
)))) {
1378 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
1379 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1380 p_fci_internal
->perf
->fError
= TRUE
;
1381 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1382 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1383 /* TODO error handling of err */
1384 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1385 /* TODO error handling of err */
1389 if(!fci_flushfolder_copy_cfdata(hfci
, reserved
, cbReserveCFData
, pfnfcis
, &err
,
1390 handleCFDATA1new
, &sizeFileCFDATA1new
, &payload
1392 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1393 /* TODO error handling of err */
1394 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1395 /* TODO error handling of err */
1396 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1397 /* TODO error handling of err */
1398 PFCI_FREE(hfci
,reserved
);
1402 PFCI_FREE(hfci
,reserved
);
1404 if(!fci_flushfolder_copy_cffolder(hfci
, &err
, cbReserveCFFolder
,
1405 sizeFileCFDATA2old
)) {
1406 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1407 /* TODO error handling of err */
1408 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1409 /* TODO error handling of err */
1410 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1411 /* TODO error handling of err */
1415 if(!fci_flushfolder_copy_cffile(hfci
, &err
, handleCFFILE1new
,
1416 &sizeFileCFFILE1new
, payload
)) {
1417 PFCI_CLOSE(hfci
,handleCFDATA1new
,&err
,p_fci_internal
->pv
);
1418 /* TODO error handling of err */
1419 PFCI_DELETE(hfci
,szFileNameCFDATA1new
,&err
,p_fci_internal
->pv
);
1420 /* TODO error handling of err */
1421 PFCI_CLOSE(hfci
,handleCFFILE1new
,&err
,p_fci_internal
->pv
);
1422 /* TODO error handling of err */
1423 PFCI_DELETE(hfci
,szFileNameCFFILE1new
,&err
,p_fci_internal
->pv
);
1424 /* TODO error handling of err */
1428 /* close and delete p_fci_internal->handleCFDATA1 */
1429 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
1430 /* TODO error handling of err */
1431 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFDATA1
,&err
,p_fci_internal
->pv
);
1432 /* TODO error handling of err */
1434 /* put new CFDATA1 into hfci */
1435 memcpy(p_fci_internal
->szFileNameCFDATA1
,szFileNameCFDATA1new
,
1438 /* put CFDATA1 file handle */
1439 PFCI_INT(hfci
)->handleCFDATA1
= handleCFDATA1new
;
1441 PFCI_INT(hfci
)->sizeFileCFDATA1
= sizeFileCFDATA1new
;
1443 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1444 PFCI_CLOSE(hfci
,p_fci_internal
->handleCFFILE1
,&err
,PFCI_INT(hfci
)->pv
);
1445 /* TODO error handling of err */
1446 PFCI_DELETE(hfci
,p_fci_internal
->szFileNameCFFILE1
,&err
,p_fci_internal
->pv
);
1447 /* TODO error handling of err */
1449 /* put new CFFILE1 into hfci */
1450 memcpy(p_fci_internal
->szFileNameCFFILE1
,szFileNameCFFILE1new
,
1453 /* put CFFILE1 file handle */
1454 p_fci_internal
->handleCFFILE1
= handleCFFILE1new
;
1456 p_fci_internal
->sizeFileCFFILE1
= sizeFileCFFILE1new
;
1458 ++(p_fci_internal
->cFolders
);
1460 /* reset CFFolder specific information */
1461 p_fci_internal
->cDataBlocks
=0;
1462 p_fci_internal
->cCompressedBytesInFolder
=0;
1465 } /* end of fci_flush_folder */
1470 static BOOL
fci_flush_cabinet(
1473 PFNFCIGETNEXTCABINET pfnfcignc
,
1474 PFNFCISTATUS pfnfcis
)
1479 cab_UWORD cbCFHeader
;
1480 cab_UBYTE cbCFFolder
;
1484 cab_ULONG read_result
;
1485 int handleCABINET
; /* file handle for cabinet */
1486 char pszFileNameCABINET
[CB_MAX_CAB_PATH
+CB_MAX_CABINET_NAME
];/* name buffer */
1487 UINT cbReserveCFHeader
, cbReserveCFFolder
, i
;
1489 BOOL returntrue
=FALSE
;
1490 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
1492 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1494 /* when FCIFlushCabinet was or FCIAddFile wasn't called */
1495 if( p_fci_internal
->sizeFileCFFILE1
==0 && fGetNextCab
) {
1499 if (!fci_flush_folder(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)){
1500 /* TODO set error */
1504 if(returntrue
) return TRUE
;
1506 if (p_fci_internal
->fSplitFolder
&& p_fci_internal
->fNextCab
==FALSE
) {
1507 /* TODO internal error */
1511 if( p_fci_internal
->fNextCab
||
1512 p_fci_internal
->fGetNextCabInVain
) {
1513 cbReserveCFFolder
=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
1514 cbReserveCFHeader
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1516 if (strlen(p_fci_internal
->oldCCAB
.szCabPath
)>=CB_MAX_CAB_PATH
||
1517 strlen(p_fci_internal
->oldCCAB
.szCab
)>=CB_MAX_CABINET_NAME
) {
1518 /* TODO set error */
1521 /* get the full name of the cabinet */
1522 memcpy(pszFileNameCABINET
,p_fci_internal
->oldCCAB
.szCabPath
,
1524 memcpy(pszFileNameCABINET
+strlen(pszFileNameCABINET
),
1525 p_fci_internal
->oldCCAB
.szCab
, CB_MAX_CABINET_NAME
);
1527 cbReserveCFFolder
=p_fci_internal
->pccab
->cbReserveCFFolder
;
1528 cbReserveCFHeader
=p_fci_internal
->pccab
->cbReserveCFHeader
;
1530 if (strlen(p_fci_internal
->pccab
->szCabPath
)>=CB_MAX_CAB_PATH
||
1531 strlen(p_fci_internal
->pccab
->szCab
)>=CB_MAX_CABINET_NAME
) {
1532 /* TODO set error */
1535 /* get the full name of the cabinet */
1536 memcpy(pszFileNameCABINET
,p_fci_internal
->pccab
->szCabPath
,
1538 memcpy(pszFileNameCABINET
+strlen(pszFileNameCABINET
),
1539 p_fci_internal
->pccab
->szCab
, CB_MAX_CABINET_NAME
);
1542 /* create the cabinet */
1543 handleCABINET
= PFCI_OPEN(hfci
, pszFileNameCABINET
,
1544 33538, 384, &err
, p_fci_internal
->pv
);
1545 /* TODO check handle */
1546 /* TODO error checking of err */
1548 memcpy(cfheader
.signature
,"!CAB",4);
1549 cfheader
.reserved1
=0;
1550 cfheader
.cbCabinet
= /* size of the cabinet file in bytes */
1552 p_fci_internal
->sizeFileCFFOLDER
+
1553 p_fci_internal
->sizeFileCFFILE2
+
1554 p_fci_internal
->sizeFileCFDATA2
;
1556 if (p_fci_internal
->fPrevCab
) {
1557 cfheader
.cbCabinet
+=strlen(p_fci_internal
->szPrevCab
)+1 +
1558 strlen(p_fci_internal
->szPrevDisk
)+1;
1560 if (p_fci_internal
->fNextCab
) {
1561 cfheader
.cbCabinet
+=strlen(p_fci_internal
->pccab
->szCab
)+1 +
1562 strlen(p_fci_internal
->pccab
->szDisk
)+1;
1564 if( p_fci_internal
->fNextCab
||
1565 p_fci_internal
->fGetNextCabInVain
) {
1566 cfheader
.cbCabinet
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1567 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1568 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1569 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1570 cfheader
.cbCabinet
+=4;
1573 cfheader
.cbCabinet
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1574 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1575 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1576 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1577 cfheader
.cbCabinet
+=4;
1581 cfheader
.reserved2
=0;
1582 cfheader
.coffFiles
= /* offset to first CFFILE section */
1583 cfheader
.cbCabinet
- p_fci_internal
->sizeFileCFFILE2
-
1584 p_fci_internal
->sizeFileCFDATA2
;
1586 cfheader
.reserved3
=0;
1587 cfheader
.versionMinor
=3;
1588 cfheader
.versionMajor
=1;
1589 /* number of CFFOLDER entries in the cabinet */
1590 cfheader
.cFolders
=p_fci_internal
->cFolders
;
1591 /* number of CFFILE entries in the cabinet */
1592 cfheader
.cFiles
=p_fci_internal
->cFiles
;
1593 cfheader
.flags
=0; /* 1=prev cab, 2=next cabinet, 4=reserved setions */
1595 if( p_fci_internal
->fPrevCab
) {
1596 cfheader
.flags
= cfheadPREV_CABINET
;
1599 if( p_fci_internal
->fNextCab
) {
1600 cfheader
.flags
|= cfheadNEXT_CABINET
;
1603 if( p_fci_internal
->fNextCab
||
1604 p_fci_internal
->fGetNextCabInVain
) {
1605 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1606 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1607 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1608 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1610 cfheader
.setID
= p_fci_internal
->oldCCAB
.setID
;
1611 cfheader
.iCabinet
= p_fci_internal
->oldCCAB
.iCab
-1;
1613 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1614 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1615 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1616 cfheader
.flags
|= cfheadRESERVE_PRESENT
;
1618 cfheader
.setID
= p_fci_internal
->pccab
->setID
;
1619 cfheader
.iCabinet
= p_fci_internal
->pccab
->iCab
-1;
1622 /* set little endian */
1623 cfheader
.reserved1
=fci_endian_ulong(cfheader
.reserved1
);
1624 cfheader
.cbCabinet
=fci_endian_ulong(cfheader
.cbCabinet
);
1625 cfheader
.reserved2
=fci_endian_ulong(cfheader
.reserved2
);
1626 cfheader
.coffFiles
=fci_endian_ulong(cfheader
.coffFiles
);
1627 cfheader
.reserved3
=fci_endian_ulong(cfheader
.reserved3
);
1628 cfheader
.cFolders
=fci_endian_uword(cfheader
.cFolders
);
1629 cfheader
.cFiles
=fci_endian_uword(cfheader
.cFiles
);
1630 cfheader
.flags
=fci_endian_uword(cfheader
.flags
);
1631 cfheader
.setID
=fci_endian_uword(cfheader
.setID
);
1632 cfheader
.iCabinet
=fci_endian_uword(cfheader
.iCabinet
);
1634 /* write CFHEADER into cabinet file */
1635 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1636 &cfheader
, /* memory buffer */
1637 sizeof(cfheader
), /* number of bytes to copy */
1638 &err
, p_fci_internal
->pv
) != sizeof(cfheader
) ) {
1639 /* TODO write error */
1642 /* TODO error handling of err */
1644 /* reset little endian */
1645 cfheader
.reserved1
=fci_endian_ulong(cfheader
.reserved1
);
1646 cfheader
.cbCabinet
=fci_endian_ulong(cfheader
.cbCabinet
);
1647 cfheader
.reserved2
=fci_endian_ulong(cfheader
.reserved2
);
1648 cfheader
.coffFiles
=fci_endian_ulong(cfheader
.coffFiles
);
1649 cfheader
.reserved3
=fci_endian_ulong(cfheader
.reserved3
);
1650 cfheader
.cFolders
=fci_endian_uword(cfheader
.cFolders
);
1651 cfheader
.cFiles
=fci_endian_uword(cfheader
.cFiles
);
1652 cfheader
.flags
=fci_endian_uword(cfheader
.flags
);
1653 cfheader
.setID
=fci_endian_uword(cfheader
.setID
);
1654 cfheader
.iCabinet
=fci_endian_uword(cfheader
.iCabinet
);
1656 if( cfheader
.flags
& cfheadRESERVE_PRESENT
) {
1657 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1658 cfreserved
.cbCFHeader
= cbReserveCFHeader
;
1659 cfreserved
.cbCFFolder
= cbReserveCFFolder
;
1660 if( p_fci_internal
->fNextCab
||
1661 p_fci_internal
->fGetNextCabInVain
) {
1662 cfreserved
.cbCFData
= p_fci_internal
->oldCCAB
.cbReserveCFData
;
1664 cfreserved
.cbCFData
= p_fci_internal
->pccab
->cbReserveCFData
;
1667 /* set little endian */
1668 cfreserved
.cbCFHeader
=fci_endian_uword(cfreserved
.cbCFHeader
);
1670 /* write reserved info into cabinet file */
1671 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1672 &cfreserved
, /* memory buffer */
1673 sizeof(cfreserved
), /* number of bytes to copy */
1674 &err
, p_fci_internal
->pv
) != sizeof(cfreserved
) ) {
1675 /* TODO write error */
1678 /* TODO error handling of err */
1680 /* reset little endian */
1681 cfreserved
.cbCFHeader
=fci_endian_uword(cfreserved
.cbCFHeader
);
1684 /* add optional reserved area */
1685 if (cbReserveCFHeader
!=0) {
1686 if(!(reserved
= (char*)PFCI_ALLOC(hfci
, cbReserveCFHeader
))) {
1687 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
1688 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1689 p_fci_internal
->perf
->fError
= TRUE
;
1690 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1693 for(i
=0;i
<cbReserveCFHeader
;) {
1696 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1697 reserved
, /* memory buffer */
1698 cbReserveCFHeader
, /* number of bytes to copy */
1699 &err
, p_fci_internal
->pv
) != cbReserveCFHeader
) {
1700 PFCI_FREE(hfci
, reserved
);
1701 /* TODO write error */
1704 /* TODO error handling of err */
1705 PFCI_FREE(hfci
, reserved
);
1708 if( cfheader
.flags
& cfheadPREV_CABINET
) {
1709 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1710 p_fci_internal
->szPrevCab
, /* memory buffer */
1711 strlen(p_fci_internal
->szPrevCab
)+1, /* number of bytes to copy */
1712 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevCab
)+1 ) {
1713 /* TODO write error */
1716 /* TODO error handling of err */
1718 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1719 p_fci_internal
->szPrevDisk
, /* memory buffer */
1720 strlen(p_fci_internal
->szPrevDisk
)+1, /* number of bytes to copy */
1721 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->szPrevDisk
)+1 ) {
1722 /* TODO write error */
1725 /* TODO error handling of err */
1728 if( cfheader
.flags
& cfheadNEXT_CABINET
) {
1729 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1730 p_fci_internal
->pccab
->szCab
, /* memory buffer */
1731 strlen(p_fci_internal
->pccab
->szCab
)+1, /* number of bytes to copy */
1732 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szCab
)+1 ) {
1733 /* TODO write error */
1736 /* TODO error handling of err */
1738 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1739 p_fci_internal
->pccab
->szDisk
, /* memory buffer */
1740 strlen(p_fci_internal
->pccab
->szDisk
)+1, /* number of bytes to copy */
1741 &err
, p_fci_internal
->pv
) != strlen(p_fci_internal
->pccab
->szDisk
)+1 ) {
1742 /* TODO write error */
1745 /* TODO error handling of err */
1748 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1749 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFOLDER
,
1750 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1751 /* TODO wrong return value */
1753 /* TODO error handling of err */
1755 /* while not all CFFOLDER structures have been copied into the cabinet do */
1757 /* use the variable read_result */
1758 /* read cffolder of p_fci_internal->handleCFFOLDER */
1759 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* handle */
1760 &cffolder
, /* memory buffer */
1761 sizeof(cffolder
), /* number of bytes to copy */
1762 &err
, p_fci_internal
->pv
);
1763 if( read_result
!= sizeof(cffolder
) ) {
1764 if( read_result
== 0 ) break; /*ALL CFFOLDER structures have been copied*/
1765 /* TODO read error */
1768 /* TODO error handling of err */
1770 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1771 cffolder
.coffCabStart
+=
1772 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
1774 if( p_fci_internal
->fNextCab
||
1775 p_fci_internal
->fGetNextCabInVain
) {
1776 cffolder
.coffCabStart
+=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1778 cffolder
.coffCabStart
+=p_fci_internal
->pccab
->cbReserveCFHeader
;
1781 if (p_fci_internal
->fPrevCab
) {
1782 cffolder
.coffCabStart
+= strlen(p_fci_internal
->szPrevCab
)+1 +
1783 strlen(p_fci_internal
->szPrevDisk
)+1;
1786 if (p_fci_internal
->fNextCab
) {
1787 cffolder
.coffCabStart
+= strlen(p_fci_internal
->oldCCAB
.szCab
)+1 +
1788 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1;
1791 if( p_fci_internal
->fNextCab
||
1792 p_fci_internal
->fGetNextCabInVain
) {
1793 cffolder
.coffCabStart
+= p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
1794 if( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
1795 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
1796 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
1797 cffolder
.coffCabStart
+= 4;
1800 cffolder
.coffCabStart
+= p_fci_internal
->pccab
->cbReserveCFHeader
;
1801 if( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
1802 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
1803 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
1804 cffolder
.coffCabStart
+= 4;
1808 /* set little endian */
1809 cffolder
.coffCabStart
=fci_endian_ulong(cffolder
.coffCabStart
);
1810 cffolder
.cCFData
=fci_endian_uword(cffolder
.cCFData
);
1811 cffolder
.typeCompress
=fci_endian_uword(cffolder
.typeCompress
);
1813 /* write cffolder to cabinet file */
1814 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1815 &cffolder
, /* memory buffer */
1816 sizeof(cffolder
), /* number of bytes to copy */
1817 &err
, p_fci_internal
->pv
) != sizeof(cffolder
) ) {
1818 /* TODO write error */
1821 /* TODO error handling of err */
1823 /* reset little endian */
1824 cffolder
.coffCabStart
=fci_endian_ulong(cffolder
.coffCabStart
);
1825 cffolder
.cCFData
=fci_endian_uword(cffolder
.cCFData
);
1826 cffolder
.typeCompress
=fci_endian_uword(cffolder
.typeCompress
);
1828 /* add optional reserved area */
1830 /* This allocation and freeing at each CFFolder block is a bit */
1831 /* inefficent, but it's harder to forget about freeing the buffer :-). */
1832 /* Reserved areas are used seldom besides that... */
1833 if (cbReserveCFFolder
!=0) {
1834 if(!(reserved
= PFCI_ALLOC(hfci
, cbReserveCFFolder
))) {
1835 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
1836 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1837 p_fci_internal
->perf
->fError
= TRUE
;
1838 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1842 if( PFCI_READ(hfci
, p_fci_internal
->handleCFFOLDER
, /* file handle */
1843 reserved
, /* memory buffer */
1844 cbReserveCFFolder
, /* number of bytes to copy */
1845 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1846 PFCI_FREE(hfci
, reserved
);
1847 /* TODO read error */
1850 /* TODO error handling of err */
1852 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1853 reserved
, /* memory buffer */
1854 cbReserveCFFolder
, /* number of bytes to copy */
1855 &err
, p_fci_internal
->pv
) != cbReserveCFFolder
) {
1856 PFCI_FREE(hfci
, reserved
);
1857 /* TODO read error */
1860 /* TODO error handling of err */
1862 PFCI_FREE(hfci
, reserved
);
1865 } /* END OF while */
1867 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1868 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFFILE2
,
1869 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1870 /* TODO wrong return value */
1872 /* TODO error handling of err */
1874 /* while not all CFFILE structures have been copied to the cabinet do */
1876 /* REUSE the variable read_result */
1877 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1878 /* read a block from p_fci_internal->handleCFFILE2 */
1879 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFFILE2
/* handle */,
1880 p_fci_internal
->data_out
, /* memory buffer */
1881 32768, /* number of bytes to copy */
1882 &err
, p_fci_internal
->pv
);
1883 if( read_result
== 0 ) break; /* ALL CFFILE structures have been copied */
1884 /* TODO error handling of err */
1886 /* write the block to the cabinet file */
1887 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1888 p_fci_internal
->data_out
, /* memory buffer */
1889 read_result
, /* number of bytes to copy */
1890 &err
, p_fci_internal
->pv
) != read_result
) {
1891 /* TODO write error */
1894 /* TODO error handling of err */
1896 if (p_fci_internal
->fSplitFolder
==FALSE
) {
1897 p_fci_internal
->statusFolderCopied
= 0;
1898 p_fci_internal
->statusFolderTotal
= p_fci_internal
->sizeFileCFDATA2
+
1899 p_fci_internal
->sizeFileCFFILE2
;
1901 p_fci_internal
->statusFolderCopied
+= read_result
;
1903 /* TODO is this correct */
1904 /* report status with pfnfcis about copied size of folder */
1905 if( (*pfnfcis
)(statusFolder
,
1906 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
1907 p_fci_internal
->statusFolderTotal
, /* total size of folder */
1908 p_fci_internal
->pv
) == -1) {
1909 /* TODO set error code and abort */
1913 } /* END OF while */
1915 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1916 if( PFCI_SEEK(hfci
,p_fci_internal
->handleCFDATA2
,
1917 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1918 /* TODO wrong return value */
1921 /* TODO error handling of err */
1923 /* reset the number of folders for the next cabinet */
1924 p_fci_internal
->cFolders
=0;
1925 /* reset the number of files for the next cabinet */
1926 p_fci_internal
->cFiles
=0;
1928 /* while not all CFDATA structures have been copied to the cabinet do */
1930 /* REUSE the variable read_result AGAIN */
1931 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1932 /* read a block from p_fci_internal->handleCFDATA2 */
1933 read_result
= PFCI_READ(hfci
, p_fci_internal
->handleCFDATA2
/* handle */,
1934 p_fci_internal
->data_out
, /* memory buffer */
1935 32768, /* number of bytes to copy */
1936 &err
, p_fci_internal
->pv
);
1937 if( read_result
== 0 ) break; /* ALL CFDATA structures have been copied */
1938 /* TODO error handling of err */
1940 /* write the block to the cabinet file */
1941 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1942 p_fci_internal
->data_out
, /* memory buffer */
1943 read_result
, /* number of bytes to copy */
1944 &err
, p_fci_internal
->pv
) != read_result
) {
1945 /* TODO write error */
1948 /* TODO error handling of err */
1950 p_fci_internal
->statusFolderCopied
+= read_result
;
1951 /* report status with pfnfcis about copied size of folder */
1952 if( (*pfnfcis
)(statusFolder
,
1953 p_fci_internal
->statusFolderCopied
, /* length of copied blocks */
1954 p_fci_internal
->statusFolderTotal
, /* total size of folder */
1955 p_fci_internal
->pv
) == -1) {
1956 /* TODO set error code and abort */
1959 } /* END OF while */
1961 /* set seek of the cabinet file to 0 */
1962 if( PFCI_SEEK(hfci
, handleCABINET
,
1963 0, SEEK_SET
, &err
, p_fci_internal
->pv
) != 0 ) {
1964 /* TODO wrong return value */
1966 /* TODO error handling of err */
1968 /* write the signature "MSCF" into the cabinet file */
1969 memcpy( cfheader
.signature
, "MSCF", 4 );
1970 if( PFCI_WRITE(hfci
, handleCABINET
, /* file handle */
1971 &cfheader
, /* memory buffer */
1972 4, /* number of bytes to copy */
1973 &err
, p_fci_internal
->pv
) != 4 ) {
1974 /* TODO write error */
1977 /* TODO error handling of err */
1979 /* close the cabinet file */
1980 PFCI_CLOSE(hfci
,handleCABINET
,&err
,p_fci_internal
->pv
);
1981 /* TODO error handling of err */
1984 /* COPIED FROM FCIDestroy */
1986 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
1987 /* TODO error handling of err */
1988 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
1989 p_fci_internal
->pv
);
1990 /* TODO error handling of err */
1991 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
1992 /* TODO error handling of err */
1993 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
1994 p_fci_internal
->pv
);
1995 /* TODO error handling of err */
1996 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
1997 /* TODO error handling of err */
1998 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
1999 p_fci_internal
->pv
);
2000 /* TODO error handling of err */
2002 /* END OF copied from FCIDestroy */
2004 /* get 3 temporary files and open them */
2005 /* write names and handles to hfci */
2008 p_fci_internal
->sizeFileCFDATA2
= 0;
2009 p_fci_internal
->sizeFileCFFILE2
= 0;
2010 p_fci_internal
->sizeFileCFFOLDER
= 0;
2012 /* COPIED FROM FCICreate */
2014 /* CFDATA with checksum and ready to be copied into cabinet */
2015 if( !PFCI_GETTEMPFILE(hfci
, p_fci_internal
->szFileNameCFDATA2
,
2017 /* TODO error handling */
2021 if ( strlen(p_fci_internal
->szFileNameCFDATA2
) >= CB_MAX_FILENAME
) {
2022 /* TODO set error code */
2025 p_fci_internal
->handleCFDATA2
= PFCI_OPEN(hfci
,
2026 p_fci_internal
->szFileNameCFDATA2
, 34050, 384, &err
, p_fci_internal
->pv
);
2027 /* TODO check handle */
2028 /* TODO error checking of err */
2030 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2031 if( !PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFILE2
,
2033 /* TODO error handling */
2037 if ( strlen(p_fci_internal
->szFileNameCFFILE2
) >= CB_MAX_FILENAME
) {
2038 /* TODO set error code */
2041 p_fci_internal
->handleCFFILE2
= PFCI_OPEN(hfci
,
2042 p_fci_internal
->szFileNameCFFILE2
, 34050, 384, &err
, p_fci_internal
->pv
);
2043 /* TODO check handle */
2044 /* TODO error checking of err */
2046 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2047 if (!PFCI_GETTEMPFILE(hfci
,p_fci_internal
->szFileNameCFFOLDER
,CB_MAX_FILENAME
)) {
2048 /* TODO error handling */
2052 if ( strlen(p_fci_internal
->szFileNameCFFOLDER
) >= CB_MAX_FILENAME
) {
2053 /* TODO set error code */
2056 p_fci_internal
->handleCFFOLDER
= PFCI_OPEN(hfci
,
2057 p_fci_internal
->szFileNameCFFOLDER
, 34050, 384, &err
, p_fci_internal
->pv
);
2058 /* TODO check handle */
2059 /* TODO error checking of err */
2061 /* END OF copied from FCICreate */
2064 /* TODO close and delete new files when return FALSE */
2067 /* report status with pfnfcis about copied size of folder */
2068 if( (*pfnfcis
)(statusCabinet
, p_fci_internal
->statusFolderTotal
, /* TODO estimated cabinet file size */
2069 cfheader
.cbCabinet
, /* real cabinet file size */ p_fci_internal
->pv
) == -1) {
2070 /* TODO set error code and abort */
2074 p_fci_internal
->fPrevCab
=TRUE
;
2075 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2076 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2078 if (p_fci_internal
->fNextCab
) {
2079 p_fci_internal
->fNextCab
=FALSE
;
2081 if (p_fci_internal
->sizeFileCFFILE1
==0 && p_fci_internal
->sizeFileCFDATA1
!=0) {
2082 /* THIS CAN NEVER HAPPEN */
2083 /* TODO set error code */
2087 /* COPIED FROM FCIAddFile and modified */
2089 /* REUSE the variable read_result */
2090 if (p_fci_internal
->fGetNextCabInVain
) {
2091 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
;
2092 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2093 read_result
+=p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2095 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2096 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2097 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2101 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
;
2102 if(p_fci_internal
->sizeFileCFFILE1
!=0) {
2103 read_result
+=p_fci_internal
->pccab
->cbReserveCFFolder
;
2105 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2106 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2107 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2111 if ( p_fci_internal
->fPrevCab
) {
2112 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2113 strlen(p_fci_internal
->szPrevDisk
)+1;
2115 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2116 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2117 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2119 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2121 if( p_fci_internal
->fNewPrevious
) {
2122 memcpy(p_fci_internal
->szPrevCab
, p_fci_internal
->oldCCAB
.szCab
,
2123 CB_MAX_CABINET_NAME
);
2124 memcpy(p_fci_internal
->szPrevDisk
, p_fci_internal
->oldCCAB
.szDisk
,
2126 p_fci_internal
->fNewPrevious
=FALSE
;
2129 /* too much data for the maximum size of a cabinet */
2130 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2131 p_fci_internal
->pccab
->cb
< read_result
) {
2132 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2135 /* Might be too much data for the maximum size of a cabinet.*/
2136 /* When any further data will be added later, it might not */
2137 /* be possible to flush the cabinet, because there might */
2138 /* not be enough space to store the name of the following */
2139 /* cabinet and name of the corresponding disk. */
2140 /* So take care of this and get the name of the next cabinet */
2141 if (p_fci_internal
->fGetNextCabInVain
==FALSE
&& (
2142 p_fci_internal
->pccab
->cb
< read_result
+
2143 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2146 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2147 /* increment cabinet index */
2148 ++(p_fci_internal
->pccab
->iCab
);
2149 /* get name of next cabinet */
2150 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0, /* estimated size of cab */
2151 p_fci_internal
->pv
)) {
2152 /* TODO error handling */
2155 /* Skip a few lines of code. This is catched by the next if. */
2156 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2159 /* too much data for cabinet */
2160 if (p_fci_internal
->fGetNextCabInVain
&& (
2161 p_fci_internal
->oldCCAB
.cb
< read_result
+
2162 strlen(p_fci_internal
->oldCCAB
.szCab
)+1+
2163 strlen(p_fci_internal
->oldCCAB
.szDisk
)+1
2165 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2166 p_fci_internal
->fNextCab
=TRUE
;
2167 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2170 /* if the FolderThreshold has been reached flush the folder automatically */
2171 if( p_fci_internal
->fGetNextCabInVain
) {
2172 if( p_fci_internal
->cCompressedBytesInFolder
>=
2173 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2174 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2177 if( p_fci_internal
->cCompressedBytesInFolder
>=
2178 p_fci_internal
->pccab
->cbFolderThresh
) {
2179 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2183 /* END OF COPIED FROM FCIAddFile and modified */
2185 if( p_fci_internal
->sizeFileCFFILE1
>0 ) {
2186 if( !FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
) ) return FALSE
;
2187 p_fci_internal
->fNewPrevious
=TRUE
;
2190 p_fci_internal
->fNewPrevious
=FALSE
;
2191 if( p_fci_internal
->sizeFileCFFILE1
>0 || p_fci_internal
->sizeFileCFDATA1
) {
2192 /* THIS MAY NEVER HAPPEN */
2193 /* TODO set error structures */
2199 } /* end of fci_flush_cabinet */
2205 /***********************************************************************
2206 * FCIAddFile (CABINET.11)
2208 * FCIAddFile adds a file to the to be created cabinet file
2211 * hfci [I] An HFCI from FCICreate
2212 * pszSourceFile [I] A pointer to a C string which contains the name and
2213 * location of the file which will be added to the cabinet
2214 * pszFileName [I] A pointer to a C string which contains the name under
2215 * which the file will be stored in the cabinet
2216 * fExecute [I] A boolean value which indicates if the file should be
2217 * executed after extraction of self extracting
2219 * pfnfcignc [I] A pointer to a function which gets information about
2221 * pfnfcis [IO] A pointer to a function which will report status
2222 * information about the compression process
2223 * pfnfcioi [I] A pointer to a function which reports file attributes
2224 * and time and date information
2225 * typeCompress [I] Compression type
2228 * On success, returns TRUE
2229 * On failure, returns FALSE
2235 BOOL __cdecl
FCIAddFile(
2237 char *pszSourceFile
,
2240 PFNFCIGETNEXTCABINET pfnfcignc
,
2241 PFNFCISTATUS pfnfcis
,
2242 PFNFCIGETOPENINFO pfnfcigoi
,
2247 cab_ULONG read_result
;
2249 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2252 if (!REALLY_IS_FCI(hfci
)) {
2253 SetLastError(ERROR_INVALID_HANDLE
);
2257 if ((!pszSourceFile
) || (!pszFileName
) || (!pfnfcignc
) || (!pfnfcis
) ||
2258 (!pfnfcigoi
) || strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2259 p_fci_internal
->perf
->erfOper
= FCIERR_NONE
;
2260 p_fci_internal
->perf
->erfType
= ERROR_BAD_ARGUMENTS
;
2261 p_fci_internal
->perf
->fError
= TRUE
;
2263 SetLastError(ERROR_BAD_ARGUMENTS
);
2267 /* TODO check if pszSourceFile??? */
2269 if(p_fci_internal
->fGetNextCabInVain
&& p_fci_internal
->fNextCab
) {
2270 /* TODO internal error */
2274 if(p_fci_internal
->fNextCab
) {
2275 /* TODO internal error */
2279 cffile
.cbFile
=0; /* size of the to be added file*/
2280 /* offset of the uncompressed file in the folder */
2281 cffile
.uoffFolderStart
=p_fci_internal
->cDataBlocks
*CAB_BLOCKMAX
+ p_fci_internal
->cdata_in
;
2282 /* number of folder in the cabinet or special 0=first */
2283 cffile
.iFolder
= p_fci_internal
->cFolders
;
2285 /* allocation of memory */
2286 if (p_fci_internal
->data_in
==NULL
) {
2287 if (p_fci_internal
->cdata_in
!=0) {
2288 /* TODO error handling */
2291 if (p_fci_internal
->data_out
!=NULL
) {
2292 /* TODO error handling */
2295 if(!(p_fci_internal
->data_in
= (char*)PFCI_ALLOC(hfci
,CB_MAX_CHUNK
))) {
2296 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
2297 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
2298 p_fci_internal
->perf
->fError
= TRUE
;
2299 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2302 if (p_fci_internal
->data_out
==NULL
) {
2303 if(!(p_fci_internal
->data_out
= PFCI_ALLOC(hfci
, 2 * CB_MAX_CHUNK
))){
2304 p_fci_internal
->perf
->erfOper
= FCIERR_ALLOC_FAIL
;
2305 p_fci_internal
->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
2306 p_fci_internal
->perf
->fError
= TRUE
;
2307 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2313 if (p_fci_internal
->data_out
==NULL
) {
2314 PFCI_FREE(hfci
,p_fci_internal
->data_in
);
2315 /* TODO error handling */
2319 /* get information about the file */
2320 file_handle
=(*pfnfcigoi
)(pszSourceFile
, &(cffile
.date
), &(cffile
.time
),
2321 &(cffile
.attribs
), &err
, p_fci_internal
->pv
);
2322 /* TODO check file_handle */
2323 /* TODO error handling of err */
2325 if (fExecute
) { cffile
.attribs
|= _A_EXEC
; }
2327 /* REUSE the variable read_result */
2328 if (p_fci_internal
->fGetNextCabInVain
) {
2329 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2330 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2331 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2332 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2333 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2337 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2338 p_fci_internal
->pccab
->cbReserveCFFolder
;
2339 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2340 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2341 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2345 if ( p_fci_internal
->fPrevCab
) {
2346 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2347 strlen(p_fci_internal
->szPrevDisk
)+1;
2349 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2350 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2351 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2354 read_result
+= sizeof(CFFILE
) + strlen(pszFileName
)+1 +
2355 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2356 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2358 sizeof(CFFOLDER
); /* size of new CFFolder entry */
2360 /* Might be too much data for the maximum size of a cabinet.*/
2361 /* When any further data will be added later, it might not */
2362 /* be possible to flush the cabinet, because there might */
2363 /* not be enough space to store the name of the following */
2364 /* cabinet and name of the corresponding disk. */
2365 /* So take care of this and get the name of the next cabinet */
2366 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2367 p_fci_internal
->fNextCab
==FALSE
&&
2368 ( p_fci_internal
->pccab
->cb
< read_result
+
2369 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2373 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2374 /* increment cabinet index */
2375 ++(p_fci_internal
->pccab
->iCab
);
2376 /* get name of next cabinet */
2377 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0,/* TODO estimated size of cab */
2378 p_fci_internal
->pv
)) {
2379 /* TODO error handling */
2382 /* Skip a few lines of code. This is catched by the next if. */
2383 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2386 if( p_fci_internal
->fGetNextCabInVain
&&
2387 p_fci_internal
->fNextCab
2389 /* THIS CAN NEVER HAPPEN */
2390 /* TODO set error code*/
2394 /* too much data for cabinet */
2395 if( p_fci_internal
->fGetNextCabInVain
&&
2397 p_fci_internal
->oldCCAB
.cb
< read_result
+
2398 strlen(p_fci_internal
->pccab
->szCab
)+1+
2399 strlen(p_fci_internal
->pccab
->szDisk
)+1
2401 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2402 p_fci_internal
->fNextCab
=TRUE
;
2403 if(!fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
)) return FALSE
;
2406 if( p_fci_internal
->fNextCab
) {
2407 /* THIS MAY NEVER HAPPEN */
2408 /* TODO set error code*/
2412 /* read the contents of the file blockwize*/
2414 if (p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2415 /* TODO internal error */
2419 read_result
= PFCI_READ(hfci
, file_handle
/* file handle */,
2420 (p_fci_internal
->data_in
+ p_fci_internal
->cdata_in
) /* memory buffer */,
2421 (CAB_BLOCKMAX
- p_fci_internal
->cdata_in
) /* number of bytes to copy */,
2422 &err
, p_fci_internal
->pv
);
2423 /* TODO error handling of err */
2425 if( read_result
==0 ) break;
2427 /* increment the block size */
2428 p_fci_internal
->cdata_in
+= read_result
;
2430 /* increment the file size */
2431 cffile
.cbFile
+= read_result
;
2434 if ( p_fci_internal
->cdata_in
> CAB_BLOCKMAX
) {
2435 /* TODO report internal error */
2438 /* write a whole block */
2439 if ( p_fci_internal
->cdata_in
== CAB_BLOCKMAX
) {
2441 if( !fci_flush_data_block(hfci
, &err
, pfnfcis
) ) return FALSE
;
2445 /* close the file from FCIAddFile */
2446 PFCI_CLOSE(hfci
,file_handle
,&err
,p_fci_internal
->pv
);
2447 /* TODO error handling of err */
2449 /* write cffile to p_fci_internal->handleCFFILE1 */
2450 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2451 &cffile
, sizeof(cffile
),&err
, p_fci_internal
->pv
) != sizeof(cffile
) ) {
2452 /* TODO write error */
2455 /* TODO error handling of err */
2457 p_fci_internal
->sizeFileCFFILE1
+= sizeof(cffile
);
2459 /* append the name of file*/
2460 if (strlen(pszFileName
)>=CB_MAX_FILENAME
) {
2462 /* TODO set error code */
2465 if( PFCI_WRITE(hfci
, p_fci_internal
->handleCFFILE1
, /* file handle */
2466 pszFileName
, strlen(pszFileName
)+1, &err
, p_fci_internal
->pv
)
2467 != strlen(pszFileName
)+1 ) {
2468 /* TODO write error */
2471 /* TODO error handling of err */
2473 p_fci_internal
->sizeFileCFFILE1
+= strlen(pszFileName
)+1;
2475 /* REUSE the variable read_result */
2476 if (p_fci_internal
->fGetNextCabInVain
||
2477 p_fci_internal
->fNextCab
2479 read_result
=p_fci_internal
->oldCCAB
.cbReserveCFHeader
+
2480 p_fci_internal
->oldCCAB
.cbReserveCFFolder
;
2481 if ( p_fci_internal
->oldCCAB
.cbReserveCFHeader
!= 0 ||
2482 p_fci_internal
->oldCCAB
.cbReserveCFFolder
!= 0 ||
2483 p_fci_internal
->oldCCAB
.cbReserveCFData
!= 0 ) {
2487 read_result
=p_fci_internal
->pccab
->cbReserveCFHeader
+
2488 p_fci_internal
->pccab
->cbReserveCFFolder
;
2489 if ( p_fci_internal
->pccab
->cbReserveCFHeader
!= 0 ||
2490 p_fci_internal
->pccab
->cbReserveCFFolder
!= 0 ||
2491 p_fci_internal
->pccab
->cbReserveCFData
!= 0 ) {
2495 if ( p_fci_internal
->fPrevCab
) {
2496 read_result
+= strlen(p_fci_internal
->szPrevCab
)+1+
2497 strlen(p_fci_internal
->szPrevDisk
)+1;
2499 if ( p_fci_internal
->fNextCab
) { /* this is never the case */
2500 read_result
+= strlen(p_fci_internal
->pccab
->szCab
)+1+
2501 strlen(p_fci_internal
->pccab
->szDisk
)+1;
2503 read_result
+= p_fci_internal
->sizeFileCFDATA1
+
2504 p_fci_internal
->sizeFileCFFILE1
+ p_fci_internal
->sizeFileCFDATA2
+
2505 p_fci_internal
->sizeFileCFFILE2
+ p_fci_internal
->sizeFileCFFOLDER
+
2507 sizeof(CFFOLDER
); /* set size of new CFFolder entry */
2509 /* too much data for the maximum size of a cabinet */
2510 /* (ignoring the unflushed data block) */
2511 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2512 p_fci_internal
->fNextCab
==FALSE
&& /* this is always the case */
2513 p_fci_internal
->pccab
->cb
< read_result
) {
2514 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2517 /* Might be too much data for the maximum size of a cabinet.*/
2518 /* When any further data will be added later, it might not */
2519 /* be possible to flush the cabinet, because there might */
2520 /* not be enough space to store the name of the following */
2521 /* cabinet and name of the corresponding disk. */
2522 /* So take care of this and get the name of the next cabinet */
2523 /* (ignoring the unflushed data block) */
2524 if( p_fci_internal
->fGetNextCabInVain
==FALSE
&&
2525 p_fci_internal
->fNextCab
==FALSE
&&
2526 ( p_fci_internal
->pccab
->cb
< read_result
+
2527 CB_MAX_CABINET_NAME
+ CB_MAX_DISK_NAME
2531 memcpy(&(p_fci_internal
->oldCCAB
), p_fci_internal
->pccab
, sizeof(CCAB
));
2532 /* increment cabinet index */
2533 ++(p_fci_internal
->pccab
->iCab
);
2534 /* get name of next cabinet */
2535 if (!(*pfnfcignc
)(p_fci_internal
->pccab
, 0,/* TODO estimated size of cab */
2536 p_fci_internal
->pv
)) {
2537 /* TODO error handling */
2540 /* Skip a few lines of code. This is catched by the next if. */
2541 p_fci_internal
->fGetNextCabInVain
=TRUE
;
2544 if( p_fci_internal
->fGetNextCabInVain
&&
2545 p_fci_internal
->fNextCab
2547 /* THIS CAN NEVER HAPPEN */
2548 /* TODO set error code*/
2552 /* too much data for cabinet */
2553 if( (p_fci_internal
->fGetNextCabInVain
||
2554 p_fci_internal
->fNextCab
) && (
2555 p_fci_internal
->oldCCAB
.cb
< read_result
+
2556 strlen(p_fci_internal
->pccab
->szCab
)+1+
2557 strlen(p_fci_internal
->pccab
->szDisk
)+1
2560 p_fci_internal
->fGetNextCabInVain
=FALSE
;
2561 p_fci_internal
->fNextCab
=TRUE
;
2562 return fci_flush_cabinet( hfci
, FALSE
, pfnfcignc
, pfnfcis
);
2565 if( p_fci_internal
->fNextCab
) {
2566 /* THIS MAY NEVER HAPPEN */
2567 /* TODO set error code*/
2571 /* if the FolderThreshold has been reached flush the folder automatically */
2572 if( p_fci_internal
->fGetNextCabInVain
) {
2573 if( p_fci_internal
->cCompressedBytesInFolder
>=
2574 p_fci_internal
->oldCCAB
.cbFolderThresh
) {
2575 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2578 if( p_fci_internal
->cCompressedBytesInFolder
>=
2579 p_fci_internal
->pccab
->cbFolderThresh
) {
2580 return FCIFlushFolder(hfci
, pfnfcignc
, pfnfcis
);
2585 } /* end of FCIAddFile */
2591 /***********************************************************************
2592 * FCIFlushFolder (CABINET.12)
2594 * FCIFlushFolder completes the CFFolder structure under construction.
2596 * All further data which is added by FCIAddFile will be associateed to
2597 * the next CFFolder structure.
2599 * FCIFlushFolder will be called by FCIAddFile automatically if the
2600 * threshold (stored in the member cbFolderThresh of the CCAB structure
2601 * pccab passed to FCICreate) is exceeded.
2603 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2604 * any data will be written into the cabinet file.
2607 * hfci [I] An HFCI from FCICreate
2608 * pfnfcignc [I] A pointer to a function which gets information about
2610 * pfnfcis [IO] A pointer to a function which will report status
2611 * information about the compression process
2614 * On success, returns TRUE
2615 * On failure, returns FALSE
2621 BOOL __cdecl
FCIFlushFolder(
2623 PFNFCIGETNEXTCABINET pfnfcignc
,
2624 PFNFCISTATUS pfnfcis
)
2626 return fci_flush_folder(hfci
,FALSE
,pfnfcignc
,pfnfcis
);
2627 } /* end of FCIFlushFolder */
2631 /***********************************************************************
2632 * FCIFlushCabinet (CABINET.13)
2634 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2635 * into the cabinet file. If the maximum cabinet size (stored in the
2636 * member cb of the CCAB structure pccab passed to FCICreate) has been
2637 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2638 * The remaining data still has to be flushed manually by calling
2641 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2642 * NOT be called again. Then hfci has to be released by FCIDestroy.
2645 * hfci [I] An HFCI from FCICreate
2646 * fGetNextCab [I] Whether you want to add additional files to a
2647 * cabinet set (TRUE) or whether you want to
2648 * finalize it (FALSE)
2649 * pfnfcignc [I] A pointer to a function which gets information about
2651 * pfnfcis [IO] A pointer to a function which will report status
2652 * information about the compression process
2655 * On success, returns TRUE
2656 * On failure, returns FALSE
2662 BOOL __cdecl
FCIFlushCabinet(
2665 PFNFCIGETNEXTCABINET pfnfcignc
,
2666 PFNFCISTATUS pfnfcis
)
2668 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2670 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2672 while( p_fci_internal
->sizeFileCFFILE1
>0 ||
2673 p_fci_internal
->sizeFileCFFILE2
>0 ) {
2674 if(!fci_flush_cabinet(hfci
,fGetNextCab
,pfnfcignc
,pfnfcis
)) return FALSE
;
2678 } /* end of FCIFlushCabinet */
2681 /***********************************************************************
2682 * FCIDestroy (CABINET.14)
2684 * Frees a handle created by FCICreate.
2685 * Only reason for failure would be an invalid handle.
2688 * hfci [I] The HFCI to free
2694 BOOL __cdecl
FCIDestroy(HFCI hfci
)
2697 PFCI_Int p_fci_internal
=((PFCI_Int
)(hfci
));
2698 if (REALLY_IS_FCI(hfci
)) {
2700 /* before hfci can be removed all temporary files must be closed */
2702 p_fci_internal
->FCI_Intmagic
= 0;
2704 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA1
,&err
,p_fci_internal
->pv
);
2705 /* TODO error handling of err */
2706 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA1
, &err
,
2707 p_fci_internal
->pv
);
2708 /* TODO error handling of err */
2709 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE1
,&err
,p_fci_internal
->pv
);
2710 /* TODO error handling of err */
2711 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE1
, &err
,
2712 p_fci_internal
->pv
);
2713 /* TODO error handling of err */
2714 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFDATA2
,&err
,p_fci_internal
->pv
);
2715 /* TODO error handling of err */
2716 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFDATA2
, &err
,
2717 p_fci_internal
->pv
);
2718 /* TODO error handling of err */
2719 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFILE2
,&err
,p_fci_internal
->pv
);
2720 /* TODO error handling of err */
2721 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFILE2
, &err
,
2722 p_fci_internal
->pv
);
2723 /* TODO error handling of err */
2724 PFCI_CLOSE (hfci
, p_fci_internal
->handleCFFOLDER
,&err
,p_fci_internal
->pv
);
2725 /* TODO error handling of err */
2726 PFCI_DELETE(hfci
, p_fci_internal
->szFileNameCFFOLDER
, &err
,
2727 p_fci_internal
->pv
);
2728 /* TODO error handling of err */
2730 /* data in and out buffers have to be removed */
2731 if (p_fci_internal
->data_in
!=NULL
)
2732 PFCI_FREE(hfci
, p_fci_internal
->data_in
);
2733 if (p_fci_internal
->data_out
!=NULL
)
2734 PFCI_FREE(hfci
, p_fci_internal
->data_out
);
2736 /* hfci can now be removed */
2737 PFCI_FREE(hfci
, hfci
);
2740 SetLastError(ERROR_INVALID_HANDLE
);
2744 } /* end of FCIDestroy */