|
|
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.