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