|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: mapmem.c ! 8: ! 9: Abstract: ! 10: ! 11: A simple driver sample which shows how to map physical memory ! 12: into a user-mode process's adrress space using the ! 13: Zw*MapViewOfSection APIs. ! 14: ! 15: Environment: ! 16: ! 17: kernel mode only ! 18: ! 19: Notes: ! 20: ! 21: For the sake of simplicity this sample does not attempt to ! 22: recognize resource conflicts with other drivers/devices. A ! 23: real-world driver would call IoReportResource usage to ! 24: determine whether or not the resource is available, and if ! 25: so, register the resource under it's name. ! 26: ! 27: Revision History: ! 28: ! 29: --*/ ! 30: ! 31: ! 32: #include "ntddk.h" ! 33: #include "mapmem.h" ! 34: #include "stdarg.h" ! 35: ! 36: ! 37: ! 38: NTSTATUS ! 39: MapMemDispatch( ! 40: IN PDEVICE_OBJECT DeviceObject, ! 41: IN PIRP Irp ! 42: ); ! 43: ! 44: VOID ! 45: MapMemUnload( ! 46: IN PDRIVER_OBJECT DriverObject ! 47: ); ! 48: ! 49: NTSTATUS ! 50: MapMemMapTheMemory( ! 51: IN PDEVICE_OBJECT DeviceObject, ! 52: IN OUT PVOID ioBuffer, ! 53: IN ULONG inputBufferLength, ! 54: IN ULONG outputBufferLength ! 55: ); ! 56: ! 57: ! 58: ! 59: #if DBG ! 60: #define MapMemKdPrint(arg) DbgPrint arg ! 61: #else ! 62: #define MapMemKdPrint(arg) ! 63: #endif ! 64: ! 65: ! 66: ! 67: NTSTATUS ! 68: DriverEntry( ! 69: IN PDRIVER_OBJECT DriverObject, ! 70: IN PUNICODE_STRING RegistryPath ! 71: ) ! 72: /*++ ! 73: ! 74: Routine Description: ! 75: ! 76: Installable driver initialization entry point. ! 77: This entry point is called directly by the I/O system. ! 78: ! 79: Arguments: ! 80: ! 81: DriverObject - pointer to the driver object ! 82: ! 83: RegistryPath - pointer to a unicode string representing the path ! 84: to driver-specific key in the registry ! 85: ! 86: Return Value: ! 87: ! 88: STATUS_SUCCESS if successful, ! 89: STATUS_UNSUCCESSFUL otherwise ! 90: ! 91: --*/ ! 92: { ! 93: ! 94: PDEVICE_OBJECT deviceObject = NULL; ! 95: NTSTATUS ntStatus; ! 96: WCHAR deviceNameBuffer[] = L"\\Device\\MapMem"; ! 97: UNICODE_STRING deviceNameUnicodeString; ! 98: WCHAR deviceLinkBuffer[] = L"\\DosDevices\\MAPMEM"; ! 99: UNICODE_STRING deviceLinkUnicodeString; ! 100: ! 101: ! 102: ! 103: MapMemKdPrint (("MAPMEM.SYS: entering DriverEntry\n")); ! 104: ! 105: ! 106: // ! 107: // Create an EXCLUSIVE device object (only 1 thread at a time ! 108: // can make requests to this device) ! 109: // ! 110: ! 111: RtlInitUnicodeString (&deviceNameUnicodeString, ! 112: deviceNameBuffer); ! 113: ! 114: ntStatus = IoCreateDevice (DriverObject, ! 115: 0, ! 116: &deviceNameUnicodeString, ! 117: FILE_DEVICE_MAPMEM, ! 118: 0, ! 119: TRUE, ! 120: &deviceObject ! 121: ); ! 122: ! 123: if (NT_SUCCESS(ntStatus)) ! 124: { ! 125: // ! 126: // Create dispatch points for device control, create, close. ! 127: // ! 128: ! 129: DriverObject->MajorFunction[IRP_MJ_CREATE] = ! 130: DriverObject->MajorFunction[IRP_MJ_CLOSE] = ! 131: DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MapMemDispatch; ! 132: DriverObject->DriverUnload = MapMemUnload; ! 133: ! 134: ! 135: ! 136: // ! 137: // Create a symbolic link, e.g. a name that a Win32 app can specify ! 138: // to open the device ! 139: // ! 140: ! 141: RtlInitUnicodeString(&deviceLinkUnicodeString, ! 142: deviceLinkBuffer); ! 143: ! 144: ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString, ! 145: &deviceNameUnicodeString); ! 146: ! 147: if (!NT_SUCCESS(ntStatus)) ! 148: { ! 149: // ! 150: // Symbolic link creation failed- note this & then delete the ! 151: // device object (it's useless if a Win32 app can't get at it). ! 152: // ! 153: ! 154: MapMemKdPrint (("MAPMEM.SYS: IoCreateSymbolicLink failed\n")); ! 155: ! 156: IoDeleteDevice (deviceObject); ! 157: } ! 158: } ! 159: else ! 160: { ! 161: MapMemKdPrint (("MAPMEM.SYS: IoCreateDevice failed\n")); ! 162: } ! 163: ! 164: return ntStatus; ! 165: } ! 166: ! 167: ! 168: ! 169: NTSTATUS ! 170: MapMemDispatch( ! 171: IN PDEVICE_OBJECT DeviceObject, ! 172: IN PIRP Irp ! 173: ) ! 174: /*++ ! 175: ! 176: Routine Description: ! 177: ! 178: Process the IRPs sent to this device. ! 179: ! 180: Arguments: ! 181: ! 182: DeviceObject - pointer to a device object ! 183: ! 184: Irp - pointer to an I/O Request Packet ! 185: ! 186: Return Value: ! 187: ! 188: ! 189: --*/ ! 190: { ! 191: PIO_STACK_LOCATION irpStack; ! 192: PVOID ioBuffer; ! 193: ULONG inputBufferLength; ! 194: ULONG outputBufferLength; ! 195: ULONG ioControlCode; ! 196: NTSTATUS ntStatus; ! 197: ! 198: ! 199: // ! 200: // Init to default settings- we only expect 1 type of ! 201: // IOCTL to roll through here, all others an error. ! 202: // ! 203: ! 204: Irp->IoStatus.Status = STATUS_SUCCESS; ! 205: Irp->IoStatus.Information = 0; ! 206: ! 207: ! 208: // ! 209: // Get a pointer to the current location in the Irp. This is where ! 210: // the function codes and parameters are located. ! 211: // ! 212: ! 213: irpStack = IoGetCurrentIrpStackLocation(Irp); ! 214: ! 215: ! 216: // ! 217: // Get the pointer to the input/output buffer and it's length ! 218: // ! 219: ! 220: ioBuffer = Irp->AssociatedIrp.SystemBuffer; ! 221: inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; ! 222: outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; ! 223: ! 224: ! 225: switch (irpStack->MajorFunction) ! 226: { ! 227: case IRP_MJ_CREATE: ! 228: ! 229: MapMemKdPrint (("MAPMEM.SYS: IRP_MJ_CREATE\n")); ! 230: ! 231: break; ! 232: ! 233: ! 234: ! 235: case IRP_MJ_CLOSE: ! 236: ! 237: MapMemKdPrint (("MAPMEM.SYS: IRP_MJ_CLOSE\n")); ! 238: ! 239: break; ! 240: ! 241: ! 242: ! 243: case IRP_MJ_DEVICE_CONTROL: ! 244: ! 245: ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; ! 246: ! 247: switch (ioControlCode) ! 248: { ! 249: case IOCTL_MAPMEM_MAP_USER_PHYSICAL_MEMORY: ! 250: ! 251: Irp->IoStatus.Status = MapMemMapTheMemory (DeviceObject, ! 252: ioBuffer, ! 253: inputBufferLength, ! 254: outputBufferLength ! 255: ); ! 256: ! 257: if (NT_SUCCESS(Irp->IoStatus.Status)) ! 258: { ! 259: // ! 260: // Success! Set the following to sizeof(PVOID) to ! 261: // indicate we're passing valid data back. ! 262: // ! 263: ! 264: Irp->IoStatus.Information = sizeof(PVOID); ! 265: ! 266: MapMemKdPrint (("MAPMEM.SYS: memory successfully mapped\n")); ! 267: } ! 268: ! 269: else ! 270: { ! 271: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; ! 272: ! 273: MapMemKdPrint (("MAPMEM.SYS: memory map failed :(\n")); ! 274: } ! 275: ! 276: break; ! 277: ! 278: ! 279: ! 280: case IOCTL_MAPMEM_UNMAP_USER_PHYSICAL_MEMORY: ! 281: ! 282: if (inputBufferLength >= sizeof(PVOID)) ! 283: { ! 284: Irp->IoStatus.Status = ZwUnmapViewOfSection ((HANDLE) -1, ! 285: *((PVOID *) ioBuffer) ! 286: ); ! 287: ! 288: MapMemKdPrint (("MAPMEM.SYS: memory successfully unmapped\n")); ! 289: } ! 290: else ! 291: { ! 292: Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; ! 293: ! 294: MapMemKdPrint (("MAPMEM.SYS: ZwUnmapViewOfSection failed\n")); ! 295: } ! 296: ! 297: break; ! 298: ! 299: ! 300: ! 301: default: ! 302: ! 303: MapMemKdPrint (("MAPMEM.SYS: unknown IRP_MJ_DEVICE_CONTROL\n")); ! 304: ! 305: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; ! 306: ! 307: break; ! 308: ! 309: } ! 310: ! 311: break; ! 312: } ! 313: ! 314: ! 315: // ! 316: // DON'T get cute and try to use the status field of ! 317: // the irp in the return status. That IRP IS GONE as ! 318: // soon as you call IoCompleteRequest. ! 319: // ! 320: ! 321: ntStatus = Irp->IoStatus.Status; ! 322: ! 323: IoCompleteRequest(Irp, ! 324: IO_NO_INCREMENT); ! 325: ! 326: ! 327: // ! 328: // We never have pending operation so always return the status code. ! 329: // ! 330: ! 331: return ntStatus; ! 332: } ! 333: ! 334: ! 335: ! 336: VOID ! 337: MapMemUnload( ! 338: IN PDRIVER_OBJECT DriverObject ! 339: ) ! 340: /*++ ! 341: ! 342: Routine Description: ! 343: ! 344: Just delete the associated device & return. ! 345: ! 346: Arguments: ! 347: ! 348: DriverObject - pointer to a driver object ! 349: ! 350: Return Value: ! 351: ! 352: ! 353: --*/ ! 354: { ! 355: WCHAR deviceLinkBuffer[] = L"\\DosDevices\\MAPMEM"; ! 356: UNICODE_STRING deviceLinkUnicodeString; ! 357: ! 358: ! 359: ! 360: // ! 361: // Free any resources ! 362: // ! 363: ! 364: ! 365: ! 366: // ! 367: // Delete the symbolic link ! 368: // ! 369: ! 370: RtlInitUnicodeString (&deviceLinkUnicodeString, ! 371: deviceLinkBuffer ! 372: ); ! 373: ! 374: IoDeleteSymbolicLink (&deviceLinkUnicodeString); ! 375: ! 376: ! 377: ! 378: // ! 379: // Delete the device object ! 380: // ! 381: ! 382: MapMemKdPrint (("MAPMEM.SYS: unloading\n")); ! 383: ! 384: IoDeleteDevice (DriverObject->DeviceObject); ! 385: } ! 386: ! 387: ! 388: ! 389: NTSTATUS ! 390: MapMemMapTheMemory( ! 391: IN PDEVICE_OBJECT DeviceObject, ! 392: IN OUT PVOID IoBuffer, ! 393: IN ULONG InputBufferLength, ! 394: IN ULONG OutputBufferLength ! 395: ) ! 396: /*++ ! 397: ! 398: Routine Description: ! 399: ! 400: Given a physical address, maps this address into a user mode process's ! 401: address space ! 402: ! 403: Arguments: ! 404: ! 405: DeviceObject - pointer to a device object ! 406: ! 407: IoBuffer - pointer to the I/O buffer ! 408: ! 409: InputBufferLength - input buffer length ! 410: ! 411: OutputBufferLength - output buffer length ! 412: ! 413: Return Value: ! 414: ! 415: STATUS_SUCCESS if sucessful, otherwise ! 416: STATUS_UNSUCCESSFUL, ! 417: STATUS_INSUFFICIENT_RESOURCES, ! 418: (other STATUS_* as returned by kernel APIs) ! 419: ! 420: --*/ ! 421: { ! 422: ! 423: PPHYSICAL_MEMORY_INFO ppmi = (PPHYSICAL_MEMORY_INFO) IoBuffer; ! 424: ! 425: INTERFACE_TYPE interfaceType; ! 426: ULONG busNumber; ! 427: PHYSICAL_ADDRESS physicalAddress; ! 428: ULONG length; ! 429: UNICODE_STRING physicalMemoryUnicodeString; ! 430: OBJECT_ATTRIBUTES objectAttributes; ! 431: HANDLE physicalMemoryHandle = NULL; ! 432: PVOID PhysicalMemorySection = NULL; ! 433: ULONG inIoSpace, inIoSpace2; ! 434: NTSTATUS ntStatus; ! 435: PHYSICAL_ADDRESS physicalAddressBase; ! 436: PHYSICAL_ADDRESS physicalAddressEnd; ! 437: PHYSICAL_ADDRESS viewBase; ! 438: PHYSICAL_ADDRESS mappedLength; ! 439: BOOLEAN translateBaseAddress; ! 440: BOOLEAN translateEndAddress; ! 441: PVOID virtualAddress; ! 442: ! 443: ! 444: ! 445: if ( ( InputBufferLength < sizeof (PHYSICAL_MEMORY_INFO) ) || ! 446: ( OutputBufferLength < sizeof (PVOID) ) ) ! 447: { ! 448: MapMemKdPrint (("MAPMEM.SYS: Insufficient input or output buffer\n")); ! 449: ! 450: ntStatus = STATUS_INSUFFICIENT_RESOURCES; ! 451: ! 452: goto done; ! 453: } ! 454: ! 455: interfaceType = ppmi->InterfaceType; ! 456: busNumber = ppmi->BusNumber; ! 457: physicalAddress = ppmi->BusAddress; ! 458: inIoSpace = inIoSpace2 = ppmi->AddressSpace; ! 459: length = ppmi->Length; ! 460: ! 461: ! 462: // ! 463: // Get a pointer to physical memory... ! 464: // ! 465: // - Create the name ! 466: // - Initialize the data to find the object ! 467: // - Open a handle to the oject and check the status ! 468: // - Get a pointer to the object ! 469: // - Free the handle ! 470: // ! 471: ! 472: RtlInitUnicodeString (&physicalMemoryUnicodeString, ! 473: L"\\Device\\PhysicalMemory"); ! 474: ! 475: InitializeObjectAttributes (&objectAttributes, ! 476: &physicalMemoryUnicodeString, ! 477: OBJ_CASE_INSENSITIVE, ! 478: (HANDLE) NULL, ! 479: (PSECURITY_DESCRIPTOR) NULL); ! 480: ! 481: ntStatus = ZwOpenSection (&physicalMemoryHandle, ! 482: SECTION_ALL_ACCESS, ! 483: &objectAttributes); ! 484: ! 485: if (!NT_SUCCESS(ntStatus)) ! 486: { ! 487: MapMemKdPrint (("MAPMEM.SYS: ZwOpenSection failed\n")); ! 488: ! 489: goto done; ! 490: } ! 491: ! 492: ntStatus = ObReferenceObjectByHandle (physicalMemoryHandle, ! 493: SECTION_ALL_ACCESS, ! 494: (POBJECT_TYPE) NULL, ! 495: KernelMode, ! 496: &PhysicalMemorySection, ! 497: (POBJECT_HANDLE_INFORMATION) NULL); ! 498: ! 499: if (!NT_SUCCESS(ntStatus)) ! 500: { ! 501: MapMemKdPrint (("MAPMEM.SYS: ObReferenceObjectByHandle failed\n")); ! 502: ! 503: goto close_handle; ! 504: } ! 505: ! 506: ! 507: // ! 508: // Initialize the physical addresses that will be translated ! 509: // ! 510: ! 511: physicalAddressEnd = RtlLargeIntegerAdd (physicalAddress, ! 512: RtlConvertUlongToLargeInteger( ! 513: length)); ! 514: ! 515: // ! 516: // Translate the physical addresses. ! 517: // ! 518: ! 519: translateBaseAddress = ! 520: HalTranslateBusAddress (interfaceType, ! 521: busNumber, ! 522: physicalAddress, ! 523: &inIoSpace, ! 524: &physicalAddressBase); ! 525: ! 526: translateEndAddress = ! 527: HalTranslateBusAddress (interfaceType, ! 528: busNumber, ! 529: physicalAddressEnd, ! 530: &inIoSpace2, ! 531: &physicalAddressEnd); ! 532: ! 533: if ( !(translateBaseAddress && translateEndAddress) ) ! 534: { ! 535: MapMemKdPrint (("MAPMEM.SYS: HalTranslatephysicalAddress failed\n")); ! 536: ! 537: ntStatus = STATUS_UNSUCCESSFUL; ! 538: ! 539: goto close_handle; ! 540: } ! 541: ! 542: // ! 543: // Calculate the length of the memory to be mapped ! 544: // ! 545: ! 546: mappedLength = RtlLargeIntegerSubtract (physicalAddressEnd, ! 547: physicalAddressBase); ! 548: ! 549: ! 550: // ! 551: // If the mappedlength is zero, somthing very weird happened in the HAL ! 552: // since the Length was checked against zero. ! 553: // ! 554: ! 555: if (mappedLength.LowPart == 0) ! 556: { ! 557: MapMemKdPrint (("MAPMEM.SYS: mappedLength.LowPart == 0\n")); ! 558: ! 559: ntStatus = STATUS_UNSUCCESSFUL; ! 560: ! 561: goto close_handle; ! 562: } ! 563: ! 564: length = mappedLength.LowPart; ! 565: ! 566: ! 567: // ! 568: // If the address is in io space, just return the address, otherwise ! 569: // go through the mapping mechanism ! 570: // ! 571: ! 572: if (inIoSpace) ! 573: { ! 574: *((PVOID *) IoBuffer) = (PVOID) physicalAddressBase.LowPart; ! 575: } ! 576: ! 577: else ! 578: { ! 579: // ! 580: // initialize view base that will receive the physical mapped ! 581: // address after the MapViewOfSection call. ! 582: // ! 583: ! 584: viewBase = physicalAddressBase; ! 585: ! 586: ! 587: // ! 588: // Let ZwMapViewOfSection pick an address ! 589: // ! 590: ! 591: virtualAddress = NULL; ! 592: ! 593: ! 594: ! 595: // ! 596: // Map the section ! 597: // ! 598: ! 599: ntStatus = ZwMapViewOfSection (physicalMemoryHandle, ! 600: (HANDLE) -1, ! 601: &virtualAddress, ! 602: 0L, ! 603: length, ! 604: &viewBase, ! 605: &length, ! 606: ViewShare, ! 607: 0, ! 608: PAGE_READWRITE | PAGE_NOCACHE); ! 609: ! 610: if (!NT_SUCCESS(ntStatus)) ! 611: { ! 612: MapMemKdPrint (("MAPMEM.SYS: ZwMapViewOfSection failed\n")); ! 613: ! 614: goto close_handle; ! 615: } ! 616: ! 617: // ! 618: // Mapping the section above rounded the physical address down to the ! 619: // nearest 64 K boundary. Now return a virtual address that sits where ! 620: // we wnat by adding in the offset from the beginning of the section. ! 621: // ! 622: ! 623: ! 624: (ULONG) virtualAddress += (ULONG)physicalAddressBase.LowPart - ! 625: (ULONG)viewBase.LowPart; ! 626: ! 627: *((PVOID *) IoBuffer) = virtualAddress; ! 628: ! 629: } ! 630: ! 631: ntStatus = STATUS_SUCCESS; ! 632: ! 633: ! 634: ! 635: close_handle: ! 636: ! 637: ZwClose (physicalMemoryHandle); ! 638: ! 639: ! 640: ! 641: done: ! 642: ! 643: return ntStatus; ! 644: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.