Changes in crossover-wine-src-6.1.0 except for configure
[wine/hacks.git] / dlls / cabinet / fci.c
blob112c06b1107ee83ac29ddd640206027e9b446c56
1 /*
2 * File Compression Interface
4 * Copyright 2002 Patrik Stridvall
5 * Copyright 2005 Gerold Jens Wucherpfennig
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 There is still some work to be done:
26 - no real compression yet
27 - unknown behaviour if files>=2GB or cabinet >=4GB
28 - check if the maximum size for a cabinet is too small to store any data
29 - call pfnfcignc on exactly the same position as MS FCIAddFile in every case
30 - probably check err
36 #include "config.h"
38 #include <stdarg.h>
39 #include <stdio.h>
40 #include <string.h>
42 #include "windef.h"
43 #include "winbase.h"
44 #include "winerror.h"
45 #include "winternl.h"
46 #include "fci.h"
47 #include "cabinet.h"
48 #include "wine/debug.h"
51 #ifdef WORDS_BIGENDIAN
52 #define fci_endian_ulong(x) RtlUlongByteSwap(x)
53 #define fci_endian_uword(x) RtlUshortByteSwap(x)
54 #else
55 #define fci_endian_ulong(x) (x)
56 #define fci_endian_uword(x) (x)
57 #endif
60 #define fci_set_error(A,B,C) do { \
61 p_fci_internal->perf->erfOper = A; \
62 p_fci_internal->perf->erfType = B; \
63 p_fci_internal->perf->fError = C; \
64 if (B) SetLastError(B); } while(0)
67 typedef struct {
68 cab_UBYTE signature[4]; /* !CAB for unfinished cabinets else MSCF */
69 cab_ULONG reserved1;
70 cab_ULONG cbCabinet; /* size of the cabinet file in bytes*/
71 cab_ULONG reserved2;
72 cab_ULONG coffFiles; /* offset to first CFFILE section */
73 cab_ULONG reserved3;
74 cab_UBYTE versionMinor; /* 3 */
75 cab_UBYTE versionMajor; /* 1 */
76 cab_UWORD cFolders; /* number of CFFOLDER entries in the cabinet*/
77 cab_UWORD cFiles; /* number of CFFILE entries in the cabinet*/
78 cab_UWORD flags; /* 1=prev cab, 2=next cabinet, 4=reserved setions*/
79 cab_UWORD setID; /* identification number of all cabinets in a set*/
80 cab_UWORD iCabinet; /* number of the cabinet in a set */
81 /* additional area if "flags" were set*/
82 } CFHEADER; /* minimum 36 bytes */
84 typedef struct {
85 cab_ULONG coffCabStart; /* offset to the folder's first CFDATA section */
86 cab_UWORD cCFData; /* number of this folder's CFDATA sections */
87 cab_UWORD typeCompress; /* compression type of data in CFDATA section*/
88 /* additional area if reserve flag was set */
89 } CFFOLDER; /* minumum 8 bytes */
91 typedef struct {
92 cab_ULONG cbFile; /* size of the uncompressed file in bytes */
93 cab_ULONG uoffFolderStart; /* offset of the uncompressed file in the folder */
94 cab_UWORD iFolder; /* number of folder in the cabinet 0=first */
95 /* for special values see below this structure*/
96 cab_UWORD date; /* last modification date*/
97 cab_UWORD time; /* last modification time*/
98 cab_UWORD attribs; /* DOS fat attributes and UTF indicator */
99 /* ... and a C string with the name of the file */
100 } CFFILE; /* 16 bytes + name of file */
103 typedef struct {
104 cab_ULONG csum; /* checksum of this entry*/
105 cab_UWORD cbData; /* number of compressed bytes */
106 cab_UWORD cbUncomp; /* number of bytes when data is uncompressed */
107 /* optional reserved area */
108 /* compressed data */
109 } CFDATA;
112 /***********************************************************************
113 * FCICreate (CABINET.10)
115 * FCICreate is provided with several callbacks and
116 * returns a handle which can be used to create cabinet files.
118 * PARAMS
119 * perf [IO] A pointer to an ERF structure. When FCICreate
120 * returns an error condition, error information may
121 * be found here as well as from GetLastError.
122 * pfnfiledest [I] A pointer to a function which is called when a file
123 * is placed. Only useful for subsequent cabinet files.
124 * pfnalloc [I] A pointer to a function which allocates ram. Uses
125 * the same interface as malloc.
126 * pfnfree [I] A pointer to a function which frees ram. Uses the
127 * same interface as free.
128 * pfnopen [I] A pointer to a function which opens a file. Uses
129 * the same interface as _open.
130 * pfnread [I] A pointer to a function which reads from a file into
131 * a caller-provided buffer. Uses the same interface
132 * as _read.
133 * pfnwrite [I] A pointer to a function which writes to a file from
134 * a caller-provided buffer. Uses the same interface
135 * as _write.
136 * pfnclose [I] A pointer to a function which closes a file handle.
137 * Uses the same interface as _close.
138 * pfnseek [I] A pointer to a function which seeks in a file.
139 * Uses the same interface as _lseek.
140 * pfndelete [I] A pointer to a function which deletes a file.
141 * pfnfcigtf [I] A pointer to a function which gets the name of a
142 * temporary file.
143 * pccab [I] A pointer to an initialized CCAB structure.
144 * pv [I] A pointer to an application-defined notification
145 * function which will be passed to other FCI functions
146 * as a parameter.
148 * RETURNS
149 * On success, returns an FCI handle of type HFCI.
150 * On failure, the NULL file handle is returned. Error
151 * info can be retrieved from perf.
153 * INCLUDES
154 * fci.h
157 HFCI __cdecl FCICreate(
158 PERF perf,
159 PFNFCIFILEPLACED pfnfiledest,
160 PFNFCIALLOC pfnalloc,
161 PFNFCIFREE pfnfree,
162 PFNFCIOPEN pfnopen,
163 PFNFCIREAD pfnread,
164 PFNFCIWRITE pfnwrite,
165 PFNFCICLOSE pfnclose,
166 PFNFCISEEK pfnseek,
167 PFNFCIDELETE pfndelete,
168 PFNFCIGETTEMPFILE pfnfcigtf,
169 PCCAB pccab,
170 void *pv)
172 HFCI hfci;
173 int err;
174 PFCI_Int p_fci_internal;
176 if ((!perf) || (!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||
177 (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||
178 (!pfnfcigtf) || (!pccab)) {
179 perf->erfOper = FCIERR_NONE;
180 perf->erfType = ERROR_BAD_ARGUMENTS;
181 perf->fError = TRUE;
183 SetLastError(ERROR_BAD_ARGUMENTS);
184 return NULL;
187 if (!((hfci = ((HFCI) (*pfnalloc)(sizeof(FCI_Int)))))) {
188 perf->erfOper = FCIERR_ALLOC_FAIL;
189 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
190 perf->fError = TRUE;
192 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
193 return NULL;
196 p_fci_internal=((PFCI_Int)(hfci));
197 p_fci_internal->FCI_Intmagic = FCI_INT_MAGIC;
198 p_fci_internal->perf = perf;
199 p_fci_internal->pfnfiledest = pfnfiledest;
200 p_fci_internal->pfnalloc = pfnalloc;
201 p_fci_internal->pfnfree = pfnfree;
202 p_fci_internal->pfnopen = pfnopen;
203 p_fci_internal->pfnread = pfnread;
204 p_fci_internal->pfnwrite = pfnwrite;
205 p_fci_internal->pfnclose = pfnclose;
206 p_fci_internal->pfnseek = pfnseek;
207 p_fci_internal->pfndelete = pfndelete;
208 p_fci_internal->pfnfcigtf = pfnfcigtf;
209 p_fci_internal->pccab = pccab;
210 p_fci_internal->fPrevCab = FALSE;
211 p_fci_internal->fNextCab = FALSE;
212 p_fci_internal->fSplitFolder = FALSE;
213 p_fci_internal->fGetNextCabInVain = FALSE;
214 p_fci_internal->pv = pv;
215 p_fci_internal->data_in = NULL;
216 p_fci_internal->cdata_in = 0;
217 p_fci_internal->data_out = NULL;
218 p_fci_internal->cCompressedBytesInFolder = 0;
219 p_fci_internal->cFolders = 0;
220 p_fci_internal->cFiles = 0;
221 p_fci_internal->cDataBlocks = 0;
222 p_fci_internal->sizeFileCFDATA1 = 0;
223 p_fci_internal->sizeFileCFFILE1 = 0;
224 p_fci_internal->sizeFileCFDATA2 = 0;
225 p_fci_internal->sizeFileCFFILE2 = 0;
226 p_fci_internal->sizeFileCFFOLDER = 0;
227 p_fci_internal->sizeFileCFFOLDER = 0;
228 p_fci_internal->fNewPrevious = FALSE;
229 p_fci_internal->estimatedCabinetSize = 0;
230 p_fci_internal->statusFolderTotal = 0;
232 memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
233 memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);
235 /* CFDATA */
236 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA1,
237 CB_MAX_FILENAME)) {
238 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
239 return FALSE;
241 /* safety */
242 if ( strlen(p_fci_internal->szFileNameCFDATA1) >= CB_MAX_FILENAME ) {
243 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
244 return FALSE;
247 p_fci_internal->handleCFDATA1 = PFCI_OPEN(hfci,
248 p_fci_internal->szFileNameCFDATA1, 34050, 384, &err, pv);
249 if(p_fci_internal->handleCFDATA1==0){
250 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
251 return FALSE;
253 /* TODO error checking of err */
255 /* array of all CFFILE in a folder */
256 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE1,
257 CB_MAX_FILENAME)) {
258 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
259 return FALSE;
261 /* safety */
262 if ( strlen(p_fci_internal->szFileNameCFFILE1) >= CB_MAX_FILENAME ) {
263 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
264 return FALSE;
266 p_fci_internal->handleCFFILE1 = PFCI_OPEN(hfci,
267 p_fci_internal->szFileNameCFFILE1, 34050, 384, &err, pv);
268 if(p_fci_internal->handleCFFILE1==0){
269 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
270 return FALSE;
272 /* TODO error checking of err */
274 /* CFDATA with checksum and ready to be copied into cabinet */
275 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA2,
276 CB_MAX_FILENAME)) {
277 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE);
278 return FALSE;
280 /* safety */
281 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
282 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
283 return FALSE;
285 p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
286 p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, pv);
287 if(p_fci_internal->handleCFDATA2==0){
288 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
289 return FALSE;
291 /* TODO error checking of err */
293 /* array of all CFFILE in a folder, ready to be copied into cabinet */
294 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
295 CB_MAX_FILENAME)) {
296 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
297 return FALSE;
299 /* safety */
300 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
301 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
302 return FALSE;
304 p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
305 p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, pv);
306 if(p_fci_internal->handleCFFILE2==0){
307 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
308 return FALSE;
310 /* TODO error checking of err */
312 /* array of all CFFILE in a folder, ready to be copied into cabinet */
313 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,
314 CB_MAX_FILENAME)) {
315 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
316 return FALSE;
318 /* safety */
319 if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
320 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
321 return FALSE;
323 p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
324 p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, pv);
325 if(p_fci_internal->handleCFFOLDER==0) {
326 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
327 return FALSE;
330 /* TODO close and delete new files when return FALSE */
331 /* TODO error checking of err */
333 return hfci;
334 } /* end of FCICreate */
341 static BOOL fci_flush_data_block (HFCI hfci, int* err,
342 PFNFCISTATUS pfnfcis) {
344 /* attention no hfci checks!!! */
345 /* attention no checks if there is data available!!! */
346 CFDATA data;
347 CFDATA* cfdata=&data;
348 char* reserved;
349 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
350 UINT cbReserveCFData=p_fci_internal->pccab->cbReserveCFData;
351 UINT i;
353 /* TODO compress the data of p_fci_internal->data_in */
354 /* and write it to p_fci_internal->data_out */
355 memcpy(p_fci_internal->data_out, p_fci_internal->data_in,
356 p_fci_internal->cdata_in /* number of bytes to copy */);
358 cfdata->csum=0; /* checksum has to be set later */
359 /* TODO set realsize of compressed data */
360 cfdata->cbData = p_fci_internal->cdata_in;
361 cfdata->cbUncomp = p_fci_internal->cdata_in;
363 /* write cfdata to p_fci_internal->handleCFDATA1 */
364 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
365 cfdata, sizeof(*cfdata), err, p_fci_internal->pv)
366 != sizeof(*cfdata) ) {
367 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
368 return FALSE;
370 /* TODO error handling of err */
372 p_fci_internal->sizeFileCFDATA1 += sizeof(*cfdata);
374 /* add optional reserved area */
376 /* This allocation and freeing at each CFData block is a bit */
377 /* inefficent, but it's harder to forget about freeing the buffer :-). */
378 /* Reserved areas are used seldom besides that... */
379 if (cbReserveCFData!=0) {
380 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData))) {
381 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
382 return FALSE;
384 for(i=0;i<cbReserveCFData;) {
385 reserved[i++]='\0';
387 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
388 reserved, /* memory buffer */
389 cbReserveCFData, /* number of bytes to copy */
390 err, p_fci_internal->pv) != cbReserveCFData ) {
391 PFCI_FREE(hfci, reserved);
392 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
393 return FALSE;
395 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
397 p_fci_internal->sizeFileCFDATA1 += cbReserveCFData;
398 PFCI_FREE(hfci, reserved);
401 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
402 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
403 p_fci_internal->data_out, /* memory buffer */
404 cfdata->cbData, /* number of bytes to copy */
405 err, p_fci_internal->pv) != cfdata->cbData) {
406 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
407 return FALSE;
409 /* TODO error handling of err */
411 p_fci_internal->sizeFileCFDATA1 += cfdata->cbData;
413 /* reset the offset */
414 p_fci_internal->cdata_in = 0;
415 p_fci_internal->cCompressedBytesInFolder += cfdata->cbData;
417 /* report status with pfnfcis about uncompressed and compressed file data */
418 if( (*pfnfcis)(statusFile, cfdata->cbData, cfdata->cbUncomp,
419 p_fci_internal->pv) == -1) {
420 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
421 return FALSE;
424 ++(p_fci_internal->cDataBlocks);
426 return TRUE;
427 } /* end of fci_flush_data_block */
433 static cab_ULONG fci_get_checksum(const void *pv, UINT cb, CHECKSUM seed)
435 cab_ULONG csum;
436 cab_ULONG ul;
437 int cUlong;
438 const BYTE *pb;
440 csum = seed;
441 cUlong = cb / 4;
442 pb = pv;
444 while (cUlong-- > 0) {
445 ul = *pb++;
446 ul |= (((cab_ULONG)(*pb++)) << 8);
447 ul |= (((cab_ULONG)(*pb++)) << 16);
448 ul |= (((cab_ULONG)(*pb++)) << 24);
450 csum ^= ul;
453 ul = 0;
454 switch (cb % 4) {
455 case 3:
456 ul |= (((ULONG)(*pb++)) << 16);
457 case 2:
458 ul |= (((ULONG)(*pb++)) << 8);
459 case 1:
460 ul |= *pb++;
461 default:
462 break;
464 csum ^= ul;
466 return csum;
467 } /* end of fci_get_checksum */
471 static BOOL fci_flushfolder_copy_cfdata(HFCI hfci, char* buffer, UINT cbReserveCFData,
472 PFNFCISTATUS pfnfcis, int* err, int handleCFDATA1new,
473 cab_ULONG* psizeFileCFDATA1new, cab_ULONG* payload)
475 cab_ULONG read_result;
476 CFDATA* pcfdata=(CFDATA*)buffer;
477 BOOL split_block=FALSE;
478 cab_UWORD savedUncomp=0;
479 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
481 *payload=0;
483 /* while not all CFDATAs have been copied do */
484 while(!FALSE) {
485 if( p_fci_internal->fNextCab ) {
486 if( split_block ) {
487 /* internal error should never happen */
488 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
489 return FALSE;
492 /* REUSE the variable read_result */
493 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
494 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
495 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
496 read_result=4;
497 } else {
498 read_result=0;
500 if (p_fci_internal->fPrevCab) {
501 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
502 strlen(p_fci_internal->szPrevDisk)+1;
504 /* No more CFDATA fits into the cabinet under construction */
505 /* So don't try to store more data into it */
506 if( p_fci_internal->fNextCab &&
507 (p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData +
508 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
509 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
510 sizeof(CFHEADER) +
511 read_result +
512 p_fci_internal->oldCCAB.cbReserveCFHeader +
513 sizeof(CFFOLDER) +
514 p_fci_internal->oldCCAB.cbReserveCFFolder +
515 strlen(p_fci_internal->pccab->szCab)+1 +
516 strlen(p_fci_internal->pccab->szDisk)+1
517 )) {
518 /* This may never be run for the first time the while loop is entered.
519 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
520 split_block=TRUE; /* In this case split_block is abused to store */
521 /* the complete data block into the next cabinet and not into the */
522 /* current one. Originally split_block is the indicator that a */
523 /* data block has been splitted across different cabinets. */
524 } else {
526 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
527 read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/*file handle*/
528 buffer, /* memory buffer */
529 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
530 err, p_fci_internal->pv);
531 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
532 if (read_result==0) break; /* ALL DATA has been copied */
533 /* read error */
534 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
535 return FALSE;
537 /* TODO error handling of err */
539 /* REUSE buffer p_fci_internal->data_out !!! */
540 /* read data from p_fci_internal->handleCFDATA1 to */
541 /* p_fci_internal->data_out */
542 if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
543 p_fci_internal->data_out /* memory buffer */,
544 pcfdata->cbData /* number of bytes to copy */,
545 err, p_fci_internal->pv) != pcfdata->cbData ) {
546 /* read error */
547 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
548 return FALSE;
550 /* TODO error handling of err */
552 /* if cabinet size is too large */
554 /* REUSE the variable read_result */
555 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
556 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
557 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
558 read_result=4;
559 } else {
560 read_result=0;
562 if (p_fci_internal->fPrevCab) {
563 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
564 strlen(p_fci_internal->szPrevDisk)+1;
567 /* Is cabinet with new CFDATA too large? Then data block has to be split */
568 if( p_fci_internal->fNextCab &&
569 (p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData +
570 pcfdata->cbData +
571 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
572 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
573 sizeof(CFHEADER) +
574 read_result +
575 p_fci_internal->oldCCAB.cbReserveCFHeader +
576 sizeof(CFFOLDER) + /* size of new CFFolder entry */
577 p_fci_internal->oldCCAB.cbReserveCFFolder +
578 strlen(p_fci_internal->pccab->szCab)+1 + /* name of next cabinet */
579 strlen(p_fci_internal->pccab->szDisk)+1 /* name of next disk */
580 )) {
581 /* REUSE read_result to save the size of the compressed data */
582 read_result=pcfdata->cbData;
583 /* Modify the size of the compressed data to store only a part of the */
584 /* data block into the current cabinet. This is done to prevent */
585 /* that the maximum cabinet size will be exceeded. The remainder */
586 /* will be stored into the next following cabinet. */
588 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
589 /* Substract everything except the size of the block of data */
590 /* to get it's actual size */
591 pcfdata->cbData = p_fci_internal->oldCCAB.cb - (
592 sizeof(CFDATA) + cbReserveCFData +
593 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
594 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
595 sizeof(CFHEADER) +
596 p_fci_internal->oldCCAB.cbReserveCFHeader +
597 sizeof(CFFOLDER) + /* set size of new CFFolder entry */
598 p_fci_internal->oldCCAB.cbReserveCFFolder );
599 /* substract the size of special header fields */
600 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
601 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
602 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
603 pcfdata->cbData-=4;
605 if (p_fci_internal->fPrevCab) {
606 pcfdata->cbData-=strlen(p_fci_internal->szPrevCab)+1 +
607 strlen(p_fci_internal->szPrevDisk)+1;
609 pcfdata->cbData-=strlen(p_fci_internal->pccab->szCab)+1 +
610 strlen(p_fci_internal->pccab->szDisk)+1;
612 savedUncomp = pcfdata->cbUncomp;
613 pcfdata->cbUncomp = 0; /* on splitted blocks of data this is zero */
615 /* if split_block==TRUE then the above while loop won't */
616 /* be executed again */
617 split_block=TRUE; /* split_block is the indicator that */
618 /* a data block has been splitted across */
619 /* diffentent cabinets.*/
622 /* This should never happen !!! */
623 if (pcfdata->cbData==0) {
624 /* set error */
625 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
626 return FALSE;
629 /* set little endian */
630 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
631 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
633 /* get checksum and write to cfdata.csum */
634 pcfdata->csum = fci_get_checksum( &(pcfdata->cbData),
635 sizeof(CFDATA)+cbReserveCFData -
636 sizeof(pcfdata->csum), fci_get_checksum( p_fci_internal->data_out, /*buffer*/
637 pcfdata->cbData, 0 ) );
639 /* set little endian */
640 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
642 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
643 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
644 buffer, /* memory buffer */
645 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
646 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
647 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
648 return FALSE;
650 /* TODO error handling of err */
652 p_fci_internal->sizeFileCFDATA2 += sizeof(CFDATA)+cbReserveCFData;
654 /* reset little endian */
655 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
656 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
657 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
659 /* write compressed data into p_fci_internal->handleCFDATA2 */
660 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
661 p_fci_internal->data_out, /* memory buffer */
662 pcfdata->cbData, /* number of bytes to copy */
663 err, p_fci_internal->pv) != pcfdata->cbData) {
664 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
665 return FALSE;
667 /* TODO error handling of err */
669 p_fci_internal->sizeFileCFDATA2 += pcfdata->cbData;
670 ++(p_fci_internal->cDataBlocks);
671 p_fci_internal->statusFolderCopied += pcfdata->cbData;
672 (*payload)+=pcfdata->cbUncomp;
673 /* if cabinet size too large and data has been split */
674 /* write the remainder of the data block to the new CFDATA1 file */
675 if( split_block ) { /* This does not include the */
676 /* abused one (just search for "abused" )*/
677 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
678 if (p_fci_internal->fNextCab==FALSE ) {
679 /* internal error */
680 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
681 return FALSE;
684 /* set cbData to the size of the remainder of the data block */
685 pcfdata->cbData = read_result - pcfdata->cbData;
686 /*recover former value of cfdata.cbData; read_result will be the offset*/
687 read_result -= pcfdata->cbData;
688 pcfdata->cbUncomp = savedUncomp;
690 /* reset checksum, it will be computed later */
691 pcfdata->csum=0;
693 /* write cfdata WITHOUT checksum to handleCFDATA1new */
694 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
695 buffer, /* memory buffer */
696 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
697 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
698 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
699 return FALSE;
701 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
703 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
705 /* write compressed data into handleCFDATA1new */
706 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
707 p_fci_internal->data_out + read_result, /* memory buffer + offset */
708 /* to last part of split data */
709 pcfdata->cbData, /* number of bytes to copy */
710 err, p_fci_internal->pv) != pcfdata->cbData) {
711 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
712 return FALSE;
714 /* TODO error handling of err */
716 p_fci_internal->statusFolderCopied += pcfdata->cbData;
718 *psizeFileCFDATA1new += pcfdata->cbData;
719 /* the two blocks of the split data block have been written */
720 /* don't reset split_data yet, because it is still needed see below */
723 /* report status with pfnfcis about copied size of folder */
724 if( (*pfnfcis)(statusFolder,
725 p_fci_internal->statusFolderCopied, /*cfdata.cbData(+previous ones)*/
726 p_fci_internal->statusFolderTotal, /* total folder size */
727 p_fci_internal->pv) == -1) {
728 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
729 return FALSE;
733 /* if cabinet size too large */
734 /* write the remaining data blocks to the new CFDATA1 file */
735 if ( split_block ) { /* This does include the */
736 /* abused one (just search for "abused" )*/
737 if (p_fci_internal->fNextCab==FALSE ) {
738 /* internal error */
739 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
740 return FALSE;
742 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
743 while(!FALSE) {
744 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
745 read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/* handle */
746 buffer, /* memory buffer */
747 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
748 err, p_fci_internal->pv);
749 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
750 if (read_result==0) break; /* ALL DATA has been copied */
751 /* read error */
752 fci_set_error(FCIERR_NONE, ERROR_READ_FAULT, TRUE );
753 return FALSE;
755 /* TODO error handling of err */
757 /* REUSE buffer p_fci_internal->data_out !!! */
758 /* read data from p_fci_internal->handleCFDATA1 to */
759 /* p_fci_internal->data_out */
760 if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
761 p_fci_internal->data_out /* memory buffer */,
762 pcfdata->cbData /* number of bytes to copy */,
763 err, p_fci_internal->pv) != pcfdata->cbData ) {
764 /* read error */
765 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE);
766 return FALSE;
768 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
770 /* write cfdata with checksum to handleCFDATA1new */
771 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
772 buffer, /* memory buffer */
773 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
774 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
775 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
776 return FALSE;
778 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
780 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
782 /* write compressed data into handleCFDATA1new */
783 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
784 p_fci_internal->data_out, /* memory buffer */
785 pcfdata->cbData, /* number of bytes to copy */
786 err, p_fci_internal->pv) != pcfdata->cbData) {
787 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
788 return FALSE;
790 /* TODO error handling of err */
792 *psizeFileCFDATA1new += pcfdata->cbData;
793 p_fci_internal->statusFolderCopied += pcfdata->cbData;
795 /* report status with pfnfcis about copied size of folder */
796 if( (*pfnfcis)(statusFolder,
797 p_fci_internal->statusFolderCopied,/*cfdata.cbData(+revious ones)*/
798 p_fci_internal->statusFolderTotal, /* total folder size */
799 p_fci_internal->pv) == -1) {
800 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
801 return FALSE;
804 } /* end of WHILE */
805 break; /* jump out of the next while loop */
806 } /* end of if( split_data ) */
807 } /* end of WHILE */
808 return TRUE;
809 } /* end of fci_flushfolder_copy_cfdata */
815 static BOOL fci_flushfolder_copy_cffolder(HFCI hfci, int* err, UINT cbReserveCFFolder,
816 cab_ULONG sizeFileCFDATA2old)
818 CFFOLDER cffolder;
819 UINT i;
820 char* reserved;
821 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
823 /* absolute offset cannot be set yet, because the size of cabinet header, */
824 /* the number of CFFOLDERs and the number of CFFILEs may change. */
825 /* Instead the size of all previous data blocks will be stored and */
826 /* the remainder of the offset will be added when the cabinet will be */
827 /* flushed to disk. */
828 /* This is exactly the way the original CABINET.DLL works!!! */
829 cffolder.coffCabStart=sizeFileCFDATA2old;
831 /* set the number of this folder's CFDATA sections */
832 cffolder.cCFData=p_fci_internal->cDataBlocks;
833 /* TODO set compression type */
834 cffolder.typeCompress = tcompTYPE_NONE;
836 /* write cffolder to p_fci_internal->handleCFFOLDER */
837 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
838 &cffolder, /* memory buffer */
839 sizeof(cffolder), /* number of bytes to copy */
840 err, p_fci_internal->pv) != sizeof(cffolder) ) {
841 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
842 return FALSE;
844 /* TODO error handling of err */
846 p_fci_internal->sizeFileCFFOLDER += sizeof(cffolder);
848 /* add optional reserved area */
849 if (cbReserveCFFolder!=0) {
850 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFFolder))) {
851 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
852 return FALSE;
854 for(i=0;i<cbReserveCFFolder;) {
855 reserved[i++]='\0';
857 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
858 reserved, /* memory buffer */
859 cbReserveCFFolder, /* number of bytes to copy */
860 err, p_fci_internal->pv) != cbReserveCFFolder ) {
861 PFCI_FREE(hfci, reserved);
862 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
863 return FALSE;
865 /* TODO error handling of err */
867 p_fci_internal->sizeFileCFFOLDER += cbReserveCFFolder;
869 PFCI_FREE(hfci, reserved);
871 return TRUE;
872 } /* end of fci_flushfolder_copy_cffolder */
878 static BOOL fci_flushfolder_copy_cffile(HFCI hfci, int* err, int handleCFFILE1new,
879 cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload)
881 CFFILE cffile;
882 cab_ULONG read_result;
883 cab_ULONG seek=0;
884 cab_ULONG sizeOfFiles=0, sizeOfFilesPrev;
885 BOOL may_be_prev=TRUE;
886 cab_ULONG cbFileRemainer=0;
887 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
888 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
889 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,0,SEEK_SET,err,
890 p_fci_internal->pv) !=0 ) {
891 /* wrong return value */
892 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
893 return FALSE;
895 /* TODO error handling of err */
897 /* while not all CFFILE structures have been copied do */
898 while(!FALSE) {
899 /* REUSE the variable read_result */
900 /* read data from p_fci_internal->handleCFFILE1 to cffile */
901 read_result = PFCI_READ(hfci,p_fci_internal->handleCFFILE1/* file handle */,
902 &cffile, /* memory buffer */
903 sizeof(cffile), /* number of bytes to copy */
904 err, p_fci_internal->pv);
905 if( read_result != sizeof(cffile) ) {
906 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
907 /* read error */
908 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
909 return FALSE;
911 /* TODO error handling of err */
913 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
914 /* position. I don't know why so I'll just omit it */
916 /* read the filename from p_fci_internal->handleCFFILE1 */
917 /* REUSE the variable read_result AGAIN */
918 /* REUSE the memory buffer PFCI(hfci)->data_out */
919 if( PFCI_READ(hfci, p_fci_internal->handleCFFILE1 /*file handle*/,
920 p_fci_internal->data_out, /* memory buffer */
921 CB_MAX_FILENAME, /* number of bytes to copy */
922 err, p_fci_internal->pv) <2) {
923 /* read error */
924 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
925 return FALSE;
927 /* TODO maybe other checks of read_result */
928 /* TODO error handling of err */
930 /* safety */
931 if( strlen(p_fci_internal->data_out)>=CB_MAX_FILENAME ) {
932 /* set error code internal error */
933 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
934 return FALSE;
937 seek+=sizeof(cffile) + strlen(p_fci_internal->data_out)+1;
939 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
940 /* i.e. seek to the next CFFILE area */
941 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,
942 seek, /* seek position*/
943 SEEK_SET ,err,
944 p_fci_internal->pv)
945 != seek) {
946 /* wrong return value */
947 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
948 return FALSE;
950 /* TODO error handling of err */
952 /* fnfilfnfildest: placed file on cabinet */
953 if (p_fci_internal->fNextCab ||
954 p_fci_internal->fGetNextCabInVain) {
955 PFCI_FILEPLACED( hfci, &(p_fci_internal->oldCCAB),
956 p_fci_internal->data_out, /* the file name*/
957 cffile.cbFile, /* file size */
958 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
959 p_fci_internal->pv
961 } else {
962 PFCI_FILEPLACED( hfci, p_fci_internal->pccab,
963 p_fci_internal->data_out, /* the file name*/
964 cffile.cbFile, /* file size */
965 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
966 p_fci_internal->pv
970 /* Check special iFolder values */
971 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
972 p_fci_internal->fPrevCab==FALSE ) {
973 /* THIS MAY NEVER HAPPEN */
974 /* set error code */
975 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
976 return FALSE;
978 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
979 cffile.iFolder==cffileCONTINUED_TO_NEXT ) {
980 /* THIS MAY NEVER HAPPEN */
981 /* set error code */
982 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
983 return FALSE;
985 if( may_be_prev && cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
986 may_be_prev=FALSE;
988 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && may_be_prev==FALSE ) {
989 /* THIS MAY NEVER HAPPEN */
990 /* set error code */
991 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
992 return FALSE;
994 if( cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
995 may_be_prev=FALSE;
998 sizeOfFilesPrev=sizeOfFiles;
999 /* Set complete size of all processed files */
1000 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
1001 p_fci_internal->cbFileRemainer!=0
1003 sizeOfFiles+=p_fci_internal->cbFileRemainer;
1004 p_fci_internal->cbFileRemainer=0;
1005 } else {
1006 sizeOfFiles+=cffile.cbFile;
1009 /* Check if spanned file fits into this cabinet folder */
1010 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && sizeOfFiles>payload ) {
1011 cffile.iFolder=cffileCONTINUED_PREV_AND_NEXT;
1012 } else
1014 /* Check if file doesn't fit into this cabinet folder */
1015 if( sizeOfFiles>payload ) {
1016 cffile.iFolder=cffileCONTINUED_TO_NEXT;
1019 /* set little endian */
1020 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1021 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1022 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1023 cffile.date=fci_endian_uword(cffile.date);
1024 cffile.time=fci_endian_uword(cffile.time);
1025 cffile.attribs=fci_endian_uword(cffile.attribs);
1027 /* write cffile to p_fci_internal->handleCFFILE2 */
1028 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */
1029 &cffile, /* memory buffer */
1030 sizeof(cffile), /* number of bytes to copy */
1031 err, p_fci_internal->pv) != sizeof(cffile) ) {
1032 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1033 return FALSE;
1035 /* TODO error handling of err */
1037 p_fci_internal->sizeFileCFFILE2 += sizeof(cffile);
1039 /* reset little endian */
1040 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1041 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1042 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1043 cffile.date=fci_endian_uword(cffile.date);
1044 cffile.time=fci_endian_uword(cffile.time);
1045 cffile.attribs=fci_endian_uword(cffile.attribs);
1047 /* write file name to p_fci_internal->handleCFFILE2 */
1048 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */
1049 p_fci_internal->data_out, /* memory buffer */
1050 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1051 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1052 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1053 return FALSE;
1055 /* TODO error handling of err */
1057 p_fci_internal->sizeFileCFFILE2 += strlen(p_fci_internal->data_out)+1;
1059 /* cFiles is used to count all files of a cabinet */
1060 ++(p_fci_internal->cFiles);
1062 /* This is only true for files which will be written into the */
1063 /* next cabinet of the spanning folder */
1064 if( sizeOfFiles>payload ) {
1066 /* Files which data will be partially written into the current cabinet */
1067 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
1068 cffile.iFolder==cffileCONTINUED_TO_NEXT
1070 if( sizeOfFilesPrev<=payload ) {
1071 /* The size of the uncompressed, data of a spanning file in a */
1072 /* spanning data */
1073 cbFileRemainer=sizeOfFiles-payload;
1075 cffile.iFolder=cffileCONTINUED_FROM_PREV;
1076 } else {
1077 cffile.iFolder=0;
1080 /* write cffile into handleCFFILE1new */
1081 if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */
1082 &cffile, /* memory buffer */
1083 sizeof(cffile), /* number of bytes to copy */
1084 err, p_fci_internal->pv) != sizeof(cffile) ) {
1085 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1086 return FALSE;
1088 /* TODO error handling of err */
1090 *psizeFileCFFILE1new += sizeof(cffile);
1091 /* write name of file into handleCFFILE1new */
1092 if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */
1093 p_fci_internal->data_out, /* memory buffer */
1094 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1095 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1096 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1097 return FALSE;
1099 /* TODO error handling of err */
1101 *psizeFileCFFILE1new += strlen(p_fci_internal->data_out)+1;
1104 } /* END OF while */
1105 p_fci_internal->cbFileRemainer=cbFileRemainer;
1106 return TRUE;
1107 } /* end of fci_flushfolder_copy_cffile */
1112 static BOOL fci_flush_folder(
1113 HFCI hfci,
1114 BOOL fGetNextCab,
1115 PFNFCIGETNEXTCABINET pfnfcignc,
1116 PFNFCISTATUS pfnfcis)
1118 int err;
1119 int handleCFDATA1new; /* handle for new temp file */
1120 char szFileNameCFDATA1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1121 int handleCFFILE1new; /* handle for new temp file */
1122 char szFileNameCFFILE1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1123 UINT cbReserveCFData, cbReserveCFFolder;
1124 char* reserved;
1125 cab_ULONG sizeFileCFDATA1new=0;
1126 cab_ULONG sizeFileCFFILE1new=0;
1127 cab_ULONG sizeFileCFDATA2old;
1128 cab_ULONG payload;
1129 cab_ULONG read_result;
1130 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
1132 /* test hfci */
1133 if (!REALLY_IS_FCI(hfci)) {
1134 SetLastError(ERROR_INVALID_HANDLE);
1135 return FALSE;
1138 if ((!pfnfcignc) || (!pfnfcis)) {
1139 fci_set_error( FCIERR_NONE, ERROR_BAD_ARGUMENTS, TRUE );
1140 return FALSE;
1143 if( p_fci_internal->fGetNextCabInVain &&
1144 p_fci_internal->fNextCab ){
1145 /* internal error */
1146 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1147 return FALSE;
1150 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1151 /* this function will return TRUE */
1152 if( p_fci_internal->sizeFileCFFILE1 == 0 ) {
1153 if ( p_fci_internal->sizeFileCFDATA1 != 0 ) {
1154 /* error handling */
1155 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1156 return FALSE;
1158 return TRUE;
1161 if (p_fci_internal->data_in==NULL || p_fci_internal->data_out==NULL ) {
1162 /* error handling */
1163 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1164 return FALSE;
1167 /* FCIFlushFolder has already been called... */
1168 if (p_fci_internal->fSplitFolder && p_fci_internal->sizeFileCFFILE2!=0) {
1169 return TRUE;
1172 /* This can be set already, because it makes only a difference */
1173 /* when the current function exits with return FALSE */
1174 p_fci_internal->fSplitFolder=FALSE;
1177 if( p_fci_internal->fGetNextCabInVain ||
1178 p_fci_internal->fNextCab ){
1179 cbReserveCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1180 cbReserveCFFolder = p_fci_internal->oldCCAB.cbReserveCFFolder;
1181 } else {
1182 cbReserveCFData = p_fci_internal->pccab->cbReserveCFData;
1183 cbReserveCFFolder = p_fci_internal->pccab->cbReserveCFFolder;
1186 /* START of COPY */
1187 /* if there is data in p_fci_internal->data_in */
1188 if (p_fci_internal->cdata_in!=0) {
1190 if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;
1193 /* reset to get the number of data blocks of this folder which are */
1194 /* actually in this cabinet ( at least partially ) */
1195 p_fci_internal->cDataBlocks=0;
1197 if ( p_fci_internal->fNextCab ||
1198 p_fci_internal->fGetNextCabInVain ) {
1199 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader+
1200 p_fci_internal->oldCCAB.cbReserveCFFolder;
1201 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1202 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1203 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1204 read_result+=4;
1206 } else {
1207 read_result= p_fci_internal->pccab->cbReserveCFHeader+
1208 p_fci_internal->pccab->cbReserveCFFolder;
1209 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1210 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1211 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1212 read_result+=4;
1215 if (p_fci_internal->fPrevCab) {
1216 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1217 strlen(p_fci_internal->szPrevDisk)+1;
1219 if (p_fci_internal->fNextCab) {
1220 read_result+=strlen(p_fci_internal->pccab->szCab)+1 +
1221 strlen(p_fci_internal->pccab->szDisk)+1;
1224 p_fci_internal->statusFolderTotal = sizeof(CFHEADER)+read_result+
1225 sizeof(CFFOLDER) + p_fci_internal->sizeFileCFFILE2+
1226 p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1+
1227 p_fci_internal->sizeFileCFDATA1 + p_fci_internal->sizeFileCFFOLDER;
1228 p_fci_internal->statusFolderCopied = 0;
1230 /* report status with pfnfcis about copied size of folder */
1231 if( (*pfnfcis)(statusFolder, p_fci_internal->statusFolderCopied,
1232 p_fci_internal->statusFolderTotal, /* TODO total folder size */
1233 p_fci_internal->pv) == -1) {
1234 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
1235 return FALSE;
1238 /* get a new temp file */
1239 if(!PFCI_GETTEMPFILE(hfci,szFileNameCFDATA1new,CB_MAX_FILENAME)) {
1240 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1241 return FALSE;
1243 /* safety */
1244 if ( strlen(szFileNameCFDATA1new) >= CB_MAX_FILENAME ) {
1245 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1246 return FALSE;
1248 handleCFDATA1new = PFCI_OPEN(hfci,szFileNameCFDATA1new,34050,384,&err,
1249 p_fci_internal->pv);
1250 if(handleCFDATA1new==0){
1251 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
1252 return FALSE;
1254 /* TODO error handling of err */
1258 /* get a new temp file */
1259 if(!PFCI_GETTEMPFILE(hfci,szFileNameCFFILE1new,CB_MAX_FILENAME)) {
1260 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1261 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1262 /* TODO error handling of err */
1263 return FALSE;
1265 /* safety */
1266 if ( strlen(szFileNameCFFILE1new) >= CB_MAX_FILENAME ) {
1267 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1268 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1269 /* TODO error handling of err */
1270 return FALSE;
1272 handleCFFILE1new = PFCI_OPEN(hfci,szFileNameCFFILE1new,34050,384,&err,
1273 p_fci_internal->pv);
1274 if(handleCFFILE1new==0){
1275 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
1276 return FALSE;
1278 /* TODO error handling of err */
1280 /* USE the variable read_result */
1281 if ( p_fci_internal->fNextCab ||
1282 p_fci_internal->fGetNextCabInVain ) {
1283 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader;
1284 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1285 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1286 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1287 read_result+=4;
1289 } else {
1290 read_result= p_fci_internal->pccab->cbReserveCFHeader;
1291 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1292 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1293 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1294 read_result+=4;
1297 if (p_fci_internal->fPrevCab) {
1298 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1299 strlen(p_fci_internal->szPrevDisk)+1;
1301 read_result+= sizeof(CFHEADER) + p_fci_internal->sizeFileCFDATA2 +
1302 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER;
1304 if(p_fci_internal->sizeFileCFFILE1!=0) {
1305 read_result+= sizeof(CFFOLDER)+p_fci_internal->pccab->cbReserveCFFolder;
1308 /* Check if multiple cabinets have to be created. */
1310 /* Might be too much data for the maximum allowed cabinet size.*/
1311 /* When any further data will be added later, it might not */
1312 /* be possible to flush the cabinet, because there might */
1313 /* not be enough space to store the name of the following */
1314 /* cabinet and name of the corresponding disk. */
1315 /* So take care of this and get the name of the next cabinet */
1316 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1317 p_fci_internal->fNextCab==FALSE &&
1320 p_fci_internal->pccab->cb < read_result +
1321 p_fci_internal->sizeFileCFDATA1 +
1322 p_fci_internal->sizeFileCFFILE1 +
1323 CB_MAX_CABINET_NAME + /* next cabinet name */
1324 CB_MAX_DISK_NAME /* next disk name */
1325 ) || fGetNextCab
1328 /* save CCAB */
1329 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
1330 /* increment cabinet index */
1331 ++(p_fci_internal->pccab->iCab);
1332 /* get name of next cabinet */
1333 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
1334 if (!(*pfnfcignc)(p_fci_internal->pccab,
1335 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
1336 p_fci_internal->pv)) {
1337 /* error handling */
1338 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1339 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1340 /* TODO error handling of err */
1341 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1342 /* TODO error handling of err */
1343 return FALSE;
1346 /* Skip a few lines of code. This is caught by the next if. */
1347 p_fci_internal->fGetNextCabInVain=TRUE;
1350 /* too much data for cabinet */
1351 if( (p_fci_internal->fGetNextCabInVain ||
1352 p_fci_internal->fNextCab ) &&
1355 p_fci_internal->oldCCAB.cb < read_result +
1356 p_fci_internal->sizeFileCFDATA1 +
1357 p_fci_internal->sizeFileCFFILE1 +
1358 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1359 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1360 ) || fGetNextCab
1363 p_fci_internal->fGetNextCabInVain=FALSE;
1364 p_fci_internal->fNextCab=TRUE;
1366 /* return FALSE if there is not enough space left*/
1367 /* this should never happen */
1368 if (p_fci_internal->oldCCAB.cb <=
1369 p_fci_internal->sizeFileCFFILE1 +
1370 read_result +
1371 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1372 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1375 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1376 /* TODO error handling of err */
1377 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1378 /* TODO error handling of err */
1380 /* close and delete p_fci_internal->handleCFFILE1 */
1381 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1382 /* TODO error handling of err */
1383 PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);
1384 /* TODO error handling of err */
1386 return FALSE;
1389 /* the folder will be split across cabinets */
1390 p_fci_internal->fSplitFolder=TRUE;
1392 } else {
1393 /* this should never happen */
1394 if (p_fci_internal->fNextCab) {
1395 /* internal error */
1396 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1397 return FALSE;
1401 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1402 if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA1,0,SEEK_SET,&err,
1403 p_fci_internal->pv) !=0 ) {
1404 /* wrong return value */
1405 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
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 */
1410 return FALSE;
1412 /* TODO error handling of err */
1414 /* save size of file CFDATA2 - required for the folder's offset to data */
1415 sizeFileCFDATA2old = p_fci_internal->sizeFileCFDATA2;
1417 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData+sizeof(CFDATA)))) {
1418 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1419 PFCI_CLOSE(hfci,handleCFDATA1new,&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 return FALSE;
1426 if(!fci_flushfolder_copy_cfdata(hfci, reserved, cbReserveCFData, pfnfcis, &err,
1427 handleCFDATA1new, &sizeFileCFDATA1new, &payload
1428 )) {
1429 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1430 /* TODO error handling of err */
1431 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1432 /* TODO error handling of err */
1433 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1434 /* TODO error handling of err */
1435 PFCI_FREE(hfci,reserved);
1436 return FALSE;
1439 PFCI_FREE(hfci,reserved);
1441 if(!fci_flushfolder_copy_cffolder(hfci, &err, cbReserveCFFolder,
1442 sizeFileCFDATA2old )) {
1443 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1444 /* TODO error handling of err */
1445 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1446 /* TODO error handling of err */
1447 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1448 /* TODO error handling of err */
1449 return FALSE;
1452 if(!fci_flushfolder_copy_cffile(hfci, &err, handleCFFILE1new,
1453 &sizeFileCFFILE1new, payload)) {
1454 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1455 /* TODO error handling of err */
1456 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1457 /* TODO error handling of err */
1458 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1459 /* TODO error handling of err */
1460 PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);
1461 /* TODO error handling of err */
1462 return FALSE;
1465 /* close and delete p_fci_internal->handleCFDATA1 */
1466 PFCI_CLOSE(hfci,p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
1467 /* TODO error handling of err */
1468 PFCI_DELETE(hfci,p_fci_internal->szFileNameCFDATA1,&err,p_fci_internal->pv);
1469 /* TODO error handling of err */
1471 /* put new CFDATA1 into hfci */
1472 memcpy(p_fci_internal->szFileNameCFDATA1,szFileNameCFDATA1new,
1473 CB_MAX_FILENAME);
1475 /* put CFDATA1 file handle */
1476 PFCI_INT(hfci)->handleCFDATA1 = handleCFDATA1new;
1477 /* set file size */
1478 PFCI_INT(hfci)->sizeFileCFDATA1 = sizeFileCFDATA1new;
1480 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1481 PFCI_CLOSE(hfci,p_fci_internal->handleCFFILE1,&err,PFCI_INT(hfci)->pv);
1482 /* TODO error handling of err */
1483 PFCI_DELETE(hfci,p_fci_internal->szFileNameCFFILE1,&err,p_fci_internal->pv);
1484 /* TODO error handling of err */
1486 /* put new CFFILE1 into hfci */
1487 memcpy(p_fci_internal->szFileNameCFFILE1,szFileNameCFFILE1new,
1488 CB_MAX_FILENAME);
1490 /* put CFFILE1 file handle */
1491 p_fci_internal->handleCFFILE1 = handleCFFILE1new;
1492 /* set file size */
1493 p_fci_internal->sizeFileCFFILE1 = sizeFileCFFILE1new;
1495 ++(p_fci_internal->cFolders);
1497 /* reset CFFolder specific information */
1498 p_fci_internal->cDataBlocks=0;
1499 p_fci_internal->cCompressedBytesInFolder=0;
1501 return TRUE;
1502 } /* end of fci_flush_folder */
1507 static BOOL fci_flush_cabinet(
1508 HFCI hfci,
1509 BOOL fGetNextCab,
1510 PFNFCIGETNEXTCABINET pfnfcignc,
1511 PFNFCISTATUS pfnfcis)
1513 int err;
1514 CFHEADER cfheader;
1515 struct {
1516 cab_UWORD cbCFHeader;
1517 cab_UBYTE cbCFFolder;
1518 cab_UBYTE cbCFData;
1519 } cfreserved;
1520 CFFOLDER cffolder;
1521 cab_ULONG read_result=0;
1522 int handleCABINET; /* file handle for cabinet */
1523 char szFileNameCABINET[CB_MAX_CAB_PATH+CB_MAX_CABINET_NAME];/* name buffer */
1524 UINT cbReserveCFHeader, cbReserveCFFolder, i;
1525 char* reserved;
1526 BOOL returntrue=FALSE;
1527 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
1529 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1531 /* when FCIFlushCabinet was or FCIAddFile hasn't been called */
1532 if( p_fci_internal->sizeFileCFFILE1==0 && fGetNextCab ) {
1533 returntrue=TRUE;
1536 if (!fci_flush_folder(hfci,fGetNextCab,pfnfcignc,pfnfcis)){
1537 /* TODO set error */
1538 return FALSE;
1541 if(returntrue) return TRUE;
1543 if ( (p_fci_internal->fSplitFolder && p_fci_internal->fNextCab==FALSE)||
1544 (p_fci_internal->sizeFileCFFOLDER==0 &&
1545 (p_fci_internal->sizeFileCFFILE1!=0 ||
1546 p_fci_internal->sizeFileCFFILE2!=0 )
1549 /* error */
1550 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1551 return FALSE;
1554 if( p_fci_internal->fNextCab ||
1555 p_fci_internal->fGetNextCabInVain ) {
1556 cbReserveCFFolder=p_fci_internal->oldCCAB.cbReserveCFFolder;
1557 cbReserveCFHeader=p_fci_internal->oldCCAB.cbReserveCFHeader;
1558 /* safety */
1559 if (strlen(p_fci_internal->oldCCAB.szCabPath)>=CB_MAX_CAB_PATH ||
1560 strlen(p_fci_internal->oldCCAB.szCab)>=CB_MAX_CABINET_NAME) {
1561 /* set error */
1562 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1563 return FALSE;
1565 /* get the full name of the cabinet */
1566 memcpy(szFileNameCABINET,p_fci_internal->oldCCAB.szCabPath,
1567 CB_MAX_CAB_PATH);
1568 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1569 p_fci_internal->oldCCAB.szCab, CB_MAX_CABINET_NAME);
1570 } else {
1571 cbReserveCFFolder=p_fci_internal->pccab->cbReserveCFFolder;
1572 cbReserveCFHeader=p_fci_internal->pccab->cbReserveCFHeader;
1573 /* safety */
1574 if (strlen(p_fci_internal->pccab->szCabPath)>=CB_MAX_CAB_PATH ||
1575 strlen(p_fci_internal->pccab->szCab)>=CB_MAX_CABINET_NAME) {
1576 /* set error */
1577 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1578 return FALSE;
1580 /* get the full name of the cabinet */
1581 memcpy(szFileNameCABINET,p_fci_internal->pccab->szCabPath,
1582 CB_MAX_CAB_PATH);
1583 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1584 p_fci_internal->pccab->szCab, CB_MAX_CABINET_NAME);
1587 memcpy(cfheader.signature,"!CAB",4);
1588 cfheader.reserved1=0;
1589 cfheader.cbCabinet= /* size of the cabinet file in bytes */
1590 sizeof(CFHEADER) +
1591 p_fci_internal->sizeFileCFFOLDER +
1592 p_fci_internal->sizeFileCFFILE2 +
1593 p_fci_internal->sizeFileCFDATA2;
1595 if (p_fci_internal->fPrevCab) {
1596 cfheader.cbCabinet+=strlen(p_fci_internal->szPrevCab)+1 +
1597 strlen(p_fci_internal->szPrevDisk)+1;
1599 if (p_fci_internal->fNextCab) {
1600 cfheader.cbCabinet+=strlen(p_fci_internal->pccab->szCab)+1 +
1601 strlen(p_fci_internal->pccab->szDisk)+1;
1603 if( p_fci_internal->fNextCab ||
1604 p_fci_internal->fGetNextCabInVain ) {
1605 cfheader.cbCabinet+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1606 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1607 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1608 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1609 cfheader.cbCabinet+=4;
1611 } else {
1612 cfheader.cbCabinet+=p_fci_internal->pccab->cbReserveCFHeader;
1613 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1614 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1615 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1616 cfheader.cbCabinet+=4;
1620 if( ( ( p_fci_internal->fNextCab ||
1621 p_fci_internal->fGetNextCabInVain ) &&
1622 cfheader.cbCabinet > p_fci_internal->oldCCAB.cb
1623 ) ||
1624 ( ( p_fci_internal->fNextCab==FALSE &&
1625 p_fci_internal->fGetNextCabInVain==FALSE ) &&
1626 cfheader.cbCabinet > p_fci_internal->pccab->cb
1630 fci_set_error( FCIERR_NONE, ERROR_MORE_DATA, TRUE );
1631 return FALSE;
1635 cfheader.reserved2=0;
1636 cfheader.coffFiles= /* offset to first CFFILE section */
1637 cfheader.cbCabinet - p_fci_internal->sizeFileCFFILE2 -
1638 p_fci_internal->sizeFileCFDATA2;
1640 cfheader.reserved3=0;
1641 cfheader.versionMinor=3;
1642 cfheader.versionMajor=1;
1643 /* number of CFFOLDER entries in the cabinet */
1644 cfheader.cFolders=p_fci_internal->cFolders;
1645 /* number of CFFILE entries in the cabinet */
1646 cfheader.cFiles=p_fci_internal->cFiles;
1647 cfheader.flags=0; /* 1=prev cab, 2=next cabinet, 4=reserved setions */
1649 if( p_fci_internal->fPrevCab ) {
1650 cfheader.flags = cfheadPREV_CABINET;
1653 if( p_fci_internal->fNextCab ) {
1654 cfheader.flags |= cfheadNEXT_CABINET;
1657 if( p_fci_internal->fNextCab ||
1658 p_fci_internal->fGetNextCabInVain ) {
1659 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1660 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1661 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1662 cfheader.flags |= cfheadRESERVE_PRESENT;
1664 cfheader.setID = p_fci_internal->oldCCAB.setID;
1665 cfheader.iCabinet = p_fci_internal->oldCCAB.iCab-1;
1666 } else {
1667 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1668 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1669 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1670 cfheader.flags |= cfheadRESERVE_PRESENT;
1672 cfheader.setID = p_fci_internal->pccab->setID;
1673 cfheader.iCabinet = p_fci_internal->pccab->iCab-1;
1676 /* create the cabinet */
1677 handleCABINET = PFCI_OPEN(hfci, szFileNameCABINET,
1678 33538, 384, &err, p_fci_internal->pv );
1679 if(handleCABINET==0){
1680 fci_set_error( FCIERR_CAB_FILE, ERROR_OPEN_FAILED, TRUE );
1681 return FALSE;
1683 /* TODO error checking of err */
1685 /* set little endian */
1686 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1687 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1688 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1689 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1690 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1691 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1692 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1693 cfheader.flags=fci_endian_uword(cfheader.flags);
1694 cfheader.setID=fci_endian_uword(cfheader.setID);
1695 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1697 /* write CFHEADER into cabinet file */
1698 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1699 &cfheader, /* memory buffer */
1700 sizeof(cfheader), /* number of bytes to copy */
1701 &err, p_fci_internal->pv) != sizeof(cfheader) ) {
1702 /* write error */
1703 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1704 return FALSE;
1706 /* TODO error handling of err */
1708 /* reset little endian */
1709 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1710 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1711 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1712 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1713 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1714 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1715 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1716 cfheader.flags=fci_endian_uword(cfheader.flags);
1717 cfheader.setID=fci_endian_uword(cfheader.setID);
1718 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1720 if( cfheader.flags & cfheadRESERVE_PRESENT ) {
1721 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1722 cfreserved.cbCFHeader = cbReserveCFHeader;
1723 cfreserved.cbCFFolder = cbReserveCFFolder;
1724 if( p_fci_internal->fNextCab ||
1725 p_fci_internal->fGetNextCabInVain ) {
1726 cfreserved.cbCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1727 } else {
1728 cfreserved.cbCFData = p_fci_internal->pccab->cbReserveCFData;
1731 /* set little endian */
1732 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1734 /* write reserved info into cabinet file */
1735 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1736 &cfreserved, /* memory buffer */
1737 sizeof(cfreserved), /* number of bytes to copy */
1738 &err, p_fci_internal->pv) != sizeof(cfreserved) ) {
1739 /* write error */
1740 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1741 return FALSE;
1743 /* TODO error handling of err */
1745 /* reset little endian */
1746 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1749 /* add optional reserved area */
1750 if (cbReserveCFHeader!=0) {
1751 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFHeader))) {
1752 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1753 return FALSE;
1755 for(i=0;i<cbReserveCFHeader;) {
1756 reserved[i++]='\0';
1758 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1759 reserved, /* memory buffer */
1760 cbReserveCFHeader, /* number of bytes to copy */
1761 &err, p_fci_internal->pv) != cbReserveCFHeader ) {
1762 PFCI_FREE(hfci, reserved);
1763 /* write error */
1764 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1765 return FALSE;
1767 /* TODO error handling of err */
1768 PFCI_FREE(hfci, reserved);
1771 if( cfheader.flags & cfheadPREV_CABINET ) {
1772 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1773 p_fci_internal->szPrevCab, /* memory buffer */
1774 strlen(p_fci_internal->szPrevCab)+1, /* number of bytes to copy */
1775 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevCab)+1 ) {
1776 /* write error */
1777 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1778 return FALSE;
1780 /* TODO error handling of err */
1782 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1783 p_fci_internal->szPrevDisk, /* memory buffer */
1784 strlen(p_fci_internal->szPrevDisk)+1, /* number of bytes to copy */
1785 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevDisk)+1 ) {
1786 /* write error */
1787 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1788 return FALSE;
1790 /* TODO error handling of err */
1793 if( cfheader.flags & cfheadNEXT_CABINET ) {
1794 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1795 p_fci_internal->pccab->szCab, /* memory buffer */
1796 strlen(p_fci_internal->pccab->szCab)+1, /* number of bytes to copy */
1797 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szCab)+1 ) {
1798 /* write error */
1799 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1800 return FALSE;
1802 /* TODO error handling of err */
1804 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1805 p_fci_internal->pccab->szDisk, /* memory buffer */
1806 strlen(p_fci_internal->pccab->szDisk)+1, /* number of bytes to copy */
1807 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szDisk)+1 ) {
1808 /* write error */
1809 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1810 return FALSE;
1812 /* TODO error handling of err */
1815 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1816 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFOLDER,
1817 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1818 /* wrong return value */
1819 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1820 return FALSE;
1822 /* TODO error handling of err */
1824 /* while not all CFFOLDER structures have been copied into the cabinet do */
1825 while(!FALSE) {
1826 /* use the variable read_result */
1827 /* read cffolder of p_fci_internal->handleCFFOLDER */
1828 read_result = PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* handle */
1829 &cffolder, /* memory buffer */
1830 sizeof(cffolder), /* number of bytes to copy */
1831 &err, p_fci_internal->pv);
1832 if( read_result != sizeof(cffolder) ) {
1833 if( read_result == 0 ) break;/*ALL CFFOLDER structures have been copied*/
1834 /* read error */
1835 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
1836 return FALSE;
1838 /* TODO error handling of err */
1840 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1841 cffolder.coffCabStart +=
1842 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
1843 sizeof(CFHEADER);
1844 if( p_fci_internal->fNextCab ||
1845 p_fci_internal->fGetNextCabInVain ) {
1846 cffolder.coffCabStart+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1847 } else {
1848 cffolder.coffCabStart+=p_fci_internal->pccab->cbReserveCFHeader;
1851 if (p_fci_internal->fPrevCab) {
1852 cffolder.coffCabStart += strlen(p_fci_internal->szPrevCab)+1 +
1853 strlen(p_fci_internal->szPrevDisk)+1;
1856 if (p_fci_internal->fNextCab) {
1857 cffolder.coffCabStart += strlen(p_fci_internal->oldCCAB.szCab)+1 +
1858 strlen(p_fci_internal->oldCCAB.szDisk)+1;
1861 if( p_fci_internal->fNextCab ||
1862 p_fci_internal->fGetNextCabInVain ) {
1863 cffolder.coffCabStart += p_fci_internal->oldCCAB.cbReserveCFHeader;
1864 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1865 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1866 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1867 cffolder.coffCabStart += 4;
1869 } else {
1870 cffolder.coffCabStart += p_fci_internal->pccab->cbReserveCFHeader;
1871 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1872 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1873 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1874 cffolder.coffCabStart += 4;
1878 /* set little endian */
1879 cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
1880 cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
1881 cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
1883 /* write cffolder to cabinet file */
1884 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1885 &cffolder, /* memory buffer */
1886 sizeof(cffolder), /* number of bytes to copy */
1887 &err, p_fci_internal->pv) != sizeof(cffolder) ) {
1888 /* write error */
1889 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1890 return FALSE;
1892 /* TODO error handling of err */
1894 /* reset little endian */
1895 cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
1896 cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
1897 cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
1899 /* add optional reserved area */
1901 /* This allocation and freeing at each CFFolder block is a bit */
1902 /* inefficent, but it's harder to forget about freeing the buffer :-). */
1903 /* Reserved areas are used seldom besides that... */
1904 if (cbReserveCFFolder!=0) {
1905 if(!(reserved = PFCI_ALLOC(hfci, cbReserveCFFolder))) {
1906 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1907 return FALSE;
1910 if( PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
1911 reserved, /* memory buffer */
1912 cbReserveCFFolder, /* number of bytes to copy */
1913 &err, p_fci_internal->pv) != cbReserveCFFolder ) {
1914 PFCI_FREE(hfci, reserved);
1915 /* read error */
1916 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
1917 return FALSE;
1919 /* TODO error handling of err */
1921 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1922 reserved, /* memory buffer */
1923 cbReserveCFFolder, /* number of bytes to copy */
1924 &err, p_fci_internal->pv) != cbReserveCFFolder ) {
1925 PFCI_FREE(hfci, reserved);
1926 /* write error */
1927 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1928 return FALSE;
1930 /* TODO error handling of err */
1932 PFCI_FREE(hfci, reserved);
1935 } /* END OF while */
1937 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1938 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE2,
1939 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1940 /* wrong return value */
1941 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1942 return FALSE;
1944 /* TODO error handling of err */
1946 /* while not all CFFILE structures have been copied to the cabinet do */
1947 while(!FALSE) {
1948 /* REUSE the variable read_result */
1949 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1950 /* read a block from p_fci_internal->handleCFFILE2 */
1951 read_result = PFCI_READ(hfci, p_fci_internal->handleCFFILE2 /* handle */,
1952 p_fci_internal->data_out, /* memory buffer */
1953 CB_MAX_CHUNK, /* number of bytes to copy */
1954 &err, p_fci_internal->pv);
1955 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
1956 /* TODO error handling of err */
1958 /* write the block to the cabinet file */
1959 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1960 p_fci_internal->data_out, /* memory buffer */
1961 read_result, /* number of bytes to copy */
1962 &err, p_fci_internal->pv) != read_result ) {
1963 /* write error */
1964 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1965 return FALSE;
1967 /* TODO error handling of err */
1969 if (p_fci_internal->fSplitFolder==FALSE) {
1970 p_fci_internal->statusFolderCopied = 0;
1971 /* TODO TEST THIS further */
1972 p_fci_internal->statusFolderTotal = p_fci_internal->sizeFileCFDATA2+
1973 p_fci_internal->sizeFileCFFILE2;
1975 p_fci_internal->statusFolderCopied += read_result;
1977 /* report status with pfnfcis about copied size of folder */
1978 if( (*pfnfcis)(statusFolder,
1979 p_fci_internal->statusFolderCopied, /* length of copied blocks */
1980 p_fci_internal->statusFolderTotal, /* total size of folder */
1981 p_fci_internal->pv) == -1) {
1982 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
1983 return FALSE;
1986 } /* END OF while */
1988 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1989 if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA2,
1990 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1991 /* wrong return value */
1992 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1993 return FALSE;
1995 /* TODO error handling of err */
1997 /* reset the number of folders for the next cabinet */
1998 p_fci_internal->cFolders=0;
1999 /* reset the number of files for the next cabinet */
2000 p_fci_internal->cFiles=0;
2002 /* while not all CFDATA structures have been copied to the cabinet do */
2003 while(!FALSE) {
2004 /* REUSE the variable read_result AGAIN */
2005 /* REUSE the buffer p_fci_internal->data_out AGAIN */
2006 /* read a block from p_fci_internal->handleCFDATA2 */
2007 read_result = PFCI_READ(hfci, p_fci_internal->handleCFDATA2 /* handle */,
2008 p_fci_internal->data_out, /* memory buffer */
2009 CB_MAX_CHUNK, /* number of bytes to copy */
2010 &err, p_fci_internal->pv);
2011 if( read_result == 0 ) break; /* ALL CFDATA structures have been copied */
2012 /* TODO error handling of err */
2014 /* write the block to the cabinet file */
2015 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
2016 p_fci_internal->data_out, /* memory buffer */
2017 read_result, /* number of bytes to copy */
2018 &err, p_fci_internal->pv) != read_result ) {
2019 /* write error */
2020 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
2021 return FALSE;
2023 /* TODO error handling of err */
2025 p_fci_internal->statusFolderCopied += read_result;
2026 /* report status with pfnfcis about copied size of folder */
2027 if( (*pfnfcis)(statusFolder,
2028 p_fci_internal->statusFolderCopied, /* length of copied blocks */
2029 p_fci_internal->statusFolderTotal, /* total size of folder */
2030 p_fci_internal->pv) == -1) {
2031 /* set error code and abort */
2032 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
2033 return FALSE;
2035 } /* END OF while */
2037 /* set seek of the cabinet file to 0 */
2038 if( PFCI_SEEK(hfci, handleCABINET,
2039 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
2040 /* wrong return value */
2041 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
2042 return FALSE;
2044 /* TODO error handling of err */
2046 /* write the signature "MSCF" into the cabinet file */
2047 memcpy( cfheader.signature, "MSCF", 4 );
2048 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
2049 &cfheader, /* memory buffer */
2050 4, /* number of bytes to copy */
2051 &err, p_fci_internal->pv) != 4 ) {
2052 /* wrtie error */
2053 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
2054 return FALSE;
2056 /* TODO error handling of err */
2058 /* close the cabinet file */
2059 PFCI_CLOSE(hfci,handleCABINET,&err,p_fci_internal->pv);
2060 /* TODO error handling of err */
2063 /* COPIED FROM FCIDestroy */
2065 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2066 /* TODO error handling of err */
2067 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,
2068 p_fci_internal->pv);
2069 /* TODO error handling of err */
2070 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2071 /* TODO error handling of err */
2072 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,
2073 p_fci_internal->pv);
2074 /* TODO error handling of err */
2075 PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
2076 /* TODO error handling of err */
2077 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,
2078 p_fci_internal->pv);
2079 /* TODO error handling of err */
2081 /* END OF copied from FCIDestroy */
2083 /* get 3 temporary files and open them */
2084 /* write names and handles to hfci */
2087 p_fci_internal->sizeFileCFDATA2 = 0;
2088 p_fci_internal->sizeFileCFFILE2 = 0;
2089 p_fci_internal->sizeFileCFFOLDER = 0;
2091 /* COPIED FROM FCICreate */
2093 /* CFDATA with checksum and ready to be copied into cabinet */
2094 if( !PFCI_GETTEMPFILE(hfci, p_fci_internal->szFileNameCFDATA2,
2095 CB_MAX_FILENAME)) {
2096 /* error handling */
2097 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2098 return FALSE;
2100 /* safety */
2101 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
2102 /* set error code and abort */
2103 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2104 return FALSE;
2106 p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
2107 p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, p_fci_internal->pv);
2108 /* check handle */
2109 if(p_fci_internal->handleCFDATA2==0){
2110 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
2111 return FALSE;
2113 /* TODO error checking of err */
2115 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2116 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
2117 CB_MAX_FILENAME)) {
2118 /* error handling */
2119 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2120 return FALSE;
2122 /* safety */
2123 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
2124 /* set error code and abort */
2125 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2126 return FALSE;
2128 p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
2129 p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, p_fci_internal->pv);
2130 /* check handle */
2131 if(p_fci_internal->handleCFFILE2==0){
2132 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
2133 return FALSE;
2135 /* TODO error checking of err */
2137 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2138 if (!PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,CB_MAX_FILENAME)) {
2139 /* error handling */
2140 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2141 return FALSE;
2143 /* safety */
2144 if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
2145 /* set error code and abort */
2146 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2147 return FALSE;
2149 p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
2150 p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, p_fci_internal->pv);
2151 /* check handle */
2152 if(p_fci_internal->handleCFFOLDER==0){
2153 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
2154 return FALSE;
2156 /* TODO error checking of err */
2158 /* END OF copied from FCICreate */
2161 /* TODO close and delete new files when return FALSE */
2164 /* report status with pfnfcis about copied size of folder */
2165 (*pfnfcis)(statusCabinet,
2166 p_fci_internal->estimatedCabinetSize, /* estimated cabinet file size */
2167 cfheader.cbCabinet /* real cabinet file size */, p_fci_internal->pv);
2169 p_fci_internal->fPrevCab=TRUE;
2170 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2171 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2173 if (p_fci_internal->fNextCab) {
2174 p_fci_internal->fNextCab=FALSE;
2176 if (p_fci_internal->sizeFileCFFILE1==0 && p_fci_internal->sizeFileCFDATA1!=0) {
2177 /* THIS CAN NEVER HAPPEN */
2178 /* set error code */
2179 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2180 return FALSE;
2183 /* COPIED FROM FCIAddFile and modified */
2185 /* REUSE the variable read_result */
2186 if (p_fci_internal->fGetNextCabInVain) {
2187 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader;
2188 if(p_fci_internal->sizeFileCFFILE1!=0) {
2189 read_result+=p_fci_internal->oldCCAB.cbReserveCFFolder;
2191 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2192 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2193 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2194 read_result+=4;
2196 } else {
2197 read_result=p_fci_internal->pccab->cbReserveCFHeader;
2198 if(p_fci_internal->sizeFileCFFILE1!=0) {
2199 read_result+=p_fci_internal->pccab->cbReserveCFFolder;
2201 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2202 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2203 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2204 read_result+=4;
2207 if ( p_fci_internal->fPrevCab ) {
2208 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2209 strlen(p_fci_internal->szPrevDisk)+1;
2211 read_result+= p_fci_internal->sizeFileCFDATA1 +
2212 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2213 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2214 sizeof(CFHEADER) +
2215 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2217 if( p_fci_internal->fNewPrevious ) {
2218 memcpy(p_fci_internal->szPrevCab, p_fci_internal->oldCCAB.szCab,
2219 CB_MAX_CABINET_NAME);
2220 memcpy(p_fci_internal->szPrevDisk, p_fci_internal->oldCCAB.szDisk,
2221 CB_MAX_DISK_NAME);
2222 p_fci_internal->fNewPrevious=FALSE;
2225 /* too much data for the maximum size of a cabinet */
2226 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2227 p_fci_internal->pccab->cb < read_result ) {
2228 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2231 /* Might be too much data for the maximum size of a cabinet.*/
2232 /* When any further data will be added later, it might not */
2233 /* be possible to flush the cabinet, because there might */
2234 /* not be enough space to store the name of the following */
2235 /* cabinet and name of the corresponding disk. */
2236 /* So take care of this and get the name of the next cabinet */
2237 if (p_fci_internal->fGetNextCabInVain==FALSE && (
2238 p_fci_internal->pccab->cb < read_result +
2239 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2240 )) {
2241 /* save CCAB */
2242 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2243 /* increment cabinet index */
2244 ++(p_fci_internal->pccab->iCab);
2245 /* get name of next cabinet */
2246 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2247 if (!(*pfnfcignc)(p_fci_internal->pccab,
2248 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2249 p_fci_internal->pv)) {
2250 /* error handling */
2251 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2252 return FALSE;
2254 /* Skip a few lines of code. This is caught by the next if. */
2255 p_fci_internal->fGetNextCabInVain=TRUE;
2258 /* too much data for cabinet */
2259 if (p_fci_internal->fGetNextCabInVain && (
2260 p_fci_internal->oldCCAB.cb < read_result +
2261 strlen(p_fci_internal->oldCCAB.szCab)+1+
2262 strlen(p_fci_internal->oldCCAB.szDisk)+1
2263 )) {
2264 p_fci_internal->fGetNextCabInVain=FALSE;
2265 p_fci_internal->fNextCab=TRUE;
2266 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2269 /* if the FolderThreshold has been reached flush the folder automatically */
2270 if( p_fci_internal->fGetNextCabInVain ) {
2271 if( p_fci_internal->cCompressedBytesInFolder >=
2272 p_fci_internal->oldCCAB.cbFolderThresh) {
2273 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2275 } else {
2276 if( p_fci_internal->cCompressedBytesInFolder >=
2277 p_fci_internal->pccab->cbFolderThresh) {
2278 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2282 /* END OF COPIED FROM FCIAddFile and modified */
2284 if( p_fci_internal->sizeFileCFFILE1>0 ) {
2285 if( !FCIFlushFolder(hfci, pfnfcignc, pfnfcis) ) return FALSE;
2286 p_fci_internal->fNewPrevious=TRUE;
2288 } else {
2289 p_fci_internal->fNewPrevious=FALSE;
2290 if( p_fci_internal->sizeFileCFFILE1>0 || p_fci_internal->sizeFileCFDATA1) {
2291 /* THIS MAY NEVER HAPPEN */
2292 /* set error structures */
2293 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2294 return FALSE;
2298 return TRUE;
2299 } /* end of fci_flush_cabinet */
2305 /***********************************************************************
2306 * FCIAddFile (CABINET.11)
2308 * FCIAddFile adds a file to the to be created cabinet file
2310 * PARAMS
2311 * hfci [I] An HFCI from FCICreate
2312 * pszSourceFile [I] A pointer to a C string which contains the name and
2313 * location of the file which will be added to the cabinet
2314 * pszFileName [I] A pointer to a C string which contains the name under
2315 * which the file will be stored in the cabinet
2316 * fExecute [I] A boolean value which indicates if the file should be
2317 * executed after extraction of self extracting
2318 * executables
2319 * pfnfcignc [I] A pointer to a function which gets information about
2320 * the next cabinet
2321 * pfnfcis [IO] A pointer to a function which will report status
2322 * information about the compression process
2323 * pfnfcioi [I] A pointer to a function which reports file attributes
2324 * and time and date information
2325 * typeCompress [I] Compression type
2327 * RETURNS
2328 * On success, returns TRUE
2329 * On failure, returns FALSE
2331 * INCLUDES
2332 * fci.h
2335 BOOL __cdecl FCIAddFile(
2336 HFCI hfci,
2337 char *pszSourceFile,
2338 char *pszFileName,
2339 BOOL fExecute,
2340 PFNFCIGETNEXTCABINET pfnfcignc,
2341 PFNFCISTATUS pfnfcis,
2342 PFNFCIGETOPENINFO pfnfcigoi,
2343 TCOMP typeCompress)
2345 int err;
2346 CFFILE cffile;
2347 cab_ULONG read_result;
2348 int file_handle;
2349 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2351 /* test hfci */
2352 if (!REALLY_IS_FCI(hfci)) {
2353 SetLastError(ERROR_INVALID_HANDLE);
2354 return FALSE;
2357 if ((!pszSourceFile) || (!pszFileName) || (!pfnfcignc) || (!pfnfcis) ||
2358 (!pfnfcigoi) || strlen(pszFileName)>=CB_MAX_FILENAME) {
2359 fci_set_error( FCIERR_NONE, ERROR_BAD_ARGUMENTS, TRUE );
2360 return FALSE;
2363 /* TODO check if pszSourceFile??? */
2365 if(p_fci_internal->fGetNextCabInVain && p_fci_internal->fNextCab) {
2366 /* internal error */
2367 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2368 return FALSE;
2371 if(p_fci_internal->fNextCab) {
2372 /* internal error */
2373 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2374 return FALSE;
2377 cffile.cbFile=0; /* size of the to be added file*/
2378 /* offset of the uncompressed file in the folder */
2379 cffile.uoffFolderStart=p_fci_internal->cDataBlocks*CAB_BLOCKMAX + p_fci_internal->cdata_in;
2380 /* number of folder in the cabinet or special 0=first */
2381 cffile.iFolder = p_fci_internal->cFolders;
2383 /* allocation of memory */
2384 if (p_fci_internal->data_in==NULL) {
2385 if (p_fci_internal->cdata_in!=0) {
2386 /* error handling */
2387 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2388 return FALSE;
2390 if (p_fci_internal->data_out!=NULL) {
2391 /* error handling */
2392 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2393 return FALSE;
2395 if(!(p_fci_internal->data_in = (char*)PFCI_ALLOC(hfci,CB_MAX_CHUNK))) {
2396 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
2397 return FALSE;
2399 if (p_fci_internal->data_out==NULL) {
2400 if(!(p_fci_internal->data_out = PFCI_ALLOC(hfci, 2 * CB_MAX_CHUNK))){
2401 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
2402 return FALSE;
2407 if (p_fci_internal->data_out==NULL) {
2408 PFCI_FREE(hfci,p_fci_internal->data_in);
2409 /* error handling */
2410 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2411 return FALSE;
2414 /* get information about the file */
2415 file_handle=(*pfnfcigoi)(pszSourceFile, &(cffile.date), &(cffile.time),
2416 &(cffile.attribs), &err, p_fci_internal->pv);
2417 /* check file_handle */
2418 if(file_handle==0){
2419 fci_set_error( FCIERR_OPEN_SRC, ERROR_OPEN_FAILED, TRUE );
2421 /* TODO error handling of err */
2423 if (fExecute) { cffile.attribs |= _A_EXEC; }
2425 /* REUSE the variable read_result */
2426 if (p_fci_internal->fGetNextCabInVain) {
2427 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2428 p_fci_internal->oldCCAB.cbReserveCFFolder;
2429 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2430 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2431 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2432 read_result+=4;
2434 } else {
2435 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2436 p_fci_internal->pccab->cbReserveCFFolder;
2437 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2438 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2439 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2440 read_result+=4;
2443 if ( p_fci_internal->fPrevCab ) {
2444 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2445 strlen(p_fci_internal->szPrevDisk)+1;
2447 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2448 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2449 strlen(p_fci_internal->pccab->szDisk)+1;
2452 read_result+= sizeof(CFFILE) + strlen(pszFileName)+1 +
2453 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2454 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2455 sizeof(CFHEADER) +
2456 sizeof(CFFOLDER); /* size of new CFFolder entry */
2458 /* Might be too much data for the maximum size of a cabinet.*/
2459 /* When any further data will be added later, it might not */
2460 /* be possible to flush the cabinet, because there might */
2461 /* not be enough space to store the name of the following */
2462 /* cabinet and name of the corresponding disk. */
2463 /* So take care of this and get the name of the next cabinet */
2464 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2465 p_fci_internal->fNextCab==FALSE &&
2466 ( p_fci_internal->pccab->cb < read_result +
2467 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2470 /* save CCAB */
2471 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2472 /* increment cabinet index */
2473 ++(p_fci_internal->pccab->iCab);
2474 /* get name of next cabinet */
2475 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2476 if (!(*pfnfcignc)(p_fci_internal->pccab,
2477 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2478 p_fci_internal->pv)) {
2479 /* error handling */
2480 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2481 return FALSE;
2483 /* Skip a few lines of code. This is caught by the next if. */
2484 p_fci_internal->fGetNextCabInVain=TRUE;
2487 if( p_fci_internal->fGetNextCabInVain &&
2488 p_fci_internal->fNextCab
2490 /* THIS CAN NEVER HAPPEN */
2491 /* set error code */
2492 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2493 return FALSE;
2496 /* too much data for cabinet */
2497 if( p_fci_internal->fGetNextCabInVain &&
2499 p_fci_internal->oldCCAB.cb < read_result +
2500 strlen(p_fci_internal->pccab->szCab)+1+
2501 strlen(p_fci_internal->pccab->szDisk)+1
2502 )) {
2503 p_fci_internal->fGetNextCabInVain=FALSE;
2504 p_fci_internal->fNextCab=TRUE;
2505 if(!fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis)) return FALSE;
2508 if( p_fci_internal->fNextCab ) {
2509 /* THIS MAY NEVER HAPPEN */
2510 /* set error code */
2511 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2512 return FALSE;
2515 /* read the contents of the file blockwise */
2516 while (!FALSE) {
2517 if (p_fci_internal->cdata_in > CAB_BLOCKMAX) {
2518 /* internal error */
2519 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2520 return FALSE;
2523 read_result = PFCI_READ(hfci, file_handle /* file handle */,
2524 (p_fci_internal->data_in + p_fci_internal->cdata_in) /* memory buffer */,
2525 (CAB_BLOCKMAX - p_fci_internal->cdata_in) /* number of bytes to copy */,
2526 &err, p_fci_internal->pv);
2527 /* TODO error handling of err */
2529 if( read_result==0 ) break;
2531 /* increment the block size */
2532 p_fci_internal->cdata_in += read_result;
2534 /* increment the file size */
2535 cffile.cbFile += read_result;
2537 if ( p_fci_internal->cdata_in > CAB_BLOCKMAX ) {
2538 /* report internal error */
2539 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2540 return FALSE;
2542 /* write a whole block */
2543 if ( p_fci_internal->cdata_in == CAB_BLOCKMAX ) {
2545 if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;
2549 /* close the file from FCIAddFile */
2550 PFCI_CLOSE(hfci,file_handle,&err,p_fci_internal->pv);
2551 /* TODO error handling of err */
2553 /* write cffile to p_fci_internal->handleCFFILE1 */
2554 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */
2555 &cffile, sizeof(cffile),&err, p_fci_internal->pv) != sizeof(cffile) ) {
2556 /* write error */
2557 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
2558 return FALSE;
2560 /* TODO error handling of err */
2562 p_fci_internal->sizeFileCFFILE1 += sizeof(cffile);
2564 /* append the name of file */
2565 if (strlen(pszFileName)>=CB_MAX_FILENAME) {
2566 /* IMPOSSIBLE */
2567 /* set error code */
2568 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2569 return FALSE;
2571 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */
2572 pszFileName, strlen(pszFileName)+1, &err, p_fci_internal->pv)
2573 != strlen(pszFileName)+1 ) {
2574 /* write error */
2575 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
2576 return FALSE;
2578 /* TODO error handling of err */
2580 p_fci_internal->sizeFileCFFILE1 += strlen(pszFileName)+1;
2582 /* REUSE the variable read_result */
2583 if (p_fci_internal->fGetNextCabInVain ||
2584 p_fci_internal->fNextCab
2586 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2587 p_fci_internal->oldCCAB.cbReserveCFFolder;
2588 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2589 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2590 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2591 read_result+=4;
2593 } else {
2594 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2595 p_fci_internal->pccab->cbReserveCFFolder;
2596 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2597 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2598 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2599 read_result+=4;
2602 if ( p_fci_internal->fPrevCab ) {
2603 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2604 strlen(p_fci_internal->szPrevDisk)+1;
2606 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2607 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2608 strlen(p_fci_internal->pccab->szDisk)+1;
2610 read_result+= p_fci_internal->sizeFileCFDATA1 +
2611 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2612 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2613 sizeof(CFHEADER) +
2614 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2616 /* too much data for the maximum size of a cabinet */
2617 /* (ignoring the unflushed data block) */
2618 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2619 p_fci_internal->fNextCab==FALSE && /* this is always the case */
2620 p_fci_internal->pccab->cb < read_result ) {
2621 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2624 /* Might be too much data for the maximum size of a cabinet.*/
2625 /* When any further data will be added later, it might not */
2626 /* be possible to flush the cabinet, because there might */
2627 /* not be enough space to store the name of the following */
2628 /* cabinet and name of the corresponding disk. */
2629 /* So take care of this and get the name of the next cabinet */
2630 /* (ignoring the unflushed data block) */
2631 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2632 p_fci_internal->fNextCab==FALSE &&
2633 ( p_fci_internal->pccab->cb < read_result +
2634 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2637 /* save CCAB */
2638 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2639 /* increment cabinet index */
2640 ++(p_fci_internal->pccab->iCab);
2641 /* get name of next cabinet */
2642 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2643 if (!(*pfnfcignc)(p_fci_internal->pccab,
2644 p_fci_internal->estimatedCabinetSize,/* estimated size of cab */
2645 p_fci_internal->pv)) {
2646 /* error handling */
2647 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2648 return FALSE;
2650 /* Skip a few lines of code. This is caught by the next if. */
2651 p_fci_internal->fGetNextCabInVain=TRUE;
2654 if( p_fci_internal->fGetNextCabInVain &&
2655 p_fci_internal->fNextCab
2657 /* THIS CAN NEVER HAPPEN */
2658 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2659 return FALSE;
2662 /* too much data for cabinet */
2663 if( (p_fci_internal->fGetNextCabInVain ||
2664 p_fci_internal->fNextCab) && (
2665 p_fci_internal->oldCCAB.cb < read_result +
2666 strlen(p_fci_internal->pccab->szCab)+1+
2667 strlen(p_fci_internal->pccab->szDisk)+1
2668 )) {
2670 p_fci_internal->fGetNextCabInVain=FALSE;
2671 p_fci_internal->fNextCab=TRUE;
2672 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2675 if( p_fci_internal->fNextCab ) {
2676 /* THIS MAY NEVER HAPPEN */
2677 /* set error code */
2678 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2679 return FALSE;
2682 /* if the FolderThreshold has been reached flush the folder automatically */
2683 if( p_fci_internal->fGetNextCabInVain ) {
2684 if( p_fci_internal->cCompressedBytesInFolder >=
2685 p_fci_internal->oldCCAB.cbFolderThresh) {
2686 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2688 } else {
2689 if( p_fci_internal->cCompressedBytesInFolder >=
2690 p_fci_internal->pccab->cbFolderThresh) {
2691 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2695 return TRUE;
2696 } /* end of FCIAddFile */
2702 /***********************************************************************
2703 * FCIFlushFolder (CABINET.12)
2705 * FCIFlushFolder completes the CFFolder structure under construction.
2707 * All further data which is added by FCIAddFile will be associateed to
2708 * the next CFFolder structure.
2710 * FCIFlushFolder will be called by FCIAddFile automatically if the
2711 * threshold (stored in the member cbFolderThresh of the CCAB structure
2712 * pccab passed to FCICreate) is exceeded.
2714 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2715 * any data will be written into the cabinet file.
2717 * PARAMS
2718 * hfci [I] An HFCI from FCICreate
2719 * pfnfcignc [I] A pointer to a function which gets information about
2720 * the next cabinet
2721 * pfnfcis [IO] A pointer to a function which will report status
2722 * information about the compression process
2724 * RETURNS
2725 * On success, returns TRUE
2726 * On failure, returns FALSE
2728 * INCLUDES
2729 * fci.h
2732 BOOL __cdecl FCIFlushFolder(
2733 HFCI hfci,
2734 PFNFCIGETNEXTCABINET pfnfcignc,
2735 PFNFCISTATUS pfnfcis)
2737 return fci_flush_folder(hfci,FALSE,pfnfcignc,pfnfcis);
2738 } /* end of FCIFlushFolder */
2742 /***********************************************************************
2743 * FCIFlushCabinet (CABINET.13)
2745 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2746 * into the cabinet file. If the maximum cabinet size (stored in the
2747 * member cb of the CCAB structure pccab passed to FCICreate) has been
2748 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2749 * The remaining data still has to be flushed manually by calling
2750 * FCIFlushCabinet.
2752 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2753 * NOT be called again. Then hfci has to be released by FCIDestroy.
2755 * PARAMS
2756 * hfci [I] An HFCI from FCICreate
2757 * fGetNextCab [I] Whether you want to add additional files to a
2758 * cabinet set (TRUE) or whether you want to
2759 * finalize it (FALSE)
2760 * pfnfcignc [I] A pointer to a function which gets information about
2761 * the next cabinet
2762 * pfnfcis [IO] A pointer to a function which will report status
2763 * information about the compression process
2765 * RETURNS
2766 * On success, returns TRUE
2767 * On failure, returns FALSE
2769 * INCLUDES
2770 * fci.h
2773 BOOL __cdecl FCIFlushCabinet(
2774 HFCI hfci,
2775 BOOL fGetNextCab,
2776 PFNFCIGETNEXTCABINET pfnfcignc,
2777 PFNFCISTATUS pfnfcis)
2779 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2781 if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2783 while( p_fci_internal->sizeFileCFFILE1>0 ||
2784 p_fci_internal->sizeFileCFFILE2>0 ) {
2785 if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2788 return TRUE;
2789 } /* end of FCIFlushCabinet */
2792 /***********************************************************************
2793 * FCIDestroy (CABINET.14)
2795 * Frees a handle created by FCICreate.
2796 * Only reason for failure would be an invalid handle.
2798 * PARAMS
2799 * hfci [I] The HFCI to free
2801 * RETURNS
2802 * TRUE for success
2803 * FALSE for failure
2805 BOOL __cdecl FCIDestroy(HFCI hfci)
2807 int err;
2808 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2809 if (REALLY_IS_FCI(hfci)) {
2811 /* before hfci can be removed all temporary files must be closed */
2812 /* and deleted */
2813 p_fci_internal->FCI_Intmagic = 0;
2815 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
2816 /* TODO error handling of err */
2817 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA1, &err,
2818 p_fci_internal->pv);
2819 /* TODO error handling of err */
2820 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE1,&err,p_fci_internal->pv);
2821 /* TODO error handling of err */
2822 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE1, &err,
2823 p_fci_internal->pv);
2824 /* TODO error handling of err */
2825 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2826 /* TODO error handling of err */
2827 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,
2828 p_fci_internal->pv);
2829 /* TODO error handling of err */
2830 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2831 /* TODO error handling of err */
2832 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,
2833 p_fci_internal->pv);
2834 /* TODO error handling of err */
2835 PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
2836 /* TODO error handling of err */
2837 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,
2838 p_fci_internal->pv);
2839 /* TODO error handling of err */
2841 /* data in and out buffers have to be removed */
2842 if (p_fci_internal->data_in!=NULL)
2843 PFCI_FREE(hfci, p_fci_internal->data_in);
2844 if (p_fci_internal->data_out!=NULL)
2845 PFCI_FREE(hfci, p_fci_internal->data_out);
2847 /* hfci can now be removed */
2848 PFCI_FREE(hfci, hfci);
2849 return TRUE;
2850 } else {
2851 SetLastError(ERROR_INVALID_HANDLE);
2852 return FALSE;
2855 } /* end of FCIDestroy */