summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/digi/digifile/digifile.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/digi/digifile/digifile.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/digi/digifile/digifile.c637
1 files changed, 637 insertions, 0 deletions
diff --git a/private/ntos/ndis/digi/digifile/digifile.c b/private/ntos/ndis/digi/digifile/digifile.c
new file mode 100644
index 000000000..edf8dba75
--- /dev/null
+++ b/private/ntos/ndis/digi/digifile/digifile.c
@@ -0,0 +1,637 @@
+/*++
+
+--*/
+
+#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