windows-nt/Source/XPSP1/NT/base/ntsetup/legacy/dll/diamond.c
2020-09-26 16:20:57 +08:00

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;
}
}