ReactOS 0.4.16-dev-329-g9223134
fci.c File Reference
#include "config.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/winternl.h"
#include "fci.h"
#include "cabinet.h"
#include "wine/list.h"
#include "wine/debug.h"
Include dependency graph for fci.c:

Go to the source code of this file.

Classes

struct  CFHEADER
 
struct  CFFOLDER
 
struct  CFFILE
 
struct  CFDATA
 
struct  temp_file
 
struct  folder
 
struct  file
 
struct  data_block
 
struct  FCI_Int
 

Macros

#define fci_endian_ulong(x)   (x)
 
#define fci_endian_uword(x)   (x)
 
#define FCI_INT_MAGIC   0xfcfcfc05
 

Typedefs

typedef struct FCI_Int FCI_Int
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (cabinet)
 
static void set_error (FCI_Int *fci, int oper, int err)
 
static FCI_Intget_fci_ptr (HFCI hfci)
 
static cab_ULONG get_header_size (FCI_Int *fci)
 
static BOOL create_temp_file (FCI_Int *fci, struct temp_file *file)
 
static BOOL close_temp_file (FCI_Int *fci, struct temp_file *file)
 
static struct fileadd_file (FCI_Int *fci, const char *filename)
 
static struct filecopy_file (FCI_Int *fci, const struct file *orig)
 
static void free_file (FCI_Int *fci, struct file *file)
 
static BOOL add_data_block (FCI_Int *fci, PFNFCISTATUS status_callback)
 
static BOOL add_file_data (FCI_Int *fci, char *sourcefile, char *filename, BOOL execute, PFNFCIGETOPENINFO get_open_info, PFNFCISTATUS status_callback)
 
static void free_data_block (FCI_Int *fci, struct data_block *block)
 
static struct folderadd_folder (FCI_Int *fci)
 
static void free_folder (FCI_Int *fci, struct folder *folder)
 
static void reset_cabinet (FCI_Int *fci)
 
static cab_ULONG fci_get_checksum (const void *pv, UINT cb, cab_ULONG seed)
 
static BOOL copy_data_blocks (FCI_Int *fci, INT_PTR handle, cab_ULONG start_pos, struct temp_file *temp, PFNFCISTATUS status_callback)
 
static BOOL write_folders (FCI_Int *fci, INT_PTR handle, cab_ULONG header_size, PFNFCISTATUS status_callback)
 
static BOOL write_files (FCI_Int *fci, INT_PTR handle, PFNFCISTATUS status_callback)
 
static BOOL write_data_blocks (FCI_Int *fci, INT_PTR handle, PFNFCISTATUS status_callback)
 
static BOOL write_cabinet (FCI_Int *fci, PFNFCISTATUS status_callback)
 
static BOOL add_data_to_folder (FCI_Int *fci, struct folder *folder, cab_ULONG *payload, PFNFCISTATUS status_callback)
 
static BOOL add_files_to_folder (FCI_Int *fci, struct folder *folder, cab_ULONG payload)
 
static cab_UWORD compress_NONE (FCI_Int *fci)
 
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)
 
