📄 ramdisk.c
字号:
~ ( DIR_ENTRIES_PER_SECTOR - 1 );
}
//
// We need to have the 0xeb and 0x90 since this is one of the
// checks the file system recognizer uses
//
bootSector->bsJump[0] = 0xeb;
bootSector->bsJump[1] = 0x3c;
bootSector->bsJump[2] = 0x90;
strncpy(bootSector->bsOemName, "RobertN ", 8);
bootSector->bsBytesPerSec = (SHORT)DiskExtension->BytesPerSector;
bootSector->bsResSectors = 1;
bootSector->bsFATs = 1;
bootSector->bsRootDirEnts = (USHORT)rootDirEntries;
bootSector->bsSectors =
(USHORT)( DiskExtension->DiskLength / DiskExtension->BytesPerSector );
bootSector->bsMedia = RAMDISK_MEDIA_TYPE;
bootSector->bsSecPerClus = (UCHAR)sectorsPerCluster;
//
// Calculate number of sectors required for FAT
//
fatEntries =
(bootSector->bsSectors - bootSector->bsResSectors -
bootSector->bsRootDirEnts / DIR_ENTRIES_PER_SECTOR) /
bootSector->bsSecPerClus + 2;
//
// Choose between 12 and 16 bit FAT based on number of clusters we
// need to map
//
if (fatEntries > 4087)
{
fatType = 16;
fatSectorCnt = (fatEntries * 2 + 511) / 512;
fatEntries -= fatSectorCnt;
fatSectorCnt = (fatEntries * 2 + 511) / 512;
}
else
{
fatType = 12;
fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512;
fatEntries -= fatSectorCnt;
fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512;
}
bootSector->bsFATsecs = fatSectorCnt;
bootSector->bsSecPerTrack = (USHORT)DiskExtension->SectorsPerTrack;
bootSector->bsHeads = (USHORT)DiskExtension->TracksPerCylinder;
bootSector->bsBootSignature = 0x29;
bootSector->bsVolumeID = 0x12345678;
strncpy(bootSector->bsLabel, "RamDisk ", 11);
strncpy(bootSector->bsFileSystemType, "FAT1? ", 8);
bootSector->bsFileSystemType[4] = ( fatType == 16 ) ? '6' : '2';
bootSector->bsSig2[0] = 0x55;
bootSector->bsSig2[1] = 0xAA;
BOUNDS_CHECKER(GENERIC_1, (bootSector,
"RamDiskFormatFat pObject:bootSector Ulong1:FatType ULong2:fatEntries",
fatType, fatEntries));
//
// The FAT is located immediately following the boot sector.
//
firstFatSector = (PUCHAR)(bootSector + 1);
firstFatSector[0] = RAMDISK_MEDIA_TYPE;
firstFatSector[1] = 0xFF;
firstFatSector[2] = 0xFF;
if (fatType == 16)
firstFatSector[3] = 0xFF;
//
// The Root Directory follows the FAT
//
rootDir = (PDIR_ENTRY)(bootSector + 1 + fatSectorCnt);
strcpy(rootDir->deName, "MS-RAMDR");
strcpy(rootDir->deExtension, "IVE");
rootDir->deAttributes = DIR_ATTR_VOLUME;
}
NTSTATUS
RamDiskCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called by the I/O system when the RamDisk is opened or
closed.
No action is performed other than completing the request successfully.
Arguments:
DeviceObject - a pointer to the object that represents the device
that I/O is to be done on.
Irp - a pointer to the I/O Request Packet for this request.
Return Value:
STATUS_INVALID_PARAMETER if parameters are invalid,
STATUS_SUCCESS otherwise.
--*/
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
BOUNDS_CHECKER(GENERIC_1, (NULL,
"RamDiskCreateClose called",
0, 0));
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
NTSTATUS
RamDiskDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called by the I/O system to perform a device I/O
control function.
Arguments:
DeviceObject - a pointer to the object that represents the device
that I/O is to be done on.
Irp - a pointer to the I/O Request Packet for this request.
Return Value:
STATUS_SUCCESS if recognized I/O control code,
STATUS_INVALID_DEVICE_REQUEST otherwise.
--*/
{
PRAMDISK_EXTENSION diskExtension;
PIO_STACK_LOCATION irpSp;
NTSTATUS ntStatus;
//
// Set up necessary object and extension pointers.
//
diskExtension = DeviceObject->DeviceExtension;
irpSp = IoGetCurrentIrpStackLocation( Irp );
//
// Assume failure.
//
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
//
// Determine which I/O control code was specified.
//
BOUNDS_CHECKER(GENERIC_1, (NULL,
"DeviceControl called ULong1 = I/O control code",
irpSp->Parameters.DeviceIoControl.IoControlCode, 0));
switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
{
case IOCTL_DISK_GET_MEDIA_TYPES:
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
//
// Return the drive geometry for the ram disk. Note that
// we return values which were made up to suit the disk size.
//
if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof( DISK_GEOMETRY ) )
{
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
else
{
PDISK_GEOMETRY outputBuffer;
outputBuffer = ( PDISK_GEOMETRY ) Irp->AssociatedIrp.SystemBuffer;
outputBuffer->MediaType = RemovableMedia;
outputBuffer->Cylinders = RtlConvertUlongToLargeInteger(
diskExtension->NumberOfCylinders );
outputBuffer->TracksPerCylinder = diskExtension->TracksPerCylinder;
outputBuffer->SectorsPerTrack = diskExtension->SectorsPerTrack;
outputBuffer->BytesPerSector = diskExtension->BytesPerSector;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof( DISK_GEOMETRY );
}
break;
case IOCTL_DISK_GET_PARTITION_INFO:
//
// Return the information about the partition.
//
if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( PARTITION_INFORMATION ) )
{
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
else
{
PPARTITION_INFORMATION outputBuffer;
PBOOT_SECTOR bootSector = (PBOOT_SECTOR) diskExtension->DiskImage;
outputBuffer = ( PPARTITION_INFORMATION )Irp->AssociatedIrp.SystemBuffer;
outputBuffer->PartitionType =
(bootSector->bsFileSystemType[4] == '6') ?
PARTITION_FAT_16 : PARTITION_FAT_12;
outputBuffer->BootIndicator = FALSE;
outputBuffer->RecognizedPartition = TRUE;
outputBuffer->RewritePartition = FALSE;
outputBuffer->StartingOffset = RtlConvertUlongToLargeInteger(0);
outputBuffer->PartitionLength = RtlConvertUlongToLargeInteger(diskExtension->DiskLength);
outputBuffer->HiddenSectors = 1L;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof( PARTITION_INFORMATION );
}
break;
case IOCTL_DISK_VERIFY:
{
//
// Move parameters from the VerifyInformation structure to
// the READ parameters area, so that we'll find them when
// we try to treat this like a READ.
//
PVERIFY_INFORMATION verifyInformation;
verifyInformation = Irp->AssociatedIrp.SystemBuffer;
irpSp->Parameters.Read.ByteOffset.LowPart =
verifyInformation->StartingOffset.LowPart;
irpSp->Parameters.Read.ByteOffset.HighPart =
verifyInformation->StartingOffset.HighPart;
irpSp->Parameters.Read.Length = verifyInformation->Length;
//
// A VERIFY is identical to a READ, except for the fact that no
// data gets transferred. So follow the READ code path.
//
ntStatus = RamDiskReadWrite( DeviceObject, Irp );
}
return ntStatus;
default:
//
// The specified I/O control code is unrecognized by this driver.
// The I/O status field in the IRP has already been set so just
// terminate the switch.
//
RamDiskDump(
RAMDDIAG1,
("RAMDISK: ERROR: unrecognized IOCTL %x\n",
irpSp->Parameters.DeviceIoControl.IoControlCode));
break;
}
//
// Finish the I/O operation by simply completing the packet and returning
// the same status as in the packet itself.
//
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
BOUNDS_CHECKER(GENERIC_1, (NULL,
"Exiting DeviceControl ULong1 = status",
ntStatus, 0));
return ntStatus;
}
NTSTATUS
RamDiskReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called by the I/O system to read or write to a
device that we control. It can also be called by
RamDiskDispatchDeviceControl() to do a VERIFY.
Arguments:
DeviceObject - a pointer to the object that represents the device
that I/O is to be done on.
Irp - a pointer to the I/O Request Packet for this request.
Return Value:
STATUS_INVALID_PARAMETER if parameters are invalid,
STATUS_SUCCESS otherwise.
--*/
{
PRAMDISK_EXTENSION diskExtension;
PIO_STACK_LOCATION irpSp;
PUCHAR CurrentAddress;
//
// Set up necessary object and extension pointers.
//
diskExtension = DeviceObject->DeviceExtension;
irpSp = IoGetCurrentIrpStackLocation( Irp );
//
// Check for invalid parameters. It is an error for the starting offset
// + length to go past the end of the buffer, or for the length to
// not be a proper multiple of the sector size.
//
// Others are possible, but we don't check them since we trust the
// file system and they aren't deadly.
//
if (RtlLargeIntegerGreaterThan(
RtlLargeIntegerAdd(
irpSp->Parameters.Read.ByteOffset,
RtlConvertUlongToLargeInteger(irpSp->Parameters.Read.Length)),
RtlConvertUlongToLargeInteger(diskExtension->DiskLength)) ||
(irpSp->Parameters.Read.Length & (diskExtension->BytesPerSector - 1)))
{
//
// Do not give an I/O boost for parameter errors.
//
RamDiskDump(
RAMDERRORS,
(
"RAMDISK: Error invalid parameter\n"
" ByteOffset: %x\n"
" Length: %d\n"
" Operation: %x\n",
Irp,
irpSp->Parameters.Read.ByteOffset,
irpSp->Parameters.Read.Length,
irpSp->MajorFunction
));
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_INVALID_PARAMETER;
}
//
// Get a system-space pointer to the user's buffer. A system
// address must be used because we may already have left the
// original caller's address space.
//
if ( Irp->MdlAddress != NULL )
{
CurrentAddress = MmGetSystemAddressForMdl( Irp->MdlAddress );
}
else
{
//
// Strictly speaking this isn't necessary, the only time we
// won't have an MDL is if we're processing IOCTL_DISK_VERIFY.
// In which case, we don't reference CurrentAddress. But at
// least this should keep the compiler from warning us.
CurrentAddress = 0;
}
RamDiskDump(
RAMDDIAG2,
(
"RAMDISK: Irp of Request: %x\n"
" Vmem Address of Transfer: %x - %x\n"
" Length of Transfer: %d\n"
" Operation: %x\n"
" Starting ByteOffset: %x\n",
Irp,
CurrentAddress,
((PUCHAR)CurrentAddress) + irpSp->Parameters.Read.Length,
irpSp->Parameters.Read.Length,
irpSp->MajorFunction,
irpSp->Parameters.Read.ByteOffset.LowPart
));
Irp->IoStatus.Information = irpSp->Parameters.Read.Length;
switch (irpSp->MajorFunction)
{
case IRP_MJ_READ:
RtlMoveMemory(
CurrentAddress,
diskExtension->DiskImage + irpSp->Parameters.Read.ByteOffset.LowPart,
irpSp->Parameters.Read.Length);
break;
case IRP_MJ_DEVICE_CONTROL:
//
// The only way we can get this major code is if the VERIFY
// ioctl called RamDiskDispatchReadWrite().
//
break;
case IRP_MJ_WRITE:
RtlMoveMemory(
diskExtension->DiskImage + irpSp->Parameters.Read.ByteOffset.LowPart,
CurrentAddress, irpSp->Parameters.Read.Length);
break;
default:
Irp->IoStatus.Information = 0;
break;
}
BOUNDS_CHECKER(GENERIC_1, (NULL,
"RamDiskReadWrite ULong1 = Major job",
irpSp->MajorFunction, 0));
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
VOID
RamDiskUnloadDriver(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
This routine is called by the I/O system to unload the driver.
Any resources previously allocated must be freed.
Arguments:
DriverObject - a pointer to the object that represents our driver.
Return Value:
None
--*/
{
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
if ( deviceObject != NULL )
{
PRAMDISK_EXTENSION diskExtension = deviceObject->DeviceExtension;
if (diskExtension != NULL)
{
if (diskExtension->DiskImage != NULL)
{
ExFreePool( diskExtension->DiskImage );
}
if (diskExtension->Win32NameString.Buffer != NULL)
{
IoDeleteSymbolicLink( &diskExtension->Win32NameString );
ExFreePool( diskExtension->Win32NameString.Buffer );
}
}
IoDeleteDevice( deviceObject );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -