406 lines
7.5 KiB
C
406 lines
7.5 KiB
C
|
//
|
||
|
// Template Driver
|
||
|
// Copyright (c) Microsoft Corporation, 2000.
|
||
|
//
|
||
|
// Module: ResrvMap.c
|
||
|
// Author: Daniel Mihai (DMihai)
|
||
|
// Created: 10/18/2000
|
||
|
//
|
||
|
// This module contains tests for Mm APIs for reserved mapping addresses
|
||
|
//
|
||
|
// MmAllocateMappingAddress
|
||
|
// MmFreeMappingAddress
|
||
|
// MmMapLockedPagesWithReservedMapping
|
||
|
// MmUnmapReservedMapping
|
||
|
//
|
||
|
// --- History ---
|
||
|
//
|
||
|
// 10/18/2000 (DMihai): initial version.
|
||
|
//
|
||
|
|
||
|
#include <ntddk.h>
|
||
|
#include <wchar.h>
|
||
|
|
||
|
#include "active.h"
|
||
|
#include "tdriver.h"
|
||
|
#include "ResrvMap.h"
|
||
|
|
||
|
#if !RESRVMAP_ACTIVE
|
||
|
|
||
|
//
|
||
|
// Dummy stubs in case this module is disabled
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
TdReservedMappingSetSize(
|
||
|
IN PVOID Irp
|
||
|
)
|
||
|
{
|
||
|
DbgPrint( "Buggy: ReservedMapping module is disabled (check \\driver\\active.h header)\n");
|
||
|
}
|
||
|
|
||
|
#else //#if !RESRVMAP_ACTIVE
|
||
|
|
||
|
//
|
||
|
// This is the real stuff
|
||
|
//
|
||
|
|
||
|
//////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Global data
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Size of the current reserved mapping address
|
||
|
//
|
||
|
|
||
|
SIZE_T CrtReservedSize;
|
||
|
|
||
|
//
|
||
|
// Current reserved mapping address
|
||
|
//
|
||
|
|
||
|
PVOID CrtReservedAddress;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Clean-up a possible currently reserved buffer
|
||
|
// Called for IRP_MJ_CLEANUP
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
TdReservedMappingCleanup(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
if( NULL != CrtReservedAddress )
|
||
|
{
|
||
|
DbgPrint( "Buggy: TdReservedMappingCleanup: free reserved mapping address %p\n",
|
||
|
CrtReservedAddress );
|
||
|
|
||
|
MmFreeMappingAddress(
|
||
|
CrtReservedAddress,
|
||
|
TD_POOL_TAG );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT( 0 == CrtReservedSize );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set the current reserved size and address as asked by the user
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
TdReservedMappingSetSize(
|
||
|
IN PVOID Irp
|
||
|
)
|
||
|
{
|
||
|
PIO_STACK_LOCATION IrpStack;
|
||
|
ULONG InputBufferLength;
|
||
|
SIZE_T NewReservedSize;
|
||
|
PVOID NewReservedAddress;
|
||
|
|
||
|
IrpStack = IoGetCurrentIrpStackLocation ( (PIRP)Irp);
|
||
|
InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
|
||
|
|
||
|
if( InputBufferLength != sizeof( SIZE_T ) )
|
||
|
{
|
||
|
//
|
||
|
// The user should send us the new size of the buffer
|
||
|
//
|
||
|
|
||
|
DbgPrint( "Buggy: TdReservedMappingSetSize: invalid buffer length %p\n",
|
||
|
InputBufferLength );
|
||
|
|
||
|
DbgBreakPoint();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// This will be our new reserved mapping address size
|
||
|
//
|
||
|
|
||
|
NewReservedSize = *(PSIZE_T) ( (PIRP) Irp )->AssociatedIrp.SystemBuffer;
|
||
|
|
||
|
if( NewReservedSize < PAGE_SIZE )
|
||
|
{
|
||
|
NewReservedSize = PAGE_SIZE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NewReservedSize = ROUND_TO_PAGES( NewReservedSize );
|
||
|
}
|
||
|
|
||
|
//DbgPrint( "Buggy: TdReservedMappingSetSize: new reserved mapping address size %p\n",
|
||
|
// NewReservedSize );
|
||
|
|
||
|
if( 0 != NewReservedSize )
|
||
|
{
|
||
|
//
|
||
|
// Try to reserve NewReservedSize bytes
|
||
|
//
|
||
|
|
||
|
NewReservedAddress = MmAllocateMappingAddress(
|
||
|
NewReservedSize,
|
||
|
TD_POOL_TAG );
|
||
|
|
||
|
if( NULL == NewReservedAddress )
|
||
|
{
|
||
|
DbgPrint(
|
||
|
"Buggy: TdReservedMappingSetSize: MmAllocateMappingAddress returned NULL, keeping old reserved address %p, size = %p\n",
|
||
|
CrtReservedAddress,
|
||
|
CrtReservedSize );
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Just release the old reserved address and set the size to 0
|
||
|
//
|
||
|
|
||
|
NewReservedAddress = NULL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We have a new buffer, release the old one
|
||
|
//
|
||
|
|
||
|
TdReservedMappingCleanup();
|
||
|
|
||
|
CrtReservedSize = NewReservedSize;
|
||
|
CrtReservedAddress = NewReservedAddress;
|
||
|
|
||
|
/*
|
||
|
DbgPrint(
|
||
|
"Buggy: TdReservedMappingSetSize: new reserved address %p, size = %p\n",
|
||
|
CrtReservedAddress,
|
||
|
CrtReservedSize );
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Simulate a "read" operation in a user-supplied buffer
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
TdReservedMappingDoRead(
|
||
|
IN PVOID Irp
|
||
|
)
|
||
|
{
|
||
|
PVOID UserBuffer;
|
||
|
PVOID MappedAddress;
|
||
|
PSIZE_T CrtPageAdddress;
|
||
|
SIZE_T UserBufferSize;
|
||
|
SIZE_T CrtPageIndex;
|
||
|
SIZE_T CrtCycleSize;
|
||
|
SIZE_T CrtCyclePages;
|
||
|
PMDL Mdl;
|
||
|
PIO_STACK_LOCATION IrpStack;
|
||
|
ULONG InputBufferLength;
|
||
|
PUSER_READ_BUFFER UserReadBufferStruct;
|
||
|
BOOLEAN Locked;
|
||
|
|
||
|
//
|
||
|
// If we don't have a reserved address for mapping currently we cannot
|
||
|
// execute the operation
|
||
|
//
|
||
|
|
||
|
if( NULL == CrtReservedAddress )
|
||
|
{
|
||
|
ASSERT( 0 == CrtReservedSize );
|
||
|
|
||
|
DbgPrint( "Buggy: TdReservedMappingDoRead: no buffer available - rejecting request\n" );
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make a copy of the user-supplied buffer address and size
|
||
|
//
|
||
|
|
||
|
IrpStack = IoGetCurrentIrpStackLocation ( (PIRP)Irp);
|
||
|
InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
|
||
|
|
||
|
if( InputBufferLength != sizeof( USER_READ_BUFFER ) )
|
||
|
{
|
||
|
//
|
||
|
// The user should have sent us a USER_READ_BUFFER
|
||
|
//
|
||
|
|
||
|
DbgPrint( "Buggy: TdReservedMappingDoRead: invalid user buffer length %p, expected %p\n",
|
||
|
InputBufferLength,
|
||
|
(SIZE_T)sizeof( USER_READ_BUFFER ) );
|
||
|
|
||
|
DbgBreakPoint();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
UserReadBufferStruct = (PUSER_READ_BUFFER) ( (PIRP) Irp )->AssociatedIrp.SystemBuffer ;
|
||
|
|
||
|
UserBuffer = UserReadBufferStruct->UserBuffer;
|
||
|
UserBufferSize = UserReadBufferStruct->UserBufferSize;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Map CrtReservedSize bytes at most
|
||
|
//
|
||
|
|
||
|
CrtPageIndex = 1;
|
||
|
|
||
|
while( UserBufferSize >= PAGE_SIZE )
|
||
|
{
|
||
|
//DbgPrint( "Buggy: TdReservedMappingDoRead: %p bytes left to be read at adddress %p\n",
|
||
|
// UserBufferSize,
|
||
|
// UserBuffer );
|
||
|
|
||
|
if( UserBufferSize > CrtReservedSize )
|
||
|
{
|
||
|
CrtCycleSize = CrtReservedSize;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CrtCycleSize = UserBufferSize;
|
||
|
}
|
||
|
|
||
|
//DbgPrint( "Buggy: TdReservedMappingDoRead: reading %p bytes this cycle\n",
|
||
|
// CrtCycleSize );
|
||
|
|
||
|
//
|
||
|
// Allocate an MDL
|
||
|
//
|
||
|
|
||
|
Mdl = IoAllocateMdl(
|
||
|
UserBuffer,
|
||
|
(ULONG)CrtCycleSize,
|
||
|
FALSE, // not secondary buffer
|
||
|
FALSE, // do not charge quota
|
||
|
NULL); // no irp
|
||
|
|
||
|
if( NULL != Mdl )
|
||
|
{
|
||
|
//
|
||
|
// Try to lock the pages
|
||
|
//
|
||
|
|
||
|
Locked = FALSE;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
MmProbeAndLockPages(
|
||
|
Mdl,
|
||
|
KernelMode,
|
||
|
IoWriteAccess);
|
||
|
|
||
|
//DbgPrint(
|
||
|
// "Buggy: locked pages in MDL %p\n",
|
||
|
// Mdl);
|
||
|
|
||
|
Locked = TRUE;
|
||
|
}
|
||
|
except (EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
DbgPrint(
|
||
|
"Buggy: MmProbeAndLockPages( %p ) raised exception %X\n",
|
||
|
Mdl,
|
||
|
GetExceptionCode() );
|
||
|
|
||
|
DbgBreakPoint();
|
||
|
}
|
||
|
|
||
|
if( TRUE == Locked )
|
||
|
{
|
||
|
//
|
||
|
// Map them to our reserved address
|
||
|
//
|
||
|
|
||
|
MappedAddress = MmMapLockedPagesWithReservedMapping(
|
||
|
CrtReservedAddress,
|
||
|
TD_POOL_TAG,
|
||
|
Mdl,
|
||
|
MmCached );
|
||
|
|
||
|
if( NULL == MappedAddress )
|
||
|
{
|
||
|
DbgPrint(
|
||
|
"Buggy: MmProbeAndLockPages( %p, MDL %p ) returned NULL. This API is almost guaranteed to succeed\n",
|
||
|
CrtReservedAddress,
|
||
|
Mdl );
|
||
|
|
||
|
DbgBreakPoint();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Mapped successfully - execute the "read"
|
||
|
//
|
||
|
|
||
|
CrtCyclePages = CrtCycleSize / PAGE_SIZE;
|
||
|
CrtPageAdddress = (PSIZE_T)MappedAddress;
|
||
|
|
||
|
//
|
||
|
// Stamp all the pages with their index, starting from 1
|
||
|
//
|
||
|
|
||
|
while( CrtCyclePages > 0 )
|
||
|
{
|
||
|
*CrtPageAdddress = CrtPageIndex;
|
||
|
|
||
|
CrtPageIndex += 1;
|
||
|
CrtCyclePages -= 1;
|
||
|
CrtPageAdddress = (PSIZE_T)( (PCHAR)CrtPageAdddress + PAGE_SIZE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Unmap
|
||
|
//
|
||
|
|
||
|
MmUnmapReservedMapping(
|
||
|
MappedAddress,
|
||
|
TD_POOL_TAG,
|
||
|
Mdl );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Unlock
|
||
|
//
|
||
|
|
||
|
MmUnlockPages (Mdl);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Free MDL
|
||
|
//
|
||
|
|
||
|
IoFreeMdl (Mdl);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Bad luck - couldn't allocate the MDL
|
||
|
//
|
||
|
|
||
|
DbgPrint( "Buggy: TdReservedMappingDoRead: IoAllocateMdl( %p, %p ) returned NULL\n",
|
||
|
UserBuffer,
|
||
|
UserBufferSize );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// How many bytes left to be read and to what address?
|
||
|
//
|
||
|
|
||
|
UserBufferSize -= CrtCycleSize;
|
||
|
UserBuffer = (PVOID)( (PCHAR)UserBuffer + CrtCycleSize );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif //#if !RESRVMAP_ACTIVE
|