|
|
/*++
Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
Module Name:
mapview.c
Abstract:
This code is used to map a read only copy of the glitch output buffer into a user mode process. It currently supports mapping the output buffer to only 1 user mode process at a time.
Author:
Joseph Ballantyne
Environment:
Kernel Mode
Revision History:
--*/
#ifdef UNDER_NT
#include "common.h"
#include <ntddk.h>
#include <rt.h>
#include "glitch.h"
#include "mapview.h"
// Note that there are PAGEABLE_CODE and PAGEABLE_DATA pragmas in common.h
// so all of this code is pageable. That is as it should be - as this code
// is all called while handling IOCTLS.
HANDLE SectionHandle=NULL; HANDLE Process=NULL;
NTSTATUS MapContiguousBufferToUserModeProcess ( PVOID Buffer, PVOID *MappedBuffer )
{
NTSTATUS Status; PHYSICAL_ADDRESS Physical; UNICODE_STRING SectionName; OBJECT_ATTRIBUTES ObjectAttributes; ULONG ViewSize; LARGE_INTEGER ViewBase; PVOID BaseAddress;
// We only map our buffer into 1 process at a time.
// Punt if we have already mapped or started to map it.
if (InterlockedCompareExchangePointer(&SectionHandle, 1, NULL)!=NULL) { return STATUS_UNSUCCESSFUL; }
// First get the physical address of the buffer we are going to
// map into read only user mode memory of the process calling us.
Physical=MmGetPhysicalAddress(Buffer);
// Now map this buffer into user mode memory and return a pointer
// to the mapped memory.
//
// Open a physical memory section to map in physical memory.
//
RtlInitUnicodeString( &SectionName, L"\\Device\\PhysicalMemory" );
InitializeObjectAttributes( &ObjectAttributes, &SectionName, OBJ_CASE_INSENSITIVE, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL );
Status = ZwOpenSection( &SectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes );
if (NT_SUCCESS(Status)) {
BaseAddress = NULL; ViewSize = GlitchInfo->BufferSize+PROCPAGESIZE; ViewBase.QuadPart = Physical.QuadPart;
Status =ZwMapViewOfSection( SectionHandle, NtCurrentProcess(), &BaseAddress, 0, ViewSize, &ViewBase, &ViewSize, ViewUnmap, 0, PAGE_READONLY );
if (NT_SUCCESS(Status)) { // Keep track of which process opened and mapped this section.
Process=IoGetCurrentProcess(); *MappedBuffer=BaseAddress; } else { // If we fail to map the view. Then we clean up here.
// Close down our SectionHandle and setup so we can run this routine
// again later.
ZwClose(SectionHandle);
// Clear the SectionHandle so we can open it again.
InterlockedExchangePointer(&SectionHandle, NULL); }
} else { // Clear the SectionHandle so we don't lock out all future mapping attempts.
InterlockedExchangePointer(&SectionHandle, NULL); }
return Status;
}
NTSTATUS UnMapContiguousBufferFromUserModeProcess ( PVOID MappedBuffer )
{
HANDLE CurrentProcess; NTSTATUS Status=STATUS_UNSUCCESSFUL;
// Only let this call through, if we have an open section handle,
// and the process calling us matches the process that opened the
// section handle.
CurrentProcess=IoGetCurrentProcess();
if (InterlockedCompareExchangePointer(&Process, NULL, CurrentProcess)==CurrentProcess) {
// I should NEVER be able to get here unless SectionHandle is valid
// and was a handle opened by the current process. I should also
// NEVER be able to get here unless MappedBuffer is valid as well.
ASSERT( SectionHandle!=NULL ); ASSERT( MappedBuffer!=NULL );
Status = ZwUnmapViewOfSection(NtCurrentProcess(), MappedBuffer);
ZwClose(SectionHandle);
// Clear the SectionHandle so we can open it again.
InterlockedExchangePointer(&SectionHandle, NULL);
} return Status;
}
#endif
|