Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

637 lines
20 KiB

/*++
--*/
#include <ntddk.h>
#include <stdarg.h>
#include <ntverp.h> // Include to determine what version of NT
//
// This is a fix for changes in DDK releases.
//
#ifdef VER_PRODUCTBUILD
#define rmm VER_PRODUCTBUILD
#endif
#include "digifile.h"
#include "memprint.h"
#ifdef ALLOC_PRAGMA
#if rmm > 528
#pragma message( "\n\\\\\n\\\\ Including PAGED CODE\n\\\\ \n" )
#pragma alloc_text( PAGEDIGIFILE, DigiOpenFile )
#pragma alloc_text( PAGEDIGIFILE, DigiCloseFile )
#pragma alloc_text( PAGEDIGIFILE, DigiMapFile )
#pragma alloc_text( PAGEDIGIFILE, DigiUnmapFile )
#endif
#endif
VOID DigiCheckMem( VOID );
#if 0
#define DigiCheckMem() \
{ \
PLIST_ENTRY _DigiQueue; \
KIRQL _OldIrql, _CurrentIrql; \
\
_CurrentIrql = KeGetCurrentIrql(); \
\
_DigiQueue = &GlobalNonPagedMemQueue; \
\
KeAcquireSpinLock( &GlobalMemSpinLock, &_OldIrql ); \
\
while( _DigiQueue->Flink != &GlobalNonPagedMemQueue ) \
{ \
PDIGI_MEM_DESCRIPTOR _MemDesc; \
PUCHAR _Buf; \
\
_MemDesc = CONTAINING_RECORD( _DigiQueue->Flink, \
DIGI_MEM_DESCRIPTOR, \
ListEntry ); \
\
_Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR); \
if( (_MemDesc->BeginTag != (ULONG)'lkir') || \
(*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') ) \
{ \
DbgPrint( "DigiCheckMem corruption found (0x%x)!\n", _MemDesc ); \
DbgBreakPoint(); \
break; \
} \
\
_DigiQueue = _DigiQueue->Flink; \
} \
\
if( _CurrentIrql < DISPATCH_LEVEL ) \
{ \
_DigiQueue = &GlobalPagedMemQueue; \
while( _DigiQueue->Flink != &GlobalPagedMemQueue ) \
{ \
PDIGI_MEM_DESCRIPTOR _MemDesc; \
PUCHAR _Buf; \
\
_MemDesc = CONTAINING_RECORD( _DigiQueue->Flink, \
DIGI_MEM_DESCRIPTOR, \
ListEntry ); \
\
_Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR); \
if( (_MemDesc->BeginTag != (ULONG)'lkir') || \
(*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') ) \
{ \
DbgPrint( "DigiCheckMem corruption found (0x%x)!\n", _MemDesc ); \
DbgBreakPoint(); \
break; \
} \
\
_DigiQueue = _DigiQueue->Flink; \
} \
} \
\
KeReleaseSpinLock( &GlobalMemSpinLock, _OldIrql ); \
}
#endif
//
// Describes an open DIGI file
//
typedef struct _DIGI_FILE_DESCRIPTOR
{
HANDLE NtFileHandle;
PVOID Data;
KSPIN_LOCK Lock;
BOOLEAN Mapped;
} DIGI_FILE_DESCRIPTOR, *PDIGI_FILE_DESCRIPTOR;
typedef struct _DIGI_MEM_DESCRIPTOR_
{
ULONG BeginTag;
ULONG Length;
LIST_ENTRY ListEntry;
} DIGI_MEM_DESCRIPTOR, *PDIGI_MEM_DESCRIPTOR;
//
// Global Data
//
ULONG TotalMemAllocated=0L;
ULONG DefaultPoolTag=(ULONG)('igiD');
LIST_ENTRY GlobalPagedMemQueue={&GlobalPagedMemQueue,&GlobalPagedMemQueue};
LIST_ENTRY GlobalNonPagedMemQueue={&GlobalNonPagedMemQueue,&GlobalNonPagedMemQueue};
KSPIN_LOCK GlobalMemSpinLock;
VOID DigiOpenFile( OUT PNTSTATUS Status,
OUT PHANDLE FileHandle,
OUT PULONG FileLength,
IN PUNICODE_STRING FileName,
IN PHYSICAL_ADDRESS HighestAcceptableAddress )
/*++
Routine Description:
This routine opens a file for future mapping and reads its contents
into allocated memory.
Arguments:
Status - The status of the operation
FileHandle - A handle to be associated with this open
FileLength - Returns the length of the file
FileName - The name of the file
HighestAcceptableAddress - The highest physical address at which
the memory for the file can be allocated.
Return Value:
None.
--*/
{
NTSTATUS NtStatus;
IO_STATUS_BLOCK IoStatus;
HANDLE NtFileHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG LengthOfFile;
WCHAR PathPrefix[] = L"\\SystemRoot\\system32\\drivers\\";
UNICODE_STRING FullFileName;
ULONG FullFileNameLength;
PDIGI_FILE_DESCRIPTOR FileDescriptor;
PVOID FileImage;
//
// This structure represents the data from the
// NtQueryInformationFile API with an information
// class of FileStandardInformation.
//
FILE_STANDARD_INFORMATION StandardInfo;
//
// Insert the correct path prefix.
//
FullFileNameLength = sizeof(PathPrefix) + FileName->MaximumLength;
FullFileName.Buffer = DigiAllocMem( NonPagedPool,
FullFileNameLength );
if (FullFileName.Buffer == NULL) {
*Status = STATUS_INSUFFICIENT_RESOURCES;
return;
}
FullFileName.Length = sizeof (PathPrefix) - sizeof(WCHAR);
FullFileName.MaximumLength = (USHORT)FullFileNameLength;
RtlMoveMemory (FullFileName.Buffer, PathPrefix, sizeof(PathPrefix));
RtlAppendUnicodeStringToString (&FullFileName, FileName);
#if DBG
DbgPrint ("DIGIFILE: Attempting to open %wZ\n", &FullFileName);
#endif
InitializeObjectAttributes ( &ObjectAttributes,
&FullFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
NtStatus = ZwCreateFile( &NtFileHandle,
SYNCHRONIZE | FILE_READ_DATA,
&ObjectAttributes,
&IoStatus,
NULL, // alloc size = none
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, // eabuffer
0 ); // ealength
if( !NT_SUCCESS(NtStatus) )
{
#if DBG
DbgPrint ("Error opening file %x\n", NtStatus);
#endif
DigiFreeMem( FullFileName.Buffer );
*Status = DIGI_STATUS_FILE_NOT_FOUND;
return;
}
DigiFreeMem( FullFileName.Buffer );
//
// Query the object to determine its length.
//
NtStatus = ZwQueryInformationFile( NtFileHandle,
&IoStatus,
&StandardInfo,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation );
if (!NT_SUCCESS(NtStatus)) {
#if DBG
DbgPrint ("Error querying info on file %x\n", NtStatus);
#endif
ZwClose( NtFileHandle );
*Status = NtStatus;
return;
}
LengthOfFile = StandardInfo.EndOfFile.LowPart;
#if DBG
DbgPrint ("File length is %d\n", LengthOfFile);
#endif
//
// Might be corrupted.
//
if( LengthOfFile < 1 )
{
#if DBG
DbgPrint ("Bad file length %d\n", LengthOfFile);
#endif
ZwClose( NtFileHandle );
*Status = DIGI_STATUS_ERROR_READING_FILE;
return;
}
//
// Allocate buffer for this file
//
FileImage = DigiAllocMem( NonPagedPool,
LengthOfFile );
if( FileImage == NULL )
{
#if DBG
DbgPrint ("Could not allocate buffer\n");
#endif
ZwClose( NtFileHandle );
*Status = DIGI_STATUS_ERROR_READING_FILE;
return;
}
//
// Read the file into our buffer.
//
NtStatus = ZwReadFile( NtFileHandle,
NULL,
NULL,
NULL,
&IoStatus,
FileImage,
LengthOfFile,
NULL,
NULL );
ZwClose( NtFileHandle );
if( (!NT_SUCCESS(NtStatus)) || (IoStatus.Information != LengthOfFile) )
{
#if DBG
DbgPrint ("error reading file %x\n", NtStatus);
#endif
*Status = DIGI_STATUS_ERROR_READING_FILE;
DigiFreeMem( FileImage );
return;
}
//
// Allocate a structure to describe the file.
//
FileDescriptor = DigiAllocMem( NonPagedPool,
sizeof(DIGI_FILE_DESCRIPTOR) );
if( FileDescriptor == NULL )
{
*Status = STATUS_INSUFFICIENT_RESOURCES;
DigiFreeMem( FileImage );
return;
}
FileDescriptor->NtFileHandle = NtFileHandle;
FileDescriptor->Data = FileImage;
KeInitializeSpinLock( &FileDescriptor->Lock );
FileDescriptor->Mapped = FALSE;
*FileHandle = (HANDLE)FileDescriptor;
*FileLength = LengthOfFile;
*Status = STATUS_SUCCESS;
}
VOID DigiCloseFile( IN HANDLE FileHandle )
/*++
Routine Description:
This routine closes a file previously opened with DigiOpenFile.
The file is unmapped if needed and the memory is freed.
Arguments:
FileHandle - The handle returned by DigiOpenFile
Return Value:
None.
--*/
{
PDIGI_FILE_DESCRIPTOR FileDescriptor = (PDIGI_FILE_DESCRIPTOR)FileHandle;
DigiFreeMem( FileDescriptor->Data );
DigiFreeMem( FileDescriptor );
}
VOID DigiMapFile( OUT PNTSTATUS Status,
OUT PVOID * MappedBuffer,
IN HANDLE FileHandle )
/*++
Routine Description:
This routine maps an open file, so that the contents can be accessed.
Files can only have one active mapping at any time.
Arguments:
Status - The status of the operation
MappedBuffer - Returns the virtual address of the mapping.
FileHandle - The handle returned by DigiOpenFile.
Return Value:
None.
--*/
{
PDIGI_FILE_DESCRIPTOR FileDescriptor = (PDIGI_FILE_DESCRIPTOR)FileHandle;
KIRQL oldirql;
KeAcquireSpinLock (&FileDescriptor->Lock, &oldirql);
if (FileDescriptor->Mapped == TRUE) {
*Status = DIGI_STATUS_ALREADY_MAPPED;
KeReleaseSpinLock (&FileDescriptor->Lock, oldirql);
return;
}
FileDescriptor->Mapped = TRUE;
KeReleaseSpinLock (&FileDescriptor->Lock, oldirql);
*MappedBuffer = FileDescriptor->Data;
*Status = STATUS_SUCCESS;
}
VOID DigiUnmapFile( IN HANDLE FileHandle )
/*++
Routine Description:
This routine unmaps a file previously mapped with DigiOpenFile.
The file is unmapped if needed and the memory is freed.
Arguments:
FileHandle - The handle returned by DigiOpenFile
Return Value:
None.
--*/
{
PDIGI_FILE_DESCRIPTOR FileDescriptor = (PDIGI_FILE_DESCRIPTOR)FileHandle;
KIRQL oldirql;
KeAcquireSpinLock (&FileDescriptor->Lock, &oldirql);
FileDescriptor->Mapped = FALSE;
KeReleaseSpinLock (&FileDescriptor->Lock, oldirql);
}
PVOID DigiInitMem( IN ULONG PoolTag )
/*++
Routine Description:
Arguments:
PoolTag - Tag to use when allocating memory.
Return Value:
None.
--*/
{
DefaultPoolTag = PoolTag;
InitializeListHead( &GlobalPagedMemQueue );
InitializeListHead( &GlobalNonPagedMemQueue );
KeInitializeSpinLock( &GlobalMemSpinLock );
return( NULL );
} // end DigiInitMem
#if DBG || DIGICHECKMEM
PVOID DigiAllocMem( IN POOL_TYPE PoolType, IN ULONG Length )
/*++
Routine Description:
Arguments:
Return Value:
None.
--*/
{
KIRQL OldIrql;
PDIGI_MEM_DESCRIPTOR buf;
ULONG Len = ((Length + (sizeof(ULONG)-1)) & ~(sizeof(ULONG)-1));
//
// Check memory consistency.
//
DigiCheckMem();
if( (buf = (PDIGI_MEM_DESCRIPTOR)ExAllocatePoolWithTag( PoolType,
Len + sizeof(DIGI_MEM_DESCRIPTOR) + sizeof(ULONG),
DefaultPoolTag)) == NULL )
return(NULL);
TotalMemAllocated += Len;
buf->Length = Len;
buf->BeginTag = (ULONG)'lkir';
*(PULONG)((PUCHAR)buf + Len + sizeof(DIGI_MEM_DESCRIPTOR)) = (ULONG)'igid';
//
// Insert onto tail of global memory queue
//
KeAcquireSpinLock( &GlobalMemSpinLock, &OldIrql );
if( PoolType == PagedPool )
{
InsertTailList( &GlobalPagedMemQueue,
&(buf->ListEntry) );
}
else
{
InsertTailList( &GlobalNonPagedMemQueue,
&(buf->ListEntry) );
}
KeReleaseSpinLock( &GlobalMemSpinLock, OldIrql );
return( (PUCHAR)buf + (sizeof(DIGI_MEM_DESCRIPTOR)) );
} // end DigiAllocMem
VOID DigiFreeMem( IN PVOID Buf )
/*++
Routine Description:
Does consistency check on passed in memory block and free's the memory
block.
Arguments:
Buf - pointer to memory block which is to be freed.
Return Value:
None.
--*/
{
PDIGI_MEM_DESCRIPTOR RealBuf;
KIRQL OldIrql;
ULONG Length;
//
// Check memory consistency.
//
DigiCheckMem();
RealBuf = (PDIGI_MEM_DESCRIPTOR)((PUCHAR)Buf - sizeof(DIGI_MEM_DESCRIPTOR));
Length = RealBuf->Length;
if( RealBuf->BeginTag != (ULONG)'lkir' )
{
DbgPrint( "Memory has been corrupted!\n" );
DbgBreakPoint();
}
if( *(PULONG)((PUCHAR)Buf + Length) != (ULONG)'igid' )
{
DbgPrint("Memory Overrun\n");
DbgBreakPoint();
}
TotalMemAllocated -= Length;
KeAcquireSpinLock( &GlobalMemSpinLock, &OldIrql );
RemoveEntryList( &(RealBuf->ListEntry) );
KeReleaseSpinLock( &GlobalMemSpinLock, OldIrql );
ExFreePool( RealBuf );
} // end DigiFreeMem
VOID DigiCheckMem( VOID )
{
PLIST_ENTRY _DigiQueue;
KIRQL _OldIrql, _CurrentIrql;
if( DigiPrintFlags & MEM_PRINT_FLAG_NOMEMCHECK )
return;
_DigiQueue = &GlobalNonPagedMemQueue;
KeAcquireSpinLock( &GlobalMemSpinLock, &_OldIrql );
while( _DigiQueue->Flink != &GlobalNonPagedMemQueue )
{
PDIGI_MEM_DESCRIPTOR _MemDesc;
PUCHAR _Buf;
_MemDesc = CONTAINING_RECORD( _DigiQueue->Flink,
DIGI_MEM_DESCRIPTOR,
ListEntry );
_Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR);
if( (_MemDesc->BeginTag != (ULONG)'lkir') ||
(*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') )
{
DbgPrint( "DigiCheckMem corruption found (0x%x)!n", _MemDesc );
DbgBreakPoint();
break;
}
_DigiQueue = _DigiQueue->Flink;
}
_DigiQueue = &GlobalPagedMemQueue;
_CurrentIrql = KeGetCurrentIrql();
while( (_CurrentIrql < DISPATCH_LEVEL) &&
(_DigiQueue->Flink != &GlobalPagedMemQueue) )
{
PDIGI_MEM_DESCRIPTOR _MemDesc;
PUCHAR _Buf;
_MemDesc = CONTAINING_RECORD( _DigiQueue->Flink,
DIGI_MEM_DESCRIPTOR,
ListEntry );
_Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR);
if( (_MemDesc->BeginTag != (ULONG)'lkir') ||
(*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') )
{
DbgPrint( "DigiCheckMem corruption found (0x%x)!n", _MemDesc );
DbgBreakPoint();
break;
}
_DigiQueue = _DigiQueue->Flink;
_CurrentIrql = KeGetCurrentIrql();
}
KeReleaseSpinLock( &GlobalMemSpinLock, _OldIrql );
}
#endif // end #if DBG || DIGICHECKMEM