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