/drivers/storage/class/disk_new/disk.c
C | 6576 lines | 4179 code | 1244 blank | 1153 comment | 367 complexity | 601a640d9c1f54fbaf8ffc56b7fbc3d7 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-3.0, CC-BY-SA-3.0, AGPL-3.0, GPL-3.0, CPL-1.0
Large files files are truncated, but you can click here to view the full file
- /*++
- Copyright (C) Microsoft Corporation, 1991 - 1999
- Module Name:
- disk.c
- Abstract:
- SCSI disk class driver
- Environment:
- kernel mode only
- Notes:
- Revision History:
- --*/
- #include "disk.h"
- //
- // Now instantiate the GUIDs
- //
- #include "initguid.h"
- #include "ntddstor.h"
- #include "ioevent.h"
- NTSTATUS
- DiskDetermineMediaTypes(
- IN PDEVICE_OBJECT Fdo,
- IN PIRP Irp,
- IN UCHAR MediumType,
- IN UCHAR DensityCode,
- IN BOOLEAN MediaPresent,
- IN BOOLEAN IsWritable
- );
- PPARTITION_INFORMATION_EX
- DiskPdoFindPartitionEntry(
- IN PPHYSICAL_DEVICE_EXTENSION Pdo,
- IN PDRIVE_LAYOUT_INFORMATION_EX LayoutInfo
- );
- PPARTITION_INFORMATION_EX
- DiskFindAdjacentPartition(
- IN PDRIVE_LAYOUT_INFORMATION_EX LayoutInfo,
- IN PPARTITION_INFORMATION_EX BasePartition
- );
- PPARTITION_INFORMATION_EX
- DiskFindContainingPartition(
- IN PDRIVE_LAYOUT_INFORMATION_EX LayoutInfo,
- IN PPARTITION_INFORMATION_EX BasePartition,
- IN BOOLEAN SearchTopToBottom
- );
- NTSTATUS
- DiskIoctlCreateDisk(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlGetDriveLayout(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlGetDriveLayoutEx(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlSetDriveLayout(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlSetDriveLayoutEx(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlGetPartitionInfo(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlGetPartitionInfoEx(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlGetLengthInfo(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlSetPartitionInfo(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlSetPartitionInfoEx(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlSetPartitionInfoEx(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- NTSTATUS
- DiskIoctlGetDriveGeometryEx(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- );
- #ifdef ALLOC_PRAGMA
- #pragma alloc_text(INIT, DriverEntry)
- #pragma alloc_text(PAGE, DiskUnload)
- #pragma alloc_text(PAGE, DiskCreateFdo)
- #pragma alloc_text(PAGE, DiskDetermineMediaTypes)
- #pragma alloc_text(PAGE, DiskModeSelect)
- #pragma alloc_text(PAGE, DisableWriteCache)
- #pragma alloc_text(PAGE, DiskIoctlVerify)
- #pragma alloc_text(PAGE, DiskSetSpecialHacks)
- #pragma alloc_text(PAGE, DiskScanRegistryForSpecial)
- #pragma alloc_text(PAGE, DiskQueryPnpCapabilities)
- #pragma alloc_text(PAGE, DiskGetCacheInformation)
- #pragma alloc_text(PAGE, DiskSetCacheInformation)
- #pragma alloc_text(PAGE, DiskSetInfoExceptionInformation)
- #pragma alloc_text(PAGE, DiskGetInfoExceptionInformation)
- #pragma alloc_text(PAGE, DiskPdoFindPartitionEntry)
- #pragma alloc_text(PAGE, DiskFindAdjacentPartition)
- #pragma alloc_text(PAGE, DiskFindContainingPartition)
- #pragma alloc_text(PAGE, DiskIoctlCreateDisk)
- #pragma alloc_text(PAGE, DiskIoctlGetDriveLayout)
- #pragma alloc_text(PAGE, DiskIoctlGetDriveLayoutEx)
- #pragma alloc_text(PAGE, DiskIoctlSetDriveLayout)
- #pragma alloc_text(PAGE, DiskIoctlSetDriveLayoutEx)
- #pragma alloc_text(PAGE, DiskIoctlGetPartitionInfo)
- #pragma alloc_text(PAGE, DiskIoctlGetPartitionInfoEx)
- #pragma alloc_text(PAGE, DiskIoctlGetLengthInfo)
- #pragma alloc_text(PAGE, DiskIoctlSetPartitionInfo)
- #pragma alloc_text(PAGE, DiskIoctlSetPartitionInfoEx)
- #pragma alloc_text(PAGE, DiskIoctlGetDriveGeometryEx)
- #endif
- extern ULONG DiskDisableGpt;
- const GUID GUID_NULL = { 0 };
- #define DiskCompareGuid(_First,_Second) \
- (memcmp ((_First),(_Second), sizeof (GUID)))
- NTSTATUS
- NTAPI
- DriverEntry(
- IN PDRIVER_OBJECT DriverObject,
- IN PUNICODE_STRING RegistryPath
- )
- /*++
- Routine Description:
- This routine initializes the SCSI hard disk class driver.
- Arguments:
- DriverObject - Pointer to driver object created by system.
- RegistryPath - Pointer to the name of the services node for this driver.
- Return Value:
- The function value is the final status from the initialization operation.
- --*/
- {
- CLASS_INIT_DATA InitializationData;
- CLASS_QUERY_WMI_REGINFO_EX_LIST classQueryWmiRegInfoExList;
- GUID guidQueryRegInfoEx = GUID_CLASSPNP_QUERY_REGINFOEX;
- NTSTATUS status;
- #if defined(_X86_)
- //
- // Read the information NtDetect squirreled away about the disks in this
- // system.
- //
- status = DiskSaveDetectInfo(DriverObject);
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "Disk: couldn't save NtDetect information (%#08lx)\n",
- status));
- }
- #endif
- //
- // Zero InitData
- //
- RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA));
- InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
- //
- // Setup sizes and entry points for functional device objects
- //
- InitializationData.FdoData.DeviceExtensionSize = FUNCTIONAL_EXTENSION_SIZE;
- InitializationData.FdoData.DeviceType = FILE_DEVICE_DISK;
- InitializationData.FdoData.DeviceCharacteristics = FILE_DEVICE_SECURE_OPEN;
- InitializationData.FdoData.ClassInitDevice = DiskInitFdo;
- InitializationData.FdoData.ClassStartDevice = DiskStartFdo;
- InitializationData.FdoData.ClassStopDevice = DiskStopDevice;
- InitializationData.FdoData.ClassRemoveDevice = DiskRemoveDevice;
- InitializationData.FdoData.ClassPowerDevice = ClassSpinDownPowerHandler;
- InitializationData.FdoData.ClassError = DiskFdoProcessError;
- InitializationData.FdoData.ClassReadWriteVerification = DiskReadWriteVerification;
- InitializationData.FdoData.ClassDeviceControl = DiskDeviceControl;
- InitializationData.FdoData.ClassShutdownFlush = DiskShutdownFlush;
- InitializationData.FdoData.ClassCreateClose = NULL;
- //
- // Setup sizes and entry points for physical device objects
- //
- InitializationData.PdoData.DeviceExtensionSize = PHYSICAL_EXTENSION_SIZE;
- InitializationData.PdoData.DeviceType = FILE_DEVICE_DISK;
- InitializationData.PdoData.DeviceCharacteristics = FILE_DEVICE_SECURE_OPEN;
- InitializationData.PdoData.ClassInitDevice = DiskInitPdo;
- InitializationData.PdoData.ClassStartDevice = DiskStartPdo;
- InitializationData.PdoData.ClassStopDevice = DiskStopDevice;
- InitializationData.PdoData.ClassRemoveDevice = DiskRemoveDevice;
- //
- // Use default power routine for PDOs
- //
- InitializationData.PdoData.ClassPowerDevice = NULL;
- InitializationData.PdoData.ClassError = NULL;
- InitializationData.PdoData.ClassReadWriteVerification = DiskReadWriteVerification;
- InitializationData.PdoData.ClassDeviceControl = DiskDeviceControl;
- InitializationData.PdoData.ClassShutdownFlush = DiskShutdownFlush;
- InitializationData.PdoData.ClassCreateClose = NULL;
- InitializationData.PdoData.ClassDeviceControl = DiskDeviceControl;
- InitializationData.PdoData.ClassQueryPnpCapabilities = DiskQueryPnpCapabilities;
- InitializationData.ClassAddDevice = DiskAddDevice;
- InitializationData.ClassEnumerateDevice = DiskEnumerateDevice;
- InitializationData.ClassQueryId = DiskQueryId;
- InitializationData.FdoData.ClassWmiInfo.GuidCount = 7;
- InitializationData.FdoData.ClassWmiInfo.GuidRegInfo = DiskWmiFdoGuidList;
- InitializationData.FdoData.ClassWmiInfo.ClassQueryWmiRegInfo = DiskFdoQueryWmiRegInfo;
- InitializationData.FdoData.ClassWmiInfo.ClassQueryWmiDataBlock = DiskFdoQueryWmiDataBlock;
- InitializationData.FdoData.ClassWmiInfo.ClassSetWmiDataBlock = DiskFdoSetWmiDataBlock;
- InitializationData.FdoData.ClassWmiInfo.ClassSetWmiDataItem = DiskFdoSetWmiDataItem;
- InitializationData.FdoData.ClassWmiInfo.ClassExecuteWmiMethod = DiskFdoExecuteWmiMethod;
- InitializationData.FdoData.ClassWmiInfo.ClassWmiFunctionControl = DiskWmiFunctionControl;
- #if 0
- //
- // Enable this to add WMI support for PDOs
- InitializationData.PdoData.ClassWmiInfo.GuidCount = 1;
- InitializationData.PdoData.ClassWmiInfo.GuidRegInfo = DiskWmiPdoGuidList;
- InitializationData.PdoData.ClassWmiInfo.ClassQueryWmiRegInfo = DiskPdoQueryWmiRegInfo;
- InitializationData.PdoData.ClassWmiInfo.ClassQueryWmiDataBlock = DiskPdoQueryWmiDataBlock;
- InitializationData.PdoData.ClassWmiInfo.ClassSetWmiDataBlock = DiskPdoSetWmiDataBlock;
- InitializationData.PdoData.ClassWmiInfo.ClassSetWmiDataItem = DiskPdoSetWmiDataItem;
- InitializationData.PdoData.ClassWmiInfo.ClassExecuteWmiMethod = DiskPdoExecuteWmiMethod;
- InitializationData.PdoData.ClassWmiInfo.ClassWmiFunctionControl = DiskWmiFunctionControl;
- #endif
- InitializationData.ClassUnload = DiskUnload;
- //
- // Initialize regregistration data structures
- //
- DiskInitializeReregistration();
- //
- // Call the class init routine
- //
- status = ClassInitialize( DriverObject, RegistryPath, &InitializationData);
- #if defined(_X86_)
- if(NT_SUCCESS(status)) {
- IoRegisterBootDriverReinitialization(DriverObject,
- DiskDriverReinitialization,
- NULL);
- }
- #endif
- //
- // Call class init Ex routine to register a
- // PCLASS_QUERY_WMI_REGINFO_EX routine
- //
- RtlZeroMemory(&classQueryWmiRegInfoExList, sizeof(CLASS_QUERY_WMI_REGINFO_EX_LIST));
- classQueryWmiRegInfoExList.Size = sizeof(CLASS_QUERY_WMI_REGINFO_EX_LIST);
- classQueryWmiRegInfoExList.ClassFdoQueryWmiRegInfoEx = DiskFdoQueryWmiRegInfoEx;
- ClassInitializeEx(DriverObject,
- &guidQueryRegInfoEx,
- &classQueryWmiRegInfoExList);
- return status;
- } // end DriverEntry()
- VOID
- DiskUnload(
- IN PDRIVER_OBJECT DriverObject
- )
- {
- PAGED_CODE();
- #if defined(_X86_)
- DiskCleanupDetectInfo(DriverObject);
- #endif
- return;
- }
- NTSTATUS
- DiskCreateFdo(
- IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT PhysicalDeviceObject,
- IN PULONG DeviceCount,
- IN BOOLEAN DasdAccessOnly
- )
- /*++
- Routine Description:
- This routine creates an object for the functional device
- Arguments:
- DriverObject - Pointer to driver object created by system.
- PhysicalDeviceObject - Lower level driver we should attach to
- DeviceCount - Number of previously installed devices.
- DasdAccessOnly - indicates whether or not a file system is allowed to mount
- on this device object. Used to avoid double-mounting of
- file systems on super-floppies (which can unfortunately be
- fixed disks). If set the i/o system will only allow rawfs
- to be mounted.
- Return Value:
- NTSTATUS
- --*/
- {
- CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
- STRING ntNameString;
- UNICODE_STRING ntUnicodeString;
- PUCHAR deviceName = NULL;
- OBJECT_ATTRIBUTES objectAttributes;
- HANDLE handle;
- NTSTATUS status;
- PDEVICE_OBJECT lowerDevice = NULL;
- PDEVICE_OBJECT deviceObject = NULL;
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
- STORAGE_PROPERTY_ID propertyId;
- PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor;
- PAGED_CODE();
- *DeviceCount = 0;
- //
- // Set up an object directory to contain the objects for this
- // device and all its partitions.
- //
- do {
- WCHAR buffer[64];
- UNICODE_STRING unicodeDirectoryName;
- swprintf(buffer, L"\\Device\\Harddisk%d", *DeviceCount);
- RtlInitUnicodeString(&unicodeDirectoryName, buffer);
- InitializeObjectAttributes(&objectAttributes,
- &unicodeDirectoryName,
- OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
- NULL,
- NULL);
- status = ZwCreateDirectoryObject(&handle,
- DIRECTORY_ALL_ACCESS,
- &objectAttributes);
- (*DeviceCount)++;
- } while((status == STATUS_OBJECT_NAME_COLLISION) ||
- (status == STATUS_OBJECT_NAME_EXISTS));
- if (!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskCreateFdo: Could not create directory - %lx\n",
- status));
- return(status);
- }
- //
- // When this loop exits the count is inflated by one - fix that.
- //
- (*DeviceCount)--;
- //
- // Claim the device.
- //
- lowerDevice = IoGetAttachedDeviceReference(PhysicalDeviceObject);
- status = ClassClaimDevice(lowerDevice, FALSE);
- if (!NT_SUCCESS(status)) {
- ZwMakeTemporaryObject(handle);
- ZwClose(handle);
- ObDereferenceObject(lowerDevice);
- return status;
- }
- //
- // Create a device object for this device. Each physical disk will
- // have at least one device object. The required device object
- // describes the entire device. Its directory path is
- // \Device\HarddiskN\Partition0, where N = device number.
- //
- status = DiskGenerateDeviceName(TRUE,
- *DeviceCount,
- 0,
- NULL,
- NULL,
- &deviceName);
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskCreateFdo - couldn't create name %lx\n",
- status));
- goto DiskCreateFdoExit;
- }
- status = ClassCreateDeviceObject(DriverObject,
- deviceName,
- PhysicalDeviceObject,
- TRUE,
- &deviceObject);
- if (!NT_SUCCESS(status)) {
- DebugPrint((1,
- "DiskCreateFdo: Can not create device object %s\n",
- ntNameBuffer));
- goto DiskCreateFdoExit;
- }
- //
- // Indicate that IRPs should include MDLs for data transfers.
- //
- SET_FLAG(deviceObject->Flags, DO_DIRECT_IO);
- fdoExtension = deviceObject->DeviceExtension;
- if(DasdAccessOnly) {
- //
- // Inidicate that only RAW should be allowed to mount on the root
- // partition object. This ensures that a file system can't doubly
- // mount on a super-floppy by mounting once on P0 and once on P1.
- //
- SET_FLAG(deviceObject->Vpb->Flags, VPB_RAW_MOUNT);
- }
- //
- // Initialize lock count to zero. The lock count is used to
- // disable the ejection mechanism on devices that support
- // removable media. Only the lock count in the physical
- // device extension is used.
- //
- fdoExtension->LockCount = 0;
- //
- // Save system disk number.
- //
- fdoExtension->DeviceNumber = *DeviceCount;
- //
- // Set the alignment requirements for the device based on the
- // host adapter requirements
- //
- if (lowerDevice->AlignmentRequirement > deviceObject->AlignmentRequirement) {
- deviceObject->AlignmentRequirement = lowerDevice->AlignmentRequirement;
- }
- //
- // Finally, attach to the pdo
- //
- fdoExtension->LowerPdo = PhysicalDeviceObject;
- fdoExtension->CommonExtension.LowerDeviceObject =
- IoAttachDeviceToDeviceStack(
- deviceObject,
- PhysicalDeviceObject);
- if(fdoExtension->CommonExtension.LowerDeviceObject == NULL) {
- //
- // Uh - oh, we couldn't attach
- // cleanup and return
- //
- status = STATUS_UNSUCCESSFUL;
- goto DiskCreateFdoExit;
- }
- {
- PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData;
- //
- // Initialize the partitioning lock as it may be used in the remove
- // code.
- //
- KeInitializeEvent(&(diskData->PartitioningEvent),
- SynchronizationEvent,
- TRUE);
- }
- //
- // Clear the init flag.
- //
- CLEAR_FLAG(deviceObject->Flags, DO_DEVICE_INITIALIZING);
- //
- // Store a handle to the device object directory for this disk
- //
- fdoExtension->DeviceDirectory = handle;
- ObDereferenceObject(lowerDevice);
- return STATUS_SUCCESS;
- DiskCreateFdoExit:
- //
- // Release the device since an error occurred.
- //
- if (deviceObject != NULL) {
- IoDeleteDevice(deviceObject);
- }
- //
- // Delete directory and return.
- //
- if (!NT_SUCCESS(status)) {
- ZwMakeTemporaryObject(handle);
- ZwClose(handle);
- }
- ObDereferenceObject(lowerDevice);
- return(status);
- }
- NTSTATUS
- DiskReadWriteVerification(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- /*++
- Routine Description:
- I/O System entry for read and write requests to SCSI disks.
- Arguments:
- DeviceObject - Pointer to driver object created by system.
- Irp - IRP involved.
- Return Value:
- NT Status
- --*/
- {
- PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
- PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
- ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
- LARGE_INTEGER startingOffset;
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
- commonExtension->PartitionZeroExtension;
- ULONG residualBytes;
- NTSTATUS status;
- //
- // Verify parameters of this request.
- // Check that ending sector is within partition and
- // that number of bytes to transfer is a multiple of
- // the sector size.
- //
- startingOffset.QuadPart =
- (currentIrpStack->Parameters.Read.ByteOffset.QuadPart +
- transferByteCount);
- residualBytes = transferByteCount &
- (fdoExtension->DiskGeometry.BytesPerSector - 1);
- if ((startingOffset.QuadPart > commonExtension->PartitionLength.QuadPart) ||
- (residualBytes != 0)) {
- //
- // This error may be caused by the fact that the drive is not ready.
- //
- status = ((PDISK_DATA) commonExtension->DriverData)->ReadyStatus;
- if (!NT_SUCCESS(status)) {
- //
- // Flag this as a user errror so that a popup is generated.
- //
- DebugPrint((1, "DiskReadWriteVerification: ReadyStatus is %lx\n",
- status));
- IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
- //
- // status will keep the current error
- //
- ASSERT( status != STATUS_INSUFFICIENT_RESOURCES );
- } else if((commonExtension->IsFdo == TRUE) && (residualBytes == 0)) {
- //
- // This failed because we think the physical disk is too small.
- // Send it down to the drive and let the hardware decide for
- // itself.
- //
- status = STATUS_SUCCESS;
- } else {
- //
- // Note fastfat depends on this parameter to determine when to
- // remount due to a sector size change.
- //
- status = STATUS_INVALID_PARAMETER;
- }
- } else {
- //
- // the drive is ready, so ok the read/write
- //
- status = STATUS_SUCCESS;
- }
- Irp->IoStatus.Status = status;
- return status;
- } // end DiskReadWrite()
- NTSTATUS
- DiskDetermineMediaTypes(
- IN PDEVICE_OBJECT Fdo,
- IN PIRP Irp,
- IN UCHAR MediumType,
- IN UCHAR DensityCode,
- IN BOOLEAN MediaPresent,
- IN BOOLEAN IsWritable
- )
- /*++
- Routine Description:
- Determines number of types based on the physical device, validates the user buffer
- and builds the MEDIA_TYPE information.
- Arguments:
- DeviceObject - Pointer to functional device object created by system.
- Irp - IOCTL_STORAGE_GET_MEDIA_TYPES_EX Irp.
- MediumType - byte returned in mode data header.
- DensityCode - byte returned in mode data block descriptor.
- NumberOfTypes - pointer to be updated based on actual device.
- Return Value:
- Status is returned.
- --*/
- {
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
- PPHYSICAL_DEVICE_EXTENSION pdoExtension = Fdo->DeviceExtension;
- PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
- PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
- PGET_MEDIA_TYPES mediaTypes = Irp->AssociatedIrp.SystemBuffer;
- PDEVICE_MEDIA_INFO mediaInfo = &mediaTypes->MediaInfo[0];
- BOOLEAN deviceMatched = FALSE;
- PAGED_CODE();
- //
- // this should be checked prior to calling into this routine
- // as we use the buffer as mediaTypes
- //
- ASSERT(irpStack->Parameters.DeviceIoControl.OutputBufferLength >=
- sizeof(GET_MEDIA_TYPES));
- //
- // Determine if this device is removable or fixed.
- //
- if (!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
- //
- // Fixed disk.
- //
- mediaTypes->DeviceType = FILE_DEVICE_DISK;
- mediaTypes->MediaInfoCount = 1;
- mediaInfo->DeviceSpecific.DiskInfo.Cylinders.QuadPart = fdoExtension->DiskGeometry.Cylinders.QuadPart;
- mediaInfo->DeviceSpecific.DiskInfo.TracksPerCylinder = fdoExtension->DiskGeometry.TracksPerCylinder;
- mediaInfo->DeviceSpecific.DiskInfo.SectorsPerTrack = fdoExtension->DiskGeometry.SectorsPerTrack;
- mediaInfo->DeviceSpecific.DiskInfo.BytesPerSector = fdoExtension->DiskGeometry.BytesPerSector;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.NumberMediaSides = 1;
- mediaInfo->DeviceSpecific.DiskInfo.MediaCharacteristics = (MEDIA_CURRENTLY_MOUNTED | MEDIA_READ_WRITE);
- if (!IsWritable) {
- SET_FLAG(mediaInfo->DeviceSpecific.DiskInfo.MediaCharacteristics,
- MEDIA_WRITE_PROTECTED);
- }
- mediaInfo->DeviceSpecific.DiskInfo.MediaType = FixedMedia;
- } else {
- PUCHAR vendorId = (PUCHAR) fdoExtension->DeviceDescriptor + fdoExtension->DeviceDescriptor->VendorIdOffset;
- PUCHAR productId = (PUCHAR) fdoExtension->DeviceDescriptor + fdoExtension->DeviceDescriptor->ProductIdOffset;
- PUCHAR productRevision = (PUCHAR) fdoExtension->DeviceDescriptor + fdoExtension->DeviceDescriptor->ProductRevisionOffset;
- DISK_MEDIA_TYPES_LIST const *mediaListEntry;
- ULONG currentMedia;
- ULONG i;
- ULONG j;
- ULONG sizeNeeded;
- DebugPrint((1,
- "DiskDetermineMediaTypes: Vendor %s, Product %s\n",
- vendorId,
- productId));
- //
- // Run through the list until we find the entry with a NULL Vendor Id.
- //
- for (i = 0; DiskMediaTypes[i].VendorId != NULL; i++) {
- mediaListEntry = &DiskMediaTypes[i];
- if (strncmp(mediaListEntry->VendorId,vendorId,strlen(mediaListEntry->VendorId))) {
- continue;
- }
- if ((mediaListEntry->ProductId != NULL) &&
- strncmp(mediaListEntry->ProductId, productId, strlen(mediaListEntry->ProductId))) {
- continue;
- }
- if ((mediaListEntry->Revision != NULL) &&
- strncmp(mediaListEntry->Revision, productRevision, strlen(mediaListEntry->Revision))) {
- continue;
- }
- deviceMatched = TRUE;
- mediaTypes->DeviceType = FILE_DEVICE_DISK;
- mediaTypes->MediaInfoCount = mediaListEntry->NumberOfTypes;
- //
- // Ensure that buffer is large enough.
- //
- sizeNeeded = FIELD_OFFSET(GET_MEDIA_TYPES, MediaInfo[0]) +
- (mediaListEntry->NumberOfTypes *
- sizeof(DEVICE_MEDIA_INFO)
- );
- if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
- sizeNeeded) {
- //
- // Buffer too small
- //
- Irp->IoStatus.Information = sizeNeeded;
- Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
- return STATUS_BUFFER_TOO_SMALL;
- }
- for (j = 0; j < mediaListEntry->NumberOfTypes; j++) {
- mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = fdoExtension->DiskGeometry.Cylinders.QuadPart;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder = fdoExtension->DiskGeometry.TracksPerCylinder;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack = fdoExtension->DiskGeometry.SectorsPerTrack;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector = fdoExtension->DiskGeometry.BytesPerSector;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.NumberMediaSides = mediaListEntry->NumberOfSides;
- //
- // Set the type.
- //
- mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType = mediaListEntry->MediaTypes[j];
- if (mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType == MO_5_WO) {
- mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = MEDIA_WRITE_ONCE;
- } else {
- mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = MEDIA_READ_WRITE;
- }
- //
- // Status will either be success, if media is present, or no media.
- // It would be optimal to base from density code and medium type, but not all devices
- // have values for these fields.
- //
- if (MediaPresent) {
- //
- // The usage of MediumType and DensityCode is device specific, so this may need
- // to be extended to further key off of product/vendor ids.
- // Currently, the MO units are the only devices that return this information.
- //
- if (MediumType == 2) {
- currentMedia = MO_5_WO;
- } else if (MediumType == 3) {
- currentMedia = MO_5_RW;
- if (DensityCode == 0x87) {
- //
- // Indicate that the pinnacle 4.6 G media
- // is present. Other density codes will default to normal
- // RW MO media.
- //
- currentMedia = PINNACLE_APEX_5_RW;
- }
- } else {
- currentMedia = 0;
- }
- if (currentMedia) {
- if (mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType == (STORAGE_MEDIA_TYPE)currentMedia) {
- SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics, MEDIA_CURRENTLY_MOUNTED);
- }
- } else {
- SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics, MEDIA_CURRENTLY_MOUNTED);
- }
- }
- if (!IsWritable) {
- SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics, MEDIA_WRITE_PROTECTED);
- }
- //
- // Advance to next entry.
- //
- mediaInfo++;
- }
- }
- if (!deviceMatched) {
- DebugPrint((1,
- "DiskDetermineMediaTypes: Unknown device. Vendor: %s Product: %s Revision: %s\n",
- vendorId,
- productId,
- productRevision));
- //
- // Build an entry for unknown.
- //
- mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = fdoExtension->DiskGeometry.Cylinders.QuadPart;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder = fdoExtension->DiskGeometry.TracksPerCylinder;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack = fdoExtension->DiskGeometry.SectorsPerTrack;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector = fdoExtension->DiskGeometry.BytesPerSector;
- //
- // Set the type.
- //
- mediaTypes->DeviceType = FILE_DEVICE_DISK;
- mediaTypes->MediaInfoCount = 1;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType = RemovableMedia;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.NumberMediaSides = 1;
- mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = MEDIA_READ_WRITE;
- if (MediaPresent) {
- SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics, MEDIA_CURRENTLY_MOUNTED);
- }
- if (!IsWritable) {
- SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics, MEDIA_WRITE_PROTECTED);
- }
- }
- }
- Irp->IoStatus.Information =
- FIELD_OFFSET(GET_MEDIA_TYPES, MediaInfo[0]) +
- (mediaTypes->MediaInfoCount * sizeof(DEVICE_MEDIA_INFO));
- return STATUS_SUCCESS;
- }
- NTSTATUS
- DiskDeviceControl(
- PDEVICE_OBJECT DeviceObject,
- PIRP Irp
- )
- /*++
- Routine Description:
- I/O system entry for device controls to SCSI disks.
- Arguments:
- Fdo - Pointer to functional device object created by system.
- Irp - IRP involved.
- Return Value:
- Status is returned.
- --*/
- #define SendToFdo(Dev, Irp, Rval) { \
- PCOMMON_DEVICE_EXTENSION ce = Dev->DeviceExtension; \
- ASSERT_PDO(Dev); \
- IoCopyCurrentIrpStackLocationToNext(Irp); \
- Rval = IoCallDriver(ce->LowerDeviceObject, Irp); \
- }
- {
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
- PPHYSICAL_DEVICE_EXTENSION pdoExtension = DeviceObject->DeviceExtension;
- PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
- PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
- PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
- PSCSI_REQUEST_BLOCK srb;
- PCDB cdb;
- PMODE_PARAMETER_HEADER modeData;
- PIRP irp2;
- ULONG length;
- NTSTATUS status;
- KEVENT event;
- IO_STATUS_BLOCK ioStatus;
- BOOLEAN b = FALSE;
- srb = ExAllocatePoolWithTag(NonPagedPool,
- SCSI_REQUEST_BLOCK_SIZE,
- DISK_TAG_SRB);
- Irp->IoStatus.Information = 0;
- if (srb == NULL) {
- Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
- ClassReleaseRemoveLock(DeviceObject, Irp);
- ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
- //
- // Write zeros to Srb.
- //
- RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
- cdb = (PCDB)srb->Cdb;
- switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
- case IOCTL_DISK_GET_CACHE_INFORMATION:
- b = TRUE;
- case IOCTL_DISK_SET_CACHE_INFORMATION: {
- BOOLEAN getCaching = b;
- PDISK_CACHE_INFORMATION cacheInfo = Irp->AssociatedIrp.SystemBuffer;
- if(!commonExtension->IsFdo) {
- ClassReleaseRemoveLock(DeviceObject, Irp);
- ExFreePool(srb);
- SendToFdo(DeviceObject, Irp, status);
- return status;
- }
- //
- // Validate the request.
- //
- if((getCaching) &&
- (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
- sizeof(DISK_CACHE_INFORMATION))
- ) {
- status = STATUS_BUFFER_TOO_SMALL;
- Irp->IoStatus.Information = sizeof(DISK_CACHE_INFORMATION);
- break;
- }
- if ((!getCaching) &&
- (irpStack->Parameters.DeviceIoControl.InputBufferLength <
- sizeof(DISK_CACHE_INFORMATION))
- ) {
- status = STATUS_INFO_LENGTH_MISMATCH;
- break;
- }
- ASSERT(Irp->AssociatedIrp.SystemBuffer != NULL);
- if (getCaching) {
- status = DiskGetCacheInformation(fdoExtension, cacheInfo);
- if (NT_SUCCESS(status)) {
- Irp->IoStatus.Information = sizeof(DISK_CACHE_INFORMATION);
- }
- } else {
- if (!cacheInfo->WriteCacheEnabled)
- {
- if (TEST_FLAG(fdoExtension->ScanForSpecialFlags,
- CLASS_SPECIAL_DISABLE_WRITE_CACHE_NOT_SUPPORTED))
- {
- //
- // This request wants to disable write cache, which is
- // not supported on this device. Instead of sending it
- // down only to see it fail, return the error code now
- //
- status = STATUS_INVALID_DEVICE_REQUEST;
- break;
- }
- }
- else
- {
- if (TEST_FLAG(fdoExtension->ScanForSpecialFlags,
- CLASS_SPECIAL_DISABLE_WRITE_CACHE))
- {
- //
- // This request wants to enable write cache, which
- // has been disabled to protect data integrity. So
- // fail this request with access denied
- //
- status = STATUS_ACCESS_DENIED;
- break;
- }
- }
- status = DiskSetCacheInformation(fdoExtension, cacheInfo);
- if (NT_SUCCESS(status))
- {
- //
- // Store the user-defined override in the registry
- //
- ClassSetDeviceParameter(fdoExtension,
- DiskDeviceParameterSubkey,
- DiskDeviceUserWriteCacheSetting,
- (cacheInfo->WriteCacheEnabled) ? DiskWriteCacheEnable : DiskWriteCacheDisable);
- }
- else if (status == STATUS_INVALID_DEVICE_REQUEST)
- {
- if (cacheInfo->WriteCacheEnabled == FALSE)
- {
- //
- // This device does not allow for
- // the write cache to be disabled
- //
- ULONG specialFlags = 0;
- ClassGetDeviceParameter(fdoExtension,
- DiskDeviceParameterSubkey,
- DiskDeviceSpecialFlags,
- &specialFlags);
- SET_FLAG(specialFlags, HackDisableWriteCacheNotSupported);
- SET_FLAG(fdoExtension->ScanForSpecialFlags,
- CLASS_SPECIAL_DISABLE_WRITE_CACHE_NOT_SUPPORTED);
- ClassSetDeviceParameter(fdoExtension,
- DiskDeviceParameterSubkey,
- DiskDeviceSpecialFlags,
- specialFlags);
- }
- }
- }
- break;
- }
- #if(_WIN32_WINNT >= 0x0500)
- case IOCTL_DISK_GET_WRITE_CACHE_STATE: {
- PDISK_WRITE_CACHE_STATE writeCacheState = (PDISK_WRITE_CACHE_STATE)Irp->AssociatedIrp.SystemBuffer;
- if(!commonExtension->IsFdo) {
- ClassReleaseRemoveLock(DeviceObject, Irp);
- ExFreePool(srb);
- SendToFdo(DeviceObject, Irp, status);
- return status;
- }
- //
- // Validate the request.
- //
- if(irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_WRITE_CACHE_STATE)) {
- status = STATUS_BUFFER_TOO_SMALL;
- Irp->IoStatus.Information = sizeof(DISK_WRITE_CACHE_STATE);
- break;
- }
- *writeCacheState = DiskWriteCacheNormal;
- //
- // Determine whether it is possible to disable the write cache
- //
- if (TEST_FLAG(fdoExtension->ScanForSpecialFlags, CLASS_SPECIAL_DISABLE_WRITE_CACHE_NOT_SUPPORTED))
- {
- *writeCacheState = DiskWriteCacheDisableNotSupported;
- }
- //
- // Determine whether it is safe to toggle the write cache
- //
- if (TEST_FLAG(fdoExtension->ScanForSpecialFlags, CLASS_SPECIAL_DISABLE_WRITE_CACHE))
- {
- *writeCacheState = DiskWriteCacheForceDisable;
- }
- Irp->IoStatus.Information = sizeof(DISK_WRITE_CACHE_STATE);
- status = STATUS_SUCCESS;
- break;
- }
- #endif
- case SMART_GET_VERSION: {
- PUCHAR buffer;
- PSRB_IO_CONTROL srbControl;
- PGETVERSIONINPARAMS versionParams;
- if(!commonExtension->IsFdo) {
- ClassReleaseRemoveLock(DeviceObject, Irp);
- ExFreePool(srb);
- SendToFdo(DeviceObject, Irp, status);
- return status;
- }
- if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
- sizeof(GETVERSIONINPARAMS)) {
- status = STATUS_BUFFER_TOO_SMALL;
- Irp->IoStatus.Information = sizeof(GETVERSIONINPARAMS);
- break;
- }
- //
- // Create notification event object to be used to signal the
- // request completion.
- //
- KeInitializeEvent(&event, NotificationEvent, FALSE);
- srbControl = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(SRB_IO_CONTROL) +
- sizeof(GETVERSIONINPARAMS),
- DISK_TAG_SMART);
- if (!srbControl) {
- status = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
- RtlZeroMemory(srbControl,
- sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS)
- );
- //
- // fill in srbControl fields
- //
- srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
- RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
- srbControl->Timeout = fdoExtension->TimeOutValue;
- srbControl->Length = sizeof(GETVERSIONINPARAMS);
- srbControl->ControlCode = IOCTL_SCSI_MINIPORT_SMART_VERSION;
- //
- // Point to the 'buffer' portion of the SRB_CONTROL
- //
- buffer = (PUCHAR)srbControl;
- buffer += srbControl->HeaderLength;
- //
- // Ensure correct target is set in the cmd parameters.
- //
- versionParams = (PGETVERSIONINPARAMS)buffer;
- versionParams->bIDEDeviceMap = diskData->ScsiAddress.TargetId;
- //
- // Copy the IOCTL parameters to the srb control buffer area.
- //
- RtlMoveMemory(buffer,
- Irp->AssociatedIrp.SystemBuffer,
- sizeof(GETVERSIONINPARAMS));
- ClassSendDeviceIoControlSynchronous(
- IOCTL_SCSI_MINIPORT,
- commonExtension->LowerDeviceObject,
- srbControl,
- sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
- sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
- FALSE,
- &ioStatus);
- status = ioStatus.Status;
- //
- // If successful, copy the data received into the output buffer.
- // This should only fail in the event that the IDE driver is older
- // than this driver.
- //
- if (NT_SUCCESS(status)) {
- buffer = (PUCHAR)srbControl;
- buffer += srbControl->HeaderLength;
- RtlMoveMemory (Irp->AssociatedIrp.SystemBuffer, buffer,
- sizeof(GETVERSIONINPARAMS));
- Irp->IoStatus.Information = sizeof(GETVERSIONINPARAMS);
- }
- ExFreePool(srbControl);
- break;
- }
- case SMART_RCV_DRIVE_DATA: {
- PSENDCMDINPARAMS cmdInParameters = ((PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer);
- ULONG controlCode = 0;
- PSRB_IO_CONTROL srbControl;
- PUCHAR buffer;
- if(!commonExtension->IsFdo) {
- ClassReleaseRemoveLock(DeviceObject, Irp);
- ExFreePool(srb);
- SendToFdo(DeviceObject, Irp, status);
- return status;
- }
- if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
- (sizeof(SENDCMDINPARAMS) - 1)) {
- status = STATUS_INVALID_PARAMETER;
- Irp->IoStatus.Information = 0;
- break;
- } else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
- (sizeof(SENDCMDOUTPARAMS) + 512 - 1)) {
- status = STATUS_BUFFER_TOO_SMALL;
- Irp->IoStatus.Information = sizeof(SENDCMDOUTPARAMS) + 512 - 1;
- break;
- }
- //
- // Create notification event object to be used to signal the
- // request completion.
- //
- KeInitializeEvent(&event, NotificationEvent, FALSE);
- //
- // use controlCode as a sort of 'STATUS_SUCCESS' to see if it's
- // a valid request type
- //
- if (cmdInParameters->irDriveRegs.bCommandReg == ID_CMD) {
- length = IDENTIFY_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS);
- controlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
- } else if (cmdInParameters->irDriveRegs.bCommandReg == SMART_CMD) {
- switch (cmdInParameters->irDriveRegs.bFeaturesReg) {
- case READ_ATTRIBUTES:
- controlCode = IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS;
- length = READ_ATTRIBUTE_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS);
- break;
- case READ_THRESHOLDS:
- controlCode = IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS;
- length = READ_THRESHOLD_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS);
- break;
- default:
- status = STATUS_INVALID_PARAMETER;
- break;
- }
- } else {
- status = STATUS_INVALID_PARAMETER;
- }
- if (controlCode == 0) {
- status = STATUS_INVALID_PARAMETER;
- break;
- }
- srbControl = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(SRB_IO_CONTROL) + length,
- DISK_TAG_SMART);
- if (!srbControl) {
- status = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
- //
- // fill in srbControl fields
- //
- srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
- RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
- srbControl->Timeout = fdoExtension->TimeOutValue;
- srbControl->Length = length;
- srbControl->ControlCode = controlCode;
- //
- // Point to the 'buffer' portion of the SRB_CONTROL
- //
- buffer = (PUCHAR)srbControl;
- buffer += srbControl->HeaderLength;
- //
- // Ensure correct target is set in the cmd parameters.
- //
- cmdInParameters->bDriveNumber = diskData->ScsiAddress.TargetId;
- //
- // Copy the IOCTL parameters to the srb control buffer area.
- //
- RtlMoveMemory(buffer,
- Irp->AssociatedIrp.SystemBuffer,
- sizeof(SENDCMDINPARAMS) - 1);
- irp2 = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
- commonExtension->LowerDeviceObject,
- srbControl,
- sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
- srbControl,
- sizeof(SRB_IO_CONTROL) + length,
- FALSE,
- &event,
- &ioStatus);
- if (irp2 == NULL) {
- status = STATUS_INSUFFICIENT_RESOURCES;
- ExFreePool(srbControl);
- break;
- }
- //
- // Call the port driver with the request and wait for it to complete.
- //
- status = IoCallDriver(commonExtension->LowerDeviceObject, irp2);
- if (status == STATUS_PENDING) {
- KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
- status = ioStatus.Status;
- }
- //
- // Copy the data received into the output buffer. Since the status buffer
- // contains error information also, always perform this copy. IO will will
- // either pass this back to the app, or zero it, in case of error.
- //
- buffer = (PUCHAR)srbControl;
- buffer += srbControl->HeaderLength;
- if (NT_SUCCESS(status)) {
- RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, buffer, length - 1);
- Irp->IoStatus.Information = length - 1;
- } else {
- RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, buffer, (sizeof(SENDCMDOUTPARAMS) - 1));
- Irp->IoStatus.Information = sizeof(SENDCMDOUTPARAMS) - 1;
- }
- ExFreePool(srbControl);
- break;
- }
- case SMART_SEND_DRIVE_COMMAND: {
- PSENDCMDINPARAMS cmdInParameters = ((PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer);
- PSRB_IO_CONTROL srbControl;
- ULONG controlCode = 0;
- PUCHAR buffer;
- if(!commonExtension->IsFdo) {
- ClassReleaseRemoveLock(DeviceObject, Irp);
- ExFreePool(srb);
- SendToFdo(DeviceObject, Irp, status);
- return status;
- }
- if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
- (sizeof(SENDCMDINPARAMS) - 1)) {
- status = STATUS_INVALID_PARAMETER;
- Irp->IoStatus.Information = 0;
- break;
- } else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
- (sizeof(SENDCMDOUTPARAMS) - 1)) {
- status = STATUS_BUFFER_TOO_SMALL;
- Irp->IoStatus.Information = sizeof(SENDCMDOUTPARAMS) - 1;
- break;
- }
- //
- // Create notification event object to be used to signal the
- // request completion.
- //
- KeInitializeEvent(&event, NotificationEvent, FALSE);
- length = 0;
- if (cmdInParameters->irDriveRegs.bCommandReg == SMART_CMD) {
- switch (cmdInParameters->irDriveRegs.bFeaturesReg) {
- case ENABLE_SMART:
- controlCode = IOCTL_SCSI_MINIPORT_ENABLE_SMART;
- break;
- case DISABLE_SMART:
- controlCode = IOCTL_SCSI_MINIPORT_DISABLE_SMART;
- break;
- case RETURN_SMART_STATUS:
- //
- // Ensure bBuffer is at least 2 bytes (to hold the values of
- // cylinderLow and cylinderHigh).
- //
- if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
- (sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS))) {
- status = STATUS_BUFFER_TOO_SMALL;
- Irp->IoStatus.Information =
- sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS);
- break;
- }
- controlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS;
- length = sizeof(IDEREGS);
- break;
- case ENABLE_DISABLE_AUTOSAVE:
- controlCode = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE;
- break;
- case SAVE_ATTRIBUTE_VALUES:
- controlCode = IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES;
- break;
- case EXECUTE_OFFLINE_DIAGS:
- //
- // Validate that this is an ok self test command
- //
- if (DiskIsValidSmartSelfTest(cmdInParameters->irDriveRegs.bSectorNumberReg))
- {
- controlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;
- }
- break;
- case ENABLE_DISABLE_AUTO_OFFLINE:
- controlCode = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE;
- break;
- default:
- status = STATUS_INVALID_PARAMETER;
- break;
- }
- } else {
- status = STATUS_INVALID_PARAMETER;
- }
- if (controlCode == 0) {
- status = STATUS_INVALID_PARAMETER;
- break;
- }
- length += (sizeof(SENDCMDOUTPARAMS) > sizeof(SENDCMDINPARAMS)) ? sizeof(SENDCMDOUTPARAMS) : sizeof(SENDCMDINPARAMS);;
- srbControl = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(SRB_IO_CONTROL) + length,
- DISK_TAG_SMART);
- if (!srbControl) {
- status = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
- //
- // fill in srbControl fields
- //
- srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
- RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
- srbControl->Timeout = fdoExtension->TimeOutValue;
- srbControl->Length = length;
- //
- // Point to the 'buffer' portion of the SRB_CONTROL
- //
- buffer = (PUCHAR)srbControl;
- buffer += srbControl->HeaderLength;
- //
- // Ensure correct target is set in the cmd parameters.
- //
- cmdInParameters->bDriveNumber …
Large files files are truncated, but you can click here to view the full file