📄 ramdisk.c
字号:
DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("Output buffer too small... \n" ) );
status = STATUS_BUFFER_TOO_SMALL; // Inform the caller we need bigger buffer
information = sizeof(PARTITION_INFORMATION);
} else {
PPARTITION_INFORMATION outputBuffer;
PBOOT_SECTOR bootSector = (PBOOT_SECTOR) devExt->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(devExt->DiskRegInfo.DiskSize);
outputBuffer->HiddenSectors = (ULONG) (1L);
outputBuffer->PartitionNumber = (ULONG) (-1L);
status = STATUS_SUCCESS;
information = sizeof( PARTITION_INFORMATION );
}
break;
}
case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_GET_DRIVE_GEOMETRY \n" ) );
//
// Return the drive geometry for the ram disk. Note that
// we return values which were made up to suit the disk size.
//
if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof( DISK_GEOMETRY ) )
{
//
// Instead of returning STATUS_INVALID_PARAMETER, we will return
// STATUS_BUFFER_TOO_SMALL and the required buffer size.
// So that the called will send a bigger buffer
//
status = STATUS_BUFFER_TOO_SMALL; // Inform the caller we need bigger buffer
information = sizeof(PARTITION_INFORMATION);
}
else
{
PDISK_GEOMETRY outputBuffer;
outputBuffer = ( PDISK_GEOMETRY ) Irp->AssociatedIrp.SystemBuffer;
RtlCopyMemory( outputBuffer, &(devExt->DiskGeometry), sizeof(DISK_GEOMETRY) );
status = STATUS_SUCCESS;
information = sizeof( DISK_GEOMETRY );
}
break;
}
case IOCTL_DISK_CHECK_VERIFY: {
DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_CHECK_VERIFY \n" ) );
//
// Return status success
//
status = STATUS_SUCCESS;
break;
}
case IOCTL_DISK_IS_WRITABLE: {
DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_IS_WRITABLE \n" ) );
//
// Return status success
//
status = STATUS_SUCCESS;
break;
}
default: {
//
// Received not supported IOCTLs, fail them
DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("Unknown IOCTL command %X\n", command ) );
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
} // end switch
COMPLETE_REQUEST( Irp, status, information );
IoReleaseRemoveLock(&devExt->RemoveLock, Irp);
DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_VERBOSE, ("IOCtl- OUT \n" ) );
return status;
} // End of RamDiskIOCtl()
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 based on the request
--*/
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status;
ULONG information = 0;
PUCHAR currentAddress;
PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
DBGPRINT( DBG_COMP_READ, DBG_LEVEL_VERBOSE, ("ReadWrite - IN \n" ) );
if ( devExt->DevState != WORKING ) {
//
// Device is not yet started or being removed, reject any IO request
// TODO: Queue the IRPs
DBGPRINT( DBG_COMP_READ, DBG_LEVEL_WARN, ("Device not ready\n" ) );
status = STATUS_INVALID_DEVICE_STATE;
COMPLETE_REQUEST( Irp, status, information );
}
status = IoAcquireRemoveLock(&devExt->RemoveLock, Irp);
if (!NT_SUCCESS(status)) {
DBGPRINT( DBG_COMP_PNP, DBG_LEVEL_ERROR, ("Acquire RemoveLock failed\n" ) );
COMPLETE_REQUEST( Irp, status, 0 );
return status;
}
irpStack = 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
//
if (RtlLargeIntegerGreaterThan(
RtlLargeIntegerAdd(
irpStack->Parameters.Read.ByteOffset,
RtlConvertUlongToLargeInteger(irpStack->Parameters.Read.Length)),
RtlConvertUlongToLargeInteger(devExt->DiskRegInfo.DiskSize)) ||
(irpStack->Parameters.Read.Length & (devExt->DiskGeometry.BytesPerSector - 1))) {
//
// Do not give an I/O boost for parameter errors.
//
DBGPRINT( DBG_COMP_READ, DBG_LEVEL_ERROR,
(
"Error invalid parameter\n"
"ByteOffset: %x\n"
"Length: %d\n"
"Operation: %x\n",
irpStack->Parameters.Read.ByteOffset,
irpStack->Parameters.Read.Length,
irpStack->MajorFunction
));
status = STATUS_INVALID_PARAMETER;
COMPLETE_REQUEST( Irp, status, information );
IoReleaseRemoveLock(&devExt->RemoveLock, Irp);
return status;
}
//
// 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.
//
ASSERT ( Irp->MdlAddress != NULL );
currentAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
//
// The mapping request can fail if system is very low on resources.
// Check for NULL and return approriate error status if the mapping failed
//
if ( currentAddress == NULL ) {
status = STATUS_INSUFFICIENT_RESOURCES;
COMPLETE_REQUEST( Irp, status, information );
IoReleaseRemoveLock(&devExt->RemoveLock, Irp);
DBGPRINT( DBG_COMP_READ, DBG_LEVEL_ERROR, ("Unable to get the system-space virtual address\n" ) );
return status;
}
DBGPRINT( DBG_COMP_READ, DBG_LEVEL_VERBOSE,
(
"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) + irpStack->Parameters.Read.Length,
irpStack->Parameters.Read.Length,
irpStack->MajorFunction,
irpStack->Parameters.Read.ByteOffset.LowPart
));
information = irpStack->Parameters.Read.Length;
switch (irpStack->MajorFunction) {
case IRP_MJ_READ:
RtlMoveMemory(
currentAddress,
devExt->DiskImage + irpStack->Parameters.Read.ByteOffset.LowPart,
irpStack->Parameters.Read.Length);
break;
case IRP_MJ_WRITE:
RtlMoveMemory(
devExt->DiskImage + irpStack->Parameters.Read.ByteOffset.LowPart,
currentAddress, irpStack->Parameters.Read.Length);
break;
default:
information = 0;
break;
}
status = STATUS_SUCCESS;
COMPLETE_REQUEST( Irp, status, information );
IoReleaseRemoveLock(&devExt->RemoveLock, Irp);
DBGPRINT( DBG_COMP_READ, DBG_LEVEL_VERBOSE, ("ReadWrite - OUT \n" ) );
return status;
} // End of RamDiskReadWrite()
#if DBG
VOID
RamDiskQueryDebugRegParameters(
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This routine is called from the DriverEntry to get the debug
parameters from the registry. If the registry query fails, then
default values are used.
Arguments:
RegistryPath - Points the service path to get the registry parameters
Return Value:
None
--*/
{
RTL_QUERY_REGISTRY_TABLE rtlQueryRegTbl[ 4 + 1 ]; // Need 1 for NULL
NTSTATUS status;
DEBUG_INFO defDebugRegInfo;
PAGED_CODE();
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE, ("QueryDebugRegParameters\n" ) );
ASSERT( RegistryPath->Buffer != NULL );
// Set the default values
defDebugRegInfo.BreakOnEntry = DEFAULT_BREAK_ON_ENTRY;
defDebugRegInfo.DebugLevel = DEFAULT_DEBUG_LEVEL;
defDebugRegInfo.DebugComp = DEFAULT_DEBUG_COMP;
RtlZeroMemory( rtlQueryRegTbl, sizeof(rtlQueryRegTbl) );
//
// Setup the query table
//
rtlQueryRegTbl[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
rtlQueryRegTbl[0].Name = L"Parameters";
rtlQueryRegTbl[0].EntryContext = NULL;
rtlQueryRegTbl[0].DefaultType = (ULONG)NULL;
rtlQueryRegTbl[0].DefaultData = NULL;
rtlQueryRegTbl[0].DefaultLength = (ULONG)NULL;
//
// Debug paramters
//
rtlQueryRegTbl[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
rtlQueryRegTbl[1].Name = L"BreakOnEntry";
rtlQueryRegTbl[1].EntryContext = &BreakOnEntry;
rtlQueryRegTbl[1].DefaultType = REG_DWORD;
rtlQueryRegTbl[1].DefaultData = &defDebugRegInfo.BreakOnEntry;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -