Annotation of q_a/samples/ddk/ramdisk/ramdisk.c, revision 1.1.1.1

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:             &paramPath.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(&paramTable[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, &paramTable[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, &paramPath);
                    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(&paramTable[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, &paramTable[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(&paramTable[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 = &sectorsPerCluster;
                    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, &paramTable[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: }

unix.superglobalmegacorp.com

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