ReactOS 0.4.15-dev-7958-gcd0bb1a
class.c File Reference
#include "classp.h"
#include "debug.h"
#include <process.h>
#include <devpkey.h>
#include <ntiologc.h>
Include dependency graph for class.c:

Go to the source code of this file.

Macros

#define CLASS_INIT_GUID   1
 
#define DEBUG_MAIN_SOURCE   1
 
#define FirstDriveLetter   'C'
 
#define LastDriveLetter   'Z'
 

Functions

NTSTATUS DllUnload (VOID)
 
NTSTATUS NTAPI DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
 
 _IRQL_requires_max_ (PASSIVE_LEVEL)
 
VOID NTAPI ClassUnload (IN PDRIVER_OBJECT DriverObject)
 
NTSTATUS NTAPI ClassAddDevice (IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)
 
NTSTATUS NTAPI ClassDispatchPnp (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS ClassPnpStartDevice (IN PDEVICE_OBJECT DeviceObject)
 
NTSTATUS NTAPI ClassReadWrite (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
VOID InterpretCapacityData (PDEVICE_OBJECT Fdo, PREAD_CAPACITY_DATA_EX ReadCapacityData)
 
_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity (_In_ PDEVICE_OBJECT Fdo)
 
VOID NTAPI ClassSendStartUnit (_In_ PDEVICE_OBJECT Fdo)
 
NTSTATUS NTAPI ClassAsynchronousCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
 
NTSTATUS ServiceTransferRequest (PDEVICE_OBJECT Fdo, PIRP Irp, BOOLEAN PostToDpc)
 
NTSTATUS NTAPI ClassIoComplete (IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN PVOID Context)
 
NTSTATUS NTAPI ClassSendSrbSynchronous (_In_ PDEVICE_OBJECT Fdo, _Inout_ PSCSI_REQUEST_BLOCK _Srb, _In_reads_bytes_opt_(BufferLength) PVOID BufferAddress, _In_ ULONG BufferLength, _In_ BOOLEAN WriteToDevice)
 
BOOLEAN NTAPI ClassInterpretSenseInfo (_In_ PDEVICE_OBJECT Fdo, _In_ PSCSI_REQUEST_BLOCK _Srb, _In_ UCHAR MajorFunctionCode, _In_ ULONG IoDeviceCode, _In_ ULONG RetryCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, 100) ULONG *RetryInterval)
 
ULONG NTAPI ClassModeSense (_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode)
 
ULONG NTAPI ClassModeSenseEx (_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ UCHAR PageControl)
 
ULONG ClasspModeSense (_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ UCHAR PageControl)
 
PVOID NTAPI ClassFindModePage (_In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ BOOLEAN Use6Byte)
 
NTSTATUS NTAPI ClassModeSelect (_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSelectBuffer, _In_ ULONG Length, _In_ BOOLEAN SavePages)
 
NTSTATUS ClasspModeSelect (_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSelectBuffer, _In_ ULONG Length, _In_ BOOLEAN SavePages)
 
 _Success_ (return==STATUS_PENDING)
 
NTSTATUS NTAPI ClassDeviceControlDispatch (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
NTSTATUS NTAPI ClassDeviceControl (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
 
NTSTATUS NTAPI ClassShutdownFlush (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS ClasspIsPortable (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _Out_ PBOOLEAN IsPortable)
 
NTSTATUS NTAPI ClassInternalIoControl (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS NTAPI ClassCheckVerifyComplete (IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN PVOID Context)
 
NTSTATUS NTAPI ClassSignalCompletion (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
 
NTSTATUS ClassPnpQueryFdoRelations (IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
 
NTSTATUS ClassRetrieveDeviceRelations (IN PDEVICE_OBJECT Fdo, IN DEVICE_RELATION_TYPE RelationType, OUT PDEVICE_RELATIONS *DeviceRelations)
 
NTSTATUS ClassGetPdoId (IN PDEVICE_OBJECT Pdo, IN BUS_QUERY_ID_TYPE IdType, IN PUNICODE_STRING IdString)
 
NTSTATUS ClassQueryPnpCapabilities (IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_CAPABILITIES Capabilities)
 
__drv_aliasesMem _IRQL_requires_max_ (DISPATCH_LEVEL)
 
VOID NTAPI ClasspStartIo (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS NTAPI ClasspSendSynchronousCompletion (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
 
VOID ClasspRegisterMountedDeviceInterface (IN PDEVICE_OBJECT DeviceObject)
 
VOID NTAPI ClassSendDeviceIoControlSynchronous (_In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT TargetDeviceObject, _Inout_updates_opt_(_Inexpressible_(max(InputBufferLength, OutputBufferLength))) PVOID Buffer, _In_ ULONG InputBufferLength, _In_ ULONG OutputBufferLength, _In_ BOOLEAN InternalDeviceIoControl, _Out_ PIO_STATUS_BLOCK IoStatus)
 
NTSTATUS NTAPI ClassForwardIrpSynchronous (_In_ PCOMMON_DEVICE_EXTENSION CommonExtension, _In_ PIRP Irp)
 
NTSTATUS NTAPI ClassSendIrpSynchronous (_In_ PDEVICE_OBJECT TargetDeviceObject, _In_ PIRP Irp)
 
PVPB NTAPI ClassGetVpb (_In_ PDEVICE_OBJECT DeviceObject)
 
NTSTATUS ClasspAllocateReleaseRequest (IN PDEVICE_OBJECT Fdo)
 
VOID ClasspFreeReleaseRequest (IN PDEVICE_OBJECT Fdo)
 
VOID NTAPI ClassReleaseQueue (_In_ PDEVICE_OBJECT Fdo)
 
NTSTATUS ClasspAllocateReleaseQueueIrp (PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspAllocatePowerProcessIrp (PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClasspReleaseQueue (IN PDEVICE_OBJECT Fdo, IN PIRP ReleaseQueueIrp OPTIONAL)
 
NTSTATUS NTAPI ClassReleaseQueueCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
 
VOID NTAPI ClassReleaseChildLock (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClassAddChild (_In_ PFUNCTIONAL_DEVICE_EXTENSION Parent, _In_ PPHYSICAL_DEVICE_EXTENSION Child, _In_ BOOLEAN AcquireLock)
 
PPHYSICAL_DEVICE_EXTENSION ClassRemoveChild (IN PFUNCTIONAL_DEVICE_EXTENSION Parent, IN PPHYSICAL_DEVICE_EXTENSION Child, IN BOOLEAN AcquireLock)
 
VOID NTAPI ClasspRetryRequestDpc (IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID Arg1, IN PVOID Arg2)
 
VOID ClassRetryRequest (IN PDEVICE_OBJECT SelfDeviceObject, IN PIRP Irp, _In_ _In_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) IN LONGLONG TimeDelta100ns)
 
VOID ClasspRetryDpcTimer (IN PCLASS_PRIVATE_FDO_DATA FdoData)
 
NTSTATUS ClasspInitializeHotplugInfo (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID NTAPI ClasspScanForClassHacks (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN ULONG_PTR Data)
 
VOID ClasspScanForSpecialInRegistry (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID NTAPI ClasspUpdateDiskProperties (IN PDEVICE_OBJECT Fdo, IN PVOID Context)
 
BOOLEAN InterpretSenseInfoWithoutHistory (_In_ PDEVICE_OBJECT Fdo, _In_opt_ PIRP OriginalRequest, _In_ PSCSI_REQUEST_BLOCK Srb, UCHAR MajorFunctionCode, ULONG IoDeviceCode, ULONG PreviousRetryCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIn100nsUnits)
 
VOID ClasspGetInquiryVpdSupportInfo (_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspGetLBProvisioningInfo (_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
 _IRQL_requires_ (PASSIVE_LEVEL) ==NDIS_MEMORY_NONCACHED
 
_IRQL_requires_same_ NTSTATUS ClasspGetBlockDeviceTokenLimitsInfo (_Inout_ PDEVICE_OBJECT DeviceObject)
 
 _IRQL_requires_max_ (APC_LEVEL)
 
VOID ClasspCompleteOffloadRequest (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ NTSTATUS CompletionStatus)
 
VOID ClasspPopulateTokenTransferPacketDone (_In_ PVOID Context)
 
VOID ClasspCompleteOffloadRead (_In_ POFFLOAD_READ_CONTEXT OffloadReadContext, _In_ NTSTATUS CompletionStatus)
 
VOID ClasspCleanupOffloadReadContext (_In_ __drv_freesMem(mem) POFFLOAD_READ_CONTEXT OffloadReadContext)
 
_IRQL_requires_same_ VOID ClasspReceivePopulateTokenInformation (_In_ POFFLOAD_READ_CONTEXT OffloadReadContext)
 
VOID ClasspReceivePopulateTokenInformationTransferPacketDone (_In_ PVOID Context)
 
VOID ClasspContinueOffloadWrite (_In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
 
VOID ClasspAdvanceOffloadWritePosition (_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ ULONGLONG SectorsToAdvance)
 
VOID ClasspWriteUsingTokenTransferPacketDone (_In_ PVOID Context)
 
VOID ClasspReceiveWriteUsingTokenInformationDone (_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ NTSTATUS CompletionCausingStatus)
 
VOID ClasspCompleteOffloadWrite (_In_ __drv_freesMem(Mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ NTSTATUS CompletionCausingStatus)
 
VOID ClasspCleanupOffloadWriteContext (_In_ __drv_freesMem(mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
 
_IRQL_requires_same_ VOID ClasspReceiveWriteUsingTokenInformation (_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
 
VOID ClasspReceiveWriteUsingTokenInformationTransferPacketDone (_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
 
NTSTATUS ClasspRefreshFunctionSupportInfo (_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ BOOLEAN ForceQuery)
 
NTSTATUS ClasspBlockLimitsDataSnapshot (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ BOOLEAN ForceQuery, _Out_ PCLASS_VPD_B0_DATA BlockLimitsData, _Out_ PULONG GenerationCount)
 

Variables

IO_COMPLETION_ROUTINE ClassCheckVerifyComplete
 
ULONG ClassPnpAllowUnload = TRUE
 
ULONG ClassMaxInterleavePerCriticalIo = CLASS_MAX_INTERLEAVE_PER_CRITICAL_IO
 
CONST LARGE_INTEGER Magic10000 = {{0xe219652c, 0xd1b71758}}
 
GUID StoragePredictFailureDPSGuid = WDI_STORAGE_PREDICT_FAILURE_DPS_GUID
 
BOOLEAN UseQPCTime = FALSE
 
BOOLEAN InitSecurityCookie = FALSE
 
ULONG MaxTokenOperationListIdentifier = MAX_TOKEN_LIST_IDENTIFIERS
 
volatile ULONG TokenOperationListIdentifier = (ULONG)-1
 
LIST_ENTRY IdlePowerFDOList = {0}
 
KGUARDED_MUTEX IdlePowerFDOListMutex
 
PVOID PowerSettingNotificationHandle
 
PVOID ScreenStateNotificationHandle
 
ULONG DiskIdleTimeoutInMS = 0xFFFFFFFF
 

Macro Definition Documentation

◆ CLASS_INIT_GUID

#define CLASS_INIT_GUID   1

Definition at line 24 of file class.c.

◆ DEBUG_MAIN_SOURCE

#define DEBUG_MAIN_SOURCE   1

Definition at line 25 of file class.c.

◆ FirstDriveLetter

#define FirstDriveLetter   'C'

Definition at line 92 of file class.c.

◆ LastDriveLetter

#define LastDriveLetter   'Z'

Definition at line 93 of file class.c.

Function Documentation

◆ _IRQL_requires_()

_IRQL_requires_ ( PASSIVE_LEVEL  ) ==NDIS_MEMORY_NONCACHED

Definition at line 13147 of file class.c.

13175{
13177
13178 PAGED_CODE();
13179
13180 TracePrint((TRACE_LEVEL_VERBOSE,
13181 TRACE_FLAG_PNP,
13182 "ClassDetermineTokenOperationCommandSupport (%p): Entering function.\n",
13183 DeviceObject));
13184
13185 //
13186 // Send down Inquiry for VPD_THIRD_PARTY_COPY_PAGE and cache away the device parameters
13187 // from WINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR.
13188 //
13190
13191 if (NT_SUCCESS(status)) {
13192
13193 ULONG maxListIdentifier = MaxTokenOperationListIdentifier;
13194
13195 //
13196 // Query the maximum list identifier to use for TokenOperation commands.
13197 //
13198 if (NT_SUCCESS(ClasspGetMaximumTokenListIdentifier(DeviceObject, REG_DISK_CLASS_CONTROL, &maxListIdentifier))) {
13199 if (maxListIdentifier >= MIN_TOKEN_LIST_IDENTIFIERS) {
13200
13201 NT_ASSERT(maxListIdentifier <= MAX_TOKEN_LIST_IDENTIFIERS);
13202 MaxTokenOperationListIdentifier = maxListIdentifier;
13203 }
13204 }
13205
13206 }
13207
13208 TracePrint((TRACE_LEVEL_VERBOSE,
13209 TRACE_FLAG_PNP,
13210 "ClassDetermineTokenOperationCommandSupport (%p): Exiting function with status %x.\n",
13212 status));
13213
13214 return status;
13215}
#define PAGED_CODE()
LONG NTSTATUS
Definition: precomp.h:26
#define REG_DISK_CLASS_CONTROL
Definition: classp.h:218
#define MAX_TOKEN_LIST_IDENTIFIERS
Definition: classp.h:215
#define MIN_TOKEN_LIST_IDENTIFIERS
Definition: classp.h:214
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG MaxTokenOperationListIdentifier
Definition: class.c:107
_IRQL_requires_same_ NTSTATUS ClasspGetBlockDeviceTokenLimitsInfo(_Inout_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:13220
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
Definition: ps.c:97
uint32_t ULONG
Definition: typedefs.h:59
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define NT_ASSERT
Definition: rtlfuncs.h:3310

◆ _IRQL_requires_max_() [1/3]

_IRQL_requires_max_ ( APC_LEVEL  )

Definition at line 13463 of file class.c.

13495{
13496 PIO_STACK_LOCATION irpStack;
13499 PDEVICE_DSM_OFFLOAD_READ_PARAMETERS offloadReadParameters;
13500 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
13501
13503
13504 //
13505 // This function must be called at less than dispatch level.
13506 // Fail if IRQL >= DISPATCH_LEVEL.
13507 //
13508 PAGED_CODE();
13509
13510 TracePrint((TRACE_LEVEL_VERBOSE,
13511 TRACE_FLAG_IOCTL,
13512 "ClassDeviceProcessOffloadRead (%p): Entering function. Irp %p\n",
13514 Irp));
13515
13516
13517 irpStack = IoGetCurrentIrpStackLocation (Irp);
13518
13519 //
13520 // Validations
13521 //
13522 status = ClasspValidateOffloadSupported(DeviceObject, Irp);
13523 if (!NT_SUCCESS(status)) {
13524 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13525 }
13526
13528
13530 TracePrint((TRACE_LEVEL_ERROR,
13531 TRACE_FLAG_IOCTL,
13532 "ClassDeviceProcessOffloadRead (%p): Called at raised IRQL.\n",
13533 DeviceObject));
13534
13536 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13537 }
13538
13539 //
13540 // Ensure that this DSM IOCTL was generated in kernel
13541 //
13542 if (Irp->RequestorMode != KernelMode) {
13543
13544 TracePrint((TRACE_LEVEL_ERROR,
13545 TRACE_FLAG_IOCTL,
13546 "ClassDeviceProcessOffloadRead (%p): Called from user mode.\n",
13547 DeviceObject));
13548
13550 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13551 }
13552
13553 status = ClasspValidateOffloadInputParameters(DeviceObject, Irp);
13554 if (!NT_SUCCESS(status)) {
13555 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13556 }
13557
13558 dsmAttributes = Irp->AssociatedIrp.SystemBuffer;
13559
13560 //
13561 // Validate that we were passed in correct sized parameter block.
13562 //
13563 if (dsmAttributes->ParameterBlockLength < sizeof(DEVICE_DSM_OFFLOAD_READ_PARAMETERS)) {
13564
13565 TracePrint((TRACE_LEVEL_ERROR,
13566 TRACE_FLAG_IOCTL,
13567 "ClassDeviceProcessOffloadRead (%p): Parameter block size (%u) too small. Required %u.\n",
13569 dsmAttributes->ParameterBlockLength,
13571
13573 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13574 }
13575
13576 offloadReadParameters = Add2Ptr(dsmAttributes, dsmAttributes->ParameterBlockOffset);
13577
13578 fdoExtension = DeviceObject->DeviceExtension;
13579
13580 //
13581 // If the request TTL is greater than the max supported by this storage, the target will
13582 // end up failing this command, so might as well do the check up front.
13583 //
13584 if ((fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer > 0) &&
13585 (offloadReadParameters->TimeToLive > fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer)) {
13586
13587 TracePrint((TRACE_LEVEL_ERROR,
13588 TRACE_FLAG_IOCTL,
13589 "ClassDeviceProcessOffloadRead (%p): Requested TTL (%u) greater than max supported (%u).\n",
13591 offloadReadParameters->TimeToLive,
13592 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer));
13593
13595 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13596 }
13597
13598 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_OFFLOAD_READ_OUTPUT)) {
13599
13600 TracePrint((TRACE_LEVEL_ERROR,
13601 TRACE_FLAG_IOCTL,
13602 "ClassDeviceProcessOffloadRead (%p): Output buffer size (%u) too small.\n",
13604 irpStack->Parameters.DeviceIoControl.OutputBufferLength));
13605
13607 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13608 }
13609
13610
13611
13612 status = ClasspServicePopulateTokenTransferRequest(DeviceObject, Irp);
13613
13614 if (status == STATUS_PENDING) {
13615 goto __ClassDeviceProcessOffloadRead_Exit;
13616 }
13617
13618__ClassDeviceProcessOffloadRead_CompleteAndExit:
13620__ClassDeviceProcessOffloadRead_Exit:
13621 TracePrint((TRACE_LEVEL_VERBOSE,
13622 TRACE_FLAG_IOCTL,
13623 "ClassDeviceProcessOffloadRead (%p): Exiting function Irp %p with status %x.\n",
13625 Irp,
13626 status));
13627
13628 return status;
13629}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
_In_ PIRP Irp
Definition: csq.h:116
VOID ClasspCompleteOffloadRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ NTSTATUS CompletionStatus)
Definition: class.c:13632
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define Add2Ptr(PTR, INC)
#define KernelMode
Definition: asm.h:34
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
struct _IO_STACK_LOCATION::@1564::@1565 DeviceIoControl
union _IO_STACK_LOCATION::@1564 Parameters
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135

◆ _IRQL_requires_max_() [2/3]

__drv_aliasesMem _IRQL_requires_max_ ( DISPATCH_LEVEL  )

Definition at line 10631 of file class.c.

10637{
10638#ifdef _MSC_VER
10639#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
10640#endif
10642} // end ClassGetDriverExtension()
#define CLASS_DRIVER_EXTENSION_KEY
Definition: classpnp.h:94
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1904
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213

◆ _IRQL_requires_max_() [3/3]

_IRQL_requires_max_ ( PASSIVE_LEVEL  )

Definition at line 207 of file class.c.

216{
219
220 PCLASS_DRIVER_EXTENSION driverExtension;
221
223
224
225
226 PAGED_CODE();
227
228 //
229 // Initialize the security cookie if needed.
230 //
231#ifndef __REACTOS__
232 if (InitSecurityCookie == FALSE) {
235 }
236#endif
237
238
239 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "\n\nSCSI Class Driver\n"));
240
242
243 //
244 // Validate the length of this structure. This is effectively a
245 // version check.
246 //
247
248 if (InitializationData->InitializationDataSize != sizeof(CLASS_INIT_DATA)) {
249
250 //
251 // This DebugPrint is to help third-party driver writers
252 //
253
254 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassInitialize: Class driver wrong version\n"));
256 }
257
258 //
259 // Check that each required entry is not NULL. Note that Shutdown, Flush and Error
260 // are not required entry points.
261 //
262
263 if ((!InitializationData->FdoData.ClassDeviceControl) ||
264 (!((InitializationData->FdoData.ClassReadWriteVerification) ||
265 (InitializationData->ClassStartIo))) ||
266 (!InitializationData->ClassAddDevice) ||
267 (!InitializationData->FdoData.ClassStartDevice)) {
268
269 //
270 // This DebugPrint is to help third-party driver writers
271 //
272
273 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
274 "ClassInitialize: Class device-specific driver missing required "
275 "FDO entry\n"));
276
278 }
279
280 if ((InitializationData->ClassEnumerateDevice) &&
281 ((!InitializationData->PdoData.ClassDeviceControl) ||
282 (!InitializationData->PdoData.ClassStartDevice) ||
283 (!((InitializationData->PdoData.ClassReadWriteVerification) ||
284 (InitializationData->ClassStartIo))))) {
285
286 //
287 // This DebugPrint is to help third-party driver writers
288 //
289
290 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassInitialize: Class device-specific missing "
291 "required PDO entry\n"));
292
294 }
295
296 if((InitializationData->FdoData.ClassStopDevice == NULL) ||
297 ((InitializationData->ClassEnumerateDevice != NULL) &&
298 (InitializationData->PdoData.ClassStopDevice == NULL))) {
299
300 //
301 // This DebugPrint is to help third-party driver writers
302 //
303
304 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassInitialize: Class device-specific missing "
305 "required PDO entry\n"));
308 }
309
310 //
311 // Setup the default power handlers if the class driver didn't provide
312 // any.
313 //
314
315 if(InitializationData->FdoData.ClassPowerDevice == NULL) {
316 InitializationData->FdoData.ClassPowerDevice = ClassMinimalPowerHandler;
317 }
318
319 if((InitializationData->ClassEnumerateDevice != NULL) &&
320 (InitializationData->PdoData.ClassPowerDevice == NULL)) {
321 InitializationData->PdoData.ClassPowerDevice = ClassMinimalPowerHandler;
322 }
323
324 //
325 // warn that unload is not supported
326 //
327 // ISSUE-2000/02/03-peterwie
328 // We should think about making this a fatal error.
329 //
330
331 if(InitializationData->ClassUnload == NULL) {
332
333 //
334 // This DebugPrint is to help third-party driver writers
335 //
336
337 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClassInitialize: driver does not support unload %wZ\n",
338 RegistryPath));
339 }
340
341 //
342 // Create an extension for the driver object
343 //
344#ifdef _MSC_VER
345#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
346#endif
348
349 if(NT_SUCCESS(status)) {
350
351 //
352 // Copy the registry path into the driver extension so we can use it later
353 //
354
355 driverExtension->RegistryPath.Length = RegistryPath->Length;
356 driverExtension->RegistryPath.MaximumLength = RegistryPath->MaximumLength;
357
358 driverExtension->RegistryPath.Buffer =
360 RegistryPath->MaximumLength,
361 '1CcS');
362
363 if(driverExtension->RegistryPath.Buffer == NULL) {
364
366 return status;
367 }
368
370 &(driverExtension->RegistryPath),
372
373 //
374 // Copy the initialization data into the driver extension so we can reuse
375 // it during our add device routine
376 //
377
379 &(driverExtension->InitData),
381 sizeof(CLASS_INIT_DATA));
382
383 driverExtension->DeviceCount = 0;
384
385 ClassInitializeDispatchTables(driverExtension);
386
387 } else if (status == STATUS_OBJECT_NAME_COLLISION) {
388
389 //
390 // The extension already exists - get a pointer to it
391 //
392#ifdef _MSC_VER
393#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
394#endif
396
397 NT_ASSERT(driverExtension != NULL);
398
399 } else {
400
401 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassInitialize: Class driver extension could not be "
402 "allocated %lx\n", status));
403 return status;
404 }
405
406
407 //
408 // Update driver object with entry points.
409 //
410
411#ifdef _MSC_VER
412#pragma prefast(push)
413#pragma prefast(disable:28175, "Accessing DRIVER_OBJECT fileds is OK here since this function " \
414 "is supposed to be invoked from DriverEntry only")
415#endif
427
428 if (InitializationData->ClassStartIo) {
429 DriverObject->DriverStartIo = ClasspStartIo;
430 }
431
432 if ((InitializationData->ClassUnload) && (ClassPnpAllowUnload == TRUE)) {
433 DriverObject->DriverUnload = ClassUnload;
434 } else {
435 DriverObject->DriverUnload = NULL;
436 }
437
438 DriverObject->DriverExtension->AddDevice = ClassAddDevice;
439#ifdef _MSC_VER
440#pragma prefast(pop)
441#endif
442
443
444 //
445 // Register for event tracing
446 //
447 if (driverExtension->EtwHandle == 0) {
449 NULL,
450 NULL,
451 &driverExtension->EtwHandle);
452 if (!NT_SUCCESS(status)) {
453 driverExtension->EtwHandle = 0;
454 }
456 }
457
458
459 //
460 // Ensure these are only initialized once.
461 //
462 if (IdlePowerFDOList.Flink == NULL) {
465 }
466
468 return status;
469} // end ClassInitialize()
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
NTSTATUS NTAPI ClassMinimalPowerHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: power.c:1890
DRIVER_STARTIO ClasspStartIo
Definition: classp.h:1454
DRIVER_UNLOAD ClassUnload
Definition: classp.h:1356
VOID ClassInitializeDispatchTables(PCLASS_DRIVER_EXTENSION DriverExtension)
Definition: dispatch.c:38
_In_ PVOID _In_ PCLASS_INIT_DATA InitializationData
Definition: classpnp.h:722
_In_ PVOID Argument2
Definition: classpnp.h:721
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define WPP_INIT_TRACING(a, b)
Definition: kdebugprint.h:56
ULONG ClassPnpAllowUnload
Definition: class.c:87
BOOLEAN InitSecurityCookie
Definition: class.c:102
KGUARDED_MUTEX IdlePowerFDOListMutex
Definition: class.c:114
GUID StoragePredictFailureDPSGuid
Definition: class.c:90
LIST_ENTRY IdlePowerFDOList
Definition: class.c:113
#define ClasspInitializeDebugGlobals()
Definition: debug.h:123
NTSTATUS NTAPI ClassGlobalDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: dispatch.c:73
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
static DRIVER_ADD_DEVICE ClassAddDevice
Definition: kbdclass.c:24
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
NTSTATUS NTAPI IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress, IN ULONG DriverObjectExtensionSize, OUT PVOID *DriverObjectExtension)
Definition: driver.c:1826
#define STATUS_REVISION_MISMATCH
Definition: ntstatus.h:325
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
void __cdecl __security_init_cookie(void)
Definition: gs_support.c:55
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
UNICODE_STRING RegistryPath
Definition: kbdclass.h:25
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_IRQL_requires_same_ _In_opt_ PVOID Argument1
Definition: cmtypes.h:696
#define IRP_MJ_SCSI
#define IRP_MJ_SYSTEM_CONTROL
#define IRP_MJ_FLUSH_BUFFERS
#define IRP_MJ_SHUTDOWN
#define IRP_MJ_POWER

◆ _Success_()

_Success_ ( return  = STATUS_PENDING)

Definition at line 7019 of file class.c.

7030{
7031
7032 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
7033 PIO_STACK_LOCATION irpStack;
7035
7036 ULONG savedFlags;
7037
7039 //
7040 // Write length to SRB.
7041 //
7042
7043 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
7044
7045 //
7046 // Set SCSI bus address.
7047 //
7048
7050 }
7051
7052 //
7053 // This is a violation of the SCSI spec but it is required for
7054 // some targets.
7055 //
7056
7057 // Srb->Cdb[1] |= deviceExtension->Lun << 5;
7058
7059 //
7060 // Indicate auto request sense by specifying buffer and size.
7061 //
7062
7063 SrbSetSenseInfoBuffer(Srb, fdoExtension->SenseData);
7065
7067
7068 //
7069 // Set the transfer length.
7070 //
7072
7073 //
7074 // Save the class driver specific flags away.
7075 //
7076
7078
7079 //
7080 // Allow the caller to specify that they do not wish
7081 // IoStartNextPacket() to be called in the completion routine.
7082 //
7083
7085
7086 //
7087 // If caller wants to this request to be tagged, save this fact.
7088 //
7089
7094
7098 }
7099 }
7100
7101 if (BufferAddress != NULL) {
7102
7103 //
7104 // Build Mdl if necessary.
7105 //
7106
7107 if (Irp->MdlAddress == NULL) {
7108
7109 PMDL mdl;
7110
7113 FALSE,
7114 FALSE,
7115 Irp);
7116
7117 if ((mdl == NULL) || (Irp->MdlAddress == NULL)) {
7118
7119 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
7120
7121 //
7122 // ClassIoComplete() would have free'd the srb
7123 //
7124
7125 if (PORT_ALLOCATED_SENSE_EX(fdoExtension, Srb)) {
7127 }
7131
7133 }
7134
7136
7137 MmBuildMdlForNonPagedPool(Irp->MdlAddress);
7138
7139 } else {
7140
7141 //
7142 // Make sure the buffer requested matches the MDL.
7143 //
7144
7146 }
7147
7148 //
7149 // Set read flag.
7150 //
7151
7153
7154 } else {
7155
7156 //
7157 // Clear flags.
7158 //
7159
7161 }
7162
7163 //
7164 // Restore saved flags.
7165 //
7166
7167 SrbSetSrbFlags(Srb, savedFlags);
7168
7169 //
7170 // Disable synchronous transfer for these requests.
7171 //
7172
7174
7175 //
7176 // Zero out status.
7177 //
7178
7180 Srb->SrbStatus = 0;
7181
7183
7184 //
7185 // Save a few parameters in the current stack location.
7186 //
7187
7189
7190 //
7191 // Save retry count in current Irp stack.
7192 //
7193
7194 irpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
7195
7196 //
7197 // Set up IoCompletion routine address.
7198 //
7199
7201
7202 //
7203 // Get next stack location and
7204 // set major function code.
7205 //
7206
7207 irpStack = IoGetNextIrpStackLocation(Irp);
7208
7209 irpStack->MajorFunction = IRP_MJ_SCSI;
7210
7211 //
7212 // Save SRB address in next stack for port driver.
7213 //
7214
7215 irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)Srb;
7216
7217 //
7218 // Set up Irp Address.
7219 //
7220
7222
7223 //
7224 // Call the port driver to process the request.
7225 //
7226
7228
7230
7231 return STATUS_PENDING;
7232
7233} // end ClassSendSrbAsynchronous()
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID BufferAddress
Definition: cdrom.h:990
#define MAXIMUM_RETRIES
Definition: cdrom.h:124
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:992
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
FORCEINLINE BOOLEAN PORT_ALLOCATED_SENSE_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2547
VOID ClassFreeOrReuseSrb(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN __drv_freesMem(mem) PSCSI_REQUEST_BLOCK Srb)
Definition: obsolete.c:882
FORCEINLINE VOID FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2560
#define SRB_CLASS_FLAGS_FREE_MDL
Definition: classpnp.h:22
FORCEINLINE UCHAR GET_FDO_EXTENSON_SENSE_DATA_LENGTH(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classpnp.h:1437
NTSTATUS NTAPI ClassIoComplete(IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN PVOID Context)
Definition: class.c:3768
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define SRB_FLAGS_CLASS_DRIVER_RESERVED
Definition: srb.h:418
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FLAGS_DONT_START_NEXT_PACKET
Definition: srb.h:415
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:401
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:402
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:423
#define SRB_ORDERED_QUEUE_TAG_REQUEST
Definition: srb.h:425
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:395
#define SRB_HEAD_OF_QUEUE_TAG_REQUEST
Definition: srb.h:424
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:404
MDL * mdl
#define IoAllocateMdl
Definition: fxmdl.h:88
IoMarkIrpPending(Irp)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:424
#define IoCallDriver
Definition: irp.c:1225
#define SRB_FUNCTION_STORAGE_REQUEST_BLOCK
Definition: srb.h:108
struct SRB_ALIGN _STORAGE_REQUEST_BLOCK_HEADER * PSTORAGE_REQUEST_BLOCK_HEADER
FORCEINLINE VOID SrbSetSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:964
FORCEINLINE VOID SrbAssignSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:946
FORCEINLINE VOID SrbSetDataTransferLength(_In_ PVOID Srb, _In_ ULONG DataTransferLength)
Definition: srbhelper.h:784
FORCEINLINE VOID SrbSetNextSrb(_In_ PVOID Srb, _In_opt_ PVOID NextSrb)
Definition: srbhelper.h:909
FORCEINLINE VOID SrbSetOriginalRequest(_In_ PVOID Srb, _In_opt_ PVOID OriginalRequest)
Definition: srbhelper.h:710
FORCEINLINE VOID SrbSetScsiStatus(_In_ PVOID Srb, _In_ UCHAR ScsiStatus)
Definition: srbhelper.h:1056
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
FORCEINLINE ULONG SrbGetSrbFlags(_In_ PVOID Srb)
Definition: srbhelper.h:927
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
FORCEINLINE ULONG SrbGetRequestAttribute(_In_ PVOID Srb)
Definition: srbhelper.h:1111
FORCEINLINE VOID SrbSetDataBuffer(_In_ PVOID Srb, _In_opt_ __drv_aliasesMem PVOID DataBuffer)
Definition: srbhelper.h:747
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
struct _IO_STACK_LOCATION::@3978::@4017 Others
struct _IO_STACK_LOCATION::@3978::@4000 Scsi
UCHAR Function
Definition: srb.h:250
USHORT Length
Definition: srb.h:249
UCHAR SrbStatus
Definition: srb.h:251
void * PVOID
Definition: typedefs.h:50
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_Must_inspect_result_ _In_ WDFDEVICE Fdo
Definition: wdffdo.h:461
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define MmGetMdlVirtualAddress(_Mdl)

◆ ClassAddChild()

VOID ClassAddChild ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  Parent,
_In_ PPHYSICAL_DEVICE_EXTENSION  Child,
_In_ BOOLEAN  AcquireLock 
)

Definition at line 12058 of file class.c.

12063{
12064 if(AcquireLock) {
12065 ClassAcquireChildLock(Parent);
12066 }
12067
12068 #if DBG
12069 //
12070 // Make sure this child's not already in the list.
12071 //
12072 {
12074
12075 for (testChild = Parent->CommonExtension.ChildList;
12076 testChild != NULL;
12077 testChild = testChild->CommonExtension.ChildList) {
12078
12079 NT_ASSERT(testChild != Child);
12080 }
12081 }
12082 #endif
12083
12084 Child->CommonExtension.ChildList = Parent->CommonExtension.ChildList;
12085 Parent->CommonExtension.ChildList = Child;
12086
12087 if(AcquireLock) {
12089 }
12090 return;
12091} // end ClassAddChild()
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
VOID NTAPI ClassReleaseChildLock(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:12019
pPkgPnp m_DeviceInterfaceLock AcquireLock(pFxDriverGlobals)
struct _PHYSICAL_DEVICE_EXTENSION * ChildList
Definition: classpnp.h:616
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:652
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536

◆ ClassAddDevice()

NTSTATUS NTAPI ClassAddDevice ( IN PDRIVER_OBJECT  DriverObject,
IN PDEVICE_OBJECT  PhysicalDeviceObject 
)

Definition at line 851 of file class.c.

855{
856#ifdef _MSC_VER
857#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
858#endif
860
862
863 PAGED_CODE();
864
865
866 status = driverExtension->InitData.ClassAddDevice(DriverObject,
868
869 return status;
870} // end ClassAddDevice()
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
PCLASS_ADD_DEVICE ClassAddDevice
Definition: classpnp.h:540

◆ ClassAsynchronousCompletion()

NTSTATUS NTAPI ClassAsynchronousCompletion ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp,
PVOID  Context 
)

Definition at line 3246 of file class.c.

3251{
3254 ULONG srbFunction;
3255 ULONG srbFlags;
3256
3257 if (context == NULL) {
3259 }
3260
3261 if (DeviceObject == NULL) {
3262
3263 DeviceObject = context->DeviceObject;
3264 }
3265
3266 srb = &context->Srb.Srb;
3267
3269 srbFunction = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFunction;
3270 srbFlags = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFlags;
3271 } else {
3272 srbFunction = srb->Function;
3273 srbFlags = srb->SrbFlags;
3274 }
3275
3276 //
3277 // If this is an execute srb, then check the return status and make sure.
3278 // the queue is not frozen.
3279 //
3280
3281 if (srbFunction == SRB_FUNCTION_EXECUTE_SCSI) {
3282
3283 //
3284 // Check for a frozen queue.
3285 //
3286
3288
3289 //
3290 // Unfreeze the queue getting the device object from the context.
3291 //
3292
3293 ClassReleaseQueue(context->DeviceObject);
3294 }
3295 }
3296
3297 { // free port-allocated sense buffer if we can detect
3298
3299 if (((PCOMMON_DEVICE_EXTENSION)(DeviceObject->DeviceExtension))->IsFdo) {
3300
3301 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
3302 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
3303 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
3304 }
3305
3306 } else {
3307
3309
3310 }
3311 }
3312
3313
3314 //
3315 // Free the context and the Irp.
3316 //
3317
3318 if (Irp->MdlAddress != NULL) {
3319 MmUnlockPages(Irp->MdlAddress);
3320 IoFreeMdl(Irp->MdlAddress);
3321
3322 Irp->MdlAddress = NULL;
3323 }
3324
3326
3328
3329 IoFreeIrp(Irp);
3330
3331 //
3332 // Indicate the I/O system should stop processing the Irp completion.
3333 //
3334
3336
3337} // end ClassAsynchronousCompletion()
FORCEINLINE BOOLEAN PORT_ALLOCATED_SENSE(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: cdrom.h:826
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
FORCEINLINE VOID FREE_PORT_ALLOCATED_SENSE_BUFFER(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: cdrom.h:839
VOID NTAPI ClassReleaseQueue(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:11589
#define SRB_FLAGS_FREE_SENSE_BUFFER
Definition: srb.h:406
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:386
#define IoFreeMdl
Definition: fxmdl.h:89
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:661
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
ULONG SrbFlags
Definition: srb.h:260
Definition: http.c:7252

Referenced by ClassSendStartUnit(), ResetBus(), and ScsiFlopProcessError().

◆ ClassCheckVerifyComplete()

NTSTATUS NTAPI ClassCheckVerifyComplete ( IN PDEVICE_OBJECT  Fdo,
IN PIRP  Irp,
IN PVOID  Context 
)

Definition at line 9578 of file class.c.

9583{
9585 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
9586
9587 PIRP originalIrp;
9588
9590
9591 ASSERT_FDO(Fdo);
9592
9593 originalIrp = irpStack->Parameters.Others.Argument1;
9594
9595 //
9596 // Copy the media change count and status
9597 //
9598
9599 *((PULONG) (originalIrp->AssociatedIrp.SystemBuffer)) =
9600 fdoExtension->MediaChangeCount;
9601
9602 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClassCheckVerifyComplete - Media change count for"
9603 "device %d is %lx - saved as %lx\n",
9604 fdoExtension->DeviceNumber,
9605 fdoExtension->MediaChangeCount,
9606 *((PULONG) originalIrp->AssociatedIrp.SystemBuffer)));
9607
9608 originalIrp->IoStatus.Status = Irp->IoStatus.Status;
9609 originalIrp->IoStatus.Information = sizeof(ULONG);
9610
9611 ClassReleaseRemoveLock(Fdo, originalIrp);
9613
9614 IoFreeIrp(Irp);
9615
9617
9618} // end ClassCheckVerifyComplete()
#define ASSERT_FDO(x)
Definition: pci.h:37
PVOID SystemBuffer
IO_STATUS_BLOCK IoStatus
union _IRP::@1566 AssociatedIrp
uint32_t * PULONG
Definition: typedefs.h:59
#define IO_DISK_INCREMENT
Definition: iotypes.h:600

◆ ClassDeviceControl()

NTSTATUS NTAPI ClassDeviceControl ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp 
)

Definition at line 7317 of file class.c.

7321{
7322 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
7323
7325 PIO_STACK_LOCATION nextStack = NULL;
7326
7327 ULONG controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
7328
7330 PCDB cdb = NULL;
7331
7333 ULONG modifiedIoControlCode = 0;
7334 GUID activityId = {0};
7335
7336
7337 //
7338 // If this is a pass through I/O control, set the minor function code
7339 // and device address and pass it to the port driver.
7340 //
7341
7342 if ( (controlCode == IOCTL_SCSI_PASS_THROUGH) ||
7343 (controlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) ||
7344 (controlCode == IOCTL_SCSI_PASS_THROUGH_EX) ||
7345 (controlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT_EX) ) {
7346
7347
7348
7349 //
7350 // Validiate the user buffer for SCSI pass through.
7351 // For pass through EX: as the handler will validate the size anyway,
7352 // do not apply the similar check and leave the work to the handler.
7353 //
7354 if ( (controlCode == IOCTL_SCSI_PASS_THROUGH) ||
7355 (controlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) ) {
7356
7357 #if BUILD_WOW64_ENABLED && defined(_WIN64)
7358
7359 if (IoIs32bitProcess(Irp)) {
7360
7361 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32)){
7362
7363 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
7364
7367
7369 goto SetStatusAndReturn;
7370 }
7371 }
7372 else
7373
7374 #endif
7375
7376 {
7377 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
7378 sizeof(SCSI_PASS_THROUGH)) {
7379
7380 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
7381
7384
7386 goto SetStatusAndReturn;
7387 }
7388 }
7389 }
7390
7391
7393
7394 nextStack = IoGetNextIrpStackLocation(Irp);
7395 nextStack->MinorFunction = 1;
7396
7398
7399 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
7400 goto SetStatusAndReturn;
7401
7402 }
7403
7404 Irp->IoStatus.Information = 0;
7405
7406
7407 switch (controlCode) {
7408
7410
7411 PMOUNTDEV_UNIQUE_ID uniqueId;
7412
7413 if (!commonExtension->MountedDeviceInterfaceName.Buffer) {
7415 break;
7416 }
7417
7418 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7419 sizeof(MOUNTDEV_UNIQUE_ID)) {
7420
7422 Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
7423 break;
7424 }
7425
7426 uniqueId = Irp->AssociatedIrp.SystemBuffer;
7427 RtlZeroMemory(uniqueId, sizeof(MOUNTDEV_UNIQUE_ID));
7428 uniqueId->UniqueIdLength =
7429 commonExtension->MountedDeviceInterfaceName.Length;
7430
7431 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7432 sizeof(USHORT) + uniqueId->UniqueIdLength) {
7433
7435 Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
7436 break;
7437 }
7438
7439 RtlCopyMemory(uniqueId->UniqueId,
7440 commonExtension->MountedDeviceInterfaceName.Buffer,
7441 uniqueId->UniqueIdLength);
7442
7444 Irp->IoStatus.Information = sizeof(USHORT) +
7445 uniqueId->UniqueIdLength;
7446 break;
7447 }
7448
7450
7452
7453 NT_ASSERT(commonExtension->DeviceName.Buffer);
7454
7455 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7456 sizeof(MOUNTDEV_NAME)) {
7457
7459 Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
7460 break;
7461 }
7462
7463 name = Irp->AssociatedIrp.SystemBuffer;
7465 name->NameLength = commonExtension->DeviceName.Length;
7466
7467 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7468 sizeof(USHORT) + name->NameLength) {
7469
7471 Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
7472 break;
7473 }
7474
7475 RtlCopyMemory(name->Name, commonExtension->DeviceName.Buffer,
7476 name->NameLength);
7477
7479 Irp->IoStatus.Information = sizeof(USHORT) + name->NameLength;
7480 break;
7481 }
7482
7484
7485 PMOUNTDEV_SUGGESTED_LINK_NAME suggestedName;
7486 WCHAR driveLetterNameBuffer[10] = {0};
7487 RTL_QUERY_REGISTRY_TABLE queryTable[2] = {0};
7488 PWSTR valueName;
7489 UNICODE_STRING driveLetterName;
7490
7491 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7493
7495 Irp->IoStatus.Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
7496 break;
7497 }
7498
7499 valueName = ExAllocatePoolWithTag(
7500 PagedPool,
7501 commonExtension->DeviceName.Length + sizeof(WCHAR),
7502 '8CcS');
7503
7504 if (!valueName) {
7506 break;
7507 }
7508
7509 RtlCopyMemory(valueName, commonExtension->DeviceName.Buffer,
7510 commonExtension->DeviceName.Length);
7511 valueName[commonExtension->DeviceName.Length/sizeof(WCHAR)] = 0;
7512
7513 driveLetterName.Buffer = driveLetterNameBuffer;
7514 driveLetterName.MaximumLength = sizeof(driveLetterNameBuffer);
7515 driveLetterName.Length = 0;
7516
7517 queryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED |
7520 queryTable[0].Name = valueName;
7521 queryTable[0].EntryContext = &driveLetterName;
7523
7525 L"\\Registry\\Machine\\System\\DISK",
7526 queryTable, NULL, NULL);
7527
7528 if (!NT_SUCCESS(status)) {
7529 FREE_POOL(valueName);
7530 break;
7531 }
7532
7533 if (driveLetterName.Length == 4 &&
7534 driveLetterName.Buffer[0] == '%' &&
7535 driveLetterName.Buffer[1] == ':') {
7536
7537 driveLetterName.Buffer[0] = 0xFF;
7538
7539 } else if (driveLetterName.Length != 4 ||
7540 driveLetterName.Buffer[0] < FirstDriveLetter ||
7541 driveLetterName.Buffer[0] > LastDriveLetter ||
7542 driveLetterName.Buffer[1] != ':') {
7543
7545 FREE_POOL(valueName);
7546 break;
7547 }
7548
7549 suggestedName = Irp->AssociatedIrp.SystemBuffer;
7550 RtlZeroMemory(suggestedName, sizeof(MOUNTDEV_SUGGESTED_LINK_NAME));
7551 suggestedName->UseOnlyIfThereAreNoOtherLinks = TRUE;
7552 suggestedName->NameLength = 28;
7553
7554 Irp->IoStatus.Information =
7556
7557 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7558 Irp->IoStatus.Information) {
7559
7560 Irp->IoStatus.Information =
7563 FREE_POOL(valueName);
7564 break;
7565 }
7566
7568 L"\\Registry\\Machine\\System\\DISK",
7569 valueName);
7570
7571 FREE_POOL(valueName);
7572
7573 RtlCopyMemory(suggestedName->Name, L"\\DosDevices\\", 24);
7574 suggestedName->Name[12] = driveLetterName.Buffer[0];
7575 suggestedName->Name[13] = ':';
7576
7577 //
7578 // NT_SUCCESS(status) based on RtlQueryRegistryValues
7579 //
7581
7582 break;
7583 }
7584
7585 default:
7587 break;
7588 }
7589
7590 if (status != STATUS_PENDING) {
7592 Irp->IoStatus.Status = status;
7593
7594
7596 return status;
7597 }
7598
7599 if (commonExtension->IsFdo){
7600
7601 PULONG_PTR function;
7602 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)commonExtension;
7603 size_t sizeNeeded;
7604
7605 //
7606 // Allocate a SCSI SRB for handling various IOCTLs.
7607 // NOTE - there is a case where an IOCTL is sent to classpnp before AdapterDescriptor
7608 // is initialized. In this case, default to legacy SRB.
7609 //
7610 if ((fdoExtension->AdapterDescriptor != NULL) &&
7611 (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
7613 } else {
7614 sizeNeeded = sizeof(SCSI_REQUEST_BLOCK);
7615 }
7616
7617 srb = ExAllocatePoolWithTag(NonPagedPoolNx,
7618 sizeNeeded +
7619 (sizeof(ULONG_PTR) * 2),
7620 '9CcS');
7621
7622 if (srb == NULL) {
7623
7624 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
7628 goto SetStatusAndReturn;
7629 }
7630
7631 if ((fdoExtension->AdapterDescriptor != NULL) &&
7632 (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
7636 1,
7638 if (NT_SUCCESS(status)) {
7640 function = (PULONG_PTR)((PCHAR)srb + sizeNeeded);
7641 } else {
7642 //
7643 // Should not occur.
7644 //
7646 goto SetStatusAndReturn;
7647 }
7648 } else {
7649 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
7650 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
7651 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
7652 function = (PULONG_PTR) ((PSCSI_REQUEST_BLOCK) (srb + 1));
7653 }
7654
7655 //
7656 // Save the function code and the device object in the memory after
7657 // the SRB.
7658 //
7659
7660 *function = (ULONG_PTR) DeviceObject;
7661 function++;
7662 *function = (ULONG_PTR) controlCode;
7663
7664 } else {
7665 srb = NULL;
7666 }
7667
7668 //
7669 // Change the device type to storage for the switch statement, but only
7670 // if from a legacy device type
7671 //
7672
7673 if (((controlCode & 0xffff0000) == (IOCTL_DISK_BASE << 16)) ||
7674 ((controlCode & 0xffff0000) == (IOCTL_TAPE_BASE << 16)) ||
7675 ((controlCode & 0xffff0000) == (IOCTL_CDROM_BASE << 16))
7676 ) {
7677
7678 modifiedIoControlCode = (controlCode & ~0xffff0000);
7679 modifiedIoControlCode |= (IOCTL_STORAGE_BASE << 16);
7680
7681 } else {
7682
7683 modifiedIoControlCode = controlCode;
7684
7685 }
7686
7687 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, "> ioctl %xh (%s)", modifiedIoControlCode, DBGGETIOCTLSTR(modifiedIoControlCode)));
7688
7689
7690 switch (modifiedIoControlCode) {
7691
7693
7694 FREE_POOL(srb);
7695
7696 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7697 sizeof(STORAGE_HOTPLUG_INFO)) {
7698
7699 //
7700 // Indicate unsuccessful status and no data transferred.
7701 //
7702
7703 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
7704 Irp->IoStatus.Information = sizeof(STORAGE_HOTPLUG_INFO);
7705
7709
7710 } else if (!commonExtension->IsFdo) {
7711
7712
7713 //
7714 // Just forward this down and return
7715 //
7716
7718
7720 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
7721
7722 } else {
7723
7724 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
7726
7727 fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)commonExtension;
7728 info = Irp->AssociatedIrp.SystemBuffer;
7729
7730 *info = fdoExtension->PrivateFdoData->HotplugInfo;
7731 Irp->IoStatus.Status = STATUS_SUCCESS;
7732 Irp->IoStatus.Information = sizeof(STORAGE_HOTPLUG_INFO);
7736 }
7737 break;
7738 }
7739
7741
7742 FREE_POOL(srb);
7743
7744 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
7745 sizeof(STORAGE_HOTPLUG_INFO)) {
7746
7747 //
7748 // Indicate unsuccessful status and no data transferred.
7749 //
7750
7751 Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH;
7752
7756 goto SetStatusAndReturn;
7757
7758 }
7759
7760 if (!commonExtension->IsFdo) {
7761
7762
7763 //
7764 // Just forward this down and return
7765 //
7766
7768
7770 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
7771
7772 } else {
7773
7774 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)commonExtension;
7775 PSTORAGE_HOTPLUG_INFO info = Irp->AssociatedIrp.SystemBuffer;
7776
7778
7779 if (info->Size != fdoExtension->PrivateFdoData->HotplugInfo.Size)
7780 {
7782 }
7783
7784 if (info->MediaRemovable != fdoExtension->PrivateFdoData->HotplugInfo.MediaRemovable)
7785 {
7787 }
7788
7789 if (info->MediaHotplug != fdoExtension->PrivateFdoData->HotplugInfo.MediaHotplug)
7790 {
7792 }
7793
7794 if (NT_SUCCESS(status))
7795 {
7796 if (info->WriteCacheEnableOverride != fdoExtension->PrivateFdoData->HotplugInfo.WriteCacheEnableOverride)
7797 {
7798 fdoExtension->PrivateFdoData->HotplugInfo.WriteCacheEnableOverride = info->WriteCacheEnableOverride;
7799
7800 //
7801 // Store the user-defined override in the registry
7802 //
7803
7804 ClassSetDeviceParameter(fdoExtension,
7807 info->WriteCacheEnableOverride);
7808 }
7809
7810 fdoExtension->PrivateFdoData->HotplugInfo.DeviceHotplug = info->DeviceHotplug;
7811
7812 //
7813 // Store the user-defined override in the registry
7814 //
7815
7816 ClassSetDeviceParameter(fdoExtension,
7820 }
7821
7822 Irp->IoStatus.Status = status;
7823
7826 }
7827
7828 break;
7829 }
7830
7833
7834 PIRP irp2 = NULL;
7835 PIO_STACK_LOCATION newStack;
7836
7837 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;
7838
7839 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DeviceIoControl: Check verify\n"));
7840
7841 //
7842 // If a buffer for a media change count was provided, make sure it's
7843 // big enough to hold the result
7844 //
7845
7846 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength) {
7847
7848 //
7849 // If the buffer is too small to hold the media change count
7850 // then return an error to the caller
7851 //
7852
7853 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7854 sizeof(ULONG)) {
7855
7856 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "DeviceIoControl: media count "
7857 "buffer too small\n"));
7858
7859 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
7860 Irp->IoStatus.Information = sizeof(ULONG);
7861
7862 FREE_POOL(srb);
7863
7866
7868 goto SetStatusAndReturn;
7869 }
7870 }
7871
7872 if (!commonExtension->IsFdo) {
7873
7874
7875 //
7876 // If this is a PDO then we should just forward the request down
7877 //
7878 NT_ASSERT(!srb);
7879
7881
7883
7884 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
7885
7886 goto SetStatusAndReturn;
7887
7888 } else {
7889
7890 fdoExtension = DeviceObject->DeviceExtension;
7891
7892 }
7893
7894 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength) {
7895
7896 //
7897 // The caller has provided a valid buffer. Allocate an additional
7898 // irp and stick the CheckVerify completion routine on it. We will
7899 // then send this down to the port driver instead of the irp the
7900 // caller sent in
7901 //
7902
7903 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DeviceIoControl: Check verify wants "
7904 "media count\n"));
7905
7906 //
7907 // Allocate a new irp to send the TestUnitReady to the port driver
7908 //
7909
7910 irp2 = IoAllocateIrp((CCHAR) (DeviceObject->StackSize + 3), FALSE);
7911
7912 if (irp2 == NULL) {
7913 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
7914 Irp->IoStatus.Information = 0;
7915 FREE_POOL(srb);
7919 goto SetStatusAndReturn;
7920
7921 break;
7922 }
7923
7924 //
7925 // Make sure to acquire the lock for the new irp.
7926 //
7927
7929
7930 irp2->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
7932
7933 //
7934 // Set the top stack location and shove the master Irp into the
7935 // top location
7936 //
7937
7938 newStack = IoGetCurrentIrpStackLocation(irp2);
7939 newStack->Parameters.Others.Argument1 = Irp;
7940 newStack->DeviceObject = DeviceObject;
7941
7942 //
7943 // Stick the check verify completion routine onto the stack
7944 // and prepare the irp for the port driver
7945 //
7946
7949 NULL,
7950 TRUE,
7951 TRUE,
7952 TRUE);
7953
7955 newStack = IoGetCurrentIrpStackLocation(irp2);
7956 newStack->DeviceObject = DeviceObject;
7957 newStack->MajorFunction = irpStack->MajorFunction;
7958 newStack->MinorFunction = irpStack->MinorFunction;
7959 newStack->Flags = irpStack->Flags;
7960
7961
7962 //
7963 // Mark the master irp as pending - whether the lower level
7964 // driver completes it immediately or not this should allow it
7965 // to go all the way back up.
7966 //
7967
7969
7970 Irp = irp2;
7971
7972 }
7973
7974 //
7975 // Test Unit Ready
7976 //
7977
7978 SrbSetCdbLength(srb, 6);
7979 cdb = SrbGetCdb(srb);
7980 cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
7981
7982 //
7983 // Set timeout value.
7984 //
7985
7986 SrbSetTimeOutValue(srb, fdoExtension->TimeOutValue);
7987
7988 //
7989 // If this was a CV2 then mark the request as low-priority so we don't
7990 // spin up the drive just to satisfy it.
7991 //
7992
7993 if (controlCode == IOCTL_STORAGE_CHECK_VERIFY2) {
7995 }
7996
7997 //
7998 // Since this routine will always hand the request to the
7999 // port driver if there isn't a data transfer to be done
8000 // we don't have to worry about completing the request here
8001 // on an error
8002 //
8003
8004 //
8005 // This routine uses a completion routine so we don't want to release
8006 // the remove lock until then.
8007 //
8008
8010 srb,
8011 Irp,
8012 NULL,
8013 0,
8014 FALSE);
8015
8016 break;
8017 }
8018
8021
8022 PPREVENT_MEDIA_REMOVAL mediaRemoval = Irp->AssociatedIrp.SystemBuffer;
8023
8024 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DiskIoControl: ejection control\n"));
8025
8026 FREE_POOL(srb);
8027
8028 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
8029 sizeof(PREVENT_MEDIA_REMOVAL)) {
8030
8031 //
8032 // Indicate unsuccessful status and no data transferred.
8033 //
8034
8035 Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH;
8036
8040 goto SetStatusAndReturn;
8041 }
8042
8043 if (!commonExtension->IsFdo) {
8044
8045
8046 //
8047 // Just forward this down and return
8048 //
8049
8051
8053 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8054 }
8055 else {
8056
8057 // i don't believe this assertion is valid. this is a request
8058 // from user-mode, so they could request this for any device
8059 // they want? also, we handle it properly.
8060 // NT_ASSERT(TEST_FLAG(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA));
8063 Irp,
8064 ((modifiedIoControlCode ==
8067 mediaRemoval->PreventMediaRemoval);
8068
8069 Irp->IoStatus.Status = status;
8072 }
8073
8074 break;
8075 }
8076
8078
8079 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DiskIoControl: MCN control\n"));
8080
8081 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
8082 sizeof(PREVENT_MEDIA_REMOVAL)) {
8083
8084 //
8085 // Indicate unsuccessful status and no data transferred.
8086 //
8087
8088 Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH;
8089 Irp->IoStatus.Information = 0;
8090
8091 FREE_POOL(srb);
8092
8096 goto SetStatusAndReturn;
8097 }
8098
8099 if (!commonExtension->IsFdo) {
8100
8101
8102 //
8103 // Just forward this down and return
8104 //
8105
8106 FREE_POOL(srb);
8107
8109
8111 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8112
8113 } else {
8114
8115 //
8116 // Call to the FDO - handle the ejection control.
8117 //
8118
8119 status = ClasspMcnControl(DeviceObject->DeviceExtension,
8120 Irp,
8121 srb);
8122 }
8123 goto SetStatusAndReturn;
8124 }
8125
8127 case IOCTL_STORAGE_RELEASE: {
8128
8129 //
8130 // Reserve logical unit.
8131 //
8132
8133 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;
8134
8135 if (!commonExtension->IsFdo) {
8136
8137
8139
8141 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8142 goto SetStatusAndReturn;
8143
8144 } else {
8145 fdoExtension = DeviceObject->DeviceExtension;
8146 }
8147
8148 if (TEST_FLAG(fdoExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_RESERVE6))
8149 {
8150 SrbSetCdbLength(srb, 10);
8151 cdb = SrbGetCdb(srb);
8152 cdb->CDB10.OperationCode = (modifiedIoControlCode == IOCTL_STORAGE_RESERVE) ? SCSIOP_RESERVE_UNIT10 : SCSIOP_RELEASE_UNIT10;
8153 }
8154 else
8155 {
8156 SrbSetCdbLength(srb, 6);
8157 cdb = SrbGetCdb(srb);
8158 cdb->CDB6GENERIC.OperationCode = (modifiedIoControlCode == IOCTL_STORAGE_RESERVE) ? SCSIOP_RESERVE_UNIT : SCSIOP_RELEASE_UNIT;
8159 }
8160
8161 //
8162 // Set timeout value.
8163 //
8164
8165 SrbSetTimeOutValue(srb, fdoExtension->TimeOutValue);
8166
8167 //
8168 // Send reserves as tagged requests.
8169 //
8170
8171 if ( IOCTL_STORAGE_RESERVE == modifiedIoControlCode ) {
8174 }
8175
8177 srb,
8178 Irp,
8179 NULL,
8180 0,
8181 FALSE);
8182
8183 break;
8184 }
8185
8188
8189 if (!commonExtension->IsFdo) {
8190
8192
8194 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8195 goto SetStatusAndReturn;
8196 }
8197
8198 //
8199 // Process Persistent Reserve
8200 //
8201
8203
8204 break;
8205
8206 }
8207
8211
8212 //
8213 // Eject media.
8214 //
8215
8216 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;
8217
8218 if (!commonExtension->IsFdo) {
8219
8220
8222
8224
8225 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8226 goto SetStatusAndReturn;
8227 } else {
8228 fdoExtension = DeviceObject->DeviceExtension;
8229 }
8230
8231 if (commonExtension->PagingPathCount != 0) {
8232
8233 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "ClassDeviceControl: call to eject paging device - "
8234 "failure\n"));
8235
8237 Irp->IoStatus.Status = status;
8238
8239 Irp->IoStatus.Information = 0;
8240
8241 FREE_POOL(srb);
8242
8245 goto SetStatusAndReturn;
8246 }
8247
8248 //
8249 // Synchronize with ejection control and ejection cleanup code as
8250 // well as other eject/load requests.
8251 //
8252
8256 KernelMode,
8257 FALSE,
8258 NULL);
8259
8260 if (fdoExtension->ProtectedLockCount != 0) {
8261
8262 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "ClassDeviceControl: call to eject protected locked "
8263 "device - failure\n"));
8264
8266 Irp->IoStatus.Status = status;
8267 Irp->IoStatus.Information = 0;
8268
8269 FREE_POOL(srb);
8270
8273
8276 FALSE);
8278
8279 goto SetStatusAndReturn;
8280 }
8281
8282 SrbSetCdbLength(srb, 6);
8283 cdb = SrbGetCdb(srb);
8284
8285 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
8286 cdb->START_STOP.LoadEject = 1;
8287
8288 if (modifiedIoControlCode == IOCTL_STORAGE_EJECT_MEDIA) {
8289 cdb->START_STOP.Start = 0;
8290 } else {
8291 cdb->START_STOP.Start = 1;
8292 }
8293
8294 //
8295 // Set timeout value.
8296 //
8297
8298 SrbSetTimeOutValue(srb, fdoExtension->TimeOutValue);
8300 srb,
8301 Irp,
8302 NULL,
8303 0,
8304 FALSE);
8305
8308
8309 break;
8310 }
8311
8313
8314 FREE_POOL(srb);
8315
8316 if (commonExtension->IsFdo) {
8317
8319 ((PFUNCTIONAL_DEVICE_EXTENSION) commonExtension)->LowerPdo,
8320 BusRelations);
8321
8323 Irp->IoStatus.Status = status;
8324
8327 }
8328 else {
8329
8330
8332
8334 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8335 }
8336 break;
8337 }
8338
8340
8341 FREE_POOL(srb);
8342
8343 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength >=
8344 sizeof(STORAGE_DEVICE_NUMBER)) {
8345
8346 PSTORAGE_DEVICE_NUMBER deviceNumber =
8347 Irp->AssociatedIrp.SystemBuffer;
8348 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
8349 commonExtension->PartitionZeroExtension;
8350
8351 deviceNumber->DeviceType = fdoExtension->CommonExtension.DeviceObject->DeviceType;
8352 deviceNumber->DeviceNumber = fdoExtension->DeviceNumber;
8353 deviceNumber->PartitionNumber = commonExtension->PartitionNumber;
8354
8356 Irp->IoStatus.Information = sizeof(STORAGE_DEVICE_NUMBER);
8357
8358 } else {
8360 Irp->IoStatus.Information = sizeof(STORAGE_DEVICE_NUMBER);
8361 }
8362
8363 Irp->IoStatus.Status = status;
8366
8367 break;
8368 }
8369
8370
8372
8373 FREE_POOL(srb);
8374
8375 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
8376 sizeof(STORAGE_READ_CAPACITY)) {
8377
8378 //
8379 // Indicate unsuccessful status and no data transferred.
8380 //
8381
8382 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
8383 Irp->IoStatus.Information = sizeof(STORAGE_READ_CAPACITY);
8384
8388 break;
8389 }
8390
8391 if (!commonExtension->IsFdo) {
8392
8393
8394 //
8395 // Just forward this down and return
8396 //
8397
8399
8401 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8402 }
8403 else {
8404
8405 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = DeviceObject->DeviceExtension;
8406 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
8407 PSTORAGE_READ_CAPACITY readCapacity = Irp->AssociatedIrp.SystemBuffer;
8408 LARGE_INTEGER diskLength;
8409
8411 if (NT_SUCCESS(status) && fdoData->IsCachedDriveCapDataValid) {
8412
8413 readCapacity->Version = sizeof(STORAGE_READ_CAPACITY);
8414 readCapacity->Size = sizeof(STORAGE_READ_CAPACITY);
8415
8416 REVERSE_BYTES(&readCapacity->BlockLength,
8418 REVERSE_BYTES_QUAD(&readCapacity->NumberOfBlocks,
8420 readCapacity->NumberOfBlocks.QuadPart++;
8421
8422 readCapacity->DiskLength = fdoExt->CommonExtension.PartitionLength;
8423
8424 //
8425 // Make sure the lengths are equal.
8426 // Remove this after testing.
8427 //
8428 diskLength.QuadPart = readCapacity->NumberOfBlocks.QuadPart *
8429 readCapacity->BlockLength;
8430
8431 Irp->IoStatus.Status = STATUS_SUCCESS;
8432 Irp->IoStatus.Information = sizeof(STORAGE_READ_CAPACITY);
8433
8434 } else {
8435 //
8436 // Read capacity request failed.
8437 //
8438 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "ClassDeviceControl: ClassReadDriveCapacity failed: 0x%X IsCachedDriveCapDataValid: %d\n",
8440 Irp->IoStatus.Status = status;
8441 Irp->IoStatus.Information = 0;
8442 }
8445 }
8446
8447 break;
8448 }
8449
8451
8452 PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;
8453
8454 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_PROPERTY_QUERY)) {
8455
8457 Irp->IoStatus.Status = status;
8460 FREE_POOL(srb);
8461 break;
8462 }
8463
8464 if (!commonExtension->IsFdo) {
8465
8466
8468
8470 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8471 FREE_POOL(srb);
8472 break;
8473 }
8474
8475 //
8476 // Determine PropertyId type and either call appropriate routine
8477 // or pass request to lower drivers.
8478 //
8479
8480 switch ( query->PropertyId ) {
8481
8483
8485 break;
8486 }
8487
8489
8491 break;
8492 }
8493
8494 // these propertyId has been implemented in some port driver and filter drivers.
8495 // to keep the backwards compatibility, classpnp will send the request down if it's supported by lower layer.
8496 // otherwise, classpnp sends SCSI command and then interprets the result.
8498
8500 break;
8501 }
8502
8504
8506 break;
8507 }
8508
8510
8512 break;
8513 }
8514
8516
8518 break;
8519 }
8520
8522
8523 status = ClasspDeviceCopyOffloadProperty(DeviceObject, Irp, srb);
8524 break;
8525 }
8526
8528
8530 break;
8531 }
8532
8533 default: {
8534
8535 //
8536 // Copy the Irp stack parameters to the next stack location.
8537 //
8538
8540
8542 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8543 break;
8544 }
8545 } // end switch
8546
8547 FREE_POOL(srb);
8548 break;
8549 }
8550
8552
8553 FREE_POOL(srb);
8554
8555 if (!commonExtension->IsFdo) {
8556
8557
8559
8561 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8562 break;
8563 }
8564
8565 //
8566 // Process priority hit request
8567 //
8568
8570 break;
8571 }
8572
8574
8575 PDEVICE_MANAGE_DATA_SET_ATTRIBUTES dsmAttributes = Irp->AssociatedIrp.SystemBuffer;
8576
8577 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES)) {
8578
8580 Irp->IoStatus.Status = status;
8583 FREE_POOL(srb);
8584 break;
8585 }
8586
8587 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
8588 (sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES) + dsmAttributes->ParameterBlockLength + dsmAttributes->DataSetRangesLength)) {
8589
8591 Irp->IoStatus.Status = status;
8594 FREE_POOL(srb);
8595 break;
8596 }
8597
8598 if (!commonExtension->IsFdo) {
8599
8600
8602
8604 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8605 FREE_POOL(srb);
8606 break;
8607 }
8608
8609 switch(dsmAttributes->Action) {
8610
8611 // only process Trim action in class layer if possible.
8612 case DeviceDsmAction_Trim: {
8613 status = ClasspDeviceTrimProcess(DeviceObject, Irp, &activityId, srb);
8614 break;
8615 }
8616
8618 status = ClassDeviceProcessOffloadRead(DeviceObject, Irp, srb);
8619 break;
8620 }
8621
8623 status = ClassDeviceProcessOffloadWrite(DeviceObject, Irp, srb);
8624 break;
8625 }
8626
8629 break;
8630 }
8631
8632
8633 default: {
8634
8635
8636 //
8637 // Copy the Irp stack parameters to the next stack location.
8638 //
8639
8641
8643 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8644 break;
8645 }
8646 } // end switch
8647
8648 FREE_POOL(srb);
8649 break;
8650 }
8651
8653
8654 if (commonExtension->IsFdo) {
8655
8657
8658 } else {
8659
8661
8663 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8664 }
8665
8666 FREE_POOL(srb);
8667
8668 break;
8669 }
8670
8672
8673 FREE_POOL(srb);
8674
8676 break;
8677 }
8678
8679#if (NTDDI_VERSION >= NTDDI_WINTRHESHOLD)
8681 FREE_POOL(srb);
8682
8684 break;
8685 }
8686
8688 if (!commonExtension->IsFdo) {
8689
8691
8693 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8694 goto SetStatusAndReturn;
8695 }
8696
8698 break;
8699 }
8700
8702 if (!commonExtension->IsFdo) {
8703
8705
8707 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8708 goto SetStatusAndReturn;
8709 }
8710
8712 break;
8713 }
8714#endif
8715
8716
8717 default: {
8718
8719 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "IoDeviceControl: Unsupported device IOCTL %x for %p\n",
8720 controlCode, DeviceObject));
8721
8722
8723 //
8724 // Pass the device control to the next driver.
8725 //
8726
8727 FREE_POOL(srb);
8728
8729 //
8730 // Copy the Irp stack parameters to the next stack location.
8731 //
8732
8734
8736 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8737 break;
8738 }
8739
8740 } // end switch( ...
8741
8742SetStatusAndReturn:
8743
8744 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "< ioctl %xh (%s): status %xh.", modifiedIoControlCode, DBGGETIOCTLSTR(modifiedIoControlCode), status));
8745
8746 return status;
8747} // end ClassDeviceControl()
#define VOID
Definition: acefi.h:82
#define SRB_CLASS_FLAGS_LOW_PRIORITY
Definition: cdrom.h:162
#define FDO_HACK_NO_RESERVE6
Definition: cdromp.h:135
#define CLASSP_REG_WRITE_CACHE_VALUE_NAME
Definition: cdromp.h:124
@ SimpleMediaLock
Definition: cdromp.h:289
@ SecureMediaLock
Definition: cdromp.h:290
#define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME
Definition: cdromp.h:126
#define CLASSP_REG_SUBKEY_NAME
Definition: cdromp.h:120
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
#define SCSIOP_RELEASE_UNIT
Definition: cdrw_hw.h:893
#define SCSIOP_RESERVE_UNIT
Definition: cdrw_hw.h:892
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
NTSTATUS ClasspDeviceLBProvisioningProperty(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:2894
NTSTATUS ClasspWriteCacheProperty(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:1199
NTSTATUS ClasspDeviceTrimProcess(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PGUID ActivityId, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:3476
_IRQL_requires_same_ NTSTATUS ClasspStorageEventNotification(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: utils.c:7826
NTSTATUS ClassDeviceHwFirmwareDownloadProcess(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:8541
NTSTATUS ClasspDeviceGetLBAStatus(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:3861
NTSTATUS ClasspPersistentReserve(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:6211
NTSTATUS ClasspDuidQueryProperty(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: utils.c:997
NTSTATUS ClasspAccessAlignmentProperty(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:1700
NTSTATUS ClassDeviceHwFirmwareGetInfoProcess(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
Definition: utils.c:8366
NTSTATUS ClasspPriorityHint(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: utils.c:6480
NTSTATUS ClasspDeviceSeekPenaltyProperty(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:2172
NTSTATUS ClasspDeviceTrimProperty(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:2730
NTSTATUS ClasspEjectionControl(IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN MEDIA_LOCK_TYPE LockType, IN BOOLEAN Lock)
Definition: create.c:474
NTSTATUS ClassDeviceGetLBProvisioningResources(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:5087
NTSTATUS ClassDeviceHwFirmwareActivateProcess(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:8902
NTSTATUS ClasspDeviceMediaTypeProperty(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:1917
NTSTATUS ClasspMcnControl(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PIRP Irp, IN PSCSI_REQUEST_BLOCK Srb)
Definition: autorun.c:3276
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
SCSIPORT_API NTSTATUS NTAPI ClassSendSrbAsynchronous(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp, _In_reads_bytes_opt_(BufferLength) __drv_aliasesMem PVOID BufferAddress, _In_ ULONG BufferLength, _In_ BOOLEAN WriteToDevice)
IO_COMPLETION_ROUTINE ClassCheckVerifyComplete
Definition: class.c:84
#define LastDriveLetter
Definition: class.c:93
_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:2742
#define FirstDriveLetter
Definition: class.c:92
#define DBGGETIOCTLSTR(_ioctl)
Definition: debug.h:25
#define ULONG_PTR
Definition: config.h:101
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define IOCTL_STORAGE_CHECK_VERIFY2
Definition: ntddk_ex.h:212
#define IOCTL_STORAGE_LOAD_MEDIA2
Definition: ntddk_ex.h:210
NTSYSAPI NTSTATUS WINAPI RtlDeleteRegistryValue(ULONG, PCWSTR, PCWSTR)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
#define REG_SZ
Definition: layer.c:22
struct _MOUNTDEV_NAME MOUNTDEV_NAME
struct _MOUNTDEV_UNIQUE_ID MOUNTDEV_UNIQUE_ID
struct _STORAGE_HOTPLUG_INFO STORAGE_HOTPLUG_INFO
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:99
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:80
#define IOCTL_STORAGE_GET_HOTPLUG_INFO
Definition: imports.h:238
struct _MOUNTDEV_SUGGESTED_LINK_NAME MOUNTDEV_SUGGESTED_LINK_NAME
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define REG_NONE
Definition: nt_native.h:1492
#define IOCTL_DISK_BASE
Definition: ntdddisk.h:44
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: ntddstor.h:178
#define IOCTL_STORAGE_RELEASE
Definition: ntddstor.h:119
#define DeviceDsmAction_OffloadRead
Definition: ntddstor.h:278
STORAGE_READ_CAPACITY
Definition: ntddstor.h:861
#define IOCTL_STORAGE_EVENT_NOTIFICATION
Definition: ntddstor.h:226
#define DeviceDsmAction_Allocation
Definition: ntddstor.h:280
struct _STORAGE_DEVICE_NUMBER STORAGE_DEVICE_NUMBER
#define IOCTL_STORAGE_SET_HOTPLUG_INFO
Definition: ntddstor.h:157
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_STORAGE_FIRMWARE_ACTIVATE
Definition: ntddstor.h:211
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define IOCTL_STORAGE_READ_CAPACITY
Definition: ntddstor.h:175
#define IOCTL_STORAGE_FIRMWARE_DOWNLOAD
Definition: ntddstor.h:208
#define DeviceDsmAction_OffloadWrite
Definition: ntddstor.h:279
#define IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
Definition: ntddstor.h:181
#define IOCTL_STORAGE_PERSISTENT_RESERVE_IN
Definition: ntddstor.h:169
#define IOCTL_STORAGE_PERSISTENT_RESERVE_OUT
Definition: ntddstor.h:172
#define IOCTL_STORAGE_LOAD_MEDIA
Definition: ntddstor.h:110
#define IOCTL_STORAGE_RESERVE
Definition: ntddstor.h:116
@ StorageDeviceUniqueIdProperty
Definition: ntddstor.h:515
@ StorageDeviceMediumProductType
Definition: ntddstor.h:527
@ StorageDeviceSeekPenaltyProperty
Definition: ntddstor.h:519
@ StorageDeviceLBProvisioningProperty
Definition: ntddstor.h:523
@ StorageDeviceWriteCacheProperty
Definition: ntddstor.h:516
@ StorageDeviceTrimProperty
Definition: ntddstor.h:520
@ StorageDeviceCopyOffloadProperty
Definition: ntddstor.h:525
@ StorageAccessAlignmentProperty
Definition: ntddstor.h:518
#define IOCTL_STORAGE_FIRMWARE_GET_INFO
Definition: ntddstor.h:205
#define IOCTL_STORAGE_GET_LB_PROVISIONING_MAP_RESOURCES
Definition: ntddstor.h:184
#define IOCTL_STORAGE_FIND_NEW_DEVICES
Definition: ntddstor.h:122
#define IOCTL_STORAGE_BASE
Definition: ntddstor.h:96
#define IOCTL_STORAGE_MCN_CONTROL
Definition: ntddstor.h:128
#define IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT
Definition: ntddstor.h:196
#define DeviceDsmAction_Trim
Definition: ntddstor.h:276
#define IOCTL_STORAGE_EJECT_MEDIA
Definition: ntddstor.h:107
#define IOCTL_STORAGE_EJECTION_CONTROL
Definition: ntddstor.h:125
#define IOCTL_STORAGE_MEDIA_REMOVAL
Definition: ntddstor.h:104
* PSTORAGE_READ_CAPACITY
Definition: ntddstor.h:861
#define IOCTL_TAPE_BASE
Definition: ntddtape.h:35
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
#define IoCompleteRequest
Definition: irp.c:1240
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
#define STATUS_INVALID_PARAMETER_3
Definition: ntstatus.h:477
#define STATUS_FILES_OPEN
Definition: ntstatus.h:499
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
#define IOCTL_SCSI_PASS_THROUGH
Definition: scsi_port.h:47
#define IOCTL_SCSI_PASS_THROUGH_DIRECT
Definition: scsi_port.h:51
#define SCSIOP_RELEASE_UNIT10
Definition: scsi.h:322
#define SCSIOP_RESERVE_UNIT10
Definition: scsi.h:320
#define REVERSE_BYTES_QUAD(Destination, Source)
Definition: scsi.h:3452
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:664
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:666
@ SrbExDataTypeScsiCdb16
Definition: srb.h:459
#define IOCTL_SCSI_PASS_THROUGH_DIRECT_EX
Definition: ntddscsi.h:38
#define IOCTL_SCSI_PASS_THROUGH_EX
Definition: ntddscsi.h:37
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
FORCEINLINE VOID SrbSetRequestAttribute(_In_ PVOID Srb, _In_ UCHAR RequestAttribute)
Definition: srbhelper.h:1131
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
BOOLEAN IsCachedDriveCapDataValid
Definition: classp.h:803
READ_CAPACITY_DATA_EX LastKnownDriveCapacityData
Definition: classp.h:802
PDEVICE_OBJECT DeviceObject
Definition: pci.h:46
UNICODE_STRING DeviceName
Definition: classpnp.h:615
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
UNICODE_STRING MountedDeviceInterfaceName
Definition: classpnp.h:628
LARGE_INTEGER PartitionLength
Definition: classpnp.h:618
DEVICE_DATA_MANAGEMENT_SET_ACTION Action
Definition: ntddstor.h:773
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
USHORT UniqueIdLength
Definition: imports.h:138
UCHAR UniqueId[1]
Definition: imports.h:139
BOOLEAN PreventMediaRemoval
Definition: ntddstor.h:343
LARGE_INTEGER LogicalBlockAddress
Definition: scsi.h:2749
DEVICE_TYPE DeviceType
Definition: ntddstor.h:324
Definition: name.c:39
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG_PTR
Definition: typedefs.h:65
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
char CCHAR
Definition: typedefs.h:51
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
Definition: cdrw_hw.h:28
struct _CDB::_CDB10 CDB10
struct _CDB::_CDB6GENERIC CDB6GENERIC
struct _CDB::_START_STOP START_STOP
LONGLONG QuadPart
Definition: typedefs.h:114
#define SrbGetCdb(srb)
Definition: usbstor.h:18
#define IOCTL_CDROM_BASE
Definition: vcdcli.c:21
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2680
@ BusRelations
Definition: iotypes.h:2152
@ RemovalPolicyExpectSurpriseRemoval
Definition: iotypes.h:842
@ RemovalPolicyExpectOrderlyRemoval
Definition: iotypes.h:841
@ UserRequest
Definition: ketypes.h:421
#define RTL_QUERY_REGISTRY_TYPECHECK
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
__wchar_t WCHAR
Definition: xmlstorage.h:180

◆ ClassDeviceControlDispatch()

NTSTATUS NTAPI ClassDeviceControlDispatch ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 7258 of file class.c.

7262{
7263
7264 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
7265 ULONG isRemoved;
7266
7268 _Analysis_assume_(isRemoved);
7269 if(isRemoved) {
7270
7272
7273 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
7276 }
7277
7278 //
7279 // Call the class specific driver DeviceControl routine.
7280 // If it doesn't handle it, it will call back into ClassDeviceControl.
7281 //
7282
7283 NT_ASSERT(commonExtension->DevInfo->ClassDeviceControl);
7284
7285 return commonExtension->DevInfo->ClassDeviceControl(DeviceObject,Irp);
7286} // end ClassDeviceControlDispatch()
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
PCLASS_DEVICE_CONTROL ClassDeviceControl
Definition: classpnp.h:524
PCLASS_DEV_INFO DevInfo
Definition: classpnp.h:620

Referenced by ClassInitializeDispatchTables().

◆ ClassDispatchPnp()

NTSTATUS NTAPI ClassDispatchPnp ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 894 of file class.c.

898{
899 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
900 BOOLEAN isFdo = commonExtension->IsFdo;
901
902 PCLASS_DRIVER_EXTENSION driverExtension;
903 PCLASS_INIT_DATA initData;
904 PCLASS_DEV_INFO devInfo;
905
907
908 NTSTATUS status = Irp->IoStatus.Status;
909 BOOLEAN completeRequest = TRUE;
910 BOOLEAN lockReleased = FALSE;
911
912
913 PAGED_CODE();
914
915 //
916 // Extract all the useful information out of the driver object
917 // extension
918 //
919
920#ifdef _MSC_VER
921#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
922#endif
924
925 if (driverExtension){
926
927 initData = &(driverExtension->InitData);
928
929 if(isFdo) {
930 devInfo = &(initData->FdoData);
931 } else {
932 devInfo = &(initData->PdoData);
933 }
934
936
937 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): minor code %#x for %s %p\n",
939 irpStack->MinorFunction,
940 isFdo ? "fdo" : "pdo",
941 DeviceObject));
942 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): previous %#x, current %#x\n",
944 commonExtension->PreviousState,
945 commonExtension->CurrentState));
946
947
948 switch(irpStack->MinorFunction) {
949
950 case IRP_MN_START_DEVICE: {
951
952 //
953 // if this is sent to the FDO we should forward it down the
954 // attachment chain before we start the FDO.
955 //
956
957 if (isFdo) {
958 status = ClassForwardIrpSynchronous(commonExtension, Irp);
959 }
960 else {
962 }
963
964 if (NT_SUCCESS(status)){
965 status = Irp->IoStatus.Status = ClassPnpStartDevice(DeviceObject);
966 }
967
968 break;
969 }
970
971
973
975 irpStack->Parameters.QueryDeviceRelations.Type;
976
977 PDEVICE_RELATIONS deviceRelations = NULL;
978
979
980 if(!isFdo) {
981
983
984 //
985 // Device relations has one entry built in to it's size.
986 //
987
989
990 deviceRelations = ExAllocatePoolWithTag(PagedPool,
991 sizeof(DEVICE_RELATIONS),
992 '2CcS');
993
994 if(deviceRelations != NULL) {
995
996 RtlZeroMemory(deviceRelations,
997 sizeof(DEVICE_RELATIONS));
998
999 Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
1000
1001 deviceRelations->Count = 1;
1002 deviceRelations->Objects[0] = DeviceObject;
1003 ObReferenceObject(deviceRelations->Objects[0]);
1004
1006 }
1007
1008 } else {
1009 //
1010 // PDO's just complete enumeration requests without altering
1011 // the status.
1012 //
1013
1014 status = Irp->IoStatus.Status;
1015 }
1016
1017 break;
1018
1019 } else if (type == BusRelations) {
1020
1021 NT_ASSERT(commonExtension->IsInitialized);
1022
1023 //
1024 // Make sure we support enumeration
1025 //
1026
1027 if(initData->ClassEnumerateDevice == NULL) {
1028
1029 //
1030 // Just send the request down to the lower driver. Perhaps
1031 // It can enumerate children.
1032 //
1033
1034 } else {
1035
1036 //
1037 // Re-enumerate the device
1038 //
1039
1041
1042 if(!NT_SUCCESS(status)) {
1043 completeRequest = TRUE;
1044 break;
1045 }
1046 }
1047 }
1048
1049
1052 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1053 completeRequest = FALSE;
1054
1055 break;
1056 }
1057
1058 case IRP_MN_QUERY_ID: {
1059
1060 BUS_QUERY_ID_TYPE idType = irpStack->Parameters.QueryId.IdType;
1061 UNICODE_STRING unicodeString;
1062
1063
1064 if(isFdo) {
1065
1066
1067 //
1068 // FDO's should just forward the query down to the lower
1069 // device objects
1070 //
1071
1074
1075 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1076 completeRequest = FALSE;
1077 break;
1078 }
1079
1080 //
1081 // PDO's need to give an answer - this is easy for now
1082 //
1083
1084 RtlInitUnicodeString(&unicodeString, NULL);
1085
1087 idType,
1088 &unicodeString);
1089
1091 //
1092 // The driver doesn't implement this ID (whatever it is).
1093 // Use the status out of the IRP so that we don't mangle a
1094 // response from someone else.
1095 //
1096
1097 status = Irp->IoStatus.Status;
1098 } else if(NT_SUCCESS(status)) {
1099 Irp->IoStatus.Information = (ULONG_PTR) unicodeString.Buffer;
1100 } else {
1101 Irp->IoStatus.Information = (ULONG_PTR) NULL;
1102 }
1103
1104 break;
1105 }
1106
1109
1110
1111 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Processing QUERY_%s irp\n",
1113 ((irpStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) ?
1114 "STOP" : "REMOVE")));
1115
1116 //
1117 // If this device is in use for some reason (paging, etc...)
1118 // then we need to fail the request.
1119 //
1120
1121 if(commonExtension->PagingPathCount != 0) {
1122
1123 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): device is in paging "
1124 "path and cannot be removed\n",
1125 DeviceObject, Irp));
1127 break;
1128 }
1129
1130
1131 //
1132 // Check with the class driver to see if the query operation
1133 // can succeed.
1134 //
1135
1136 if(irpStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) {
1138 irpStack->MinorFunction);
1139 } else {
1141 irpStack->MinorFunction);
1142 }
1143
1144 if(NT_SUCCESS(status)) {
1145
1146 //
1147 // ASSERT that we never get two queries in a row, as
1148 // this will severly mess up the state machine
1149 //
1150 NT_ASSERT(commonExtension->CurrentState != irpStack->MinorFunction);
1151 commonExtension->PreviousState = commonExtension->CurrentState;
1152 commonExtension->CurrentState = irpStack->MinorFunction;
1153
1154 if(isFdo) {
1155 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Forwarding QUERY_"
1156 "%s irp\n", DeviceObject, Irp,
1157 ((irpStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) ?
1158 "STOP" : "REMOVE")));
1159 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1160 }
1161 }
1162
1163
1164 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Final status == %x\n",
1166
1167 break;
1168 }
1169
1172
1173
1174 //
1175 // Check with the class driver to see if the query or cancel
1176 // operation can succeed.
1177 //
1178
1179 if(irpStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) {
1181 irpStack->MinorFunction);
1182 NT_ASSERTMSG("ClassDispatchPnp !! CANCEL_STOP_DEVICE should never be failed\n", NT_SUCCESS(status));
1183 } else {
1185 irpStack->MinorFunction);
1186 NT_ASSERTMSG("ClassDispatchPnp !! CANCEL_REMOVE_DEVICE should never be failed\n", NT_SUCCESS(status));
1187 }
1188
1189 Irp->IoStatus.Status = status;
1190
1191 //
1192 // We got a CANCEL - roll back to the previous state only
1193 // if the current state is the respective QUERY state.
1194 //
1195
1196 if(((irpStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) &&
1197 (commonExtension->CurrentState == IRP_MN_QUERY_STOP_DEVICE)
1198 ) ||
1200 (commonExtension->CurrentState == IRP_MN_QUERY_REMOVE_DEVICE)
1201 )
1202 ) {
1203
1204 commonExtension->CurrentState =
1205 commonExtension->PreviousState;
1206 commonExtension->PreviousState = 0xff;
1207
1208 }
1209
1210
1211 if(isFdo) {
1212
1213
1216 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1217 completeRequest = FALSE;
1218 } else {
1220 }
1221
1222 break;
1223 }
1224
1225 case IRP_MN_STOP_DEVICE: {
1226
1227
1228 //
1229 // These all mean nothing to the class driver currently. The
1230 // port driver will handle all queueing when necessary.
1231 //
1232
1233 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): got stop request for %s\n",
1235 (isFdo ? "fdo" : "pdo")
1236 ));
1237
1238 NT_ASSERT(commonExtension->PagingPathCount == 0);
1239
1240 //
1241 // ISSUE-2000/02/03-peterwie
1242 // if we stop the timer here then it means no class driver can
1243 // do i/o in its ClassStopDevice routine. This is because the
1244 // retry (among other things) is tied into the tick handler
1245 // and disabling retries could cause the class driver to deadlock.
1246 // Currently no class driver we're aware of issues i/o in its
1247 // Stop routine but this is a case we may want to defend ourself
1248 // against.
1249 //
1250
1252
1253
1255
1256 NT_ASSERTMSG("ClassDispatchPnp !! STOP_DEVICE should never be failed\n", NT_SUCCESS(status));
1257
1258 if(isFdo) {
1259 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1260 }
1261
1262 if(NT_SUCCESS(status)) {
1263 commonExtension->CurrentState = irpStack->MinorFunction;
1264 commonExtension->PreviousState = 0xff;
1265 }
1266
1267
1268 break;
1269 }
1270
1273 UCHAR removeType = irpStack->MinorFunction;
1274
1275 //
1276 // Log a sytem event when non-removable disks are surprise-removed.
1277 //
1278 if (isFdo &&
1279 (removeType == IRP_MN_SURPRISE_REMOVAL)) {
1280
1281 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
1282 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
1283 BOOLEAN logSurpriseRemove = TRUE;
1284 STORAGE_BUS_TYPE busType = fdoExtension->DeviceDescriptor->BusType;
1285
1286 //
1287 // Don't log an event for VHDs
1288 //
1289 if (busType == BusTypeFileBackedVirtual) {
1290 logSurpriseRemove = FALSE;
1291
1292 } else if (fdoData->HotplugInfo.MediaRemovable) {
1293 logSurpriseRemove = FALSE;
1294
1295 } else if (fdoData->HotplugInfo.DeviceHotplug && ( busType == BusTypeUsb || busType == BusType1394)) {
1296
1297 /*
1298 This device is reported as DeviceHotplug but since the busType is Usb or 1394, don't log an event
1299 Note that some storage arrays may report DeviceHotplug and we would like to log an event in those cases
1300 */
1301
1302 logSurpriseRemove = FALSE;
1303 }
1304
1305 if (logSurpriseRemove) {
1306
1308 }
1309
1310 }
1311
1312 if (commonExtension->PagingPathCount != 0) {
1313 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): paging device is getting removed!", DeviceObject, Irp));
1314 }
1315
1316 //
1317 // Release the lock for this IRP before calling in.
1318 //
1320 lockReleased = TRUE;
1321
1322 /*
1323 * Set IsRemoved before propagating the REMOVE down the stack.
1324 * This keeps class-initiated I/O (e.g. the MCN irp) from getting sent
1325 * after we propagate the remove.
1326 */
1327 commonExtension->IsRemoved = REMOVE_PENDING;
1328
1329 /*
1330 * If a timer was started on the device, stop it.
1331 */
1333
1334 /*
1335 * "Fire-and-forget" the remove irp to the lower stack.
1336 * Don't touch the irp (or the irp stack!) after this.
1337 */
1338 if (isFdo) {
1339
1340
1342 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1344 completeRequest = FALSE;
1345 }
1346 else {
1348 }
1349
1350 /*
1351 * Do our own cleanup and call the class driver's remove
1352 * cleanup routine.
1353 * For IRP_MN_REMOVE_DEVICE, this also deletes our device object,
1354 * so don't touch the extension after this.
1355 */
1356 commonExtension->PreviousState = commonExtension->CurrentState;
1357 commonExtension->CurrentState = removeType;
1358 ClassRemoveDevice(DeviceObject, removeType);
1359
1360 break;
1361 }
1362
1364
1366 BOOLEAN setPagable;
1367
1368
1369 switch(type) {
1370
1371 case DeviceUsageTypePaging: {
1372
1373 if ((irpStack->Parameters.UsageNotification.InPath) &&
1374 (commonExtension->CurrentState != IRP_MN_START_DEVICE)) {
1375
1376 //
1377 // Device isn't started. Don't allow adding a
1378 // paging file, but allow a removal of one.
1379 //
1380
1382 break;
1383 }
1384
1385 NT_ASSERT(commonExtension->IsInitialized);
1386
1387 /*
1388 * Ensure that this user thread is not suspended while we are holding the PathCountEvent.
1389 */
1391
1392 (VOID)KeWaitForSingleObject(&commonExtension->PathCountEvent,
1394 FALSE, NULL);
1396
1397 //
1398 // If the volume is removable we should try to lock it in
1399 // place or unlock it once per paging path count
1400 //
1401
1402 if (commonExtension->IsFdo){
1405 Irp,
1407 (BOOLEAN)irpStack->Parameters.UsageNotification.InPath);
1408 }
1409
1410 if (!NT_SUCCESS(status)){
1411 KeSetEvent(&commonExtension->PathCountEvent, IO_NO_INCREMENT, FALSE);
1413 break;
1414 }
1415
1416 //
1417 // if removing last paging device, need to set DO_POWER_PAGABLE
1418 // bit here, and possible re-set it below on failure.
1419 //
1420
1421 setPagable = FALSE;
1422
1423 if ((!irpStack->Parameters.UsageNotification.InPath) &&
1424 (commonExtension->PagingPathCount == 1)) {
1425
1426 //
1427 // removing last paging file
1428 // must have DO_POWER_PAGABLE bits set, but only
1429 // if none set the DO_POWER_INRUSH bit and no other special files
1430 //
1431
1432 if (TEST_FLAG(DeviceObject->Flags, DO_POWER_INRUSH)) {
1433 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1434 "paging file removed, but "
1435 "DO_POWER_INRUSH was set, so NOT "
1436 "setting DO_POWER_PAGABLE\n",
1437 DeviceObject, Irp));
1438 } else if ((commonExtension->HibernationPathCount == 0) &&
1439 (commonExtension->DumpPathCount == 0)) {
1440 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1441 "paging file removed, "
1442 "setting DO_POWER_PAGABLE\n",
1443 DeviceObject, Irp));
1445 setPagable = TRUE;
1446 }
1447
1448 }
1449
1450 //
1451 // forward the irp before finishing handling the
1452 // special cases
1453 //
1454
1455 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1456
1457 //
1458 // now deal with the failure and success cases.
1459 // note that we are not allowed to fail the irp
1460 // once it is sent to the lower drivers.
1461 //
1462
1463 if (NT_SUCCESS(status)) {
1464
1466 (volatile LONG *)&commonExtension->PagingPathCount,
1467 irpStack->Parameters.UsageNotification.InPath);
1468
1469 if (irpStack->Parameters.UsageNotification.InPath) {
1470 if (commonExtension->PagingPathCount == 1) {
1471 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): "
1472 "Clearing PAGABLE bit\n",
1473 DeviceObject, Irp));
1475
1476
1477 }
1478
1479 }
1480
1481 } else {
1482
1483 //
1484 // cleanup the changes done above
1485 //
1486
1487 if (setPagable == TRUE) {
1488 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Unsetting "
1489 "PAGABLE bit due to irp failure\n",
1490 DeviceObject, Irp));
1492 setPagable = FALSE;
1493 }
1494
1495 //
1496 // relock or unlock the media if needed.
1497 //
1498
1499 if (commonExtension->IsFdo) {
1500
1503 Irp,
1505 (BOOLEAN)!irpStack->Parameters.UsageNotification.InPath);
1506 }
1507 }
1508
1509 //
1510 // set the event so the next one can occur.
1511 //
1512
1513 KeSetEvent(&commonExtension->PathCountEvent,
1516 break;
1517 }
1518
1520
1521 //
1522 // if removing last hiber device, need to set DO_POWER_PAGABLE
1523 // bit here, and possible re-set it below on failure.
1524 //
1525
1526 setPagable = FALSE;
1527
1528 if ((!irpStack->Parameters.UsageNotification.InPath) &&
1529 (commonExtension->HibernationPathCount == 1)) {
1530
1531 //
1532 // removing last hiber file
1533 // must have DO_POWER_PAGABLE bits set, but only
1534 // if none set the DO_POWER_INRUSH bit and no other special files
1535 //
1536
1537 if (TEST_FLAG(DeviceObject->Flags, DO_POWER_INRUSH)) {
1538 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1539 "hiber file removed, but "
1540 "DO_POWER_INRUSH was set, so NOT "
1541 "setting DO_POWER_PAGABLE\n",
1542 DeviceObject, Irp));
1543 } else if ((commonExtension->PagingPathCount == 0) &&
1544 (commonExtension->DumpPathCount == 0)) {
1545 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1546 "hiber file removed, "
1547 "setting DO_POWER_PAGABLE\n",
1548 DeviceObject, Irp));
1550 setPagable = TRUE;
1551 }
1552
1553 }
1554
1555 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1556 if (!NT_SUCCESS(status)) {
1557
1558 if (setPagable == TRUE) {
1559 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Unsetting "
1560 "PAGABLE bit due to irp failure\n",
1561 DeviceObject, Irp));
1563 setPagable = FALSE;
1564 }
1565
1566 } else {
1567
1569 (volatile LONG *)&commonExtension->HibernationPathCount,
1570 irpStack->Parameters.UsageNotification.InPath
1571 );
1572
1573 if ((irpStack->Parameters.UsageNotification.InPath) &&
1574 (commonExtension->HibernationPathCount == 1)) {
1575 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): "
1576 "Clearing PAGABLE bit\n",
1577 DeviceObject, Irp));
1579 }
1580 }
1581
1582 break;
1583 }
1584
1586
1587 //
1588 // if removing last dump device, need to set DO_POWER_PAGABLE
1589 // bit here, and possible re-set it below on failure.
1590 //
1591
1592 setPagable = FALSE;
1593
1594 if ((!irpStack->Parameters.UsageNotification.InPath) &&
1595 (commonExtension->DumpPathCount == 1)) {
1596
1597 //
1598 // removing last dump file
1599 // must have DO_POWER_PAGABLE bits set, but only
1600 // if none set the DO_POWER_INRUSH bit and no other special files
1601 //
1602
1603 if (TEST_FLAG(DeviceObject->Flags, DO_POWER_INRUSH)) {
1604 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1605 "dump file removed, but "
1606 "DO_POWER_INRUSH was set, so NOT "
1607 "setting DO_POWER_PAGABLE\n",
1608 DeviceObject, Irp));
1609 } else if ((commonExtension->PagingPathCount == 0) &&
1610 (commonExtension->HibernationPathCount == 0)) {
1611 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1612 "dump file removed, "
1613 "setting DO_POWER_PAGABLE\n",
1614 DeviceObject, Irp));
1616 setPagable = TRUE;
1617 }
1618
1619 }
1620
1621 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1622 if (!NT_SUCCESS(status)) {
1623
1624 if (setPagable == TRUE) {
1625 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Unsetting "
1626 "PAGABLE bit due to irp failure\n",
1627 DeviceObject, Irp));
1629 setPagable = FALSE;
1630 }
1631
1632 } else {
1633
1635 (volatile LONG *)&commonExtension->DumpPathCount,
1636 irpStack->Parameters.UsageNotification.InPath
1637 );
1638
1639 if ((irpStack->Parameters.UsageNotification.InPath) &&
1640 (commonExtension->DumpPathCount == 1)) {
1641 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): "
1642 "Clearing PAGABLE bit\n",
1643 DeviceObject, Irp));
1645 }
1646 }
1647
1648 break;
1649 }
1650
1651 case DeviceUsageTypeBoot: {
1652
1653 if (isFdo) {
1655
1656 fdoData = ((PFUNCTIONAL_DEVICE_EXTENSION)(DeviceObject->DeviceExtension))->PrivateFdoData;
1657
1658
1659 //
1660 // If boot disk has removal policy as RemovalPolicyExpectSurpriseRemoval (e.g. disk is hotplug-able),
1661 // change the removal policy to RemovalPolicyExpectOrderlyRemoval.
1662 // This will cause the write cache of disk to be enabled on subsequent start Fdo (next boot).
1663 //
1664 if ((fdoData != NULL) &&
1665 fdoData->HotplugInfo.DeviceHotplug) {
1666
1667 fdoData->HotplugInfo.DeviceHotplug = FALSE;
1668 fdoData->HotplugInfo.MediaRemovable = FALSE;
1669
1670 ClassSetDeviceParameter((PFUNCTIONAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension,
1674 }
1675 }
1676
1677 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1678 break;
1679 }
1680
1681 default: {
1683 break;
1684 }
1685 }
1686 break;
1687 }
1688
1690
1691 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): QueryCapabilities\n",
1692 DeviceObject, Irp));
1693
1694 if(!isFdo) {
1695
1698 irpStack->Parameters.DeviceCapabilities.Capabilities
1699 );
1700
1701 break;
1702
1703 } else {
1704
1705 PDEVICE_CAPABILITIES deviceCapabilities;
1706 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
1708
1709 fdoExtension = DeviceObject->DeviceExtension;
1710 fdoData = fdoExtension->PrivateFdoData;
1711 deviceCapabilities =
1712 irpStack->Parameters.DeviceCapabilities.Capabilities;
1713
1714 //
1715 // forward the irp before handling the special cases
1716 //
1717
1718 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1719 if (!NT_SUCCESS(status)) {
1720 break;
1721 }
1722
1723 //
1724 // we generally want to remove the device from the hotplug
1725 // applet, which requires the SR-OK bit to be set.
1726 // only when the user specifies that they are capable of
1727 // safely removing things do we want to clear this bit
1728 // (saved in WriteCacheEnableOverride)
1729 //
1730 // setting of this bit is done either above, or by the
1731 // lower driver.
1732 //
1733 // note: may not be started, so check we have FDO data first.
1734 //
1735
1736 if (fdoData &&
1738 if (deviceCapabilities->SurpriseRemovalOK) {
1739 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "Classpnp: Clearing SR-OK bit in "
1740 "device capabilities due to hotplug "
1741 "device or media\n"));
1742 }
1743 deviceCapabilities->SurpriseRemovalOK = FALSE;
1744 }
1745 break;
1746
1747 } // end QUERY_CAPABILITIES for FDOs
1748
1749 break;
1750
1751
1752 } // end QUERY_CAPABILITIES
1753
1754 default: {
1755
1756 if (isFdo){
1757
1758
1760
1762 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1763
1764 completeRequest = FALSE;
1765 }
1766
1767 break;
1768 }
1769 }
1770 }
1771 else {
1772 NT_ASSERT(driverExtension);
1774 }
1775
1776 if (completeRequest){
1777 Irp->IoStatus.Status = status;
1778
1779 if (!lockReleased){
1781 }
1782
1784
1785 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): leaving with previous %#x, current %#x.", DeviceObject, Irp, commonExtension->PreviousState, commonExtension->CurrentState));
1786 }
1787 else {
1788 /*
1789 * The irp is already completed so don't touch it.
1790 * This may be a remove so don't touch the device extension.
1791 */
1792 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): leaving.", DeviceObject, Irp));
1793 }
1794
1795 return status;
1796} // end ClassDispatchPnp()
unsigned char BOOLEAN
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
@ InternalMediaLock
Definition: cdromp.h:291
NTSTATUS ClasspLogSystemEventWithDeviceNumber(_In_ PDEVICE_OBJECT DeviceObject, _In_ NTSTATUS IoErrorCode)
Definition: utils.c:5354
VOID ClasspDisableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3956
#define REMOVE_PENDING
Definition: classpnp.h:97
NTSTATUS ClassPnpStartDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: class.c:1819
NTSTATUS ClassGetPdoId(IN PDEVICE_OBJECT Pdo, IN BUS_QUERY_ID_TYPE IdType, IN PUNICODE_STRING IdString)
Definition: class.c:10151
NTSTATUS ClassQueryPnpCapabilities(IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_CAPABILITIES Capabilities)
Definition: class.c:10192
NTSTATUS ClassPnpQueryFdoRelations(IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
Definition: class.c:9843
NTSTATUS NTAPI ClassForwardIrpSynchronous(_In_ PCOMMON_DEVICE_EXTENSION CommonExtension, _In_ PIRP Irp)
Definition: class.c:11343
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
@ BusTypeFileBackedVirtual
Definition: ntddstor.h:453
@ BusTypeUsb
Definition: ntddstor.h:445
@ BusType1394
Definition: ntddstor.h:442
enum _STORAGE_BUS_TYPE STORAGE_BUS_TYPE
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
#define IO_WARNING_DISK_SURPRISE_REMOVED
Definition: ntiologc.h:118
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
long LONG
Definition: pedump.c:60
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
PCLASS_REMOVE_DEVICE ClassRemoveDevice
Definition: classpnp.h:531
PCLASS_STOP_DEVICE ClassStopDevice
Definition: classpnp.h:530
CLASS_DEV_INFO FdoData
Definition: classpnp.h:538
CLASS_DEV_INFO PdoData
Definition: classpnp.h:539
PCLASS_ENUM_DEVICE ClassEnumerateDevice
Definition: classpnp.h:541
STORAGE_HOTPLUG_INFO HotplugInfo
Definition: classp.h:739
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: classpnp.h:876
struct _IO_STACK_LOCATION::@3978::@4003 QueryDeviceRelations
struct _IO_STACK_LOCATION::@3978::@4005 DeviceCapabilities
struct _IO_STACK_LOCATION::@3978::@4009 QueryId
struct _IO_STACK_LOCATION::@3978::@4011 UsageNotification
BOOLEAN WriteCacheEnableOverride
Definition: imports.h:249
BOOLEAN MediaRemovable
Definition: imports.h:246
BOOLEAN DeviceHotplug
Definition: imports.h:248
#define IoAdjustPagingPathCount(_Count, _Increment)
#define IRP_MN_CANCEL_STOP_DEVICE
@ TargetDeviceRelation
Definition: iotypes.h:2156
enum _BUS_QUERY_ID_TYPE BUS_QUERY_ID_TYPE
#define IRP_MN_START_DEVICE
#define IRP_MN_DEVICE_USAGE_NOTIFICATION
#define IRP_MN_QUERY_ID
#define IRP_MN_REMOVE_DEVICE
#define IRP_MN_QUERY_DEVICE_RELATIONS
#define DO_POWER_PAGABLE
#define IRP_MN_QUERY_STOP_DEVICE
#define IRP_MN_QUERY_CAPABILITIES
* PDEVICE_CAPABILITIES
Definition: iotypes.h:965
#define DO_POWER_INRUSH
#define IRP_MN_CANCEL_REMOVE_DEVICE
#define IRP_MN_STOP_DEVICE
enum _DEVICE_RELATION_TYPE DEVICE_RELATION_TYPE
enum _DEVICE_USAGE_NOTIFICATION_TYPE DEVICE_USAGE_NOTIFICATION_TYPE
@ DeviceUsageTypeHibernation
Definition: iotypes.h:1171
@ DeviceUsageTypeBoot
Definition: iotypes.h:1173
@ DeviceUsageTypeDumpFile
Definition: iotypes.h:1172
@ DeviceUsageTypePaging
Definition: iotypes.h:1170
#define IRP_MN_QUERY_REMOVE_DEVICE
@ Executive
Definition: ketypes.h:415
#define ObReferenceObject
Definition: obfuncs.h:204
#define NT_ASSERTMSG
Definition: rtlfuncs.h:3311
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by ClassInitializeDispatchTables().

◆ ClassFindModePage()

PVOID NTAPI ClassFindModePage ( _In_reads_bytes_(Length) PCHAR  ModeSenseBuffer,
_In_ ULONG  Length,
_In_ UCHAR  PageMode,
_In_ BOOLEAN  Use6Byte 
)

Definition at line 6798 of file class.c.

6804{
6805 PUCHAR limit;
6806 ULONG parameterHeaderLength;
6807 PVOID result = NULL;
6808
6809 limit = (PUCHAR)ModeSenseBuffer + Length;
6810 parameterHeaderLength = (Use6Byte) ? sizeof(MODE_PARAMETER_HEADER) : sizeof(MODE_PARAMETER_HEADER10);
6811
6812 if (Length >= parameterHeaderLength) {
6813
6814 PMODE_PARAMETER_HEADER10 modeParam10;
6815 ULONG blockDescriptorLength;
6816
6817 /*
6818 * Skip the mode select header and block descriptors.
6819 */
6820 if (Use6Byte){
6821 blockDescriptorLength = ((PMODE_PARAMETER_HEADER) ModeSenseBuffer)->BlockDescriptorLength;
6822 }
6823 else {
6824 modeParam10 = (PMODE_PARAMETER_HEADER10) ModeSenseBuffer;
6825 blockDescriptorLength = modeParam10->BlockDescriptorLength[1];
6826 }
6827
6828 ModeSenseBuffer += parameterHeaderLength + blockDescriptorLength;
6829
6830 //
6831 // ModeSenseBuffer now points at pages. Walk the pages looking for the
6832 // requested page until the limit is reached.
6833 //
6834
6835 while (ModeSenseBuffer +
6837
6838 if (((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageCode == PageMode) {
6839
6840 /*
6841 * found the mode page. make sure it's safe to touch it all
6842 * before returning the pointer to caller
6843 */
6844
6845 if (ModeSenseBuffer + ((PMODE_DISCONNECT_PAGE)ModeSenseBuffer)->PageLength > (PCHAR)limit) {
6846 /*
6847 * Return NULL since the page is not safe to access in full
6848 */
6849 result = NULL;
6850 }
6851 else {
6852 result = ModeSenseBuffer;
6853 }
6854 break;
6855 }
6856
6857 //
6858 // Advance to the next page which is 4-byte-aligned offset after this page.
6859 //
6860 ModeSenseBuffer +=
6861 ((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageLength +
6863
6864 }
6865 }
6866
6867 return result;
6868} // end ClassFindModePage()
_In_ size_t _In_ UCHAR _In_ BOOLEAN Use6Byte
Definition: cdrom.h:1328
_In_ size_t _In_ UCHAR PageMode
Definition: cdrom.h:1326
_In_ ULONG _In_ UCHAR PageCode
Definition: cdrom.h:1317
struct _MODE_PARAMETER_HEADER10 MODE_PARAMETER_HEADER10
struct _MODE_PARAMETER_HEADER10 * PMODE_PARAMETER_HEADER10
struct _MODE_PARAMETER_HEADER * PMODE_PARAMETER_HEADER
GLint limit
Definition: glext.h:10326
GLuint64EXT * result
Definition: glext.h:11304
#define PCHAR
Definition: match.c:90
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
struct _MODE_DISCONNECT_PAGE * PMODE_DISCONNECT_PAGE
UCHAR BlockDescriptorLength[2]
Definition: cdrw_hw.h:2516
unsigned char * PUCHAR
Definition: typedefs.h:53

Referenced by ClasspWriteCacheProperty(), ClasspZeroQERR(), DetermineDriveType(), DiskGetCacheInformation(), DiskGetInfoExceptionInformation(), DiskGetModePage(), DiskInfoExceptionComplete(), DiskSetCacheInformation(), and FormatMedia().

◆ ClassForwardIrpSynchronous()

NTSTATUS NTAPI ClassForwardIrpSynchronous ( _In_ PCOMMON_DEVICE_EXTENSION  CommonExtension,
_In_ PIRP  Irp 
)

Definition at line 11343 of file class.c.

11347{
11349 return ClassSendIrpSynchronous(CommonExtension->LowerDeviceObject, Irp);
11350} // end ClassForwardIrpSynchronous()
NTSTATUS NTAPI ClassSendIrpSynchronous(_In_ PDEVICE_OBJECT TargetDeviceObject, _In_ PIRP Irp)
Definition: class.c:11373

Referenced by ClassDispatchPnp(), ClasspAccessAlignmentProperty(), ClasspDeviceSeekPenaltyProperty(), ClasspDeviceTrimProcess(), ClasspDeviceTrimProperty(), and ClasspPriorityHint().

◆ ClassGetPdoId()

NTSTATUS ClassGetPdoId ( IN PDEVICE_OBJECT  Pdo,
IN BUS_QUERY_ID_TYPE  IdType,
IN PUNICODE_STRING  IdString 
)

Definition at line 10151 of file class.c.

10156{
10157#ifdef _MSC_VER
10158#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
10159#endif
10161
10162 _Analysis_assume_(driverExtension != NULL);
10163
10164 ASSERT_PDO(Pdo);
10165 NT_ASSERT(driverExtension->InitData.ClassQueryId);
10166
10167 PAGED_CODE();
10168
10169 return driverExtension->InitData.ClassQueryId( Pdo, IdType, IdString);
10170} // end ClassGetPdoId()
_In_ BUS_QUERY_ID_TYPE IdType
Definition: classpnp.h:374
_In_ BUS_QUERY_ID_TYPE _In_ PUNICODE_STRING IdString
Definition: classpnp.h:375
#define ASSERT_PDO(x)
Definition: pci.h:38
PCLASS_QUERY_ID ClassQueryId
Definition: classpnp.h:542
WDF_EXTERN_C_START typedef _Must_inspect_result_ _In_ WDFDRIVER _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ PDEVICE_OBJECT _In_opt_ PDEVICE_OBJECT _In_opt_ PDEVICE_OBJECT Pdo
Definition: wdfminiport.h:72

Referenced by ClassDispatchPnp().

◆ ClassGetVpb()

PVPB NTAPI ClassGetVpb ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 11473 of file class.c.

11476{
11477#ifdef _MSC_VER
11478#pragma prefast(suppress:28175)
11479#endif
11480 return DeviceObject->Vpb;
11481} // end ClassGetVpb()

Referenced by ClassInterpretSenseInfo(), ClassMinimalPowerHandler(), and ClasspInterpretGesnData().

◆ ClassInternalIoControl()

NTSTATUS NTAPI ClassInternalIoControl ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 9394 of file class.c.

9398{
9399 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
9400
9403
9404 ULONG isRemoved;
9405
9407
9409 _Analysis_assume_(isRemoved);
9410 if(isRemoved) {
9411
9412 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
9413
9415
9417
9419 }
9420
9421 //
9422 // Get a pointer to the SRB.
9423 //
9424
9425 srb = irpStack->Parameters.Scsi.Srb;
9426
9427 //
9428 // Set the parameters in the next stack location.
9429 //
9430
9431 if(commonExtension->IsFdo) {
9432 nextStack->Parameters.Scsi.Srb = srb;
9433 nextStack->MajorFunction = IRP_MJ_SCSI;
9434 nextStack->MinorFunction = IRP_MN_SCSI_CLASS;
9435
9436 } else {
9437
9439 }
9440
9442
9443 return IoCallDriver(commonExtension->LowerDeviceObject, Irp);
9444} // end ClassInternalIoControl()
#define IRP_MN_SCSI_CLASS

Referenced by ClassInitializeDispatchTables().

◆ ClassInterpretSenseInfo()

BOOLEAN NTAPI ClassInterpretSenseInfo ( _In_ PDEVICE_OBJECT  Fdo,
_In_ PSCSI_REQUEST_BLOCK  _Srb,
_In_ UCHAR  MajorFunctionCode,
_In_ ULONG  IoDeviceCode,
_In_ ULONG  RetryCount,
_Out_ NTSTATUS Status,
_Out_opt_ _Deref_out_range_(0, 100) ULONG RetryInterval 
)

Definition at line 4452 of file class.c.

4461{
4462 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
4463 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
4465 PVOID senseBuffer = SrbGetSenseInfoBuffer(Srb);
4466 BOOLEAN retry = TRUE;
4467 BOOLEAN logError = FALSE;
4468 BOOLEAN unhandledError = FALSE;
4469 BOOLEAN incrementErrorCount = FALSE;
4470
4471 //
4472 // NOTE: This flag must be used only for read/write requests that
4473 // fail with a unexpected retryable error.
4474 //
4475 BOOLEAN logRetryableError = TRUE;
4476
4477 //
4478 // Indicates if we should log this error in our internal log.
4479 //
4480 BOOLEAN logErrorInternal = TRUE;
4481
4482 ULONGLONG badSector = 0;
4483 ULONG uniqueId = 0;
4484
4485 NTSTATUS logStatus;
4486
4487 ULONGLONG readSector;
4488 ULONG index;
4489
4490 ULONG retryInterval = 0;
4491 KIRQL oldIrql;
4492 PCDB cdb = SrbGetCdb(Srb);
4493 UCHAR cdbOpcode = 0;
4494 ULONG cdbLength = SrbGetCdbLength(Srb);
4495
4496#if DBG
4497 BOOLEAN isReservationConflict = FALSE;
4498#endif
4499
4500 if (cdb) {
4501 cdbOpcode = cdb->CDB6GENERIC.OperationCode;
4502 }
4503
4505 logStatus = -1;
4506
4508
4509 //
4510 // Log anything remotely incorrect about paging i/o
4511 //
4512
4513 logError = TRUE;
4514 uniqueId = 301;
4515 logStatus = IO_WARNING_PAGING_FAILURE;
4516 }
4517
4518 //
4519 // Check that request sense buffer is valid.
4520 //
4521
4522 NT_ASSERT(fdoExtension->CommonExtension.IsFdo);
4523
4524
4525 //
4526 // must handle the SRB_STATUS_INTERNAL_ERROR case first,
4527 // as it has all the flags set.
4528 //
4529
4531
4532 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
4533 "ClassInterpretSenseInfo: Internal Error code is %x\n",
4535
4536 retry = FALSE;
4538
4540
4541 //
4542 // Need to reserve STATUS_DEVICE_BUSY to convey reservation conflict
4543 // for read/write requests as there are upper level components that
4544 // have built-in assumptions that STATUS_DEVICE_BUSY implies reservation
4545 // conflict.
4546 //
4548 retry = FALSE;
4549 logError = FALSE;
4550#if DBG
4551 isReservationConflict = TRUE;
4552#endif
4553
4554 } else {
4555
4557
4558 if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) && senseBuffer) {
4559
4560 UCHAR errorCode = 0;
4561 UCHAR senseKey = 0;
4562 UCHAR addlSenseCode = 0;
4563 UCHAR addlSenseCodeQual = 0;
4564 BOOLEAN isIncorrectLengthValid = FALSE;
4565 BOOLEAN incorrectLength = FALSE;
4566 BOOLEAN isInformationValid = FALSE;
4568
4569
4570 validSense = ScsiGetSenseKeyAndCodes(senseBuffer,
4573 &senseKey,
4574 &addlSenseCode,
4575 &addlSenseCodeQual);
4576
4577 if (!validSense && !IsSenseDataFormatValueValid(senseBuffer)) {
4578
4580
4581 validSense = ScsiGetFixedSenseKeyAndCodes(senseBuffer,
4583 &senseKey,
4584 &addlSenseCode,
4585 &addlSenseCodeQual);
4586 }
4587
4588 if (!validSense) {
4589 goto __ClassInterpretSenseInfo_ProcessingInvalidSenseBuffer;
4590 }
4591
4592 errorCode = ScsiGetSenseErrorCode(senseBuffer);
4593
4594 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: Error code is %x\n", errorCode));
4595 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: Sense key is %x\n", senseKey));
4596 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: Additional sense code is %x\n", addlSenseCode));
4597 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: Additional sense code qualifier is %x\n", addlSenseCodeQual));
4598
4599 if (IsDescriptorSenseDataFormat(senseBuffer)) {
4600
4601 //
4602 // Sense data in Descriptor format
4603 //
4604
4605 PVOID startBuffer = NULL;
4606 UCHAR startBufferLength = 0;
4607
4608
4609 if (ScsiGetSenseDescriptor(senseBuffer,
4611 &startBuffer,
4612 &startBufferLength)) {
4613 UCHAR outType;
4615 UCHAR outBufferLength = 0;
4616 BOOLEAN foundBlockCommandType = FALSE;
4617 BOOLEAN foundInformationType = FALSE;
4619
4622
4623 while ((!foundBlockCommandType || !foundInformationType) &&
4624 ScsiGetNextSenseDescriptorByType(startBuffer,
4625 startBufferLength,
4626 typeList,
4627 ARRAYSIZE(typeList),
4628 &outType,
4629 &outBuffer,
4630 &outBufferLength)) {
4631
4633
4634 if (outBufferLength < descriptorLength) {
4635
4636 // Descriptor data is truncated.
4637 // Complete searching descriptors. Exit the loop now.
4638 break;
4639 }
4640
4642
4643 //
4644 // Block Command type
4645 //
4646
4647 if (!foundBlockCommandType) {
4648
4649 foundBlockCommandType = TRUE;
4650
4651 if (ScsiValidateBlockCommandSenseDescriptor(outBuffer, outBufferLength)) {
4652 incorrectLength = ((PSCSI_SENSE_DESCRIPTOR_BLOCK_COMMAND)outBuffer)->IncorrectLength;
4653 isIncorrectLengthValid = TRUE;
4654 }
4655 } else {
4656
4657 //
4658 // A Block Command descriptor is already found earlier.
4659 //
4660 // T10 SPC specification only allows one descriptor for Block Command Descriptor type.
4661 // Assert here to catch devices that violate this rule. Ignore this descriptor.
4662 //
4664 }
4665
4666 } else if (outType == SCSI_SENSE_DESCRIPTOR_TYPE_INFORMATION) {
4667
4668 //
4669 // Information type
4670 //
4671
4672 if (!foundInformationType) {
4673
4674 foundInformationType = TRUE;
4675
4676 if (ScsiValidateInformationSenseDescriptor(outBuffer, outBufferLength)) {
4678 isInformationValid = TRUE;
4679 }
4680 } else {
4681
4682 //
4683 // A Information descriptor is already found earlier.
4684 //
4685 // T10 SPC specification only allows one descriptor for Information Descriptor type.
4686 // Assert here to catch devices that violate this rule. Ignore this descriptor.
4687 //
4689 }
4690
4691 } else {
4692
4693 //
4694 // ScsiGetNextDescriptorByType should only return a type that is specified by us.
4695 //
4697 break;
4698 }
4699
4700 //
4701 // Advance to start address of next descriptor
4702 //
4703 startBuffer = (PUCHAR)outBuffer + descriptorLength;
4704 startBufferLength = outBufferLength - descriptorLength;
4705 }
4706 }
4707 } else {
4708
4709 //
4710 // Sense data in Fixed format
4711 //
4712
4713 incorrectLength = ((PFIXED_SENSE_DATA)(senseBuffer))->IncorrectLength;
4715 isInformationValid = TRUE;
4716 isIncorrectLengthValid = TRUE;
4717 }
4718
4719
4720 switch (senseKey) {
4721
4722 case SCSI_SENSE_NO_SENSE: {
4723
4724 //
4725 // Check other indicators.
4726 //
4727
4728 if (isIncorrectLengthValid && incorrectLength) {
4729
4730 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4731 "Incorrect length detected.\n"));
4733 retry = FALSE;
4734
4735 } else {
4736
4737 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4738 "No specific sense key\n"));
4740 retry = TRUE;
4741 }
4742
4743 break;
4744 } // end SCSI_SENSE_NO_SENSE
4745
4747
4748 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4749 "Recovered error\n"));
4751 retry = FALSE;
4752 logError = TRUE;
4753 uniqueId = 258;
4754
4755 switch(addlSenseCode) {
4758 logStatus = IO_ERR_SEEK_ERROR;
4759 break;
4760 }
4761
4764 logStatus = IO_RECOVERED_VIA_ECC;
4765 break;
4766 }
4767
4769
4770 UCHAR wmiEventData[sizeof(ULONG)+sizeof(UCHAR)] = {0};
4771
4772 *((PULONG)wmiEventData) = sizeof(UCHAR);
4773 wmiEventData[sizeof(ULONG)] = addlSenseCodeQual;
4774
4775 //
4776 // Don't log another eventlog if we have already logged once
4777 // NOTE: this should have been interlocked, but the structure
4778 // was publicly defined to use a BOOLEAN (char). Since
4779 // media only reports these errors once per X minutes,
4780 // the potential race condition is nearly non-existant.
4781 // the worst case is duplicate log entries, so ignore.
4782 //
4783
4784 logError = FALSE;
4785 if (fdoExtension->FailurePredicted == 0) {
4786 logError = TRUE;
4787 }
4788 fdoExtension->FailureReason = addlSenseCodeQual;
4789 logStatus = IO_WRN_FAILURE_PREDICTED;
4790
4791 ClassNotifyFailurePredicted(fdoExtension,
4792 (PUCHAR)wmiEventData,
4793 sizeof(wmiEventData),
4794 FALSE, // do not log error
4795 4, // unique error value
4798 SrbGetLun(Srb));
4799
4800 fdoExtension->FailurePredicted = TRUE;
4801 break;
4802 }
4803
4804 default: {
4805 logStatus = IO_ERR_CONTROLLER_ERROR;
4806 break;
4807 }
4808
4809 } // end switch(addlSenseCode)
4810
4811 if (isIncorrectLengthValid && incorrectLength) {
4812
4813 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4814 "Incorrect length detected.\n"));
4816 }
4817
4818
4819 break;
4820 } // end SCSI_SENSE_RECOVERED_ERROR
4821
4822 case SCSI_SENSE_NOT_READY: {
4823
4824 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4825 "Device not ready\n"));
4827
4828 switch (addlSenseCode) {
4829
4831
4832 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4833 "Lun not ready\n"));
4834
4835 retryInterval = NOT_READY_RETRY_INTERVAL;
4836
4837 switch (addlSenseCodeQual) {
4838
4840 DEVICE_EVENT_BECOMING_READY notReady = {0};
4841
4842 logRetryableError = FALSE;
4843 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4844 "In process of becoming ready\n"));
4845
4846 notReady.Version = 1;
4847 notReady.Reason = 1;
4848 notReady.Estimated100msToReady = retryInterval * 10;
4849 ClassSendNotification(fdoExtension,
4850 &GUID_IO_DEVICE_BECOMING_READY,
4852 &notReady);
4853 break;
4854 }
4855
4857 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4858 "Manual intervention required\n"));
4860 retry = FALSE;
4861 break;
4862 }
4863
4865 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4866 "Format in progress\n"));
4867 retry = FALSE;
4868 break;
4869 }
4870
4872 DEVICE_EVENT_BECOMING_READY notReady = {0};
4873
4874 logRetryableError = FALSE;
4875 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4876 "Operation In Progress\n"));
4877
4878 notReady.Version = 1;
4879 notReady.Reason = 2;
4880 notReady.Estimated100msToReady = retryInterval * 10;
4881 ClassSendNotification(fdoExtension,
4882 &GUID_IO_DEVICE_BECOMING_READY,
4884 &notReady);
4885
4886 break;
4887 }
4888
4890 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4891 "Long write in progress\n"));
4892 //
4893 // This has been seen as a transcient failure on some cdrom
4894 // drives. The cdrom class driver is going to override this
4895 // setting but has no way of dropping the retry interval
4896 //
4897 retry = FALSE;
4898 retryInterval = 1;
4899 break;
4900 }
4901
4903 logRetryableError = FALSE;
4904 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4905 "The device (%p) is busy allocating space.\n",
4906 Fdo));
4907
4908 //
4909 // This indicates that a thinly-provisioned device has hit
4910 // a temporary resource exhaustion and is busy allocating
4911 // more space. We need to retry the request as the device
4912 // will eventually be able to service it.
4913 //
4915 retry = TRUE;
4916
4917 break;
4918 }
4919
4921
4922 if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
4924
4925 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
4926 "ClassInterpretSenseInfo: "
4927 "not ready, cause unknown\n"));
4928 /*
4929 Many non-WHQL certified drives (mostly CD-RW) return
4930 this when they have no media instead of the obvious
4931 choice of:
4932
4933 SCSI_SENSE_NOT_READY/SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
4934
4935 These drives should not pass WHQL certification due
4936 to this discrepency.
4937
4938 */
4939 retry = FALSE;
4940 break;
4941
4942 } else {
4943
4944 //
4945 // Treat this as init command required and fall through.
4946 //
4947 }
4948 }
4949
4951 default: {
4952 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4953 "Initializing command required\n"));
4954 retryInterval = 0; // go back to default
4955 logRetryableError = FALSE;
4956
4957 //
4958 // This sense code/additional sense code
4959 // combination may indicate that the device
4960 // needs to be started. Send an start unit if this
4961 // is a disk device.
4962 //
4963 if (TEST_FLAG(fdoExtension->DeviceFlags, DEV_SAFE_START_UNIT) &&
4965
4967 }
4968 break;
4969 }
4970
4971 } // end switch (addlSenseCodeQual)
4972 break;
4973 }
4974
4976 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4977 "No Media in device.\n"));
4979 retry = FALSE;
4980
4981 //
4982 // signal MCN that there isn't any media in the device
4983 //
4984 if (!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
4985 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4986 "No Media in a non-removable device %p\n",
4987 Fdo));
4988 }
4989
4990 if (addlSenseCodeQual == 0xCC){
4991 /*
4992 * The IMAPI filter returns this ASCQ value when it is burning CD-R media.
4993 * We want to indicate that the media is not present to most applications;
4994 * but RSM has to know that the media is still in the drive (i.e. the drive is not free).
4995 */
4996 ClassSetMediaChangeState(fdoExtension, MediaUnavailable, FALSE);
4997 }
4998 else {
4999 ClassSetMediaChangeState(fdoExtension, MediaNotPresent, FALSE);
5000 }
5001
5002 break;
5003 }
5004 } // end switch (addlSenseCode)
5005
5006 break;
5007 } // end SCSI_SENSE_NOT_READY
5008
5010 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5011 "Medium Error (bad block)\n"));
5013
5014 retry = FALSE;
5015 logError = TRUE;
5016 uniqueId = 256;
5017 logStatus = IO_ERR_BAD_BLOCK;
5018
5019 //
5020 // Check if this error is due to unknown format
5021 //
5022 if (addlSenseCode == SCSI_ADSENSE_INVALID_MEDIA) {
5023
5024 switch (addlSenseCodeQual) {
5025
5027
5029
5030 //
5031 // Log error only if this is a paging request
5032 //
5034 logError = FALSE;
5035 }
5036 break;
5037 }
5038
5040
5042 logError = FALSE;
5043 break;
5044
5045 }
5046 default: {
5047 break;
5048 }
5049 } // end switch addlSenseCodeQual
5050
5051 } // end SCSI_ADSENSE_INVALID_MEDIA
5052
5053 break;
5054
5055 } // end SCSI_SENSE_MEDIUM_ERROR
5056
5058 BOOLEAN logHardwareError = TRUE;
5059
5060 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5061 "Hardware error\n"));
5062
5063 if (fdoData->LegacyErrorHandling == FALSE) {
5064 //
5065 // Hardware errors indicate something has seriously gone
5066 // wrong with the device and retries are very unlikely to
5067 // succeed so fail this request back immediately.
5068 //
5069 retry = FALSE;
5071 logError = FALSE;
5072
5073 } else {
5074 //
5075 // Revert to legacy behavior. That is, retry everything by default.
5076 //
5077 retry = TRUE;
5079 logError = TRUE;
5080 uniqueId = 257;
5081 logStatus = IO_ERR_CONTROLLER_ERROR;
5082 logHardwareError = FALSE;
5083
5084 //
5085 // This indicates the possibility of a dropped FC packet.
5086 //
5087 if ((addlSenseCode == SCSI_ADSENSE_LOGICAL_UNIT_ERROR && addlSenseCodeQual == SCSI_SENSEQ_TIMEOUT_ON_LOGICAL_UNIT) ||
5088 (addlSenseCode == SCSI_ADSENSE_DATA_TRANSFER_ERROR && addlSenseCodeQual == SCSI_SENSEQ_INITIATOR_RESPONSE_TIMEOUT)) {
5089 //
5090 // Fail requests that report this error back to the application.
5091 //
5092 retry = FALSE;
5093
5094 //
5095 // Log a more descriptive error and avoid a second
5096 // error message (IO_ERR_CONTROLLER_ERROR) being logged.
5097 //
5098 logHardwareError = TRUE;
5099 logError = FALSE;
5100 }
5101 }
5102
5103 //
5104 // If CRC error was returned, retry after a slight delay.
5105 //
5106 if (addlSenseCode == SCSI_ADSENSE_LUN_COMMUNICATION &&
5107 addlSenseCodeQual == SCSI_SESNEQ_COMM_CRC_ERROR) {
5108 retry = TRUE;
5109 retryInterval = 1;
5110 logHardwareError = FALSE;
5111 logError = FALSE;
5112 }
5113
5114 //
5115 // Hardware errors warrant a more descriptive error.
5116 // Specifically, we need to ensure this disk is easily
5117 // identifiable.
5118 //
5119 if (logHardwareError) {
5120 UCHAR senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb);
5121 UCHAR senseBufferSize = 0;
5122
5123 if (ScsiGetTotalSenseByteCountIndicated(senseBuffer,
5124 senseInfoBufferLength,
5125 &senseBufferSize)) {
5126
5127 senseBufferSize = min(senseBufferSize, senseInfoBufferLength);
5128
5129 } else {
5130 //
5131 // it's smaller than required to read the total number of
5132 // valid bytes, so just use the SenseInfoBufferLength field.
5133 //
5134 senseBufferSize = senseInfoBufferLength;
5135 }
5136
5138 senseBufferSize,
5139 senseBuffer,
5143 cdbLength,
5144 cdb,
5145 NULL);
5146 }
5147
5148 break;
5149 } // end SCSI_SENSE_HARDWARE_ERROR
5150
5152
5153 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5154 "Illegal SCSI request\n"));
5156 retry = FALSE;
5157
5158 switch (addlSenseCode) {
5159
5160 case SCSI_ADSENSE_NO_SENSE: {
5161
5162 switch (addlSenseCodeQual) {
5163
5164 //
5165 // 1. Duplicate List Identifier
5166 //
5168
5169 //
5170 // XCOPY, READ BUFFER and CHANGE ALIASES return this sense combination under
5171 // certain conditions. Since these commands aren't sent down natively by the
5172 // Windows OS, return the default error for them and only handle this sense
5173 // combination for offload data transfer commands.
5174 //
5176
5177 TracePrint((TRACE_LEVEL_ERROR,
5178 TRACE_FLAG_IOCTL,
5179 "ClassInterpretSenseInfo (%p): Duplicate List Identifier (command %x, parameter field offset 0x%016llx)\n",
5180 Fdo,
5181 cdbOpcode,
5182 information));
5183
5184 NT_ASSERTMSG("Duplicate list identifier specified", FALSE);
5185
5186 //
5187 // The host should ensure that it uses unique list id for each TokenOperation request.
5188 //
5190 }
5191 break;
5192 }
5193 }
5194 break;
5195 }
5196
5198
5199 switch (addlSenseCodeQual) {
5200
5201 //
5202 // 1. Source/Destination pairing can't communicate with each other or the copy manager.
5203 //
5205
5206 TracePrint((TRACE_LEVEL_ERROR,
5207 TRACE_FLAG_IOCTL,
5208 "ClassInterpretSenseInfo (%p): Source-Destination LUNs can't communicate (command %x)\n",
5209 Fdo,
5210 cdbOpcode));
5211
5213 break;
5214 }
5215 }
5216 break;
5217 }
5218
5220
5221 switch (addlSenseCodeQual) {
5222
5223 //
5224 // 1. Sum of logical block fields in all block device range descriptors is greater than number
5225 // of logical blocks in the ROD minus block offset into ROD
5226 //
5228
5229 TracePrint((TRACE_LEVEL_ERROR,
5230 TRACE_FLAG_IOCTL,
5231 "ClassInterpretSenseInfo (%p): Host specified a transfer length greater than what is represented by the token (considering the offset) [command %x]\n",
5232 Fdo,
5233 cdbOpcode));
5234
5235 NT_ASSERTMSG("Host specified blocks to write beyond what is represented by the token", FALSE);
5236
5238 break;
5239 }
5240 }
5241 break;
5242 }
5243
5244 //
5245 // 1. Parameter data truncation (e.g. last descriptor was not fully specified)
5246 //
5248
5249 TracePrint((TRACE_LEVEL_ERROR,
5250 TRACE_FLAG_IOCTL,
5251 "ClassInterpretSenseInfo (%p): Target truncated the block device range descriptors in the parameter list (command %x)\n",
5252 Fdo,
5253 cdbOpcode));
5254
5255 NT_ASSERTMSG("Parameter data truncation", FALSE);
5256
5258 break;
5259 }
5260
5262 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5263 "Illegal command\n"));
5264 break;
5265 }
5266
5268
5269 LARGE_INTEGER logicalBlockAddr;
5270 LARGE_INTEGER lastLBA;
5271 ULONG numTransferBlocks = 0;
5272
5273 logicalBlockAddr.QuadPart = 0;
5274
5275 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: Illegal block address\n"));
5276
5278
5279 if (Fdo->DeviceType == FILE_DEVICE_DISK) {
5280
5281 if (IS_SCSIOP_READWRITE(cdbOpcode) && cdb) {
5282
5283 if (TEST_FLAG(fdoExtension->DeviceFlags, DEV_USE_16BYTE_CDB)) {
5284 REVERSE_BYTES_QUAD(&logicalBlockAddr, &cdb->CDB16.LogicalBlock);
5285 REVERSE_BYTES(&numTransferBlocks, &cdb->CDB16.TransferLength);
5286 } else {
5287 REVERSE_BYTES(&logicalBlockAddr.LowPart, &cdb->CDB10.LogicalBlockByte0);
5288 REVERSE_BYTES_SHORT((PUSHORT)&numTransferBlocks, &cdb->CDB10.TransferBlocksMsb);
5289 }
5290
5292
5293 if ((logicalBlockAddr.QuadPart > lastLBA.QuadPart) ||
5294 ((logicalBlockAddr.QuadPart + numTransferBlocks - 1) > lastLBA.QuadPart)) {
5295
5296 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5297 "Request beyond boundary. Last LBA: 0x%I64X Read LBA: 0x%I64X Length: 0x%X\n",
5298 (__int64) lastLBA.QuadPart, (__int64) logicalBlockAddr.QuadPart, numTransferBlocks));
5299 } else {
5300 //
5301 // Should only retry these if the request was
5302 // truly within our expected size.
5303 //
5304 // Fujitsu IDE drives have been observed to
5305 // return this error transiently for a legal LBA;
5306 // manual retry in the debugger then works, so
5307 // there is a good chance that a programmed retry
5308 // will also work.
5309 //
5310
5311 retry = TRUE;
5312 retryInterval = 5;
5313 }
5314 } else if (ClasspIsOffloadDataTransferCommand(cdb)) {
5315
5316 //
5317 // 1. Number of logical blocks of block device range descriptor exceeds capacity of the medium
5318 //
5319 TracePrint((TRACE_LEVEL_ERROR,
5320 TRACE_FLAG_IOCTL,
5321 "ClassInterpretSenseInfo (%p): LBA out of range (command %x, parameter field offset 0x%016llx)\n",
5322 Fdo,
5323 cdbOpcode,
5324 information));
5325
5326 NT_ASSERTMSG("Number of blocks specified exceeds LUN capacity", FALSE);
5327 }
5328 }
5329 break;
5330 }
5331
5332 //
5333 // 1. Generic error - cause not reportable
5334 // 2. Insufficient resources to create ROD
5335 // 3. Insufficient resources to create Token
5336 // 4. Max number of tokens exceeded
5337 // 5. Remote Token creation not supported
5338 // 6. Token expired
5339 // 7. Token unknown
5340 // 8. Unsupported Token type
5341 // 9. Token corrupt
5342 // 10. Token revoked
5343 // 11. Token cancelled
5344 // 12. Remote Token usage not supported
5345 //
5347
5348 TracePrint((TRACE_LEVEL_ERROR,
5349 TRACE_FLAG_IOCTL,
5350 "ClassInterpretSenseInfo (%p): Invalid/Expired/Modified token specified (command %x, parameter field offset 0x%016llx)\n",
5351 Fdo,
5352 cdbOpcode,
5353 information));
5354
5356 break;
5357 }
5358
5361
5362 //
5363 // 1. Mismatched I_T nexus and list identifier
5364 //
5365 TracePrint((TRACE_LEVEL_ERROR,
5366 TRACE_FLAG_IOCTL,
5367 "ClassInterpretSenseInfo (%p): Incorrect I_T nexus likely used (command %x)\n",
5368 Fdo,
5369 cdbOpcode));
5370
5371 //
5372 // The host should ensure that it sends TokenOperation and ReceiveTokenInformation for the same
5373 // list Id using the same I_T nexus.
5374 //
5376
5377 } else {
5378
5379 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5380 "Invalid CDB\n"));
5381
5382 //
5383 // Note: the retry interval is not typically used.
5384 // it is set here only because a ClassErrorHandler
5385 // cannot set the retryInterval, and the error may
5386 // require a few commands to be sent to clear whatever
5387 // caused this condition (i.e. disk clears the write
5388 // cache, requiring at least two commands)
5389 //
5390 // hopefully, this shortcoming can be changed for
5391 // blackcomb.
5392 //
5393
5394 retryInterval = 3;
5395 }
5396 break;
5397 }
5398
5400 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5401 "Invalid LUN\n"));
5403 break;
5404 }
5405
5407
5408 switch (addlSenseCodeQual) {
5409
5410 //
5411 // 1. Alignment violation (e.g. copy manager is unable to copy because destination offset is NOT aligned to LUN's granularity/alignment)
5412 //
5414
5415 TracePrint((TRACE_LEVEL_ERROR,
5416 TRACE_FLAG_IOCTL,
5417 "ClassInterpretSenseInfo (%p): Alignment violation for command %x.\n",
5418 Fdo,
5419 cdbOpcode));
5420
5421 NT_ASSERTMSG("Specified offset is not aligned to LUN's granularity", FALSE);
5422
5424 break;
5425 }
5426
5427 //
5428 // 1. Number of block device range descriptors is greater than maximum range descriptors
5429 //
5431
5432 TracePrint((TRACE_LEVEL_ERROR,
5433 TRACE_FLAG_IOCTL,
5434 "ClassInterpretSenseInfo (%p): Too many descriptors in parameter list for command %x (parameter field offset 0x%016llx)\n",
5435 Fdo,
5436 cdbOpcode,
5437 information));
5438
5439 NT_ASSERTMSG("Too many descriptors specified", FALSE);
5440
5442 break;
5443 }
5444
5445 default: {
5446
5448
5449 //
5450 // 1. (Various) Invalid parameter length
5451 // 2. Requested inactivity timeout is greater than maximum inactivity timeout
5452 // 3. Same LBA is included in more than one block device range descriptor (overlapping LBAs)
5453 // 4. Total number of logical blocks of all block range descriptors is greater than the maximum transfer size
5454 // 5. Total number of logical blocks of all block range descriptors is greater than maximum token transfer size
5455 // (e.g. WriteUsingToken descriptors specify a cumulative total block count that exceeds the PopulateToken that created the token)
5456 // 6. Block offset into ROD specified an offset that is greater than or equal to the number of logical blocks in the ROD
5457 // 7. Number of logical blocks in a block device range descriptor is greater than maximum transfer length in blocks
5458 //
5459 TracePrint((TRACE_LEVEL_ERROR,
5460 TRACE_FLAG_IOCTL,
5461 "ClassInterpretSenseInfo (%p): Illegal field in parameter list for command %x (parameter field offset 0x%016llx) [AddSense %x, AddSenseQ %x]\n",
5462 Fdo,
5463 cdbOpcode,
5465 addlSenseCode,
5466 addlSenseCodeQual));
5467
5468 NT_ASSERTMSG("Invalid field in parameter list", FALSE);
5469
5471 }
5472
5473 break;
5474 }
5475 }
5476 break;
5477 }
5478
5480 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5481 "Copy protection failure\n"));
5482
5484
5485 switch (addlSenseCodeQual) {
5487 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5488 "ClassInterpretSenseInfo: "
5489 "Authentication failure\n"));
5491 break;
5493 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5494 "ClassInterpretSenseInfo: "
5495 "Key not present\n"));
5497 break;
5499 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5500 "ClassInterpretSenseInfo: "
5501 "Key not established\n"));
5503 break;
5505 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5506 "ClassInterpretSenseInfo: "
5507 "Read of scrambled sector w/o "
5508 "authentication\n"));
5510 break;
5512 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5513 "ClassInterpretSenseInfo: "
5514 "Media region does not logical unit "
5515 "region\n"));
5517 break;
5519 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5520 "ClassInterpretSenseInfo: "
5521 "Region set error -- region may "
5522 "be permanent\n"));
5524 break;
5525 } // end switch of ASCQ for COPY_PROTECTION_FAILURE
5526
5527 break;
5528 }
5529
5531 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5532 "Music area\n"));
5533 break;
5534 }
5535
5537 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5538 "Data area\n"));
5539 break;
5540 }
5541
5543 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5544 "Volume overflow\n"));
5545 break;
5546 }
5547
5548 } // end switch (addlSenseCode)
5549
5550 break;
5551 } // end SCSI_SENSE_ILLEGAL_REQUEST
5552
5554
5555 ULONG count;
5556
5557 //
5558 // A media change may have occured so increment the change
5559 // count for the physical device
5560 //
5561
5562 count = InterlockedIncrement((volatile LONG *)&fdoExtension->MediaChangeCount);
5563 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassInterpretSenseInfo: "
5564 "Media change count for device %d incremented to %#lx\n",
5565 fdoExtension->DeviceNumber, count));
5566
5567
5568 switch (addlSenseCode) {
5570 logRetryableError = FALSE;
5571 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassInterpretSenseInfo: "
5572 "Media changed\n"));
5573
5574 if (!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
5575 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_MCN, "ClassInterpretSenseInfo: "
5576 "Media Changed on non-removable device %p\n",
5577 Fdo));
5578 }
5579 ClassSetMediaChangeState(fdoExtension, MediaPresent, FALSE);
5580 break;
5581 }
5582
5584 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5585 "Bus reset\n"));
5586 break;
5587 }
5588
5590 logRetryableError = FALSE;
5591 if (addlSenseCodeQual == SCSI_SENSEQ_CAPACITY_DATA_CHANGED) {
5592 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5593 "Device capacity changed (e.g. thinly provisioned LUN). Retry the request.\n"));
5594
5596
5597 //
5598 // Retry with 1 second delay as ClassQueueCapacityChangedEventWorker may trigger a couple of commands sent to disk.
5599 //
5600 retryInterval = 1;
5601 retry = TRUE;
5602 }
5603 break;
5604 }
5605
5607
5608 switch (addlSenseCodeQual) {
5609
5611
5612 logRetryableError = FALSE;
5613 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5614 "Device (%p) has hit a soft threshold.\n",
5615 Fdo));
5616
5617 //
5618 // This indicates that a resource provisioned or thinly
5619 // provisioned device has hit a soft threshold. Queue a
5620 // worker thread to log a system event and then retry the
5621 // original request.
5622 //
5624 break;
5625 }
5626 default: {
5627 retry = FALSE;
5628 break;
5629 }
5630
5631 } // end switch (addlSenseCodeQual)
5632 break;
5633 }
5634
5636
5637 if (addlSenseCodeQual == SCSI_SENSEQ_MICROCODE_CHANGED) {
5638 //
5639 // Device firmware has been changed. Retry the request.
5640 //
5641 logRetryableError = TRUE;
5642 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5643 "Device firmware has been changed.\n"));
5644
5645 retryInterval = 1;
5646 retry = TRUE;
5647 } else {
5648 //
5649 // Device information has changed, we need to rescan the
5650 // bus for changed information such as the capacity.
5651 //
5652 logRetryableError = FALSE;
5653 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5654 "Device information changed. Invalidate the bus\n"));
5655
5656 if (addlSenseCodeQual == SCSI_SENSEQ_INQUIRY_DATA_CHANGED) {
5657
5659 }
5660
5661 if (addlSenseCodeQual == SCSI_SENSEQ_INQUIRY_DATA_CHANGED ||
5662 addlSenseCodeQual == SCSI_SENSEQ_OPERATING_DEFINITION_CHANGED) {
5663
5664 //
5665 // Since either the LB provisioning type changed, or the block/slab size
5666 // changed, next time anyone trying to query the FunctionSupportInfo, we
5667 // will requery the device.
5668 //
5669 InterlockedIncrement((volatile LONG *)&fdoExtension->FunctionSupportInfo->ChangeRequestCount);
5670 }
5671
5673 retryInterval = 5;
5674 }
5675 break;
5676 }
5677
5679 switch (addlSenseCodeQual) {
5680
5682 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5683 "Ejection request received!\n"));
5684 ClassSendEjectionNotification(fdoExtension);
5685 break;
5686 }
5687
5689 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5690 "Operator selected write permit?! "
5691 "(unsupported!)\n"));
5692 break;
5693 }
5694
5696 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5697 "Operator selected write protect?! "
5698 "(unsupported!)\n"));
5699 break;
5700 }
5701 }
5702 }
5703
5705
5706 UCHAR wmiEventData[sizeof(ULONG)+sizeof(UCHAR)] = {0};
5707
5708 *((PULONG)wmiEventData) = sizeof(UCHAR);
5709 wmiEventData[sizeof(ULONG)] = addlSenseCodeQual;
5710
5711 //
5712 // Don't log another eventlog if we have already logged once
5713 // NOTE: this should have been interlocked, but the structure
5714 // was publicly defined to use a BOOLEAN (char). Since
5715 // media only reports these errors once per X minutes,
5716 // the potential race condition is nearly non-existant.
5717 // the worst case is duplicate log entries, so ignore.
5718 //
5719
5720 logError = FALSE;
5721 if (fdoExtension->FailurePredicted == 0) {
5722 logError = TRUE;
5723 }
5724 fdoExtension->FailureReason = addlSenseCodeQual;
5725 logStatus = IO_WRN_FAILURE_PREDICTED;
5726
5727 ClassNotifyFailurePredicted(fdoExtension,
5728 (PUCHAR)wmiEventData,
5729 sizeof(wmiEventData),
5730 FALSE, // do not log error
5731 4, // unique error value
5734 SrbGetLun(Srb));
5735
5736 fdoExtension->FailurePredicted = TRUE;
5737
5738 //
5739 // Since this is a Unit Attention we need to make
5740 // sure we retry this request.
5741 //
5742 retry = TRUE;
5743
5744 break;
5745 }
5746
5747 default: {
5748 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5749 "Unit attention\n"));
5750 break;
5751 }
5752
5753 } // end switch (addlSenseCode)
5754
5755 if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA))
5756 {
5757
5758 if ((ClassGetVpb(Fdo) != NULL) && (ClassGetVpb(Fdo)->Flags & VPB_MOUNTED))
5759 {
5760 //
5761 // Set bit to indicate that media may have changed
5762 // and volume needs verification.
5763 //
5764
5765 SET_FLAG(Fdo->Flags, DO_VERIFY_VOLUME);
5766
5768 retry = FALSE;
5769 }
5770 else {
5772 }
5773 }
5774 else
5775 {
5777 }
5778
5779 break;
5780
5781 } // end SCSI_SENSE_UNIT_ATTENTION
5782
5784
5785 retry = FALSE;
5786
5787 if (addlSenseCode == SCSI_ADSENSE_WRITE_PROTECT)
5788 {
5789 switch (addlSenseCodeQual) {
5790
5792
5793 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5794 "Device's (%p) resources are exhausted.\n",
5795 Fdo));
5796
5798
5799 //
5800 // This indicates that a thinly-provisioned device has
5801 // hit a permanent resource exhaustion. We need to
5802 // return this status code so that patmgr can take the
5803 // disk offline.
5804 //
5806 break;
5807 }
5808 default:
5809 {
5810 break;
5811 }
5812
5813 } // end switch addlSenseCodeQual
5814 }
5815 else
5816 {
5817 if (IS_SCSIOP_WRITE(cdbOpcode)) {
5818 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5819 "Media write protected\n"));
5821 } else {
5822 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5823 "Access denied\n"));
5825 }
5826 }
5827 break;
5828 } // end SCSI_SENSE_DATA_PROTECT
5829
5831 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5832 "Media blank check\n"));
5833 retry = FALSE;
5835 break;
5836 } // end SCSI_SENSE_BLANK_CHECK
5837
5839
5840 switch (addlSenseCode) {
5841
5843
5844 switch (addlSenseCodeQual) {
5845
5846 //
5847 // 1. Target truncated the data transfer.
5848 //
5850
5851 TracePrint((TRACE_LEVEL_WARNING,
5852 TRACE_FLAG_IOCTL,
5853 "ClassInterpretSenseInfo (%p): Data transfer was truncated (command %x)\n",
5854 Fdo,
5855 cdbOpcode));
5856
5858 retry = FALSE;
5859 break;
5860 }
5861 }
5862 break;
5863 }
5864 }
5865 break;
5866 }
5867
5870
5871 switch (addlSenseCode) {
5872
5874
5875 switch (addlSenseCodeQual) {
5876
5877 //
5878 // 1. Target truncated the data transfer.
5879 //
5881
5882 TracePrint((TRACE_LEVEL_WARNING,
5883 TRACE_FLAG_IOCTL,
5884 "ClassInterpretSenseInfo (%p): Target has truncated the data transfer (command %x)\n",
5885 Fdo,
5886 cdbOpcode));
5887
5889 retry = FALSE;
5890 break;
5891 }
5892 }
5893 break;
5894 }
5895
5897
5898 switch (addlSenseCodeQual) {
5899
5900 //
5901 // 1. Copy manager wasn't able to finish the operation because of insuffient resources
5902 // (e.g. microsnapshot failure on read, no space on write, etc.)
5903 //
5905
5906 TracePrint((TRACE_LEVEL_ERROR,
5907 TRACE_FLAG_IOCTL,
5908 "ClassInterpretSenseInfo (%p): Target has insufficient resources (command %x)\n",
5909 Fdo,
5910 cdb->CDB6GENERIC.OperationCode));
5911
5913 retry = FALSE;
5914 break;
5915 }
5916 }
5917 break;
5918 }
5919 }
5920 } else {
5921 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5922 "Command aborted\n"));
5924 retryInterval = 1;
5925 }
5926 break;
5927 } // end SCSI_SENSE_ABORTED_COMMAND
5928
5929 default: {
5930 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5931 "Unrecognized sense code\n"));
5933 break;
5934 }
5935
5936 } // end switch (senseKey)
5937
5938
5939
5940 //
5941 // Try to determine bad sector information from sense data
5942 //
5943
5944 if (((IS_SCSIOP_READWRITE(cdbOpcode)) ||
5945 (cdbOpcode == SCSIOP_VERIFY) ||
5946 (cdbOpcode == SCSIOP_VERIFY16)) && cdb) {
5947
5948 if (isInformationValid)
5949 {
5950 readSector = 0;
5951 badSector = information;
5952
5953 if (cdbOpcode == SCSIOP_READ16 || cdbOpcode == SCSIOP_WRITE16 || cdbOpcode == SCSIOP_VERIFY16) {
5954 REVERSE_BYTES_QUAD(&readSector, &(cdb->AsByte[2]));
5955 } else {
5956 REVERSE_BYTES(&readSector, &(cdb->AsByte[2]));
5957 }
5958
5959 if (cdbOpcode == SCSIOP_READ || cdbOpcode == SCSIOP_WRITE || cdbOpcode == SCSIOP_VERIFY) {
5960 REVERSE_BYTES_SHORT(&index, &(cdb->CDB10.TransferBlocksMsb));
5961 } else if (cdbOpcode == SCSIOP_READ6 || cdbOpcode == SCSIOP_WRITE6) {
5962 index = cdb->CDB6READWRITE.TransferBlocks;
5963 } else if(cdbOpcode == SCSIOP_READ12 || cdbOpcode == SCSIOP_WRITE12) {
5964 REVERSE_BYTES(&index, &(cdb->CDB12.TransferLength));
5965 } else {
5966 REVERSE_BYTES(&index, &(cdb->CDB16.TransferLength));
5967 }
5968
5969 //
5970 // Make sure the bad sector is within the read sectors.
5971 //
5972
5973 if (!(badSector >= readSector && badSector < readSector + index)) {
5974 badSector = readSector;
5975 }
5976 }
5977 }
5978 }
5979
5980__ClassInterpretSenseInfo_ProcessingInvalidSenseBuffer:
5981
5982 if (!validSense) {
5983
5984 //
5985 // Request sense buffer not valid. No sense information
5986 // to pinpoint the error. Return general request fail.
5987 //
5988
5989 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5990 "Request sense info not valid. SrbStatus %2x\n",
5992 retry = TRUE;
5993
5994
5995 switch (SRB_STATUS(Srb->SrbStatus)) {
5996 case SRB_STATUS_ABORTED: {
5997
5998 //
5999 // Update the error count for the device.
6000 //
6001
6002 incrementErrorCount = TRUE;
6004 retryInterval = 1;
6005 retry = TRUE;
6006 break;
6007 }
6008
6009 case SRB_STATUS_ERROR: {
6010
6013
6014 //
6015 // This is some strange return code. Update the error
6016 // count for the device.
6017 //
6018
6019 incrementErrorCount = TRUE;
6020
6021 } else if (SrbGetScsiStatus(Srb) == SCSISTAT_BUSY) {
6022
6024 logRetryableError = FALSE;
6025 }
6026
6027 break;
6028 }
6029
6032 retry = FALSE;
6033 break;
6034 }
6035
6038 case SRB_STATUS_NO_HBA:
6042 retry = FALSE;
6043 break;
6044 }
6045
6047 logError = TRUE;
6048 logStatus = IO_ERR_NOT_READY;
6049 uniqueId = 260;
6051 retry = FALSE;
6052 break;
6053 }
6054
6055 case SRB_STATUS_TIMEOUT:
6057
6058 //
6059 // Update the error count for the device.
6060 //
6061 incrementErrorCount = TRUE;
6063 break;
6064 }
6065
6068
6069 //
6070 // Update the error count for the device
6071 // and fall through to below
6072 //
6073 incrementErrorCount = TRUE;
6074
6075 case SRB_STATUS_BUS_RESET: {
6076
6078 logRetryableError = FALSE;
6079 break;
6080 }
6081
6083
6085 retry = FALSE;
6086
6087 //
6088 // For some commands, we allocate a buffer that may be
6089 // larger than necessary. In these cases, the SRB may be
6090 // returned with SRB_STATUS_DATA_OVERRUN to indicate a
6091 // buffer *underrun*. However, the command was still
6092 // successful so we ensure STATUS_SUCCESS is returned.
6093 // We will also prevent these errors from causing noise in
6094 // the error logs.
6095 //
6096 if ((cdbOpcode == SCSIOP_MODE_SENSE && SrbGetDataTransferLength(Srb) <= cdb->MODE_SENSE.AllocationLength) ||
6097 (cdbOpcode == SCSIOP_INQUIRY && SrbGetDataTransferLength(Srb) <= cdb->CDB6INQUIRY.AllocationLength)) {
6099 logErrorInternal = FALSE;
6100 logError = FALSE;
6101 } else if (cdbOpcode == SCSIOP_MODE_SENSE10) {
6102 USHORT allocationLength;
6103 REVERSE_BYTES_SHORT(&(cdb->MODE_SENSE10.AllocationLength), &allocationLength);
6104 if (SrbGetDataTransferLength(Srb) <= allocationLength) {
6106 logErrorInternal = FALSE;
6107 logError = FALSE;
6108 }
6109 } else if (ClasspIsReceiveTokenInformation(cdb)) {
6110 ULONG allocationLength;
6111 REVERSE_BYTES(&(cdb->RECEIVE_TOKEN_INFORMATION.AllocationLength), &allocationLength);
6112 if (SrbGetDataTransferLength(Srb) <= allocationLength) {
6114 logErrorInternal = FALSE;
6115 logError = FALSE;
6116 }
6117 }
6118
6119 break;
6120 }
6121
6123
6124 //
6125 // Update the error count for the device.
6126 //
6127
6128 incrementErrorCount = TRUE;
6130
6131 //
6132 // If there was phase sequence error then limit the number of
6133 // retries.
6134 //
6135
6136 if (RetryCount > 1 ) {
6137 retry = FALSE;
6138 }
6139
6140 break;
6141 }
6142
6144
6145 //
6146 // If the status needs verification bit is set. Then set
6147 // the status to need verification and no retry; otherwise,
6148 // just retry the request.
6149 //
6150
6151 if (TEST_FLAG(Fdo->Flags, DO_VERIFY_VOLUME)) {
6152
6154 retry = FALSE;
6155
6156 } else {
6158 logRetryableError = FALSE;
6159 }
6160
6161 break;
6162 }
6163
6164
6165 default: {
6166 logError = TRUE;
6167 logStatus = IO_ERR_CONTROLLER_ERROR;
6168 uniqueId = 259;
6170 unhandledError = TRUE;
6171 logRetryableError = FALSE;
6172 break;
6173 }
6174 }
6175
6176
6177 //
6178 // NTRAID #183546 - if we support GESN subtype NOT_READY events, and
6179 // we know from a previous poll when the device will be ready (ETA)
6180 // we should delay the retry more appropriately than just guessing.
6181 //
6182 /*
6183 if (fdoExtension->MediaChangeDetectionInfo &&
6184 fdoExtension->MediaChangeDetectionInfo->Gesn.Supported &&
6185 TEST_FLAG(fdoExtension->MediaChangeDetectionInfo->Gesn.EventMask,
6186 NOTIFICATION_DEVICE_BUSY_CLASS_MASK)
6187 ) {
6188 // check if Gesn.ReadyTime if greater than current tick count
6189 // if so, delay that long (from 1 to 30 seconds max?)
6190 // else, leave the guess of time alone.
6191 }
6192 */
6193
6194 }
6195
6196 }
6197
6198 if (incrementErrorCount) {
6199
6200 //
6201 // if any error count occurred, delay the retry of this io by
6202 // at least one second, if caller supports it.
6203 //
6204
6205 if (retryInterval == 0) {
6206 retryInterval = 1;
6207 }
6208 ClasspPerfIncrementErrorCount(fdoExtension);
6209 }
6210
6211 //
6212 // If there is a class specific error handler call it.
6213 //
6214
6215 if (fdoExtension->CommonExtension.DevInfo->ClassError != NULL) {
6216
6217 SCSI_REQUEST_BLOCK tempSrb = {0};
6219
6220 //
6221 // If class driver does not support extended SRB and this is
6222 // an extended SRB, convert to legacy SRB and pass to class
6223 // driver.
6224 //
6226 ((fdoExtension->CommonExtension.DriverExtension->SrbSupport &
6229 srbPtr = &tempSrb;
6230 }
6231
6232 fdoExtension->CommonExtension.DevInfo->ClassError(Fdo,
6233 srbPtr,
6234 Status,
6235 &retry);
6236 }
6237
6238 //
6239 // If the caller wants to know the suggested retry interval tell them.
6240 //
6241
6242 if (ARGUMENT_PRESENT(RetryInterval)) {
6243 *RetryInterval = retryInterval;
6244 }
6245
6246 //
6247 // The RESERVE(6) / RELEASE(6) commands are optional. So
6248 // if they aren't supported, try the 10-byte equivalents
6249 //
6250
6251 cdb = SrbGetCdb(Srb);
6252 if (cdb) {
6253 cdbOpcode = cdb->CDB6GENERIC.OperationCode;
6254 }
6255
6256 if ((cdbOpcode == SCSIOP_RESERVE_UNIT ||
6257 cdbOpcode == SCSIOP_RELEASE_UNIT) && cdb)
6258 {
6260 {
6261 SrbSetCdbLength(Srb, 10);
6262 cdb->CDB10.OperationCode = (cdb->CDB6GENERIC.OperationCode == SCSIOP_RESERVE_UNIT) ? SCSIOP_RESERVE_UNIT10 : SCSIOP_RELEASE_UNIT10;
6263
6264 SET_FLAG(fdoExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_RESERVE6);
6265 retry = TRUE;
6266 }
6267 }
6268
6269#if DBG
6270
6271 //
6272 // Ensure that for read/write requests, only return STATUS_DEVICE_BUSY if
6273 // reservation conflict.
6274 //
6275 if (IS_SCSIOP_READWRITE(cdbOpcode) && (*Status == STATUS_DEVICE_BUSY)) {
6276 NT_ASSERT(isReservationConflict == TRUE);
6277 }
6278
6279#endif
6280
6281 /*
6282 * LOG the error:
6283 * If logErrorInternal is set, log the error in our internal log.
6284 * If logError is set, also log the error in the system log.
6285 */
6286 if (logErrorInternal || logError) {
6287 ULONG totalSize;
6288 ULONG senseBufferSize = 0;
6289 IO_ERROR_LOG_PACKET staticErrLogEntry = {0};
6290 CLASS_ERROR_LOG_DATA staticErrLogData = {0};
6291 SENSE_DATA convertedSenseBuffer = {0};
6292 UCHAR convertedSenseBufferLength = 0;
6293 BOOLEAN senseDataConverted = FALSE;
6294
6295 //
6296 // Logic below assumes that IO_ERROR_LOG_PACKET + CLASS_ERROR_LOG_DATA
6297 // is less than ERROR_LOG_MAXIMUM_SIZE which is not true for extended SRB.
6298 // Given that classpnp currently does not use >16 byte CDB, we'll convert
6299 // an extended SRB to SCSI_REQUEST_BLOCK instead of changing this code.
6300 // More changes will need to be made when classpnp starts using >16 byte
6301 // CDBs.
6302 //
6303
6304 //
6305 // Calculate the total size of the error log entry.
6306 // add to totalSize in the order that they are used.
6307 // the advantage to calculating all the sizes here is
6308 // that we don't have to do a bunch of extraneous checks
6309 // later on in this code path.
6310 //
6311 totalSize = sizeof(IO_ERROR_LOG_PACKET) // required
6312 + sizeof(CLASS_ERROR_LOG_DATA);// struct for ease
6313
6314 //
6315 // also save any available extra sense data, up to the maximum errlog
6316 // packet size . WMI should be used for real-time analysis.
6317 // the event log should only be used for post-mortem debugging.
6318 //
6319 if ((TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID)) && senseBuffer) {
6320
6321 UCHAR validSenseBytes = 0;
6322 UCHAR senseInfoBufferLength = 0;
6323
6324 senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb);
6325
6326 //
6327 // If sense data is in Descriptor format, convert it to Fixed format
6328 // for the private log.
6329 //
6330
6331 if (IsDescriptorSenseDataFormat(senseBuffer)) {
6332
6333 convertedSenseBufferLength = sizeof(convertedSenseBuffer);
6334
6335 senseDataConverted = ScsiConvertToFixedSenseFormat(senseBuffer,
6336 senseInfoBufferLength,
6337 (PVOID)&convertedSenseBuffer,
6338 convertedSenseBufferLength);
6339 }
6340
6341 //
6342 // For System Log, copy the maximum amount of available sense data
6343 //
6344
6345 if (ScsiGetTotalSenseByteCountIndicated(senseBuffer,
6346 senseInfoBufferLength,
6347 &validSenseBytes)) {
6348
6349 //
6350 // If it is able to determine number of valid bytes,
6351 // copy the maximum amount of available
6352 // sense data that can be saved into the the errlog.
6353 //
6354
6355 //
6356 // set to save the most sense buffer possible
6357 //
6358
6359 senseBufferSize = max(validSenseBytes, sizeof(staticErrLogData.SenseData));
6360 senseBufferSize = min(senseBufferSize, senseInfoBufferLength);
6361
6362 } else {
6363 //
6364 // it's smaller than required to read the total number of
6365 // valid bytes, so just use the SenseInfoBufferLength field.
6366 //
6367 senseBufferSize = senseInfoBufferLength;
6368 }
6369
6370 /*
6371 * Bump totalSize by the number of extra senseBuffer bytes
6372 * (beyond the default sense buffer within CLASS_ERROR_LOG_DATA).
6373 * Make sure to never allocate more than ERROR_LOG_MAXIMUM_SIZE.
6374 */
6375 if (senseBufferSize > sizeof(staticErrLogData.SenseData)){
6376 totalSize += senseBufferSize-sizeof(staticErrLogData.SenseData);
6377 if (totalSize > ERROR_LOG_MAXIMUM_SIZE){
6378 senseBufferSize -= totalSize-ERROR_LOG_MAXIMUM_SIZE;
6379 totalSize = ERROR_LOG_MAXIMUM_SIZE;
6380 }
6381 }
6382 }
6383
6384 //
6385 // If we've used up all of our retry attempts, set the final status to
6386 // reflect the appropriate result.
6387 //
6388 // ISSUE: the test below should also check RetryCount to determine if we will actually retry,
6389 // but there is no easy test because we'd have to consider the original retry count
6390 // for the op; besides, InterpretTransferPacketError sometimes ignores the retry
6391 // decision returned by this function. So just ErrorRetried to be true in the majority case.
6392 //
6393 if (retry){
6394 staticErrLogEntry.FinalStatus = STATUS_SUCCESS;
6395 staticErrLogData.ErrorRetried = TRUE;
6396 } else {
6397 staticErrLogEntry.FinalStatus = *Status;
6398 }
6399
6400 //
6401 // Don't log generic IO_WARNING_PAGING_FAILURE message if either the
6402 // I/O is retried, or it completed successfully.
6403 //
6404 if (logStatus == IO_WARNING_PAGING_FAILURE &&
6405 (retry || NT_SUCCESS(*Status)) ) {
6406 logError = FALSE;
6407 }
6408
6410 staticErrLogData.ErrorPaging = TRUE;
6411 }
6412 if (unhandledError) {
6413 staticErrLogData.ErrorUnhandled = TRUE;
6414 }
6415
6416 //
6417 // Calculate the device offset if there is a geometry.
6418 //
6419 staticErrLogEntry.DeviceOffset.QuadPart = (LONGLONG)badSector;
6420 staticErrLogEntry.DeviceOffset.QuadPart *= (LONGLONG)fdoExtension->DiskGeometry.BytesPerSector;
6421 if (logStatus == -1){
6422 staticErrLogEntry.ErrorCode = STATUS_IO_DEVICE_ERROR;
6423 } else {
6424 staticErrLogEntry.ErrorCode = logStatus;
6425 }
6426
6427 /*
6428 * The dump data follows the IO_ERROR_LOG_PACKET
6429 */
6430 staticErrLogEntry.DumpDataSize = (USHORT)totalSize - sizeof(IO_ERROR_LOG_PACKET);
6431
6432 staticErrLogEntry.SequenceNumber = 0;
6433 staticErrLogEntry.MajorFunctionCode = MajorFunctionCode;
6434 staticErrLogEntry.IoControlCode = IoDeviceCode;
6435 staticErrLogEntry.RetryCount = (UCHAR) RetryCount;
6436 staticErrLogEntry.UniqueErrorValue = uniqueId;
6437
6438 KeQueryTickCount(&staticErrLogData.TickCount);
6439 staticErrLogData.PortNumber = (ULONG)-1;
6440
6441 /*
6442 * Save the entire contents of the SRB.
6443 */
6446 } else {
6447 staticErrLogData.Srb = *(PSCSI_REQUEST_BLOCK)Srb;
6448 }
6449
6450 /*
6451 * For our private log, save just the default length of the SENSE_DATA.
6452 */
6453
6454 if ((senseBufferSize != 0) && senseBuffer) {
6455
6456 //
6457 // If sense buffer is in Fixed format, put it in the private log
6458 //
6459 // If sense buffer is in Descriptor format, put it in the private log if conversion to Fixed format
6460 // succeeded. Otherwise, do not put it in the private log.
6461 //
6462 // If sense buffer is in unknown format, the device or the driver probably does not populate
6463 // the first byte of sense data, we probably still want to log error in this case assuming
6464 // it's fixed format, so that its sense key, its additional sense code, and its additional sense code
6465 // qualifier would be shown in the debugger extension output. By doing so, it minimizes any potential
6466 // negative impacts to our ability to diagnose issue.
6467 //
6468 if (IsDescriptorSenseDataFormat(senseBuffer)) {
6469 if (senseDataConverted) {
6470 RtlCopyMemory(&staticErrLogData.SenseData, &convertedSenseBuffer, min(convertedSenseBufferLength, sizeof(staticErrLogData.SenseData)));
6471 }
6472 } else {
6473 RtlCopyMemory(&staticErrLogData.SenseData, senseBuffer, min(senseBufferSize, sizeof(staticErrLogData.SenseData)));
6474 }
6475 }
6476
6477 /*
6478 * Save the error log in our context.
6479 * We only save the default sense buffer length.
6480 */
6481 if (logErrorInternal) {
6482 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
6483 fdoData->ErrorLogs[fdoData->ErrorLogNextIndex] = staticErrLogData;
6484 fdoData->ErrorLogNextIndex++;
6486 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
6487 }
6488
6489 /*
6490 * Log an event if an IO is being retried for reasons that may indicate
6491 * a transient/permanent problem with the I_T_L nexus. But log the event
6492 * only once per retried IO.
6493 */
6494 if (!IS_SCSIOP_READWRITE(cdbOpcode) ||
6495 !retry ||
6496 (RetryCount != 0)) {
6497
6498 logRetryableError = FALSE;
6499 }
6500
6501 if (logRetryableError) {
6502
6503 logError = TRUE;
6504 }
6505
6506 /*
6507 * If logError is set, also save this log in the system's error log.
6508 * But make sure we don't log TUR failures over and over
6509 * (e.g. if an external drive was switched off and we're still sending TUR's to it every second).
6510 */
6511
6512 if (logError)
6513 {
6514 //
6515 // We do not want to log certain system events repetitively
6516 //
6517
6518 cdb = SrbGetCdb(Srb);
6519 if (cdb) {
6520 switch (cdb->CDB10.OperationCode)
6521 {
6523 {
6524 if (fdoData->LoggedTURFailureSinceLastIO)
6525 {
6526 logError = FALSE;
6527 }
6528 else
6529 {
6531 }
6532
6533 break;
6534 }
6535
6537 {
6538 if (fdoData->LoggedSYNCFailure)
6539 {
6540 logError = FALSE;
6541 }
6542 else
6543 {
6544 fdoData->LoggedSYNCFailure = TRUE;
6545 }
6546
6547 break;
6548 }
6549 }
6550 }
6551 }
6552
6553 if (logError){
6554
6555 if (logRetryableError) {
6556
6557 NT_ASSERT(IS_SCSIOP_READWRITE(cdbOpcode));
6558
6559 //
6560 // A large Disk TimeOutValue (like 60 seconds) results in giving a command a
6561 // large window to complete in. However, if the target returns a retryable error
6562 // just prior to the command timing out, and if multiple retries kick in, it may
6563 // take a significantly long time for the request to complete back to the
6564 // application, leading to a user perception of a hung system. So log an event
6565 // for retried IO so that an admin can help explain the reason for this behavior.
6566 //
6568 senseBufferSize,
6569 senseBuffer,
6573 cdbLength,
6574 cdb,
6575 NULL);
6576
6577 } else {
6578
6579 PIO_ERROR_LOG_PACKET errorLogEntry;
6580 PCLASS_ERROR_LOG_DATA errlogData;
6581
6582 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(Fdo, (UCHAR)totalSize);
6583 if (errorLogEntry){
6584 errlogData = (PCLASS_ERROR_LOG_DATA)errorLogEntry->DumpData;
6585
6586 *errorLogEntry = staticErrLogEntry;
6587 *errlogData = staticErrLogData;
6588
6589 /*
6590 * For the system log, copy as much of the sense buffer as possible.
6591 */
6592 if ((senseBufferSize != 0) && senseBuffer) {
6593 RtlCopyMemory(&errlogData->SenseData, senseBuffer, senseBufferSize);
6594 }
6595
6596 /*
6597 * Write the error log packet to the system error logging thread.
6598 * It will be freed by the kernel.
6599 */
6600 IoWriteErrorLogEntry(errorLogEntry);
6601 }
6602 }
6603 }
6604 }
6605
6606 return retry;
6607
6608} // end ClassInterpretSenseInfo()
#define InterlockedIncrement
Definition: armddk.h:53
#define index(s, c)
Definition: various.h:29
#define __int64
Definition: basetyps.h:16
#define DEV_SAFE_START_UNIT
Definition: cdrom.h:139
#define IS_SCSIOP_READWRITE(opCode)
Definition: cdrom.h:803
#define IS_SCSIOP_WRITE(opCode)
Definition: cdrom.h:797
#define SRB_CLASS_FLAGS_PAGING
Definition: cdrom.h:165
#define NUM_ERROR_LOG_ENTRIES
Definition: cdromp.h:323
@ MediaPresent
Definition: cdromp.h:82
@ MediaNotPresent
Definition: cdromp.h:83
@ MediaUnavailable
Definition: cdromp.h:84
#define SCSI_ADSENSE_ILLEGAL_BLOCK
Definition: cdrw_hw.h:1264
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define SCSIOP_MODE_SENSE10
Definition: cdrw_hw.h:946
#define SCSI_SENSEQ_INVALID_RELEASE_OF_PERSISTENT_RESERVATION
Definition: cdrw_hw.h:1362
#define SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED
Definition: cdrw_hw.h:1315
#define SCSI_SENSE_NO_SENSE
Definition: cdrw_hw.h:1187
#define SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED
Definition: cdrw_hw.h:1324
#define SCSI_SENSEQ_OPERATION_IN_PROGRESS
Definition: cdrw_hw.h:1317
#define SCSISTAT_RESERVATION_CONFLICT
Definition: cdrw_hw.h:1084
#define SCSI_SENSEQ_AUTHENTICATION_FAILURE
Definition: cdrw_hw.h:1390
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
#define SCSISTAT_GOOD
Definition: cdrw_hw.h:1078
#define SCSI_ADSENSE_SEEK_ERROR
Definition: cdrw_hw.h:1232
#define SCSISTAT_BUSY
Definition: cdrw_hw.h:1081
#define SCSI_ADSENSE_REC_DATA_NOECC
Definition: cdrw_hw.h:1211
#define SCSI_SENSE_COPY_ABORTED
Definition: cdrw_hw.h:1197
#define SCSI_ADSENSE_INVALID_LUN
Definition: cdrw_hw.h:1266
#define SCSI_SENSE_DATA_PROTECT
Definition: cdrw_hw.h:1194
#define SCSI_ADSENSE_INVALID_CDB
Definition: cdrw_hw.h:1265
#define SCSI_ADSENSE_WRITE_PROTECT
Definition: cdrw_hw.h:1268
#define SCSIOP_WRITE6
Definition: cdrw_hw.h:876
#define SCSI_ADSENSE_MUSIC_AREA
Definition: cdrw_hw.h:1282
#define SCSI_ADSENSE_TRACK_ERROR
Definition: cdrw_hw.h:1231
#define SCSI_SENSEQ_KEY_NOT_ESTABLISHED
Definition: cdrw_hw.h:1392
#define SCSI_SENSE_MEDIUM_ERROR
Definition: cdrw_hw.h:1190
#define SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION
Definition: cdrw_hw.h:1393
#define SCSI_ADSENSE_ILLEGAL_COMMAND
Definition: cdrw_hw.h:1263
#define SCSI_SENSEQ_UNKNOWN_FORMAT
Definition: cdrw_hw.h:1322
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
#define SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT
Definition: cdrw_hw.h:1394
#define SCSI_SENSEQ_CAUSE_NOT_REPORTABLE
Definition: cdrw_hw.h:1312
#define SCSIOP_VERIFY
Definition: cdrw_hw.h:912
#define SCSI_SENSEQ_KEY_NOT_PRESENT
Definition: cdrw_hw.h:1391
#define SCSIOP_READ6
Definition: cdrw_hw.h:874
#define SCSI_ADSENSE_REC_DATA_ECC
Definition: cdrw_hw.h:1212
#define NOT_READY_RETRY_INTERVAL
Definition: cdrw_hw.h:1094
#define SCSI_SENSEQ_BECOMING_READY
Definition: cdrw_hw.h:1313
#define SCSI_ADSENSE_INVALID_MEDIA
Definition: cdrw_hw.h:1220
#define SCSIOP_READ12
Definition: cdrw_hw.h:956
#define SCSI_SENSE_ILLEGAL_REQUEST
Definition: cdrw_hw.h:1192
#define SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR
Definition: cdrw_hw.h:1395
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define SCSI_ADSENSE_NO_SENSE
Definition: cdrw_hw.h:1207
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define SCSIOP_WRITE12
Definition: cdrw_hw.h:957
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
Definition: cdrw_hw.h:1221
#define SCSI_SENSEQ_INIT_COMMAND_REQUIRED
Definition: cdrw_hw.h:1314
#define SCSI_ADSENSE_DATA_AREA
Definition: cdrw_hw.h:1283
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define SCSI_SENSE_BLANK_CHECK
Definition: cdrw_hw.h:1195
#define SCSI_SENSE_HARDWARE_ERROR
Definition: cdrw_hw.h:1191
#define SCSI_ADSENSE_VOLUME_OVERFLOW
Definition: cdrw_hw.h:1284
#define SCSI_SENSE_RECOVERED_ERROR
Definition: cdrw_hw.h:1188
#define SCSIOP_READ
Definition: cdrw_hw.h:905
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define SCSI_SENSE_ABORTED_COMMAND
Definition: cdrw_hw.h:1198
#define SCSI_ADSENSE_BUS_RESET
Definition: cdrw_hw.h:1289
#define SCSI_SENSEQ_FORMAT_IN_PROGRESS
Definition: cdrw_hw.h:1316
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
#define SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
Definition: cdrw_hw.h:1318
VOID ClassQueueResourceExhaustionEventWorker(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:5528
VOID ClassQueueCapacityChangedEventWorker(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:5637
VOID ClasspQueueLogIOEventWithContextWorker(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG SenseBufferSize, _In_ PVOID SenseData, _In_ UCHAR SrbStatus, _In_ UCHAR ScsiStatus, _In_ ULONG ErrorCode, _In_ ULONG CdbLength, _In_opt_ PCDB Cdb, _In_opt_ PTRANSFER_PACKET Pkt)
Definition: utils.c:6010
FORCEINLINE BOOLEAN ClasspIsOffloadDataTransferCommand(_In_ PCDB Cdb)
Definition: classp.h:2087
FORCEINLINE BOOLEAN ClasspIsReceiveTokenInformation(_In_ PCDB Cdb)
Definition: classp.h:2066
VOID ClassQueueThresholdEventWorker(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:5471
VOID ClassQueueProvisioningTypeChangedEventWorker(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:5726
struct _CLASS_ERROR_LOG_DATA * PCLASS_ERROR_LOG_DATA
VOID ClasspPerfIncrementErrorCount(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: utils.c:432
VOID ClasspConvertToScsiRequestBlock(_Out_ PSCSI_REQUEST_BLOCK Srb, _In_ PSTORAGE_REQUEST_BLOCK SrbEx)
Definition: utils.c:6559
VOID ClassSendEjectionNotification(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:155
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR MajorFunctionCode
Definition: classpnp.h:484
#define DEV_USE_16BYTE_CDB
Definition: classpnp.h:183
#define CLASS_SRB_STORAGE_REQUEST_BLOCK
Definition: classpnp.h:573
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR _In_ ULONG IoDeviceCode
Definition: classpnp.h:485
static PDB_INFORMATION information
Definition: db.cpp:178
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
PVPB NTAPI ClassGetVpb(_In_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:11473
VOID NTAPI ClassSendStartUnit(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:3071
#define SCSIOP_READ16
Definition: scsi.h:914
#define SCSIOP_VERIFY16
Definition: scsi.h:916
#define SCSIOP_WRITE16
Definition: scsi.h:915
#define SRB_STATUS_INVALID_LUN
Definition: srb.h:362
#define SRB_STATUS_REQUEST_FLUSHED
Definition: srb.h:361
#define SRB_STATUS_PHASE_SEQUENCE_FAILURE
Definition: srb.h:359
#define SRB_STATUS_NO_HBA
Definition: srb.h:356
#define SRB_STATUS_BUS_RESET
Definition: srb.h:353
#define SRB_STATUS_INVALID_TARGET_ID
Definition: srb.h:363
#define SRB_STATUS_UNEXPECTED_BUS_FREE
Definition: srb.h:358
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_STATUS_ABORTED
Definition: srb.h:342
#define SRB_STATUS_INVALID_PATH_ID
Definition: srb.h:347
#define SRB_STATUS_TIMEOUT
Definition: srb.h:349
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:387
#define SRB_STATUS_ERROR
Definition: srb.h:344
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_INTERNAL_ERROR
Definition: srb.h:373
#define SRB_STATUS_COMMAND_TIMEOUT
Definition: srb.h:351
#define SRB_STATUS_PARITY_ERROR
Definition: srb.h:354
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:348
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
Status
Definition: gdiplustypes.h:25
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint index
Definition: glext.h:6031
if(dx< 0)
Definition: linetemp.h:194
#define min(a, b)
Definition: monoChain.cc:55
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define ARGUMENT_PRESENT(ArgumentPointer)
#define IO_ERR_NOT_READY
Definition: ntiologc.h:42
#define IO_ERR_SEEK_ERROR
Definition: ntiologc.h:33
#define IO_WRN_FAILURE_PREDICTED
Definition: ntiologc.h:78
#define IO_WARNING_PAGING_FAILURE
Definition: ntiologc.h:77
#define IO_ERR_CONTROLLER_ERROR
Definition: ntiologc.h:38
#define IO_WARNING_IO_OPERATION_RETRIED
Definition: ntiologc.h:114
#define IO_ERROR_IO_HARDWARE_ERROR
Definition: ntiologc.h:115
#define IO_RECOVERED_VIA_ECC
Definition: ntiologc.h:60
#define IO_ERR_BAD_BLOCK
Definition: ntiologc.h:34
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:628
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:528
#define STATUS_CLEANER_CARTRIDGE_INSTALLED
Definition: ntstatus.h:218
#define STATUS_CSS_AUTHENTICATION_FAILURE
Definition: ntstatus.h:882
#define STATUS_COPY_PROTECTION_FAILURE
Definition: ntstatus.h:881
#define STATUS_DISK_RESOURCES_EXHAUSTED
Definition: ntstatus.h:983
#define STATUS_CSS_REGION_MISMATCH
Definition: ntstatus.h:886
#define STATUS_INVALID_INITIATOR_TARGET_PATH
Definition: ntstatus.h:1005
#define STATUS_CSS_KEY_NOT_ESTABLISHED
Definition: ntstatus.h:884
#define STATUS_CSS_SCRAMBLED_SECTOR
Definition: ntstatus.h:885
#define STATUS_TOO_MANY_SEGMENT_DESCRIPTORS
Definition: ntstatus.h:1001
#define STATUS_CSS_KEY_NOT_PRESENT
Definition: ntstatus.h:883
#define STATUS_INVALID_OFFSET_ALIGNMENT
Definition: ntstatus.h:1002
#define STATUS_INVALID_TOKEN
Definition: ntstatus.h:987
#define STATUS_DEVICE_UNREACHABLE
Definition: ntstatus.h:986
#define STATUS_OPERATION_IN_PROGRESS
Definition: ntstatus.h:1004
#define STATUS_DEVICE_HARDWARE_ERROR
Definition: ntstatus.h:1017
#define STATUS_INVALID_FIELD_IN_PARAMETER_LIST
Definition: ntstatus.h:1003
#define STATUS_CSS_RESETS_EXHAUSTED
Definition: ntstatus.h:887
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
#define CLASS_SPECIAL_CAUSE_NOT_REPORTABLE_HACK
Definition: scsi_port.h:175
#define SCSI_ADSENSE_INVALID_FIELD_PARAMETER_LIST
Definition: scsi.h:672
#define ScsiGetSenseDescriptorLength(DescriptorBuffer)
Definition: scsi.h:3678
#define SCSI_ADSENSE_COPY_PROTECTION_FAILURE
Definition: scsi.h:694
#define SCSI_ADSENSE_INVALID_TOKEN
Definition: scsi.h:669
#define SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED
Definition: scsi.h:692
#define SCSI_SENSEQ_TOO_MANY_SEGMENT_DESCRIPTORS
Definition: scsi.h:799
#define SCSI_ADSENSE_LB_PROVISIONING
Definition: scsi.h:680
#define SCSI_SENSEQ_OPERATION_IS_IN_PROGRESS
Definition: scsi.h:712
#define SCSI_SENSEQ_OPERATING_DEFINITION_CHANGED
Definition: scsi.h:842
#define SCSI_SENSEQ_INSUFFICIENT_RESOURCES
Definition: scsi.h:874
#define SCSI_SENSE_DESCRIPTOR_TYPE_INFORMATION
Definition: scsi.h:630
#define SCSI_SENSEQ_INITIATOR_RESPONSE_TIMEOUT
Definition: scsi.h:867
#define SCSI_SENSEQ_INQUIRY_DATA_CHANGED
Definition: scsi.h:843
#define SCSI_SENSEQ_SPACE_ALLOC_IN_PROGRESS
Definition: scsi.h:731
#define SCSI_ADSENSE_RESOURCE_FAILURE
Definition: scsi.h:690
#define SCSI_SESNEQ_COMM_CRC_ERROR
Definition: scsi.h:738
#define SCSI_SENSEQ_SOFT_THRESHOLD_REACHED
Definition: scsi.h:828
#define SCSI_ADSENSE_LUN_COMMUNICATION
Definition: scsi.h:653
#define SCSI_SENSEQ_TIMEOUT_ON_LOGICAL_UNIT
Definition: scsi.h:834
#define IsSenseDataFormatValueValid(SenseInfoBuffer)
Definition: scsi.h:3697
UCHAR descriptorLength
Definition: scsi.h:4078
#define SCSI_SENSE_DESCRIPTOR_TYPE_BLOCK_COMMAND
Definition: scsi.h:635
#define SCSI_SENSEQ_WRITE_PROTECT_DISABLE
Definition: scsi.h:881
#define REVERSE_BYTES_SHORT(Destination, Source)
Definition: scsi.h:3474
#define SCSI_SENSEQ_MICROCODE_CHANGED
Definition: scsi.h:841
#define SCSI_ADSENSE_PARAMETERS_CHANGED
Definition: scsi.h:676
#define SCSI_SENSEQ_UNREACHABLE_TARGET
Definition: scsi.h:739
UCHAR senseKey
Definition: scsi.h:4019
#define SCSI_SENSEQ_MEDIUM_REMOVAL
Definition: scsi.h:879
struct _SENSE_DATA * PFIXED_SENSE_DATA
Definition: scsi.h:2723
#define ScsiGetSenseErrorCode(SenseInfoBuffer)
Definition: scsi.h:3676
#define SCSI_SENSEQ_CAPACITY_DATA_CHANGED
Definition: scsi.h:807
#define SCSI_ADSENSE_OPERATOR_REQUEST
Definition: scsi.h:691
#define SCSI_ADSENSE_COPY_TARGET_DEVICE_ERROR
Definition: scsi.h:657
#define SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED
Definition: scsi.h:684
#define SCSI_ADSENSE_DATA_TRANSFER_ERROR
Definition: scsi.h:688
#define SCSI_SENSEQ_DATA_UNDERRUN
Definition: scsi.h:761
PFIXED_SENSE_DATA outBuffer
Definition: scsi.h:4022
struct _SCSI_SENSE_DESCRIPTOR_BLOCK_COMMAND * PSCSI_SENSE_DESCRIPTOR_BLOCK_COMMAND
#define SCSI_ADSENSE_PARAMETER_LIST_LENGTH
Definition: scsi.h:664
#define SCSI_ADSENSE_LOGICAL_UNIT_ERROR
Definition: scsi.h:683
#define SCSI_SENSEQ_WRITE_PROTECT_ENABLE
Definition: scsi.h:880
#define SCSI_SENSEQ_SPACE_ALLOC_FAILED_WRITE_PROTECT
Definition: scsi.h:803
#define SCSI_SENSE_OPTIONS_NONE
Definition: scsi.h:3838
BOOLEAN validSense
Definition: scsi.h:4018
#define IsDescriptorSenseDataFormat(SenseInfoBuffer)
Definition: scsi.h:3685
#define KeQueryTickCount(CurrentCount)
Definition: ke.h:43
FORCEINLINE UCHAR SrbGetCdbLength(_In_ PVOID Srb)
Definition: srbhelper.h:1074
FORCEINLINE UCHAR SrbGetTargetId(_In_ PVOID Srb)
Definition: srbhelper.h:1184
FORCEINLINE UCHAR SrbGetLun(_In_ PVOID Srb)
Definition: srbhelper.h:1217
FORCEINLINE UCHAR SrbGetPathId(_In_ PVOID Srb)
Definition: srbhelper.h:1151
FORCEINLINE UCHAR SrbGetScsiStatus(_In_ PVOID Srb)
Definition: srbhelper.h:1037
FORCEINLINE PVOID SrbGetSenseInfoBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:619
FORCEINLINE ULONG SrbGetSystemStatus(_In_ PVOID Srb)
Definition: srbhelper.h:1000
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638
FORCEINLINE ULONG SrbGetDataTransferLength(_In_ PVOID Srb)
Definition: srbhelper.h:765
PCLASS_ERROR ClassError
Definition: classpnp.h:522
SENSE_DATA SenseData
Definition: classp.h:479
LARGE_INTEGER TickCount
Definition: classp.h:461
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:471
BOOLEAN LegacyErrorHandling
Definition: classp.h:971
BOOLEAN LoggedSYNCFailure
Definition: classp.h:754
KSPIN_LOCK SpinLock
Definition: classp.h:795
BOOLEAN LoggedTURFailureSinceLastIO
Definition: classp.h:753
CLASS_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES]
Definition: classp.h:821
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
ULONG BytesPerSector
Definition: ntdddisk.h:409
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
PDEVICE_OBJECT LowerPdo
Definition: classpnp.h:875
LARGE_INTEGER DeviceOffset
Definition: iotypes.h:2012
NTSTATUS ErrorCode
Definition: iotypes.h:2007
NTSTATUS FinalStatus
Definition: iotypes.h:2009
#define max(a, b)
Definition: svc.c:63
int64_t LONGLONG
Definition: typedefs.h:68
uint16_t * PUSHORT
Definition: typedefs.h:56
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_RETRY
Definition: udferr_usr.h:182
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_UNRECOGNIZED_MEDIA
Definition: udferr_usr.h:142
#define STATUS_INVALID_BLOCK_LENGTH
Definition: udferr_usr.h:175
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_NONEXISTENT_SECTOR
Definition: udferr_usr.h:143
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
#define STATUS_NO_DATA_DETECTED
Definition: udferr_usr.h:131
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_DEVICE_DATA_ERROR
Definition: udferr_usr.h:159
UCHAR AsByte[16]
Definition: scsi.h:1988
struct _CDB::_MODE_SENSE10 MODE_SENSE10
struct _CDB::_CDB12 CDB12
struct _CDB::_CDB6INQUIRY CDB6INQUIRY
struct _CDB::_MODE_SENSE MODE_SENSE
struct _CDB::_RECEIVE_TOKEN_INFORMATION RECEIVE_TOKEN_INFORMATION
struct _CDB::_CDB16 CDB16
struct _CDB::_CDB6READWRITE CDB6READWRITE
ULONG LowPart
Definition: typedefs.h:106
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ERROR_LOG_MAXIMUM_SIZE
Definition: iotypes.h:2042
#define VPB_MOUNTED
Definition: iotypes.h:1807
struct _IO_ERROR_LOG_PACKET * PIO_ERROR_LOG_PACKET
struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET

Referenced by ClasspReceivePopulateTokenInformationTransferPacketDone(), ClasspReceiveWriteUsingTokenInformationTransferPacketDone(), DiskInfoExceptionComplete(), InterpretSenseInfoWithoutHistory(), and InterpretTransferPacketError().

◆ ClassIoComplete()

NTSTATUS NTAPI ClassIoComplete ( IN PDEVICE_OBJECT  Fdo,
IN PIRP  Irp,
IN PVOID  Context 
)

Definition at line 3768 of file class.c.

3773{
3776 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
3777 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
3779 BOOLEAN retry;
3780 BOOLEAN callStartNextPacket;
3781 ULONG srbFlags;
3782 ULONG srbFunction;
3783
3784 NT_ASSERT(fdoExtension->CommonExtension.IsFdo);
3785
3787 srbFlags = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFlags;
3788 srbFunction = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFunction;
3789 } else {
3790 srbFlags = srb->SrbFlags;
3791 srbFunction = srb->Function;
3792 }
3793
3794 #if DBG
3795 if (srbFunction == SRB_FUNCTION_FLUSH) {
3796 DBGLOGFLUSHINFO(fdoData, FALSE, FALSE, TRUE);
3797 }
3798 #endif
3799
3800 //
3801 // Check SRB status for success of completing request.
3802 //
3803
3805 LONGLONG retryInterval;
3806
3807 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassIoComplete: IRP %p, SRB %p\n", Irp, srb));
3808
3809 //
3810 // Release the queue if it is frozen.
3811 //
3812
3815 }
3817 Fdo,
3818 Irp,
3819 srb,
3820 irpStack->MajorFunction,
3821 ((irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) ?
3822 irpStack->Parameters.DeviceIoControl.IoControlCode :
3823 0),
3825 ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4),
3826 &status,
3827 &retryInterval);
3828
3829 //
3830 // For Persistent Reserve requests, make sure user gets back partial data.
3831 //
3832
3833 if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
3837
3839 retry = FALSE;
3840 }
3841
3842 //
3843 // If the status is verified required and the this request
3844 // should bypass verify required then retry the request.
3845 //
3846
3847 if (TEST_FLAG(irpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME) &&
3849
3851 retry = TRUE;
3852 }
3853
3854#ifndef __REACTOS__
3855#pragma warning(suppress:4213) // okay to cast Arg4 as a ulong for this use case
3856 if (retry && ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4)--) {
3857#else
3858 if (retry && (*(ULONG *)&irpStack->Parameters.Others.Argument4)--) {
3859#endif
3860
3861
3862 //
3863 // Retry request.
3864 //
3865
3866 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "Retry request %p\n", Irp));
3867
3868 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
3869 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
3870 }
3871
3872 RetryRequest(Fdo, Irp, srb, FALSE, retryInterval);
3874 }
3875
3876 } else {
3877
3878 //
3879 // Set status for successful request
3880 //
3882 ClasspPerfIncrementSuccessfulIo(fdoExtension);
3884 } // end if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS)
3885
3886
3887 //
3888 // ensure we have returned some info, and it matches what the
3889 // original request wanted for PAGING operations only
3890 //
3891
3892 if ((NT_SUCCESS(status)) && TEST_FLAG(Irp->Flags, IRP_PAGING_IO)) {
3893 NT_ASSERT(Irp->IoStatus.Information != 0);
3894 NT_ASSERT(irpStack->Parameters.Read.Length == Irp->IoStatus.Information);
3895 }
3896
3897 //
3898 // remember if the caller wanted to skip calling IoStartNextPacket.
3899 // for legacy reasons, we cannot call IoStartNextPacket for IoDeviceControl
3900 // calls. this setting only affects device objects with StartIo routines.
3901 //
3902
3903 callStartNextPacket = !TEST_FLAG(srbFlags, SRB_FLAGS_DONT_START_NEXT_PACKET);
3904 if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
3905 callStartNextPacket = FALSE;
3906 }
3907
3908 //
3909 // Free MDL if allocated.
3910 //
3911
3912 if (TEST_FLAG(srbFlags, SRB_CLASS_FLAGS_FREE_MDL)) {
3914 IoFreeMdl(Irp->MdlAddress);
3915 Irp->MdlAddress = NULL;
3916 }
3917
3918
3919 //
3920 // Free the srb
3921 //
3922
3923 if (!TEST_FLAG(srbFlags, SRB_CLASS_FLAGS_PERSISTANT)) {
3924
3925 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
3926 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
3927 }
3928
3930 ClassFreeOrReuseSrb(fdoExtension, srb);
3931 }
3932 else {
3933 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassIoComplete is freeing an SRB (possibly) on behalf of another driver."));
3934 FREE_POOL(srb);
3935 }
3936
3937 } else {
3938
3939 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassIoComplete: Not Freeing srb @ %p because "
3940 "SRB_CLASS_FLAGS_PERSISTANT set\n", srb));
3941 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
3942 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassIoComplete: Not Freeing sensebuffer @ %p "
3943 " because SRB_CLASS_FLAGS_PERSISTANT set\n",
3944 srb->SenseInfoBuffer));
3945 }
3946
3947 }
3948
3949 //
3950 // Set status in completing IRP.
3951 //
3952
3953 Irp->IoStatus.Status = status;
3954
3955 //
3956 // Set the hard error if necessary.
3957 //
3958
3959 if (!NT_SUCCESS(status) &&
3961 (Irp->Tail.Overlay.Thread != NULL)
3962 ) {
3963
3964 //
3965 // Store DeviceObject for filesystem, and clear
3966 // in IoStatus.Information field.
3967 //
3968
3970 Irp->IoStatus.Information = 0;
3971 }
3972
3973 //
3974 // If disk firmware update succeeded, log a system event.
3975 //
3976
3977 if (NT_SUCCESS(status) &&
3978 (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) &&
3979 (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_FIRMWARE_ACTIVATE)) {
3980
3982 }
3983
3984 //
3985 // If pending has be returned for this irp then mark the current stack as
3986 // pending.
3987 //
3988
3989 if (Irp->PendingReturned) {
3991 }
3992
3994 if (callStartNextPacket) {
3995 KIRQL oldIrql;
3996 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
3997 IoStartNextPacket(Fdo, TRUE); // Yes, some IO must now be cancellable.
3998 KeLowerIrql(oldIrql);
3999 }
4000 }
4001
4003
4004 return status;
4005
4006} // end ClassIoComplete()
VOID RetryRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, PSCSI_REQUEST_BLOCK Srb, BOOLEAN Associated, LONGLONG TimeDelta100ns)
Definition: obsolete.c:359
VOID ClasspPerfIncrementSuccessfulIo(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: utils.c:486
#define SRB_CLASS_FLAGS_PERSISTANT
Definition: classpnp.h:20
BOOLEAN InterpretSenseInfoWithoutHistory(_In_ PDEVICE_OBJECT Fdo, _In_opt_ PIRP OriginalRequest, _In_ PSCSI_REQUEST_BLOCK Srb, UCHAR MajorFunctionCode, ULONG IoDeviceCode, ULONG PreviousRetryCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIn100nsUnits)
Definition: class.c:12844
#define DBGLOGFLUSHINFO(_fdoData, _isIO, _isFUA, _isFlush)
Definition: debug.h:129
#define SRB_FUNCTION_FLUSH
Definition: srb.h:323
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define IO_WARNING_DISK_FIRMWARE_UPDATED
Definition: ntiologc.h:120
VOID NTAPI IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable)
Definition: device.c:1847
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
FORCEINLINE VOID SrbClearSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:982
PDRIVER_STARTIO ClassStartIo
Definition: classpnp.h:543
BOOLEAN IsSrbLookasideListInitialized
Definition: classpnp.h:610
struct _IO_STACK_LOCATION::@3978::@3982 Read
PVOID SenseInfoBuffer
Definition: srb.h:264
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define IRP_PAGING_IO

Referenced by _Success_(), ClasspBuildRequestEx(), DiskFlushComplete(), DiskShutdownFlush(), and RetryRequest().

◆ ClassModeSelect()

NTSTATUS NTAPI ClassModeSelect ( _In_ PDEVICE_OBJECT  Fdo,
_In_reads_bytes_(Length) PCHAR  ModeSelectBuffer,
_In_ ULONG  Length,
_In_ BOOLEAN  SavePages 
)

Definition at line 6873 of file class.c.

6879{
6880#if (NTDDI_VERSION >= NTDDI_WINBLUE)
6881 return ClasspModeSelect(Fdo,
6882 ModeSelectBuffer,
6883 Length,
6884 SavePages);
6885#else
6887 UNREFERENCED_PARAMETER(ModeSelectBuffer);
6889 UNREFERENCED_PARAMETER(SavePages);
6890 return STATUS_NOT_SUPPORTED;
6891#endif
6892}
NTSTATUS ClasspModeSelect(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSelectBuffer, _In_ ULONG Length, _In_ BOOLEAN SavePages)
Definition: class.c:6919
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423

Referenced by DiskEnableInfoExceptions().

◆ ClassModeSense()

ULONG NTAPI ClassModeSense ( _In_ PDEVICE_OBJECT  Fdo,
_In_reads_bytes_(Length) PCHAR  ModeSenseBuffer,
_In_ ULONG  Length,
_In_ UCHAR  PageMode 
)

Definition at line 6637 of file class.c.

6643{
6644 PAGED_CODE();
6645
6646 return ClasspModeSense(Fdo,
6647 ModeSenseBuffer,
6648 Length,
6649 PageMode,
6651}
#define MODE_SENSE_CURRENT_VALUES
Definition: cdrw_hw.h:859
ULONG ClasspModeSense(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ UCHAR PageControl)
Definition: class.c:6681

Referenced by ClasspWriteCacheProperty(), ClasspZeroQERR(), DetermineDriveType(), DiskGetCacheInformation(), DiskGetInfoExceptionInformation(), DiskSetCacheInformation(), FormatMedia(), and ScsiFlopDeviceControl().

◆ ClassModeSenseEx()

ULONG NTAPI ClassModeSenseEx ( _In_ PDEVICE_OBJECT  Fdo,
_In_reads_bytes_(Length) PCHAR  ModeSenseBuffer,
_In_ ULONG  Length,
_In_ UCHAR  PageMode,
_In_ UCHAR  PageControl 
)

Definition at line 6656 of file class.c.

6663{
6664 PAGED_CODE();
6665#if (NTDDI_VERSION >= NTDDI_WINBLUE)
6666 return ClasspModeSense(Fdo,
6667 ModeSenseBuffer,
6668 Length,
6669 PageMode,
6670 PageControl);
6671#else
6673 UNREFERENCED_PARAMETER(ModeSenseBuffer);
6677 return 0;
6678#endif
6679}
_In_ ULONG _In_ UCHAR _In_ UCHAR PageControl
Definition: cdrom.h:1319

Referenced by DiskGetModePage().

◆ ClasspAdvanceOffloadWritePosition()

VOID ClasspAdvanceOffloadWritePosition ( _In_ POFFLOAD_WRITE_CONTEXT  OffloadWriteContext,
_In_ ULONGLONG  SectorsToAdvance 
)

Definition at line 15445 of file class.c.

15478{
15479 ULONGLONG bytesToAdvance;
15480 ULONGLONG bytesToDo;
15481 PULONGLONG dataSetRangeByteOffset;
15482 PULONG dataSetRangeIndex;
15483 PDEVICE_DATA_SET_RANGE dataSetRanges;
15484 PDEVICE_OBJECT fdo;
15486 PULONGLONG totalSectorsProcessedSuccessfully;
15487
15488 fdo = OffloadWriteContext->Fdo;
15489 fdoExt = fdo->DeviceExtension;
15490 dataSetRanges = OffloadWriteContext->DataSetRanges;
15491 dataSetRangeByteOffset = &OffloadWriteContext->DataSetRangeByteOffset;
15492 dataSetRangeIndex = &OffloadWriteContext->DataSetRangeIndex;
15493 totalSectorsProcessedSuccessfully = &OffloadWriteContext->TotalSectorsProcessedSuccessfully;
15494 bytesToAdvance = SectorsToAdvance * fdoExt->DiskGeometry.BytesPerSector;
15495
15496 (*totalSectorsProcessedSuccessfully) += SectorsToAdvance;
15497 NT_ASSERT((*totalSectorsProcessedSuccessfully) <= OffloadWriteContext->TotalRequestSizeSectors);
15498
15499 while (bytesToAdvance != 0) {
15500 bytesToDo = dataSetRanges[*dataSetRangeIndex].LengthInBytes - *dataSetRangeByteOffset;
15501 if (bytesToDo > bytesToAdvance) {
15502 bytesToDo = bytesToAdvance;
15503 }
15504 (*dataSetRangeByteOffset) += bytesToDo;
15505 bytesToAdvance -= bytesToDo;
15506 if ((*dataSetRangeByteOffset) == dataSetRanges[*dataSetRangeIndex].LengthInBytes) {
15507 (*dataSetRangeIndex) += 1;
15508 (*dataSetRangeByteOffset) = 0;
15509 }
15510 }
15511
15512 NT_ASSERT((*dataSetRangeIndex) <= OffloadWriteContext->DataSetRangesCount);
15513
15514 return;
15515}
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
ULONGLONG LengthInBytes
Definition: ntddstor.h:768
PVOID DeviceExtension
Definition: env_spec_w32.h:418

Referenced by ClasspReceiveWriteUsingTokenInformationTransferPacketDone(), and ClasspWriteUsingTokenTransferPacketDone().

◆ ClasspAllocatePowerProcessIrp()

NTSTATUS ClasspAllocatePowerProcessIrp ( PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 11683 of file class.c.

11686{
11687 UCHAR stackSize;
11688
11689 NT_ASSERT(FdoExtension->PrivateFdoData != NULL);
11690
11691 stackSize = FdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1;
11692
11693 FdoExtension->PrivateFdoData->PowerProcessIrp = ExAllocatePoolWithTag(NonPagedPoolNx,
11694 IoSizeOfIrp(stackSize),
11696 );
11697
11698 if (FdoExtension->PrivateFdoData->PowerProcessIrp == NULL) {
11699
11701 } else {
11702
11703 IoInitializeIrp(FdoExtension->PrivateFdoData->PowerProcessIrp,
11704 IoSizeOfIrp(stackSize),
11705 stackSize);
11706
11707 return STATUS_SUCCESS;
11708 }
11709}
#define CLASS_TAG_POWER
Definition: power.c:37
@ FdoExtension
Definition: precomp.h:48
VOID NTAPI IoInitializeIrp(IN PIRP Irp, IN USHORT PacketSize, IN CCHAR StackSize)
Definition: irp.c:1854
#define IoSizeOfIrp(_StackSize)

Referenced by ClassPnpStartDevice().

◆ ClasspAllocateReleaseQueueIrp()

NTSTATUS ClasspAllocateReleaseQueueIrp ( PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 11621 of file class.c.

11624{
11625 UCHAR lowerStackSize;
11626
11627 //
11628 // do an initial check w/o the spinlock
11629 //
11630
11631 if (FdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated) {
11632 return STATUS_SUCCESS;
11633 }
11634
11635
11636 lowerStackSize = FdoExtension->CommonExtension.LowerDeviceObject->StackSize;
11637
11638 //
11639 // don't allocate one if one is in progress! this means whoever called
11640 // this routine didn't check if one was in progress.
11641 //
11642
11643 NT_ASSERT(!(FdoExtension->ReleaseQueueInProgress));
11644
11645 FdoExtension->PrivateFdoData->ReleaseQueueIrp =
11646 ExAllocatePoolWithTag(NonPagedPoolNx,
11647 IoSizeOfIrp(lowerStackSize),
11649 );
11650
11651 if (FdoExtension->PrivateFdoData->ReleaseQueueIrp == NULL) {
11652 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate for "
11653 "release queue irp\n"));
11655 }
11656 IoInitializeIrp(FdoExtension->PrivateFdoData->ReleaseQueueIrp,
11657 IoSizeOfIrp(lowerStackSize),
11658 lowerStackSize);
11659 FdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated = TRUE;
11660
11661 return STATUS_SUCCESS;
11662}
#define CLASS_TAG_RELEASE_QUEUE
Definition: classpnp.h:81

Referenced by ClassPnpStartDevice(), and ClasspReleaseQueue().

◆ ClasspAllocateReleaseRequest()

NTSTATUS ClasspAllocateReleaseRequest ( IN PDEVICE_OBJECT  Fdo)

Definition at line 11489 of file class.c.

11492{
11493 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
11494
11495 PAGED_CODE();
11496
11498
11499 fdoExtension->ReleaseQueueNeeded = FALSE;
11500 fdoExtension->ReleaseQueueInProgress = FALSE;
11501 fdoExtension->ReleaseQueueIrpFromPool = FALSE;
11502
11503 //
11504 // The class driver is responsible for allocating a properly sized irp,
11505 // or ClassReleaseQueue will attempt to do it on the first error.
11506 //
11507
11508 fdoExtension->ReleaseQueueIrp = NULL;
11509
11510 //
11511 // Write length to SRB.
11512 //
11513
11514 fdoExtension->ReleaseQueueSrb.Length = sizeof(SCSI_REQUEST_BLOCK);
11515
11516 return STATUS_SUCCESS;
11517} // end ClasspAllocateReleaseRequest()
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
KSPIN_LOCK ReleaseQueueSpinLock
Definition: classpnp.h:911
SCSI_REQUEST_BLOCK ReleaseQueueSrb
Definition: classpnp.h:913

◆ ClasspBlockLimitsDataSnapshot()

NTSTATUS ClasspBlockLimitsDataSnapshot ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
_In_ BOOLEAN  ForceQuery,
_Out_ PCLASS_VPD_B0_DATA  BlockLimitsData,
_Out_ PULONG  GenerationCount 
)

Definition at line 16504 of file class.c.

16539{
16541 KLOCK_QUEUE_HANDLE lockHandle;
16542
16544
16545 KeAcquireInStackQueuedSpinLock(&FdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
16546 *BlockLimitsData = FdoExtension->FunctionSupportInfo->BlockLimitsData;
16547 *GenerationCount = FdoExtension->FunctionSupportInfo->GenerationCount;
16548 KeReleaseInStackQueuedSpinLock(&lockHandle);
16549
16550 return status;
16551}
NTSTATUS ClasspRefreshFunctionSupportInfo(_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ BOOLEAN ForceQuery)
Definition: class.c:16395
VOID FASTCALL KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:130
VOID FASTCALL KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:166

Referenced by ClasspDeviceGetLBAStatus(), ClasspDeviceLBProvisioningProperty(), and ClasspDeviceTrimProcess().

◆ ClasspCleanupOffloadReadContext()

VOID ClasspCleanupOffloadReadContext ( _In_ __drv_freesMem(mem) POFFLOAD_READ_CONTEXT  OffloadReadContext)

Definition at line 14335 of file class.c.

14356{
14357 PMDL populateTokenMdl;
14358
14359 populateTokenMdl = OffloadReadContext->PopulateTokenMdl;
14360
14361 NT_ASSERT(OffloadReadContext != NULL);
14362
14363 if (populateTokenMdl) {
14364 ClasspFreeDeviceMdl(populateTokenMdl);
14365 }
14366 FREE_POOL(OffloadReadContext);
14367
14368 return;
14369}
VOID ClasspFreeDeviceMdl(PMDL Mdl)
Definition: utils.c:615

Referenced by ClasspCompleteOffloadRead().

◆ ClasspCleanupOffloadWriteContext()

VOID ClasspCleanupOffloadWriteContext ( _In_ __drv_freesMem(mem) POFFLOAD_WRITE_CONTEXT  OffloadWriteContext)

Definition at line 15902 of file class.c.

15923{
15924 PMDL writeUsingTokenMdl = OffloadWriteContext->WriteUsingTokenMdl;
15925
15926 if (writeUsingTokenMdl) {
15927 ClasspFreeDeviceMdl(writeUsingTokenMdl);
15928 }
15929 FREE_POOL(OffloadWriteContext);
15930
15931 return;
15932}

Referenced by ClasspCompleteOffloadWrite().

◆ ClasspCompleteOffloadRead()

VOID ClasspCompleteOffloadRead ( _In_ POFFLOAD_READ_CONTEXT  OffloadReadContext,
_In_ NTSTATUS  CompletionStatus 
)

Definition at line 14255 of file class.c.

14280{
14282 ULONGLONG entireXferLen;
14283 PDEVICE_OBJECT fdo;
14285 PIRP irp;
14287 PUCHAR token;
14288 ULONGLONG totalSectorsProcessed;
14289
14290 status = CompletionStatus;
14291 dsmAttributes = OffloadReadContext->OffloadReadDsmIrp->AssociatedIrp.SystemBuffer;
14292 totalSectorsProcessed = OffloadReadContext->TotalSectorsProcessed;
14293 fdoExt = OffloadReadContext->Fdo->DeviceExtension;
14294 entireXferLen = OffloadReadContext->EntireXferLen;
14295 token = OffloadReadContext->Token;
14296 irp = OffloadReadContext->OffloadReadDsmIrp;
14297 fdo = OffloadReadContext->Fdo;
14298
14299 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->OffloadReadFlags = 0;
14300 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->Reserved = 0;
14301
14302 if (NT_SUCCESS(status)) {
14303 ULONGLONG totalBytesProcessed = totalSectorsProcessed * fdoExt->DiskGeometry.BytesPerSector;
14304
14305 TracePrint((totalBytesProcessed == entireXferLen ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_WARNING,
14306 TRACE_FLAG_IOCTL,
14307 "ClasspCompleteOffloadRead (%p): Successfully populated token with %I64u (out of %I64u) bytes (list Id %x).\n",
14308 fdo,
14309 totalBytesProcessed,
14310 entireXferLen,
14311 OffloadReadContext->ListIdentifier));
14312
14313 if (totalBytesProcessed < entireXferLen) {
14315 }
14316 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->LengthProtected = totalBytesProcessed;
14317 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->TokenLength = STORAGE_OFFLOAD_MAX_TOKEN_LENGTH;
14319 } else {
14320 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->LengthProtected = 0;
14321 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->TokenLength = 0;
14322 }
14323
14324 irp->IoStatus.Information = sizeof(STORAGE_OFFLOAD_READ_OUTPUT);
14325
14327 ClasspCleanupOffloadReadContext(OffloadReadContext);
14328 OffloadReadContext = NULL;
14329
14330 return;
14331}
VOID ClasspCleanupOffloadReadContext(_In_ __drv_freesMem(mem) POFFLOAD_READ_CONTEXT OffloadReadContext)
Definition: class.c:14335
FxIrp * irp
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
#define STORAGE_OFFLOAD_MAX_TOKEN_LENGTH
Definition: ntddstor.h:986
struct _STORAGE_OFFLOAD_READ_OUTPUT * PSTORAGE_OFFLOAD_READ_OUTPUT
#define STORAGE_OFFLOAD_READ_RANGE_TRUNCATED
Definition: ntddstor.h:1026
struct _STORAGE_OFFLOAD_READ_OUTPUT STORAGE_OFFLOAD_READ_OUTPUT

Referenced by ClasspPopulateTokenTransferPacketDone(), ClasspReceivePopulateTokenInformation(), and ClasspReceivePopulateTokenInformationTransferPacketDone().

◆ ClasspCompleteOffloadRequest()

VOID ClasspCompleteOffloadRequest ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_In_ NTSTATUS  CompletionStatus 
)

Definition at line 13632 of file class.c.

13636{
13637 NTSTATUS status = CompletionStatus;
13638
13639
13640 Irp->IoStatus.Status = status;
13641
13644
13645 return;
13646}

Referenced by _IRQL_requires_max_(), ClasspCompleteOffloadRead(), and ClasspCompleteOffloadWrite().

◆ ClasspCompleteOffloadWrite()

VOID ClasspCompleteOffloadWrite ( _In_ __drv_freesMem(Mem) POFFLOAD_WRITE_CONTEXT  OffloadWriteContext,
_In_ NTSTATUS  CompletionCausingStatus 
)

Definition at line 15788 of file class.c.

15824{
15825 PDEVICE_OBJECT fdo;
15828 PULONGLONG totalSectorsProcessedSuccessfully;
15829 ULONGLONG entireXferLen;
15830 PIRP irp;
15831 PBOOLEAN tokenInvalidated;
15832 ULONG listIdentifier;
15833 ULONGLONG totalSectorsProcessed;
15835 ULONGLONG totalBytesProcessed;
15836
15837 fdo = OffloadWriteContext->Fdo;
15838 fdoExt = fdo->DeviceExtension;
15839 dsmAttributes = OffloadWriteContext->DsmAttributes;
15840 totalSectorsProcessedSuccessfully = &OffloadWriteContext->TotalSectorsProcessedSuccessfully;
15841 entireXferLen = OffloadWriteContext->EntireXferLen;
15842 irp = OffloadWriteContext->OffloadWriteDsmIrp;
15843 tokenInvalidated = &OffloadWriteContext->TokenInvalidated;
15844 listIdentifier = OffloadWriteContext->ListIdentifier;
15845 totalSectorsProcessed = OffloadWriteContext->TotalSectorsProcessed;
15846 status = CompletionCausingStatus;
15847
15848 ((PSTORAGE_OFFLOAD_WRITE_OUTPUT)dsmAttributes)->OffloadWriteFlags = 0;
15849 ((PSTORAGE_OFFLOAD_WRITE_OUTPUT)dsmAttributes)->Reserved = 0;
15850
15851 totalBytesProcessed = (*totalSectorsProcessedSuccessfully) * fdoExt->DiskGeometry.BytesPerSector;
15852
15853 TracePrint((totalBytesProcessed == entireXferLen ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_WARNING,
15854 TRACE_FLAG_IOCTL,
15855 "ClasspCompleteOffloadWrite (%p): %ws wrote using token %I64u (out of %I64u) bytes (Irp %p).\n",
15856 fdo,
15857 NT_SUCCESS(status) ? L"Successful" : L"Failed",
15858 totalBytesProcessed,
15859 entireXferLen,
15860 irp));
15861
15862 if (totalBytesProcessed > 0 && totalBytesProcessed < entireXferLen) {
15864 }
15865 if (*tokenInvalidated) {
15866 SET_FLAG(((PSTORAGE_OFFLOAD_WRITE_OUTPUT)dsmAttributes)->OffloadWriteFlags, STORAGE_OFFLOAD_TOKEN_INVALID);
15867 }
15868 ((PSTORAGE_OFFLOAD_WRITE_OUTPUT)dsmAttributes)->LengthCopied = totalBytesProcessed;
15869
15870
15871 if (!NT_SUCCESS(status)) {
15872
15873 TracePrint((TRACE_LEVEL_WARNING,
15874 TRACE_FLAG_IOCTL,
15875 "ClasspCompleteOffloadWrite (%p): TokenOperation for WriteUsingToken (list Id %u) completed with %x writing %I64u blocks (currentTotal %I64u blocks).\n",
15876 fdo,
15877 listIdentifier,
15878 status,
15879 totalSectorsProcessed,
15880 *totalSectorsProcessedSuccessfully));
15881
15882 //
15883 // Even if target returned an error, from the OS upper layers' perspective,
15884 // it is a success (with truncation) if any data at all was written.
15885 //
15886 if (*totalSectorsProcessedSuccessfully) {
15888 }
15889 }
15890
15891 irp->IoStatus.Information = sizeof(STORAGE_OFFLOAD_WRITE_OUTPUT);
15892
15894 ClasspCleanupOffloadWriteContext(OffloadWriteContext);
15895 OffloadWriteContext = NULL;
15896
15897 return;
15898}
VOID ClasspCleanupOffloadWriteContext(_In_ __drv_freesMem(mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
Definition: class.c:15902
#define STORAGE_OFFLOAD_WRITE_RANGE_TRUNCATED
Definition: ntddstor.h:1051
#define STORAGE_OFFLOAD_TOKEN_INVALID
Definition: ntddstor.h:1052
struct _STORAGE_OFFLOAD_WRITE_OUTPUT * PSTORAGE_OFFLOAD_WRITE_OUTPUT
struct _STORAGE_OFFLOAD_WRITE_OUTPUT STORAGE_OFFLOAD_WRITE_OUTPUT
unsigned char * PBOOLEAN
Definition: typedefs.h:53

Referenced by ClasspContinueOffloadWrite(), ClasspReceiveWriteUsingTokenInformation(), ClasspReceiveWriteUsingTokenInformationDone(), ClasspReceiveWriteUsingTokenInformationTransferPacketDone(), and ClasspWriteUsingTokenTransferPacketDone().

◆ ClasspContinueOffloadWrite()

VOID ClasspContinueOffloadWrite ( _In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT  OffloadWriteContext)

Definition at line 15187 of file class.c.

15213{
15214 BOOLEAN allDataSetRangeFullyConverted;
15215 ULONG blockDescrIndex;
15216 PBLOCK_DEVICE_RANGE_DESCRIPTOR blockDescrPointer;
15217 PVOID buffer;
15219 ULONGLONG dataSetRangeByteOffset;
15220 ULONG dataSetRangeIndex;
15221 PDEVICE_DATA_SET_RANGE dataSetRanges;
15222 ULONG dataSetRangesCount;
15223 ULONGLONG entireXferLen;
15224 PDEVICE_OBJECT fdo;
15226 PIRP irp;
15227 ULONG lbaCount;
15228 ULONG listIdentifier;
15229 ULONGLONG logicalBlockOffset;
15230 ULONG maxBlockDescrCount;
15231 ULONGLONG maxLbaCount;
15232 PDEVICE_DSM_OFFLOAD_WRITE_PARAMETERS offloadWriteParameters;
15233 PTRANSFER_PACKET pkt;
15234 PIRP pseudoIrp;
15236 DEVICE_DATA_SET_RANGE tempDataSetRange;
15237 BOOLEAN tempDataSetRangeFullyConverted;
15238 PVOID tokenAscii;
15239 ULONG tokenSize;
15240 ULONGLONG totalSectorCount;
15241 ULONGLONG totalSectorsProcessedSuccessfully;
15242 ULONGLONG totalSectorsToProcess;
15243 ULONG transferSize;
15244 USHORT writeUsingTokenDataLength;
15245 USHORT writeUsingTokenDescriptorsLength;
15246 PMDL writeUsingTokenMdl;
15247
15248 tokenAscii = NULL;
15249 tokenSize = BLOCK_DEVICE_TOKEN_SIZE;
15250 tempDataSetRangeFullyConverted = FALSE;
15251 allDataSetRangeFullyConverted = FALSE;
15252 fdo = OffloadWriteContext->Fdo;
15253 fdoExt = fdo->DeviceExtension;
15254 irp = OffloadWriteContext->OffloadWriteDsmIrp;
15255 buffer = OffloadWriteContext + 1;
15256 bufferLength = OffloadWriteContext->BufferLength;
15257 dataSetRanges = OffloadWriteContext->DataSetRanges;
15258 offloadWriteParameters = OffloadWriteContext->OffloadWriteParameters;
15259 pseudoIrp = &OffloadWriteContext->PseudoIrp;
15260 writeUsingTokenMdl = OffloadWriteContext->WriteUsingTokenMdl;
15261 entireXferLen = OffloadWriteContext->EntireXferLen;
15262
15264
15265 pkt = DequeueFreeTransferPacket(fdo, TRUE);
15266 if (!pkt){
15267
15268 TracePrint((TRACE_LEVEL_ERROR,
15269 TRACE_FLAG_IOCTL,
15270 "ClasspContinueOffloadWrite (%p): Failed to retrieve transfer packet for TokenOperation (WriteUsingToken) operation.\n",
15271 fdo));
15272
15274 goto __ClasspContinueOffloadWrite_ErrorExit;
15275 }
15276
15277 OffloadWriteContext->Pkt = pkt;
15278
15279 blockDescrPointer = (PBLOCK_DEVICE_RANGE_DESCRIPTOR)
15280 &((PWRITE_USING_TOKEN_HEADER)buffer)->BlockDeviceRangeDescriptor[0];
15281
15282 blockDescrIndex = 0;
15283 lbaCount = 0;
15284
15285 totalSectorsToProcess = 0;
15286
15287 maxBlockDescrCount = OffloadWriteContext->MaxBlockDescrCount;
15288 maxLbaCount = OffloadWriteContext->MaxLbaCount;
15289
15290 //
15291 // The OffloadWriteContext->DataSetRangeIndex, DataSetRangeByteOffset, and
15292 // TotalSectorsProcessedSuccessfully don't move forward until RRTI has
15293 // reported the actual amount written.
15294 //
15295 // For that reason, this function only updates
15296 // OffloadWriteContext->TotalSectorsProcessed, which tracks the number of
15297 // sectors requested to be written by the current WRITE USING TOKEN command
15298 // (not all will necessarily be written).
15299 //
15300
15301 dataSetRangeIndex = OffloadWriteContext->DataSetRangeIndex;
15302 dataSetRangesCount = OffloadWriteContext->DataSetRangesCount;
15303 dataSetRangeByteOffset = OffloadWriteContext->DataSetRangeByteOffset;
15304 totalSectorsProcessedSuccessfully = OffloadWriteContext->TotalSectorsProcessedSuccessfully;
15305
15306 //
15307 // Send WriteUsingToken commands when the buffer is full or all input entries are converted.
15308 //
15309 while (!((blockDescrIndex == maxBlockDescrCount) || // buffer full or block descriptor count reached
15310 (lbaCount == maxLbaCount) || // block LBA count reached
15311 (allDataSetRangeFullyConverted))) { // all DataSetRanges have been converted
15312
15313 NT_ASSERT(dataSetRangeIndex < dataSetRangesCount);
15314 NT_ASSERT(dataSetRangeByteOffset < dataSetRanges[dataSetRangeIndex].LengthInBytes);
15315
15316 tempDataSetRange.StartingOffset = dataSetRanges[dataSetRangeIndex].StartingOffset + dataSetRangeByteOffset;
15317 tempDataSetRange.LengthInBytes = dataSetRanges[dataSetRangeIndex].LengthInBytes - dataSetRangeByteOffset;
15318
15319 totalSectorCount = 0;
15320
15321 ClasspConvertDataSetRangeToBlockDescr(fdo,
15322 blockDescrPointer,
15323 &blockDescrIndex,
15324 maxBlockDescrCount,
15325 &lbaCount,
15326 maxLbaCount,
15327 &tempDataSetRange,
15328 &totalSectorCount);
15329
15330 tempDataSetRangeFullyConverted = (tempDataSetRange.LengthInBytes == 0) ? TRUE : FALSE;
15331
15332 allDataSetRangeFullyConverted = tempDataSetRangeFullyConverted && ((dataSetRangeIndex + 1) == dataSetRangesCount);
15333
15334 if (tempDataSetRangeFullyConverted) {
15335 dataSetRangeIndex += 1;
15336 dataSetRangeByteOffset = 0;
15337 NT_ASSERT(dataSetRangeIndex <= dataSetRangesCount);
15338 } else {
15339 dataSetRangeByteOffset += totalSectorCount * fdoExt->DiskGeometry.BytesPerSector;
15340 NT_ASSERT(dataSetRangeByteOffset < dataSetRanges[dataSetRangeIndex].LengthInBytes);
15341 }
15342
15343 totalSectorsToProcess += totalSectorCount;
15344 }
15345
15346 //
15347 // Save the number of sectors being attempted in this WRITE USING TOKEN
15348 // command, so that a success return from the command will know how much
15349 // was written, without needing to issue a RECEIVE ROD TOKEN INFORMATION
15350 // command.
15351 //
15352 OffloadWriteContext->TotalSectorsToProcess = totalSectorsToProcess;
15353 OffloadWriteContext->TotalSectorsProcessed = 0;
15354
15355 //
15356 // Calculate transfer size, including the header
15357 //
15358 transferSize = (blockDescrIndex * sizeof(BLOCK_DEVICE_RANGE_DESCRIPTOR)) + FIELD_OFFSET(WRITE_USING_TOKEN_HEADER, BlockDeviceRangeDescriptor);
15359
15361
15362 writeUsingTokenDataLength = (USHORT)transferSize - RTL_SIZEOF_THROUGH_FIELD(WRITE_USING_TOKEN_HEADER, WriteUsingTokenDataLength);
15363 REVERSE_BYTES_SHORT(((PWRITE_USING_TOKEN_HEADER)buffer)->WriteUsingTokenDataLength, &writeUsingTokenDataLength);
15364
15365 ((PWRITE_USING_TOKEN_HEADER)buffer)->Immediate = 0;
15366
15367 logicalBlockOffset = OffloadWriteContext->LogicalBlockOffset + totalSectorsProcessedSuccessfully;
15368 REVERSE_BYTES_QUAD(((PWRITE_USING_TOKEN_HEADER)buffer)->BlockOffsetIntoToken, &logicalBlockOffset);
15369
15371 &offloadWriteParameters->Token,
15373
15374 writeUsingTokenDescriptorsLength = (USHORT)transferSize - FIELD_OFFSET(WRITE_USING_TOKEN_HEADER, BlockDeviceRangeDescriptor);
15375 REVERSE_BYTES_SHORT(((PWRITE_USING_TOKEN_HEADER)buffer)->BlockDeviceRangeDescriptorListLength, &writeUsingTokenDescriptorsLength);
15376
15377 RtlZeroMemory(pseudoIrp, sizeof(IRP));
15378
15379 pseudoIrp->IoStatus.Status = STATUS_SUCCESS;
15380 pseudoIrp->IoStatus.Information = 0;
15381 pseudoIrp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
15382 pseudoIrp->MdlAddress = writeUsingTokenMdl;
15383
15385 listIdentifier = InterlockedIncrement((volatile LONG *)&TokenOperationListIdentifier);
15386
15387 ClasspSetupWriteUsingTokenTransferPacket(
15388 OffloadWriteContext,
15389 pkt,
15390 transferSize,
15391 (PUCHAR)buffer,
15392 pseudoIrp,
15393 listIdentifier);
15394
15396 tokenSize,
15397 &tokenSize);
15398
15399 TracePrint((TRACE_LEVEL_INFORMATION,
15400 TRACE_FLAG_IOCTL,
15401 "ClasspContinueOffloadWrite (%p): Offloading write for %I64u bytes (versus %I64u) [via %u descriptors]. \
15402 \n\t\t\tDataLength: %u, DescriptorsLength: %u. Pkt %p (list id %x) [Token: %s]\n",
15403 fdo,
15404 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector,
15405 entireXferLen,
15406 blockDescrIndex,
15407 writeUsingTokenDataLength,
15408 writeUsingTokenDescriptorsLength,
15409 pkt,
15410 listIdentifier,
15411 (tokenAscii == NULL) ? "" : tokenAscii));
15412
15413 FREE_POOL(tokenAscii);
15414
15415 OffloadWriteContext->ListIdentifier = listIdentifier;
15416
15418
15419 //
15420 // ClasspWriteUsingTokenTransferPacketDone() takes care of completing the
15421 // IRP, so this function is done.
15422 //
15423
15424 return;
15425
15426 //
15427 // Error cleaup label only - not used in success case:
15428 //
15429
15430__ClasspContinueOffloadWrite_ErrorExit:
15431
15433
15434 //
15435 // ClasspCompleteOffloadWrite also cleans up offloadWriteContext.
15436 //
15437
15438 ClasspCompleteOffloadWrite(OffloadWriteContext, status);
15439
15440 return;
15441}
#define LongToPtr(l)
Definition: basetsd.h:91
#define MAX_TOKEN_OPERATION_PARAMETER_DATA_LENGTH
Definition: classp.h:207
_IRQL_requires_same_ PUCHAR ClasspBinaryToAscii(_In_reads_(Length) PUCHAR HexBuffer, _In_ ULONG Length, _Inout_ PULONG UpdateLength)
Definition: utils.c:7717
PTRANSFER_PACKET DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
Definition: xferpkt.c:656
NTSTATUS SubmitTransferPacket(PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:850
VOID ClasspCompleteOffloadWrite(_In_ __drv_freesMem(Mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ NTSTATUS CompletionCausingStatus)
Definition: class.c:15788
volatile ULONG TokenOperationListIdentifier
Definition: class.c:108
GLuint buffer
Definition: glext.h:5915
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define BLOCK_DEVICE_TOKEN_SIZE
Definition: scsi.h:3584
struct BLOCK_DEVICE_RANGE_DESCRIPTOR * PBLOCK_DEVICE_RANGE_DESCRIPTOR
struct WRITE_USING_TOKEN_HEADER * PWRITE_USING_TOKEN_HEADER
LONGLONG StartingOffset
Definition: ntddstor.h:767
STORAGE_OFFLOAD_TOKEN Token
Definition: ntddstor.h:1048
_In_opt_ PVOID _In_ ULONG bufferLength
Definition: wdfdriver.h:109

Referenced by ClasspReceiveWriteUsingTokenInformationDone().

◆ ClasspFreeReleaseRequest()

VOID ClasspFreeReleaseRequest ( IN PDEVICE_OBJECT  Fdo)

Definition at line 11525 of file class.c.

11528{
11529 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
11530
11531 PAGED_CODE();
11532
11533 //KIRQL oldIrql;
11534
11535 NT_ASSERT(fdoExtension->CommonExtension.IsRemoved != NO_REMOVE);
11536
11537 //
11538 // free anything the driver allocated
11539 //
11540
11541 if (fdoExtension->ReleaseQueueIrp) {
11542 if (fdoExtension->ReleaseQueueIrpFromPool) {
11543 FREE_POOL(fdoExtension->ReleaseQueueIrp);
11544 } else {
11545 IoFreeIrp(fdoExtension->ReleaseQueueIrp);
11546 }
11547 fdoExtension->ReleaseQueueIrp = NULL;
11548 }
11549
11550 //
11551 // free anything that we allocated
11552 //
11553
11554 if ((fdoExtension->PrivateFdoData) &&
11555 (fdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated)) {
11556
11557 FREE_POOL(fdoExtension->PrivateFdoData->ReleaseQueueIrp);
11558 fdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated = FALSE;
11559 }
11560
11561 return;
11562} // end ClasspFreeReleaseRequest()
#define NO_REMOVE
Definition: classpnp.h:96

◆ ClasspGetBlockDeviceTokenLimitsInfo()

_IRQL_requires_same_ NTSTATUS ClasspGetBlockDeviceTokenLimitsInfo ( _Inout_ PDEVICE_OBJECT  DeviceObject)

Definition at line 13220 of file class.c.

13243{
13244 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
13247 ULONG srbSize = 0;
13248 USHORT pageLength = 0;
13252 ULONG allocationBufferLength = bufferLength;
13253 PCDB cdb;
13254 ULONG dataTransferLength = 0;
13255 PVPD_THIRD_PARTY_COPY_PAGE operatingParameters = NULL;
13256 PWINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR blockDeviceTokenLimits = NULL;
13257
13258 TracePrint((TRACE_LEVEL_VERBOSE,
13259 TRACE_FLAG_PNP,
13260 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Entering function.\n",
13261 DeviceObject));
13262
13263 //
13264 // Allocate an SRB for querying the device for LBP-related info.
13265 //
13266 if ((fdoExtension->AdapterDescriptor != NULL) &&
13267 (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
13269 } else {
13270 srbSize = sizeof(SCSI_REQUEST_BLOCK);
13271 }
13272
13273 srb = ExAllocatePoolWithTag(NonPagedPoolNx, srbSize, CLASSPNP_POOL_TAG_SRB);
13274
13275 if (!srb) {
13276
13277 TracePrint((TRACE_LEVEL_ERROR,
13278 TRACE_FLAG_PNP,
13279 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Couldn't allocate SRB.\n",
13280 DeviceObject));
13281
13283 goto __ClasspGetBlockDeviceTokenLimitsInfo_Exit;
13284 }
13285
13286#if defined(_ARM_) || defined(_ARM64_)
13287 //
13288 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
13289 // based platforms. We are taking the conservative approach here.
13290 //
13291 allocationBufferLength = ALIGN_UP_BY(allocationBufferLength, KeGetRecommendedSharedDataAlignment());
13292 dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, allocationBufferLength, CLASSPNP_POOL_TAG_VPD);
13293#else
13295#endif
13296
13297 if (!dataBuffer) {
13298
13299 TracePrint((TRACE_LEVEL_ERROR,
13300 TRACE_FLAG_PNP,
13301 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Couldn't allocate dataBuffer.\n",
13302 DeviceObject));
13303
13305 goto __ClasspGetBlockDeviceTokenLimitsInfo_Exit;
13306 }
13307
13308 operatingParameters = (PVPD_THIRD_PARTY_COPY_PAGE)dataBuffer;
13309
13310 RtlZeroMemory(dataBuffer, allocationBufferLength);
13311
13312 if ((fdoExtension->AdapterDescriptor != NULL) &&
13313 (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
13317 1,
13319 if (NT_SUCCESS(status)) {
13320
13322
13323 } else {
13324
13325 //
13326 // Should not occur. Revert to legacy SRB.
13327 //
13329
13330 TracePrint((TRACE_LEVEL_WARNING,
13331 TRACE_FLAG_PNP,
13332 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Falling back to using SRB (instead of SRB_EX).\n",
13333 DeviceObject));
13334
13335 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
13336 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
13338 }
13339 } else {
13340
13341 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
13342 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
13344 }
13345
13346 SrbSetTimeOutValue(srb, fdoExtension->TimeOutValue);
13349 SrbAssignSrbFlags(srb, fdoExtension->SrbFlags);
13350
13351 SrbSetCdbLength(srb, 6);
13352
13353 cdb = SrbGetCdb(srb);
13354 cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY;
13355 cdb->CDB6INQUIRY3.EnableVitalProductData = 1;
13356 cdb->CDB6INQUIRY3.PageCode = VPD_THIRD_PARTY_COPY;
13357 cdb->CDB6INQUIRY3.AllocationLength = bufferLength;
13358
13360 srb,
13361 dataBuffer,
13362 allocationBufferLength,
13363 FALSE);
13364
13365 //
13366 // Handle the case where we get back STATUS_DATA_OVERRUN because the input
13367 // buffer was larger than necessary.
13368 //
13369 dataTransferLength = SrbGetDataTransferLength(srb);
13370
13371 if (status == STATUS_DATA_OVERRUN && dataTransferLength < bufferLength) {
13372
13374 }
13375
13376 if (NT_SUCCESS(status)) {
13377
13378 REVERSE_BYTES_SHORT(&pageLength, &operatingParameters->PageLength);
13379
13380 } else {
13381 TracePrint((TRACE_LEVEL_ERROR,
13382 TRACE_FLAG_PNP,
13383 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Inquiry for TPC VPD failed with %x.\n",
13385 status));
13386 }
13387
13388 if ((NT_SUCCESS(status)) &&
13389 (pageLength >= sizeof(WINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR))) {
13390
13391 USHORT descriptorType;
13392
13393 blockDeviceTokenLimits = (PWINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR)operatingParameters->ThirdPartyCopyDescriptors;
13394 REVERSE_BYTES_SHORT(&descriptorType, &blockDeviceTokenLimits->DescriptorType);
13395 REVERSE_BYTES_SHORT(&descriptorLength, &blockDeviceTokenLimits->DescriptorLength);
13396
13397 if ((descriptorType == BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR_TYPE_WINDOWS) &&
13399
13400 fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits = TRUE;
13401
13402 REVERSE_BYTES_SHORT(&fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumRangeDescriptors, &blockDeviceTokenLimits->MaximumRangeDescriptors);
13403 REVERSE_BYTES(&fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer, &blockDeviceTokenLimits->MaximumInactivityTimer);
13404 REVERSE_BYTES(&fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.DefaultInactivityTimer, &blockDeviceTokenLimits->DefaultInactivityTimer);
13405 REVERSE_BYTES_QUAD(&fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumTokenTransferSize, &blockDeviceTokenLimits->MaximumTokenTransferSize);
13406 REVERSE_BYTES_QUAD(&fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount, &blockDeviceTokenLimits->OptimalTransferCount);
13407
13408 TracePrint((TRACE_LEVEL_INFORMATION,
13409 TRACE_FLAG_PNP,
13410 "ClasspGetBlockDeviceTokenLimitsInfo (%p): %s %s (rev %s) reported following parameters: \
13411 \n\t\t\tMaxRangeDescriptors: %u\n\t\t\tMaxIAT: %u\n\t\t\tDefaultIAT: %u \
13412 \n\t\t\tMaxTokenTransferSize: %I64u\n\t\t\tOptimalTransferCount: %I64u\n\t\t\tOptimalTransferLengthGranularity: %u \
13413 \n\t\t\tOptimalTransferLength: %u\n\t\t\tMaxTransferLength: %u\n",
13415 (PCSZ)(((PUCHAR)fdoExtension->DeviceDescriptor) + fdoExtension->DeviceDescriptor->VendorIdOffset),
13416 (PCSZ)(((PUCHAR)fdoExtension->DeviceDescriptor) + fdoExtension->DeviceDescriptor->ProductIdOffset),
13417 (PCSZ)(((PUCHAR)fdoExtension->DeviceDescriptor) + fdoExtension->DeviceDescriptor->ProductRevisionOffset),
13418 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumRangeDescriptors,
13419 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer,
13420 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.DefaultInactivityTimer,
13421 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumTokenTransferSize,
13422 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount,
13423 fdoExtension->FunctionSupportInfo->BlockLimitsData.OptimalTransferLengthGranularity,
13424 fdoExtension->FunctionSupportInfo->BlockLimitsData.OptimalTransferLength,
13425 fdoExtension->FunctionSupportInfo->BlockLimitsData.MaximumTransferLength));
13426 } else {
13427
13428 TracePrint((TRACE_LEVEL_WARNING,
13429 TRACE_FLAG_PNP,
13430 "ClasspGetBlockDeviceTokenLimitsInfo (%p): ThirdPartyCopy VPD data doesn't have Windows OffloadDataTransfer descriptor.\n",
13431 DeviceObject));
13432
13433 fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits = FALSE;
13435 }
13436 } else {
13437
13438 TracePrint((TRACE_LEVEL_WARNING,
13439 TRACE_FLAG_PNP,
13440 "ClasspGetBlockDeviceTokenLimitsInfo (%p): TPC VPD data didn't return TPC descriptors of interest.\n",
13441 DeviceObject));
13442
13443 fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits = FALSE;
13445 }
13446
13447__ClasspGetBlockDeviceTokenLimitsInfo_Exit:
13448
13450 FREE_POOL(srb);
13451 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus = status;
13452
13453 TracePrint((TRACE_LEVEL_VERBOSE,
13454 TRACE_FLAG_PNP,
13455 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Exiting function with status %x.\n",
13457 status));
13458
13459 return status;
13460}
#define ALIGN_UP_BY(size, align)
#define CLASSPNP_POOL_TAG_VPD
Definition: classp.h:195
#define CLASSPNP_POOL_TAG_SRB
Definition: classp.h:194
#define VPD_PAGE_HEADER_SIZE
Definition: classp.h:221
NTSTATUS NTAPI ClassSendSrbSynchronous(_In_ PDEVICE_OBJECT Fdo, _Inout_ PSCSI_REQUEST_BLOCK _Srb, _In_reads_bytes_opt_(BufferLength) PVOID BufferAddress, _In_ ULONG BufferLength, _In_ BOOLEAN WriteToDevice)
Definition: class.c:4042
#define SP_UNTAGGED
Definition: srb.h:233
PVOID dataBuffer
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:710
#define STATUS_DEVICE_FEATURE_NOT_SUPPORTED
Definition: ntstatus.h:985
#define VPD_MAX_BUFFER_SIZE
Definition: scsi.h:2402
struct _VPD_THIRD_PARTY_COPY_PAGE * PVPD_THIRD_PARTY_COPY_PAGE
#define BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR_TYPE_WINDOWS
Definition: scsi.h:2523
struct _WINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR * PWINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR
#define VPD_THIRD_PARTY_COPY
Definition: scsi.h:2415
#define SrbSetRequestTag
Definition: srbhelper.h:869
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
UCHAR ThirdPartyCopyDescriptors[ANYSIZE_ARRAY]
Definition: scsi.h:2508
CONST char * PCSZ
Definition: umtypes.h:125
struct _CDB::_CDB6INQUIRY3 CDB6INQUIRY3

Referenced by _IRQL_requires_().

◆ ClasspGetInquiryVpdSupportInfo()

VOID ClasspGetInquiryVpdSupportInfo ( _Inout_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 12914 of file class.c.

12917{
12920 SCSI_REQUEST_BLOCK srb = {0};
12921 PCDB cdb;
12922 PVPD_SUPPORTED_PAGES_PAGE supportedPages = NULL;
12924 ULONG allocationBufferLength = bufferLength;
12925 UCHAR srbExBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE] = {0};
12927
12928#if defined(_ARM_) || defined(_ARM64_)
12929 //
12930 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
12931 // based platforms. We are taking the conservative approach here.
12932 //
12933 allocationBufferLength = ALIGN_UP_BY(allocationBufferLength,KeGetRecommendedSharedDataAlignment());
12934 supportedPages = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
12935 allocationBufferLength,
12936 '3CcS'
12937 );
12938
12939#else
12940 supportedPages = ExAllocatePoolWithTag(NonPagedPoolNx,
12942 '3CcS'
12943 );
12944#endif
12945
12946 if (supportedPages == NULL) {
12947 // memory allocation failure.
12948 return;
12949 }
12950
12951 RtlZeroMemory(supportedPages, allocationBufferLength);
12952
12953 // prepare the Srb
12954 if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
12955
12956#ifdef _MSC_VER
12957 #pragma prefast(suppress:26015, "InitializeStorageRequestBlock ensures buffer access is bounded")
12958#endif
12961 sizeof(srbExBuffer),
12962 1,
12964
12965 if (!NT_SUCCESS(status)) {
12966 //
12967 // Should not happen. Revert to legacy SRB.
12971 srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&srb;
12972 } else {
12973 ((PSTORAGE_REQUEST_BLOCK)srbExBuffer)->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
12974 srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)srbExBuffer;
12975 }
12976
12977 } else {
12980 srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&srb;
12981 }
12982
12983 SrbSetTimeOutValue(srbHeader, FdoExtension->TimeOutValue);
12984 SrbSetRequestTag(srbHeader, SP_UNTAGGED);
12986 SrbAssignSrbFlags(srbHeader, FdoExtension->SrbFlags);
12987 SrbSetCdbLength(srbHeader, 6);
12988
12989 cdb = SrbGetCdb(srbHeader);
12990 cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY;
12991 cdb->CDB6INQUIRY3.EnableVitalProductData = 1; //EVPD bit
12992 cdb->CDB6INQUIRY3.PageCode = VPD_SUPPORTED_PAGES;
12993 cdb->CDB6INQUIRY3.AllocationLength = bufferLength; //AllocationLength field in CDB6INQUIRY3 is only one byte.
12994
12995 status = ClassSendSrbSynchronous(commonExtension->DeviceObject,
12996 (PSCSI_REQUEST_BLOCK)srbHeader,
12997 supportedPages,
12998 allocationBufferLength,
12999 FALSE);
13000
13001 //
13002 // Handle the case where we get back STATUS_DATA_OVERRUN b/c the input
13003 // buffer was larger than necessary.
13004 //
13006 {
13008 }
13009
13010 if ( NT_SUCCESS(status) &&
13011 (supportedPages->PageLength > 0) &&
13012 (supportedPages->SupportedPageList[0] > 0) ) {
13013 // ataport treats all INQUIRY command as standard INQUIRY command, thus fills invalid info
13014 // If VPD INQUIRY is supported, the first page reported (additional length field for standard INQUIRY data) should be '00'
13016 }
13017
13018 if (NT_SUCCESS(status)) {
13019 int i;
13020
13021 for (i = 0; i < supportedPages->PageLength; i++) {
13022 if ( (i > 0) && (supportedPages->SupportedPageList[i] <= supportedPages->SupportedPageList[i - 1]) ) {
13023 // shall be in ascending order beginning with page code 00h.
13024 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits = FALSE;
13025 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockLimits = FALSE;
13026 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceCharacteristics = FALSE;
13027 FdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning = FALSE;
13028
13029
13030 break;
13031 }
13032 switch (supportedPages->SupportedPageList[i]) {
13034 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits = TRUE;
13035 break;
13036
13037 case VPD_BLOCK_LIMITS:
13038 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockLimits = TRUE;
13039 break;
13040
13042 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceCharacteristics = TRUE;
13043 break;
13044
13046 FdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning = TRUE;
13047 break;
13048
13049 }
13050 }
13051 }
13052
13053 ExFreePool(supportedPages);
13054
13055 return;
13056}
struct _COMMON_DEVICE_EXTENSION * PCOMMON_DEVICE_EXTENSION
#define SCSI_REQUEST_BLOCK_SIZE
Definition: srb.h:282
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define VPD_BLOCK_DEVICE_CHARACTERISTICS
Definition: scsi.h:2417
#define VPD_LOGICAL_BLOCK_PROVISIONING
Definition: scsi.h:2418
#define VPD_SUPPORTED_PAGES
Definition: scsi.h:2404
#define VPD_BLOCK_LIMITS
Definition: scsi.h:2416
UCHAR SupportedPageList[0]
Definition: scsi.h:2633

◆ ClasspGetLBProvisioningInfo()

NTSTATUS ClasspGetLBProvisioningInfo ( _Inout_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 13087 of file class.c.

13090{
13092 ULONG srbSize = 0;
13093
13094 //
13095 // Make sure we actually have data structures to work with.
13096 //
13097 if (FdoExtension == NULL ||
13098 FdoExtension->FunctionSupportInfo == NULL) {
13100 }
13101
13102 //
13103 // Allocate an SRB for querying the device for LBP-related info if either
13104 // the Logical Block Provisioning (0xB2) or Block Limits (0xB0) VPD page
13105 // exists.
13106 //
13107 if ((FdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning == TRUE) ||
13108 (FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockLimits == TRUE)) {
13109
13110 if ((FdoExtension->AdapterDescriptor != NULL) &&
13111 (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
13113 } else {
13114 srbSize = sizeof(SCSI_REQUEST_BLOCK);
13115 }
13116
13117 srb = ExAllocatePoolWithTag(NonPagedPoolNx, srbSize, '0DcS');
13118
13119 if (srb == NULL) {
13121 }
13122 }
13123
13124 //
13125 // Get the Logical Block Provisioning VPD page (0xB2). This function will
13126 // set some default values if the LBP VPD page is not supported.
13127 //
13129
13130
13131 //
13132 // Get the Block Limits VPD page (0xB0), which may override the default
13133 // UNMAP parameter values set above.
13134 //
13136 srb,
13137 srbSize,
13138 &FdoExtension->FunctionSupportInfo->BlockLimitsData);
13139
13140 FREE_POOL(srb);
13141
13142 return STATUS_SUCCESS;
13143}
NTSTATUS ClasspDeviceGetLBProvisioningVPDPage(_In_ PDEVICE_OBJECT DeviceObject, _Inout_opt_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:2350
NTSTATUS ClasspDeviceGetBlockLimitsVPDPage(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _Inout_bytecount_(SrbSize) PSCSI_REQUEST_BLOCK Srb, _In_ ULONG SrbSize, _Out_ PCLASS_VPD_B0_DATA BlockLimitsData)
Definition: utils.c:2521

◆ ClasspInitializeHotplugInfo()

NTSTATUS ClasspInitializeHotplugInfo ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 12507 of file class.c.

12510{
12511 PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
12512 DEVICE_REMOVAL_POLICY deviceRemovalPolicy = 0;
12514 ULONG resultLength = 0;
12515 ULONG writeCacheOverride;
12516
12517 PAGED_CODE();
12518
12519 //
12520 // start with some default settings
12521 //
12522 RtlZeroMemory(&(fdoData->HotplugInfo), sizeof(STORAGE_HOTPLUG_INFO));
12523
12524 //
12525 // set the size (aka version)
12526 //
12527
12528 fdoData->HotplugInfo.Size = sizeof(STORAGE_HOTPLUG_INFO);
12529
12530 //
12531 // set if the device has removable media
12532 //
12533
12534 if (FdoExtension->DeviceDescriptor->RemovableMedia) {
12535 fdoData->HotplugInfo.MediaRemovable = TRUE;
12536 } else {
12537 fdoData->HotplugInfo.MediaRemovable = FALSE;
12538 }
12539
12540 //
12541 // this refers to devices which, for reasons not yet understood,
12542 // do not fail PREVENT_MEDIA_REMOVAL requests even though they
12543 // have no way to lock the media into the drive. this allows
12544 // the filesystems to turn off delayed-write caching for these
12545 // devices as well.
12546 //
12547
12548 if (TEST_FLAG(FdoExtension->PrivateFdoData->HackFlags,
12550 fdoData->HotplugInfo.MediaHotplug = TRUE;
12551 } else {
12552 fdoData->HotplugInfo.MediaHotplug = FALSE;
12553 }
12554
12555 //
12556 // Query the default removal policy from the kernel
12557 //
12558
12561 sizeof(DEVICE_REMOVAL_POLICY),
12562 (PVOID)&deviceRemovalPolicy,
12563 &resultLength);
12564 if (!NT_SUCCESS(status)) {
12565 return status;
12566 }
12567
12568 if (resultLength != sizeof(DEVICE_REMOVAL_POLICY)) {
12569 return STATUS_UNSUCCESSFUL;
12570 }
12571
12572 //
12573 // Look into the registry to see if the user has chosen
12574 // to override the default setting for the removal policy.
12575 // User can override only if the default removal policy is
12576 // orderly or suprise removal.
12577
12578 if ((deviceRemovalPolicy == RemovalPolicyExpectOrderlyRemoval) ||
12579 (deviceRemovalPolicy == RemovalPolicyExpectSurpriseRemoval)) {
12580
12581 DEVICE_REMOVAL_POLICY userRemovalPolicy = 0;
12582
12583 ClassGetDeviceParameter(FdoExtension,
12586 (PULONG)&userRemovalPolicy);
12587
12588 //
12589 // Validate the override value and use it only if it is an
12590 // allowed value.
12591 //
12592 if ((userRemovalPolicy == RemovalPolicyExpectOrderlyRemoval) ||
12593 (userRemovalPolicy == RemovalPolicyExpectSurpriseRemoval)) {
12594 deviceRemovalPolicy = userRemovalPolicy;
12595 }
12596 }
12597
12598 //
12599 // use this info to set the DeviceHotplug setting
12600 // don't rely on DeviceCapabilities, since it can't properly
12601 // determine device relations, etc. let the kernel figure this
12602 // stuff out instead.
12603 //
12604
12605 if (deviceRemovalPolicy == RemovalPolicyExpectSurpriseRemoval) {
12606 fdoData->HotplugInfo.DeviceHotplug = TRUE;
12607 } else {
12608 fdoData->HotplugInfo.DeviceHotplug = FALSE;
12609 }
12610
12611 //
12612 // this refers to the *filesystem* caching, but has to be included
12613 // here since it's a per-device setting. this may change to be
12614 // stored by the system in the future.
12615 //
12616
12617 writeCacheOverride = FALSE;
12618 ClassGetDeviceParameter(FdoExtension,
12621 &writeCacheOverride);
12622
12623 if (writeCacheOverride) {
12625 } else {
12627 }
12628
12629 return STATUS_SUCCESS;
12630}
#define FDO_HACK_CANNOT_LOCK_MEDIA
Definition: cdromp.h:133
NTSTATUS NTAPI IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_REGISTRY_PROPERTY DeviceProperty, IN ULONG BufferLength, OUT PVOID PropertyBuffer, OUT PULONG ResultLength)
Definition: pnpmgr.c:1382
BOOLEAN MediaHotplug
Definition: imports.h:247
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
enum _DEVICE_REMOVAL_POLICY DEVICE_REMOVAL_POLICY
@ DevicePropertyRemovalPolicy
Definition: iotypes.h:1214

Referenced by ClassPnpStartDevice().

◆ ClasspIsPortable()

NTSTATUS ClasspIsPortable ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
_Out_ PBOOLEAN  IsPortable 
)

Definition at line 8837 of file class.c.

8841{
8842 DEVPROP_BOOLEAN isInternal = DEVPROP_FALSE;
8843 BOOLEAN isPortable = FALSE;
8844 ULONG size = 0;
8847
8848 PAGED_CODE();
8849
8850 *IsPortable = FALSE;
8851
8852 //
8853 // Check to see if the underlying device
8854 // object is in local machine container
8855 //
8856
8857 status = IoGetDevicePropertyData(FdoExtension->LowerPdo,
8858 &DEVPKEY_Device_InLocalMachineContainer,
8859 0,
8860 0,
8861 sizeof(isInternal),
8862 &isInternal,
8863 &size,
8864 &type);
8865
8866 if (!NT_SUCCESS(status)) {
8867 goto cleanup;
8868 }
8869
8870 NT_ASSERT(size == sizeof(isInternal));
8872
8873 //
8874 // Volume is hot-pluggable if the disk pdo
8875 // container id differs from that of root device
8876 //
8877
8878 if (isInternal == DEVPROP_TRUE) {
8879 goto cleanup;
8880 }
8881
8882 isPortable = TRUE;
8883
8884 //
8885 // Examine the bus type to ensure
8886 // that this really is a fixed disk
8887 //
8888
8889 if (FdoExtension->DeviceDescriptor->BusType == BusTypeFibre ||
8890 FdoExtension->DeviceDescriptor->BusType == BusTypeiScsi ||
8891 FdoExtension->DeviceDescriptor->BusType == BusTypeRAID) {
8892
8893 isPortable = FALSE;
8894 }
8895
8896 *IsPortable = isPortable;
8897
8898cleanup:
8899
8900 return status;
8901}
#define DEVPROP_FALSE
Definition: devpropdef.h:67
ULONG DEVPROPTYPE
Definition: devpropdef.h:24
CHAR DEVPROP_BOOLEAN
Definition: devpropdef.h:64
#define DEVPROP_TYPE_EMPTY
Definition: devpropdef.h:29
#define DEVPROP_TYPE_BOOLEAN
Definition: devpropdef.h:46
#define DEVPROP_TRUE
Definition: devpropdef.h:66
static void cleanup(void)
Definition: main.c:1335
GLsizeiptr size
Definition: glext.h:5919
@ BusTypeiScsi
Definition: ntddstor.h:447
@ BusTypeRAID
Definition: ntddstor.h:446
@ BusTypeFibre
Definition: ntddstor.h:444

Referenced by ClassPnpStartDevice().

◆ ClasspModeSelect()

NTSTATUS ClasspModeSelect ( _In_ PDEVICE_OBJECT  Fdo,
_In_reads_bytes_(Length) PCHAR  ModeSelectBuffer,
_In_ ULONG  Length,
_In_ BOOLEAN  SavePages 
)

Definition at line 6919 of file class.c.

6925{
6926
6927 PMDL senseBufferMdl;
6929
6930 senseBufferMdl = BuildDeviceInputMdl(ModeSelectBuffer, Length);
6931 if (senseBufferMdl) {
6932
6934 if (pkt){
6935 KEVENT event;
6936 IRP pseudoIrp = {0};
6937
6938 /*
6939 * Store the number of packets servicing the irp (one)
6940 * inside the original IRP. It will be used to counted down
6941 * to zero when the packet completes.
6942 * Initialize the original IRP's status to success.
6943 * If the packet fails, we will set it to the error status.
6944 */
6945 pseudoIrp.Tail.Overlay.DriverContext[0] = LongToPtr(1);
6946 pseudoIrp.IoStatus.Status = STATUS_SUCCESS;
6947 pseudoIrp.IoStatus.Information = 0;
6948 pseudoIrp.MdlAddress = senseBufferMdl;
6949
6950 /*
6951 * Set this up as a SYNCHRONOUS transfer, submit it,
6952 * and wait for the packet to complete. The result
6953 * status will be written to the original irp.
6954 */
6955 NT_ASSERT(Length <= 0x0ff);
6957 SetupModeSelectTransferPacket(pkt, &event, ModeSelectBuffer, (UCHAR)Length, SavePages, &pseudoIrp);
6960
6961 if (!NT_SUCCESS(pseudoIrp.IoStatus.Status)){
6962 /*
6963 * This request can sometimes fail legitimately
6964 * (e.g. when a SCSI device is attached but turned off)
6965 * so this is not necessarily a device/driver bug.
6966 */
6967 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassModeSelect on Fdo %ph failed with status %xh.", Fdo, pseudoIrp.IoStatus.Status));
6968 }
6969
6970 status = pseudoIrp.IoStatus.Status;
6971 }
6972
6973 FreeDeviceInputMdl(senseBufferMdl);
6974 } else {
6976 }
6977
6978 return status;
6979}
VOID FreeDeviceInputMdl(PMDL Mdl)
Definition: utils.c:622
VOID SetupModeSelectTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSelectBuffer, UCHAR ModeSelectBufferLen, BOOLEAN SavePages, PIRP OriginalIrp)
Definition: xferpkt.c:1425
PMDL BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen)
Definition: utils.c:609
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
struct _cl_event * event
Definition: glext.h:7739
@ SynchronizationEvent

Referenced by ClassModeSelect(), and ClasspZeroQERR().

◆ ClasspModeSense()

ULONG ClasspModeSense ( _In_ PDEVICE_OBJECT  Fdo,
_In_reads_bytes_(Length) PCHAR  ModeSenseBuffer,
_In_ ULONG  Length,
_In_ UCHAR  PageMode,
_In_ UCHAR  PageControl 
)

Definition at line 6681 of file class.c.

6716{
6717 ULONG lengthTransferred = 0;
6718 PMDL senseBufferMdl;
6719
6720 PAGED_CODE();
6721
6722 senseBufferMdl = BuildDeviceInputMdl(ModeSenseBuffer, Length);
6723 if (senseBufferMdl){
6724
6726 if (pkt){
6727 KEVENT event;
6728 IRP pseudoIrp = {0};
6729
6730 /*
6731 * Store the number of packets servicing the irp (one)
6732 * inside the original IRP. It will be used to counted down
6733 * to zero when the packet completes.
6734 * Initialize the original IRP's status to success.
6735 * If the packet fails, we will set it to the error status.
6736 */
6737 pseudoIrp.Tail.Overlay.DriverContext[0] = LongToPtr(1);
6738 pseudoIrp.IoStatus.Status = STATUS_SUCCESS;
6739 pseudoIrp.IoStatus.Information = 0;
6740 pseudoIrp.MdlAddress = senseBufferMdl;
6741
6742 /*
6743 * Set this up as a SYNCHRONOUS transfer, submit it,
6744 * and wait for the packet to complete. The result
6745 * status will be written to the original irp.
6746 */
6747 NT_ASSERT(Length <= 0x0ff);
6749 SetupModeSenseTransferPacket(pkt, &event, ModeSenseBuffer, (UCHAR)Length, PageMode, 0, &pseudoIrp, PageControl);
6752
6753 if (NT_SUCCESS(pseudoIrp.IoStatus.Status)){
6754 lengthTransferred = (ULONG)pseudoIrp.IoStatus.Information;
6755 }
6756 else {
6757 /*
6758 * This request can sometimes fail legitimately
6759 * (e.g. when a SCSI device is attached but turned off)
6760 * so this is not necessarily a device/driver bug.
6761 */
6762 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClasspModeSense on Fdo %ph failed with status %xh.", Fdo, pseudoIrp.IoStatus.Status));
6763 }
6764 }
6765
6766 FreeDeviceInputMdl(senseBufferMdl);
6767 }
6768
6769 return lengthTransferred;
6770}
VOID SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, UCHAR SubPage, PIRP OriginalIrp, UCHAR PageControl)
Definition: xferpkt.c:1365

Referenced by ClassModeSense(), ClassModeSenseEx(), and ClasspWriteCacheProperty().

◆ ClassPnpQueryFdoRelations()

NTSTATUS ClassPnpQueryFdoRelations ( IN PDEVICE_OBJECT  Fdo,
IN PIRP  Irp 
)

Definition at line 9843 of file class.c.

9847{
9848 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
9849#ifdef _MSC_VER
9850#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
9851#endif
9853
9854 PAGED_CODE();
9855
9856 _Analysis_assume_(driverExtension != NULL);
9857
9858 //
9859 // If there's already an enumeration in progress then don't start another
9860 // one.
9861 //
9862
9863 if(InterlockedIncrement((volatile LONG *)&(fdoExtension->EnumerationInterlock)) == 1) {
9864 driverExtension->InitData.ClassEnumerateDevice(Fdo);
9865 }
9866
9867 Irp->IoStatus.Status = ClassRetrieveDeviceRelations(
9868 Fdo,
9870 (PDEVICE_RELATIONS *) &Irp->IoStatus.Information);
9871 InterlockedDecrement((volatile LONG *)&(fdoExtension->EnumerationInterlock));
9872
9873 return Irp->IoStatus.Status;
9874} // end ClassPnpQueryFdoRelations()
#define InterlockedDecrement
Definition: armddk.h:52
NTSTATUS ClassRetrieveDeviceRelations(IN PDEVICE_OBJECT Fdo, IN DEVICE_RELATION_TYPE RelationType, OUT PDEVICE_RELATIONS *DeviceRelations)
Definition: class.c:10005

Referenced by ClassDispatchPnp().

◆ ClassPnpStartDevice()

NTSTATUS ClassPnpStartDevice ( IN PDEVICE_OBJECT  DeviceObject)

Definition at line 1819 of file class.c.

1820{
1821 PCLASS_DRIVER_EXTENSION driverExtension;
1822 PCLASS_INIT_DATA initData;
1823
1824 PCLASS_DEV_INFO devInfo;
1825
1826 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
1827 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
1828 BOOLEAN isFdo = commonExtension->IsFdo;
1829
1830 BOOLEAN isMountedDevice = TRUE;
1831 BOOLEAN isPortable = FALSE;
1832
1834 PDEVICE_POWER_DESCRIPTOR powerDescriptor = NULL;
1835
1836
1837 PAGED_CODE();
1838
1839#ifdef _MSC_VER
1840#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
1841#endif
1842 driverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject, CLASS_DRIVER_EXTENSION_KEY);
1843
1844 initData = &(driverExtension->InitData);
1845 if(isFdo) {
1846 devInfo = &(initData->FdoData);
1847 } else {
1848 devInfo = &(initData->PdoData);
1849 }
1850
1851 NT_ASSERT(devInfo->ClassInitDevice != NULL);
1852 NT_ASSERT(devInfo->ClassStartDevice != NULL);
1853
1854 if (!commonExtension->IsInitialized){
1855
1856 //
1857 // perform FDO/PDO specific initialization
1858 //
1859
1860 if (isFdo){
1861 STORAGE_PROPERTY_ID propertyId;
1862
1863 //
1864 // allocate a private extension for class data
1865 //
1866
1867 if (fdoExtension->PrivateFdoData == NULL) {
1868 fdoExtension->PrivateFdoData = ExAllocatePoolWithTag(NonPagedPoolNx,
1869 sizeof(CLASS_PRIVATE_FDO_DATA),
1871 );
1872 }
1873
1874 if (fdoExtension->PrivateFdoData == NULL) {
1875 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate for private fdo data\n"));
1877 }
1878
1879 RtlZeroMemory(fdoExtension->PrivateFdoData, sizeof(CLASS_PRIVATE_FDO_DATA));
1880
1881
1882#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1883 //
1884 // Allocate a structure to hold more data than what we can put in FUNCTIONAL_DEVICE_EXTENSION.
1885 // This structure's memory is managed by classpnp, so it is more extensible.
1886 //
1887 if (fdoExtension->AdditionalFdoData == NULL) {
1888 fdoExtension->AdditionalFdoData = ExAllocatePoolWithTag(NonPagedPoolNx,
1889 sizeof(ADDITIONAL_FDO_DATA),
1891 );
1892 }
1893
1894 if (fdoExtension->AdditionalFdoData == NULL) {
1895 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate memory for the additional data structure.\n"));
1897 }
1898
1899 RtlZeroMemory(fdoExtension->AdditionalFdoData, sizeof(ADDITIONAL_FDO_DATA));
1900#endif
1901
1902 status = ClasspInitializeTimer(fdoExtension);
1903 if (NT_SUCCESS(status) == FALSE) {
1904 FREE_POOL(fdoExtension->PrivateFdoData);
1905#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1906 FREE_POOL(fdoExtension->AdditionalFdoData);
1907#endif
1908 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Failed to initialize tick timer\n"));
1910 }
1911
1912 //
1913 // allocate LowerLayerSupport for class data
1914 //
1915
1916 if (fdoExtension->FunctionSupportInfo == NULL) {
1917 fdoExtension->FunctionSupportInfo = (PCLASS_FUNCTION_SUPPORT_INFO)ExAllocatePoolWithTag(NonPagedPoolNx,
1919 '3BcS'
1920 );
1921 }
1922
1923 if (fdoExtension->FunctionSupportInfo == NULL) {
1924 ClasspDeleteTimer(fdoExtension);
1925 FREE_POOL(fdoExtension->PrivateFdoData);
1926#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1927 FREE_POOL(fdoExtension->AdditionalFdoData);
1928#endif
1929 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate for FunctionSupportInfo\n"));
1931 }
1932
1933 //
1934 // initialize the struct's various fields.
1935 //
1936 RtlZeroMemory(fdoExtension->FunctionSupportInfo, sizeof(CLASS_FUNCTION_SUPPORT_INFO));
1937 KeInitializeSpinLock(&fdoExtension->FunctionSupportInfo->SyncLock);
1938
1939 //
1940 // intialize the CommandStatus to -1 indicates that no effort made yet to retrieve the info.
1941 // Possible values of CommandStatus (data type: NTSTATUS):
1942 // -1: It's not attempted yet to retrieve the information.
1943 // success: Command sent and succeeded, information cached in FdoExtension.
1944 // failed/warning: Command is either not supported or failed by device or lower level driver.
1945 // The command should not be attempted again.
1946 //
1947 fdoExtension->FunctionSupportInfo->BlockLimitsData.CommandStatus = -1;
1948 fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.CommandStatus = -1;
1949 fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus = -1;
1950 fdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus = -1;
1951 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus = -1;
1952
1953
1954 KeInitializeTimer(&fdoExtension->PrivateFdoData->Retry.Timer);
1955 KeInitializeDpc(&fdoExtension->PrivateFdoData->Retry.Dpc,
1957 DeviceObject);
1958 KeInitializeSpinLock(&fdoExtension->PrivateFdoData->Retry.Lock);
1959 fdoExtension->PrivateFdoData->Retry.Granularity = KeQueryTimeIncrement();
1960 commonExtension->Reserved4 = (ULONG_PTR)(' GPH'); // debug aid
1961 InitializeListHead(&fdoExtension->PrivateFdoData->DeferredClientIrpList);
1962
1963 KeInitializeSpinLock(&fdoExtension->PrivateFdoData->SpinLock);
1964
1965 //
1966 // keep a pointer to the senseinfo2 stuff locally also (used in every read/write).
1967 //
1968 fdoExtension->PrivateFdoData->InterpretSenseInfo = driverExtension->InterpretSenseInfo;
1969
1970 fdoExtension->PrivateFdoData->MaxNumberOfIoRetries = NUM_IO_RETRIES;
1971
1972 //
1973 // Initialize release queue extended SRB
1974 //
1975 status = InitializeStorageRequestBlock(&(fdoExtension->PrivateFdoData->ReleaseQueueSrb.SrbEx),
1977 sizeof(fdoExtension->PrivateFdoData->ReleaseQueueSrb.ReleaseQueueSrbBuffer),
1978 0);
1979 if (!NT_SUCCESS(status)) {
1981 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
1982 "ClassPnpStartDevice: fail to initialize release queue extended SRB 0x%x\n", status));
1983 return status;
1984 }
1985
1986
1987 /*
1988 * Anchor the FDO in our static list.
1989 * Pnp is synchronized, so we shouldn't need any synchronization here.
1990 */
1991 InsertTailList(&AllFdosList, &fdoExtension->PrivateFdoData->AllFdosListEntry);
1992
1993 //
1994 // NOTE: the old interface allowed the class driver to allocate
1995 // this. this was unsafe for low-memory conditions. allocate one
1996 // unconditionally now, and modify our internal functions to use
1997 // our own exclusively as it is the only safe way to do this.
1998 //
1999
2000 status = ClasspAllocateReleaseQueueIrp(fdoExtension);
2001 if (!NT_SUCCESS(status)) {
2002 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate the private release queue irp\n"));
2003 return status;
2004 }
2005
2006 status = ClasspAllocatePowerProcessIrp(fdoExtension);
2007 if (!NT_SUCCESS(status)) {
2008 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate the power process irp\n"));
2009 return status;
2010 }
2011
2012 //
2013 // Call port driver to get miniport properties for disk devices
2014 // It's ok for this call to fail
2015 //
2016
2017 if ((DeviceObject->DeviceType == FILE_DEVICE_DISK) &&
2018 (!TEST_FLAG(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE))) {
2019
2020 propertyId = StorageMiniportProperty;
2021
2022 status = ClassGetDescriptor(fdoExtension->CommonExtension.LowerDeviceObject,
2023 &propertyId,
2024 (PVOID *)&fdoExtension->MiniportDescriptor);
2025
2026 //
2027 // function ClassGetDescriptor returns succeed with buffer "fdoExtension->MiniportDescriptor" allocated.
2028 //
2029 if ( NT_SUCCESS(status) &&
2030 (fdoExtension->MiniportDescriptor->Portdriver != StoragePortCodeSetStorport &&
2031 fdoExtension->MiniportDescriptor->Portdriver != StoragePortCodeSetUSBport) ) {
2032 //
2033 // field "IoTimeoutValue" supported for either Storport or USBStor
2034 //
2035 fdoExtension->MiniportDescriptor->IoTimeoutValue = 0;
2036 }
2037
2038
2039
2040 }
2041
2042 //
2043 // Call port driver to get adapter capabilities.
2044 //
2045
2046 propertyId = StorageAdapterProperty;
2047
2048 status = ClassGetDescriptor(
2049 commonExtension->LowerDeviceObject,
2050 &propertyId,
2051 (PVOID *)&fdoExtension->AdapterDescriptor);
2052 if (!NT_SUCCESS(status)) {
2053 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: ClassGetDescriptor [ADAPTER] failed %lx\n", status));
2054 return status;
2055 }
2056
2057 //
2058 // Call port driver to get device descriptor.
2059 //
2060
2061 propertyId = StorageDeviceProperty;
2062
2063 status = ClassGetDescriptor(
2064 commonExtension->LowerDeviceObject,
2065 &propertyId,
2066 (PVOID *)&fdoExtension->DeviceDescriptor);
2067 if (NT_SUCCESS(status)){
2068
2069 ClasspScanForSpecialInRegistry(fdoExtension);
2070 ClassScanForSpecial(fdoExtension, ClassBadItems, ClasspScanForClassHacks);
2071
2072 //
2073 // allow perf to be re-enabled after a given number of failed IOs
2074 // require this number to be at least CLASS_PERF_RESTORE_MINIMUM
2075 //
2076
2077 {
2079
2080 ClassGetDeviceParameter(fdoExtension,
2083 &t);
2085 fdoExtension->PrivateFdoData->Perf.ReEnableThreshhold = t;
2086 }
2087 }
2088
2089 //
2090 // compatibility comes first. writable cd media will not
2091 // get a SYNCH_CACHE on power down.
2092 //
2093 if (fdoExtension->DeviceObject->DeviceType != FILE_DEVICE_DISK) {
2094 SET_FLAG(fdoExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_SYNC_CACHE);
2095 }
2096
2097
2098 //
2099 // Test if the device is portable and updated the characteristics if so
2100 //
2101 status = ClasspIsPortable(fdoExtension,
2102 &isPortable);
2103
2104 if (NT_SUCCESS(status) && (isPortable == TRUE)) {
2105 DeviceObject->Characteristics |= FILE_PORTABLE_DEVICE;
2106 }
2107
2108 //
2109 // initialize the hotplug information only after the ScanForSpecial
2110 // routines, as it relies upon the hack flags.
2111 //
2112 status = ClasspInitializeHotplugInfo(fdoExtension);
2113 if (NT_SUCCESS(status)){
2114 /*
2115 * Allocate/initialize TRANSFER_PACKETs and related resources.
2116 */
2118 }
2119 else {
2120 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClassPnpStartDevice: Could not initialize hotplug information %lx\n", status));
2121 }
2122 }
2123 else {
2124 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: ClassGetDescriptor [DEVICE] failed %lx\n", status));
2125 return status;
2126 }
2127
2128
2129 if (NT_SUCCESS(status)) {
2130
2131 //
2132 // Retrieve info on whether async notification is supported by port drivers
2133 //
2134 propertyId = StorageDevicePowerProperty;
2135
2136 status = ClassGetDescriptor(fdoExtension->CommonExtension.LowerDeviceObject,
2137 &propertyId,
2138 (PVOID *)&powerDescriptor);
2139 if (NT_SUCCESS(status) && (powerDescriptor != NULL)) {
2140 fdoExtension->FunctionSupportInfo->AsynchronousNotificationSupported = powerDescriptor->AsynchronousNotificationSupported;
2141 fdoExtension->FunctionSupportInfo->IdlePower.D3ColdSupported = powerDescriptor->D3ColdSupported;
2142 fdoExtension->FunctionSupportInfo->IdlePower.NoVerifyDuringIdlePower = powerDescriptor->NoVerifyDuringIdlePower;
2143 FREE_POOL(powerDescriptor);
2144 } else {
2145 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: ClassGetDescriptor [DevicePower] failed %lx\n", status));
2146
2147 //
2148 // Ignore error as device power property is optional
2149 //
2151 }
2152 }
2153 }
2154
2155 //
2156 // ISSUE - drivers need to disable write caching on the media
2157 // if hotplug and !useroverride. perhaps we should
2158 // allow registration of a callback to enable/disable
2159 // write cache instead.
2160 //
2161
2162 if (NT_SUCCESS(status)){
2164 }
2165
2166 if (commonExtension->IsFdo) {
2167 fdoExtension->PrivateFdoData->Perf.OriginalSrbFlags = fdoExtension->SrbFlags;
2168
2169 //
2170 // initialization for disk device
2171 //
2172 if ((DeviceObject->DeviceType == FILE_DEVICE_DISK) &&
2173 (!TEST_FLAG(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE))) {
2174
2175 ULONG accessAlignmentNotSupported = 0;
2176 ULONG qerrOverrideMode = QERR_SET_ZERO_ODX_OR_TP_ONLY;
2177 ULONG legacyErrorHandling = FALSE;
2178
2179 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP,
2180 "ClassPnpStartDevice: Enabling idle timer for %p\n", DeviceObject));
2181 // Initialize idle timer for disk devices
2182 ClasspInitializeIdleTimer(fdoExtension);
2183
2184 if (ClasspIsObsoletePortDriver(fdoExtension) == FALSE) {
2185 // get INQUIRY VPD support information. It's safe to send command as everything is ready in ClassInitDevice().
2186 ClasspGetInquiryVpdSupportInfo(fdoExtension);
2187
2188 // Query and cache away Logical Block Provisioning info in the FDO extension.
2189 // The cached information will be used in responding to some IOCTLs
2190 ClasspGetLBProvisioningInfo(fdoExtension);
2191
2192 //
2193 // Query and cache away Block Device ROD Limits info in the FDO extension.
2194 //
2195 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits) {
2196 ClassDetermineTokenOperationCommandSupport(DeviceObject);
2197 }
2198
2199 //
2200 // See if the user has specified a particular QERR override
2201 // mode. "Override" meaning setting QERR = 0 via Mode Select.
2202 // 0 = Only when ODX or Thin Provisioning are supported (default)
2203 // 1 = Always
2204 // 2 = Never (or any value >= 2)
2205 //
2206 ClassGetDeviceParameter(fdoExtension,
2209 &qerrOverrideMode);
2210
2211 //
2212 // If this device is thinly provisioned or supports ODX, we
2213 // may need to force QERR to zero. The user may have also
2214 // specified that we should always or never do this.
2215 //
2216 if (qerrOverrideMode == QERR_SET_ZERO_ALWAYS ||
2217 (qerrOverrideMode == QERR_SET_ZERO_ODX_OR_TP_ONLY &&
2218 (ClasspIsThinProvisioned(fdoExtension->FunctionSupportInfo) ||
2219 NT_SUCCESS(ClasspValidateOffloadSupported(DeviceObject, NULL))))) {
2220
2222 }
2223
2224 } else {
2225
2226 //
2227 // Since this device has been exposed by a legacy miniport (e.g. SCSIPort miniport)
2228 // set its LB Provisioning command status to an error status that will be surfaced
2229 // up to the caller of a TRIM/Unmap command.
2230 //
2231 fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus = STATUS_UNSUCCESSFUL;
2232 fdoExtension->FunctionSupportInfo->BlockLimitsData.CommandStatus = STATUS_UNSUCCESSFUL;
2233 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus = STATUS_UNSUCCESSFUL;
2234 }
2235
2236 // Get registry setting of failing the IOCTL for AccessAlignment Property.
2237 ClassGetDeviceParameter(fdoExtension,
2240 &accessAlignmentNotSupported);
2241
2242 if (accessAlignmentNotSupported > 0) {
2243 fdoExtension->FunctionSupportInfo->RegAccessAlignmentQueryNotSupported = TRUE;
2244 }
2245
2246#if (NTDDI_VERSION >= NTDDI_WINBLUE)
2247
2248
2249 //
2250 // See if the user has specified legacy error handling.
2251 //
2252 ClassGetDeviceParameter(fdoExtension,
2255 &legacyErrorHandling);
2256
2257 if (legacyErrorHandling) {
2258 //
2259 // Legacy error handling means that the maximum number of
2260 // retries allowd for an IO request is 8 instead of 4.
2261 //
2262 fdoExtension->PrivateFdoData->MaxNumberOfIoRetries = LEGACY_NUM_IO_RETRIES;
2263 fdoExtension->PrivateFdoData->LegacyErrorHandling = TRUE;
2264 }
2265#else
2266 UNREFERENCED_PARAMETER(legacyErrorHandling);
2267#endif
2268
2269
2270 //
2271 // Get the copy offload max target duration value.
2272 // This function will set the default value if one hasn't been
2273 // specified in the registry.
2274 //
2275 ClasspGetCopyOffloadMaxDuration(DeviceObject,
2277 &(fdoExtension->PrivateFdoData->CopyOffloadMaxTargetDuration));
2278
2279 }
2280
2281 }
2282 }
2283
2284 if (!NT_SUCCESS(status)){
2285
2286 //
2287 // Just bail out - the remove that comes down will clean up the
2288 // initialized scraps.
2289 //
2290
2291 return status;
2292 } else {
2293 commonExtension->IsInitialized = TRUE;
2294 }
2295
2296 //
2297 // If device requests autorun functionality or a once a second callback
2298 // then enable the once per second timer. Exception is if media change
2299 // detection is desired but device supports async notification.
2300 //
2301 // NOTE: This assumes that ClassInitializeMediaChangeDetection is always
2302 // called in the context of the ClassInitDevice callback. If called
2303 // after then this check will have already been made and the
2304 // once a second timer will not have been enabled.
2305 //
2306 if ((isFdo) &&
2307 ((initData->ClassTick != NULL) ||
2308 ((fdoExtension->MediaChangeDetectionInfo != NULL) &&
2309 (fdoExtension->FunctionSupportInfo != NULL) &&
2310 (fdoExtension->FunctionSupportInfo->AsynchronousNotificationSupported == FALSE)) ||
2311 ((fdoExtension->FailurePredictionInfo != NULL) &&
2312 (fdoExtension->FailurePredictionInfo->Method != FailurePredictionNone))))
2313 {
2314 ClasspEnableTimer(fdoExtension);
2315
2316 //
2317 // In addition, we may change our polling behavior when the screen is
2318 // off so register for screen state notification if we haven't already
2319 // done so.
2320 //
2323 &GUID_CONSOLE_DISPLAY_STATE,
2325 NULL,
2327 }
2328 }
2329
2330 //
2331 // NOTE: the timer looks at commonExtension->CurrentState now
2332 // to prevent Media Change Notification code from running
2333 // until the device is started, but allows the device
2334 // specific tick handler to run. therefore it is imperative
2335 // that commonExtension->CurrentState not be updated until
2336 // the device specific startdevice handler has finished.
2337 //
2338
2340
2341 if (NT_SUCCESS(status)){
2342 commonExtension->CurrentState = IRP_MN_START_DEVICE;
2343
2344 if((isFdo) && (initData->ClassEnumerateDevice != NULL)) {
2345 isMountedDevice = FALSE;
2346 }
2347
2348 if (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM) {
2349
2350 isMountedDevice = FALSE;
2351 }
2352
2353 //
2354 // Register for mounted device interface if this is a
2355 // sfloppy device.
2356 //
2357 if ((DeviceObject->DeviceType == FILE_DEVICE_DISK) &&
2358 (TEST_FLAG(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE))) {
2359
2360 isMountedDevice = TRUE;
2361 }
2362
2363 if(isMountedDevice) {
2365 }
2366
2367 if(commonExtension->IsFdo) {
2369
2370 //
2371 // Tell Storport (Usbstor or SD) to enable idle power management for this
2372 // device, assuming the user hasn't turned it off in the registry.
2373 //
2374 if (fdoExtension->FunctionSupportInfo != NULL &&
2375 fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled == FALSE &&
2376 fdoExtension->MiniportDescriptor != NULL &&
2377 (fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetStorport ||
2378 fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetSDport ||
2379 fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetUSBport)) {
2380 ULONG disableIdlePower= 0;
2381 ClassGetDeviceParameter(fdoExtension,
2384 &disableIdlePower);
2385
2386 if (!disableIdlePower) {
2388 }
2389 }
2390 }
2391 }
2392 else {
2393 ClasspDisableTimer(fdoExtension);
2394 }
2395
2396
2397 return status;
2398}
#define CLASS_PERF_RESTORE_MINIMUM
Definition: cdromp.h:129
#define CLASSP_REG_PERF_RESTORE_VALUE_NAME
Definition: cdromp.h:125
VOID ClasspZeroQERR(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:7938
#define CLASSP_REG_ACCESS_ALIGNMENT_NOT_SUPPORTED
Definition: classp.h:122
CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[]
Definition: data.c:43
VOID ClasspInitializeIdleTimer(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: clntirp.c:175
#define CLASSP_REG_QERR_OVERRIDE_MODE
Definition: classp.h:126
LIST_ENTRY AllFdosList
Definition: data.c:29
NTSTATUS InitializeTransferPackets(PDEVICE_OBJECT Fdo)
Definition: xferpkt.c:45
#define NUM_IO_RETRIES
Definition: classp.h:169
#define CLASSPNP_POOL_TAG_ADDITIONAL_DATA
Definition: classp.h:197
FORCEINLINE BOOLEAN ClasspIsObsoletePortDriver(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classp.h:1335
#define FDO_HACK_NO_SYNC_CACHE
Definition: classp.h:137
#define QERR_SET_ZERO_ODX_OR_TP_ONLY
Definition: classp.h:1185
#define QERR_SET_ZERO_ALWAYS
Definition: classp.h:1186
FORCEINLINE BOOLEAN ClasspIsThinProvisioned(_In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo)
Definition: classp.h:1317
KDEFERRED_ROUTINE ClasspRetryRequestDpc
Definition: classp.h:1644
#define CLASSP_REG_LEGACY_ERROR_HANDLING
Definition: classp.h:127
_IRQL_requires_same_ NTSTATUS ClasspEnableIdlePower(_In_ PDEVICE_OBJECT DeviceObject)
Definition: power.c:2550
#define CLASS_TAG_PRIVATE_DATA
Definition: classp.h:189
#define CLASSP_REG_DISBALE_IDLE_POWER_NAME
Definition: classp.h:123
#define LEGACY_NUM_IO_RETRIES
Definition: classp.h:170
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
Definition: classp.h:1619
NTSTATUS ClasspInitializeTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3737
VOID ClasspEnableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3857
VOID ClasspDeleteTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3798
struct _CLASS_FUNCTION_SUPPORT_INFO * PCLASS_FUNCTION_SUPPORT_INFO
@ FailurePredictionNone
Definition: classpnp.h:234
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
VOID NTAPI ClasspScanForClassHacks(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN ULONG_PTR Data)
Definition: class.c:12634
PVOID ScreenStateNotificationHandle
Definition: class.c:124
VOID ClasspGetInquiryVpdSupportInfo(_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:12914
VOID ClasspScanForSpecialInRegistry(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:12651
NTSTATUS ClasspAllocateReleaseQueueIrp(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:11621
NTSTATUS ClasspGetLBProvisioningInfo(_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:13087
NTSTATUS ClasspIsPortable(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _Out_ PBOOLEAN IsPortable)
Definition: class.c:8837
VOID ClasspRegisterMountedDeviceInterface(IN PDEVICE_OBJECT DeviceObject)
Definition: class.c:10970
NTSTATUS ClasspAllocatePowerProcessIrp(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:11683
NTSTATUS ClasspInitializeHotplugInfo(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:12507
#define InsertTailList(ListHead, Entry)
GLdouble GLdouble t
Definition: gl.h:2047
#define FILE_PORTABLE_DEVICE
Definition: winternl.h:1855
#define FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
enum _STORAGE_PROPERTY_ID STORAGE_PROPERTY_ID
@ StorageMiniportProperty
Definition: ntddstor.h:517
@ StorageAdapterProperty
Definition: ntddstor.h:513
@ StorageDevicePowerProperty
Definition: ntddstor.h:524
@ StorageDeviceProperty
Definition: ntddstor.h:512
@ StoragePortCodeSetStorport
Definition: ntddstor.h:619
@ StoragePortCodeSetUSBport
Definition: ntddstor.h:623
@ StoragePortCodeSetSDport
Definition: ntddstor.h:625
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
NTSTATUS NTAPI IoWMIRegistrationControl(IN PDEVICE_OBJECT DeviceObject, IN ULONG Action)
Definition: wmi.c:68
NTKRNLVISTAAPI NTSTATUS NTAPI PoRegisterPowerSettingCallback(_In_opt_ PDEVICE_OBJECT DeviceObject, _In_ LPCGUID SettingGuid, _In_ PPOWER_SETTING_CALLBACK Callback, _In_opt_ PVOID Context, _Outptr_opt_ PVOID *Handle)
Definition: po.c:14
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:108
PCLASS_INIT_DEVICE ClassInitDevice
Definition: classpnp.h:527
PCLASS_START_DEVICE ClassStartDevice
Definition: classpnp.h:528
PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo
Definition: classpnp.h:587
PCLASS_TICK ClassTick
Definition: classpnp.h:545
BOOLEAN NoVerifyDuringIdlePower
Definition: ntddstor.h:671
BOOLEAN AsynchronousNotificationSupported
Definition: ntddstor.h:667
struct _FAILURE_PREDICTION_INFO * FailurePredictionInfo
Definition: classpnp.h:919
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
#define WMIREG_ACTION_REGISTER

Referenced by ClassDispatchPnp().

◆ ClasspPopulateTokenTransferPacketDone()

VOID ClasspPopulateTokenTransferPacketDone ( _In_ PVOID  Context)

Definition at line 14166 of file class.c.

14191{
14192 PDEVICE_OBJECT fdo;
14193 ULONG listIdentifier;
14194 POFFLOAD_READ_CONTEXT offloadReadContext;
14195 PTRANSFER_PACKET pkt;
14196 PIRP pseudoIrp;
14198
14199 offloadReadContext = Context;
14200 pseudoIrp = &offloadReadContext->PseudoIrp;
14201 pkt = offloadReadContext->Pkt;
14202 fdo = offloadReadContext->Fdo;
14203 listIdentifier = offloadReadContext->ListIdentifier;
14204
14205 offloadReadContext->Pkt = NULL;
14206
14207
14208 status = pseudoIrp->IoStatus.Status;
14210
14211 if (!NT_SUCCESS(status)) {
14212 TracePrint((TRACE_LEVEL_ERROR,
14213 TRACE_FLAG_IOCTL,
14214 "ClasspPopulateTokenTransferPacketDone (%p): Generate token for list Id %x failed with %x (Pkt %p).\n",
14215 fdo,
14216 listIdentifier,
14217 status,
14218 pkt));
14219 goto __ClasspPopulateTokenTransferPacketDone_ErrorExit;
14220 }
14221
14222 //
14223 // If a token was successfully generated, it is now time to retrieve the token.
14224 // The called function is responsible for completing the offload read DSM IRP.
14225 //
14226 ClasspReceivePopulateTokenInformation(offloadReadContext);
14227
14228 //
14229 // ClasspReceivePopulateTokenInformation() takes care of completing the IRP,
14230 // so this function is done regardless of success or failure in
14231 // ClasspReceivePopulateTokenInformation().
14232 //
14233
14234 return;
14235
14236 //
14237 // Error cleanup label only - not used in success case:
14238 //
14239
14240__ClasspPopulateTokenTransferPacketDone_ErrorExit:
14241
14243
14244 //
14245 // ClasspCompleteOffloadRead also cleans up offloadReadContext.
14246 //
14247
14248 ClasspCompleteOffloadRead(offloadReadContext, status);
14249
14250 return;
14251}
VOID ClasspCompleteOffloadRead(_In_ POFFLOAD_READ_CONTEXT OffloadReadContext, _In_ NTSTATUS CompletionStatus)
Definition: class.c:14255
_IRQL_requires_same_ VOID ClasspReceivePopulateTokenInformation(_In_ POFFLOAD_READ_CONTEXT OffloadReadContext)
Definition: class.c:14374
PTRANSFER_PACKET Pkt
Definition: classp.h:1066
PDEVICE_OBJECT Fdo
Definition: classp.h:1040

Referenced by _IRQL_requires_max_().

◆ ClasspReceivePopulateTokenInformation()

_IRQL_requires_same_ VOID ClasspReceivePopulateTokenInformation ( _In_ POFFLOAD_READ_CONTEXT  OffloadReadContext)

Definition at line 14374 of file class.c.

14403{
14404 PVOID buffer;
14406 ULONG cdbLength;
14407 PDEVICE_OBJECT fdo;
14408 PIRP irp;
14409 ULONG listIdentifier;
14410 PTRANSFER_PACKET pkt;
14411 PIRP pseudoIrp;
14412 ULONG receiveTokenInformationBufferLength;
14415 ULONG tempSizeUlong;
14416 PULONGLONG totalSectorsProcessed;
14417
14418 totalSectorsProcessed = &OffloadReadContext->TotalSectorsProcessed;
14419 buffer = OffloadReadContext + 1;
14420 bufferLength = OffloadReadContext->BufferLength;
14421 fdo = OffloadReadContext->Fdo;
14422 irp = OffloadReadContext->OffloadReadDsmIrp;
14423 receiveTokenInformationBufferLength = OffloadReadContext->ReceiveTokenInformationBufferLength;
14424 listIdentifier = OffloadReadContext->ListIdentifier;
14425
14426 TracePrint((TRACE_LEVEL_VERBOSE,
14427 TRACE_FLAG_IOCTL,
14428 "ClasspReceivePopulateTokenInformation (%p): Entering function. Irp %p\n",
14429 fdo,
14430 irp));
14431
14432 srb = &OffloadReadContext->Srb;
14433 *totalSectorsProcessed = 0;
14434
14435 pkt = DequeueFreeTransferPacket(fdo, TRUE);
14436 if (!pkt){
14437
14438 TracePrint((TRACE_LEVEL_ERROR,
14439 TRACE_FLAG_IOCTL,
14440 "ClasspReceivePopulateTokenInformation (%p): Failed to retrieve transfer packet for ReceiveTokenInformation (PopulateToken) operation.\n",
14441 fdo));
14442
14444 goto __ClasspReceivePopulateTokenInformation_ErrorExit;
14445 }
14446
14447 OffloadReadContext->Pkt = pkt;
14448
14450
14451 tempSizeUlong = receiveTokenInformationBufferLength - 4;
14452 REVERSE_BYTES(((PRECEIVE_TOKEN_INFORMATION_HEADER)buffer)->AvailableData, &tempSizeUlong);
14453
14454 pseudoIrp = &OffloadReadContext->PseudoIrp;
14455 RtlZeroMemory(pseudoIrp, sizeof(IRP));
14456
14457
14458 pseudoIrp->IoStatus.Status = STATUS_SUCCESS;
14459 pseudoIrp->IoStatus.Information = 0;
14460 pseudoIrp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
14461 pseudoIrp->MdlAddress = OffloadReadContext->PopulateTokenMdl;
14462
14463 ClasspSetupReceivePopulateTokenInformationTransferPacket(
14464 OffloadReadContext,
14465 pkt,
14466 receiveTokenInformationBufferLength,
14467 (PUCHAR)buffer,
14468 pseudoIrp,
14469 listIdentifier);
14470
14471 //
14472 // Cache away the CDB as it may be required for forwarded sense data
14473 // after this command completes.
14474 //
14475 RtlZeroMemory(srb, sizeof(*srb));
14476 cdbLength = SrbGetCdbLength(pkt->Srb);
14477 if (cdbLength <= 16) {
14478 RtlCopyMemory(&srb->Cdb, SrbGetCdb(pkt->Srb), cdbLength);
14479 }
14480
14482
14483 return;
14484
14485 //
14486 // Error cleanup label only - not used in success case:
14487 //
14488
14489__ClasspReceivePopulateTokenInformation_ErrorExit:
14490
14492
14493 //
14494 // ClasspCompleteOffloadRead also cleans up offloadReadContext.
14495 //
14496
14497 ClasspCompleteOffloadRead(OffloadReadContext, status);
14498
14499 return;
14500}
UCHAR Cdb[16]
Definition: srb.h:279
PSTORAGE_REQUEST_BLOCK_HEADER Srb
Definition: classp.h:580

Referenced by ClasspPopulateTokenTransferPacketDone().

◆ ClasspReceivePopulateTokenInformationTransferPacketDone()

VOID ClasspReceivePopulateTokenInformationTransferPacketDone ( _In_ PVOID  Context)

Definition at line 14504 of file class.c.

14529{
14530 ULONG availableData;
14531 PVOID buffer;
14532 UCHAR completionStatus;
14533 ULONG estimatedRetryInterval;
14534 PDEVICE_OBJECT fdo;
14536 PIRP irp;
14537 ULONG listIdentifier;
14538 POFFLOAD_READ_CONTEXT offloadReadContext;
14539 BOOLEAN operationCompleted;
14540 UCHAR operationStatus;
14541 PIRP pseudoIrp;
14542 USHORT segmentsProcessed;
14543 PSENSE_DATA senseData;
14544 ULONG senseDataFieldLength;
14545 UCHAR senseDataLength;
14548 PUCHAR token;
14549 PVOID tokenAscii;
14550 PBLOCK_DEVICE_TOKEN_DESCRIPTOR tokenDescriptor;
14551 ULONG tokenDescriptorLength;
14552 PRECEIVE_TOKEN_INFORMATION_HEADER tokenInformationResults;
14553 PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER tokenInformationResultsResponse;
14554 ULONG tokenLength;
14555 ULONG tokenSize;
14556 PULONGLONG totalSectorsProcessed;
14557 ULONGLONG totalSectorsToProcess;
14558 ULONGLONG transferBlockCount;
14559
14560 offloadReadContext = Context;
14561 fdo = offloadReadContext->Fdo;
14562 fdoExt = fdo->DeviceExtension;
14563 buffer = offloadReadContext + 1;
14564 listIdentifier = offloadReadContext->ListIdentifier;
14565 irp = offloadReadContext->OffloadReadDsmIrp;
14566 totalSectorsToProcess = offloadReadContext->TotalSectorsToProcess;
14567 totalSectorsProcessed = &offloadReadContext->TotalSectorsProcessed;
14568 srb = &offloadReadContext->Srb;
14569 tokenAscii = NULL;
14570 tokenSize = BLOCK_DEVICE_TOKEN_SIZE;
14571 tokenInformationResults = (PRECEIVE_TOKEN_INFORMATION_HEADER)buffer;
14572 senseData = (PSENSE_DATA)((PUCHAR)tokenInformationResults + FIELD_OFFSET(RECEIVE_TOKEN_INFORMATION_HEADER, SenseData));
14573 transferBlockCount = 0;
14574 tokenInformationResultsResponse = NULL;
14575 tokenDescriptor = NULL;
14576 operationCompleted = FALSE;
14577 tokenDescriptorLength = 0;
14578 tokenLength = 0;
14579 token = NULL;
14580 pseudoIrp = &offloadReadContext->PseudoIrp;
14581
14582 status = pseudoIrp->IoStatus.Status;
14584
14585 //
14586 // The buffer we hand allows for the max sizes for all the fields whereas the returned
14587 // data may be lesser (e.g. sense data info will almost never be MAX_SENSE_BUFFER_SIZE, etc.
14588 // so handle underrun "error"
14589 //
14590 if (status == STATUS_DATA_OVERRUN) {
14591
14593 }
14594
14595 if (!NT_SUCCESS(status)) {
14596 TracePrint((TRACE_LEVEL_ERROR,
14597 TRACE_FLAG_IOCTL,
14598 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Token retrieval failed for list Id %x with %x.\n",
14599 fdo,
14600 listIdentifier,
14601 status));
14602 goto __ClasspReceivePopulateTokenInformationTransferPacketDone_Exit;
14603 }
14604
14605 REVERSE_BYTES(&availableData, &tokenInformationResults->AvailableData);
14606
14609
14611
14612 operationStatus = tokenInformationResults->OperationStatus;
14613 operationCompleted = ClasspIsTokenOperationComplete(operationStatus);
14614 NT_ASSERT(operationCompleted);
14615
14616 REVERSE_BYTES(&estimatedRetryInterval, &tokenInformationResults->EstimatedStatusUpdateDelay);
14617
14618 completionStatus = tokenInformationResults->CompletionStatus;
14619
14621 REVERSE_BYTES_QUAD(&transferBlockCount, &tokenInformationResults->TransferCount);
14622
14623 REVERSE_BYTES_SHORT(&segmentsProcessed, &tokenInformationResults->SegmentsProcessed);
14624 NT_ASSERT(segmentsProcessed == 0);
14625
14626 if (operationCompleted) {
14627
14628 if (transferBlockCount > totalSectorsToProcess) {
14629
14630 //
14631 // Buggy or hostile target. Don't let it claim more was procesed
14632 // than was requested. Since this is likely a bug and it's unknown
14633 // how much was actually transferred, assume no data was
14634 // transferred.
14635 //
14636
14637 NT_ASSERT(transferBlockCount <= totalSectorsToProcess);
14638 transferBlockCount = 0;
14639 }
14640
14641 if (operationStatus != OPERATION_COMPLETED_WITH_SUCCESS &&
14642 operationStatus != OPERATION_COMPLETED_WITH_RESIDUAL_DATA) {
14643
14644 //
14645 // Assert on buggy response from target, but in any case, make sure not
14646 // to claim that any data was written.
14647 //
14648
14649 NT_ASSERT(transferBlockCount == 0);
14650 transferBlockCount = 0;
14651 }
14652
14653 //
14654 // Since the TokenOperation was sent down synchronously, the operation is complete as soon as the command returns.
14655 //
14656
14657 senseDataFieldLength = tokenInformationResults->SenseDataFieldLength;
14658 senseDataLength = tokenInformationResults->SenseDataLength;
14659 NT_ASSERT(senseDataFieldLength >= senseDataLength);
14660
14661 tokenInformationResultsResponse = (PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER)((PUCHAR)tokenInformationResults +
14663 tokenInformationResults->SenseDataFieldLength);
14664
14665 REVERSE_BYTES(&tokenDescriptorLength, &tokenInformationResultsResponse->TokenDescriptorsLength);
14666
14667 if (tokenDescriptorLength > 0) {
14668
14669 NT_ASSERT(tokenDescriptorLength == sizeof(BLOCK_DEVICE_TOKEN_DESCRIPTOR));
14670
14671 if (tokenDescriptorLength != sizeof(BLOCK_DEVICE_TOKEN_DESCRIPTOR)) {
14672
14673 TracePrint((TRACE_LEVEL_ERROR,
14674 TRACE_FLAG_IOCTL,
14675 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Bad firmware, token descriptor length %u.\n",
14676 fdo,
14677 tokenDescriptorLength));
14678
14679 NT_ASSERT((*totalSectorsProcessed) == 0);
14680 NT_ASSERT(tokenLength == 0);
14681
14682 } else {
14683
14684 USHORT restrictedId;
14685
14686 tokenDescriptor = (PBLOCK_DEVICE_TOKEN_DESCRIPTOR)tokenInformationResultsResponse->TokenDescriptor;
14687
14688 REVERSE_BYTES_SHORT(&restrictedId, &tokenDescriptor->TokenIdentifier);
14689 NT_ASSERT(restrictedId == 0);
14690
14691 tokenLength = BLOCK_DEVICE_TOKEN_SIZE;
14692 token = tokenDescriptor->Token;
14693
14694 *totalSectorsProcessed = transferBlockCount;
14695
14696 if (transferBlockCount < totalSectorsToProcess) {
14697
14699 operationStatus == OPERATION_COMPLETED_WITH_ERROR ||
14700 operationStatus == OPERATION_TERMINATED);
14701
14702 if (transferBlockCount == 0) {
14703 //
14704 // Treat the same as not getting a token.
14705 //
14706
14707 tokenLength = 0;
14708 }
14709
14710 } else {
14711
14712 NT_ASSERT(operationStatus == OPERATION_COMPLETED_WITH_SUCCESS);
14713 NT_ASSERT(transferBlockCount == totalSectorsToProcess);
14714 }
14715
14716 //
14717 // Need to convert to ascii.
14718 //
14719 tokenAscii = ClasspBinaryToAscii((PUCHAR)token,
14720 tokenSize,
14721 &tokenSize);
14722
14723 TracePrint((transferBlockCount == totalSectorsToProcess ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_WARNING,
14724 TRACE_FLAG_IOCTL,
14725 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): %wsToken %s generated successfully for list Id %x for data size %I64u bytes.\n",
14726 fdo,
14727 transferBlockCount == totalSectorsToProcess ? L"" : L"Target truncated read. ",
14728 (tokenAscii == NULL) ? "" : tokenAscii,
14729 listIdentifier,
14730 (*totalSectorsProcessed) * fdoExt->DiskGeometry.BytesPerSector));
14731
14732 FREE_POOL(tokenAscii);
14733 }
14734 } else {
14735
14736 TracePrint((TRACE_LEVEL_ERROR,
14737 TRACE_FLAG_IOCTL,
14738 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Target failed to generate a token for list Id %x for data size %I64u bytes (requested %I64u bytes).\n",
14739 fdo,
14740 listIdentifier,
14741 transferBlockCount * fdoExt->DiskGeometry.BytesPerSector,
14742 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector));
14743
14744 *totalSectorsProcessed = 0;
14745
14746 NT_ASSERT(operationStatus == OPERATION_COMPLETED_WITH_ERROR);
14747 }
14748
14749 //
14750 // Operation that completes with success can have sense data (for target to pass on some extra info)
14751 // but we don't care about such sense info.
14752 // Operation that complete but not with success, may not have sense data associated, but may
14753 // have valid CompletionStatus.
14754 //
14755 // The "status" may be overriden by ClassInterpretSenseInfo(). Final
14756 // status is determined a bit later - this is just the default status
14757 // when ClassInterpretSenseInfo() doesn't get to run here.
14758 //
14760 if (operationStatus == OPERATION_COMPLETED_WITH_ERROR ||
14761 operationStatus == OPERATION_COMPLETED_WITH_RESIDUAL_DATA ||
14762 operationStatus == OPERATION_TERMINATED) {
14763
14764 SrbSetScsiStatus((PSTORAGE_REQUEST_BLOCK_HEADER)srb, completionStatus);
14765
14766 if (senseDataLength) {
14767
14768 ULONG retryInterval;
14769
14770 NT_ASSERT(senseDataLength <= sizeof(SENSE_DATA));
14771
14773
14777
14779 srb,
14781 0,
14782 0,
14783 &status,
14784 &retryInterval);
14785
14786 TracePrint((TRACE_LEVEL_WARNING,
14787 TRACE_FLAG_IOCTL,
14788 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Reason for truncation/failure: %x - for list Id %x for data size %I64u bytes.\n",
14789 fdo,
14790 status,
14791 listIdentifier,
14792 transferBlockCount * fdoExt->DiskGeometry.BytesPerSector));
14793 } else {
14794
14795 TracePrint((TRACE_LEVEL_WARNING,
14796 TRACE_FLAG_IOCTL,
14797 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): No sense data available but reason for truncation/failure, possibly: %x - for list Id %x for data size %I64u bytes.\n",
14798 fdo,
14799 completionStatus,
14800 listIdentifier,
14801 transferBlockCount * fdoExt->DiskGeometry.BytesPerSector));
14802 }
14803 }
14804
14805 if (tokenLength > 0) {
14806
14807 offloadReadContext->Token = token;
14808
14809 //
14810 // Even if target returned an error, from the OS upper layers' perspective,
14811 // it is a success (with truncation) if any data at all was read.
14812 //
14814
14815 } else {
14816
14817 if (NT_SUCCESS(status)) {
14818 //
14819 // Make sure status is a failing status, without throwing away an
14820 // already-failing status obtained from sense data.
14821 //
14823 }
14824 }
14825
14826 //
14827 // Done with the operation.
14828 //
14829
14831 goto __ClasspReceivePopulateTokenInformationTransferPacketDone_Exit;
14832
14833 } else {
14834
14836
14837 TracePrint((TRACE_LEVEL_ERROR,
14838 TRACE_FLAG_IOCTL,
14839 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Token retrieval failed for list Id %x with %x.\n",
14840 fdo,
14841 listIdentifier,
14842 status));
14843
14844 NT_ASSERT(*totalSectorsProcessed == 0);
14845 goto __ClasspReceivePopulateTokenInformationTransferPacketDone_Exit;
14846 }
14847
14848__ClasspReceivePopulateTokenInformationTransferPacketDone_Exit:
14849
14850 if (status != STATUS_PENDING) {
14851
14852 //
14853 // The "status" value can be success or failure at this point, as
14854 // appropriate.
14855 //
14856
14857 ClasspCompleteOffloadRead(offloadReadContext, status);
14858 }
14859
14860 //
14861 // Due to tracing a potentially freed pointer value "Irp", this trace could
14862 // be delayed beyond another offload op picking up the same pointer value
14863 // for its Irp. This function exits after the operation is complete when
14864 // status != STATUS_PENDING.
14865 //
14866
14867 TracePrint((TRACE_LEVEL_VERBOSE,
14868 TRACE_FLAG_IOCTL,
14869 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Exiting function (Irp %p) with internal status %x.\n",
14870 fdo,
14871 irp,
14872 status));
14873
14874 return;
14875}
struct _SENSE_DATA * PSENSE_DATA
FORCEINLINE BOOLEAN ClasspIsTokenOperationComplete(_In_ ULONG CurrentStatus)
Definition: classp.h:2023
BOOLEAN NTAPI ClassInterpretSenseInfo(_In_ PDEVICE_OBJECT Fdo, _In_ PSCSI_REQUEST_BLOCK _Srb, _In_ UCHAR MajorFunctionCode, _In_ ULONG IoDeviceCode, _In_ ULONG RetryCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, 100) ULONG *RetryInterval)
Definition: class.c:4452
struct BLOCK_DEVICE_TOKEN_DESCRIPTOR * PBLOCK_DEVICE_TOKEN_DESCRIPTOR
#define SERVICE_ACTION_POPULATE_TOKEN
Definition: scsi.h:442
struct RECEIVE_TOKEN_INFORMATION_HEADER * PRECEIVE_TOKEN_INFORMATION_HEADER
@ OPERATION_COMPLETED_WITH_SUCCESS
Definition: scsi.h:3652
@ OPERATION_COMPLETED_WITH_ERROR
Definition: scsi.h:3653
@ OPERATION_COMPLETED_WITH_RESIDUAL_DATA
Definition: scsi.h:3654
@ OPERATION_TERMINATED
Definition: scsi.h:3657
struct RECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER * PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER
@ TRANSFER_COUNT_UNITS_NUMBER_BLOCKS
Definition: scsi.h:3668
#define MAX_SENSE_BUFFER_SIZE
Definition: scsi.h:598
UCHAR Token[BLOCK_DEVICE_TOKEN_SIZE]
Definition: scsi.h:3648
UCHAR TokenDescriptor[ANYSIZE_ARRAY]
Definition: scsi.h:3642
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:1098
ULONGLONG TotalSectorsToProcess
Definition: classp.h:1080
ULONGLONG TotalSectorsProcessed
Definition: classp.h:1086

◆ ClasspReceiveWriteUsingTokenInformation()

_IRQL_requires_same_ VOID ClasspReceiveWriteUsingTokenInformation ( _In_ POFFLOAD_WRITE_CONTEXT  OffloadWriteContext)

Definition at line 15937 of file class.c.

15963{
15964 PVOID buffer;
15966 ULONG cdbLength;
15967 PDEVICE_OBJECT fdo;
15968 PIRP irp;
15969 ULONG listIdentifier;
15970 PTRANSFER_PACKET pkt;
15971 PIRP pseudoIrp;
15972 ULONG receiveTokenInformationBufferLength;
15975 ULONG tempSizeUlong;
15976 PMDL writeUsingTokenMdl;
15977
15978 fdo = OffloadWriteContext->Fdo;
15979 irp = OffloadWriteContext->OffloadWriteDsmIrp;
15980 pseudoIrp = &OffloadWriteContext->PseudoIrp;
15981 buffer = OffloadWriteContext + 1;
15982 bufferLength = OffloadWriteContext->BufferLength;
15983 receiveTokenInformationBufferLength = OffloadWriteContext->ReceiveTokenInformationBufferLength;
15984 writeUsingTokenMdl = OffloadWriteContext->WriteUsingTokenMdl;
15985 listIdentifier = OffloadWriteContext->ListIdentifier;
15986 srb = &OffloadWriteContext->Srb;
15988
15989 TracePrint((TRACE_LEVEL_VERBOSE,
15990 TRACE_FLAG_IOCTL,
15991 "ClasspReceiveWriteUsingTokenInformation (%p): Entering function. Irp %p\n",
15992 fdo,
15993 irp));
15994
15995 //
15996 // The WRITE USING TOKEN wasn't immediately fully successful, so that means
15997 // the only way to find out how many sectors were processed by the WRITE
15998 // USING TOKEN is to get a successful RECEIVE ROD TOKEN INFORMATION that
15999 // indicates the operation is complete.
16000 //
16001
16002 NT_ASSERT(OffloadWriteContext->TotalSectorsProcessed == 0);
16003
16004 pkt = DequeueFreeTransferPacket(fdo, TRUE);
16005
16006 if (!pkt) {
16007
16008 TracePrint((TRACE_LEVEL_ERROR,
16009 TRACE_FLAG_IOCTL,
16010 "ClasspReceiveWriteUsingTokenInformation (%p): Failed to retrieve transfer packet for ReceiveTokenInformation (WriteUsingToken) operation.\n",
16011 fdo));
16012
16014
16015 goto __ClasspReceiveWriteUsingTokenInformation_ErrorExit;
16016 }
16017
16019
16020 tempSizeUlong = receiveTokenInformationBufferLength - 4;
16021 REVERSE_BYTES(((PRECEIVE_TOKEN_INFORMATION_HEADER)buffer)->AvailableData, &tempSizeUlong);
16022
16023 RtlZeroMemory(pseudoIrp, sizeof(IRP));
16024
16025 pseudoIrp->IoStatus.Status = STATUS_SUCCESS;
16026 pseudoIrp->IoStatus.Information = 0;
16027 pseudoIrp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
16028 pseudoIrp->MdlAddress = writeUsingTokenMdl;
16029
16030 ClasspSetupReceiveWriteUsingTokenInformationTransferPacket(
16031 OffloadWriteContext,
16032 pkt,
16034 (PUCHAR)buffer,
16035 pseudoIrp,
16036 listIdentifier);
16037
16038 //
16039 // Cache away the CDB as it may be required for forwarded sense data
16040 // after this command completes.
16041 //
16042 RtlZeroMemory(srb, sizeof(*srb));
16043 cdbLength = SrbGetCdbLength(pkt->Srb);
16044 if (cdbLength <= 16) {
16045 RtlCopyMemory(&srb->Cdb, SrbGetCdb(pkt->Srb), cdbLength);
16046 }
16047
16049
16050 return;
16051
16052 //
16053 // Error label only - not used by success cases:
16054 //
16055
16056__ClasspReceiveWriteUsingTokenInformation_ErrorExit:
16057
16059
16060 //
16061 // ClasspCompleteOffloadWrite also cleans up OffloadWriteContext.
16062 //
16063
16064 ClasspCompleteOffloadWrite(OffloadWriteContext, status);
16065
16066 return;
16067}

Referenced by ClasspWriteUsingTokenTransferPacketDone().

◆ ClasspReceiveWriteUsingTokenInformationDone()

VOID ClasspReceiveWriteUsingTokenInformationDone ( _In_ POFFLOAD_WRITE_CONTEXT  OffloadWriteContext,
_In_ NTSTATUS  CompletionCausingStatus 
)

Definition at line 15695 of file class.c.

15727{
15728 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = OffloadWriteContext->Fdo->DeviceExtension;
15729 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
15730
15731 //
15732 // Time taken in 100ns units.
15733 //
15734 ULONGLONG durationIn100ns = (KeQueryInterruptTime() - OffloadWriteContext->OperationStartTime);
15735 ULONGLONG maxTargetDuration = fdoData->CopyOffloadMaxTargetDuration * 10ULL * 1000 * 1000;
15736
15737 NT_ASSERT(
15738 OffloadWriteContext->TotalSectorsProcessedSuccessfully <=
15739 OffloadWriteContext->TotalRequestSizeSectors);
15740
15741
15742 if (OffloadWriteContext->TotalSectorsProcessedSuccessfully == OffloadWriteContext->TotalRequestSizeSectors) {
15743
15744 ClasspCompleteOffloadWrite(OffloadWriteContext, CompletionCausingStatus);
15745
15746 goto __ClasspReceiveWriteUsingTokenInformationDone_Exit;
15747 }
15748
15749 //
15750 // Since we don't want a layered timeout mechanism (e.g. guest and parent OS in Hyper-V scenarios)
15751 // to cause a SCSI timeout for the higher layer token operations.
15752 //
15753 if (maxTargetDuration <= durationIn100ns) {
15754
15755 TracePrint((TRACE_LEVEL_WARNING,
15756 TRACE_FLAG_IOCTL,
15757 "ClasspReceiveWriteUsingTokenInformationDone (%p): Truncating write (list id %x) because of max-duration-rule.\n",
15758 OffloadWriteContext->Fdo,
15759 OffloadWriteContext->ListIdentifier));
15760
15761 //
15762 // We could technically pass in STATUS_IO_OPERATION_TIMEOUT, but ClasspCompleteOffloadWrite
15763 // won't end up doing anything (useful) with this status, since some bytes would already
15764 // have been transferred.
15765 //
15766 ClasspCompleteOffloadWrite(OffloadWriteContext, STATUS_UNSUCCESSFUL);
15767
15768 goto __ClasspReceiveWriteUsingTokenInformationDone_Exit;
15769 }
15770
15771 NT_ASSERT(
15772 OffloadWriteContext->TotalSectorsProcessedSuccessfully <
15773 OffloadWriteContext->TotalRequestSizeSectors);
15774
15775 //
15776 // Keep going with the next sub-request.
15777 //
15778
15779 ClasspContinueOffloadWrite(OffloadWriteContext);
15780
15781__ClasspReceiveWriteUsingTokenInformationDone_Exit:
15782
15783 return;
15784}
VOID ClasspContinueOffloadWrite(_In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
Definition: class.c:15187
#define KeQueryInterruptTime()
Definition: ke.h:37
ULONG CopyOffloadMaxTargetDuration
Definition: classp.h:665

Referenced by ClasspReceiveWriteUsingTokenInformationTransferPacketDone(), and ClasspWriteUsingTokenTransferPacketDone().

◆ ClasspReceiveWriteUsingTokenInformationTransferPacketDone()

VOID ClasspReceiveWriteUsingTokenInformationTransferPacketDone ( _In_ POFFLOAD_WRITE_CONTEXT  OffloadWriteContext)

Definition at line 16071 of file class.c.

16100{
16101 ULONG availableData;
16102 PVOID buffer;
16103 UCHAR completionStatus;
16104 ULONG estimatedRetryInterval;
16105 PDEVICE_OBJECT fdo;
16107 PIRP irp;
16108 ULONG listIdentifier;
16109 BOOLEAN operationCompleted;
16110 UCHAR operationStatus;
16111 PIRP pseudoIrp;
16112 USHORT segmentsProcessed;
16113 PSENSE_DATA senseData;
16114 ULONG senseDataFieldLength;
16115 UCHAR senseDataLength;
16118 ULONG tokenDescriptorLength;
16119 PRECEIVE_TOKEN_INFORMATION_HEADER tokenInformationResults;
16120 PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER tokenInformationResponsePadding;
16121 PBOOLEAN tokenInvalidated;
16122 PULONGLONG totalSectorsProcessed;
16123 ULONGLONG totalSectorsToProcess;
16124 ULONGLONG transferBlockCount;
16125
16126 fdo = OffloadWriteContext->Fdo;
16127 fdoExt = fdo->DeviceExtension;
16128 listIdentifier = OffloadWriteContext->ListIdentifier;
16129 totalSectorsProcessed = &OffloadWriteContext->TotalSectorsProcessed;
16130 totalSectorsToProcess = OffloadWriteContext->TotalSectorsToProcess;
16131 irp = OffloadWriteContext->OffloadWriteDsmIrp;
16132 pseudoIrp = &OffloadWriteContext->PseudoIrp;
16133 tokenInvalidated = &OffloadWriteContext->TokenInvalidated;
16134 srb = &OffloadWriteContext->Srb;
16135 operationCompleted = FALSE;
16136 buffer = OffloadWriteContext + 1;
16137 tokenInformationResults = (PRECEIVE_TOKEN_INFORMATION_HEADER)buffer;
16138 senseData = (PSENSE_DATA)((PUCHAR)tokenInformationResults + FIELD_OFFSET(RECEIVE_TOKEN_INFORMATION_HEADER, SenseData));
16139 transferBlockCount = 0;
16140 tokenInformationResponsePadding = NULL;
16141 tokenDescriptorLength = 0;
16142
16143 NT_ASSERT((*totalSectorsProcessed) == 0);
16144
16145 OffloadWriteContext->Pkt = NULL;
16146
16147
16148 status = pseudoIrp->IoStatus.Status;
16150
16151 //
16152 // The buffer we hand allows for the max sizes for all the fields whereas the returned
16153 // data may be lesser (e.g. sense data info will almost never be MAX_SENSE_BUFFER_SIZE, etc.
16154 // so handle underrun "error"
16155 //
16156 if (status == STATUS_DATA_OVERRUN) {
16157
16159 }
16160
16161 if (!NT_SUCCESS(status)) {
16162 TracePrint((TRACE_LEVEL_ERROR,
16163 TRACE_FLAG_IOCTL,
16164 "ClasspReceiveWriteUsingTokenInformationTransferPacketDone (%p): Failed with %x to retrieve write results for list Id %x for data size %I64u bytes.\n",
16165 fdo,
16166 status,
16167 listIdentifier,
16168 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector));
16169
16170 NT_ASSERT((*totalSectorsProcessed) == 0);
16171
16172 goto __ClasspReceiveWriteUsingTokenInformationTransferPacketDone_ErrorExit;
16173 }
16174
16175 REVERSE_BYTES(&availableData, &tokenInformationResults->AvailableData);
16176
16178
16180
16181 operationStatus = tokenInformationResults->OperationStatus;
16182 operationCompleted = ClasspIsTokenOperationComplete(operationStatus);
16183 NT_ASSERT(operationCompleted);
16184
16185 REVERSE_BYTES(&estimatedRetryInterval, &tokenInformationResults->EstimatedStatusUpdateDelay);
16186
16187 completionStatus = tokenInformationResults->CompletionStatus;
16188
16189 senseDataFieldLength = tokenInformationResults->SenseDataFieldLength;
16190 senseDataLength = tokenInformationResults->SenseDataLength;
16191 NT_ASSERT(senseDataFieldLength >= senseDataLength);
16192
16193 tokenInformationResponsePadding = (PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER)((PUCHAR)tokenInformationResults +
16195 tokenInformationResults->SenseDataFieldLength);
16196
16197 REVERSE_BYTES(&tokenDescriptorLength, &tokenInformationResponsePadding->TokenDescriptorsLength);
16198 NT_ASSERT(tokenDescriptorLength == 0);
16199
16201 REVERSE_BYTES_QUAD(&transferBlockCount, &tokenInformationResults->TransferCount);
16202
16203 REVERSE_BYTES_SHORT(&segmentsProcessed, &tokenInformationResults->SegmentsProcessed);
16204 NT_ASSERT(segmentsProcessed == 0);
16205
16206 if (operationCompleted) {
16207
16208 if (transferBlockCount > totalSectorsToProcess) {
16209
16210 //
16211 // Buggy or hostile target. Don't let it claim more was procesed
16212 // than was requested. Since this is likely a bug and it's unknown
16213 // how much was actually transferred, assume no data was
16214 // transferred.
16215 //
16216
16217 NT_ASSERT(transferBlockCount <= totalSectorsToProcess);
16218 transferBlockCount = 0;
16219 }
16220
16221 if (operationStatus != OPERATION_COMPLETED_WITH_SUCCESS &&
16222 operationStatus != OPERATION_COMPLETED_WITH_RESIDUAL_DATA) {
16223
16224 //
16225 // Assert on buggy response from target, but in any case, make sure not
16226 // to claim that any data was written.
16227 //
16228
16229 NT_ASSERT(transferBlockCount == 0);
16230 transferBlockCount = 0;
16231 }
16232
16233 //
16234 // Since the TokenOperation was sent down synchronously but failed, the operation is complete as soon as the
16235 // ReceiveTokenInformation command returns.
16236 //
16237
16238 NT_ASSERT((*totalSectorsProcessed) == 0);
16239 *totalSectorsProcessed = transferBlockCount;
16240 ClasspAdvanceOffloadWritePosition(OffloadWriteContext, transferBlockCount);
16241
16242 if (transferBlockCount < totalSectorsToProcess) {
16243
16245 operationStatus == OPERATION_COMPLETED_WITH_ERROR ||
16246 operationStatus == OPERATION_TERMINATED);
16247
16248 } else {
16249
16250 NT_ASSERT(operationStatus == OPERATION_COMPLETED_WITH_SUCCESS);
16251 }
16252
16253 TracePrint((transferBlockCount == totalSectorsToProcess ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_WARNING,
16254 TRACE_FLAG_IOCTL,
16255 "ClasspReceiveWriteUsingTokenInformationTransferPacketDone (%p): %wsSuccessfully wrote (for list Id %x) for data size %I64u bytes\n",
16256 fdo,
16257 transferBlockCount == totalSectorsToProcess ? L"" : L"Target truncated write. ",
16258 listIdentifier,
16259 (*totalSectorsProcessed) * fdoExt->DiskGeometry.BytesPerSector));
16260
16261 //
16262 // Operation that completes with success can have sense data (for target to pass on some extra info)
16263 // but we don't care about such sense info.
16264 // Operation that complete but not with success, may not have sense data associated, but may
16265 // have valid CompletionStatus.
16266 //
16267 // The "status" may be overriden by ClassInterpretSenseInfo(). Final
16268 // status is determined a bit later - this is just the default status
16269 // when ClassInterpretSenseInfo() doesn't get to run here.
16270 //
16272 if (operationStatus == OPERATION_COMPLETED_WITH_ERROR ||
16273 operationStatus == OPERATION_COMPLETED_WITH_RESIDUAL_DATA ||
16274 operationStatus == OPERATION_TERMINATED) {
16275
16276 SrbSetScsiStatus((PSTORAGE_REQUEST_BLOCK_HEADER)srb, completionStatus);
16277
16278 if (senseDataLength) {
16279
16280 ULONG retryInterval;
16281
16282 NT_ASSERT(senseDataLength <= sizeof(SENSE_DATA));
16283
16285
16289
16291 srb,
16293 0,
16294 0,
16295 &status,
16296 &retryInterval);
16297
16298 TracePrint((TRACE_LEVEL_WARNING,
16299 TRACE_FLAG_IOCTL,
16300 "ClasspReceiveWriteUsingTokenInformationTransferPacketDone (%p): Reason for truncation/failure: %x - for list Id %x for data size %I64u bytes.\n",
16301 fdo,
16302 status,
16303 listIdentifier,
16304 transferBlockCount * fdoExt->DiskGeometry.BytesPerSector));
16305
16306 //
16307 // If the token isn't valid any longer, we should let the upper layers know so that
16308 // they don't waste time retrying the write with the same token.
16309 //
16311
16312 *tokenInvalidated = TRUE;
16313 }
16314 } else {
16315
16316 TracePrint((TRACE_LEVEL_WARNING,
16317 TRACE_FLAG_IOCTL,
16318 "ClasspReceiveWriteUsingTokenInformationTransferPacketDone (%p): No sense data available but reason for truncation/failure, possibly: %x - for list Id %x for data size %I64u bytes.\n",
16319 fdo,
16320 completionStatus,
16321 listIdentifier,
16322 transferBlockCount * fdoExt->DiskGeometry.BytesPerSector));
16323 }
16324 }
16325
16326 //
16327 // Initialize status. Upper layer needs to know if command failed because it
16328 // timed out without doing any writing. ClasspCompleteOffloadWrite() will
16329 // force status to success if any data was written, so it's this function's
16330 // job to set the status appropriately based on the outcome of this
16331 // WRITE USING TOKEN command, and then ClasspCompleteOffloadWrite()
16332 // can override with success if previos WRITE USING TOKEN commands
16333 // issued for the same upper request were able to write some data.
16334 //
16335 if (transferBlockCount != 0) {
16337 } else {
16338
16339 if (NT_SUCCESS(status)) {
16340 //
16341 // Make sure status is a failing status, without throwing away an
16342 // already-failing status obtained from sense data.
16343 //
16345 }
16346 }
16347
16349
16350 if (!NT_SUCCESS(status)) {
16351 goto __ClasspReceiveWriteUsingTokenInformationTransferPacketDone_ErrorExit;
16352 }
16353
16356 goto __ClasspReceiveWriteUsingTokenInformationTransferPacketDone_Exit;
16357
16358 } else {
16359
16361
16362 goto __ClasspReceiveWriteUsingTokenInformationTransferPacketDone_ErrorExit;
16363 }
16364
16365 //
16366 // Error label only - not used in success case:
16367 //
16368
16369__ClasspReceiveWriteUsingTokenInformationTransferPacketDone_ErrorExit:
16370
16372
16373 ClasspCompleteOffloadWrite(OffloadWriteContext, status);
16374
16375__ClasspReceiveWriteUsingTokenInformationTransferPacketDone_Exit:
16376
16377 //
16378 // Due to tracing a potentially freed pointer value "Irp", this trace could
16379 // be delayed beyond another offload op picking up the same pointer value
16380 // for its Irp.
16381 //
16382
16383 TracePrint((TRACE_LEVEL_VERBOSE,
16384 TRACE_FLAG_IOCTL,
16385 "ClasspReceiveWriteUsingTokenInformationTransferPacketDone (%p): Exiting function (Irp %p) with status %x.\n",
16386 fdo,
16387 irp,
16388 status));
16389
16390 return;
16391}
VOID ClasspAdvanceOffloadWritePosition(_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ ULONGLONG SectorsToAdvance)
Definition: class.c:15445
VOID ClasspReceiveWriteUsingTokenInformationDone(_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ NTSTATUS CompletionCausingStatus)
Definition: class.c:15695
#define SERVICE_ACTION_WRITE_USING_TOKEN
Definition: scsi.h:443

◆ ClasspRefreshFunctionSupportInfo()

NTSTATUS ClasspRefreshFunctionSupportInfo ( _Inout_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
_In_ BOOLEAN  ForceQuery 
)

Definition at line 16395 of file class.c.

16420{
16423 ULONG srbSize;
16424 CLASS_VPD_B0_DATA blockLimitsDataNew;
16425 PCLASS_VPD_B0_DATA blockLimitsDataOriginal;
16426 KLOCK_QUEUE_HANDLE lockHandle;
16427 ULONG generationCount;
16428 ULONG changeRequestCount;
16429
16430 //
16431 // ChangeRequestCount is incremented every time we get an unit attention with
16432 // SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED. GenerationCount will be set to
16433 // ChangeRequestCount after CLASS_FUNCTION_SUPPORT_INFO is refreshed with the latest
16434 // VPD data. i.e. if both values are the same, data in
16435 // CLASS_FUNCTION_SUPPORT_INFO is current
16436 //
16437
16438 generationCount = FdoExtension->FunctionSupportInfo->GenerationCount;
16439 changeRequestCount = FdoExtension->FunctionSupportInfo->ChangeRequestCount;
16440 if (!ForceQuery && generationCount == changeRequestCount) {
16441 return STATUS_SUCCESS;
16442 }
16443
16444 //
16445 // Allocate an SRB for querying the device for LBP-related info if either
16446 // the Logical Block Provisioning (0xB2) or Block Limits (0xB0) VPD page
16447 // exists.
16448 //
16449 if ((FdoExtension->AdapterDescriptor != NULL) &&
16450 (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
16452 } else {
16453 srbSize = sizeof(SCSI_REQUEST_BLOCK);
16454 }
16455
16456 srb = ExAllocatePoolWithTag(NonPagedPoolNx, srbSize, '1DcS');
16457 if (srb == NULL) {
16459 }
16460
16462 srb,
16463 srbSize,
16464 &blockLimitsDataNew);
16465
16466 if (NT_SUCCESS(status)) {
16467
16468 KeAcquireInStackQueuedSpinLock(&FdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
16469
16470 //
16471 // If the generationCount didn't change since we looked at it last time, it means
16472 // no one has tried to update the CLASS_FUNCTION_SUPPORT_INFO data; otherwise, someone
16473 // else has beat us to it.
16474 //
16475 if (generationCount == FdoExtension->FunctionSupportInfo->GenerationCount) {
16476
16477 blockLimitsDataOriginal = &FdoExtension->FunctionSupportInfo->BlockLimitsData;
16478 if (blockLimitsDataOriginal->CommandStatus == -1) {
16479 //
16480 // CommandStatus == -1 means this is the first time we have
16481 // gotten the block limits data.
16482 //
16483 *blockLimitsDataOriginal = blockLimitsDataNew;
16484 } else {
16485 //
16486 // We only expect the Optimal Unmap Granularity (and alignment)
16487 // to change, so those are the only parameters we update.
16488 //
16489 blockLimitsDataOriginal->UGAVALID = blockLimitsDataNew.UGAVALID;
16490 blockLimitsDataOriginal->UnmapGranularityAlignment = blockLimitsDataNew.UnmapGranularityAlignment;
16491 blockLimitsDataOriginal->OptimalUnmapGranularity = blockLimitsDataNew.OptimalUnmapGranularity;
16492 }
16493 FdoExtension->FunctionSupportInfo->GenerationCount = changeRequestCount;
16494 }
16495
16496 KeReleaseInStackQueuedSpinLock(&lockHandle);
16497 }
16498
16499 FREE_POOL(srb);
16500 return status;
16501}
BOOLEAN UGAVALID
Definition: classpnp.h:754
ULONG UnmapGranularityAlignment
Definition: classpnp.h:753
ULONG OptimalUnmapGranularity
Definition: classpnp.h:752
NTSTATUS CommandStatus
Definition: classpnp.h:749

Referenced by ClasspBlockLimitsDataSnapshot().

◆ ClasspRegisterMountedDeviceInterface()

VOID ClasspRegisterMountedDeviceInterface ( IN PDEVICE_OBJECT  DeviceObject)

Definition at line 10970 of file class.c.

10973{
10974
10975 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
10976 BOOLEAN isFdo = commonExtension->IsFdo;
10977 PDEVICE_OBJECT pdo;
10978 UNICODE_STRING interfaceName;
10979
10981
10982 PAGED_CODE();
10983
10984 if(isFdo) {
10985
10986 PFUNCTIONAL_DEVICE_EXTENSION functionalExtension;
10987
10988 functionalExtension =
10989 (PFUNCTIONAL_DEVICE_EXTENSION) commonExtension;
10990 pdo = functionalExtension->LowerPdo;
10991 } else {
10992 pdo = DeviceObject;
10993 }
10994
10995#ifdef _MSC_VER
10996#pragma prefast(suppress:6014, "The allocated memory that interfaceName points to will be freed in ClassRemoveDevice().")
10997#endif
10999 pdo,
11000 &MOUNTDEV_MOUNTED_DEVICE_GUID,
11001 NULL,
11002 &interfaceName
11003 );
11004
11005 if(NT_SUCCESS(status)) {
11006
11007 //
11008 // Copy the interface name before setting the interface state - the
11009 // name is needed by the components we notify.
11010 //
11011
11012 commonExtension->MountedDeviceInterfaceName = interfaceName;
11013 status = IoSetDeviceInterfaceState(&interfaceName, TRUE);
11014
11015 if(!NT_SUCCESS(status)) {
11016 RtlFreeUnicodeString(&interfaceName);
11017 }
11018 }
11019
11020 if(!NT_SUCCESS(status)) {
11022 NULL);
11023 }
11024 return;
11025} // end ClasspRegisterMountedDeviceInterface()
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
Definition: deviface.c:955
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1311

◆ ClasspReleaseQueue()

VOID ClasspReleaseQueue ( IN PDEVICE_OBJECT  Fdo,
IN PIRP ReleaseQueueIrp  OPTIONAL 
)

Definition at line 11743 of file class.c.

11747{
11748 PIO_STACK_LOCATION irpStack;
11749 PIRP irp;
11750 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
11751 PDEVICE_OBJECT lowerDevice;
11753 KIRQL currentIrql;
11754 ULONG function;
11755
11756 lowerDevice = fdoExtension->CommonExtension.LowerDeviceObject;
11757
11758 //
11759 // we raise irql seperately so we're not swapped out or suspended
11760 // while holding the release queue irp in this routine. this lets
11761 // us release the spin lock before lowering irql.
11762 //
11763
11764 KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
11765
11767
11768 //
11769 // make sure that if they passed us an irp, it matches our allocated irp.
11770 //
11771
11772 NT_ASSERT((ReleaseQueueIrp == NULL) ||
11773 (ReleaseQueueIrp == fdoExtension->PrivateFdoData->ReleaseQueueIrp));
11774
11775 //
11776 // ASSERT that we've already allocated this. (should not occur)
11777 // try to allocate it anyways, then finally bugcheck if
11778 // there's still no memory...
11779 //
11780
11781 NT_ASSERT(fdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated);
11782 if (!fdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated) {
11783 ClasspAllocateReleaseQueueIrp(fdoExtension);
11784 }
11785 if (!fdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated) {
11786 KeBugCheckEx(SCSI_DISK_DRIVER_INTERNAL, 0x12, (ULONG_PTR)Fdo, 0x0, 0x0);
11787 }
11788
11789 if ((fdoExtension->ReleaseQueueInProgress) && (ReleaseQueueIrp == NULL)) {
11790
11791 //
11792 // Someone is already using the irp - just set the flag to indicate that
11793 // we need to release the queue again.
11794 //
11795
11796 fdoExtension->ReleaseQueueNeeded = TRUE;
11798 KeLowerIrql(currentIrql);
11799 return;
11800
11801 }
11802
11803 //
11804 // Mark that there is a release queue in progress and drop the spinlock.
11805 //
11806
11807 fdoExtension->ReleaseQueueInProgress = TRUE;
11808 if (ReleaseQueueIrp) {
11809 irp = ReleaseQueueIrp;
11810 } else {
11811 irp = fdoExtension->PrivateFdoData->ReleaseQueueIrp;
11812 }
11813
11814 if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
11815 srb = (PSTORAGE_REQUEST_BLOCK_HEADER)&(fdoExtension->PrivateFdoData->ReleaseQueueSrb.SrbEx);
11816 } else {
11817 srb = (PSTORAGE_REQUEST_BLOCK_HEADER)&(fdoExtension->ReleaseQueueSrb);
11818 }
11819
11821
11822 NT_ASSERT(irp != NULL);
11823
11824 irpStack = IoGetNextIrpStackLocation(irp);
11825
11826 irpStack->MajorFunction = IRP_MJ_SCSI;
11827
11829
11830 //
11831 // Store the SRB address in next stack for port driver.
11832 //
11833
11834 irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srb;
11835
11836 //
11837 // If this device is removable then flush the queue. This will also
11838 // release it.
11839 //
11840
11841 if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)){
11842 function = SRB_FUNCTION_FLUSH_QUEUE;
11843 }
11844 else {
11845 function = SRB_FUNCTION_RELEASE_QUEUE;
11846 }
11847
11848 if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
11849 ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFunction = function;
11850 } else {
11851 srb->Function = (UCHAR)function;
11852 }
11853
11855
11858 Fdo,
11859 TRUE,
11860 TRUE,
11861 TRUE);
11862
11863 IoCallDriver(lowerDevice, irp);
11864
11865 KeLowerIrql(currentIrql);
11866
11867 return;
11868
11869} // end ClassReleaseQueue()
IO_COMPLETION_ROUTINE ClassReleaseQueueCompletion
Definition: classp.h:1586
#define SRB_FUNCTION_RELEASE_QUEUE
Definition: srb.h:319
#define SRB_FUNCTION_FLUSH_QUEUE
Definition: srb.h:329
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135

Referenced by ClassReleaseQueue(), and ClassReleaseQueueCompletion().

◆ ClasspRetryDpcTimer()

VOID ClasspRetryDpcTimer ( IN PCLASS_PRIVATE_FDO_DATA  FdoData)

Definition at line 12457 of file class.c.

12460{
12461 LARGE_INTEGER fire;
12462
12463 NT_ASSERT(FdoData->Retry.Tick.QuadPart != (LONGLONG)0);
12464 NT_ASSERT(FdoData->Retry.ListHead != NULL); // never fire an empty list
12465
12466 //
12467 // fire == (CurrentTick - now) * (100ns per tick)
12468 //
12469 // NOTE: Overflow is nearly impossible and is ignored here
12470 //
12471
12472 KeQueryTickCount(&fire);
12473 fire.QuadPart = FdoData->Retry.Tick.QuadPart - fire.QuadPart;
12474 fire.QuadPart *= FdoData->Retry.Granularity;
12475
12476 //
12477 // fire is now multiples of 100ns until should fire the timer.
12478 // if timer should already have expired, or would fire too quickly,
12479 // fire it in some arbitrary number of ticks to prevent infinitely
12480 // recursing.
12481 //
12482
12483 if (fire.QuadPart < MINIMUM_RETRY_UNITS) {
12485 }
12486
12487 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
12488 "ClassRetry: ======= %I64x ticks\n",
12489 fire.QuadPart));
12490
12491 //
12492 // must use negative to specify relative time to fire
12493 //
12494
12495 fire.QuadPart = fire.QuadPart * ((LONGLONG)-1);
12496
12497 //
12498 // set the timer, since this is the first addition
12499 //
12500
12501 KeSetTimerEx(&FdoData->Retry.Timer, fire, 0, &FdoData->Retry.Dpc);
12502
12503 return;
12504} // end ClasspRetryDpcTimer()
#define MINIMUM_RETRY_UNITS
Definition: classp.h:1195
BOOLEAN NTAPI KeSetTimerEx(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN LONG Period, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:294

Referenced by ClasspRetryRequestDpc(), and ClassRetryRequest().

◆ ClasspRetryRequestDpc()

VOID NTAPI ClasspRetryRequestDpc ( IN PKDPC  Dpc,
IN PVOID  DeferredContext,
IN PVOID  Arg1,
IN PVOID  Arg2 
)

Definition at line 12194 of file class.c.

12200{
12201 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
12202 PCOMMON_DEVICE_EXTENSION commonExtension;
12204 PCLASS_RETRY_INFO retryList;
12205 KIRQL irql;
12207
12211
12212 if (DeferredContext == NULL) {
12214 return;
12215 }
12216
12217 commonExtension = DeviceObject->DeviceExtension;
12218 NT_ASSERT(commonExtension->IsFdo);
12219 fdoExtension = DeviceObject->DeviceExtension;
12220 fdoData = fdoExtension->PrivateFdoData;
12221
12222
12223 KeAcquireSpinLock(&fdoData->Retry.Lock, &irql);
12224 {
12227
12228 //
12229 // if CurrentTick is less than now
12230 // fire another DPC
12231 // else
12232 // retry entire list
12233 // endif
12234 //
12235
12236 if (now.QuadPart < fdoData->Retry.Tick.QuadPart) {
12237
12238 ClasspRetryDpcTimer(fdoData);
12239 retryList = NULL;
12240
12241 } else {
12242
12243 retryList = fdoData->Retry.ListHead;
12244 fdoData->Retry.ListHead = NULL;
12245 fdoData->Retry.Delta.QuadPart = (LONGLONG)0;
12246 fdoData->Retry.Tick.QuadPart = (LONGLONG)0;
12247
12248 }
12249 }
12250 KeReleaseSpinLock(&fdoData->Retry.Lock, irql);
12251
12252 while (retryList != NULL) {
12253
12254 PIRP irp;
12255
12256
12257 irp = CONTAINING_RECORD(retryList, IRP, Tail.Overlay.DriverContext[0]);
12258 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassRetry: -- %p\n", irp));
12259 retryList = retryList->Next;
12260 #if DBG
12261 irp->Tail.Overlay.DriverContext[0] = ULongToPtr(0xdddddddd); // invalidate data
12262 irp->Tail.Overlay.DriverContext[1] = ULongToPtr(0xdddddddd); // invalidate data
12263 irp->Tail.Overlay.DriverContext[2] = ULongToPtr(0xdddddddd); // invalidate data
12264 irp->Tail.Overlay.DriverContext[3] = ULongToPtr(0xdddddddd); // invalidate data
12265 #endif
12266
12267
12268 if (NO_REMOVE == InterlockedCompareExchange((volatile LONG *)&commonExtension->IsRemoved, REMOVE_PENDING, REMOVE_PENDING)) {
12269
12270 IoCallDriver(commonExtension->LowerDeviceObject, irp);
12271
12272 } else {
12273
12274 PIO_STACK_LOCATION irpStack;
12275
12276 //
12277 // Ensure that we don't skip a completion routine (equivalent of sending down a request
12278 // to a device after it has received a remove and it completes the request. We need to
12279 // mimic that behavior here).
12280 //
12282
12284
12285 if (irpStack->MajorFunction == IRP_MJ_SCSI) {
12286
12287 PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
12288
12289 if (srb) {
12291 }
12292 }
12293
12294 //
12295 // Ensure that no retries will take place. This takes care of requests that are either
12296 // not IRP_MJ_SCSI or for ones where the SRB was passed in to the completion routine
12297 // as a context as opposed to an argument on the IRP stack location.
12298 //
12299 irpStack->Parameters.Others.Argument4 = (PVOID)0;
12300
12301 irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
12302 irp->IoStatus.Information = 0;
12304 }
12305
12306 }
12307 return;
12308
12309} // end ClasspRetryRequestDpc()
#define ULongToPtr(ul)
Definition: basetsd.h:92
KIRQL irql
Definition: wave.h:1
VOID ClasspRetryDpcTimer(IN PCLASS_PRIVATE_FDO_DATA FdoData)
Definition: class.c:12457
struct _DEVICE_OBJECT * PDEVICE_OBJECT
time_t now
Definition: finger.c:65
struct _CLASS_PRIVATE_FDO_DATA::@1053 Retry
struct _CLASS_RETRY_INFO * Next
Definition: classp.h:408
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687

◆ ClasspScanForClassHacks()

VOID NTAPI ClasspScanForClassHacks ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN ULONG_PTR  Data 
)

Definition at line 12634 of file class.c.

12638{
12639 PAGED_CODE();
12640
12641 //
12642 // remove invalid flags and save
12643 //
12644
12646 SET_FLAG(FdoExtension->PrivateFdoData->HackFlags, Data);
12647 return;
12648}
#define FDO_HACK_INVALID_FLAGS
Definition: cdromp.h:141

Referenced by ClassPnpStartDevice().

◆ ClasspScanForSpecialInRegistry()

VOID ClasspScanForSpecialInRegistry ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 12651 of file class.c.

12654{
12655 HANDLE deviceParameterHandle; // device instance key
12656 HANDLE classParameterHandle; // classpnp subkey
12657 OBJECT_ATTRIBUTES objectAttributes = {0};
12658 UNICODE_STRING subkeyName;
12660
12661 //
12662 // seeded in the ENUM tree by ClassInstaller
12663 //
12664 ULONG deviceHacks;
12665 RTL_QUERY_REGISTRY_TABLE queryTable[2] = {0}; // null terminated array
12666
12667 PAGED_CODE();
12668
12669 deviceParameterHandle = NULL;
12670 classParameterHandle = NULL;
12671 deviceHacks = 0;
12672
12675 KEY_WRITE,
12676 &deviceParameterHandle
12677 );
12678
12679 if (!NT_SUCCESS(status)) {
12680 goto cleanupScanForSpecial;
12681 }
12682
12684 InitializeObjectAttributes(&objectAttributes,
12685 &subkeyName,
12687 deviceParameterHandle,
12688 NULL
12689 );
12690
12691 status = ZwOpenKey( &classParameterHandle,
12692 KEY_READ,
12693 &objectAttributes
12694 );
12695
12696 if (!NT_SUCCESS(status)) {
12697 goto cleanupScanForSpecial;
12698 }
12699
12700 //
12701 // Setup the structure to read
12702 //
12703
12705 queryTable[0].Name = CLASSP_REG_HACK_VALUE_NAME;
12706 queryTable[0].EntryContext = &deviceHacks;
12708 queryTable[0].DefaultData = &deviceHacks;
12709 queryTable[0].DefaultLength = 0;
12710
12711 //
12712 // read values
12713 //
12714
12716 (PWSTR)classParameterHandle,
12717 &queryTable[0],
12718 NULL,
12719 NULL
12720 );
12721 if (!NT_SUCCESS(status)) {
12722 goto cleanupScanForSpecial;
12723 }
12724
12725 //
12726 // remove unknown values and save...
12727 //
12728
12729 CLEAR_FLAG(deviceHacks, FDO_HACK_INVALID_FLAGS);
12730 SET_FLAG(FdoExtension->PrivateFdoData->HackFlags, deviceHacks);
12731
12732
12733cleanupScanForSpecial:
12734
12735 if (deviceParameterHandle) {
12736 ZwClose(deviceParameterHandle);
12737 }
12738
12739 if (classParameterHandle) {
12740 ZwClose(classParameterHandle);
12741 }
12742
12743 //
12744 // we should modify the system hive to include another key for us to grab
12745 // settings from. in this case: Classpnp\HackFlags
12746 //
12747 // the use of a DWORD value for the HackFlags allows 32 hacks w/o
12748 // significant use of the registry, and also reduces OEM exposure.
12749 //
12750 // definition of bit flags:
12751 // 0x00000001 -- Device succeeds PREVENT_MEDIUM_REMOVAL, but
12752 // cannot actually prevent removal.
12753 // 0x00000002 -- Device hard-hangs or times out for GESN requests.
12754 // 0xfffffffc -- Currently reserved, may be used later.
12755 //
12756
12757 return;
12758}
#define CLASSP_REG_HACK_VALUE_NAME
Definition: cdromp.h:122
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define KEY_READ
Definition: nt_native.h:1023
#define KEY_WRITE
Definition: nt_native.h:1031
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
NTSTATUS NTAPI IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject, IN ULONG DevInstKeyType, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DevInstRegKey)
Definition: pnpmgr.c:1621
#define REG_DWORD
Definition: sdbapi.c:596
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2786

Referenced by ClassPnpStartDevice().

◆ ClasspSendSynchronousCompletion()

NTSTATUS NTAPI ClasspSendSynchronousCompletion ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context 
)

Definition at line 10925 of file class.c.

10930{
10931 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClasspSendSynchronousCompletion: %p %p %p\n",
10933 //
10934 // First set the status and information fields in the io status block
10935 // provided by the caller.
10936 //
10937
10938 *(Irp->UserIosb) = Irp->IoStatus;
10939
10940 //
10941 // Unlock the pages for the data buffer.
10942 //
10943
10944 if(Irp->MdlAddress) {
10945 MmUnlockPages(Irp->MdlAddress);
10946 IoFreeMdl(Irp->MdlAddress);
10947 }
10948
10949 //
10950 // Signal the caller's event.
10951 //
10952
10953 KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE);
10954
10955 //
10956 // Free the MDL and the IRP.
10957 //
10958
10959 IoFreeIrp(Irp);
10960
10962} // end ClasspSendSynchronousCompletion()

◆ ClasspStartIo()

VOID NTAPI ClasspStartIo ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 10663 of file class.c.

10667{
10668 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
10669
10670 //
10671 // We're already holding the remove lock so just check the variable and
10672 // see what's going on.
10673 //
10674
10675 if(commonExtension->IsRemoved) {
10676
10677 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
10678
10679#ifdef _MSC_VER
10680#pragma warning(suppress:4054) // okay to type cast function pointer to PIRP for this use case
10681#endif
10683
10686 IoStartNextPacket(DeviceObject, TRUE); // Some IO is cancellable
10687
10688#ifdef _MSC_VER
10689#pragma warning(suppress:4054) // okay to type cast function pointer to PIRP for this use case
10690#endif
10692
10693 return;
10694 }
10695
10696 commonExtension->DriverExtension->InitData.ClassStartIo(
10698 Irp);
10699
10700 return;
10701} // ClasspStartIo()

◆ ClasspUpdateDiskProperties()

VOID NTAPI ClasspUpdateDiskProperties ( IN PDEVICE_OBJECT  Fdo,
IN PVOID  Context 
)

Definition at line 12781 of file class.c.

12785{
12786 PDEVICE_OBJECT topOfStack;
12787 IO_STATUS_BLOCK ioStatus;
12789 KEVENT event;
12790 PIRP irp = NULL;
12791 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
12792 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
12794
12796
12797 topOfStack = IoGetAttachedDeviceReference(Fdo);
12798
12799 //
12800 // Send down irp to update properties
12801 //
12802
12805 topOfStack,
12806 NULL,
12807 0,
12808 NULL,
12809 0,
12810 FALSE,
12811 &event,
12812 &ioStatus);
12813
12814 if (irp != NULL) {
12815
12816
12817 status = IoCallDriver(topOfStack, irp);
12818 if (status == STATUS_PENDING) {
12820 status = ioStatus.Status;
12821 }
12822
12823 } else {
12825 }
12826
12828
12829 if (!NT_SUCCESS(status)) {
12830 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClasspUpdateDiskProperties: Disk property update for fdo %p failed with status 0x%X.\n", Fdo, status));
12831 } else {
12832 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspUpdateDiskProperties: Drive capacity has changed for %p.\n", Fdo));
12833 }
12834 ObDereferenceObject(topOfStack);
12835
12836 if (WorkItem != NULL) {
12838 }
12839
12840 return;
12841}
#define InterlockedExchange
Definition: armddk.h:54
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
#define IOCTL_DISK_UPDATE_PROPERTIES
Definition: ntdddisk.h:242
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
ULONG UpdateDiskPropertiesWorkItemActive
Definition: classp.h:704
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
struct _IO_WORKITEM * PIO_WORKITEM
Definition: iotypes.h:506
#define ObDereferenceObject
Definition: obfuncs.h:203

◆ ClasspWriteUsingTokenTransferPacketDone()

VOID ClasspWriteUsingTokenTransferPacketDone ( _In_ PVOID  Context)

Definition at line 15519 of file class.c.

15549{
15550 ULONGLONG entireXferLen;
15551 PDEVICE_OBJECT fdo;
15553 ULONG listIdentifier;
15554 POFFLOAD_WRITE_CONTEXT offloadWriteContext;
15555 PTRANSFER_PACKET pkt;
15556 PIRP pseudoIrp;
15558 PBOOLEAN tokenInvalidated;
15559 ULONGLONG totalSectorsToProcess;
15560
15561 offloadWriteContext = Context;
15562 pseudoIrp = &offloadWriteContext->PseudoIrp;
15563 fdo = offloadWriteContext->Fdo;
15564 fdoExt = fdo->DeviceExtension;
15565 listIdentifier = offloadWriteContext->ListIdentifier;
15566 totalSectorsToProcess = offloadWriteContext->TotalSectorsToProcess;
15567 entireXferLen = offloadWriteContext->EntireXferLen;
15568 tokenInvalidated = &offloadWriteContext->TokenInvalidated;
15569 pkt = offloadWriteContext->Pkt;
15570
15571 offloadWriteContext->Pkt = NULL;
15572
15573
15574 status = pseudoIrp->IoStatus.Status;
15576
15577 //
15578 // If the request failed with any of the following errors, then it is meaningless to send
15579 // down a ReceiveTokenInformation (regardless of whether the transfer was requested as sync
15580 // or async), since the target has no saved information about the command:
15581 // - STATUS_INVALID_TOKEN
15582 // - STATUS_INVALID_PARAMETER
15583 //
15586
15587 TracePrint((TRACE_LEVEL_ERROR,
15588 TRACE_FLAG_IOCTL,
15589 "ClasspWriteUsingTokenTransferPacketDone (%p): Write failed with %x (list id %x).\n",
15590 fdo,
15591 status,
15592 listIdentifier));
15593
15594 //
15595 // If the token isn't valid any longer, we should let the upper layers know so that
15596 // they don't waste time retrying the write with the same token.
15597 //
15599
15600 *tokenInvalidated = TRUE;
15601 }
15602
15604 goto __ClasspWriteUsingTokenTransferPacketDone_Exit;
15605
15606 } else if ((NT_SUCCESS(status)) &&
15607 (pkt->Srb->SrbStatus == SRB_STATUS_SUCCESS || pkt->TransferCount != 0)) {
15608
15609 //
15610 // If the TokenOperation command was sent to the target requesting synchronous data
15611 // transfer, a success indicates that the command is complete.
15612 // This could either be because of a successful completion of the entire transfer
15613 // or because of a partial transfer due to target truncation. If it is the latter,
15614 // and the information field of the sense data has returned the TransferCount, we
15615 // can avoid sending down an RRTI.
15616 //
15617 if (pkt->Srb->SrbStatus == SRB_STATUS_SUCCESS) {
15618
15619 //
15620 // The entire transfer has completed successfully.
15621 //
15622 offloadWriteContext->TotalSectorsProcessed = totalSectorsToProcess;
15623 TracePrint((TRACE_LEVEL_INFORMATION,
15624 TRACE_FLAG_IOCTL,
15625 "ClasspWriteUsingTokenTransferPacketDone (%p): Successfully wrote using token %I64u (out of %I64u) bytes (list Id %x).\n",
15626 fdo,
15627 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector,
15628 entireXferLen,
15629 listIdentifier));
15630 } else {
15631
15632 //
15633 // The target has returned how much data it transferred in the response to the
15634 // WUT command itself, allowing us to optimize by removing the necessaity for
15635 // sending down an RRTI to query the TransferCount.
15636 //
15638
15639 offloadWriteContext->TotalSectorsProcessed = totalSectorsToProcess = pkt->TransferCount;
15640 TracePrint((TRACE_LEVEL_INFORMATION,
15641 TRACE_FLAG_IOCTL,
15642 "ClasspWriteUsingTokenTransferPacketDone (%p): Target truncated write using token %I64u (out of %I64u) bytes (list Id %x).\n",
15643 fdo,
15644 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector,
15645 entireXferLen,
15646 listIdentifier));
15647 }
15648
15649 ClasspAdvanceOffloadWritePosition(offloadWriteContext, totalSectorsToProcess);
15650
15652
15653 //
15654 // ClasspReceiveWriteUsingTokenInformationDone() takes care of
15655 // completing the operation (eventually), so pending from point of view
15656 // of this function.
15657 //
15658
15661
15662 goto __ClasspWriteUsingTokenTransferPacketDone_Exit;
15663
15664 } else {
15665
15666 //
15667 // Since the TokenOperation was failed (or the target truncated the transfer but
15668 // didn't indicate the amount), we need to send down ReceiveTokenInformation.
15669 //
15670 TracePrint((TRACE_LEVEL_ERROR,
15671 TRACE_FLAG_IOCTL,
15672 "ClasspWriteUsingTokenTransferPacketDone (%p): Write failed with status %x, %x (list id %x).\n",
15673 fdo,
15674 status,
15675 pkt->Srb->SrbStatus,
15676 listIdentifier));
15677
15678 ClasspReceiveWriteUsingTokenInformation(offloadWriteContext);
15679
15681 goto __ClasspWriteUsingTokenTransferPacketDone_Exit;
15682 }
15683
15684__ClasspWriteUsingTokenTransferPacketDone_Exit:
15685
15686 if (status != STATUS_PENDING) {
15687 ClasspCompleteOffloadWrite(offloadWriteContext, status);
15688 }
15689
15690 return;
15691}
_IRQL_requires_same_ VOID ClasspReceiveWriteUsingTokenInformation(_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
Definition: class.c:15937
ULONGLONG EntireXferLen
Definition: classp.h:1119
BOOLEAN TokenInvalidated
Definition: classp.h:1154
PDEVICE_OBJECT Fdo
Definition: classp.h:1115
PTRANSFER_PACKET Pkt
Definition: classp.h:1143
ULONGLONG TotalSectorsToProcess
Definition: classp.h:1149
ULONGLONG TotalSectorsProcessed
Definition: classp.h:1150
ULONGLONG TransferCount
Definition: classp.h:610

◆ ClassQueryPnpCapabilities()

NTSTATUS ClassQueryPnpCapabilities ( IN PDEVICE_OBJECT  DeviceObject,
IN PDEVICE_CAPABILITIES  Capabilities 
)

Definition at line 10192 of file class.c.

10196{
10197 PCLASS_DRIVER_EXTENSION driverExtension =
10198 ClassGetDriverExtension(DeviceObject->DriverObject);
10199 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
10200
10201 PCLASS_QUERY_PNP_CAPABILITIES queryRoutine = NULL;
10202
10203 PAGED_CODE();
10204
10207
10208 if(commonExtension->IsFdo) {
10209 queryRoutine = driverExtension->InitData.FdoData.ClassQueryPnpCapabilities;
10210 } else {
10211 queryRoutine = driverExtension->InitData.PdoData.ClassQueryPnpCapabilities;
10212 }
10213
10214 if(queryRoutine) {
10215 return queryRoutine(DeviceObject,
10216 Capabilities);
10217 } else {
10219 }
10220} // end ClassQueryPnpCapabilities()
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
PCLASS_QUERY_PNP_CAPABILITIES ClassQueryPnpCapabilities
Definition: classpnp.h:532

Referenced by ClassDispatchPnp().

◆ ClassReadDriveCapacity()

_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity ( _In_ PDEVICE_OBJECT  Fdo)

Definition at line 2742 of file class.c.

2743{
2744 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
2745 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
2746 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
2747 READ_CAPACITY_DATA_EX PTRALIGN readCapacityData = {0};
2748 PTRANSFER_PACKET pkt;
2750 PMDL driveCapMdl = NULL;
2751 KEVENT event;
2752 IRP pseudoIrp = {0};
2753 ULONG readCapacityDataSize;
2754 BOOLEAN use16ByteCdb;
2755 BOOLEAN match = TRUE;
2756
2757 use16ByteCdb = TEST_FLAG(fdoExt->DeviceFlags, DEV_USE_16BYTE_CDB);
2758
2760
2761 if (use16ByteCdb) {
2762 readCapacityDataSize = sizeof(READ_CAPACITY_DATA_EX);
2763 } else {
2764 readCapacityDataSize = sizeof(READ_CAPACITY_DATA);
2765 }
2766
2767 if (driveCapMdl != NULL) {
2768 FreeDeviceInputMdl(driveCapMdl);
2769 driveCapMdl = NULL;
2770 }
2771
2772 //
2773 // Allocate the MDL based on the Read Capacity command.
2774 //
2775 driveCapMdl = BuildDeviceInputMdl(&readCapacityData, readCapacityDataSize);
2776 if (driveCapMdl == NULL) {
2778 goto SafeExit;
2779 }
2780
2782 if (pkt == NULL) {
2784 goto SafeExit;
2785 }
2786
2787 //
2788 // Our engine needs an "original irp" to write the status back to
2789 // and to count down packets (one in this case).
2790 // Just use a pretend irp for this.
2791 //
2792
2793 pseudoIrp.Tail.Overlay.DriverContext[0] = LongToPtr(1);
2794 pseudoIrp.IoStatus.Status = STATUS_SUCCESS;
2795 pseudoIrp.IoStatus.Information = 0;
2796 pseudoIrp.MdlAddress = driveCapMdl;
2797
2798 //
2799 // Set this up as a SYNCHRONOUS transfer, submit it,
2800 // and wait for the packet to complete. The result
2801 // status will be written to the original irp.
2802 //
2803
2806 &readCapacityData,
2807 readCapacityDataSize,
2808 &event,
2809 &pseudoIrp,
2810 use16ByteCdb);
2813
2814 status = pseudoIrp.IoStatus.Status;
2815
2816 //
2817 // If we got an UNDERRUN, retry exactly once.
2818 // (The transfer_packet engine didn't retry because the result
2819 // status was success).
2820 //
2821
2822 if (NT_SUCCESS(status) &&
2823 (pseudoIrp.IoStatus.Information < readCapacityDataSize)) {
2824
2825 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassReadDriveCapacity: read len (%xh) < %xh, retrying ...",
2826 (ULONG)pseudoIrp.IoStatus.Information, readCapacityDataSize));
2827
2829 if (pkt) {
2830 pseudoIrp.Tail.Overlay.DriverContext[0] = LongToPtr(1);
2831 pseudoIrp.IoStatus.Status = STATUS_SUCCESS;
2832 pseudoIrp.IoStatus.Information = 0;
2835 &readCapacityData,
2836 readCapacityDataSize,
2837 &event,
2838 &pseudoIrp,
2839 use16ByteCdb);
2842 status = pseudoIrp.IoStatus.Status;
2843 if (pseudoIrp.IoStatus.Information < readCapacityDataSize){
2845 }
2846 } else {
2848 }
2849 }
2850
2851 if (NT_SUCCESS(status)) {
2852 //
2853 // The request succeeded. Check for 8 byte LBA support.
2854 //
2855
2856 if (use16ByteCdb == FALSE) {
2857
2858 PREAD_CAPACITY_DATA readCapacity;
2859
2860 //
2861 // Check whether the device supports 8 byte LBA. If the device supports
2862 // it then retry the request using 16 byte CDB.
2863 //
2864
2865 readCapacity = (PREAD_CAPACITY_DATA) &readCapacityData;
2866
2867 if (readCapacity->LogicalBlockAddress == 0xFFFFFFFF) {
2868 //
2869 // Device returned max size for last LBA. Need to send
2870 // 16 byte request to get the size.
2871 //
2872 use16ByteCdb = TRUE;
2873 goto RetryRequest;
2874
2875 } else {
2876 //
2877 // Convert the 4 byte LBA (READ_CAPACITY_DATA) to 8 byte LBA (READ_CAPACITY_DATA_EX)
2878 // format for ease of use. This is the only format stored in the device extension.
2879 //
2880
2881 RtlMoveMemory((PUCHAR)(&readCapacityData) + sizeof(ULONG), readCapacity, sizeof(READ_CAPACITY_DATA));
2882 RtlZeroMemory((PUCHAR)(&readCapacityData), sizeof(ULONG));
2883
2884 }
2885 } else {
2886 //
2887 // Device completed 16 byte command successfully, it supports 8-byte LBA.
2888 //
2889
2891 }
2892
2893 //
2894 // Read out and store the drive information.
2895 //
2896
2897 InterpretCapacityData(Fdo, &readCapacityData);
2898
2899 //
2900 // Before caching the new drive capacity, compare it with the
2901 // cached capacity for any change.
2902 //
2903
2904 if (fdoData->IsCachedDriveCapDataValid == TRUE) {
2905
2907 &readCapacityData, sizeof(READ_CAPACITY_DATA_EX));
2908 }
2909
2910 //
2911 // Store the readCapacityData in private FDO data.
2912 // This is so that runtime memory failures don't cause disk.sys to put
2913 // the paging disk in an error state. Also this is used in
2914 // IOCTL_STORAGE_READ_CAPACITY.
2915 //
2916 fdoData->LastKnownDriveCapacityData = readCapacityData;
2918
2919 if (match == FALSE) {
2920 if (commonExtension->CurrentState != IRP_MN_START_DEVICE)
2921 {
2922 //
2923 // This can happen if a disk reports Parameters Changed / Capacity Data Changed sense data.
2924 // NT_ASSERT(!"Drive capacity has changed while the device wasn't started!");
2925 //
2926 } else {
2927 //
2928 // state of (commonExtension->CurrentState == IRP_MN_START_DEVICE) indicates that the device has been started.
2929 // UpdateDiskPropertiesWorkItemActive is used as a flag to ensure we only have one work item updating the disk
2930 // properties at a time.
2931 //
2932 if (InterlockedCompareExchange((volatile LONG *)&fdoData->UpdateDiskPropertiesWorkItemActive, 1, 0) == 0)
2933 {
2934 PIO_WORKITEM workItem;
2935
2936 workItem = IoAllocateWorkItem(Fdo);
2937
2938 if (workItem) {
2939 //
2940 // The disk capacity has changed, send notification to the disk driver.
2941 // Start a work item to notify the disk class driver asynchronously.
2942 //
2944 } else {
2946 }
2947 }
2948 }
2949 }
2950
2951 } else {
2952 //
2953 // The request failed.
2954 //
2955
2956 //
2957 // ISSUE - 2000/02/04 - henrygab - non-512-byte sector sizes and failed geometry update
2958 // what happens when the disk's sector size is bigger than
2959 // 512 bytes and we hit this code path? this is untested.
2960 //
2961 // If the read capacity fails, set the geometry to reasonable parameter
2962 // so things don't fail at unexpected places. Zero the geometry
2963 // except for the bytes per sector and sector shift.
2964 //
2965
2966 //
2967 // This request can sometimes fail legitimately
2968 // (e.g. when a SCSI device is attached but turned off)
2969 // so this is not necessarily a device/driver bug.
2970 //
2971
2972 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClassReadDriveCapacity on Fdo %p failed with status %ul.", Fdo, status));
2973
2974 //
2975 // Write in a default disk geometry which we HOPE is right (??).
2976 //
2977
2978 RtlZeroMemory(&fdoExt->DiskGeometry, sizeof(DISK_GEOMETRY));
2979 fdoExt->DiskGeometry.BytesPerSector = 512;
2980 fdoExt->SectorShift = 9;
2982
2983 //
2984 // Is this removable or fixed media
2985 //
2986
2987 if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)){
2989 } else {
2991 }
2992 }
2993
2994SafeExit:
2995
2996
2997 //
2998 // In case DEV_USE_16BYTE_CDB flag is not set, classpnp translates R/W request into READ/WRITE 10 SCSI command.
2999 // These SCSI commands have 2 bytes in "Transfer Blocks" field.
3000 // Make sure this max length (0xFFFF * sector size) is respected during request split.
3001 //
3002 if (!TEST_FLAG(fdoExt->DeviceFlags, DEV_USE_16BYTE_CDB)) {
3003 ULONG cdb10MaxBlocks = ((ULONG)USHORT_MAX) << fdoExt->SectorShift;
3004
3005 fdoData->HwMaxXferLen = min(cdb10MaxBlocks, fdoData->HwMaxXferLen);
3006 }
3007
3008 if (driveCapMdl != NULL) {
3009 FreeDeviceInputMdl(driveCapMdl);
3010 }
3011
3012 //
3013 // If the request failed for some reason then invalidate the cached
3014 // capacity data for removable devices. So that we won't return
3015 // wrong capacity in IOCTL_STORAGE_READ_CAPACITY
3016 //
3017
3018 if (!NT_SUCCESS(status) && (fdoExt->DiskGeometry.MediaType == RemovableMedia)) {
3020 }
3021
3022 //
3023 // Don't let memory failures (either here or in the port driver) in the ReadDriveCapacity call
3024 // put the paging disk in an error state such that paging fails.
3025 // Return the last known drive capacity (which may possibly be slightly out of date, even on
3026 // fixed media, e.g. for storage cabinets that can grow a logical disk).
3027 //
3029 (fdoData->IsCachedDriveCapDataValid) &&
3030 (fdoExt->DiskGeometry.MediaType == FixedMedia)) {
3031 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClassReadDriveCapacity: defaulting to cached DriveCapacity data"));
3034 }
3035
3036 return status;
3037}
#define PTRALIGN
Definition: cdromp.h:44
struct _READ_CAPACITY_DATA * PREAD_CAPACITY_DATA
struct _READ_CAPACITY_DATA READ_CAPACITY_DATA
VOID SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp, BOOLEAN Use16ByteCdb)
Definition: xferpkt.c:1480
IO_WORKITEM_ROUTINE ClasspUpdateDiskProperties
Definition: classp.h:1714
VOID InterpretCapacityData(PDEVICE_OBJECT Fdo, PREAD_CAPACITY_DATA_EX ReadCapacityData)
Definition: class.c:2640
#define USHORT_MAX
Definition: intsafe.h:147
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
#define RtlEqualMemory(a, b, c)
Definition: kdvm.h:18
@ RemovableMedia
Definition: ntdddisk.h:387
@ FixedMedia
Definition: ntdddisk.h:388
#define BOOLEAN
Definition: pedump.c:73
struct _READ_CAPACITY_DATA_EX READ_CAPACITY_DATA_EX
MEDIA_TYPE MediaType
Definition: ntdddisk.h:406
ULONG LogicalBlockAddress
Definition: cdrw_hw.h:1471
Definition: match.c:28
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
@ DelayedWorkQueue
Definition: extypes.h:190

Referenced by ClassDeviceControl(), ClasspDeviceGetLBAStatusWorker(), ClasspDeviceLBProvisioningProperty(), ClasspDeviceTrimProcess(), DetermineMediaType(), DiskInitFdo(), and USBFlopGetMediaTypes().

◆ ClassReadWrite()

NTSTATUS NTAPI ClassReadWrite ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 2431 of file class.c.

2432{
2433 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
2434 PDEVICE_OBJECT lowerDeviceObject = commonExtension->LowerDeviceObject;
2436 ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
2437 ULONG isRemoved;
2439
2440 /*
2441 * Grab the remove lock. If we can't acquire it, bail out.
2442 */
2444 if (isRemoved) {
2445 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
2446 Irp->IoStatus.Information = 0;
2450 }
2451 else if (TEST_FLAG(DeviceObject->Flags, DO_VERIFY_VOLUME) &&
2452 (currentIrpStack->MinorFunction != CLASSP_VOLUME_VERIFY_CHECKED) &&
2453 !TEST_FLAG(currentIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME)){
2454
2455 /*
2456 * DO_VERIFY_VOLUME is set for the device object,
2457 * but this request is not itself a verify request.
2458 * So fail this request.
2459 */
2460 if (Irp->Tail.Overlay.Thread != NULL) {
2462 }
2463 Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
2464 Irp->IoStatus.Information = 0;
2468 }
2469 else {
2470
2471 /*
2472 * Since we've bypassed the verify-required tests we don't need to repeat
2473 * them with this IRP - in particular we don't want to worry about
2474 * hitting them at the partition 0 level if the request has come through
2475 * a non-zero partition.
2476 */
2478
2479 /*
2480 * Call the miniport driver's pre-pass filter to check if we
2481 * should continue with this transfer.
2482 */
2483 NT_ASSERT(commonExtension->DevInfo->ClassReadWriteVerification);
2485 // Code Analysis cannot analyze the code paths specific to clients.
2487 if (!NT_SUCCESS(status)){
2488 NT_ASSERT(Irp->IoStatus.Status == status);
2489 Irp->IoStatus.Information = 0;
2492 }
2493 else if (status == STATUS_PENDING){
2494 /*
2495 * ClassReadWriteVerification queued this request.
2496 * So don't touch the irp anymore.
2497 */
2498 }
2499 else {
2500
2501 if (transferByteCount == 0) {
2502 /*
2503 * Several parts of the code turn 0 into 0xffffffff,
2504 * so don't process a zero-length request any further.
2505 */
2506 Irp->IoStatus.Status = STATUS_SUCCESS;
2507 Irp->IoStatus.Information = 0;
2511 }
2512 else {
2513 /*
2514 * If the driver has its own StartIo routine, call it.
2515 */
2516 if (commonExtension->DriverExtension->InitData.ClassStartIo) {
2520 }
2521 else {
2522 /*
2523 * The driver does not have its own StartIo routine.
2524 * So process this request ourselves.
2525 */
2526
2527 /*
2528 * Add partition byte offset to make starting byte relative to
2529 * beginning of disk.
2530 */
2531 currentIrpStack->Parameters.Read.ByteOffset.QuadPart +=
2532 commonExtension->StartingOffset.QuadPart;
2533
2534 if (commonExtension->IsFdo){
2535
2536 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
2537 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
2538
2539 /*
2540 * Add in any skew for the disk manager software.
2541 */
2542 currentIrpStack->Parameters.Read.ByteOffset.QuadPart +=
2543 commonExtension->PartitionZeroExtension->DMByteSkew;
2544
2545 //
2546 // In case DEV_USE_16BYTE_CDB flag is not set, R/W request will be translated into READ/WRITE 10 SCSI command.
2547 // These SCSI commands have 4 bytes in "Starting LBA" field.
2548 // Requests cannot be represented in these SCSI commands should be failed.
2549 //
2550 if (!TEST_FLAG(fdoExtension->DeviceFlags, DEV_USE_16BYTE_CDB)) {
2551 LARGE_INTEGER startingLba;
2552
2553 startingLba.QuadPart = currentIrpStack->Parameters.Read.ByteOffset.QuadPart >> fdoExtension->SectorShift;
2554
2555 if (startingLba.QuadPart > MAXULONG) {
2556 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2557 Irp->IoStatus.Information = 0;
2561 goto Exit;
2562 }
2563 }
2564
2565#if DBG
2566 //
2567 // Record the caller if:
2568 // 1. the disk is currently off
2569 // 2. the operation is a read, (likely resulting in disk spinnage)
2570 // 3. the operation is marked WT (likely resulting in disk spinnage)
2571 //
2572 if((fdoExtension->DevicePowerState == PowerDeviceD3) && // disk is off
2573 ((currentIrpStack->MajorFunction == IRP_MJ_READ) || // It's a read.
2574 (TEST_FLAG(currentIrpStack->Flags, SL_WRITE_THROUGH))) ) { // they *really* want it to go to disk.
2575
2577 }
2578#endif
2579
2580 /*
2581 * Perform the actual transfer(s) on the hardware
2582 * to service this request.
2583 */
2584 if (ClasspIsIdleRequestSupported(fdoData, Irp)) {
2587 } else {
2588 UCHAR uniqueAddr = 0;
2589
2590 //
2591 // Since we're touching fdoData after servicing the transfer packet, this opens us up to
2592 // a potential window, where the device may be removed between the time that
2593 // ServiceTransferPacket completes and we've had a chance to access fdoData. In order
2594 // to guard against this, we acquire the removelock an additional time here. This
2595 // acquire is guaranteed to succeed otherwise we wouldn't be here (because of the
2596 // outer acquire).
2597 // The sequence of events we're guarding against with this remLock acquire is:
2598 // 1. This UL IRP acquired the lock.
2599 // 2. Device gets surprised removed, then gets IRP_MN_REMOVE_DEVICE; ClassRemoveDevice
2600 // waits for the above RemoveLock.
2601 // 3. ServiceTransferRequest breaks the UL IRP into DL IRPs.
2602 // 4. DL IRPs complete with STATUS_NO_SUCH_DEVICE and TransferPktComplete completes the UL
2603 // IRP with STATUS_NO_SUCH_DEVICE; releases the RemoveLock.
2604 // 5. ClassRemoveDevice is now unblocked, continues running and frees resources (including
2605 // fdoData).
2606 // 6. Finally ClassReadWrite gets to run again and accesses a freed fdoData when trying to
2607 // check/update idle-related fields.
2608 //
2610
2613 if (fdoData->IdlePrioritySupported == TRUE) {
2615 }
2616
2618 }
2619 }
2620 else {
2621 /*
2622 * This is a child PDO enumerated for our FDO by e.g. disk.sys
2623 * and owned by e.g. partmgr. Send it down to the next device
2624 * and the same irp will come back to us for the FDO.
2625 */
2628 status = IoCallDriver(lowerDeviceObject, Irp);
2629 }
2630 }
2631 }
2632 }
2633 }
2634
2635Exit:
2636 return status;
2637}
FORCEINLINE VOID ClasspMarkIrpAsIdle(PIRP Irp, BOOLEAN Idle)
Definition: classp.h:1251
FORCEINLINE LARGE_INTEGER ClasspGetCurrentTime(VOID)
Definition: classp.h:1280
FORCEINLINE BOOLEAN ClasspIsIdleRequestSupported(PCLASS_PRIVATE_FDO_DATA FdoData, PIRP Irp)
Definition: classp.h:1236
NTSTATUS ClasspEnqueueIdleRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: clntirp.c:576
#define CLASSP_VOLUME_VERIFY_CHECKED
Definition: classp.h:187
NTSTATUS ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp, BOOLEAN PostToDpc)
Definition: class.c:3341
#define SnapDiskStartup()
Definition: debug.h:124
VOID NTAPI IoStartPacket(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PULONG Key, IN PDRIVER_CANCEL CancelFunction)
Definition: device.c:1876
@ PowerDeviceD3
Definition: ntpoapi.h:52
static void Exit(void)
Definition: sock.c:1330
PCLASS_READ_WRITE ClassReadWriteVerification
Definition: classpnp.h:523
BOOLEAN IdlePrioritySupported
Definition: classp.h:808
LARGE_INTEGER LastNonIdleIoTime
Definition: classp.h:935
LARGE_INTEGER StartingOffset
Definition: classpnp.h:619
DEVICE_POWER_STATE DevicePowerState
Definition: classpnp.h:878
#define MAXULONG
Definition: typedefs.h:251
#define SL_WRITE_THROUGH
Definition: iotypes.h:1824

Referenced by ClassInitializeDispatchTables().

◆ ClassReleaseChildLock()

VOID NTAPI ClassReleaseChildLock ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 12019 of file class.c.

12022{
12023 NT_ASSERT(FdoExtension->ChildLockOwner == KeGetCurrentThread());
12024 NT_ASSERT(FdoExtension->ChildLockAcquisitionCount != 0);
12025
12026 FdoExtension->ChildLockAcquisitionCount -= 1;
12027
12028 if(FdoExtension->ChildLockAcquisitionCount == 0) {
12029 FdoExtension->ChildLockOwner = NULL;
12031 }
12032
12033 return;
12034} // end ClassReleaseChildLock(
#define KeGetCurrentThread
Definition: hal.h:55

Referenced by ClassAddChild(), ClassRemoveChild(), and ClassRetrieveDeviceRelations().

◆ ClassReleaseQueue()

VOID NTAPI ClassReleaseQueue ( _In_ PDEVICE_OBJECT  Fdo)

Definition at line 11589 of file class.c.

11592{
11594 return;
11595} // end ClassReleaseQueue()
VOID ClasspReleaseQueue(IN PDEVICE_OBJECT Fdo, IN PIRP ReleaseQueueIrp OPTIONAL)
Definition: class.c:11743

Referenced by ClassAsynchronousCompletion(), ClassIoComplete(), ClassIoCompleteAssociated(), DiskInfoExceptionComplete(), and TransferPktComplete().

◆ ClassReleaseQueueCompletion()

NTSTATUS NTAPI ClassReleaseQueueCompletion ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp,
PVOID  Context 
)

Definition at line 11898 of file class.c.

11903{
11904 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
11905 KIRQL oldIrql;
11906
11907 BOOLEAN releaseQueueNeeded;
11908
11909 if (Context == NULL) {
11912 }
11913
11915
11916 fdoExtension = DeviceObject->DeviceExtension;
11917
11919
11920 //
11921 // Grab the spinlock and clear the release queue in progress flag so others
11922 // can run. Save (and clear) the state of the release queue needed flag
11923 // so that we can issue a new release queue outside the spinlock.
11924 //
11925
11926 KeAcquireSpinLock(&(fdoExtension->ReleaseQueueSpinLock), &oldIrql);
11927
11928 releaseQueueNeeded = fdoExtension->ReleaseQueueNeeded;
11929
11930 fdoExtension->ReleaseQueueNeeded = FALSE;
11931 fdoExtension->ReleaseQueueInProgress = FALSE;
11932
11933 KeReleaseSpinLock(&(fdoExtension->ReleaseQueueSpinLock), oldIrql);
11934
11935 //
11936 // If we need a release queue then issue one now. Another processor may
11937 // have already started one in which case we'll try to issue this one after
11938 // it is done - but we should never recurse more than one deep.
11939 //
11940
11941 if(releaseQueueNeeded) {
11943 }
11944
11945 //
11946 // Indicate the I/O system should stop processing the Irp completion.
11947 //
11948
11950
11951} // ClassAsynchronousCompletion()

◆ ClassRemoveChild()

PPHYSICAL_DEVICE_EXTENSION ClassRemoveChild ( IN PFUNCTIONAL_DEVICE_EXTENSION  Parent,
IN PPHYSICAL_DEVICE_EXTENSION  Child,
IN BOOLEAN  AcquireLock 
)

Definition at line 12119 of file class.c.

12124{
12125 if(AcquireLock) {
12126 ClassAcquireChildLock(Parent);
12127 }
12128
12129 TRY {
12130 PCOMMON_DEVICE_EXTENSION previousChild = &Parent->CommonExtension;
12131
12132 //
12133 // If the list is empty then bail out now.
12134 //
12135
12136 if(Parent->CommonExtension.ChildList == NULL) {
12137 Child = NULL;
12138 LEAVE;
12139 }
12140
12141 //
12142 // If the caller specified a child then find the child object before
12143 // it. If none was specified then the FDO is the child object before
12144 // the one we want to remove.
12145 //
12146
12147 if(Child != NULL) {
12148
12149 //
12150 // Scan through the child list to find the entry which points to
12151 // this one.
12152 //
12153
12154 do {
12155 NT_ASSERT(previousChild != &Child->CommonExtension);
12156
12157 if(previousChild->ChildList == Child) {
12158 break;
12159 }
12160
12161 previousChild = &previousChild->ChildList->CommonExtension;
12162 } while(previousChild != NULL);
12163
12164 if(previousChild == NULL) {
12165 Child = NULL;
12166 LEAVE;
12167 }
12168 }
12169
12170 //
12171 // Save the next child away then unlink it from the list.
12172 //
12173
12174 Child = previousChild->ChildList;
12175 previousChild->ChildList = Child->CommonExtension.ChildList;
12176 Child->CommonExtension.ChildList = NULL;
12177
12178 } FINALLY {
12179 if(AcquireLock) {
12181 }
12182 }
12183 return Child;
12184} // end ClassRemoveChild()
#define FINALLY
Definition: classpnp.h:116
#define LEAVE
Definition: classpnp.h:115
#define TRY(sps, bps)

◆ ClassRetrieveDeviceRelations()

NTSTATUS ClassRetrieveDeviceRelations ( IN PDEVICE_OBJECT  Fdo,
IN DEVICE_RELATION_TYPE  RelationType,
OUT PDEVICE_RELATIONS DeviceRelations 
)

Definition at line 10005 of file class.c.

10010{
10011 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
10012
10013 ULONG count = 0;
10014 ULONG i;
10015
10017
10018 ULONG relationsSize;
10019 PDEVICE_RELATIONS deviceRelations = NULL;
10020 PDEVICE_RELATIONS oldRelations = *DeviceRelations;
10021
10023
10025
10026 PAGED_CODE();
10027
10028 ClassAcquireChildLock(fdoExtension);
10029
10030 nextChild = fdoExtension->CommonExtension.ChildList;
10031
10032 //
10033 // Count the number of PDO's attached to this disk
10034 //
10035
10036 while (nextChild != NULL) {
10037 PCOMMON_DEVICE_EXTENSION commonExtension;
10038
10039 commonExtension = &(nextChild->CommonExtension);
10040
10041 NT_ASSERTMSG("ClassPnp internal error: missing child on active list\n",
10042 (nextChild->IsMissing == FALSE));
10043
10044 nextChild = commonExtension->ChildList;
10045
10046 count++;
10047 };
10048
10049 //
10050 // If relations already exist in the QDR, adjust the current count
10051 // to include the previous list.
10052 //
10053
10054 if (oldRelations) {
10055 count += oldRelations->Count;
10056 }
10057
10058 relationsSize = (sizeof(DEVICE_RELATIONS) +
10059 (count * sizeof(PDEVICE_OBJECT)));
10060
10061 deviceRelations = ExAllocatePoolWithTag(PagedPool, relationsSize, '5BcS');
10062
10063 if (deviceRelations == NULL) {
10064
10065 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_ENUM, "ClassRetrieveDeviceRelations: unable to allocate "
10066 "%d bytes for device relations\n", relationsSize));
10067
10068 ClassReleaseChildLock(fdoExtension);
10069
10071 }
10072
10073 RtlZeroMemory(deviceRelations, relationsSize);
10074
10075 if (oldRelations) {
10076
10077 //
10078 // Copy the old relations to the new list and free the old list.
10079 //
10080
10081 for (i = 0; i < oldRelations->Count; i++) {
10082 deviceRelations->Objects[i] = oldRelations->Objects[i];
10083 }
10084
10085 FREE_POOL(oldRelations);
10086 }
10087
10088 nextChild = fdoExtension->CommonExtension.ChildList;
10089 i = count;
10090
10091 while (nextChild != NULL) {
10092 PCOMMON_DEVICE_EXTENSION commonExtension;
10093
10094 commonExtension = &(nextChild->CommonExtension);
10095
10096 NT_ASSERTMSG("ClassPnp internal error: missing child on active list\n",
10097 (nextChild->IsMissing == FALSE));
10098
10099 _Analysis_assume_(i >= 1);
10100 deviceRelations->Objects[--i] = nextChild->DeviceObject;
10101
10103 nextChild->DeviceObject,
10104 0,
10105 NULL,
10106 KernelMode);
10107 if (!NT_SUCCESS(status)) {
10108 NT_ASSERT(!"Error referencing child device by pointer");
10109 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_ENUM,
10110 "ClassRetrieveDeviceRelations: Error referencing child "
10111 "device %p by pointer\n", nextChild->DeviceObject));
10112
10113 }
10114 nextChild->IsEnumerated = TRUE;
10115 nextChild = commonExtension->ChildList;
10116 }
10117
10118 NT_ASSERTMSG("Child list has changed: ", i == 0);
10119
10120 deviceRelations->Count = count;
10121 *DeviceRelations = deviceRelations;
10122
10123 ClassReleaseChildLock(fdoExtension);
10124 return STATUS_SUCCESS;
10125} // end ClassRetrieveDeviceRelations()
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:381
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:650
_In_ DEVICE_RELATION_TYPE RelationType
Definition: wdfdevice.h:1059
struct _DEVICE_RELATIONS DEVICE_RELATIONS

Referenced by ClassPnpQueryFdoRelations().

◆ ClassRetryRequest()

VOID ClassRetryRequest ( IN PDEVICE_OBJECT  SelfDeviceObject,
IN PIRP  Irp,
_In_ _In_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) IN LONGLONG  TimeDelta100ns 
)

Definition at line 12317 of file class.c.

12323{
12324 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
12326 PCLASS_RETRY_INFO retryInfo;
12327 LARGE_INTEGER delta;
12328 KIRQL irql;
12329
12330 //
12331 // this checks we aren't destroying irps
12332 //
12333 NT_ASSERT(sizeof(CLASS_RETRY_INFO) <= (4*sizeof(PVOID)));
12334
12335 fdoExtension = SelfDeviceObject->DeviceExtension;
12336
12337 if (!fdoExtension->CommonExtension.IsFdo) {
12338
12339 //
12340 // this debug print/assertion should ALWAYS be investigated.
12341 // ClassRetryRequest can currently only be used by FDO's
12342 //
12343
12344 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassRetryRequestEx: LOST IRP %p\n", Irp));
12345 NT_ASSERT(!"ClassRetryRequestEx Called From PDO? LOST IRP");
12346 return;
12347
12348 }
12349
12350 fdoData = fdoExtension->PrivateFdoData;
12351
12352 if (TimeDelta100ns < 0) {
12353 NT_ASSERT(!"ClassRetryRequest - must use positive delay");
12354 TimeDelta100ns *= -1;
12355 }
12356
12357 /*
12358 * We are going to queue the irp and send it down in a timer DPC.
12359 * This means that we may be causing the irp to complete on a different thread than the issuing thread.
12360 * So mark the irp pending.
12361 */
12363
12364 //
12365 // prepare what we can out of the loop
12366 //
12367
12368 retryInfo = (PCLASS_RETRY_INFO)(&Irp->Tail.Overlay.DriverContext[0]);
12369 RtlZeroMemory(retryInfo, sizeof(CLASS_RETRY_INFO));
12370
12371 delta.QuadPart = (TimeDelta100ns / fdoData->Retry.Granularity);
12372 if (TimeDelta100ns % fdoData->Retry.Granularity) {
12373 delta.QuadPart ++; // round up to next tick
12374 }
12375 if (delta.QuadPart == (LONGLONG)0) {
12377 }
12378
12379 //
12380 // now determine if we should fire another DPC or not
12381 //
12382
12383 KeAcquireSpinLock(&fdoData->Retry.Lock, &irql);
12384
12385 //
12386 // always add request to the list
12387 //
12388
12389 retryInfo->Next = fdoData->Retry.ListHead;
12390 fdoData->Retry.ListHead = retryInfo;
12391
12392 if (fdoData->Retry.Delta.QuadPart == (LONGLONG)0) {
12393
12394 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassRetry: +++ %p\n", Irp));
12395
12396 //
12397 // must be exactly one item on list
12398 //
12399
12400 NT_ASSERT(fdoData->Retry.ListHead != NULL);
12401 NT_ASSERT(fdoData->Retry.ListHead->Next == NULL);
12402
12403 //
12404 // if currentDelta is zero, always fire a DPC
12405 //
12406
12407 KeQueryTickCount(&fdoData->Retry.Tick);
12408 fdoData->Retry.Tick.QuadPart += delta.QuadPart;
12409 fdoData->Retry.Delta.QuadPart = delta.QuadPart;
12410 ClasspRetryDpcTimer(fdoData);
12411
12412 } else if (delta.QuadPart > fdoData->Retry.Delta.QuadPart) {
12413
12414 //
12415 // if delta is greater than the list's current delta,
12416 // increase the DPC handling time by difference
12417 // and update the delta to new larger value
12418 // allow the DPC to re-fire itself if needed
12419 //
12420
12421 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassRetry: ++ %p\n", Irp));
12422
12423 //
12424 // must be at least two items on list
12425 //
12426
12427 NT_ASSERT(fdoData->Retry.ListHead != NULL);
12428 NT_ASSERT(fdoData->Retry.ListHead->Next != NULL);
12429
12430 fdoData->Retry.Tick.QuadPart -= fdoData->Retry.Delta.QuadPart;
12431 fdoData->Retry.Tick.QuadPart += delta.QuadPart;
12432
12433 fdoData->Retry.Delta.QuadPart = delta.QuadPart;
12434
12435 } else {
12436
12437 //
12438 // just inserting it on the list was enough
12439 //
12440
12441 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassRetry: ++ %p\n", Irp));
12442
12443 }
12444
12445
12446 KeReleaseSpinLock(&fdoData->Retry.Lock, irql);
12447
12448
12449} // end ClassRetryRequest()
struct _CLASS_RETRY_INFO * PCLASS_RETRY_INFO
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)

Referenced by RetryPowerRequest(), and RetryRequest().

◆ ClassSendDeviceIoControlSynchronous()

VOID NTAPI ClassSendDeviceIoControlSynchronous ( _In_ ULONG  IoControlCode,
_In_ PDEVICE_OBJECT  TargetDeviceObject,
_Inout_updates_opt_(_Inexpressible_(max(InputBufferLength, OutputBufferLength))) PVOID  Buffer,
_In_ ULONG  InputBufferLength,
_In_ ULONG  OutputBufferLength,
_In_ BOOLEAN  InternalDeviceIoControl,
_Out_ PIO_STATUS_BLOCK  IoStatus 
)

Definition at line 11065 of file class.c.

11074{
11075 PIRP irp;
11077 ULONG method;
11078
11079 PAGED_CODE();
11080
11081 irp = NULL;
11082 method = IoControlCode & 3;
11083
11084 #if DBG // Begin Argument Checking (nop in fre version)
11085
11087
11088 if ((InputBufferLength != 0) || (OutputBufferLength != 0)) {
11090 }
11091 else {
11093 }
11094 #endif
11095
11096 //
11097 // Begin by allocating the IRP for this request. Do not charge quota to
11098 // the current process for this IRP.
11099 //
11100
11102 if (!irp) {
11103 IoStatus->Information = 0;
11105 return;
11106 }
11107
11108 //
11109 // Get a pointer to the stack location of the first driver which will be
11110 // invoked. This is where the function codes and the parameters are set.
11111 //
11112
11114
11115 //
11116 // Set the major function code based on the type of device I/O control
11117 // function the caller has specified.
11118 //
11119
11121 irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
11122 } else {
11123 irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
11124 }
11125
11126 //
11127 // Copy the caller's parameters to the service-specific portion of the
11128 // IRP for those parameters that are the same for all four methods.
11129 //
11130
11131 irpSp->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength;
11132 irpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
11133 irpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
11134
11135 //
11136 // Get the method bits from the I/O control code to determine how the
11137 // buffers are to be passed to the driver.
11138 //
11139
11140 switch (method)
11141 {
11142 //
11143 // case 0
11144 //
11145 case METHOD_BUFFERED:
11146 {
11147 if ((InputBufferLength != 0) || (OutputBufferLength != 0))
11148 {
11149 irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
11152 if (irp->AssociatedIrp.SystemBuffer == NULL)
11153 {
11154 IoFreeIrp(irp);
11155
11156 IoStatus->Information = 0;
11158 return;
11159 }
11160
11161 if (InputBufferLength != 0)
11162 {
11163 RtlCopyMemory(irp->AssociatedIrp.SystemBuffer, Buffer, InputBufferLength);
11164 }
11165 }
11166
11167 irp->UserBuffer = Buffer;
11168
11169 break;
11170 }
11171
11172 //
11173 // case 1, case 2
11174 //
11175 case METHOD_IN_DIRECT:
11176 case METHOD_OUT_DIRECT:
11177 {
11178 if (InputBufferLength != 0)
11179 {
11180 irp->AssociatedIrp.SystemBuffer = Buffer;
11181 }
11182
11183 if (OutputBufferLength != 0)
11184 {
11185 irp->MdlAddress = IoAllocateMdl(Buffer,
11187 FALSE,
11188 FALSE,
11189 (PIRP) NULL);
11190 if (irp->MdlAddress == NULL)
11191 {
11192 IoFreeIrp(irp);
11193
11194 IoStatus->Information = 0;
11196 return;
11197 }
11198
11199 _SEH2_TRY
11200 {
11201 MmProbeAndLockPages(irp->MdlAddress,
11202 KernelMode,
11204 }
11205#ifdef _MSC_VER
11206 #pragma warning(suppress: 6320) // We want to handle any exception that MmProbeAndLockPages might throw
11207#endif
11209 {
11210 IoFreeMdl(irp->MdlAddress);
11211 IoFreeIrp(irp);
11212
11213 IoStatus->Information = 0;
11214 IoStatus->Status = _SEH2_GetExceptionCode();
11215 _SEH2_YIELD(return);
11216 } _SEH2_END;
11217 }
11218
11219 break;
11220 }
11221
11222 //
11223 // case 3
11224 //
11225 case METHOD_NEITHER:
11226 {
11227 NT_ASSERT(!"ClassSendDeviceIoControlSynchronous does not support METHOD_NEITHER Ioctls");
11228
11229 IoFreeIrp(irp);
11230
11231 IoStatus->Information = 0;
11233 return;
11234 }
11235 }
11236
11237 irp->Tail.Overlay.Thread = PsGetCurrentThread();
11238
11239 //
11240 // send the irp synchronously
11241 //
11242
11244
11245 //
11246 // copy the iostatus block for the caller
11247 //
11248
11249 *IoStatus = irp->IoStatus;
11250
11251 //
11252 // free any allocated resources
11253 //
11254
11255 switch (method) {
11256 case METHOD_BUFFERED: {
11257
11258 NT_ASSERT(irp->UserBuffer == Buffer);
11259
11260 //
11261 // first copy the buffered result, if any
11262 // Note that there are no security implications in
11263 // not checking for success since only drivers can
11264 // call into this routine anyways...
11265 //
11266
11267 if (OutputBufferLength != 0) {
11268#ifdef _MSC_VER
11269 #pragma warning(suppress: 6386) // Buffer's size is max(InputBufferLength, OutputBufferLength)
11270#endif
11271 RtlCopyMemory(Buffer, // irp->UserBuffer
11272 irp->AssociatedIrp.SystemBuffer,
11274 );
11275 }
11276
11277 //
11278 // then free the memory allocated to buffer the io
11279 //
11280
11281 if ((InputBufferLength !=0) || (OutputBufferLength != 0)) {
11282 FREE_POOL(irp->AssociatedIrp.SystemBuffer);
11283 }
11284 break;
11285 }
11286
11287 case METHOD_IN_DIRECT:
11288 case METHOD_OUT_DIRECT: {
11289
11290 //
11291 // we alloc a mdl if there is an output buffer specified
11292 // free it here after unlocking the pages
11293 //
11294
11295 if (OutputBufferLength != 0) {
11296 NT_ASSERT(irp->MdlAddress != NULL);
11297 MmUnlockPages(irp->MdlAddress);
11298 IoFreeMdl(irp->MdlAddress);
11299 irp->MdlAddress = (PMDL) NULL;
11300 }
11301 break;
11302 }
11303
11304 case METHOD_NEITHER: {
11305 NT_ASSERT(!"Code is out of date");
11306 break;
11307 }
11308 }
11309
11310 //
11311 // we always have allocated an irp. free it here.
11312 //
11313
11314 IoFreeIrp(irp);
11315 irp = (PIRP) NULL;
11316
11317 //
11318 // return the io status block's status to the caller
11319 //
11320
11321 return;
11322} // end ClassSendDeviceIoControlSynchronous()
struct _IRP * PIRP
Definition: bufpool.h:45
#define CLASS_TAG_DEVICE_CONTROL
Definition: classpnp.h:85
method
Definition: dragdrop.c:54
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
IN OUT PVCB IN PDEVICE_OBJECT TargetDeviceObject
Definition: fatprocs.h:1674
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define METHOD_NEITHER
Definition: nt_native.h:597
#define METHOD_OUT_DIRECT
Definition: nt_native.h:596
#define METHOD_BUFFERED
Definition: nt_native.h:594
#define METHOD_IN_DIRECT
Definition: nt_native.h:595
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
PVOID PMDL
Definition: usb.h:39
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:325
_In_ WDFREQUEST _In_ size_t OutputBufferLength
Definition: wdfio.h:320
_In_ WDFREQUEST _In_ size_t _In_ size_t InputBufferLength
Definition: wdfio.h:322
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID _In_ ULONG _In_ BOOLEAN InternalDeviceIoControl
Definition: iofuncs.h:720
irpSp
Definition: iofuncs.h:2719
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864

Referenced by ClasspGetHwFirmwareInfo(), ClasspSendEnableIdlePowerIoctl(), and DiskIoctlSmartGetVersion().

◆ ClassSendIrpSynchronous()

NTSTATUS NTAPI ClassSendIrpSynchronous ( _In_ PDEVICE_OBJECT  TargetDeviceObject,
_In_ PIRP  Irp 
)

Definition at line 11373 of file class.c.

11377{
11378 KEVENT event;
11380
11383 NT_ASSERT(Irp != NULL);
11384 NT_ASSERT(Irp->StackCount >= TargetDeviceObject->StackSize);
11385
11386 //
11387 // ISSUE-2000/02/20-henrygab What if APCs are disabled?
11388 // May need to enter critical section before IoCallDriver()
11389 // until the event is hit?
11390 //
11391
11394 TRUE, TRUE, TRUE);
11395
11398 if (status == STATUS_PENDING) {
11399
11400 #if DBG
11402
11403 timeout.QuadPart = (LONGLONG)(-1 * 10 * 1000 * (LONGLONG)1000 *
11404 ClasspnpGlobals.SecondsToWaitForIrps);
11405
11406 do {
11408 Executive,
11409 KernelMode,
11410 FALSE,
11411 &timeout);
11412
11413
11414 if (status == STATUS_TIMEOUT) {
11415
11416 //
11417 // This DebugPrint should almost always be investigated by the
11418 // party who sent the irp and/or the current owner of the irp.
11419 // Synchronous Irps should not take this long (currently 30
11420 // seconds) without good reason. This points to a potentially
11421 // serious problem in the underlying device stack.
11422 //
11423
11424 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendIrpSynchronous: (%p) irp %p did not "
11425 "complete within %x seconds\n",
11427 ClasspnpGlobals.SecondsToWaitForIrps
11428 ));
11429
11430 if (ClasspnpGlobals.BreakOnLostIrps != 0) {
11431 NT_ASSERT(!" - Irp failed to complete within 30 seconds - ");
11432 }
11433 }
11434
11435
11436 } while (status==STATUS_TIMEOUT);
11437 #else
11439 Executive,
11440 KernelMode,
11441 FALSE,
11442 NULL);
11443 #endif
11444
11445 status = Irp->IoStatus.Status;
11446 }
11447
11448 return status;
11449} // end ClassSendIrpSynchronous()
IO_COMPLETION_ROUTINE ClassSignalCompletion
Definition: classpnp.h:1330
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
Definition: dhcpd.h:245

Referenced by ClassForwardIrpSynchronous(), and ClassSendDeviceIoControlSynchronous().

◆ ClassSendSrbSynchronous()

NTSTATUS NTAPI ClassSendSrbSynchronous ( _In_ PDEVICE_OBJECT  Fdo,
_Inout_ PSCSI_REQUEST_BLOCK  _Srb,
_In_reads_bytes_opt_(BufferLength) PVOID  BufferAddress,
_In_ ULONG  BufferLength,
_In_ BOOLEAN  WriteToDevice 
)

Definition at line 4042 of file class.c.

4049{
4050
4051 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
4052 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
4053 IO_STATUS_BLOCK ioStatus = {0};
4054 PIRP irp;
4055 PIO_STACK_LOCATION irpStack;
4056 KEVENT event;
4058 ULONG senseInfoBufferLength = SENSE_BUFFER_SIZE_EX;
4059 ULONG retryCount = MAXIMUM_RETRIES;
4061 BOOLEAN retry;
4063
4064 //
4065 // NOTE: This code is only pagable because we are not freezing
4066 // the queue. Allowing the queue to be frozen from a pagable
4067 // routine could leave the queue frozen as we try to page in
4068 // the code to unfreeze the queue. The result would be a nice
4069 // case of deadlock. Therefore, since we are unfreezing the
4070 // queue regardless of the result, just set the NO_FREEZE_QUEUE
4071 // flag in the SRB.
4072 //
4073
4075 NT_ASSERT(fdoExtension->CommonExtension.IsFdo);
4076
4078 //
4079 // Write length to SRB.
4080 //
4081
4082 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
4083
4084 //
4085 // Set SCSI bus address.
4086 //
4087
4089 }
4090
4091 //
4092 // The Srb->Function should have been set corresponding to SrbType.
4093 //
4094
4097
4098
4099 //
4100 // Sense buffer is in aligned nonpaged pool.
4101 //
4102
4103#if defined(_ARM_) || defined(_ARM64_)
4104
4105 //
4106 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
4107 // based platforms. We are taking the conservative approach here.
4108 //
4109 senseInfoBufferLength = ALIGN_UP_BY(senseInfoBufferLength,KeGetRecommendedSharedDataAlignment());
4110
4111#endif
4112
4113 senseInfoBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
4114 senseInfoBufferLength,
4115 '7CcS');
4116
4117 if (senseInfoBuffer == NULL) {
4118
4119 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendSrbSynchronous: Can't allocate request sense "
4120 "buffer\n"));
4122 }
4123
4124
4125 //
4126 // Enable auto request sense.
4127 //
4130
4132
4133
4134 //
4135 // Start retries here.
4136 //
4137
4138retry:
4139
4140 //
4141 // use fdoextension's flags by default.
4142 // do not move out of loop, as the flag may change due to errors
4143 // sending this command.
4144 //
4145
4146 SrbAssignSrbFlags(Srb, fdoExtension->SrbFlags);
4147
4148 if (BufferAddress != NULL) {
4149 if (WriteToDevice) {
4151 } else {
4153 }
4154 }
4155
4156
4157 //
4158 // Initialize the QueueAction field.
4159 //
4160
4162
4163 //
4164 // Disable synchronous transfer for these requests.
4165 //
4167
4168 //
4169 // Set the event object to the unsignaled state.
4170 // It will be used to signal request completion.
4171 //
4172
4174
4175 //
4176 // Build device I/O control request with METHOD_NEITHER data transfer.
4177 // We'll queue a completion routine to cleanup the MDL's and such ourself.
4178 //
4179
4181 (CCHAR) (fdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1),
4182 FALSE);
4183
4184 if (irp == NULL) {
4188 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendSrbSynchronous: Can't allocate Irp\n"));
4190 }
4191
4192 //
4193 // Get next stack location.
4194 //
4195
4196 irpStack = IoGetNextIrpStackLocation(irp);
4197
4198 //
4199 // Set up SRB for execute scsi request. Save SRB address in next stack
4200 // for the port driver.
4201 //
4202
4203 irpStack->MajorFunction = IRP_MJ_SCSI;
4204 irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)Srb;
4205
4208 Srb,
4209 TRUE,
4210 TRUE,
4211 TRUE);
4212
4213 irp->UserIosb = &ioStatus;
4214 irp->UserEvent = &event;
4215
4216 if (BufferAddress) {
4217 //
4218 // Build an MDL for the data buffer and stick it into the irp. The
4219 // completion routine will unlock the pages and free the MDL.
4220 //
4221
4222 irp->MdlAddress = IoAllocateMdl( BufferAddress,
4224 FALSE,
4225 FALSE,
4226 irp );
4227 if (irp->MdlAddress == NULL) {
4231 IoFreeIrp( irp );
4232 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendSrbSynchronous: Can't allocate MDL\n"));
4234 }
4235
4236 _SEH2_TRY {
4237
4238 //
4239 // the io manager unlocks these pages upon completion
4240 //
4241
4242 MmProbeAndLockPages( irp->MdlAddress,
4243 KernelMode,
4245 IoWriteAccess));
4246
4247#ifdef _MSC_VER
4248 #pragma warning(suppress: 6320) // We want to handle any exception that MmProbeAndLockPages might throw
4249#endif
4252
4256 IoFreeMdl(irp->MdlAddress);
4257 IoFreeIrp(irp);
4258
4259 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendSrbSynchronous: Exception %lx "
4260 "locking buffer\n", status));
4261 _SEH2_YIELD(return status);
4262 } _SEH2_END;
4263 }
4264
4265 //
4266 // Set the transfer length.
4267 //
4268
4270
4271 //
4272 // Zero out status.
4273 //
4274
4276 Srb->SrbStatus = 0;
4278
4279 //
4280 // Set up IRP Address.
4281 //
4282
4284
4285 //
4286 // Call the port driver with the request and wait for it to complete.
4287 //
4288
4290
4291 if (status == STATUS_PENDING) {
4293 status = ioStatus.Status;
4294 }
4295
4296// NT_ASSERT(SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_PENDING);
4299
4300 //
4301 // Clear the IRP address in SRB as IRP has been freed at this time
4302 // and don't want to leave any references that may be accessed.
4303 //
4304
4306
4307 //
4308 // Check that request completed without error.
4309 //
4310
4312
4313 LONGLONG retryInterval;
4314
4315 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendSrbSynchronous - srb %ph failed (op=%s srbstat=%s(%xh), irpstat=%xh, sense=%s/%s/%s)", Srb,
4321
4322 //
4323 // assert that the queue is not frozen
4324 //
4325
4327
4328 //
4329 // Update status and determine if request should be retried.
4330 //
4331
4333 NULL, // no valid irp exists
4336 0,
4337 MAXIMUM_RETRIES - retryCount,
4338 &status,
4339 &retryInterval);
4340
4341 if (retry) {
4342
4345
4347
4348 validSense = ScsiGetSenseKeyAndCodes(senseInfoBuffer,
4351 NULL,
4353 NULL);
4354 }
4355
4358
4359 LARGE_INTEGER delay;
4360
4361 //
4362 // Delay for at least 2 seconds.
4363 //
4364
4365 if (retryInterval < 2*1000*1000*10) {
4366 retryInterval = 2*1000*1000*10;
4367 }
4368
4369 delay.QuadPart = -retryInterval;
4370
4371 //
4372 // Stall for a while to let the device become ready
4373 //
4374
4376
4377 }
4378
4379
4380 //
4381 // If retries are not exhausted then retry this operation.
4382 //
4383
4384 if (retryCount--) {
4385
4386 if (PORT_ALLOCATED_SENSE_EX(fdoExtension, Srb)) {
4388 }
4389
4390 goto retry;
4391 }
4392 }
4393
4394
4395 } else {
4398 }
4399
4400 //
4401 // required even though we allocated our own, since the port driver may
4402 // have allocated one also
4403 //
4404
4405 if (PORT_ALLOCATED_SENSE_EX(fdoExtension, Srb)) {
4407 }
4408
4412
4413 return status;
4414}
IO_COMPLETION_ROUTINE ClasspSendSynchronousCompletion
Definition: classp.h:1410
#define DBGGETSCSIOPSTR(_pSrb)
Definition: debug.h:26
#define DBGGETADSENSECODESTR(_pSrb)
Definition: debug.h:29
#define DBGGETADSENSEQUALIFIERSTR(_pSrb)
Definition: debug.h:30
#define DBGGETSRBSTATUSSTR(_pSrb)
Definition: debug.h:27
#define DBGGETSENSECODESTR(_pSrb)
Definition: debug.h:28
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
@ NotificationEvent
UCHAR additionalSenseCode
Definition: scsi.h:4020
#define SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED
Definition: scsi.h:3839
PFIXED_SENSE_DATA senseInfoBuffer
Definition: scsi.h:3710
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:596
#define SRB_TYPE_SCSI_REQUEST_BLOCK
Definition: srb.h:663

Referenced by ClassGetLBProvisioningLogPage(), ClasspCleanupProtectedLocks(), ClasspDeviceGetBlockDeviceCharacteristicsVPDPage(), ClasspDeviceGetBlockLimitsVPDPage(), ClasspDeviceGetLBProvisioningVPDPage(), ClasspEjectionControl(), ClasspGetBlockDeviceTokenLimitsInfo(), ClasspGetInquiryVpdSupportInfo(), ClasspWriteCacheProperty(), ClassReadCapacity16(), DetermineMediaType(), DeviceProcessDsmTrimRequest(), DiskFlushDispatch(), DiskIoctlGetMediaTypesEx(), DiskIoctlIsWritable(), DiskIoctlReassignBlocks(), DiskIoctlReassignBlocksEx(), DiskIoctlVerifyThread(), DiskModeSelect(), DiskShutdownFlush(), FormatMedia(), GetLBAStatus(), USBFlopFormatTracks(), and USBFlopGetMediaTypes().

◆ ClassSendStartUnit()

VOID NTAPI ClassSendStartUnit ( _In_ PDEVICE_OBJECT  Fdo)

Definition at line 3071 of file class.c.

3074{
3075 PIO_STACK_LOCATION irpStack;
3076 PIRP irp;
3077 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
3080 PCDB cdb;
3083
3084 //
3085 // Allocate Srb from nonpaged pool.
3086 //
3087
3088 context = ExAllocatePoolWithTag(NonPagedPoolNx,
3089 sizeof(COMPLETION_CONTEXT),
3090 '6CcS');
3091
3092 if (context == NULL) {
3093
3094 //
3095 // ISSUE-2000/02/03-peterwie
3096 // This code path was inheritted from the NT 4.0 class2.sys driver.
3097 // It needs to be changed to survive low-memory conditions.
3098 //
3099
3100 KeBugCheck(SCSI_DISK_DRIVER_INTERNAL);
3101 }
3102
3103 //
3104 // Save the device object in the context for use by the completion
3105 // routine.
3106 //
3107
3108 context->DeviceObject = Fdo;
3109
3110 srb = &context->Srb.Srb;
3111 if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
3112 srbEx = &context->Srb.SrbEx;
3115 sizeof(context->Srb.SrbExBuffer),
3116 1,
3118 if (!NT_SUCCESS(status)) {
3121 return;
3122 }
3123
3124 srbEx->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
3125
3126 } else {
3127
3128 //
3129 // Zero out srb.
3130 //
3131
3132 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
3133
3134 //
3135 // Write length to SRB.
3136 //
3137
3138 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
3139
3141 }
3142
3143 //
3144 // Set timeout value large enough for drive to spin up.
3145 //
3146
3148
3149 //
3150 // Set the transfer length.
3151 //
3152
3157
3158 //
3159 // Build the start unit CDB.
3160 //
3161
3162 SrbSetCdbLength(srb, 6);
3163 cdb = SrbGetCdb(srb);
3164
3165 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
3166 cdb->START_STOP.Start = 1;
3167 cdb->START_STOP.Immediate = 0;
3168 cdb->START_STOP.LogicalUnitNumber = srb->Lun;
3169
3170 //
3171 // Build the asynchronous request to be sent to the port driver.
3172 // Since this routine is called from a DPC the IRP should always be
3173 // available.
3174 //
3175
3176 irp = IoAllocateIrp(Fdo->StackSize, FALSE);
3177
3178 if (irp == NULL) {
3179
3180 //
3181 // ISSUE-2000/02/03-peterwie
3182 // This code path was inheritted from the NT 4.0 class2.sys driver.
3183 // It needs to be changed to survive low-memory conditions.
3184 //
3185
3186 KeBugCheck(SCSI_DISK_DRIVER_INTERNAL);
3187
3188 }
3189
3191
3194 context,
3195 TRUE,
3196 TRUE,
3197 TRUE);
3198
3199 irpStack = IoGetNextIrpStackLocation(irp);
3200 irpStack->MajorFunction = IRP_MJ_SCSI;
3202
3203 //
3204 // Store the SRB address in next stack for port driver.
3205 //
3206
3207 irpStack->Parameters.Scsi.Srb = srb;
3208
3209 //
3210 // Call the port driver with the IRP.
3211 //
3212
3214
3215 return;
3216
3217} // end StartUnit()
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1430
#define START_UNIT_TIMEOUT
Definition: cdrom.h:132
NTSTATUS NTAPI ClassAsynchronousCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: class.c:3246
#define SRB_FLAGS_DISABLE_AUTOSENSE
Definition: srb.h:399
IO_COMPLETION_ROUTINE * PIO_COMPLETION_ROUTINE
Definition: iotypes.h:2835

Referenced by ClassInterpretSenseInfo().

◆ ClassShutdownFlush()

NTSTATUS NTAPI ClassShutdownFlush ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 8773 of file class.c.

8777{
8778 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8779
8780 ULONG isRemoved;
8781
8783 _Analysis_assume_(isRemoved);
8784 if(isRemoved) {
8785
8787
8788 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
8789
8791
8793 }
8794
8795 if (commonExtension->DevInfo->ClassShutdownFlush) {
8796
8797 //
8798 // Call the device-specific driver's routine.
8799 //
8800
8801 return commonExtension->DevInfo->ClassShutdownFlush(DeviceObject, Irp);
8802 }
8803
8804 //
8805 // Device-specific driver doesn't support this.
8806 //
8807
8808 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
8809
8812
8814} // end ClassShutdownFlush()
PCLASS_SHUTDOWN_FLUSH ClassShutdownFlush
Definition: classpnp.h:525

Referenced by ClassInitializeDispatchTables().

◆ ClassSignalCompletion()

NTSTATUS NTAPI ClassSignalCompletion ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context 
)

Definition at line 9799 of file class.c.

9804{
9806
9809
9810 if (Context == NULL) {
9813 }
9814
9816
9818} // end ClassSignalCompletion()
#define PKEVENT
Definition: env_spec_w32.h:70

◆ ClassUnload()

VOID NTAPI ClassUnload ( IN PDRIVER_OBJECT  DriverObject)

Definition at line 764 of file class.c.

767{
768 PCLASS_DRIVER_EXTENSION driverExtension;
769
770 PAGED_CODE();
771
772 NT_ASSERT( DriverObject->DeviceObject == NULL );
773
774#ifdef _MSC_VER
775#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
776#endif
778
779
780 if (driverExtension == NULL)
781 {
783 return;
784 }
785
786 NT_ASSERT(driverExtension->RegistryPath.Buffer != NULL);
787 NT_ASSERT(driverExtension->InitData.ClassUnload != NULL);
788
789 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClassUnload: driver unloading %wZ\n",
790 &driverExtension->RegistryPath));
791
792 //
793 // attempt to process the driver's unload routine first.
794 //
795
796 driverExtension->InitData.ClassUnload(DriverObject);
797
798 //
799 // free own allocated resources and return
800 //
801
802 FREE_POOL( driverExtension->WorkingSet );
803 FREE_POOL( driverExtension->InterpretSenseInfo );
804 FREE_POOL( driverExtension->RegistryPath.Buffer );
805 driverExtension->RegistryPath.Length = 0;
806 driverExtension->RegistryPath.MaximumLength = 0;
807
808
809 //
810 // Unregister ETW
811 //
812 if (driverExtension->EtwHandle != 0) {
813 EtwUnregister(driverExtension->EtwHandle);
814 driverExtension->EtwHandle = 0;
815
817 }
818
819
820 return;
821} // end ClassUnload()
#define WPP_CLEANUP(a)
Definition: kdebugprint.h:57
PCLASS_WORKING_SET WorkingSet
Definition: classpnp.h:588
PCLASS_UNLOAD ClassUnload
Definition: classpnp.h:544

◆ DllUnload()

NTSTATUS DllUnload ( VOID  )

Definition at line 135 of file class.c.

136{
137 DbgPrintEx(DPFLTR_CLASSPNP_ID, DPFLTR_INFO_LEVEL, "classpnp.sys is now unloading\n");
138
140 PoUnregisterPowerSettingCallback(PowerSettingNotificationHandle);
142 }
143
145 PoUnregisterPowerSettingCallback(ScreenStateNotificationHandle);
147 }
148
149
150 return STATUS_SUCCESS;
151}
@ DPFLTR_CLASSPNP_ID
Definition: dpfilter.h:36
PVOID PowerSettingNotificationHandle
Definition: class.c:119
#define DPFLTR_INFO_LEVEL
Definition: kdtypes.h:33
NTSYSAPI ULONG __cdecl DbgPrintEx(_In_ ULONG ComponentId, _In_ ULONG Level, _In_z_ _Printf_format_string_ PCSTR Format,...)

◆ DriverEntry()

NTSTATUS NTAPI DriverEntry ( IN PDRIVER_OBJECT  DriverObject,
IN PUNICODE_STRING  RegistryPath 
)

Definition at line 174 of file class.c.

◆ InterpretCapacityData()

VOID InterpretCapacityData ( PDEVICE_OBJECT  Fdo,
PREAD_CAPACITY_DATA_EX  ReadCapacityData 
)

Definition at line 2640 of file class.c.

2641{
2642 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
2643 ULONG cylinderSize;
2644 ULONG bytesPerSector;
2645 LARGE_INTEGER lastSector;
2646 LARGE_INTEGER largeInt;
2647
2648 bytesPerSector = ClasspCalculateLogicalSectorSize(Fdo, ReadCapacityData->BytesPerBlock);
2649
2650 fdoExt->DiskGeometry.BytesPerSector = bytesPerSector;
2652
2653 /*
2654 * LogicalBlockAddress is the last sector of the logical drive, in big-endian.
2655 * It tells us the size of the drive (#sectors is lastSector+1).
2656 */
2657
2658 largeInt = ReadCapacityData->LogicalBlockAddress;
2659 REVERSE_BYTES_QUAD(&lastSector, &largeInt);
2660
2661 if (fdoExt->DMActive){
2662 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClassReadDriveCapacity: reducing number of sectors by %d\n", fdoExt->DMSkew));
2663 lastSector.QuadPart -= fdoExt->DMSkew;
2664 }
2665
2666 /*
2667 * Check to see if we have a geometry we should be using already.
2668 * If not, we set part of the disk geometry to garbage values that will be filled in by the caller (e.g. disk.sys).
2669 *
2670 * So the first call to ClassReadDriveCapacity always sets a meaningless geometry.
2671 * TracksPerCylinder and SectorsPerTrack are kind of meaningless anyway wrt I/O,
2672 * because I/O is always targeted to a logical sector number.
2673 * All that really matters is BytesPerSector and the number of sectors.
2674 */
2675 cylinderSize = fdoExt->DiskGeometry.TracksPerCylinder * fdoExt->DiskGeometry.SectorsPerTrack;
2676 if (cylinderSize == 0){
2677 fdoExt->DiskGeometry.TracksPerCylinder = 0xff;
2678 fdoExt->DiskGeometry.SectorsPerTrack = 0x3f;
2679 cylinderSize = fdoExt->DiskGeometry.TracksPerCylinder * fdoExt->DiskGeometry.SectorsPerTrack;
2680 }
2681
2682 /*
2683 * Calculate number of cylinders.
2684 * If there are zero cylinders, then the device lied AND it's
2685 * smaller than 0xff*0x3f (about 16k sectors, usually 8 meg)
2686 * this can fit into a single LONGLONG, so create another usable
2687 * geometry, even if it's unusual looking.
2688 * This allows small, non-standard devices, such as Sony's Memory Stick, to show up as having a partition.
2689 */
2690 fdoExt->DiskGeometry.Cylinders.QuadPart = (LONGLONG)((lastSector.QuadPart + 1)/cylinderSize);
2691 if (fdoExt->DiskGeometry.Cylinders.QuadPart == (LONGLONG)0) {
2692 fdoExt->DiskGeometry.SectorsPerTrack = 1;
2693 fdoExt->DiskGeometry.TracksPerCylinder = 1;
2694 fdoExt->DiskGeometry.Cylinders.QuadPart = lastSector.QuadPart + 1;
2695 }
2696
2697 /*
2698 * Calculate media capacity in bytes.
2699 * For this purpose we treat the entire LUN as is if it is one partition. Disk will deal with actual partitioning.
2700 */
2702 ((LONGLONG)(lastSector.QuadPart + 1)) << fdoExt->SectorShift;
2703
2704 /*
2705 * Is this removable or fixed media
2706 */
2707 if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)){
2709 }
2710 else {
2712 }
2713
2714}
ULONG ClasspCalculateLogicalSectorSize(_In_ PDEVICE_OBJECT Fdo, _In_ ULONG BytesPerBlockInBigEndian)
Definition: utils.c:1483
#define WHICH_BIT(Data, Bit)
Definition: tools.h:80
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:405
ULONG TracksPerCylinder
Definition: ntdddisk.h:407
ULONG SectorsPerTrack
Definition: ntdddisk.h:408

Referenced by ClassReadDriveCapacity().

◆ InterpretSenseInfoWithoutHistory()

BOOLEAN InterpretSenseInfoWithoutHistory ( _In_ PDEVICE_OBJECT  Fdo,
_In_opt_ PIRP  OriginalRequest,
_In_ PSCSI_REQUEST_BLOCK  Srb,
UCHAR  MajorFunctionCode,
ULONG  IoDeviceCode,
ULONG  PreviousRetryCount,
_Out_ NTSTATUS Status,
_Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG RetryIn100nsUnits 
)

Definition at line 12844 of file class.c.

12855{
12856 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
12857 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
12858 LONGLONG tmpRetry = 0;
12859 BOOLEAN retry = FALSE;
12860
12861 if (fdoData->InterpretSenseInfo != NULL)
12862 {
12863 SCSI_REQUEST_BLOCK tempSrb = {0};
12864 PSCSI_REQUEST_BLOCK srbPtr = Srb;
12865
12866 // SAL annotations and ClassInitializeEx() both validate this
12868
12869 //
12870 // If class driver does not support extended SRB and this is
12871 // an extended SRB, convert to legacy SRB and pass to class
12872 // driver.
12873 //
12875 ((fdoExtension->CommonExtension.DriverExtension->SrbSupport &
12878 srbPtr = &tempSrb;
12879 }
12880
12881 retry = fdoData->InterpretSenseInfo->Interpret(Fdo,
12883 srbPtr,
12887 NULL,
12888 Status,
12889 &tmpRetry);
12890 }
12891 else
12892 {
12893 ULONG seconds = 0;
12894
12896 Srb,
12900 Status,
12901 &seconds);
12902 tmpRetry = ((LONGLONG)seconds) * 1000 * 1000 * 10;
12903 }
12904
12905
12906 if (RetryIn100nsUnits != NULL)
12907 {
12908 *RetryIn100nsUnits = tmpRetry;
12909 }
12910 return retry;
12911}
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN _In_opt_ WDFREQUEST OriginalRequest
Definition: cdrom.h:994
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR _In_ ULONG _In_ ULONG PreviousRetryCount
Definition: classpnp.h:486
__callback PCLASS_INTERPRET_SENSE_INFO Interpret
Definition: classpnp.h:566
PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo
Definition: classp.h:958

Referenced by ClassIoComplete(), ClassIoCompleteAssociated(), ClasspInitializeGesn(), ClasspMediaChangeDetectionCompletion(), ClasspPowerDownCompletion(), ClasspPowerUpCompletion(), and ClassSendSrbSynchronous().

◆ ServiceTransferRequest()

NTSTATUS ServiceTransferRequest ( PDEVICE_OBJECT  Fdo,
PIRP  Irp,
BOOLEAN  PostToDpc 
)

Definition at line 3341 of file class.c.

3371{
3372 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
3373 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
3374 PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExtension->PartitionZeroExtension->AdapterDescriptor;
3375 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
3377 BOOLEAN deferClientIrp = FALSE;
3378 BOOLEAN driverUsesStartIO = (commonExtension->DriverExtension->InitData.ClassStartIo != NULL);
3379 KIRQL oldIrql;
3382
3383 /*
3384 * Initialize IRP status for the master IRP to
3385 * - STATUS_FT_READ_FROM_COPY if it's a copy-specific read
3386 * - STATUS_SUCCESS otherwise.
3387 *
3388 * This is required. When Classpnp determines the status for the master IRP
3389 * when completing child IRPs, the call to IoSetMasterIrpStatus
3390 * will be functioning properly (See TransferPktComplete function)
3391 *
3392 * Note:
3393 * If the IRP is a copy-specific read, File System already initialized the IRP status
3394 * to be STATUS_FT_READ_FROM_COPY. However, this can be changed when the IRP arrives
3395 * at Classpnp. It's possible that other drivers in the stack may initialize the
3396 * IRP status field to other values before forwarding the IRP down the stack.
3397 * To be defensive, we initialize the IRP status to either STATUS_FT_READ_FROM_COPY
3398 * if it's a copy-specific read, or STATUS_SUCCESS otherwise.
3399 */
3400 if (currentIrpStack->MajorFunction == IRP_MJ_READ &&
3401 TEST_FLAG(currentIrpStack->Flags, SL_KEY_SPECIFIED) &&
3402 IsKeyReadCopyNumber(currentIrpStack->Parameters.Read.Key)) {
3403 Irp->IoStatus.Status = STATUS_FT_READ_FROM_COPY;
3404 } else {
3405 Irp->IoStatus.Status = STATUS_SUCCESS;
3406 }
3407
3408 //
3409 // If this is a high priority request, hold off all other Io requests
3410 //
3411
3413 {
3414 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
3415
3416 if (fdoData->NumHighPriorityPagingIo == 0)
3417 {
3418 //
3419 // Entering throttle mode
3420 //
3421
3423 }
3424
3425 fdoData->NumHighPriorityPagingIo++;
3427
3428 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
3429 }
3430 else
3431 {
3432 if (fdoData->NumHighPriorityPagingIo != 0)
3433 {
3434 //
3435 // This request wasn't flagged as critical and atleast one critical request
3436 // is currently outstanding. Queue this request until all of those are done
3437 // but only if the interleave threshold has been reached
3438 //
3439
3440 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
3441
3442 if (fdoData->NumHighPriorityPagingIo != 0)
3443 {
3444 if (fdoData->MaxInterleavedNormalIo == 0)
3445 {
3446 deferClientIrp = TRUE;
3447 }
3448 else
3449 {
3450 fdoData->MaxInterleavedNormalIo--;
3451 }
3452 }
3453
3454 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
3455 }
3456 }
3457
3458 if (!deferClientIrp)
3459 {
3461 ULONG entireXferLen = currentSp->Parameters.Read.Length;
3462 PUCHAR bufPtr = MmGetMdlVirtualAddress(Irp->MdlAddress);
3463 LARGE_INTEGER targetLocation = currentSp->Parameters.Read.ByteOffset;
3464 PTRANSFER_PACKET pkt;
3465 SINGLE_LIST_ENTRY pktList;
3466 PSINGLE_LIST_ENTRY slistEntry;
3467 ULONG hwMaxXferLen;
3468 ULONG numPackets;
3469 ULONG i;
3470
3471
3472 /*
3473 * We precomputed fdoData->HwMaxXferLen using (MaximumPhysicalPages-1).
3474 * If the buffer is page-aligned, that's one less page crossing so we can add the page back in.
3475 * Note: adapters that return MaximumPhysicalPages=0x10 depend on this to
3476 * transfer aligned 64K requests in one piece.
3477 * Also note: make sure adding PAGE_SIZE back in doesn't wrap to zero.
3478 */
3479 if (((ULONG_PTR)bufPtr & (PAGE_SIZE-1)) || (fdoData->HwMaxXferLen > 0xffffffff-PAGE_SIZE)){
3480 hwMaxXferLen = fdoData->HwMaxXferLen;
3481 }
3482 else {
3484 hwMaxXferLen = min(fdoData->HwMaxXferLen+PAGE_SIZE, adapterDesc->MaximumTransferLength);
3485 }
3486
3487 /*
3488 * Compute the number of hw xfers we'll have to do.
3489 * Calculate this without allowing for an overflow condition.
3490 */
3491 NT_ASSERT(hwMaxXferLen >= PAGE_SIZE);
3492 numPackets = entireXferLen/hwMaxXferLen;
3493 if (entireXferLen % hwMaxXferLen){
3494 numPackets++;
3495 }
3496
3497 /*
3498 * Use our 'simple' slist functions since we don't need interlocked.
3499 */
3500 SimpleInitSlistHdr(&pktList);
3501
3502 if (driverUsesStartIO) {
3503 /*
3504 * special case: StartIO-based writing must stay serialized, so just
3505 * re-use one packet.
3506 */
3508 if (pkt) {
3510 i = 1;
3511 } else {
3512 i = 0;
3513 }
3514 } else {
3515 /*
3516 * First get all the TRANSFER_PACKETs that we'll need at once.
3517 */
3518 for (i = 0; i < numPackets; i++){
3520 if (pkt){
3522 }
3523 else {
3524 break;
3525 }
3526 }
3527 }
3528
3529
3530 if ((i == numPackets) &&
3531 (!driverUsesStartIO)) {
3532 NTSTATUS pktStat;
3533
3534 /*
3535 * The IoStatus.Information field will be incremented to the
3536 * transfer length as the pieces complete.
3537 */
3538 Irp->IoStatus.Information = 0;
3539
3540 /*
3541 * Store the number of transfer pieces inside the original IRP.
3542 * It will be used to count down the pieces as they complete.
3543 */
3544 Irp->Tail.Overlay.DriverContext[0] = LongToPtr(numPackets);
3545
3546 /*
3547 * For the common 1-packet case, we want to allow for an optimization by BlkCache
3548 * (and also potentially synchronous storage drivers) which may complete the
3549 * downward request synchronously.
3550 * In that synchronous completion case, we want to _not_ mark the original irp pending
3551 * and thereby save on the top-level APC.
3552 * It's critical to coordinate this with the completion routine so that we mark the original irp
3553 * pending if-and-only-if we return STATUS_PENDING for it.
3554 */
3555 if (numPackets > 1){
3558 }
3559 else {
3561 }
3562
3563 /*
3564 * Transmit the pieces of the transfer.
3565 */
3566 while (entireXferLen > 0){
3567 ULONG thisPieceLen = MIN(hwMaxXferLen, entireXferLen);
3568
3569 /*
3570 * Set up a TRANSFER_PACKET for this piece and send it.
3571 */
3572 slistEntry = SimplePopSlist(&pktList);
3573 NT_ASSERT(slistEntry);
3574 pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
3576 bufPtr,
3577 thisPieceLen,
3578 targetLocation,
3579 Irp);
3580
3581 //
3582 // If the IRP needs to be split, then we need to use a partial MDL.
3583 // This prevents problems if the same MDL is mapped multiple times.
3584 //
3585 if (numPackets > 1) {
3586 pkt->UsePartialMdl = TRUE;
3587 }
3588
3589 /*
3590 * When an IRP is completed, the completion routine checks to see if there
3591 * is a deferred IRP ready to sent down (assuming that there are no non-idle
3592 * requests waiting to be serviced). If such a deferred IRP is available, it
3593 * is sent down using this routine. However, if the lower driver completes
3594 * the request inline, there is a potential for multiple deferred IRPs being
3595 * sent down in the context of the same completion thread, thus exhausting
3596 * the call stack.
3597 * In order to prevent this from happening, we need to ensure that deferred
3598 * IRPs that are dequeued in the context of a request's completion routine
3599 * get posted to a DPC.
3600 */
3601 if (PostToDpc) {
3602
3603 pkt->RetryIn100nsUnits = 0;
3606
3607 } else {
3608
3609 pktStat = SubmitTransferPacket(pkt);
3610
3611 /*
3612 * If any of the packets completes with pending, we MUST return pending.
3613 * Also, if a packet completes with an error, return pending; this is because
3614 * in the completion routine we mark the original irp pending if the packet failed
3615 * (since we may retry, thereby switching threads).
3616 */
3617 if (pktStat != STATUS_SUCCESS){
3619 }
3620 }
3621
3622 entireXferLen -= thisPieceLen;
3623 bufPtr += thisPieceLen;
3624 targetLocation.QuadPart += thisPieceLen;
3625 }
3626 NT_ASSERT(SimpleIsSlistEmpty(&pktList));
3627 }
3628 else if (i >= 1){
3629 /*
3630 * We were unable to get all the TRANSFER_PACKETs we need,
3631 * but we did get at least one.
3632 * That means that we are in extreme low-memory stress.
3633 * We'll try doing this transfer using a single packet.
3634 * The port driver is certainly also in stress, so use one-page
3635 * transfers.
3636 */
3637
3638 /*
3639 * Free all but one of the TRANSFER_PACKETs.
3640 */
3641 while (i-- > 1){
3642 slistEntry = SimplePopSlist(&pktList);
3643 NT_ASSERT(slistEntry);
3644 pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
3646 }
3647
3648 /*
3649 * Get the single TRANSFER_PACKET that we'll be using.
3650 */
3651 slistEntry = SimplePopSlist(&pktList);
3652 NT_ASSERT(slistEntry);
3653 NT_ASSERT(SimpleIsSlistEmpty(&pktList));
3654 pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
3655
3656 if (!driverUsesStartIO) {
3657 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Insufficient packets available in ServiceTransferRequest - entering lowMemRetry with pkt=%p.", pkt));
3658 }
3659
3660 /*
3661 * Set the number of transfer packets (one)
3662 * inside the original irp.
3663 */
3664 Irp->IoStatus.Information = 0;
3665 Irp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
3667
3668 /*
3669 * Set up the TRANSFER_PACKET for a lowMem transfer and launch.
3670 */
3672 bufPtr,
3673 entireXferLen,
3674 targetLocation,
3675 Irp);
3676
3677 InitLowMemRetry(pkt, bufPtr, entireXferLen, targetLocation);
3678 StepLowMemRetry(pkt);
3680 }
3681 else {
3682 /*
3683 * We were unable to get ANY TRANSFER_PACKETs.
3684 * Defer this client irp until some TRANSFER_PACKETs free up.
3685 */
3686 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "No packets available in ServiceTransferRequest - deferring transfer (Irp=%p)...", Irp));
3687
3689 {
3690 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
3691
3693 {
3694 fdoData->MaxInterleavedNormalIo = 0;
3695 }
3696 else
3697 {
3699 }
3700
3701 fdoData->NumHighPriorityPagingIo--;
3702
3703 if (fdoData->NumHighPriorityPagingIo == 0)
3704 {
3705 LARGE_INTEGER period;
3706
3707 //
3708 // Exiting throttle mode
3709 //
3710
3712
3713 period.QuadPart = fdoData->ThrottleStopTime.QuadPart - fdoData->ThrottleStartTime.QuadPart;
3715 }
3716
3717 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
3718 }
3719
3720 deferClientIrp = TRUE;
3721 }
3722 }
3723 _Analysis_assume_(deferClientIrp);
3724 if (deferClientIrp)
3725 {
3729 }
3730
3732
3733 return status;
3734}
#define MIN(x, y)
Definition: rdesktop.h:171
BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt)
Definition: retry.c:706
FORCEINLINE VOID SimpleInitSlistHdr(SINGLE_LIST_ENTRY *SListHdr)
Definition: classp.h:1211
FORCEINLINE SINGLE_LIST_ENTRY * SimplePopSlist(SINGLE_LIST_ENTRY *SListHdr)
Definition: classp.h:1220
VOID EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, __drv_aliasesMem PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:529
FORCEINLINE BOOLEAN SimpleIsSlistEmpty(SINGLE_LIST_ENTRY *SListHdr)
Definition: classp.h:1229
FORCEINLINE VOID SimplePushSlist(SINGLE_LIST_ENTRY *SListHdr, SINGLE_LIST_ENTRY *SListEntry)
Definition: classp.h:1215
VOID EnqueueDeferredClientIrp(PDEVICE_OBJECT Fdo, PIRP Irp)
Definition: clntirp.c:78
VOID TransferPacketQueueRetryDpc(PTRANSFER_PACKET Pkt)
Definition: retry.c:604
VOID InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation)
Definition: retry.c:670
VOID SetupReadWriteTransferPacket(PTRANSFER_PACKET pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp)
Definition: xferpkt.c:718
ULONG ClassMaxInterleavePerCriticalIo
Definition: class.c:88
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
static int priority
Definition: timer.c:163
#define IsKeyReadCopyNumber(_k)
Definition: ntddstor.h:1072
* PSTORAGE_ADAPTER_DESCRIPTOR
Definition: ntddstor.h:599
IO_PAGING_PRIORITY FASTCALL IoGetPagingIoPriority(IN PIRP Irp)
Definition: irp.c:1748
#define STATUS_FT_READ_FROM_COPY
Definition: ntstatus.h:167
ULONG MaxInterleavedNormalIo
Definition: classp.h:831
LARGE_INTEGER LongestThrottlePeriod
Definition: classp.h:846
LARGE_INTEGER ThrottleStartTime
Definition: classp.h:836
ULONG NumHighPriorityPagingIo
Definition: classp.h:826
LARGE_INTEGER ThrottleStopTime
Definition: classp.h:841
Definition: ntbasedef.h:628
SLIST_ENTRY SlistEntry
Definition: classp.h:500
BOOLEAN UsePartialMdl
Definition: classp.h:595
enum _IO_PAGING_PRIORITY IO_PAGING_PRIORITY
#define SL_KEY_SPECIFIED
Definition: iotypes.h:1822
@ IoPagingPriorityHigh
Definition: iotypes.h:2822
@ IoPagingPriorityInvalid
Definition: iotypes.h:2820

Referenced by ClasspServiceIdleRequest(), ClassReadWrite(), ClassSplitRequest(), and TransferPktComplete().

Variable Documentation

◆ ClassCheckVerifyComplete

IO_COMPLETION_ROUTINE ClassCheckVerifyComplete

Definition at line 84 of file class.c.

Referenced by ClassDeviceControl().

◆ ClassMaxInterleavePerCriticalIo

ULONG ClassMaxInterleavePerCriticalIo = CLASS_MAX_INTERLEAVE_PER_CRITICAL_IO

Definition at line 88 of file class.c.

Referenced by ServiceTransferRequest(), and TransferPktComplete().

◆ ClassPnpAllowUnload

ULONG ClassPnpAllowUnload = TRUE

Definition at line 87 of file class.c.

Referenced by _IRQL_requires_max_().

◆ DiskIdleTimeoutInMS

ULONG DiskIdleTimeoutInMS = 0xFFFFFFFF

Definition at line 132 of file class.c.

Referenced by _Function_class_(), and ClasspEnableIdlePower().

◆ IdlePowerFDOList

LIST_ENTRY IdlePowerFDOList = {0}

Definition at line 113 of file class.c.

Referenced by _Function_class_(), _IRQL_requires_max_(), and ClasspEnableIdlePower().

◆ IdlePowerFDOListMutex

KGUARDED_MUTEX IdlePowerFDOListMutex

Definition at line 114 of file class.c.

Referenced by _Function_class_(), _IRQL_requires_max_(), and ClasspEnableIdlePower().

◆ InitSecurityCookie

BOOLEAN InitSecurityCookie = FALSE

Definition at line 102 of file class.c.

Referenced by _IRQL_requires_max_().

◆ Magic10000

CONST LARGE_INTEGER Magic10000 = {{0xe219652c, 0xd1b71758}}

Definition at line 89 of file class.c.

◆ MaxTokenOperationListIdentifier

ULONG MaxTokenOperationListIdentifier = MAX_TOKEN_LIST_IDENTIFIERS

Definition at line 107 of file class.c.

Referenced by _IRQL_requires_(), and ClasspContinueOffloadWrite().

◆ PowerSettingNotificationHandle

PVOID PowerSettingNotificationHandle

Definition at line 119 of file class.c.

Referenced by ClasspEnableIdlePower(), and DllUnload().

◆ ScreenStateNotificationHandle

PVOID ScreenStateNotificationHandle

Definition at line 124 of file class.c.

Referenced by ClasspInitializePolling(), and DllUnload().

◆ StoragePredictFailureDPSGuid

GUID StoragePredictFailureDPSGuid = WDI_STORAGE_PREDICT_FAILURE_DPS_GUID

Definition at line 90 of file class.c.

Referenced by _IRQL_requires_max_().

◆ TokenOperationListIdentifier

volatile ULONG TokenOperationListIdentifier = (ULONG)-1

Definition at line 108 of file class.c.

Referenced by ClasspContinueOffloadWrite().

◆ UseQPCTime

BOOLEAN UseQPCTime = FALSE

Definition at line 95 of file class.c.