static BOOL fci_flush_folder (FCI_Int *p_fci_internal, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
 
static BOOL fci_flush_cabinet (FCI_Int *p_fci_internal, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
 
BOOL __cdecl FCIAddFile (HFCI hfci, char *pszSourceFile, char *pszFileName, BOOL fExecute, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis, PFNFCIGETOPENINFO pfnfcigoi, TCOMP typeCompress)
 
BOOL __cdecl FCIFlushFolder (HFCI hfci, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
 
BOOL __cdecl FCIFlushCabinet (HFCI hfci, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
 
BOOL __cdecl FCIDestroy (HFCI hfci)
 

Macro Definition Documentation

◆ fci_endian_ulong

#define fci_endian_ulong (   x)    (x)

Definition at line 60 of file fci.c.

◆ fci_endian_uword

#define fci_endian_uword (   x)    (x)

Definition at line 61 of file fci.c.

◆ FCI_INT_MAGIC

#define FCI_INT_MAGIC   0xfcfcfc05

Definition at line 194 of file fci.c.

Typedef Documentation

◆ FCI_Int

Function Documentation

◆ add_data_block()

static BOOL add_data_block ( FCI_Int fci,
PFNFCISTATUS  status_callback 
)
static

Definition at line 313 of file fci.c.

314{
315 int err;
316 struct data_block *block;
317
318 if (!fci->cdata_in) return TRUE;
319
320 if (fci->data.handle == -1 && !create_temp_file( fci, &fci->data )) return FALSE;
321
322 if (!(block = fci->alloc( sizeof(*block) )))
323 {
325 return FALSE;
326 }
327 block->uncompressed = fci->cdata_in;
328 block->compressed = fci->compress( fci );
329
330 if (fci->write( fci->data.handle, fci->data_out,
331 block->compressed, &err, fci->pv ) != block->compressed)
332 {
334 fci->free( block );
335 return FALSE;
336 }
337
338 fci->cdata_in = 0;
339 fci->pending_data_size += sizeof(CFDATA) + fci->ccab.cbReserveCFData + block->compressed;
340 fci->cCompressedBytesInFolder += block->compressed;
341 fci->cDataBlocks++;
342 list_add_tail( &fci->blocks_list, &block->entry );
343
344 if (status_callback( statusFile, block->compressed, block->uncompressed, fci->pv ) == -1)
345 {
346 set_error( fci, FCIERR_USER_ABORT, 0 );
347 return FALSE;
348 }
349 return TRUE;
350}
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static void set_error(FCI_Int *fci, int oper, int err)
Definition: fci.c:196
static BOOL create_temp_file(FCI_Int *fci, struct temp_file *file)
Definition: fci.c:233
#define statusFile
Definition: fci.h:219
@ FCIERR_TEMP_FILE
Definition: fci.h:121
@ FCIERR_USER_ABORT
Definition: fci.h:124
@ FCIERR_ALLOC_FAIL
Definition: fci.h:120
static void WINAPI status_callback(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID info, DWORD info_len)
Definition: ftp.c:948
#define err(...)
UINT cbReserveCFData
Definition: fci.h:150
Definition: fci.c:101
PFNFCIFREE free
Definition: fci.c:151
void * pv
Definition: fci.c:167
PFNFCIWRITE write
Definition: fci.c:154
unsigned char data_out[2 *CAB_BLOCKMAX]
Definition: fci.c:171
struct temp_file data
Definition: fci.c:179
cab_ULONG pending_data_size
Definition: fci.c:188
cab_UWORD cdata_in
Definition: fci.c:172
PFNFCIALLOC alloc
Definition: fci.c:150
CCAB ccab
Definition: fci.c:159
ULONG cCompressedBytesInFolder
Definition: fci.c:173
struct list blocks_list
Definition: fci.c:184
cab_UWORD(* compress)(struct FCI_Int *)
Definition: fci.c:191
cab_ULONG cDataBlocks
Definition: fci.c:176
static unsigned int block
Definition: xmlmemory.c:101

Referenced by add_file_data(), and fci_flush_folder().

◆ add_data_to_folder()

static BOOL add_data_to_folder ( FCI_Int fci,
struct folder folder,
cab_ULONG payload,
PFNFCISTATUS  status_callback 
)
static

Definition at line 762 of file fci.c.

764{
765 struct data_block *block, *new, *next;
766 BOOL split_block = FALSE;
767 cab_ULONG current_size, start_pos = 0;
768
769 *payload = 0;
770 current_size = get_header_size( fci ) + fci->folders_size +
772
773 /* move the temp file into the folder structure */
774 folder->data = fci->data;
775 fci->data.handle = -1;
776 fci->pending_data_size = 0;
777
779 {
780 /* No more CFDATA fits into the cabinet under construction */
781 /* So don't try to store more data into it */
782 if (fci->fNextCab && (fci->ccab.cb <= sizeof(CFDATA) + fci->ccab.cbReserveCFData +
783 current_size + sizeof(CFFOLDER) + fci->ccab.cbReserveCFFolder))
784 break;
785
786 if (!(new = fci->alloc( sizeof(*new) )))
787 {
789 return FALSE;
790 }
791 /* Is cabinet with new CFDATA too large? Then data block has to be split */
792 if( fci->fNextCab &&
793 (fci->ccab.cb < sizeof(CFDATA) + fci->ccab.cbReserveCFData +
794 block->compressed + current_size + sizeof(CFFOLDER) + fci->ccab.cbReserveCFFolder))
795 {
796 /* Modify the size of the compressed data to store only a part of the */
797 /* data block into the current cabinet. This is done to prevent */
798 /* that the maximum cabinet size will be exceeded. The remainder */
799 /* will be stored into the next following cabinet. */
800
801 new->compressed = fci->ccab.cb - (sizeof(CFDATA) + fci->ccab.cbReserveCFData + current_size +
802 sizeof(CFFOLDER) + fci->ccab.cbReserveCFFolder );
803 new->uncompressed = 0; /* on split blocks of data this is zero */
804 block->compressed -= new->compressed;
805 split_block = TRUE;
806 }
807 else
808 {
809 new->compressed = block->compressed;
810 new->uncompressed = block->uncompressed;
811 }
812
813 start_pos += new->compressed;
814 current_size += sizeof(CFDATA) + fci->ccab.cbReserveCFData + new->compressed;
815 fci->folders_data_size += sizeof(CFDATA) + fci->ccab.cbReserveCFData + new->compressed;
816 fci->statusFolderCopied += new->compressed;
817 (*payload) += new->uncompressed;
818
819 list_add_tail( &folder->blocks_list, &new->entry );
821
822 /* report status with pfnfcis about copied size of folder */
824 fci->statusFolderTotal, fci->pv ) == -1)
825 {
826 set_error( fci, FCIERR_USER_ABORT, 0 );
827 return FALSE;
828 }
829 if (split_block) break;
830 free_data_block( fci, block );
831 fci->cDataBlocks--;
832 }
833
834 if (list_empty( &fci->blocks_list )) return TRUE;
835 return copy_data_blocks( fci, folder->data.handle, start_pos, &fci->data, status_callback );
836}
static int list_empty(struct list_entry *head)
Definition: list.h:58
UINT32 cab_ULONG
Definition: mszip.h:27
static void free_data_block(FCI_Int *fci, struct data_block *block)
Definition: fci.c:390
static cab_ULONG get_header_size(FCI_Int *fci)
Definition: fci.c:217
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
#define statusFolder
Definition: fci.h:220
unsigned int BOOL
Definition: ntddk_ex.h:94
uint32_t entry
Definition: isohybrid.c:63
static unsigned __int64 next
Definition: rand_nt.c:6
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
UINT cbReserveCFFolder
Definition: fci.h:149
ULONG cb
Definition: fci.h:145
Definition: fci.c:82
cab_ULONG folders_size
Definition: fci.c:185
cab_ULONG files_size
Definition: fci.c:186
cab_ULONG statusFolderCopied
Definition: fci.c:164
cab_ULONG statusFolderTotal
Definition: fci.c:165
BOOL fNextCab
Definition: fci.c:162
cab_ULONG folders_data_size
Definition: fci.c:189
cab_ULONG placed_files_size
Definition: fci.c:187
Definition: fci.c:116
struct temp_file data
Definition: fci.c:120
struct list blocks_list
Definition: fci.c:119
cab_UWORD data_count
Definition: fci.c:122
#define new(TYPE, numElems)
Definition: treelist.c:54

Referenced by fci_flush_folder().

◆ add_file()

static struct file * add_file ( FCI_Int fci,
const char filename 
)
static

Definition at line 270 of file fci.c.

271{
272 unsigned int size = FIELD_OFFSET( struct file, name[strlen(filename) + 1] );
273 struct file *file = fci->alloc( size );
274
275 if (!file)
276 {
278 return NULL;
279 }
280 file->size = 0;
282 file->folder = fci->cFolders;
283 file->date = 0;
284 file->time = 0;
285 file->attribs = 0;
288 fci->files_size += sizeof(CFFILE) + strlen(filename) + 1;
289 return file;
290}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define NULL
Definition: types.h:112
#define CAB_BLOCKMAX
Definition: mszip.h:97
GLsizeiptr size
Definition: glext.h:5919
const char * filename
Definition: ioapi.h:137
Definition: fci.c:89
struct list files_list
Definition: fci.c:183
cab_UWORD cFolders
Definition: fci.c:174
Definition: fci.c:127
cab_ULONG offset
Definition: fci.c:130
cab_UWORD folder
Definition: fci.c:131
cab_UWORD date
Definition: fci.c:132
struct list entry
Definition: fci.c:128
cab_UWORD attribs
Definition: fci.c:134
cab_ULONG size
Definition: fci.c:129
cab_UWORD time
Definition: fci.c:133
char name[1]
Definition: fci.c:135
Definition: name.c:39
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255

Referenced by add_file_data().

◆ add_file_data()

static BOOL add_file_data ( FCI_Int fci,
char sourcefile,
char filename,
BOOL  execute,
PFNFCIGETOPENINFO  get_open_info,
PFNFCISTATUS  status_callback 
)
static

Definition at line 353 of file fci.c.

355{
356 int err, len;
358 struct file *file;
359
360 if (!(file = add_file( fci, filename ))) return FALSE;
361
362 handle = get_open_info( sourcefile, &file->date, &file->time, &file->attribs, &err, fci->pv );
363 if (handle == -1)
364 {
365 free_file( fci, file );
367 return FALSE;
368 }
369 if (execute) file->attribs |= _A_EXEC;
370
371 for (;;)
372 {
373 len = fci->read( handle, fci->data_in + fci->cdata_in,
374 CAB_BLOCKMAX - fci->cdata_in, &err, fci->pv );
375 if (!len) break;
376
377 if (len == -1)
378 {
380 return FALSE;
381 }
382 file->size += len;
383 fci->cdata_in += len;
384 if (fci->cdata_in == CAB_BLOCKMAX && !add_data_block( fci, status_callback )) return FALSE;
385 }
386 fci->close( handle, &err, fci->pv );
387 return TRUE;
388}
static BOOL add_data_block(FCI_Int *fci, PFNFCISTATUS status_callback)
Definition: fci.c:313
static struct file * add_file(FCI_Int *fci, const char *filename)
Definition: fci.c:270
static void free_file(FCI_Int *fci, struct file *file)
Definition: fci.c:306
#define _A_EXEC
Definition: fci.h:135
@ FCIERR_OPEN_SRC
Definition: fci.h:118
@ FCIERR_READ_SRC
Definition: fci.h:119
GLenum GLsizei len
Definition: glext.h:6722
static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime, USHORT *pattribs, int *err, void *pv)
Definition: files.c:304
void execute(char *message, int(*func)(int))
Definition: noexecute.c:13
PFNFCIREAD read
Definition: fci.c:153
PFNFCICLOSE close
Definition: fci.c:155
unsigned char data_in[CAB_BLOCKMAX]
Definition: fci.c:170
int32_t INT_PTR
Definition: typedefs.h:64

Referenced by FCIAddFile().

◆ add_files_to_folder()

static BOOL add_files_to_folder ( FCI_Int fci,
struct folder folder,
cab_ULONG  payload 
)
static

Definition at line 839 of file fci.c.

840{
841 cab_ULONG sizeOfFiles = 0, sizeOfFilesPrev;
842 cab_ULONG cbFileRemainder = 0;
843 struct file *file, *next;
844
846 {
847 cab_ULONG size = sizeof(CFFILE) + strlen(file->name) + 1;
848
849 /* fnfilfnfildest: placed file on cabinet */
850 fci->fileplaced( &fci->ccab, file->name, file->size,
852
853 sizeOfFilesPrev = sizeOfFiles;
854 /* set complete size of all processed files */
856 {
857 sizeOfFiles += fci->cbFileRemainder;
858 fci->cbFileRemainder = 0;
859 }
860 else sizeOfFiles += file->size;
861
862 /* check if spanned file fits into this cabinet folder */
863 if (sizeOfFiles > payload)
864 {
867 else
869 }
870
873 fci->placed_files_size += size;
874 fci->cFiles++;
875
876 /* This is only true for files which will be written into the */
877 /* next cabinet of the spanning folder */
878 if (sizeOfFiles > payload)
879 {
880 /* add a copy back onto the list */
881 if (!(file = copy_file( fci, file ))) return FALSE;
882 list_add_before( &next->entry, &file->entry );
883
884 /* Files which data will be partially written into the current cabinet */
886 {
887 if (sizeOfFilesPrev <= payload)
888 {
889 /* The size of the uncompressed, data of a spanning file in a */
890 /* spanning data */
891 cbFileRemainder = sizeOfFiles - payload;
892 }
894 }
895 else file->folder = 0;
896 }
897 else
898 {
899 fci->files_size -= size;
900 }
901 }
902 fci->cbFileRemainder = cbFileRemainder;
903 return TRUE;
904}
static void list_remove(struct list_entry *entry)
Definition: list.h:90
#define cffileCONTINUED_FROM_PREV
Definition: cabinet.h:108
#define cffileCONTINUED_PREV_AND_NEXT
Definition: cabinet.h:110
#define cffileCONTINUED_TO_NEXT
Definition: cabinet.h:109
static struct file * copy_file(FCI_Int *fci, const struct file *orig)
Definition: fci.c:292
__WINE_SERVER_LIST_INLINE void list_add_before(struct list *elem, struct list *to_add)
Definition: list.h:87
cab_UWORD cFiles
Definition: fci.c:175
cab_ULONG cbFileRemainder
Definition: fci.c:177
PFNFCIFILEPLACED fileplaced
Definition: fci.c:149
struct list files_list
Definition: fci.c:118

Referenced by fci_flush_folder().

◆ add_folder()

static struct folder * add_folder ( FCI_Int fci)
static

Definition at line 396 of file fci.c.

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}
static void list_init(struct list_entry *head)
Definition: list.h:51
TCOMP compression
Definition: fci.c:190
struct list folders_list
Definition: fci.c:182
TCOMP compression
Definition: fci.c:123
struct list entry
Definition: fci.c:117
cab_ULONG data_start
Definition: fci.c:121

Referenced by fci_flush_folder().

◆ close_temp_file()

static BOOL close_temp_file ( FCI_Int fci,
struct temp_file file 
)
static

Definition at line 251 of file fci.c.

252{
253 int err;
254
255 if (file->handle == -1) return TRUE;
256 if (fci->close( file->handle, &err, fci->pv ) == -1)
257 {
259 return FALSE;
260 }
261 file->handle = -1;
262 if (fci->delete( file->name, &err, fci->pv ) == -1)
263 {
265 return FALSE;
266 }
267 return TRUE;
268}
PFNFCIDELETE delete
Definition: fci.c:157

Referenced by copy_data_blocks(), FCIDestroy(), and free_folder().

◆ compress_NONE()

static cab_UWORD compress_NONE ( FCI_Int fci)
static

Definition at line 906 of file fci.c.

907{
908 memcpy( fci->data_out, fci->data_in, fci->cdata_in );
909 return fci->cdata_in;
910}
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878

Referenced by FCIAddFile(), and FCICreate().

◆ copy_data_blocks()

static BOOL copy_data_blocks ( FCI_Int fci,
INT_PTR  handle,
cab_ULONG  start_pos,
struct temp_file temp,
PFNFCISTATUS  status_callback 
)
static

Definition at line 485 of file fci.c.

487{
488 struct data_block *block;
489 int err;
490
491 if (fci->seek( handle, start_pos, SEEK_SET, &err, fci->pv ) != start_pos)
492 {
494 return FALSE;
495 }
496 if (!create_temp_file( fci, temp )) return FALSE;
497
499 {
500 if (fci->read( handle, fci->data_out, block->compressed,
501 &err, fci->pv ) != block->compressed)
502 {
503 close_temp_file( fci, temp );
505 return FALSE;
506 }
507 if (fci->write( temp->handle, fci->data_out, block->compressed,
508 &err, fci->pv ) != block->compressed)
509 {
510 close_temp_file( fci, temp );
512 return FALSE;
513 }
514 fci->pending_data_size += sizeof(CFDATA) + fci->ccab.cbReserveCFData + block->compressed;
515 fci->statusFolderCopied += block->compressed;
516
518 fci->statusFolderTotal, fci->pv) == -1)
519 {
520 close_temp_file( fci, temp );
521 set_error( fci, FCIERR_USER_ABORT, 0 );
522 return FALSE;
523 }
524 }
525 return TRUE;
526}
static BOOL close_temp_file(FCI_Int *fci, struct temp_file *file)
Definition: fci.c:251
#define SEEK_SET
Definition: jmemansi.c:26
if(dx< 0)
Definition: linetemp.h:194
static calc_node_t temp
Definition: rpn_ieee.c:38
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
PFNFCISEEK seek
Definition: fci.c:156

Referenced by add_data_to_folder().

◆ copy_file()

static struct file * copy_file ( FCI_Int fci,
const struct file orig 
)
static

Definition at line 292 of file fci.c.

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}

Referenced by add_files_to_folder().

◆ create_temp_file()

static BOOL create_temp_file ( FCI_Int fci,
struct temp_file file 
)
static

Definition at line 233 of file fci.c.

234{
235 int err;
236
237 if (!fci->gettemp( file->name, CB_MAX_FILENAME, fci->pv ))
238 {
240 return FALSE;
241 }
242 if ((file->handle = fci->open( file->name, _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
243 _S_IREAD | _S_IWRITE, &err, fci->pv )) == -1)
244 {
246 return FALSE;
247 }
248 return TRUE;
249}
#define _O_RDWR
Definition: cabinet.h:39
#define _O_BINARY
Definition: cabinet.h:51
#define _O_CREAT
Definition: cabinet.h:46
#define _O_EXCL
Definition: cabinet.h:48
#define _S_IWRITE
Definition: cabinet.h:33
#define _S_IREAD
Definition: cabinet.h:34
#define CB_MAX_FILENAME
Definition: fci.h:54
PFNFCIOPEN open
Definition: fci.c:152
PFNFCIGETTEMPFILE gettemp
Definition: fci.c:158
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985

Referenced by add_data_block(), and copy_data_blocks().

◆ fci_flush_cabinet()

static BOOL fci_flush_cabinet ( FCI_Int p_fci_internal,
BOOL  fGetNextCab,
PFNFCIGETNEXTCABINET  pfnfcignc,
PFNFCISTATUS  pfnfcis 
)
static

Definition at line 1231 of file fci.c.

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 */
static BOOL fci_flush_folder(FCI_Int *p_fci_internal, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1071
static BOOL fci_flush_cabinet(FCI_Int *p_fci_internal, BOOL fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1231
static BOOL write_cabinet(FCI_Int *fci, PFNFCISTATUS status_callback)
Definition: fci.c:649
#define CB_MAX_DISK_NAME
Definition: fci.h:57
#define CB_MAX_CABINET_NAME
Definition: fci.h:55
@ FCIERR_NONE
Definition: fci.h:117
ULONG cbFolderThresh
Definition: fci.h:146
int iCab
Definition: fci.h:151
char szDisk[CB_MAX_DISK_NAME]
Definition: fci.h:159
char szCab[CB_MAX_CABINET_NAME]
Definition: fci.h:160
char szPrevDisk[CB_MAX_DISK_NAME]
Definition: fci.c:169
BOOL fGetNextCabInVain
Definition: fci.c:166
cab_ULONG estimatedCabinetSize
Definition: fci.c:181
BOOL fPrevCab
Definition: fci.c:161
BOOL fSplitFolder
Definition: fci.c:163
BOOL fNewPrevious
Definition: fci.c:180
PCCAB pccab
Definition: fci.c:160
char szPrevCab[CB_MAX_CABINET_NAME]
Definition: fci.c:168
#define ERROR_GEN_FAILURE
Definition: winerror.h:134

Referenced by fci_flush_cabinet(), FCIAddFile(), and FCIFlushCabinet().

◆ fci_flush_folder()

static BOOL fci_flush_folder ( FCI_Int p_fci_internal,
BOOL  fGetNextCab,
PFNFCIGETNEXTCABINET  pfnfcignc,
PFNFCISTATUS  pfnfcis 
)
static

Definition at line 1071 of file fci.c.

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}
static struct folder * add_folder(FCI_Int *fci)
Definition: fci.c:396
static BOOL add_files_to_folder(FCI_Int *fci, struct folder *folder, cab_ULONG payload)
Definition: fci.c:839
static BOOL add_data_to_folder(FCI_Int *fci, struct folder *folder, cab_ULONG *payload, PFNFCISTATUS status_callback)
Definition: fci.c:762
#define ERROR_BAD_ARGUMENTS
Definition: winerror.h:232

Referenced by fci_flush_cabinet(), and FCIFlushFolder().

◆ fci_get_checksum()

static cab_ULONG fci_get_checksum ( const void pv,
UINT  cb,
cab_ULONG  seed 
)
static

Definition at line 446 of file fci.c.

447{
449 cab_ULONG ul;
450 int cUlong;
451 const BYTE *pb;
452
453 csum = seed;
454 cUlong = cb / 4;
455 pb = pv;
456
457 while (cUlong-- > 0) {
458 ul = *pb++;
459 ul |= (((cab_ULONG)(*pb++)) << 8);
460 ul |= (((cab_ULONG)(*pb++)) << 16);
461 ul |= (((cab_ULONG)(*pb++)) << 24);
462 csum ^= ul;
463 }
464
465 ul = 0;
466 switch (cb % 4) {
467 case 3:
468 ul |= (((ULONG)(*pb++)) << 16);
469 /* fall through */
470 case 2:
471 ul |= (((ULONG)(*pb++)) << 8);
472 /* fall through */
473 case 1:
474 ul |= *pb;
475 /* fall through */
476 default:
477 break;
478 }
479 csum ^= ul;
480
481 return csum;
482}
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
Definition: ffs.h:52
uint32_t ULONG
Definition: typedefs.h:59
unsigned char BYTE
Definition: xxhash.c:193

Referenced by write_data_blocks().

◆ FCIAddFile()

BOOL __cdecl FCIAddFile ( HFCI  hfci,
char pszSourceFile,
char pszFileName,
BOOL  fExecute,
PFNFCIGETNEXTCABINET  pfnfcignc,
PFNFCISTATUS  pfnfcis,
PFNFCIGETOPENINFO  pfnfcigoi,
TCOMP  typeCompress 
)

Definition at line 1397 of file fci.c.

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 */
#define FIXME(fmt,...)
Definition: precomp.h:53
static BOOL add_file_data(FCI_Int *fci, char *sourcefile, char *filename, BOOL execute, PFNFCIGETOPENINFO get_open_info, PFNFCISTATUS status_callback)
Definition: fci.c:353
static cab_UWORD compress_NONE(FCI_Int *fci)
Definition: fci.c:906
static FCI_Int * get_fci_ptr(HFCI hfci)
Definition: fci.c:204
BOOL __cdecl FCIFlushFolder(HFCI hfci, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis)
Definition: fci.c:1631
#define tcompTYPE_NONE
Definition: fci.h:64
#define tcompTYPE_MSZIP
Definition: fci.h:65
Definition: fci.c:146
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:44

Referenced by add_file().

◆ FCICreate()

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 at line 998 of file fci.c.

1012{
1013 FCI_Int *p_fci_internal;
1014
1015 if (!perf) {
1017 return NULL;
1018 }
1019 if ((!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||
1020 (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||
1021 (!pfnfcigtf) || (!pccab)) {
1022 perf->erfOper = FCIERR_NONE;
1024 perf->fError = TRUE;
1025
1027 return NULL;
1028 }
1029
1030 if (!((p_fci_internal = pfnalloc(sizeof(FCI_Int))))) {
1031 perf->erfOper = FCIERR_ALLOC_FAIL;
1033 perf->fError = TRUE;
1034
1036 return NULL;
1037 }
1038
1039 memset(p_fci_internal, 0, sizeof(FCI_Int));
1040 p_fci_internal->magic = FCI_INT_MAGIC;
1041 p_fci_internal->perf = perf;
1042 p_fci_internal->fileplaced = pfnfiledest;
1043 p_fci_internal->alloc = pfnalloc;
1044 p_fci_internal->free = pfnfree;
1045 p_fci_internal->open = pfnopen;
1046 p_fci_internal->read = pfnread;
1047 p_fci_internal->write = pfnwrite;
1048 p_fci_internal->close = pfnclose;
1049 p_fci_internal->seek = pfnseek;
1050 p_fci_internal->delete = pfndelete;
1051 p_fci_internal->gettemp = pfnfcigtf;
1052 p_fci_internal->ccab = *pccab;
1053 p_fci_internal->pccab = pccab;
1054 p_fci_internal->pv = pv;
1055 p_fci_internal->data.handle = -1;
1056 p_fci_internal->compress = compress_NONE;
1057
1058 list_init( &p_fci_internal->folders_list );
1059 list_init( &p_fci_internal->files_list );
1060 list_init( &p_fci_internal->blocks_list );
1061
1062 memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
1063 memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);
1064
1065 return (HFCI)p_fci_internal;
1066}
#define SetLastError(x)
Definition: compat.h:752
#define FCI_INT_MAGIC
Definition: fci.c:194
#define memset(x, y, z)
Definition: compat.h:39
int erfType
Definition: fci.h:46
BOOL fError
Definition: fci.h:47
int erfOper
Definition: fci.h:45
PERF perf
Definition: fci.c:148
unsigned int magic
Definition: fci.c:147

Referenced by create_cab_file(), create_cc_test_files(), and test_FDICopy().

◆ FCIDestroy()

BOOL __cdecl FCIDestroy ( HFCI  hfci)

Definition at line 1709 of file fci.c.

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 void free_folder(FCI_Int *fci, struct folder *folder)
Definition: fci.c:417

Referenced by create_cab_file(), create_cc_test_files(), and test_FDICopy().

◆ FCIFlushCabinet()

BOOL __cdecl FCIFlushCabinet ( HFCI  hfci,
BOOL  fGetNextCab,
PFNFCIGETNEXTCABINET  pfnfcignc,
PFNFCISTATUS  pfnfcis 
)

Definition at line 1675 of file fci.c.

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}

Referenced by create_cab_file(), create_cc_test_files(), and test_FDICopy().

◆ FCIFlushFolder()

BOOL __cdecl FCIFlushFolder ( HFCI  hfci,
PFNFCIGETNEXTCABINET  pfnfcignc,
PFNFCISTATUS  pfnfcis 
)

Definition at line 1631 of file fci.c.

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}

Referenced by FCIAddFile().

◆ free_data_block()

static void free_data_block ( FCI_Int fci,
struct data_block block 
)
static

Definition at line 390 of file fci.c.

391{
392 list_remove( &block->entry );
393 fci->free( block );
394}

Referenced by add_data_to_folder(), FCIDestroy(), and free_folder().

◆ free_file()

static void free_file ( FCI_Int fci,
struct file file 
)
static

Definition at line 306 of file fci.c.

307{
309 fci->free( file );
310}

Referenced by add_file_data(), FCIDestroy(), and free_folder().

◆ free_folder()

static void free_folder ( FCI_Int fci,
struct folder folder 
)
static

Definition at line 417 of file fci.c.

418{
419 struct file *file, *file_next;
420 struct data_block *block, *block_next;
421
422 LIST_FOR_EACH_ENTRY_SAFE( file, file_next, &folder->files_list, struct file, entry )
423 free_file( fci, file );
425 free_data_block( fci, block );
426 close_temp_file( fci, &folder->data );
428 fci->free( folder );
429}

Referenced by FCIDestroy(), and reset_cabinet().

◆ get_fci_ptr()

static FCI_Int * get_fci_ptr ( HFCI  hfci)
static

Definition at line 204 of file fci.c.

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}
#define ERROR_INVALID_HANDLE
Definition: compat.h:98

Referenced by FCIAddFile(), FCIDestroy(), FCIFlushCabinet(), and FCIFlushFolder().

◆ get_header_size()

static cab_ULONG get_header_size ( FCI_Int fci)
static

Definition at line 217 of file fci.c.

218{
220
222 ret += 4;
223
224 if (fci->fPrevCab)
225 ret += strlen( fci->szPrevCab ) + 1 + strlen( fci->szPrevDisk ) + 1;
226
227 if (fci->fNextCab)
228 ret += strlen( fci->pccab->szCab ) + 1 + strlen( fci->pccab->szDisk ) + 1;
229
230 return ret;
231}
UINT cbReserveCFHeader
Definition: fci.h:148
Definition: fci.c:65
int ret

Referenced by add_data_to_folder(), fci_flush_cabinet(), fci_flush_folder(), FCIAddFile(), and write_cabinet().

◆ reset_cabinet()

static void reset_cabinet ( FCI_Int fci)
static

Definition at line 432 of file fci.c.

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}

Referenced by write_cabinet().

◆ set_error()

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( cabinet  )

◆ write_cabinet()

static BOOL write_cabinet ( FCI_Int fci,
PFNFCISTATUS  status_callback 
)
static

Definition at line 649 of file fci.c.

650{
652 int err;
653 char *ptr;
655 CFHEADER *cfheader = (CFHEADER *)fci->data_out;
656 cab_UWORD flags = 0;
657 cab_ULONG header_size = get_header_size( fci );
658 cab_ULONG total_size = header_size + fci->folders_size +
660
661 assert( header_size <= sizeof(fci->data_out) );
662 memset( cfheader, 0, header_size );
663
664 if (fci->fPrevCab) flags |= cfheadPREV_CABINET;
665 if (fci->fNextCab) flags |= cfheadNEXT_CABINET;
668
669 memcpy( cfheader->signature, "!CAB", 4 );
670 cfheader->cbCabinet = fci_endian_ulong( total_size );
671 cfheader->coffFiles = fci_endian_ulong( header_size + fci->folders_size );
672 cfheader->versionMinor = 3;
673 cfheader->versionMajor = 1;
674 cfheader->cFolders = fci_endian_uword( fci->cFolders );
675 cfheader->cFiles = fci_endian_uword( fci->cFiles );
676 cfheader->flags = fci_endian_uword( flags );
677 cfheader->setID = fci_endian_uword( fci->ccab.setID );
678 cfheader->iCabinet = fci_endian_uword( fci->ccab.iCab );
679 ptr = (char *)(cfheader + 1);
680
682 {
683 struct
684 {
685 cab_UWORD cbCFHeader;
686 cab_UBYTE cbCFFolder;
687 cab_UBYTE cbCFData;
688 } *reserve = (void *)ptr;
689
690 reserve->cbCFHeader = fci_endian_uword( fci->ccab.cbReserveCFHeader );
691 reserve->cbCFFolder = fci->ccab.cbReserveCFFolder;
692 reserve->cbCFData = fci->ccab.cbReserveCFData;
693 ptr = (char *)(reserve + 1);
694 }
695 ptr += fci->ccab.cbReserveCFHeader;
696
698 {
699 strcpy( ptr, fci->szPrevCab );
700 ptr += strlen( ptr ) + 1;
701 strcpy( ptr, fci->szPrevDisk );
702 ptr += strlen( ptr ) + 1;
703 }
704
706 {
707 strcpy( ptr, fci->pccab->szCab );
708 ptr += strlen( ptr ) + 1;
709 strcpy( ptr, fci->pccab->szDisk );
710 ptr += strlen( ptr ) + 1;
711 }
712
713 assert( ptr - (char *)cfheader == header_size );
714
715 strcpy( filename, fci->ccab.szCabPath );
716 strcat( filename, fci->ccab.szCab );
717
719 _S_IREAD | _S_IWRITE, &err, fci->pv )) == -1)
720 {
722 return FALSE;
723 }
724
725 if (fci->write( handle, cfheader, header_size, &err, fci->pv ) != header_size)
726 {
728 goto failed;
729 }
730
731 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
732 header_size += fci->placed_files_size + fci->folders_size;
733 if (!write_folders( fci, handle, header_size, status_callback )) goto failed;
734 if (!write_files( fci, handle, status_callback )) goto failed;
735 if (!write_data_blocks( fci, handle, status_callback )) goto failed;
736
737 /* update the signature */
738 if (fci->seek( handle, 0, SEEK_SET, &err, fci->pv ) != 0 )
739 {
741 goto failed;
742 }
743 memcpy( cfheader->signature, "MSCF", 4 );
744 if (fci->write( handle, cfheader->signature, 4, &err, fci->pv ) != 4)
745 {
747 goto failed;
748 }
749 fci->close( handle, &err, fci->pv );
750
751 reset_cabinet( fci );
752 status_callback( statusCabinet, fci->estimatedCabinetSize, total_size, fci->pv );
753 return TRUE;
754
755failed:
756 fci->close( handle, &err, fci->pv );
757 fci->delete( filename, &err, fci->pv );
758 return FALSE;
759}
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
Definition: mesh.c:5392
UINT16 cab_UWORD
Definition: mszip.h:26
unsigned char cab_UBYTE
Definition: mszip.h:25
#define cfheadRESERVE_PRESENT
Definition: cabinet.h:107
#define _O_TRUNC
Definition: cabinet.h:47
#define cfheadNEXT_CABINET
Definition: cabinet.h:106
#define cfheadPREV_CABINET
Definition: cabinet.h:105
#define assert(x)
Definition: debug.h:53
static BOOL write_files(FCI_Int *fci, INT_PTR handle, PFNFCISTATUS status_callback)
Definition: fci.c:554
static void reset_cabinet(FCI_Int *fci)
Definition: fci.c:432
static BOOL write_folders(FCI_Int *fci, INT_PTR handle, cab_ULONG header_size, PFNFCISTATUS status_callback)
Definition: fci.c:529
static BOOL write_data_blocks(FCI_Int *fci, INT_PTR handle, PFNFCISTATUS status_callback)
Definition: fci.c:599
#define fci_endian_uword(x)
Definition: fci.c:61
#define fci_endian_ulong(x)
Definition: fci.c:60
#define CB_MAX_CAB_PATH
Definition: fci.h:56
#define statusCabinet
Definition: fci.h:221
@ FCIERR_CAB_FILE
Definition: fci.h:123
GLbitfield flags
Definition: glext.h:7161
static PVOID ptr
Definition: dispmode.c:27
USHORT setID
Definition: fci.h:157
char szCabPath[CB_MAX_CAB_PATH]
Definition: fci.h:161
cab_UBYTE versionMajor
Definition: fci.c:73
cab_UBYTE versionMinor
Definition: fci.c:72
cab_UWORD flags
Definition: fci.c:76
cab_ULONG coffFiles
Definition: fci.c:70
cab_UWORD cFolders
Definition: fci.c:74
cab_ULONG cbCabinet
Definition: fci.c:68
cab_UWORD cFiles
Definition: fci.c:75
cab_UWORD setID
Definition: fci.c:77
cab_UWORD iCabinet
Definition: fci.c:78
cab_UBYTE signature[4]
Definition: fci.c:66

