ole32: Allocate memory for the generic composite moniker in CompositeMonikerImpl_Cons...
[wine/multimedia.git] / dlls / cabinet / fci.c
blobb8589973e76652c349ad2bf87fe77e5a65a23ad3
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
69 typedef struct {
70 cab_UBYTE signature[4]; /* !CAB for unfinished cabinets else MSCF */
71 cab_ULONG reserved1;
72 cab_ULONG cbCabinet; /* size of the cabinet file in bytes*/
73 cab_ULONG reserved2;
74 cab_ULONG coffFiles; /* offset to first CFFILE section */
75 cab_ULONG reserved3;
76 cab_UBYTE versionMinor; /* 3 */
77 cab_UBYTE versionMajor; /* 1 */
78 cab_UWORD cFolders; /* number of CFFOLDER entries in the cabinet*/
79 cab_UWORD cFiles; /* number of CFFILE entries in the cabinet*/
80 cab_UWORD flags; /* 1=prev cab, 2=next cabinet, 4=reserved setions*/
81 cab_UWORD setID; /* identification number of all cabinets in a set*/
82 cab_UWORD iCabinet; /* number of the cabinet in a set */
83 /* additional area if "flags" were set*/
84 } CFHEADER; /* minimum 36 bytes */
86 typedef struct {
87 cab_ULONG coffCabStart; /* offset to the folder's first CFDATA section */
88 cab_UWORD cCFData; /* number of this folder's CFDATA sections */
89 cab_UWORD typeCompress; /* compression type of data in CFDATA section*/
90 /* additional area if reserve flag was set */
91 } CFFOLDER; /* minumum 8 bytes */
93 typedef struct {
94 cab_ULONG cbFile; /* size of the uncompressed file in bytes */
95 cab_ULONG uoffFolderStart; /* offset of the uncompressed file in the folder */
96 cab_UWORD iFolder; /* number of folder in the cabinet 0=first */
97 /* for special values see below this structure*/
98 cab_UWORD date; /* last modification date*/
99 cab_UWORD time; /* last modification time*/
100 cab_UWORD attribs; /* DOS fat attributes and UTF indicator */
101 /* ... and a C string with the name of the file */
102 } CFFILE; /* 16 bytes + name of file */
105 typedef struct {
106 cab_ULONG csum; /* checksum of this entry*/
107 cab_UWORD cbData; /* number of compressed bytes */
108 cab_UWORD cbUncomp; /* number of bytes when data is uncompressed */
109 /* optional reserved area */
110 /* compressed data */
111 } CFDATA;
114 /***********************************************************************
115 * FCICreate (CABINET.10)
117 * FCICreate is provided with several callbacks and
118 * returns a handle which can be used to create cabinet files.
120 * PARAMS
121 * perf [IO] A pointer to an ERF structure. When FCICreate
122 * returns an error condition, error information may
123 * be found here as well as from GetLastError.
124 * pfnfiledest [I] A pointer to a function which is called when a file
125 * is placed. Only useful for subsequent cabinet files.
126 * pfnalloc [I] A pointer to a function which allocates ram. Uses
127 * the same interface as malloc.
128 * pfnfree [I] A pointer to a function which frees ram. Uses the
129 * same interface as free.
130 * pfnopen [I] A pointer to a function which opens a file. Uses
131 * the same interface as _open.
132 * pfnread [I] A pointer to a function which reads from a file into
133 * a caller-provided buffer. Uses the same interface
134 * as _read.
135 * pfnwrite [I] A pointer to a function which writes to a file from
136 * a caller-provided buffer. Uses the same interface
137 * as _write.
138 * pfnclose [I] A pointer to a function which closes a file handle.
139 * Uses the same interface as _close.
140 * pfnseek [I] A pointer to a function which seeks in a file.
141 * Uses the same interface as _lseek.
142 * pfndelete [I] A pointer to a function which deletes a file.
143 * pfnfcigtf [I] A pointer to a function which gets the name of a
144 * temporary file.
145 * pccab [I] A pointer to an initialized CCAB structure.
146 * pv [I] A pointer to an application-defined notification
147 * function which will be passed to other FCI functions
148 * as a parameter.
150 * RETURNS
151 * On success, returns an FCI handle of type HFCI.
152 * On failure, the NULL file handle is returned. Error
153 * info can be retrieved from perf.
155 * INCLUDES
156 * fci.h
159 HFCI __cdecl FCICreate(
160 PERF perf,
161 PFNFCIFILEPLACED pfnfiledest,
162 PFNFCIALLOC pfnalloc,
163 PFNFCIFREE pfnfree,
164 PFNFCIOPEN pfnopen,
165 PFNFCIREAD pfnread,
166 PFNFCIWRITE pfnwrite,
167 PFNFCICLOSE pfnclose,
168 PFNFCISEEK pfnseek,
169 PFNFCIDELETE pfndelete,
170 PFNFCIGETTEMPFILE pfnfcigtf,
171 PCCAB pccab,
172 void *pv)
174 HFCI hfci;
175 int err;
176 PFCI_Int p_fci_internal;
178 if ((!perf) || (!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||
179 (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||
180 (!pfnfcigtf) || (!pccab)) {
181 perf->erfOper = FCIERR_NONE;
182 perf->erfType = ERROR_BAD_ARGUMENTS;
183 perf->fError = TRUE;
185 SetLastError(ERROR_BAD_ARGUMENTS);
186 return NULL;
189 if (!((hfci = ((HFCI) (*pfnalloc)(sizeof(FCI_Int)))))) {
190 perf->erfOper = FCIERR_ALLOC_FAIL;
191 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
192 perf->fError = TRUE;
194 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
195 return NULL;
198 p_fci_internal=((PFCI_Int)(hfci));
199 p_fci_internal->FCI_Intmagic = FCI_INT_MAGIC;
200 p_fci_internal->perf = perf;
201 p_fci_internal->pfnfiledest = pfnfiledest;
202 p_fci_internal->pfnalloc = pfnalloc;
203 p_fci_internal->pfnfree = pfnfree;
204 p_fci_internal->pfnopen = pfnopen;
205 p_fci_internal->pfnread = pfnread;
206 p_fci_internal->pfnwrite = pfnwrite;
207 p_fci_internal->pfnclose = pfnclose;
208 p_fci_internal->pfnseek = pfnseek;
209 p_fci_internal->pfndelete = pfndelete;
210 p_fci_internal->pfnfcigtf = pfnfcigtf;
211 p_fci_internal->pccab = pccab;
212 p_fci_internal->fPrevCab = FALSE;
213 p_fci_internal->fNextCab = FALSE;
214 p_fci_internal->fSplitFolder = FALSE;
215 p_fci_internal->fGetNextCabInVain = FALSE;
216 p_fci_internal->pv = pv;
217 p_fci_internal->data_in = NULL;
218 p_fci_internal->cdata_in = 0;
219 p_fci_internal->data_out = NULL;
220 p_fci_internal->cCompressedBytesInFolder = 0;
221 p_fci_internal->cFolders = 0;
222 p_fci_internal->cFiles = 0;
223 p_fci_internal->cDataBlocks = 0;
224 p_fci_internal->sizeFileCFDATA1 = 0;
225 p_fci_internal->sizeFileCFFILE1 = 0;
226 p_fci_internal->sizeFileCFDATA2 = 0;
227 p_fci_internal->sizeFileCFFILE2 = 0;
228 p_fci_internal->sizeFileCFFOLDER = 0;
229 p_fci_internal->sizeFileCFFOLDER = 0;
230 p_fci_internal->fNewPrevious = FALSE;
231 p_fci_internal->estimatedCabinetSize = 0;
232 p_fci_internal->statusFolderTotal = 0;
234 memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
235 memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);
237 /* CFDATA */
238 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA1,
239 CB_MAX_FILENAME)) {
240 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
241 return FALSE;
243 /* safety */
244 if ( strlen(p_fci_internal->szFileNameCFDATA1) >= CB_MAX_FILENAME ) {
245 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
246 return FALSE;
249 p_fci_internal->handleCFDATA1 = PFCI_OPEN(hfci,
250 p_fci_internal->szFileNameCFDATA1, 34050, 384, &err, pv);
251 if(p_fci_internal->handleCFDATA1==0){
252 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
253 return FALSE;
255 /* TODO error checking of err */
257 /* array of all CFFILE in a folder */
258 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE1,
259 CB_MAX_FILENAME)) {
260 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
261 return FALSE;
263 /* safety */
264 if ( strlen(p_fci_internal->szFileNameCFFILE1) >= CB_MAX_FILENAME ) {
265 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
266 return FALSE;
268 p_fci_internal->handleCFFILE1 = PFCI_OPEN(hfci,
269 p_fci_internal->szFileNameCFFILE1, 34050, 384, &err, pv);
270 if(p_fci_internal->handleCFFILE1==0){
271 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
272 return FALSE;
274 /* TODO error checking of err */
276 /* CFDATA with checksum and ready to be copied into cabinet */
277 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA2,
278 CB_MAX_FILENAME)) {
279 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE);
280 return FALSE;
282 /* safety */
283 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
284 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
285 return FALSE;
287 p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
288 p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, pv);
289 if(p_fci_internal->handleCFDATA2==0){
290 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
291 return FALSE;
293 /* TODO error checking of err */
295 /* array of all CFFILE in a folder, ready to be copied into cabinet */
296 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
297 CB_MAX_FILENAME)) {
298 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
299 return FALSE;
301 /* safety */
302 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
303 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
304 return FALSE;
306 p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
307 p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, pv);
308 if(p_fci_internal->handleCFFILE2==0){
309 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
310 return FALSE;
312 /* TODO error checking of err */
314 /* array of all CFFILE in a folder, ready to be copied into cabinet */
315 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,
316 CB_MAX_FILENAME)) {
317 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
318 return FALSE;
320 /* safety */
321 if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
322 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
323 return FALSE;
325 p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
326 p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, pv);
327 if(p_fci_internal->handleCFFOLDER==0) {
328 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
329 return FALSE;
332 /* TODO close and delete new files when return FALSE */
333 /* TODO error checking of err */
335 return hfci;
336 } /* end of FCICreate */
343 static BOOL fci_flush_data_block (HFCI hfci, int* err,
344 PFNFCISTATUS pfnfcis) {
346 /* attention no hfci checks!!! */
347 /* attention no checks if there is data available!!! */
348 CFDATA data;
349 CFDATA* cfdata=&data;
350 char* reserved;
351 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
352 UINT cbReserveCFData=p_fci_internal->pccab->cbReserveCFData;
353 UINT i;
355 /* TODO compress the data of p_fci_internal->data_in */
356 /* and write it to p_fci_internal->data_out */
357 memcpy(p_fci_internal->data_out, p_fci_internal->data_in,
358 p_fci_internal->cdata_in /* number of bytes to copy */);
360 cfdata->csum=0; /* checksum has to be set later */
361 /* TODO set realsize of compressed data */
362 cfdata->cbData = p_fci_internal->cdata_in;
363 cfdata->cbUncomp = p_fci_internal->cdata_in;
365 /* write cfdata to p_fci_internal->handleCFDATA1 */
366 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
367 cfdata, sizeof(*cfdata), err, p_fci_internal->pv)
368 != sizeof(*cfdata) ) {
369 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
370 return FALSE;
372 /* TODO error handling of err */
374 p_fci_internal->sizeFileCFDATA1 += sizeof(*cfdata);
376 /* add optional reserved area */
378 /* This allocation and freeing at each CFData block is a bit */
379 /* inefficent, but it's harder to forget about freeing the buffer :-). */
380 /* Reserved areas are used seldom besides that... */
381 if (cbReserveCFData!=0) {
382 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData))) {
383 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
384 return FALSE;
386 for(i=0;i<cbReserveCFData;) {
387 reserved[i++]='\0';
389 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
390 reserved, /* memory buffer */
391 cbReserveCFData, /* number of bytes to copy */
392 err, p_fci_internal->pv) != cbReserveCFData ) {
393 PFCI_FREE(hfci, reserved);
394 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
395 return FALSE;
397 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
399 p_fci_internal->sizeFileCFDATA1 += cbReserveCFData;
400 PFCI_FREE(hfci, reserved);
403 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
404 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
405 p_fci_internal->data_out, /* memory buffer */
406 cfdata->cbData, /* number of bytes to copy */
407 err, p_fci_internal->pv) != cfdata->cbData) {
408 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
409 return FALSE;
411 /* TODO error handling of err */
413 p_fci_internal->sizeFileCFDATA1 += cfdata->cbData;
415 /* reset the offset */
416 p_fci_internal->cdata_in = 0;
417 p_fci_internal->cCompressedBytesInFolder += cfdata->cbData;
419 /* report status with pfnfcis about uncompressed and compressed file data */
420 if( (*pfnfcis)(statusFile, cfdata->cbData, cfdata->cbUncomp,
421 p_fci_internal->pv) == -1) {
422 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
423 return FALSE;
426 ++(p_fci_internal->cDataBlocks);
428 return TRUE;
429 } /* end of fci_flush_data_block */
435 static cab_ULONG fci_get_checksum(void *pv, UINT cb, CHECKSUM seed)
437 cab_ULONG csum;
438 cab_ULONG ul;
439 int cUlong;
440 BYTE *pb;
442 csum = seed;
443 cUlong = cb / 4;
444 pb = pv;
446 while (cUlong-- > 0) {
447 ul = *pb++;
448 ul |= (((cab_ULONG)(*pb++)) << 8);
449 ul |= (((cab_ULONG)(*pb++)) << 16);
450 ul |= (((cab_ULONG)(*pb++)) << 24);
452 csum ^= ul;
455 ul = 0;
456 switch (cb % 4) {
457 case 3:
458 ul |= (((ULONG)(*pb++)) << 16);
459 case 2:
460 ul |= (((ULONG)(*pb++)) << 8);
461 case 1:
462 ul |= *pb++;
463 default:
464 break;
466 csum ^= ul;
468 return csum;
469 } /* end of fci_get_checksum */
473 static BOOL fci_flushfolder_copy_cfdata(HFCI hfci, char* buffer, UINT cbReserveCFData,
474 PFNFCISTATUS pfnfcis, int* err, int handleCFDATA1new,
475 cab_ULONG* psizeFileCFDATA1new, cab_ULONG* payload)
477 cab_ULONG read_result;
478 CFDATA* pcfdata=(CFDATA*)buffer;
479 BOOL split_block=FALSE;
480 cab_UWORD savedUncomp=0;
481 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
483 *payload=0;
485 /* while not all CFDATAs have been copied do */
486 while(!FALSE) {
487 if( p_fci_internal->fNextCab ) {
488 if( split_block ) {
489 /* internal error should never happen */
490 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
491 return FALSE;
494 /* REUSE the variable read_result */
495 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
496 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
497 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
498 read_result=4;
499 } else {
500 read_result=0;
502 if (p_fci_internal->fPrevCab) {
503 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
504 strlen(p_fci_internal->szPrevDisk)+1;
506 /* No more CFDATA fits into the cabinet under construction */
507 /* So don't try to store more data into it */
508 if( p_fci_internal->fNextCab &&
509 (p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData +
510 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
511 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
512 sizeof(CFHEADER) +
513 read_result +
514 p_fci_internal->oldCCAB.cbReserveCFHeader +
515 sizeof(CFFOLDER) +
516 p_fci_internal->oldCCAB.cbReserveCFFolder +
517 strlen(p_fci_internal->pccab->szCab)+1 +
518 strlen(p_fci_internal->pccab->szDisk)+1
519 )) {
520 /* This may never be run for the first time the while loop is entered.
521 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
522 split_block=TRUE; /* In this case split_block is abused to store */
523 /* the complete data block into the next cabinet and not into the */
524 /* current one. Originally split_block is the indicator that a */
525 /* data block has been splitted across different cabinets. */
526 } else {
528 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
529 read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/*file handle*/
530 buffer, /* memory buffer */
531 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
532 err, p_fci_internal->pv);
533 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
534 if (read_result==0) break; /* ALL DATA has been copied */
535 /* read error */
536 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
537 return FALSE;
539 /* TODO error handling of err */
541 /* REUSE buffer p_fci_internal->data_out !!! */
542 /* read data from p_fci_internal->handleCFDATA1 to */
543 /* p_fci_internal->data_out */
544 if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
545 p_fci_internal->data_out /* memory buffer */,
546 pcfdata->cbData /* number of bytes to copy */,
547 err, p_fci_internal->pv) != pcfdata->cbData ) {
548 /* read error */
549 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
550 return FALSE;
552 /* TODO error handling of err */
554 /* if cabinet size is too large */
556 /* REUSE the variable read_result */
557 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
558 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
559 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
560 read_result=4;
561 } else {
562 read_result=0;
564 if (p_fci_internal->fPrevCab) {
565 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
566 strlen(p_fci_internal->szPrevDisk)+1;
569 /* Is cabinet with new CFDATA too large? Then data block has to be split */
570 if( p_fci_internal->fNextCab &&
571 (p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData +
572 pcfdata->cbData +
573 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
574 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
575 sizeof(CFHEADER) +
576 read_result +
577 p_fci_internal->oldCCAB.cbReserveCFHeader +
578 sizeof(CFFOLDER) + /* size of new CFFolder entry */
579 p_fci_internal->oldCCAB.cbReserveCFFolder +
580 strlen(p_fci_internal->pccab->szCab)+1 + /* name of next cabinet */
581 strlen(p_fci_internal->pccab->szDisk)+1 /* name of next disk */
582 )) {
583 /* REUSE read_result to save the size of the compressed data */
584 read_result=pcfdata->cbData;
585 /* Modify the size of the compressed data to store only a part of the */
586 /* data block into the current cabinet. This is done to prevent */
587 /* that the maximum cabinet size will be exceeded. The remainder */
588 /* will be stored into the next following cabinet. */
590 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
591 /* Substract everything except the size of the block of data */
592 /* to get it's actual size */
593 pcfdata->cbData = p_fci_internal->oldCCAB.cb - (
594 sizeof(CFDATA) + cbReserveCFData +
595 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
596 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
597 sizeof(CFHEADER) +
598 p_fci_internal->oldCCAB.cbReserveCFHeader +
599 sizeof(CFFOLDER) + /* set size of new CFFolder entry */
600 p_fci_internal->oldCCAB.cbReserveCFFolder );
601 /* substract the size of special header fields */
602 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
603 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
604 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
605 pcfdata->cbData-=4;
607 if (p_fci_internal->fPrevCab) {
608 pcfdata->cbData-=strlen(p_fci_internal->szPrevCab)+1 +
609 strlen(p_fci_internal->szPrevDisk)+1;
611 pcfdata->cbData-=strlen(p_fci_internal->pccab->szCab)+1 +
612 strlen(p_fci_internal->pccab->szDisk)+1;
614 savedUncomp = pcfdata->cbUncomp;
615 pcfdata->cbUncomp = 0; /* on splitted blocks of data this is zero */
617 /* if split_block==TRUE then the above while loop won't */
618 /* be executed again */
619 split_block=TRUE; /* split_block is the indicator that */
620 /* a data block has been splitted across */
621 /* diffentent cabinets.*/
624 /* This should never happen !!! */
625 if (pcfdata->cbData==0) {
626 /* set error */
627 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
628 return FALSE;
631 /* set little endian */
632 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
633 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
635 /* get checksum and write to cfdata.csum */
636 pcfdata->csum = fci_get_checksum( &(pcfdata->cbData),
637 sizeof(CFDATA)+cbReserveCFData -
638 sizeof(pcfdata->csum), fci_get_checksum( p_fci_internal->data_out, /*buffer*/
639 pcfdata->cbData, 0 ) );
641 /* set little endian */
642 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
644 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
645 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
646 buffer, /* memory buffer */
647 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
648 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
649 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
650 return FALSE;
652 /* TODO error handling of err */
654 p_fci_internal->sizeFileCFDATA2 += sizeof(CFDATA)+cbReserveCFData;
656 /* reset little endian */
657 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
658 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
659 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
661 /* write compressed data into p_fci_internal->handleCFDATA2 */
662 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
663 p_fci_internal->data_out, /* memory buffer */
664 pcfdata->cbData, /* number of bytes to copy */
665 err, p_fci_internal->pv) != pcfdata->cbData) {
666 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
667 return FALSE;
669 /* TODO error handling of err */
671 p_fci_internal->sizeFileCFDATA2 += pcfdata->cbData;
672 ++(p_fci_internal->cDataBlocks);
673 p_fci_internal->statusFolderCopied += pcfdata->cbData;
674 (*payload)+=pcfdata->cbUncomp;
675 /* if cabinet size too large and data has been split */
676 /* write the remainder of the data block to the new CFDATA1 file */
677 if( split_block ) { /* This does not include the */
678 /* abused one (just search for "abused" )*/
679 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
680 if (p_fci_internal->fNextCab==FALSE ) {
681 /* internal error */
682 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
683 return FALSE;
686 /* set cbData to the size of the remainder of the data block */
687 pcfdata->cbData = read_result - pcfdata->cbData;
688 /*recover former value of cfdata.cbData; read_result will be the offset*/
689 read_result -= pcfdata->cbData;
690 pcfdata->cbUncomp = savedUncomp;
692 /* reset checksum, it will be computed later */
693 pcfdata->csum=0;
695 /* write cfdata WITHOUT checksum to handleCFDATA1new */
696 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
697 buffer, /* memory buffer */
698 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
699 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
700 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
701 return FALSE;
703 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
705 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
707 /* write compressed data into handleCFDATA1new */
708 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
709 p_fci_internal->data_out + read_result, /* memory buffer + offset */
710 /* to last part of split data */
711 pcfdata->cbData, /* number of bytes to copy */
712 err, p_fci_internal->pv) != pcfdata->cbData) {
713 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
714 return FALSE;
716 /* TODO error handling of err */
718 p_fci_internal->statusFolderCopied += pcfdata->cbData;
720 *psizeFileCFDATA1new += pcfdata->cbData;
721 /* the two blocks of the split data block have been written */
722 /* don't reset split_data yet, because it is still needed see below */
725 /* report status with pfnfcis about copied size of folder */
726 if( (*pfnfcis)(statusFolder,
727 p_fci_internal->statusFolderCopied, /*cfdata.cbData(+previous ones)*/
728 p_fci_internal->statusFolderTotal, /* total folder size */
729 p_fci_internal->pv) == -1) {
730 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
731 return FALSE;
735 /* if cabinet size too large */
736 /* write the remaining data blocks to the new CFDATA1 file */
737 if ( split_block ) { /* This does include the */
738 /* abused one (just search for "abused" )*/
739 if (p_fci_internal->fNextCab==FALSE ) {
740 /* internal error */
741 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
742 return FALSE;
744 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
745 while(!FALSE) {
746 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
747 read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/* handle */
748 buffer, /* memory buffer */
749 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
750 err, p_fci_internal->pv);
751 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
752 if (read_result==0) break; /* ALL DATA has been copied */
753 /* read error */
754 fci_set_error(FCIERR_NONE, ERROR_READ_FAULT, TRUE );
755 return FALSE;
757 /* TODO error handling of err */
759 /* REUSE buffer p_fci_internal->data_out !!! */
760 /* read data from p_fci_internal->handleCFDATA1 to */
761 /* p_fci_internal->data_out */
762 if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
763 p_fci_internal->data_out /* memory buffer */,
764 pcfdata->cbData /* number of bytes to copy */,
765 err, p_fci_internal->pv) != pcfdata->cbData ) {
766 /* read error */
767 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE);
768 return FALSE;
770 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
772 /* write cfdata with checksum to handleCFDATA1new */
773 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
774 buffer, /* memory buffer */
775 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
776 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
777 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
778 return FALSE;
780 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
782 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
784 /* write compressed data into handleCFDATA1new */
785 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
786 p_fci_internal->data_out, /* memory buffer */
787 pcfdata->cbData, /* number of bytes to copy */
788 err, p_fci_internal->pv) != pcfdata->cbData) {
789 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
790 return FALSE;
792 /* TODO error handling of err */
794 *psizeFileCFDATA1new += pcfdata->cbData;
795 p_fci_internal->statusFolderCopied += pcfdata->cbData;
797 /* report status with pfnfcis about copied size of folder */
798 if( (*pfnfcis)(statusFolder,
799 p_fci_internal->statusFolderCopied,/*cfdata.cbData(+revious ones)*/
800 p_fci_internal->statusFolderTotal, /* total folder size */
801 p_fci_internal->pv) == -1) {
802 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
803 return FALSE;
806 } /* end of WHILE */
807 break; /* jump out of the next while loop */
808 } /* end of if( split_data ) */
809 } /* end of WHILE */
810 return TRUE;
811 } /* end of fci_flushfolder_copy_cfdata */
817 static BOOL fci_flushfolder_copy_cffolder(HFCI hfci, int* err, UINT cbReserveCFFolder,
818 cab_ULONG sizeFileCFDATA2old)
820 CFFOLDER cffolder;
821 UINT i;
822 char* reserved;
823 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
825 /* absolute offset cannot be set yet, because the size of cabinet header, */
826 /* the number of CFFOLDERs and the number of CFFILEs may change. */
827 /* Instead the size of all previous data blocks will be stored and */
828 /* the remainder of the offset will be added when the cabinet will be */
829 /* flushed to disk. */
830 /* This is exactly the way the original CABINET.DLL works!!! */
831 cffolder.coffCabStart=sizeFileCFDATA2old;
833 /* set the number of this folder's CFDATA sections */
834 cffolder.cCFData=p_fci_internal->cDataBlocks;
835 /* TODO set compression type */
836 cffolder.typeCompress = tcompTYPE_NONE;
838 /* write cffolder to p_fci_internal->handleCFFOLDER */
839 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
840 &cffolder, /* memory buffer */
841 sizeof(cffolder), /* number of bytes to copy */
842 err, p_fci_internal->pv) != sizeof(cffolder) ) {
843 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
844 return FALSE;
846 /* TODO error handling of err */
848 p_fci_internal->sizeFileCFFOLDER += sizeof(cffolder);
850 /* add optional reserved area */
851 if (cbReserveCFFolder!=0) {
852 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFFolder))) {
853 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
854 return FALSE;
856 for(i=0;i<cbReserveCFFolder;) {
857 reserved[i++]='\0';
859 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
860 reserved, /* memory buffer */
861 cbReserveCFFolder, /* number of bytes to copy */
862 err, p_fci_internal->pv) != cbReserveCFFolder ) {
863 PFCI_FREE(hfci, reserved);
864 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
865 return FALSE;
867 /* TODO error handling of err */
869 p_fci_internal->sizeFileCFFOLDER += cbReserveCFFolder;
871 PFCI_FREE(hfci, reserved);
873 return TRUE;
874 } /* end of fci_flushfolder_copy_cffolder */
880 static BOOL fci_flushfolder_copy_cffile(HFCI hfci, int* err, int handleCFFILE1new,
881 cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload)
883 CFFILE cffile;
884 cab_ULONG read_result;
885 cab_ULONG seek=0;
886 cab_ULONG sizeOfFiles=0, sizeOfFilesPrev;
887 BOOL may_be_prev=TRUE;
888 cab_ULONG cbFileRemainer=0;
889 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
890 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
891 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,0,SEEK_SET,err,
892 p_fci_internal->pv) !=0 ) {
893 /* wrong return value */
894 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
895 return FALSE;
897 /* TODO error handling of err */
899 /* while not all CFFILE structures have been copied do */
900 while(!FALSE) {
901 /* REUSE the variable read_result */
902 /* read data from p_fci_internal->handleCFFILE1 to cffile */
903 read_result = PFCI_READ(hfci,p_fci_internal->handleCFFILE1/* file handle */,
904 &cffile, /* memory buffer */
905 sizeof(cffile), /* number of bytes to copy */
906 err, p_fci_internal->pv);
907 if( read_result != sizeof(cffile) ) {
908 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
909 /* read error */
910 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
911 return FALSE;
913 /* TODO error handling of err */
915 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
916 /* position. I don't know why so I'll just omit it */
918 /* read the filename from p_fci_internal->handleCFFILE1 */
919 /* REUSE the variable read_result AGAIN */
920 /* REUSE the memory buffer PFCI(hfci)->data_out */
921 if( PFCI_READ(hfci, p_fci_internal->handleCFFILE1 /*file handle*/,
922 p_fci_internal->data_out, /* memory buffer */
923 CB_MAX_FILENAME, /* number of bytes to copy */
924 err, p_fci_internal->pv) <2) {
925 /* read error */
926 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
927 return FALSE;
929 /* TODO maybe other checks of read_result */
930 /* TODO error handling of err */
932 /* safety */
933 if( strlen(p_fci_internal->data_out)>=CB_MAX_FILENAME ) {
934 /* set error code internal error */
935 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
936 return FALSE;
939 seek+=sizeof(cffile) + strlen(p_fci_internal->data_out)+1;
941 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
942 /* i.e. seek to the next CFFILE area */
943 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,
944 seek, /* seek position*/
945 SEEK_SET ,err,
946 p_fci_internal->pv)
947 != seek) {
948 /* wrong return value */
949 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
950 return FALSE;
952 /* TODO error handling of err */
954 /* fnfilfnfildest: placed file on cabinet */
955 if (p_fci_internal->fNextCab ||
956 p_fci_internal->fGetNextCabInVain) {
957 PFCI_FILEPLACED( hfci, &(p_fci_internal->oldCCAB),
958 p_fci_internal->data_out, /* the file name*/
959 cffile.cbFile, /* file size */
960 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
961 p_fci_internal->pv
963 } else {
964 PFCI_FILEPLACED( hfci, p_fci_internal->pccab,
965 p_fci_internal->data_out, /* the file name*/
966 cffile.cbFile, /* file size */
967 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
968 p_fci_internal->pv
972 /* Check special iFolder values */
973 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
974 p_fci_internal->fPrevCab==FALSE ) {
975 /* THIS MAY NEVER HAPPEN */
976 /* set error code */
977 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
978 return FALSE;
980 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
981 cffile.iFolder==cffileCONTINUED_TO_NEXT ) {
982 /* THIS MAY NEVER HAPPEN */
983 /* set error code */
984 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
985 return FALSE;
987 if( may_be_prev && cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
988 may_be_prev=FALSE;
990 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && may_be_prev==FALSE ) {
991 /* THIS MAY NEVER HAPPEN */
992 /* set error code */
993 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
994 return FALSE;
996 if( cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
997 may_be_prev=FALSE;
1000 sizeOfFilesPrev=sizeOfFiles;
1001 /* Set complete size of all processed files */
1002 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
1003 p_fci_internal->cbFileRemainer!=0
1005 sizeOfFiles+=p_fci_internal->cbFileRemainer;
1006 p_fci_internal->cbFileRemainer=0;
1007 } else {
1008 sizeOfFiles+=cffile.cbFile;
1011 /* Check if spanned file fits into this cabinet folder */
1012 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && sizeOfFiles>payload ) {
1013 cffile.iFolder=cffileCONTINUED_PREV_AND_NEXT;
1014 } else
1016 /* Check if file doesn't fit into this cabinet folder */
1017 if( sizeOfFiles>payload ) {
1018 cffile.iFolder=cffileCONTINUED_TO_NEXT;
1021 /* set little endian */
1022 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1023 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1024 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1025 cffile.date=fci_endian_uword(cffile.date);
1026 cffile.time=fci_endian_uword(cffile.time);
1027 cffile.attribs=fci_endian_uword(cffile.attribs);
1029 /* write cffile to p_fci_internal->handleCFFILE2 */
1030 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */
1031 &cffile, /* memory buffer */
1032 sizeof(cffile), /* number of bytes to copy */
1033 err, p_fci_internal->pv) != sizeof(cffile) ) {
1034 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1035 return FALSE;
1037 /* TODO error handling of err */
1039 p_fci_internal->sizeFileCFFILE2 += sizeof(cffile);
1041 /* reset little endian */
1042 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1043 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1044 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1045 cffile.date=fci_endian_uword(cffile.date);
1046 cffile.time=fci_endian_uword(cffile.time);
1047 cffile.attribs=fci_endian_uword(cffile.attribs);
1049 /* write file name to p_fci_internal->handleCFFILE2 */
1050 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */
1051 p_fci_internal->data_out, /* memory buffer */
1052 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1053 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1054 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1055 return FALSE;
1057 /* TODO error handling of err */
1059 p_fci_internal->sizeFileCFFILE2 += strlen(p_fci_internal->data_out)+1;
1061 /* cFiles is used to count all files of a cabinet */
1062 ++(p_fci_internal->cFiles);
1064 /* This is only true for files which will be written into the */
1065 /* next cabinet of the spanning folder */
1066 if( sizeOfFiles>payload ) {
1068 /* Files which data will be partially written into the current cabinet */
1069 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
1070 cffile.iFolder==cffileCONTINUED_TO_NEXT
1072 if( sizeOfFilesPrev<=payload ) {
1073 /* The size of the uncompressed, data of a spanning file in a */
1074 /* spanning data */
1075 cbFileRemainer=sizeOfFiles-payload;
1077 cffile.iFolder=cffileCONTINUED_FROM_PREV;
1078 } else {
1079 cffile.iFolder=0;
1082 /* write cffile into handleCFFILE1new */
1083 if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */
1084 &cffile, /* memory buffer */
1085 sizeof(cffile), /* number of bytes to copy */
1086 err, p_fci_internal->pv) != sizeof(cffile) ) {
1087 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1088 return FALSE;
1090 /* TODO error handling of err */
1092 *psizeFileCFFILE1new += sizeof(cffile);
1093 /* write name of file into handleCFFILE1new */
1094 if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */
1095 p_fci_internal->data_out, /* memory buffer */
1096 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1097 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1098 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1099 return FALSE;
1101 /* TODO error handling of err */
1103 *psizeFileCFFILE1new += strlen(p_fci_internal->data_out)+1;
1106 } /* END OF while */
1107 p_fci_internal->cbFileRemainer=cbFileRemainer;
1108 return TRUE;
1109 } /* end of fci_flushfolder_copy_cffile */
1114 static BOOL fci_flush_folder(
1115 HFCI hfci,
1116 BOOL fGetNextCab,
1117 PFNFCIGETNEXTCABINET pfnfcignc,
1118 PFNFCISTATUS pfnfcis)
1120 int err;
1121 int handleCFDATA1new; /* handle for new temp file */
1122 char szFileNameCFDATA1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1123 int handleCFFILE1new; /* handle for new temp file */
1124 char szFileNameCFFILE1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1125 UINT cbReserveCFData, cbReserveCFFolder;
1126 char* reserved;
1127 cab_ULONG sizeFileCFDATA1new=0;
1128 cab_ULONG sizeFileCFFILE1new=0;
1129 cab_ULONG sizeFileCFDATA2old;
1130 cab_ULONG payload;
1131 cab_ULONG read_result;
1132 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
1134 /* test hfci */
1135 if (!REALLY_IS_FCI(hfci)) {
1136 SetLastError(ERROR_INVALID_HANDLE);
1137 return FALSE;
1140 if ((!pfnfcignc) || (!pfnfcis)) {
1141 fci_set_error( FCIERR_NONE, ERROR_BAD_ARGUMENTS, TRUE );
1142 return FALSE;
1145 if( p_fci_internal->fGetNextCabInVain &&
1146 p_fci_internal->fNextCab ){
1147 /* internal error */
1148 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1149 return FALSE;
1152 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1153 /* this function will return TRUE */
1154 if( p_fci_internal->sizeFileCFFILE1 == 0 ) {
1155 if ( p_fci_internal->sizeFileCFDATA1 != 0 ) {
1156 /* error handling */
1157 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1158 return FALSE;
1160 return TRUE;
1163 if (p_fci_internal->data_in==NULL || p_fci_internal->data_out==NULL ) {
1164 /* error handling */
1165 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1166 return FALSE;
1169 /* FCIFlushFolder has already been called... */
1170 if (p_fci_internal->fSplitFolder && p_fci_internal->sizeFileCFFILE2!=0) {
1171 return TRUE;
1174 /* This can be set already, because it makes only a difference */
1175 /* when the current function exits with return FALSE */
1176 p_fci_internal->fSplitFolder=FALSE;
1179 if( p_fci_internal->fGetNextCabInVain ||
1180 p_fci_internal->fNextCab ){
1181 cbReserveCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1182 cbReserveCFFolder = p_fci_internal->oldCCAB.cbReserveCFFolder;
1183 } else {
1184 cbReserveCFData = p_fci_internal->pccab->cbReserveCFData;
1185 cbReserveCFFolder = p_fci_internal->pccab->cbReserveCFFolder;
1188 /* START of COPY */
1189 /* if there is data in p_fci_internal->data_in */
1190 if (p_fci_internal->cdata_in!=0) {
1192 if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;
1195 /* reset to get the number of data blocks of this folder which are */
1196 /* actually in this cabinet ( at least partially ) */
1197 p_fci_internal->cDataBlocks=0;
1199 if ( p_fci_internal->fNextCab ||
1200 p_fci_internal->fGetNextCabInVain ) {
1201 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader+
1202 p_fci_internal->oldCCAB.cbReserveCFFolder;
1203 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1204 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1205 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1206 read_result+=4;
1208 } else {
1209 read_result= p_fci_internal->pccab->cbReserveCFHeader+
1210 p_fci_internal->pccab->cbReserveCFFolder;
1211 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1212 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1213 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1214 read_result+=4;
1217 if (p_fci_internal->fPrevCab) {
1218 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1219 strlen(p_fci_internal->szPrevDisk)+1;
1221 if (p_fci_internal->fNextCab) {
1222 read_result+=strlen(p_fci_internal->pccab->szCab)+1 +
1223 strlen(p_fci_internal->pccab->szDisk)+1;
1226 p_fci_internal->statusFolderTotal = sizeof(CFHEADER)+read_result+
1227 sizeof(CFFOLDER) + p_fci_internal->sizeFileCFFILE2+
1228 p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1+
1229 p_fci_internal->sizeFileCFDATA1 + p_fci_internal->sizeFileCFFOLDER;
1230 p_fci_internal->statusFolderCopied = 0;
1232 /* report status with pfnfcis about copied size of folder */
1233 if( (*pfnfcis)(statusFolder, p_fci_internal->statusFolderCopied,
1234 p_fci_internal->statusFolderTotal, /* TODO total folder size */
1235 p_fci_internal->pv) == -1) {
1236 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
1237 return FALSE;
1240 /* get a new temp file */
1241 if(!PFCI_GETTEMPFILE(hfci,szFileNameCFDATA1new,CB_MAX_FILENAME)) {
1242 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1243 return FALSE;
1245 /* safety */
1246 if ( strlen(szFileNameCFDATA1new) >= CB_MAX_FILENAME ) {
1247 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1248 return FALSE;
1250 handleCFDATA1new = PFCI_OPEN(hfci,szFileNameCFDATA1new,34050,384,&err,
1251 p_fci_internal->pv);
1252 if(handleCFDATA1new==0){
1253 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
1254 return FALSE;
1256 /* TODO error handling of err */
1260 /* get a new temp file */
1261 if(!PFCI_GETTEMPFILE(hfci,szFileNameCFFILE1new,CB_MAX_FILENAME)) {
1262 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1263 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1264 /* TODO error handling of err */
1265 return FALSE;
1267 /* safety */
1268 if ( strlen(szFileNameCFFILE1new) >= CB_MAX_FILENAME ) {
1269 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1270 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1271 /* TODO error handling of err */
1272 return FALSE;
1274 handleCFFILE1new = PFCI_OPEN(hfci,szFileNameCFFILE1new,34050,384,&err,
1275 p_fci_internal->pv);
1276 if(handleCFFILE1new==0){
1277 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
1278 return FALSE;
1280 /* TODO error handling of err */
1282 /* USE the variable read_result */
1283 if ( p_fci_internal->fNextCab ||
1284 p_fci_internal->fGetNextCabInVain ) {
1285 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader;
1286 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1287 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1288 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1289 read_result+=4;
1291 } else {
1292 read_result= p_fci_internal->pccab->cbReserveCFHeader;
1293 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1294 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1295 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1296 read_result+=4;
1299 if (p_fci_internal->fPrevCab) {
1300 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1301 strlen(p_fci_internal->szPrevDisk)+1;
1303 read_result+= sizeof(CFHEADER) + p_fci_internal->sizeFileCFDATA2 +
1304 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER;
1306 if(p_fci_internal->sizeFileCFFILE1!=0) {
1307 read_result+= sizeof(CFFOLDER)+p_fci_internal->pccab->cbReserveCFFolder;
1310 /* Check if multiple cabinets have to be created. */
1312 /* Might be too much data for the maximum allowed cabinet size.*/
1313 /* When any further data will be added later, it might not */
1314 /* be possible to flush the cabinet, because there might */
1315 /* not be enough space to store the name of the following */
1316 /* cabinet and name of the corresponding disk. */
1317 /* So take care of this and get the name of the next cabinet */
1318 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1319 p_fci_internal->fNextCab==FALSE &&
1322 p_fci_internal->pccab->cb < read_result +
1323 p_fci_internal->sizeFileCFDATA1 +
1324 p_fci_internal->sizeFileCFFILE1 +
1325 CB_MAX_CABINET_NAME + /* next cabinet name */
1326 CB_MAX_DISK_NAME /* next disk name */
1327 ) || fGetNextCab
1330 /* save CCAB */
1331 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
1332 /* increment cabinet index */
1333 ++(p_fci_internal->pccab->iCab);
1334 /* get name of next cabinet */
1335 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
1336 if (!(*pfnfcignc)(p_fci_internal->pccab,
1337 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
1338 p_fci_internal->pv)) {
1339 /* error handling */
1340 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1341 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1342 /* TODO error handling of err */
1343 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1344 /* TODO error handling of err */
1345 return FALSE;
1348 /* Skip a few lines of code. This is catched by the next if. */
1349 p_fci_internal->fGetNextCabInVain=TRUE;
1352 /* too much data for cabinet */
1353 if( (p_fci_internal->fGetNextCabInVain ||
1354 p_fci_internal->fNextCab ) &&
1357 p_fci_internal->oldCCAB.cb < read_result +
1358 p_fci_internal->sizeFileCFDATA1 +
1359 p_fci_internal->sizeFileCFFILE1 +
1360 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1361 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1362 ) || fGetNextCab
1365 p_fci_internal->fGetNextCabInVain=FALSE;
1366 p_fci_internal->fNextCab=TRUE;
1368 /* return FALSE if there is not enough space left*/
1369 /* this should never happen */
1370 if (p_fci_internal->oldCCAB.cb <=
1371 p_fci_internal->sizeFileCFFILE1 +
1372 read_result +
1373 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1374 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1377 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1378 /* TODO error handling of err */
1379 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1380 /* TODO error handling of err */
1382 /* close and delete p_fci_internal->handleCFFILE1 */
1383 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1384 /* TODO error handling of err */
1385 PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);
1386 /* TODO error handling of err */
1388 return FALSE;
1391 /* the folder will be split across cabinets */
1392 p_fci_internal->fSplitFolder=TRUE;
1394 } else {
1395 /* this should never happen */
1396 if (p_fci_internal->fNextCab) {
1397 /* internal error */
1398 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1399 return FALSE;
1403 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1404 if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA1,0,SEEK_SET,&err,
1405 p_fci_internal->pv) !=0 ) {
1406 /* wrong return value */
1407 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1408 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1409 /* TODO error handling of err */
1410 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1411 /* TODO error handling of err */
1412 return FALSE;
1414 /* TODO error handling of err */
1416 /* save size of file CFDATA2 - required for the folder's offset to data */
1417 sizeFileCFDATA2old = p_fci_internal->sizeFileCFDATA2;
1419 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData+sizeof(CFDATA)))) {
1420 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1421 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1422 /* TODO error handling of err */
1423 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1424 /* TODO error handling of err */
1425 return FALSE;
1428 if(!fci_flushfolder_copy_cfdata(hfci, reserved, cbReserveCFData, pfnfcis, &err,
1429 handleCFDATA1new, &sizeFileCFDATA1new, &payload
1430 )) {
1431 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1432 /* TODO error handling of err */
1433 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1434 /* TODO error handling of err */
1435 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1436 /* TODO error handling of err */
1437 PFCI_FREE(hfci,reserved);
1438 return FALSE;
1441 PFCI_FREE(hfci,reserved);
1443 if(!fci_flushfolder_copy_cffolder(hfci, &err, cbReserveCFFolder,
1444 sizeFileCFDATA2old )) {
1445 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1446 /* TODO error handling of err */
1447 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1448 /* TODO error handling of err */
1449 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1450 /* TODO error handling of err */
1451 return FALSE;
1454 if(!fci_flushfolder_copy_cffile(hfci, &err, handleCFFILE1new,
1455 &sizeFileCFFILE1new, payload)) {
1456 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1457 /* TODO error handling of err */
1458 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1459 /* TODO error handling of err */
1460 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1461 /* TODO error handling of err */
1462 PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);
1463 /* TODO error handling of err */
1464 return FALSE;
1467 /* close and delete p_fci_internal->handleCFDATA1 */
1468 PFCI_CLOSE(hfci,p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
1469 /* TODO error handling of err */
1470 PFCI_DELETE(hfci,p_fci_internal->szFileNameCFDATA1,&err,p_fci_internal->pv);
1471 /* TODO error handling of err */
1473 /* put new CFDATA1 into hfci */
1474 memcpy(p_fci_internal->szFileNameCFDATA1,szFileNameCFDATA1new,
1475 CB_MAX_FILENAME);
1477 /* put CFDATA1 file handle */
1478 PFCI_INT(hfci)->handleCFDATA1 = handleCFDATA1new;
1479 /* set file size */
1480 PFCI_INT(hfci)->sizeFileCFDATA1 = sizeFileCFDATA1new;
1482 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1483 PFCI_CLOSE(hfci,p_fci_internal->handleCFFILE1,&err,PFCI_INT(hfci)->pv);
1484 /* TODO error handling of err */
1485 PFCI_DELETE(hfci,p_fci_internal->szFileNameCFFILE1,&err,p_fci_internal->pv);
1486 /* TODO error handling of err */
1488 /* put new CFFILE1 into hfci */
1489 memcpy(p_fci_internal->szFileNameCFFILE1,szFileNameCFFILE1new,
1490 CB_MAX_FILENAME);
1492 /* put CFFILE1 file handle */
1493 p_fci_internal->handleCFFILE1 = handleCFFILE1new;
1494 /* set file size */
1495 p_fci_internal->sizeFileCFFILE1 = sizeFileCFFILE1new;
1497 ++(p_fci_internal->cFolders);
1499 /* reset CFFolder specific information */
1500 p_fci_internal->cDataBlocks=0;
1501 p_fci_internal->cCompressedBytesInFolder=0;
1503 return TRUE;
1504 } /* end of fci_flush_folder */
1509 static BOOL fci_flush_cabinet(
1510 HFCI hfci,
1511 BOOL fGetNextCab,
1512 PFNFCIGETNEXTCABINET pfnfcignc,
1513 PFNFCISTATUS pfnfcis)
1515 int err;
1516 CFHEADER cfheader;
1517 struct {
1518 cab_UWORD cbCFHeader;
1519 cab_UBYTE cbCFFolder;
1520 cab_UBYTE cbCFData;
1521 } cfreserved;
1522 CFFOLDER cffolder;
1523 cab_ULONG read_result=0;
1524 int handleCABINET; /* file handle for cabinet */
1525 char szFileNameCABINET[CB_MAX_CAB_PATH+CB_MAX_CABINET_NAME];/* name buffer */
1526 UINT cbReserveCFHeader, cbReserveCFFolder, i;
1527 char* reserved;
1528 BOOL returntrue=FALSE;
1529 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
1531 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1533 /* when FCIFlushCabinet was or FCIAddFile hasn't been called */
1534 if( p_fci_internal->sizeFileCFFILE1==0 && fGetNextCab ) {
1535 returntrue=TRUE;
1538 if (!fci_flush_folder(hfci,fGetNextCab,pfnfcignc,pfnfcis)){
1539 /* TODO set error */
1540 return FALSE;
1543 if(returntrue) return TRUE;
1545 if ( (p_fci_internal->fSplitFolder && p_fci_internal->fNextCab==FALSE)||
1546 (p_fci_internal->sizeFileCFFOLDER==0 &&
1547 (p_fci_internal->sizeFileCFFILE1!=0 ||
1548 p_fci_internal->sizeFileCFFILE2!=0 )
1551 /* error */
1552 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1553 return FALSE;
1556 if( p_fci_internal->fNextCab ||
1557 p_fci_internal->fGetNextCabInVain ) {
1558 cbReserveCFFolder=p_fci_internal->oldCCAB.cbReserveCFFolder;
1559 cbReserveCFHeader=p_fci_internal->oldCCAB.cbReserveCFHeader;
1560 /* safety */
1561 if (strlen(p_fci_internal->oldCCAB.szCabPath)>=CB_MAX_CAB_PATH ||
1562 strlen(p_fci_internal->oldCCAB.szCab)>=CB_MAX_CABINET_NAME) {
1563 /* set error */
1564 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1565 return FALSE;
1567 /* get the full name of the cabinet */
1568 memcpy(szFileNameCABINET,p_fci_internal->oldCCAB.szCabPath,
1569 CB_MAX_CAB_PATH);
1570 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1571 p_fci_internal->oldCCAB.szCab, CB_MAX_CABINET_NAME);
1572 } else {
1573 cbReserveCFFolder=p_fci_internal->pccab->cbReserveCFFolder;
1574 cbReserveCFHeader=p_fci_internal->pccab->cbReserveCFHeader;
1575 /* safety */
1576 if (strlen(p_fci_internal->pccab->szCabPath)>=CB_MAX_CAB_PATH ||
1577 strlen(p_fci_internal->pccab->szCab)>=CB_MAX_CABINET_NAME) {
1578 /* set error */
1579 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1580 return FALSE;
1582 /* get the full name of the cabinet */
1583 memcpy(szFileNameCABINET,p_fci_internal->pccab->szCabPath,
1584 CB_MAX_CAB_PATH);
1585 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1586 p_fci_internal->pccab->szCab, CB_MAX_CABINET_NAME);
1589 memcpy(cfheader.signature,"!CAB",4);
1590 cfheader.reserved1=0;
1591 cfheader.cbCabinet= /* size of the cabinet file in bytes */
1592 sizeof(CFHEADER) +
1593 p_fci_internal->sizeFileCFFOLDER +
1594 p_fci_internal->sizeFileCFFILE2 +
1595 p_fci_internal->sizeFileCFDATA2;
1597 if (p_fci_internal->fPrevCab) {
1598 cfheader.cbCabinet+=strlen(p_fci_internal->szPrevCab)+1 +
1599 strlen(p_fci_internal->szPrevDisk)+1;
1601 if (p_fci_internal->fNextCab) {
1602 cfheader.cbCabinet+=strlen(p_fci_internal->pccab->szCab)+1 +
1603 strlen(p_fci_internal->pccab->szDisk)+1;
1605 if( p_fci_internal->fNextCab ||
1606 p_fci_internal->fGetNextCabInVain ) {
1607 cfheader.cbCabinet+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1608 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1609 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1610 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1611 cfheader.cbCabinet+=4;
1613 } else {
1614 cfheader.cbCabinet+=p_fci_internal->pccab->cbReserveCFHeader;
1615 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1616 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1617 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1618 cfheader.cbCabinet+=4;
1622 if( ( ( p_fci_internal->fNextCab ||
1623 p_fci_internal->fGetNextCabInVain ) &&
1624 cfheader.cbCabinet > p_fci_internal->oldCCAB.cb
1625 ) ||
1626 ( ( p_fci_internal->fNextCab==FALSE &&
1627 p_fci_internal->fGetNextCabInVain==FALSE ) &&
1628 cfheader.cbCabinet > p_fci_internal->pccab->cb
1632 fci_set_error( FCIERR_NONE, ERROR_MORE_DATA, TRUE );
1633 return FALSE;
1637 cfheader.reserved2=0;
1638 cfheader.coffFiles= /* offset to first CFFILE section */
1639 cfheader.cbCabinet - p_fci_internal->sizeFileCFFILE2 -
1640 p_fci_internal->sizeFileCFDATA2;
1642 cfheader.reserved3=0;
1643 cfheader.versionMinor=3;
1644 cfheader.versionMajor=1;
1645 /* number of CFFOLDER entries in the cabinet */
1646 cfheader.cFolders=p_fci_internal->cFolders;
1647 /* number of CFFILE entries in the cabinet */
1648 cfheader.cFiles=p_fci_internal->cFiles;
1649 cfheader.flags=0; /* 1=prev cab, 2=next cabinet, 4=reserved setions */
1651 if( p_fci_internal->fPrevCab ) {
1652 cfheader.flags = cfheadPREV_CABINET;
1655 if( p_fci_internal->fNextCab ) {
1656 cfheader.flags |= cfheadNEXT_CABINET;
1659 if( p_fci_internal->fNextCab ||
1660 p_fci_internal->fGetNextCabInVain ) {
1661 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1662 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1663 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1664 cfheader.flags |= cfheadRESERVE_PRESENT;
1666 cfheader.setID = p_fci_internal->oldCCAB.setID;
1667 cfheader.iCabinet = p_fci_internal->oldCCAB.iCab-1;
1668 } else {
1669 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1670 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1671 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1672 cfheader.flags |= cfheadRESERVE_PRESENT;
1674 cfheader.setID = p_fci_internal->pccab->setID;
1675 cfheader.iCabinet = p_fci_internal->pccab->iCab-1;
1678 /* create the cabinet */
1679 handleCABINET = PFCI_OPEN(hfci, szFileNameCABINET,
1680 33538, 384, &err, p_fci_internal->pv );
1681 if(handleCABINET==0){
1682 fci_set_error( FCIERR_CAB_FILE, ERROR_OPEN_FAILED, TRUE );
1683 return FALSE;
1685 /* TODO error checking of err */
1687 /* set little endian */
1688 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1689 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1690 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1691 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1692 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1693 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1694 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1695 cfheader.flags=fci_endian_uword(cfheader.flags);
1696 cfheader.setID=fci_endian_uword(cfheader.setID);
1697 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1699 /* write CFHEADER into cabinet file */
1700 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1701 &cfheader, /* memory buffer */
1702 sizeof(cfheader), /* number of bytes to copy */
1703 &err, p_fci_internal->pv) != sizeof(cfheader) ) {
1704 /* write error */
1705 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1706 return FALSE;
1708 /* TODO error handling of err */
1710 /* reset little endian */
1711 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1712 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1713 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1714 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1715 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1716 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1717 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1718 cfheader.flags=fci_endian_uword(cfheader.flags);
1719 cfheader.setID=fci_endian_uword(cfheader.setID);
1720 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1722 if( cfheader.flags & cfheadRESERVE_PRESENT ) {
1723 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1724 cfreserved.cbCFHeader = cbReserveCFHeader;
1725 cfreserved.cbCFFolder = cbReserveCFFolder;
1726 if( p_fci_internal->fNextCab ||
1727 p_fci_internal->fGetNextCabInVain ) {
1728 cfreserved.cbCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1729 } else {
1730 cfreserved.cbCFData = p_fci_internal->pccab->cbReserveCFData;
1733 /* set little endian */
1734 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1736 /* write reserved info into cabinet file */
1737 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1738 &cfreserved, /* memory buffer */
1739 sizeof(cfreserved), /* number of bytes to copy */
1740 &err, p_fci_internal->pv) != sizeof(cfreserved) ) {
1741 /* write error */
1742 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1743 return FALSE;
1745 /* TODO error handling of err */
1747 /* reset little endian */
1748 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1751 /* add optional reserved area */
1752 if (cbReserveCFHeader!=0) {
1753 if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFHeader))) {
1754 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1755 return FALSE;
1757 for(i=0;i<cbReserveCFHeader;) {
1758 reserved[i++]='\0';
1760 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1761 reserved, /* memory buffer */
1762 cbReserveCFHeader, /* number of bytes to copy */
1763 &err, p_fci_internal->pv) != cbReserveCFHeader ) {
1764 PFCI_FREE(hfci, reserved);
1765 /* write error */
1766 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1767 return FALSE;
1769 /* TODO error handling of err */
1770 PFCI_FREE(hfci, reserved);
1773 if( cfheader.flags & cfheadPREV_CABINET ) {
1774 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1775 p_fci_internal->szPrevCab, /* memory buffer */
1776 strlen(p_fci_internal->szPrevCab)+1, /* number of bytes to copy */
1777 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevCab)+1 ) {
1778 /* write error */
1779 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1780 return FALSE;
1782 /* TODO error handling of err */
1784 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1785 p_fci_internal->szPrevDisk, /* memory buffer */
1786 strlen(p_fci_internal->szPrevDisk)+1, /* number of bytes to copy */
1787 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevDisk)+1 ) {
1788 /* write error */
1789 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1790 return FALSE;
1792 /* TODO error handling of err */
1795 if( cfheader.flags & cfheadNEXT_CABINET ) {
1796 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1797 p_fci_internal->pccab->szCab, /* memory buffer */
1798 strlen(p_fci_internal->pccab->szCab)+1, /* number of bytes to copy */
1799 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szCab)+1 ) {
1800 /* write error */
1801 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1802 return FALSE;
1804 /* TODO error handling of err */
1806 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1807 p_fci_internal->pccab->szDisk, /* memory buffer */
1808 strlen(p_fci_internal->pccab->szDisk)+1, /* number of bytes to copy */
1809 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szDisk)+1 ) {
1810 /* write error */
1811 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1812 return FALSE;
1814 /* TODO error handling of err */
1817 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1818 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFOLDER,
1819 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1820 /* wrong return value */
1821 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1822 return FALSE;
1824 /* TODO error handling of err */
1826 /* while not all CFFOLDER structures have been copied into the cabinet do */
1827 while(!FALSE) {
1828 /* use the variable read_result */
1829 /* read cffolder of p_fci_internal->handleCFFOLDER */
1830 read_result = PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* handle */
1831 &cffolder, /* memory buffer */
1832 sizeof(cffolder), /* number of bytes to copy */
1833 &err, p_fci_internal->pv);
1834 if( read_result != sizeof(cffolder) ) {
1835 if( read_result == 0 ) break;/*ALL CFFOLDER structures have been copied*/
1836 /* read error */
1837 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
1838 return FALSE;
1840 /* TODO error handling of err */
1842 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1843 cffolder.coffCabStart +=
1844 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
1845 sizeof(CFHEADER);
1846 if( p_fci_internal->fNextCab ||
1847 p_fci_internal->fGetNextCabInVain ) {
1848 cffolder.coffCabStart+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1849 } else {
1850 cffolder.coffCabStart+=p_fci_internal->pccab->cbReserveCFHeader;
1853 if (p_fci_internal->fPrevCab) {
1854 cffolder.coffCabStart += strlen(p_fci_internal->szPrevCab)+1 +
1855 strlen(p_fci_internal->szPrevDisk)+1;
1858 if (p_fci_internal->fNextCab) {
1859 cffolder.coffCabStart += strlen(p_fci_internal->oldCCAB.szCab)+1 +
1860 strlen(p_fci_internal->oldCCAB.szDisk)+1;
1863 if( p_fci_internal->fNextCab ||
1864 p_fci_internal->fGetNextCabInVain ) {
1865 cffolder.coffCabStart += p_fci_internal->oldCCAB.cbReserveCFHeader;
1866 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1867 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1868 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1869 cffolder.coffCabStart += 4;
1871 } else {
1872 cffolder.coffCabStart += p_fci_internal->pccab->cbReserveCFHeader;
1873 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1874 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1875 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1876 cffolder.coffCabStart += 4;
1880 /* set little endian */
1881 cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
1882 cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
1883 cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
1885 /* write cffolder to cabinet file */
1886 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1887 &cffolder, /* memory buffer */
1888 sizeof(cffolder), /* number of bytes to copy */
1889 &err, p_fci_internal->pv) != sizeof(cffolder) ) {
1890 /* write error */
1891 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1892 return FALSE;
1894 /* TODO error handling of err */
1896 /* reset little endian */
1897 cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
1898 cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
1899 cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
1901 /* add optional reserved area */
1903 /* This allocation and freeing at each CFFolder block is a bit */
1904 /* inefficent, but it's harder to forget about freeing the buffer :-). */
1905 /* Reserved areas are used seldom besides that... */
1906 if (cbReserveCFFolder!=0) {
1907 if(!(reserved = PFCI_ALLOC(hfci, cbReserveCFFolder))) {
1908 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1909 return FALSE;
1912 if( PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
1913 reserved, /* memory buffer */
1914 cbReserveCFFolder, /* number of bytes to copy */
1915 &err, p_fci_internal->pv) != cbReserveCFFolder ) {
1916 PFCI_FREE(hfci, reserved);
1917 /* read error */
1918 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
1919 return FALSE;
1921 /* TODO error handling of err */
1923 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1924 reserved, /* memory buffer */
1925 cbReserveCFFolder, /* number of bytes to copy */
1926 &err, p_fci_internal->pv) != cbReserveCFFolder ) {
1927 PFCI_FREE(hfci, reserved);
1928 /* write error */
1929 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1930 return FALSE;
1932 /* TODO error handling of err */
1934 PFCI_FREE(hfci, reserved);
1937 } /* END OF while */
1939 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1940 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE2,
1941 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1942 /* wrong return value */
1943 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1944 return FALSE;
1946 /* TODO error handling of err */
1948 /* while not all CFFILE structures have been copied to the cabinet do */
1949 while(!FALSE) {
1950 /* REUSE the variable read_result */
1951 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1952 /* read a block from p_fci_internal->handleCFFILE2 */
1953 read_result = PFCI_READ(hfci, p_fci_internal->handleCFFILE2 /* handle */,
1954 p_fci_internal->data_out, /* memory buffer */
1955 CB_MAX_CHUNK, /* number of bytes to copy */
1956 &err, p_fci_internal->pv);
1957 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
1958 /* TODO error handling of err */
1960 /* write the block to the cabinet file */
1961 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1962 p_fci_internal->data_out, /* memory buffer */
1963 read_result, /* number of bytes to copy */
1964 &err, p_fci_internal->pv) != read_result ) {
1965 /* write error */
1966 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1967 return FALSE;
1969 /* TODO error handling of err */
1971 if (p_fci_internal->fSplitFolder==FALSE) {
1972 p_fci_internal->statusFolderCopied = 0;
1973 /* TODO TEST THIS further */
1974 p_fci_internal->statusFolderTotal = p_fci_internal->sizeFileCFDATA2+
1975 p_fci_internal->sizeFileCFFILE2;
1977 p_fci_internal->statusFolderCopied += read_result;
1979 /* report status with pfnfcis about copied size of folder */
1980 if( (*pfnfcis)(statusFolder,
1981 p_fci_internal->statusFolderCopied, /* length of copied blocks */
1982 p_fci_internal->statusFolderTotal, /* total size of folder */
1983 p_fci_internal->pv) == -1) {
1984 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
1985 return FALSE;
1988 } /* END OF while */
1990 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1991 if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA2,
1992 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1993 /* wrong return value */
1994 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1995 return FALSE;
1997 /* TODO error handling of err */
1999 /* reset the number of folders for the next cabinet */
2000 p_fci_internal->cFolders=0;
2001 /* reset the number of files for the next cabinet */
2002 p_fci_internal->cFiles=0;
2004 /* while not all CFDATA structures have been copied to the cabinet do */
2005 while(!FALSE) {
2006 /* REUSE the variable read_result AGAIN */
2007 /* REUSE the buffer p_fci_internal->data_out AGAIN */
2008 /* read a block from p_fci_internal->handleCFDATA2 */
2009 read_result = PFCI_READ(hfci, p_fci_internal->handleCFDATA2 /* handle */,
2010 p_fci_internal->data_out, /* memory buffer */
2011 CB_MAX_CHUNK, /* number of bytes to copy */
2012 &err, p_fci_internal->pv);
2013 if( read_result == 0 ) break; /* ALL CFDATA structures have been copied */
2014 /* TODO error handling of err */
2016 /* write the block to the cabinet file */
2017 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
2018 p_fci_internal->data_out, /* memory buffer */
2019 read_result, /* number of bytes to copy */
2020 &err, p_fci_internal->pv) != read_result ) {
2021 /* write error */
2022 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
2023 return FALSE;
2025 /* TODO error handling of err */
2027 p_fci_internal->statusFolderCopied += read_result;
2028 /* report status with pfnfcis about copied size of folder */
2029 if( (*pfnfcis)(statusFolder,
2030 p_fci_internal->statusFolderCopied, /* length of copied blocks */
2031 p_fci_internal->statusFolderTotal, /* total size of folder */
2032 p_fci_internal->pv) == -1) {
2033 /* set error code and abort */
2034 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
2035 return FALSE;
2037 } /* END OF while */
2039 /* set seek of the cabinet file to 0 */
2040 if( PFCI_SEEK(hfci, handleCABINET,
2041 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
2042 /* wrong return value */
2043 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
2044 return FALSE;
2046 /* TODO error handling of err */
2048 /* write the signature "MSCF" into the cabinet file */
2049 memcpy( cfheader.signature, "MSCF", 4 );
2050 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
2051 &cfheader, /* memory buffer */
2052 4, /* number of bytes to copy */
2053 &err, p_fci_internal->pv) != 4 ) {
2054 /* wrtie error */
2055 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
2056 return FALSE;
2058 /* TODO error handling of err */
2060 /* close the cabinet file */
2061 PFCI_CLOSE(hfci,handleCABINET,&err,p_fci_internal->pv);
2062 /* TODO error handling of err */
2065 /* COPIED FROM FCIDestroy */
2067 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2068 /* TODO error handling of err */
2069 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,
2070 p_fci_internal->pv);
2071 /* TODO error handling of err */
2072 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2073 /* TODO error handling of err */
2074 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,
2075 p_fci_internal->pv);
2076 /* TODO error handling of err */
2077 PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
2078 /* TODO error handling of err */
2079 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,
2080 p_fci_internal->pv);
2081 /* TODO error handling of err */
2083 /* END OF copied from FCIDestroy */
2085 /* get 3 temporary files and open them */
2086 /* write names and handles to hfci */
2089 p_fci_internal->sizeFileCFDATA2 = 0;
2090 p_fci_internal->sizeFileCFFILE2 = 0;
2091 p_fci_internal->sizeFileCFFOLDER = 0;
2093 /* COPIED FROM FCICreate */
2095 /* CFDATA with checksum and ready to be copied into cabinet */
2096 if( !PFCI_GETTEMPFILE(hfci, p_fci_internal->szFileNameCFDATA2,
2097 CB_MAX_FILENAME)) {
2098 /* error handling */
2099 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2100 return FALSE;
2102 /* safety */
2103 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
2104 /* set error code and abort */
2105 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2106 return FALSE;
2108 p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
2109 p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, p_fci_internal->pv);
2110 /* check handle */
2111 if(p_fci_internal->handleCFDATA2==0){
2112 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
2113 return FALSE;
2115 /* TODO error checking of err */
2117 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2118 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
2119 CB_MAX_FILENAME)) {
2120 /* error handling */
2121 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2122 return FALSE;
2124 /* safety */
2125 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
2126 /* set error code and abort */
2127 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2128 return FALSE;
2130 p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
2131 p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, p_fci_internal->pv);
2132 /* check handle */
2133 if(p_fci_internal->handleCFFILE2==0){
2134 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
2135 return FALSE;
2137 /* TODO error checking of err */
2139 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2140 if (!PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,CB_MAX_FILENAME)) {
2141 /* error handling */
2142 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2143 return FALSE;
2145 /* safety */
2146 if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
2147 /* set error code and abort */
2148 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2149 return FALSE;
2151 p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
2152 p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, p_fci_internal->pv);
2153 /* check handle */
2154 if(p_fci_internal->handleCFFOLDER==0){
2155 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
2156 return FALSE;
2158 /* TODO error checking of err */
2160 /* END OF copied from FCICreate */
2163 /* TODO close and delete new files when return FALSE */
2166 /* report status with pfnfcis about copied size of folder */
2167 (*pfnfcis)(statusCabinet,
2168 p_fci_internal->estimatedCabinetSize, /* estimated cabinet file size */
2169 cfheader.cbCabinet /* real cabinet file size */, p_fci_internal->pv);
2171 p_fci_internal->fPrevCab=TRUE;
2172 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2173 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2175 if (p_fci_internal->fNextCab) {
2176 p_fci_internal->fNextCab=FALSE;
2178 if (p_fci_internal->sizeFileCFFILE1==0 && p_fci_internal->sizeFileCFDATA1!=0) {
2179 /* THIS CAN NEVER HAPPEN */
2180 /* set error code */
2181 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2182 return FALSE;
2185 /* COPIED FROM FCIAddFile and modified */
2187 /* REUSE the variable read_result */
2188 if (p_fci_internal->fGetNextCabInVain) {
2189 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader;
2190 if(p_fci_internal->sizeFileCFFILE1!=0) {
2191 read_result+=p_fci_internal->oldCCAB.cbReserveCFFolder;
2193 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2194 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2195 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2196 read_result+=4;
2198 } else {
2199 read_result=p_fci_internal->pccab->cbReserveCFHeader;
2200 if(p_fci_internal->sizeFileCFFILE1!=0) {
2201 read_result+=p_fci_internal->pccab->cbReserveCFFolder;
2203 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2204 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2205 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2206 read_result+=4;
2209 if ( p_fci_internal->fPrevCab ) {
2210 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2211 strlen(p_fci_internal->szPrevDisk)+1;
2213 read_result+= p_fci_internal->sizeFileCFDATA1 +
2214 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2215 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2216 sizeof(CFHEADER) +
2217 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2219 if( p_fci_internal->fNewPrevious ) {
2220 memcpy(p_fci_internal->szPrevCab, p_fci_internal->oldCCAB.szCab,
2221 CB_MAX_CABINET_NAME);
2222 memcpy(p_fci_internal->szPrevDisk, p_fci_internal->oldCCAB.szDisk,
2223 CB_MAX_DISK_NAME);
2224 p_fci_internal->fNewPrevious=FALSE;
2227 /* too much data for the maximum size of a cabinet */
2228 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2229 p_fci_internal->pccab->cb < read_result ) {
2230 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2233 /* Might be too much data for the maximum size of a cabinet.*/
2234 /* When any further data will be added later, it might not */
2235 /* be possible to flush the cabinet, because there might */
2236 /* not be enough space to store the name of the following */
2237 /* cabinet and name of the corresponding disk. */
2238 /* So take care of this and get the name of the next cabinet */
2239 if (p_fci_internal->fGetNextCabInVain==FALSE && (
2240 p_fci_internal->pccab->cb < read_result +
2241 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2242 )) {
2243 /* save CCAB */
2244 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2245 /* increment cabinet index */
2246 ++(p_fci_internal->pccab->iCab);
2247 /* get name of next cabinet */
2248 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2249 if (!(*pfnfcignc)(p_fci_internal->pccab,
2250 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2251 p_fci_internal->pv)) {
2252 /* error handling */
2253 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2254 return FALSE;
2256 /* Skip a few lines of code. This is catched by the next if. */
2257 p_fci_internal->fGetNextCabInVain=TRUE;
2260 /* too much data for cabinet */
2261 if (p_fci_internal->fGetNextCabInVain && (
2262 p_fci_internal->oldCCAB.cb < read_result +
2263 strlen(p_fci_internal->oldCCAB.szCab)+1+
2264 strlen(p_fci_internal->oldCCAB.szDisk)+1
2265 )) {
2266 p_fci_internal->fGetNextCabInVain=FALSE;
2267 p_fci_internal->fNextCab=TRUE;
2268 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2271 /* if the FolderThreshold has been reached flush the folder automatically */
2272 if( p_fci_internal->fGetNextCabInVain ) {
2273 if( p_fci_internal->cCompressedBytesInFolder >=
2274 p_fci_internal->oldCCAB.cbFolderThresh) {
2275 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2277 } else {
2278 if( p_fci_internal->cCompressedBytesInFolder >=
2279 p_fci_internal->pccab->cbFolderThresh) {
2280 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2284 /* END OF COPIED FROM FCIAddFile and modified */
2286 if( p_fci_internal->sizeFileCFFILE1>0 ) {
2287 if( !FCIFlushFolder(hfci, pfnfcignc, pfnfcis) ) return FALSE;
2288 p_fci_internal->fNewPrevious=TRUE;
2290 } else {
2291 p_fci_internal->fNewPrevious=FALSE;
2292 if( p_fci_internal->sizeFileCFFILE1>0 || p_fci_internal->sizeFileCFDATA1) {
2293 /* THIS MAY NEVER HAPPEN */
2294 /* set error structures */
2295 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2296 return FALSE;
2300 return TRUE;
2301 } /* end of fci_flush_cabinet */
2307 /***********************************************************************
2308 * FCIAddFile (CABINET.11)
2310 * FCIAddFile adds a file to the to be created cabinet file
2312 * PARAMS
2313 * hfci [I] An HFCI from FCICreate
2314 * pszSourceFile [I] A pointer to a C string which contains the name and
2315 * location of the file which will be added to the cabinet
2316 * pszFileName [I] A pointer to a C string which contains the name under
2317 * which the file will be stored in the cabinet
2318 * fExecute [I] A boolean value which indicates if the file should be
2319 * executed after extraction of self extracting
2320 * executables
2321 * pfnfcignc [I] A pointer to a function which gets information about
2322 * the next cabinet
2323 * pfnfcis [IO] A pointer to a function which will report status
2324 * information about the compression process
2325 * pfnfcioi [I] A pointer to a function which reports file attributes
2326 * and time and date information
2327 * typeCompress [I] Compression type
2329 * RETURNS
2330 * On success, returns TRUE
2331 * On failure, returns FALSE
2333 * INCLUDES
2334 * fci.h
2337 BOOL __cdecl FCIAddFile(
2338 HFCI hfci,
2339 char *pszSourceFile,
2340 char *pszFileName,
2341 BOOL fExecute,
2342 PFNFCIGETNEXTCABINET pfnfcignc,
2343 PFNFCISTATUS pfnfcis,
2344 PFNFCIGETOPENINFO pfnfcigoi,
2345 TCOMP typeCompress)
2347 int err;
2348 CFFILE cffile;
2349 cab_ULONG read_result;
2350 int file_handle;
2351 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2353 /* test hfci */
2354 if (!REALLY_IS_FCI(hfci)) {
2355 SetLastError(ERROR_INVALID_HANDLE);
2356 return FALSE;
2359 if ((!pszSourceFile) || (!pszFileName) || (!pfnfcignc) || (!pfnfcis) ||
2360 (!pfnfcigoi) || strlen(pszFileName)>=CB_MAX_FILENAME) {
2361 fci_set_error( FCIERR_NONE, ERROR_BAD_ARGUMENTS, TRUE );
2362 return FALSE;
2365 /* TODO check if pszSourceFile??? */
2367 if(p_fci_internal->fGetNextCabInVain && p_fci_internal->fNextCab) {
2368 /* internal error */
2369 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2370 return FALSE;
2373 if(p_fci_internal->fNextCab) {
2374 /* internal error */
2375 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2376 return FALSE;
2379 cffile.cbFile=0; /* size of the to be added file*/
2380 /* offset of the uncompressed file in the folder */
2381 cffile.uoffFolderStart=p_fci_internal->cDataBlocks*CAB_BLOCKMAX + p_fci_internal->cdata_in;
2382 /* number of folder in the cabinet or special 0=first */
2383 cffile.iFolder = p_fci_internal->cFolders;
2385 /* allocation of memory */
2386 if (p_fci_internal->data_in==NULL) {
2387 if (p_fci_internal->cdata_in!=0) {
2388 /* error handling */
2389 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2390 return FALSE;
2392 if (p_fci_internal->data_out!=NULL) {
2393 /* error handling */
2394 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2395 return FALSE;
2397 if(!(p_fci_internal->data_in = (char*)PFCI_ALLOC(hfci,CB_MAX_CHUNK))) {
2398 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
2399 return FALSE;
2401 if (p_fci_internal->data_out==NULL) {
2402 if(!(p_fci_internal->data_out = PFCI_ALLOC(hfci, 2 * CB_MAX_CHUNK))){
2403 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
2404 return FALSE;
2409 if (p_fci_internal->data_out==NULL) {
2410 PFCI_FREE(hfci,p_fci_internal->data_in);
2411 /* error handling */
2412 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2413 return FALSE;
2416 /* get information about the file */
2417 file_handle=(*pfnfcigoi)(pszSourceFile, &(cffile.date), &(cffile.time),
2418 &(cffile.attribs), &err, p_fci_internal->pv);
2419 /* check file_handle */
2420 if(file_handle==0){
2421 fci_set_error( FCIERR_OPEN_SRC, ERROR_OPEN_FAILED, TRUE );
2423 /* TODO error handling of err */
2425 if (fExecute) { cffile.attribs |= _A_EXEC; }
2427 /* REUSE the variable read_result */
2428 if (p_fci_internal->fGetNextCabInVain) {
2429 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2430 p_fci_internal->oldCCAB.cbReserveCFFolder;
2431 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2432 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2433 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2434 read_result+=4;
2436 } else {
2437 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2438 p_fci_internal->pccab->cbReserveCFFolder;
2439 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2440 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2441 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2442 read_result+=4;
2445 if ( p_fci_internal->fPrevCab ) {
2446 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2447 strlen(p_fci_internal->szPrevDisk)+1;
2449 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2450 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2451 strlen(p_fci_internal->pccab->szDisk)+1;
2454 read_result+= sizeof(CFFILE) + strlen(pszFileName)+1 +
2455 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2456 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2457 sizeof(CFHEADER) +
2458 sizeof(CFFOLDER); /* size of new CFFolder entry */
2460 /* Might be too much data for the maximum size of a cabinet.*/
2461 /* When any further data will be added later, it might not */
2462 /* be possible to flush the cabinet, because there might */
2463 /* not be enough space to store the name of the following */
2464 /* cabinet and name of the corresponding disk. */
2465 /* So take care of this and get the name of the next cabinet */
2466 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2467 p_fci_internal->fNextCab==FALSE &&
2468 ( p_fci_internal->pccab->cb < read_result +
2469 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2472 /* save CCAB */
2473 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2474 /* increment cabinet index */
2475 ++(p_fci_internal->pccab->iCab);
2476 /* get name of next cabinet */
2477 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2478 if (!(*pfnfcignc)(p_fci_internal->pccab,
2479 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2480 p_fci_internal->pv)) {
2481 /* error handling */
2482 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2483 return FALSE;
2485 /* Skip a few lines of code. This is catched by the next if. */
2486 p_fci_internal->fGetNextCabInVain=TRUE;
2489 if( p_fci_internal->fGetNextCabInVain &&
2490 p_fci_internal->fNextCab
2492 /* THIS CAN NEVER HAPPEN */
2493 /* set error code */
2494 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2495 return FALSE;
2498 /* too much data for cabinet */
2499 if( p_fci_internal->fGetNextCabInVain &&
2501 p_fci_internal->oldCCAB.cb < read_result +
2502 strlen(p_fci_internal->pccab->szCab)+1+
2503 strlen(p_fci_internal->pccab->szDisk)+1
2504 )) {
2505 p_fci_internal->fGetNextCabInVain=FALSE;
2506 p_fci_internal->fNextCab=TRUE;
2507 if(!fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis)) return FALSE;
2510 if( p_fci_internal->fNextCab ) {
2511 /* THIS MAY NEVER HAPPEN */
2512 /* set error code */
2513 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2514 return FALSE;
2517 /* read the contents of the file blockwise */
2518 while (!FALSE) {
2519 if (p_fci_internal->cdata_in > CAB_BLOCKMAX) {
2520 /* internal error */
2521 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2522 return FALSE;
2525 read_result = PFCI_READ(hfci, file_handle /* file handle */,
2526 (p_fci_internal->data_in + p_fci_internal->cdata_in) /* memory buffer */,
2527 (CAB_BLOCKMAX - p_fci_internal->cdata_in) /* number of bytes to copy */,
2528 &err, p_fci_internal->pv);
2529 /* TODO error handling of err */
2531 if( read_result==0 ) break;
2533 /* increment the block size */
2534 p_fci_internal->cdata_in += read_result;
2536 /* increment the file size */
2537 cffile.cbFile += read_result;
2539 if ( p_fci_internal->cdata_in > CAB_BLOCKMAX ) {
2540 /* report internal error */
2541 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2542 return FALSE;
2544 /* write a whole block */
2545 if ( p_fci_internal->cdata_in == CAB_BLOCKMAX ) {
2547 if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;
2551 /* close the file from FCIAddFile */
2552 PFCI_CLOSE(hfci,file_handle,&err,p_fci_internal->pv);
2553 /* TODO error handling of err */
2555 /* write cffile to p_fci_internal->handleCFFILE1 */
2556 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */
2557 &cffile, sizeof(cffile),&err, p_fci_internal->pv) != sizeof(cffile) ) {
2558 /* write error */
2559 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
2560 return FALSE;
2562 /* TODO error handling of err */
2564 p_fci_internal->sizeFileCFFILE1 += sizeof(cffile);
2566 /* append the name of file */
2567 if (strlen(pszFileName)>=CB_MAX_FILENAME) {
2568 /* IMPOSSIBLE */
2569 /* set error code */
2570 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2571 return FALSE;
2573 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */
2574 pszFileName, strlen(pszFileName)+1, &err, p_fci_internal->pv)
2575 != strlen(pszFileName)+1 ) {
2576 /* write error */
2577 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
2578 return FALSE;
2580 /* TODO error handling of err */
2582 p_fci_internal->sizeFileCFFILE1 += strlen(pszFileName)+1;
2584 /* REUSE the variable read_result */
2585 if (p_fci_internal->fGetNextCabInVain ||
2586 p_fci_internal->fNextCab
2588 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2589 p_fci_internal->oldCCAB.cbReserveCFFolder;
2590 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2591 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2592 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2593 read_result+=4;
2595 } else {
2596 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2597 p_fci_internal->pccab->cbReserveCFFolder;
2598 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2599 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2600 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2601 read_result+=4;
2604 if ( p_fci_internal->fPrevCab ) {
2605 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2606 strlen(p_fci_internal->szPrevDisk)+1;
2608 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2609 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2610 strlen(p_fci_internal->pccab->szDisk)+1;
2612 read_result+= p_fci_internal->sizeFileCFDATA1 +
2613 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2614 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2615 sizeof(CFHEADER) +
2616 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2618 /* too much data for the maximum size of a cabinet */
2619 /* (ignoring the unflushed data block) */
2620 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2621 p_fci_internal->fNextCab==FALSE && /* this is always the case */
2622 p_fci_internal->pccab->cb < read_result ) {
2623 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2626 /* Might be too much data for the maximum size of a cabinet.*/
2627 /* When any further data will be added later, it might not */
2628 /* be possible to flush the cabinet, because there might */
2629 /* not be enough space to store the name of the following */
2630 /* cabinet and name of the corresponding disk. */
2631 /* So take care of this and get the name of the next cabinet */
2632 /* (ignoring the unflushed data block) */
2633 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2634 p_fci_internal->fNextCab==FALSE &&
2635 ( p_fci_internal->pccab->cb < read_result +
2636 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2639 /* save CCAB */
2640 memcpy(&(p_fci_internal->oldCCAB), p_fci_internal->pccab, sizeof(CCAB));
2641 /* increment cabinet index */
2642 ++(p_fci_internal->pccab->iCab);
2643 /* get name of next cabinet */
2644 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2645 if (!(*pfnfcignc)(p_fci_internal->pccab,
2646 p_fci_internal->estimatedCabinetSize,/* estimated size of cab */
2647 p_fci_internal->pv)) {
2648 /* error handling */
2649 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2650 return FALSE;
2652 /* Skip a few lines of code. This is catched by the next if. */
2653 p_fci_internal->fGetNextCabInVain=TRUE;
2656 if( p_fci_internal->fGetNextCabInVain &&
2657 p_fci_internal->fNextCab
2659 /* THIS CAN NEVER HAPPEN */
2660 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2661 return FALSE;
2664 /* too much data for cabinet */
2665 if( (p_fci_internal->fGetNextCabInVain ||
2666 p_fci_internal->fNextCab) && (
2667 p_fci_internal->oldCCAB.cb < read_result +
2668 strlen(p_fci_internal->pccab->szCab)+1+
2669 strlen(p_fci_internal->pccab->szDisk)+1
2670 )) {
2672 p_fci_internal->fGetNextCabInVain=FALSE;
2673 p_fci_internal->fNextCab=TRUE;
2674 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2677 if( p_fci_internal->fNextCab ) {
2678 /* THIS MAY NEVER HAPPEN */
2679 /* set error code */
2680 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2681 return FALSE;
2684 /* if the FolderThreshold has been reached flush the folder automatically */
2685 if( p_fci_internal->fGetNextCabInVain ) {
2686 if( p_fci_internal->cCompressedBytesInFolder >=
2687 p_fci_internal->oldCCAB.cbFolderThresh) {
2688 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2690 } else {
2691 if( p_fci_internal->cCompressedBytesInFolder >=
2692 p_fci_internal->pccab->cbFolderThresh) {
2693 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2697 return TRUE;
2698 } /* end of FCIAddFile */
2704 /***********************************************************************
2705 * FCIFlushFolder (CABINET.12)
2707 * FCIFlushFolder completes the CFFolder structure under construction.
2709 * All further data which is added by FCIAddFile will be associateed to
2710 * the next CFFolder structure.
2712 * FCIFlushFolder will be called by FCIAddFile automatically if the
2713 * threshold (stored in the member cbFolderThresh of the CCAB structure
2714 * pccab passed to FCICreate) is exceeded.
2716 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2717 * any data will be written into the cabinet file.
2719 * PARAMS
2720 * hfci [I] An HFCI from FCICreate
2721 * pfnfcignc [I] A pointer to a function which gets information about
2722 * the next cabinet
2723 * pfnfcis [IO] A pointer to a function which will report status
2724 * information about the compression process
2726 * RETURNS
2727 * On success, returns TRUE
2728 * On failure, returns FALSE
2730 * INCLUDES
2731 * fci.h
2734 BOOL __cdecl FCIFlushFolder(
2735 HFCI hfci,
2736 PFNFCIGETNEXTCABINET pfnfcignc,
2737 PFNFCISTATUS pfnfcis)
2739 return fci_flush_folder(hfci,FALSE,pfnfcignc,pfnfcis);
2740 } /* end of FCIFlushFolder */
2744 /***********************************************************************
2745 * FCIFlushCabinet (CABINET.13)
2747 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2748 * into the cabinet file. If the maximum cabinet size (stored in the
2749 * member cb of the CCAB structure pccab passed to FCICreate) has been
2750 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2751 * The remaining data still has to be flushed manually by calling
2752 * FCIFlushCabinet.
2754 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2755 * NOT be called again. Then hfci has to be released by FCIDestroy.
2757 * PARAMS
2758 * hfci [I] An HFCI from FCICreate
2759 * fGetNextCab [I] Whether you want to add additional files to a
2760 * cabinet set (TRUE) or whether you want to
2761 * finalize it (FALSE)
2762 * pfnfcignc [I] A pointer to a function which gets information about
2763 * the next cabinet
2764 * pfnfcis [IO] A pointer to a function which will report status
2765 * information about the compression process
2767 * RETURNS
2768 * On success, returns TRUE
2769 * On failure, returns FALSE
2771 * INCLUDES
2772 * fci.h
2775 BOOL __cdecl FCIFlushCabinet(
2776 HFCI hfci,
2777 BOOL fGetNextCab,
2778 PFNFCIGETNEXTCABINET pfnfcignc,
2779 PFNFCISTATUS pfnfcis)
2781 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2783 if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2785 while( p_fci_internal->sizeFileCFFILE1>0 ||
2786 p_fci_internal->sizeFileCFFILE2>0 ) {
2787 if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2790 return TRUE;
2791 } /* end of FCIFlushCabinet */
2794 /***********************************************************************
2795 * FCIDestroy (CABINET.14)
2797 * Frees a handle created by FCICreate.
2798 * Only reason for failure would be an invalid handle.
2800 * PARAMS
2801 * hfci [I] The HFCI to free
2803 * RETURNS
2804 * TRUE for success
2805 * FALSE for failure
2807 BOOL __cdecl FCIDestroy(HFCI hfci)
2809 int err;
2810 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2811 if (REALLY_IS_FCI(hfci)) {
2813 /* before hfci can be removed all temporary files must be closed */
2814 /* and deleted */
2815 p_fci_internal->FCI_Intmagic = 0;
2817 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
2818 /* TODO error handling of err */
2819 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA1, &err,
2820 p_fci_internal->pv);
2821 /* TODO error handling of err */
2822 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE1,&err,p_fci_internal->pv);
2823 /* TODO error handling of err */
2824 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE1, &err,
2825 p_fci_internal->pv);
2826 /* TODO error handling of err */
2827 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2828 /* TODO error handling of err */
2829 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,
2830 p_fci_internal->pv);
2831 /* TODO error handling of err */
2832 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2833 /* TODO error handling of err */
2834 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,
2835 p_fci_internal->pv);
2836 /* TODO error handling of err */
2837 PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
2838 /* TODO error handling of err */
2839 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,
2840 p_fci_internal->pv);
2841 /* TODO error handling of err */
2843 /* data in and out buffers have to be removed */
2844 if (p_fci_internal->data_in!=NULL)
2845 PFCI_FREE(hfci, p_fci_internal->data_in);
2846 if (p_fci_internal->data_out!=NULL)
2847 PFCI_FREE(hfci, p_fci_internal->data_out);
2849 /* hfci can now be removed */
2850 PFCI_FREE(hfci, hfci);
2851 return TRUE;
2852 } else {
2853 SetLastError(ERROR_INVALID_HANDLE);
2854 return FALSE;
2857 } /* end of FCIDestroy */