593 lines
10 KiB
C
593 lines
10 KiB
C
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
//#define MY_FDI_MEM_STATS
|
||
|
|
||
|
HFDI FdiContext;
|
||
|
ERF FdiError;
|
||
|
|
||
|
LONG MyLastDiamondWriteError,MyLastDiamondIoError;
|
||
|
|
||
|
INT_PTR CurrentTargetFileHandle;
|
||
|
INT TicksForThisFile;
|
||
|
|
||
|
DWORD CurrentTargetFileSize;
|
||
|
|
||
|
PFNWFROMW GaugeTicker;
|
||
|
|
||
|
extern HWND hwndFrame;
|
||
|
|
||
|
#ifdef MY_FDI_MEM_STATS
|
||
|
DWORD DiAllocCount,DiFreeCount;
|
||
|
LONG DiCurrentAllocation,DiPeakAllocation;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
INT_PTR
|
||
|
DIAMONDAPI
|
||
|
DiamondNotifyFunction(
|
||
|
IN FDINOTIFICATIONTYPE Operation,
|
||
|
IN PFDINOTIFICATION Parameters
|
||
|
)
|
||
|
{
|
||
|
switch(Operation) {
|
||
|
|
||
|
case fdintCABINET_INFO:
|
||
|
case fdintNEXT_CABINET:
|
||
|
case fdintPARTIAL_FILE:
|
||
|
default:
|
||
|
|
||
|
//
|
||
|
// Cabinet management functions which we don't use.
|
||
|
// Return success.
|
||
|
//
|
||
|
return(0);
|
||
|
|
||
|
case fdintCOPY_FILE:
|
||
|
|
||
|
//
|
||
|
// Diamond is asking us whether we want to copy the file.
|
||
|
// The name for the destination is stored as the
|
||
|
// user parameter; open the file.
|
||
|
//
|
||
|
|
||
|
CurrentTargetFileSize = Parameters->cb;
|
||
|
|
||
|
//
|
||
|
// Target file handle is the user data value.
|
||
|
//
|
||
|
return((INT_PTR)Parameters->pv);
|
||
|
|
||
|
case fdintCLOSE_FILE_INFO:
|
||
|
|
||
|
//
|
||
|
// Diamond is done with the target file and wants us to close it.
|
||
|
// (ie, this is the counterpart to fdint_COPY_FILE).
|
||
|
// However our target file open/close operations are controlled
|
||
|
// in copy.c so we do nothing here.
|
||
|
//
|
||
|
//_lclose(Parameters->hf);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
PVOID
|
||
|
DIAMONDAPI
|
||
|
SpdFdiAlloc(
|
||
|
IN ULONG NumberOfBytes
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Callback used by FDICopy to allocate memory.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
NumberOfBytes - supplies desired size of block.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Returns pointer to a block of memory or NULL
|
||
|
if memory cannot be allocated.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
#ifdef MY_FDI_MEM_STATS
|
||
|
|
||
|
PDWORD p;
|
||
|
|
||
|
p = SAlloc(NumberOfBytes+sizeof(DWORD));
|
||
|
if(p) {
|
||
|
*p++ = NumberOfBytes;
|
||
|
DiAllocCount++;
|
||
|
|
||
|
DiCurrentAllocation += (LONG)NumberOfBytes;
|
||
|
if(DiCurrentAllocation > DiPeakAllocation) {
|
||
|
DiPeakAllocation = DiCurrentAllocation;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(p);
|
||
|
#else
|
||
|
return(SAlloc(NumberOfBytes));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
DIAMONDAPI
|
||
|
SpdFdiFree(
|
||
|
IN PVOID Block
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Callback used by FDICopy to free a memory block.
|
||
|
The block must have been allocated with SpdFdiAlloc().
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Block - supplies pointer to block of memory to be freed.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
#ifdef MY_FDI_MEM_STATS
|
||
|
PDWORD p = (PDWORD)Block - 1;
|
||
|
|
||
|
DiCurrentAllocation -= (LONG)*p;
|
||
|
DiFreeCount++;
|
||
|
|
||
|
SFree(p);
|
||
|
|
||
|
#else
|
||
|
SFree(Block);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
INT_PTR
|
||
|
DIAMONDAPI
|
||
|
SpdFdiOpen(
|
||
|
IN PSTR FileName,
|
||
|
IN int oflag,
|
||
|
IN int pmode
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Callback used by FDICopy to open files.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
FileName - supplies name of file to be opened.
|
||
|
|
||
|
oflag - supplies flags for open.
|
||
|
|
||
|
pmode - supplies additional flags for open.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Handle to open file or -1 if error occurs.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
HFILE h;
|
||
|
int OpenMode;
|
||
|
|
||
|
if(oflag & _O_WRONLY) {
|
||
|
OpenMode = OF_WRITE;
|
||
|
} else {
|
||
|
if(oflag & _O_RDWR) {
|
||
|
OpenMode = OF_READWRITE;
|
||
|
} else {
|
||
|
OpenMode = OF_READ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
h = _lopen(FileName,OpenMode | OF_SHARE_DENY_WRITE);
|
||
|
|
||
|
if(h == HFILE_ERROR) {
|
||
|
//
|
||
|
// Want to return an open error, but there is none.
|
||
|
//
|
||
|
MyLastDiamondIoError = rcReadError;
|
||
|
return(-1);
|
||
|
}
|
||
|
|
||
|
return((INT_PTR)h);
|
||
|
}
|
||
|
|
||
|
|
||
|
UINT
|
||
|
DIAMONDAPI
|
||
|
SpdFdiRead(
|
||
|
IN INT_PTR Handle,
|
||
|
OUT PVOID pv,
|
||
|
IN UINT ByteCount
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Callback used by FDICopy to read from a file.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Handle - supplies handle to open file to be read from.
|
||
|
|
||
|
pv - supplies pointer to buffer to receive bytes we read.
|
||
|
|
||
|
ByteCount - supplies number of bytes to read.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Number of bytes read (ByteCount) or -1 if an error occurs.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
UINT rc;
|
||
|
|
||
|
FYield();
|
||
|
if(fUserQuit) {
|
||
|
|
||
|
rc = (UINT)(-1);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
rc = _lread((HFILE)Handle,pv,ByteCount);
|
||
|
|
||
|
if(rc == HFILE_ERROR) {
|
||
|
rc = (UINT)(-1);
|
||
|
MyLastDiamondIoError = rcReadError;
|
||
|
}
|
||
|
}
|
||
|
FYield();
|
||
|
|
||
|
return(rc);
|
||
|
}
|
||
|
|
||
|
|
||
|
UINT
|
||
|
DIAMONDAPI
|
||
|
SpdFdiWrite(
|
||
|
IN INT_PTR Handle,
|
||
|
IN PVOID pv,
|
||
|
IN UINT ByteCount
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Callback used by FDICopy to write to a file.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Handle - supplies handle to open file to be written to.
|
||
|
|
||
|
pv - supplies pointer to buffer containing bytes to write.
|
||
|
|
||
|
ByteCount - supplies number of bytes to write.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Number of bytes written (ByteCount) or -1 if an error occurs.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
UINT rc;
|
||
|
|
||
|
//
|
||
|
// Assume failure.
|
||
|
//
|
||
|
rc = (UINT)(-1);
|
||
|
|
||
|
FYield();
|
||
|
if(!fUserQuit) {
|
||
|
|
||
|
rc = _lwrite((HFILE)Handle,pv,ByteCount);
|
||
|
|
||
|
if(rc == HFILE_ERROR) {
|
||
|
|
||
|
MyLastDiamondIoError = (GetLastError() == ERROR_DISK_FULL) ? rcDiskFull : rcWriteError;
|
||
|
MyLastDiamondWriteError = MyLastDiamondWriteError;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if(rc == ByteCount) {
|
||
|
|
||
|
if((Handle == CurrentTargetFileHandle) && GaugeTicker) {
|
||
|
|
||
|
//
|
||
|
// Update gauge.
|
||
|
//
|
||
|
GaugeTicker(ByteCount * TicksForThisFile / CurrentTargetFileSize);
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
MyLastDiamondIoError = rcDiskFull;
|
||
|
MyLastDiamondWriteError = rcDiskFull;
|
||
|
rc = (UINT)(-1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
FYield();
|
||
|
|
||
|
return(rc);
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
DIAMONDAPI
|
||
|
SpdFdiClose(
|
||
|
IN INT_PTR Handle
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Callback used by FDICopy to close files.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Handle - handle of file to close.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
0 (success).
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// Don't close the target file because it screws up logic in FCopy().
|
||
|
//
|
||
|
if(Handle != CurrentTargetFileHandle) {
|
||
|
_lclose((HFILE)Handle);
|
||
|
}
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
LONG
|
||
|
DIAMONDAPI
|
||
|
SpdFdiSeek(
|
||
|
IN INT_PTR Handle,
|
||
|
IN long Distance,
|
||
|
IN int SeekType
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Callback used by FDICopy to seek files.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Handle - handle of file to close.
|
||
|
|
||
|
Distance - supplies distance to seek. Interpretation of this
|
||
|
parameter depends on the value of SeekType.
|
||
|
|
||
|
SeekType - supplies a value indicating how Distance is to be
|
||
|
interpreted; one of SEEK_SET, SEEK_CUR, SEEK_END.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
New file offset or -1 if an error occurs.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
LONG rc;
|
||
|
|
||
|
FYield();
|
||
|
if(fUserQuit) {
|
||
|
rc = -1L;
|
||
|
} else {
|
||
|
|
||
|
rc = _llseek((HFILE)Handle,Distance,SeekType);
|
||
|
|
||
|
if(rc == HFILE_ERROR) {
|
||
|
MyLastDiamondIoError = (Handle == CurrentTargetFileHandle)
|
||
|
? rcWriteSeekError
|
||
|
: rcReadSeekError;
|
||
|
rc = -1L;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(rc);
|
||
|
}
|
||
|
|
||
|
|
||
|
LONG
|
||
|
DecompDiamondFile(
|
||
|
PSTR SourceFileName,
|
||
|
HANDLE TargetFileHandle,
|
||
|
PFNWFROMW ProgressCallback,
|
||
|
INT NumberOfTicks
|
||
|
)
|
||
|
{
|
||
|
BOOL b;
|
||
|
LONG rc;
|
||
|
|
||
|
if(!FdiContext) {
|
||
|
return(rcGenericDecompError);
|
||
|
}
|
||
|
|
||
|
MyLastDiamondWriteError = rcNoError;
|
||
|
MyLastDiamondIoError = rcNoError;
|
||
|
|
||
|
CurrentTargetFileHandle = (INT_PTR)TargetFileHandle;
|
||
|
TicksForThisFile = NumberOfTicks;
|
||
|
GaugeTicker = ProgressCallback;
|
||
|
|
||
|
CurrentTargetFileSize = 0;
|
||
|
|
||
|
fUserQuit = FALSE;
|
||
|
|
||
|
//
|
||
|
// The target file is opened exclusive by FCopy().
|
||
|
// To avoid changing too much code this routine is passed the
|
||
|
// open file handle instead of the target file name.
|
||
|
// We can then return this file handle in the fdintCOPY_FILE
|
||
|
// case in the fdi notification function (see above).
|
||
|
//
|
||
|
|
||
|
b = FDICopy(
|
||
|
FdiContext,
|
||
|
SourceFileName, // pass the whole path as the name
|
||
|
"", // don't bother with the path part
|
||
|
0, // flags
|
||
|
DiamondNotifyFunction,
|
||
|
NULL, // no decryption
|
||
|
(PVOID)TargetFileHandle // user data is target file handle
|
||
|
);
|
||
|
|
||
|
if(b) {
|
||
|
|
||
|
rc = rcNoError;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if(fUserQuit) {
|
||
|
rc = rcUserQuit;
|
||
|
} else {
|
||
|
|
||
|
switch(FdiError.erfOper) {
|
||
|
|
||
|
case FDIERROR_CORRUPT_CABINET:
|
||
|
rc = MyLastDiamondIoError;
|
||
|
break;
|
||
|
|
||
|
case FDIERROR_ALLOC_FAIL:
|
||
|
rc = rcOutOfMemory;
|
||
|
break;
|
||
|
|
||
|
case FDIERROR_UNKNOWN_CABINET_VERSION:
|
||
|
case FDIERROR_BAD_COMPR_TYPE:
|
||
|
rc = rcUnknownAlgType;
|
||
|
break;
|
||
|
|
||
|
case FDIERROR_TARGET_FILE:
|
||
|
rc = MyLastDiamondWriteError;
|
||
|
break;
|
||
|
|
||
|
case FDIERROR_USER_ABORT:
|
||
|
rc = MyLastDiamondIoError;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
//
|
||
|
// The rest of the errors are not handled specially.
|
||
|
//
|
||
|
rc = rcGenericDecompError;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(rc);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
IsDiamondFile(
|
||
|
IN PSTR FileName
|
||
|
)
|
||
|
{
|
||
|
FDICABINETINFO CabinetInfo;
|
||
|
BOOL b;
|
||
|
INT_PTR h;
|
||
|
|
||
|
if(!FdiContext) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open the file such that the handle is valid for use
|
||
|
// in the diamond context (ie, seek, read routines above).
|
||
|
//
|
||
|
h = SpdFdiOpen(FileName,_O_RDONLY,0);
|
||
|
if(h == -1) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
b = FDIIsCabinet(FdiContext,h,&CabinetInfo);
|
||
|
|
||
|
_lclose((HFILE)h);
|
||
|
|
||
|
return(b);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
InitDiamond(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
if(FdiContext) {
|
||
|
return(fTrue);
|
||
|
}
|
||
|
|
||
|
#ifdef MY_FDI_MEM_STATS
|
||
|
DiAllocCount = DiFreeCount = 0;
|
||
|
DiCurrentAllocation = DiPeakAllocation = 0;
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// Initialize a diamond context.
|
||
|
//
|
||
|
while((FdiContext = FDICreate(
|
||
|
SpdFdiAlloc,
|
||
|
SpdFdiFree,
|
||
|
SpdFdiOpen,
|
||
|
SpdFdiRead,
|
||
|
SpdFdiWrite,
|
||
|
SpdFdiClose,
|
||
|
SpdFdiSeek,
|
||
|
cpuUNKNOWN,
|
||
|
&FdiError
|
||
|
)) == NULL)
|
||
|
{
|
||
|
if (!FHandleOOM(hwndFrame)) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
TermDiamond(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
if(FdiContext) {
|
||
|
FDIDestroy(FdiContext);
|
||
|
FdiContext = NULL;
|
||
|
}
|
||
|
}
|