Referenced by fci_flush_cabinet().

◆ write_data_blocks()

static BOOL write_data_blocks ( FCI_Int fci,
INT_PTR  handle,
PFNFCISTATUS  status_callback 
)
static

Definition at line 599 of file fci.c.

600{
601 struct folder *folder;
602 struct data_block *block;
603 int err, len;
604 CFDATA *cfdata;
605 void *data;
606 cab_UWORD header_size;
607
608 header_size = sizeof(CFDATA) + fci->ccab.cbReserveCFData;
609 cfdata = (CFDATA *)fci->data_out;
610 memset( cfdata, 0, header_size );
611 data = (char *)cfdata + header_size;
612
614 {
615 if (fci->seek( folder->data.handle, 0, SEEK_SET, &err, fci->pv ) != 0)
616 {
618 return FALSE;
619 }
621 {
622 len = fci->read( folder->data.handle, data, block->compressed, &err, fci->pv );
623 if (len != block->compressed) return FALSE;
624
625 cfdata->cbData = fci_endian_uword( block->compressed );
626 cfdata->cbUncomp = fci_endian_uword( block->uncompressed );
627 cfdata->csum = fci_endian_ulong( fci_get_checksum( &cfdata->cbData,
628 header_size - FIELD_OFFSET(CFDATA, cbData),
629 fci_get_checksum( data, len, 0 )));
630
631 fci->statusFolderCopied += len;
632 len += header_size;
633 if (fci->write( handle, fci->data_out, len, &err, fci->pv ) != len)
634 {
636 return FALSE;
637 }
639 {
640 set_error( fci, FCIERR_USER_ABORT, 0 );
641 return FALSE;
642 }
643 }
644 }
645 return TRUE;
646}
static cab_ULONG fci_get_checksum(const void *pv, UINT cb, cab_ULONG seed)
Definition: fci.c:446
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
cab_ULONG csum
Definition: fci.c:102
cab_UWORD cbUncomp
Definition: fci.c:104
cab_UWORD cbData
Definition: fci.c:103

