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