home *** CD-ROM | disk | FTP | other *** search
- //
- // Simple driver that demonstrates mapping physical memory into
- // a user mode process's address space
- //
-
- #include "ntddk.h"
- #include "..\mapmem.h"
- #include "stdarg.h"
-
-
-
- //
- // The following was not included in the October release of the
- // preliminary NT DDK, and is necessary when utilizing the
- // ZwMapViewOfSection API.
- //
-
- #define SECTION_QUERY 0x0001
- #define SECTION_MAP_WRITE 0x0002
- #define SECTION_MAP_READ 0x0004
- #define SECTION_MAP_EXECUTE 0x0008
- #define SECTION_EXTEND_SIZE 0x0010
-
- #define SECTION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SECTION_QUERY | \
- SECTION_MAP_WRITE | \
- SECTION_MAP_READ | \
- SECTION_MAP_EXECUTE | \
- SECTION_EXTEND_SIZE)
-
- typedef enum _SECTION_INHERIT {
- ViewShare = 1,
- ViewUnmap = 2
- } SECTION_INHERIT;
-
- #define PAGE_NOACCESS 0x01 // winnt
- #define PAGE_READONLY 0x02 // winnt
- #define PAGE_READWRITE 0x04 // winnt
- #define PAGE_WRITECOPY 0x08
- #define PAGE_EXECUTE 0x10
- #define PAGE_EXECUTE_READ 0x20
- #define PAGE_EXECUTE_READWRITE 0x40
- #define PAGE_EXECUTE_WRITECOPY 0x80
- #define PAGE_GUARD 0x100
- #define PAGE_NOCACHE 0x200
-
- NTSTATUS
- ZwMapViewOfSection(
- IN HANDLE SectionHandle,
- IN HANDLE ProcessHandle,
- IN OUT PVOID *BaseAddress,
- IN ULONG ZeroBits,
- IN ULONG CommitSize,
- IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
- IN OUT PULONG ViewSize,
- IN SECTION_INHERIT InheritDisposition,
- IN ULONG AllocationType,
- IN ULONG Protect
- );
-
-
- //
- // Function prototypes for this module
- //
-
- NTSTATUS
- MapMemCreateClose(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
-
- NTSTATUS
- MapMemDispatch(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
-
- NTSTATUS
- MapMemMapTheMemory(
- IN PDEVICE_OBJECT DeviceObject,
- IN OUT PVOID ioBuffer,
- IN ULONG inputBufferLength,
- IN ULONG outputBufferLength
- );
-
- #if DBG
- #define MapMemDebugPrint(arg) DbgPrint arg
- #else
- #define MapMemDebugPrint(arg)
- #endif
-
-
-
- //
- // The code...
- //
-
- NTSTATUS
- DriverEntry(
- IN PDRIVER_OBJECT DriverObject,
- IN PUNICODE_STRING RegistryPath
- )
- {
-
- PDEVICE_OBJECT deviceObject = NULL;
- NTSTATUS ntStatus;
- WCHAR deviceNameBuffer[] = L"\\Device\\MapMem";
- UNICODE_STRING deviceNameUnicodeString;
-
-
- MapMemDebugPrint(("MapMem: entering DriverEntry\n"));
-
-
- RtlInitUnicodeString(&deviceNameUnicodeString,
- deviceNameBuffer);
-
- //
- // Create the device object
- //
-
- ntStatus = IoCreateDevice(
- DriverObject,
- 0,
- &deviceNameUnicodeString,
- FILE_DEVICE_UNKNOWN,
- 0,
- TRUE,
- &deviceObject
- );
-
-
- if (NT_SUCCESS(ntStatus))
- {
- //
- // Create dispatch points for device control, create, close.
- //
-
- DriverObject->MajorFunction[IRP_MJ_CREATE] =
- DriverObject->MajorFunction[IRP_MJ_CLOSE] = MapMemCreateClose;
- DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MapMemDispatch;
- }
-
- return ntStatus;
- }
-
-
-
- NTSTATUS
- MapMemCreateClose(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- {
- //
- // No need to do anything.
- //
-
- //
- // Fill these in before calling IoCompleteRequest.
- //
- // DON'T get cute and try to use the status field of
- // the irp in the return status. That IRP IS GONE as
- // soon as you call IoCompleteRequest.
- //
-
- MapMemDebugPrint(("MapMemOpenClose: enter\n"));
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(
- Irp,
- IO_NO_INCREMENT
- );
-
- return STATUS_SUCCESS;
-
- }
-
-
-
- NTSTATUS
- MapMemDispatch(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- {
- PIO_STACK_LOCATION irpStack;
- PVOID ioBuffer;
- ULONG inputBufferLength;
- ULONG outputBufferLength;
- ULONG ioControlCode;
- NTSTATUS ntStatus;
-
- //
- // Init to default settings- we only expect 1 type of
- // IOCTL to roll through here, all others an error.
- //
-
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
- Irp->IoStatus.Information = 0;
-
-
- //
- // Get a pointer to the current location in the Irp. This is where
- // the function codes and parameters are located.
- //
-
- irpStack = IoGetCurrentIrpStackLocation(Irp);
-
-
- //
- // Get the pointer to the input/output buffer and it's length
- //
-
- ioBuffer = Irp->AssociatedIrp.SystemBuffer;
- inputBufferLength =
- irpStack->Parameters.DeviceIoControl.InputBufferLength;
- outputBufferLength =
- irpStack->Parameters.DeviceIoControl.OutputBufferLength;
-
-
- switch (irpStack->MajorFunction)
- {
-
- case IRP_MJ_DEVICE_CONTROL:
-
- ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
-
- switch (ioControlCode)
- {
- case IOCTL_MAPMEM_MAP_USER_PHYSICAL_MEMORY:
-
- Irp->IoStatus.Status = MapMemMapTheMemory (DeviceObject,
- ioBuffer,
- inputBufferLength,
- outputBufferLength
- );
-
- if (NT_SUCCESS(Irp->IoStatus.Status))
- {
- //
- // Success! Set the following to sizeof(PVOID) to
- // indicate we're passing valid data back.
- //
-
- Irp->IoStatus.Information = sizeof(PVOID);
-
- MapMemDebugPrint(("MapMem: memory successfully mapped :)\n"));
- }
-
- else
-
- MapMemDebugPrint(("MapMem: memory map failed :(\n"));
-
- break;
-
- default:
-
- MapMemDebugPrint(("MapMem: unknown IRP_MJ_DEVICE_CONTROL\n"));
-
-
- break;
-
- } // switch (ioControlCode)
-
- break;
- }
-
-
- //
- // DON'T get cute and try to use the status field of
- // the irp in the return status. That IRP IS GONE as
- // soon as you call IoCompleteRequest.
- //
-
- ntStatus = Irp->IoStatus.Status;
-
- IoCompleteRequest(Irp,
- IO_NO_INCREMENT);
-
-
- //
- // We never have pending operation so always return the status code.
- //
-
- return ntStatus;
- }
-
-
-
- NTSTATUS
- MapMemMapTheMemory(
- IN PDEVICE_OBJECT DeviceObject,
- IN OUT PVOID ioBuffer,
- IN ULONG inputBufferLength,
- IN ULONG outputBufferLength
- )
- {
- PPHYSICAL_MEMORY_INFO ppmi = (PPHYSICAL_MEMORY_INFO) ioBuffer;
-
- INTERFACE_TYPE interfaceType;
- ULONG busNumber;
- PHYSICAL_ADDRESS physicalAddress;
- ULONG length;
- UNICODE_STRING physicalMemoryUnicodeString;
- OBJECT_ATTRIBUTES objectAttributes;
- HANDLE physicalMemoryHandle = NULL;
- PVOID PhysicalMemorySection = NULL;
- ULONG inIoSpace, inIoSpace2;
- NTSTATUS ntStatus;
- PHYSICAL_ADDRESS physicalAddressBase;
- PHYSICAL_ADDRESS physicalAddressEnd;
- PHYSICAL_ADDRESS viewBase;
- PHYSICAL_ADDRESS mappedLength;
- BOOLEAN translateBaseAddress;
- BOOLEAN translateEndAddress;
- PVOID virtualAddress;
-
-
-
- if ( ( inputBufferLength < sizeof (PHYSICAL_MEMORY_INFO) ) ||
- ( outputBufferLength < sizeof (PVOID) ) )
- {
- MapMemDebugPrint(("MapMem: Insufficient input or output buffer\n"));
-
- ntStatus = STATUS_INSUFFICIENT_RESOURCES;
-
- goto done;
- }
-
- interfaceType = ppmi->interfaceType;
- busNumber = ppmi->busNumber;
- physicalAddress = ppmi->physicalAddress;
- length = ppmi->length;
-
-
- //
- // Get a pointer to physical memory...
- //
- // - Create the name
- // - Initialize the data to find the object
- // - Open a handle to the oject and check the status
- // - Get a pointer to the object
- // - Free the handle
- //
-
- RtlInitUnicodeString(&physicalMemoryUnicodeString,
- L"\\Device\\PhysicalMemory");
-
- InitializeObjectAttributes (&objectAttributes,
- &physicalMemoryUnicodeString,
- OBJ_CASE_INSENSITIVE,
- (HANDLE) NULL,
- (PSECURITY_DESCRIPTOR) NULL);
-
- ntStatus = ZwOpenSection (&physicalMemoryHandle,
- SECTION_ALL_ACCESS,
- &objectAttributes);
-
- if (!NT_SUCCESS(ntStatus))
- {
- MapMemDebugPrint(("MapMem: ZwOpenSection failed\n"));
-
- goto done;
- }
-
- ntStatus = ObReferenceObjectByHandle (physicalMemoryHandle,
- SECTION_ALL_ACCESS,
- (POBJECT_TYPE) NULL,
- KernelMode,
- &PhysicalMemorySection,
- (POBJECT_HANDLE_INFORMATION) NULL);
-
- if (!NT_SUCCESS(ntStatus))
- {
- MapMemDebugPrint(("MapMem: ObReferenceObjectByHandle failed\n"));
-
- goto close_handle;
- }
-
- //
- // Have a second variable used for the second HalTranslateBusAddres call.
- //
-
- inIoSpace = inIoSpace2 = 0;
-
-
- //
- // Initialize the physical addresses that will be translated
- //
-
- physicalAddressEnd = RtlLargeIntegerAdd (physicalAddress,
- RtlConvertUlongToLargeInteger(
- length));
-
- //
- // Translate the physical addresses.
- //
-
- translateBaseAddress =
- HalTranslateBusAddress (interfaceType,
- busNumber,
- physicalAddress,
- &inIoSpace,
- &physicalAddressBase);
-
- translateEndAddress =
- HalTranslateBusAddress (interfaceType,
- busNumber,
- physicalAddressEnd,
- &inIoSpace2,
- &physicalAddressEnd);
-
- if ( !(translateBaseAddress && translateEndAddress) )
- {
- MapMemDebugPrint(("MapMem: HalTranslateBusAddress failed\n"));
-
- ntStatus = STATUS_UNSUCCESSFUL;
-
- goto close_handle;
- }
-
- //
- // Calculate the length of the memory to be mapped
- //
-
- mappedLength = RtlLargeIntegerSubtract (physicalAddressEnd,
- physicalAddressBase);
-
-
- //
- // If the mappedlength is zero, somthing very weird happened in the HAL
- // since the Length was checked against zero.
- //
-
- if (mappedLength.LowPart == 0)
- {
- MapMemDebugPrint(("MapMem: mappedLength.LowPart == 0\n"));
-
- ntStatus = STATUS_UNSUCCESSFUL;
-
- goto close_handle;
- }
-
- length = mappedLength.LowPart;
-
-
- //
- // If the address is in io space, just return the address, otherwise
- // go through the mapping mechanism
- //
-
- if (inIoSpace)
- {
- *((PVOID *) ioBuffer) = physicalAddressBase.LowPart;
- }
-
- else
- {
- //
- // initialize view base that will receive the physical mapped
- // address after the MapViewOfSection call.
- //
-
- viewBase = physicalAddressBase;
-
-
- //
- // Let ZwMapViewOfSection pick an address
- //
-
- virtualAddress = NULL;
-
-
-
- //
- // Map the section
- //
-
- ntStatus = ZwMapViewOfSection (physicalMemoryHandle,
- (HANDLE) -1,
- &virtualAddress,
- 0L,
- length,
- &viewBase,
- &length,
- ViewShare,
- 0,
- PAGE_READWRITE | PAGE_NOCACHE);
-
- if (!NT_SUCCESS(ntStatus))
- {
- MapMemDebugPrint(("MapMem: ZwMapViewOfSection failed\n"));
-
- goto close_handle;
- }
-
- //
- // Mapping the section above rounded the physical address down to the
- // nearest 64 K boundary. Now return a virtual address that sits where
- // we wnat by adding in the offset from the beginning of the section.
- //
-
-
- (ULONG) virtualAddress += (ULONG)physicalAddressBase.LowPart -
- (ULONG)viewBase.LowPart;
-
- *((PVOID *) ioBuffer) = virtualAddress;
-
- }
-
- ntStatus = STATUS_SUCCESS;
-
-
-
- close_handle:
-
- ZwClose(physicalMemoryHandle);
-
-
-
- done:
-
- MapMemDebugPrint(("\t ntStatus = %x\n"));
- return ntStatus;
- }
-