gdiplus: Added GdipCreatePath2.
[wine/hacks.git] / dlls / cabinet / fci.c
blobb5e6c9c23f6f7f0be8390f70ab6a20c9478cfd79
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) {
177 SetLastError(ERROR_BAD_ARGUMENTS);
178 return NULL;
180 if ((!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||
181 (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||
182 (!pfnfcigtf) || (!pccab)) {
183 perf->erfOper = FCIERR_NONE;
184 perf->erfType = ERROR_BAD_ARGUMENTS;
185 perf->fError = TRUE;
187 SetLastError(ERROR_BAD_ARGUMENTS);
188 return NULL;
191 if (!((hfci = ((HFCI) (*pfnalloc)(sizeof(FCI_Int)))))) {
192 perf->erfOper = FCIERR_ALLOC_FAIL;
193 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
194 perf->fError = TRUE;
196 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
197 return NULL;
200 p_fci_internal=((PFCI_Int)(hfci));
201 p_fci_internal->FCI_Intmagic = FCI_INT_MAGIC;
202 p_fci_internal->perf = perf;
203 p_fci_internal->pfnfiledest = pfnfiledest;
204 p_fci_internal->pfnalloc = pfnalloc;
205 p_fci_internal->pfnfree = pfnfree;
206 p_fci_internal->pfnopen = pfnopen;
207 p_fci_internal->pfnread = pfnread;
208 p_fci_internal->pfnwrite = pfnwrite;
209 p_fci_internal->pfnclose = pfnclose;
210 p_fci_internal->pfnseek = pfnseek;
211 p_fci_internal->pfndelete = pfndelete;
212 p_fci_internal->pfnfcigtf = pfnfcigtf;
213 p_fci_internal->pccab = pccab;
214 p_fci_internal->fPrevCab = FALSE;
215 p_fci_internal->fNextCab = FALSE;
216 p_fci_internal->fSplitFolder = FALSE;
217 p_fci_internal->fGetNextCabInVain = FALSE;
218 p_fci_internal->pv = pv;
219 p_fci_internal->data_in = NULL;
220 p_fci_internal->cdata_in = 0;
221 p_fci_internal->data_out = NULL;
222 p_fci_internal->cCompressedBytesInFolder = 0;
223 p_fci_internal->cFolders = 0;
224 p_fci_internal->cFiles = 0;
225 p_fci_internal->cDataBlocks = 0;
226 p_fci_internal->sizeFileCFDATA1 = 0;
227 p_fci_internal->sizeFileCFFILE1 = 0;
228 p_fci_internal->sizeFileCFDATA2 = 0;
229 p_fci_internal->sizeFileCFFILE2 = 0;
230 p_fci_internal->sizeFileCFFOLDER = 0;
231 p_fci_internal->sizeFileCFFOLDER = 0;
232 p_fci_internal->fNewPrevious = FALSE;
233 p_fci_internal->estimatedCabinetSize = 0;
234 p_fci_internal->statusFolderTotal = 0;
236 memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
237 memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);
239 /* CFDATA */
240 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA1,
241 CB_MAX_FILENAME)) {
242 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
243 return FALSE;
245 /* safety */
246 if ( strlen(p_fci_internal->szFileNameCFDATA1) >= CB_MAX_FILENAME ) {
247 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
248 return FALSE;
251 p_fci_internal->handleCFDATA1 = PFCI_OPEN(hfci,
252 p_fci_internal->szFileNameCFDATA1, 34050, 384, &err, pv);
253 if(p_fci_internal->handleCFDATA1==0){
254 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
255 return FALSE;
257 /* TODO error checking of err */
259 /* array of all CFFILE in a folder */
260 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE1,
261 CB_MAX_FILENAME)) {
262 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
263 return FALSE;
265 /* safety */
266 if ( strlen(p_fci_internal->szFileNameCFFILE1) >= CB_MAX_FILENAME ) {
267 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
268 return FALSE;
270 p_fci_internal->handleCFFILE1 = PFCI_OPEN(hfci,
271 p_fci_internal->szFileNameCFFILE1, 34050, 384, &err, pv);
272 if(p_fci_internal->handleCFFILE1==0){
273 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
274 return FALSE;
276 /* TODO error checking of err */
278 /* CFDATA with checksum and ready to be copied into cabinet */
279 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA2,
280 CB_MAX_FILENAME)) {
281 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE);
282 return FALSE;
284 /* safety */
285 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
286 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
287 return FALSE;
289 p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
290 p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, pv);
291 if(p_fci_internal->handleCFDATA2==0){
292 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
293 return FALSE;
295 /* TODO error checking of err */
297 /* array of all CFFILE in a folder, ready to be copied into cabinet */
298 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
299 CB_MAX_FILENAME)) {
300 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
301 return FALSE;
303 /* safety */
304 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
305 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
306 return FALSE;
308 p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
309 p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, pv);
310 if(p_fci_internal->handleCFFILE2==0){
311 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
312 return FALSE;
314 /* TODO error checking of err */
316 /* array of all CFFILE in a folder, ready to be copied into cabinet */
317 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,
318 CB_MAX_FILENAME)) {
319 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
320 return FALSE;
322 /* safety */
323 if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
324 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
325 return FALSE;
327 p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
328 p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, pv);
329 if(p_fci_internal->handleCFFOLDER==0) {
330 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
331 return FALSE;
334 /* TODO close and delete new files when return FALSE */
335 /* TODO error checking of err */
337 return hfci;
338 } /* end of FCICreate */
345 static BOOL fci_flush_data_block (HFCI hfci, int* err,
346 PFNFCISTATUS pfnfcis) {
348 /* attention no hfci checks!!! */
349 /* attention no checks if there is data available!!! */
350 CFDATA data;
351 CFDATA* cfdata=&data;
352 char* reserved;
353 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
354 UINT cbReserveCFData=p_fci_internal->pccab->cbReserveCFData;
355 UINT i;
357 /* TODO compress the data of p_fci_internal->data_in */
358 /* and write it to p_fci_internal->data_out */
359 memcpy(p_fci_internal->data_out, p_fci_internal->data_in,
360 p_fci_internal->cdata_in /* number of bytes to copy */);
362 cfdata->csum=0; /* checksum has to be set later */
363 /* TODO set realsize of compressed data */
364 cfdata->cbData = p_fci_internal->cdata_in;
365 cfdata->cbUncomp = p_fci_internal->cdata_in;
367 /* write cfdata to p_fci_internal->handleCFDATA1 */
368 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
369 cfdata, sizeof(*cfdata), err, p_fci_internal->pv)
370 != sizeof(*cfdata) ) {
371 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
372 return FALSE;
374 /* TODO error handling of err */
376 p_fci_internal->sizeFileCFDATA1 += sizeof(*cfdata);
378 /* add optional reserved area */
380 /* This allocation and freeing at each CFData block is a bit */
381 /* inefficent, but it's harder to forget about freeing the buffer :-). */
382 /* Reserved areas are used seldom besides that... */
383 if (cbReserveCFData!=0) {
384 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData))) {
385 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
386 return FALSE;
388 for(i=0;i<cbReserveCFData;) {
389 reserved[i++]='\0';
391 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
392 reserved, /* memory buffer */
393 cbReserveCFData, /* number of bytes to copy */
394 err, p_fci_internal->pv) != cbReserveCFData ) {
395 PFCI_FREE(hfci, reserved);
396 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
397 return FALSE;
399 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
401 p_fci_internal->sizeFileCFDATA1 += cbReserveCFData;
402 PFCI_FREE(hfci, reserved);
405 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
406 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
407 p_fci_internal->data_out, /* memory buffer */
408 cfdata->cbData, /* number of bytes to copy */
409 err, p_fci_internal->pv) != cfdata->cbData) {
410 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
411 return FALSE;
413 /* TODO error handling of err */
415 p_fci_internal->sizeFileCFDATA1 += cfdata->cbData;
417 /* reset the offset */
418 p_fci_internal->cdata_in = 0;
419 p_fci_internal->cCompressedBytesInFolder += cfdata->cbData;
421 /* report status with pfnfcis about uncompressed and compressed file data */
422 if( (*pfnfcis)(statusFile, cfdata->cbData, cfdata->cbUncomp,
423 p_fci_internal->pv) == -1) {
424 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
425 return FALSE;
428 ++(p_fci_internal->cDataBlocks);
430 return TRUE;
431 } /* end of fci_flush_data_block */
437 static cab_ULONG fci_get_checksum(const void *pv, UINT cb, CHECKSUM seed)
439 cab_ULONG csum;
440 cab_ULONG ul;
441 int cUlong;
442 const BYTE *pb;
444 csum = seed;
445 cUlong = cb / 4;
446 pb = pv;
448 while (cUlong-- > 0) {
449 ul = *pb++;
450 ul |= (((cab_ULONG)(*pb++)) << 8);
451 ul |= (((cab_ULONG)(*pb++)) << 16);
452 ul |= (((cab_ULONG)(*pb++)) << 24);
454 csum ^= ul;
457 ul = 0;
458 switch (cb % 4) {
459 case 3:
460 ul |= (((ULONG)(*pb++)) << 16);
461 case 2:
462 ul |= (((ULONG)(*pb++)) << 8);
463 case 1:
464 ul |= *pb++;
465 default:
466 break;
468 csum ^= ul;
470 return csum;
471 } /* end of fci_get_checksum */
475 static BOOL fci_flushfolder_copy_cfdata(HFCI hfci, char* buffer, UINT cbReserveCFData,
476 PFNFCISTATUS pfnfcis, int* err, int handleCFDATA1new,
477 cab_ULONG* psizeFileCFDATA1new, cab_ULONG* payload)
479 cab_ULONG read_result;
480 CFDATA* pcfdata=(CFDATA*)buffer;
481 BOOL split_block=FALSE;
482 cab_UWORD savedUncomp=0;
483 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
485 *payload=0;
487 /* while not all CFDATAs have been copied do */
488 while(!FALSE) {
489 if( p_fci_internal->fNextCab ) {
490 if( split_block ) {
491 /* internal error should never happen */
492 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
493 return FALSE;
496 /* REUSE the variable read_result */
497 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
498 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
499 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
500 read_result=4;
501 } else {
502 read_result=0;
504 if (p_fci_internal->fPrevCab) {
505 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
506 strlen(p_fci_internal->szPrevDisk)+1;
508 /* No more CFDATA fits into the cabinet under construction */
509 /* So don't try to store more data into it */
510 if( p_fci_internal->fNextCab &&
511 (p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData +
512 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
513 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
514 sizeof(CFHEADER) +
515 read_result +
516 p_fci_internal->oldCCAB.cbReserveCFHeader +
517 sizeof(CFFOLDER) +
518 p_fci_internal->oldCCAB.cbReserveCFFolder +
519 strlen(p_fci_internal->pccab->szCab)+1 +
520 strlen(p_fci_internal->pccab->szDisk)+1
521 )) {
522 /* This may never be run for the first time the while loop is entered.
523 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
524 split_block=TRUE; /* In this case split_block is abused to store */
525 /* the complete data block into the next cabinet and not into the */
526 /* current one. Originally split_block is the indicator that a */
527 /* data block has been splitted across different cabinets. */
528 } else {
530 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
531 read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/*file handle*/
532 buffer, /* memory buffer */
533 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
534 err, p_fci_internal->pv);
535 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
536 if (read_result==0) break; /* ALL DATA has been copied */
537 /* read error */
538 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
539 return FALSE;
541 /* TODO error handling of err */
543 /* REUSE buffer p_fci_internal->data_out !!! */
544 /* read data from p_fci_internal->handleCFDATA1 to */
545 /* p_fci_internal->data_out */
546 if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
547 p_fci_internal->data_out /* memory buffer */,
548 pcfdata->cbData /* number of bytes to copy */,
549 err, p_fci_internal->pv) != pcfdata->cbData ) {
550 /* read error */
551 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
552 return FALSE;
554 /* TODO error handling of err */
556 /* if cabinet size is too large */
558 /* REUSE the variable read_result */
559 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
560 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
561 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
562 read_result=4;
563 } else {
564 read_result=0;
566 if (p_fci_internal->fPrevCab) {
567 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
568 strlen(p_fci_internal->szPrevDisk)+1;
571 /* Is cabinet with new CFDATA too large? Then data block has to be split */
572 if( p_fci_internal->fNextCab &&
573 (p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData +
574 pcfdata->cbData +
575 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
576 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
577 sizeof(CFHEADER) +
578 read_result +
579 p_fci_internal->oldCCAB.cbReserveCFHeader +
580 sizeof(CFFOLDER) + /* size of new CFFolder entry */
581 p_fci_internal->oldCCAB.cbReserveCFFolder +
582 strlen(p_fci_internal->pccab->szCab)+1 + /* name of next cabinet */
583 strlen(p_fci_internal->pccab->szDisk)+1 /* name of next disk */
584 )) {
585 /* REUSE read_result to save the size of the compressed data */
586 read_result=pcfdata->cbData;
587 /* Modify the size of the compressed data to store only a part of the */
588 /* data block into the current cabinet. This is done to prevent */
589 /* that the maximum cabinet size will be exceeded. The remainder */
590 /* will be stored into the next following cabinet. */
592 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
593 /* Substract everything except the size of the block of data */
594 /* to get it's actual size */
595 pcfdata->cbData = p_fci_internal->oldCCAB.cb - (
596 sizeof(CFDATA) + cbReserveCFData +
597 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
598 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
599 sizeof(CFHEADER) +
600 p_fci_internal->oldCCAB.cbReserveCFHeader +
601 sizeof(CFFOLDER) + /* set size of new CFFolder entry */
602 p_fci_internal->oldCCAB.cbReserveCFFolder );
603 /* substract the size of special header fields */
604 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
605 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
606 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
607 pcfdata->cbData-=4;
609 if (p_fci_internal->fPrevCab) {
610 pcfdata->cbData-=strlen(p_fci_internal->szPrevCab)+1 +
611 strlen(p_fci_internal->szPrevDisk)+1;
613 pcfdata->cbData-=strlen(p_fci_internal->pccab->szCab)+1 +
614 strlen(p_fci_internal->pccab->szDisk)+1;
616 savedUncomp = pcfdata->cbUncomp;
617 pcfdata->cbUncomp = 0; /* on splitted blocks of data this is zero */
619 /* if split_block==TRUE then the above while loop won't */
620 /* be executed again */
621 split_block=TRUE; /* split_block is the indicator that */
622 /* a data block has been splitted across */
623 /* diffentent cabinets.*/
626 /* This should never happen !!! */
627 if (pcfdata->cbData==0) {
628 /* set error */
629 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
630 return FALSE;
633 /* set little endian */
634 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
635 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
637 /* get checksum and write to cfdata.csum */
638 pcfdata->csum = fci_get_checksum( &(pcfdata->cbData),
639 sizeof(CFDATA)+cbReserveCFData -
640 sizeof(pcfdata->csum), fci_get_checksum( p_fci_internal->data_out, /*buffer*/
641 pcfdata->cbData, 0 ) );
643 /* set little endian */
644 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
646 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
647 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
648 buffer, /* memory buffer */
649 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
650 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
651 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
652 return FALSE;
654 /* TODO error handling of err */
656 p_fci_internal->sizeFileCFDATA2 += sizeof(CFDATA)+cbReserveCFData;
658 /* reset little endian */
659 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
660 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
661 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
663 /* write compressed data into p_fci_internal->handleCFDATA2 */
664 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
665 p_fci_internal->data_out, /* memory buffer */
666 pcfdata->cbData, /* number of bytes to copy */
667 err, p_fci_internal->pv) != pcfdata->cbData) {
668 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
669 return FALSE;
671 /* TODO error handling of err */
673 p_fci_internal->sizeFileCFDATA2 += pcfdata->cbData;
674 ++(p_fci_internal->cDataBlocks);
675 p_fci_internal->statusFolderCopied += pcfdata->cbData;
676 (*payload)+=pcfdata->cbUncomp;
677 /* if cabinet size too large and data has been split */
678 /* write the remainder of the data block to the new CFDATA1 file */
679 if( split_block ) { /* This does not include the */
680 /* abused one (just search for "abused" )*/
681 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
682 if (p_fci_internal->fNextCab==FALSE ) {
683 /* internal error */
684 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
685 return FALSE;
688 /* set cbData to the size of the remainder of the data block */
689 pcfdata->cbData = read_result - pcfdata->cbData;
690 /*recover former value of cfdata.cbData; read_result will be the offset*/
691 read_result -= pcfdata->cbData;
692 pcfdata->cbUncomp = savedUncomp;
694 /* reset checksum, it will be computed later */
695 pcfdata->csum=0;
697 /* write cfdata WITHOUT checksum to handleCFDATA1new */
698 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
699 buffer, /* memory buffer */
700 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
701 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
702 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
703 return FALSE;
705 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
707 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
709 /* write compressed data into handleCFDATA1new */
710 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
711 p_fci_internal->data_out + read_result, /* memory buffer + offset */
712 /* to last part of split data */
713 pcfdata->cbData, /* number of bytes to copy */
714 err, p_fci_internal->pv) != pcfdata->cbData) {
715 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
716 return FALSE;
718 /* TODO error handling of err */
720 p_fci_internal->statusFolderCopied += pcfdata->cbData;
722 *psizeFileCFDATA1new += pcfdata->cbData;
723 /* the two blocks of the split data block have been written */
724 /* don't reset split_data yet, because it is still needed see below */
727 /* report status with pfnfcis about copied size of folder */
728 if( (*pfnfcis)(statusFolder,
729 p_fci_internal->statusFolderCopied, /*cfdata.cbData(+previous ones)*/
730 p_fci_internal->statusFolderTotal, /* total folder size */
731 p_fci_internal->pv) == -1) {
732 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
733 return FALSE;
737 /* if cabinet size too large */
738 /* write the remaining data blocks to the new CFDATA1 file */
739 if ( split_block ) { /* This does include the */
740 /* abused one (just search for "abused" )*/
741 if (p_fci_internal->fNextCab==FALSE ) {
742 /* internal error */
743 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
744 return FALSE;
746 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
747 while(!FALSE) {
748 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
749 read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/* handle */
750 buffer, /* memory buffer */
751 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
752 err, p_fci_internal->pv);
753 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
754 if (read_result==0) break; /* ALL DATA has been copied */
755 /* read error */
756 fci_set_error(FCIERR_NONE, ERROR_READ_FAULT, TRUE );
757 return FALSE;
759 /* TODO error handling of err */
761 /* REUSE buffer p_fci_internal->data_out !!! */
762 /* read data from p_fci_internal->handleCFDATA1 to */
763 /* p_fci_internal->data_out */
764 if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
765 p_fci_internal->data_out /* memory buffer */,
766 pcfdata->cbData /* number of bytes to copy */,
767 err, p_fci_internal->pv) != pcfdata->cbData ) {
768 /* read error */
769 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE);
770 return FALSE;
772 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
774 /* write cfdata with checksum to handleCFDATA1new */
775 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
776 buffer, /* memory buffer */
777 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
778 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
779 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
780 return FALSE;
782 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
784 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
786 /* write compressed data into handleCFDATA1new */
787 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
788 p_fci_internal->data_out, /* memory buffer */
789 pcfdata->cbData, /* number of bytes to copy */
790 err, p_fci_internal->pv) != pcfdata->cbData) {
791 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
792 return FALSE;
794 /* TODO error handling of err */
796 *psizeFileCFDATA1new += pcfdata->cbData;
797 p_fci_internal->statusFolderCopied += pcfdata->cbData;
799 /* report status with pfnfcis about copied size of folder */
800 if( (*pfnfcis)(statusFolder,
801 p_fci_internal->statusFolderCopied,/*cfdata.cbData(+revious ones)*/
802 p_fci_internal->statusFolderTotal, /* total folder size */
803 p_fci_internal->pv) == -1) {
804 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
805 return FALSE;
808 } /* end of WHILE */
809 break; /* jump out of the next while loop */
810 } /* end of if( split_data ) */
811 } /* end of WHILE */
812 return TRUE;
813 } /* end of fci_flushfolder_copy_cfdata */
819 static BOOL fci_flushfolder_copy_cffolder(HFCI hfci, int* err, UINT cbReserveCFFolder,
820 cab_ULONG sizeFileCFDATA2old)
822 CFFOLDER cffolder;
823 UINT i;
824 char* reserved;
825 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
827 /* absolute offset cannot be set yet, because the size of cabinet header, */
828 /* the number of CFFOLDERs and the number of CFFILEs may change. */
829 /* Instead the size of all previous data blocks will be stored and */
830 /* the remainder of the offset will be added when the cabinet will be */
831 /* flushed to disk. */
832 /* This is exactly the way the original CABINET.DLL works!!! */
833 cffolder.coffCabStart=sizeFileCFDATA2old;
835 /* set the number of this folder's CFDATA sections */
836 cffolder.cCFData=p_fci_internal->cDataBlocks;
837 /* TODO set compression type */
838 cffolder.typeCompress = tcompTYPE_NONE;
840 /* write cffolder to p_fci_internal->handleCFFOLDER */
841 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
842 &cffolder, /* memory buffer */
843 sizeof(cffolder), /* number of bytes to copy */
844 err, p_fci_internal->pv) != sizeof(cffolder) ) {
845 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
846 return FALSE;
848 /* TODO error handling of err */
850 p_fci_internal->sizeFileCFFOLDER += sizeof(cffolder);
852 /* add optional reserved area */
853 if (cbReserveCFFolder!=0) {
854 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFFolder))) {
855 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
856 return FALSE;
858 for(i=0;i<cbReserveCFFolder;) {
859 reserved[i++]='\0';
861 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
862 reserved, /* memory buffer */
863 cbReserveCFFolder, /* number of bytes to copy */
864 err, p_fci_internal->pv) != cbReserveCFFolder ) {
865 PFCI_FREE(hfci, reserved);
866 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
867 return FALSE;
869 /* TODO error handling of err */
871 p_fci_internal->sizeFileCFFOLDER += cbReserveCFFolder;
873 PFCI_FREE(hfci, reserved);
875 return TRUE;
876 } /* end of fci_flushfolder_copy_cffolder */
882 static BOOL fci_flushfolder_copy_cffile(HFCI hfci, int* err, int handleCFFILE1new,
883 cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload)
885 CFFILE cffile;
886 cab_ULONG read_result;
887 cab_ULONG seek=0;
888 cab_ULONG sizeOfFiles=0, sizeOfFilesPrev;
889 BOOL may_be_prev=TRUE;
890 cab_ULONG cbFileRemainer=0;
891 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
892 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
893 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,0,SEEK_SET,err,
894 p_fci_internal->pv) !=0 ) {
895 /* wrong return value */
896 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
897 return FALSE;
899 /* TODO error handling of err */
901 /* while not all CFFILE structures have been copied do */
902 while(!FALSE) {
903 /* REUSE the variable read_result */
904 /* read data from p_fci_internal->handleCFFILE1 to cffile */
905 read_result = PFCI_READ(hfci,p_fci_internal->handleCFFILE1/* file handle */,
906 &cffile, /* memory buffer */
907 sizeof(cffile), /* number of bytes to copy */
908 err, p_fci_internal->pv);
909 if( read_result != sizeof(cffile) ) {
910 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
911 /* read error */
912 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
913 return FALSE;
915 /* TODO error handling of err */
917 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
918 /* position. I don't know why so I'll just omit it */
920 /* read the filename from p_fci_internal->handleCFFILE1 */
921 /* REUSE the variable read_result AGAIN */
922 /* REUSE the memory buffer PFCI(hfci)->data_out */
923 if( PFCI_READ(hfci, p_fci_internal->handleCFFILE1 /*file handle*/,
924 p_fci_internal->data_out, /* memory buffer */
925 CB_MAX_FILENAME, /* number of bytes to copy */
926 err, p_fci_internal->pv) <2) {
927 /* read error */
928 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
929 return FALSE;
931 /* TODO maybe other checks of read_result */
932 /* TODO error handling of err */
934 /* safety */
935 if( strlen(p_fci_internal->data_out)>=CB_MAX_FILENAME ) {
936 /* set error code internal error */
937 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
938 return FALSE;
941 seek+=sizeof(cffile) + strlen(p_fci_internal->data_out)+1;
943 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
944 /* i.e. seek to the next CFFILE area */
945 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,
946 seek, /* seek position*/
947 SEEK_SET ,err,
948 p_fci_internal->pv)
949 != seek) {
950 /* wrong return value */
951 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
952 return FALSE;
954 /* TODO error handling of err */
956 /* fnfilfnfildest: placed file on cabinet */
957 if (p_fci_internal->fNextCab ||
958 p_fci_internal->fGetNextCabInVain) {
959 PFCI_FILEPLACED( hfci, &(p_fci_internal->oldCCAB),
960 p_fci_internal->data_out, /* the file name*/
961 cffile.cbFile, /* file size */
962 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
963 p_fci_internal->pv
965 } else {
966 PFCI_FILEPLACED( hfci, p_fci_internal->pccab,
967 p_fci_internal->data_out, /* the file name*/
968 cffile.cbFile, /* file size */
969 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
970 p_fci_internal->pv
974 /* Check special iFolder values */
975 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
976 p_fci_internal->fPrevCab==FALSE ) {
977 /* THIS MAY NEVER HAPPEN */
978 /* set error code */
979 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
980 return FALSE;
982 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
983 cffile.iFolder==cffileCONTINUED_TO_NEXT ) {
984 /* THIS MAY NEVER HAPPEN */
985 /* set error code */
986 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
987 return FALSE;
989 if( may_be_prev && cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
990 may_be_prev=FALSE;
992 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && may_be_prev==FALSE ) {
993 /* THIS MAY NEVER HAPPEN */
994 /* set error code */
995 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
996 return FALSE;
998 if( cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
999 may_be_prev=FALSE;
1002 sizeOfFilesPrev=sizeOfFiles;
1003 /* Set complete size of all processed files */
1004 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
1005 p_fci_internal->cbFileRemainer!=0
1007 sizeOfFiles+=p_fci_internal->cbFileRemainer;
1008 p_fci_internal->cbFileRemainer=0;
1009 } else {
1010 sizeOfFiles+=cffile.cbFile;
1013 /* Check if spanned file fits into this cabinet folder */
1014 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && sizeOfFiles>payload ) {
1015 cffile.iFolder=cffileCONTINUED_PREV_AND_NEXT;
1016 } else
1018 /* Check if file doesn't fit into this cabinet folder */
1019 if( sizeOfFiles>payload ) {
1020 cffile.iFolder=cffileCONTINUED_TO_NEXT;
1023 /* set little endian */
1024 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1025 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1026 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1027 cffile.date=fci_endian_uword(cffile.date);
1028 cffile.time=fci_endian_uword(cffile.time);
1029 cffile.attribs=fci_endian_uword(cffile.attribs);
1031 /* write cffile to p_fci_internal->handleCFFILE2 */
1032 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */
1033 &cffile, /* memory buffer */
1034 sizeof(cffile), /* number of bytes to copy */
1035 err, p_fci_internal->pv) != sizeof(cffile) ) {
1036 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1037 return FALSE;
1039 /* TODO error handling of err */
1041 p_fci_internal->sizeFileCFFILE2 += sizeof(cffile);
1043 /* reset little endian */
1044 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1045 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1046 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1047 cffile.date=fci_endian_uword(cffile.date);
1048 cffile.time=fci_endian_uword(cffile.time);
1049 cffile.attribs=fci_endian_uword(cffile.attribs);
1051 /* write file name to p_fci_internal->handleCFFILE2 */
1052 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */
1053 p_fci_internal->data_out, /* memory buffer */
1054 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1055 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1056 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1057 return FALSE;
1059 /* TODO error handling of err */
1061 p_fci_internal->sizeFileCFFILE2 += strlen(p_fci_internal->data_out)+1;
1063 /* cFiles is used to count all files of a cabinet */
1064 ++(p_fci_internal->cFiles);
1066 /* This is only true for files which will be written into the */
1067 /* next cabinet of the spanning folder */
1068 if( sizeOfFiles>payload ) {
1070 /* Files which data will be partially written into the current cabinet */
1071 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
1072 cffile.iFolder==cffileCONTINUED_TO_NEXT
1074 if( sizeOfFilesPrev<=payload ) {
1075 /* The size of the uncompressed, data of a spanning file in a */
1076 /* spanning data */
1077 cbFileRemainer=sizeOfFiles-payload;
1079 cffile.iFolder=cffileCONTINUED_FROM_PREV;
1080 } else {
1081 cffile.iFolder=0;
1084 /* write cffile into handleCFFILE1new */
1085 if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */
1086 &cffile, /* memory buffer */
1087 sizeof(cffile), /* number of bytes to copy */
1088 err, p_fci_internal->pv) != sizeof(cffile) ) {
1089 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1090 return FALSE;
1092 /* TODO error handling of err */
1094 *psizeFileCFFILE1new += sizeof(cffile);
1095 /* write name of file into handleCFFILE1new */
1096 if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */
1097 p_fci_internal->data_out, /* memory buffer */
1098 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1099 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1100 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1101 return FALSE;
1103 /* TODO error handling of err */
1105 *psizeFileCFFILE1new += strlen(p_fci_internal->data_out)+1;
1108 } /* END OF while */
1109 p_fci_internal->cbFileRemainer=cbFileRemainer;
1110 return TRUE;
1111 } /* end of fci_flushfolder_copy_cffile */
1116 static BOOL fci_flush_folder(
1117 HFCI hfci,
1118 BOOL fGetNextCab,
1119 PFNFCIGETNEXTCABINET pfnfcignc,
1120 PFNFCISTATUS pfnfcis)
1122 int err;
1123 int handleCFDATA1new; /* handle for new temp file */
1124 char szFileNameCFDATA1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1125 int handleCFFILE1new; /* handle for new temp file */
1126 char szFileNameCFFILE1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1127 UINT cbReserveCFData, cbReserveCFFolder;
1128 char* reserved;
1129 cab_ULONG sizeFileCFDATA1new=0;
1130 cab_ULONG sizeFileCFFILE1new=0;
1131 cab_ULONG sizeFileCFDATA2old;
1132 cab_ULONG payload;
1133 cab_ULONG read_result;
1134 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
1136 /* test hfci */
1137 if (!REALLY_IS_FCI(hfci)) {
1138 SetLastError(ERROR_INVALID_HANDLE);
1139 return FALSE;
1142 if ((!pfnfcignc) || (!pfnfcis)) {
1143 fci_set_error( FCIERR_NONE, ERROR_BAD_ARGUMENTS, TRUE );
1144 return FALSE;
1147 if( p_fci_internal->fGetNextCabInVain &&
1148 p_fci_internal->fNextCab ){
1149 /* internal error */
1150 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1151 return FALSE;
1154 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1155 /* this function will return TRUE */
1156 if( p_fci_internal->sizeFileCFFILE1 == 0 ) {
1157 if ( p_fci_internal->sizeFileCFDATA1 != 0 ) {
1158 /* error handling */
1159 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1160 return FALSE;
1162 return TRUE;
1165 if (p_fci_internal->data_in==NULL || p_fci_internal->data_out==NULL ) {
1166 /* error handling */
1167 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1168 return FALSE;
1171 /* FCIFlushFolder has already been called... */
1172 if (p_fci_internal->fSplitFolder && p_fci_internal->sizeFileCFFILE2!=0) {
1173 return TRUE;
1176 /* This can be set already, because it makes only a difference */
1177 /* when the current function exits with return FALSE */
1178 p_fci_internal->fSplitFolder=FALSE;
1181 if( p_fci_internal->fGetNextCabInVain ||
1182 p_fci_internal->fNextCab ){
1183 cbReserveCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1184 cbReserveCFFolder = p_fci_internal->oldCCAB.cbReserveCFFolder;
1185 } else {
1186 cbReserveCFData = p_fci_internal->pccab->cbReserveCFData;
1187 cbReserveCFFolder = p_fci_internal->pccab->cbReserveCFFolder;
1190 /* START of COPY */
1191 /* if there is data in p_fci_internal->data_in */
1192 if (p_fci_internal->cdata_in!=0) {
1194 if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;
1197 /* reset to get the number of data blocks of this folder which are */
1198 /* actually in this cabinet ( at least partially ) */
1199 p_fci_internal->cDataBlocks=0;
1201 if ( p_fci_internal->fNextCab ||
1202 p_fci_internal->fGetNextCabInVain ) {
1203 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader+
1204 p_fci_internal->oldCCAB.cbReserveCFFolder;
1205 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1206 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1207 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1208 read_result+=4;
1210 } else {
1211 read_result= p_fci_internal->pccab->cbReserveCFHeader+
1212 p_fci_internal->pccab->cbReserveCFFolder;
1213 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1214 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1215 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1216 read_result+=4;
1219 if (p_fci_internal->fPrevCab) {
1220 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1221 strlen(p_fci_internal->szPrevDisk)+1;
1223 if (p_fci_internal->fNextCab) {
1224 read_result+=strlen(p_fci_internal->pccab->szCab)+1 +
1225 strlen(p_fci_internal->pccab->szDisk)+1;
1228 p_fci_internal->statusFolderTotal = sizeof(CFHEADER)+read_result+
1229 sizeof(CFFOLDER) + p_fci_internal->sizeFileCFFILE2+
1230 p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1+
1231 p_fci_internal->sizeFileCFDATA1 + p_fci_internal->sizeFileCFFOLDER;
1232 p_fci_internal->statusFolderCopied = 0;
1234 /* report status with pfnfcis about copied size of folder */
1235 if( (*pfnfcis)(statusFolder, p_fci_internal->statusFolderCopied,
1236 p_fci_internal->statusFolderTotal, /* TODO total folder size */
1237 p_fci_internal->pv) == -1) {
1238 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
1239 return FALSE;
1242 /* get a new temp file */
1243 if(!PFCI_GETTEMPFILE(hfci,szFileNameCFDATA1new,CB_MAX_FILENAME)) {
1244 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1245 return FALSE;
1247 /* safety */
1248 if ( strlen(szFileNameCFDATA1new) >= CB_MAX_FILENAME ) {
1249 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1250 return FALSE;
1252 handleCFDATA1new = PFCI_OPEN(hfci,szFileNameCFDATA1new,34050,384,&err,
1253 p_fci_internal->pv);
1254 if(handleCFDATA1new==0){
1255 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
1256 return FALSE;
1258 /* TODO error handling of err */
1262 /* get a new temp file */
1263 if(!PFCI_GETTEMPFILE(hfci,szFileNameCFFILE1new,CB_MAX_FILENAME)) {
1264 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1265 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1266 /* TODO error handling of err */
1267 return FALSE;
1269 /* safety */
1270 if ( strlen(szFileNameCFFILE1new) >= CB_MAX_FILENAME ) {
1271 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1272 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1273 /* TODO error handling of err */
1274 return FALSE;
1276 handleCFFILE1new = PFCI_OPEN(hfci,szFileNameCFFILE1new,34050,384,&err,
1277 p_fci_internal->pv);
1278 if(handleCFFILE1new==0){
1279 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
1280 return FALSE;
1282 /* TODO error handling of err */
1284 /* USE the variable read_result */
1285 if ( p_fci_internal->fNextCab ||
1286 p_fci_internal->fGetNextCabInVain ) {
1287 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader;
1288 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1289 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1290 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1291 read_result+=4;
1293 } else {
1294 read_result= p_fci_internal->pccab->cbReserveCFHeader;
1295 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1296 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1297 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1298 read_result+=4;
1301 if (p_fci_internal->fPrevCab) {
1302 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1303 strlen(p_fci_internal->szPrevDisk)+1;
1305 read_result+= sizeof(CFHEADER) + p_fci_internal->sizeFileCFDATA2 +
1306 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER;
1308 if(p_fci_internal->sizeFileCFFILE1!=0) {
1309 read_result+= sizeof(CFFOLDER)+p_fci_internal->pccab->cbReserveCFFolder;
1312 /* Check if multiple cabinets have to be created. */
1314 /* Might be too much data for the maximum allowed cabinet size.*/
1315 /* When any further data will be added later, it might not */
1316 /* be possible to flush the cabinet, because there might */
1317 /* not be enough space to store the name of the following */
1318 /* cabinet and name of the corresponding disk. */
1319 /* So take care of this and get the name of the next cabinet */
1320 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1321 p_fci_internal->fNextCab==FALSE &&
1324 p_fci_internal->pccab->cb < read_result +
1325 p_fci_internal->sizeFileCFDATA1 +
1326 p_fci_internal->sizeFileCFFILE1 +
1327 CB_MAX_CABINET_NAME + /* next cabinet name */
1328 CB_MAX_DISK_NAME /* next disk name */
1329 ) || fGetNextCab
1332 /* save CCAB */
1333 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
1334 /* increment cabinet index */
1335 ++(p_fci_internal->pccab->iCab);
1336 /* get name of next cabinet */
1337 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
1338 if (!(*pfnfcignc)(p_fci_internal->pccab,
1339 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
1340 p_fci_internal->pv)) {
1341 /* error handling */
1342 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1343 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1344 /* TODO error handling of err */
1345 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1346 /* TODO error handling of err */
1347 return FALSE;
1350 /* Skip a few lines of code. This is caught by the next if. */
1351 p_fci_internal->fGetNextCabInVain=TRUE;
1354 /* too much data for cabinet */
1355 if( (p_fci_internal->fGetNextCabInVain ||
1356 p_fci_internal->fNextCab ) &&
1359 p_fci_internal->oldCCAB.cb < read_result +
1360 p_fci_internal->sizeFileCFDATA1 +
1361 p_fci_internal->sizeFileCFFILE1 +
1362 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1363 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1364 ) || fGetNextCab
1367 p_fci_internal->fGetNextCabInVain=FALSE;
1368 p_fci_internal->fNextCab=TRUE;
1370 /* return FALSE if there is not enough space left*/
1371 /* this should never happen */
1372 if (p_fci_internal->oldCCAB.cb <=
1373 p_fci_internal->sizeFileCFFILE1 +
1374 read_result +
1375 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1376 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1379 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1380 /* TODO error handling of err */
1381 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1382 /* TODO error handling of err */
1384 /* close and delete p_fci_internal->handleCFFILE1 */
1385 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1386 /* TODO error handling of err */
1387 PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);
1388 /* TODO error handling of err */
1390 return FALSE;
1393 /* the folder will be split across cabinets */
1394 p_fci_internal->fSplitFolder=TRUE;
1396 } else {
1397 /* this should never happen */
1398 if (p_fci_internal->fNextCab) {
1399 /* internal error */
1400 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1401 return FALSE;
1405 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1406 if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA1,0,SEEK_SET,&err,
1407 p_fci_internal->pv) !=0 ) {
1408 /* wrong return value */
1409 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1410 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1411 /* TODO error handling of err */
1412 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1413 /* TODO error handling of err */
1414 return FALSE;
1416 /* TODO error handling of err */
1418 /* save size of file CFDATA2 - required for the folder's offset to data */
1419 sizeFileCFDATA2old = p_fci_internal->sizeFileCFDATA2;
1421 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData+sizeof(CFDATA)))) {
1422 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1423 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1424 /* TODO error handling of err */
1425 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1426 /* TODO error handling of err */
1427 return FALSE;
1430 if(!fci_flushfolder_copy_cfdata(hfci, reserved, cbReserveCFData, pfnfcis, &err,
1431 handleCFDATA1new, &sizeFileCFDATA1new, &payload
1432 )) {
1433 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1434 /* TODO error handling of err */
1435 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1436 /* TODO error handling of err */
1437 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1438 /* TODO error handling of err */
1439 PFCI_FREE(hfci,reserved);
1440 return FALSE;
1443 PFCI_FREE(hfci,reserved);
1445 if(!fci_flushfolder_copy_cffolder(hfci, &err, cbReserveCFFolder,
1446 sizeFileCFDATA2old )) {
1447 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1448 /* TODO error handling of err */
1449 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1450 /* TODO error handling of err */
1451 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1452 /* TODO error handling of err */
1453 return FALSE;
1456 if(!fci_flushfolder_copy_cffile(hfci, &err, handleCFFILE1new,
1457 &sizeFileCFFILE1new, payload)) {
1458 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1459 /* TODO error handling of err */
1460 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1461 /* TODO error handling of err */
1462 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1463 /* TODO error handling of err */
1464 PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);
1465 /* TODO error handling of err */
1466 return FALSE;
1469 /* close and delete p_fci_internal->handleCFDATA1 */
1470 PFCI_CLOSE(hfci,p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
1471 /* TODO error handling of err */
1472 PFCI_DELETE(hfci,p_fci_internal->szFileNameCFDATA1,&err,p_fci_internal->pv);
1473 /* TODO error handling of err */
1475 /* put new CFDATA1 into hfci */
1476 memcpy(p_fci_internal->szFileNameCFDATA1,szFileNameCFDATA1new,
1477 CB_MAX_FILENAME);
1479 /* put CFDATA1 file handle */
1480 PFCI_INT(hfci)->handleCFDATA1 = handleCFDATA1new;
1481 /* set file size */
1482 PFCI_INT(hfci)->sizeFileCFDATA1 = sizeFileCFDATA1new;
1484 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1485 PFCI_CLOSE(hfci,p_fci_internal->handleCFFILE1,&err,PFCI_INT(hfci)->pv);
1486 /* TODO error handling of err */
1487 PFCI_DELETE(hfci,p_fci_internal->szFileNameCFFILE1,&err,p_fci_internal->pv);
1488 /* TODO error handling of err */
1490 /* put new CFFILE1 into hfci */
1491 memcpy(p_fci_internal->szFileNameCFFILE1,szFileNameCFFILE1new,
1492 CB_MAX_FILENAME);
1494 /* put CFFILE1 file handle */
1495 p_fci_internal->handleCFFILE1 = handleCFFILE1new;
1496 /* set file size */
1497 p_fci_internal->sizeFileCFFILE1 = sizeFileCFFILE1new;
1499 ++(p_fci_internal->cFolders);
1501 /* reset CFFolder specific information */
1502 p_fci_internal->cDataBlocks=0;
1503 p_fci_internal->cCompressedBytesInFolder=0;
1505 return TRUE;
1506 } /* end of fci_flush_folder */
1511 static BOOL fci_flush_cabinet(
1512 HFCI hfci,
1513 BOOL fGetNextCab,
1514 PFNFCIGETNEXTCABINET pfnfcignc,
1515 PFNFCISTATUS pfnfcis)
1517 int err;
1518 CFHEADER cfheader;
1519 struct {
1520 cab_UWORD cbCFHeader;
1521 cab_UBYTE cbCFFolder;
1522 cab_UBYTE cbCFData;
1523 } cfreserved;
1524 CFFOLDER cffolder;
1525 cab_ULONG read_result=0;
1526 int handleCABINET; /* file handle for cabinet */
1527 char szFileNameCABINET[CB_MAX_CAB_PATH+CB_MAX_CABINET_NAME];/* name buffer */
1528 UINT cbReserveCFHeader, cbReserveCFFolder, i;
1529 char* reserved;
1530 BOOL returntrue=FALSE;
1531 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
1533 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1535 /* when FCIFlushCabinet was or FCIAddFile hasn't been called */
1536 if( p_fci_internal->sizeFileCFFILE1==0 && fGetNextCab ) {
1537 returntrue=TRUE;
1540 if (!fci_flush_folder(hfci,fGetNextCab,pfnfcignc,pfnfcis)){
1541 /* TODO set error */
1542 return FALSE;
1545 if(returntrue) return TRUE;
1547 if ( (p_fci_internal->fSplitFolder && p_fci_internal->fNextCab==FALSE)||
1548 (p_fci_internal->sizeFileCFFOLDER==0 &&
1549 (p_fci_internal->sizeFileCFFILE1!=0 ||
1550 p_fci_internal->sizeFileCFFILE2!=0 )
1553 /* error */
1554 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1555 return FALSE;
1558 if( p_fci_internal->fNextCab ||
1559 p_fci_internal->fGetNextCabInVain ) {
1560 cbReserveCFFolder=p_fci_internal->oldCCAB.cbReserveCFFolder;
1561 cbReserveCFHeader=p_fci_internal->oldCCAB.cbReserveCFHeader;
1562 /* safety */
1563 if (strlen(p_fci_internal->oldCCAB.szCabPath)>=CB_MAX_CAB_PATH ||
1564 strlen(p_fci_internal->oldCCAB.szCab)>=CB_MAX_CABINET_NAME) {
1565 /* set error */
1566 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1567 return FALSE;
1569 /* get the full name of the cabinet */
1570 memcpy(szFileNameCABINET,p_fci_internal->oldCCAB.szCabPath,
1571 CB_MAX_CAB_PATH);
1572 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1573 p_fci_internal->oldCCAB.szCab, CB_MAX_CABINET_NAME);
1574 } else {
1575 cbReserveCFFolder=p_fci_internal->pccab->cbReserveCFFolder;
1576 cbReserveCFHeader=p_fci_internal->pccab->cbReserveCFHeader;
1577 /* safety */
1578 if (strlen(p_fci_internal->pccab->szCabPath)>=CB_MAX_CAB_PATH ||
1579 strlen(p_fci_internal->pccab->szCab)>=CB_MAX_CABINET_NAME) {
1580 /* set error */
1581 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1582 return FALSE;
1584 /* get the full name of the cabinet */
1585 memcpy(szFileNameCABINET,p_fci_internal->pccab->szCabPath,
1586 CB_MAX_CAB_PATH);
1587 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1588 p_fci_internal->pccab->szCab, CB_MAX_CABINET_NAME);
1591 memcpy(cfheader.signature,"!CAB",4);
1592 cfheader.reserved1=0;
1593 cfheader.cbCabinet= /* size of the cabinet file in bytes */
1594 sizeof(CFHEADER) +
1595 p_fci_internal->sizeFileCFFOLDER +
1596 p_fci_internal->sizeFileCFFILE2 +
1597 p_fci_internal->sizeFileCFDATA2;
1599 if (p_fci_internal->fPrevCab) {
1600 cfheader.cbCabinet+=strlen(p_fci_internal->szPrevCab)+1 +
1601 strlen(p_fci_internal->szPrevDisk)+1;
1603 if (p_fci_internal->fNextCab) {
1604 cfheader.cbCabinet+=strlen(p_fci_internal->pccab->szCab)+1 +
1605 strlen(p_fci_internal->pccab->szDisk)+1;
1607 if( p_fci_internal->fNextCab ||
1608 p_fci_internal->fGetNextCabInVain ) {
1609 cfheader.cbCabinet+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1610 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1611 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1612 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1613 cfheader.cbCabinet+=4;
1615 } else {
1616 cfheader.cbCabinet+=p_fci_internal->pccab->cbReserveCFHeader;
1617 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1618 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1619 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1620 cfheader.cbCabinet+=4;
1624 if( ( ( p_fci_internal->fNextCab ||
1625 p_fci_internal->fGetNextCabInVain ) &&
1626 cfheader.cbCabinet > p_fci_internal->oldCCAB.cb
1627 ) ||
1628 ( ( p_fci_internal->fNextCab==FALSE &&
1629 p_fci_internal->fGetNextCabInVain==FALSE ) &&
1630 cfheader.cbCabinet > p_fci_internal->pccab->cb
1634 fci_set_error( FCIERR_NONE, ERROR_MORE_DATA, TRUE );
1635 return FALSE;
1639 cfheader.reserved2=0;
1640 cfheader.coffFiles= /* offset to first CFFILE section */
1641 cfheader.cbCabinet - p_fci_internal->sizeFileCFFILE2 -
1642 p_fci_internal->sizeFileCFDATA2;
1644 cfheader.reserved3=0;
1645 cfheader.versionMinor=3;
1646 cfheader.versionMajor=1;
1647 /* number of CFFOLDER entries in the cabinet */
1648 cfheader.cFolders=p_fci_internal->cFolders;
1649 /* number of CFFILE entries in the cabinet */
1650 cfheader.cFiles=p_fci_internal->cFiles;
1651 cfheader.flags=0; /* 1=prev cab, 2=next cabinet, 4=reserved setions */
1653 if( p_fci_internal->fPrevCab ) {
1654 cfheader.flags = cfheadPREV_CABINET;
1657 if( p_fci_internal->fNextCab ) {
1658 cfheader.flags |= cfheadNEXT_CABINET;
1661 if( p_fci_internal->fNextCab ||
1662 p_fci_internal->fGetNextCabInVain ) {
1663 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1664 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1665 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1666 cfheader.flags |= cfheadRESERVE_PRESENT;
1668 cfheader.setID = p_fci_internal->oldCCAB.setID;
1669 cfheader.iCabinet = p_fci_internal->oldCCAB.iCab-1;
1670 } else {
1671 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1672 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1673 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1674 cfheader.flags |= cfheadRESERVE_PRESENT;
1676 cfheader.setID = p_fci_internal->pccab->setID;
1677 cfheader.iCabinet = p_fci_internal->pccab->iCab-1;
1680 /* create the cabinet */
1681 handleCABINET = PFCI_OPEN(hfci, szFileNameCABINET,
1682 33538, 384, &err, p_fci_internal->pv );
1683 if(handleCABINET==0){
1684 fci_set_error( FCIERR_CAB_FILE, ERROR_OPEN_FAILED, TRUE );
1685 return FALSE;
1687 /* TODO error checking of err */
1689 /* set little endian */
1690 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1691 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1692 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1693 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1694 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1695 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1696 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1697 cfheader.flags=fci_endian_uword(cfheader.flags);
1698 cfheader.setID=fci_endian_uword(cfheader.setID);
1699 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1701 /* write CFHEADER into cabinet file */
1702 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1703 &cfheader, /* memory buffer */
1704 sizeof(cfheader), /* number of bytes to copy */
1705 &err, p_fci_internal->pv) != sizeof(cfheader) ) {
1706 /* write error */
1707 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1708 return FALSE;
1710 /* TODO error handling of err */
1712 /* reset little endian */
1713 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1714 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1715 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1716 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1717 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1718 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1719 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1720 cfheader.flags=fci_endian_uword(cfheader.flags);
1721 cfheader.setID=fci_endian_uword(cfheader.setID);
1722 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1724 if( cfheader.flags & cfheadRESERVE_PRESENT ) {
1725 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1726 cfreserved.cbCFHeader = cbReserveCFHeader;
1727 cfreserved.cbCFFolder = cbReserveCFFolder;
1728 if( p_fci_internal->fNextCab ||
1729 p_fci_internal->fGetNextCabInVain ) {
1730 cfreserved.cbCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1731 } else {
1732 cfreserved.cbCFData = p_fci_internal->pccab->cbReserveCFData;
1735 /* set little endian */
1736 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1738 /* write reserved info into cabinet file */
1739 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1740 &cfreserved, /* memory buffer */
1741 sizeof(cfreserved), /* number of bytes to copy */
1742 &err, p_fci_internal->pv) != sizeof(cfreserved) ) {
1743 /* write error */
1744 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1745 return FALSE;
1747 /* TODO error handling of err */
1749 /* reset little endian */
1750 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1753 /* add optional reserved area */
1754 if (cbReserveCFHeader!=0) {
1755 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFHeader))) {
1756 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1757 return FALSE;
1759 for(i=0;i<cbReserveCFHeader;) {
1760 reserved[i++]='\0';
1762 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1763 reserved, /* memory buffer */
1764 cbReserveCFHeader, /* number of bytes to copy */
1765 &err, p_fci_internal->pv) != cbReserveCFHeader ) {
1766 PFCI_FREE(hfci, reserved);
1767 /* write error */
1768 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1769 return FALSE;
1771 /* TODO error handling of err */
1772 PFCI_FREE(hfci, reserved);
1775 if( cfheader.flags & cfheadPREV_CABINET ) {
1776 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1777 p_fci_internal->szPrevCab, /* memory buffer */
1778 strlen(p_fci_internal->szPrevCab)+1, /* number of bytes to copy */
1779 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevCab)+1 ) {
1780 /* write error */
1781 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1782 return FALSE;
1784 /* TODO error handling of err */
1786 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1787 p_fci_internal->szPrevDisk, /* memory buffer */
1788 strlen(p_fci_internal->szPrevDisk)+1, /* number of bytes to copy */
1789 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevDisk)+1 ) {
1790 /* write error */
1791 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1792 return FALSE;
1794 /* TODO error handling of err */
1797 if( cfheader.flags & cfheadNEXT_CABINET ) {
1798 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1799 p_fci_internal->pccab->szCab, /* memory buffer */
1800 strlen(p_fci_internal->pccab->szCab)+1, /* number of bytes to copy */
1801 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szCab)+1 ) {
1802 /* write error */
1803 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1804 return FALSE;
1806 /* TODO error handling of err */
1808 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1809 p_fci_internal->pccab->szDisk, /* memory buffer */
1810 strlen(p_fci_internal->pccab->szDisk)+1, /* number of bytes to copy */
1811 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szDisk)+1 ) {
1812 /* write error */
1813 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1814 return FALSE;
1816 /* TODO error handling of err */
1819 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1820 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFOLDER,
1821 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1822 /* wrong return value */
1823 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1824 return FALSE;
1826 /* TODO error handling of err */
1828 /* while not all CFFOLDER structures have been copied into the cabinet do */
1829 while(!FALSE) {
1830 /* use the variable read_result */
1831 /* read cffolder of p_fci_internal->handleCFFOLDER */
1832 read_result = PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* handle */
1833 &cffolder, /* memory buffer */
1834 sizeof(cffolder), /* number of bytes to copy */
1835 &err, p_fci_internal->pv);
1836 if( read_result != sizeof(cffolder) ) {
1837 if( read_result == 0 ) break;/*ALL CFFOLDER structures have been copied*/
1838 /* read error */
1839 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
1840 return FALSE;
1842 /* TODO error handling of err */
1844 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1845 cffolder.coffCabStart +=
1846 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
1847 sizeof(CFHEADER);
1848 if( p_fci_internal->fNextCab ||
1849 p_fci_internal->fGetNextCabInVain ) {
1850 cffolder.coffCabStart+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1851 } else {
1852 cffolder.coffCabStart+=p_fci_internal->pccab->cbReserveCFHeader;
1855 if (p_fci_internal->fPrevCab) {
1856 cffolder.coffCabStart += strlen(p_fci_internal->szPrevCab)+1 +
1857 strlen(p_fci_internal->szPrevDisk)+1;
1860 if (p_fci_internal->fNextCab) {
1861 cffolder.coffCabStart += strlen(p_fci_internal->oldCCAB.szCab)+1 +
1862 strlen(p_fci_internal->oldCCAB.szDisk)+1;
1865 if( p_fci_internal->fNextCab ||
1866 p_fci_internal->fGetNextCabInVain ) {
1867 cffolder.coffCabStart += p_fci_internal->oldCCAB.cbReserveCFHeader;
1868 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1869 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1870 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1871 cffolder.coffCabStart += 4;
1873 } else {
1874 cffolder.coffCabStart += p_fci_internal->pccab->cbReserveCFHeader;
1875 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1876 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1877 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1878 cffolder.coffCabStart += 4;
1882 /* set little endian */
1883 cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
1884 cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
1885 cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
1887 /* write cffolder to cabinet file */
1888 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1889 &cffolder, /* memory buffer */
1890 sizeof(cffolder), /* number of bytes to copy */
1891 &err, p_fci_internal->pv) != sizeof(cffolder) ) {
1892 /* write error */
1893 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1894 return FALSE;
1896 /* TODO error handling of err */
1898 /* reset little endian */
1899 cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
1900 cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
1901 cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
1903 /* add optional reserved area */
1905 /* This allocation and freeing at each CFFolder block is a bit */
1906 /* inefficent, but it's harder to forget about freeing the buffer :-). */
1907 /* Reserved areas are used seldom besides that... */
1908 if (cbReserveCFFolder!=0) {
1909 if(!(reserved = PFCI_ALLOC(hfci, cbReserveCFFolder))) {
1910 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1911 return FALSE;
1914 if( PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
1915 reserved, /* memory buffer */
1916 cbReserveCFFolder, /* number of bytes to copy */
1917 &err, p_fci_internal->pv) != cbReserveCFFolder ) {
1918 PFCI_FREE(hfci, reserved);
1919 /* read error */
1920 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
1921 return FALSE;
1923 /* TODO error handling of err */
1925 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1926 reserved, /* memory buffer */
1927 cbReserveCFFolder, /* number of bytes to copy */
1928 &err, p_fci_internal->pv) != cbReserveCFFolder ) {
1929 PFCI_FREE(hfci, reserved);
1930 /* write error */
1931 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1932 return FALSE;
1934 /* TODO error handling of err */
1936 PFCI_FREE(hfci, reserved);
1939 } /* END OF while */
1941 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1942 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE2,
1943 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1944 /* wrong return value */
1945 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1946 return FALSE;
1948 /* TODO error handling of err */
1950 /* while not all CFFILE structures have been copied to the cabinet do */
1951 while(!FALSE) {
1952 /* REUSE the variable read_result */
1953 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1954 /* read a block from p_fci_internal->handleCFFILE2 */
1955 read_result = PFCI_READ(hfci, p_fci_internal->handleCFFILE2 /* handle */,
1956 p_fci_internal->data_out, /* memory buffer */
1957 CB_MAX_CHUNK, /* number of bytes to copy */
1958 &err, p_fci_internal->pv);
1959 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
1960 /* TODO error handling of err */
1962 /* write the block to the cabinet file */
1963 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1964 p_fci_internal->data_out, /* memory buffer */
1965 read_result, /* number of bytes to copy */
1966 &err, p_fci_internal->pv) != read_result ) {
1967 /* write error */
1968 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1969 return FALSE;
1971 /* TODO error handling of err */
1973 if (p_fci_internal->fSplitFolder==FALSE) {
1974 p_fci_internal->statusFolderCopied = 0;
1975 /* TODO TEST THIS further */
1976 p_fci_internal->statusFolderTotal = p_fci_internal->sizeFileCFDATA2+
1977 p_fci_internal->sizeFileCFFILE2;
1979 p_fci_internal->statusFolderCopied += read_result;
1981 /* report status with pfnfcis about copied size of folder */
1982 if( (*pfnfcis)(statusFolder,
1983 p_fci_internal->statusFolderCopied, /* length of copied blocks */
1984 p_fci_internal->statusFolderTotal, /* total size of folder */
1985 p_fci_internal->pv) == -1) {
1986 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
1987 return FALSE;
1990 } /* END OF while */
1992 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1993 if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA2,
1994 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1995 /* wrong return value */
1996 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1997 return FALSE;
1999 /* TODO error handling of err */
2001 /* reset the number of folders for the next cabinet */
2002 p_fci_internal->cFolders=0;
2003 /* reset the number of files for the next cabinet */
2004 p_fci_internal->cFiles=0;
2006 /* while not all CFDATA structures have been copied to the cabinet do */
2007 while(!FALSE) {
2008 /* REUSE the variable read_result AGAIN */
2009 /* REUSE the buffer p_fci_internal->data_out AGAIN */
2010 /* read a block from p_fci_internal->handleCFDATA2 */
2011 read_result = PFCI_READ(hfci, p_fci_internal->handleCFDATA2 /* handle */,
2012 p_fci_internal->data_out, /* memory buffer */
2013 CB_MAX_CHUNK, /* number of bytes to copy */
2014 &err, p_fci_internal->pv);
2015 if( read_result == 0 ) break; /* ALL CFDATA structures have been copied */
2016 /* TODO error handling of err */
2018 /* write the block to the cabinet file */
2019 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
2020 p_fci_internal->data_out, /* memory buffer */
2021 read_result, /* number of bytes to copy */
2022 &err, p_fci_internal->pv) != read_result ) {
2023 /* write error */
2024 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
2025 return FALSE;
2027 /* TODO error handling of err */
2029 p_fci_internal->statusFolderCopied += read_result;
2030 /* report status with pfnfcis about copied size of folder */
2031 if( (*pfnfcis)(statusFolder,
2032 p_fci_internal->statusFolderCopied, /* length of copied blocks */
2033 p_fci_internal->statusFolderTotal, /* total size of folder */
2034 p_fci_internal->pv) == -1) {
2035 /* set error code and abort */
2036 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
2037 return FALSE;
2039 } /* END OF while */
2041 /* set seek of the cabinet file to 0 */
2042 if( PFCI_SEEK(hfci, handleCABINET,
2043 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
2044 /* wrong return value */
2045 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
2046 return FALSE;
2048 /* TODO error handling of err */
2050 /* write the signature "MSCF" into the cabinet file */
2051 memcpy( cfheader.signature, "MSCF", 4 );
2052 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
2053 &cfheader, /* memory buffer */
2054 4, /* number of bytes to copy */
2055 &err, p_fci_internal->pv) != 4 ) {
2056 /* wrtie error */
2057 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
2058 return FALSE;
2060 /* TODO error handling of err */
2062 /* close the cabinet file */
2063 PFCI_CLOSE(hfci,handleCABINET,&err,p_fci_internal->pv);
2064 /* TODO error handling of err */
2067 /* COPIED FROM FCIDestroy */
2069 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2070 /* TODO error handling of err */
2071 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,
2072 p_fci_internal->pv);
2073 /* TODO error handling of err */
2074 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2075 /* TODO error handling of err */
2076 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,
2077 p_fci_internal->pv);
2078 /* TODO error handling of err */
2079 PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
2080 /* TODO error handling of err */
2081 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,
2082 p_fci_internal->pv);
2083 /* TODO error handling of err */
2085 /* END OF copied from FCIDestroy */
2087 /* get 3 temporary files and open them */
2088 /* write names and handles to hfci */
2091 p_fci_internal->sizeFileCFDATA2 = 0;
2092 p_fci_internal->sizeFileCFFILE2 = 0;
2093 p_fci_internal->sizeFileCFFOLDER = 0;
2095 /* COPIED FROM FCICreate */
2097 /* CFDATA with checksum and ready to be copied into cabinet */
2098 if( !PFCI_GETTEMPFILE(hfci, p_fci_internal->szFileNameCFDATA2,
2099 CB_MAX_FILENAME)) {
2100 /* error handling */
2101 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2102 return FALSE;
2104 /* safety */
2105 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
2106 /* set error code and abort */
2107 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2108 return FALSE;
2110 p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
2111 p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, p_fci_internal->pv);
2112 /* check handle */
2113 if(p_fci_internal->handleCFDATA2==0){
2114 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
2115 return FALSE;
2117 /* TODO error checking of err */
2119 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2120 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
2121 CB_MAX_FILENAME)) {
2122 /* error handling */
2123 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2124 return FALSE;
2126 /* safety */
2127 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
2128 /* set error code and abort */
2129 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2130 return FALSE;
2132 p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
2133 p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, p_fci_internal->pv);
2134 /* check handle */
2135 if(p_fci_internal->handleCFFILE2==0){
2136 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
2137 return FALSE;
2139 /* TODO error checking of err */
2141 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2142 if (!PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,CB_MAX_FILENAME)) {
2143 /* error handling */
2144 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2145 return FALSE;
2147 /* safety */
2148 if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
2149 /* set error code and abort */
2150 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2151 return FALSE;
2153 p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
2154 p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, p_fci_internal->pv);
2155 /* check handle */
2156 if(p_fci_internal->handleCFFOLDER==0){
2157 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
2158 return FALSE;
2160 /* TODO error checking of err */
2162 /* END OF copied from FCICreate */
2165 /* TODO close and delete new files when return FALSE */
2168 /* report status with pfnfcis about copied size of folder */
2169 (*pfnfcis)(statusCabinet,
2170 p_fci_internal->estimatedCabinetSize, /* estimated cabinet file size */
2171 cfheader.cbCabinet /* real cabinet file size */, p_fci_internal->pv);
2173 p_fci_internal->fPrevCab=TRUE;
2174 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2175 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2177 if (p_fci_internal->fNextCab) {
2178 p_fci_internal->fNextCab=FALSE;
2180 if (p_fci_internal->sizeFileCFFILE1==0 && p_fci_internal->sizeFileCFDATA1!=0) {
2181 /* THIS CAN NEVER HAPPEN */
2182 /* set error code */
2183 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2184 return FALSE;
2187 /* COPIED FROM FCIAddFile and modified */
2189 /* REUSE the variable read_result */
2190 if (p_fci_internal->fGetNextCabInVain) {
2191 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader;
2192 if(p_fci_internal->sizeFileCFFILE1!=0) {
2193 read_result+=p_fci_internal->oldCCAB.cbReserveCFFolder;
2195 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2196 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2197 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2198 read_result+=4;
2200 } else {
2201 read_result=p_fci_internal->pccab->cbReserveCFHeader;
2202 if(p_fci_internal->sizeFileCFFILE1!=0) {
2203 read_result+=p_fci_internal->pccab->cbReserveCFFolder;
2205 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2206 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2207 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2208 read_result+=4;
2211 if ( p_fci_internal->fPrevCab ) {
2212 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2213 strlen(p_fci_internal->szPrevDisk)+1;
2215 read_result+= p_fci_internal->sizeFileCFDATA1 +
2216 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2217 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2218 sizeof(CFHEADER) +
2219 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2221 if( p_fci_internal->fNewPrevious ) {
2222 memcpy(p_fci_internal->szPrevCab, p_fci_internal->oldCCAB.szCab,
2223 CB_MAX_CABINET_NAME);
2224 memcpy(p_fci_internal->szPrevDisk, p_fci_internal->oldCCAB.szDisk,
2225 CB_MAX_DISK_NAME);
2226 p_fci_internal->fNewPrevious=FALSE;
2229 /* too much data for the maximum size of a cabinet */
2230 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2231 p_fci_internal->pccab->cb < read_result ) {
2232 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2235 /* Might be too much data for the maximum size of a cabinet.*/
2236 /* When any further data will be added later, it might not */
2237 /* be possible to flush the cabinet, because there might */
2238 /* not be enough space to store the name of the following */
2239 /* cabinet and name of the corresponding disk. */
2240 /* So take care of this and get the name of the next cabinet */
2241 if (p_fci_internal->fGetNextCabInVain==FALSE && (
2242 p_fci_internal->pccab->cb < read_result +
2243 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2244 )) {
2245 /* save CCAB */
2246 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2247 /* increment cabinet index */
2248 ++(p_fci_internal->pccab->iCab);
2249 /* get name of next cabinet */
2250 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2251 if (!(*pfnfcignc)(p_fci_internal->pccab,
2252 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2253 p_fci_internal->pv)) {
2254 /* error handling */
2255 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2256 return FALSE;
2258 /* Skip a few lines of code. This is caught by the next if. */
2259 p_fci_internal->fGetNextCabInVain=TRUE;
2262 /* too much data for cabinet */
2263 if (p_fci_internal->fGetNextCabInVain && (
2264 p_fci_internal->oldCCAB.cb < read_result +
2265 strlen(p_fci_internal->oldCCAB.szCab)+1+
2266 strlen(p_fci_internal->oldCCAB.szDisk)+1
2267 )) {
2268 p_fci_internal->fGetNextCabInVain=FALSE;
2269 p_fci_internal->fNextCab=TRUE;
2270 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2273 /* if the FolderThreshold has been reached flush the folder automatically */
2274 if( p_fci_internal->fGetNextCabInVain ) {
2275 if( p_fci_internal->cCompressedBytesInFolder >=
2276 p_fci_internal->oldCCAB.cbFolderThresh) {
2277 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2279 } else {
2280 if( p_fci_internal->cCompressedBytesInFolder >=
2281 p_fci_internal->pccab->cbFolderThresh) {
2282 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2286 /* END OF COPIED FROM FCIAddFile and modified */
2288 if( p_fci_internal->sizeFileCFFILE1>0 ) {
2289 if( !FCIFlushFolder(hfci, pfnfcignc, pfnfcis) ) return FALSE;
2290 p_fci_internal->fNewPrevious=TRUE;
2292 } else {
2293 p_fci_internal->fNewPrevious=FALSE;
2294 if( p_fci_internal->sizeFileCFFILE1>0 || p_fci_internal->sizeFileCFDATA1) {
2295 /* THIS MAY NEVER HAPPEN */
2296 /* set error structures */
2297 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2298 return FALSE;
2302 return TRUE;
2303 } /* end of fci_flush_cabinet */
2309 /***********************************************************************
2310 * FCIAddFile (CABINET.11)
2312 * FCIAddFile adds a file to the to be created cabinet file
2314 * PARAMS
2315 * hfci [I] An HFCI from FCICreate
2316 * pszSourceFile [I] A pointer to a C string which contains the name and
2317 * location of the file which will be added to the cabinet
2318 * pszFileName [I] A pointer to a C string which contains the name under
2319 * which the file will be stored in the cabinet
2320 * fExecute [I] A boolean value which indicates if the file should be
2321 * executed after extraction of self extracting
2322 * executables
2323 * pfnfcignc [I] A pointer to a function which gets information about
2324 * the next cabinet
2325 * pfnfcis [IO] A pointer to a function which will report status
2326 * information about the compression process
2327 * pfnfcioi [I] A pointer to a function which reports file attributes
2328 * and time and date information
2329 * typeCompress [I] Compression type
2331 * RETURNS
2332 * On success, returns TRUE
2333 * On failure, returns FALSE
2335 * INCLUDES
2336 * fci.h
2339 BOOL __cdecl FCIAddFile(
2340 HFCI hfci,
2341 char *pszSourceFile,
2342 char *pszFileName,
2343 BOOL fExecute,
2344 PFNFCIGETNEXTCABINET pfnfcignc,
2345 PFNFCISTATUS pfnfcis,
2346 PFNFCIGETOPENINFO pfnfcigoi,
2347 TCOMP typeCompress)
2349 int err;
2350 CFFILE cffile;
2351 cab_ULONG read_result;
2352 int file_handle;
2353 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2355 /* test hfci */
2356 if (!REALLY_IS_FCI(hfci)) {
2357 SetLastError(ERROR_INVALID_HANDLE);
2358 return FALSE;
2361 if ((!pszSourceFile) || (!pszFileName) || (!pfnfcignc) || (!pfnfcis) ||
2362 (!pfnfcigoi) || strlen(pszFileName)>=CB_MAX_FILENAME) {
2363 fci_set_error( FCIERR_NONE, ERROR_BAD_ARGUMENTS, TRUE );
2364 return FALSE;
2367 /* TODO check if pszSourceFile??? */
2369 if(p_fci_internal->fGetNextCabInVain && p_fci_internal->fNextCab) {
2370 /* internal error */
2371 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2372 return FALSE;
2375 if(p_fci_internal->fNextCab) {
2376 /* internal error */
2377 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2378 return FALSE;
2381 cffile.cbFile=0; /* size of the to be added file*/
2382 /* offset of the uncompressed file in the folder */
2383 cffile.uoffFolderStart=p_fci_internal->cDataBlocks*CAB_BLOCKMAX + p_fci_internal->cdata_in;
2384 /* number of folder in the cabinet or special 0=first */
2385 cffile.iFolder = p_fci_internal->cFolders;
2387 /* allocation of memory */
2388 if (p_fci_internal->data_in==NULL) {
2389 if (p_fci_internal->cdata_in!=0) {
2390 /* error handling */
2391 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2392 return FALSE;
2394 if (p_fci_internal->data_out!=NULL) {
2395 /* error handling */
2396 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2397 return FALSE;
2399 if(!(p_fci_internal->data_in = (char*)PFCI_ALLOC(hfci,CB_MAX_CHUNK))) {
2400 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
2401 return FALSE;
2403 if (p_fci_internal->data_out==NULL) {
2404 if(!(p_fci_internal->data_out = PFCI_ALLOC(hfci, 2 * CB_MAX_CHUNK))){
2405 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
2406 return FALSE;
2411 if (p_fci_internal->data_out==NULL) {
2412 PFCI_FREE(hfci,p_fci_internal->data_in);
2413 /* error handling */
2414 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2415 return FALSE;
2418 /* get information about the file */
2419 file_handle=(*pfnfcigoi)(pszSourceFile, &(cffile.date), &(cffile.time),
2420 &(cffile.attribs), &err, p_fci_internal->pv);
2421 /* check file_handle */
2422 if(file_handle==0){
2423 fci_set_error( FCIERR_OPEN_SRC, ERROR_OPEN_FAILED, TRUE );
2425 /* TODO error handling of err */
2427 if (fExecute) { cffile.attribs |= _A_EXEC; }
2429 /* REUSE the variable read_result */
2430 if (p_fci_internal->fGetNextCabInVain) {
2431 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2432 p_fci_internal->oldCCAB.cbReserveCFFolder;
2433 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2434 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2435 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2436 read_result+=4;
2438 } else {
2439 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2440 p_fci_internal->pccab->cbReserveCFFolder;
2441 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2442 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2443 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2444 read_result+=4;
2447 if ( p_fci_internal->fPrevCab ) {
2448 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2449 strlen(p_fci_internal->szPrevDisk)+1;
2451 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2452 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2453 strlen(p_fci_internal->pccab->szDisk)+1;
2456 read_result+= sizeof(CFFILE) + strlen(pszFileName)+1 +
2457 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2458 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2459 sizeof(CFHEADER) +
2460 sizeof(CFFOLDER); /* size of new CFFolder entry */
2462 /* Might be too much data for the maximum size of a cabinet.*/
2463 /* When any further data will be added later, it might not */
2464 /* be possible to flush the cabinet, because there might */
2465 /* not be enough space to store the name of the following */
2466 /* cabinet and name of the corresponding disk. */
2467 /* So take care of this and get the name of the next cabinet */
2468 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2469 p_fci_internal->fNextCab==FALSE &&
2470 ( p_fci_internal->pccab->cb < read_result +
2471 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2474 /* save CCAB */
2475 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2476 /* increment cabinet index */
2477 ++(p_fci_internal->pccab->iCab);
2478 /* get name of next cabinet */
2479 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2480 if (!(*pfnfcignc)(p_fci_internal->pccab,
2481 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2482 p_fci_internal->pv)) {
2483 /* error handling */
2484 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2485 return FALSE;
2487 /* Skip a few lines of code. This is caught by the next if. */
2488 p_fci_internal->fGetNextCabInVain=TRUE;
2491 if( p_fci_internal->fGetNextCabInVain &&
2492 p_fci_internal->fNextCab
2494 /* THIS CAN NEVER HAPPEN */
2495 /* set error code */
2496 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2497 return FALSE;
2500 /* too much data for cabinet */
2501 if( p_fci_internal->fGetNextCabInVain &&
2503 p_fci_internal->oldCCAB.cb < read_result +
2504 strlen(p_fci_internal->pccab->szCab)+1+
2505 strlen(p_fci_internal->pccab->szDisk)+1
2506 )) {
2507 p_fci_internal->fGetNextCabInVain=FALSE;
2508 p_fci_internal->fNextCab=TRUE;
2509 if(!fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis)) return FALSE;
2512 if( p_fci_internal->fNextCab ) {
2513 /* THIS MAY NEVER HAPPEN */
2514 /* set error code */
2515 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2516 return FALSE;
2519 /* read the contents of the file blockwise */
2520 while (!FALSE) {
2521 if (p_fci_internal->cdata_in > CAB_BLOCKMAX) {
2522 /* internal error */
2523 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2524 return FALSE;
2527 read_result = PFCI_READ(hfci, file_handle /* file handle */,
2528 (p_fci_internal->data_in + p_fci_internal->cdata_in) /* memory buffer */,
2529 (CAB_BLOCKMAX - p_fci_internal->cdata_in) /* number of bytes to copy */,
2530 &err, p_fci_internal->pv);
2531 /* TODO error handling of err */
2533 if( read_result==0 ) break;
2535 /* increment the block size */
2536 p_fci_internal->cdata_in += read_result;
2538 /* increment the file size */
2539 cffile.cbFile += read_result;
2541 if ( p_fci_internal->cdata_in > CAB_BLOCKMAX ) {
2542 /* report internal error */
2543 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2544 return FALSE;
2546 /* write a whole block */
2547 if ( p_fci_internal->cdata_in == CAB_BLOCKMAX ) {
2549 if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;
2553 /* close the file from FCIAddFile */
2554 PFCI_CLOSE(hfci,file_handle,&err,p_fci_internal->pv);
2555 /* TODO error handling of err */
2557 /* write cffile to p_fci_internal->handleCFFILE1 */
2558 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */
2559 &cffile, sizeof(cffile),&err, p_fci_internal->pv) != sizeof(cffile) ) {
2560 /* write error */
2561 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
2562 return FALSE;
2564 /* TODO error handling of err */
2566 p_fci_internal->sizeFileCFFILE1 += sizeof(cffile);
2568 /* append the name of file */
2569 if (strlen(pszFileName)>=CB_MAX_FILENAME) {
2570 /* IMPOSSIBLE */
2571 /* set error code */
2572 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2573 return FALSE;
2575 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */
2576 pszFileName, strlen(pszFileName)+1, &err, p_fci_internal->pv)
2577 != strlen(pszFileName)+1 ) {
2578 /* write error */
2579 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
2580 return FALSE;
2582 /* TODO error handling of err */
2584 p_fci_internal->sizeFileCFFILE1 += strlen(pszFileName)+1;
2586 /* REUSE the variable read_result */
2587 if (p_fci_internal->fGetNextCabInVain ||
2588 p_fci_internal->fNextCab
2590 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2591 p_fci_internal->oldCCAB.cbReserveCFFolder;
2592 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2593 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2594 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2595 read_result+=4;
2597 } else {
2598 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2599 p_fci_internal->pccab->cbReserveCFFolder;
2600 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2601 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2602 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2603 read_result+=4;
2606 if ( p_fci_internal->fPrevCab ) {
2607 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2608 strlen(p_fci_internal->szPrevDisk)+1;
2610 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2611 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2612 strlen(p_fci_internal->pccab->szDisk)+1;
2614 read_result+= p_fci_internal->sizeFileCFDATA1 +
2615 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2616 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2617 sizeof(CFHEADER) +
2618 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2620 /* too much data for the maximum size of a cabinet */
2621 /* (ignoring the unflushed data block) */
2622 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2623 p_fci_internal->fNextCab==FALSE && /* this is always the case */
2624 p_fci_internal->pccab->cb < read_result ) {
2625 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2628 /* Might be too much data for the maximum size of a cabinet.*/
2629 /* When any further data will be added later, it might not */
2630 /* be possible to flush the cabinet, because there might */
2631 /* not be enough space to store the name of the following */
2632 /* cabinet and name of the corresponding disk. */
2633 /* So take care of this and get the name of the next cabinet */
2634 /* (ignoring the unflushed data block) */
2635 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2636 p_fci_internal->fNextCab==FALSE &&
2637 ( p_fci_internal->pccab->cb < read_result +
2638 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2641 /* save CCAB */
2642 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2643 /* increment cabinet index */
2644 ++(p_fci_internal->pccab->iCab);
2645 /* get name of next cabinet */
2646 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2647 if (!(*pfnfcignc)(p_fci_internal->pccab,
2648 p_fci_internal->estimatedCabinetSize,/* estimated size of cab */
2649 p_fci_internal->pv)) {
2650 /* error handling */
2651 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2652 return FALSE;
2654 /* Skip a few lines of code. This is caught by the next if. */
2655 p_fci_internal->fGetNextCabInVain=TRUE;
2658 if( p_fci_internal->fGetNextCabInVain &&
2659 p_fci_internal->fNextCab
2661 /* THIS CAN NEVER HAPPEN */
2662 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2663 return FALSE;
2666 /* too much data for cabinet */
2667 if( (p_fci_internal->fGetNextCabInVain ||
2668 p_fci_internal->fNextCab) && (
2669 p_fci_internal->oldCCAB.cb < read_result +
2670 strlen(p_fci_internal->pccab->szCab)+1+
2671 strlen(p_fci_internal->pccab->szDisk)+1
2672 )) {
2674 p_fci_internal->fGetNextCabInVain=FALSE;
2675 p_fci_internal->fNextCab=TRUE;
2676 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2679 if( p_fci_internal->fNextCab ) {
2680 /* THIS MAY NEVER HAPPEN */
2681 /* set error code */
2682 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2683 return FALSE;
2686 /* if the FolderThreshold has been reached flush the folder automatically */
2687 if( p_fci_internal->fGetNextCabInVain ) {
2688 if( p_fci_internal->cCompressedBytesInFolder >=
2689 p_fci_internal->oldCCAB.cbFolderThresh) {
2690 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2692 } else {
2693 if( p_fci_internal->cCompressedBytesInFolder >=
2694 p_fci_internal->pccab->cbFolderThresh) {
2695 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2699 return TRUE;
2700 } /* end of FCIAddFile */
2706 /***********************************************************************
2707 * FCIFlushFolder (CABINET.12)
2709 * FCIFlushFolder completes the CFFolder structure under construction.
2711 * All further data which is added by FCIAddFile will be associateed to
2712 * the next CFFolder structure.
2714 * FCIFlushFolder will be called by FCIAddFile automatically if the
2715 * threshold (stored in the member cbFolderThresh of the CCAB structure
2716 * pccab passed to FCICreate) is exceeded.
2718 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2719 * any data will be written into the cabinet file.
2721 * PARAMS
2722 * hfci [I] An HFCI from FCICreate
2723 * pfnfcignc [I] A pointer to a function which gets information about
2724 * the next cabinet
2725 * pfnfcis [IO] A pointer to a function which will report status
2726 * information about the compression process
2728 * RETURNS
2729 * On success, returns TRUE
2730 * On failure, returns FALSE
2732 * INCLUDES
2733 * fci.h
2736 BOOL __cdecl FCIFlushFolder(
2737 HFCI hfci,
2738 PFNFCIGETNEXTCABINET pfnfcignc,
2739 PFNFCISTATUS pfnfcis)
2741 return fci_flush_folder(hfci,FALSE,pfnfcignc,pfnfcis);
2742 } /* end of FCIFlushFolder */
2746 /***********************************************************************
2747 * FCIFlushCabinet (CABINET.13)
2749 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2750 * into the cabinet file. If the maximum cabinet size (stored in the
2751 * member cb of the CCAB structure pccab passed to FCICreate) has been
2752 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2753 * The remaining data still has to be flushed manually by calling
2754 * FCIFlushCabinet.
2756 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2757 * NOT be called again. Then hfci has to be released by FCIDestroy.
2759 * PARAMS
2760 * hfci [I] An HFCI from FCICreate
2761 * fGetNextCab [I] Whether you want to add additional files to a
2762 * cabinet set (TRUE) or whether you want to
2763 * finalize it (FALSE)
2764 * pfnfcignc [I] A pointer to a function which gets information about
2765 * the next cabinet
2766 * pfnfcis [IO] A pointer to a function which will report status
2767 * information about the compression process
2769 * RETURNS
2770 * On success, returns TRUE
2771 * On failure, returns FALSE
2773 * INCLUDES
2774 * fci.h
2777 BOOL __cdecl FCIFlushCabinet(
2778 HFCI hfci,
2779 BOOL fGetNextCab,
2780 PFNFCIGETNEXTCABINET pfnfcignc,
2781 PFNFCISTATUS pfnfcis)
2783 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2785 if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2787 while( p_fci_internal->sizeFileCFFILE1>0 ||
2788 p_fci_internal->sizeFileCFFILE2>0 ) {
2789 if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2792 return TRUE;
2793 } /* end of FCIFlushCabinet */
2796 /***********************************************************************
2797 * FCIDestroy (CABINET.14)
2799 * Frees a handle created by FCICreate.
2800 * Only reason for failure would be an invalid handle.
2802 * PARAMS
2803 * hfci [I] The HFCI to free
2805 * RETURNS
2806 * TRUE for success
2807 * FALSE for failure
2809 BOOL __cdecl FCIDestroy(HFCI hfci)
2811 int err;
2812 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2813 if (REALLY_IS_FCI(hfci)) {
2815 /* before hfci can be removed all temporary files must be closed */
2816 /* and deleted */
2817 p_fci_internal->FCI_Intmagic = 0;
2819 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
2820 /* TODO error handling of err */
2821 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA1, &err,
2822 p_fci_internal->pv);
2823 /* TODO error handling of err */
2824 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE1,&err,p_fci_internal->pv);
2825 /* TODO error handling of err */
2826 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE1, &err,
2827 p_fci_internal->pv);
2828 /* TODO error handling of err */
2829 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2830 /* TODO error handling of err */
2831 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,
2832 p_fci_internal->pv);
2833 /* TODO error handling of err */
2834 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2835 /* TODO error handling of err */
2836 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,
2837 p_fci_internal->pv);
2838 /* TODO error handling of err */
2839 PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
2840 /* TODO error handling of err */
2841 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,
2842 p_fci_internal->pv);
2843 /* TODO error handling of err */
2845 /* data in and out buffers have to be removed */
2846 if (p_fci_internal->data_in!=NULL)
2847 PFCI_FREE(hfci, p_fci_internal->data_in);
2848 if (p_fci_internal->data_out!=NULL)
2849 PFCI_FREE(hfci, p_fci_internal->data_out);
2851 /* hfci can now be removed */
2852 PFCI_FREE(hfci, hfci);
2853 return TRUE;
2854 } else {
2855 SetLastError(ERROR_INVALID_HANDLE);
2856 return FALSE;
2859 } /* end of FCIDestroy */