Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
4e1ec201
Commit
4e1ec201
authored
Jun 24, 2005
by
Gerold Jens Wucherpfennig
Committed by
Alexandre Julliard
Jun 24, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Some FCI work.
parent
25f1e75d
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
2578 additions
and
98 deletions
+2578
-98
cabinet.h
dlls/cabinet/cabinet.h
+46
-0
fci.c
dlls/cabinet/fci.c
+2532
-98
No files found.
dlls/cabinet/cabinet.h
View file @
4e1ec201
...
...
@@ -305,7 +305,41 @@ typedef struct {
PFNFCIDELETE
pfndelete
;
PFNFCIGETTEMPFILE
pfnfcigtf
;
PCCAB
pccab
;
BOOL
fPrevCab
;
BOOL
fNextCab
;
BOOL
fSplitFolder
;
cab_ULONG
statusFolderCopied
;
cab_ULONG
statusFolderTotal
;
BOOL
fGetNextCabInVain
;
void
*
pv
;
char
szPrevCab
[
CB_MAX_CABINET_NAME
];
/* previous cabinet name */
char
szPrevDisk
[
CB_MAX_DISK_NAME
];
/* disk name of previous cabinet */
CCAB
oldCCAB
;
char
*
data_in
;
/* uncompressed data blocks */
cab_UWORD
cdata_in
;
char
*
data_out
;
/* compressed data blocks */
ULONG
cCompressedBytesInFolder
;
cab_UWORD
cFolders
;
cab_UWORD
cFiles
;
cab_ULONG
cDataBlocks
;
cab_ULONG
cbFileRemainer
;
/* uncompressed, yet to be written data */
/* of spanned file of a spanning folder of a spanning cabinet */
cab_UBYTE
szFileNameCFDATA1
[
CB_MAX_FILENAME
];
int
handleCFDATA1
;
cab_UBYTE
szFileNameCFFILE1
[
CB_MAX_FILENAME
];
int
handleCFFILE1
;
cab_UBYTE
szFileNameCFDATA2
[
CB_MAX_FILENAME
];
int
handleCFDATA2
;
cab_UBYTE
szFileNameCFFILE2
[
CB_MAX_FILENAME
];
int
handleCFFILE2
;
cab_UBYTE
szFileNameCFFOLDER
[
CB_MAX_FILENAME
];
int
handleCFFOLDER
;
cab_ULONG
sizeFileCFDATA1
;
cab_ULONG
sizeFileCFFILE1
;
cab_ULONG
sizeFileCFDATA2
;
cab_ULONG
sizeFileCFFILE2
;
cab_ULONG
sizeFileCFFOLDER
;
BOOL
fNewPrevious
;
}
FCI_Int
,
*
PFCI_Int
;
typedef
struct
{
...
...
@@ -326,6 +360,18 @@ typedef struct {
/* cast an HFDI into a PFDI_Int */
#define PFDI_INT(hfdi) ((PFDI_Int)(hfdi))
/* quick pfci method invokers */
#define PFCI_ALLOC(hfdi, size) ((*PFCI_INT(hfdi)->pfnalloc) (size))
#define PFCI_FREE(hfdi, ptr) ((*PFCI_INT(hfdi)->pfnfree) (ptr))
#define PFCI_GETTEMPFILE(hfci,name,length) ((*PFCI_INT(hfci)->pfnfcigtf)(name,length,PFCI_INT(hfci)->pv))
#define PFCI_DELETE(hfci,name,err,pv) ((*PFCI_INT(hfci)->pfndelete)(name,err,pv))
#define PFCI_OPEN(hfci,name,oflag,pmode,err,pv) ((*PFCI_INT(hfci)->pfnopen)(name,oflag,pmode,err,pv))
#define PFCI_READ(hfci,hf,memory,cb,err,pv)((*PFCI_INT(hfci)->pfnread)(hf,memory,cb,err,pv))
#define PFCI_WRITE(hfci,hf,memory,cb,err,pv) ((*PFCI_INT(hfci)->pfnwrite)(hf,memory,cb,err,pv))
#define PFCI_CLOSE(hfci,hf,err,pv) ((*PFCI_INT(hfci)->pfnclose)(hf,err,pv))
#define PFCI_SEEK(hfci,hf,dist,seektype,err,pv)((*PFCI_INT(hfci)->pfnseek)(hf,dist,seektype,err,pv))
#define PFCI_FILEPLACED(hfci,pccab,name,cb,cont,pv)((*PFCI_INT(hfci)->pfnfiledest)(pccab,name,cb,cont,pv))
/* quickie pfdi method invokers */
#define PFDI_ALLOC(hfdi, size) ((*PFDI_INT(hfdi)->pfnalloc) (size))
#define PFDI_FREE(hfdi, ptr) ((*PFDI_INT(hfdi)->pfnfree) (ptr))
...
...
dlls/cabinet/fci.c
View file @
4e1ec201
...
...
@@ -19,9 +19,27 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
There is still some work to be done:
- currently no support for big-endian machines
- the ERF error structure aren't used on error
- no real compression yet
- unknown behaviour if files>4GB or cabinet >4GB
- incorrect status information
- check if the maximum size for a cabinet is too small to store any data
- call pfnfcignc on exactly the same position as MS FCIAddFile in every case
*/
#include "config.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
...
...
@@ -33,12 +51,56 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
cabinet
);
typedef
struct
{
cab_UBYTE
signature
[
4
];
/* !CAB for unfinished cabinets else MSCF */
cab_ULONG
reserved1
;
cab_ULONG
cbCabinet
;
/* size of the cabinet file in bytes*/
cab_ULONG
reserved2
;
cab_ULONG
coffFiles
;
/* offset to first CFFILE section */
cab_ULONG
reserved3
;
cab_UBYTE
versionMinor
;
/* 3 */
cab_UBYTE
versionMajor
;
/* 1 */
cab_UWORD
cFolders
;
/* number of CFFOLDER entries in the cabinet*/
cab_UWORD
cFiles
;
/* number of CFFILE entries in the cabinet*/
cab_UWORD
flags
;
/* 1=prev cab, 2=next cabinet, 4=reserved setions*/
cab_UWORD
setID
;
/* identification number of all cabinets in a set*/
cab_UWORD
iCabinet
;
/* number of the cabinet in a set */
/* additional area if "flags" were set*/
}
CFHEADER
;
/* minimum 36 bytes */
typedef
struct
{
cab_ULONG
coffCabStart
;
/* offset to the folder's first CFDATA section */
cab_UWORD
cCFData
;
/* number of this folder's CFDATA sections */
cab_UWORD
typeCompress
;
/* compression type of data in CFDATA section*/
/* additional area if reserve flag was set */
}
CFFOLDER
;
/* minumum 8 bytes */
typedef
struct
{
cab_ULONG
cbFile
;
/* size of the uncompressed file in bytes */
cab_ULONG
uoffFolderStart
;
/* offset of the uncompressed file in the folder */
cab_UWORD
iFolder
;
/* number of folder in the cabinet 0=first */
/* for special values see below this structure*/
cab_UWORD
date
;
/* last modification date*/
cab_UWORD
time
;
/* last modification time*/
cab_UWORD
attribs
;
/* DOS fat attributes and UTF indicator */
/* ... and a C string with the name of the file */
}
CFFILE
;
/* 16 bytes + name of file */
typedef
struct
{
cab_ULONG
csum
;
/* checksum of this entry*/
cab_UWORD
cbData
;
/* number of compressed bytes */
cab_UWORD
cbUncomp
;
/* number of bytes when data is uncompressed */
/* optional reserved area */
/* compressed data */
}
CFDATA
;
/***********************************************************************
* FCICreate (CABINET.10)
*
* Provided with several callbacks,
* returns a handle which can be used to perform operations
* on cabinet files.
* FCICreate is provided with several callbacks and
* returns a handle which can be used to create cabinet files.
*
* PARAMS
* perf [IO] A pointer to an ERF structure. When FCICreate
...
...
@@ -54,7 +116,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
* the same interface as _open.
* pfnread [I] A pointer to a function which reads from a file into
* a caller-provided buffer. Uses the same interface
* as _read
* as _read
.
* pfnwrite [I] A pointer to a function which writes to a file from
* a caller-provided buffer. Uses the same interface
* as _write.
...
...
@@ -64,8 +126,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
* Uses the same interface as _lseek.
* pfndelete [I] A pointer to a function which deletes a file.
* pfnfcigtf [I] A pointer to a function which gets the name of a
* temporary file
; ignored in wine
* pccab [I] A pointer to an initialized CCAB structure
* temporary file
.
* pccab [I] A pointer to an initialized CCAB structure
.
* pv [I] A pointer to an application-defined notification
* function which will be passed to other FCI functions
* as a parameter.
...
...
@@ -94,9 +156,13 @@ HFCI __cdecl FCICreate(
PCCAB
pccab
,
void
*
pv
)
{
HFCI
rv
;
HFCI
hfci
;
int
err
;
PFCI_Int
p_fci_internal
;
if
((
!
pfnalloc
)
||
(
!
pfnfree
))
{
if
((
!
perf
)
||
(
!
pfnalloc
)
||
(
!
pfnfree
)
||
(
!
pfnopen
)
||
(
!
pfnread
)
||
(
!
pfnwrite
)
||
(
!
pfnclose
)
||
(
!
pfnseek
)
||
(
!
pfndelete
)
||
(
!
pfnfcigtf
)
||
(
!
pccab
))
{
perf
->
erfOper
=
FCIERR_NONE
;
perf
->
erfType
=
ERROR_BAD_ARGUMENTS
;
perf
->
fError
=
TRUE
;
...
...
@@ -105,7 +171,7 @@ HFCI __cdecl FCICreate(
return
NULL
;
}
if
(
!
(
rv
=
(
HFCI
)
(
*
pfnalloc
)(
sizeof
(
FCI_Int
))))
{
if
(
!
(
(
hfci
=
((
HFCI
)
(
*
pfnalloc
)(
sizeof
(
FCI_Int
))
))))
{
perf
->
erfOper
=
FCIERR_ALLOC_FAIL
;
perf
->
erfType
=
ERROR_NOT_ENOUGH_MEMORY
;
perf
->
fError
=
TRUE
;
...
...
@@ -114,117 +180,2485 @@ HFCI __cdecl FCICreate(
return
NULL
;
}
PFCI_INT
(
rv
)
->
FCI_Intmagic
=
FCI_INT_MAGIC
;
PFCI_INT
(
rv
)
->
perf
=
perf
;
PFCI_INT
(
rv
)
->
pfnfiledest
=
pfnfiledest
;
PFCI_INT
(
rv
)
->
pfnalloc
=
pfnalloc
;
PFCI_INT
(
rv
)
->
pfnfree
=
pfnfree
;
PFCI_INT
(
rv
)
->
pfnopen
=
pfnopen
;
PFCI_INT
(
rv
)
->
pfnread
=
pfnread
;
PFCI_INT
(
rv
)
->
pfnwrite
=
pfnwrite
;
PFCI_INT
(
rv
)
->
pfnclose
=
pfnclose
;
PFCI_INT
(
rv
)
->
pfnseek
=
pfnseek
;
PFCI_INT
(
rv
)
->
pfndelete
=
pfndelete
;
PFCI_INT
(
rv
)
->
pfnfcigtf
=
pfnfcigtf
;
PFCI_INT
(
rv
)
->
pccab
=
pccab
;
PFCI_INT
(
rv
)
->
pv
=
pv
;
/* Still mark as incomplete, because of other missing FCI* APIs */
PFCI_INT
(
rv
)
->
FCI_Intmagic
=
0
;
PFDI_FREE
(
rv
,
rv
);
FIXME
(
"(%p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p): stub
\n
"
,
perf
,
pfnfiledest
,
pfnalloc
,
pfnfree
,
pfnopen
,
pfnread
,
pfnwrite
,
pfnclose
,
pfnseek
,
pfndelete
,
pfnfcigtf
,
pccab
,
pv
);
p_fci_internal
=
((
PFCI_Int
)(
hfci
));
p_fci_internal
->
FCI_Intmagic
=
FCI_INT_MAGIC
;
p_fci_internal
->
perf
=
perf
;
p_fci_internal
->
pfnfiledest
=
pfnfiledest
;
p_fci_internal
->
pfnalloc
=
pfnalloc
;
p_fci_internal
->
pfnfree
=
pfnfree
;
p_fci_internal
->
pfnopen
=
pfnopen
;
p_fci_internal
->
pfnread
=
pfnread
;
p_fci_internal
->
pfnwrite
=
pfnwrite
;
p_fci_internal
->
pfnclose
=
pfnclose
;
p_fci_internal
->
pfnseek
=
pfnseek
;
p_fci_internal
->
pfndelete
=
pfndelete
;
p_fci_internal
->
pfnfcigtf
=
pfnfcigtf
;
p_fci_internal
->
pccab
=
pccab
;
p_fci_internal
->
fPrevCab
=
FALSE
;
p_fci_internal
->
fNextCab
=
FALSE
;
p_fci_internal
->
fSplitFolder
=
FALSE
;
p_fci_internal
->
fGetNextCabInVain
=
FALSE
;
p_fci_internal
->
pv
=
pv
;
p_fci_internal
->
data_in
=
NULL
;
p_fci_internal
->
cdata_in
=
0
;
p_fci_internal
->
data_out
=
NULL
;
p_fci_internal
->
cCompressedBytesInFolder
=
0
;
p_fci_internal
->
cFolders
=
0
;
p_fci_internal
->
cFiles
=
0
;
p_fci_internal
->
cDataBlocks
=
0
;
p_fci_internal
->
sizeFileCFDATA1
=
0
;
p_fci_internal
->
sizeFileCFFILE1
=
0
;
p_fci_internal
->
sizeFileCFDATA2
=
0
;
p_fci_internal
->
sizeFileCFFILE2
=
0
;
p_fci_internal
->
sizeFileCFFOLDER
=
0
;
p_fci_internal
->
sizeFileCFFOLDER
=
0
;
p_fci_internal
->
fNewPrevious
=
FALSE
;
perf
->
erfOper
=
FCIERR_NONE
;
perf
->
erfType
=
0
;
perf
->
fError
=
TRUE
;
memcpy
(
p_fci_internal
->
szPrevCab
,
pccab
->
szCab
,
CB_MAX_CABINET_NAME
);
memcpy
(
p_fci_internal
->
szPrevDisk
,
pccab
->
szDisk
,
CB_MAX_DISK_NAME
);
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
/* CFDATA */
if
(
!
PFCI_GETTEMPFILE
(
hfci
,
p_fci_internal
->
szFileNameCFDATA1
,
CB_MAX_FILENAME
))
{
/* TODO error handling */
return
FALSE
;
}
/* safety */
if
(
strlen
(
p_fci_internal
->
szFileNameCFDATA1
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code */
return
FALSE
;
}
return
NULL
;
p_fci_internal
->
handleCFDATA1
=
PFCI_OPEN
(
hfci
,
p_fci_internal
->
szFileNameCFDATA1
,
34050
,
384
,
&
err
,
pv
);
/* TODO check handle */
/* TODO error checking of err */
}
/* array of all CFFILE in a folder */
if
(
!
PFCI_GETTEMPFILE
(
hfci
,
p_fci_internal
->
szFileNameCFFILE1
,
CB_MAX_FILENAME
))
{
/* TODO error handling */
return
FALSE
;
}
/* safety */
if
(
strlen
(
p_fci_internal
->
szFileNameCFFILE1
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code */
return
FALSE
;
}
p_fci_internal
->
handleCFFILE1
=
PFCI_OPEN
(
hfci
,
p_fci_internal
->
szFileNameCFFILE1
,
34050
,
384
,
&
err
,
pv
);
/* TODO check handle */
/* TODO error checking of err */
/***********************************************************************
* FCIAddFile (CABINET.11)
*/
BOOL
__cdecl
FCIAddFile
(
HFCI
hfci
,
char
*
pszSourceFile
,
char
*
pszFileName
,
BOOL
fExecute
,
PFNFCIGETNEXTCABINET
pfnfcignc
,
PFNFCISTATUS
pfnfcis
,
PFNFCIGETOPENINFO
pfnfcigoi
,
TCOMP
typeCompress
)
{
FIXME
(
"(%p, %p, %p, %d, %p, %p, %p, %hu): stub
\n
"
,
hfci
,
pszSourceFile
,
pszFileName
,
fExecute
,
pfnfcignc
,
pfnfcis
,
pfnfcigoi
,
typeCompress
);
/* CFDATA with checksum and ready to be copied into cabinet */
if
(
!
PFCI_GETTEMPFILE
(
hfci
,
p_fci_internal
->
szFileNameCFDATA2
,
CB_MAX_FILENAME
))
{
/* TODO error handling */
return
FALSE
;
}
/* safety */
if
(
strlen
(
p_fci_internal
->
szFileNameCFDATA2
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code */
return
FALSE
;
}
p_fci_internal
->
handleCFDATA2
=
PFCI_OPEN
(
hfci
,
p_fci_internal
->
szFileNameCFDATA2
,
34050
,
384
,
&
err
,
pv
);
/* TODO check handle */
/* TODO error checking of err */
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
/* array of all CFFILE in a folder, ready to be copied into cabinet */
if
(
!
PFCI_GETTEMPFILE
(
hfci
,
p_fci_internal
->
szFileNameCFFILE2
,
CB_MAX_FILENAME
))
{
/* TODO error handling */
return
FALSE
;
}
/* safety */
if
(
strlen
(
p_fci_internal
->
szFileNameCFFILE2
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code */
return
FALSE
;
}
p_fci_internal
->
handleCFFILE2
=
PFCI_OPEN
(
hfci
,
p_fci_internal
->
szFileNameCFFILE2
,
34050
,
384
,
&
err
,
pv
);
/* TODO check handle */
/* TODO error checking of err */
/* array of all CFFILE in a folder, ready to be copied into cabinet */
if
(
!
PFCI_GETTEMPFILE
(
hfci
,
p_fci_internal
->
szFileNameCFFOLDER
,
CB_MAX_FILENAME
))
{
/* TODO error handling */
return
FALSE
;
}
/* safety */
if
(
strlen
(
p_fci_internal
->
szFileNameCFFOLDER
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code */
return
FALSE
;
}
}
p_fci_internal
->
handleCFFOLDER
=
PFCI_OPEN
(
hfci
,
p_fci_internal
->
szFileNameCFFOLDER
,
34050
,
384
,
&
err
,
pv
);
/***********************************************************************
* FCIFlushCabinet (CABINET.13)
*/
BOOL
__cdecl
FCIFlushCabinet
(
HFCI
hfci
,
BOOL
fGetNextCab
,
PFNFCIGETNEXTCABINET
pfnfcignc
,
PFNFCISTATUS
pfnfcis
)
/* TODO close and delete new files when return FALSE */
/* TODO check handle */
/* TODO error checking of err */
return
hfci
;
}
/* end of FCICreate */
static
BOOL
fci_flush_data_block
(
HFCI
hfci
,
int
*
err
,
PFNFCISTATUS
pfnfcis
)
{
/* attention no hfci checks!!! */
/* attention no checks if there is data available!!! */
CFDATA
data
;
CFDATA
*
cfdata
=&
data
;
char
*
reserved
;
PFCI_Int
p_fci_internal
=
((
PFCI_Int
)(
hfci
));
UINT
cbReserveCFData
=
p_fci_internal
->
pccab
->
cbReserveCFData
;
UINT
i
;
/* TODO compress the data of p_fci_internal->data_in */
/* and write it to p_fci_internal->data_out */
memcpy
(
p_fci_internal
->
data_out
,
p_fci_internal
->
data_in
,
p_fci_internal
->
cdata_in
/* number of bytes to copy */
);
cfdata
->
csum
=
0
;
/* checksum has to be set later */
/* TODO set realsize of compressed data */
cfdata
->
cbData
=
p_fci_internal
->
cdata_in
;
cfdata
->
cbUncomp
=
p_fci_internal
->
cdata_in
;
/* write cfdata to p_fci_internal->handleCFDATA1 */
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFDATA1
,
/* file handle */
cfdata
,
sizeof
(
*
cfdata
),
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
*
cfdata
)
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
p_fci_internal
->
sizeFileCFDATA1
+=
sizeof
(
*
cfdata
);
/* add optional reserved area */
/* This allocation and freeing at each CFData block is a bit */
/* inefficent, but it's harder to forget about freeing the buffer :-). */
/* Reserved areas are used seldom besides that... */
if
(
cbReserveCFData
!=
0
)
{
if
(
!
(
reserved
=
(
char
*
)
PFCI_ALLOC
(
hfci
,
cbReserveCFData
)))
{
p_fci_internal
->
perf
->
erfOper
=
FCIERR_ALLOC_FAIL
;
p_fci_internal
->
perf
->
erfType
=
ERROR_NOT_ENOUGH_MEMORY
;
p_fci_internal
->
perf
->
fError
=
TRUE
;
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
}
for
(
i
=
0
;
i
<
cbReserveCFData
;)
{
reserved
[
i
++
]
=
'\0'
;
}
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFDATA1
,
/* file handle */
reserved
,
/* memory buffer */
cbReserveCFData
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
cbReserveCFData
)
{
PFCI_FREE
(
hfci
,
reserved
);
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err PFCI_FREE(hfci, reserved)*/
p_fci_internal
->
sizeFileCFDATA1
+=
cbReserveCFData
;
PFCI_FREE
(
hfci
,
reserved
);
}
/* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFDATA1
,
/* file handle */
p_fci_internal
->
data_out
,
/* memory buffer */
cfdata
->
cbData
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
cfdata
->
cbData
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
p_fci_internal
->
sizeFileCFDATA1
+=
cfdata
->
cbData
;
/* reset the offset */
p_fci_internal
->
cdata_in
=
0
;
p_fci_internal
->
cCompressedBytesInFolder
+=
cfdata
->
cbData
;
/* report status with pfnfcis about uncompressed and compressed file data */
if
(
(
*
pfnfcis
)(
statusFile
,
cfdata
->
cbData
,
cfdata
->
cbUncomp
,
p_fci_internal
->
pv
)
==
-
1
)
{
/* TODO set error code and abort */
return
FALSE
;
}
++
(
p_fci_internal
->
cDataBlocks
);
return
TRUE
;
}
/* end of fci_flush_data_block */
static
cab_ULONG
fci_get_checksum
(
void
*
pv
,
UINT
cb
,
CHECKSUM
seed
)
{
cab_ULONG
csum
;
cab_ULONG
ul
;
int
cUlong
;
BYTE
*
pb
;
csum
=
seed
;
cUlong
=
cb
/
4
;
pb
=
pv
;
while
(
cUlong
--
>
0
)
{
ul
=
*
pb
++
;
ul
|=
(((
cab_ULONG
)(
*
pb
++
))
<<
8
);
ul
|=
(((
cab_ULONG
)(
*
pb
++
))
<<
16
);
ul
|=
(((
cab_ULONG
)(
*
pb
++
))
<<
24
);
csum
^=
ul
;
}
ul
=
0
;
switch
(
cb
%
4
)
{
case
3
:
ul
|=
(((
ULONG
)(
*
pb
++
))
<<
16
);
case
2
:
ul
|=
(((
ULONG
)(
*
pb
++
))
<<
8
);
case
1
:
ul
|=
*
pb
++
;
default:
break
;
}
csum
^=
ul
;
return
csum
;
}
/* end of fci_get_checksum */
static
BOOL
fci_flushfolder_copy_cfdata
(
HFCI
hfci
,
char
*
buffer
,
UINT
cbReserveCFData
,
PFNFCISTATUS
pfnfcis
,
int
*
err
,
int
handleCFDATA1new
,
cab_ULONG
*
psizeFileCFDATA1new
,
cab_ULONG
*
payload
)
{
FIXME
(
"(%p, %d, %p, %p): stub
\n
"
,
hfci
,
fGetNextCab
,
pfnfcignc
,
pfnfcis
);
cab_ULONG
read_result
;
CFDATA
*
pcfdata
=
(
CFDATA
*
)
buffer
;
BOOL
split_block
=
FALSE
;
cab_UWORD
savedUncomp
=
0
;
PFCI_Int
p_fci_internal
=
((
PFCI_Int
)(
hfci
));
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
*
payload
=
0
;
/* while not all CFDATAs have been copied do */
while
(
!
FALSE
)
{
if
(
p_fci_internal
->
fNextCab
)
{
if
(
split_block
)
{
/* TODO internal error should never happen */
return
FALSE
;
}
}
/* REUSE the variable read_result */
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
read_result
=
4
;
}
else
{
read_result
=
0
;
}
if
(
p_fci_internal
->
fPrevCab
)
{
read_result
+=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
+
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
;
}
/* No more CFDATA fits into the cabinet under construction */
/* So don't try to store more data into it */
if
(
p_fci_internal
->
fNextCab
&&
(
p_fci_internal
->
oldCCAB
.
cb
<=
sizeof
(
CFDATA
)
+
cbReserveCFData
+
p_fci_internal
->
sizeFileCFFILE1
+
p_fci_internal
->
sizeFileCFDATA2
+
p_fci_internal
->
sizeFileCFFILE2
+
p_fci_internal
->
sizeFileCFFOLDER
+
sizeof
(
CFHEADER
)
+
read_result
+
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
+
sizeof
(
CFFOLDER
)
+
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
+
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
))
{
/* This may never be run for the first time the while loop is entered.
Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
split_block
=
TRUE
;
/* In this case split_block is abused to store */
/* the complete data block into the next cabinet and not into the */
/* current one. Originally split_block is the indicator that a */
/* data block has been splitted across different cabinets. */
}
else
{
/* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
read_result
=
PFCI_READ
(
hfci
,
p_fci_internal
->
handleCFDATA1
,
/*file handle*/
buffer
,
/* memory buffer */
sizeof
(
CFDATA
)
+
cbReserveCFData
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
);
if
(
read_result
!=
sizeof
(
CFDATA
)
+
cbReserveCFData
)
{
if
(
read_result
==
0
)
break
;
/* ALL DATA has been copied */
/* TODO read error */
return
FALSE
;
}
}
/* TODO error handling of err */
/***********************************************************************
* FCIFlushFolder (CABINET.12)
*/
BOOL
__cdecl
FCIFlushFolder
(
HFCI
hfci
,
PFNFCIGETNEXTCABINET
pfnfcignc
,
PFNFCISTATUS
pfnfcis
)
/* REUSE buffer p_fci_internal->data_out !!! */
/* read data from p_fci_internal->handleCFDATA1 to */
/* p_fci_internal->data_out */
if
(
PFCI_READ
(
hfci
,
p_fci_internal
->
handleCFDATA1
/* file handle */
,
p_fci_internal
->
data_out
/* memory buffer */
,
pcfdata
->
cbData
/* number of bytes to copy */
,
err
,
p_fci_internal
->
pv
)
!=
pcfdata
->
cbData
)
{
/* TODO read error */
return
FALSE
;
}
/* TODO error handling of err */
/* if cabinet size is too large */
/* REUSE the variable read_result */
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
read_result
=
4
;
}
else
{
read_result
=
0
;
}
if
(
p_fci_internal
->
fPrevCab
)
{
read_result
+=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
+
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
;
}
/* Is cabinet with new CFDATA too large? Then data block has to be split */
if
(
p_fci_internal
->
fNextCab
&&
(
p_fci_internal
->
oldCCAB
.
cb
<
sizeof
(
CFDATA
)
+
cbReserveCFData
+
pcfdata
->
cbData
+
p_fci_internal
->
sizeFileCFFILE1
+
p_fci_internal
->
sizeFileCFDATA2
+
p_fci_internal
->
sizeFileCFFILE2
+
p_fci_internal
->
sizeFileCFFOLDER
+
sizeof
(
CFHEADER
)
+
read_result
+
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
+
sizeof
(
CFFOLDER
)
+
/* size of new CFFolder entry */
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
+
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
/* name of next cabinet */
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
/* name of next disk */
))
{
/* REUSE read_result to save the size of the compressed data */
read_result
=
pcfdata
->
cbData
;
/* Modify the size of the compressed data to store only a part of the */
/* data block into the current cabinet. This is done to prevent */
/* that the maximum cabinet size will be exceeded. The remainer */
/* will be stored into the next following cabinet. */
/* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
/* Substract everything except the size of the block of data */
/* to get it's actual size */
pcfdata
->
cbData
=
p_fci_internal
->
oldCCAB
.
cb
-
(
sizeof
(
CFDATA
)
+
cbReserveCFData
+
p_fci_internal
->
sizeFileCFFILE1
+
p_fci_internal
->
sizeFileCFDATA2
+
p_fci_internal
->
sizeFileCFFILE2
+
p_fci_internal
->
sizeFileCFFOLDER
+
sizeof
(
CFHEADER
)
+
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
+
sizeof
(
CFFOLDER
)
+
/* set size of new CFFolder entry */
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
);
/* substract the size of special header fields */
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
pcfdata
->
cbData
-=
4
;
}
if
(
p_fci_internal
->
fPrevCab
)
{
pcfdata
->
cbData
-=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
+
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
;
}
pcfdata
->
cbData
-=
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
;
savedUncomp
=
pcfdata
->
cbUncomp
;
pcfdata
->
cbUncomp
=
0
;
/* on splitted blocks of data this is zero */
/* if split_block==TRUE then the above while loop won't */
/* be executed again */
split_block
=
TRUE
;
/* split_block is the indicator that */
/* a data block has been splitted across */
/* diffentent cabinets.*/
}
/* This should never happen !!! */
if
(
pcfdata
->
cbData
==
0
)
{
/* TODO set error */
return
FALSE
;
}
/* get checksum and write to cfdata.csum */
pcfdata
->
csum
=
fci_get_checksum
(
&
(
pcfdata
->
cbData
),
sizeof
(
CFDATA
)
+
cbReserveCFData
-
sizeof
(
pcfdata
->
csum
),
fci_get_checksum
(
p_fci_internal
->
data_out
,
/*buffer*/
pcfdata
->
cbData
,
0
)
);
/* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFDATA2
,
/* file handle */
buffer
,
/* memory buffer */
sizeof
(
CFDATA
)
+
cbReserveCFData
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
CFDATA
)
+
cbReserveCFData
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
p_fci_internal
->
sizeFileCFDATA2
+=
sizeof
(
CFDATA
)
+
cbReserveCFData
;
/* write compressed data into p_fci_internal->handleCFDATA2 */
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFDATA2
,
/* file handle */
p_fci_internal
->
data_out
,
/* memory buffer */
pcfdata
->
cbData
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
pcfdata
->
cbData
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
p_fci_internal
->
sizeFileCFDATA2
+=
pcfdata
->
cbData
;
++
(
p_fci_internal
->
cDataBlocks
);
p_fci_internal
->
statusFolderCopied
+=
pcfdata
->
cbData
;
(
*
payload
)
+=
pcfdata
->
cbUncomp
;
/* if cabinet size too large and data has been split */
/* write the remainer of the data block to the new CFDATA1 file */
if
(
split_block
)
{
/* This does not include the */
/* abused one (just search for "abused" )*/
/* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
if
(
p_fci_internal
->
fNextCab
==
FALSE
)
{
/* TODO internal error */
return
FALSE
;
}
/* set cbData the size of the remainer of the data block */
pcfdata
->
cbData
=
read_result
-
pcfdata
->
cbData
;
/*recover former value of cfdata.cbData; read_result will be the offset*/
read_result
-=
pcfdata
->
cbData
;
pcfdata
->
cbUncomp
=
savedUncomp
;
/* reset checksum, it will be computed later */
pcfdata
->
csum
=
0
;
/* write cfdata WITHOUT checksum to handleCFDATA1new */
if
(
PFCI_WRITE
(
hfci
,
handleCFDATA1new
,
/* file handle */
buffer
,
/* memory buffer */
sizeof
(
CFDATA
)
+
cbReserveCFData
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
CFDATA
)
+
cbReserveCFData
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */
*
psizeFileCFDATA1new
+=
sizeof
(
CFDATA
)
+
cbReserveCFData
;
/* write compressed data into handleCFDATA1new */
if
(
PFCI_WRITE
(
hfci
,
handleCFDATA1new
,
/* file handle */
p_fci_internal
->
data_out
+
read_result
,
/* memory buffer + offset */
/* to last part of split data */
pcfdata
->
cbData
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
pcfdata
->
cbData
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
p_fci_internal
->
statusFolderCopied
+=
pcfdata
->
cbData
;
*
psizeFileCFDATA1new
+=
pcfdata
->
cbData
;
/* the two blocks of the split data block have been written */
/* dont reset split_data yet, because it is still needed see below */
}
/* report status with pfnfcis about copied size of folder */
if
(
(
*
pfnfcis
)(
statusFolder
,
p_fci_internal
->
statusFolderCopied
,
/*cfdata.cbData(+previous ones)*/
p_fci_internal
->
statusFolderTotal
,
/* total folder size */
p_fci_internal
->
pv
)
==
-
1
)
{
/* TODO set error code and abort */
return
FALSE
;
}
}
/* if cabinet size too large */
/* write the remaining data blocks to the new CFDATA1 file */
if
(
split_block
)
{
/* This does include the */
/* abused one (just search for "abused" )*/
if
(
p_fci_internal
->
fNextCab
==
FALSE
)
{
/* TODO internal error */
return
FALSE
;
}
/* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
while
(
!
FALSE
)
{
/* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
read_result
=
PFCI_READ
(
hfci
,
p_fci_internal
->
handleCFDATA1
,
/* handle */
buffer
,
/* memory buffer */
sizeof
(
CFDATA
)
+
cbReserveCFData
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
);
if
(
read_result
!=
sizeof
(
CFDATA
)
+
cbReserveCFData
)
{
if
(
read_result
==
0
)
break
;
/* ALL DATA has been copied */
/* TODO read error */
return
FALSE
;
}
/* TODO error handling of err */
/* REUSE buffer p_fci_internal->data_out !!! */
/* read data from p_fci_internal->handleCFDATA1 to */
/* p_fci_internal->data_out */
if
(
PFCI_READ
(
hfci
,
p_fci_internal
->
handleCFDATA1
/* file handle */
,
p_fci_internal
->
data_out
/* memory buffer */
,
pcfdata
->
cbData
/* number of bytes to copy */
,
err
,
p_fci_internal
->
pv
)
!=
pcfdata
->
cbData
)
{
/* TODO read error */
return
FALSE
;
}
/* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */
/* write cfdata with checksum to handleCFDATA1new */
if
(
PFCI_WRITE
(
hfci
,
handleCFDATA1new
,
/* file handle */
buffer
,
/* memory buffer */
sizeof
(
CFDATA
)
+
cbReserveCFData
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
CFDATA
)
+
cbReserveCFData
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err dont forget PFCI_FREE(hfci, reserved) */
*
psizeFileCFDATA1new
+=
sizeof
(
CFDATA
)
+
cbReserveCFData
;
/* write compressed data into handleCFDATA1new */
if
(
PFCI_WRITE
(
hfci
,
handleCFDATA1new
,
/* file handle */
p_fci_internal
->
data_out
,
/* memory buffer */
pcfdata
->
cbData
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
pcfdata
->
cbData
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
*
psizeFileCFDATA1new
+=
pcfdata
->
cbData
;
p_fci_internal
->
statusFolderCopied
+=
pcfdata
->
cbData
;
/* report status with pfnfcis about copied size of folder */
if
(
(
*
pfnfcis
)(
statusFolder
,
p_fci_internal
->
statusFolderCopied
,
/*cfdata.cbData(+revious ones)*/
p_fci_internal
->
statusFolderTotal
,
/* total folder size */
p_fci_internal
->
pv
)
==
-
1
)
{
/* TODO set error code and abort */
return
FALSE
;
}
}
/* end of WHILE */
break
;
/* jump out of the next while loop */
}
/* end of if( split_data ) */
}
/* end of WHILE */
return
TRUE
;
}
/* end of fci_flushfolder_copy_cfdata */
static
BOOL
fci_flushfolder_copy_cffolder
(
HFCI
hfci
,
int
*
err
,
UINT
cbReserveCFFolder
,
cab_ULONG
sizeFileCFDATA2old
)
{
FIXME
(
"(%p, %p, %p): stub
\n
"
,
hfci
,
pfnfcignc
,
pfnfcis
);
CFFOLDER
cffolder
;
UINT
i
;
char
*
reserved
;
PFCI_Int
p_fci_internal
=
((
PFCI_Int
)(
hfci
));
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
/* absolute offset cannot be set yet, because the size of cabinet header, */
/* the number of CFFOLDERs and the number of CFFILEs may change. */
/* Instead the size of all previous data blocks will be stored and */
/* the remainer of the offset will be added when the cabinet will be */
/* flushed to disk. */
/* This is exactly the way the original CABINET.DLL works!!! */
cffolder
.
coffCabStart
=
sizeFileCFDATA2old
;
/* set the number of this folder's CFDATA sections */
cffolder
.
cCFData
=
p_fci_internal
->
cDataBlocks
;
/* TODO set compression type */
cffolder
.
typeCompress
=
tcompTYPE_NONE
;
/* write cffolder to p_fci_internal->handleCFFOLDER */
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFFOLDER
,
/* file handle */
&
cffolder
,
/* memory buffer */
sizeof
(
cffolder
),
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
cffolder
)
)
{
/* TODO write error */
return
FALSE
;
}
}
/* TODO error handling of err */
/***********************************************************************
* FCIDestroy (CABINET.14)
*
* Frees a handle created by FCICreate.
* Only reason for failure would be an invalid handle.
*
* PARAMS
* hfci [I] The HFCI to free
*
* RETURNS
* TRUE for success
* FALSE for failure
*/
BOOL
__cdecl
FCIDestroy
(
HFCI
hfci
)
p_fci_internal
->
sizeFileCFFOLDER
+=
sizeof
(
cffolder
);
/* add optional reserved area */
if
(
cbReserveCFFolder
!=
0
)
{
if
(
!
(
reserved
=
(
char
*
)
PFCI_ALLOC
(
hfci
,
cbReserveCFFolder
)))
{
p_fci_internal
->
perf
->
erfOper
=
FCIERR_ALLOC_FAIL
;
p_fci_internal
->
perf
->
erfType
=
ERROR_NOT_ENOUGH_MEMORY
;
p_fci_internal
->
perf
->
fError
=
TRUE
;
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
}
for
(
i
=
0
;
i
<
cbReserveCFFolder
;)
{
reserved
[
i
++
]
=
'\0'
;
}
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFFOLDER
,
/* file handle */
reserved
,
/* memory buffer */
cbReserveCFFolder
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
cbReserveCFFolder
)
{
PFCI_FREE
(
hfci
,
reserved
);
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
p_fci_internal
->
sizeFileCFFOLDER
+=
cbReserveCFFolder
;
PFCI_FREE
(
hfci
,
reserved
);
}
return
TRUE
;
}
/* end of fci_flushfolder_copy_cffolder */
static
BOOL
fci_flushfolder_copy_cffile
(
HFCI
hfci
,
int
*
err
,
int
handleCFFILE1new
,
cab_ULONG
*
psizeFileCFFILE1new
,
cab_ULONG
payload
)
{
if
(
REALLY_IS_FCI
(
hfci
))
{
PFCI_INT
(
hfci
)
->
FCI_Intmagic
=
0
;
PFDI_FREE
(
hfci
,
hfci
);
/*return TRUE; */
CFFILE
cffile
;
cab_ULONG
read_result
;
cab_ULONG
seek
=
0
;
cab_ULONG
sizeOfFiles
=
0
,
sizeOfFilesPrev
;
BOOL
may_be_prev
=
TRUE
;
cab_ULONG
cbFileRemainer
=
0
;
PFCI_Int
p_fci_internal
=
((
PFCI_Int
)(
hfci
));
/* set seek of p_fci_internal->handleCFFILE1 to 0 */
if
(
PFCI_SEEK
(
hfci
,
p_fci_internal
->
handleCFFILE1
,
0
,
SEEK_SET
,
err
,
p_fci_internal
->
pv
)
!=
0
)
{
/* TODO wrong return value */
}
/* TODO error handling of err */
/* while not all CFFILE structures have been copied do */
while
(
!
FALSE
)
{
/* REUSE the variable read_result */
/* read data from p_fci_internal->handleCFFILE1 to cffile */
read_result
=
PFCI_READ
(
hfci
,
p_fci_internal
->
handleCFFILE1
/* file handle */
,
&
cffile
,
/* memory buffer */
sizeof
(
cffile
),
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
);
if
(
read_result
!=
sizeof
(
cffile
)
)
{
if
(
read_result
==
0
)
break
;
/* ALL CFFILE structures have been copied */
/* TODO read error */
return
FALSE
;
}
/* TODO error handling of err */
/* Microsoft's(R) CABINET.DLL would do a seek to the current! */
/* position. I don't know why so I'll just omit it */
/* read the filename from p_fci_internal->handleCFFILE1 */
/* REUSE the variable read_result AGAIN */
/* REUSE the memory buffer PFCI(hfci)->data_out */
if
(
PFCI_READ
(
hfci
,
p_fci_internal
->
handleCFFILE1
/*file handle*/
,
p_fci_internal
->
data_out
,
/* memory buffer */
CB_MAX_FILENAME
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
<
2
)
{
/* TODO read error */
return
FALSE
;
}
/* TODO maybe other checks of read_result */
/* TODO error handling of err */
/* safety */
if
(
strlen
(
p_fci_internal
->
data_out
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code internal error */
return
FALSE
;
}
seek
+=
sizeof
(
cffile
)
+
strlen
(
p_fci_internal
->
data_out
)
+
1
;
/* set seek of p_fci_internal->handleCFFILE1 to end of file name */
/* i.e. seek to the next CFFILE area */
if
(
PFCI_SEEK
(
hfci
,
p_fci_internal
->
handleCFFILE1
,
seek
,
/* seek position*/
SEEK_SET
,
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
cffile
)
+
strlen
(
p_fci_internal
->
data_out
)
+
1
)
{
/* TODO wrong return value */
}
/* TODO error handling of err */
/* fnfilfnfildest: placed file on cabinet */
if
(
p_fci_internal
->
fNextCab
||
p_fci_internal
->
fGetNextCabInVain
)
{
PFCI_FILEPLACED
(
hfci
,
&
(
p_fci_internal
->
oldCCAB
),
p_fci_internal
->
data_out
,
/* the file name*/
cffile
.
cbFile
,
/* file size */
(
cffile
.
iFolder
==
cffileCONTINUED_FROM_PREV
),
p_fci_internal
->
pv
);
}
else
{
SetLastError
(
ERROR_INVALID_HANDLE
);
PFCI_FILEPLACED
(
hfci
,
p_fci_internal
->
pccab
,
p_fci_internal
->
data_out
,
/* the file name*/
cffile
.
cbFile
,
/* file size */
(
cffile
.
iFolder
==
cffileCONTINUED_FROM_PREV
),
p_fci_internal
->
pv
);
}
/* Check special iFolder values */
if
(
cffile
.
iFolder
==
cffileCONTINUED_FROM_PREV
&&
p_fci_internal
->
fPrevCab
==
FALSE
)
{
/* THIS MAY NEVER HAPPEN */
/* TODO set error code */
return
FALSE
;
}
if
(
cffile
.
iFolder
==
cffileCONTINUED_PREV_AND_NEXT
||
cffile
.
iFolder
==
cffileCONTINUED_TO_NEXT
)
{
/* THIS MAY NEVER HAPPEN */
/* TODO set error code */
return
FALSE
;
}
if
(
may_be_prev
&&
cffile
.
iFolder
!=
cffileCONTINUED_FROM_PREV
)
{
may_be_prev
=
FALSE
;
}
if
(
cffile
.
iFolder
==
cffileCONTINUED_FROM_PREV
&&
may_be_prev
==
FALSE
)
{
/* THIS MAY NEVER HAPPEN */
/* TODO set error code */
return
FALSE
;
}
if
(
cffile
.
iFolder
!=
cffileCONTINUED_FROM_PREV
)
{
may_be_prev
=
FALSE
;
}
sizeOfFilesPrev
=
sizeOfFiles
;
/* Set complete size of all processed files */
if
(
cffile
.
iFolder
==
cffileCONTINUED_FROM_PREV
&&
p_fci_internal
->
cbFileRemainer
!=
0
)
{
sizeOfFiles
+=
p_fci_internal
->
cbFileRemainer
;
p_fci_internal
->
cbFileRemainer
=
0
;
}
else
{
sizeOfFiles
+=
cffile
.
cbFile
;
}
/* Check if spanned file fits into this cabinet folder */
if
(
cffile
.
iFolder
==
cffileCONTINUED_FROM_PREV
&&
sizeOfFiles
>
payload
)
{
cffile
.
iFolder
=
cffileCONTINUED_PREV_AND_NEXT
;
}
else
/* Check if file doesn't fit into this cabinet folder */
if
(
sizeOfFiles
>
payload
)
{
cffile
.
iFolder
=
cffileCONTINUED_TO_NEXT
;
}
/* Still mark as incomplete, because of other missing FCI* APIs */
FIXME
(
"(%p): stub
\n
"
,
hfci
);
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
/* write cffile to p_fci_internal->handleCFFILE2 */
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFFILE2
,
/* file handle */
&
cffile
,
/* memory buffer */
sizeof
(
cffile
),
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
cffile
)
)
{
/* TODO write error */
return
FALSE
;
}
}
/* TODO error handling of err */
p_fci_internal
->
sizeFileCFFILE2
+=
sizeof
(
cffile
);
/* write file name to p_fci_internal->handleCFFILE2 */
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFFILE2
,
/* file handle */
p_fci_internal
->
data_out
,
/* memory buffer */
strlen
(
p_fci_internal
->
data_out
)
+
1
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
strlen
(
p_fci_internal
->
data_out
)
+
1
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
p_fci_internal
->
sizeFileCFFILE2
+=
strlen
(
p_fci_internal
->
data_out
)
+
1
;
/* cFiles is used to count all files of a cabinet */
++
(
p_fci_internal
->
cFiles
);
/* This is only true for files which will be written into the */
/* next cabinet of the spanning folder */
if
(
sizeOfFiles
>
payload
)
{
/* Files which data will be partially written into the current cabinet */
if
(
cffile
.
iFolder
==
cffileCONTINUED_PREV_AND_NEXT
||
cffile
.
iFolder
==
cffileCONTINUED_TO_NEXT
)
{
if
(
sizeOfFilesPrev
<=
payload
)
{
/* The size of the uncompressed, data of a spanning file in a */
/* spanning data */
cbFileRemainer
=
sizeOfFiles
-
payload
;
}
cffile
.
iFolder
=
cffileCONTINUED_FROM_PREV
;
}
else
{
cffile
.
iFolder
=
0
;
}
/* write cffile into handleCFFILE1new */
if
(
PFCI_WRITE
(
hfci
,
handleCFFILE1new
,
/* file handle */
&
cffile
,
/* memory buffer */
sizeof
(
cffile
),
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
cffile
)
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
*
psizeFileCFFILE1new
+=
sizeof
(
cffile
);
/* write name of file into handleCFFILE1new */
if
(
PFCI_WRITE
(
hfci
,
handleCFFILE1new
,
/* file handle */
p_fci_internal
->
data_out
,
/* memory buffer */
strlen
(
p_fci_internal
->
data_out
)
+
1
,
/* number of bytes to copy */
err
,
p_fci_internal
->
pv
)
!=
strlen
(
p_fci_internal
->
data_out
)
+
1
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
*
psizeFileCFFILE1new
+=
strlen
(
p_fci_internal
->
data_out
)
+
1
;
}
}
/* END OF while */
p_fci_internal
->
cbFileRemainer
=
cbFileRemainer
;
return
TRUE
;
}
/* end of fci_flushfolder_copy_cffile */
static
BOOL
fci_flush_folder
(
HFCI
hfci
,
BOOL
fGetNextCab
,
PFNFCIGETNEXTCABINET
pfnfcignc
,
PFNFCISTATUS
pfnfcis
)
{
int
err
;
int
handleCFDATA1new
;
/* handle for new temp file */
char
szFileNameCFDATA1new
[
CB_MAX_FILENAME
];
/* name buffer for temp file */
int
handleCFFILE1new
;
/* handle for new temp file */
char
szFileNameCFFILE1new
[
CB_MAX_FILENAME
];
/* name buffer for temp file */
UINT
cbReserveCFData
,
cbReserveCFFolder
;
char
*
reserved
;
cab_ULONG
sizeFileCFDATA1new
=
0
;
cab_ULONG
sizeFileCFFILE1new
=
0
;
cab_ULONG
sizeFileCFDATA2old
;
cab_ULONG
payload
;
cab_ULONG
read_result
;
PFCI_Int
p_fci_internal
=
((
PFCI_Int
)(
hfci
));
/* test hfci */
if
(
!
REALLY_IS_FCI
(
hfci
))
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
if
((
!
pfnfcignc
)
||
(
!
pfnfcis
))
{
p_fci_internal
->
perf
->
erfOper
=
FCIERR_NONE
;
p_fci_internal
->
perf
->
erfType
=
ERROR_BAD_ARGUMENTS
;
p_fci_internal
->
perf
->
fError
=
TRUE
;
SetLastError
(
ERROR_BAD_ARGUMENTS
);
return
FALSE
;
}
if
(
p_fci_internal
->
fGetNextCabInVain
&&
p_fci_internal
->
fNextCab
){
/* TODO internal error */
return
FALSE
;
}
/* If there was no FCIAddFile or FCIFlushFolder has already been called */
/* this function will return TRUE */
if
(
p_fci_internal
->
sizeFileCFFILE1
==
0
)
{
if
(
p_fci_internal
->
sizeFileCFDATA1
!=
0
)
{
/* TODO error handling */
return
FALSE
;
}
return
TRUE
;
}
if
(
p_fci_internal
->
data_in
==
NULL
||
p_fci_internal
->
data_out
==
NULL
)
{
/* TODO error handling */
return
FALSE
;
}
/* FCIFlushFolder has already been called... */
if
(
p_fci_internal
->
fSplitFolder
&&
p_fci_internal
->
sizeFileCFFILE2
!=
0
)
{
if
(
p_fci_internal
->
sizeFileCFFILE2
==
0
)
{
/* TODO set error code */
return
FALSE
;
}
return
TRUE
;
}
/* TODO check what will happen when return FALSE later */
/* and p_fci_internal->fSplitFolder is set to FALSE */
p_fci_internal
->
fSplitFolder
=
FALSE
;
if
(
p_fci_internal
->
fGetNextCabInVain
||
p_fci_internal
->
fNextCab
){
cbReserveCFData
=
p_fci_internal
->
oldCCAB
.
cbReserveCFData
;
cbReserveCFFolder
=
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
;
}
else
{
cbReserveCFData
=
p_fci_internal
->
pccab
->
cbReserveCFData
;
cbReserveCFFolder
=
p_fci_internal
->
pccab
->
cbReserveCFFolder
;
}
/* START of COPY */
/* if there is data in p_fci_internal->data_in */
if
(
p_fci_internal
->
cdata_in
!=
0
)
{
if
(
!
fci_flush_data_block
(
hfci
,
&
err
,
pfnfcis
)
)
return
FALSE
;
}
/* reset to get the number of data blocks of this folder which are */
/* actually in this cabinet ( at least partially ) */
p_fci_internal
->
cDataBlocks
=
0
;
if
(
p_fci_internal
->
fNextCab
||
p_fci_internal
->
fGetNextCabInVain
)
{
read_result
=
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
+
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
;
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
read_result
+=
4
;
}
}
else
{
read_result
=
p_fci_internal
->
pccab
->
cbReserveCFHeader
+
p_fci_internal
->
pccab
->
cbReserveCFFolder
;
if
(
p_fci_internal
->
pccab
->
cbReserveCFHeader
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFFolder
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFData
!=
0
)
{
read_result
+=
4
;
}
}
if
(
p_fci_internal
->
fPrevCab
)
{
read_result
+=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
+
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
;
}
if
(
p_fci_internal
->
fNextCab
)
{
read_result
+=
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
;
}
p_fci_internal
->
statusFolderTotal
=
sizeof
(
CFHEADER
)
+
read_result
+
sizeof
(
CFFOLDER
)
+
p_fci_internal
->
sizeFileCFFILE2
+
p_fci_internal
->
sizeFileCFDATA2
+
p_fci_internal
->
sizeFileCFFILE1
+
p_fci_internal
->
sizeFileCFDATA1
;
p_fci_internal
->
statusFolderCopied
=
0
;
/* report status with pfnfcis about copied size of folder */
if
(
(
*
pfnfcis
)(
statusFolder
,
p_fci_internal
->
statusFolderCopied
,
p_fci_internal
->
statusFolderTotal
,
/* TODO total folder size */
p_fci_internal
->
pv
)
==
-
1
)
{
/* TODO set error code and abort */
return
FALSE
;
}
/* get a new temp file */
if
(
!
PFCI_GETTEMPFILE
(
hfci
,
szFileNameCFDATA1new
,
CB_MAX_FILENAME
))
{
/* TODO error handling */
return
FALSE
;
}
/* safety */
if
(
strlen
(
szFileNameCFDATA1new
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code */
return
FALSE
;
}
handleCFDATA1new
=
PFCI_OPEN
(
hfci
,
szFileNameCFDATA1new
,
34050
,
384
,
&
err
,
p_fci_internal
->
pv
);
/* get a new temp file */
if
(
!
PFCI_GETTEMPFILE
(
hfci
,
szFileNameCFFILE1new
,
CB_MAX_FILENAME
))
{
/* TODO error handling */
PFCI_CLOSE
(
hfci
,
handleCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
return
FALSE
;
}
/* safety */
if
(
strlen
(
szFileNameCFFILE1new
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code */
PFCI_CLOSE
(
hfci
,
handleCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
return
FALSE
;
}
handleCFFILE1new
=
PFCI_OPEN
(
hfci
,
szFileNameCFFILE1new
,
34050
,
384
,
&
err
,
p_fci_internal
->
pv
);
/* USE the variable read_result */
if
(
p_fci_internal
->
fNextCab
||
p_fci_internal
->
fGetNextCabInVain
)
{
read_result
=
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
;
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
read_result
+=
4
;
}
}
else
{
read_result
=
p_fci_internal
->
pccab
->
cbReserveCFHeader
;
if
(
p_fci_internal
->
pccab
->
cbReserveCFHeader
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFFolder
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFData
!=
0
)
{
read_result
+=
4
;
}
}
if
(
p_fci_internal
->
fPrevCab
)
{
read_result
+=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
+
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
;
}
read_result
+=
sizeof
(
CFHEADER
)
+
p_fci_internal
->
sizeFileCFDATA2
+
p_fci_internal
->
sizeFileCFFILE2
+
p_fci_internal
->
sizeFileCFFOLDER
;
if
(
p_fci_internal
->
sizeFileCFFILE1
!=
0
)
{
read_result
+=
sizeof
(
CFFOLDER
)
+
p_fci_internal
->
pccab
->
cbReserveCFFolder
;
}
/* Check if multiple cabinets have to be created. */
/* Might be too much data for the maximum allowed cabinet size.*/
/* When any further data will be added later, it might not */
/* be possible to flush the cabinet, because there might */
/* not be enough space to store the name of the following */
/* cabinet and name of the corresponding disk. */
/* So take care of this and get the name of the next cabinet */
if
(
p_fci_internal
->
fGetNextCabInVain
==
FALSE
&&
p_fci_internal
->
fNextCab
==
FALSE
&&
(
(
p_fci_internal
->
pccab
->
cb
<
read_result
+
p_fci_internal
->
sizeFileCFDATA1
+
p_fci_internal
->
sizeFileCFFILE1
+
CB_MAX_CABINET_NAME
+
/* next cabinet name */
CB_MAX_DISK_NAME
/* next disk name */
)
||
fGetNextCab
)
)
{
/* save CCAB */
memcpy
(
&
(
p_fci_internal
->
oldCCAB
),
p_fci_internal
->
pccab
,
sizeof
(
CCAB
));
/* increment cabinet index */
++
(
p_fci_internal
->
pccab
->
iCab
);
/* get name of next cabinet */
if
(
!
(
*
pfnfcignc
)(
p_fci_internal
->
pccab
,
0
,
/* estimated size of cab */
p_fci_internal
->
pv
))
{
/* TODO error handling */
PFCI_CLOSE
(
hfci
,
handleCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
handleCFFILE1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
return
FALSE
;
}
/* Skip a few lines of code. This is catched by the next if. */
p_fci_internal
->
fGetNextCabInVain
=
TRUE
;
}
/* too much data for cabinet */
if
(
(
p_fci_internal
->
fGetNextCabInVain
||
p_fci_internal
->
fNextCab
)
&&
(
(
p_fci_internal
->
oldCCAB
.
cb
<
read_result
+
p_fci_internal
->
sizeFileCFDATA1
+
p_fci_internal
->
sizeFileCFFILE1
+
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
/* next cabinet name */
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
/* next disk name */
)
||
fGetNextCab
)
)
{
p_fci_internal
->
fGetNextCabInVain
=
FALSE
;
p_fci_internal
->
fNextCab
=
TRUE
;
/* return FALSE if there is not enough space left*/
/* this should never happen */
if
(
p_fci_internal
->
oldCCAB
.
cb
<=
p_fci_internal
->
sizeFileCFFILE1
+
read_result
+
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
/* next cabinet name */
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
/* next disk name */
)
{
PFCI_CLOSE
(
hfci
,
handleCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
szFileNameCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
/* close and delete p_fci_internal->handleCFFILE1 */
PFCI_CLOSE
(
hfci
,
handleCFFILE1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
szFileNameCFFILE1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
return
FALSE
;
}
/* the folder will be split across cabinets */
p_fci_internal
->
fSplitFolder
=
TRUE
;
}
else
{
/* this should never happen */
if
(
p_fci_internal
->
fNextCab
)
{
/* TODO internal error */
return
FALSE
;
}
}
/* set seek of p_fci_internal->handleCFDATA1 to 0 */
if
(
PFCI_SEEK
(
hfci
,
p_fci_internal
->
handleCFDATA1
,
0
,
SEEK_SET
,
&
err
,
p_fci_internal
->
pv
)
!=
0
)
{
/* TODO wrong return value */
PFCI_CLOSE
(
hfci
,
handleCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
handleCFFILE1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
return
FALSE
;
}
/* TODO error handling of err */
/* save size of file CFDATA2 - required for the folder's offset to data */
sizeFileCFDATA2old
=
p_fci_internal
->
sizeFileCFDATA2
;
if
(
!
(
reserved
=
(
char
*
)
PFCI_ALLOC
(
hfci
,
cbReserveCFData
+
sizeof
(
CFDATA
))))
{
p_fci_internal
->
perf
->
erfOper
=
FCIERR_ALLOC_FAIL
;
p_fci_internal
->
perf
->
erfType
=
ERROR_NOT_ENOUGH_MEMORY
;
p_fci_internal
->
perf
->
fError
=
TRUE
;
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
PFCI_CLOSE
(
hfci
,
handleCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
handleCFFILE1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
return
FALSE
;
}
if
(
!
fci_flushfolder_copy_cfdata
(
hfci
,
reserved
,
cbReserveCFData
,
pfnfcis
,
&
err
,
handleCFDATA1new
,
&
sizeFileCFDATA1new
,
&
payload
))
{
PFCI_CLOSE
(
hfci
,
handleCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
szFileNameCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
handleCFFILE1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_FREE
(
hfci
,
reserved
);
return
FALSE
;
}
PFCI_FREE
(
hfci
,
reserved
);
if
(
!
fci_flushfolder_copy_cffolder
(
hfci
,
&
err
,
cbReserveCFFolder
,
sizeFileCFDATA2old
))
{
PFCI_CLOSE
(
hfci
,
handleCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
szFileNameCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
handleCFFILE1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
return
FALSE
;
}
if
(
!
fci_flushfolder_copy_cffile
(
hfci
,
&
err
,
handleCFFILE1new
,
&
sizeFileCFFILE1new
,
payload
))
{
PFCI_CLOSE
(
hfci
,
handleCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
szFileNameCFDATA1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
handleCFFILE1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
szFileNameCFFILE1new
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
return
FALSE
;
}
/* close and delete p_fci_internal->handleCFDATA1 */
PFCI_CLOSE
(
hfci
,
p_fci_internal
->
handleCFDATA1
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
p_fci_internal
->
szFileNameCFDATA1
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
/* put new CFDATA1 into hfci */
memcpy
(
p_fci_internal
->
szFileNameCFDATA1
,
szFileNameCFDATA1new
,
CB_MAX_FILENAME
);
/* put CFDATA1 file handle */
PFCI_INT
(
hfci
)
->
handleCFDATA1
=
handleCFDATA1new
;
/* set file size */
PFCI_INT
(
hfci
)
->
sizeFileCFDATA1
=
sizeFileCFDATA1new
;
/* close and delete PFCI_INT(hfci)->handleCFFILE1 */
PFCI_CLOSE
(
hfci
,
p_fci_internal
->
handleCFFILE1
,
&
err
,
PFCI_INT
(
hfci
)
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
p_fci_internal
->
szFileNameCFFILE1
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
/* put new CFFILE1 into hfci */
memcpy
(
p_fci_internal
->
szFileNameCFFILE1
,
szFileNameCFFILE1new
,
CB_MAX_FILENAME
);
/* put CFFILE1 file handle */
p_fci_internal
->
handleCFFILE1
=
handleCFFILE1new
;
/* set file size */
p_fci_internal
->
sizeFileCFFILE1
=
sizeFileCFFILE1new
;
++
(
p_fci_internal
->
cFolders
);
/* reset CFFolder specific information */
p_fci_internal
->
cDataBlocks
=
0
;
p_fci_internal
->
cCompressedBytesInFolder
=
0
;
return
TRUE
;
}
/* end of fci_flush_folder */
static
BOOL
fci_flush_cabinet
(
HFCI
hfci
,
BOOL
fGetNextCab
,
PFNFCIGETNEXTCABINET
pfnfcignc
,
PFNFCISTATUS
pfnfcis
)
{
int
err
;
CFHEADER
cfheader
;
struct
{
cab_UWORD
cbCFHeader
;
cab_UBYTE
cbCFFolder
;
cab_UBYTE
cbCFData
;
}
cfreserved
;
CFFOLDER
cffolder
;
cab_ULONG
read_result
;
int
handleCABINET
;
/* file handle for cabinet */
char
pszFileNameCABINET
[
CB_MAX_CAB_PATH
+
CB_MAX_CABINET_NAME
];
/* name buffer */
UINT
cbReserveCFHeader
,
cbReserveCFFolder
,
i
;
char
*
reserved
;
BOOL
returntrue
=
FALSE
;
PFCI_Int
p_fci_internal
=
((
PFCI_Int
)(
hfci
));
/* TODO test if fci_flush_cabinet really aborts if there was no FCIAddFile */
/* when FCIFlushCabinet was or FCIAddFile wasn't called */
if
(
p_fci_internal
->
sizeFileCFFILE1
==
0
&&
fGetNextCab
)
{
returntrue
=
TRUE
;
}
if
(
!
fci_flush_folder
(
hfci
,
fGetNextCab
,
pfnfcignc
,
pfnfcis
)){
/* TODO set error */
return
FALSE
;
}
if
(
returntrue
)
return
TRUE
;
if
(
p_fci_internal
->
fSplitFolder
&&
p_fci_internal
->
fNextCab
==
FALSE
)
{
/* TODO internal error */
return
FALSE
;
}
if
(
p_fci_internal
->
fNextCab
||
p_fci_internal
->
fGetNextCabInVain
)
{
cbReserveCFFolder
=
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
;
cbReserveCFHeader
=
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
;
/* safety */
if
(
strlen
(
p_fci_internal
->
oldCCAB
.
szCabPath
)
>=
CB_MAX_CAB_PATH
||
strlen
(
p_fci_internal
->
oldCCAB
.
szCab
)
>=
CB_MAX_CABINET_NAME
)
{
/* TODO set error */
return
FALSE
;
}
/* get the full name of the cabinet */
memcpy
(
pszFileNameCABINET
,
p_fci_internal
->
oldCCAB
.
szCabPath
,
CB_MAX_CAB_PATH
);
memcpy
(
pszFileNameCABINET
+
strlen
(
pszFileNameCABINET
),
p_fci_internal
->
oldCCAB
.
szCab
,
CB_MAX_CABINET_NAME
);
}
else
{
cbReserveCFFolder
=
p_fci_internal
->
pccab
->
cbReserveCFFolder
;
cbReserveCFHeader
=
p_fci_internal
->
pccab
->
cbReserveCFHeader
;
/* safety */
if
(
strlen
(
p_fci_internal
->
pccab
->
szCabPath
)
>=
CB_MAX_CAB_PATH
||
strlen
(
p_fci_internal
->
pccab
->
szCab
)
>=
CB_MAX_CABINET_NAME
)
{
/* TODO set error */
return
FALSE
;
}
/* get the full name of the cabinet */
memcpy
(
pszFileNameCABINET
,
p_fci_internal
->
pccab
->
szCabPath
,
CB_MAX_CAB_PATH
);
memcpy
(
pszFileNameCABINET
+
strlen
(
pszFileNameCABINET
),
p_fci_internal
->
pccab
->
szCab
,
CB_MAX_CABINET_NAME
);
}
/* create the cabinet */
handleCABINET
=
PFCI_OPEN
(
hfci
,
pszFileNameCABINET
,
33538
,
384
,
&
err
,
p_fci_internal
->
pv
);
/* TODO check handle */
/* TODO error checking of err */
memcpy
(
cfheader
.
signature
,
"!CAB"
,
4
);
cfheader
.
reserved1
=
0
;
cfheader
.
cbCabinet
=
/* size of the cabinet file in bytes */
sizeof
(
CFHEADER
)
+
p_fci_internal
->
sizeFileCFFOLDER
+
p_fci_internal
->
sizeFileCFFILE2
+
p_fci_internal
->
sizeFileCFDATA2
;
if
(
p_fci_internal
->
fPrevCab
)
{
cfheader
.
cbCabinet
+=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
+
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
;
}
if
(
p_fci_internal
->
fNextCab
)
{
cfheader
.
cbCabinet
+=
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
;
}
if
(
p_fci_internal
->
fNextCab
||
p_fci_internal
->
fGetNextCabInVain
)
{
cfheader
.
cbCabinet
+=
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
;
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
cfheader
.
cbCabinet
+=
4
;
}
}
else
{
cfheader
.
cbCabinet
+=
p_fci_internal
->
pccab
->
cbReserveCFHeader
;
if
(
p_fci_internal
->
pccab
->
cbReserveCFHeader
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFFolder
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFData
!=
0
)
{
cfheader
.
cbCabinet
+=
4
;
}
}
cfheader
.
reserved2
=
0
;
cfheader
.
coffFiles
=
/* offset to first CFFILE section */
cfheader
.
cbCabinet
-
p_fci_internal
->
sizeFileCFFILE2
-
p_fci_internal
->
sizeFileCFDATA2
;
cfheader
.
reserved3
=
0
;
cfheader
.
versionMinor
=
3
;
cfheader
.
versionMajor
=
1
;
/* number of CFFOLDER entries in the cabinet */
cfheader
.
cFolders
=
p_fci_internal
->
cFolders
;
/* number of CFFILE entries in the cabinet */
cfheader
.
cFiles
=
p_fci_internal
->
cFiles
;
cfheader
.
flags
=
0
;
/* 1=prev cab, 2=next cabinet, 4=reserved setions */
if
(
p_fci_internal
->
fPrevCab
)
{
cfheader
.
flags
=
cfheadPREV_CABINET
;
}
if
(
p_fci_internal
->
fNextCab
)
{
cfheader
.
flags
|=
cfheadNEXT_CABINET
;
}
if
(
p_fci_internal
->
fNextCab
||
p_fci_internal
->
fGetNextCabInVain
)
{
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
cfheader
.
flags
|=
cfheadRESERVE_PRESENT
;
}
cfheader
.
setID
=
p_fci_internal
->
oldCCAB
.
setID
;
cfheader
.
iCabinet
=
p_fci_internal
->
oldCCAB
.
iCab
-
1
;
}
else
{
if
(
p_fci_internal
->
pccab
->
cbReserveCFHeader
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFFolder
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFData
!=
0
)
{
cfheader
.
flags
|=
cfheadRESERVE_PRESENT
;
}
cfheader
.
setID
=
p_fci_internal
->
pccab
->
setID
;
cfheader
.
iCabinet
=
p_fci_internal
->
pccab
->
iCab
-
1
;
}
/* write CFHEADER into cabinet file */
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
&
cfheader
,
/* memory buffer */
sizeof
(
cfheader
),
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
cfheader
)
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
if
(
cfheader
.
flags
&
cfheadRESERVE_PRESENT
)
{
/* NOTE: No checks for maximum value overflows as designed by MS!!! */
cfreserved
.
cbCFHeader
=
cbReserveCFHeader
;
cfreserved
.
cbCFFolder
=
cbReserveCFFolder
;
if
(
p_fci_internal
->
fNextCab
||
p_fci_internal
->
fGetNextCabInVain
)
{
cfreserved
.
cbCFData
=
p_fci_internal
->
oldCCAB
.
cbReserveCFData
;
}
else
{
cfreserved
.
cbCFData
=
p_fci_internal
->
pccab
->
cbReserveCFData
;
}
/* write reserved info into cabinet file */
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
&
cfreserved
,
/* memory buffer */
sizeof
(
cfreserved
),
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
cfreserved
)
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
}
/* add optional reserved area */
if
(
cbReserveCFHeader
!=
0
)
{
if
(
!
(
reserved
=
(
char
*
)
PFCI_ALLOC
(
hfci
,
cbReserveCFHeader
)))
{
p_fci_internal
->
perf
->
erfOper
=
FCIERR_ALLOC_FAIL
;
p_fci_internal
->
perf
->
erfType
=
ERROR_NOT_ENOUGH_MEMORY
;
p_fci_internal
->
perf
->
fError
=
TRUE
;
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
}
for
(
i
=
0
;
i
<
cbReserveCFHeader
;)
{
reserved
[
i
++
]
=
'\0'
;
}
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
reserved
,
/* memory buffer */
cbReserveCFHeader
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
cbReserveCFHeader
)
{
PFCI_FREE
(
hfci
,
reserved
);
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
PFCI_FREE
(
hfci
,
reserved
);
}
if
(
cfheader
.
flags
&
cfheadPREV_CABINET
)
{
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
p_fci_internal
->
szPrevCab
,
/* memory buffer */
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
p_fci_internal
->
szPrevDisk
,
/* memory buffer */
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
}
if
(
cfheader
.
flags
&
cfheadNEXT_CABINET
)
{
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
p_fci_internal
->
pccab
->
szCab
,
/* memory buffer */
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
p_fci_internal
->
pccab
->
szDisk
,
/* memory buffer */
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
}
/* set seek of p_fci_internal->handleCFFOLDER to 0 */
if
(
PFCI_SEEK
(
hfci
,
p_fci_internal
->
handleCFFOLDER
,
0
,
SEEK_SET
,
&
err
,
p_fci_internal
->
pv
)
!=
0
)
{
/* TODO wrong return value */
}
/* TODO error handling of err */
/* while not all CFFOLDER structures have been copied into the cabinet do */
while
(
!
FALSE
)
{
/* use the variable read_result */
/* read cffolder of p_fci_internal->handleCFFOLDER */
read_result
=
PFCI_READ
(
hfci
,
p_fci_internal
->
handleCFFOLDER
,
/* handle */
&
cffolder
,
/* memory buffer */
sizeof
(
cffolder
),
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
);
if
(
read_result
!=
sizeof
(
cffolder
)
)
{
if
(
read_result
==
0
)
break
;
/*ALL CFFOLDER structures have been copied*/
/* TODO read error */
return
FALSE
;
}
/* TODO error handling of err */
/* add size of header size of all CFFOLDERs and size of all CFFILEs */
cffolder
.
coffCabStart
+=
p_fci_internal
->
sizeFileCFFILE2
+
p_fci_internal
->
sizeFileCFFOLDER
+
sizeof
(
CFHEADER
);
if
(
p_fci_internal
->
fNextCab
||
p_fci_internal
->
fGetNextCabInVain
)
{
cffolder
.
coffCabStart
+=
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
;
}
else
{
cffolder
.
coffCabStart
+=
p_fci_internal
->
pccab
->
cbReserveCFHeader
;
}
if
(
p_fci_internal
->
fPrevCab
)
{
cffolder
.
coffCabStart
+=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
+
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
;
}
if
(
p_fci_internal
->
fNextCab
)
{
cffolder
.
coffCabStart
+=
strlen
(
p_fci_internal
->
oldCCAB
.
szCab
)
+
1
+
strlen
(
p_fci_internal
->
oldCCAB
.
szDisk
)
+
1
;
}
if
(
p_fci_internal
->
fNextCab
||
p_fci_internal
->
fGetNextCabInVain
)
{
cffolder
.
coffCabStart
+=
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
;
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
cffolder
.
coffCabStart
+=
4
;
}
}
else
{
cffolder
.
coffCabStart
+=
p_fci_internal
->
pccab
->
cbReserveCFHeader
;
if
(
p_fci_internal
->
pccab
->
cbReserveCFHeader
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFFolder
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFData
!=
0
)
{
cffolder
.
coffCabStart
+=
4
;
}
}
/* write cffolder to cabinet file */
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
&
cffolder
,
/* memory buffer */
sizeof
(
cffolder
),
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
cffolder
)
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
/* add optional reserved area */
/* This allocation and freeing at each CFFolder block is a bit */
/* inefficent, but it's harder to forget about freeing the buffer :-). */
/* Reserved areas are used seldom besides that... */
if
(
cbReserveCFFolder
!=
0
)
{
if
(
!
(
reserved
=
PFCI_ALLOC
(
hfci
,
cbReserveCFFolder
)))
{
p_fci_internal
->
perf
->
erfOper
=
FCIERR_ALLOC_FAIL
;
p_fci_internal
->
perf
->
erfType
=
ERROR_NOT_ENOUGH_MEMORY
;
p_fci_internal
->
perf
->
fError
=
TRUE
;
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
}
if
(
PFCI_READ
(
hfci
,
p_fci_internal
->
handleCFFOLDER
,
/* file handle */
reserved
,
/* memory buffer */
cbReserveCFFolder
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
cbReserveCFFolder
)
{
PFCI_FREE
(
hfci
,
reserved
);
/* TODO read error */
return
FALSE
;
}
/* TODO error handling of err */
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
reserved
,
/* memory buffer */
cbReserveCFFolder
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
cbReserveCFFolder
)
{
PFCI_FREE
(
hfci
,
reserved
);
/* TODO read error */
return
FALSE
;
}
/* TODO error handling of err */
PFCI_FREE
(
hfci
,
reserved
);
}
}
/* END OF while */
/* set seek of p_fci_internal->handleCFFILE2 to 0 */
if
(
PFCI_SEEK
(
hfci
,
p_fci_internal
->
handleCFFILE2
,
0
,
SEEK_SET
,
&
err
,
p_fci_internal
->
pv
)
!=
0
)
{
/* TODO wrong return value */
}
/* TODO error handling of err */
/* while not all CFFILE structures have been copied to the cabinet do */
while
(
!
FALSE
)
{
/* REUSE the variable read_result */
/* REUSE the buffer p_fci_internal->data_out AGAIN */
/* read a block from p_fci_internal->handleCFFILE2 */
read_result
=
PFCI_READ
(
hfci
,
p_fci_internal
->
handleCFFILE2
/* handle */
,
p_fci_internal
->
data_out
,
/* memory buffer */
32768
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
);
if
(
read_result
==
0
)
break
;
/* ALL CFFILE structures have been copied */
/* TODO error handling of err */
/* write the block to the cabinet file */
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
p_fci_internal
->
data_out
,
/* memory buffer */
read_result
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
read_result
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
if
(
p_fci_internal
->
fSplitFolder
==
FALSE
)
{
p_fci_internal
->
statusFolderCopied
=
0
;
p_fci_internal
->
statusFolderTotal
=
p_fci_internal
->
sizeFileCFDATA2
+
p_fci_internal
->
sizeFileCFFILE2
;
}
p_fci_internal
->
statusFolderCopied
+=
read_result
;
/* TODO is this correct */
/* report status with pfnfcis about copied size of folder */
if
(
(
*
pfnfcis
)(
statusFolder
,
p_fci_internal
->
statusFolderCopied
,
/* length of copied blocks */
p_fci_internal
->
statusFolderTotal
,
/* total size of folder */
p_fci_internal
->
pv
)
==
-
1
)
{
/* TODO set error code and abort */
return
FALSE
;
}
}
/* END OF while */
/* set seek of p_fci_internal->handleCFDATA2 to 0 */
if
(
PFCI_SEEK
(
hfci
,
p_fci_internal
->
handleCFDATA2
,
0
,
SEEK_SET
,
&
err
,
p_fci_internal
->
pv
)
!=
0
)
{
/* TODO wrong return value */
return
FALSE
;
}
/* TODO error handling of err */
/* reset the number of folders for the next cabinet */
p_fci_internal
->
cFolders
=
0
;
/* reset the number of files for the next cabinet */
p_fci_internal
->
cFiles
=
0
;
/* while not all CFDATA structures have been copied to the cabinet do */
while
(
!
FALSE
)
{
/* REUSE the variable read_result AGAIN */
/* REUSE the buffer p_fci_internal->data_out AGAIN */
/* read a block from p_fci_internal->handleCFDATA2 */
read_result
=
PFCI_READ
(
hfci
,
p_fci_internal
->
handleCFDATA2
/* handle */
,
p_fci_internal
->
data_out
,
/* memory buffer */
32768
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
);
if
(
read_result
==
0
)
break
;
/* ALL CFDATA structures have been copied */
/* TODO error handling of err */
/* write the block to the cabinet file */
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
p_fci_internal
->
data_out
,
/* memory buffer */
read_result
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
read_result
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
p_fci_internal
->
statusFolderCopied
+=
read_result
;
/* report status with pfnfcis about copied size of folder */
if
(
(
*
pfnfcis
)(
statusFolder
,
p_fci_internal
->
statusFolderCopied
,
/* length of copied blocks */
p_fci_internal
->
statusFolderTotal
,
/* total size of folder */
p_fci_internal
->
pv
)
==
-
1
)
{
/* TODO set error code and abort */
return
FALSE
;
}
}
/* END OF while */
/* set seek of the cabinet file to 0 */
if
(
PFCI_SEEK
(
hfci
,
handleCABINET
,
0
,
SEEK_SET
,
&
err
,
p_fci_internal
->
pv
)
!=
0
)
{
/* TODO wrong return value */
}
/* TODO error handling of err */
/* write the signature "MSCF" into the cabinet file */
memcpy
(
cfheader
.
signature
,
"MSCF"
,
4
);
if
(
PFCI_WRITE
(
hfci
,
handleCABINET
,
/* file handle */
&
cfheader
,
/* memory buffer */
4
,
/* number of bytes to copy */
&
err
,
p_fci_internal
->
pv
)
!=
4
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
/* close the cabinet file */
PFCI_CLOSE
(
hfci
,
handleCABINET
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
/* COPIED FROM FCIDestroy */
PFCI_CLOSE
(
hfci
,
p_fci_internal
->
handleCFDATA2
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
p_fci_internal
->
szFileNameCFDATA2
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
p_fci_internal
->
handleCFFILE2
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
p_fci_internal
->
szFileNameCFFILE2
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
p_fci_internal
->
handleCFFOLDER
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
p_fci_internal
->
szFileNameCFFOLDER
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
/* END OF copied from FCIDestroy */
/* get 3 temporary files and open them */
/* write names and handles to hfci */
p_fci_internal
->
sizeFileCFDATA2
=
0
;
p_fci_internal
->
sizeFileCFFILE2
=
0
;
p_fci_internal
->
sizeFileCFFOLDER
=
0
;
/* COPIED FROM FCICreate */
/* CFDATA with checksum and ready to be copied into cabinet */
if
(
!
PFCI_GETTEMPFILE
(
hfci
,
p_fci_internal
->
szFileNameCFDATA2
,
CB_MAX_FILENAME
))
{
/* TODO error handling */
return
FALSE
;
}
/* safety */
if
(
strlen
(
p_fci_internal
->
szFileNameCFDATA2
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code */
return
FALSE
;
}
p_fci_internal
->
handleCFDATA2
=
PFCI_OPEN
(
hfci
,
p_fci_internal
->
szFileNameCFDATA2
,
34050
,
384
,
&
err
,
p_fci_internal
->
pv
);
/* TODO check handle */
/* TODO error checking of err */
/* array of all CFFILE in a folder, ready to be copied into cabinet */
if
(
!
PFCI_GETTEMPFILE
(
hfci
,
p_fci_internal
->
szFileNameCFFILE2
,
CB_MAX_FILENAME
))
{
/* TODO error handling */
return
FALSE
;
}
/* safety */
if
(
strlen
(
p_fci_internal
->
szFileNameCFFILE2
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code */
return
FALSE
;
}
p_fci_internal
->
handleCFFILE2
=
PFCI_OPEN
(
hfci
,
p_fci_internal
->
szFileNameCFFILE2
,
34050
,
384
,
&
err
,
p_fci_internal
->
pv
);
/* TODO check handle */
/* TODO error checking of err */
/* array of all CFFILE in a folder, ready to be copied into cabinet */
if
(
!
PFCI_GETTEMPFILE
(
hfci
,
p_fci_internal
->
szFileNameCFFOLDER
,
CB_MAX_FILENAME
))
{
/* TODO error handling */
return
FALSE
;
}
/* safety */
if
(
strlen
(
p_fci_internal
->
szFileNameCFFOLDER
)
>=
CB_MAX_FILENAME
)
{
/* TODO set error code */
return
FALSE
;
}
p_fci_internal
->
handleCFFOLDER
=
PFCI_OPEN
(
hfci
,
p_fci_internal
->
szFileNameCFFOLDER
,
34050
,
384
,
&
err
,
p_fci_internal
->
pv
);
/* TODO check handle */
/* TODO error checking of err */
/* END OF copied from FCICreate */
/* TODO close and delete new files when return FALSE */
/* report status with pfnfcis about copied size of folder */
if
(
(
*
pfnfcis
)(
statusCabinet
,
p_fci_internal
->
statusFolderTotal
,
/* TODO estimated cabinet file size */
cfheader
.
cbCabinet
,
/* real cabinet file size */
p_fci_internal
->
pv
)
==
-
1
)
{
/* TODO set error code and abort */
return
FALSE
;
}
p_fci_internal
->
fPrevCab
=
TRUE
;
/* The sections szPrevCab and szPrevDisk are not being updated, because */
/* MS CABINET.DLL always puts the first cabinet name and disk into them */
if
(
p_fci_internal
->
fNextCab
)
{
p_fci_internal
->
fNextCab
=
FALSE
;
if
(
p_fci_internal
->
sizeFileCFFILE1
==
0
&&
p_fci_internal
->
sizeFileCFDATA1
!=
0
)
{
/* THIS CAN NEVER HAPPEN */
/* TODO set error code */
return
FALSE
;
}
/* COPIED FROM FCIAddFile and modified */
/* REUSE the variable read_result */
if
(
p_fci_internal
->
fGetNextCabInVain
)
{
read_result
=
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
;
if
(
p_fci_internal
->
sizeFileCFFILE1
!=
0
)
{
read_result
+=
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
;
}
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
read_result
+=
4
;
}
}
else
{
read_result
=
p_fci_internal
->
pccab
->
cbReserveCFHeader
;
if
(
p_fci_internal
->
sizeFileCFFILE1
!=
0
)
{
read_result
+=
p_fci_internal
->
pccab
->
cbReserveCFFolder
;
}
if
(
p_fci_internal
->
pccab
->
cbReserveCFHeader
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFFolder
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFData
!=
0
)
{
read_result
+=
4
;
}
}
if
(
p_fci_internal
->
fPrevCab
)
{
read_result
+=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
+
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
;
}
read_result
+=
p_fci_internal
->
sizeFileCFDATA1
+
p_fci_internal
->
sizeFileCFFILE1
+
p_fci_internal
->
sizeFileCFDATA2
+
p_fci_internal
->
sizeFileCFFILE2
+
p_fci_internal
->
sizeFileCFFOLDER
+
sizeof
(
CFHEADER
)
+
sizeof
(
CFFOLDER
);
/* set size of new CFFolder entry */
if
(
p_fci_internal
->
fNewPrevious
)
{
memcpy
(
p_fci_internal
->
szPrevCab
,
p_fci_internal
->
oldCCAB
.
szCab
,
CB_MAX_CABINET_NAME
);
memcpy
(
p_fci_internal
->
szPrevDisk
,
p_fci_internal
->
oldCCAB
.
szDisk
,
CB_MAX_DISK_NAME
);
p_fci_internal
->
fNewPrevious
=
FALSE
;
}
/* too much data for the maximum size of a cabinet */
if
(
p_fci_internal
->
fGetNextCabInVain
==
FALSE
&&
p_fci_internal
->
pccab
->
cb
<
read_result
)
{
return
fci_flush_cabinet
(
hfci
,
FALSE
,
pfnfcignc
,
pfnfcis
);
}
/* Might be too much data for the maximum size of a cabinet.*/
/* When any further data will be added later, it might not */
/* be possible to flush the cabinet, because there might */
/* not be enough space to store the name of the following */
/* cabinet and name of the corresponding disk. */
/* So take care of this and get the name of the next cabinet */
if
(
p_fci_internal
->
fGetNextCabInVain
==
FALSE
&&
(
p_fci_internal
->
pccab
->
cb
<
read_result
+
CB_MAX_CABINET_NAME
+
CB_MAX_DISK_NAME
))
{
/* save CCAB */
memcpy
(
&
(
p_fci_internal
->
oldCCAB
),
p_fci_internal
->
pccab
,
sizeof
(
CCAB
));
/* increment cabinet index */
++
(
p_fci_internal
->
pccab
->
iCab
);
/* get name of next cabinet */
if
(
!
(
*
pfnfcignc
)(
p_fci_internal
->
pccab
,
0
,
/* estimated size of cab */
p_fci_internal
->
pv
))
{
/* TODO error handling */
return
FALSE
;
}
/* Skip a few lines of code. This is catched by the next if. */
p_fci_internal
->
fGetNextCabInVain
=
TRUE
;
}
/* too much data for cabinet */
if
(
p_fci_internal
->
fGetNextCabInVain
&&
(
p_fci_internal
->
oldCCAB
.
cb
<
read_result
+
strlen
(
p_fci_internal
->
oldCCAB
.
szCab
)
+
1
+
strlen
(
p_fci_internal
->
oldCCAB
.
szDisk
)
+
1
))
{
p_fci_internal
->
fGetNextCabInVain
=
FALSE
;
p_fci_internal
->
fNextCab
=
TRUE
;
return
fci_flush_cabinet
(
hfci
,
FALSE
,
pfnfcignc
,
pfnfcis
);
}
/* if the FolderThreshold has been reached flush the folder automatically */
if
(
p_fci_internal
->
fGetNextCabInVain
)
{
if
(
p_fci_internal
->
cCompressedBytesInFolder
>=
p_fci_internal
->
oldCCAB
.
cbFolderThresh
)
{
return
FCIFlushFolder
(
hfci
,
pfnfcignc
,
pfnfcis
);
}
}
else
{
if
(
p_fci_internal
->
cCompressedBytesInFolder
>=
p_fci_internal
->
pccab
->
cbFolderThresh
)
{
return
FCIFlushFolder
(
hfci
,
pfnfcignc
,
pfnfcis
);
}
}
/* END OF COPIED FROM FCIAddFile and modified */
if
(
p_fci_internal
->
sizeFileCFFILE1
>
0
)
{
if
(
!
FCIFlushFolder
(
hfci
,
pfnfcignc
,
pfnfcis
)
)
return
FALSE
;
p_fci_internal
->
fNewPrevious
=
TRUE
;
}
}
else
{
p_fci_internal
->
fNewPrevious
=
FALSE
;
if
(
p_fci_internal
->
sizeFileCFFILE1
>
0
||
p_fci_internal
->
sizeFileCFDATA1
)
{
/* THIS MAY NEVER HAPPEN */
/* TODO set error structures */
return
FALSE
;
}
}
return
TRUE
;
}
/* end of fci_flush_cabinet */
/***********************************************************************
* FCIAddFile (CABINET.11)
*
* FCIAddFile adds a file to the to be created cabinet file
*
* PARAMS
* hfci [I] An HFCI from FCICreate
* pszSourceFile [I] A pointer to a C string which contains the name and
* location of the file which will be added to the cabinet
* pszFileName [I] A pointer to a C string which contains the name under
* which the file will be stored in the cabinet
* fExecute [I] A boolean value which indicates if the file should be
* executed after extraction of self extracting
* executables
* pfnfcignc [I] A pointer to a function which gets information about
* the next cabinet
* pfnfcis [IO] A pointer to a function which will report status
* information about the compression process
* pfnfcioi [I] A pointer to a function which reports file attributes
* and time and date information
* typeCompress [I] Compression type
*
* RETURNS
* On success, returns TRUE
* On failure, returns FALSE
*
* INCLUDES
* fci.h
*
*/
BOOL
__cdecl
FCIAddFile
(
HFCI
hfci
,
char
*
pszSourceFile
,
char
*
pszFileName
,
BOOL
fExecute
,
PFNFCIGETNEXTCABINET
pfnfcignc
,
PFNFCISTATUS
pfnfcis
,
PFNFCIGETOPENINFO
pfnfcigoi
,
TCOMP
typeCompress
)
{
int
err
;
CFFILE
cffile
;
cab_ULONG
read_result
;
int
file_handle
;
PFCI_Int
p_fci_internal
=
((
PFCI_Int
)(
hfci
));
/* test hfci */
if
(
!
REALLY_IS_FCI
(
hfci
))
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
if
((
!
pszSourceFile
)
||
(
!
pszFileName
)
||
(
!
pfnfcignc
)
||
(
!
pfnfcis
)
||
(
!
pfnfcigoi
)
||
strlen
(
pszFileName
)
>=
CB_MAX_FILENAME
)
{
p_fci_internal
->
perf
->
erfOper
=
FCIERR_NONE
;
p_fci_internal
->
perf
->
erfType
=
ERROR_BAD_ARGUMENTS
;
p_fci_internal
->
perf
->
fError
=
TRUE
;
SetLastError
(
ERROR_BAD_ARGUMENTS
);
return
FALSE
;
}
/* TODO check if pszSourceFile??? */
if
(
p_fci_internal
->
fGetNextCabInVain
&&
p_fci_internal
->
fNextCab
)
{
/* TODO internal error */
return
FALSE
;
}
if
(
p_fci_internal
->
fNextCab
)
{
/* TODO internal error */
return
FALSE
;
}
cffile
.
cbFile
=
0
;
/* size of the to be added file*/
/* offset of the uncompressed file in the folder */
cffile
.
uoffFolderStart
=
p_fci_internal
->
cDataBlocks
*
CAB_BLOCKMAX
+
p_fci_internal
->
cdata_in
;
/* number of folder in the cabinet or special 0=first */
cffile
.
iFolder
=
p_fci_internal
->
cFolders
;
/* allocation of memory */
if
(
p_fci_internal
->
data_in
==
NULL
)
{
if
(
p_fci_internal
->
cdata_in
!=
0
)
{
/* TODO error handling */
return
FALSE
;
}
if
(
p_fci_internal
->
data_out
!=
NULL
)
{
/* TODO error handling */
return
FALSE
;
}
if
(
!
(
p_fci_internal
->
data_in
=
(
char
*
)
PFCI_ALLOC
(
hfci
,
CB_MAX_CHUNK
)))
{
p_fci_internal
->
perf
->
erfOper
=
FCIERR_ALLOC_FAIL
;
p_fci_internal
->
perf
->
erfType
=
ERROR_NOT_ENOUGH_MEMORY
;
p_fci_internal
->
perf
->
fError
=
TRUE
;
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
}
if
(
p_fci_internal
->
data_out
==
NULL
)
{
if
(
!
(
p_fci_internal
->
data_out
=
PFCI_ALLOC
(
hfci
,
2
*
CB_MAX_CHUNK
))){
p_fci_internal
->
perf
->
erfOper
=
FCIERR_ALLOC_FAIL
;
p_fci_internal
->
perf
->
erfType
=
ERROR_NOT_ENOUGH_MEMORY
;
p_fci_internal
->
perf
->
fError
=
TRUE
;
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
}
}
}
if
(
p_fci_internal
->
data_out
==
NULL
)
{
PFCI_FREE
(
hfci
,
p_fci_internal
->
data_in
);
/* TODO error handling */
return
FALSE
;
}
/* get information about the file */
file_handle
=
(
*
pfnfcigoi
)(
pszSourceFile
,
&
(
cffile
.
date
),
&
(
cffile
.
time
),
&
(
cffile
.
attribs
),
&
err
,
p_fci_internal
->
pv
);
/* TODO check file_handle */
/* TODO error handling of err */
if
(
fExecute
)
{
cffile
.
attribs
|=
_A_EXEC
;
}
/* REUSE the variable read_result */
if
(
p_fci_internal
->
fGetNextCabInVain
)
{
read_result
=
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
+
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
;
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
read_result
+=
4
;
}
}
else
{
read_result
=
p_fci_internal
->
pccab
->
cbReserveCFHeader
+
p_fci_internal
->
pccab
->
cbReserveCFFolder
;
if
(
p_fci_internal
->
pccab
->
cbReserveCFHeader
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFFolder
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFData
!=
0
)
{
read_result
+=
4
;
}
}
if
(
p_fci_internal
->
fPrevCab
)
{
read_result
+=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
+
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
;
}
if
(
p_fci_internal
->
fNextCab
)
{
/* this is never the case */
read_result
+=
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
;
}
read_result
+=
sizeof
(
CFFILE
)
+
strlen
(
pszFileName
)
+
1
+
p_fci_internal
->
sizeFileCFFILE1
+
p_fci_internal
->
sizeFileCFDATA2
+
p_fci_internal
->
sizeFileCFFILE2
+
p_fci_internal
->
sizeFileCFFOLDER
+
sizeof
(
CFHEADER
)
+
sizeof
(
CFFOLDER
);
/* size of new CFFolder entry */
/* Might be too much data for the maximum size of a cabinet.*/
/* When any further data will be added later, it might not */
/* be possible to flush the cabinet, because there might */
/* not be enough space to store the name of the following */
/* cabinet and name of the corresponding disk. */
/* So take care of this and get the name of the next cabinet */
if
(
p_fci_internal
->
fGetNextCabInVain
==
FALSE
&&
p_fci_internal
->
fNextCab
==
FALSE
&&
(
p_fci_internal
->
pccab
->
cb
<
read_result
+
CB_MAX_CABINET_NAME
+
CB_MAX_DISK_NAME
)
)
{
/* save CCAB */
memcpy
(
&
(
p_fci_internal
->
oldCCAB
),
p_fci_internal
->
pccab
,
sizeof
(
CCAB
));
/* increment cabinet index */
++
(
p_fci_internal
->
pccab
->
iCab
);
/* get name of next cabinet */
if
(
!
(
*
pfnfcignc
)(
p_fci_internal
->
pccab
,
0
,
/* TODO estimated size of cab */
p_fci_internal
->
pv
))
{
/* TODO error handling */
return
FALSE
;
}
/* Skip a few lines of code. This is catched by the next if. */
p_fci_internal
->
fGetNextCabInVain
=
TRUE
;
}
if
(
p_fci_internal
->
fGetNextCabInVain
&&
p_fci_internal
->
fNextCab
)
{
/* THIS CAN NEVER HAPPEN */
/* TODO set error code*/
return
FALSE
;
}
/* too much data for cabinet */
if
(
p_fci_internal
->
fGetNextCabInVain
&&
(
p_fci_internal
->
oldCCAB
.
cb
<
read_result
+
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
))
{
p_fci_internal
->
fGetNextCabInVain
=
FALSE
;
p_fci_internal
->
fNextCab
=
TRUE
;
if
(
!
fci_flush_cabinet
(
hfci
,
FALSE
,
pfnfcignc
,
pfnfcis
))
return
FALSE
;
}
if
(
p_fci_internal
->
fNextCab
)
{
/* THIS MAY NEVER HAPPEN */
/* TODO set error code*/
return
FALSE
;
}
/* read the contents of the file blockwize*/
while
(
!
FALSE
)
{
if
(
p_fci_internal
->
cdata_in
>
CAB_BLOCKMAX
)
{
/* TODO internal error */
return
FALSE
;
}
read_result
=
PFCI_READ
(
hfci
,
file_handle
/* file handle */
,
(
p_fci_internal
->
data_in
+
p_fci_internal
->
cdata_in
)
/* memory buffer */
,
(
CAB_BLOCKMAX
-
p_fci_internal
->
cdata_in
)
/* number of bytes to copy */
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
if
(
read_result
==
0
)
break
;
/* increment the block size */
p_fci_internal
->
cdata_in
+=
read_result
;
/* increment the file size */
cffile
.
cbFile
+=
read_result
;
if
(
p_fci_internal
->
cdata_in
>
CAB_BLOCKMAX
)
{
/* TODO report internal error */
return
FALSE
;
}
/* write a whole block */
if
(
p_fci_internal
->
cdata_in
==
CAB_BLOCKMAX
)
{
if
(
!
fci_flush_data_block
(
hfci
,
&
err
,
pfnfcis
)
)
return
FALSE
;
}
}
/* close the file from FCIAddFile */
PFCI_CLOSE
(
hfci
,
file_handle
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
/* write cffile to p_fci_internal->handleCFFILE1 */
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFFILE1
,
/* file handle */
&
cffile
,
sizeof
(
cffile
),
&
err
,
p_fci_internal
->
pv
)
!=
sizeof
(
cffile
)
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
p_fci_internal
->
sizeFileCFFILE1
+=
sizeof
(
cffile
);
/* append the name of file*/
if
(
strlen
(
pszFileName
)
>=
CB_MAX_FILENAME
)
{
/* IMPOSSIBLE */
/* TODO set error code */
return
FALSE
;
}
if
(
PFCI_WRITE
(
hfci
,
p_fci_internal
->
handleCFFILE1
,
/* file handle */
pszFileName
,
strlen
(
pszFileName
)
+
1
,
&
err
,
p_fci_internal
->
pv
)
!=
strlen
(
pszFileName
)
+
1
)
{
/* TODO write error */
return
FALSE
;
}
/* TODO error handling of err */
p_fci_internal
->
sizeFileCFFILE1
+=
strlen
(
pszFileName
)
+
1
;
/* REUSE the variable read_result */
if
(
p_fci_internal
->
fGetNextCabInVain
||
p_fci_internal
->
fNextCab
)
{
read_result
=
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
+
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
;
if
(
p_fci_internal
->
oldCCAB
.
cbReserveCFHeader
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFFolder
!=
0
||
p_fci_internal
->
oldCCAB
.
cbReserveCFData
!=
0
)
{
read_result
+=
4
;
}
}
else
{
read_result
=
p_fci_internal
->
pccab
->
cbReserveCFHeader
+
p_fci_internal
->
pccab
->
cbReserveCFFolder
;
if
(
p_fci_internal
->
pccab
->
cbReserveCFHeader
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFFolder
!=
0
||
p_fci_internal
->
pccab
->
cbReserveCFData
!=
0
)
{
read_result
+=
4
;
}
}
if
(
p_fci_internal
->
fPrevCab
)
{
read_result
+=
strlen
(
p_fci_internal
->
szPrevCab
)
+
1
+
strlen
(
p_fci_internal
->
szPrevDisk
)
+
1
;
}
if
(
p_fci_internal
->
fNextCab
)
{
/* this is never the case */
read_result
+=
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
;
}
read_result
+=
p_fci_internal
->
sizeFileCFDATA1
+
p_fci_internal
->
sizeFileCFFILE1
+
p_fci_internal
->
sizeFileCFDATA2
+
p_fci_internal
->
sizeFileCFFILE2
+
p_fci_internal
->
sizeFileCFFOLDER
+
sizeof
(
CFHEADER
)
+
sizeof
(
CFFOLDER
);
/* set size of new CFFolder entry */
/* too much data for the maximum size of a cabinet */
/* (ignoring the unflushed data block) */
if
(
p_fci_internal
->
fGetNextCabInVain
==
FALSE
&&
p_fci_internal
->
fNextCab
==
FALSE
&&
/* this is always the case */
p_fci_internal
->
pccab
->
cb
<
read_result
)
{
return
fci_flush_cabinet
(
hfci
,
FALSE
,
pfnfcignc
,
pfnfcis
);
}
/* Might be too much data for the maximum size of a cabinet.*/
/* When any further data will be added later, it might not */
/* be possible to flush the cabinet, because there might */
/* not be enough space to store the name of the following */
/* cabinet and name of the corresponding disk. */
/* So take care of this and get the name of the next cabinet */
/* (ignoring the unflushed data block) */
if
(
p_fci_internal
->
fGetNextCabInVain
==
FALSE
&&
p_fci_internal
->
fNextCab
==
FALSE
&&
(
p_fci_internal
->
pccab
->
cb
<
read_result
+
CB_MAX_CABINET_NAME
+
CB_MAX_DISK_NAME
)
)
{
/* save CCAB */
memcpy
(
&
(
p_fci_internal
->
oldCCAB
),
p_fci_internal
->
pccab
,
sizeof
(
CCAB
));
/* increment cabinet index */
++
(
p_fci_internal
->
pccab
->
iCab
);
/* get name of next cabinet */
if
(
!
(
*
pfnfcignc
)(
p_fci_internal
->
pccab
,
0
,
/* TODO estimated size of cab */
p_fci_internal
->
pv
))
{
/* TODO error handling */
return
FALSE
;
}
/* Skip a few lines of code. This is catched by the next if. */
p_fci_internal
->
fGetNextCabInVain
=
TRUE
;
}
if
(
p_fci_internal
->
fGetNextCabInVain
&&
p_fci_internal
->
fNextCab
)
{
/* THIS CAN NEVER HAPPEN */
/* TODO set error code*/
return
FALSE
;
}
/* too much data for cabinet */
if
(
(
p_fci_internal
->
fGetNextCabInVain
||
p_fci_internal
->
fNextCab
)
&&
(
p_fci_internal
->
oldCCAB
.
cb
<
read_result
+
strlen
(
p_fci_internal
->
pccab
->
szCab
)
+
1
+
strlen
(
p_fci_internal
->
pccab
->
szDisk
)
+
1
))
{
p_fci_internal
->
fGetNextCabInVain
=
FALSE
;
p_fci_internal
->
fNextCab
=
TRUE
;
return
fci_flush_cabinet
(
hfci
,
FALSE
,
pfnfcignc
,
pfnfcis
);
}
if
(
p_fci_internal
->
fNextCab
)
{
/* THIS MAY NEVER HAPPEN */
/* TODO set error code*/
return
FALSE
;
}
/* if the FolderThreshold has been reached flush the folder automatically */
if
(
p_fci_internal
->
fGetNextCabInVain
)
{
if
(
p_fci_internal
->
cCompressedBytesInFolder
>=
p_fci_internal
->
oldCCAB
.
cbFolderThresh
)
{
return
FCIFlushFolder
(
hfci
,
pfnfcignc
,
pfnfcis
);
}
}
else
{
if
(
p_fci_internal
->
cCompressedBytesInFolder
>=
p_fci_internal
->
pccab
->
cbFolderThresh
)
{
return
FCIFlushFolder
(
hfci
,
pfnfcignc
,
pfnfcis
);
}
}
return
TRUE
;
}
/* end of FCIAddFile */
/***********************************************************************
* FCIFlushFolder (CABINET.12)
*
* FCIFlushFolder completes the CFFolder structure under construction.
*
* All further data which is added by FCIAddFile will be associateed to
* the next CFFolder structure.
*
* FCIFlushFolder will be called by FCIAddFile automatically if the
* threshold (stored in the member cbFolderThresh of the CCAB structure
* pccab passed to FCICreate) is exceeded.
*
* FCIFlushFolder will be called by FCIFlushFolder automatically before
* any data will be written into the cabinet file.
*
* PARAMS
* hfci [I] An HFCI from FCICreate
* pfnfcignc [I] A pointer to a function which gets information about
* the next cabinet
* pfnfcis [IO] A pointer to a function which will report status
* information about the compression process
*
* RETURNS
* On success, returns TRUE
* On failure, returns FALSE
*
* INCLUDES
* fci.h
*
*/
BOOL
__cdecl
FCIFlushFolder
(
HFCI
hfci
,
PFNFCIGETNEXTCABINET
pfnfcignc
,
PFNFCISTATUS
pfnfcis
)
{
return
fci_flush_folder
(
hfci
,
FALSE
,
pfnfcignc
,
pfnfcis
);
}
/* end of FCIFlushFolder */
/***********************************************************************
* FCIFlushCabinet (CABINET.13)
*
* FCIFlushCabinet stores the data which has been added by FCIAddFile
* into the cabinet file. If the maximum cabinet size (stored in the
* member cb of the CCAB structure pccab passed to FCICreate) has been
* exceeded FCIFlushCabinet will be called automatic by FCIAddFile.
* The remaining data still has to be flushed manually by calling
* FCIFlushCabinet.
*
* After FCIFlushCabinet has been called (manually) FCIAddFile must
* NOT be called again. Then hfci has to be released by FCIDestroy.
*
* PARAMS
* hfci [I] An HFCI from FCICreate
* fGetNextCab [I] Whether you want to add additional files to a
* cabinet set (TRUE) or whether you want to
* finalize it (FALSE)
* pfnfcignc [I] A pointer to a function which gets information about
* the next cabinet
* pfnfcis [IO] A pointer to a function which will report status
* information about the compression process
*
* RETURNS
* On success, returns TRUE
* On failure, returns FALSE
*
* INCLUDES
* fci.h
*
*/
BOOL
__cdecl
FCIFlushCabinet
(
HFCI
hfci
,
BOOL
fGetNextCab
,
PFNFCIGETNEXTCABINET
pfnfcignc
,
PFNFCISTATUS
pfnfcis
)
{
PFCI_Int
p_fci_internal
=
((
PFCI_Int
)(
hfci
));
if
(
!
fci_flush_cabinet
(
hfci
,
fGetNextCab
,
pfnfcignc
,
pfnfcis
))
return
FALSE
;
while
(
p_fci_internal
->
sizeFileCFFILE1
>
0
||
p_fci_internal
->
sizeFileCFFILE2
>
0
)
{
if
(
!
fci_flush_cabinet
(
hfci
,
fGetNextCab
,
pfnfcignc
,
pfnfcis
))
return
FALSE
;
}
return
TRUE
;
}
/* end of FCIFlushCabinet */
/***********************************************************************
* FCIDestroy (CABINET.14)
*
* Frees a handle created by FCICreate.
* Only reason for failure would be an invalid handle.
*
* PARAMS
* hfci [I] The HFCI to free
*
* RETURNS
* TRUE for success
* FALSE for failure
*/
BOOL
__cdecl
FCIDestroy
(
HFCI
hfci
)
{
int
err
;
PFCI_Int
p_fci_internal
=
((
PFCI_Int
)(
hfci
));
if
(
REALLY_IS_FCI
(
hfci
))
{
/* before hfci can be removed all temporary files must be closed */
/* and deleted */
p_fci_internal
->
FCI_Intmagic
=
0
;
PFCI_CLOSE
(
hfci
,
p_fci_internal
->
handleCFDATA1
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
p_fci_internal
->
szFileNameCFDATA1
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
p_fci_internal
->
handleCFFILE1
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
p_fci_internal
->
szFileNameCFFILE1
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
p_fci_internal
->
handleCFDATA2
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
p_fci_internal
->
szFileNameCFDATA2
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
p_fci_internal
->
handleCFFILE2
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
p_fci_internal
->
szFileNameCFFILE2
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_CLOSE
(
hfci
,
p_fci_internal
->
handleCFFOLDER
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
PFCI_DELETE
(
hfci
,
p_fci_internal
->
szFileNameCFFOLDER
,
&
err
,
p_fci_internal
->
pv
);
/* TODO error handling of err */
/* data in and out buffers have to be removed */
if
(
p_fci_internal
->
data_in
!=
NULL
)
PFCI_FREE
(
hfci
,
p_fci_internal
->
data_in
);
if
(
p_fci_internal
->
data_out
!=
NULL
)
PFCI_FREE
(
hfci
,
p_fci_internal
->
data_out
);
/* hfci can now be removed */
PFCI_FREE
(
hfci
,
hfci
);
return
TRUE
;
}
else
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
}
/* end of FCIDestroy */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment