|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
decomp.c
Abstract:
Routines to handle reading of files compressed into single-file cabinet format.
Author:
Ted Miller (tedm) 16 May 1997
Revision History:
--*/
#include "..\lib\bootlib.h"
#include "diamondd.h"
#include <stdio.h>
#include <fcntl.h>
#include <basetsd.h>
#ifdef i386
#include "bldrx86.h"
#endif
#if defined(_IA64_)
#include "bldria64.h"
#endif
#if 0
#define TmErrOut(x) DbgPrint x
#define TmDbgOut(x) DbgPrint x
#define TmDbgPause() DbgBreakPoint()
#else
#define TmErrOut(x)
#define TmDbgOut(x)
#define TmDbgPause()
#endif
BOOLEAN Decompress;
//
// Global variable that points to a buffer used for decompressing the file
// being opened. After that, reads are satisfied from this buffer. The buffer
// holds exactly one file at a time. We rely on the ordering of stuff in the loader
// to ensure that only one file that needs to be decompressed is open at a time!
//
ULONG_PTR DecompressBufferBasePage; PVOID DecompressBuffer; ULONG DecompressBufferSize; BOOLEAN DecompressBufferInUse; ULONG SizeOfFileInDecompressBuffer; ULONG DecompExpectedSize; HFDI FdiContext; ERF DecompErf;
//
// The diamond stuff allocates and frees blocks of memory
// for each file. There's no memory allocator in the boot loader that allows
// for memory frees. So we have to fake it.
//
PVOID DecompressHeap; ULONG_PTR DecompressHeapPage; #define DECOMP_HEAP_SIZE ((128+2048)*1024) // 128K work + 2MB window
typedef struct _DECOMP_HEAP_BLOCK { struct _DECOMP_HEAP_BLOCK *Next; ULONG BlockSize; BOOL Free; } DECOMP_HEAP_BLOCK, *PDECOMP_HEAP_BLOCK;
VOID ReinitializeDiamondMiniHeap( VOID );
//
// Bogus global variable used to track the device id for the device that
// the file we are currently decompressing lives on.
//
ULONG DecompDeviceId; ARC_STATUS DecompLastIoError;
//
// This is the value we return to diamond when it asks us to create
// the target file.
//
#define DECOMP_MAGIC_HANDLE 0x87654
//
// Misc forward references.
//
ARC_STATUS DecompAllocateDecompressBuffer ( IN ULONG BufferSize );
VOID DecompFreeDecompressBuffer ( VOID );
ARC_STATUS DecompClose( IN ULONG FileId );
ARC_STATUS DecompRead( IN ULONG FileId, OUT VOID * FIRMWARE_PTR Buffer, IN ULONG Length, OUT ULONG * FIRMWARE_PTR Transfer );
ARC_STATUS DecompSeek( IN ULONG FileId, IN LARGE_INTEGER * FIRMWARE_PTR Offset, IN SEEK_MODE SeekMode );
ARC_STATUS DecompGetFileInfo( IN ULONG FileId, OUT FILE_INFORMATION * FIRMWARE_PTR FileInfo );
PVOID DIAMONDAPI DiamondAlloc( IN ULONG Size );
VOID DIAMONDAPI DiamondFree( IN PVOID Block );
INT_PTR DIAMONDAPI DiamondOpen( IN LPSTR FileName, IN int oflag, IN int pmode );
UINT DIAMONDAPI DiamondRead( IN INT_PTR Handle, OUT PVOID pv, IN UINT ByteCount );
UINT DIAMONDAPI DiamondWrite( IN INT_PTR Handle, IN PVOID pv, IN UINT ByteCount );
int DIAMONDAPI DiamondClose( IN INT_PTR Handle );
long DIAMONDAPI DiamondSeek( IN INT_PTR Handle, IN long Distance, IN int SeekType );
INT_PTR DIAMONDAPI DiamondNotifyFunction( IN FDINOTIFICATIONTYPE Operation, IN PFDINOTIFICATION Parameters );
//
// Device dispatch table for our pseudo-filesystem.
//
BL_DEVICE_ENTRY_TABLE DecompDeviceEntryTable = { DecompClose, // close
NULL, // mount
NULL, // open
DecompRead, // read
NULL, // read status
DecompSeek, // seek
NULL, // write
DecompGetFileInfo, // get file info
NULL, // set file info
NULL, // rename
NULL, // get dirent
NULL // PBOOTFS_INFO, unused
};
VOID DecompEnableDecompression( IN BOOLEAN Enable ) { #if defined(_X86_) || defined(_IA64_)
//
// Disable on alpha, since it doesn't seem to work.
//
Decompress = Enable; #endif
}
BOOLEAN DecompGenerateCompressedName( IN LPCSTR Filename, OUT LPSTR CompressedName )
/*++
Routine Description:
This routine generates the "compressed-form" name of a file. The compressed form substitutes the last character of the extension with a _. If there is no extension then ._ is appended to the name. Only the final component is relevent; others are preserved in the compressed form name.
Arguments:
Filename - supplies full pathname of file whose compressed form name is desired.
CompressedName - receives compressed form of the full path. The caller must ensure that the buffer is large enough.
Return Value:
TRUE - the caller should try to locate the compressed filename first. FALSE - the caller should not attempt to locate the compressed filename at all.
This value depends on the state of the Decompress global.
--*/
{ PCHAR p,q;
if(!Decompress) { return(FALSE); }
strcpy(CompressedName,Filename); p = strrchr(CompressedName,'.'); q = strrchr(CompressedName,'\\'); if(q < p) { //
// If there are 0, 1, or 2 characters after the dot, just append
// the underscore. p points to the dot so include that in the length.
//
if(strlen(p) < 4) { strcat(CompressedName,"_"); } else { //
// Assume there are 3 characters in the extension and replace
// the final one with an underscore.
//
p[3] = '_'; } } else { //
// No dot, just add ._.
//
strcat(CompressedName,"._"); }
return(TRUE); }
DECOMP_STRUCTURE_CONTEXT DecompStructureContext = {0};
ULONG DecompPrepareToReadCompressedFile( IN LPCSTR Filename, IN ULONG FileId ) { ULONG Status; BOOL b; int err; ULONGLONG x; FDICABINETINFO CabinetInfo; ULONG OldUsableBase, OldUsableLimit;
//
// On both x86 and alpha the allocation of our large decompress buffer
// has an unfortunate tendency to place the block right where the
// (non-relocatable) kernel wants to go. By allocating from the top
// of memory we make this problem go away.
//
if(!Decompress) { return((ULONG)(-1)); }
//
// If we're in the middle of FDICopy or FDIIsCabinet then
// we don't want to do our special processing. Special return code
// of -1 tells the caller that we didn't process it.
//
if(FdiContext) { return((ULONG)(-1)); }
//
// If there's no decompression heap yet, allocate one.
//
if(!DecompressHeap) {
//
// Set allocatable range to the decompression-specific range
//
OldUsableBase = BlUsableBase; OldUsableLimit = BlUsableLimit; BlUsableBase = BL_DECOMPRESS_RANGE_LOW; BlUsableLimit = BL_DECOMPRESS_RANGE_HIGH;
Status = BlAllocateDescriptor( LoaderOsloaderHeap, 0, ROUND_TO_PAGES(DECOMP_HEAP_SIZE) >> PAGE_SHIFT, (PULONG)&DecompressHeapPage );
//
// Restore the previous alloc range.
//
BlUsableBase = OldUsableBase; BlUsableLimit = OldUsableLimit;
if(Status != ESUCCESS) { TmErrOut(("Setup: couldn't allocate decompression heap (%u)\r\n",Status)); DecompressHeap = NULL; return(Status); }
DecompressHeap = (PVOID)(KSEG0_BASE | (DecompressHeapPage << PAGE_SHIFT)); }
//
// We reinitialize diamond each time because of the way we deal with
// the heap for alloc and free requests from diamond -- doing this
// allows us to wipe our heap clean for each file.
//
ReinitializeDiamondMiniHeap();
FdiContext = FDICreate( DiamondAlloc, DiamondFree, DiamondOpen, DiamondRead, DiamondWrite, DiamondClose, DiamondSeek, 0, // cpu type flag is ignored
&DecompErf );
if(!FdiContext) { TmErrOut(("Setup: FDICreate failed\r\n")); return(ENOMEM); }
//
// Check if file is a cabinet and reset file pointer.
//
b = FDIIsCabinet(FdiContext,FileId,&CabinetInfo);
x = 0; BlSeek(FileId,(PLARGE_INTEGER)&x,SeekAbsolute);
if(!b) { //
// Not a cabinet, we're done. Bail with return code of -1
// which tells the caller that everything's OK.
//
TmDbgOut(("Setup: file %s is not a cabinet\r\n",Filename)); FDIDestroy(FdiContext); FdiContext = NULL; return((ULONG)(-1)); }
TmDbgOut(("Setup: file %s is compressed, prearing it for read\r\n",Filename));
DecompDeviceId = BlFileTable[FileId].DeviceId; DecompLastIoError = ESUCCESS;
b = FDICopy( FdiContext, "", // filename part only
(LPSTR)Filename, // full path
0, // no flags relevent
DiamondNotifyFunction, // routine to process control messages
NULL, // no decryption
NULL // no user-specified data
);
err = DecompErf.erfOper;
FDIDestroy(FdiContext); FdiContext = NULL;
if(b) { //
// Everything worked.
//
// Get file information from the original file system so we can
// return it later if someone wants it.
//
// Close the original file and switch context
// structures so that read, seek, close, etc. requests come to us
// instead of the original filesystem.
//
if(SizeOfFileInDecompressBuffer != DecompExpectedSize) { TmErrOut(("Setup: warning: expected size %lx, actual size = %lx\r\n",DecompExpectedSize,SizeOfFileInDecompressBuffer)); }
Status = BlGetFileInformation(FileId,&DecompStructureContext.FileInfo); if(Status != ESUCCESS) { TmErrOut(("DecompPrepareToReadCompressedFile: BlGetFileInfo returned %u\r\n",Status)); DecompFreeDecompressBuffer(); return(Status); } DecompStructureContext.FileInfo.EndingAddress.LowPart = SizeOfFileInDecompressBuffer; DecompStructureContext.FileInfo.EndingAddress.HighPart = 0;
//
// We don't handle files whose size doesn't fit in a DWORD.
//
if(DecompStructureContext.FileInfo.EndingAddress.HighPart) { TmErrOut(("DecompPrepareToReadCompressedFile: file too big\r\n")); DecompFreeDecompressBuffer(); return(E2BIG); }
BlClose(FileId);
BlFileTable[FileId].Flags.Open = 1; BlFileTable[FileId].Position.QuadPart = 0; BlFileTable[FileId].DeviceEntryTable = &DecompDeviceEntryTable;
#ifdef CACHE_DEVINFO
BlFileTable[FileId].StructureContext = &DecompStructureContext; #else
RtlCopyMemory( BlFileTable[FileId].StructureContext, &DecompStructureContext, sizeof(DECOMP_STRUCTURE_CONTEXT) ); #endif
return(ESUCCESS);
} else { //
// Failure.
//
TmErrOut(("Setupldr: FDICopy failed (FDIERROR = %u, last io err = %u)\r\n",err,DecompLastIoError)); TmDbgPause(); return(EINVAL); } }
ARC_STATUS DecompAllocateDecompressBuffer ( IN ULONG BufferSize ) { ARC_STATUS Status; ULONG OldUsableBase, OldUsableLimit;
//
// On both x86 and alpha the allocation of our large decompress buffer
// has an unfortunate tendency to place the block right where the
// (non-relocatable) kernel wants to go. By allocating from the top
// of memory we make this problem go away.
//
DecompressBufferSize = BufferSize;
//
// Set allocatable range to the decompression-specific range
//
OldUsableBase = BlUsableBase; OldUsableLimit = BlUsableLimit; BlUsableBase = BL_DECOMPRESS_RANGE_LOW; BlUsableLimit = BL_DECOMPRESS_RANGE_HIGH;
Status = BlAllocateDescriptor( LoaderOsloaderHeap, 0, (ULONG)(ROUND_TO_PAGES(DecompressBufferSize) >> PAGE_SHIFT), (PULONG)&DecompressBufferBasePage );
//
// Restore the previous alloc range.
//
BlUsableBase = OldUsableBase; BlUsableLimit = OldUsableLimit;
if ( Status != ESUCCESS ) { TmErrOut(("Setup: couldn't allocate decompression buffer (%u)\r\n",Status)); DecompressBuffer = NULL; return(Status); }
DecompressBuffer = (PVOID)(KSEG0_BASE | (DecompressBufferBasePage << PAGE_SHIFT));
DecompressBufferInUse = TRUE;
return ESUCCESS; }
VOID DecompFreeDecompressBuffer ( VOID ) { if ( DecompressBufferInUse ) { DecompressBufferInUse = FALSE; BlFreeDescriptor( (ULONG)DecompressBufferBasePage ); }
if(DecompressHeap) { BlFreeDescriptor( (ULONG)DecompressHeapPage ); DecompressHeap = NULL; }
return; }
ARC_STATUS DecompClose( IN ULONG FileId )
/*++
Routine Description:
Close routine for decompression pseudo-filesystem.
We mark the decompression buffer free and return success.
Arguments:
FileId - supplies open file id to be closed.
Return Value:
--*/
{ TmDbgOut(("DecompClose\r\n"));
if(DecompressBufferInUse) { DecompFreeDecompressBuffer(); } else { TmErrOut(("DecompClose: warning: no file buffered!\r\n")); TmDbgPause(); }
BlFileTable[FileId].Flags.Open = 0;
return(ESUCCESS); }
ARC_STATUS DecompRead( IN ULONG FileId, OUT VOID * FIRMWARE_PTR Buffer, IN ULONG Length, OUT ULONG * FIRMWARE_PTR Transfer )
/*++
Routine Description:
Read routine for the decompression pseudo-filesystem.
Reads are satisfied out of the decompression buffer.
Arguments:
FileId - supplies id for open file as returned by BlOpen().
Buffer - receives data read from file.
Length - supplies amount of data to be read, in bytes.
Transfer - recieves number of bytes actually transferred into caller's buffer.
Return Value:
ARC status indicating outcome.
--*/
{ ARC_STATUS Status;
if(DecompressBufferInUse) { //
// Make sure we don't try to read past EOF.
//
if((Length + BlFileTable[FileId].Position.LowPart) > SizeOfFileInDecompressBuffer) { TmErrOut(("DecompRead: warning: attempt to read past eof; read trucated\r\n")); TmDbgPause(); Length = SizeOfFileInDecompressBuffer - BlFileTable[FileId].Position.LowPart; }
//
// Transfer data into caller's buffer.
//
TmDbgOut(("DecompRead: %lx bytes at filepos %lx\r\n",Length,BlFileTable[FileId].Position.LowPart));
RtlCopyMemory( Buffer, (PCHAR)DecompressBuffer + BlFileTable[FileId].Position.LowPart, Length );
*Transfer = Length;
BlFileTable[FileId].Position.QuadPart += Length;
Status = ESUCCESS;
} else { //
// Should never get here.
//
TmErrOut(("DecompRead: no file buffered!\r\n")); TmDbgPause(); Status = EACCES; }
return(Status); }
ARC_STATUS DecompSeek( IN ULONG FileId, IN LARGE_INTEGER * FIRMWARE_PTR Offset, IN SEEK_MODE SeekMode )
/*++
Routine Description:
Seek routine for the decompression pseudo-filesystem. Sets pseudo-file pointer to given offset.
Arguments:
FileId - supplies id for open file as returned by BlOpen().
Offset - supplies new offset, whose interpretation depends on the SeekMode parameter.
SeekMode - supplies type of seek. One of SeekAbsolute or SeekRelative.
Return Value:
ARC status indicating outcome.
--*/
{ LONGLONG NewPosition;
TmDbgOut(("DecompSeek: mode %u, pos = %lx\r\n",SeekMode,Offset->LowPart));
if(DecompressBufferInUse) {
switch(SeekMode) {
case SeekAbsolute:
NewPosition = Offset->QuadPart; break;
case SeekRelative:
NewPosition = BlFileTable[FileId].Position.QuadPart + Offset->QuadPart; break;
default: TmErrOut(("DecompSeek: invalid seek mode\r\n")); TmDbgPause(); return(EINVAL); }
//
// Make sure we don't try to seek to a negative offset or past EOF.
//
if(NewPosition < 0) { TmErrOut(("DecompSeek: warning: attempt to seek to negative offset\r\n")); TmDbgPause(); NewPosition = 0; } else { if((ULONGLONG)NewPosition > (ULONGLONG)SizeOfFileInDecompressBuffer) { TmErrOut(("DecompSeek: attempt to seek past eof\r\n")); TmDbgPause(); return(EINVAL); } }
//
// Remember new position.
//
TmDbgOut(("DecompSeek: new position is %lx\r\n",NewPosition)); BlFileTable[FileId].Position.QuadPart = NewPosition;
} else { //
// Should never get here.
//
TmErrOut(("DecompSeek: no file buffered!\r\n")); TmDbgPause(); return(EACCES); }
return(ESUCCESS); }
ARC_STATUS DecompGetFileInfo( IN ULONG FileId, OUT FILE_INFORMATION * FIRMWARE_PTR FileInfo ) { RtlCopyMemory( FileInfo, &((PDECOMP_STRUCTURE_CONTEXT)BlFileTable[FileId].StructureContext)->FileInfo, sizeof(FILE_INFORMATION) );
TmDbgOut(("DecompGetFileInfo: size = %lx\r\n",FileInfo->EndingAddress.LowPart));
return(ESUCCESS); }
VOID ReinitializeDiamondMiniHeap( VOID ) { PDECOMP_HEAP_BLOCK p;
p = DecompressHeap;
p->BlockSize = DECOMP_HEAP_SIZE - sizeof(DECOMP_HEAP_BLOCK); p->Next = NULL; p->Free = TRUE; }
PVOID DIAMONDAPI DiamondAlloc( IN ULONG Size ) { PDECOMP_HEAP_BLOCK p,q; ULONG LeftOver;
TmDbgOut(("DiamondAlloc: request %lx bytes\r\n",Size));
//
// Round size up to dword boundary.
//
if(Size % sizeof(ULONG_PTR)) { Size += sizeof(ULONG_PTR) - (Size % sizeof(ULONG_PTR)); }
//
// Nothing fancy. First-fit algorithm, traversing all blocks
// in the heap every time.
//
for(p=DecompressHeap; p; p=p->Next) { if(p->Free && (p->BlockSize >= Size)) {
p->Free = FALSE;
LeftOver = p->BlockSize - Size;
if(LeftOver > sizeof(DECOMP_HEAP_BLOCK)) { //
// Split the block.
//
p->BlockSize = Size;
q = (PDECOMP_HEAP_BLOCK)((PUCHAR)(p+1) + Size); q->Next = p->Next;
p->Next = q;
q->Free = TRUE; q->BlockSize = LeftOver - sizeof(DECOMP_HEAP_BLOCK); }
//
// Return pointer to data area of the block.
//
TmDbgOut(("DiamondAlloc(%lx): %lx\r\n",Size,p+1)); return(p+1); } }
TmErrOut(("DiamondAlloc: out of heap space!\r\n")); TmDbgPause(); return(NULL); }
VOID DIAMONDAPI DiamondFree( IN PVOID Block ) { PDECOMP_HEAP_BLOCK p;
TmDbgOut(("DiamondFree(%lx)\r\n",Block));
//
// Get pointer to header for block.
//
Block = (PUCHAR)Block - sizeof(DECOMP_HEAP_BLOCK);
//
// Nothing fancy, no coalescing free blocks.
//
for(p=DecompressHeap; p; p=p->Next) {
if(p == Block) {
if(p->Free) { TmErrOut(("DiamondFree: warning: freeing free block\r\n")); TmDbgPause(); return; }
p->Free = TRUE; return; } }
TmErrOut(("DiamondFree: warning: freeing invalid block\r\n")); TmDbgPause(); }
INT_PTR DIAMONDAPI DiamondOpen( IN LPSTR FileName, IN int oflag, IN int pmode ) { ARC_STATUS Status; ULONG FileId;
UNREFERENCED_PARAMETER(pmode);
TmDbgOut(("DiamondOpen: %s\r\n",FileName));
if(oflag & (_O_WRONLY | _O_RDWR | _O_APPEND | _O_CREAT | _O_TRUNC | _O_EXCL)) {
TmErrOut(("DiamondOpen: invalid oflag %lx for %s\r\n",oflag,FileName)); TmDbgPause(); DecompLastIoError = EINVAL; return(-1); }
Status = BlOpen(DecompDeviceId,FileName,ArcOpenReadOnly,&FileId); if(Status != ESUCCESS) {
TmErrOut(("DiamondOpen: BlOpen %s returned %u\r\n",FileName,Status)); TmDbgPause(); DecompLastIoError = Status; return(-1); } else { TmDbgOut(("DiamondOpen: handle to %s is %lx\r\n",FileName,FileId)); }
return((INT_PTR)FileId); }
UINT DIAMONDAPI DiamondRead( IN INT_PTR Handle, OUT PVOID pv, IN UINT ByteCount ) { ARC_STATUS Status; ULONG n;
TmDbgOut(("DiamondRead: %lx bytes, handle %lx\r\n",ByteCount,Handle));
//
// We should never be asked to read from the target file.
//
if(Handle == DECOMP_MAGIC_HANDLE) { TmErrOut(("DiamondRead: called for unexpected file!\r\n")); TmDbgPause(); DecompLastIoError = EACCES; return((UINT)(-1)); }
Status = BlRead((ULONG)Handle,pv,ByteCount,&n); if(Status != ESUCCESS) { TmErrOut(("DiamondRead: BlRead failed %u\r\n",Status)); TmDbgPause(); DecompLastIoError = Status; n = (UINT)(-1); }
return(n); }
UINT DIAMONDAPI DiamondWrite( IN INT_PTR Handle, IN PVOID pv, IN UINT ByteCount ) { TmDbgOut(("DiamondWrite: %lx bytes\r\n",ByteCount));
//
// This guy should be called ONLY to write decompressed data
// into the decompress buffer.
//
if(Handle != DECOMP_MAGIC_HANDLE) { TmErrOut(("DiamondWrite: called for unexpected file!\r\n")); TmDbgPause(); DecompLastIoError = EACCES; return((UINT)(-1)); }
//
// Check for overflow.
//
if(SizeOfFileInDecompressBuffer+ByteCount > DecompressBufferSize) { TmErrOut(("DiamondWrite: decompressed file too big!\r\n")); TmDbgPause(); DecompLastIoError = E2BIG; return((UINT)(-1)); }
RtlCopyMemory( (PCHAR)DecompressBuffer + SizeOfFileInDecompressBuffer, pv, ByteCount );
SizeOfFileInDecompressBuffer += ByteCount; return(ByteCount); }
int DIAMONDAPI DiamondClose( IN INT_PTR Handle ) { TmDbgOut(("DiamondClose, handle=%lx\r\n",Handle));
if(Handle != DECOMP_MAGIC_HANDLE) { BlClose((ULONG)Handle); }
return(0); }
long DIAMONDAPI DiamondSeek( IN INT_PTR Handle, IN long Distance, IN int SeekType ) { ARC_STATUS Status; LARGE_INTEGER Offset;
TmDbgOut(("DiamondSeek: type=%u, dist=%lx, handle=%lx\r\n",SeekType,Distance,Handle));
//
// We should never be asked to seek in the output file.
//
if(Handle == DECOMP_MAGIC_HANDLE) { TmErrOut(("DiamondSeek: asked to seek target file!\r\n")); TmDbgPause(); DecompLastIoError = EACCES; return(-1); }
//
// We can't handle seek from end of file.
//
if(SeekType == SEEK_END) { TmErrOut(("DiamondSeek: asked to seek relative to end of file!\r\n")); TmDbgPause(); DecompLastIoError = EACCES; return(-1); }
Offset.QuadPart = Distance;
Status = BlSeek((ULONG)Handle,&Offset,SeekType); if(Status != ESUCCESS) { TmErrOut(("DiamondSeek: BlSeek(%lx,%x) returned %u\r\n",Distance,SeekType,Status)); TmDbgPause(); DecompLastIoError = Status; return(-1); }
TmDbgOut(("DiamondSeek: BlSeek(%lx,%x) new file position is %lx\r\n",Distance,SeekType,BlFileTable[Handle].Position.LowPart)); return((long)BlFileTable[Handle].Position.LowPart); }
INT_PTR DIAMONDAPI DiamondNotifyFunction( IN FDINOTIFICATIONTYPE Operation, IN PFDINOTIFICATION Parameters ) { ARC_STATUS Status;
switch(Operation) {
case fdintCABINET_INFO: //
// Nothing interesting here. Return 0 to continue.
//
return(0);
case fdintCOPY_FILE:
//
// The file was obviously a cabinet so we're going to extract
// the file out of it. Rememember that the decompression buffer
// is in use. If it's already in use, then a fundamental
// principle of our implementation has been violated and we
// must bail now.
//
if(DecompressBufferInUse) { TmErrOut(("DiamondNotifyFunction: opens overlap (%s)!\r\n",Parameters->psz1)); DecompLastIoError = EACCES; return(-1); }
DecompExpectedSize = Parameters->cb;
Status = DecompAllocateDecompressBuffer( DecompExpectedSize ); if (Status != ESUCCESS) { TmErrOut(("DiamondNotifyFunction: unable to allocate decompress buffer!\r\n")); return(-1); }
SizeOfFileInDecompressBuffer = 0; return(DECOMP_MAGIC_HANDLE);
case fdintCLOSE_FILE_INFO: //
// Diamond is asking to close the target handle. There's nothing we really
// care about here, just return success as long as we recognize the handle.
//
if(Parameters->hf == DECOMP_MAGIC_HANDLE) { return(TRUE); } else { TmErrOut(("DiamondNotifyFunction: asked to close unexpected file!\r\n")); TmDbgPause(); DecompLastIoError = EINVAL; return(FALSE); }
default: //
// Disregard any other messages
//
return(0); }
}
|