📄 autorun.c
字号:
MediaPresent - indicates whether the device has media inserted into it
(TRUE) or not (FALSE).
Wait - indicates whether the function should wait until it can acquire
the synchronization lock or not.
Return Value:
none
--*/
VOID
ClasspSetMediaChangeStateEx(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN MEDIA_CHANGE_DETECTION_STATE NewState,
IN BOOLEAN Wait,
IN BOOLEAN KnownStateChange // can ignore oldstate == unknown
)
{
PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
LARGE_INTEGER zero;
NTSTATUS status;
DBGTRACE(ClassDebugMCN, ("> ClasspSetMediaChangeStateEx"));
//
// Reset SMART status on media removal as the old status may not be
// valid when there is no media in the device or when new media is
// inserted.
//
if (NewState == MediaNotPresent) {
FdoExtension->FailurePredicted = FALSE;
FdoExtension->FailureReason = 0;
}
zero.QuadPart = 0;
if(info == NULL) {
return;
}
status = KeWaitForMutexObject(&info->MediaChangeMutex,
Executive,
KernelMode,
FALSE,
((Wait == TRUE) ? NULL : &zero));
if(status == STATUS_TIMEOUT) {
//
// Someone else is in the process of setting the media state
//
DBGWARN(("ClasspSetMediaChangeStateEx - timed out waiting for mutex"));
return;
}
//
// Change the media present state and signal an event, if applicable
//
ClasspInternalSetMediaChangeState(FdoExtension, NewState, KnownStateChange);
KeReleaseMutex(&info->MediaChangeMutex, FALSE);
DBGTRACE(ClassDebugMCN, ("< ClasspSetMediaChangeStateEx"));
return;
} // end ClassSetMediaChangeStateEx()
VOID
ClassSetMediaChangeState(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN MEDIA_CHANGE_DETECTION_STATE NewState,
IN BOOLEAN Wait
)
{
ClasspSetMediaChangeStateEx(FdoExtension, NewState, Wait, FALSE);
return;
}
/*++////////////////////////////////////////////////////////////////////////////
ClasspMediaChangeDetectionCompletion()
Routine Description:
This routine handles the completion of the test unit ready irps used to
determine if the media has changed. If the media has changed, this code
signals the named event to wake up other system services that react to
media change (aka AutoPlay).
Arguments:
DeviceObject - the object for the completion
Irp - the IRP being completed
Context - the SRB from the IRP
Return Value:
NTSTATUS
--*/
NTSTATUS
ClasspMediaChangeDetectionCompletion(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PSCSI_REQUEST_BLOCK Srb
)
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
PCLASS_PRIVATE_FDO_DATA fdoData;
PMEDIA_CHANGE_DETECTION_INFO info;
PIO_STACK_LOCATION nextIrpStack;
NTSTATUS status;
BOOLEAN retryImmediately = FALSE;
//
// Since the class driver created this request, it's completion routine
// will not get a valid device object handed in. Use the one in the
// irp stack instead
//
DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject;
fdoExtension = DeviceObject->DeviceExtension;
fdoData = fdoExtension->PrivateFdoData;
info = fdoExtension->MediaChangeDetectionInfo;
ASSERT(info->MediaChangeIrp != NULL);
ASSERT(!TEST_FLAG(Srb->SrbStatus, SRB_STATUS_QUEUE_FROZEN));
DBGTRACE(ClassDebugMCN, ("> ClasspMediaChangeDetectionCompletion: Device %p completed MCN irp %p.", DeviceObject, Irp));
/*
* HACK for IoMega 2GB Jaz drive:
* This drive spins down on its own to preserve the media.
* When spun down, TUR fails with 2/4/0 (SCSI_SENSE_NOT_READY/SCSI_ADSENSE_LUN_NOT_READY/?).
* ClassInterpretSenseInfo would then call ClassSendStartUnit to spin the media up, which defeats the
* purpose of the spindown.
* So in this case, make this into a successful TUR.
* This allows the drive to stay spun down until it is actually accessed again.
* (If the media were actually removed, TUR would fail with 2/3a/0 ).
* This hack only applies to drives with the CAUSE_NOT_REPORTABLE_HACK bit set; this
* is set by disk.sys when HackCauseNotReportableHack is set for the drive in its BadControllers list.
*/
if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
TEST_FLAG(fdoExtension->ScanForSpecialFlags, CLASS_SPECIAL_CAUSE_NOT_REPORTABLE_HACK) &&
(Srb->SenseInfoBufferLength >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCode))){
PSENSE_DATA senseData = Srb->SenseInfoBuffer;
if ((senseData->SenseKey == SCSI_SENSE_NOT_READY) &&
(senseData->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)){
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
}
//
// use ClassInterpretSenseInfo() to check for media state, and also
// to call ClassError() with correct parameters.
//
status = STATUS_SUCCESS;
if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) {
DBGTRACE(ClassDebugMCN, ("ClasspMediaChangeDetectionCompletion - failed - srb status=%s, sense=%s/%s/%s.", DBGGETSRBSTATUSSTR(Srb), DBGGETSENSECODESTR(Srb), DBGGETADSENSECODESTR(Srb), DBGGETADSENSEQUALIFIERSTR(Srb)));
ClassInterpretSenseInfo(DeviceObject,
Srb,
IRP_MJ_SCSI,
0,
0,
&status,
NULL);
}
else {
fdoData->LoggedTURFailureSinceLastIO = FALSE;
if (!info->Gesn.Supported) {
DBGTRACE(ClassDebugMCN, ("ClasspMediaChangeDetectionCompletion - succeeded and GESN NOT supported, setting MediaPresent."));
//
// success != media for GESN case
//
ClassSetMediaChangeState(fdoExtension, MediaPresent, FALSE);
}
else {
DBGTRACE(ClassDebugMCN, ("ClasspMediaChangeDetectionCompletion - succeeded (GESN supported)."));
}
}
if (info->Gesn.Supported) {
if (status == STATUS_DATA_OVERRUN) {
DBGTRACE(ClassDebugMCN, ("ClasspMediaChangeDetectionCompletion - Overrun"));
status = STATUS_SUCCESS;
}
if (!NT_SUCCESS(status)) {
DBGTRACE(ClassDebugMCN, ("ClasspMediaChangeDetectionCompletion: GESN failed with status %x", status));
} else {
//
// for GESN, need to interpret the results of the data.
// this may also require an immediate retry
//
if (Irp->IoStatus.Information == 8 ) {
ClasspInterpretGesnData(fdoExtension,
(PVOID)info->Gesn.Buffer,
&retryImmediately);
}
} // end of NT_SUCCESS(status)
} // end of Info->Gesn.Supported
//
// free port-allocated sense buffer, if any.
//
if (PORT_ALLOCATED_SENSE(fdoExtension, Srb)) {
FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, Srb);
}
//
// Remember the IRP and SRB for use the next time.
//
ASSERT(IoGetNextIrpStackLocation(Irp));
IoGetNextIrpStackLocation(Irp)->Parameters.Scsi.Srb = Srb;
//
// Reset the MCN timer.
//
ClassResetMediaChangeTimer(fdoExtension);
//
// run a sanity check to make sure we're not recursing continuously
//
if (retryImmediately) {
info->MediaChangeRetryCount++;
if (info->MediaChangeRetryCount > MAXIMUM_IMMEDIATE_MCN_RETRIES) {
//
// Disable GESN on this device.
// Create a work item to set the value in the registry
//
PIO_WORKITEM workItem;
DBGTRACE(ClassDebugMCN, ("ClasspMediaChangeDetectionCompletion: Disabling GESN for device %p", DeviceObject));
workItem = IoAllocateWorkItem(DeviceObject);
if (workItem) {
IoQueueWorkItem(workItem, ClasspDisableGesn, DelayedWorkQueue, workItem);
}
info->Gesn.Supported = 0;
info->Gesn.EventMask = 0;
info->Gesn.BufferSize = 0;
info->MediaChangeRetryCount = 0;
retryImmediately = FALSE;
}
} else {
info->MediaChangeRetryCount = 0;
}
//
// release the remove lock....
//
{
UCHAR uniqueValue;
ClassAcquireRemoveLock(DeviceObject, (PIRP)(&uniqueValue));
ClassReleaseRemoveLock(DeviceObject, Irp);
//
// set the irp as not in use
//
{
volatile LONG irpWasInUse;
irpWasInUse = InterlockedCompareExchange(&info->MediaChangeIrpInUse, 0, 1);
#if _MSC_FULL_VER != 13009111 // This compiler always takes the wrong path here.
ASSERT(irpWasInUse);
#endif
}
//
// now send it again before we release our last remove lock
//
if (retryImmediately) {
ClasspSendMediaStateIrp(fdoExtension, info, 0);
}
else {
DBGTRACE(ClassDebugMCN, ("ClasspMediaChangeDetectionCompletion - not retrying immediately"));
}
//
// release the temporary remove lock
//
ClassReleaseRemoveLock(DeviceObject, (PIRP)(&uniqueValue));
}
DBGTRACE(ClassDebugMCN, ("< ClasspMediaChangeDetectionCompletion"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
/*++////////////////////////////////////////////////////////////////////////////
ClasspSendTestUnitIrp() - ISSUE-2000/02/20-henrygab - not documented
Routine Description:
This routine
Arguments:
DeviceObject -
Irp -
Return Value:
--*/
PIRP
ClasspPrepareMcnIrp(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN PMEDIA_CHANGE_DETECTION_INFO Info,
IN BOOLEAN UseGesn
)
{
PSCSI_REQUEST_BLOCK srb;
PIO_STACK_LOCATION irpStack;
PIO_STACK_LOCATION nextIrpStack;
NTSTATUS status;
PCDB cdb;
PIRP irp;
PVOID buffer;
//
// Setup the IRP to perform a test unit ready.
//
irp = Info->MediaChangeIrp;
ASSERT(irp);
if (irp == NULL) {
return NULL;
}
//
// don't keep sending this if the device is being removed.
//
status = ClassAcquireRemoveLock(FdoExtension->DeviceObject, irp);
if (status == REMOVE_COMPLETE) {
ASSERT(status != REMOVE_COMPLETE);
return NULL;
}
else if (status == REMOVE_PENDING) {
ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
return NULL;
}
else {
ASSERT(status == NO_REMOVE);
}
IoReuseIrp(irp, STATUS_NOT_SUPPORTED);
/*
* For the driver that creates an IRP, there is no 'current' stack location.
* Step down one IRP stack location so that the extra top one
* becomes our 'current' one.
*/
IoSetNextIrpStackLocation(irp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -