📄 disk.c
字号:
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;
}
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -