|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 Microsoft Corporation
4:
5: Module Name:
6:
7: ramdisk.c
8:
9: Abstract:
10:
11: This is the Ram Disk driver.
12:
13: Author:
14:
15: Robert Nelson (RobertN) 10-Mar-1993.
16:
17: Environment:
18:
19: Kernel mode only.
20:
21: Notes:
22:
23: Revision History:
24: Added the IOCTL_DISK_GET_PARTITION_INFO query to make it work with NTFS
25: driver loaded (thanks Robert Vierthaler (RobertVi)).
26:
27: --*/
28:
29:
30: //
31: // Include files.
32: //
33:
34: #include <ntddk.h> // various NT definitions
35: #include <ntdddisk.h> // disk device driver I/O control codes
36: #include <ntiologc.h>
37:
38: #include <string.h>
39:
40: #include "ramdisk.h"
41:
42: #if DBG
43: ULONG RamDiskDebugLevel = 0;
44: #endif
45:
46:
47: NTSTATUS
48: DriverEntry(
49: IN OUT PDRIVER_OBJECT DriverObject,
50: IN PUNICODE_STRING RegistryPath
51: )
52: /*++
53:
54: Routine Description:
55: This routine is called by the Operating System to initialize the driver.
56:
57: It fills in the dispatch entry points in the driver object. Then
58: RamDiskInitializeDisk is called to create the device object and complete
59: the initialization.
60:
61: Arguments:
62: DriverObject - a pointer to the object that represents this device
63: driver.
64:
65: RegistryPath - a pointer to our Services key in the registry.
66:
67: Return Value:
68: STATUS_SUCCESS if this disk is initialized; an error otherwise.
69:
70: --*/
71:
72: {
73: NTSTATUS ntStatus;
74: UNICODE_STRING paramPath;
75: static WCHAR SubKeyString[] = L"\\Parameters";
76:
77: //
78: // The registry path parameter points to our key, we will append
79: // the Parameters key and look for any additional configuration items
80: // there. We add room for a trailing NUL for those routines which
81: // require it.
82:
83: paramPath.MaximumLength = RegistryPath->Length + sizeof(SubKeyString);
84: paramPath.Buffer = ExAllocatePool(PagedPool, paramPath.MaximumLength);
85:
86: if (paramPath.Buffer != NULL)
87: {
88: RtlMoveMemory(
89: paramPath.Buffer, RegistryPath->Buffer, RegistryPath->Length);
90:
91: RtlMoveMemory(
92: ¶mPath.Buffer[RegistryPath->Length / 2], SubKeyString,
93: sizeof(SubKeyString));
94:
95: paramPath.Length = paramPath.MaximumLength;
96: }
97: else
98: {
99: return STATUS_INSUFFICIENT_RESOURCES;
100: }
101:
102: #if DBG
103: {
104: //
105: // We use this to query into the registry as to whether we
106: // should break at driver entry.
107: //
108:
109: RTL_QUERY_REGISTRY_TABLE paramTable[3];
110: ULONG zero = 0;
111:
112: ULONG debugLevel = 0;
113: ULONG shouldBreak = 0;
114:
115: RtlZeroMemory(¶mTable[0], sizeof(paramTable));
116:
117: paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
118: paramTable[0].Name = L"BreakOnEntry";
119: paramTable[0].EntryContext = &shouldBreak;
120: paramTable[0].DefaultType = REG_DWORD;
121: paramTable[0].DefaultData = &zero;
122: paramTable[0].DefaultLength = sizeof(ULONG);
123:
124: paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
125: paramTable[1].Name = L"DebugLevel";
126: paramTable[1].EntryContext = &debugLevel;
127: paramTable[1].DefaultType = REG_DWORD;
128: paramTable[1].DefaultData = &zero;
129: paramTable[1].DefaultLength = sizeof(ULONG);
130:
131: if (!NT_SUCCESS(RtlQueryRegistryValues(
132: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
133: paramPath.Buffer, ¶mTable[0], NULL, NULL)))
134: {
135: shouldBreak = 0;
136: debugLevel = 0;
137: }
138:
139: RamDiskDebugLevel = debugLevel;
140:
141: if (shouldBreak)
142: {
143: DbgBreakPoint();
144: }
145: }
146: #endif
147:
148: //
149: // Initialize the driver object with this driver's entry points.
150: //
151:
152: DriverObject->MajorFunction[IRP_MJ_CREATE] = RamDiskCreateClose;
153: DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamDiskCreateClose;
154: DriverObject->MajorFunction[IRP_MJ_READ] = RamDiskReadWrite;
155: DriverObject->MajorFunction[IRP_MJ_WRITE] = RamDiskReadWrite;
156: DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamDiskDeviceControl;
157:
158: //
159: // We'll enable unload when the Filesystem drivers support it
160: //
161: // DriverObject->DriverUnload = RamDiskUnloadDriver;
162:
163: ntStatus = RamDiskInitializeDisk(DriverObject, ¶mPath);
164:
165: //
166: // We don't need that path anymore.
167: //
168:
169: if (paramPath.Buffer)
170: {
171: ExFreePool( paramPath.Buffer );
172: }
173:
174: return ntStatus;
175: }
176:
177: NTSTATUS
178: RamDiskInitializeDisk(
179: IN PDRIVER_OBJECT DriverObject,
180: IN PUNICODE_STRING ParamPath
181: )
182:
183: /*++
184:
185: Routine Description:
186: This routine is called at initialization time by DriverEntry().
187:
188: It creates and initializes a device object for the disk. Memory for the
189: Ram Disk is allocated from the non-paged Pool. RamDiskFormatFat is called
190: to create a FAT filesystem in the memory buffer allocated.
191:
192: Two parameters may be configured using the registry. DiskSize specifies
193: the desired size (in bytes). If the requested memory is not available in
194: the nonpaged pool then STATUS_INSUFFICIENT_RESOURCES is returned. The
195: default value is 0x00100000 (1MB).
196:
197: DriveLetter is used to indicate the drive letter for the RamDisk. The
198: string must be a letter, optionally followed by :.
199:
200: Arguments:
201: DriverObject - a pointer to the object that represents this device
202: driver.
203:
204: ParamPath - a pointer to the Parameters key under our key in the Services
205: section of the registry.
206:
207: Return Value:
208: STATUS_SUCCESS if this disk is initialized; an error otherwise.
209:
210: --*/
211:
212: {
213: STRING ntNameString; // NT Device Name "\Device\RamDisk"
214: UNICODE_STRING ntUnicodeString; // Unicode version of ntNameString
215: UNICODE_STRING Win32PathString; // Win32 Name "\DosDevices\Z:"
216:
217: PDEVICE_OBJECT deviceObject = NULL; // ptr to device object
218: PRAMDISK_EXTENSION diskExtension = NULL; // ptr to device extension
219:
220: NTSTATUS ntStatus;
221:
222: RTL_QUERY_REGISTRY_TABLE paramTable[3];
223:
224: ULONG defaultDiskSize = DEFAULT_DISK_SIZE;
225: ULONG diskSize = DEFAULT_DISK_SIZE;
226: UNICODE_STRING driveLetterString;
227: WCHAR driveLetterBuffer[sizeof(WCHAR) * 10];
228:
229: RtlInitUnicodeString( &driveLetterString, NULL );
230:
231: driveLetterString.MaximumLength = sizeof(WCHAR) * 9;
232: driveLetterString.Buffer = driveLetterBuffer;
233:
234: RtlZeroMemory(¶mTable[0], sizeof(paramTable));
235: RtlZeroMemory(&driveLetterBuffer[0], sizeof(driveLetterBuffer));
236:
237: paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
238: paramTable[0].Name = L"DiskSize";
239: paramTable[0].EntryContext = &diskSize;
240: paramTable[0].DefaultType = REG_DWORD;
241: paramTable[0].DefaultData = &defaultDiskSize;
242: paramTable[0].DefaultLength = sizeof(ULONG);
243:
244: paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
245: paramTable[1].Name = L"DriveLetter";
246: paramTable[1].EntryContext = &driveLetterString;
247:
248: if (!NT_SUCCESS(RtlQueryRegistryValues(
249: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
250: ParamPath->Buffer, ¶mTable[0], NULL, NULL)))
251: {
252: diskSize = DEFAULT_DISK_SIZE;
253: }
254:
255: ASSERT(sizeof(BOOT_SECTOR) == 512);
256:
257: RtlInitString( &ntNameString, "\\Device\\Ramdisk" );
258:
259: ntStatus = RtlAnsiStringToUnicodeString(
260: &ntUnicodeString, &ntNameString, TRUE );
261:
262: if ( !NT_SUCCESS( ntStatus ) )
263: {
264: RamDiskDump(
265: RAMDERRORS, ("RAMDISK: Couldn't create the unicode device name\n"));
266: goto RamDiskInitializeDiskExit;
267: }
268:
269: ntStatus = IoCreateDevice(
270: DriverObject, // Our Driver Object
271: sizeof( RAMDISK_EXTENSION ), // Size of state information
272: &ntUnicodeString, // Device name "\Device\RamDisk"
273: FILE_DEVICE_VIRTUAL_DISK, // Device type
274: 0, // Device characteristics
275: FALSE, // Exclusive device
276: &deviceObject ); // Returned ptr to Device Object
277:
278: if ( !NT_SUCCESS( ntStatus ) )
279: {
280: RamDiskDump(
281: RAMDERRORS, ("RAMDISK: Couldn't create the device object\n"));
282: goto RamDiskInitializeDiskExit;
283: }
284:
285: //
286: // Initialize device object and extension.
287: //
288:
289: deviceObject->Flags |= DO_DIRECT_IO;
290: deviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
291:
292: diskExtension = (PRAMDISK_EXTENSION)deviceObject->DeviceExtension;
293:
294: RtlInitUnicodeString( &diskExtension->Win32NameString, NULL );
295:
296: //
297: // Allocate and zero the memory disk image.
298: //
299:
300: diskExtension->DiskImage = ExAllocatePool( NonPagedPool, diskSize );
301:
302: if ( diskExtension->DiskImage == NULL )
303: {
304: RamDiskDump(
305: RAMDERRORS, ("RAMDISK: Can't allocate memory for disk image\n") );
306: goto RamDiskInitializeDiskExit;
307: }
308:
309: RtlZeroMemory( diskExtension->DiskImage, diskSize );
310:
311: //
312: // Fill in device-specific numbers based on disk size obtained from the
313: // configuration manager.
314: //
315:
316: diskExtension->DeviceObject = deviceObject;
317: diskExtension->DiskLength = diskSize;
318: diskExtension->BytesPerSector = 512;
319: diskExtension->SectorsPerTrack = 32;
320: diskExtension->TracksPerCylinder = 2;
321: diskExtension->NumberOfCylinders = diskSize / 512 / 32 / 2;
322:
323: // Format a FAT filesystem in the memory buffer
324:
325: RamDiskFormatFat(diskExtension, ParamPath);
326:
327: //
328: // Allocate and initialize a Unicode String containing the Win32 name
329: // for our device.
330: //
331: RtlInitUnicodeString( &Win32PathString, WIN32_PATH );
332:
333: diskExtension->Win32NameString.Buffer = ExAllocatePool(
334: PagedPool,
335: sizeof(WIN32_PATH) + 2 * sizeof(WCHAR) );
336:
337: if (!diskExtension->Win32NameString.Buffer) {
338: RamDiskDump(
339: RAMDERRORS,
340: ("RAMDISK: Couldn't allocate buffer for the symbolic link\n")
341: );
342:
343: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
344:
345: goto RamDiskInitializeDiskExit;
346: }
347:
348: diskExtension->Win32NameString.MaximumLength = sizeof(WIN32_PATH) + sizeof(WCHAR);
349:
350: //
351: // If a drive letter wasn't specified in the registry, use drive Z.
352: //
353: if (driveLetterBuffer[0] == L'\0')
354: {
355: driveLetterBuffer[0] = L'Z';
356: }
357:
358: if (driveLetterBuffer[1] != L':')
359: {
360: driveLetterBuffer[1] = L':';
361: }
362:
363: driveLetterBuffer[2] = L'\0';
364: driveLetterString.Length = 2 * sizeof(WCHAR);
365:
366:
367: RtlAppendUnicodeStringToString(
368: &diskExtension->Win32NameString, &Win32PathString );
369:
370: RtlAppendUnicodeStringToString(
371: &diskExtension->Win32NameString, &driveLetterString );
372:
373: //
374: // Create a symbolic link between our device name "\Device\RamDisk" and
375: // the Win32 name (ie "\DosDevices\Z:").
376: //
377: ntStatus = IoCreateSymbolicLink(
378: &diskExtension->Win32NameString, &ntUnicodeString );
379:
380:
381: RamDiskInitializeDiskExit:
382:
383: if (ntUnicodeString.Buffer != NULL)
384: {
385: RtlFreeUnicodeString( &ntUnicodeString );
386: }
387:
388: if ( !NT_SUCCESS( ntStatus ) )
389: {
390: //
391: // Delete everything that this routine has allocated.
392: //
393:
394: if ( deviceObject != NULL )
395: {
396: if (diskExtension->DiskImage != NULL)
397: {
398: ExFreePool( diskExtension->DiskImage );
399: }
400: if (diskExtension->Win32NameString.Buffer != NULL)
401: {
402: ExFreePool( diskExtension->Win32NameString.Buffer );
403: }
404: IoDeleteDevice( deviceObject );
405: }
406: }
407:
408: return ntStatus;
409: }
410:
411: VOID
412: RamDiskFormatFat(
413: IN PRAMDISK_EXTENSION DiskExtension,
414: IN PUNICODE_STRING ParamPath
415: )
416: /*++
417:
418: Routine Description:
419:
420: This routine is called by RamDiskInitializeDisk to format a FAT filesystem
421: on the memory buffer.
422:
423: Two parameters may be configured using the registry. RootDirEntries
424: specifies the desired number of Root Directory entries. If necessary,
425: the value is rounded up to an integral number of ROOT_DIR_ENTRIES (16).
426: The default value (DEFAULT_ROOT_DIR_ENTRIES) is 512.
427:
428: SectorsPerCluster determines the number of sectors in each cluster. The
429: default value (DEFAULT_SECTORS_PER_CLUSTER) is 2.
430:
431: Arguments:
432:
433: DiskExtension - a pointer to the object that represents the device
434: that I/O is to be done on.
435:
436: ParamPath - a pointer to the Parameters key of our key under the Serices
437: section of the registry.
438:
439: Return Value:
440:
441: None
442:
443: --*/
444: {
445: RTL_QUERY_REGISTRY_TABLE paramTable[3];
446:
447: ULONG defaultRootDirEntries = DEFAULT_ROOT_DIR_ENTRIES;
448: ULONG rootDirEntries = DEFAULT_ROOT_DIR_ENTRIES;
449:
450: ULONG defaultSectorsPerCluster = DEFAULT_SECTORS_PER_CLUSTER;
451: ULONG sectorsPerCluster = DEFAULT_SECTORS_PER_CLUSTER;
452:
453:
454: PBOOT_SECTOR bootSector = (PBOOT_SECTOR) DiskExtension->DiskImage;
455: PUCHAR firstFatSector;
456:
457: int fatType; // Type of FAT - 12 or 16
458: USHORT fatEntries; // Number of cluster entries in FAT
459: USHORT fatSectorCnt; // Number of sectors for FAT
460:
461: PDIR_ENTRY rootDir; // Pointer to first entry in root dir
462: //
463: // Retrieve user tunable parameters
464: //
465: RtlZeroMemory(¶mTable[0], sizeof(paramTable));
466:
467: paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
468: paramTable[0].Name = L"RootDirEntries";
469: paramTable[0].EntryContext = &rootDirEntries;
470: paramTable[0].DefaultType = REG_DWORD;
471: paramTable[0].DefaultData = &defaultRootDirEntries;
472: paramTable[0].DefaultLength = sizeof(ULONG);
473:
474: paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
475: paramTable[1].Name = L"SectorsPerCluster";
476: paramTable[1].EntryContext = §orsPerCluster;
477: paramTable[1].DefaultType = REG_DWORD;
478: paramTable[1].DefaultData = &defaultSectorsPerCluster;
479: paramTable[1].DefaultLength = sizeof(ULONG);
480:
481: if (!NT_SUCCESS(RtlQueryRegistryValues(
482: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
483: ParamPath->Buffer, ¶mTable[0], NULL, NULL)))
484: {
485: rootDirEntries = DEFAULT_ROOT_DIR_ENTRIES;
486: sectorsPerCluster = DEFAULT_SECTORS_PER_CLUSTER;
487: }
488:
489: //
490: // Round Root Directory entries up if necessary
491: //
492: if (rootDirEntries & (DIR_ENTRIES_PER_SECTOR - 1))
493: {
494: RamDiskDump(RAMDDIAG1, ("RAMDISK: Adjusting RootDirEntries\n"));
495:
496: rootDirEntries =
497: (rootDirEntries + ( DIR_ENTRIES_PER_SECTOR - 1 )) &
498: ~ ( DIR_ENTRIES_PER_SECTOR - 1 );
499: }
500:
501: //
502: // We need to have the 0xeb and 0x90 since this is one of the
503: // checks the file system recognizer uses
504: //
505: bootSector->bsJump[0] = 0xeb;
506: bootSector->bsJump[1] = 0x3c;
507: bootSector->bsJump[2] = 0x90;
508:
509: strncpy(bootSector->bsOemName, "RobertN ", 8);
510: bootSector->bsBytesPerSec = (SHORT)DiskExtension->BytesPerSector;
511: bootSector->bsResSectors = 1;
512: bootSector->bsFATs = 1;
513: bootSector->bsRootDirEnts = (USHORT)rootDirEntries;
514:
515: bootSector->bsSectors =
516: (USHORT)( DiskExtension->DiskLength / DiskExtension->BytesPerSector );
517: bootSector->bsMedia = RAMDISK_MEDIA_TYPE;
518:
519: bootSector->bsSecPerClus = (UCHAR)sectorsPerCluster;
520:
521: //
522: // Calculate number of sectors required for FAT
523: //
524: fatEntries =
525: (bootSector->bsSectors - bootSector->bsResSectors -
526: bootSector->bsRootDirEnts / DIR_ENTRIES_PER_SECTOR) /
527: bootSector->bsSecPerClus + 2;
528:
529: //
530: // Choose between 12 and 16 bit FAT based on number of clusters we
531: // need to map
532: //
533: if (fatEntries > 4087)
534: {
535: fatType = 16;
536:
537: fatSectorCnt = (fatEntries * 2 + 511) / 512;
538:
539: fatEntries -= fatSectorCnt;
540:
541: fatSectorCnt = (fatEntries * 2 + 511) / 512;
542: }
543: else
544: {
545: fatType = 12;
546:
547: fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512;
548:
549: fatEntries -= fatSectorCnt;
550:
551: fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512;
552: }
553:
554: bootSector->bsFATsecs = fatSectorCnt;
555: bootSector->bsSecPerTrack = (USHORT)DiskExtension->SectorsPerTrack;
556: bootSector->bsHeads = (USHORT)DiskExtension->TracksPerCylinder;
557: bootSector->bsBootSignature = 0x29;
558: bootSector->bsVolumeID = 0x12345678;
559: strncpy(bootSector->bsLabel, "RamDisk ", 11);
560: strncpy(bootSector->bsFileSystemType, "FAT1? ", 8);
561: bootSector->bsFileSystemType[4] = ( fatType == 16 ) ? '6' : '2';
562:
563: bootSector->bsSig2[0] = 0x55;
564: bootSector->bsSig2[1] = 0xAA;
565:
566: //
567: // The FAT is located immediately following the boot sector.
568: //
569: firstFatSector = (PUCHAR)(bootSector + 1);
570: firstFatSector[0] = RAMDISK_MEDIA_TYPE;
571: firstFatSector[1] = 0xFF;
572: firstFatSector[2] = 0xFF;
573:
574: if (fatType == 16)
575: firstFatSector[3] = 0xFF;
576:
577: //
578: // The Root Directory follows the FAT
579: //
580: rootDir = (PDIR_ENTRY)(bootSector + 1 + fatSectorCnt);
581: strcpy(rootDir->deName, "MS-RAMDR");
582: strcpy(rootDir->deExtension, "IVE");
583: rootDir->deAttributes = DIR_ATTR_VOLUME;
584: }
585:
586: NTSTATUS
587: RamDiskCreateClose(
588: IN PDEVICE_OBJECT DeviceObject,
589: IN PIRP Irp
590: )
591: /*++
592:
593: Routine Description:
594:
595: This routine is called by the I/O system when the RamDisk is opened or
596: closed.
597:
598: No action is performed other than completing the request successfully.
599:
600: Arguments:
601:
602: DeviceObject - a pointer to the object that represents the device
603: that I/O is to be done on.
604:
605: Irp - a pointer to the I/O Request Packet for this request.
606:
607: Return Value:
608:
609: STATUS_INVALID_PARAMETER if parameters are invalid,
610: STATUS_SUCCESS otherwise.
611:
612: --*/
613:
614: {
615: Irp->IoStatus.Status = STATUS_SUCCESS;
616: Irp->IoStatus.Information = 0;
617:
618: IoCompleteRequest( Irp, IO_NO_INCREMENT );
619:
620: return STATUS_SUCCESS;
621: }
622:
623: NTSTATUS
624: RamDiskDeviceControl(
625: IN PDEVICE_OBJECT DeviceObject,
626: IN PIRP Irp
627: )
628:
629: /*++
630:
631: Routine Description:
632:
633: This routine is called by the I/O system to perform a device I/O
634: control function.
635:
636: Arguments:
637:
638: DeviceObject - a pointer to the object that represents the device
639: that I/O is to be done on.
640:
641: Irp - a pointer to the I/O Request Packet for this request.
642:
643: Return Value:
644:
645: STATUS_SUCCESS if recognized I/O control code,
646: STATUS_INVALID_DEVICE_REQUEST otherwise.
647:
648: --*/
649:
650: {
651: PRAMDISK_EXTENSION diskExtension;
652: PIO_STACK_LOCATION irpSp;
653: NTSTATUS ntStatus;
654:
655: //
656: // Set up necessary object and extension pointers.
657: //
658:
659: diskExtension = DeviceObject->DeviceExtension;
660: irpSp = IoGetCurrentIrpStackLocation( Irp );
661:
662: //
663: // Assume failure.
664: //
665:
666: Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
667:
668: //
669: // Determine which I/O control code was specified.
670: //
671:
672: switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
673: {
674:
675: case IOCTL_DISK_GET_MEDIA_TYPES:
676: case IOCTL_DISK_GET_DRIVE_GEOMETRY:
677: //
678: // Return the drive geometry for the ram disk. Note that
679: // we return values which were made up to suit the disk size.
680: //
681:
682: if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
683: sizeof( DISK_GEOMETRY ) )
684: {
685:
686: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
687:
688: }
689: else
690: {
691: PDISK_GEOMETRY outputBuffer;
692:
693: outputBuffer = ( PDISK_GEOMETRY ) Irp->AssociatedIrp.SystemBuffer;
694: outputBuffer->MediaType = RemovableMedia;
695: outputBuffer->Cylinders = RtlConvertUlongToLargeInteger(
696: diskExtension->NumberOfCylinders );
697: outputBuffer->TracksPerCylinder = diskExtension->TracksPerCylinder;
698: outputBuffer->SectorsPerTrack = diskExtension->SectorsPerTrack;
699: outputBuffer->BytesPerSector = diskExtension->BytesPerSector;
700:
701: Irp->IoStatus.Status = STATUS_SUCCESS;
702: Irp->IoStatus.Information = sizeof( DISK_GEOMETRY );
703: }
704: break;
705:
706: case IOCTL_DISK_GET_PARTITION_INFO:
707: //
708: // Return the information about the partition.
709: //
710:
711: if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( PARTITION_INFORMATION ) )
712: {
713: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
714: }
715: else
716: {
717: PPARTITION_INFORMATION outputBuffer;
718: PBOOT_SECTOR bootSector = (PBOOT_SECTOR) diskExtension->DiskImage;
719:
720: outputBuffer = ( PPARTITION_INFORMATION )Irp->AssociatedIrp.SystemBuffer;
721:
722: outputBuffer->PartitionType =
723: (bootSector->bsFileSystemType[4] == '6') ?
724: PARTITION_FAT_16 : PARTITION_FAT_12;
725:
726: outputBuffer->BootIndicator = FALSE;
727:
728: outputBuffer->RecognizedPartition = TRUE;
729:
730: outputBuffer->RewritePartition = FALSE;
731:
732: outputBuffer->StartingOffset = RtlConvertUlongToLargeInteger(0);
733:
734: outputBuffer->PartitionLength = RtlConvertUlongToLargeInteger(diskExtension->DiskLength);
735:
736: outputBuffer->HiddenSectors = RtlConvertUlongToLargeInteger(1);
737:
738: Irp->IoStatus.Status = STATUS_SUCCESS;
739: Irp->IoStatus.Information = sizeof( PARTITION_INFORMATION );
740: }
741: break;
742:
743:
744: case IOCTL_DISK_VERIFY:
745: {
746: //
747: // Move parameters from the VerifyInformation structure to
748: // the READ parameters area, so that we'll find them when
749: // we try to treat this like a READ.
750: //
751:
752: PVERIFY_INFORMATION verifyInformation;
753:
754: verifyInformation = Irp->AssociatedIrp.SystemBuffer;
755:
756: irpSp->Parameters.Read.ByteOffset.LowPart =
757: verifyInformation->StartingOffset.LowPart;
758: irpSp->Parameters.Read.ByteOffset.HighPart =
759: verifyInformation->StartingOffset.HighPart;
760: irpSp->Parameters.Read.Length = verifyInformation->Length;
761:
762: //
763: // A VERIFY is identical to a READ, except for the fact that no
764: // data gets transferred. So follow the READ code path.
765: //
766:
767: ntStatus = RamDiskReadWrite( DeviceObject, Irp );
768: }
769: return ntStatus;
770:
771: default:
772: //
773: // The specified I/O control code is unrecognized by this driver.
774: // The I/O status field in the IRP has already been set so just
775: // terminate the switch.
776: //
777:
778: RamDiskDump(
779: RAMDDIAG1,
780: ("RAMDISK: ERROR: unrecognized IOCTL %x\n",
781: irpSp->Parameters.DeviceIoControl.IoControlCode));
782:
783: break;
784: }
785:
786: //
787: // Finish the I/O operation by simply completing the packet and returning
788: // the same status as in the packet itself.
789: //
790:
791: ntStatus = Irp->IoStatus.Status;
792:
793: IoCompleteRequest( Irp, IO_NO_INCREMENT );
794:
795: return ntStatus;
796: }
797:
798: NTSTATUS
799: RamDiskReadWrite(
800: IN PDEVICE_OBJECT DeviceObject,
801: IN PIRP Irp
802: )
803: /*++
804:
805: Routine Description:
806:
807: This routine is called by the I/O system to read or write to a
808: device that we control. It can also be called by
809: RamDiskDispatchDeviceControl() to do a VERIFY.
810:
811: Arguments:
812:
813: DeviceObject - a pointer to the object that represents the device
814: that I/O is to be done on.
815:
816: Irp - a pointer to the I/O Request Packet for this request.
817:
818: Return Value:
819:
820: STATUS_INVALID_PARAMETER if parameters are invalid,
821: STATUS_SUCCESS otherwise.
822:
823: --*/
824:
825: {
826: PRAMDISK_EXTENSION diskExtension;
827: PIO_STACK_LOCATION irpSp;
828: PUCHAR CurrentAddress;
829:
830: //
831: // Set up necessary object and extension pointers.
832: //
833:
834: diskExtension = DeviceObject->DeviceExtension;
835:
836: irpSp = IoGetCurrentIrpStackLocation( Irp );
837:
838: //
839: // Check for invalid parameters. It is an error for the starting offset
840: // + length to go past the end of the buffer, or for the length to
841: // not be a proper multiple of the sector size.
842: //
843: // Others are possible, but we don't check them since we trust the
844: // file system and they aren't deadly.
845: //
846:
847: if (RtlLargeIntegerGreaterThan(
848: RtlLargeIntegerAdd(
849: irpSp->Parameters.Read.ByteOffset,
850: RtlConvertUlongToLargeInteger(irpSp->Parameters.Read.Length)),
851: RtlConvertUlongToLargeInteger(diskExtension->DiskLength)) ||
852: (irpSp->Parameters.Read.Length & (diskExtension->BytesPerSector - 1)))
853: {
854: //
855: // Do not give an I/O boost for parameter errors.
856: //
857:
858: RamDiskDump(
859: RAMDERRORS,
860: (
861: "RAMDISK: Error invalid parameter\n"
862: " ByteOffset: %x\n"
863: " Length: %d\n"
864: " Operation: %x\n",
865: Irp,
866: irpSp->Parameters.Read.ByteOffset,
867: irpSp->Parameters.Read.Length,
868: irpSp->MajorFunction
869: ));
870:
871: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
872: IoCompleteRequest( Irp, IO_NO_INCREMENT );
873:
874: return STATUS_INVALID_PARAMETER;
875: }
876:
877: //
878: // Get a system-space pointer to the user's buffer. A system
879: // address must be used because we may already have left the
880: // original caller's address space.
881: //
882:
883: if ( Irp->MdlAddress != NULL )
884: {
885: CurrentAddress = MmGetSystemAddressForMdl( Irp->MdlAddress );
886: }
887:
888: RamDiskDump(
889: RAMDDIAG2,
890: (
891: "RAMDISK: Irp of Request: %x\n"
892: " Vmem Address of Transfer: %x - %x\n"
893: " Length of Transfer: %d\n"
894: " Operation: %x\n"
895: " Starting ByteOffset: %x\n",
896: Irp,
897: CurrentAddress,
898: ((PUCHAR)CurrentAddress) + irpSp->Parameters.Read.Length,
899: irpSp->Parameters.Read.Length,
900: irpSp->MajorFunction,
901: irpSp->Parameters.Read.ByteOffset.LowPart
902: ));
903:
904: Irp->IoStatus.Information = irpSp->Parameters.Read.Length;
905:
906: switch (irpSp->MajorFunction)
907: {
908: case IRP_MJ_READ:
909: RtlMoveMemory(
910: CurrentAddress,
911: diskExtension->DiskImage + irpSp->Parameters.Read.ByteOffset.LowPart,
912: irpSp->Parameters.Read.Length);
913: break;
914:
915: case IRP_MJ_DEVICE_CONTROL:
916: //
917: // The only way we can get this major code is if the VERIFY
918: // ioctl called RamDiskDispatchReadWrite().
919: //
920: break;
921:
922: case IRP_MJ_WRITE:
923: RtlMoveMemory(
924: diskExtension->DiskImage + irpSp->Parameters.Read.ByteOffset.LowPart,
925: CurrentAddress, irpSp->Parameters.Read.Length);
926: break;
927:
928: default:
929: Irp->IoStatus.Information = 0;
930: break;
931: }
932:
933: Irp->IoStatus.Status = STATUS_SUCCESS;
934: IoCompleteRequest( Irp, IO_NO_INCREMENT );
935:
936: return STATUS_SUCCESS;
937: }
938:
939: VOID
940: RamDiskUnloadDriver(
941: IN PDRIVER_OBJECT DriverObject
942: )
943: /*++
944:
945: Routine Description:
946:
947: This routine is called by the I/O system to unload the driver.
948:
949: Any resources previously allocated must be freed.
950:
951: Arguments:
952:
953: DriverObject - a pointer to the object that represents our driver.
954:
955: Return Value:
956:
957: None
958: --*/
959:
960: {
961: PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
962:
963: if ( deviceObject != NULL )
964: {
965: PRAMDISK_EXTENSION diskExtension = deviceObject->DeviceExtension;
966:
967: if (diskExtension != NULL)
968: {
969: if (diskExtension->DiskImage != NULL)
970: {
971: ExFreePool( diskExtension->DiskImage );
972: }
973: if (diskExtension->Win32NameString.Buffer != NULL)
974: {
975: IoDeleteSymbolicLink( &diskExtension->Win32NameString );
976:
977: ExFreePool( diskExtension->Win32NameString.Buffer );
978: }
979: }
980: IoDeleteDevice( deviceObject );
981: }
982: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.