Annotation of q_a/samples/ddk/ramdisk/ramdisk.c, revision 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.