cabinet: Store folders in a list in memory instead of in a temp file.
[wine.git] / dlls / cabinet / fci.c
blob089829b11cd41573fd29187921190d9de02aa704
1 /*
2 * File Compression Interface
4 * Copyright 2002 Patrik Stridvall
5 * Copyright 2005 Gerold Jens Wucherpfennig
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 There is still some work to be done:
26 - no real compression yet
27 - unknown behaviour if files>=2GB or cabinet >=4GB
28 - check if the maximum size for a cabinet is too small to store any data
29 - call pfnfcignc on exactly the same position as MS FCIAddFile in every case
30 - probably check err
36 #include "config.h"
38 #include <stdarg.h>
39 #include <stdio.h>
40 #include <string.h>
42 #include "windef.h"
43 #include "winbase.h"
44 #include "winerror.h"
45 #include "winternl.h"
46 #include "fci.h"
47 #include "cabinet.h"
48 #include "wine/list.h"
49 #include "wine/debug.h"
52 #ifdef WORDS_BIGENDIAN
53 #define fci_endian_ulong(x) RtlUlongByteSwap(x)
54 #define fci_endian_uword(x) RtlUshortByteSwap(x)
55 #else
56 #define fci_endian_ulong(x) (x)
57 #define fci_endian_uword(x) (x)
58 #endif
61 typedef struct {
62 cab_UBYTE signature[4]; /* !CAB for unfinished cabinets else MSCF */
63 cab_ULONG reserved1;
64 cab_ULONG cbCabinet; /* size of the cabinet file in bytes*/
65 cab_ULONG reserved2;
66 cab_ULONG coffFiles; /* offset to first CFFILE section */
67 cab_ULONG reserved3;
68 cab_UBYTE versionMinor; /* 3 */
69 cab_UBYTE versionMajor; /* 1 */
70 cab_UWORD cFolders; /* number of CFFOLDER entries in the cabinet*/
71 cab_UWORD cFiles; /* number of CFFILE entries in the cabinet*/
72 cab_UWORD flags; /* 1=prev cab, 2=next cabinet, 4=reserved sections*/
73 cab_UWORD setID; /* identification number of all cabinets in a set*/
74 cab_UWORD iCabinet; /* number of the cabinet in a set */
75 /* additional area if "flags" were set*/
76 } CFHEADER; /* minimum 36 bytes */
78 typedef struct {
79 cab_ULONG coffCabStart; /* offset to the folder's first CFDATA section */
80 cab_UWORD cCFData; /* number of this folder's CFDATA sections */
81 cab_UWORD typeCompress; /* compression type of data in CFDATA section*/
82 /* additional area if reserve flag was set */
83 } CFFOLDER; /* minimum 8 bytes */
85 typedef struct {
86 cab_ULONG cbFile; /* size of the uncompressed file in bytes */
87 cab_ULONG uoffFolderStart; /* offset of the uncompressed file in the folder */
88 cab_UWORD iFolder; /* number of folder in the cabinet 0=first */
89 /* for special values see below this structure*/
90 cab_UWORD date; /* last modification date*/
91 cab_UWORD time; /* last modification time*/
92 cab_UWORD attribs; /* DOS fat attributes and UTF indicator */
93 /* ... and a C string with the name of the file */
94 } CFFILE; /* 16 bytes + name of file */
97 typedef struct {
98 cab_ULONG csum; /* checksum of this entry*/
99 cab_UWORD cbData; /* number of compressed bytes */
100 cab_UWORD cbUncomp; /* number of bytes when data is uncompressed */
101 /* optional reserved area */
102 /* compressed data */
103 } CFDATA;
105 struct folder
107 struct list entry;
108 cab_ULONG data_start;
109 cab_UWORD data_count;
110 cab_UWORD compression;
113 typedef struct
115 unsigned int magic;
116 PERF perf;
117 PFNFCIFILEPLACED fileplaced;
118 PFNFCIALLOC alloc;
119 PFNFCIFREE free;
120 PFNFCIOPEN open;
121 PFNFCIREAD read;
122 PFNFCIWRITE write;
123 PFNFCICLOSE close;
124 PFNFCISEEK seek;
125 PFNFCIDELETE delete;
126 PFNFCIGETTEMPFILE gettemp;
127 PCCAB pccab;
128 BOOL fPrevCab;
129 BOOL fNextCab;
130 BOOL fSplitFolder;
131 cab_ULONG statusFolderCopied;
132 cab_ULONG statusFolderTotal;
133 BOOL fGetNextCabInVain;
134 void *pv;
135 char szPrevCab[CB_MAX_CABINET_NAME]; /* previous cabinet name */
136 char szPrevDisk[CB_MAX_DISK_NAME]; /* disk name of previous cabinet */
137 CCAB oldCCAB;
138 char* data_in; /* uncompressed data blocks */
139 cab_UWORD cdata_in;
140 char* data_out; /* compressed data blocks */
141 ULONG cCompressedBytesInFolder;
142 cab_UWORD cFolders;
143 cab_UWORD cFiles;
144 cab_ULONG cDataBlocks;
145 cab_ULONG cbFileRemainer; /* uncompressed, yet to be written data */
146 /* of spanned file of a spanning folder of a spanning cabinet */
147 char szFileNameCFDATA1[CB_MAX_FILENAME];
148 int handleCFDATA1;
149 char szFileNameCFFILE1[CB_MAX_FILENAME];
150 int handleCFFILE1;
151 char szFileNameCFDATA2[CB_MAX_FILENAME];
152 int handleCFDATA2;
153 char szFileNameCFFILE2[CB_MAX_FILENAME];
154 int handleCFFILE2;
155 cab_ULONG sizeFileCFDATA1;
156 cab_ULONG sizeFileCFFILE1;
157 cab_ULONG sizeFileCFDATA2;
158 cab_ULONG sizeFileCFFILE2;
159 BOOL fNewPrevious;
160 cab_ULONG estimatedCabinetSize;
161 struct list folders_list;
162 cab_ULONG folders_size;
163 } FCI_Int;
165 #define FCI_INT_MAGIC 0xfcfcfc05
167 static void set_error( FCI_Int *fci, int oper, int err )
169 fci->perf->erfOper = oper;
170 fci->perf->erfType = err;
171 fci->perf->fError = TRUE;
172 if (err) SetLastError( err );
175 static FCI_Int *get_fci_ptr( HFCI hfci )
177 FCI_Int *fci= (FCI_Int *)hfci;
179 if (!fci || !fci->magic == FCI_INT_MAGIC)
181 SetLastError( ERROR_INVALID_HANDLE );
182 return NULL;
184 return fci;
187 static cab_ULONG get_folder_size( FCI_Int *fci )
189 if (fci->fNextCab || fci->fGetNextCabInVain)
190 return sizeof(CFFOLDER) + fci->oldCCAB.cbReserveCFFolder;
191 else
192 return sizeof(CFFOLDER) + fci->pccab->cbReserveCFFolder;
195 static struct folder *add_folder( FCI_Int *fci )
197 struct folder *folder = fci->alloc( sizeof(*folder) );
199 if (!folder)
201 set_error( fci, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
202 return NULL;
204 folder->data_start = fci->sizeFileCFDATA2;
205 folder->compression = tcompTYPE_NONE; /* FIXME */
206 list_add_tail( &fci->folders_list, &folder->entry );
207 fci->folders_size += get_folder_size( fci );
208 fci->cFolders++;
209 return folder;
212 /* write all folders to disk and remove them from the list */
213 static BOOL write_folders( FCI_Int *fci, INT_PTR handle, cab_ULONG header_size )
215 struct folder *folder, *next;
216 int err;
217 BOOL ret = TRUE;
218 CFFOLDER *cffolder;
219 cab_ULONG folder_size = get_folder_size( fci );
221 if (!(cffolder = fci->alloc( folder_size )))
223 set_error( fci, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
224 return FALSE;
226 memset( cffolder, 0, folder_size );
228 LIST_FOR_EACH_ENTRY_SAFE( folder, next, &fci->folders_list, struct folder, entry )
230 cffolder->coffCabStart = fci_endian_ulong( folder->data_start + header_size );
231 cffolder->cCFData = fci_endian_uword( folder->data_count );
232 cffolder->typeCompress = fci_endian_uword( folder->compression );
233 if (fci->write( handle, cffolder, folder_size, &err, fci->pv ) != folder_size)
235 set_error( fci, FCIERR_CAB_FILE, err );
236 ret = FALSE;
237 break;
239 list_remove( &folder->entry );
241 fci->free( cffolder );
242 return ret;
245 /***********************************************************************
246 * FCICreate (CABINET.10)
248 * FCICreate is provided with several callbacks and
249 * returns a handle which can be used to create cabinet files.
251 * PARAMS
252 * perf [IO] A pointer to an ERF structure. When FCICreate
253 * returns an error condition, error information may
254 * be found here as well as from GetLastError.
255 * pfnfiledest [I] A pointer to a function which is called when a file
256 * is placed. Only useful for subsequent cabinet files.
257 * pfnalloc [I] A pointer to a function which allocates ram. Uses
258 * the same interface as malloc.
259 * pfnfree [I] A pointer to a function which frees ram. Uses the
260 * same interface as free.
261 * pfnopen [I] A pointer to a function which opens a file. Uses
262 * the same interface as _open.
263 * pfnread [I] A pointer to a function which reads from a file into
264 * a caller-provided buffer. Uses the same interface
265 * as _read.
266 * pfnwrite [I] A pointer to a function which writes to a file from
267 * a caller-provided buffer. Uses the same interface
268 * as _write.
269 * pfnclose [I] A pointer to a function which closes a file handle.
270 * Uses the same interface as _close.
271 * pfnseek [I] A pointer to a function which seeks in a file.
272 * Uses the same interface as _lseek.
273 * pfndelete [I] A pointer to a function which deletes a file.
274 * pfnfcigtf [I] A pointer to a function which gets the name of a
275 * temporary file.
276 * pccab [I] A pointer to an initialized CCAB structure.
277 * pv [I] A pointer to an application-defined notification
278 * function which will be passed to other FCI functions
279 * as a parameter.
281 * RETURNS
282 * On success, returns an FCI handle of type HFCI.
283 * On failure, the NULL file handle is returned. Error
284 * info can be retrieved from perf.
286 * INCLUDES
287 * fci.h
290 HFCI __cdecl FCICreate(
291 PERF perf,
292 PFNFCIFILEPLACED pfnfiledest,
293 PFNFCIALLOC pfnalloc,
294 PFNFCIFREE pfnfree,
295 PFNFCIOPEN pfnopen,
296 PFNFCIREAD pfnread,
297 PFNFCIWRITE pfnwrite,
298 PFNFCICLOSE pfnclose,
299 PFNFCISEEK pfnseek,
300 PFNFCIDELETE pfndelete,
301 PFNFCIGETTEMPFILE pfnfcigtf,
302 PCCAB pccab,
303 void *pv)
305 int err;
306 FCI_Int *p_fci_internal;
308 if (!perf) {
309 SetLastError(ERROR_BAD_ARGUMENTS);
310 return NULL;
312 if ((!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||
313 (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||
314 (!pfnfcigtf) || (!pccab)) {
315 perf->erfOper = FCIERR_NONE;
316 perf->erfType = ERROR_BAD_ARGUMENTS;
317 perf->fError = TRUE;
319 SetLastError(ERROR_BAD_ARGUMENTS);
320 return NULL;
323 if (!((p_fci_internal = pfnalloc(sizeof(FCI_Int))))) {
324 perf->erfOper = FCIERR_ALLOC_FAIL;
325 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
326 perf->fError = TRUE;
328 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
329 return NULL;
332 p_fci_internal->magic = FCI_INT_MAGIC;
333 p_fci_internal->perf = perf;
334 p_fci_internal->fileplaced = pfnfiledest;
335 p_fci_internal->alloc = pfnalloc;
336 p_fci_internal->free = pfnfree;
337 p_fci_internal->open = pfnopen;
338 p_fci_internal->read = pfnread;
339 p_fci_internal->write = pfnwrite;
340 p_fci_internal->close = pfnclose;
341 p_fci_internal->seek = pfnseek;
342 p_fci_internal->delete = pfndelete;
343 p_fci_internal->gettemp = pfnfcigtf;
344 p_fci_internal->pccab = pccab;
345 p_fci_internal->fPrevCab = FALSE;
346 p_fci_internal->fNextCab = FALSE;
347 p_fci_internal->fSplitFolder = FALSE;
348 p_fci_internal->fGetNextCabInVain = FALSE;
349 p_fci_internal->pv = pv;
350 p_fci_internal->data_in = NULL;
351 p_fci_internal->cdata_in = 0;
352 p_fci_internal->data_out = NULL;
353 p_fci_internal->cCompressedBytesInFolder = 0;
354 p_fci_internal->cFolders = 0;
355 p_fci_internal->cFiles = 0;
356 p_fci_internal->cDataBlocks = 0;
357 p_fci_internal->sizeFileCFDATA1 = 0;
358 p_fci_internal->sizeFileCFFILE1 = 0;
359 p_fci_internal->sizeFileCFDATA2 = 0;
360 p_fci_internal->sizeFileCFFILE2 = 0;
361 p_fci_internal->fNewPrevious = FALSE;
362 p_fci_internal->estimatedCabinetSize = 0;
363 p_fci_internal->statusFolderTotal = 0;
364 p_fci_internal->folders_size = 0;
366 list_init( &p_fci_internal->folders_list );
368 memset(&p_fci_internal->oldCCAB, 0, sizeof(CCAB));
369 memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
370 memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);
372 /* CFDATA */
373 if( !p_fci_internal->gettemp(p_fci_internal->szFileNameCFDATA1,
374 CB_MAX_FILENAME, p_fci_internal->pv)) {
375 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
376 return FALSE;
378 /* safety */
379 if ( strlen(p_fci_internal->szFileNameCFDATA1) >= CB_MAX_FILENAME ) {
380 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
381 return FALSE;
384 p_fci_internal->handleCFDATA1 = p_fci_internal->open( p_fci_internal->szFileNameCFDATA1,
385 _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
386 _S_IREAD | _S_IWRITE, &err, pv);
387 if(p_fci_internal->handleCFDATA1==0){
388 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_OPEN_FAILED );
389 return FALSE;
391 /* TODO error checking of err */
393 /* array of all CFFILE in a folder */
394 if( !p_fci_internal->gettemp(p_fci_internal->szFileNameCFFILE1,
395 CB_MAX_FILENAME, p_fci_internal->pv)) {
396 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
397 return FALSE;
399 /* safety */
400 if ( strlen(p_fci_internal->szFileNameCFFILE1) >= CB_MAX_FILENAME ) {
401 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
402 return FALSE;
404 p_fci_internal->handleCFFILE1 = p_fci_internal->open( p_fci_internal->szFileNameCFFILE1,
405 _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
406 _S_IREAD | _S_IWRITE, &err, pv);
407 if(p_fci_internal->handleCFFILE1==0){
408 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_OPEN_FAILED );
409 return FALSE;
411 /* TODO error checking of err */
413 /* CFDATA with checksum and ready to be copied into cabinet */
414 if( !p_fci_internal->gettemp(p_fci_internal->szFileNameCFDATA2,
415 CB_MAX_FILENAME, p_fci_internal->pv)) {
416 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
417 return FALSE;
419 /* safety */
420 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
421 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
422 return FALSE;
424 p_fci_internal->handleCFDATA2 = p_fci_internal->open( p_fci_internal->szFileNameCFDATA2,
425 _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
426 _S_IREAD | _S_IWRITE, &err, pv);
427 if(p_fci_internal->handleCFDATA2==0){
428 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_OPEN_FAILED );
429 return FALSE;
431 /* TODO error checking of err */
433 /* array of all CFFILE in a folder, ready to be copied into cabinet */
434 if( !p_fci_internal->gettemp(p_fci_internal->szFileNameCFFILE2,
435 CB_MAX_FILENAME, p_fci_internal->pv)) {
436 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
437 return FALSE;
439 /* safety */
440 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
441 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
442 return FALSE;
444 p_fci_internal->handleCFFILE2 = p_fci_internal->open( p_fci_internal->szFileNameCFFILE2,
445 _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
446 _S_IREAD | _S_IWRITE, &err, pv);
447 if(p_fci_internal->handleCFFILE2==0){
448 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_OPEN_FAILED );
449 return FALSE;
451 /* TODO error checking of err */
453 /* TODO close and delete new files when return FALSE */
455 return (HFCI)p_fci_internal;
463 static BOOL fci_flush_data_block (FCI_Int *p_fci_internal, int* err,
464 PFNFCISTATUS pfnfcis) {
466 /* attention no checks if there is data available!!! */
467 CFDATA data;
468 CFDATA* cfdata=&data;
469 char* reserved;
470 UINT cbReserveCFData=p_fci_internal->pccab->cbReserveCFData;
471 UINT i;
473 /* TODO compress the data of p_fci_internal->data_in */
474 /* and write it to p_fci_internal->data_out */
475 memcpy(p_fci_internal->data_out, p_fci_internal->data_in,
476 p_fci_internal->cdata_in /* number of bytes to copy */);
478 cfdata->csum=0; /* checksum has to be set later */
479 /* TODO set realsize of compressed data */
480 cfdata->cbData = p_fci_internal->cdata_in;
481 cfdata->cbUncomp = p_fci_internal->cdata_in;
483 /* write cfdata to p_fci_internal->handleCFDATA1 */
484 if( p_fci_internal->write( p_fci_internal->handleCFDATA1, /* file handle */
485 cfdata, sizeof(*cfdata), err, p_fci_internal->pv)
486 != sizeof(*cfdata) ) {
487 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
488 return FALSE;
490 /* TODO error handling of err */
492 p_fci_internal->sizeFileCFDATA1 += sizeof(*cfdata);
494 /* add optional reserved area */
496 /* This allocation and freeing at each CFData block is a bit */
497 /* inefficient, but it's harder to forget about freeing the buffer :-). */
498 /* Reserved areas are used seldom besides that... */
499 if (cbReserveCFData!=0) {
500 if(!(reserved = p_fci_internal->alloc( cbReserveCFData))) {
501 set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
502 return FALSE;
504 for(i=0;i<cbReserveCFData;) {
505 reserved[i++]='\0';
507 if( p_fci_internal->write( p_fci_internal->handleCFDATA1, /* file handle */
508 reserved, /* memory buffer */
509 cbReserveCFData, /* number of bytes to copy */
510 err, p_fci_internal->pv) != cbReserveCFData ) {
511 p_fci_internal->free(reserved);
512 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
513 return FALSE;
515 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
517 p_fci_internal->sizeFileCFDATA1 += cbReserveCFData;
518 p_fci_internal->free( reserved);
521 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
522 if( p_fci_internal->write( p_fci_internal->handleCFDATA1, /* file handle */
523 p_fci_internal->data_out, /* memory buffer */
524 cfdata->cbData, /* number of bytes to copy */
525 err, p_fci_internal->pv) != cfdata->cbData) {
526 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
527 return FALSE;
529 /* TODO error handling of err */
531 p_fci_internal->sizeFileCFDATA1 += cfdata->cbData;
533 /* reset the offset */
534 p_fci_internal->cdata_in = 0;
535 p_fci_internal->cCompressedBytesInFolder += cfdata->cbData;
537 /* report status with pfnfcis about uncompressed and compressed file data */
538 if( (*pfnfcis)(statusFile, cfdata->cbData, cfdata->cbUncomp,
539 p_fci_internal->pv) == -1) {
540 set_error( p_fci_internal, FCIERR_USER_ABORT, 0 );
541 return FALSE;
544 ++(p_fci_internal->cDataBlocks);
546 return TRUE;
547 } /* end of fci_flush_data_block */
553 static cab_ULONG fci_get_checksum(const void *pv, UINT cb, CHECKSUM seed)
555 cab_ULONG csum;
556 cab_ULONG ul;
557 int cUlong;
558 const BYTE *pb;
560 csum = seed;
561 cUlong = cb / 4;
562 pb = pv;
564 while (cUlong-- > 0) {
565 ul = *pb++;
566 ul |= (((cab_ULONG)(*pb++)) << 8);
567 ul |= (((cab_ULONG)(*pb++)) << 16);
568 ul |= (((cab_ULONG)(*pb++)) << 24);
570 csum ^= ul;
573 ul = 0;
574 switch (cb % 4) {
575 case 3:
576 ul |= (((ULONG)(*pb++)) << 16);
577 case 2:
578 ul |= (((ULONG)(*pb++)) << 8);
579 case 1:
580 ul |= *pb;
581 default:
582 break;
584 csum ^= ul;
586 return csum;
587 } /* end of fci_get_checksum */
591 static BOOL fci_flushfolder_copy_cfdata(FCI_Int *p_fci_internal, char* buffer, UINT cbReserveCFData,
592 PFNFCISTATUS pfnfcis, int* err, int handleCFDATA1new,
593 cab_ULONG* psizeFileCFDATA1new, cab_ULONG* payload)
595 cab_ULONG read_result;
596 CFDATA* pcfdata=(CFDATA*)buffer;
597 BOOL split_block=FALSE;
598 cab_UWORD savedUncomp=0;
600 *payload=0;
602 /* while not all CFDATAs have been copied do */
603 while(!FALSE) {
604 if( p_fci_internal->fNextCab ) {
605 if( split_block ) {
606 /* internal error should never happen */
607 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
608 return FALSE;
611 /* REUSE the variable read_result */
612 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
613 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
614 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
615 read_result=4;
616 } else {
617 read_result=0;
619 if (p_fci_internal->fPrevCab) {
620 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
621 strlen(p_fci_internal->szPrevDisk)+1;
623 /* No more CFDATA fits into the cabinet under construction */
624 /* So don't try to store more data into it */
625 if( p_fci_internal->fNextCab &&
626 (p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData +
627 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
628 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
629 sizeof(CFHEADER) +
630 read_result +
631 p_fci_internal->oldCCAB.cbReserveCFHeader +
632 sizeof(CFFOLDER) +
633 p_fci_internal->oldCCAB.cbReserveCFFolder +
634 strlen(p_fci_internal->pccab->szCab)+1 +
635 strlen(p_fci_internal->pccab->szDisk)+1
636 )) {
637 /* This may never be run for the first time the while loop is entered.
638 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
639 split_block=TRUE; /* In this case split_block is abused to store */
640 /* the complete data block into the next cabinet and not into the */
641 /* current one. Originally split_block is the indicator that a */
642 /* data block has been split across different cabinets. */
643 } else {
645 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
646 read_result= p_fci_internal->read( p_fci_internal->handleCFDATA1,/*file handle*/
647 buffer, /* memory buffer */
648 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
649 err, p_fci_internal->pv);
650 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
651 if (read_result==0) break; /* ALL DATA has been copied */
652 /* read error */
653 set_error( p_fci_internal, FCIERR_NONE, ERROR_READ_FAULT );
654 return FALSE;
656 /* TODO error handling of err */
658 /* REUSE buffer p_fci_internal->data_out !!! */
659 /* read data from p_fci_internal->handleCFDATA1 to */
660 /* p_fci_internal->data_out */
661 if( p_fci_internal->read( p_fci_internal->handleCFDATA1 /* file handle */,
662 p_fci_internal->data_out /* memory buffer */,
663 pcfdata->cbData /* number of bytes to copy */,
664 err, p_fci_internal->pv) != pcfdata->cbData ) {
665 /* read error */
666 set_error( p_fci_internal, FCIERR_NONE, ERROR_READ_FAULT );
667 return FALSE;
669 /* TODO error handling of err */
671 /* if cabinet size is too large */
673 /* REUSE the variable read_result */
674 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
675 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
676 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
677 read_result=4;
678 } else {
679 read_result=0;
681 if (p_fci_internal->fPrevCab) {
682 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
683 strlen(p_fci_internal->szPrevDisk)+1;
686 /* Is cabinet with new CFDATA too large? Then data block has to be split */
687 if( p_fci_internal->fNextCab &&
688 (p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData +
689 pcfdata->cbData +
690 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
691 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
692 sizeof(CFHEADER) +
693 read_result +
694 p_fci_internal->oldCCAB.cbReserveCFHeader +
695 sizeof(CFFOLDER) + /* size of new CFFolder entry */
696 p_fci_internal->oldCCAB.cbReserveCFFolder +
697 strlen(p_fci_internal->pccab->szCab)+1 + /* name of next cabinet */
698 strlen(p_fci_internal->pccab->szDisk)+1 /* name of next disk */
699 )) {
700 /* REUSE read_result to save the size of the compressed data */
701 read_result=pcfdata->cbData;
702 /* Modify the size of the compressed data to store only a part of the */
703 /* data block into the current cabinet. This is done to prevent */
704 /* that the maximum cabinet size will be exceeded. The remainder */
705 /* will be stored into the next following cabinet. */
707 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
708 /* Substract everything except the size of the block of data */
709 /* to get it's actual size */
710 pcfdata->cbData = p_fci_internal->oldCCAB.cb - (
711 sizeof(CFDATA) + cbReserveCFData +
712 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
713 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
714 sizeof(CFHEADER) +
715 p_fci_internal->oldCCAB.cbReserveCFHeader +
716 sizeof(CFFOLDER) + /* set size of new CFFolder entry */
717 p_fci_internal->oldCCAB.cbReserveCFFolder );
718 /* substract the size of special header fields */
719 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
720 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
721 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
722 pcfdata->cbData-=4;
724 if (p_fci_internal->fPrevCab) {
725 pcfdata->cbData-=strlen(p_fci_internal->szPrevCab)+1 +
726 strlen(p_fci_internal->szPrevDisk)+1;
728 pcfdata->cbData-=strlen(p_fci_internal->pccab->szCab)+1 +
729 strlen(p_fci_internal->pccab->szDisk)+1;
731 savedUncomp = pcfdata->cbUncomp;
732 pcfdata->cbUncomp = 0; /* on split blocks of data this is zero */
734 /* if split_block==TRUE then the above while loop won't */
735 /* be executed again */
736 split_block=TRUE; /* split_block is the indicator that */
737 /* a data block has been split across */
738 /* different cabinets.*/
741 /* This should never happen !!! */
742 if (pcfdata->cbData==0) {
743 /* set error */
744 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
745 return FALSE;
748 /* set little endian */
749 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
750 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
752 /* get checksum and write to cfdata.csum */
753 pcfdata->csum = fci_get_checksum( &(pcfdata->cbData),
754 sizeof(CFDATA)+cbReserveCFData -
755 sizeof(pcfdata->csum), fci_get_checksum( p_fci_internal->data_out, /*buffer*/
756 pcfdata->cbData, 0 ) );
758 /* set little endian */
759 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
761 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
762 if( p_fci_internal->write( p_fci_internal->handleCFDATA2, /* file handle */
763 buffer, /* memory buffer */
764 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
765 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
766 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
767 return FALSE;
769 /* TODO error handling of err */
771 p_fci_internal->sizeFileCFDATA2 += sizeof(CFDATA)+cbReserveCFData;
773 /* reset little endian */
774 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
775 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
776 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
778 /* write compressed data into p_fci_internal->handleCFDATA2 */
779 if( p_fci_internal->write( p_fci_internal->handleCFDATA2, /* file handle */
780 p_fci_internal->data_out, /* memory buffer */
781 pcfdata->cbData, /* number of bytes to copy */
782 err, p_fci_internal->pv) != pcfdata->cbData) {
783 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
784 return FALSE;
786 /* TODO error handling of err */
788 p_fci_internal->sizeFileCFDATA2 += pcfdata->cbData;
789 ++(p_fci_internal->cDataBlocks);
790 p_fci_internal->statusFolderCopied += pcfdata->cbData;
791 (*payload)+=pcfdata->cbUncomp;
792 /* if cabinet size too large and data has been split */
793 /* write the remainder of the data block to the new CFDATA1 file */
794 if( split_block ) { /* This does not include the */
795 /* abused one (just search for "abused" )*/
796 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
797 if (p_fci_internal->fNextCab==FALSE ) {
798 /* internal error */
799 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
800 return FALSE;
803 /* set cbData to the size of the remainder of the data block */
804 pcfdata->cbData = read_result - pcfdata->cbData;
805 /*recover former value of cfdata.cbData; read_result will be the offset*/
806 read_result -= pcfdata->cbData;
807 pcfdata->cbUncomp = savedUncomp;
809 /* reset checksum, it will be computed later */
810 pcfdata->csum=0;
812 /* write cfdata WITHOUT checksum to handleCFDATA1new */
813 if( p_fci_internal->write( handleCFDATA1new, /* file handle */
814 buffer, /* memory buffer */
815 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
816 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
817 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
818 return FALSE;
820 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
822 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
824 /* write compressed data into handleCFDATA1new */
825 if( p_fci_internal->write( handleCFDATA1new, /* file handle */
826 p_fci_internal->data_out + read_result, /* memory buffer + offset */
827 /* to last part of split data */
828 pcfdata->cbData, /* number of bytes to copy */
829 err, p_fci_internal->pv) != pcfdata->cbData) {
830 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
831 return FALSE;
833 /* TODO error handling of err */
835 p_fci_internal->statusFolderCopied += pcfdata->cbData;
837 *psizeFileCFDATA1new += pcfdata->cbData;
838 /* the two blocks of the split data block have been written */
839 /* don't reset split_data yet, because it is still needed see below */
842 /* report status with pfnfcis about copied size of folder */
843 if( (*pfnfcis)(statusFolder,
844 p_fci_internal->statusFolderCopied, /*cfdata.cbData(+previous ones)*/
845 p_fci_internal->statusFolderTotal, /* total folder size */
846 p_fci_internal->pv) == -1) {
847 set_error( p_fci_internal, FCIERR_USER_ABORT, 0 );
848 return FALSE;
852 /* if cabinet size too large */
853 /* write the remaining data blocks to the new CFDATA1 file */
854 if ( split_block ) { /* This does include the */
855 /* abused one (just search for "abused" )*/
856 if (p_fci_internal->fNextCab==FALSE ) {
857 /* internal error */
858 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
859 return FALSE;
861 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
862 while(!FALSE) {
863 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
864 read_result= p_fci_internal->read( p_fci_internal->handleCFDATA1,/* handle */
865 buffer, /* memory buffer */
866 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
867 err, p_fci_internal->pv);
868 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
869 if (read_result==0) break; /* ALL DATA has been copied */
870 /* read error */
871 set_error( p_fci_internal,FCIERR_NONE, ERROR_READ_FAULT );
872 return FALSE;
874 /* TODO error handling of err */
876 /* REUSE buffer p_fci_internal->data_out !!! */
877 /* read data from p_fci_internal->handleCFDATA1 to */
878 /* p_fci_internal->data_out */
879 if( p_fci_internal->read( p_fci_internal->handleCFDATA1 /* file handle */,
880 p_fci_internal->data_out /* memory buffer */,
881 pcfdata->cbData /* number of bytes to copy */,
882 err, p_fci_internal->pv) != pcfdata->cbData ) {
883 /* read error */
884 set_error( p_fci_internal, FCIERR_NONE, ERROR_READ_FAULT );
885 return FALSE;
887 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
889 /* write cfdata with checksum to handleCFDATA1new */
890 if( p_fci_internal->write( handleCFDATA1new, /* file handle */
891 buffer, /* memory buffer */
892 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
893 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
894 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
895 return FALSE;
897 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
899 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
901 /* write compressed data into handleCFDATA1new */
902 if( p_fci_internal->write( handleCFDATA1new, /* file handle */
903 p_fci_internal->data_out, /* memory buffer */
904 pcfdata->cbData, /* number of bytes to copy */
905 err, p_fci_internal->pv) != pcfdata->cbData) {
906 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
907 return FALSE;
909 /* TODO error handling of err */
911 *psizeFileCFDATA1new += pcfdata->cbData;
912 p_fci_internal->statusFolderCopied += pcfdata->cbData;
914 /* report status with pfnfcis about copied size of folder */
915 if( (*pfnfcis)(statusFolder,
916 p_fci_internal->statusFolderCopied,/*cfdata.cbData(+previous ones)*/
917 p_fci_internal->statusFolderTotal, /* total folder size */
918 p_fci_internal->pv) == -1) {
919 set_error( p_fci_internal, FCIERR_USER_ABORT, 0 );
920 return FALSE;
923 } /* end of WHILE */
924 break; /* jump out of the next while loop */
925 } /* end of if( split_data ) */
926 } /* end of WHILE */
927 return TRUE;
928 } /* end of fci_flushfolder_copy_cfdata */
934 static BOOL fci_flushfolder_copy_cffile(FCI_Int *p_fci_internal, int* err, int handleCFFILE1new,
935 cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload)
937 CFFILE cffile;
938 cab_ULONG read_result;
939 cab_ULONG seek=0;
940 cab_ULONG sizeOfFiles=0, sizeOfFilesPrev;
941 BOOL may_be_prev=TRUE;
942 cab_ULONG cbFileRemainer=0;
944 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
945 if( p_fci_internal->seek(p_fci_internal->handleCFFILE1,0,SEEK_SET,err,
946 p_fci_internal->pv) !=0 ) {
947 /* wrong return value */
948 set_error( p_fci_internal, FCIERR_NONE, ERROR_SEEK );
949 return FALSE;
951 /* TODO error handling of err */
953 /* while not all CFFILE structures have been copied do */
954 while(!FALSE) {
955 /* REUSE the variable read_result */
956 /* read data from p_fci_internal->handleCFFILE1 to cffile */
957 read_result = p_fci_internal->read(p_fci_internal->handleCFFILE1/* file handle */,
958 &cffile, /* memory buffer */
959 sizeof(cffile), /* number of bytes to copy */
960 err, p_fci_internal->pv);
961 if( read_result != sizeof(cffile) ) {
962 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
963 /* read error */
964 set_error( p_fci_internal, FCIERR_NONE, ERROR_READ_FAULT );
965 return FALSE;
967 /* TODO error handling of err */
969 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
970 /* position. I don't know why so I'll just omit it */
972 /* read the filename from p_fci_internal->handleCFFILE1 */
973 /* REUSE the variable read_result AGAIN */
974 /* REUSE the memory buffer PFCI(hfci)->data_out */
975 if( p_fci_internal->read( p_fci_internal->handleCFFILE1 /*file handle*/,
976 p_fci_internal->data_out, /* memory buffer */
977 CB_MAX_FILENAME, /* number of bytes to copy */
978 err, p_fci_internal->pv) <2) {
979 /* read error */
980 set_error( p_fci_internal, FCIERR_NONE, ERROR_READ_FAULT );
981 return FALSE;
983 /* TODO maybe other checks of read_result */
984 /* TODO error handling of err */
986 /* safety */
987 if( strlen(p_fci_internal->data_out)>=CB_MAX_FILENAME ) {
988 /* set error code internal error */
989 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
990 return FALSE;
993 seek+=sizeof(cffile) + strlen(p_fci_internal->data_out)+1;
995 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
996 /* i.e. seek to the next CFFILE area */
997 if( p_fci_internal->seek(p_fci_internal->handleCFFILE1,
998 seek, /* seek position*/
999 SEEK_SET ,err,
1000 p_fci_internal->pv)
1001 != seek) {
1002 /* wrong return value */
1003 set_error( p_fci_internal, FCIERR_NONE, ERROR_SEEK );
1004 return FALSE;
1006 /* TODO error handling of err */
1008 /* fnfilfnfildest: placed file on cabinet */
1009 if (p_fci_internal->fNextCab ||
1010 p_fci_internal->fGetNextCabInVain) {
1011 p_fci_internal->fileplaced( &p_fci_internal->oldCCAB,
1012 p_fci_internal->data_out, /* the file name*/
1013 cffile.cbFile, /* file size */
1014 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
1015 p_fci_internal->pv
1017 } else {
1018 p_fci_internal->fileplaced( p_fci_internal->pccab,
1019 p_fci_internal->data_out, /* the file name*/
1020 cffile.cbFile, /* file size */
1021 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
1022 p_fci_internal->pv
1026 /* Check special iFolder values */
1027 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
1028 p_fci_internal->fPrevCab==FALSE ) {
1029 /* THIS MAY NEVER HAPPEN */
1030 /* set error code */
1031 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1032 return FALSE;
1034 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
1035 cffile.iFolder==cffileCONTINUED_TO_NEXT ) {
1036 /* THIS MAY NEVER HAPPEN */
1037 /* set error code */
1038 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1039 return FALSE;
1041 if( may_be_prev && cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
1042 may_be_prev=FALSE;
1044 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && may_be_prev==FALSE ) {
1045 /* THIS MAY NEVER HAPPEN */
1046 /* set error code */
1047 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1048 return FALSE;
1050 if( cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
1051 may_be_prev=FALSE;
1054 sizeOfFilesPrev=sizeOfFiles;
1055 /* Set complete size of all processed files */
1056 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
1057 p_fci_internal->cbFileRemainer!=0
1059 sizeOfFiles+=p_fci_internal->cbFileRemainer;
1060 p_fci_internal->cbFileRemainer=0;
1061 } else {
1062 sizeOfFiles+=cffile.cbFile;
1065 /* Check if spanned file fits into this cabinet folder */
1066 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && sizeOfFiles>payload ) {
1067 cffile.iFolder=cffileCONTINUED_PREV_AND_NEXT;
1068 } else
1070 /* Check if file doesn't fit into this cabinet folder */
1071 if( sizeOfFiles>payload ) {
1072 cffile.iFolder=cffileCONTINUED_TO_NEXT;
1075 /* set little endian */
1076 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1077 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1078 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1079 cffile.date=fci_endian_uword(cffile.date);
1080 cffile.time=fci_endian_uword(cffile.time);
1081 cffile.attribs=fci_endian_uword(cffile.attribs);
1083 /* write cffile to p_fci_internal->handleCFFILE2 */
1084 if( p_fci_internal->write( p_fci_internal->handleCFFILE2, /* file handle */
1085 &cffile, /* memory buffer */
1086 sizeof(cffile), /* number of bytes to copy */
1087 err, p_fci_internal->pv) != sizeof(cffile) ) {
1088 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
1089 return FALSE;
1091 /* TODO error handling of err */
1093 p_fci_internal->sizeFileCFFILE2 += sizeof(cffile);
1095 /* reset little endian */
1096 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1097 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1098 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1099 cffile.date=fci_endian_uword(cffile.date);
1100 cffile.time=fci_endian_uword(cffile.time);
1101 cffile.attribs=fci_endian_uword(cffile.attribs);
1103 /* write file name to p_fci_internal->handleCFFILE2 */
1104 if( p_fci_internal->write( p_fci_internal->handleCFFILE2, /* file handle */
1105 p_fci_internal->data_out, /* memory buffer */
1106 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1107 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1108 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
1109 return FALSE;
1111 /* TODO error handling of err */
1113 p_fci_internal->sizeFileCFFILE2 += strlen(p_fci_internal->data_out)+1;
1115 /* cFiles is used to count all files of a cabinet */
1116 ++(p_fci_internal->cFiles);
1118 /* This is only true for files which will be written into the */
1119 /* next cabinet of the spanning folder */
1120 if( sizeOfFiles>payload ) {
1122 /* Files which data will be partially written into the current cabinet */
1123 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
1124 cffile.iFolder==cffileCONTINUED_TO_NEXT
1126 if( sizeOfFilesPrev<=payload ) {
1127 /* The size of the uncompressed, data of a spanning file in a */
1128 /* spanning data */
1129 cbFileRemainer=sizeOfFiles-payload;
1131 cffile.iFolder=cffileCONTINUED_FROM_PREV;
1132 } else {
1133 cffile.iFolder=0;
1136 /* write cffile into handleCFFILE1new */
1137 if( p_fci_internal->write( handleCFFILE1new, /* file handle */
1138 &cffile, /* memory buffer */
1139 sizeof(cffile), /* number of bytes to copy */
1140 err, p_fci_internal->pv) != sizeof(cffile) ) {
1141 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
1142 return FALSE;
1144 /* TODO error handling of err */
1146 *psizeFileCFFILE1new += sizeof(cffile);
1147 /* write name of file into handleCFFILE1new */
1148 if( p_fci_internal->write( handleCFFILE1new, /* file handle */
1149 p_fci_internal->data_out, /* memory buffer */
1150 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1151 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1152 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
1153 return FALSE;
1155 /* TODO error handling of err */
1157 *psizeFileCFFILE1new += strlen(p_fci_internal->data_out)+1;
1160 } /* END OF while */
1161 p_fci_internal->cbFileRemainer=cbFileRemainer;
1162 return TRUE;
1163 } /* end of fci_flushfolder_copy_cffile */
1168 static BOOL fci_flush_folder( FCI_Int *p_fci_internal,
1169 BOOL fGetNextCab,
1170 PFNFCIGETNEXTCABINET pfnfcignc,
1171 PFNFCISTATUS pfnfcis)
1173 int err;
1174 int handleCFDATA1new; /* handle for new temp file */
1175 char szFileNameCFDATA1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1176 int handleCFFILE1new; /* handle for new temp file */
1177 char szFileNameCFFILE1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1178 UINT cbReserveCFData, cbReserveCFFolder;
1179 char* reserved;
1180 cab_ULONG sizeFileCFDATA1new=0;
1181 cab_ULONG sizeFileCFFILE1new=0;
1182 cab_ULONG payload;
1183 cab_ULONG read_result;
1184 struct folder *folder;
1186 if ((!pfnfcignc) || (!pfnfcis)) {
1187 set_error( p_fci_internal, FCIERR_NONE, ERROR_BAD_ARGUMENTS );
1188 return FALSE;
1191 if( p_fci_internal->fGetNextCabInVain &&
1192 p_fci_internal->fNextCab ){
1193 /* internal error */
1194 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1195 return FALSE;
1198 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1199 /* this function will return TRUE */
1200 if( p_fci_internal->sizeFileCFFILE1 == 0 ) {
1201 if ( p_fci_internal->sizeFileCFDATA1 != 0 ) {
1202 /* error handling */
1203 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1204 return FALSE;
1206 return TRUE;
1209 if (p_fci_internal->data_in==NULL || p_fci_internal->data_out==NULL ) {
1210 /* error handling */
1211 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1212 return FALSE;
1215 /* FCIFlushFolder has already been called... */
1216 if (p_fci_internal->fSplitFolder && p_fci_internal->sizeFileCFFILE2!=0) {
1217 return TRUE;
1220 /* This can be set already, because it makes only a difference */
1221 /* when the current function exits with return FALSE */
1222 p_fci_internal->fSplitFolder=FALSE;
1225 if( p_fci_internal->fGetNextCabInVain ||
1226 p_fci_internal->fNextCab ){
1227 cbReserveCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1228 cbReserveCFFolder = p_fci_internal->oldCCAB.cbReserveCFFolder;
1229 } else {
1230 cbReserveCFData = p_fci_internal->pccab->cbReserveCFData;
1231 cbReserveCFFolder = p_fci_internal->pccab->cbReserveCFFolder;
1234 /* START of COPY */
1235 /* if there is data in p_fci_internal->data_in */
1236 if (p_fci_internal->cdata_in!=0) {
1238 if( !fci_flush_data_block(p_fci_internal, &err, pfnfcis) ) return FALSE;
1241 /* reset to get the number of data blocks of this folder which are */
1242 /* actually in this cabinet ( at least partially ) */
1243 p_fci_internal->cDataBlocks=0;
1245 if ( p_fci_internal->fNextCab ||
1246 p_fci_internal->fGetNextCabInVain ) {
1247 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader+
1248 p_fci_internal->oldCCAB.cbReserveCFFolder;
1249 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1250 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1251 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1252 read_result+=4;
1254 } else {
1255 read_result= p_fci_internal->pccab->cbReserveCFHeader+
1256 p_fci_internal->pccab->cbReserveCFFolder;
1257 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1258 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1259 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1260 read_result+=4;
1263 if (p_fci_internal->fPrevCab) {
1264 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1265 strlen(p_fci_internal->szPrevDisk)+1;
1267 if (p_fci_internal->fNextCab) {
1268 read_result+=strlen(p_fci_internal->pccab->szCab)+1 +
1269 strlen(p_fci_internal->pccab->szDisk)+1;
1272 p_fci_internal->statusFolderTotal = sizeof(CFHEADER)+read_result+
1273 sizeof(CFFOLDER) + p_fci_internal->sizeFileCFFILE2+
1274 p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1+
1275 p_fci_internal->sizeFileCFDATA1 + p_fci_internal->folders_size;
1276 p_fci_internal->statusFolderCopied = 0;
1278 /* report status with pfnfcis about copied size of folder */
1279 if( (*pfnfcis)(statusFolder, p_fci_internal->statusFolderCopied,
1280 p_fci_internal->statusFolderTotal, /* TODO total folder size */
1281 p_fci_internal->pv) == -1) {
1282 set_error( p_fci_internal, FCIERR_USER_ABORT, 0 );
1283 return FALSE;
1286 /* get a new temp file */
1287 if(!p_fci_internal->gettemp(szFileNameCFDATA1new,CB_MAX_FILENAME, p_fci_internal->pv)) {
1288 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
1289 return FALSE;
1291 /* safety */
1292 if ( strlen(szFileNameCFDATA1new) >= CB_MAX_FILENAME ) {
1293 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
1294 return FALSE;
1296 handleCFDATA1new = p_fci_internal->open(szFileNameCFDATA1new, _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
1297 _S_IREAD | _S_IWRITE, &err, p_fci_internal->pv);
1298 if(handleCFDATA1new==0){
1299 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_OPEN_FAILED );
1300 return FALSE;
1302 /* TODO error handling of err */
1306 /* get a new temp file */
1307 if(!p_fci_internal->gettemp(szFileNameCFFILE1new,CB_MAX_FILENAME, p_fci_internal->pv)) {
1308 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
1309 p_fci_internal->close(handleCFDATA1new,&err,p_fci_internal->pv);
1310 /* TODO error handling of err */
1311 return FALSE;
1313 /* safety */
1314 if ( strlen(szFileNameCFFILE1new) >= CB_MAX_FILENAME ) {
1315 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
1316 p_fci_internal->close(handleCFDATA1new,&err,p_fci_internal->pv);
1317 /* TODO error handling of err */
1318 return FALSE;
1320 handleCFFILE1new = p_fci_internal->open(szFileNameCFFILE1new, _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
1321 _S_IREAD | _S_IWRITE, &err, p_fci_internal->pv);
1322 if(handleCFFILE1new==0){
1323 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_OPEN_FAILED );
1324 return FALSE;
1326 /* TODO error handling of err */
1328 /* USE the variable read_result */
1329 if ( p_fci_internal->fNextCab ||
1330 p_fci_internal->fGetNextCabInVain ) {
1331 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader;
1332 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1333 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1334 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1335 read_result+=4;
1337 } else {
1338 read_result= p_fci_internal->pccab->cbReserveCFHeader;
1339 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1340 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1341 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1342 read_result+=4;
1345 if (p_fci_internal->fPrevCab) {
1346 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1347 strlen(p_fci_internal->szPrevDisk)+1;
1349 read_result+= sizeof(CFHEADER) + p_fci_internal->sizeFileCFDATA2 +
1350 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size;
1352 if(p_fci_internal->sizeFileCFFILE1!=0) {
1353 read_result+= sizeof(CFFOLDER)+p_fci_internal->pccab->cbReserveCFFolder;
1356 /* Check if multiple cabinets have to be created. */
1358 /* Might be too much data for the maximum allowed cabinet size.*/
1359 /* When any further data will be added later, it might not */
1360 /* be possible to flush the cabinet, because there might */
1361 /* not be enough space to store the name of the following */
1362 /* cabinet and name of the corresponding disk. */
1363 /* So take care of this and get the name of the next cabinet */
1364 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1365 p_fci_internal->fNextCab==FALSE &&
1368 p_fci_internal->pccab->cb < read_result +
1369 p_fci_internal->sizeFileCFDATA1 +
1370 p_fci_internal->sizeFileCFFILE1 +
1371 CB_MAX_CABINET_NAME + /* next cabinet name */
1372 CB_MAX_DISK_NAME /* next disk name */
1373 ) || fGetNextCab
1376 /* save CCAB */
1377 p_fci_internal->oldCCAB = *p_fci_internal->pccab;
1378 /* increment cabinet index */
1379 ++(p_fci_internal->pccab->iCab);
1380 /* get name of next cabinet */
1381 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
1382 if (!(*pfnfcignc)(p_fci_internal->pccab,
1383 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
1384 p_fci_internal->pv)) {
1385 /* error handling */
1386 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
1387 p_fci_internal->close(handleCFDATA1new,&err,p_fci_internal->pv);
1388 /* TODO error handling of err */
1389 p_fci_internal->close(handleCFFILE1new,&err,p_fci_internal->pv);
1390 /* TODO error handling of err */
1391 return FALSE;
1394 /* Skip a few lines of code. This is caught by the next if. */
1395 p_fci_internal->fGetNextCabInVain=TRUE;
1398 /* too much data for cabinet */
1399 if( (p_fci_internal->fGetNextCabInVain ||
1400 p_fci_internal->fNextCab ) &&
1403 p_fci_internal->oldCCAB.cb < read_result +
1404 p_fci_internal->sizeFileCFDATA1 +
1405 p_fci_internal->sizeFileCFFILE1 +
1406 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1407 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1408 ) || fGetNextCab
1411 p_fci_internal->fGetNextCabInVain=FALSE;
1412 p_fci_internal->fNextCab=TRUE;
1414 /* return FALSE if there is not enough space left*/
1415 /* this should never happen */
1416 if (p_fci_internal->oldCCAB.cb <=
1417 p_fci_internal->sizeFileCFFILE1 +
1418 read_result +
1419 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1420 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1423 p_fci_internal->close(handleCFDATA1new,&err,p_fci_internal->pv);
1424 /* TODO error handling of err */
1425 p_fci_internal->delete(szFileNameCFDATA1new,&err,p_fci_internal->pv);
1426 /* TODO error handling of err */
1428 /* close and delete p_fci_internal->handleCFFILE1 */
1429 p_fci_internal->close(handleCFFILE1new,&err,p_fci_internal->pv);
1430 /* TODO error handling of err */
1431 p_fci_internal->delete(szFileNameCFFILE1new,&err,p_fci_internal->pv);
1432 /* TODO error handling of err */
1434 return FALSE;
1437 /* the folder will be split across cabinets */
1438 p_fci_internal->fSplitFolder=TRUE;
1440 } else {
1441 /* this should never happen */
1442 if (p_fci_internal->fNextCab) {
1443 /* internal error */
1444 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1445 return FALSE;
1449 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1450 if( p_fci_internal->seek(p_fci_internal->handleCFDATA1,0,SEEK_SET,&err,
1451 p_fci_internal->pv) !=0 ) {
1452 /* wrong return value */
1453 set_error( p_fci_internal, FCIERR_NONE, ERROR_SEEK );
1454 p_fci_internal->close(handleCFDATA1new,&err,p_fci_internal->pv);
1455 /* TODO error handling of err */
1456 p_fci_internal->close(handleCFFILE1new,&err,p_fci_internal->pv);
1457 /* TODO error handling of err */
1458 return FALSE;
1460 /* TODO error handling of err */
1462 if (!(folder = add_folder( p_fci_internal ))) return FALSE;
1464 if(!(reserved = p_fci_internal->alloc( cbReserveCFData+sizeof(CFDATA)))) {
1465 set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
1466 p_fci_internal->close(handleCFDATA1new,&err,p_fci_internal->pv);
1467 /* TODO error handling of err */
1468 p_fci_internal->close(handleCFFILE1new,&err,p_fci_internal->pv);
1469 /* TODO error handling of err */
1470 return FALSE;
1473 if(!fci_flushfolder_copy_cfdata(p_fci_internal, reserved, cbReserveCFData, pfnfcis, &err,
1474 handleCFDATA1new, &sizeFileCFDATA1new, &payload
1475 )) {
1476 p_fci_internal->close(handleCFDATA1new,&err,p_fci_internal->pv);
1477 /* TODO error handling of err */
1478 p_fci_internal->delete(szFileNameCFDATA1new,&err,p_fci_internal->pv);
1479 /* TODO error handling of err */
1480 p_fci_internal->close(handleCFFILE1new,&err,p_fci_internal->pv);
1481 /* TODO error handling of err */
1482 p_fci_internal->free(reserved);
1483 return FALSE;
1486 p_fci_internal->free(reserved);
1488 folder->data_count = p_fci_internal->cDataBlocks;
1490 if(!fci_flushfolder_copy_cffile(p_fci_internal, &err, handleCFFILE1new,
1491 &sizeFileCFFILE1new, payload)) {
1492 p_fci_internal->close(handleCFDATA1new,&err,p_fci_internal->pv);
1493 /* TODO error handling of err */
1494 p_fci_internal->delete(szFileNameCFDATA1new,&err,p_fci_internal->pv);
1495 /* TODO error handling of err */
1496 p_fci_internal->close(handleCFFILE1new,&err,p_fci_internal->pv);
1497 /* TODO error handling of err */
1498 p_fci_internal->delete(szFileNameCFFILE1new,&err,p_fci_internal->pv);
1499 /* TODO error handling of err */
1500 return FALSE;
1503 /* close and delete p_fci_internal->handleCFDATA1 */
1504 p_fci_internal->close(p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
1505 /* TODO error handling of err */
1506 p_fci_internal->delete(p_fci_internal->szFileNameCFDATA1,&err,p_fci_internal->pv);
1507 /* TODO error handling of err */
1509 /* put new CFDATA1 into hfci */
1510 memcpy(p_fci_internal->szFileNameCFDATA1,szFileNameCFDATA1new,
1511 CB_MAX_FILENAME);
1513 /* put CFDATA1 file handle */
1514 p_fci_internal->handleCFDATA1 = handleCFDATA1new;
1515 /* set file size */
1516 p_fci_internal->sizeFileCFDATA1 = sizeFileCFDATA1new;
1518 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1519 p_fci_internal->close(p_fci_internal->handleCFFILE1,&err,p_fci_internal->pv);
1520 /* TODO error handling of err */
1521 p_fci_internal->delete(p_fci_internal->szFileNameCFFILE1,&err,p_fci_internal->pv);
1522 /* TODO error handling of err */
1524 /* put new CFFILE1 into hfci */
1525 memcpy(p_fci_internal->szFileNameCFFILE1,szFileNameCFFILE1new,
1526 CB_MAX_FILENAME);
1528 /* put CFFILE1 file handle */
1529 p_fci_internal->handleCFFILE1 = handleCFFILE1new;
1530 /* set file size */
1531 p_fci_internal->sizeFileCFFILE1 = sizeFileCFFILE1new;
1533 /* reset CFFolder specific information */
1534 p_fci_internal->cDataBlocks=0;
1535 p_fci_internal->cCompressedBytesInFolder=0;
1537 return TRUE;
1538 } /* end of fci_flush_folder */
1543 static BOOL fci_flush_cabinet( FCI_Int *p_fci_internal,
1544 BOOL fGetNextCab,
1545 PFNFCIGETNEXTCABINET pfnfcignc,
1546 PFNFCISTATUS pfnfcis)
1548 int err;
1549 CFHEADER cfheader;
1550 struct {
1551 cab_UWORD cbCFHeader;
1552 cab_UBYTE cbCFFolder;
1553 cab_UBYTE cbCFData;
1554 } cfreserved;
1555 cab_ULONG header_size;
1556 cab_ULONG read_result=0;
1557 int handleCABINET; /* file handle for cabinet */
1558 char szFileNameCABINET[CB_MAX_CAB_PATH+CB_MAX_CABINET_NAME];/* name buffer */
1559 UINT cbReserveCFHeader, cbReserveCFFolder, i;
1560 char* reserved;
1561 BOOL returntrue=FALSE;
1563 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1565 /* when FCIFlushCabinet was or FCIAddFile hasn't been called */
1566 if( p_fci_internal->sizeFileCFFILE1==0 && fGetNextCab ) {
1567 returntrue=TRUE;
1570 if (!fci_flush_folder(p_fci_internal,fGetNextCab,pfnfcignc,pfnfcis)){
1571 /* TODO set error */
1572 return FALSE;
1575 if(returntrue) return TRUE;
1577 if ( (p_fci_internal->fSplitFolder && p_fci_internal->fNextCab==FALSE)||
1578 (p_fci_internal->folders_size==0 &&
1579 (p_fci_internal->sizeFileCFFILE1!=0 ||
1580 p_fci_internal->sizeFileCFFILE2!=0 )
1583 /* error */
1584 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1585 return FALSE;
1588 if( p_fci_internal->fNextCab ||
1589 p_fci_internal->fGetNextCabInVain ) {
1590 cbReserveCFFolder=p_fci_internal->oldCCAB.cbReserveCFFolder;
1591 cbReserveCFHeader=p_fci_internal->oldCCAB.cbReserveCFHeader;
1592 /* safety */
1593 if (strlen(p_fci_internal->oldCCAB.szCabPath)>=CB_MAX_CAB_PATH ||
1594 strlen(p_fci_internal->oldCCAB.szCab)>=CB_MAX_CABINET_NAME) {
1595 /* set error */
1596 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
1597 return FALSE;
1599 /* get the full name of the cabinet */
1600 memcpy(szFileNameCABINET,p_fci_internal->oldCCAB.szCabPath,
1601 CB_MAX_CAB_PATH);
1602 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1603 p_fci_internal->oldCCAB.szCab, CB_MAX_CABINET_NAME);
1604 } else {
1605 cbReserveCFFolder=p_fci_internal->pccab->cbReserveCFFolder;
1606 cbReserveCFHeader=p_fci_internal->pccab->cbReserveCFHeader;
1607 /* safety */
1608 if (strlen(p_fci_internal->pccab->szCabPath)>=CB_MAX_CAB_PATH ||
1609 strlen(p_fci_internal->pccab->szCab)>=CB_MAX_CABINET_NAME) {
1610 /* set error */
1611 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
1612 return FALSE;
1614 /* get the full name of the cabinet */
1615 memcpy(szFileNameCABINET,p_fci_internal->pccab->szCabPath,
1616 CB_MAX_CAB_PATH);
1617 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1618 p_fci_internal->pccab->szCab, CB_MAX_CABINET_NAME);
1621 memcpy(cfheader.signature,"!CAB",4);
1622 cfheader.reserved1=0;
1623 cfheader.cbCabinet= /* size of the cabinet file in bytes */
1624 sizeof(CFHEADER) +
1625 p_fci_internal->folders_size +
1626 p_fci_internal->sizeFileCFFILE2 +
1627 p_fci_internal->sizeFileCFDATA2;
1629 if (p_fci_internal->fPrevCab) {
1630 cfheader.cbCabinet+=strlen(p_fci_internal->szPrevCab)+1 +
1631 strlen(p_fci_internal->szPrevDisk)+1;
1633 if (p_fci_internal->fNextCab) {
1634 cfheader.cbCabinet+=strlen(p_fci_internal->pccab->szCab)+1 +
1635 strlen(p_fci_internal->pccab->szDisk)+1;
1637 if( p_fci_internal->fNextCab ||
1638 p_fci_internal->fGetNextCabInVain ) {
1639 cfheader.cbCabinet+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1640 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1641 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1642 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1643 cfheader.cbCabinet+=4;
1645 } else {
1646 cfheader.cbCabinet+=p_fci_internal->pccab->cbReserveCFHeader;
1647 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1648 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1649 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1650 cfheader.cbCabinet+=4;
1654 if( ( ( p_fci_internal->fNextCab ||
1655 p_fci_internal->fGetNextCabInVain ) &&
1656 cfheader.cbCabinet > p_fci_internal->oldCCAB.cb
1657 ) ||
1658 ( ( p_fci_internal->fNextCab==FALSE &&
1659 p_fci_internal->fGetNextCabInVain==FALSE ) &&
1660 cfheader.cbCabinet > p_fci_internal->pccab->cb
1664 set_error( p_fci_internal, FCIERR_NONE, ERROR_MORE_DATA );
1665 return FALSE;
1669 cfheader.reserved2=0;
1670 cfheader.coffFiles= /* offset to first CFFILE section */
1671 cfheader.cbCabinet - p_fci_internal->sizeFileCFFILE2 -
1672 p_fci_internal->sizeFileCFDATA2;
1674 cfheader.reserved3=0;
1675 cfheader.versionMinor=3;
1676 cfheader.versionMajor=1;
1677 /* number of CFFOLDER entries in the cabinet */
1678 cfheader.cFolders=p_fci_internal->cFolders;
1679 /* number of CFFILE entries in the cabinet */
1680 cfheader.cFiles=p_fci_internal->cFiles;
1681 cfheader.flags=0; /* 1=prev cab, 2=next cabinet, 4=reserved sections */
1683 if( p_fci_internal->fPrevCab ) {
1684 cfheader.flags = cfheadPREV_CABINET;
1687 if( p_fci_internal->fNextCab ) {
1688 cfheader.flags |= cfheadNEXT_CABINET;
1691 if( p_fci_internal->fNextCab ||
1692 p_fci_internal->fGetNextCabInVain ) {
1693 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1694 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1695 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1696 cfheader.flags |= cfheadRESERVE_PRESENT;
1698 cfheader.setID = p_fci_internal->oldCCAB.setID;
1699 cfheader.iCabinet = p_fci_internal->oldCCAB.iCab-1;
1700 } else {
1701 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1702 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1703 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1704 cfheader.flags |= cfheadRESERVE_PRESENT;
1706 cfheader.setID = p_fci_internal->pccab->setID;
1707 cfheader.iCabinet = p_fci_internal->pccab->iCab-1;
1710 /* create the cabinet */
1711 handleCABINET = p_fci_internal->open( szFileNameCABINET, _O_RDWR | _O_CREAT | _O_TRUNC | _O_BINARY,
1712 _S_IREAD | _S_IWRITE, &err, p_fci_internal->pv );
1713 if(handleCABINET==-1)
1715 set_error( p_fci_internal, FCIERR_CAB_FILE, err );
1716 return FALSE;
1718 /* TODO error checking of err */
1720 /* set little endian */
1721 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1722 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1723 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1724 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1725 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1726 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1727 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1728 cfheader.flags=fci_endian_uword(cfheader.flags);
1729 cfheader.setID=fci_endian_uword(cfheader.setID);
1730 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1732 /* write CFHEADER into cabinet file */
1733 if( p_fci_internal->write( handleCABINET, /* file handle */
1734 &cfheader, /* memory buffer */
1735 sizeof(cfheader), /* number of bytes to copy */
1736 &err, p_fci_internal->pv) != sizeof(cfheader) ) {
1737 /* write error */
1738 set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
1739 return FALSE;
1741 /* TODO error handling of err */
1743 /* reset little endian */
1744 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1745 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1746 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1747 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1748 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1749 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1750 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1751 cfheader.flags=fci_endian_uword(cfheader.flags);
1752 cfheader.setID=fci_endian_uword(cfheader.setID);
1753 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1755 if( cfheader.flags & cfheadRESERVE_PRESENT ) {
1756 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1757 cfreserved.cbCFHeader = cbReserveCFHeader;
1758 cfreserved.cbCFFolder = cbReserveCFFolder;
1759 if( p_fci_internal->fNextCab ||
1760 p_fci_internal->fGetNextCabInVain ) {
1761 cfreserved.cbCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1762 } else {
1763 cfreserved.cbCFData = p_fci_internal->pccab->cbReserveCFData;
1766 /* set little endian */
1767 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1769 /* write reserved info into cabinet file */
1770 if( p_fci_internal->write( handleCABINET, /* file handle */
1771 &cfreserved, /* memory buffer */
1772 sizeof(cfreserved), /* number of bytes to copy */
1773 &err, p_fci_internal->pv) != sizeof(cfreserved) ) {
1774 /* write error */
1775 set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
1776 return FALSE;
1778 /* TODO error handling of err */
1780 /* reset little endian */
1781 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1784 /* add optional reserved area */
1785 if (cbReserveCFHeader!=0) {
1786 if(!(reserved = p_fci_internal->alloc( cbReserveCFHeader))) {
1787 set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
1788 return FALSE;
1790 for(i=0;i<cbReserveCFHeader;) {
1791 reserved[i++]='\0';
1793 if( p_fci_internal->write( handleCABINET, /* file handle */
1794 reserved, /* memory buffer */
1795 cbReserveCFHeader, /* number of bytes to copy */
1796 &err, p_fci_internal->pv) != cbReserveCFHeader ) {
1797 p_fci_internal->free(reserved);
1798 /* write error */
1799 set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
1800 return FALSE;
1802 /* TODO error handling of err */
1803 p_fci_internal->free(reserved);
1806 if( cfheader.flags & cfheadPREV_CABINET ) {
1807 if( p_fci_internal->write( handleCABINET, /* file handle */
1808 p_fci_internal->szPrevCab, /* memory buffer */
1809 strlen(p_fci_internal->szPrevCab)+1, /* number of bytes to copy */
1810 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevCab)+1 ) {
1811 /* write error */
1812 set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
1813 return FALSE;
1815 /* TODO error handling of err */
1817 if( p_fci_internal->write( handleCABINET, /* file handle */
1818 p_fci_internal->szPrevDisk, /* memory buffer */
1819 strlen(p_fci_internal->szPrevDisk)+1, /* number of bytes to copy */
1820 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevDisk)+1 ) {
1821 /* write error */
1822 set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
1823 return FALSE;
1825 /* TODO error handling of err */
1828 if( cfheader.flags & cfheadNEXT_CABINET ) {
1829 if( p_fci_internal->write( handleCABINET, /* file handle */
1830 p_fci_internal->pccab->szCab, /* memory buffer */
1831 strlen(p_fci_internal->pccab->szCab)+1, /* number of bytes to copy */
1832 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szCab)+1 ) {
1833 /* write error */
1834 set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
1835 return FALSE;
1837 /* TODO error handling of err */
1839 if( p_fci_internal->write( handleCABINET, /* file handle */
1840 p_fci_internal->pccab->szDisk, /* memory buffer */
1841 strlen(p_fci_internal->pccab->szDisk)+1, /* number of bytes to copy */
1842 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szDisk)+1 ) {
1843 /* write error */
1844 set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
1845 return FALSE;
1847 /* TODO error handling of err */
1850 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1851 header_size = p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size + sizeof(CFHEADER);
1852 if( p_fci_internal->fNextCab || p_fci_internal->fGetNextCabInVain ) {
1853 header_size+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1854 } else {
1855 header_size+=p_fci_internal->pccab->cbReserveCFHeader;
1858 if (p_fci_internal->fPrevCab) {
1859 header_size += strlen(p_fci_internal->szPrevCab)+1 +
1860 strlen(p_fci_internal->szPrevDisk)+1;
1863 if (p_fci_internal->fNextCab) {
1864 header_size += strlen(p_fci_internal->oldCCAB.szCab)+1 +
1865 strlen(p_fci_internal->oldCCAB.szDisk)+1;
1868 if( p_fci_internal->fNextCab || p_fci_internal->fGetNextCabInVain ) {
1869 header_size += p_fci_internal->oldCCAB.cbReserveCFHeader;
1870 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1871 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1872 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1873 header_size += 4;
1875 } else {
1876 header_size += p_fci_internal->pccab->cbReserveCFHeader;
1877 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1878 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1879 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1880 header_size += 4;
1884 if (!write_folders( p_fci_internal, handleCABINET, header_size )) return FALSE;
1886 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1887 if( p_fci_internal->seek(p_fci_internal->handleCFFILE2,
1888 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1889 /* wrong return value */
1890 set_error( p_fci_internal, FCIERR_NONE, ERROR_SEEK );
1891 return FALSE;
1893 /* TODO error handling of err */
1895 /* while not all CFFILE structures have been copied to the cabinet do */
1896 if (p_fci_internal->data_out) while(!FALSE) {
1897 /* REUSE the variable read_result */
1898 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1899 /* read a block from p_fci_internal->handleCFFILE2 */
1900 read_result = p_fci_internal->read( p_fci_internal->handleCFFILE2 /* handle */,
1901 p_fci_internal->data_out, /* memory buffer */
1902 CB_MAX_CHUNK, /* number of bytes to copy */
1903 &err, p_fci_internal->pv);
1904 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
1905 /* TODO error handling of err */
1907 /* write the block to the cabinet file */
1908 if( p_fci_internal->write( handleCABINET, /* file handle */
1909 p_fci_internal->data_out, /* memory buffer */
1910 read_result, /* number of bytes to copy */
1911 &err, p_fci_internal->pv) != read_result ) {
1912 /* write error */
1913 set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
1914 return FALSE;
1916 /* TODO error handling of err */
1918 if (p_fci_internal->fSplitFolder==FALSE) {
1919 p_fci_internal->statusFolderCopied = 0;
1920 /* TODO TEST THIS further */
1921 p_fci_internal->statusFolderTotal = p_fci_internal->sizeFileCFDATA2+
1922 p_fci_internal->sizeFileCFFILE2;
1924 p_fci_internal->statusFolderCopied += read_result;
1926 /* report status with pfnfcis about copied size of folder */
1927 if( (*pfnfcis)(statusFolder,
1928 p_fci_internal->statusFolderCopied, /* length of copied blocks */
1929 p_fci_internal->statusFolderTotal, /* total size of folder */
1930 p_fci_internal->pv) == -1) {
1931 set_error( p_fci_internal, FCIERR_USER_ABORT, 0 );
1932 return FALSE;
1935 } /* END OF while */
1937 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1938 if( p_fci_internal->seek(p_fci_internal->handleCFDATA2,
1939 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1940 /* wrong return value */
1941 set_error( p_fci_internal, FCIERR_NONE, ERROR_SEEK );
1942 return FALSE;
1944 /* TODO error handling of err */
1946 /* reset the number of folders for the next cabinet */
1947 p_fci_internal->cFolders=0;
1948 /* reset the number of files for the next cabinet */
1949 p_fci_internal->cFiles=0;
1951 /* while not all CFDATA structures have been copied to the cabinet do */
1952 if (p_fci_internal->data_out) while(!FALSE) {
1953 /* REUSE the variable read_result AGAIN */
1954 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1955 /* read a block from p_fci_internal->handleCFDATA2 */
1956 read_result = p_fci_internal->read( p_fci_internal->handleCFDATA2 /* handle */,
1957 p_fci_internal->data_out, /* memory buffer */
1958 CB_MAX_CHUNK, /* number of bytes to copy */
1959 &err, p_fci_internal->pv);
1960 if( read_result == 0 ) break; /* ALL CFDATA structures have been copied */
1961 /* TODO error handling of err */
1963 /* write the block to the cabinet file */
1964 if( p_fci_internal->write( handleCABINET, /* file handle */
1965 p_fci_internal->data_out, /* memory buffer */
1966 read_result, /* number of bytes to copy */
1967 &err, p_fci_internal->pv) != read_result ) {
1968 /* write error */
1969 set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
1970 return FALSE;
1972 /* TODO error handling of err */
1974 p_fci_internal->statusFolderCopied += read_result;
1975 /* report status with pfnfcis about copied size of folder */
1976 if( (*pfnfcis)(statusFolder,
1977 p_fci_internal->statusFolderCopied, /* length of copied blocks */
1978 p_fci_internal->statusFolderTotal, /* total size of folder */
1979 p_fci_internal->pv) == -1) {
1980 /* set error code and abort */
1981 set_error( p_fci_internal, FCIERR_USER_ABORT, 0 );
1982 return FALSE;
1984 } /* END OF while */
1986 /* set seek of the cabinet file to 0 */
1987 if( p_fci_internal->seek( handleCABINET,
1988 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1989 /* wrong return value */
1990 set_error( p_fci_internal, FCIERR_NONE, ERROR_SEEK );
1991 return FALSE;
1993 /* TODO error handling of err */
1995 /* write the signature "MSCF" into the cabinet file */
1996 memcpy( cfheader.signature, "MSCF", 4 );
1997 if( p_fci_internal->write( handleCABINET, /* file handle */
1998 &cfheader, /* memory buffer */
1999 4, /* number of bytes to copy */
2000 &err, p_fci_internal->pv) != 4 ) {
2001 /* wrtie error */
2002 set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
2003 return FALSE;
2005 /* TODO error handling of err */
2007 /* close the cabinet file */
2008 p_fci_internal->close(handleCABINET,&err,p_fci_internal->pv);
2009 /* TODO error handling of err */
2012 /* COPIED FROM FCIDestroy */
2014 p_fci_internal->close( p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2015 /* TODO error handling of err */
2016 p_fci_internal->delete( p_fci_internal->szFileNameCFDATA2, &err,
2017 p_fci_internal->pv);
2018 /* TODO error handling of err */
2019 p_fci_internal->close( p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2020 /* TODO error handling of err */
2021 p_fci_internal->delete( p_fci_internal->szFileNameCFFILE2, &err,
2022 p_fci_internal->pv);
2023 /* TODO error handling of err */
2025 /* END OF copied from FCIDestroy */
2027 /* get 3 temporary files and open them */
2028 /* write names and handles to hfci */
2030 p_fci_internal->folders_size = 0;
2031 p_fci_internal->sizeFileCFDATA2 = 0;
2032 p_fci_internal->sizeFileCFFILE2 = 0;
2033 p_fci_internal->folders_size = 0;
2035 /* COPIED FROM FCICreate */
2037 /* CFDATA with checksum and ready to be copied into cabinet */
2038 if( !p_fci_internal->gettemp( p_fci_internal->szFileNameCFDATA2,
2039 CB_MAX_FILENAME, p_fci_internal->pv)) {
2040 /* error handling */
2041 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
2042 return FALSE;
2044 /* safety */
2045 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
2046 /* set error code and abort */
2047 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
2048 return FALSE;
2050 p_fci_internal->handleCFDATA2 = p_fci_internal->open( p_fci_internal->szFileNameCFDATA2,
2051 _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
2052 _S_IREAD | _S_IWRITE, &err, p_fci_internal->pv);
2053 /* check handle */
2054 if(p_fci_internal->handleCFDATA2==0){
2055 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_OPEN_FAILED );
2056 return FALSE;
2058 /* TODO error checking of err */
2060 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2061 if( !p_fci_internal->gettemp(p_fci_internal->szFileNameCFFILE2,
2062 CB_MAX_FILENAME, p_fci_internal->pv)) {
2063 /* error handling */
2064 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
2065 return FALSE;
2067 /* safety */
2068 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
2069 /* set error code and abort */
2070 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
2071 return FALSE;
2073 p_fci_internal->handleCFFILE2 = p_fci_internal->open( p_fci_internal->szFileNameCFFILE2,
2074 _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
2075 _S_IREAD | _S_IWRITE, &err, p_fci_internal->pv);
2076 /* check handle */
2077 if(p_fci_internal->handleCFFILE2==0){
2078 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_OPEN_FAILED );
2079 return FALSE;
2081 /* TODO error checking of err */
2083 /* END OF copied from FCICreate */
2086 /* TODO close and delete new files when return FALSE */
2089 /* report status with pfnfcis about copied size of folder */
2090 (*pfnfcis)(statusCabinet,
2091 p_fci_internal->estimatedCabinetSize, /* estimated cabinet file size */
2092 cfheader.cbCabinet /* real cabinet file size */, p_fci_internal->pv);
2094 p_fci_internal->fPrevCab=TRUE;
2095 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2096 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2098 if (p_fci_internal->fNextCab) {
2099 p_fci_internal->fNextCab=FALSE;
2101 if (p_fci_internal->sizeFileCFFILE1==0 && p_fci_internal->sizeFileCFDATA1!=0) {
2102 /* THIS CAN NEVER HAPPEN */
2103 /* set error code */
2104 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2105 return FALSE;
2108 /* COPIED FROM FCIAddFile and modified */
2110 /* REUSE the variable read_result */
2111 if (p_fci_internal->fGetNextCabInVain) {
2112 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader;
2113 if(p_fci_internal->sizeFileCFFILE1!=0) {
2114 read_result+=p_fci_internal->oldCCAB.cbReserveCFFolder;
2116 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2117 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2118 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2119 read_result+=4;
2121 } else {
2122 read_result=p_fci_internal->pccab->cbReserveCFHeader;
2123 if(p_fci_internal->sizeFileCFFILE1!=0) {
2124 read_result+=p_fci_internal->pccab->cbReserveCFFolder;
2126 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2127 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2128 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2129 read_result+=4;
2132 if ( p_fci_internal->fPrevCab ) {
2133 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2134 strlen(p_fci_internal->szPrevDisk)+1;
2136 read_result+= p_fci_internal->sizeFileCFDATA1 +
2137 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2138 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
2139 sizeof(CFHEADER) +
2140 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2142 if( p_fci_internal->fNewPrevious ) {
2143 memcpy(p_fci_internal->szPrevCab, p_fci_internal->oldCCAB.szCab,
2144 CB_MAX_CABINET_NAME);
2145 memcpy(p_fci_internal->szPrevDisk, p_fci_internal->oldCCAB.szDisk,
2146 CB_MAX_DISK_NAME);
2147 p_fci_internal->fNewPrevious=FALSE;
2150 /* too much data for the maximum size of a cabinet */
2151 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2152 p_fci_internal->pccab->cb < read_result ) {
2153 return fci_flush_cabinet( p_fci_internal, FALSE, pfnfcignc, pfnfcis);
2156 /* Might be too much data for the maximum size of a cabinet.*/
2157 /* When any further data will be added later, it might not */
2158 /* be possible to flush the cabinet, because there might */
2159 /* not be enough space to store the name of the following */
2160 /* cabinet and name of the corresponding disk. */
2161 /* So take care of this and get the name of the next cabinet */
2162 if (p_fci_internal->fGetNextCabInVain==FALSE && (
2163 p_fci_internal->pccab->cb < read_result +
2164 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2165 )) {
2166 /* save CCAB */
2167 p_fci_internal->oldCCAB = *p_fci_internal->pccab;
2168 /* increment cabinet index */
2169 ++(p_fci_internal->pccab->iCab);
2170 /* get name of next cabinet */
2171 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2172 if (!(*pfnfcignc)(p_fci_internal->pccab,
2173 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2174 p_fci_internal->pv)) {
2175 /* error handling */
2176 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
2177 return FALSE;
2179 /* Skip a few lines of code. This is caught by the next if. */
2180 p_fci_internal->fGetNextCabInVain=TRUE;
2183 /* too much data for cabinet */
2184 if (p_fci_internal->fGetNextCabInVain && (
2185 p_fci_internal->oldCCAB.cb < read_result +
2186 strlen(p_fci_internal->oldCCAB.szCab)+1+
2187 strlen(p_fci_internal->oldCCAB.szDisk)+1
2188 )) {
2189 p_fci_internal->fGetNextCabInVain=FALSE;
2190 p_fci_internal->fNextCab=TRUE;
2191 return fci_flush_cabinet( p_fci_internal, FALSE, pfnfcignc, pfnfcis);
2194 /* if the FolderThreshold has been reached flush the folder automatically */
2195 if( p_fci_internal->fGetNextCabInVain ) {
2196 if( p_fci_internal->cCompressedBytesInFolder >=
2197 p_fci_internal->oldCCAB.cbFolderThresh) {
2198 return fci_flush_folder(p_fci_internal, FALSE, pfnfcignc, pfnfcis);
2200 } else {
2201 if( p_fci_internal->cCompressedBytesInFolder >=
2202 p_fci_internal->pccab->cbFolderThresh) {
2203 return fci_flush_folder(p_fci_internal, FALSE, pfnfcignc, pfnfcis);
2207 /* END OF COPIED FROM FCIAddFile and modified */
2209 if( p_fci_internal->sizeFileCFFILE1>0 ) {
2210 if( !fci_flush_folder(p_fci_internal, FALSE, pfnfcignc, pfnfcis) ) return FALSE;
2211 p_fci_internal->fNewPrevious=TRUE;
2213 } else {
2214 p_fci_internal->fNewPrevious=FALSE;
2215 if( p_fci_internal->sizeFileCFFILE1>0 || p_fci_internal->sizeFileCFDATA1) {
2216 /* THIS MAY NEVER HAPPEN */
2217 /* set error structures */
2218 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2219 return FALSE;
2223 return TRUE;
2224 } /* end of fci_flush_cabinet */
2230 /***********************************************************************
2231 * FCIAddFile (CABINET.11)
2233 * FCIAddFile adds a file to the to be created cabinet file
2235 * PARAMS
2236 * hfci [I] An HFCI from FCICreate
2237 * pszSourceFile [I] A pointer to a C string which contains the name and
2238 * location of the file which will be added to the cabinet
2239 * pszFileName [I] A pointer to a C string which contains the name under
2240 * which the file will be stored in the cabinet
2241 * fExecute [I] A boolean value which indicates if the file should be
2242 * executed after extraction of self extracting
2243 * executables
2244 * pfnfcignc [I] A pointer to a function which gets information about
2245 * the next cabinet
2246 * pfnfcis [IO] A pointer to a function which will report status
2247 * information about the compression process
2248 * pfnfcioi [I] A pointer to a function which reports file attributes
2249 * and time and date information
2250 * typeCompress [I] Compression type
2252 * RETURNS
2253 * On success, returns TRUE
2254 * On failure, returns FALSE
2256 * INCLUDES
2257 * fci.h
2260 BOOL __cdecl FCIAddFile(
2261 HFCI hfci,
2262 char *pszSourceFile,
2263 char *pszFileName,
2264 BOOL fExecute,
2265 PFNFCIGETNEXTCABINET pfnfcignc,
2266 PFNFCISTATUS pfnfcis,
2267 PFNFCIGETOPENINFO pfnfcigoi,
2268 TCOMP typeCompress)
2270 int err;
2271 CFFILE cffile;
2272 cab_ULONG read_result;
2273 int file_handle;
2274 FCI_Int *p_fci_internal = get_fci_ptr( hfci );
2276 if (!p_fci_internal) return FALSE;
2278 if ((!pszSourceFile) || (!pszFileName) || (!pfnfcignc) || (!pfnfcis) ||
2279 (!pfnfcigoi) || strlen(pszFileName)>=CB_MAX_FILENAME) {
2280 set_error( p_fci_internal, FCIERR_NONE, ERROR_BAD_ARGUMENTS );
2281 return FALSE;
2284 /* TODO check if pszSourceFile??? */
2286 if(p_fci_internal->fGetNextCabInVain && p_fci_internal->fNextCab) {
2287 /* internal error */
2288 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2289 return FALSE;
2292 if(p_fci_internal->fNextCab) {
2293 /* internal error */
2294 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2295 return FALSE;
2298 cffile.cbFile=0; /* size of the to be added file*/
2299 /* offset of the uncompressed file in the folder */
2300 cffile.uoffFolderStart=p_fci_internal->cDataBlocks*CAB_BLOCKMAX + p_fci_internal->cdata_in;
2301 /* number of folder in the cabinet or special 0=first */
2302 cffile.iFolder = p_fci_internal->cFolders;
2304 /* allocation of memory */
2305 if (p_fci_internal->data_in==NULL) {
2306 if (p_fci_internal->cdata_in!=0) {
2307 /* error handling */
2308 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2309 return FALSE;
2311 if (p_fci_internal->data_out!=NULL) {
2312 /* error handling */
2313 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2314 return FALSE;
2316 if(!(p_fci_internal->data_in = p_fci_internal->alloc(CB_MAX_CHUNK))) {
2317 set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
2318 return FALSE;
2320 if (p_fci_internal->data_out==NULL) {
2321 if(!(p_fci_internal->data_out = p_fci_internal->alloc( 2 * CB_MAX_CHUNK))){
2322 set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
2323 return FALSE;
2328 if (p_fci_internal->data_out==NULL) {
2329 p_fci_internal->free(p_fci_internal->data_in);
2330 /* error handling */
2331 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2332 return FALSE;
2335 /* get information about the file */
2336 /* set defaults in case callback doesn't set one or more fields */
2337 cffile.attribs=0;
2338 cffile.date=0;
2339 cffile.time=0;
2340 file_handle=(*pfnfcigoi)(pszSourceFile, &(cffile.date), &(cffile.time),
2341 &(cffile.attribs), &err, p_fci_internal->pv);
2342 /* check file_handle */
2343 if(file_handle==0){
2344 set_error( p_fci_internal, FCIERR_OPEN_SRC, ERROR_OPEN_FAILED );
2346 /* TODO error handling of err */
2348 if (fExecute) { cffile.attribs |= _A_EXEC; }
2350 /* REUSE the variable read_result */
2351 if (p_fci_internal->fGetNextCabInVain) {
2352 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2353 p_fci_internal->oldCCAB.cbReserveCFFolder;
2354 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2355 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2356 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2357 read_result+=4;
2359 } else {
2360 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2361 p_fci_internal->pccab->cbReserveCFFolder;
2362 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2363 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2364 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2365 read_result+=4;
2368 if ( p_fci_internal->fPrevCab ) {
2369 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2370 strlen(p_fci_internal->szPrevDisk)+1;
2372 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2373 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2374 strlen(p_fci_internal->pccab->szDisk)+1;
2377 read_result+= sizeof(CFFILE) + strlen(pszFileName)+1 +
2378 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2379 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
2380 sizeof(CFHEADER) +
2381 sizeof(CFFOLDER); /* size of new CFFolder entry */
2383 /* Might be too much data for the maximum size of a cabinet.*/
2384 /* When any further data will be added later, it might not */
2385 /* be possible to flush the cabinet, because there might */
2386 /* not be enough space to store the name of the following */
2387 /* cabinet and name of the corresponding disk. */
2388 /* So take care of this and get the name of the next cabinet */
2389 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2390 p_fci_internal->fNextCab==FALSE &&
2391 ( p_fci_internal->pccab->cb < read_result +
2392 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2395 /* save CCAB */
2396 p_fci_internal->oldCCAB = *p_fci_internal->pccab;
2397 /* increment cabinet index */
2398 ++(p_fci_internal->pccab->iCab);
2399 /* get name of next cabinet */
2400 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2401 if (!(*pfnfcignc)(p_fci_internal->pccab,
2402 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2403 p_fci_internal->pv)) {
2404 /* error handling */
2405 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
2406 return FALSE;
2408 /* Skip a few lines of code. This is caught by the next if. */
2409 p_fci_internal->fGetNextCabInVain=TRUE;
2412 if( p_fci_internal->fGetNextCabInVain &&
2413 p_fci_internal->fNextCab
2415 /* THIS CAN NEVER HAPPEN */
2416 /* set error code */
2417 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2418 return FALSE;
2421 /* too much data for cabinet */
2422 if( p_fci_internal->fGetNextCabInVain &&
2424 p_fci_internal->oldCCAB.cb < read_result +
2425 strlen(p_fci_internal->pccab->szCab)+1+
2426 strlen(p_fci_internal->pccab->szDisk)+1
2427 )) {
2428 p_fci_internal->fGetNextCabInVain=FALSE;
2429 p_fci_internal->fNextCab=TRUE;
2430 if(!fci_flush_cabinet( p_fci_internal, FALSE, pfnfcignc, pfnfcis)) return FALSE;
2433 if( p_fci_internal->fNextCab ) {
2434 /* THIS MAY NEVER HAPPEN */
2435 /* set error code */
2436 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2437 return FALSE;
2440 /* read the contents of the file blockwise */
2441 while (!FALSE) {
2442 if (p_fci_internal->cdata_in > CAB_BLOCKMAX) {
2443 /* internal error */
2444 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2445 return FALSE;
2448 read_result = p_fci_internal->read( file_handle /* file handle */,
2449 (p_fci_internal->data_in + p_fci_internal->cdata_in) /* memory buffer */,
2450 (CAB_BLOCKMAX - p_fci_internal->cdata_in) /* number of bytes to copy */,
2451 &err, p_fci_internal->pv);
2452 /* TODO error handling of err */
2454 if( read_result==0 ) break;
2456 /* increment the block size */
2457 p_fci_internal->cdata_in += read_result;
2459 /* increment the file size */
2460 cffile.cbFile += read_result;
2462 if ( p_fci_internal->cdata_in > CAB_BLOCKMAX ) {
2463 /* report internal error */
2464 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2465 return FALSE;
2467 /* write a whole block */
2468 if ( p_fci_internal->cdata_in == CAB_BLOCKMAX ) {
2470 if( !fci_flush_data_block(p_fci_internal, &err, pfnfcis) ) return FALSE;
2474 /* close the file from FCIAddFile */
2475 p_fci_internal->close(file_handle,&err,p_fci_internal->pv);
2476 /* TODO error handling of err */
2478 /* write cffile to p_fci_internal->handleCFFILE1 */
2479 if( p_fci_internal->write( p_fci_internal->handleCFFILE1, /* file handle */
2480 &cffile, sizeof(cffile),&err, p_fci_internal->pv) != sizeof(cffile) ) {
2481 /* write error */
2482 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
2483 return FALSE;
2485 /* TODO error handling of err */
2487 p_fci_internal->sizeFileCFFILE1 += sizeof(cffile);
2489 /* append the name of file */
2490 if (strlen(pszFileName)>=CB_MAX_FILENAME) {
2491 /* IMPOSSIBLE */
2492 /* set error code */
2493 set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
2494 return FALSE;
2496 if( p_fci_internal->write( p_fci_internal->handleCFFILE1, /* file handle */
2497 pszFileName, strlen(pszFileName)+1, &err, p_fci_internal->pv)
2498 != strlen(pszFileName)+1 ) {
2499 /* write error */
2500 set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
2501 return FALSE;
2503 /* TODO error handling of err */
2505 p_fci_internal->sizeFileCFFILE1 += strlen(pszFileName)+1;
2507 /* REUSE the variable read_result */
2508 if (p_fci_internal->fGetNextCabInVain ||
2509 p_fci_internal->fNextCab
2511 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2512 p_fci_internal->oldCCAB.cbReserveCFFolder;
2513 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2514 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2515 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2516 read_result+=4;
2518 } else {
2519 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2520 p_fci_internal->pccab->cbReserveCFFolder;
2521 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2522 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2523 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2524 read_result+=4;
2527 if ( p_fci_internal->fPrevCab ) {
2528 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2529 strlen(p_fci_internal->szPrevDisk)+1;
2531 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2532 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2533 strlen(p_fci_internal->pccab->szDisk)+1;
2535 read_result+= p_fci_internal->sizeFileCFDATA1 +
2536 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2537 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
2538 sizeof(CFHEADER) +
2539 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2541 /* too much data for the maximum size of a cabinet */
2542 /* (ignoring the unflushed data block) */
2543 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2544 p_fci_internal->fNextCab==FALSE && /* this is always the case */
2545 p_fci_internal->pccab->cb < read_result ) {
2546 return fci_flush_cabinet( p_fci_internal, FALSE, pfnfcignc, pfnfcis);
2549 /* Might be too much data for the maximum size of a cabinet.*/
2550 /* When any further data will be added later, it might not */
2551 /* be possible to flush the cabinet, because there might */
2552 /* not be enough space to store the name of the following */
2553 /* cabinet and name of the corresponding disk. */
2554 /* So take care of this and get the name of the next cabinet */
2555 /* (ignoring the unflushed data block) */
2556 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2557 p_fci_internal->fNextCab==FALSE &&
2558 ( p_fci_internal->pccab->cb < read_result +
2559 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2562 /* save CCAB */
2563 p_fci_internal->oldCCAB = *p_fci_internal->pccab;
2564 /* increment cabinet index */
2565 ++(p_fci_internal->pccab->iCab);
2566 /* get name of next cabinet */
2567 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2568 if (!(*pfnfcignc)(p_fci_internal->pccab,
2569 p_fci_internal->estimatedCabinetSize,/* estimated size of cab */
2570 p_fci_internal->pv)) {
2571 /* error handling */
2572 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
2573 return FALSE;
2575 /* Skip a few lines of code. This is caught by the next if. */
2576 p_fci_internal->fGetNextCabInVain=TRUE;
2579 if( p_fci_internal->fGetNextCabInVain &&
2580 p_fci_internal->fNextCab
2582 /* THIS CAN NEVER HAPPEN */
2583 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2584 return FALSE;
2587 /* too much data for cabinet */
2588 if( (p_fci_internal->fGetNextCabInVain ||
2589 p_fci_internal->fNextCab) && (
2590 p_fci_internal->oldCCAB.cb < read_result +
2591 strlen(p_fci_internal->pccab->szCab)+1+
2592 strlen(p_fci_internal->pccab->szDisk)+1
2593 )) {
2595 p_fci_internal->fGetNextCabInVain=FALSE;
2596 p_fci_internal->fNextCab=TRUE;
2597 return fci_flush_cabinet( p_fci_internal, FALSE, pfnfcignc, pfnfcis);
2600 if( p_fci_internal->fNextCab ) {
2601 /* THIS MAY NEVER HAPPEN */
2602 /* set error code */
2603 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
2604 return FALSE;
2607 /* if the FolderThreshold has been reached flush the folder automatically */
2608 if( p_fci_internal->fGetNextCabInVain ) {
2609 if( p_fci_internal->cCompressedBytesInFolder >=
2610 p_fci_internal->oldCCAB.cbFolderThresh) {
2611 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2613 } else {
2614 if( p_fci_internal->cCompressedBytesInFolder >=
2615 p_fci_internal->pccab->cbFolderThresh) {
2616 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2620 return TRUE;
2621 } /* end of FCIAddFile */
2627 /***********************************************************************
2628 * FCIFlushFolder (CABINET.12)
2630 * FCIFlushFolder completes the CFFolder structure under construction.
2632 * All further data which is added by FCIAddFile will be associated to
2633 * the next CFFolder structure.
2635 * FCIFlushFolder will be called by FCIAddFile automatically if the
2636 * threshold (stored in the member cbFolderThresh of the CCAB structure
2637 * pccab passed to FCICreate) is exceeded.
2639 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2640 * any data will be written into the cabinet file.
2642 * PARAMS
2643 * hfci [I] An HFCI from FCICreate
2644 * pfnfcignc [I] A pointer to a function which gets information about
2645 * the next cabinet
2646 * pfnfcis [IO] A pointer to a function which will report status
2647 * information about the compression process
2649 * RETURNS
2650 * On success, returns TRUE
2651 * On failure, returns FALSE
2653 * INCLUDES
2654 * fci.h
2657 BOOL __cdecl FCIFlushFolder(
2658 HFCI hfci,
2659 PFNFCIGETNEXTCABINET pfnfcignc,
2660 PFNFCISTATUS pfnfcis)
2662 FCI_Int *p_fci_internal = get_fci_ptr( hfci );
2664 if (!p_fci_internal) return FALSE;
2665 return fci_flush_folder(p_fci_internal,FALSE,pfnfcignc,pfnfcis);
2670 /***********************************************************************
2671 * FCIFlushCabinet (CABINET.13)
2673 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2674 * into the cabinet file. If the maximum cabinet size (stored in the
2675 * member cb of the CCAB structure pccab passed to FCICreate) has been
2676 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2677 * The remaining data still has to be flushed manually by calling
2678 * FCIFlushCabinet.
2680 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2681 * NOT be called again. Then hfci has to be released by FCIDestroy.
2683 * PARAMS
2684 * hfci [I] An HFCI from FCICreate
2685 * fGetNextCab [I] Whether you want to add additional files to a
2686 * cabinet set (TRUE) or whether you want to
2687 * finalize it (FALSE)
2688 * pfnfcignc [I] A pointer to a function which gets information about
2689 * the next cabinet
2690 * pfnfcis [IO] A pointer to a function which will report status
2691 * information about the compression process
2693 * RETURNS
2694 * On success, returns TRUE
2695 * On failure, returns FALSE
2697 * INCLUDES
2698 * fci.h
2701 BOOL __cdecl FCIFlushCabinet(
2702 HFCI hfci,
2703 BOOL fGetNextCab,
2704 PFNFCIGETNEXTCABINET pfnfcignc,
2705 PFNFCISTATUS pfnfcis)
2707 FCI_Int *p_fci_internal = get_fci_ptr( hfci );
2709 if (!p_fci_internal) return FALSE;
2711 if(!fci_flush_cabinet(p_fci_internal,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2713 while( p_fci_internal->sizeFileCFFILE1>0 ||
2714 p_fci_internal->sizeFileCFFILE2>0 ) {
2715 if(!fci_flush_cabinet(p_fci_internal,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2718 return TRUE;
2722 /***********************************************************************
2723 * FCIDestroy (CABINET.14)
2725 * Frees a handle created by FCICreate.
2726 * Only reason for failure would be an invalid handle.
2728 * PARAMS
2729 * hfci [I] The HFCI to free
2731 * RETURNS
2732 * TRUE for success
2733 * FALSE for failure
2735 BOOL __cdecl FCIDestroy(HFCI hfci)
2737 int err;
2738 struct folder *folder, *folder_next;
2739 FCI_Int *p_fci_internal = get_fci_ptr( hfci );
2741 if (!p_fci_internal) return FALSE;
2743 /* before hfci can be removed all temporary files must be closed */
2744 /* and deleted */
2745 p_fci_internal->magic = 0;
2747 LIST_FOR_EACH_ENTRY_SAFE( folder, folder_next, &p_fci_internal->folders_list, struct folder, entry )
2749 list_remove( &folder->entry );
2750 p_fci_internal->free( folder );
2753 p_fci_internal->close( p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
2754 /* TODO error handling of err */
2755 p_fci_internal->delete( p_fci_internal->szFileNameCFDATA1, &err,
2756 p_fci_internal->pv);
2757 /* TODO error handling of err */
2758 p_fci_internal->close( p_fci_internal->handleCFFILE1,&err,p_fci_internal->pv);
2759 /* TODO error handling of err */
2760 p_fci_internal->delete( p_fci_internal->szFileNameCFFILE1, &err,
2761 p_fci_internal->pv);
2762 /* TODO error handling of err */
2763 p_fci_internal->close( p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2764 /* TODO error handling of err */
2765 p_fci_internal->delete( p_fci_internal->szFileNameCFDATA2, &err,
2766 p_fci_internal->pv);
2767 /* TODO error handling of err */
2768 p_fci_internal->close( p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2769 /* TODO error handling of err */
2770 p_fci_internal->delete( p_fci_internal->szFileNameCFFILE2, &err,
2771 p_fci_internal->pv);
2772 /* TODO error handling of err */
2774 /* data in and out buffers have to be removed */
2775 if (p_fci_internal->data_in!=NULL)
2776 p_fci_internal->free(p_fci_internal->data_in);
2777 if (p_fci_internal->data_out!=NULL)
2778 p_fci_internal->free(p_fci_internal->data_out);
2780 /* hfci can now be removed */
2781 p_fci_internal->free(hfci);
2782 return TRUE;