Annotation of q_a/samples/ddk/mapmem/mapmem.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.