ReactOS 0.4.15-dev-7788-g1ad9096
fci.c
Go to the documentation of this file.
1/*
2 * File Compression Interface
3 *
4 * Copyright 2002 Patrik Stridvall
5 * Copyright 2005 Gerold Jens Wucherpfennig
6 * Copyright 2011 Alexandre Julliard
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23/*
24
25There is still some work to be done:
26
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
31*/
32
33
34
35#include "config.h"
36
37#include <assert.h>
38#include <stdarg.h>
39#include <stdio.h>
40#include <string.h>
41#ifdef HAVE_ZLIB
42# include <zlib.h>
43#endif
44
45#include "windef.h"
46#include "winbase.h"
47#include "winerror.h"
48#include "wine/winternl.h"
49#include "fci.h"
50#include "cabinet.h"
51#include "wine/list.h"
52#include "wine/debug.h"
53
55
56#ifdef WORDS_BIGENDIAN
57#define fci_endian_ulong(x) RtlUlongByteSwap(x)
58#define fci_endian_uword(x) RtlUshortByteSwap(x)
59#else
60#define fci_endian_ulong(x) (x)
61#define fci_endian_uword(x) (x)
62#endif
63
64
65typedef struct {
66 cab_UBYTE signature[4]; /* !CAB for unfinished cabinets else MSCF */
68 cab_ULONG cbCabinet; /* size of the cabinet file in bytes*/
70 cab_ULONG coffFiles; /* offset to first CFFILE section */
74 cab_UWORD cFolders; /* number of CFFOLDER entries in the cabinet*/
75 cab_UWORD cFiles; /* number of CFFILE entries in the cabinet*/
76 cab_UWORD flags; /* 1=prev cab, 2=next cabinet, 4=reserved sections*/
77 cab_UWORD setID; /* identification number of all cabinets in a set*/
78 cab_UWORD iCabinet; /* number of the cabinet in a set */
79 /* additional area if "flags" were set*/
80} CFHEADER; /* minimum 36 bytes */
81
82typedef struct {
83 cab_ULONG coffCabStart; /* offset to the folder's first CFDATA section */
84 cab_UWORD cCFData; /* number of this folder's CFDATA sections */
85 cab_UWORD typeCompress; /* compression type of data in CFDATA section*/
86 /* additional area if reserve flag was set */
87} CFFOLDER; /* minimum 8 bytes */
88
89typedef struct {
90 cab_ULONG cbFile; /* size of the uncompressed file in bytes */
91 cab_ULONG uoffFolderStart; /* offset of the uncompressed file in the folder */
92 cab_UWORD iFolder; /* number of folder in the cabinet 0=first */
93 /* for special values see below this structure*/
94 cab_UWORD date; /* last modification date*/
95 cab_UWORD time; /* last modification time*/
96 cab_UWORD attribs; /* DOS fat attributes and UTF indicator */
97 /* ... and a C string with the name of the file */
98} CFFILE; /* 16 bytes + name of file */
99
100
101typedef struct {
102 cab_ULONG csum; /* checksum of this entry*/
103 cab_UWORD cbData; /* number of compressed bytes */
104 cab_UWORD cbUncomp; /* number of bytes when data is uncompressed */
105 /* optional reserved area */
106 /* compressed data */
107} CFDATA;
108
110{
113};
114
115struct folder
116{
117 struct list entry;
124};
125
126struct file
127{
128 struct list entry;
129 cab_ULONG size; /* uncompressed size */
130 cab_ULONG offset; /* offset in folder */
131 cab_UWORD folder; /* index of folder */
135 char name[1];
136};
137
139{
140 struct list entry;
143};
144
145typedef struct FCI_Int
146{
147 unsigned int magic;
150 PFNFCIALLOC alloc;
167 void *pv;
168 char szPrevCab[CB_MAX_CABINET_NAME]; /* previous cabinet name */
169 char szPrevDisk[CB_MAX_DISK_NAME]; /* disk name of previous cabinet */
170 unsigned char data_in[CAB_BLOCKMAX]; /* uncompressed data blocks */
171 unsigned char data_out[2 * CAB_BLOCKMAX]; /* compressed data blocks */
177 cab_ULONG cbFileRemainder; /* uncompressed, yet to be written data */
178 /* of spanned file of a spanning folder of a spanning cabinet */
186 cab_ULONG files_size; /* size of files not yet assigned to a folder */
187 cab_ULONG placed_files_size; /* size of files already placed into a folder */
188 cab_ULONG pending_data_size; /* size of data not yet assigned to a folder */
189 cab_ULONG folders_data_size; /* total size of data contained in the current folders */
193
194#define FCI_INT_MAGIC 0xfcfcfc05
195
196static void set_error( FCI_Int *fci, int oper, int err )
197{
198 fci->perf->erfOper = oper;
199 fci->perf->erfType = err;
200 fci->perf->fError = TRUE;
201 if (err) SetLastError( err );
202}
203
204static FCI_Int *get_fci_ptr( HFCI hfci )
205{
206 FCI_Int *fci= (FCI_Int *)hfci;
207
208 if (!fci || fci->magic != FCI_INT_MAGIC)
209 {
211 return NULL;
212 }
213 return fci;
214}
215
216/* compute the cabinet header size */
218{
220
222 ret += 4;
223
224 if (fci->fPrevCab)
225 ret += strlen( fci->szPrevCab ) + 1 + strlen( fci->szPrevDisk ) + 1;
226
227 if (fci->fNextCab)
228 ret += strlen( fci->pccab->szCab ) + 1 + strlen( fci->pccab->szDisk ) + 1;
229
230 return ret;
231}
232
234{
235 int err;
236
237 if (!fci->gettemp( file->name, CB_MAX_FILENAME, fci->pv ))
238 {
240 return FALSE;
241 }
242 if ((file->handle = fci->open( file->name, _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
243 _S_IREAD | _S_IWRITE, &err, fci->pv )) == -1)
244 {
246 return FALSE;
247 }
248 return TRUE;
249}
250
252{
253 int err;
254
255 if (file->handle == -1) return TRUE;
256 if (fci->close( file->handle, &err, fci->pv ) == -1)
257 {
259 return FALSE;
260 }
261 file->handle = -1;
262 if (fci->delete( file->name, &err, fci->pv ) == -1)
263 {
265 return FALSE;
266 }
267 return TRUE;
268}
269
270static struct file *add_file( FCI_Int *fci, const char *filename )
271{
272 unsigned int size = FIELD_OFFSET( struct file, name[strlen(filename) + 1] );
273 struct file *file = fci->alloc( size );
274
275 if (!file)
276 {
278 return NULL;
279 }
280 file->size = 0;
282 file->folder = fci->cFolders;
283 file->date = 0;
284 file->time = 0;
285 file->attribs = 0;
288 fci->files_size += sizeof(CFFILE) + strlen(filename) + 1;
289 return file;
290}
291
292static struct file *copy_file( FCI_Int *fci, const struct file *orig )
293{
294 unsigned int size = FIELD_OFFSET( struct file, name[strlen(orig->name) + 1] );
295 struct file *file = fci->alloc( size );
296
297 if (!file)
298 {
300 return NULL;
301 }
302 memcpy( file, orig, size );
303 return file;
304}
305
306static void free_file( FCI_Int *fci, struct file *file )
307{
309 fci->free( file );
310}
311
312/* create a new data block for the data in fci->data_in */
314{
315 int err;
316 struct data_block *block;
317
318 if (!fci->cdata_in) return TRUE;
319
320 if (fci->data.handle == -1 && !create_temp_file( fci, &fci->data )) return FALSE;
321
322 if (!(block = fci->alloc( sizeof(*block) )))
323 {
325 return FALSE;
326 }
327 block->uncompressed = fci->cdata_in;
328 block->compressed = fci->compress( fci );
329
330 if (fci->write( fci->data.handle, fci->data_out,
331 block->compressed, &err, fci->pv ) != block->compressed)
332 {
334 fci->free( block );
335 return FALSE;
336 }
337
338 fci->cdata_in = 0;
339 fci->pending_data_size += sizeof(CFDATA) + fci->ccab.cbReserveCFData + block->compressed;
340 fci->cCompressedBytesInFolder += block->compressed;
341 fci->cDataBlocks++;
342 list_add_tail( &fci->blocks_list, &block->entry );
343
344 if (status_callback( statusFile, block->compressed, block->uncompressed, fci->pv ) == -1)
345 {
346 set_error( fci, FCIERR_USER_ABORT, 0 );
347 return FALSE;
348 }
349 return TRUE;
350}
351
352/* add compressed blocks for all the data that can be read from the file */
353static BOOL add_file_data( FCI_Int *fci, char *sourcefile, char *filename, BOOL execute,
355{
356 int err, len;
358 struct file *file;
359
360 if (!(file = add_file( fci, filename ))) return FALSE;
361
362 handle = get_open_info( sourcefile, &file->date, &file->time, &file->attribs, &err, fci->pv );
363 if (handle == -1)
364 {
365 free_file( fci, file );
367 return FALSE;
368 }
369 if (execute) file->attribs |= _A_EXEC;
370
371 for (;;)
372 {
373 len = fci->read( handle, fci->data_in + fci->cdata_in,
374 CAB_BLOCKMAX - fci->cdata_in, &err, fci->pv );
375 if (!len) break;
376
377 if (len == -1)
378 {
380 return FALSE;
381 }
382 file->size += len;
383 fci->cdata_in += len;
384 if (fci->cdata_in == CAB_BLOCKMAX && !add_data_block( fci, status_callback )) return FALSE;
385 }
386 fci->close( handle, &err, fci->pv );
387 return TRUE;
388}
389
390static void free_data_block( FCI_Int *fci, struct data_block *block )
391{
392 list_remove( &block->entry );
393 fci->free( block );
394}
395
396static struct folder *add_folder( FCI_Int *fci )
397{
398 struct folder *folder = fci->alloc( sizeof(*folder) );
399
400 if (!folder)
401 {
403 return NULL;
404 }
405 folder->data.handle = -1;
407 folder->data_count = 0;
412 fci->folders_size += sizeof(CFFOLDER) + fci->ccab.cbReserveCFFolder;
413 fci->cFolders++;
414 return folder;
415}
416
417static void free_folder( FCI_Int *fci, struct folder *folder )
418{
419 struct file *file, *file_next;
420 struct data_block *block, *block_next;
421
422 LIST_FOR_EACH_ENTRY_SAFE( file, file_next, &folder->files_list, struct file, entry )
423 free_file( fci, file );
425 free_data_block( fci, block );
426 close_temp_file( fci, &folder->data );
428 fci->free( folder );
429}
430
431/* reset state for the next cabinet file once the current one has been flushed */
432static void reset_cabinet( FCI_Int *fci )
433{
434 struct folder *folder, *folder_next;
435
436 LIST_FOR_EACH_ENTRY_SAFE( folder, folder_next, &fci->folders_list, struct folder, entry )
437 free_folder( fci, folder );
438
439 fci->cFolders = 0;
440 fci->cFiles = 0;
441 fci->folders_size = 0;
442 fci->placed_files_size = 0;
443 fci->folders_data_size = 0;
444}
445
446static cab_ULONG fci_get_checksum( const void *pv, UINT cb, cab_ULONG seed )
447{
449 cab_ULONG ul;
450 int cUlong;
451 const BYTE *pb;
452
453 csum = seed;
454 cUlong = cb / 4;
455 pb = pv;
456
457 while (cUlong-- > 0) {
458 ul = *pb++;
459 ul |= (((cab_ULONG)(*pb++)) << 8);
460 ul |= (((cab_ULONG)(*pb++)) << 16);
461 ul |= (((cab_ULONG)(*pb++)) << 24);
462 csum ^= ul;
463 }
464
465 ul = 0;
466 switch (cb % 4) {
467 case 3:
468 ul |= (((ULONG)(*pb++)) << 16);
469 /* fall through */
470 case 2:
471 ul |= (((ULONG)(*pb++)) << 8);
472 /* fall through */
473 case 1:
474 ul |= *pb;
475 /* fall through */
476 default:
477 break;
478 }
479 csum ^= ul;
480
481 return csum;
482}
483
484/* copy all remaining data block to a new temp file */
487{
488 struct data_block *block;
489 int err;
490
491 if (fci->seek( handle, start_pos, SEEK_SET, &err, fci->pv ) != start_pos)
492 {
494 return FALSE;
495 }
496 if (!create_temp_file( fci, temp )) return FALSE;
497
499 {
500 if (fci->read( handle, fci->data_out, block->compressed,
501 &err, fci->pv ) != block->compressed)
502 {
503 close_temp_file( fci, temp );
505 return FALSE;
506 }
507 if (fci->write( temp->handle, fci->data_out, block->compressed,
508 &err, fci->pv ) != block->compressed)
509 {
510 close_temp_file( fci, temp );
512 return FALSE;
513 }
514 fci->pending_data_size += sizeof(CFDATA) + fci->ccab.cbReserveCFData + block->compressed;
515 fci->statusFolderCopied += block->compressed;
516
518 fci->statusFolderTotal, fci->pv) == -1)
519 {
520 close_temp_file( fci, temp );
521 set_error( fci, FCIERR_USER_ABORT, 0 );
522 return FALSE;
523 }
524 }
525 return TRUE;
526}
527
528/* write all folders to disk and remove them from the list */
530{
531 struct folder *folder;
532 int err;
533 CFFOLDER *cffolder = (CFFOLDER *)fci->data_out;
534 cab_ULONG folder_size = sizeof(CFFOLDER) + fci->ccab.cbReserveCFFolder;
535
536 memset( cffolder, 0, folder_size );
537
538 /* write the folders */
540 {
541 cffolder->coffCabStart = fci_endian_ulong( folder->data_start + header_size );
544 if (fci->write( handle, cffolder, folder_size, &err, fci->pv ) != folder_size)
545 {
547 return FALSE;
548 }
549 }
550 return TRUE;
551}
552
553/* write all the files to the cabinet file */
555{
557 struct folder *folder;
558 struct file *file;
559 int err;
560 CFFILE *cffile = (CFFILE *)fci->data_out;
561
563 {
565 {
566 cffile->cbFile = fci_endian_ulong( file->size );
568 cffile->iFolder = fci_endian_uword( file->folder );
569 cffile->date = fci_endian_uword( file->date );
570 cffile->time = fci_endian_uword( file->time );
571 cffile->attribs = fci_endian_uword( file->attribs );
572 lstrcpynA( (char *)(cffile + 1), file->name, CB_MAX_FILENAME );
573 file_size = sizeof(CFFILE) + strlen( (char *)(cffile + 1) ) + 1;
574 if (fci->write( handle, cffile, file_size, &err, fci->pv ) != file_size)
575 {
577 return FALSE;
578 }
579 if (!fci->fSplitFolder)
580 {
581 fci->statusFolderCopied = 0;
582 /* TODO TEST THIS further */
584 }
586 /* report status about copied size of folder */
588 fci->statusFolderTotal, fci->pv ) == -1)
589 {
590 set_error( fci, FCIERR_USER_ABORT, 0 );
591 return FALSE;
592 }
593 }
594 }
595 return TRUE;
596}
597
598/* write all data blocks to the cabinet file */
600{
601 struct folder *folder;
602 struct data_block *block;
603 int err, len;
604 CFDATA *cfdata;
605 void *data;
606 cab_UWORD header_size;
607
608 header_size = sizeof(CFDATA) + fci->ccab.cbReserveCFData;
609 cfdata = (CFDATA *)fci->data_out;
610 memset( cfdata, 0, header_size );
611 data = (char *)cfdata + header_size;
612
614 {
615 if (fci->seek( folder->data.handle, 0, SEEK_SET, &err, fci->pv ) != 0)
616 {
618 return FALSE;
619 }
621 {
622 len = fci->read( folder->data.handle, data, block->compressed, &err, fci->pv );
623 if (len != block->compressed) return FALSE;
624
625 cfdata->cbData = fci_endian_uword( block->compressed );
626 cfdata->cbUncomp = fci_endian_uword( block->uncompressed );
627 cfdata->csum = fci_endian_ulong( fci_get_checksum( &cfdata->cbData,
628 header_size - FIELD_OFFSET(CFDATA, cbData),
629 fci_get_checksum( data, len, 0 )));
630
631 fci->statusFolderCopied += len;
632 len += header_size;
633 if (fci->write( handle, fci->data_out, len, &err, fci->pv ) != len)
634 {
636 return FALSE;
637 }
639 {
640 set_error( fci, FCIERR_USER_ABORT, 0 );
641 return FALSE;
642 }
643 }
644 }
645 return TRUE;
646}
647
648/* write the cabinet file to disk */
650{
652 int err;
653 char *ptr;
655 CFHEADER *cfheader = (CFHEADER *)fci->data_out;
656 cab_UWORD flags = 0;
657 cab_ULONG header_size = get_header_size( fci );
658 cab_ULONG total_size = header_size + fci->folders_size +
660
661 assert( header_size <= sizeof(fci->data_out) );
662 memset( cfheader, 0, header_size );
663
664 if (fci->fPrevCab) flags |= cfheadPREV_CABINET;
665 if (fci->fNextCab) flags |= cfheadNEXT_CABINET;
668
669 memcpy( cfheader->signature, "!CAB", 4 );
670 cfheader->cbCabinet = fci_endian_ulong( total_size );
671 cfheader->coffFiles = fci_endian_ulong( header_size + fci->folders_size );
672 cfheader->versionMinor = 3;
673 cfheader->versionMajor = 1;
674 cfheader->cFolders = fci_endian_uword( fci->cFolders );
675 cfheader->cFiles = fci_endian_uword( fci->cFiles );
676 cfheader->flags = fci_endian_uword( flags );
677 cfheader->setID = fci_endian_uword( fci->ccab.setID );
678 cfheader->iCabinet = fci_endian_uword( fci->ccab.iCab );
679 ptr = (char *)(cfheader + 1);
680
682 {
683 struct
684 {
685 cab_UWORD cbCFHeader;
686 cab_UBYTE cbCFFolder;
687 cab_UBYTE cbCFData;
688 } *reserve = (void *)ptr;
689
690 reserve->cbCFHeader = fci_endian_uword( fci->ccab.cbReserveCFHeader );
691 reserve->cbCFFolder = fci->ccab.cbReserveCFFolder;
692 reserve->cbCFData = fci->ccab.cbReserveCFData;
693 ptr = (char *)(reserve + 1);
694 }
695 ptr += fci->ccab.cbReserveCFHeader;
696
698 {
699 strcpy( ptr, fci->szPrevCab );
700 ptr += strlen( ptr ) + 1;
701 strcpy( ptr, fci->szPrevDisk );
702 ptr += strlen( ptr ) + 1;
703 }
704
706 {
707 strcpy( ptr, fci->pccab->szCab );
708 ptr += strlen( ptr ) + 1;
709 strcpy( ptr, fci->pccab->szDisk );
710 ptr += strlen( ptr ) + 1;
711 }
712
713 assert( ptr - (char *)cfheader == header_size );
714
715 strcpy( filename, fci->ccab.szCabPath );
716 strcat( filename, fci->ccab.szCab );
717
719 _S_IREAD | _S_IWRITE, &err, fci->pv )) == -1)
720 {
722 return FALSE;
723 }
724
725 if (fci->write( handle, cfheader, header_size, &err, fci->pv ) != header_size)
726 {
728 goto failed;
729 }
730
731 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
732 header_size += fci->placed_files_size + fci->folders_size;
733 if (!write_folders( fci, handle, header_size, status_callback )) goto failed;
734 if (!write_files( fci, handle, status_callback )) goto failed;
735 if (!write_data_blocks( fci, handle, status_callback )) goto failed;
736
737 /* update the signature */
738 if (fci->seek( handle, 0, SEEK_SET, &err, fci->pv ) != 0 )
739 {
741 goto failed;
742 }
743 memcpy( cfheader->signature, "MSCF", 4 );
744 if (fci->write( handle, cfheader->signature, 4, &err, fci->pv ) != 4)
745 {
747 goto failed;
748 }
749 fci->close( handle, &err, fci->pv );
750
751 reset_cabinet( fci );
752 status_callback( statusCabinet, fci->estimatedCabinetSize, total_size, fci->pv );
753 return TRUE;
754
755failed:
756 fci->close( handle, &err, fci->pv );
757 fci->delete( filename, &err, fci->pv );
758 return FALSE;
759}
760
761/* add all pending data blocks folder */
762static BOOL add_data_to_folder( FCI_Int *fci, struct folder *folder, cab_ULONG *payload,
764{
765 struct data_block *block, *new, *next;
766 BOOL split_block = FALSE;
767 cab_ULONG current_size, start_pos = 0;
768
769 *payload = 0;
770 current_size = get_header_size( fci ) + fci->folders_size +
772
773 /* move the temp file into the folder structure */
774 folder->data = fci->data;
775 fci->data.handle = -1;
776 fci->pending_data_size = 0;
777
779 {
780 /* No more CFDATA fits into the cabinet under construction */
781 /* So don't try to store more data into it */
782 if (fci->fNextCab && (fci->ccab.cb <= sizeof(CFDATA) + fci->ccab.cbReserveCFData +
783 current_size + sizeof(CFFOLDER) + fci->ccab.cbReserveCFFolder))
784 break;
785
786 if (!(new = fci->alloc( sizeof(*new) )))
787 {
789 return FALSE;
790 }
791 /* Is cabinet with new CFDATA too large? Then data block has to be split */
792 if( fci->fNextCab &&
793 (fci->ccab.cb < sizeof(CFDATA) + fci->ccab.cbReserveCFData +
794 block->compressed + current_size + sizeof(CFFOLDER) + fci->ccab.cbReserveCFFolder))
795 {
796 /* Modify the size of the compressed data to store only a part of the */
797 /* data block into the current cabinet. This is done to prevent */
798 /* that the maximum cabinet size will be exceeded. The remainder */
799 /* will be stored into the next following cabinet. */
800
801 new->compressed = fci->ccab.cb - (sizeof(CFDATA) + fci->ccab.cbReserveCFData + current_size +
802 sizeof(CFFOLDER) + fci->ccab.cbReserveCFFolder );
803 new->uncompressed = 0; /* on split blocks of data this is zero */
804 block->compressed -= new->compressed;
805 split_block = TRUE;
806 }
807 else
808 {
809 new->compressed = block->compressed;
810 new->uncompressed = block->uncompressed;
811 }
812
813 start_pos += new->compressed;
814 current_size += sizeof(CFDATA) + fci->ccab.cbReserveCFData + new->compressed;
815 fci->folders_data_size += sizeof(CFDATA) + fci->ccab.cbReserveCFData + new->compressed;
816 fci->statusFolderCopied += new->compressed;
817 (*payload) += new->uncompressed;
818
819 list_add_tail( &folder->blocks_list, &new->entry );
821
822 /* report status with pfnfcis about copied size of folder */
824 fci->statusFolderTotal, fci->pv ) == -1)
825 {
826 set_error( fci, FCIERR_USER_ABORT, 0 );
827 return FALSE;
828 }
829 if (split_block) break;
830 free_data_block( fci, block );
831 fci->cDataBlocks--;
832 }
833
834 if (list_empty( &fci->blocks_list )) return TRUE;
835 return copy_data_blocks( fci, folder->data.handle, start_pos, &fci->data, status_callback );
836}
837
838/* add all pending files to folder */
839static BOOL add_files_to_folder( FCI_Int *fci, struct folder *folder, cab_ULONG payload )
840{
841 cab_ULONG sizeOfFiles = 0, sizeOfFilesPrev;
842 cab_ULONG cbFileRemainder = 0;
843 struct file *file, *next;
844
846 {
847 cab_ULONG size = sizeof(CFFILE) + strlen(file->name) + 1;
848
849 /* fnfilfnfildest: placed file on cabinet */
850 fci->fileplaced( &fci->ccab, file->name, file->size,
852
853 sizeOfFilesPrev = sizeOfFiles;
854 /* set complete size of all processed files */
856 {
857 sizeOfFiles += fci->cbFileRemainder;
858 fci->cbFileRemainder = 0;
859 }
860 else sizeOfFiles += file->size;
861
862 /* check if spanned file fits into this cabinet folder */
863 if (sizeOfFiles > payload)
864 {
867 else
869 }
870
873 fci->placed_files_size += size;
874 fci->cFiles++;
875
876 /* This is only true for files which will be written into the */
877 /* next cabinet of the spanning folder */
878 if (sizeOfFiles > payload)
879 {
880 /* add a copy back onto the list */
881 if (!(file = copy_file( fci, file ))) return FALSE;
882 list_add_before( &next->entry, &file->entry );
883
884 /* Files which data will be partially written into the current cabinet */
886 {
887 if (sizeOfFilesPrev <= payload)
888 {
889 /* The size of the uncompressed, data of a spanning file in a */
890 /* spanning data */
891 cbFileRemainder = sizeOfFiles - payload;
892 }
894 }
895 else file->folder = 0;
896 }
897 else
898 {
899 fci->files_size -= size;
900 }
901 }
902 fci->cbFileRemainder = cbFileRemainder;
903 return TRUE;
904}
905
907{
908 memcpy( fci->data_out, fci->data_in, fci->cdata_in );
909 return fci->cdata_in;
910}
911
912#ifdef HAVE_ZLIB
913
914static void *zalloc( void *opaque, unsigned int items, unsigned int size )
915{
916 FCI_Int *fci = opaque;
917 return fci->alloc( items * size );
918}
919
920static void zfree( void *opaque, void *ptr )
921{
922 FCI_Int *fci = opaque;
923 fci->free( ptr );
924}
925
926static cab_UWORD compress_MSZIP( FCI_Int *fci )
927{
929
930 stream.zalloc = zalloc;
931 stream.zfree = zfree;
932 stream.opaque = fci;
934 {
936 return 0;
937 }
938 stream.next_in = fci->data_in;
939 stream.avail_in = fci->cdata_in;
940 stream.next_out = fci->data_out + 2;
941 stream.avail_out = sizeof(fci->data_out) - 2;
942 /* insert the signature */
943 fci->data_out[0] = 'C';
944 fci->data_out[1] = 'K';
946 deflateEnd( &stream );
947 return stream.total_out + 2;
948}
949
950#endif /* HAVE_ZLIB */
951
952
953/***********************************************************************
954 * FCICreate (CABINET.10)
955 *
956 * FCICreate is provided with several callbacks and
957 * returns a handle which can be used to create cabinet files.
958 *
959 * PARAMS
960 * perf [IO] A pointer to an ERF structure. When FCICreate
961 * returns an error condition, error information may
962 * be found here as well as from GetLastError.
963 * pfnfiledest [I] A pointer to a function which is called when a file
964 * is placed. Only useful for subsequent cabinet files.
965 * pfnalloc [I] A pointer to a function which allocates ram. Uses
966 * the same interface as malloc.
967 * pfnfree [I] A pointer to a function which frees ram. Uses the
968 * same interface as free.
969 * pfnopen [I] A pointer to a function which opens a file. Uses
970 * the same interface as _open.
971 * pfnread [I] A pointer to a function which reads from a file into
972 * a caller-provided buffer. Uses the same interface
973 * as _read.
974 * pfnwrite [I] A pointer to a function which writes to a file from
975 * a caller-provided buffer. Uses the same interface
976 * as _write.
977 * pfnclose [I] A pointer to a function which closes a file handle.
978 * Uses the same interface as _close.
979 * pfnseek [I] A pointer to a function which seeks in a file.
980 * Uses the same interface as _lseek.
981 * pfndelete [I] A pointer to a function which deletes a file.
982 * pfnfcigtf [I] A pointer to a function which gets the name of a
983 * temporary file.
984 * pccab [I] A pointer to an initialized CCAB structure.
985 * pv [I] A pointer to an application-defined notification
986 * function which will be passed to other FCI functions
987 * as a parameter.
988 *
989 * RETURNS
990 * On success, returns an FCI handle of type HFCI.
991 * On failure, the NULL file handle is returned. Error
992 * info can be retrieved from perf.
993 *
994 * INCLUDES
995 * fci.h
996 *
997 */
999 PERF perf,
1000 PFNFCIFILEPLACED pfnfiledest,
1001 PFNFCIALLOC pfnalloc,
1002 PFNFCIFREE pfnfree,
1003 PFNFCIOPEN pfnopen,
1004 PFNFCIREAD pfnread,
1005 PFNFCIWRITE pfnwrite,
1006 PFNFCICLOSE pfnclose,
1007 PFNFCISEEK pfnseek,
1008 PFNFCIDELETE pfndelete,
1009 PFNFCIGETTEMPFILE pfnfcigtf,
1010 PCCAB pccab,
1011 void *pv)
1012{
1013 FCI_Int *p_fci_internal;
1014
1015 if (!perf) {
1017 return NULL;
1018 }
1019 if ((!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||
1020 (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||
1021 (!pfnfcigtf) || (!pccab)) {
1022 perf->erfOper = FCIERR_NONE;
1024 perf->fError = TRUE;
1025
1027 return NULL;
1028 }
1029
1030 if (!((p_fci_internal = pfnalloc(sizeof(FCI_Int))))) {
1031 perf->erfOper = FCIERR_ALLOC_FAIL;
1033 perf->fError = TRUE;
1034
1036 return NULL;
1037 }
1038
1039 memset(p_fci_internal, 0, sizeof(FCI_Int));
1040 p_fci_internal->magic = FCI_INT_MAGIC;
1041 p_fci_internal->perf = perf;
1042 p_fci_internal->fileplaced = pfnfiledest;
1043 p_fci_internal->alloc = pfnalloc;
1044 p_fci_internal->free = pfnfree;
1045 p_fci_internal->open = pfnopen;
1046 p_fci_internal->read = pfnread;
1047 p_fci_internal->write = pfnwrite;
1048 p_fci_internal->close = pfnclose;
1049 p_fci_internal->seek = pfnseek;
1050 p_fci_internal->delete = pfndelete;
1051 p_fci_internal->gettemp = pfnfcigtf;
1052 p_fci_internal->ccab = *pccab;
1053 p_fci_internal->pccab = pccab;
1054 p_fci_internal->pv = pv;
1055 p_fci_internal->data.handle = -1;
1056 p_fci_internal->compress = compress_NONE;
1057
1058 list_init( &p_fci_internal->folders_list );
1059 list_init( &p_fci_internal->files_list );
1060 list_init( &p_fci_internal->blocks_list );
1061
1062 memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
1063 memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);
1064
1065 return (HFCI)p_fci_internal;
1066}
1067
1068
1069
1070
1071static BOOL fci_flush_folder( FCI_Int *p_fci_internal,
1072 BOOL fGetNextCab,
1073 PFNFCIGETNEXTCABINET pfnfcignc,
1074 PFNFCISTATUS pfnfcis)
1075{
1076 cab_ULONG payload;
1077 cab_ULONG read_result;
1078 struct folder *folder;
1079
1080 if ((!pfnfcignc) || (!pfnfcis)) {
1081 set_error( p_fci_internal, FCIERR_NONE, ERROR_BAD_ARGUMENTS );
1082 return FALSE;
1083 }
1084
1085 if( p_fci_internal->fGetNextCabInVain &&
1086 p_fci_internal->fNextCab ){
1087 /* internal error */
1088 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1089 return FALSE;
1090 }
1091
1092 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1093 /* this function will return TRUE */
1094 if( p_fci_internal->files_size == 0 ) {
1095 if ( p_fci_internal->pending_data_size != 0 ) {
1096 /* error handling */
1097 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1098 return FALSE;
1099 }
1100 return TRUE;
1101 }
1102
1103 /* FCIFlushFolder has already been called... */
1104 if (p_fci_internal->fSplitFolder && p_fci_internal->placed_files_size!=0) {
1105 return TRUE;
1106 }
1107
1108 /* This can be set already, because it makes only a difference */
1109 /* when the current function exits with return FALSE */
1110 p_fci_internal->fSplitFolder=FALSE;
1111
1112 /* START of COPY */
1113 if (!add_data_block( p_fci_internal, pfnfcis )) return FALSE;
1114
1115 /* reset to get the number of data blocks of this folder which are */
1116 /* actually in this cabinet ( at least partially ) */
1117 p_fci_internal->cDataBlocks=0;
1118
1119 p_fci_internal->statusFolderTotal = get_header_size( p_fci_internal ) +
1120 sizeof(CFFOLDER) + p_fci_internal->ccab.cbReserveCFFolder +
1121 p_fci_internal->placed_files_size+
1122 p_fci_internal->folders_data_size + p_fci_internal->files_size+
1123 p_fci_internal->pending_data_size + p_fci_internal->folders_size;
1124 p_fci_internal->statusFolderCopied = 0;
1125
1126 /* report status with pfnfcis about copied size of folder */
1127 if( (*pfnfcis)(statusFolder, p_fci_internal->statusFolderCopied,
1128 p_fci_internal->statusFolderTotal, /* TODO total folder size */
1129 p_fci_internal->pv) == -1) {
1130 set_error( p_fci_internal, FCIERR_USER_ABORT, 0 );
1131 return FALSE;
1132 }
1133
1134 /* USE the variable read_result */
1135 read_result = get_header_size( p_fci_internal ) + p_fci_internal->folders_data_size +
1136 p_fci_internal->placed_files_size + p_fci_internal->folders_size;
1137
1138 if(p_fci_internal->files_size!=0) {
1139 read_result+= sizeof(CFFOLDER)+p_fci_internal->ccab.cbReserveCFFolder;
1140 }
1141
1142 /* Check if multiple cabinets have to be created. */
1143
1144 /* Might be too much data for the maximum allowed cabinet size.*/
1145 /* When any further data will be added later, it might not */
1146 /* be possible to flush the cabinet, because there might */
1147 /* not be enough space to store the name of the following */
1148 /* cabinet and name of the corresponding disk. */
1149 /* So take care of this and get the name of the next cabinet */
1150 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1151 p_fci_internal->fNextCab==FALSE &&
1152 (
1153 (
1154 p_fci_internal->ccab.cb < read_result +
1155 p_fci_internal->pending_data_size +
1156 p_fci_internal->files_size +
1157 CB_MAX_CABINET_NAME + /* next cabinet name */
1158 CB_MAX_DISK_NAME /* next disk name */
1159 ) || fGetNextCab
1160 )
1161 ) {
1162 /* increment cabinet index */
1163 ++(p_fci_internal->pccab->iCab);
1164 /* get name of next cabinet */
1165 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
1166 if (!(*pfnfcignc)(p_fci_internal->pccab,
1167 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
1168 p_fci_internal->pv)) {
1169 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
1170 return FALSE;
1171 }
1172
1173 /* Skip a few lines of code. This is caught by the next if. */
1174 p_fci_internal->fGetNextCabInVain=TRUE;
1175 }
1176
1177 /* too much data for cabinet */
1178 if( (p_fci_internal->fGetNextCabInVain ||
1179 p_fci_internal->fNextCab ) &&
1180 (
1181 (
1182 p_fci_internal->ccab.cb < read_result +
1183 p_fci_internal->pending_data_size +
1184 p_fci_internal->files_size +
1185 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1186 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1187 ) || fGetNextCab
1188 )
1189 ) {
1190 p_fci_internal->fGetNextCabInVain=FALSE;
1191 p_fci_internal->fNextCab=TRUE;
1192
1193 /* return FALSE if there is not enough space left*/
1194 /* this should never happen */
1195 if (p_fci_internal->ccab.cb <=
1196 p_fci_internal->files_size +
1197 read_result +
1198 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1199 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1200 ) {
1201
1202 return FALSE;
1203 }
1204
1205 /* the folder will be split across cabinets */
1206 p_fci_internal->fSplitFolder=TRUE;
1207
1208 } else {
1209 /* this should never happen */
1210 if (p_fci_internal->fNextCab) {
1211 /* internal error */
1212 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1213 return FALSE;
1214 }
1215 }
1216
1217 if (!(folder = add_folder( p_fci_internal ))) return FALSE;
1218 if (!add_data_to_folder( p_fci_internal, folder, &payload, pfnfcis )) return FALSE;
1219 if (!add_files_to_folder( p_fci_internal, folder, payload )) return FALSE;
1220
1221 /* reset CFFolder specific information */
1222 p_fci_internal->cDataBlocks=0;
1223 p_fci_internal->cCompressedBytesInFolder=0;
1224
1225 return TRUE;
1226}
1227
1228
1229
1230
1231static BOOL fci_flush_cabinet( FCI_Int *p_fci_internal,
1232 BOOL fGetNextCab,
1233 PFNFCIGETNEXTCABINET pfnfcignc,
1234 PFNFCISTATUS pfnfcis)
1235{
1236 cab_ULONG read_result=0;
1237 BOOL returntrue=FALSE;
1238
1239 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1240
1241 /* when FCIFlushCabinet was or FCIAddFile hasn't been called */
1242 if( p_fci_internal->files_size==0 && fGetNextCab ) {
1243 returntrue=TRUE;
1244 }
1245
1246 if (!fci_flush_folder(p_fci_internal,fGetNextCab,pfnfcignc,pfnfcis)){
1247 /* TODO set error */
1248 return FALSE;
1249 }
1250
1251 if(returntrue) return TRUE;
1252
1253 if ( (p_fci_internal->fSplitFolder && p_fci_internal->fNextCab==FALSE)||
1254 (p_fci_internal->folders_size==0 &&
1255 (p_fci_internal->files_size!=0 ||
1256 p_fci_internal->placed_files_size!=0 )
1257 ) )
1258 {
1259 /* error */
1260 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1261 return FALSE;
1262 }
1263
1264 /* create the cabinet */
1265 if (!write_cabinet( p_fci_internal, pfnfcis )) return FALSE;
1266
1267 p_fci_internal->fPrevCab=TRUE;
1268 /* The sections szPrevCab and szPrevDisk are not being updated, because */
1269 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
1270
1271 if (p_fci_internal->fNextCab) {
1272 p_fci_internal->fNextCab=FALSE;
1273
1274 if (p_fci_internal->files_size==0 && p_fci_internal->pending_data_size!=0) {
1275 /* THIS CAN NEVER HAPPEN */
1276 /* set error code */
1277 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1278 return FALSE;
1279 }
1280
1281 if( p_fci_internal->fNewPrevious ) {
1282 memcpy(p_fci_internal->szPrevCab, p_fci_internal->ccab.szCab,
1284 memcpy(p_fci_internal->szPrevDisk, p_fci_internal->ccab.szDisk,
1286 p_fci_internal->fNewPrevious=FALSE;
1287 }
1288 p_fci_internal->ccab = *p_fci_internal->pccab;
1289
1290 /* REUSE the variable read_result */
1291 read_result=get_header_size( p_fci_internal );
1292 if(p_fci_internal->files_size!=0) {
1293 read_result+=p_fci_internal->ccab.cbReserveCFFolder;
1294 }
1295 read_result+= p_fci_internal->pending_data_size +
1296 p_fci_internal->files_size + p_fci_internal->folders_data_size +
1297 p_fci_internal->placed_files_size + p_fci_internal->folders_size +
1298 sizeof(CFFOLDER); /* set size of new CFFolder entry */
1299
1300 /* too much data for the maximum size of a cabinet */
1301 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1302 p_fci_internal->ccab.cb < read_result ) {
1303 return fci_flush_cabinet( p_fci_internal, FALSE, pfnfcignc, pfnfcis);
1304 }
1305
1306 /* Might be too much data for the maximum size of a cabinet.*/
1307 /* When any further data will be added later, it might not */
1308 /* be possible to flush the cabinet, because there might */
1309 /* not be enough space to store the name of the following */
1310 /* cabinet and name of the corresponding disk. */
1311 /* So take care of this and get the name of the next cabinet */
1312 if (p_fci_internal->fGetNextCabInVain==FALSE && (
1313 p_fci_internal->ccab.cb < read_result +
1315 )) {
1316 /* increment cabinet index */
1317 ++(p_fci_internal->pccab->iCab);
1318 /* get name of next cabinet */
1319 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
1320 if (!(*pfnfcignc)(p_fci_internal->pccab,
1321 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
1322 p_fci_internal->pv)) {
1323 /* error handling */
1324 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
1325 return FALSE;
1326 }
1327 /* Skip a few lines of code. This is caught by the next if. */
1328 p_fci_internal->fGetNextCabInVain=TRUE;
1329 }
1330
1331 /* too much data for cabinet */
1332 if (p_fci_internal->fGetNextCabInVain && (
1333 p_fci_internal->ccab.cb < read_result +
1334 strlen(p_fci_internal->ccab.szCab)+1+
1335 strlen(p_fci_internal->ccab.szDisk)+1
1336 )) {
1337 p_fci_internal->fGetNextCabInVain=FALSE;
1338 p_fci_internal->fNextCab=TRUE;
1339 return fci_flush_cabinet( p_fci_internal, FALSE, pfnfcignc, pfnfcis);
1340 }
1341
1342 /* if the FolderThreshold has been reached flush the folder automatically */
1343 if (p_fci_internal->cCompressedBytesInFolder >= p_fci_internal->ccab.cbFolderThresh)
1344 return fci_flush_folder(p_fci_internal, FALSE, pfnfcignc, pfnfcis);
1345
1346 if( p_fci_internal->files_size>0 ) {
1347 if( !fci_flush_folder(p_fci_internal, FALSE, pfnfcignc, pfnfcis) ) return FALSE;
1348 p_fci_internal->fNewPrevious=TRUE;
1349 }
1350 } else {
1351 p_fci_internal->fNewPrevious=FALSE;
1352 if( p_fci_internal->files_size>0 || p_fci_internal->pending_data_size) {
1353 /* THIS MAY NEVER HAPPEN */
1354 /* set error structures */
1355 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1356 return FALSE;
1357 }
1358 }
1359
1360 return TRUE;
1361} /* end of fci_flush_cabinet */
1362
1363
1364
1365
1366
1367/***********************************************************************
1368 * FCIAddFile (CABINET.11)
1369 *
1370 * FCIAddFile adds a file to the to be created cabinet file
1371 *
1372 * PARAMS
1373 * hfci [I] An HFCI from FCICreate
1374 * pszSourceFile [I] A pointer to a C string which contains the name and
1375 * location of the file which will be added to the cabinet
1376 * pszFileName [I] A pointer to a C string which contains the name under
1377 * which the file will be stored in the cabinet
1378 * fExecute [I] A boolean value which indicates if the file should be
1379 * executed after extraction of self extracting
1380 * executables
1381 * pfnfcignc [I] A pointer to a function which gets information about
1382 * the next cabinet
1383 * pfnfcis [IO] A pointer to a function which will report status
1384 * information about the compression process
1385 * pfnfcioi [I] A pointer to a function which reports file attributes
1386 * and time and date information
1387 * typeCompress [I] Compression type
1388 *
1389 * RETURNS
1390 * On success, returns TRUE
1391 * On failure, returns FALSE
1392 *
1393 * INCLUDES
1394 * fci.h
1395 *
1396 */
1398 HFCI hfci,
1399 char *pszSourceFile,
1400 char *pszFileName,
1401 BOOL fExecute,
1402 PFNFCIGETNEXTCABINET pfnfcignc,
1403 PFNFCISTATUS pfnfcis,
1404 PFNFCIGETOPENINFO pfnfcigoi,
1405 TCOMP typeCompress)
1406{
1407 cab_ULONG read_result;
1408 FCI_Int *p_fci_internal = get_fci_ptr( hfci );
1409
1410 if (!p_fci_internal) return FALSE;
1411
1412 if ((!pszSourceFile) || (!pszFileName) || (!pfnfcignc) || (!pfnfcis) ||
1413 (!pfnfcigoi) || strlen(pszFileName)>=CB_MAX_FILENAME) {
1414 set_error( p_fci_internal, FCIERR_NONE, ERROR_BAD_ARGUMENTS );
1415 return FALSE;
1416 }
1417
1418 if (typeCompress != p_fci_internal->compression)
1419 {
1420 if (!FCIFlushFolder( hfci, pfnfcignc, pfnfcis )) return FALSE;
1421 switch (typeCompress)
1422 {
1423 case tcompTYPE_MSZIP:
1424#ifdef HAVE_ZLIB
1425 p_fci_internal->compression = tcompTYPE_MSZIP;
1426 p_fci_internal->compress = compress_MSZIP;
1427 break;
1428#endif
1429 default:
1430 FIXME( "compression %x not supported, defaulting to none\n", typeCompress );
1431 /* fall through */
1432 case tcompTYPE_NONE:
1433 p_fci_internal->compression = tcompTYPE_NONE;
1434 p_fci_internal->compress = compress_NONE;
1435 break;
1436 }
1437 }
1438
1439 /* TODO check if pszSourceFile??? */
1440
1441 if(p_fci_internal->fGetNextCabInVain && p_fci_internal->fNextCab) {
1442 /* internal error */
1443 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1444 return FALSE;
1445 }
1446
1447 if(p_fci_internal->fNextCab) {
1448 /* internal error */
1449 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1450 return FALSE;
1451 }
1452
1453 /* REUSE the variable read_result */
1454 read_result=get_header_size( p_fci_internal ) + p_fci_internal->ccab.cbReserveCFFolder;
1455
1456 read_result+= sizeof(CFFILE) + strlen(pszFileName)+1 +
1457 p_fci_internal->files_size + p_fci_internal->folders_data_size +
1458 p_fci_internal->placed_files_size + p_fci_internal->folders_size +
1459 sizeof(CFFOLDER); /* size of new CFFolder entry */
1460
1461 /* Might be too much data for the maximum size of a cabinet.*/
1462 /* When any further data will be added later, it might not */
1463 /* be possible to flush the cabinet, because there might */
1464 /* not be enough space to store the name of the following */
1465 /* cabinet and name of the corresponding disk. */
1466 /* So take care of this and get the name of the next cabinet */
1467 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1468 p_fci_internal->fNextCab==FALSE &&
1469 ( p_fci_internal->ccab.cb < read_result +
1471 )
1472 ) {
1473 /* increment cabinet index */
1474 ++(p_fci_internal->pccab->iCab);
1475 /* get name of next cabinet */
1476 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
1477 if (!(*pfnfcignc)(p_fci_internal->pccab,
1478 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
1479 p_fci_internal->pv)) {
1480 /* error handling */
1481 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
1482 return FALSE;
1483 }
1484 /* Skip a few lines of code. This is caught by the next if. */
1485 p_fci_internal->fGetNextCabInVain=TRUE;
1486 }
1487
1488 if( p_fci_internal->fGetNextCabInVain &&
1489 p_fci_internal->fNextCab
1490 ) {
1491 /* THIS CAN NEVER HAPPEN */
1492 /* set error code */
1493 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1494 return FALSE;
1495 }
1496
1497 /* too much data for cabinet */
1498 if( p_fci_internal->fGetNextCabInVain &&
1499 (
1500 p_fci_internal->ccab.cb < read_result +
1501 strlen(p_fci_internal->pccab->szCab)+1+
1502 strlen(p_fci_internal->pccab->szDisk)+1
1503 )) {
1504 p_fci_internal->fGetNextCabInVain=FALSE;
1505 p_fci_internal->fNextCab=TRUE;
1506 if(!fci_flush_cabinet( p_fci_internal, FALSE, pfnfcignc, pfnfcis)) return FALSE;
1507 }
1508
1509 if( p_fci_internal->fNextCab ) {
1510 /* THIS MAY NEVER HAPPEN */
1511 /* set error code */
1512 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1513 return FALSE;
1514 }
1515
1516 if (!add_file_data( p_fci_internal, pszSourceFile, pszFileName, fExecute, pfnfcigoi, pfnfcis ))
1517 return FALSE;
1518
1519 /* REUSE the variable read_result */
1520 read_result = get_header_size( p_fci_internal ) + p_fci_internal->ccab.cbReserveCFFolder;
1521 read_result+= p_fci_internal->pending_data_size +
1522 p_fci_internal->files_size + p_fci_internal->folders_data_size +
1523 p_fci_internal->placed_files_size + p_fci_internal->folders_size +
1524 sizeof(CFFOLDER); /* set size of new CFFolder entry */
1525
1526 /* too much data for the maximum size of a cabinet */
1527 /* (ignoring the unflushed data block) */
1528 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1529 p_fci_internal->fNextCab==FALSE && /* this is always the case */
1530 p_fci_internal->ccab.cb < read_result ) {
1531 return fci_flush_cabinet( p_fci_internal, FALSE, pfnfcignc, pfnfcis);
1532 }
1533
1534 /* Might be too much data for the maximum size of a cabinet.*/
1535 /* When any further data will be added later, it might not */
1536 /* be possible to flush the cabinet, because there might */
1537 /* not be enough space to store the name of the following */
1538 /* cabinet and name of the corresponding disk. */
1539 /* So take care of this and get the name of the next cabinet */
1540 /* (ignoring the unflushed data block) */
1541 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1542 p_fci_internal->fNextCab==FALSE &&
1543 ( p_fci_internal->ccab.cb < read_result +
1545 )
1546 ) {
1547 /* increment cabinet index */
1548 ++(p_fci_internal->pccab->iCab);
1549 /* get name of next cabinet */
1550 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
1551 if (!(*pfnfcignc)(p_fci_internal->pccab,
1552 p_fci_internal->estimatedCabinetSize,/* estimated size of cab */
1553 p_fci_internal->pv)) {
1554 /* error handling */
1555 set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
1556 return FALSE;
1557 }
1558 /* Skip a few lines of code. This is caught by the next if. */
1559 p_fci_internal->fGetNextCabInVain=TRUE;
1560 }
1561
1562 if( p_fci_internal->fGetNextCabInVain &&
1563 p_fci_internal->fNextCab
1564 ) {
1565 /* THIS CAN NEVER HAPPEN */
1566 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1567 return FALSE;
1568 }
1569
1570 /* too much data for cabinet */
1571 if( (p_fci_internal->fGetNextCabInVain ||
1572 p_fci_internal->fNextCab) && (
1573 p_fci_internal->ccab.cb < read_result +
1574 strlen(p_fci_internal->pccab->szCab)+1+
1575 strlen(p_fci_internal->pccab->szDisk)+1
1576 )) {
1577
1578 p_fci_internal->fGetNextCabInVain=FALSE;
1579 p_fci_internal->fNextCab=TRUE;
1580 return fci_flush_cabinet( p_fci_internal, FALSE, pfnfcignc, pfnfcis);
1581 }
1582
1583 if( p_fci_internal->fNextCab ) {
1584 /* THIS MAY NEVER HAPPEN */
1585 /* set error code */
1586 set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
1587 return FALSE;
1588 }
1589
1590 /* if the FolderThreshold has been reached flush the folder automatically */
1591 if (p_fci_internal->cCompressedBytesInFolder >= p_fci_internal->ccab.cbFolderThresh)
1592 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
1593
1594 return TRUE;
1595} /* end of FCIAddFile */
1596
1597
1598
1599
1600
1601/***********************************************************************
1602 * FCIFlushFolder (CABINET.12)
1603 *
1604 * FCIFlushFolder completes the CFFolder structure under construction.
1605 *
1606 * All further data which is added by FCIAddFile will be associated to
1607 * the next CFFolder structure.
1608 *
1609 * FCIFlushFolder will be called by FCIAddFile automatically if the
1610 * threshold (stored in the member cbFolderThresh of the CCAB structure
1611 * pccab passed to FCICreate) is exceeded.
1612 *
1613 * FCIFlushFolder will be called by FCIFlushFolder automatically before
1614 * any data will be written into the cabinet file.
1615 *
1616 * PARAMS
1617 * hfci [I] An HFCI from FCICreate
1618 * pfnfcignc [I] A pointer to a function which gets information about
1619 * the next cabinet
1620 * pfnfcis [IO] A pointer to a function which will report status
1621 * information about the compression process
1622 *
1623 * RETURNS
1624 * On success, returns TRUE
1625 * On failure, returns FALSE
1626 *
1627 * INCLUDES
1628 * fci.h
1629 *
1630 */
1632 HFCI hfci,
1633 PFNFCIGETNEXTCABINET pfnfcignc,
1634 PFNFCISTATUS pfnfcis)
1635{
1636 FCI_Int *p_fci_internal = get_fci_ptr( hfci );
1637
1638 if (!p_fci_internal) return FALSE;
1639 return fci_flush_folder(p_fci_internal,FALSE,pfnfcignc,pfnfcis);
1640}
1641
1642
1643
1644/***********************************************************************
1645 * FCIFlushCabinet (CABINET.13)
1646 *
1647 * FCIFlushCabinet stores the data which has been added by FCIAddFile
1648 * into the cabinet file. If the maximum cabinet size (stored in the
1649 * member cb of the CCAB structure pccab passed to FCICreate) has been
1650 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
1651 * The remaining data still has to be flushed manually by calling
1652 * FCIFlushCabinet.
1653 *
1654 * After FCIFlushCabinet has been called (manually) FCIAddFile must
1655 * NOT be called again. Then hfci has to be released by FCIDestroy.
1656 *
1657 * PARAMS
1658 * hfci [I] An HFCI from FCICreate
1659 * fGetNextCab [I] Whether you want to add additional files to a
1660 * cabinet set (TRUE) or whether you want to
1661 * finalize it (FALSE)
1662 * pfnfcignc [I] A pointer to a function which gets information about
1663 * the next cabinet
1664 * pfnfcis [IO] A pointer to a function which will report status
1665 * information about the compression process
1666 *
1667 * RETURNS
1668 * On success, returns TRUE
1669 * On failure, returns FALSE
1670 *
1671 * INCLUDES
1672 * fci.h
1673 *
1674 */
1676 HFCI hfci,
1677 BOOL fGetNextCab,
1678 PFNFCIGETNEXTCABINET pfnfcignc,
1679 PFNFCISTATUS pfnfcis)
1680{
1681 FCI_Int *p_fci_internal = get_fci_ptr( hfci );
1682
1683 if (!p_fci_internal) return FALSE;
1684
1685 if(!fci_flush_cabinet(p_fci_internal,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
1686
1687 while( p_fci_internal->files_size>0 ||
1688 p_fci_internal->placed_files_size>0 ) {
1689 if(!fci_flush_cabinet(p_fci_internal,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
1690 }
1691
1692 return TRUE;
1693}
1694
1695
1696/***********************************************************************
1697 * FCIDestroy (CABINET.14)
1698 *
1699 * Frees a handle created by FCICreate.
1700 * Only reason for failure would be an invalid handle.
1701 *
1702 * PARAMS
1703 * hfci [I] The HFCI to free
1704 *
1705 * RETURNS
1706 * TRUE for success
1707 * FALSE for failure
1708 */
1710{
1711 struct folder *folder, *folder_next;
1712 struct file *file, *file_next;
1713 struct data_block *block, *block_next;
1714 FCI_Int *p_fci_internal = get_fci_ptr( hfci );
1715
1716 if (!p_fci_internal) return FALSE;
1717
1718 /* before hfci can be removed all temporary files must be closed */
1719 /* and deleted */
1720 p_fci_internal->magic = 0;
1721
1722 LIST_FOR_EACH_ENTRY_SAFE( folder, folder_next, &p_fci_internal->folders_list, struct folder, entry )
1723 {
1724 free_folder( p_fci_internal, folder );
1725 }
1726 LIST_FOR_EACH_ENTRY_SAFE( file, file_next, &p_fci_internal->files_list, struct file, entry )
1727 {
1728 free_file( p_fci_internal, file );
1729 }
1730 LIST_FOR_EACH_ENTRY_SAFE( block, block_next, &p_fci_internal->blocks_list, struct data_block, entry )
1731 {
1732 free_data_block( p_fci_internal, block );
1733 }
1734
1735 close_temp_file( p_fci_internal, &p_fci_internal->data );
1736
1737 /* hfci can now be removed */
1738 p_fci_internal->free(hfci);
1739 return TRUE;
1740}
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define __cdecl
Definition: accygwin.h:79
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: debug.h:111
Definition: list.h:37
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
Definition: mesh.c:5392
#define CAB_BLOCKMAX
Definition: mszip.h:97
UINT32 cab_ULONG
Definition: mszip.h:27
UINT16 cab_UWORD
Definition: mszip.h:26
unsigned char cab_UBYTE
Definition: mszip.h:25
#define _O_RDWR
Definition: cabinet.h:39
#define _O_BINARY
Definition: cabinet.h:51
#define cffileCONTINUED_FROM_PREV
Definition: cabinet.h:108
#define cfheadRESERVE_PRESENT
Definition: cabinet.h:107
#define cffileCONTINUED_PREV_AND_NEXT
Definition: cabinet.h:110
#define _O_TRUNC
Definition: cabinet.h:47
#define cfheadNEXT_CABINET
Definition: cabinet.h:106
#define cffileCONTINUED_TO_NEXT
Definition: cabinet.h:109
#define _O_CREAT
Definition: cabinet.h:46
#define _O_EXCL
Definition: cabinet.h:48
#define cfheadPREV_CABINET
Definition: cabinet.h:105
#define _S_IWRITE
Definition: cabinet.h:33
#define _S_IREAD
Definition: cabinet.h:34
#define lstrcpynA
Definition: compat.h:751
#define SetLastError(x)
Definition: compat.h:752
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define Z_DEFLATED
Definition: zlib.h:146
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:137
#define Z_FINISH
Definition: zlib.h:109
#define Z_OK
Definition: zlib.h:114
int deflate(z_streamp strm, int flush) DECLSPEC_HIDDEN
Definition: deflate.c:815
int deflateEnd(z_streamp strm) DECLSPEC_HIDDEN
Definition: deflate.c:1130
#define Z_DEFAULT_COMPRESSION
Definition: zlib.h:130
#define assert(x)
Definition: debug.h:53
static void * zalloc(void *priv, uInt items, uInt sz)
Definition: dwarf.c:3386
static void zfree(void *priv, void *addr)
Definition: dwarf.c:3391
static BOOL fci_flush_folder(FCI_Int *p_fci_internal, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1071
static void free_folder(FCI_Int *fci, struct folder *folder)
Definition: fci.c:417
static BOOL write_files(FCI_Int *fci, INT_PTR handle, PFNFCISTATUS status_callback)
Definition: fci.c:554
static struct file * copy_file(FCI_Int *fci, const struct file *orig)
Definition: fci.c:292
static struct folder * add_folder(FCI_Int *fci)
Definition: fci.c:396
static void free_data_block(FCI_Int *fci, struct data_block *block)
Definition: fci.c:390
static BOOL add_data_block(FCI_Int *fci, PFNFCISTATUS status_callback)
Definition: fci.c:313
static cab_ULONG get_header_size(FCI_Int *fci)
Definition: fci.c:217
BOOL __cdecl FCIAddFile(HFCI hfci, char *pszSourceFile, char *pszFileName, BOOL fExecute, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis, PFNFCIGETOPENINFO pfnfcigoi, TCOMP typeCompress)
Definition: fci.c:1397
static BOOL add_file_data(FCI_Int *fci, char *sourcefile, char *filename, BOOL execute, PFNFCIGETOPENINFO get_open_info, PFNFCISTATUS status_callback)
Definition: fci.c:353
static struct file * add_file(FCI_Int *fci, const char *filename)
Definition: fci.c:270
static BOOL copy_data_blocks(FCI_Int *fci, INT_PTR handle, cab_ULONG start_pos, struct temp_file *temp, PFNFCISTATUS status_callback)
Definition: fci.c:485
static void reset_cabinet(FCI_Int *fci)
Definition: fci.c:432
static cab_UWORD compress_NONE(FCI_Int *fci)
Definition: fci.c:906
static void set_error(FCI_Int *fci, int oper, int err)
Definition: fci.c:196
static FCI_Int * get_fci_ptr(HFCI hfci)
Definition: fci.c:204
static BOOL fci_flush_cabinet(FCI_Int *p_fci_internal, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1231
#define FCI_INT_MAGIC
Definition: fci.c:194
static BOOL write_cabinet(FCI_Int *fci, PFNFCISTATUS status_callback)
Definition: fci.c:649
BOOL __cdecl FCIDestroy(HFCI hfci)
Definition: fci.c:1709
static BOOL create_temp_file(FCI_Int *fci, struct temp_file *file)
Definition: fci.c:233
static cab_ULONG fci_get_checksum(const void *pv, UINT cb, cab_ULONG seed)
Definition: fci.c:446
static BOOL write_folders(FCI_Int *fci, INT_PTR handle, cab_ULONG header_size, PFNFCISTATUS status_callback)
Definition: fci.c:529
static BOOL write_data_blocks(FCI_Int *fci, INT_PTR handle, PFNFCISTATUS status_callback)
Definition: fci.c:599
HFCI __cdecl FCICreate(PERF perf, PFNFCIFILEPLACED pfnfiledest, PFNFCIALLOC pfnalloc, PFNFCIFREE pfnfree, PFNFCIOPEN pfnopen, PFNFCIREAD pfnread, PFNFCIWRITE pfnwrite, PFNFCICLOSE pfnclose, PFNFCISEEK pfnseek, PFNFCIDELETE pfndelete, PFNFCIGETTEMPFILE pfnfcigtf, PCCAB pccab, void *pv)
Definition: fci.c:998
#define fci_endian_uword(x)
Definition: fci.c:61
static BOOL close_temp_file(FCI_Int *fci, struct temp_file *file)
Definition: fci.c:251
BOOL __cdecl FCIFlushFolder(HFCI hfci, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1631
BOOL __cdecl FCIFlushCabinet(HFCI hfci, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1675
static void free_file(FCI_Int *fci, struct file *file)
Definition: fci.c:306
static BOOL add_files_to_folder(FCI_Int *fci, struct folder *folder, cab_ULONG payload)
Definition: fci.c:839
static BOOL add_data_to_folder(FCI_Int *fci, struct folder *folder, cab_ULONG *payload, PFNFCISTATUS status_callback)
Definition: fci.c:762
#define fci_endian_ulong(x)
Definition: fci.c:60
unsigned short TCOMP
Definition: fci.h:61
#define CB_MAX_DISK_NAME
Definition: fci.h:57
#define statusFile
Definition: fci.h:219
#define CB_MAX_CABINET_NAME
Definition: fci.h:55
LONG(__cdecl * PFNFCISEEK)(INT_PTR hf, LONG dist, int seektype, int *err, void *pv)
Definition: fci.h:184
INT_PTR(__cdecl * PFNFCIOPEN)(char *pszFile, int oflag, int pmode, int *err, void *pv)
Definition: fci.h:172
UINT(__cdecl * PFNFCIWRITE)(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
Definition: fci.h:178
#define tcompTYPE_NONE
Definition: fci.h:64
int(__cdecl * PFNFCIDELETE)(char *pszFile, int *err, void *pv)
Definition: fci.h:187
UINT(__cdecl * PFNFCIREAD)(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
Definition: fci.h:175
#define CB_MAX_FILENAME
Definition: fci.h:54
BOOL(__cdecl * PFNFCIGETTEMPFILE)(char *pszTempName, int cbTempName, void *pv)
Definition: fci.h:232
LONG(__cdecl * PFNFCISTATUS)(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
Definition: fci.h:223
void(__cdecl * PFNFCIFREE)(void *memory)
Definition: fci.h:169
#define CB_MAX_CAB_PATH
Definition: fci.h:56
int(__cdecl * PFNFCIFILEPLACED)(PCCAB pccab, char *pszFile, LONG cbFile, BOOL fContinuation, void *pv)
Definition: fci.h:195
int(__cdecl * PFNFCICLOSE)(INT_PTR hf, int *err, void *pv)
Definition: fci.h:181
INT_PTR(__cdecl * PFNFCIGETOPENINFO)(char *pszName, USHORT *pdate, USHORT *ptime, USHORT *pattribs, int *err, void *pv)
Definition: fci.h:206
#define statusCabinet
Definition: fci.h:221
#define _A_EXEC
Definition: fci.h:135
#define tcompTYPE_MSZIP
Definition: fci.h:65
@ FCIERR_TEMP_FILE
Definition: fci.h:121
@ FCIERR_USER_ABORT
Definition: fci.h:124
@ FCIERR_OPEN_SRC
Definition: fci.h:118
@ FCIERR_CAB_FILE
Definition: fci.h:123
@ FCIERR_ALLOC_FAIL
Definition: fci.h:120
@ FCIERR_READ_SRC
Definition: fci.h:119
@ FCIERR_NONE
Definition: fci.h:117
#define statusFolder
Definition: fci.h:220
BOOL(__cdecl * PFNFCIGETNEXTCABINET)(PCCAB pccab, ULONG cbPrevCab, void *pv)
Definition: fci.h:190
unsigned int BOOL
Definition: ntddk_ex.h:94
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLbitfield flags
Definition: glext.h:7161
GLenum GLsizei len
Definition: glext.h:6722
const char * filename
Definition: ioapi.h:137
uint32_t entry
Definition: isohybrid.c:63
#define SEEK_SET
Definition: jmemansi.c:26
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime, USHORT *pattribs, int *err, void *pv)
Definition: files.c:304
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
static void WINAPI status_callback(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID info, DWORD info_len)
Definition: ftp.c:948
unsigned int UINT
Definition: ndis.h:50
void execute(char *message, int(*func)(int))
Definition: noexecute.c:13
static TCHAR * items[]
Definition: page1.c:45
static unsigned __int64 next
Definition: rand_nt.c:6
#define err(...)
static unsigned int file_size
Definition: regtests2xml.c:47
static calc_node_t temp
Definition: rpn_ieee.c:38
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy)
Definition: zlib.h:1814
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
__WINE_SERVER_LIST_INLINE void list_add_before(struct list *elem, struct list *to_add)
Definition: list.h:87
#define memset(x, y, z)
Definition: compat.h:39
Definition: fci.h:144
UINT cbReserveCFFolder
Definition: fci.h:149
ULONG cbFolderThresh
Definition: fci.h:146
UINT cbReserveCFData
Definition: fci.h:150
int iCab
Definition: fci.h:151
UINT cbReserveCFHeader
Definition: fci.h:148
char szDisk[CB_MAX_DISK_NAME]
Definition: fci.h:159
USHORT setID
Definition: fci.h:157
char szCabPath[CB_MAX_CAB_PATH]
Definition: fci.h:161
ULONG cb
Definition: fci.h:145
char szCab[CB_MAX_CABINET_NAME]
Definition: fci.h:160
Definition: fci.c:101
cab_ULONG csum
Definition: fci.c:102
cab_UWORD cbUncomp
Definition: fci.c:104
cab_UWORD cbData
Definition: fci.c:103
Definition: fci.c:89
cab_UWORD time
Definition: fci.c:95
cab_ULONG uoffFolderStart
Definition: fci.c:91
cab_ULONG cbFile
Definition: fci.c:90
cab_UWORD date
Definition: fci.c:94
cab_UWORD iFolder
Definition: fci.c:92
cab_UWORD attribs
Definition: fci.c:96
Definition: fci.c:82
cab_UWORD cCFData
Definition: fci.c:84
cab_ULONG coffCabStart
Definition: fci.c:83
cab_UWORD typeCompress
Definition: fci.c:85
Definition: fci.c:65
cab_ULONG reserved1
Definition: fci.c:67
cab_ULONG reserved2
Definition: fci.c:69
cab_UBYTE versionMajor
Definition: fci.c:73
cab_UBYTE versionMinor
Definition: fci.c:72
cab_UWORD flags
Definition: fci.c:76
cab_ULONG coffFiles
Definition: fci.c:70
cab_UWORD cFolders
Definition: fci.c:74
cab_ULONG cbCabinet
Definition: fci.c:68
cab_ULONG reserved3
Definition: fci.c:71
cab_UWORD cFiles
Definition: fci.c:75
cab_UWORD setID
Definition: fci.c:77
cab_UWORD iCabinet
Definition: fci.c:78
cab_UBYTE signature[4]
Definition: fci.c:66
Definition: fci.h:44
int erfType
Definition: fci.h:46
BOOL fError
Definition: fci.h:47
int erfOper
Definition: fci.h:45
Definition: fci.c:146
PFNFCIFREE free
Definition: fci.c:151
char szPrevDisk[CB_MAX_DISK_NAME]
Definition: fci.c:169
PFNFCISEEK seek
Definition: fci.c:156
void * pv
Definition: fci.c:167
PFNFCIWRITE write
Definition: fci.c:154
cab_ULONG folders_size
Definition: fci.c:185
cab_UWORD cFiles
Definition: fci.c:175
BOOL fGetNextCabInVain
Definition: fci.c:166
cab_ULONG files_size
Definition: fci.c:186
cab_ULONG estimatedCabinetSize
Definition: fci.c:181
cab_ULONG cbFileRemainder
Definition: fci.c:177
unsigned char data_out[2 *CAB_BLOCKMAX]
Definition: fci.c:171
struct temp_file data
Definition: fci.c:179
cab_ULONG pending_data_size
Definition: fci.c:188
TCOMP compression
Definition: fci.c:190
struct list folders_list
Definition: fci.c:182
struct list files_list
Definition: fci.c:183
cab_ULONG statusFolderCopied
Definition: fci.c:164
BOOL fPrevCab
Definition: fci.c:161
BOOL fSplitFolder
Definition: fci.c:163
cab_UWORD cdata_in
Definition: fci.c:172
PERF perf
Definition: fci.c:148
PFNFCIREAD read
Definition: fci.c:153
cab_ULONG statusFolderTotal
Definition: fci.c:165
PFNFCIFILEPLACED fileplaced
Definition: fci.c:149
BOOL fNewPrevious
Definition: fci.c:180
PFNFCIDELETE delete
Definition: fci.c:157
BOOL fNextCab
Definition: fci.c:162
PFNFCICLOSE close
Definition: fci.c:155
PFNFCIALLOC alloc
Definition: fci.c:150
CCAB ccab
Definition: fci.c:159
unsigned char data_in[CAB_BLOCKMAX]
Definition: fci.c:170
PFNFCIOPEN open
Definition: fci.c:152
cab_UWORD cFolders
Definition: fci.c:174
cab_ULONG folders_data_size
Definition: fci.c:189
PCCAB pccab
Definition: fci.c:160
ULONG cCompressedBytesInFolder
Definition: fci.c:173
struct list blocks_list
Definition: fci.c:184
cab_UWORD(* compress)(struct FCI_Int *)
Definition: fci.c:191
cab_ULONG placed_files_size
Definition: fci.c:187
unsigned int magic
Definition: fci.c:147
cab_ULONG cDataBlocks
Definition: fci.c:176
char szPrevCab[CB_MAX_CABINET_NAME]
Definition: fci.c:168
PFNFCIGETTEMPFILE gettemp
Definition: fci.c:158
Definition: ffs.h:52
cab_UWORD compressed
Definition: fci.c:141
cab_UWORD uncompressed
Definition: fci.c:142
struct list entry
Definition: fci.c:140
Definition: fci.c:127
cab_ULONG offset
Definition: fci.c:130
cab_UWORD folder
Definition: fci.c:131
cab_UWORD date
Definition: fci.c:132
struct list entry
Definition: fci.c:128
cab_UWORD attribs
Definition: fci.c:134
cab_ULONG size
Definition: fci.c:129
cab_UWORD time
Definition: fci.c:133
char name[1]
Definition: fci.c:135
Definition: fci.c:116
TCOMP compression
Definition: fci.c:123
struct temp_file data
Definition: fci.c:120
struct list files_list
Definition: fci.c:118
struct list blocks_list
Definition: fci.c:119
struct list entry
Definition: fci.c:117
cab_ULONG data_start
Definition: fci.c:121
cab_UWORD data_count
Definition: fci.c:122
Definition: name.c:39
Definition: parse.h:23
Definition: fci.c:110
INT_PTR handle
Definition: fci.c:111
#define new(TYPE, numElems)
Definition: treelist.c:54
int32_t INT_PTR
Definition: typedefs.h:64
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint32_t ULONG
Definition: typedefs.h:59
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:44
int ret
#define ERROR_GEN_FAILURE
Definition: winerror.h:134
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
#define ERROR_BAD_ARGUMENTS
Definition: winerror.h:232
static unsigned int block
Definition: xmlmemory.c:101
unsigned char BYTE
Definition: xxhash.c:193