ReactOS  0.4.14-dev-55-g2da92ac
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 
25 There 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 
65 typedef 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 
82 typedef 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 
89 typedef 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 
101 typedef 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 
109 struct temp_file
110 {
113 };
114 
115 struct folder
116 {
117  struct list entry;
118  struct list files_list;
120  struct temp_file data;
124 };
125 
126 struct 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 
145 typedef struct FCI_Int
146 {
147  unsigned int magic;
150  PFNFCIALLOC alloc;
157  PFNFCIDELETE delete;
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 cbFileRemainer; /* uncompressed, yet to be written data */
178  /* of spanned file of a spanning folder of a spanning cabinet */
179  struct temp_file data;
183  struct list files_list;
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 */
191  cab_UWORD (*compress)(struct FCI_Int *);
192 } FCI_Int;
193 
194 #define FCI_INT_MAGIC 0xfcfcfc05
195 
196 static 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 
204 static 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 {
219  cab_ULONG ret = sizeof(CFHEADER) + fci->ccab.cbReserveCFHeader;
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 
233 static BOOL create_temp_file( FCI_Int *fci, struct temp_file *file )
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  {
245  set_error( fci, FCIERR_TEMP_FILE, err );
246  return FALSE;
247  }
248  return TRUE;
249 }
250 
251 static BOOL close_temp_file( FCI_Int *fci, struct temp_file *file )
252 {
253  int err;
254 
255  if (file->handle == -1) return TRUE;
256  if (fci->close( file->handle, &err, fci->pv ) == -1)
257  {
258  set_error( fci, FCIERR_TEMP_FILE, err );
259  return FALSE;
260  }
261  file->handle = -1;
262  if (fci->delete( file->name, &err, fci->pv ) == -1)
263  {
264  set_error( fci, FCIERR_TEMP_FILE, err );
265  return FALSE;
266  }
267  return TRUE;
268 }
269 
270 static 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;
281  file->offset = fci->cDataBlocks * CAB_BLOCKMAX + fci->cdata_in;
282  file->folder = fci->cFolders;
283  file->date = 0;
284  file->time = 0;
285  file->attribs = 0;
286  strcpy( file->name, filename );
287  list_add_tail( &fci->files_list, &file->entry );
288  fci->files_size += sizeof(CFFILE) + strlen(filename) + 1;
289  return file;
290 }
291 
292 static 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 
306 static void free_file( FCI_Int *fci, struct file *file )
307 {
308  list_remove( &file->entry );
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  {
333  set_error( fci, FCIERR_TEMP_FILE, err );
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 */
353 static BOOL add_file_data( FCI_Int *fci, char *sourcefile, char *filename, BOOL execute,
355 {
356  int err, len;
357  INT_PTR handle;
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 );
366  set_error( fci, FCIERR_OPEN_SRC, err );
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  {
379  set_error( fci, FCIERR_READ_SRC, err );
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 
390 static void free_data_block( FCI_Int *fci, struct data_block *block )
391 {
392  list_remove( &block->entry );
393  fci->free( block );
394 }
395 
396 static 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 
417 static 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 );
427  list_remove( &folder->entry );
428  fci->free( folder );
429 }
430 
431 /* reset state for the next cabinet file once the current one has been flushed */
432 static 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 
446 static cab_ULONG fci_get_checksum( const void *pv, UINT cb, cab_ULONG seed )
447 {
448  cab_ULONG csum;
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  {
493  set_error( fci, FCIERR_TEMP_FILE, err );
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 );
504  set_error( fci, FCIERR_TEMP_FILE, err );
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 );
511  set_error( fci, FCIERR_TEMP_FILE, err );
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 );
542  cffolder->cCFData = fci_endian_uword( folder->data_count );
544  if (fci->write( handle, cffolder, folder_size, &err, fci->pv ) != folder_size)
545  {
546  set_error( fci, FCIERR_CAB_FILE, err );
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  {
576  set_error( fci, FCIERR_CAB_FILE, err );
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  {
617  set_error( fci, FCIERR_CAB_FILE, err );
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  {
635  set_error( fci, FCIERR_CAB_FILE, err );
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;
654  INT_PTR handle;
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 
718  if ((handle = fci->open( filename, _O_RDWR | _O_CREAT | _O_TRUNC | _O_BINARY,
719  _S_IREAD | _S_IWRITE, &err, fci->pv )) == -1)
720  {
721  set_error( fci, FCIERR_CAB_FILE, err );
722  return FALSE;
723  }
724 
725  if (fci->write( handle, cfheader, header_size, &err, fci->pv ) != header_size)
726  {
727  set_error( fci, FCIERR_CAB_FILE, err );
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  {
740  set_error( fci, FCIERR_CAB_FILE, err );
741  goto failed;
742  }
743  memcpy( cfheader->signature, "MSCF", 4 );
744  if (fci->write( handle, cfheader->signature, 4, &err, fci->pv ) != 4)
745  {
746  set_error( fci, FCIERR_CAB_FILE, err );
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 
755 failed:
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 */
762 static 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 );
820  folder->data_count++;
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 */
839 static BOOL add_files_to_folder( FCI_Int *fci, struct folder *folder, cab_ULONG payload )
840 {
841  cab_ULONG sizeOfFiles = 0, sizeOfFilesPrev;
842  cab_ULONG cbFileRemainer = 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,
851  (file->folder == cffileCONTINUED_FROM_PREV), fci->pv );
852 
853  sizeOfFilesPrev = sizeOfFiles;
854  /* set complete size of all processed files */
856  {
857  sizeOfFiles += fci->cbFileRemainer;
858  fci->cbFileRemainer = 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 
871  list_remove( &file->entry );
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  cbFileRemainer = sizeOfFiles - payload;
892  }
894  }
895  else file->folder = 0;
896  }
897  else
898  {
899  fci->files_size -= size;
900  }
901  }
902  fci->cbFileRemainer = cbFileRemainer;
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 
914 static void *zalloc( void *opaque, unsigned int items, unsigned int size )
915 {
916  FCI_Int *fci = opaque;
917  return fci->alloc( items * size );
918 }
919 
920 static void zfree( void *opaque, void *ptr )
921 {
922  FCI_Int *fci = opaque;
923  fci->free( ptr );
924 }
925 
926 static 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';
945  deflate( &stream, Z_FINISH );
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;
1023  perf->erfType = ERROR_BAD_ARGUMENTS;
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 
1071 static 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 
1231 static 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 }
static unsigned int block
Definition: xmlmemory.c:118
ULONG cbFolderThresh
Definition: fci.h:146
#define CB_MAX_CAB_PATH
Definition: fci.h:56
BOOL fNewPrevious
Definition: fci.c:180
struct _CFHEADER CFHEADER
PFNFCISEEK seek
Definition: fci.c:156
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
cab_ULONG pending_data_size
Definition: fci.c:188
cab_UWORD attribs
Definition: fci.c:134
cab_UBYTE signature[4]
Definition: fci.c:66
WINE_DEFAULT_DEBUG_CHANNEL(cabinet)
Definition: fci.c:115
PFNFCIDELETE delete
Definition: fci.c:157
Definition: fci.c:109
#define _S_IREAD
Definition: cabinet.h:34
cab_UWORD cdata_in
Definition: fci.c:172
BOOL __cdecl FCIFlushCabinet(HFCI hfci, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1675
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 new(TYPE, numElems)
Definition: treelist.c:54
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
#define __cdecl
Definition: accygwin.h:79
cab_ULONG cbFile
Definition: fci.c:90
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
PFNFCIALLOC alloc
Definition: fci.c:150
unsigned int magic
Definition: fci.c:147
static void set_error(FCI_Int *fci, int oper, int err)
Definition: fci.c:196
#define _O_CREAT
Definition: cabinet.h:46
cab_UWORD typeCompress
Definition: fci.c:85
cab_UWORD cbData
Definition: fci.c:103
static BOOL fci_flush_cabinet(FCI_Int *p_fci_internal, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1231
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
cab_ULONG placed_files_size
Definition: fci.c:187
#define ERROR_BAD_ARGUMENTS
Definition: winerror.h:232
BOOL __cdecl FCIDestroy(HFCI hfci)
Definition: fci.c:1709
CCAB ccab
Definition: fci.c:159
#define fci_endian_ulong(x)
Definition: fci.c:60
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define assert(x)
Definition: debug.h:53
BOOL __cdecl FCIFlushFolder(HFCI hfci, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1631
#define CB_MAX_FILENAME
Definition: fci.h:54
PFNFCIFREE free
Definition: fci.c:151
static struct file * copy_file(FCI_Int *fci, const struct file *orig)
Definition: fci.c:292
cab_UWORD date
Definition: fci.c:132
cab_ULONG files_size
Definition: fci.c:186
INT_PTR(__cdecl * PFNFCIGETOPENINFO)(char *pszName, USHORT *pdate, USHORT *ptime, USHORT *pattribs, int *err, void *pv)
Definition: fci.h:206
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy)
Definition: zlib.h:1797
Definition: fci.h:144
#define fci_endian_uword(x)
Definition: fci.c:61
int32_t INT_PTR
Definition: typedefs.h:62
int(__cdecl * PFNFCIFILEPLACED)(PCCAB pccab, char *pszFile, LONG cbFile, BOOL fContinuation, void *pv)
Definition: fci.h:195
char szPrevDisk[CB_MAX_DISK_NAME]
Definition: fci.c:169
#define cfheadRESERVE_PRESENT
Definition: cabinet.h:107
const char * filename
Definition: ioapi.h:135
BOOL fSplitFolder
Definition: fci.c:163
cab_ULONG cDataBlocks
Definition: fci.c:176
UINT(__cdecl * PFNFCIWRITE)(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
Definition: fci.h:178
UINT16 cab_UWORD
Definition: mszip.h:26
cab_ULONG csum
Definition: fci.c:102
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:200
void execute(char *message, int(*func)(int))
Definition: noexecute.c:13
struct _CFFILE CFFILE
TCOMP compression
Definition: fci.c:123
int iCab
Definition: fci.h:151
int ZEXPORT deflateEnd(z_streamp strm)
Definition: deflate.c:1079
cab_UWORD cFolders
Definition: fci.c:74
static void WINAPI status_callback(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID info, DWORD info_len)
Definition: ftp.c:943
static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime, USHORT *pattribs, int *err, void *pv)
Definition: files.c:304
Definition: fci.c:145
#define tcompTYPE_MSZIP
Definition: fci.h:65
static BOOL write_files(FCI_Int *fci, INT_PTR handle, PFNFCISTATUS status_callback)
Definition: fci.c:554
BOOL fNextCab
Definition: fci.c:162
cab_ULONG uoffFolderStart
Definition: fci.c:91
cab_UWORD cCFData
Definition: fci.c:84
static cab_ULONG fci_get_checksum(const void *pv, UINT cb, cab_ULONG seed)
Definition: fci.c:446
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
cab_UWORD iFolder
Definition: fci.c:92
#define _O_RDWR
Definition: cabinet.h:39
cab_UWORD data_count
Definition: fci.c:122
LONG(__cdecl * PFNFCISTATUS)(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
Definition: fci.h:223
#define _O_EXCL
Definition: cabinet.h:48
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
struct _CFFOLDER CFFOLDER
UINT cbReserveCFHeader
Definition: fci.h:148
INT_PTR handle
Definition: fci.c:111
#define cffileCONTINUED_TO_NEXT
Definition: cabinet.h:109
struct list entry
Definition: fci.c:140
UINT(__cdecl * PFNFCIREAD)(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
Definition: fci.h:175
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
char name[1]
Definition: fci.c:135
static BOOL add_files_to_folder(FCI_Int *fci, struct folder *folder, cab_ULONG payload)
Definition: fci.c:839
unsigned int BOOL
Definition: ntddk_ex.h:94
UINT32 cab_ULONG
Definition: mszip.h:27
INT_PTR(__cdecl * PFNFCIOPEN)(char *pszFile, int oflag, int pmode, int *err, void *pv)
Definition: fci.h:172
#define cfheadPREV_CABINET
Definition: cabinet.h:105
Definition: fci.c:82
cab_ULONG folders_data_size
Definition: fci.c:189
char szDisk[CB_MAX_DISK_NAME]
Definition: fci.h:159
Definition: fci.h:44
#define statusCabinet
Definition: fci.h:221
#define Z_OK
Definition: zlib.h:177
#define FIXME(fmt,...)
Definition: debug.h:110
char szCab[CB_MAX_CABINET_NAME]
Definition: fci.h:160
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:41
static PVOID ptr
Definition: dispmode.c:27
#define _A_EXEC
Definition: fci.h:135
Definition: fci.c:101
ULONG cb
Definition: fci.h:145
smooth NULL
Definition: ftsmooth.c:416
cab_UWORD time
Definition: fci.c:95
static BOOL fci_flush_folder(FCI_Int *p_fci_internal, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1071
static BOOL write_folders(FCI_Int *fci, INT_PTR handle, cab_ULONG header_size, PFNFCISTATUS status_callback)
Definition: fci.c:529
#define Z_DEFLATED
Definition: zlib.h:209
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
TCOMP compression
Definition: fci.c:190
#define _O_TRUNC
Definition: cabinet.h:47
#define _S_IWRITE
Definition: cabinet.h:33
cab_UWORD cbUncomp
Definition: fci.c:104
#define Z_DEFAULT_COMPRESSION
Definition: zlib.h:193
struct CFFOLDER folder
Definition: fdi.c:110
cab_UWORD iCabinet
Definition: fci.c:78
cab_UWORD attribs
Definition: fci.c:96
struct list folders_list
Definition: fci.c:182
cab_ULONG data_start
Definition: fci.c:121
cab_UWORD cFiles
Definition: fci.c:75
BOOL(__cdecl * PFNFCIGETNEXTCABINET)(PCCAB pccab, ULONG cbPrevCab, void *pv)
Definition: fci.h:190
cab_ULONG reserved2
Definition: fci.c:69
uint32_t * csum
Definition: write.c:2821
struct temp_file data
Definition: fci.c:120
PFNFCIFILEPLACED fileplaced
Definition: fci.c:149
#define SEEK_SET
Definition: jmemansi.c:26
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
BOOL fGetNextCabInVain
Definition: fci.c:166
cab_ULONG statusFolderCopied
Definition: fci.c:164
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
GLsizeiptr size
Definition: glext.h:5919
static void free_folder(FCI_Int *fci, struct folder *folder)
Definition: fci.c:417
#define tcompTYPE_NONE
Definition: fci.h:64
if(!(yy_init))
Definition: macro.lex.yy.c:714
cab_ULONG statusFolderTotal
Definition: fci.c:165
static BOOL create_temp_file(FCI_Int *fci, struct temp_file *file)
Definition: fci.c:233
unsigned short TCOMP
Definition: fci.h:61
BOOL fPrevCab
Definition: fci.c:161
static struct file * add_file(FCI_Int *fci, const char *filename)
Definition: fci.c:270
const char file[]
Definition: icontest.c:11
static void free_data_block(FCI_Int *fci, struct data_block *block)
Definition: fci.c:390
Definition: fci.c:89
#define SetLastError(x)
Definition: compat.h:409
cab_ULONG folders_size
Definition: fci.c:185
cab_ULONG offset
Definition: fci.c:130
cab_ULONG size
Definition: fci.c:129
static DWORD cb
Definition: integrity.c:41
struct list blocks_list
Definition: fci.c:119
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLbitfield flags
Definition: glext.h:7161
#define FCI_INT_MAGIC
Definition: fci.c:194
unsigned char cab_UBYTE
Definition: mszip.h:25
int ret
cab_ULONG coffFiles
Definition: fci.c:70
#define _O_BINARY
Definition: cabinet.h:51
cab_UBYTE versionMinor
Definition: fci.c:72
static BOOL add_data_to_folder(FCI_Int *fci, struct folder *folder, cab_ULONG *payload, PFNFCISTATUS status_callback)
Definition: fci.c:762
static cab_UWORD compress_NONE(FCI_Int *fci)
Definition: fci.c:906
Definition: parse.h:22
struct list files_list
Definition: fci.c:118
GLuint GLuint stream
Definition: glext.h:7522
int ZEXPORT deflate(z_streamp strm, int flush)
Definition: deflate.c:766
cab_UWORD compressed
Definition: fci.c:141
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
Definition: _list.h:228
int erfOper
Definition: fci.h:45
#define err(...)
#define CB_MAX_DISK_NAME
Definition: fci.h:57
static struct folder * add_folder(FCI_Int *fci)
Definition: fci.c:396
cab_UWORD time
Definition: fci.c:133
struct _CFDATA CFDATA
static BOOL add_data_block(FCI_Int *fci, PFNFCISTATUS status_callback)
Definition: fci.c:313
cab_UWORD setID
Definition: fci.c:77
cab_UWORD folder
Definition: fci.c:131
int erfType
Definition: fci.h:46
LONG(__cdecl * PFNFCISEEK)(INT_PTR hf, LONG dist, int seektype, int *err, void *pv)
Definition: fci.h:184
PFNFCIGETTEMPFILE gettemp
Definition: fci.c:158
cab_UWORD date
Definition: fci.c:94
#define CB_MAX_CABINET_NAME
Definition: fci.h:55
PFNFCIREAD read
Definition: fci.c:153
static BOOL write_data_blocks(FCI_Int *fci, INT_PTR handle, PFNFCISTATUS status_callback)
Definition: fci.c:599
unsigned char data_in[CAB_BLOCKMAX]
Definition: fci.c:170
cab_ULONG estimatedCabinetSize
Definition: fci.c:181
static BOOL write_cabinet(FCI_Int *fci, PFNFCISTATUS status_callback)
Definition: fci.c:649
#define Z_FINISH
Definition: zlib.h:172
ULONG cCompressedBytesInFolder
Definition: fci.c:173
__WINE_SERVER_LIST_INLINE int list_empty(const struct list *list)
Definition: list.h:143
static unsigned __int64 next
Definition: rand_nt.c:6
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
Definition: mesh.c:5392
static void free_file(FCI_Int *fci, struct file *file)
Definition: fci.c:306
static calc_node_t temp
Definition: rpn_ieee.c:38
struct temp_file data
Definition: fci.c:179
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
USHORT setID
Definition: fci.h:157
struct FCI_Int FCI_Int
unsigned int UINT
Definition: ndis.h:50
cab_UWORD cFiles
Definition: fci.c:175
#define lstrcpynA
Definition: compat.h:408
__WINE_SERVER_LIST_INLINE void list_add_before(struct list *elem, struct list *to_add)
Definition: list.h:87
struct list entry
Definition: fci.c:128
Definition: fci.c:65
BOOL(__cdecl * PFNFCIGETTEMPFILE)(char *pszTempName, int cbTempName, void *pv)
Definition: fci.h:232
UINT cbReserveCFData
Definition: fci.h:150
BOOL __cdecl FCIAddFile(HFCI hfci, char *pszSourceFile, char *pszFileName, BOOL fExecute, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis, PFNFCIGETOPENINFO pfnfcigoi, TCOMP typeCompress)
Definition: fci.c:1397
char szPrevCab[CB_MAX_CABINET_NAME]
Definition: fci.c:168
cab_UWORD(* compress)(struct FCI_Int *)
Definition: fci.c:191
cab_UBYTE versionMajor
Definition: fci.c:73
cab_UWORD uncompressed
Definition: fci.c:142
Definition: fs.h:216
UINT cbReserveCFFolder
Definition: fci.h:149
PFNFCIWRITE write
Definition: fci.c:154
cab_ULONG reserved1
Definition: fci.c:67
Definition: name.c:36
cab_ULONG reserved3
Definition: fci.c:71
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
static FCI_Int * get_fci_ptr(HFCI hfci)
Definition: fci.c:204
PFNFCIOPEN open
Definition: fci.c:152
char szCabPath[CB_MAX_CAB_PATH]
Definition: fci.h:161
unsigned int ULONG
Definition: retypes.h:1
#define statusFolder
Definition: fci.h:220
PFNFCICLOSE close
Definition: fci.c:155
cab_UWORD cFolders
Definition: fci.c:174
struct list blocks_list
Definition: fci.c:184
#define ERROR_GEN_FAILURE
Definition: winerror.h:134
#define cfheadNEXT_CABINET
Definition: cabinet.h:106
struct list files_list
Definition: fci.c:183
static TCHAR * items[]
Definition: page1.c:45
cab_ULONG cbFileRemainer
Definition: fci.c:177
static void reset_cabinet(FCI_Int *fci)
Definition: fci.c:432
cab_ULONG cbCabinet
Definition: fci.c:68
void * pv
Definition: fci.c:167
#define memset(x, y, z)
Definition: compat.h:39
void(__cdecl * PFNFCIFREE)(void *memory)
Definition: fci.h:169
#define statusFile
Definition: fci.h:219
int(__cdecl * PFNFCICLOSE)(INT_PTR hf, int *err, void *pv)
Definition: fci.h:181
cab_ULONG coffCabStart
Definition: fci.c:83
BOOL fError
Definition: fci.h:47
static BOOL close_temp_file(FCI_Int *fci, struct temp_file *file)
Definition: fci.c:251
#define CAB_BLOCKMAX
Definition: mszip.h:97
cab_UWORD flags
Definition: fci.c:76
#define file_size(inode)
Definition: reiserfs_fs.h:1869
int(__cdecl * PFNFCIDELETE)(char *pszFile, int *err, void *pv)
Definition: fci.h:187
unsigned char data_out[2 *CAB_BLOCKMAX]
Definition: fci.c:171
PCCAB pccab
Definition: fci.c:160
#define cffileCONTINUED_FROM_PREV
Definition: cabinet.h:108
static cab_ULONG get_header_size(FCI_Int *fci)
Definition: fci.c:217
PERF perf
Definition: fci.c:148
#define cffileCONTINUED_PREV_AND_NEXT
Definition: cabinet.h:110
Definition: fci.c:126
struct list entry
Definition: fci.c:117