Referenced by write_cabinet().

◆ write_files()

static BOOL write_files ( FCI_Int fci,
INT_PTR  handle,
PFNFCISTATUS  status_callback 
)
static

Definition at line 554 of file fci.c.

555{
557 struct folder *folder;
558 struct file *file;
559 int err;
560 CFFILE *cffile = (CFFILE *)fci->data_out;
561
563 {
565 {
566 cffile->cbFile = fci_endian_ulong( file->size );
568 cffile->iFolder = fci_endian_uword( file->folder );
569 cffile->date = fci_endian_uword( file->date );
570 cffile->time = fci_endian_uword( file->time );
571 cffile->attribs = fci_endian_uword( file->attribs );
572 lstrcpynA( (char *)(cffile + 1), file->name, CB_MAX_FILENAME );
573 file_size = sizeof(CFFILE) + strlen( (char *)(cffile + 1) ) + 1;
574 if (fci->write( handle, cffile, file_size, &err, fci->pv ) != file_size)
575 {
577 return FALSE;
578 }
579 if (!fci->fSplitFolder)
580 {
581 fci->statusFolderCopied = 0;
582 /* TODO TEST THIS further */
584 }
586 /* report status about copied size of folder */
588 fci->statusFolderTotal, fci->pv ) == -1)
589 {
590 set_error( fci, FCIERR_USER_ABORT, 0 );
591 return FALSE;
592 }
593 }
594 }
595 return TRUE;
596}
#define lstrcpynA
Definition: compat.h:751
static unsigned int file_size
Definition: regtests2xml.c:47
cab_UWORD time
Definition: fci.c:95
cab_ULONG uoffFolderStart
Definition: fci.c:91
cab_ULONG cbFile
Definition: fci.c:90
cab_UWORD date
Definition: fci.c:94
cab_UWORD iFolder
Definition: fci.c:92
cab_UWORD attribs
Definition: fci.c:96

Referenced by write_cabinet().

◆ write_folders()

static BOOL write_folders ( FCI_Int fci,
INT_PTR  handle,
cab_ULONG  header_size,
PFNFCISTATUS  status_callback 
)
static

Definition at line 529 of file fci.c.

530{
531 struct folder *folder;
532 int err;
533 CFFOLDER *cffolder = (CFFOLDER *)fci->data_out;
534 cab_ULONG folder_size = sizeof(CFFOLDER) + fci->ccab.cbReserveCFFolder;
535
536 memset( cffolder, 0, folder_size );
537
538 /* write the folders */
540 {
541 cffolder->coffCabStart = fci_endian_ulong( folder->data_start + header_size );
544 if (fci->write( handle, cffolder, folder_size, &err, fci->pv ) != folder_size)
545 {
547 return FALSE;
548 }
549 }
550 return TRUE;
551}
cab_UWORD cCFData
Definition: fci.c:84
cab_ULONG coffCabStart
Definition: fci.c:83
cab_UWORD typeCompress
Definition: fci.c:85

Referenced by write_cabinet().