windows-nt/Source/XPSP1/NT/base/boot/setup/decomp.c

1134 lines
26 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
ULONG length;
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);
}
}