~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/cabinet/fci.c

Version: ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * File Compression Interface
  3  *
  4  * Copyright 2002 Patrik Stridvall
  5  * Copyright 2005 Gerold Jens Wucherpfennig
  6  *
  7  * This library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Lesser General Public
  9  * License as published by the Free Software Foundation; either
 10  * version 2.1 of the License, or (at your option) any later version.
 11  *
 12  * This library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Lesser General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public
 18  * License along with this library; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 20  */
 21 
 22 /*
 23 
 24 There is still some work to be done:
 25 
 26 - no real compression yet
 27 - unknown behaviour if files>=2GB or cabinet >=4GB
 28 - check if the maximum size for a cabinet is too small to store any data
 29 - call pfnfcignc on exactly the same position as MS FCIAddFile in every case
 30 - probably check err
 31 
 32 */
 33 
 34 
 35 
 36 #include "config.h"
 37 
 38 #include <stdarg.h>
 39 #include <stdio.h>
 40 #include <string.h>
 41 
 42 #include "windef.h"
 43 #include "winbase.h"
 44 #include "winerror.h"
 45 #include "winternl.h"
 46 #include "fci.h"
 47 #include "cabinet.h"
 48 #include "wine/debug.h"
 49 
 50 
 51 #ifdef WORDS_BIGENDIAN
 52 #define fci_endian_ulong(x) RtlUlongByteSwap(x)
 53 #define fci_endian_uword(x) RtlUshortByteSwap(x)
 54 #else
 55 #define fci_endian_ulong(x) (x)
 56 #define fci_endian_uword(x) (x)
 57 #endif
 58 
 59 
 60 #define fci_set_error(A,B,C) do {      \
 61     p_fci_internal->perf->erfOper = A; \
 62     p_fci_internal->perf->erfType = B; \
 63     p_fci_internal->perf->fError =  C; \
 64     if (B) SetLastError(B); } while(0)
 65 
 66 
 67 typedef struct {
 68   cab_UBYTE signature[4]; /* !CAB for unfinished cabinets else MSCF */
 69   cab_ULONG reserved1;
 70   cab_ULONG cbCabinet;    /*  size of the cabinet file in bytes*/
 71   cab_ULONG reserved2;
 72   cab_ULONG coffFiles;    /* offset to first CFFILE section */
 73   cab_ULONG reserved3;
 74   cab_UBYTE versionMinor; /* 3 */
 75   cab_UBYTE versionMajor; /* 1 */
 76   cab_UWORD cFolders;     /* number of CFFOLDER entries in the cabinet*/
 77   cab_UWORD cFiles;       /* number of CFFILE entries in the cabinet*/
 78   cab_UWORD flags;        /* 1=prev cab, 2=next cabinet, 4=reserved sections*/
 79   cab_UWORD setID;        /* identification number of all cabinets in a set*/
 80   cab_UWORD iCabinet;     /* number of the cabinet in a set */
 81   /* additional area if "flags" were set*/
 82 } CFHEADER; /* minimum 36 bytes */
 83 
 84 typedef struct {
 85   cab_ULONG coffCabStart; /* offset to the folder's first CFDATA section */
 86   cab_UWORD cCFData;      /* number of this folder's CFDATA sections */
 87   cab_UWORD typeCompress; /* compression type of data in CFDATA section*/
 88   /* additional area if reserve flag was set */
 89 } CFFOLDER; /* minimum 8 bytes */
 90 
 91 typedef struct {
 92   cab_ULONG cbFile;          /* size of the uncompressed file in bytes */
 93   cab_ULONG uoffFolderStart; /* offset of the uncompressed file in the folder */
 94   cab_UWORD iFolder;         /* number of folder in the cabinet 0=first  */
 95                              /* for special values see below this structure*/
 96   cab_UWORD date;            /* last modification date*/
 97   cab_UWORD time;            /* last modification time*/
 98   cab_UWORD attribs;         /* DOS fat attributes and UTF indicator */
 99   /* ... and a C string with the name of the file */
100 } CFFILE; /* 16 bytes + name of file */
101 
102 
103 typedef struct {
104   cab_ULONG csum;          /* checksum of this entry*/
105   cab_UWORD cbData;        /* number of compressed bytes  */
106   cab_UWORD cbUncomp;      /* number of bytes when data is uncompressed */
107   /* optional reserved area */
108   /* compressed data */
109 } CFDATA;
110 
111 
112 /***********************************************************************
113  *              FCICreate (CABINET.10)
114  *
115  * FCICreate is provided with several callbacks and
116  * returns a handle which can be used to create cabinet files.
117  *
118  * PARAMS
119  *   perf       [IO]  A pointer to an ERF structure.  When FCICreate
120  *                    returns an error condition, error information may
121  *                    be found here as well as from GetLastError.
122  *   pfnfiledest [I]  A pointer to a function which is called when a file
123  *                    is placed. Only useful for subsequent cabinet files.
124  *   pfnalloc    [I]  A pointer to a function which allocates ram.  Uses
125  *                    the same interface as malloc.
126  *   pfnfree     [I]  A pointer to a function which frees ram.  Uses the
127  *                    same interface as free.
128  *   pfnopen     [I]  A pointer to a function which opens a file.  Uses
129  *                    the same interface as _open.
130  *   pfnread     [I]  A pointer to a function which reads from a file into
131  *                    a caller-provided buffer.  Uses the same interface
132  *                    as _read.
133  *   pfnwrite    [I]  A pointer to a function which writes to a file from
134  *                    a caller-provided buffer.  Uses the same interface
135  *                    as _write.
136  *   pfnclose    [I]  A pointer to a function which closes a file handle.
137  *                    Uses the same interface as _close.
138  *   pfnseek     [I]  A pointer to a function which seeks in a file.
139  *                    Uses the same interface as _lseek.
140  *   pfndelete   [I]  A pointer to a function which deletes a file.
141  *   pfnfcigtf   [I]  A pointer to a function which gets the name of a
142  *                    temporary file.
143  *   pccab       [I]  A pointer to an initialized CCAB structure.
144  *   pv          [I]  A pointer to an application-defined notification
145  *                    function which will be passed to other FCI functions
146  *                    as a parameter.
147  *
148  * RETURNS
149  *   On success, returns an FCI handle of type HFCI.
150  *   On failure, the NULL file handle is returned. Error
151  *   info can be retrieved from perf.
152  *
153  * INCLUDES
154  *   fci.h
155  *
156  */
157 HFCI __cdecl FCICreate(
158         PERF perf,
159         PFNFCIFILEPLACED   pfnfiledest,
160         PFNFCIALLOC        pfnalloc,
161         PFNFCIFREE         pfnfree,
162         PFNFCIOPEN         pfnopen,
163         PFNFCIREAD         pfnread,
164         PFNFCIWRITE        pfnwrite,
165         PFNFCICLOSE        pfnclose,
166         PFNFCISEEK         pfnseek,
167         PFNFCIDELETE       pfndelete,
168         PFNFCIGETTEMPFILE  pfnfcigtf,
169         PCCAB              pccab,
170         void *pv)
171 {
172   HFCI hfci;
173   int err;
174   PFCI_Int p_fci_internal;
175 
176   if (!perf) {
177     SetLastError(ERROR_BAD_ARGUMENTS);
178     return NULL;
179   }
180   if ((!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) ||
181       (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) ||
182       (!pfnfcigtf) || (!pccab)) {
183     perf->erfOper = FCIERR_NONE;
184     perf->erfType = ERROR_BAD_ARGUMENTS;
185     perf->fError = TRUE;
186 
187     SetLastError(ERROR_BAD_ARGUMENTS);
188     return NULL;
189   }
190 
191   if (!((hfci = (*pfnalloc)(sizeof(FCI_Int))))) {
192     perf->erfOper = FCIERR_ALLOC_FAIL;
193     perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
194     perf->fError = TRUE;
195 
196     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
197     return NULL;
198   }
199 
200   p_fci_internal=((PFCI_Int)(hfci));
201   p_fci_internal->FCI_Intmagic = FCI_INT_MAGIC;
202   p_fci_internal->perf = perf;
203   p_fci_internal->pfnfiledest = pfnfiledest;
204   p_fci_internal->pfnalloc = pfnalloc;
205   p_fci_internal->pfnfree = pfnfree;
206   p_fci_internal->pfnopen = pfnopen;
207   p_fci_internal->pfnread = pfnread;
208   p_fci_internal->pfnwrite = pfnwrite;
209   p_fci_internal->pfnclose = pfnclose;
210   p_fci_internal->pfnseek = pfnseek;
211   p_fci_internal->pfndelete = pfndelete;
212   p_fci_internal->pfnfcigtf = pfnfcigtf;
213   p_fci_internal->pccab = pccab;
214   p_fci_internal->fPrevCab = FALSE;
215   p_fci_internal->fNextCab = FALSE;
216   p_fci_internal->fSplitFolder = FALSE;
217   p_fci_internal->fGetNextCabInVain = FALSE;
218   p_fci_internal->pv = pv;
219   p_fci_internal->data_in  = NULL;
220   p_fci_internal->cdata_in = 0;
221   p_fci_internal->data_out = NULL;
222   p_fci_internal->cCompressedBytesInFolder = 0;
223   p_fci_internal->cFolders = 0;
224   p_fci_internal->cFiles = 0;
225   p_fci_internal->cDataBlocks = 0;
226   p_fci_internal->sizeFileCFDATA1 = 0;
227   p_fci_internal->sizeFileCFFILE1 = 0;
228   p_fci_internal->sizeFileCFDATA2 = 0;
229   p_fci_internal->sizeFileCFFILE2 = 0;
230   p_fci_internal->sizeFileCFFOLDER = 0;
231   p_fci_internal->sizeFileCFFOLDER = 0;
232   p_fci_internal->fNewPrevious = FALSE;
233   p_fci_internal->estimatedCabinetSize = 0;
234   p_fci_internal->statusFolderTotal = 0;
235 
236   memset(&p_fci_internal->oldCCAB, 0, sizeof(CCAB));
237   memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
238   memcpy(p_fci_internal->szPrevDisk, pccab->szDisk, CB_MAX_DISK_NAME);
239 
240   /* CFDATA */
241   if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA1,
242       CB_MAX_FILENAME)) {
243     fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
244     return FALSE;
245   }
246   /* safety */
247   if ( strlen(p_fci_internal->szFileNameCFDATA1) >= CB_MAX_FILENAME ) {
248     fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
249     return FALSE;
250   }
251 
252   p_fci_internal->handleCFDATA1 = PFCI_OPEN(hfci,
253     p_fci_internal->szFileNameCFDATA1, 34050, 384, &err, pv);
254   if(p_fci_internal->handleCFDATA1==0){
255     fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
256     return FALSE;
257   }
258   /* TODO error checking of err */
259 
260   /* array of all CFFILE in a folder */
261   if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE1,
262       CB_MAX_FILENAME)) {
263     fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
264     return FALSE;
265   }
266   /* safety */
267   if ( strlen(p_fci_internal->szFileNameCFFILE1) >= CB_MAX_FILENAME ) {
268     fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
269     return FALSE;
270   }
271   p_fci_internal->handleCFFILE1 = PFCI_OPEN(hfci,
272     p_fci_internal->szFileNameCFFILE1, 34050, 384, &err, pv);
273   if(p_fci_internal->handleCFFILE1==0){
274     fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
275     return FALSE;
276   }
277   /* TODO error checking of err */
278 
279   /* CFDATA with checksum and ready to be copied into cabinet */
280   if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFDATA2,
281       CB_MAX_FILENAME)) {
282     fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE);
283     return FALSE;
284   }
285   /* safety */
286   if ( strlen(p_fci_internal->szFileNameCFDATA2) >= CB_MAX_FILENAME ) {
287     fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
288     return FALSE;
289   }
290   p_fci_internal->handleCFDATA2 = PFCI_OPEN(hfci,
291     p_fci_internal->szFileNameCFDATA2, 34050, 384, &err, pv);
292   if(p_fci_internal->handleCFDATA2==0){
293     fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
294     return FALSE;
295   }
296   /* TODO error checking of err */
297 
298   /* array of all CFFILE in a folder, ready to be copied into cabinet */
299   if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFILE2,
300       CB_MAX_FILENAME)) {
301     fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
302     return FALSE;
303   }
304   /* safety */
305   if ( strlen(p_fci_internal->szFileNameCFFILE2) >= CB_MAX_FILENAME ) {
306     fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
307     return FALSE;
308   }
309   p_fci_internal->handleCFFILE2 = PFCI_OPEN(hfci,
310     p_fci_internal->szFileNameCFFILE2, 34050, 384, &err, pv);
311   if(p_fci_internal->handleCFFILE2==0){
312     fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE );
313     return FALSE;
314   }
315   /* TODO error checking of err */
316 
317   /* array of all CFFILE in a folder, ready to be copied into cabinet */
318   if( !PFCI_GETTEMPFILE(hfci,p_fci_internal->szFileNameCFFOLDER,
319       CB_MAX_FILENAME)) {
320     fci_set_error( FCIERR_NONE, ERROR_FUNCTION_FAILED, TRUE );
321     return FALSE;
322   }
323   /* safety */
324   if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
325     fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
326     return FALSE;
327   }
328   p_fci_internal->handleCFFOLDER = PFCI_OPEN(hfci,
329     p_fci_internal->szFileNameCFFOLDER, 34050, 384, &err, pv);
330   if(p_fci_internal->handleCFFOLDER==0) {
331     fci_set_error( FCIERR_TEMP_FILE, ERROR_OPEN_FAILED, TRUE);
332     return FALSE;
333   }
334 
335   /* TODO close and delete new files when return FALSE */
336   /* TODO error checking of err */
337 
338   return hfci;
339 } /* end of FCICreate */
340 
341 
342 
343 
344 
345 
346 static BOOL fci_flush_data_block (HFCI hfci, int* err,
347     PFNFCISTATUS pfnfcis) {
348 
349   /* attention no hfci checks!!! */
350   /* attention no checks if there is data available!!! */
351   CFDATA data;
352   CFDATA* cfdata=&data;
353   char* reserved;
354   PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
355   UINT cbReserveCFData=p_fci_internal->pccab->cbReserveCFData;
356   UINT i;
357 
358   /* TODO compress the data of p_fci_internal->data_in */
359   /* and write it to p_fci_internal->data_out */
360   memcpy(p_fci_internal->data_out, p_fci_internal->data_in,
361     p_fci_internal->cdata_in /* number of bytes to copy */);
362 
363   cfdata->csum=0; /* checksum has to be set later */
364   /* TODO set realsize of compressed data */
365   cfdata->cbData   = p_fci_internal->cdata_in;
366   cfdata->cbUncomp = p_fci_internal->cdata_in;
367 
368   /* write cfdata to p_fci_internal->handleCFDATA1 */
369   if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
370       cfdata, sizeof(*cfdata), err, p_fci_internal->pv)
371       != sizeof(*cfdata) ) {
372     fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
373     return FALSE;
374   }
375   /* TODO error handling of err */
376 
377   p_fci_internal->sizeFileCFDATA1 += sizeof(*cfdata);
378 
379   /* add optional reserved area */
380 
381   /* This allocation and freeing at each CFData block is a bit */
382   /* inefficient, but it's harder to forget about freeing the buffer :-). */
383   /* Reserved areas are used seldom besides that... */
384   if (cbReserveCFData!=0) {
385     if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData))) {
386       fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
387       return FALSE;
388     }
389     for(i=0;i<cbReserveCFData;) {
390       reserved[i++]='\0';
391     }
392     if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
393         reserved, /* memory buffer */
394         cbReserveCFData, /* number of bytes to copy */
395         err, p_fci_internal->pv) != cbReserveCFData ) {
396       PFCI_FREE(hfci, reserved);
397       fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
398       return FALSE;
399     }
400     /* TODO error handling of err PFCI_FREE(hfci, reserved)*/
401 
402     p_fci_internal->sizeFileCFDATA1 += cbReserveCFData;
403     PFCI_FREE(hfci, reserved);
404   }
405 
406   /* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
407   if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
408       p_fci_internal->data_out, /* memory buffer */
409       cfdata->cbData, /* number of bytes to copy */
410       err, p_fci_internal->pv) != cfdata->cbData) {
411     fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
412     return FALSE;
413   }
414   /* TODO error handling of err */
415 
416   p_fci_internal->sizeFileCFDATA1 += cfdata->cbData;
417 
418   /* reset the offset */
419   p_fci_internal->cdata_in = 0;
420   p_fci_internal->cCompressedBytesInFolder += cfdata->cbData;
421 
422   /* report status with pfnfcis about uncompressed and compressed file data */
423   if( (*pfnfcis)(statusFile, cfdata->cbData, cfdata->cbUncomp,
424       p_fci_internal->pv) == -1) {
425     fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
426     return FALSE;
427   }
428 
429   ++(p_fci_internal->cDataBlocks);
430 
431   return TRUE;
432 } /* end of fci_flush_data_block */
433 
434 
435 
436 
437 
438 static cab_ULONG fci_get_checksum(const void *pv, UINT cb, CHECKSUM seed)
439 {
440   cab_ULONG     csum;
441   cab_ULONG     ul;
442   int           cUlong;
443   const BYTE    *pb;
444 
445   csum = seed;
446   cUlong = cb / 4;
447   pb = pv;
448 
449   while (cUlong-- > 0) {
450     ul = *pb++;
451     ul |= (((cab_ULONG)(*pb++)) <<  8);
452     ul |= (((cab_ULONG)(*pb++)) << 16);
453     ul |= (((cab_ULONG)(*pb++)) << 24);
454 
455     csum ^= ul;
456   }
457 
458   ul = 0;
459   switch (cb % 4) {
460     case 3:
461       ul |= (((ULONG)(*pb++)) << 16);
462     case 2:
463       ul |= (((ULONG)(*pb++)) <<  8);
464     case 1:
465       ul |= *pb++;
466     default:
467       break;
468   }
469   csum ^= ul;
470 
471   return csum;
472 } /* end of fci_get_checksum */
473 
474 
475 
476 static BOOL fci_flushfolder_copy_cfdata(HFCI hfci, char* buffer, UINT cbReserveCFData,
477   PFNFCISTATUS pfnfcis, int* err, int handleCFDATA1new,
478   cab_ULONG* psizeFileCFDATA1new, cab_ULONG* payload)
479 {
480   cab_ULONG read_result;
481   CFDATA* pcfdata=(CFDATA*)buffer;
482   BOOL split_block=FALSE;
483   cab_UWORD savedUncomp=0;
484   PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
485 
486   *payload=0;
487 
488   /* while not all CFDATAs have been copied do */
489   while(!FALSE) {
490     if( p_fci_internal->fNextCab ) {
491       if( split_block ) {
492         /* internal error should never happen */
493         fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
494         return FALSE;
495       }
496     }
497     /* REUSE the variable read_result */
498     if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
499         p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
500         p_fci_internal->oldCCAB.cbReserveCFData   != 0 ) {
501       read_result=4;
502     } else {
503       read_result=0;
504     }
505     if (p_fci_internal->fPrevCab) {
506       read_result+=strlen(p_fci_internal->szPrevCab)+1 +
507         strlen(p_fci_internal->szPrevDisk)+1;
508     }
509     /* No more CFDATA fits into the cabinet under construction */
510     /* So don't try to store more data into it */
511     if( p_fci_internal->fNextCab &&
512         (p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData +
513         p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
514         p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
515         sizeof(CFHEADER) +
516         read_result +
517         p_fci_internal->oldCCAB.cbReserveCFHeader +
518         sizeof(CFFOLDER) +
519         p_fci_internal->oldCCAB.cbReserveCFFolder +
520         strlen(p_fci_internal->pccab->szCab)+1 +
521         strlen(p_fci_internal->pccab->szDisk)+1
522     )) {
523       /* This may never be run for the first time the while loop is entered.
524       Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
525       split_block=TRUE;  /* In this case split_block is abused to store */
526       /* the complete data block into the next cabinet and not into the */
527       /* current one. Originally split_block is the indicator that a */
528       /* data block has been split across different cabinets. */
529     } else {
530 
531       /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
532       read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/*file handle*/
533           buffer, /* memory buffer */
534           sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
535           err, p_fci_internal->pv);
536       if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
537         if (read_result==0) break; /* ALL DATA has been copied */
538         /* read error */
539         fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
540         return FALSE;
541       }
542       /* TODO error handling of err */
543 
544       /* REUSE buffer p_fci_internal->data_out !!! */
545       /* read data from p_fci_internal->handleCFDATA1 to */
546       /*      p_fci_internal->data_out */
547       if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
548           p_fci_internal->data_out /* memory buffer */,
549           pcfdata->cbData /* number of bytes to copy */,
550           err, p_fci_internal->pv) != pcfdata->cbData ) {
551         /* read error */
552         fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
553         return FALSE;
554       }
555       /* TODO error handling of err */
556 
557       /* if cabinet size is too large */
558 
559       /* REUSE the variable read_result */
560       if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
561           p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
562           p_fci_internal->oldCCAB.cbReserveCFData   != 0 ) {
563         read_result=4;
564       } else {
565         read_result=0;
566       }
567       if (p_fci_internal->fPrevCab) {
568         read_result+=strlen(p_fci_internal->szPrevCab)+1 +
569           strlen(p_fci_internal->szPrevDisk)+1;
570       }
571 
572       /* Is cabinet with new CFDATA too large? Then data block has to be split */
573       if( p_fci_internal->fNextCab &&
574           (p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData +
575           pcfdata->cbData +
576           p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
577           p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
578           sizeof(CFHEADER) +
579           read_result +
580           p_fci_internal->oldCCAB.cbReserveCFHeader +
581           sizeof(CFFOLDER) + /* size of new CFFolder entry */
582           p_fci_internal->oldCCAB.cbReserveCFFolder +
583           strlen(p_fci_internal->pccab->szCab)+1 + /* name of next cabinet */
584           strlen(p_fci_internal->pccab->szDisk)+1  /* name of next disk */
585       )) {
586         /* REUSE read_result to save the size of the compressed data */
587         read_result=pcfdata->cbData;
588         /* Modify the size of the compressed data to store only a part of the */
589         /* data block into the current cabinet. This is done to prevent */
590         /* that the maximum cabinet size will be exceeded. The remainder */
591         /* will be stored into the next following cabinet. */
592 
593         /* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
594         /* Substract everything except the size of the block of data */
595         /* to get it's actual size */
596         pcfdata->cbData = p_fci_internal->oldCCAB.cb - (
597           sizeof(CFDATA) + cbReserveCFData +
598           p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
599           p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
600           sizeof(CFHEADER) +
601           p_fci_internal->oldCCAB.cbReserveCFHeader +
602           sizeof(CFFOLDER) + /* set size of new CFFolder entry */
603           p_fci_internal->oldCCAB.cbReserveCFFolder );
604         /* substract the size of special header fields */
605         if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
606             p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
607             p_fci_internal->oldCCAB.cbReserveCFData   != 0 ) {
608           pcfdata->cbData-=4;
609         }
610         if (p_fci_internal->fPrevCab) {
611           pcfdata->cbData-=strlen(p_fci_internal->szPrevCab)+1 +
612             strlen(p_fci_internal->szPrevDisk)+1;
613         }
614         pcfdata->cbData-=strlen(p_fci_internal->pccab->szCab)+1 +
615           strlen(p_fci_internal->pccab->szDisk)+1;
616 
617         savedUncomp = pcfdata->cbUncomp;
618         pcfdata->cbUncomp = 0; /* on split blocks of data this is zero */
619 
620         /* if split_block==TRUE then the above while loop won't */
621         /* be executed again */
622         split_block=TRUE; /* split_block is the indicator that */
623                           /* a data block has been split across */
624                           /* different cabinets.*/
625       }
626 
627       /* This should never happen !!! */
628       if (pcfdata->cbData==0) {
629         /* set error */
630         fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
631         return FALSE;
632       }
633 
634       /* set little endian */
635       pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
636       pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
637 
638       /* get checksum and write to cfdata.csum */
639       pcfdata->csum = fci_get_checksum( &(pcfdata->cbData),
640         sizeof(CFDATA)+cbReserveCFData -
641         sizeof(pcfdata->csum), fci_get_checksum( p_fci_internal->data_out, /*buffer*/
642         pcfdata->cbData, 0 ) );
643 
644       /* set little endian */
645       pcfdata->csum=fci_endian_ulong(pcfdata->csum);
646 
647       /* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
648       if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
649           buffer, /* memory buffer */
650           sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
651           err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
652          fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
653          return FALSE;
654       }
655       /* TODO error handling of err */
656 
657       p_fci_internal->sizeFileCFDATA2 += sizeof(CFDATA)+cbReserveCFData;
658 
659       /* reset little endian */
660       pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
661       pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
662       pcfdata->csum=fci_endian_ulong(pcfdata->csum);
663 
664       /* write compressed data into p_fci_internal->handleCFDATA2 */
665       if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
666           p_fci_internal->data_out, /* memory buffer */
667           pcfdata->cbData, /* number of bytes to copy */
668           err, p_fci_internal->pv) != pcfdata->cbData) {
669         fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
670         return FALSE;
671       }
672       /* TODO error handling of err */
673 
674       p_fci_internal->sizeFileCFDATA2 += pcfdata->cbData;
675       ++(p_fci_internal->cDataBlocks);
676       p_fci_internal->statusFolderCopied += pcfdata->cbData;
677       (*payload)+=pcfdata->cbUncomp;
678       /* if cabinet size too large and data has been split */
679       /* write the remainder of the data block to the new CFDATA1 file */
680       if( split_block  ) { /* This does not include the */
681                                   /* abused one (just search for "abused" )*/
682       /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
683         if (p_fci_internal->fNextCab==FALSE ) {
684           /* internal error */
685           fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
686           return FALSE;
687         }
688 
689         /* set cbData to the size of the remainder of the data block */
690         pcfdata->cbData = read_result - pcfdata->cbData;
691         /*recover former value of cfdata.cbData; read_result will be the offset*/
692         read_result -= pcfdata->cbData;
693         pcfdata->cbUncomp = savedUncomp;
694 
695         /* reset checksum, it will be computed later */
696         pcfdata->csum=0;
697 
698         /* write cfdata WITHOUT checksum to handleCFDATA1new */
699         if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
700             buffer, /* memory buffer */
701             sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
702             err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
703           fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
704           return FALSE;
705         }
706         /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
707 
708         *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
709 
710         /* write compressed data into handleCFDATA1new */
711         if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
712             p_fci_internal->data_out + read_result, /* memory buffer + offset */
713                                                 /* to last part of split data */
714             pcfdata->cbData, /* number of bytes to copy */
715             err, p_fci_internal->pv) != pcfdata->cbData) {
716           fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
717           return FALSE;
718         }
719         /* TODO error handling of err */
720 
721         p_fci_internal->statusFolderCopied += pcfdata->cbData;
722 
723         *psizeFileCFDATA1new += pcfdata->cbData;
724         /* the two blocks of the split data block have been written */
725         /* don't reset split_data yet, because it is still needed see below */
726       }
727 
728       /* report status with pfnfcis about copied size of folder */
729       if( (*pfnfcis)(statusFolder,
730           p_fci_internal->statusFolderCopied, /*cfdata.cbData(+previous ones)*/
731           p_fci_internal->statusFolderTotal, /* total folder size */
732           p_fci_internal->pv) == -1) {
733         fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
734         return FALSE;
735       }
736     }
737 
738     /* if cabinet size too large */
739     /* write the remaining data blocks to the new CFDATA1 file */
740     if ( split_block ) { /* This does include the */
741                                /* abused one (just search for "abused" )*/
742       if (p_fci_internal->fNextCab==FALSE ) {
743         /* internal error */
744         fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
745         return FALSE;
746       }
747       /* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
748       while(!FALSE) {
749         /* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
750         read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/* handle */
751             buffer, /* memory buffer */
752             sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
753             err, p_fci_internal->pv);
754         if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
755           if (read_result==0) break; /* ALL DATA has been copied */
756           /* read error */
757           fci_set_error(FCIERR_NONE, ERROR_READ_FAULT, TRUE );
758           return FALSE;
759         }
760         /* TODO error handling of err */
761 
762         /* REUSE buffer p_fci_internal->data_out !!! */
763         /* read data from p_fci_internal->handleCFDATA1 to */
764         /*      p_fci_internal->data_out */
765         if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
766             p_fci_internal->data_out /* memory buffer */,
767             pcfdata->cbData /* number of bytes to copy */,
768             err, p_fci_internal->pv) != pcfdata->cbData ) {
769           /* read error */
770           fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE);
771           return FALSE;
772         }
773         /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
774 
775         /* write cfdata with checksum to handleCFDATA1new */
776         if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
777             buffer, /* memory buffer */
778             sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
779             err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
780           fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
781           return FALSE;
782         }
783         /* TODO error handling of err don't forget PFCI_FREE(hfci, reserved) */
784 
785         *psizeFileCFDATA1new += sizeof(CFDATA)+cbReserveCFData;
786 
787         /* write compressed data into handleCFDATA1new */
788         if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
789             p_fci_internal->data_out, /* memory buffer */
790             pcfdata->cbData, /* number of bytes to copy */
791             err, p_fci_internal->pv) != pcfdata->cbData) {
792           fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
793           return FALSE;
794         }
795         /* TODO error handling of err */
796 
797         *psizeFileCFDATA1new += pcfdata->cbData;
798         p_fci_internal->statusFolderCopied += pcfdata->cbData;
799 
800         /* report status with pfnfcis about copied size of folder */
801         if( (*pfnfcis)(statusFolder,
802             p_fci_internal->statusFolderCopied,/*cfdata.cbData(+previous ones)*/
803             p_fci_internal->statusFolderTotal, /* total folder size */
804             p_fci_internal->pv) == -1) {
805           fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
806           return FALSE;
807         }
808 
809       } /* end of WHILE */
810       break; /* jump out of the next while loop */
811     } /* end of if( split_data  ) */
812   } /* end of WHILE */
813   return TRUE;
814 } /* end of fci_flushfolder_copy_cfdata */
815 
816 
817 
818 
819 
820 static BOOL fci_flushfolder_copy_cffolder(HFCI hfci, int* err, UINT cbReserveCFFolder,
821   cab_ULONG sizeFileCFDATA2old)
822 {
823   CFFOLDER cffolder;
824   UINT i;
825   char* reserved;
826   PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
827 
828   /* absolute offset cannot be set yet, because the size of cabinet header, */
829   /* the number of CFFOLDERs and the number of CFFILEs may change. */
830   /* Instead the size of all previous data blocks will be stored and */
831   /* the remainder of the offset will be added when the cabinet will be */
832   /* flushed to disk. */
833   /* This is exactly the way the original CABINET.DLL works!!! */
834   cffolder.coffCabStart=sizeFileCFDATA2old;
835 
836   /* set the number of this folder's CFDATA sections */
837   cffolder.cCFData=p_fci_internal->cDataBlocks;
838   /* TODO set compression type */
839   cffolder.typeCompress = tcompTYPE_NONE;
840 
841   /* write cffolder to p_fci_internal->handleCFFOLDER */
842   if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
843       &cffolder, /* memory buffer */
844       sizeof(cffolder), /* number of bytes to copy */
845       err, p_fci_internal->pv) != sizeof(cffolder) ) {
846     fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
847     return FALSE;
848   }
849   /* TODO error handling of err */
850 
851   p_fci_internal->sizeFileCFFOLDER += sizeof(cffolder);
852 
853   /* add optional reserved area */
854   if (cbReserveCFFolder!=0) {
855     if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFFolder))) {
856       fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
857       return FALSE;
858     }
859     for(i=0;i<cbReserveCFFolder;) {
860       reserved[i++]='\0';
861     }
862     if( PFCI_WRITE(hfci, p_fci_internal->handleCFFOLDER, /* file handle */
863         reserved, /* memory buffer */
864         cbReserveCFFolder, /* number of bytes to copy */
865         err, p_fci_internal->pv) != cbReserveCFFolder ) {
866       PFCI_FREE(hfci, reserved);
867       fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
868       return FALSE;
869     }
870     /* TODO error handling of err */
871 
872     p_fci_internal->sizeFileCFFOLDER += cbReserveCFFolder;
873 
874     PFCI_FREE(hfci, reserved);
875   }
876   return TRUE;
877 } /* end of fci_flushfolder_copy_cffolder */
878 
879 
880 
881 
882 
883 static BOOL fci_flushfolder_copy_cffile(HFCI hfci, int* err, int handleCFFILE1new,
884   cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload)
885 {
886   CFFILE cffile;
887   cab_ULONG read_result;
888   cab_ULONG seek=0;
889   cab_ULONG sizeOfFiles=0, sizeOfFilesPrev;
890   BOOL may_be_prev=TRUE;
891   cab_ULONG cbFileRemainer=0;
892   PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
893   /* set seek of p_fci_internal->handleCFFILE1 to 0 */
894   if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,0,SEEK_SET,err,
895     p_fci_internal->pv) !=0 ) {
896     /* wrong return value */
897     fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
898     return FALSE;
899   }
900   /* TODO error handling of err */
901 
902   /* while not all CFFILE structures have been copied do */
903   while(!FALSE) {
904     /* REUSE the variable read_result */
905     /* read data from p_fci_internal->handleCFFILE1 to cffile */
906     read_result = PFCI_READ(hfci,p_fci_internal->handleCFFILE1/* file handle */,
907       &cffile, /* memory buffer */
908       sizeof(cffile), /* number of bytes to copy */
909       err, p_fci_internal->pv);
910     if( read_result != sizeof(cffile) ) {
911       if( read_result == 0 ) break; /* ALL CFFILE structures have been copied */
912       /* read error */
913       fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
914       return FALSE;
915     }
916     /* TODO error handling of err */
917 
918     /* Microsoft's(R) CABINET.DLL would do a seek to the current! */
919     /* position. I don't know why so I'll just omit it */
920 
921     /* read the filename from p_fci_internal->handleCFFILE1 */
922     /* REUSE the variable read_result AGAIN */
923     /* REUSE the memory buffer PFCI(hfci)->data_out */
924     if( PFCI_READ(hfci, p_fci_internal->handleCFFILE1 /*file handle*/,
925         p_fci_internal->data_out, /* memory buffer */
926         CB_MAX_FILENAME, /* number of bytes to copy */
927         err, p_fci_internal->pv) <2) {
928       /* read error */
929       fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
930       return FALSE;
931     }
932     /* TODO maybe other checks of read_result */
933     /* TODO error handling of err */
934 
935     /* safety */
936     if( strlen(p_fci_internal->data_out)>=CB_MAX_FILENAME ) {
937       /* set error code internal error */
938       fci_set_error( FCIERR_NONE, ERROR_INVALID_DATA, TRUE );
939       return FALSE;
940     }
941 
942     seek+=sizeof(cffile) + strlen(p_fci_internal->data_out)+1;
943 
944     /* set seek of p_fci_internal->handleCFFILE1 to end of file name */
945     /* i.e. seek to the next CFFILE area */
946     if( PFCI_SEEK(hfci,p_fci_internal->handleCFFILE1,
947         seek, /* seek position*/
948         SEEK_SET ,err,
949         p_fci_internal->pv)
950         != seek) {
951       /* wrong return value */
952       fci_set_error( FCIERR_NONE, ERROR_SEEK, TRUE );
953       return FALSE;
954     }
955     /* TODO error handling of err */
956 
957     /* fnfilfnfildest: placed file on cabinet */
958     if (p_fci_internal->fNextCab ||
959         p_fci_internal->fGetNextCabInVain) {
960       PFCI_FILEPLACED( hfci, &(p_fci_internal->oldCCAB),
961         p_fci_internal->data_out, /* the file name*/
962         cffile.cbFile, /* file size */
963         (cffile.iFolder==cffileCONTINUED_FROM_PREV),
964         p_fci_internal->pv
965       );
966     } else {
967       PFCI_FILEPLACED( hfci, p_fci_internal->pccab,
968         p_fci_internal->data_out, /* the file name*/
969         cffile.cbFile, /* file size */
970         (cffile.iFolder==cffileCONTINUED_FROM_PREV),
971         p_fci_internal->pv
972       );
973     }
974 
975     /* Check special iFolder values */
976     if( cffile.iFolder==cffileCONTINUED_FROM_PREV &&
977         p_fci_internal->fPrevCab==FALSE ) {
978       /* THIS MAY NEVER HAPPEN */
979       /* set error code */
980       fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
981       return FALSE;
982     }
983     if( cffile.iFolder==cffileCONTINUED_PREV_AND_NEXT ||
984         cffile.iFolder==cffileCONTINUED_TO_NEXT ) {
985       /* THIS MAY NEVER HAPPEN */
986       /* set error code */
987       fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
988       return FALSE;
989     }
990     if( may_be_prev && cffile.iFolder!=cffileCONTINUED_FROM_PREV ) {
991       may_be_prev=FALSE;
992     }
993     if( cffile.iFolder==cffileCONTINUED_FROM_PREV && may_be_prev==FALSE ) {
994       /* THIS MAY NEVER HAPPEN */