Merge r55012 adding Wine3D control panel as per Amine's request.
[reactos.git] / dll / win32 / cabinet / fci.c
1 /*
2 * File Compression Interface
3 *
4 * Copyright 2002 Patrik Stridvall
5 * Copyright 2005 Gerold Jens Wucherpfennig
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 /*
23
24 There is still some work to be done:
25
26 - no real compression yet
27 - unknown behaviour if files>=2GB or cabinet >=4GB
28 - check if the maximum size for a cabinet is too small to store any data
29 - call pfnfcignc on exactly the same position as MS FCIAddFile in every case
30 - probably check err
31
32 */
33
34
35
36 #include "config.h"
37
38 #include <stdarg.h>
39 #include <stdio.h>
40 #include <string.h>
41
42 #include "windef.h"
43 #include "winbase.h"
44 #include "winerror.h"
45 #include "winternl.h"
46 #include "fci.h"
47 #include "cabinet.h"
48 #include "wine/debug.h"
49
50
51 #ifdef WORDS_BIGENDIAN
52 #define fci_endian_ulong(x) RtlUlongByteSwap(x)
53 #define fci_endian_uword(x) RtlUshortByteSwap(x)
54 #else
55 #define fci_endian_ulong(x) (x)
56 #define fci_endian_uword(x) (x)
57 #endif
58
59
60 #define fci_set_error(A,B,C) do { \
61 p_fci_internal->perf->erfOper = A; \
62 p_fci_internal->perf->erfType = B; \
63 p_fci_internal->perf->fError = C; \
64 if (B) SetLastError(B); } while(0)
65
66
67 typedef struct {
68 cab_UBYTE signature[4]; /* !CAB for unfinished cabinets else MSCF */
69 cab_ULONG reserved1;
70 cab_ULONG cbCabinet; /* size of the cabinet file in bytes*/
71 cab_ULONG reserved2;
72 cab_ULONG coffFiles; /* offset to first CFFILE section */
73 cab_ULONG reserved3;
74 cab_UBYTE versionMinor; /* 3 */
75 cab_UBYTE versionMajor; /* 1 */
76 cab_UWORD cFolders; /* number of CFFOLDER entries in the cabinet*/
77 cab_UWORD cFiles; /* number of CFFILE entries in the cabinet*/
78 cab_UWORD flags; /* 1=prev cab, 2=next cabinet, 4=reserved sections*/
79 cab_UWORD setID; /* identification number of all cabinets in a set*/
80 cab_UWORD iCabinet; /* number of the cabinet in a set */
81 /* additional area if "flags" were set*/
82 } CFHEADER; /* minimum 36 bytes */
83
84 typedef struct {
85 cab_ULONG coffCabStart; /* offset to the folder's first CFDATA section */
86 cab_UWORD cCFData; /* number of this folder's CFDATA sections */
87 cab_UWORD typeCompress; /* compression type of data in CFDATA section*/
88 /* additional area if reserve flag was set */
89 } CFFOLDER; /* minimum 8 bytes */
90
91 typedef struct {
92 cab_ULONG cbFile; /* size of the uncompressed file in bytes */
93 cab_ULONG uoffFolderStart; /* offset of the uncompressed file in the folder */
94 cab_UWORD iFolder; /* number of folder in the cabinet 0=first */
95 /* for special values see below this structure*/
96 cab_UWORD date; /* last modification date*/
97 cab_UWORD time; /* last modification time*/
98 cab_UWORD attribs; /* DOS fat attributes and UTF indicator */
99 /* ... and a C string with the name of the file */
100 } CFFILE; /* 16 bytes + name of file */
101
102
103 typedef struct {
104 cab_ULONG csum; /* checksum of this entry*/
105 cab_UWORD cbData; /* number of compressed bytes */
106 cab_UWORD cbUncomp; /* number of bytes when data is uncompressed */
107 /* optional reserved area */
108 /* compressed data */
109 } CFDATA;
110
111
112 /***********************************************************************
113 * FCICreate (CABINET.10)
114 *
115 * FCICreate is provided with several callbacks and
116 * returns a handle which can be used to create cabinet files.
117 *
118 * PARAMS
119 * perf [IO] A pointer to an ERF structure. When FCICreate
120 * returns an error condition, error information may
121 * be found here as well as from GetLastError.
122 * pfnfiledest [I] A pointer to a function which is called when a file
123 * is placed. Only useful for subsequent cabinet files.
124 * pfnalloc [I] A pointer to a function which allocates ram. Uses
125 * the same interface as malloc.
126 * pfnfree [I] A pointer to a function which frees ram. Uses the
127 * same interface as free.
128 * pfnopen [I] A pointer to a function which opens a file. Uses
129 * the same interface as _open.
130 * pfnread [I] A pointer to a function which reads from a file into
131 * a caller-provided buffer. Uses the same interface
132 * as _read.
133 * pfnwrite [I] A pointer to a function which writes to a file from
134 * a caller-provided buffer. Uses the same interface
135 * as _write.
136 * pfnclose [I] A pointer to a function which closes a file handle.
137 * Uses the same interface as _close.
138 * pfnseek [I] A pointer to a function which seeks in a file.
139 * Uses the same interface as _lseek.
140 * pfndelete [I] A pointer to a function which deletes a file.
141 * pfnfcigtf [I] A pointer to a function which gets the name of a
142 * temporary file.
143 * pccab [I] A pointer to an initialized CCAB structure.
144 * pv [I] A pointer to an application-defined notification
145 * function which will be passed to other FCI functions
146 * as a parameter.
147 *
148 * RETURNS
149 * On success, returns an FCI handle of type HFCI.
150 * On failure, the NULL file handle is returned. Error
151 * info can be retrieved from perf.
152 *
153 * INCLUDES
154 * fci.h
155 *
156 */
157 HFCI __cdecl FCICreate(
158 PERF perf,
159 PFNFCIFILEPLACED pfnfiledest,
160 PFNFCIALLOC pfnalloc,
161 PFNFCIFREE pfnfree,
162 PFNFCIOPEN pfnopen,
163 PFNFCIREAD pfnread,
164 PFNFCIWRITE pfnwrite,
165 PFNFCICLOSE pfnclose,
166 PFNFCISEEK pfnseek,
167 PFNFCIDELETE pfndelete,
168 PFNFCIGETTEMPFILE pfnfcigtf,
169 PCCAB pccab,
170 void *pv)
171 {
172 HFCI hfci;
173 int err;
174 PFCI_Int p_fci_internal;
175
176 if (!perf) {
177 SetLastError(ERROR_BAD_ARGUMENTS);
178 return NULL;
179 }
180 if ((!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||
181 (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||
182 (!pfnfcigtf) || (!pccab)) {
183 perf->erfOper = FCIERR_NONE;
184 perf->erfType = ERROR_BAD_ARGUMENTS;
185 perf->fError = TRUE;
186
187 SetLastError(ERROR_BAD_ARGUMENTS);
188 return NULL;
189 }
190
191 if (!((hfci = (*pfnalloc)(sizeof(FCI_Int))))) {
192 perf->erfOper = FCIERR_ALLOC_FAIL;
193 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
194 perf->fError = TRUE;
195
196 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
197 return NULL;
198 }
199
200 p_fci_internal=((PFCI_Int)(hfci));
201 p_fci_internal->FCI_Intmagic = FCI_INT_MAGIC;
202 p_fci_internal->perf = perf;
203 p_fci_internal->pfnfiledest = pfnfiledest;
204 p_fci_internal->pfnalloc = pfnalloc;
205 p_fci_internal->pfnfree = pfnfree;
206 p_fci_internal->pfnopen = pfnopen;
207 p_fci_internal->pfnread = pfnread;
208 p_fci_internal->pfnwrite = pfnwrite;
209 p_fci_internal->pfnclose = pfnclose;
210 p_fci_internal->pfnseek = pfnseek;
211 p_fci_internal->pfndelete = pfndelete;
212 p_fci_internal->pfnfcigtf = pfnfcigtf;
213 p_fci_internal->pccab = pccab;
214 p_fci_internal->fPrevCab = FALSE;
215 p_fci_internal->fNextCab = FALSE;
216 p_fci_internal->fSplitFolder = FALSE;
217 p_fci_internal->fGetNextCabInVain = FALSE;
218 p_fci_internal->pv = pv;
219 p_fci_internal->data_in = NULL;
220 p_fci_internal->cdata_in = 0;
221 p_fci_internal->data_out = NULL;
222 p_fci_internal->cCompressedBytesInFolder = 0;
223 p_fci_internal->cFolders = 0;
224 p_fci_internal->cFiles = 0;
225 p_fci_internal->cDataBlocks = 0;
226 p_fci_internal->sizeFileCFDATA1 = 0;
227 p_fci_internal->sizeFileCFFILE1 = 0;
228 p_fci_internal->sizeFileCFDATA2 = 0;
229 p_fci_internal->sizeFileCFFILE2 = 0;
230 p_fci_internal->sizeFileCFFOLDER = 0;
231 p_fci_internal->sizeFileCFFOLDER = 0;
232 p_fci_internal->fNewPrevious = FALSE;
233 p_fci_internal->estimatedCabinetSize = 0;
234 p_fci_internal->statusFolderTotal = 0;
235
236 memset(&p_fci_internal->oldCCAB, 0, sizeof(CCAB));
237 memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
238 memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);
239
240 /* CFDATA */
241 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA1,
242 CB_MAX_FILENAME)) {
243 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
244 return FALSE;
245 }
246 /* safety */
247 if ( strlen(p_fci_internal->szFileNameCFDATA1) >= CB_MAX_FILENAME ) {
248 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
249 return FALSE;
250 }
251
252 p_fci_internal->handleCFDATA1 = PFCI_OPEN(hfci,
253 p_fci_internal->szFileNameCFDATA1, 34050, 384, &err, pv);
254 if(p_fci_internal->handleCFDATA1==0){
255 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
256 return FALSE;
257 }
258 /* TODO error checking of err */
259
260 /* array of all CFFILE in a folder */
261 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE1,
262 CB_MAX_FILENAME)) {
263 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
264 return FALSE;
265 }
266 /* safety */
267 if ( strlen(p_fci_internal->szFileNameCFFILE1) >= CB_MAX_FILENAME ) {
268 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
269 return FALSE;
270 }
271 p_fci_internal->handleCFFILE1 = PFCI_OPEN(hfci,
272 p_fci_internal->szFileNameCFFILE1, 34050, 384, &err, pv);
273 if(p_fci_internal->handleCFFILE1==0){
274 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
275 return FALSE;
276 }
277 /* TODO error checking of err */
278
279 /* CFDATA with checksum and ready to be copied into cabinet */
280 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA2,
281 CB_MAX_FILENAME)) {
282 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE);
283 return FALSE;
284 }
285 /* safety */
286 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
287 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
288 return FALSE;
289 }
290 p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
291 p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, pv);
292 if(p_fci_internal->handleCFDATA2==0){
293 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
294 return FALSE;
295 }
296 /* TODO error checking of err */
297
298 /* array of all CFFILE in a folder, ready to be copied into cabinet */
299 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
300 CB_MAX_FILENAME)) {
301 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
302 return FALSE;
303 }
304 /* safety */
305 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
306 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
307 return FALSE;
308 }
309 p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
310 p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, pv);
311 if(p_fci_internal->handleCFFILE2==0){
312 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
313 return FALSE;
314 }
315 /* TODO error checking of err */
316
317 /* array of all CFFILE in a folder, ready to be copied into cabinet */
318 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,
319 CB_MAX_FILENAME)) {
320 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
321 return FALSE;
322 }
323 /* safety */
324 if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
325 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
326 return FALSE;
327 }
328 p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
329 p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, pv);
330 if(p_fci_internal->handleCFFOLDER==0) {
331 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
332 return FALSE;
333 }
334
335 /* TODO close and delete new files when return FALSE */
336 /* TODO error checking of err */
337
338 return hfci;
339 } /* end of FCICreate */
340
341
342
343
344
345
346 static BOOL fci_flush_data_block (HFCI hfci, int* err,
347 PFNFCISTATUS pfnfcis) {
348
349 /* attention no hfci checks!!! */
350 /* attention no checks if there is data available!!! */
351 CFDATA data;
352 CFDATA* cfdata=&data;
353 char* reserved;
354 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
355 UINT cbReserveCFData=p_fci_internal->pccab->cbReserveCFData;
356 UINT i;
357
358 /* TODO compress the data of p_fci_internal->data_in */
359 /* and write it to p_fci_internal->data_out */
360 memcpy(p_fci_internal->data_out, p_fci_internal->data_in,
361 p_fci_internal->cdata_in /* number of bytes to copy */);
362
363 cfdata->csum=0; /* checksum has to be set later */
364 /* TODO set realsize of compressed data */
365 cfdata->cbData = p_fci_internal->cdata_in;
366 cfdata->cbUncomp = p_fci_internal->cdata_in;
367
368 /* write cfdata to p_fci_internal->handleCFDATA1 */
369 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
370 cfdata, sizeof(*cfdata), err, p_fci_internal->pv)
371 != sizeof(*cfdata) ) {
372 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
373 return FALSE;
374 }
375 /* TODO error handling of err */
376
377 p_fci_internal->sizeFileCFDATA1 += sizeof(*cfdata);
378
379 /* add optional reserved area */
380
381 /* This allocation and freeing at each CFData block is a bit */
382 /* inefficient, but it's harder to forget about freeing the buffer :-). */
383 /* Reserved areas are used seldom besides that... */
384 if (cbReserveCFData!=0) {
385 if(!(reserved = PFCI_ALLOC(hfci, cbReserveCFData))) {
386 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
387 return FALSE;
388 }
389 for(i=0;i<cbReserveCFData;) {
390 reserved[i++]='\0';
391 }
392 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
393 reserved, /* memory buffer */
394 cbReserveCFData, /* number of bytes to copy */
395 err, p_fci_internal->pv) != cbReserveCFData ) {
396 PFCI_FREE(hfci, reserved);
397 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
398 return FALSE;
399 }
400 /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
401
402 p_fci_internal->sizeFileCFDATA1 += cbReserveCFData;
403 PFCI_FREE(hfci, reserved);
404 }
405
406 /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
407 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
408 p_fci_internal->data_out, /* memory buffer */
409 cfdata->cbData, /* number of bytes to copy */
410 err, p_fci_internal->pv) != cfdata->cbData) {
411 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
412 return FALSE;
413 }
414 /* TODO error handling of err */
415
416 p_fci_internal->sizeFileCFDATA1 += cfdata->cbData;
417
418 /* reset the offset */
419 p_fci_internal->cdata_in = 0;
420 p_fci_internal->cCompressedBytesInFolder += cfdata->cbData;
421
422 /* report status with pfnfcis about uncompressed and compressed file data */
423 if( (*pfnfcis)(statusFile, cfdata->cbData, cfdata->cbUncomp,
424 p_fci_internal->pv) == -1) {
425 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
426 return FALSE;
427 }
428
429 ++(p_fci_internal->cDataBlocks);
430
431 return TRUE;
432 } /* end of fci_flush_data_block */
433
434
435
436
437
438 static cab_ULONG fci_get_checksum(const void *pv, UINT cb, CHECKSUM seed)
439 {
440 cab_ULONG csum;
441 cab_ULONG ul;
442 int cUlong;
443 const BYTE *pb;
444
445 csum = seed;
446 cUlong = cb / 4;
447 pb = pv;
448
449 while (cUlong-- > 0) {
450 ul = *pb++;
451 ul |= (((cab_ULONG)(*pb++)) << 8);
452 ul |= (((cab_ULONG)(*pb++)) << 16);
453 ul |= (((cab_ULONG)(*pb++)) << 24);
454
455 csum ^= ul;
456 }
457
458 ul = 0;
459 switch (cb % 4) {
460 case 3:
461 ul |= (((ULONG)(*pb++)) << 16);
462 case 2:
463 ul |= (((ULONG)(*pb++)) << 8);
464 case 1:
465 ul |= *pb;
466 default:
467 break;
468 }
469 csum ^= ul;
470
471 return csum;
472 } /* end of fci_get_checksum */
473
474
475
476 static BOOL fci_flushfolder_copy_cfdata(HFCI hfci, char* buffer, UINT cbReserveCFData,
477 PFNFCISTATUS pfnfcis, int* err, int handleCFDATA1new,
478 cab_ULONG* psizeFileCFDATA1new, cab_ULONG* payload)
479 {
480 cab_ULONG read_result;
481 CFDATA* pcfdata=(CFDATA*)buffer;
482 BOOL split_block=FALSE;
483 cab_UWORD savedUncomp=0;
484 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
485
486 *payload=0;
487
488 /* while not all CFDATAs have been copied do */
489 while(!FALSE) {
490 if( p_fci_internal->fNextCab ) {
491 if( split_block ) {
492 /* internal error should never happen */
493 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
494 return FALSE;
495 }
496 }
497 /* REUSE the variable read_result */
498 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
499 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
500 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
501 read_result=4;
502 } else {
503 read_result=0;
504 }
505 if (p_fci_internal->fPrevCab) {
506 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
507 strlen(p_fci_internal->szPrevDisk)+1;
508 }
509 /* No more CFDATA fits into the cabinet under construction */
510 /* So don't try to store more data into it */
511 if( p_fci_internal->fNextCab &&
512 (p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData +
513 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
514 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
515 sizeof(CFHEADER) +
516 read_result +
517 p_fci_internal->oldCCAB.cbReserveCFHeader +
518 sizeof(CFFOLDER) +
519 p_fci_internal->oldCCAB.cbReserveCFFolder +
520 strlen(p_fci_internal->pccab->szCab)+1 +
521 strlen(p_fci_internal->pccab->szDisk)+1
522 )) {
523 /* This may never be run for the first time the while loop is entered.
524 Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
525 split_block=TRUE; /* In this case split_block is abused to store */
526 /* the complete data block into the next cabinet and not into the */
527 /* current one. Originally split_block is the indicator that a */
528 /* data block has been split across different cabinets. */
529 } else {
530
531 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
532 read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/*file handle*/
533 buffer, /* memory buffer */
534 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
535 err, p_fci_internal->pv);
536 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
537 if (read_result==0) break; /* ALL DATA has been copied */
538 /* read error */
539 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
540 return FALSE;
541 }
542 /* TODO error handling of err */
543
544 /* REUSE buffer p_fci_internal->data_out !!! */
545 /* read data from p_fci_internal->handleCFDATA1 to */
546 /* p_fci_internal->data_out */
547 if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
548 p_fci_internal->data_out /* memory buffer */,
549 pcfdata->cbData /* number of bytes to copy */,
550 err, p_fci_internal->pv) != pcfdata->cbData ) {
551 /* read error */
552 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
553 return FALSE;
554 }
555 /* TODO error handling of err */
556
557 /* if cabinet size is too large */
558
559 /* REUSE the variable read_result */
560 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
561 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
562 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
563 read_result=4;
564 } else {
565 read_result=0;
566 }
567 if (p_fci_internal->fPrevCab) {
568 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
569 strlen(p_fci_internal->szPrevDisk)+1;
570 }
571
572 /* Is cabinet with new CFDATA too large? Then data block has to be split */
573 if( p_fci_internal->fNextCab &&
574 (p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData +
575 pcfdata->cbData +
576 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
577 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
578 sizeof(CFHEADER) +
579 read_result +
580 p_fci_internal->oldCCAB.cbReserveCFHeader +
581 sizeof(CFFOLDER) + /* size of new CFFolder entry */
582 p_fci_internal->oldCCAB.cbReserveCFFolder +
583 strlen(p_fci_internal->pccab->szCab)+1 + /* name of next cabinet */
584 strlen(p_fci_internal->pccab->szDisk)+1 /* name of next disk */
585 )) {
586 /* REUSE read_result to save the size of the compressed data */
587 read_result=pcfdata->cbData;
588 /* Modify the size of the compressed data to store only a part of the */
589 /* data block into the current cabinet. This is done to prevent */
590 /* that the maximum cabinet size will be exceeded. The remainder */
591 /* will be stored into the next following cabinet. */
592
593 /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
594 /* Substract everything except the size of the block of data */
595 /* to get it's actual size */
596 pcfdata->cbData = p_fci_internal->oldCCAB.cb - (
597 sizeof(CFDATA) + cbReserveCFData +
598 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
599 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
600 sizeof(CFHEADER) +
601 p_fci_internal->oldCCAB.cbReserveCFHeader +
602 sizeof(CFFOLDER) + /* set size of new CFFolder entry */
603 p_fci_internal->oldCCAB.cbReserveCFFolder );
604 /* substract the size of special header fields */
605 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
606 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
607 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
608 pcfdata->cbData-=4;
609 }
610 if (p_fci_internal->fPrevCab) {
611 pcfdata->cbData-=strlen(p_fci_internal->szPrevCab)+1 +
612 strlen(p_fci_internal->szPrevDisk)+1;
613 }
614 pcfdata->cbData-=strlen(p_fci_internal->pccab->szCab)+1 +
615 strlen(p_fci_internal->pccab->szDisk)+1;
616
617 savedUncomp = pcfdata->cbUncomp;
618 pcfdata->cbUncomp = 0; /* on split blocks of data this is zero */
619
620 /* if split_block==TRUE then the above while loop won't */
621 /* be executed again */
622 split_block=TRUE; /* split_block is the indicator that */
623 /* a data block has been split across */
624 /* different cabinets.*/
625 }
626
627 /* This should never happen !!! */
628 if (pcfdata->cbData==0) {
629 /* set error */
630 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
631 return FALSE;
632 }
633
634 /* set little endian */
635 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
636 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
637
638 /* get checksum and write to cfdata.csum */
639 pcfdata->csum = fci_get_checksum( &(pcfdata->cbData),
640 sizeof(CFDATA)+cbReserveCFData -
641 sizeof(pcfdata->csum), fci_get_checksum( p_fci_internal->data_out, /*buffer*/
642 pcfdata->cbData, 0 ) );
643
644 /* set little endian */
645 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
646
647 /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
648 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
649 buffer, /* memory buffer */
650 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
651 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
652 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
653 return FALSE;
654 }
655 /* TODO error handling of err */
656
657 p_fci_internal->sizeFileCFDATA2 += sizeof(CFDATA)+cbReserveCFData;
658
659 /* reset little endian */
660 pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
661 pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
662 pcfdata->csum=fci_endian_ulong(pcfdata->csum);
663
664 /* write compressed data into p_fci_internal->handleCFDATA2 */
665 if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
666 p_fci_internal->data_out, /* memory buffer */
667 pcfdata->cbData, /* number of bytes to copy */
668 err, p_fci_internal->pv) != pcfdata->cbData) {
669 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
670 return FALSE;
671 }
672 /* TODO error handling of err */
673
674 p_fci_internal->sizeFileCFDATA2 += pcfdata->cbData;
675 ++(p_fci_internal->cDataBlocks);
676 p_fci_internal->statusFolderCopied += pcfdata->cbData;
677 (*payload)+=pcfdata->cbUncomp;
678 /* if cabinet size too large and data has been split */
679 /* write the remainder of the data block to the new CFDATA1 file */
680 if( split_block ) { /* This does not include the */
681 /* abused one (just search for "abused" )*/
682 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
683 if (p_fci_internal->fNextCab==FALSE ) {
684 /* internal error */
685 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
686 return FALSE;
687 }
688
689 /* set cbData to the size of the remainder of the data block */
690 pcfdata->cbData = read_result - pcfdata->cbData;
691 /*recover former value of cfdata.cbData; read_result will be the offset*/
692 read_result -= pcfdata->cbData;
693 pcfdata->cbUncomp = savedUncomp;
694
695 /* reset checksum, it will be computed later */
696 pcfdata->csum=0;
697
698 /* write cfdata WITHOUT checksum to handleCFDATA1new */
699 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
700 buffer, /* memory buffer */
701 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
702 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
703 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
704 return FALSE;
705 }
706 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
707
708 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
709
710 /* write compressed data into handleCFDATA1new */
711 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
712 p_fci_internal->data_out + read_result, /* memory buffer + offset */
713 /* to last part of split data */
714 pcfdata->cbData, /* number of bytes to copy */
715 err, p_fci_internal->pv) != pcfdata->cbData) {
716 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
717 return FALSE;
718 }
719 /* TODO error handling of err */
720
721 p_fci_internal->statusFolderCopied += pcfdata->cbData;
722
723 *psizeFileCFDATA1new += pcfdata->cbData;
724 /* the two blocks of the split data block have been written */
725 /* don't reset split_data yet, because it is still needed see below */
726 }
727
728 /* report status with pfnfcis about copied size of folder */
729 if( (*pfnfcis)(statusFolder,
730 p_fci_internal->statusFolderCopied, /*cfdata.cbData(+previous ones)*/
731 p_fci_internal->statusFolderTotal, /* total folder size */
732 p_fci_internal->pv) == -1) {
733 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
734 return FALSE;
735 }
736 }
737
738 /* if cabinet size too large */
739 /* write the remaining data blocks to the new CFDATA1 file */
740 if ( split_block ) { /* This does include the */
741 /* abused one (just search for "abused" )*/
742 if (p_fci_internal->fNextCab==FALSE ) {
743 /* internal error */
744 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
745 return FALSE;
746 }
747 /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
748 while(!FALSE) {
749 /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
750 read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/* handle */
751 buffer, /* memory buffer */
752 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
753 err, p_fci_internal->pv);
754 if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
755 if (read_result==0) break; /* ALL DATA has been copied */
756 /* read error */
757 fci_set_error(FCIERR_NONE, ERROR_READ_FAULT, TRUE );
758 return FALSE;
759 }
760 /* TODO error handling of err */
761
762 /* REUSE buffer p_fci_internal->data_out !!! */
763 /* read data from p_fci_internal->handleCFDATA1 to */
764 /* p_fci_internal->data_out */
765 if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
766 p_fci_internal->data_out /* memory buffer */,
767 pcfdata->cbData /* number of bytes to copy */,
768 err, p_fci_internal->pv) != pcfdata->cbData ) {
769 /* read error */
770 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE);
771 return FALSE;
772 }
773 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
774
775 /* write cfdata with checksum to handleCFDATA1new */
776 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
777 buffer, /* memory buffer */
778 sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
779 err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
780 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
781 return FALSE;
782 }
783 /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
784
785 *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
786
787 /* write compressed data into handleCFDATA1new */
788 if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
789 p_fci_internal->data_out, /* memory buffer */
790 pcfdata->cbData, /* number of bytes to copy */
791 err, p_fci_internal->pv) != pcfdata->cbData) {
792 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
793 return FALSE;
794 }
795 /* TODO error handling of err */
796
797 *psizeFileCFDATA1new += pcfdata->cbData;
798 p_fci_internal->statusFolderCopied += pcfdata->cbData;
799
800 /* report status with pfnfcis about copied size of folder */
801 if( (*pfnfcis)(statusFolder,
802 p_fci_internal->statusFolderCopied,/*cfdata.cbData(+previous ones)*/
803 p_fci_internal->statusFolderTotal, /* total folder size */
804 p_fci_internal->pv) == -1) {
805 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
806 return FALSE;
807 }
808
809 } /* end of WHILE */
810 break; /* jump out of the next while loop */
811 } /* end of if( split_data ) */
812 } /* end of WHILE */
813 return TRUE;
814 } /* end of fci_flushfolder_copy_cfdata */
815
816
817
818
819
820 static BOOL fci_flushfolder_copy_cffolder(HFCI hfci, int* err, UINT cbReserveCFFolder,
821 cab_ULONG sizeFileCFDATA2old)
822 {
823 CFFOLDER cffolder;
824 UINT i;
825 char* reserved;
826 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
827
828 /* absolute offset cannot be set yet, because the size of cabinet header, */
829 /* the number of CFFOLDERs and the number of CFFILEs may change. */
830 /* Instead the size of all previous data blocks will be stored and */
831 /* the remainder of the offset will be added when the cabinet will be */
832 /* flushed to disk. */
833 /* This is exactly the way the original CABINET.DLL works!!! */
834 cffolder.coffCabStart=sizeFileCFDATA2old;
835
836 /* set the number of this folder's CFDATA sections */
837 cffolder.cCFData=p_fci_internal->cDataBlocks;
838 /* TODO set compression type */
839 cffolder.typeCompress = tcompTYPE_NONE;
840
841 /* write cffolder to p_fci_internal->handleCFFOLDER */
842 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
843 &cffolder, /* memory buffer */
844 sizeof(cffolder), /* number of bytes to copy */
845 err, p_fci_internal->pv) != sizeof(cffolder) ) {
846 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
847 return FALSE;
848 }
849 /* TODO error handling of err */
850
851 p_fci_internal->sizeFileCFFOLDER += sizeof(cffolder);
852
853 /* add optional reserved area */
854 if (cbReserveCFFolder!=0) {
855 if(!(reserved = PFCI_ALLOC(hfci, cbReserveCFFolder))) {
856 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
857 return FALSE;
858 }
859 for(i=0;i<cbReserveCFFolder;) {
860 reserved[i++]='\0';
861 }
862 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
863 reserved, /* memory buffer */
864 cbReserveCFFolder, /* number of bytes to copy */
865 err, p_fci_internal->pv) != cbReserveCFFolder ) {
866 PFCI_FREE(hfci, reserved);
867 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
868 return FALSE;
869 }
870 /* TODO error handling of err */
871
872 p_fci_internal->sizeFileCFFOLDER += cbReserveCFFolder;
873
874 PFCI_FREE(hfci, reserved);
875 }
876 return TRUE;
877 } /* end of fci_flushfolder_copy_cffolder */
878
879
880
881
882
883 static BOOL fci_flushfolder_copy_cffile(HFCI hfci, int* err, int handleCFFILE1new,
884 cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload)
885 {
886 CFFILE cffile;
887 cab_ULONG read_result;
888 cab_ULONG seek=0;
889 cab_ULONG sizeOfFiles=0, sizeOfFilesPrev;
890 BOOL may_be_prev=TRUE;
891 cab_ULONG cbFileRemainer=0;
892 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
893 /* set seek of p_fci_internal->handleCFFILE1 to 0 */
894 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,0,SEEK_SET,err,
895 p_fci_internal->pv) !=0 ) {
896 /* wrong return value */
897 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
898 return FALSE;
899 }
900 /* TODO error handling of err */
901
902 /* while not all CFFILE structures have been copied do */
903 while(!FALSE) {
904 /* REUSE the variable read_result */
905 /* read data from p_fci_internal->handleCFFILE1 to cffile */
906 read_result = PFCI_READ(hfci,p_fci_internal->handleCFFILE1/* file handle */,
907 &cffile, /* memory buffer */
908 sizeof(cffile), /* number of bytes to copy */
909 err, p_fci_internal->pv);
910 if( read_result != sizeof(cffile) ) {
911 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
912 /* read error */
913 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
914 return FALSE;
915 }
916 /* TODO error handling of err */
917
918 /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
919 /* position. I don't know why so I'll just omit it */
920
921 /* read the filename from p_fci_internal->handleCFFILE1 */
922 /* REUSE the variable read_result AGAIN */
923 /* REUSE the memory buffer PFCI(hfci)->data_out */
924 if( PFCI_READ(hfci, p_fci_internal->handleCFFILE1 /*file handle*/,
925 p_fci_internal->data_out, /* memory buffer */
926 CB_MAX_FILENAME, /* number of bytes to copy */
927 err, p_fci_internal->pv) <2) {
928 /* read error */
929 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
930 return FALSE;
931 }
932 /* TODO maybe other checks of read_result */
933 /* TODO error handling of err */
934
935 /* safety */
936 if( strlen(p_fci_internal->data_out)>=CB_MAX_FILENAME ) {
937 /* set error code internal error */
938 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
939 return FALSE;
940 }
941
942 seek+=sizeof(cffile) + strlen(p_fci_internal->data_out)+1;
943
944 /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
945 /* i.e. seek to the next CFFILE area */
946 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,
947 seek, /* seek position*/
948 SEEK_SET ,err,
949 p_fci_internal->pv)
950 != seek) {
951 /* wrong return value */
952 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
953 return FALSE;
954 }
955 /* TODO error handling of err */
956
957 /* fnfilfnfildest: placed file on cabinet */
958 if (p_fci_internal->fNextCab ||
959 p_fci_internal->fGetNextCabInVain) {
960 PFCI_FILEPLACED( hfci, &(p_fci_internal->oldCCAB),
961 p_fci_internal->data_out, /* the file name*/
962 cffile.cbFile, /* file size */
963 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
964 p_fci_internal->pv
965 );
966 } else {
967 PFCI_FILEPLACED( hfci, p_fci_internal->pccab,
968 p_fci_internal->data_out, /* the file name*/
969 cffile.cbFile, /* file size */
970 (cffile.iFolder==cffileCONTINUED_FROM_PREV),
971 p_fci_internal->pv
972 );
973 }
974
975 /* Check special iFolder values */
976 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
977 p_fci_internal->fPrevCab==FALSE ) {
978 /* THIS MAY NEVER HAPPEN */
979 /* set error code */
980 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
981 return FALSE;
982 }
983 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
984 cffile.iFolder==cffileCONTINUED_TO_NEXT ) {
985 /* THIS MAY NEVER HAPPEN */
986 /* set error code */
987 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
988 return FALSE;
989 }
990 if( may_be_prev && cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
991 may_be_prev=FALSE;
992 }
993 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && may_be_prev==FALSE ) {
994 /* THIS MAY NEVER HAPPEN */
995 /* set error code */
996 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
997 return FALSE;
998 }
999 if( cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
1000 may_be_prev=FALSE;
1001 }
1002
1003 sizeOfFilesPrev=sizeOfFiles;
1004 /* Set complete size of all processed files */
1005 if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
1006 p_fci_internal->cbFileRemainer!=0
1007 ) {
1008 sizeOfFiles+=p_fci_internal->cbFileRemainer;
1009 p_fci_internal->cbFileRemainer=0;
1010 } else {
1011 sizeOfFiles+=cffile.cbFile;
1012 }
1013
1014 /* Check if spanned file fits into this cabinet folder */
1015 if( cffile.iFolder==cffileCONTINUED_FROM_PREV && sizeOfFiles>payload ) {
1016 cffile.iFolder=cffileCONTINUED_PREV_AND_NEXT;
1017 } else
1018
1019 /* Check if file doesn't fit into this cabinet folder */
1020 if( sizeOfFiles>payload ) {
1021 cffile.iFolder=cffileCONTINUED_TO_NEXT;
1022 }
1023
1024 /* set little endian */
1025 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1026 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1027 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1028 cffile.date=fci_endian_uword(cffile.date);
1029 cffile.time=fci_endian_uword(cffile.time);
1030 cffile.attribs=fci_endian_uword(cffile.attribs);
1031
1032 /* write cffile to p_fci_internal->handleCFFILE2 */
1033 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */
1034 &cffile, /* memory buffer */
1035 sizeof(cffile), /* number of bytes to copy */
1036 err, p_fci_internal->pv) != sizeof(cffile) ) {
1037 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1038 return FALSE;
1039 }
1040 /* TODO error handling of err */
1041
1042 p_fci_internal->sizeFileCFFILE2 += sizeof(cffile);
1043
1044 /* reset little endian */
1045 cffile.cbFile=fci_endian_ulong(cffile.cbFile);
1046 cffile.uoffFolderStart=fci_endian_ulong(cffile.uoffFolderStart);
1047 cffile.iFolder=fci_endian_uword(cffile.iFolder);
1048 cffile.date=fci_endian_uword(cffile.date);
1049 cffile.time=fci_endian_uword(cffile.time);
1050 cffile.attribs=fci_endian_uword(cffile.attribs);
1051
1052 /* write file name to p_fci_internal->handleCFFILE2 */
1053 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE2, /* file handle */
1054 p_fci_internal->data_out, /* memory buffer */
1055 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1056 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1057 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1058 return FALSE;
1059 }
1060 /* TODO error handling of err */
1061
1062 p_fci_internal->sizeFileCFFILE2 += strlen(p_fci_internal->data_out)+1;
1063
1064 /* cFiles is used to count all files of a cabinet */
1065 ++(p_fci_internal->cFiles);
1066
1067 /* This is only true for files which will be written into the */
1068 /* next cabinet of the spanning folder */
1069 if( sizeOfFiles>payload ) {
1070
1071 /* Files which data will be partially written into the current cabinet */
1072 if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
1073 cffile.iFolder==cffileCONTINUED_TO_NEXT
1074 ) {
1075 if( sizeOfFilesPrev<=payload ) {
1076 /* The size of the uncompressed, data of a spanning file in a */
1077 /* spanning data */
1078 cbFileRemainer=sizeOfFiles-payload;
1079 }
1080 cffile.iFolder=cffileCONTINUED_FROM_PREV;
1081 } else {
1082 cffile.iFolder=0;
1083 }
1084
1085 /* write cffile into handleCFFILE1new */
1086 if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */
1087 &cffile, /* memory buffer */
1088 sizeof(cffile), /* number of bytes to copy */
1089 err, p_fci_internal->pv) != sizeof(cffile) ) {
1090 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1091 return FALSE;
1092 }
1093 /* TODO error handling of err */
1094
1095 *psizeFileCFFILE1new += sizeof(cffile);
1096 /* write name of file into handleCFFILE1new */
1097 if( PFCI_WRITE(hfci, handleCFFILE1new, /* file handle */
1098 p_fci_internal->data_out, /* memory buffer */
1099 strlen(p_fci_internal->data_out)+1, /* number of bytes to copy */
1100 err, p_fci_internal->pv) != strlen(p_fci_internal->data_out)+1 ) {
1101 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
1102 return FALSE;
1103 }
1104 /* TODO error handling of err */
1105
1106 *psizeFileCFFILE1new += strlen(p_fci_internal->data_out)+1;
1107 }
1108
1109 } /* END OF while */
1110 p_fci_internal->cbFileRemainer=cbFileRemainer;
1111 return TRUE;
1112 } /* end of fci_flushfolder_copy_cffile */
1113
1114
1115
1116
1117 static BOOL fci_flush_folder(
1118 HFCI hfci,
1119 BOOL fGetNextCab,
1120 PFNFCIGETNEXTCABINET pfnfcignc,
1121 PFNFCISTATUS pfnfcis)
1122 {
1123 int err;
1124 int handleCFDATA1new; /* handle for new temp file */
1125 char szFileNameCFDATA1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1126 int handleCFFILE1new; /* handle for new temp file */
1127 char szFileNameCFFILE1new[CB_MAX_FILENAME]; /* name buffer for temp file */
1128 UINT cbReserveCFData, cbReserveCFFolder;
1129 char* reserved;
1130 cab_ULONG sizeFileCFDATA1new=0;
1131 cab_ULONG sizeFileCFFILE1new=0;
1132 cab_ULONG sizeFileCFDATA2old;
1133 cab_ULONG payload;
1134 cab_ULONG read_result;
1135 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
1136
1137 /* test hfci */
1138 if (!REALLY_IS_FCI(hfci)) {
1139 SetLastError(ERROR_INVALID_HANDLE);
1140 return FALSE;
1141 }
1142
1143 if ((!pfnfcignc) || (!pfnfcis)) {
1144 fci_set_error( FCIERR_NONE, ERROR_BAD_ARGUMENTS, TRUE );
1145 return FALSE;
1146 }
1147
1148 if( p_fci_internal->fGetNextCabInVain &&
1149 p_fci_internal->fNextCab ){
1150 /* internal error */
1151 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1152 return FALSE;
1153 }
1154
1155 /* If there was no FCIAddFile or FCIFlushFolder has already been called */
1156 /* this function will return TRUE */
1157 if( p_fci_internal->sizeFileCFFILE1 == 0 ) {
1158 if ( p_fci_internal->sizeFileCFDATA1 != 0 ) {
1159 /* error handling */
1160 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1161 return FALSE;
1162 }
1163 return TRUE;
1164 }
1165
1166 if (p_fci_internal->data_in==NULL || p_fci_internal->data_out==NULL ) {
1167 /* error handling */
1168 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1169 return FALSE;
1170 }
1171
1172 /* FCIFlushFolder has already been called... */
1173 if (p_fci_internal->fSplitFolder && p_fci_internal->sizeFileCFFILE2!=0) {
1174 return TRUE;
1175 }
1176
1177 /* This can be set already, because it makes only a difference */
1178 /* when the current function exits with return FALSE */
1179 p_fci_internal->fSplitFolder=FALSE;
1180
1181
1182 if( p_fci_internal->fGetNextCabInVain ||
1183 p_fci_internal->fNextCab ){
1184 cbReserveCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1185 cbReserveCFFolder = p_fci_internal->oldCCAB.cbReserveCFFolder;
1186 } else {
1187 cbReserveCFData = p_fci_internal->pccab->cbReserveCFData;
1188 cbReserveCFFolder = p_fci_internal->pccab->cbReserveCFFolder;
1189 }
1190
1191 /* START of COPY */
1192 /* if there is data in p_fci_internal->data_in */
1193 if (p_fci_internal->cdata_in!=0) {
1194
1195 if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;
1196
1197 }
1198 /* reset to get the number of data blocks of this folder which are */
1199 /* actually in this cabinet ( at least partially ) */
1200 p_fci_internal->cDataBlocks=0;
1201
1202 if ( p_fci_internal->fNextCab ||
1203 p_fci_internal->fGetNextCabInVain ) {
1204 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader+
1205 p_fci_internal->oldCCAB.cbReserveCFFolder;
1206 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1207 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1208 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1209 read_result+=4;
1210 }
1211 } else {
1212 read_result= p_fci_internal->pccab->cbReserveCFHeader+
1213 p_fci_internal->pccab->cbReserveCFFolder;
1214 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1215 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1216 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1217 read_result+=4;
1218 }
1219 }
1220 if (p_fci_internal->fPrevCab) {
1221 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1222 strlen(p_fci_internal->szPrevDisk)+1;
1223 }
1224 if (p_fci_internal->fNextCab) {
1225 read_result+=strlen(p_fci_internal->pccab->szCab)+1 +
1226 strlen(p_fci_internal->pccab->szDisk)+1;
1227 }
1228
1229 p_fci_internal->statusFolderTotal = sizeof(CFHEADER)+read_result+
1230 sizeof(CFFOLDER) + p_fci_internal->sizeFileCFFILE2+
1231 p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1+
1232 p_fci_internal->sizeFileCFDATA1 + p_fci_internal->sizeFileCFFOLDER;
1233 p_fci_internal->statusFolderCopied = 0;
1234
1235 /* report status with pfnfcis about copied size of folder */
1236 if( (*pfnfcis)(statusFolder, p_fci_internal->statusFolderCopied,
1237 p_fci_internal->statusFolderTotal, /* TODO total folder size */
1238 p_fci_internal->pv) == -1) {
1239 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
1240 return FALSE;
1241 }
1242
1243 /* get a new temp file */
1244 if(!PFCI_GETTEMPFILE(hfci,szFileNameCFDATA1new,CB_MAX_FILENAME)) {
1245 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1246 return FALSE;
1247 }
1248 /* safety */
1249 if ( strlen(szFileNameCFDATA1new) >= CB_MAX_FILENAME ) {
1250 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1251 return FALSE;
1252 }
1253 handleCFDATA1new = PFCI_OPEN(hfci,szFileNameCFDATA1new,34050,384,&err,
1254 p_fci_internal->pv);
1255 if(handleCFDATA1new==0){
1256 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
1257 return FALSE;
1258 }
1259 /* TODO error handling of err */
1260
1261
1262
1263 /* get a new temp file */
1264 if(!PFCI_GETTEMPFILE(hfci,szFileNameCFFILE1new,CB_MAX_FILENAME)) {
1265 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1266 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1267 /* TODO error handling of err */
1268 return FALSE;
1269 }
1270 /* safety */
1271 if ( strlen(szFileNameCFFILE1new) >= CB_MAX_FILENAME ) {
1272 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1273 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1274 /* TODO error handling of err */
1275 return FALSE;
1276 }
1277 handleCFFILE1new = PFCI_OPEN(hfci,szFileNameCFFILE1new,34050,384,&err,
1278 p_fci_internal->pv);
1279 if(handleCFFILE1new==0){
1280 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
1281 return FALSE;
1282 }
1283 /* TODO error handling of err */
1284
1285 /* USE the variable read_result */
1286 if ( p_fci_internal->fNextCab ||
1287 p_fci_internal->fGetNextCabInVain ) {
1288 read_result= p_fci_internal->oldCCAB.cbReserveCFHeader;
1289 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1290 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1291 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1292 read_result+=4;
1293 }
1294 } else {
1295 read_result= p_fci_internal->pccab->cbReserveCFHeader;
1296 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1297 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1298 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1299 read_result+=4;
1300 }
1301 }
1302 if (p_fci_internal->fPrevCab) {
1303 read_result+=strlen(p_fci_internal->szPrevCab)+1 +
1304 strlen(p_fci_internal->szPrevDisk)+1;
1305 }
1306 read_result+= sizeof(CFHEADER) + p_fci_internal->sizeFileCFDATA2 +
1307 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER;
1308
1309 if(p_fci_internal->sizeFileCFFILE1!=0) {
1310 read_result+= sizeof(CFFOLDER)+p_fci_internal->pccab->cbReserveCFFolder;
1311 }
1312
1313 /* Check if multiple cabinets have to be created. */
1314
1315 /* Might be too much data for the maximum allowed cabinet size.*/
1316 /* When any further data will be added later, it might not */
1317 /* be possible to flush the cabinet, because there might */
1318 /* not be enough space to store the name of the following */
1319 /* cabinet and name of the corresponding disk. */
1320 /* So take care of this and get the name of the next cabinet */
1321 if( p_fci_internal->fGetNextCabInVain==FALSE &&
1322 p_fci_internal->fNextCab==FALSE &&
1323 (
1324 (
1325 p_fci_internal->pccab->cb < read_result +
1326 p_fci_internal->sizeFileCFDATA1 +
1327 p_fci_internal->sizeFileCFFILE1 +
1328 CB_MAX_CABINET_NAME + /* next cabinet name */
1329 CB_MAX_DISK_NAME /* next disk name */
1330 ) || fGetNextCab
1331 )
1332 ) {
1333 /* save CCAB */
1334 p_fci_internal->oldCCAB = *p_fci_internal->pccab;
1335 /* increment cabinet index */
1336 ++(p_fci_internal->pccab->iCab);
1337 /* get name of next cabinet */
1338 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
1339 if (!(*pfnfcignc)(p_fci_internal->pccab,
1340 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
1341 p_fci_internal->pv)) {
1342 /* error handling */
1343 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
1344 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1345 /* TODO error handling of err */
1346 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1347 /* TODO error handling of err */
1348 return FALSE;
1349 }
1350
1351 /* Skip a few lines of code. This is caught by the next if. */
1352 p_fci_internal->fGetNextCabInVain=TRUE;
1353 }
1354
1355 /* too much data for cabinet */
1356 if( (p_fci_internal->fGetNextCabInVain ||
1357 p_fci_internal->fNextCab ) &&
1358 (
1359 (
1360 p_fci_internal->oldCCAB.cb < read_result +
1361 p_fci_internal->sizeFileCFDATA1 +
1362 p_fci_internal->sizeFileCFFILE1 +
1363 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1364 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1365 ) || fGetNextCab
1366 )
1367 ) {
1368 p_fci_internal->fGetNextCabInVain=FALSE;
1369 p_fci_internal->fNextCab=TRUE;
1370
1371 /* return FALSE if there is not enough space left*/
1372 /* this should never happen */
1373 if (p_fci_internal->oldCCAB.cb <=
1374 p_fci_internal->sizeFileCFFILE1 +
1375 read_result +
1376 strlen(p_fci_internal->pccab->szCab)+1 + /* next cabinet name */
1377 strlen(p_fci_internal->pccab->szDisk)+1 /* next disk name */
1378 ) {
1379
1380 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1381 /* TODO error handling of err */
1382 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1383 /* TODO error handling of err */
1384
1385 /* close and delete p_fci_internal->handleCFFILE1 */
1386 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1387 /* TODO error handling of err */
1388 PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);
1389 /* TODO error handling of err */
1390
1391 return FALSE;
1392 }
1393
1394 /* the folder will be split across cabinets */
1395 p_fci_internal->fSplitFolder=TRUE;
1396
1397 } else {
1398 /* this should never happen */
1399 if (p_fci_internal->fNextCab) {
1400 /* internal error */
1401 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1402 return FALSE;
1403 }
1404 }
1405
1406 /* set seek of p_fci_internal->handleCFDATA1 to 0 */
1407 if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA1,0,SEEK_SET,&err,
1408 p_fci_internal->pv) !=0 ) {
1409 /* wrong return value */
1410 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1411 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1412 /* TODO error handling of err */
1413 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1414 /* TODO error handling of err */
1415 return FALSE;
1416 }
1417 /* TODO error handling of err */
1418
1419 /* save size of file CFDATA2 - required for the folder's offset to data */
1420 sizeFileCFDATA2old = p_fci_internal->sizeFileCFDATA2;
1421
1422 if(!(reserved = PFCI_ALLOC(hfci, cbReserveCFData+sizeof(CFDATA)))) {
1423 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1424 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1425 /* TODO error handling of err */
1426 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1427 /* TODO error handling of err */
1428 return FALSE;
1429 }
1430
1431 if(!fci_flushfolder_copy_cfdata(hfci, reserved, cbReserveCFData, pfnfcis, &err,
1432 handleCFDATA1new, &sizeFileCFDATA1new, &payload
1433 )) {
1434 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1435 /* TODO error handling of err */
1436 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1437 /* TODO error handling of err */
1438 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1439 /* TODO error handling of err */
1440 PFCI_FREE(hfci,reserved);
1441 return FALSE;
1442 }
1443
1444 PFCI_FREE(hfci,reserved);
1445
1446 if(!fci_flushfolder_copy_cffolder(hfci, &err, cbReserveCFFolder,
1447 sizeFileCFDATA2old )) {
1448 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1449 /* TODO error handling of err */
1450 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1451 /* TODO error handling of err */
1452 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1453 /* TODO error handling of err */
1454 return FALSE;
1455 }
1456
1457 if(!fci_flushfolder_copy_cffile(hfci, &err, handleCFFILE1new,
1458 &sizeFileCFFILE1new, payload)) {
1459 PFCI_CLOSE(hfci,handleCFDATA1new,&err,p_fci_internal->pv);
1460 /* TODO error handling of err */
1461 PFCI_DELETE(hfci,szFileNameCFDATA1new,&err,p_fci_internal->pv);
1462 /* TODO error handling of err */
1463 PFCI_CLOSE(hfci,handleCFFILE1new,&err,p_fci_internal->pv);
1464 /* TODO error handling of err */
1465 PFCI_DELETE(hfci,szFileNameCFFILE1new,&err,p_fci_internal->pv);
1466 /* TODO error handling of err */
1467 return FALSE;
1468 }
1469
1470 /* close and delete p_fci_internal->handleCFDATA1 */
1471 PFCI_CLOSE(hfci,p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
1472 /* TODO error handling of err */
1473 PFCI_DELETE(hfci,p_fci_internal->szFileNameCFDATA1,&err,p_fci_internal->pv);
1474 /* TODO error handling of err */
1475
1476 /* put new CFDATA1 into hfci */
1477 memcpy(p_fci_internal->szFileNameCFDATA1,szFileNameCFDATA1new,
1478 CB_MAX_FILENAME);
1479
1480 /* put CFDATA1 file handle */
1481 PFCI_INT(hfci)->handleCFDATA1 = handleCFDATA1new;
1482 /* set file size */
1483 PFCI_INT(hfci)->sizeFileCFDATA1 = sizeFileCFDATA1new;
1484
1485 /* close and delete PFCI_INT(hfci)->handleCFFILE1 */
1486 PFCI_CLOSE(hfci,p_fci_internal->handleCFFILE1,&err,PFCI_INT(hfci)->pv);
1487 /* TODO error handling of err */
1488 PFCI_DELETE(hfci,p_fci_internal->szFileNameCFFILE1,&err,p_fci_internal->pv);
1489 /* TODO error handling of err */
1490
1491 /* put new CFFILE1 into hfci */
1492 memcpy(p_fci_internal->szFileNameCFFILE1,szFileNameCFFILE1new,
1493 CB_MAX_FILENAME);
1494
1495 /* put CFFILE1 file handle */
1496 p_fci_internal->handleCFFILE1 = handleCFFILE1new;
1497 /* set file size */
1498 p_fci_internal->sizeFileCFFILE1 = sizeFileCFFILE1new;
1499
1500 ++(p_fci_internal->cFolders);
1501
1502 /* reset CFFolder specific information */
1503 p_fci_internal->cDataBlocks=0;
1504 p_fci_internal->cCompressedBytesInFolder=0;
1505
1506 return TRUE;
1507 } /* end of fci_flush_folder */
1508
1509
1510
1511
1512 static BOOL fci_flush_cabinet(
1513 HFCI hfci,
1514 BOOL fGetNextCab,
1515 PFNFCIGETNEXTCABINET pfnfcignc,
1516 PFNFCISTATUS pfnfcis)
1517 {
1518 int err;
1519 CFHEADER cfheader;
1520 struct {
1521 cab_UWORD cbCFHeader;
1522 cab_UBYTE cbCFFolder;
1523 cab_UBYTE cbCFData;
1524 } cfreserved;
1525 CFFOLDER cffolder;
1526 cab_ULONG read_result=0;
1527 int handleCABINET; /* file handle for cabinet */
1528 char szFileNameCABINET[CB_MAX_CAB_PATH+CB_MAX_CABINET_NAME];/* name buffer */
1529 UINT cbReserveCFHeader, cbReserveCFFolder, i;
1530 char* reserved;
1531 BOOL returntrue=FALSE;
1532 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
1533
1534 /* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
1535
1536 /* when FCIFlushCabinet was or FCIAddFile hasn't been called */
1537 if( p_fci_internal->sizeFileCFFILE1==0 && fGetNextCab ) {
1538 returntrue=TRUE;
1539 }
1540
1541 if (!fci_flush_folder(hfci,fGetNextCab,pfnfcignc,pfnfcis)){
1542 /* TODO set error */
1543 return FALSE;
1544 }
1545
1546 if(returntrue) return TRUE;
1547
1548 if ( (p_fci_internal->fSplitFolder && p_fci_internal->fNextCab==FALSE)||
1549 (p_fci_internal->sizeFileCFFOLDER==0 &&
1550 (p_fci_internal->sizeFileCFFILE1!=0 ||
1551 p_fci_internal->sizeFileCFFILE2!=0 )
1552 ) )
1553 {
1554 /* error */
1555 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
1556 return FALSE;
1557 }
1558
1559 if( p_fci_internal->fNextCab ||
1560 p_fci_internal->fGetNextCabInVain ) {
1561 cbReserveCFFolder=p_fci_internal->oldCCAB.cbReserveCFFolder;
1562 cbReserveCFHeader=p_fci_internal->oldCCAB.cbReserveCFHeader;
1563 /* safety */
1564 if (strlen(p_fci_internal->oldCCAB.szCabPath)>=CB_MAX_CAB_PATH ||
1565 strlen(p_fci_internal->oldCCAB.szCab)>=CB_MAX_CABINET_NAME) {
1566 /* set error */
1567 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1568 return FALSE;
1569 }
1570 /* get the full name of the cabinet */
1571 memcpy(szFileNameCABINET,p_fci_internal->oldCCAB.szCabPath,
1572 CB_MAX_CAB_PATH);
1573 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1574 p_fci_internal->oldCCAB.szCab, CB_MAX_CABINET_NAME);
1575 } else {
1576 cbReserveCFFolder=p_fci_internal->pccab->cbReserveCFFolder;
1577 cbReserveCFHeader=p_fci_internal->pccab->cbReserveCFHeader;
1578 /* safety */
1579 if (strlen(p_fci_internal->pccab->szCabPath)>=CB_MAX_CAB_PATH ||
1580 strlen(p_fci_internal->pccab->szCab)>=CB_MAX_CABINET_NAME) {
1581 /* set error */
1582 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
1583 return FALSE;
1584 }
1585 /* get the full name of the cabinet */
1586 memcpy(szFileNameCABINET,p_fci_internal->pccab->szCabPath,
1587 CB_MAX_CAB_PATH);
1588 memcpy(szFileNameCABINET+strlen(szFileNameCABINET),
1589 p_fci_internal->pccab->szCab, CB_MAX_CABINET_NAME);
1590 }
1591
1592 memcpy(cfheader.signature,"!CAB",4);
1593 cfheader.reserved1=0;
1594 cfheader.cbCabinet= /* size of the cabinet file in bytes */
1595 sizeof(CFHEADER) +
1596 p_fci_internal->sizeFileCFFOLDER +
1597 p_fci_internal->sizeFileCFFILE2 +
1598 p_fci_internal->sizeFileCFDATA2;
1599
1600 if (p_fci_internal->fPrevCab) {
1601 cfheader.cbCabinet+=strlen(p_fci_internal->szPrevCab)+1 +
1602 strlen(p_fci_internal->szPrevDisk)+1;
1603 }
1604 if (p_fci_internal->fNextCab) {
1605 cfheader.cbCabinet+=strlen(p_fci_internal->pccab->szCab)+1 +
1606 strlen(p_fci_internal->pccab->szDisk)+1;
1607 }
1608 if( p_fci_internal->fNextCab ||
1609 p_fci_internal->fGetNextCabInVain ) {
1610 cfheader.cbCabinet+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1611 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1612 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1613 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1614 cfheader.cbCabinet+=4;
1615 }
1616 } else {
1617 cfheader.cbCabinet+=p_fci_internal->pccab->cbReserveCFHeader;
1618 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1619 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1620 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1621 cfheader.cbCabinet+=4;
1622 }
1623 }
1624
1625 if( ( ( p_fci_internal->fNextCab ||
1626 p_fci_internal->fGetNextCabInVain ) &&
1627 cfheader.cbCabinet > p_fci_internal->oldCCAB.cb
1628 ) ||
1629 ( ( p_fci_internal->fNextCab==FALSE &&
1630 p_fci_internal->fGetNextCabInVain==FALSE ) &&
1631 cfheader.cbCabinet > p_fci_internal->pccab->cb
1632 )
1633 )
1634 {
1635 fci_set_error( FCIERR_NONE, ERROR_MORE_DATA, TRUE );
1636 return FALSE;
1637 }
1638
1639
1640 cfheader.reserved2=0;
1641 cfheader.coffFiles= /* offset to first CFFILE section */
1642 cfheader.cbCabinet - p_fci_internal->sizeFileCFFILE2 -
1643 p_fci_internal->sizeFileCFDATA2;
1644
1645 cfheader.reserved3=0;
1646 cfheader.versionMinor=3;
1647 cfheader.versionMajor=1;
1648 /* number of CFFOLDER entries in the cabinet */
1649 cfheader.cFolders=p_fci_internal->cFolders;
1650 /* number of CFFILE entries in the cabinet */
1651 cfheader.cFiles=p_fci_internal->cFiles;
1652 cfheader.flags=0; /* 1=prev cab, 2=next cabinet, 4=reserved sections */
1653
1654 if( p_fci_internal->fPrevCab ) {
1655 cfheader.flags = cfheadPREV_CABINET;
1656 }
1657
1658 if( p_fci_internal->fNextCab ) {
1659 cfheader.flags |= cfheadNEXT_CABINET;
1660 }
1661
1662 if( p_fci_internal->fNextCab ||
1663 p_fci_internal->fGetNextCabInVain ) {
1664 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1665 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1666 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1667 cfheader.flags |= cfheadRESERVE_PRESENT;
1668 }
1669 cfheader.setID = p_fci_internal->oldCCAB.setID;
1670 cfheader.iCabinet = p_fci_internal->oldCCAB.iCab-1;
1671 } else {
1672 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1673 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1674 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1675 cfheader.flags |= cfheadRESERVE_PRESENT;
1676 }
1677 cfheader.setID = p_fci_internal->pccab->setID;
1678 cfheader.iCabinet = p_fci_internal->pccab->iCab-1;
1679 }
1680
1681 /* create the cabinet */
1682 handleCABINET = PFCI_OPEN(hfci, szFileNameCABINET,
1683 33538, 384, &err, p_fci_internal->pv );
1684 if(handleCABINET==0){
1685 fci_set_error( FCIERR_CAB_FILE, ERROR_OPEN_FAILED, TRUE );
1686 return FALSE;
1687 }
1688 /* TODO error checking of err */
1689
1690 /* set little endian */
1691 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1692 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1693 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1694 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1695 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1696 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1697 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1698 cfheader.flags=fci_endian_uword(cfheader.flags);
1699 cfheader.setID=fci_endian_uword(cfheader.setID);
1700 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1701
1702 /* write CFHEADER into cabinet file */
1703 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1704 &cfheader, /* memory buffer */
1705 sizeof(cfheader), /* number of bytes to copy */
1706 &err, p_fci_internal->pv) != sizeof(cfheader) ) {
1707 /* write error */
1708 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1709 return FALSE;
1710 }
1711 /* TODO error handling of err */
1712
1713 /* reset little endian */
1714 cfheader.reserved1=fci_endian_ulong(cfheader.reserved1);
1715 cfheader.cbCabinet=fci_endian_ulong(cfheader.cbCabinet);
1716 cfheader.reserved2=fci_endian_ulong(cfheader.reserved2);
1717 cfheader.coffFiles=fci_endian_ulong(cfheader.coffFiles);
1718 cfheader.reserved3=fci_endian_ulong(cfheader.reserved3);
1719 cfheader.cFolders=fci_endian_uword(cfheader.cFolders);
1720 cfheader.cFiles=fci_endian_uword(cfheader.cFiles);
1721 cfheader.flags=fci_endian_uword(cfheader.flags);
1722 cfheader.setID=fci_endian_uword(cfheader.setID);
1723 cfheader.iCabinet=fci_endian_uword(cfheader.iCabinet);
1724
1725 if( cfheader.flags & cfheadRESERVE_PRESENT ) {
1726 /* NOTE: No checks for maximum value overflows as designed by MS!!! */
1727 cfreserved.cbCFHeader = cbReserveCFHeader;
1728 cfreserved.cbCFFolder = cbReserveCFFolder;
1729 if( p_fci_internal->fNextCab ||
1730 p_fci_internal->fGetNextCabInVain ) {
1731 cfreserved.cbCFData = p_fci_internal->oldCCAB.cbReserveCFData;
1732 } else {
1733 cfreserved.cbCFData = p_fci_internal->pccab->cbReserveCFData;
1734 }
1735
1736 /* set little endian */
1737 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1738
1739 /* write reserved info into cabinet file */
1740 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1741 &cfreserved, /* memory buffer */
1742 sizeof(cfreserved), /* number of bytes to copy */
1743 &err, p_fci_internal->pv) != sizeof(cfreserved) ) {
1744 /* write error */
1745 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1746 return FALSE;
1747 }
1748 /* TODO error handling of err */
1749
1750 /* reset little endian */
1751 cfreserved.cbCFHeader=fci_endian_uword(cfreserved.cbCFHeader);
1752 }
1753
1754 /* add optional reserved area */
1755 if (cbReserveCFHeader!=0) {
1756 if(!(reserved = PFCI_ALLOC(hfci, cbReserveCFHeader))) {
1757 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1758 return FALSE;
1759 }
1760 for(i=0;i<cbReserveCFHeader;) {
1761 reserved[i++]='\0';
1762 }
1763 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1764 reserved, /* memory buffer */
1765 cbReserveCFHeader, /* number of bytes to copy */
1766 &err, p_fci_internal->pv) != cbReserveCFHeader ) {
1767 PFCI_FREE(hfci, reserved);
1768 /* write error */
1769 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1770 return FALSE;
1771 }
1772 /* TODO error handling of err */
1773 PFCI_FREE(hfci, reserved);
1774 }
1775
1776 if( cfheader.flags & cfheadPREV_CABINET ) {
1777 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1778 p_fci_internal->szPrevCab, /* memory buffer */
1779 strlen(p_fci_internal->szPrevCab)+1, /* number of bytes to copy */
1780 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevCab)+1 ) {
1781 /* write error */
1782 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1783 return FALSE;
1784 }
1785 /* TODO error handling of err */
1786
1787 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1788 p_fci_internal->szPrevDisk, /* memory buffer */
1789 strlen(p_fci_internal->szPrevDisk)+1, /* number of bytes to copy */
1790 &err, p_fci_internal->pv) != strlen(p_fci_internal->szPrevDisk)+1 ) {
1791 /* write error */
1792 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1793 return FALSE;
1794 }
1795 /* TODO error handling of err */
1796 }
1797
1798 if( cfheader.flags & cfheadNEXT_CABINET ) {
1799 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1800 p_fci_internal->pccab->szCab, /* memory buffer */
1801 strlen(p_fci_internal->pccab->szCab)+1, /* number of bytes to copy */
1802 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szCab)+1 ) {
1803 /* write error */
1804 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1805 return FALSE;
1806 }
1807 /* TODO error handling of err */
1808
1809 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1810 p_fci_internal->pccab->szDisk, /* memory buffer */
1811 strlen(p_fci_internal->pccab->szDisk)+1, /* number of bytes to copy */
1812 &err, p_fci_internal->pv) != strlen(p_fci_internal->pccab->szDisk)+1 ) {
1813 /* write error */
1814 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1815 return FALSE;
1816 }
1817 /* TODO error handling of err */
1818 }
1819
1820 /* set seek of p_fci_internal->handleCFFOLDER to 0 */
1821 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFOLDER,
1822 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1823 /* wrong return value */
1824 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1825 return FALSE;
1826 }
1827 /* TODO error handling of err */
1828
1829 /* while not all CFFOLDER structures have been copied into the cabinet do */
1830 while(!FALSE) {
1831 /* use the variable read_result */
1832 /* read cffolder of p_fci_internal->handleCFFOLDER */
1833 read_result = PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* handle */
1834 &cffolder, /* memory buffer */
1835 sizeof(cffolder), /* number of bytes to copy */
1836 &err, p_fci_internal->pv);
1837 if( read_result != sizeof(cffolder) ) {
1838 if( read_result == 0 ) break;/*ALL CFFOLDER structures have been copied*/
1839 /* read error */
1840 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
1841 return FALSE;
1842 }
1843 /* TODO error handling of err */
1844
1845 /* add size of header size of all CFFOLDERs and size of all CFFILEs */
1846 cffolder.coffCabStart +=
1847 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
1848 sizeof(CFHEADER);
1849 if( p_fci_internal->fNextCab ||
1850 p_fci_internal->fGetNextCabInVain ) {
1851 cffolder.coffCabStart+=p_fci_internal->oldCCAB.cbReserveCFHeader;
1852 } else {
1853 cffolder.coffCabStart+=p_fci_internal->pccab->cbReserveCFHeader;
1854 }
1855
1856 if (p_fci_internal->fPrevCab) {
1857 cffolder.coffCabStart += strlen(p_fci_internal->szPrevCab)+1 +
1858 strlen(p_fci_internal->szPrevDisk)+1;
1859 }
1860
1861 if (p_fci_internal->fNextCab) {
1862 cffolder.coffCabStart += strlen(p_fci_internal->oldCCAB.szCab)+1 +
1863 strlen(p_fci_internal->oldCCAB.szDisk)+1;
1864 }
1865
1866 if( p_fci_internal->fNextCab ||
1867 p_fci_internal->fGetNextCabInVain ) {
1868 cffolder.coffCabStart += p_fci_internal->oldCCAB.cbReserveCFHeader;
1869 if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
1870 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
1871 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
1872 cffolder.coffCabStart += 4;
1873 }
1874 } else {
1875 cffolder.coffCabStart += p_fci_internal->pccab->cbReserveCFHeader;
1876 if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
1877 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
1878 p_fci_internal->pccab->cbReserveCFData != 0 ) {
1879 cffolder.coffCabStart += 4;
1880 }
1881 }
1882
1883 /* set little endian */
1884 cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
1885 cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
1886 cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
1887
1888 /* write cffolder to cabinet file */
1889 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1890 &cffolder, /* memory buffer */
1891 sizeof(cffolder), /* number of bytes to copy */
1892 &err, p_fci_internal->pv) != sizeof(cffolder) ) {
1893 /* write error */
1894 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1895 return FALSE;
1896 }
1897 /* TODO error handling of err */
1898
1899 /* reset little endian */
1900 cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
1901 cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
1902 cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
1903
1904 /* add optional reserved area */
1905
1906 /* This allocation and freeing at each CFFolder block is a bit */
1907 /* inefficient, but it's harder to forget about freeing the buffer :-). */
1908 /* Reserved areas are used seldom besides that... */
1909 if (cbReserveCFFolder!=0) {
1910 if(!(reserved = PFCI_ALLOC(hfci, cbReserveCFFolder))) {
1911 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
1912 return FALSE;
1913 }
1914
1915 if( PFCI_READ(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
1916 reserved, /* memory buffer */
1917 cbReserveCFFolder, /* number of bytes to copy */
1918 &err, p_fci_internal->pv) != cbReserveCFFolder ) {
1919 PFCI_FREE(hfci, reserved);
1920 /* read error */
1921 fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
1922 return FALSE;
1923 }
1924 /* TODO error handling of err */
1925
1926 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1927 reserved, /* memory buffer */
1928 cbReserveCFFolder, /* number of bytes to copy */
1929 &err, p_fci_internal->pv) != cbReserveCFFolder ) {
1930 PFCI_FREE(hfci, reserved);
1931 /* write error */
1932 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1933 return FALSE;
1934 }
1935 /* TODO error handling of err */
1936
1937 PFCI_FREE(hfci, reserved);
1938 }
1939
1940 } /* END OF while */
1941
1942 /* set seek of p_fci_internal->handleCFFILE2 to 0 */
1943 if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE2,
1944 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1945 /* wrong return value */
1946 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1947 return FALSE;
1948 }
1949 /* TODO error handling of err */
1950
1951 /* while not all CFFILE structures have been copied to the cabinet do */
1952 if (p_fci_internal->data_out) while(!FALSE) {
1953 /* REUSE the variable read_result */
1954 /* REUSE the buffer p_fci_internal->data_out AGAIN */
1955 /* read a block from p_fci_internal->handleCFFILE2 */
1956 read_result = PFCI_READ(hfci, p_fci_internal->handleCFFILE2 /* handle */,
1957 p_fci_internal->data_out, /* memory buffer */
1958 CB_MAX_CHUNK, /* number of bytes to copy */
1959 &err, p_fci_internal->pv);
1960 if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
1961 /* TODO error handling of err */
1962
1963 /* write the block to the cabinet file */
1964 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
1965 p_fci_internal->data_out, /* memory buffer */
1966 read_result, /* number of bytes to copy */
1967 &err, p_fci_internal->pv) != read_result ) {
1968 /* write error */
1969 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
1970 return FALSE;
1971 }
1972 /* TODO error handling of err */
1973
1974 if (p_fci_internal->fSplitFolder==FALSE) {
1975 p_fci_internal->statusFolderCopied = 0;
1976 /* TODO TEST THIS further */
1977 p_fci_internal->statusFolderTotal = p_fci_internal->sizeFileCFDATA2+
1978 p_fci_internal->sizeFileCFFILE2;
1979 }
1980 p_fci_internal->statusFolderCopied += read_result;
1981
1982 /* report status with pfnfcis about copied size of folder */
1983 if( (*pfnfcis)(statusFolder,
1984 p_fci_internal->statusFolderCopied, /* length of copied blocks */
1985 p_fci_internal->statusFolderTotal, /* total size of folder */
1986 p_fci_internal->pv) == -1) {
1987 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
1988 return FALSE;
1989 }
1990
1991 } /* END OF while */
1992
1993 /* set seek of p_fci_internal->handleCFDATA2 to 0 */
1994 if( PFCI_SEEK(hfci,p_fci_internal->handleCFDATA2,
1995 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
1996 /* wrong return value */
1997 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
1998 return FALSE;
1999 }
2000 /* TODO error handling of err */
2001
2002 /* reset the number of folders for the next cabinet */
2003 p_fci_internal->cFolders=0;
2004 /* reset the number of files for the next cabinet */
2005 p_fci_internal->cFiles=0;
2006
2007 /* while not all CFDATA structures have been copied to the cabinet do */
2008 if (p_fci_internal->data_out) while(!FALSE) {
2009 /* REUSE the variable read_result AGAIN */
2010 /* REUSE the buffer p_fci_internal->data_out AGAIN */
2011 /* read a block from p_fci_internal->handleCFDATA2 */
2012 read_result = PFCI_READ(hfci, p_fci_internal->handleCFDATA2 /* handle */,
2013 p_fci_internal->data_out, /* memory buffer */
2014 CB_MAX_CHUNK, /* number of bytes to copy */
2015 &err, p_fci_internal->pv);
2016 if( read_result == 0 ) break; /* ALL CFDATA structures have been copied */
2017 /* TODO error handling of err */
2018
2019 /* write the block to the cabinet file */
2020 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
2021 p_fci_internal->data_out, /* memory buffer */
2022 read_result, /* number of bytes to copy */
2023 &err, p_fci_internal->pv) != read_result ) {
2024 /* write error */
2025 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
2026 return FALSE;
2027 }
2028 /* TODO error handling of err */
2029
2030 p_fci_internal->statusFolderCopied += read_result;
2031 /* report status with pfnfcis about copied size of folder */
2032 if( (*pfnfcis)(statusFolder,
2033 p_fci_internal->statusFolderCopied, /* length of copied blocks */
2034 p_fci_internal->statusFolderTotal, /* total size of folder */
2035 p_fci_internal->pv) == -1) {
2036 /* set error code and abort */
2037 fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
2038 return FALSE;
2039 }
2040 } /* END OF while */
2041
2042 /* set seek of the cabinet file to 0 */
2043 if( PFCI_SEEK(hfci, handleCABINET,
2044 0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) {
2045 /* wrong return value */
2046 fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
2047 return FALSE;
2048 }
2049 /* TODO error handling of err */
2050
2051 /* write the signature "MSCF" into the cabinet file */
2052 memcpy( cfheader.signature, "MSCF", 4 );
2053 if( PFCI_WRITE(hfci, handleCABINET, /* file handle */
2054 &cfheader, /* memory buffer */
2055 4, /* number of bytes to copy */
2056 &err, p_fci_internal->pv) != 4 ) {
2057 /* wrtie error */
2058 fci_set_error( FCIERR_CAB_FILE, ERROR_WRITE_FAULT, TRUE );
2059 return FALSE;
2060 }
2061 /* TODO error handling of err */
2062
2063 /* close the cabinet file */
2064 PFCI_CLOSE(hfci,handleCABINET,&err,p_fci_internal->pv);
2065 /* TODO error handling of err */
2066
2067
2068 /* COPIED FROM FCIDestroy */
2069
2070 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2071 /* TODO error handling of err */
2072 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,
2073 p_fci_internal->pv);
2074 /* TODO error handling of err */
2075 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2076 /* TODO error handling of err */
2077 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,
2078 p_fci_internal->pv);
2079 /* TODO error handling of err */
2080 PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
2081 /* TODO error handling of err */
2082 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,
2083 p_fci_internal->pv);
2084 /* TODO error handling of err */
2085
2086 /* END OF copied from FCIDestroy */
2087
2088 /* get 3 temporary files and open them */
2089 /* write names and handles to hfci */
2090
2091
2092 p_fci_internal->sizeFileCFDATA2 = 0;
2093 p_fci_internal->sizeFileCFFILE2 = 0;
2094 p_fci_internal->sizeFileCFFOLDER = 0;
2095
2096 /* COPIED FROM FCICreate */
2097
2098 /* CFDATA with checksum and ready to be copied into cabinet */
2099 if( !PFCI_GETTEMPFILE(hfci, p_fci_internal->szFileNameCFDATA2,
2100 CB_MAX_FILENAME)) {
2101 /* error handling */
2102 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2103 return FALSE;
2104 }
2105 /* safety */
2106 if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
2107 /* set error code and abort */
2108 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2109 return FALSE;
2110 }
2111 p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
2112 p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, p_fci_internal->pv);
2113 /* check handle */
2114 if(p_fci_internal->handleCFDATA2==0){
2115 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
2116 return FALSE;
2117 }
2118 /* TODO error checking of err */
2119
2120 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2121 if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
2122 CB_MAX_FILENAME)) {
2123 /* error handling */
2124 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2125 return FALSE;
2126 }
2127 /* safety */
2128 if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
2129 /* set error code and abort */
2130 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2131 return FALSE;
2132 }
2133 p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
2134 p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, p_fci_internal->pv);
2135 /* check handle */
2136 if(p_fci_internal->handleCFFILE2==0){
2137 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
2138 return FALSE;
2139 }
2140 /* TODO error checking of err */
2141
2142 /* array of all CFFILE in a folder, ready to be copied into cabinet */
2143 if (!PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,CB_MAX_FILENAME)) {
2144 /* error handling */
2145 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2146 return FALSE;
2147 }
2148 /* safety */
2149 if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
2150 /* set error code and abort */
2151 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2152 return FALSE;
2153 }
2154 p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
2155 p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, p_fci_internal->pv);
2156 /* check handle */
2157 if(p_fci_internal->handleCFFOLDER==0){
2158 fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
2159 return FALSE;
2160 }
2161 /* TODO error checking of err */
2162
2163 /* END OF copied from FCICreate */
2164
2165
2166 /* TODO close and delete new files when return FALSE */
2167
2168
2169 /* report status with pfnfcis about copied size of folder */
2170 (*pfnfcis)(statusCabinet,
2171 p_fci_internal->estimatedCabinetSize, /* estimated cabinet file size */
2172 cfheader.cbCabinet /* real cabinet file size */, p_fci_internal->pv);
2173
2174 p_fci_internal->fPrevCab=TRUE;
2175 /* The sections szPrevCab and szPrevDisk are not being updated, because */
2176 /* MS CABINET.DLL always puts the first cabinet name and disk into them */
2177
2178 if (p_fci_internal->fNextCab) {
2179 p_fci_internal->fNextCab=FALSE;
2180
2181 if (p_fci_internal->sizeFileCFFILE1==0 && p_fci_internal->sizeFileCFDATA1!=0) {
2182 /* THIS CAN NEVER HAPPEN */
2183 /* set error code */
2184 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2185 return FALSE;
2186 }
2187
2188 /* COPIED FROM FCIAddFile and modified */
2189
2190 /* REUSE the variable read_result */
2191 if (p_fci_internal->fGetNextCabInVain) {
2192 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader;
2193 if(p_fci_internal->sizeFileCFFILE1!=0) {
2194 read_result+=p_fci_internal->oldCCAB.cbReserveCFFolder;
2195 }
2196 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2197 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2198 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2199 read_result+=4;
2200 }
2201 } else {
2202 read_result=p_fci_internal->pccab->cbReserveCFHeader;
2203 if(p_fci_internal->sizeFileCFFILE1!=0) {
2204 read_result+=p_fci_internal->pccab->cbReserveCFFolder;
2205 }
2206 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2207 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2208 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2209 read_result+=4;
2210 }
2211 }
2212 if ( p_fci_internal->fPrevCab ) {
2213 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2214 strlen(p_fci_internal->szPrevDisk)+1;
2215 }
2216 read_result+= p_fci_internal->sizeFileCFDATA1 +
2217 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2218 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2219 sizeof(CFHEADER) +
2220 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2221
2222 if( p_fci_internal->fNewPrevious ) {
2223 memcpy(p_fci_internal->szPrevCab, p_fci_internal->oldCCAB.szCab,
2224 CB_MAX_CABINET_NAME);
2225 memcpy(p_fci_internal->szPrevDisk, p_fci_internal->oldCCAB.szDisk,
2226 CB_MAX_DISK_NAME);
2227 p_fci_internal->fNewPrevious=FALSE;
2228 }
2229
2230 /* too much data for the maximum size of a cabinet */
2231 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2232 p_fci_internal->pccab->cb < read_result ) {
2233 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2234 }
2235
2236 /* Might be too much data for the maximum size of a cabinet.*/
2237 /* When any further data will be added later, it might not */
2238 /* be possible to flush the cabinet, because there might */
2239 /* not be enough space to store the name of the following */
2240 /* cabinet and name of the corresponding disk. */
2241 /* So take care of this and get the name of the next cabinet */
2242 if (p_fci_internal->fGetNextCabInVain==FALSE && (
2243 p_fci_internal->pccab->cb < read_result +
2244 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2245 )) {
2246 /* save CCAB */
2247 p_fci_internal->oldCCAB = *p_fci_internal->pccab;
2248 /* increment cabinet index */
2249 ++(p_fci_internal->pccab->iCab);
2250 /* get name of next cabinet */
2251 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2252 if (!(*pfnfcignc)(p_fci_internal->pccab,
2253 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2254 p_fci_internal->pv)) {
2255 /* error handling */
2256 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2257 return FALSE;
2258 }
2259 /* Skip a few lines of code. This is caught by the next if. */
2260 p_fci_internal->fGetNextCabInVain=TRUE;
2261 }
2262
2263 /* too much data for cabinet */
2264 if (p_fci_internal->fGetNextCabInVain && (
2265 p_fci_internal->oldCCAB.cb < read_result +
2266 strlen(p_fci_internal->oldCCAB.szCab)+1+
2267 strlen(p_fci_internal->oldCCAB.szDisk)+1
2268 )) {
2269 p_fci_internal->fGetNextCabInVain=FALSE;
2270 p_fci_internal->fNextCab=TRUE;
2271 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2272 }
2273
2274 /* if the FolderThreshold has been reached flush the folder automatically */
2275 if( p_fci_internal->fGetNextCabInVain ) {
2276 if( p_fci_internal->cCompressedBytesInFolder >=
2277 p_fci_internal->oldCCAB.cbFolderThresh) {
2278 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2279 }
2280 } else {
2281 if( p_fci_internal->cCompressedBytesInFolder >=
2282 p_fci_internal->pccab->cbFolderThresh) {
2283 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2284 }
2285 }
2286
2287 /* END OF COPIED FROM FCIAddFile and modified */
2288
2289 if( p_fci_internal->sizeFileCFFILE1>0 ) {
2290 if( !FCIFlushFolder(hfci, pfnfcignc, pfnfcis) ) return FALSE;
2291 p_fci_internal->fNewPrevious=TRUE;
2292 }
2293 } else {
2294 p_fci_internal->fNewPrevious=FALSE;
2295 if( p_fci_internal->sizeFileCFFILE1>0 || p_fci_internal->sizeFileCFDATA1) {
2296 /* THIS MAY NEVER HAPPEN */
2297 /* set error structures */
2298 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2299 return FALSE;
2300 }
2301 }
2302
2303 return TRUE;
2304 } /* end of fci_flush_cabinet */
2305
2306
2307
2308
2309
2310 /***********************************************************************
2311 * FCIAddFile (CABINET.11)
2312 *
2313 * FCIAddFile adds a file to the to be created cabinet file
2314 *
2315 * PARAMS
2316 * hfci [I] An HFCI from FCICreate
2317 * pszSourceFile [I] A pointer to a C string which contains the name and
2318 * location of the file which will be added to the cabinet
2319 * pszFileName [I] A pointer to a C string which contains the name under
2320 * which the file will be stored in the cabinet
2321 * fExecute [I] A boolean value which indicates if the file should be
2322 * executed after extraction of self extracting
2323 * executables
2324 * pfnfcignc [I] A pointer to a function which gets information about
2325 * the next cabinet
2326 * pfnfcis [IO] A pointer to a function which will report status
2327 * information about the compression process
2328 * pfnfcioi [I] A pointer to a function which reports file attributes
2329 * and time and date information
2330 * typeCompress [I] Compression type
2331 *
2332 * RETURNS
2333 * On success, returns TRUE
2334 * On failure, returns FALSE
2335 *
2336 * INCLUDES
2337 * fci.h
2338 *
2339 */
2340 BOOL __cdecl FCIAddFile(
2341 HFCI hfci,
2342 char *pszSourceFile,
2343 char *pszFileName,
2344 BOOL fExecute,
2345 PFNFCIGETNEXTCABINET pfnfcignc,
2346 PFNFCISTATUS pfnfcis,
2347 PFNFCIGETOPENINFO pfnfcigoi,
2348 TCOMP typeCompress)
2349 {
2350 int err;
2351 CFFILE cffile;
2352 cab_ULONG read_result;
2353 int file_handle;
2354 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2355
2356 /* test hfci */
2357 if (!REALLY_IS_FCI(hfci)) {
2358 SetLastError(ERROR_INVALID_HANDLE);
2359 return FALSE;
2360 }
2361
2362 if ((!pszSourceFile) || (!pszFileName) || (!pfnfcignc) || (!pfnfcis) ||
2363 (!pfnfcigoi) || strlen(pszFileName)>=CB_MAX_FILENAME) {
2364 fci_set_error( FCIERR_NONE, ERROR_BAD_ARGUMENTS, TRUE );
2365 return FALSE;
2366 }
2367
2368 /* TODO check if pszSourceFile??? */
2369
2370 if(p_fci_internal->fGetNextCabInVain && p_fci_internal->fNextCab) {
2371 /* internal error */
2372 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2373 return FALSE;
2374 }
2375
2376 if(p_fci_internal->fNextCab) {
2377 /* internal error */
2378 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2379 return FALSE;
2380 }
2381
2382 cffile.cbFile=0; /* size of the to be added file*/
2383 /* offset of the uncompressed file in the folder */
2384 cffile.uoffFolderStart=p_fci_internal->cDataBlocks*CAB_BLOCKMAX + p_fci_internal->cdata_in;
2385 /* number of folder in the cabinet or special 0=first */
2386 cffile.iFolder = p_fci_internal->cFolders;
2387
2388 /* allocation of memory */
2389 if (p_fci_internal->data_in==NULL) {
2390 if (p_fci_internal->cdata_in!=0) {
2391 /* error handling */
2392 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2393 return FALSE;
2394 }
2395 if (p_fci_internal->data_out!=NULL) {
2396 /* error handling */
2397 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2398 return FALSE;
2399 }
2400 if(!(p_fci_internal->data_in = PFCI_ALLOC(hfci,CB_MAX_CHUNK))) {
2401 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
2402 return FALSE;
2403 }
2404 if (p_fci_internal->data_out==NULL) {
2405 if(!(p_fci_internal->data_out = PFCI_ALLOC(hfci, 2 * CB_MAX_CHUNK))){
2406 fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
2407 return FALSE;
2408 }
2409 }
2410 }
2411
2412 if (p_fci_internal->data_out==NULL) {
2413 PFCI_FREE(hfci,p_fci_internal->data_in);
2414 /* error handling */
2415 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2416 return FALSE;
2417 }
2418
2419 /* get information about the file */
2420 /* set defaults in case callback doesn't set one or more fields */
2421 cffile.attribs=0;
2422 cffile.date=0;
2423 cffile.time=0;
2424 file_handle=(*pfnfcigoi)(pszSourceFile, &(cffile.date), &(cffile.time),
2425 &(cffile.attribs), &err, p_fci_internal->pv);
2426 /* check file_handle */
2427 if(file_handle==0){
2428 fci_set_error( FCIERR_OPEN_SRC, ERROR_OPEN_FAILED, TRUE );
2429 }
2430 /* TODO error handling of err */
2431
2432 if (fExecute) { cffile.attribs |= _A_EXEC; }
2433
2434 /* REUSE the variable read_result */
2435 if (p_fci_internal->fGetNextCabInVain) {
2436 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2437 p_fci_internal->oldCCAB.cbReserveCFFolder;
2438 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2439 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2440 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2441 read_result+=4;
2442 }
2443 } else {
2444 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2445 p_fci_internal->pccab->cbReserveCFFolder;
2446 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2447 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2448 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2449 read_result+=4;
2450 }
2451 }
2452 if ( p_fci_internal->fPrevCab ) {
2453 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2454 strlen(p_fci_internal->szPrevDisk)+1;
2455 }
2456 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2457 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2458 strlen(p_fci_internal->pccab->szDisk)+1;
2459 }
2460
2461 read_result+= sizeof(CFFILE) + strlen(pszFileName)+1 +
2462 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2463 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2464 sizeof(CFHEADER) +
2465 sizeof(CFFOLDER); /* size of new CFFolder entry */
2466
2467 /* Might be too much data for the maximum size of a cabinet.*/
2468 /* When any further data will be added later, it might not */
2469 /* be possible to flush the cabinet, because there might */
2470 /* not be enough space to store the name of the following */
2471 /* cabinet and name of the corresponding disk. */
2472 /* So take care of this and get the name of the next cabinet */
2473 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2474 p_fci_internal->fNextCab==FALSE &&
2475 ( p_fci_internal->pccab->cb < read_result +
2476 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2477 )
2478 ) {
2479 /* save CCAB */
2480 p_fci_internal->oldCCAB = *p_fci_internal->pccab;
2481 /* increment cabinet index */
2482 ++(p_fci_internal->pccab->iCab);
2483 /* get name of next cabinet */
2484 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2485 if (!(*pfnfcignc)(p_fci_internal->pccab,
2486 p_fci_internal->estimatedCabinetSize, /* estimated size of cab */
2487 p_fci_internal->pv)) {
2488 /* error handling */
2489 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2490 return FALSE;
2491 }
2492 /* Skip a few lines of code. This is caught by the next if. */
2493 p_fci_internal->fGetNextCabInVain=TRUE;
2494 }
2495
2496 if( p_fci_internal->fGetNextCabInVain &&
2497 p_fci_internal->fNextCab
2498 ) {
2499 /* THIS CAN NEVER HAPPEN */
2500 /* set error code */
2501 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2502 return FALSE;
2503 }
2504
2505 /* too much data for cabinet */
2506 if( p_fci_internal->fGetNextCabInVain &&
2507 (
2508 p_fci_internal->oldCCAB.cb < read_result +
2509 strlen(p_fci_internal->pccab->szCab)+1+
2510 strlen(p_fci_internal->pccab->szDisk)+1
2511 )) {
2512 p_fci_internal->fGetNextCabInVain=FALSE;
2513 p_fci_internal->fNextCab=TRUE;
2514 if(!fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis)) return FALSE;
2515 }
2516
2517 if( p_fci_internal->fNextCab ) {
2518 /* THIS MAY NEVER HAPPEN */
2519 /* set error code */
2520 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2521 return FALSE;
2522 }
2523
2524 /* read the contents of the file blockwise */
2525 while (!FALSE) {
2526 if (p_fci_internal->cdata_in > CAB_BLOCKMAX) {
2527 /* internal error */
2528 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2529 return FALSE;
2530 }
2531
2532 read_result = PFCI_READ(hfci, file_handle /* file handle */,
2533 (p_fci_internal->data_in + p_fci_internal->cdata_in) /* memory buffer */,
2534 (CAB_BLOCKMAX - p_fci_internal->cdata_in) /* number of bytes to copy */,
2535 &err, p_fci_internal->pv);
2536 /* TODO error handling of err */
2537
2538 if( read_result==0 ) break;
2539
2540 /* increment the block size */
2541 p_fci_internal->cdata_in += read_result;
2542
2543 /* increment the file size */
2544 cffile.cbFile += read_result;
2545
2546 if ( p_fci_internal->cdata_in > CAB_BLOCKMAX ) {
2547 /* report internal error */
2548 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2549 return FALSE;
2550 }
2551 /* write a whole block */
2552 if ( p_fci_internal->cdata_in == CAB_BLOCKMAX ) {
2553
2554 if( !fci_flush_data_block(hfci, &err, pfnfcis) ) return FALSE;
2555 }
2556 }
2557
2558 /* close the file from FCIAddFile */
2559 PFCI_CLOSE(hfci,file_handle,&err,p_fci_internal->pv);
2560 /* TODO error handling of err */
2561
2562 /* write cffile to p_fci_internal->handleCFFILE1 */
2563 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */
2564 &cffile, sizeof(cffile),&err, p_fci_internal->pv) != sizeof(cffile) ) {
2565 /* write error */
2566 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
2567 return FALSE;
2568 }
2569 /* TODO error handling of err */
2570
2571 p_fci_internal->sizeFileCFFILE1 += sizeof(cffile);
2572
2573 /* append the name of file */
2574 if (strlen(pszFileName)>=CB_MAX_FILENAME) {
2575 /* IMPOSSIBLE */
2576 /* set error code */
2577 fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
2578 return FALSE;
2579 }
2580 if( PFCI_WRITE(hfci, p_fci_internal->handleCFFILE1, /* file handle */
2581 pszFileName, strlen(pszFileName)+1, &err, p_fci_internal->pv)
2582 != strlen(pszFileName)+1 ) {
2583 /* write error */
2584 fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
2585 return FALSE;
2586 }
2587 /* TODO error handling of err */
2588
2589 p_fci_internal->sizeFileCFFILE1 += strlen(pszFileName)+1;
2590
2591 /* REUSE the variable read_result */
2592 if (p_fci_internal->fGetNextCabInVain ||
2593 p_fci_internal->fNextCab
2594 ) {
2595 read_result=p_fci_internal->oldCCAB.cbReserveCFHeader +
2596 p_fci_internal->oldCCAB.cbReserveCFFolder;
2597 if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
2598 p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
2599 p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
2600 read_result+=4;
2601 }
2602 } else {
2603 read_result=p_fci_internal->pccab->cbReserveCFHeader +
2604 p_fci_internal->pccab->cbReserveCFFolder;
2605 if ( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
2606 p_fci_internal->pccab->cbReserveCFFolder != 0 ||
2607 p_fci_internal->pccab->cbReserveCFData != 0 ) {
2608 read_result+=4;
2609 }
2610 }
2611 if ( p_fci_internal->fPrevCab ) {
2612 read_result+= strlen(p_fci_internal->szPrevCab)+1+
2613 strlen(p_fci_internal->szPrevDisk)+1;
2614 }
2615 if ( p_fci_internal->fNextCab ) { /* this is never the case */
2616 read_result+= strlen(p_fci_internal->pccab->szCab)+1+
2617 strlen(p_fci_internal->pccab->szDisk)+1;
2618 }
2619 read_result+= p_fci_internal->sizeFileCFDATA1 +
2620 p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
2621 p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
2622 sizeof(CFHEADER) +
2623 sizeof(CFFOLDER); /* set size of new CFFolder entry */
2624
2625 /* too much data for the maximum size of a cabinet */
2626 /* (ignoring the unflushed data block) */
2627 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2628 p_fci_internal->fNextCab==FALSE && /* this is always the case */
2629 p_fci_internal->pccab->cb < read_result ) {
2630 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2631 }
2632
2633 /* Might be too much data for the maximum size of a cabinet.*/
2634 /* When any further data will be added later, it might not */
2635 /* be possible to flush the cabinet, because there might */
2636 /* not be enough space to store the name of the following */
2637 /* cabinet and name of the corresponding disk. */
2638 /* So take care of this and get the name of the next cabinet */
2639 /* (ignoring the unflushed data block) */
2640 if( p_fci_internal->fGetNextCabInVain==FALSE &&
2641 p_fci_internal->fNextCab==FALSE &&
2642 ( p_fci_internal->pccab->cb < read_result +
2643 CB_MAX_CABINET_NAME + CB_MAX_DISK_NAME
2644 )
2645 ) {
2646 /* save CCAB */
2647 p_fci_internal->oldCCAB = *p_fci_internal->pccab;
2648 /* increment cabinet index */
2649 ++(p_fci_internal->pccab->iCab);
2650 /* get name of next cabinet */
2651 p_fci_internal->estimatedCabinetSize=p_fci_internal->statusFolderTotal;
2652 if (!(*pfnfcignc)(p_fci_internal->pccab,
2653 p_fci_internal->estimatedCabinetSize,/* estimated size of cab */
2654 p_fci_internal->pv)) {
2655 /* error handling */
2656 fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
2657 return FALSE;
2658 }
2659 /* Skip a few lines of code. This is caught by the next if. */
2660 p_fci_internal->fGetNextCabInVain=TRUE;
2661 }
2662
2663 if( p_fci_internal->fGetNextCabInVain &&
2664 p_fci_internal->fNextCab
2665 ) {
2666 /* THIS CAN NEVER HAPPEN */
2667 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2668 return FALSE;
2669 }
2670
2671 /* too much data for cabinet */
2672 if( (p_fci_internal->fGetNextCabInVain ||
2673 p_fci_internal->fNextCab) && (
2674 p_fci_internal->oldCCAB.cb < read_result +
2675 strlen(p_fci_internal->pccab->szCab)+1+
2676 strlen(p_fci_internal->pccab->szDisk)+1
2677 )) {
2678
2679 p_fci_internal->fGetNextCabInVain=FALSE;
2680 p_fci_internal->fNextCab=TRUE;
2681 return fci_flush_cabinet( hfci, FALSE, pfnfcignc, pfnfcis);
2682 }
2683
2684 if( p_fci_internal->fNextCab ) {
2685 /* THIS MAY NEVER HAPPEN */
2686 /* set error code */
2687 fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
2688 return FALSE;
2689 }
2690
2691 /* if the FolderThreshold has been reached flush the folder automatically */
2692 if( p_fci_internal->fGetNextCabInVain ) {
2693 if( p_fci_internal->cCompressedBytesInFolder >=
2694 p_fci_internal->oldCCAB.cbFolderThresh) {
2695 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2696 }
2697 } else {
2698 if( p_fci_internal->cCompressedBytesInFolder >=
2699 p_fci_internal->pccab->cbFolderThresh) {
2700 return FCIFlushFolder(hfci, pfnfcignc, pfnfcis);
2701 }
2702 }
2703
2704 return TRUE;
2705 } /* end of FCIAddFile */
2706
2707
2708
2709
2710
2711 /***********************************************************************
2712 * FCIFlushFolder (CABINET.12)
2713 *
2714 * FCIFlushFolder completes the CFFolder structure under construction.
2715 *
2716 * All further data which is added by FCIAddFile will be associated to
2717 * the next CFFolder structure.
2718 *
2719 * FCIFlushFolder will be called by FCIAddFile automatically if the
2720 * threshold (stored in the member cbFolderThresh of the CCAB structure
2721 * pccab passed to FCICreate) is exceeded.
2722 *
2723 * FCIFlushFolder will be called by FCIFlushFolder automatically before
2724 * any data will be written into the cabinet file.
2725 *
2726 * PARAMS
2727 * hfci [I] An HFCI from FCICreate
2728 * pfnfcignc [I] A pointer to a function which gets information about
2729 * the next cabinet
2730 * pfnfcis [IO] A pointer to a function which will report status
2731 * information about the compression process
2732 *
2733 * RETURNS
2734 * On success, returns TRUE
2735 * On failure, returns FALSE
2736 *
2737 * INCLUDES
2738 * fci.h
2739 *
2740 */
2741 BOOL __cdecl FCIFlushFolder(
2742 HFCI hfci,
2743 PFNFCIGETNEXTCABINET pfnfcignc,
2744 PFNFCISTATUS pfnfcis)
2745 {
2746 return fci_flush_folder(hfci,FALSE,pfnfcignc,pfnfcis);
2747 } /* end of FCIFlushFolder */
2748
2749
2750
2751 /***********************************************************************
2752 * FCIFlushCabinet (CABINET.13)
2753 *
2754 * FCIFlushCabinet stores the data which has been added by FCIAddFile
2755 * into the cabinet file. If the maximum cabinet size (stored in the
2756 * member cb of the CCAB structure pccab passed to FCICreate) has been
2757 * exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
2758 * The remaining data still has to be flushed manually by calling
2759 * FCIFlushCabinet.
2760 *
2761 * After FCIFlushCabinet has been called (manually) FCIAddFile must
2762 * NOT be called again. Then hfci has to be released by FCIDestroy.
2763 *
2764 * PARAMS
2765 * hfci [I] An HFCI from FCICreate
2766 * fGetNextCab [I] Whether you want to add additional files to a
2767 * cabinet set (TRUE) or whether you want to
2768 * finalize it (FALSE)
2769 * pfnfcignc [I] A pointer to a function which gets information about
2770 * the next cabinet
2771 * pfnfcis [IO] A pointer to a function which will report status
2772 * information about the compression process
2773 *
2774 * RETURNS
2775 * On success, returns TRUE
2776 * On failure, returns FALSE
2777 *
2778 * INCLUDES
2779 * fci.h
2780 *
2781 */
2782 BOOL __cdecl FCIFlushCabinet(
2783 HFCI hfci,
2784 BOOL fGetNextCab,
2785 PFNFCIGETNEXTCABINET pfnfcignc,
2786 PFNFCISTATUS pfnfcis)
2787 {
2788 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2789
2790 if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2791
2792 while( p_fci_internal->sizeFileCFFILE1>0 ||
2793 p_fci_internal->sizeFileCFFILE2>0 ) {
2794 if(!fci_flush_cabinet(hfci,fGetNextCab,pfnfcignc,pfnfcis)) return FALSE;
2795 }
2796
2797 return TRUE;
2798 } /* end of FCIFlushCabinet */
2799
2800
2801 /***********************************************************************
2802 * FCIDestroy (CABINET.14)
2803 *
2804 * Frees a handle created by FCICreate.
2805 * Only reason for failure would be an invalid handle.
2806 *
2807 * PARAMS
2808 * hfci [I] The HFCI to free
2809 *
2810 * RETURNS
2811 * TRUE for success
2812 * FALSE for failure
2813 */
2814 BOOL __cdecl FCIDestroy(HFCI hfci)
2815 {
2816 int err;
2817 PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
2818 if (REALLY_IS_FCI(hfci)) {
2819
2820 /* before hfci can be removed all temporary files must be closed */
2821 /* and deleted */
2822 p_fci_internal->FCI_Intmagic = 0;
2823
2824 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
2825 /* TODO error handling of err */
2826 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA1, &err,
2827 p_fci_internal->pv);
2828 /* TODO error handling of err */
2829 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE1,&err,p_fci_internal->pv);
2830 /* TODO error handling of err */
2831 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE1, &err,
2832 p_fci_internal->pv);
2833 /* TODO error handling of err */
2834 PFCI_CLOSE (hfci, p_fci_internal->handleCFDATA2,&err,p_fci_internal->pv);
2835 /* TODO error handling of err */
2836 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFDATA2, &err,
2837 p_fci_internal->pv);
2838 /* TODO error handling of err */
2839 PFCI_CLOSE (hfci, p_fci_internal->handleCFFILE2,&err,p_fci_internal->pv);
2840 /* TODO error handling of err */
2841 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFILE2, &err,
2842 p_fci_internal->pv);
2843 /* TODO error handling of err */
2844 PFCI_CLOSE (hfci, p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
2845 /* TODO error handling of err */
2846 PFCI_DELETE(hfci, p_fci_internal->szFileNameCFFOLDER, &err,
2847 p_fci_internal->pv);
2848 /* TODO error handling of err */
2849
2850 /* data in and out buffers have to be removed */
2851 if (p_fci_internal->data_in!=NULL)
2852 PFCI_FREE(hfci, p_fci_internal->data_in);
2853 if (p_fci_internal->data_out!=NULL)
2854 PFCI_FREE(hfci, p_fci_internal->data_out);
2855
2856 /* hfci can now be removed */
2857 PFCI_FREE(hfci, hfci);
2858 return TRUE;
2859 } else {
2860 SetLastError(ERROR_INVALID_HANDLE);
2861 return FALSE;
2862 }
2863
2864 } /* end of FCIDestroy */