mirror of
https://github.com/reactos/reactos.git
synced 2024-12-19 00:53:33 +08:00
228 lines
6.7 KiB
C
228 lines
6.7 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS File System Recognizer
|
|
* FILE: drivers/filesystems/fs_rec/blockdev.c
|
|
* PURPOSE: Generic Helper Functions
|
|
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
|
|
* Eric Kohl
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include "fs_rec.h"
|
|
|
|
#include <ntdddisk.h>
|
|
#include <ntddcdrm.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
FsRecGetDeviceSectors(IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONG SectorSize,
|
|
OUT PLARGE_INTEGER SectorCount)
|
|
{
|
|
PARTITION_INFORMATION PartitionInfo;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
KEVENT Event;
|
|
PIRP Irp;
|
|
NTSTATUS Status;
|
|
ULONG Remainder;
|
|
PAGED_CODE();
|
|
|
|
/* Only needed for disks */
|
|
if (DeviceObject->DeviceType != FILE_DEVICE_DISK) return FALSE;
|
|
|
|
/* Build the information IRP */
|
|
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
|
Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO,
|
|
DeviceObject,
|
|
NULL,
|
|
0,
|
|
&PartitionInfo,
|
|
sizeof(PARTITION_INFORMATION),
|
|
FALSE,
|
|
&Event,
|
|
&IoStatusBlock);
|
|
if (!Irp) return FALSE;
|
|
|
|
/* Override verification */
|
|
IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
|
|
|
|
/* Do the request */
|
|
Status = IoCallDriver(DeviceObject, Irp);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
/* Wait for completion */
|
|
KeWaitForSingleObject(&Event,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
|
|
/* Fail if we couldn't get the data */
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
|
|
|
/* Otherwise, return the number of sectors */
|
|
*SectorCount = RtlExtendedLargeIntegerDivide(PartitionInfo.PartitionLength,
|
|
SectorSize,
|
|
&Remainder);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
FsRecGetDeviceSectorSize(IN PDEVICE_OBJECT DeviceObject,
|
|
OUT PULONG SectorSize)
|
|
{
|
|
DISK_GEOMETRY DiskGeometry;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
KEVENT Event;
|
|
PIRP Irp;
|
|
NTSTATUS Status;
|
|
ULONG ControlCode;
|
|
PAGED_CODE();
|
|
|
|
/* Check what device we have */
|
|
switch (DeviceObject->DeviceType)
|
|
{
|
|
case FILE_DEVICE_CD_ROM:
|
|
|
|
/* Use the CD IOCTL */
|
|
ControlCode = IOCTL_CDROM_GET_DRIVE_GEOMETRY;
|
|
break;
|
|
|
|
case FILE_DEVICE_DISK:
|
|
|
|
/* Use the Disk IOCTL */
|
|
ControlCode = IOCTL_DISK_GET_DRIVE_GEOMETRY;
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Invalid device type */
|
|
return FALSE;
|
|
}
|
|
|
|
/* Build the information IRP */
|
|
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
|
Irp = IoBuildDeviceIoControlRequest(ControlCode,
|
|
DeviceObject,
|
|
NULL,
|
|
0,
|
|
&DiskGeometry,
|
|
sizeof(DISK_GEOMETRY),
|
|
FALSE,
|
|
&Event,
|
|
&IoStatusBlock);
|
|
if (!Irp) return FALSE;
|
|
|
|
/* Override verification */
|
|
IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
|
|
|
|
/* Do the request */
|
|
Status = IoCallDriver(DeviceObject, Irp);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
/* Wait for completion */
|
|
KeWaitForSingleObject(&Event,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
|
|
/* Fail if we couldn't get the data */
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
|
|
|
/* Return the sector size if it's valid */
|
|
if (!DiskGeometry.BytesPerSector) return FALSE;
|
|
*SectorSize = DiskGeometry.BytesPerSector;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
FsRecReadBlock(IN PDEVICE_OBJECT DeviceObject,
|
|
IN PLARGE_INTEGER Offset,
|
|
IN ULONG Length,
|
|
IN ULONG SectorSize,
|
|
IN OUT PVOID *Buffer,
|
|
OUT PBOOLEAN DeviceError OPTIONAL)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
KEVENT Event;
|
|
PIRP Irp;
|
|
NTSTATUS Status;
|
|
PAGED_CODE();
|
|
|
|
/* Assume failure */
|
|
if (DeviceError) *DeviceError = FALSE;
|
|
|
|
/* Check if the caller requested too little */
|
|
if (Length < SectorSize)
|
|
{
|
|
/* Read at least the sector size */
|
|
Length = SectorSize;
|
|
}
|
|
else
|
|
{
|
|
/* Otherwise, just round up the request to sector size */
|
|
Length = ROUND_UP(Length, SectorSize);
|
|
}
|
|
|
|
/* Check if the caller gave us a buffer */
|
|
if (!*Buffer)
|
|
{
|
|
/* He didn't, allocate one */
|
|
*Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
ROUND_TO_PAGES(Length),
|
|
FSREC_TAG);
|
|
if (!*Buffer) return FALSE;
|
|
}
|
|
|
|
/* Build the IRP */
|
|
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
|
|
DeviceObject,
|
|
*Buffer,
|
|
Length,
|
|
Offset,
|
|
&Event,
|
|
&IoStatusBlock);
|
|
if (!Irp) return FALSE;
|
|
|
|
/* Override verification */
|
|
IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
|
|
|
|
/* Do the request */
|
|
Status = IoCallDriver(DeviceObject, Irp);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
/* Wait for completion */
|
|
KeWaitForSingleObject(&Event,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
|
|
/* Check if we couldn't get the data */
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Check if caller wanted to know about the device and fail */
|
|
if (DeviceError) *DeviceError = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/* All went well */
|
|
return TRUE;
|
|
}
|