ReactOS 0.4.16-dev-292-gbbdcc14
classp.h File Reference
#include <stddef.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ntddk.h>
#include <scsi.h>
#include <wmidata.h>
#include <classpnp.h>
#include <storduid.h>
#include <mountdev.h>
#include <ioevent.h>
#include <ntstrsafe.h>
#include <ntintsafe.h>
#include <wdmguid.h>
#include <ntpoapi.h>
#include <srbhelper.h>
#include <storswtr.h>
Include dependency graph for classp.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _MEDIA_CHANGE_DETECTION_INFO
 
struct  _FAILURE_PREDICTION_INFO
 
struct  _CLASS_RETRY_INFO
 
struct  _CSCAN_LIST
 
struct  _CLASS_ERROR_LOG_DATA
 
struct  _TRANSFER_PACKET
 
struct  _PNL_SLIST_HEADER
 
struct  _CLASS_PRIVATE_FDO_DATA
 
struct  _CLASS_PRIVATE_COMMON_DATA
 
struct  _IDLE_POWER_FDO_LIST_ENTRY
 
struct  _OFFLOAD_READ_CONTEXT
 
struct  _OFFLOAD_WRITE_CONTEXT
 
struct  _OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER
 
struct  _IO_RETRIED_LOG_MESSAGE_CONTEXT
 

Macros

#define RTL_USE_AVL_TABLES   0
 
#define DEBUG_COMP_ID   DPFLTR_CLASSPNP_ID
 
#define WPP_GUID_CLASSPNP   (FA8DE7C4, ACDE, 4443, 9994, C4E2359A9EDB)
 
#define WPP_CONTROL_GUIDS   WPP_CONTROL_GUIDS_NORMAL_FLAGS(WPP_GUID_CLASSPNP)
 
#define PTRALIGN
 
#define Add2Ptr(P, I)   ((PVOID)((PUCHAR)(P) + (I)))
 
#define CLASSP_REG_SUBKEY_NAME   (L"Classpnp")
 
#define CLASSP_REG_HACK_VALUE_NAME   (L"HackMask")
 
#define CLASSP_REG_MMC_DETECTION_VALUE_NAME   (L"MMCDetectionState")
 
#define CLASSP_REG_WRITE_CACHE_VALUE_NAME   (L"WriteCacheEnableOverride")
 
#define CLASSP_REG_PERF_RESTORE_VALUE_NAME   (L"RestorePerfAtCount")
 
#define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME   (L"UserRemovalPolicy")
 
#define CLASSP_REG_IDLE_INTERVAL_NAME   (L"IdleInterval")
 
#define CLASSP_REG_IDLE_ACTIVE_MAX   (L"IdleOutstandingIoMax")
 
#define CLASSP_REG_IDLE_PRIORITY_SUPPORTED   (L"IdlePrioritySupported")
 
#define CLASSP_REG_ACCESS_ALIGNMENT_NOT_SUPPORTED   (L"AccessAlignmentQueryNotSupported")
 
#define CLASSP_REG_DISBALE_IDLE_POWER_NAME   (L"DisableIdlePowerManagement")
 
#define CLASSP_REG_IDLE_TIMEOUT_IN_SECONDS   (L"IdleTimeoutInSeconds")
 
#define CLASSP_REG_DISABLE_D3COLD   (L"DisableD3Cold")
 
#define CLASSP_REG_QERR_OVERRIDE_MODE   (L"QERROverrideMode")
 
#define CLASSP_REG_LEGACY_ERROR_HANDLING   (L"LegacyErrorHandling")
 
#define CLASSP_REG_COPY_OFFLOAD_MAX_TARGET_DURATION   (L"CopyOffloadMaxTargetDuration")
 
#define CLASS_PERF_RESTORE_MINIMUM   (0x10)
 
#define CLASS_ERROR_LEVEL_1   (0x4)
 
#define CLASS_ERROR_LEVEL_2   (0x8)
 
#define CLASS_MAX_INTERLEAVE_PER_CRITICAL_IO   (0x4)
 
#define FDO_HACK_CANNOT_LOCK_MEDIA   (0x00000001)
 
#define FDO_HACK_GESN_IS_BAD   (0x00000002)
 
#define FDO_HACK_NO_SYNC_CACHE   (0x00000004)
 
#define FDO_HACK_NO_RESERVE6   (0x00000008)
 
#define FDO_HACK_GESN_IGNORE_OPCHANGE   (0x00000010)
 
#define FDO_HACK_VALID_FLAGS   (0x0000001F)
 
#define FDO_HACK_INVALID_FLAGS   (~FDO_HACK_VALID_FLAGS)
 
#define NUM_LOCKMEDIAREMOVAL_RETRIES   1
 
#define NUM_MODESENSE_RETRIES   1
 
#define NUM_MODESELECT_RETRIES   1
 
#define NUM_DRIVECAPACITY_RETRIES   1
 
#define NUM_THIN_PROVISIONING_RETRIES   32
 
#define NUM_IO_RETRIES   MAXIMUM_RETRIES
 
#define LEGACY_NUM_IO_RETRIES   8
 
#define CLASS_FILE_OBJECT_EXTENSION_KEY   'eteP'
 
#define CLASSP_VOLUME_VERIFY_CHECKED   0x34
 
#define CLASS_TAG_PRIVATE_DATA   'CPcS'
 
#define CLASS_TAG_SENSE2   '2ScS'
 
#define CLASS_TAG_WORKING_SET   'sWcS'
 
#define CLASSPNP_POOL_TAG_GENERIC   'pCcS'
 
#define CLASSPNP_POOL_TAG_TOKEN_OPERATION   'oTcS'
 
#define CLASSPNP_POOL_TAG_SRB   'rScS'
 
#define CLASSPNP_POOL_TAG_VPD   'pVcS'
 
#define CLASSPNP_POOL_TAG_LOG_MESSAGE   'mlcS'
 
#define CLASSPNP_POOL_TAG_ADDITIONAL_DATA   'DAcS'
 
#define CLASSPNP_POOL_TAG_FIRMWARE   'wFcS'
 
#define MAX_LIST_IDENTIFIER   MAXULONG
 
#define NUM_POPULATE_TOKEN_RETRIES   1
 
#define NUM_WRITE_USING_TOKEN_RETRIES   2
 
#define NUM_RECEIVE_TOKEN_INFORMATION_RETRIES   2
 
#define MAX_TOKEN_OPERATION_PARAMETER_DATA_LENGTH   MAXUSHORT
 
#define MAX_RECEIVE_TOKEN_INFORMATION_PARAMETER_DATA_LENGTH   MAXULONG
 
#define MAX_TOKEN_TRANSFER_SIZE   MAXULONGLONG
 
#define MAX_NUMBER_BLOCKS_PER_BLOCK_DEVICE_RANGE_DESCRIPTOR   MAXULONG
 
#define DEFAULT_MAX_TARGET_DURATION   4
 
#define DEFAULT_MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN   (64ULL * 1024 * 1024)
 
#define MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN   (256ULL * 1024 * 1024)
 
#define MIN_TOKEN_LIST_IDENTIFIERS   256
 
#define MAX_TOKEN_LIST_IDENTIFIERS   MAXULONG
 
#define MAX_NUMBER_BLOCK_DEVICE_DESCRIPTORS   64
 
#define REG_DISK_CLASS_CONTROL   L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\DISK"
 
#define REG_MAX_LIST_IDENTIFIER_VALUE   L"MaximumListIdentifier"
 
#define VPD_PAGE_HEADER_SIZE   0x04
 
#define GET_LBA_STATUS_RETRY_COUNT_MAX   (2)
 
#define SHIFT10000   13
 
#define CONST_MSECS_PER_SEC   1000
 
#define Convert100nsToMilliseconds(LARGE_INTEGER)
 
#define ConvertMillisecondsTo100ns(MILLISECONDS)
 
#define NUM_ERROR_LOG_ENTRIES   16
 
#define DBG_NUM_PACKET_LOG_ENTRIES   (64*2)
 
#define MIN_INITIAL_TRANSFER_PACKETS   1
 
#define MIN_WORKINGSET_TRANSFER_PACKETS_Client   16
 
#define MAX_WORKINGSET_TRANSFER_PACKETS_Client   32
 
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server_UpperBound   256
 
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound   32
 
#define MAX_WORKINGSET_TRANSFER_PACKETS_Server   1024
 
#define MIN_WORKINGSET_TRANSFER_PACKETS_SPACES   512
 
#define MAX_WORKINGSET_TRANSFER_PACKETS_SPACES   2048
 
#define MAX_OUTSTANDING_IO_PER_LUN_DEFAULT   16
 
#define MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE   8192
 
#define QERR_SET_ZERO_ODX_OR_TP_ONLY   0
 
#define QERR_SET_ZERO_ALWAYS   1
 
#define QERR_SET_ZERO_NEVER   2
 
#define MIN(a, b)   ((a) < (b) ? (a) : (b))
 
#define MAX(a, b)   ((a) > (b) ? (a) : (b))
 
#define NOT_READY_RETRY_INTERVAL   10
 
#define MINIMUM_RETRY_UNITS   ((LONGLONG)32)
 
#define MODE_PAGE_DATA_SIZE   192
 
#define CLASS_IDLE_INTERVAL_MIN   12
 
#define CLASS_IDLE_INTERVAL   12
 
#define CLASS_STARVATION_INTERVAL   500
 
#define FIFTY_MS_IN_100NS_UNITS   50 * 100
 
#define HISTORYINITIALIZERETRYLOGS(_packet)
 
#define HISTORYLOGSENDPACKET(_packet)
 
#define HISTORYLOGRETURNEDPACKET(_packet)
 
#define TRACKING_FORWARD_PROGRESS_PATH1   (0x00000001)
 
#define TRACKING_FORWARD_PROGRESS_PATH2   (0x00000002)
 
#define TRACKING_FORWARD_PROGRESS_PATH3   (0x00000004)
 

Typedefs

typedef struct _MEDIA_CHANGE_DETECTION_INFO MEDIA_CHANGE_DETECTION_INFO
 
typedef struct _MEDIA_CHANGE_DETECTION_INFOPMEDIA_CHANGE_DETECTION_INFO
 
typedef enum MEDIA_LOCK_TYPEPMEDIA_LOCK_TYPE
 
typedef struct _FAILURE_PREDICTION_INFO FAILURE_PREDICTION_INFO
 
typedef struct _FAILURE_PREDICTION_INFOPFAILURE_PREDICTION_INFO
 
typedef struct _CLASS_RETRY_INFO CLASS_RETRY_INFO
 
typedef struct _CLASS_RETRY_INFOPCLASS_RETRY_INFO
 
typedef struct _CSCAN_LIST CSCAN_LIST
 
typedef struct _CSCAN_LISTPCSCAN_LIST
 
typedef enum _CLASS_DETECTION_STATE CLASS_DETECTION_STATE
 
typedef enum _CLASS_DETECTION_STATEPCLASS_DETECTION_STATE
 
typedef struct _CLASS_ERROR_LOG_DATA CLASS_ERROR_LOG_DATA
 
typedef struct _CLASS_ERROR_LOG_DATAPCLASS_ERROR_LOG_DATA
 
typedef VOID(* PCONTINUATION_ROUTINE) (_In_ PVOID Context)
 
typedef struct _TRANSFER_PACKET TRANSFER_PACKET
 
typedef struct _TRANSFER_PACKETPTRANSFER_PACKET
 
typedef struct _PNL_SLIST_HEADER PNL_SLIST_HEADER
 
typedef struct _PNL_SLIST_HEADERPPNL_SLIST_HEADER
 
typedef struct _IDLE_POWER_FDO_LIST_ENTRY IDLE_POWER_FDO_LIST_ENTRY
 
typedef struct _IDLE_POWER_FDO_LIST_ENTRYPIDLE_POWER_FDO_LIST_ENTRY
 
typedef struct _OFFLOAD_READ_CONTEXT OFFLOAD_READ_CONTEXT
 
typedef struct _OFFLOAD_READ_CONTEXTPOFFLOAD_READ_CONTEXT
 
typedef struct _OFFLOAD_WRITE_CONTEXT OFFLOAD_WRITE_CONTEXT
 
typedef struct _OFFLOAD_WRITE_CONTEXTPOFFLOAD_WRITE_CONTEXT
 
typedef struct _OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER
 
typedef struct _OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADERPOPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER
 
typedef struct _IO_RETRIED_LOG_MESSAGE_CONTEXT IO_RETRIED_LOG_MESSAGE_CONTEXT
 
typedef struct _IO_RETRIED_LOG_MESSAGE_CONTEXTPIO_RETRIED_LOG_MESSAGE_CONTEXT
 
typedef PVOID(* PSRB_ALLOCATE_ROUTINE) (_In_ CLONG ByteSize)
 

Enumerations

enum  MEDIA_LOCK_TYPE {
  SimpleMediaLock , SecureMediaLock , InternalMediaLock , SimpleMediaLock ,
  SecureMediaLock , InternalMediaLock
}
 
enum  _CLASS_DETECTION_STATE { ClassDetectionUnknown = 0 , ClassDetectionUnsupported = 1 , ClassDetectionSupported = 2 }
 

Functions

 C_ASSERT ((sizeof(struct _CLASS_PRIVATE_COMMON_DATA) % sizeof(PVOID))==0)
 
FORCEINLINE VOID SimpleInitSlistHdr (SINGLE_LIST_ENTRY *SListHdr)
 
FORCEINLINE VOID SimplePushSlist (SINGLE_LIST_ENTRY *SListHdr, SINGLE_LIST_ENTRY *SListEntry)
 
FORCEINLINE SINGLE_LIST_ENTRYSimplePopSlist (SINGLE_LIST_ENTRY *SListHdr)
 
FORCEINLINE BOOLEAN SimpleIsSlistEmpty (SINGLE_LIST_ENTRY *SListHdr)
 
FORCEINLINE BOOLEAN ClasspIsIdleRequestSupported (PCLASS_PRIVATE_FDO_DATA FdoData, PIRP Irp)
 
FORCEINLINE VOID ClasspMarkIrpAsIdle (PIRP Irp, BOOLEAN Idle)
 
FORCEINLINE BOOLEAN ClasspIsIdleRequest (PIRP Irp)
 
FORCEINLINE LARGE_INTEGER ClasspGetCurrentTime (VOID)
 
FORCEINLINE ULONGLONG ClasspTimeDiffToMs (ULONGLONG TimeDiff)
 
FORCEINLINE BOOLEAN ClasspSupportsUnmap (_In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo)
 
FORCEINLINE BOOLEAN ClasspIsThinProvisioned (_In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo)
 
FORCEINLINE BOOLEAN ClasspIsObsoletePortDriver (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
ULONG ClasspCalculateLogicalSectorSize (_In_ PDEVICE_OBJECT Fdo, _In_ ULONG BytesPerBlockInBigEndian)
 
 _Dispatch_type_ (IRP_MJ_CREATE) _Dispatch_type_(IRP_MJ_CLOSE) DRIVER_DISPATCH ClassCreateClose
 
NTSTATUS ClasspCreateClose (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
VOID ClasspCleanupProtectedLocks (IN PFILE_OBJECT_EXTENSION FsContext)
 
NTSTATUS ClasspEjectionControl (IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN MEDIA_LOCK_TYPE LockType, IN BOOLEAN Lock)
 
 _Dispatch_type_ (IRP_MJ_READ) _Dispatch_type_(IRP_MJ_WRITE) DRIVER_DISPATCH ClassReadWrite
 
 _Dispatch_type_ (IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH ClassDeviceControlDispatch
 
 _Dispatch_type_ (IRP_MJ_PNP) DRIVER_DISPATCH ClassDispatchPnp
 
NTSTATUS ClassPnpStartDevice (IN PDEVICE_OBJECT DeviceObject)
 
 _Dispatch_type_ (IRP_MJ_SHUTDOWN) _Dispatch_type_(IRP_MJ_FLUSH_BUFFERS) DRIVER_DISPATCH ClassShutdownFlush
 
 _Dispatch_type_ (IRP_MJ_SYSTEM_CONTROL) DRIVER_DISPATCH ClassSystemControl
 
VOID RetryRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp, PSCSI_REQUEST_BLOCK Srb, BOOLEAN Associated, LONGLONG TimeDelta100ns)
 
NTSTATUS ClassIoCompletion (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 PhysicalDeviceObject, IN PDEVICE_CAPABILITIES Capabilities)
 
NTSTATUS ClasspPagingNotificationCompletion (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_OBJECT RealDeviceObject)
 
NTSTATUS ClasspMediaChangeCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
 
NTSTATUS ClasspMcnControl (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PIRP Irp, IN PSCSI_REQUEST_BLOCK Srb)
 
VOID ClasspRegisterMountedDeviceInterface (IN PDEVICE_OBJECT DeviceObject)
 
VOID ClasspDisableTimer (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClasspEnableTimer (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspInitializeTimer (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClasspDeleteTimer (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
BOOLEAN ClasspUpdateTimerNoWakeTolerance (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspDuidQueryProperty (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
VOID ClassInitializeDispatchTables (PCLASS_DRIVER_EXTENSION DriverExtension)
 
NTSTATUS ClasspPersistentReserve (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
VOID InitializeDictionary (IN PDICTIONARY Dictionary)
 
BOOLEAN TestDictionarySignature (IN PDICTIONARY Dictionary)
 
NTSTATUS AllocateDictionaryEntry (IN PDICTIONARY Dictionary, IN ULONGLONG Key, IN ULONG Size, IN ULONG Tag, OUT PVOID *Entry)
 
PVOID GetDictionaryEntry (IN PDICTIONARY Dictionary, IN ULONGLONG Key)
 
VOID FreeDictionaryEntry (IN PDICTIONARY Dictionary, IN PVOID Entry)
 
NTSTATUS ClasspAllocateReleaseRequest (IN PDEVICE_OBJECT Fdo)
 
VOID ClasspFreeReleaseRequest (IN PDEVICE_OBJECT Fdo)
 
VOID ClasspReleaseQueue (IN PDEVICE_OBJECT DeviceObject, IN PIRP ReleaseQueueIrp)
 
VOID ClasspDisablePowerNotification (PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
 _Dispatch_type_ (IRP_MJ_POWER) DRIVER_DISPATCH ClassDispatchPower
 
NTSTATUS NTAPI ClassMinimalPowerHandler (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
_IRQL_requires_same_ NTSTATUS ClasspEnableIdlePower (_In_ PDEVICE_OBJECT DeviceObject)
 
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 ClasspRetryDpcTimer (IN PCLASS_PRIVATE_FDO_DATA FdoData)
 
VOID ClassFreeOrReuseSrb (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN __drv_freesMem(mem) PSCSI_REQUEST_BLOCK Srb)
 
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 ClasspBuildRequestEx (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PIRP Irp, _In_ __drv_aliasesMem PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspAllocateReleaseQueueIrp (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspAllocatePowerProcessIrp (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspInitializeGesn (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info)
 
VOID ClassSendEjectionNotification (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClasspScanForSpecialInRegistry (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID NTAPI ClasspScanForClassHacks (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN ULONG_PTR Data)
 
NTSTATUS ClasspInitializeHotplugInfo (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClasspPerfIncrementErrorCount (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClasspPerfIncrementSuccessfulIo (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
 __drv_allocatesMem (Mem) PTRANSFER_PACKET NewTransferPacket(PDEVICE_OBJECT Fdo)
 
VOID DestroyTransferPacket (_In_ __drv_freesMem(mem) PTRANSFER_PACKET Pkt)
 
VOID EnqueueFreeTransferPacket (PDEVICE_OBJECT Fdo, __drv_aliasesMem PTRANSFER_PACKET Pkt)
 
PTRANSFER_PACKET DequeueFreeTransferPacket (PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
 
PTRANSFER_PACKET DequeueFreeTransferPacketEx (_In_ PDEVICE_OBJECT Fdo, _In_ BOOLEAN AllocIfNeeded, _In_ ULONG Node)
 
VOID SetupReadWriteTransferPacket (PTRANSFER_PACKET pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp)
 
NTSTATUS SubmitTransferPacket (PTRANSFER_PACKET Pkt)
 
NTSTATUS ServiceTransferRequest (PDEVICE_OBJECT Fdo, PIRP Irp, BOOLEAN PostToDpc)
 
VOID TransferPacketQueueRetryDpc (PTRANSFER_PACKET Pkt)
 
BOOLEAN InterpretTransferPacketError (PTRANSFER_PACKET Pkt)
 
BOOLEAN RetryTransferPacket (PTRANSFER_PACKET Pkt)
 
VOID EnqueueDeferredClientIrp (PDEVICE_OBJECT Fdo, PIRP Irp)
 
PIRP DequeueDeferredClientIrp (PDEVICE_OBJECT Fdo)
 
VOID InitLowMemRetry (PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation)
 
BOOLEAN StepLowMemRetry (PTRANSFER_PACKET Pkt)
 
VOID SetupEjectionTransferPacket (TRANSFER_PACKET *Pkt, BOOLEAN PreventMediaRemoval, PKEVENT SyncEventPtr, PIRP OriginalIrp)
 
VOID SetupModeSenseTransferPacket (TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, UCHAR SubPage, PIRP OriginalIrp, UCHAR PageControl)
 
VOID SetupModeSelectTransferPacket (TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSelectBuffer, UCHAR ModeSelectBufferLen, BOOLEAN SavePages, PIRP OriginalIrp)
 
VOID SetupDriveCapacityTransferPacket (TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp, BOOLEAN Use16ByteCdb)
 
PMDL BuildDeviceInputMdl (PVOID Buffer, ULONG BufferLen)
 
PMDL ClasspBuildDeviceMdl (PVOID Buffer, ULONG BufferLen, BOOLEAN WriteToDevice)
 
VOID FreeDeviceInputMdl (PMDL Mdl)
 
VOID ClasspFreeDeviceMdl (PMDL Mdl)
 
NTSTATUS InitializeTransferPackets (PDEVICE_OBJECT Fdo)
 
VOID DestroyAllTransferPackets (PDEVICE_OBJECT Fdo)
 
VOID InterpretCapacityData (PDEVICE_OBJECT Fdo, PREAD_CAPACITY_DATA_EX ReadCapacityData)
 
VOID CleanupTransferPacketToWorkingSetSize (_In_ PDEVICE_OBJECT Fdo, _In_ BOOLEAN LimitNumPktToDelete, _In_ ULONG Node)
 
 _IRQL_requires_max_ (APC_LEVEL) _IRQL_requires_min_(PASSIVE_LEVEL) _IRQL_requires_same_ VOID ClasspSetupPopulateTokenTransferPacket(_In_ __drv_aliasesMem POFFLOAD_READ_CONTEXT OffloadReadContext
 
_In_ PTRANSFER_PACKET _In_ ULONG _In_reads_bytes_ (Length) PUCHAR PopulateTokenBuffer
 
ULONG ClasspModeSense (_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ UCHAR PageControl)
 
NTSTATUS ClasspModeSelect (_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSelectBuffer, _In_ ULONG Length, _In_ BOOLEAN SavePages)
 
NTSTATUS ClasspWriteCacheProperty (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspAccessAlignmentProperty (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspDeviceSeekPenaltyProperty (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspDeviceGetLBProvisioningVPDPage (_In_ PDEVICE_OBJECT DeviceObject, _Inout_opt_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspDeviceGetBlockDeviceCharacteristicsVPDPage (_In_ PFUNCTIONAL_DEVICE_EXTENSION fdoExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspDeviceGetBlockLimitsVPDPage (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _Inout_bytecount_(SrbSize) PSCSI_REQUEST_BLOCK Srb, _In_ ULONG SrbSize, _Out_ PCLASS_VPD_B0_DATA BlockLimitsData)
 
NTSTATUS ClasspDeviceTrimProperty (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspDeviceLBProvisioningProperty (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspDeviceTrimProcess (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PGUID ActivityId, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspDeviceGetLBAStatus (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspDeviceGetLBAStatusWorker (_In_ PDEVICE_OBJECT DeviceObject, _In_ PCLASS_VPD_B0_DATA BlockLimitsData, _In_ ULONGLONG StartingOffset, _In_ ULONGLONG LengthInBytes, _Out_ PDEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT DsmOutput, _Inout_ PULONG DsmOutputLength, _Inout_ PSCSI_REQUEST_BLOCK Srb, _In_ BOOLEAN ConsolidateableBlocksOnly, _In_ ULONG OutputVersion, _Out_ PBOOLEAN BlockLimitsDataMayHaveChanged)
 
VOID ClassQueueThresholdEventWorker (_In_ PDEVICE_OBJECT DeviceObject)
 
VOID ClassQueueResourceExhaustionEventWorker (_In_ PDEVICE_OBJECT DeviceObject)
 
VOID ClassQueueCapacityChangedEventWorker (_In_ PDEVICE_OBJECT DeviceObject)
 
VOID ClassQueueProvisioningTypeChangedEventWorker (_In_ PDEVICE_OBJECT DeviceObject)
 
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)
 
VOID ClasspZeroQERR (_In_ PDEVICE_OBJECT DeviceObject)
 
 _IRQL_requires_max_ (PASSIVE_LEVEL) NTSTATUS ClasspGetMaximumTokenListIdentifier(_In_ PDEVICE_OBJECT DeviceObject
 
_IRQL_requires_same_ NTSTATUS ClasspGetTokenOperationCommandBufferLength (_In_ PDEVICE_OBJECT Fdo, _In_ ULONG ServiceAction, _Inout_ PULONG CommandBufferLength, _Out_opt_ PULONG TokenOperationBufferLength, _Out_opt_ PULONG ReceiveTokenInformationBufferLength)
 
_IRQL_requires_same_ NTSTATUS ClasspGetTokenOperationDescriptorLimits (_In_ PDEVICE_OBJECT Fdo, _In_ ULONG ServiceAction, _In_ ULONG MaxParameterBufferLength, _Out_ PULONG MaxBlockDescriptorsCount, _Out_ PULONGLONG MaxBlockDescriptorsLength)
 
NTSTATUS ClasspDeviceMediaTypeProperty (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
_IRQL_requires_same_ PUCHAR ClasspBinaryToAscii (_In_reads_(Length) PUCHAR HexBuffer, _In_ ULONG Length, _Inout_ PULONG UpdateLength)
 
FORCEINLINE BOOLEAN ClasspIsTokenOperationComplete (_In_ ULONG CurrentStatus)
 
FORCEINLINE BOOLEAN ClasspIsTokenOperation (_In_ PCDB Cdb)
 
FORCEINLINE BOOLEAN ClasspIsReceiveTokenInformation (_In_ PCDB Cdb)
 
FORCEINLINE BOOLEAN ClasspIsOffloadDataTransferCommand (_In_ PCDB Cdb)
 
VOID ClasspInitializeIdleTimer (PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspIsPortable (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _Out_ PBOOLEAN IsPortable)
 
VOID ClasspGetInquiryVpdSupportInfo (_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspGetLBProvisioningInfo (_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
 _IRQL_requires_ (PASSIVE_LEVEL) _IRQL_requires_same_ NTSTATUS ClassDetermineTokenOperationCommandSupport(_In_ PDEVICE_OBJECT DeviceObject)
 Sends a synchronous IOCTL to the specified device object.
 
_IRQL_requires_same_ NTSTATUS ClasspGetBlockDeviceTokenLimitsInfo (_Inout_ PDEVICE_OBJECT DeviceObject)
 
_IRQL_requires_same_ VOID ClasspReceivePopulateTokenInformation (_In_ POFFLOAD_READ_CONTEXT OffloadReadContext)
 
_IRQL_requires_same_ VOID ClasspReceiveWriteUsingTokenInformation (_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
 
VOID ClasspCompleteOffloadRequest (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ NTSTATUS CompletionStatus)
 
VOID ClasspCleanupOffloadReadContext (_In_ __drv_freesMem(mem) POFFLOAD_READ_CONTEXT OffloadReadContext)
 
VOID ClasspCompleteOffloadRead (_In_ POFFLOAD_READ_CONTEXT OffloadReadContext, _In_ NTSTATUS CompletionStatus)
 
VOID ClasspPopulateTokenTransferPacketDone (_In_ PVOID Context)
 
VOID ClasspReceivePopulateTokenInformationTransferPacketDone (_In_ PVOID Context)
 
VOID ClasspContinueOffloadWrite (_In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
 
VOID ClasspCleanupOffloadWriteContext (_In_ __drv_freesMem(mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
 
VOID ClasspCompleteOffloadWrite (_In_ __drv_freesMem(Mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ NTSTATUS CompletionCausingStatus)
 
VOID ClasspReceiveWriteUsingTokenInformationDone (_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ NTSTATUS CompletionCausingStatus)
 
VOID ClasspWriteUsingTokenTransferPacketDone (_In_ PVOID Context)
 
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)
 
NTSTATUS InterpretReadCapacity16Data (_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PREAD_CAPACITY16_DATA ReadCapacity16Data)
 
NTSTATUS ClassReadCapacity16 (_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClassDeviceGetLBProvisioningResources (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
_IRQL_requires_same_ NTSTATUS ClasspStorageEventNotification (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
 
NTSTATUS ClasspLogSystemEventWithDeviceNumber (_In_ PDEVICE_OBJECT DeviceObject, _In_ NTSTATUS IoErrorCode)
 
NTSTATUS ClasspEnqueueIdleRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
VOID ClasspCompleteIdleRequest (PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspPriorityHint (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
VOID HistoryInitializeRetryLogs (_Out_ PSRB_HISTORY History, ULONG HistoryCount)
 
VOID HistoryLogSendPacket (TRANSFER_PACKET *Pkt)
 
VOID HistoryLogReturnedPacket (TRANSFER_PACKET *Pkt)
 
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)
 
BOOLEAN ClasspMyStringMatches (_In_opt_z_ PCHAR StringToMatch, _In_z_ PCHAR TargetString)
 
VOID ClasspInitializeRemoveTracking (_In_ PDEVICE_OBJECT DeviceObject)
 
VOID ClasspUninitializeRemoveTracking (_In_ PDEVICE_OBJECT DeviceObject)
 
PVOID DefaultStorageRequestBlockAllocateRoutine (_In_ CLONG ByteSize)
 
NTSTATUS CreateStorageRequestBlock (_Inout_ PSTORAGE_REQUEST_BLOCK *Srb, _In_ USHORT AddressType, _In_opt_ PSRB_ALLOCATE_ROUTINE AllocateRoutine, _Inout_opt_ ULONG *ByteSize, _In_ ULONG NumSrbExData,...)
 
NTSTATUS InitializeStorageRequestBlock (_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
 
VOID ClasspConvertToScsiRequestBlock (_Out_ PSCSI_REQUEST_BLOCK Srb, _In_ PSTORAGE_REQUEST_BLOCK SrbEx)
 
FORCEINLINE PCDB ClasspTransferPacketGetCdb (_In_ PTRANSFER_PACKET Pkt)
 
FORCEINLINE BOOLEAN ClasspTransferPacketGetNumberOfRetriesDone (_In_ PTRANSFER_PACKET Pkt, _In_ PCDB Cdb, _Out_ PULONG TimesAlreadyRetried)
 
FORCEINLINE PVOID ClasspTransferPacketGetSenseInfoBuffer (_In_ PTRANSFER_PACKET Pkt)
 
FORCEINLINE UCHAR ClasspTransferPacketGetSenseInfoBufferLength (_In_ PTRANSFER_PACKET Pkt)
 
FORCEINLINE VOID ClasspSrbSetOriginalIrp (_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb, _In_ PIRP Irp)
 
FORCEINLINE BOOLEAN PORT_ALLOCATED_SENSE_EX (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
 
FORCEINLINE VOID FREE_PORT_ALLOCATED_SENSE_BUFFER_EX (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
 
BOOLEAN ClasspFailurePredictionPeriodMissed (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
FORCEINLINE ULONG ClasspGetMaxUsableBufferLengthFromOffset (_In_ PVOID BaseAddress, _In_ ULONG OffsetInBytes, _In_ ULONG BaseStructureSizeInBytes)
 
BOOLEAN ClasspIsThinProvisioningError (_In_ PSCSI_REQUEST_BLOCK _Srb)
 
FORCEINLINE BOOLEAN ClasspLowerLayerNotSupport (_In_ NTSTATUS Status)
 
NTSTATUS ClassDeviceHwFirmwareGetInfoProcess (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
 
NTSTATUS ClassDeviceHwFirmwareDownloadProcess (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClassDeviceHwFirmwareActivateProcess (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 

Variables

CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems []
 
GUID ClassGuidQueryRegInfoEx
 
GUID ClassGuidSenseInfo2
 
GUID ClassGuidWorkingSet
 
GUID ClassGuidSrbSupport
 
ULONG ClassMaxInterleavePerCriticalIo
 
ULONG MaxTokenOperationListIdentifier
 
volatile ULONG TokenOperationListIdentifier
 
LIST_ENTRY IdlePowerFDOList
 
PVOID PowerSettingNotificationHandle
 
PVOID ScreenStateNotificationHandle
 
BOOLEAN ClasspScreenOff
 
KGUARDED_MUTEX IdlePowerFDOListMutex
 
ULONG DiskIdleTimeoutInMS
 
CONST LARGE_INTEGER Magic10000
 
DRIVER_INITIALIZE DriverEntry
 
DRIVER_UNLOAD ClassUnload
 
DRIVER_ADD_DEVICE ClassAddDevice
 
IO_COMPLETION_ROUTINE ClasspSendSynchronousCompletion
 
DRIVER_STARTIO ClasspStartIo
 
IO_COMPLETION_ROUTINE ClassReleaseQueueCompletion
 
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
 
KDEFERRED_ROUTINE ClasspRetryRequestDpc
 
IO_WORKITEM_ROUTINE ClasspUpdateDiskProperties
 
IO_COMPLETION_ROUTINE TransferPktComplete
 
KDEFERRED_ROUTINE TransferPacketRetryTimerDpc
 
IO_WORKITEM_ROUTINE_EX CleanupTransferPacketToWorkingSetSizeWorker
 
_In_ PTRANSFER_PACKET Pkt
 
_In_ PTRANSFER_PACKET _In_ ULONG Length
 
_In_ PTRANSFER_PACKET _In_ ULONG _In_ PIRP OriginalIrp
 
_In_ PTRANSFER_PACKET _In_ ULONG _In_ PIRP _In_ ULONG ListIdentifier
 
IO_WORKITEM_ROUTINE ClasspLogIOEventWithContext
 
_In_z_ PWSTR RegistryPath
 
_In_z_ PWSTR _Out_ PULONG MaximumListIdentifier
 
_In_z_ PWSTR _Out_ PULONG MaxDuration
 
_Inout_ PIRP Irp
 
_Inout_ PIRP _Inout_ PSCSI_REQUEST_BLOCK Srb
 
_In_ PVOID BlockDescr
 
_In_ PVOID _Inout_ PULONG CurrentBlockDescrIndex
 
_In_ PVOID _Inout_ PULONG _In_ ULONG MaxBlockDescrCount
 
_In_ PVOID _Inout_ PULONG _In_ ULONG _Inout_ PULONG CurrentLbaCount
 
_In_ PVOID _Inout_ PULONG _In_ ULONG _Inout_ PULONG _In_ ULONGLONG MaxLbaCount
 
_In_ PVOID _Inout_ PULONG _In_ ULONG _Inout_ PULONG _In_ ULONGLONG _Inout_ PDEVICE_DATA_SET_RANGE DataSetRange
 
_In_ PVOID _Inout_ PULONG _In_ ULONG _Inout_ PULONG _In_ ULONGLONG _Inout_ PDEVICE_DATA_SET_RANGE _Inout_ PULONGLONG TotalSectorsProcessed
 
LIST_ENTRY AllFdosList
 
IO_WORKITEM_ROUTINE ClassLogThresholdEvent
 
IO_WORKITEM_ROUTINE ClassLogResourceExhaustionEvent
 
RTL_GENERIC_COMPARE_ROUTINE RemoveTrackingCompareRoutine
 
RTL_GENERIC_ALLOCATE_ROUTINE RemoveTrackingAllocateRoutine
 
RTL_GENERIC_FREE_ROUTINE RemoveTrackingFreeRoutine
 

Macro Definition Documentation

◆ Add2Ptr

#define Add2Ptr (   P,
  I 
)    ((PVOID)((PUCHAR)(P) + (I)))

Definition at line 110 of file classp.h.

◆ CLASS_ERROR_LEVEL_1

#define CLASS_ERROR_LEVEL_1   (0x4)

Definition at line 131 of file classp.h.

◆ CLASS_ERROR_LEVEL_2

#define CLASS_ERROR_LEVEL_2   (0x8)

Definition at line 132 of file classp.h.

◆ CLASS_FILE_OBJECT_EXTENSION_KEY

#define CLASS_FILE_OBJECT_EXTENSION_KEY   'eteP'

Definition at line 186 of file classp.h.

◆ CLASS_IDLE_INTERVAL

#define CLASS_IDLE_INTERVAL   12

Definition at line 1199 of file classp.h.

◆ CLASS_IDLE_INTERVAL_MIN

#define CLASS_IDLE_INTERVAL_MIN   12

Definition at line 1198 of file classp.h.

◆ CLASS_MAX_INTERLEAVE_PER_CRITICAL_IO

#define CLASS_MAX_INTERLEAVE_PER_CRITICAL_IO   (0x4)

Definition at line 133 of file classp.h.

◆ CLASS_PERF_RESTORE_MINIMUM

#define CLASS_PERF_RESTORE_MINIMUM   (0x10)

Definition at line 130 of file classp.h.

◆ CLASS_STARVATION_INTERVAL

#define CLASS_STARVATION_INTERVAL   500

Definition at line 1200 of file classp.h.

◆ CLASS_TAG_PRIVATE_DATA

#define CLASS_TAG_PRIVATE_DATA   'CPcS'

Definition at line 189 of file classp.h.

◆ CLASS_TAG_SENSE2

#define CLASS_TAG_SENSE2   '2ScS'

Definition at line 190 of file classp.h.

◆ CLASS_TAG_WORKING_SET

#define CLASS_TAG_WORKING_SET   'sWcS'

Definition at line 191 of file classp.h.

◆ CLASSP_REG_ACCESS_ALIGNMENT_NOT_SUPPORTED

#define CLASSP_REG_ACCESS_ALIGNMENT_NOT_SUPPORTED   (L"AccessAlignmentQueryNotSupported")

Definition at line 122 of file classp.h.

◆ CLASSP_REG_COPY_OFFLOAD_MAX_TARGET_DURATION

#define CLASSP_REG_COPY_OFFLOAD_MAX_TARGET_DURATION   (L"CopyOffloadMaxTargetDuration")

Definition at line 128 of file classp.h.

◆ CLASSP_REG_DISABLE_D3COLD

#define CLASSP_REG_DISABLE_D3COLD   (L"DisableD3Cold")

Definition at line 125 of file classp.h.

◆ CLASSP_REG_DISBALE_IDLE_POWER_NAME

#define CLASSP_REG_DISBALE_IDLE_POWER_NAME   (L"DisableIdlePowerManagement")

Definition at line 123 of file classp.h.

◆ CLASSP_REG_HACK_VALUE_NAME

#define CLASSP_REG_HACK_VALUE_NAME   (L"HackMask")

Definition at line 114 of file classp.h.

◆ CLASSP_REG_IDLE_ACTIVE_MAX

#define CLASSP_REG_IDLE_ACTIVE_MAX   (L"IdleOutstandingIoMax")

Definition at line 120 of file classp.h.

◆ CLASSP_REG_IDLE_INTERVAL_NAME

#define CLASSP_REG_IDLE_INTERVAL_NAME   (L"IdleInterval")

Definition at line 119 of file classp.h.

◆ CLASSP_REG_IDLE_PRIORITY_SUPPORTED

#define CLASSP_REG_IDLE_PRIORITY_SUPPORTED   (L"IdlePrioritySupported")

Definition at line 121 of file classp.h.

◆ CLASSP_REG_IDLE_TIMEOUT_IN_SECONDS

#define CLASSP_REG_IDLE_TIMEOUT_IN_SECONDS   (L"IdleTimeoutInSeconds")

Definition at line 124 of file classp.h.

◆ CLASSP_REG_LEGACY_ERROR_HANDLING

#define CLASSP_REG_LEGACY_ERROR_HANDLING   (L"LegacyErrorHandling")

Definition at line 127 of file classp.h.

◆ CLASSP_REG_MMC_DETECTION_VALUE_NAME

#define CLASSP_REG_MMC_DETECTION_VALUE_NAME   (L"MMCDetectionState")

Definition at line 115 of file classp.h.

◆ CLASSP_REG_PERF_RESTORE_VALUE_NAME

#define CLASSP_REG_PERF_RESTORE_VALUE_NAME   (L"RestorePerfAtCount")

Definition at line 117 of file classp.h.

◆ CLASSP_REG_QERR_OVERRIDE_MODE

#define CLASSP_REG_QERR_OVERRIDE_MODE   (L"QERROverrideMode")

Definition at line 126 of file classp.h.

◆ CLASSP_REG_REMOVAL_POLICY_VALUE_NAME

#define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME   (L"UserRemovalPolicy")

Definition at line 118 of file classp.h.

◆ CLASSP_REG_SUBKEY_NAME

#define CLASSP_REG_SUBKEY_NAME   (L"Classpnp")

Definition at line 112 of file classp.h.

◆ CLASSP_REG_WRITE_CACHE_VALUE_NAME

#define CLASSP_REG_WRITE_CACHE_VALUE_NAME   (L"WriteCacheEnableOverride")

Definition at line 116 of file classp.h.

◆ CLASSP_VOLUME_VERIFY_CHECKED

#define CLASSP_VOLUME_VERIFY_CHECKED   0x34

Definition at line 187 of file classp.h.

◆ CLASSPNP_POOL_TAG_ADDITIONAL_DATA

#define CLASSPNP_POOL_TAG_ADDITIONAL_DATA   'DAcS'

Definition at line 197 of file classp.h.

◆ CLASSPNP_POOL_TAG_FIRMWARE

#define CLASSPNP_POOL_TAG_FIRMWARE   'wFcS'

Definition at line 198 of file classp.h.

◆ CLASSPNP_POOL_TAG_GENERIC

#define CLASSPNP_POOL_TAG_GENERIC   'pCcS'

Definition at line 192 of file classp.h.

◆ CLASSPNP_POOL_TAG_LOG_MESSAGE

#define CLASSPNP_POOL_TAG_LOG_MESSAGE   'mlcS'

Definition at line 196 of file classp.h.

◆ CLASSPNP_POOL_TAG_SRB

#define CLASSPNP_POOL_TAG_SRB   'rScS'

Definition at line 194 of file classp.h.

◆ CLASSPNP_POOL_TAG_TOKEN_OPERATION

#define CLASSPNP_POOL_TAG_TOKEN_OPERATION   'oTcS'

Definition at line 193 of file classp.h.

◆ CLASSPNP_POOL_TAG_VPD

#define CLASSPNP_POOL_TAG_VPD   'pVcS'

Definition at line 195 of file classp.h.

◆ CONST_MSECS_PER_SEC

#define CONST_MSECS_PER_SEC   1000

Definition at line 251 of file classp.h.

◆ Convert100nsToMilliseconds

#define Convert100nsToMilliseconds (   LARGE_INTEGER)
Value:
( \
RtlExtendedMagicDivide((LARGE_INTEGER), Magic10000, SHIFT10000) \
)
CONST LARGE_INTEGER Magic10000
Definition: class.c:89
#define SHIFT10000
Definition: classp.h:246

Definition at line 253 of file classp.h.

◆ ConvertMillisecondsTo100ns

#define ConvertMillisecondsTo100ns (   MILLISECONDS)
Value:
( \
RtlExtendedIntegerMultiply ((MILLISECONDS), 10000) \
)
#define MILLISECONDS(milli)
Definition: nfs41_driver.c:116

Definition at line 258 of file classp.h.

◆ DBG_NUM_PACKET_LOG_ENTRIES

#define DBG_NUM_PACKET_LOG_ENTRIES   (64*2)

Definition at line 487 of file classp.h.

◆ DEBUG_COMP_ID

#define DEBUG_COMP_ID   DPFLTR_CLASSPNP_ID

Definition at line 78 of file classp.h.

◆ DEFAULT_MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN

#define DEFAULT_MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN   (64ULL * 1024 * 1024)

Definition at line 212 of file classp.h.

◆ DEFAULT_MAX_TARGET_DURATION

#define DEFAULT_MAX_TARGET_DURATION   4

Definition at line 211 of file classp.h.

◆ FDO_HACK_CANNOT_LOCK_MEDIA

#define FDO_HACK_CANNOT_LOCK_MEDIA   (0x00000001)

Definition at line 135 of file classp.h.

◆ FDO_HACK_GESN_IGNORE_OPCHANGE

#define FDO_HACK_GESN_IGNORE_OPCHANGE   (0x00000010)

Definition at line 139 of file classp.h.

◆ FDO_HACK_GESN_IS_BAD

#define FDO_HACK_GESN_IS_BAD   (0x00000002)

Definition at line 136 of file classp.h.

◆ FDO_HACK_INVALID_FLAGS

#define FDO_HACK_INVALID_FLAGS   (~FDO_HACK_VALID_FLAGS)

Definition at line 142 of file classp.h.

◆ FDO_HACK_NO_RESERVE6

#define FDO_HACK_NO_RESERVE6   (0x00000008)

Definition at line 138 of file classp.h.

◆ FDO_HACK_NO_SYNC_CACHE

#define FDO_HACK_NO_SYNC_CACHE   (0x00000004)

Definition at line 137 of file classp.h.

◆ FDO_HACK_VALID_FLAGS

#define FDO_HACK_VALID_FLAGS   (0x0000001F)

Definition at line 141 of file classp.h.

◆ FIFTY_MS_IN_100NS_UNITS

#define FIFTY_MS_IN_100NS_UNITS   50 * 100

Definition at line 1205 of file classp.h.

◆ GET_LBA_STATUS_RETRY_COUNT_MAX

#define GET_LBA_STATUS_RETRY_COUNT_MAX   (2)

Definition at line 229 of file classp.h.

◆ HISTORYINITIALIZERETRYLOGS

#define HISTORYINITIALIZERETRYLOGS (   _packet)
Value:
{ \
if (_packet->RetryHistory != NULL) \
{ \
HistoryInitializeRetryLogs( \
_packet->RetryHistory, \
_packet->RetryHistory->TotalHistoryCount \
); \
} \
}
#define NULL
Definition: types.h:112

Definition at line 2330 of file classp.h.

◆ HISTORYLOGRETURNEDPACKET

#define HISTORYLOGRETURNEDPACKET (   _packet)
Value:
{ \
if (_packet->RetryHistory != NULL) { \
HistoryLogReturnedPacket(_packet); \
} \
}

Definition at line 2357 of file classp.h.

◆ HISTORYLOGSENDPACKET

#define HISTORYLOGSENDPACKET (   _packet)
Value:
{ \
if (_packet->RetryHistory != NULL) { \
HistoryLogSendPacket(_packet); \
} \
}

Definition at line 2345 of file classp.h.

◆ LEGACY_NUM_IO_RETRIES

#define LEGACY_NUM_IO_RETRIES   8

Definition at line 170 of file classp.h.

◆ MAX

#define MAX (   a,
  b 
)    ((a) > (b) ? (a) : (b))

Definition at line 1191 of file classp.h.

◆ MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE

#define MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE   8192

Definition at line 639 of file classp.h.

◆ MAX_LIST_IDENTIFIER

#define MAX_LIST_IDENTIFIER   MAXULONG

Definition at line 203 of file classp.h.

◆ MAX_NUMBER_BLOCK_DEVICE_DESCRIPTORS

#define MAX_NUMBER_BLOCK_DEVICE_DESCRIPTORS   64

Definition at line 216 of file classp.h.

◆ MAX_NUMBER_BLOCKS_PER_BLOCK_DEVICE_RANGE_DESCRIPTOR

#define MAX_NUMBER_BLOCKS_PER_BLOCK_DEVICE_RANGE_DESCRIPTOR   MAXULONG

Definition at line 210 of file classp.h.

◆ MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN

#define MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN   (256ULL * 1024 * 1024)

Definition at line 213 of file classp.h.

◆ MAX_OUTSTANDING_IO_PER_LUN_DEFAULT

#define MAX_OUTSTANDING_IO_PER_LUN_DEFAULT   16

Definition at line 638 of file classp.h.

◆ MAX_RECEIVE_TOKEN_INFORMATION_PARAMETER_DATA_LENGTH

#define MAX_RECEIVE_TOKEN_INFORMATION_PARAMETER_DATA_LENGTH   MAXULONG

Definition at line 208 of file classp.h.

◆ MAX_TOKEN_LIST_IDENTIFIERS

#define MAX_TOKEN_LIST_IDENTIFIERS   MAXULONG

Definition at line 215 of file classp.h.

◆ MAX_TOKEN_OPERATION_PARAMETER_DATA_LENGTH

#define MAX_TOKEN_OPERATION_PARAMETER_DATA_LENGTH   MAXUSHORT

Definition at line 207 of file classp.h.

◆ MAX_TOKEN_TRANSFER_SIZE

#define MAX_TOKEN_TRANSFER_SIZE   MAXULONGLONG

Definition at line 209 of file classp.h.

◆ MAX_WORKINGSET_TRANSFER_PACKETS_Client

#define MAX_WORKINGSET_TRANSFER_PACKETS_Client   32

Definition at line 632 of file classp.h.

◆ MAX_WORKINGSET_TRANSFER_PACKETS_Server

#define MAX_WORKINGSET_TRANSFER_PACKETS_Server   1024

Definition at line 635 of file classp.h.

◆ MAX_WORKINGSET_TRANSFER_PACKETS_SPACES

#define MAX_WORKINGSET_TRANSFER_PACKETS_SPACES   2048

Definition at line 637 of file classp.h.

◆ MIN

#define MIN (   a,
  b 
)    ((a) < (b) ? (a) : (b))

Definition at line 1190 of file classp.h.

◆ MIN_INITIAL_TRANSFER_PACKETS

#define MIN_INITIAL_TRANSFER_PACKETS   1

Definition at line 630 of file classp.h.

◆ MIN_TOKEN_LIST_IDENTIFIERS

#define MIN_TOKEN_LIST_IDENTIFIERS   256

Definition at line 214 of file classp.h.

◆ MIN_WORKINGSET_TRANSFER_PACKETS_Client

#define MIN_WORKINGSET_TRANSFER_PACKETS_Client   16

Definition at line 631 of file classp.h.

◆ MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound

#define MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound   32

Definition at line 634 of file classp.h.

◆ MIN_WORKINGSET_TRANSFER_PACKETS_Server_UpperBound

#define MIN_WORKINGSET_TRANSFER_PACKETS_Server_UpperBound   256

Definition at line 633 of file classp.h.

◆ MIN_WORKINGSET_TRANSFER_PACKETS_SPACES

#define MIN_WORKINGSET_TRANSFER_PACKETS_SPACES   512

Definition at line 636 of file classp.h.

◆ MINIMUM_RETRY_UNITS

#define MINIMUM_RETRY_UNITS   ((LONGLONG)32)

Definition at line 1195 of file classp.h.

◆ MODE_PAGE_DATA_SIZE

#define MODE_PAGE_DATA_SIZE   192

Definition at line 1196 of file classp.h.

◆ NOT_READY_RETRY_INTERVAL

#define NOT_READY_RETRY_INTERVAL   10

Definition at line 1194 of file classp.h.

◆ NUM_DRIVECAPACITY_RETRIES

#define NUM_DRIVECAPACITY_RETRIES   1

Definition at line 161 of file classp.h.

◆ NUM_ERROR_LOG_ENTRIES

#define NUM_ERROR_LOG_ENTRIES   16

Definition at line 486 of file classp.h.

◆ NUM_IO_RETRIES

#define NUM_IO_RETRIES   MAXIMUM_RETRIES

Definition at line 169 of file classp.h.

◆ NUM_LOCKMEDIAREMOVAL_RETRIES

#define NUM_LOCKMEDIAREMOVAL_RETRIES   1

Definition at line 158 of file classp.h.

◆ NUM_MODESELECT_RETRIES

#define NUM_MODESELECT_RETRIES   1

Definition at line 160 of file classp.h.

◆ NUM_MODESENSE_RETRIES

#define NUM_MODESENSE_RETRIES   1

Definition at line 159 of file classp.h.

◆ NUM_POPULATE_TOKEN_RETRIES

#define NUM_POPULATE_TOKEN_RETRIES   1

Definition at line 204 of file classp.h.

◆ NUM_RECEIVE_TOKEN_INFORMATION_RETRIES

#define NUM_RECEIVE_TOKEN_INFORMATION_RETRIES   2

Definition at line 206 of file classp.h.

◆ NUM_THIN_PROVISIONING_RETRIES

#define NUM_THIN_PROVISIONING_RETRIES   32

Definition at line 162 of file classp.h.

◆ NUM_WRITE_USING_TOKEN_RETRIES

#define NUM_WRITE_USING_TOKEN_RETRIES   2

Definition at line 205 of file classp.h.

◆ PTRALIGN

#define PTRALIGN

Definition at line 96 of file classp.h.

◆ QERR_SET_ZERO_ALWAYS

#define QERR_SET_ZERO_ALWAYS   1

Definition at line 1186 of file classp.h.

◆ QERR_SET_ZERO_NEVER

#define QERR_SET_ZERO_NEVER   2

Definition at line 1187 of file classp.h.

◆ QERR_SET_ZERO_ODX_OR_TP_ONLY

#define QERR_SET_ZERO_ODX_OR_TP_ONLY   0

Definition at line 1185 of file classp.h.

◆ REG_DISK_CLASS_CONTROL

#define REG_DISK_CLASS_CONTROL   L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\DISK"

Definition at line 218 of file classp.h.

◆ REG_MAX_LIST_IDENTIFIER_VALUE

#define REG_MAX_LIST_IDENTIFIER_VALUE   L"MaximumListIdentifier"

Definition at line 219 of file classp.h.

◆ RTL_USE_AVL_TABLES

#define RTL_USE_AVL_TABLES   0

Definition at line 28 of file classp.h.

◆ SHIFT10000

#define SHIFT10000   13

Definition at line 246 of file classp.h.

◆ TRACKING_FORWARD_PROGRESS_PATH1

#define TRACKING_FORWARD_PROGRESS_PATH1   (0x00000001)

Definition at line 2385 of file classp.h.

◆ TRACKING_FORWARD_PROGRESS_PATH2

#define TRACKING_FORWARD_PROGRESS_PATH2   (0x00000002)

Definition at line 2386 of file classp.h.

◆ TRACKING_FORWARD_PROGRESS_PATH3

#define TRACKING_FORWARD_PROGRESS_PATH3   (0x00000004)

Definition at line 2387 of file classp.h.

◆ VPD_PAGE_HEADER_SIZE

#define VPD_PAGE_HEADER_SIZE   0x04

Definition at line 221 of file classp.h.

◆ WPP_CONTROL_GUIDS

Definition at line 87 of file classp.h.

◆ WPP_GUID_CLASSPNP

#define WPP_GUID_CLASSPNP   (FA8DE7C4, ACDE, 4443, 9994, C4E2359A9EDB)

Definition at line 85 of file classp.h.

Typedef Documentation

◆ CLASS_DETECTION_STATE

◆ CLASS_ERROR_LOG_DATA

◆ CLASS_RETRY_INFO

◆ CSCAN_LIST

◆ FAILURE_PREDICTION_INFO

◆ IDLE_POWER_FDO_LIST_ENTRY

◆ IO_RETRIED_LOG_MESSAGE_CONTEXT

◆ MEDIA_CHANGE_DETECTION_INFO

◆ OFFLOAD_READ_CONTEXT

◆ OFFLOAD_WRITE_CONTEXT

◆ OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER

◆ PCLASS_DETECTION_STATE

◆ PCLASS_ERROR_LOG_DATA

◆ PCLASS_RETRY_INFO

◆ PCONTINUATION_ROUTINE

typedef VOID(* PCONTINUATION_ROUTINE) (_In_ PVOID Context)

Definition at line 491 of file classp.h.

◆ PCSCAN_LIST

◆ PFAILURE_PREDICTION_INFO

◆ PIDLE_POWER_FDO_LIST_ENTRY

◆ PIO_RETRIED_LOG_MESSAGE_CONTEXT

◆ PMEDIA_CHANGE_DETECTION_INFO

◆ PMEDIA_LOCK_TYPE

◆ PNL_SLIST_HEADER

◆ POFFLOAD_READ_CONTEXT

◆ POFFLOAD_WRITE_CONTEXT

◆ POPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER

◆ PPNL_SLIST_HEADER

◆ PSRB_ALLOCATE_ROUTINE

typedef PVOID(* PSRB_ALLOCATE_ROUTINE) (_In_ CLONG ByteSize)

Definition at line 2408 of file classp.h.

◆ PTRANSFER_PACKET

◆ TRANSFER_PACKET

Enumeration Type Documentation

◆ _CLASS_DETECTION_STATE

Enumerator
ClassDetectionUnknown 
ClassDetectionUnsupported 
ClassDetectionSupported 

Definition at line 444 of file classp.h.

444 {
enum _CLASS_DETECTION_STATE CLASS_DETECTION_STATE
@ ClassDetectionUnknown
Definition: classp.h:445
@ ClassDetectionUnsupported
Definition: classp.h:446
@ ClassDetectionSupported
Definition: classp.h:447
enum _CLASS_DETECTION_STATE * PCLASS_DETECTION_STATE

◆ MEDIA_LOCK_TYPE

Enumerator
SimpleMediaLock 
SecureMediaLock 
InternalMediaLock 
SimpleMediaLock 
SecureMediaLock 
InternalMediaLock 

Definition at line 378 of file classp.h.

378 {
enum MEDIA_LOCK_TYPE * PMEDIA_LOCK_TYPE
MEDIA_LOCK_TYPE
Definition: classp.h:378
@ SimpleMediaLock
Definition: classp.h:379
@ InternalMediaLock
Definition: classp.h:381
@ SecureMediaLock
Definition: classp.h:380

Function Documentation

◆ __drv_allocatesMem()

__drv_allocatesMem ( Mem  )

Definition at line 55 of file gui.c.

58{
59 return NULL;
60}

◆ _Dispatch_type_() [1/7]

_Dispatch_type_ ( IRP_MJ_CREATE  )

Definition at line 1353 of file isapnp.c.

1364{
1365 PAGED_CODE();
1366
1367 Irp->IoStatus.Status = STATUS_SUCCESS;
1368
1369 DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp);
1370
1372
1373 return STATUS_SUCCESS;
1374}
#define PAGED_CODE()
_In_ PIRP Irp
Definition: csq.h:116
#define __FUNCTION__
Definition: types.h:116
#define IoCompleteRequest
Definition: irp.c:1240
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define IO_NO_INCREMENT
Definition: iotypes.h:598

◆ _Dispatch_type_() [2/7]

_Dispatch_type_ ( IRP_MJ_DEVICE_CONTROL  )

Definition at line 1376 of file isapnp.c.

1387{
1388 PISAPNP_COMMON_EXTENSION CommonExt = DeviceObject->DeviceExtension;
1389
1390 PAGED_CODE();
1391
1392 DPRINT("%s(%p, %p) Minor - %X\n", __FUNCTION__, DeviceObject, Irp,
1394
1395 if (CommonExt->Signature == IsaPnpBus)
1396 {
1398 return IoCallDriver(((PISAPNP_FDO_EXTENSION)CommonExt)->Ldo, Irp);
1399 }
1400 else
1401 {
1402 NTSTATUS Status = Irp->IoStatus.Status;
1403
1405 return Status;
1406 }
1407}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
LONG NTSTATUS
Definition: precomp.h:26
Status
Definition: gdiplustypes.h:25
@ IsaPnpBus
Definition: isapnp.h:36
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCallDriver
Definition: irp.c:1225
ISAPNP_SIGNATURE Signature
Definition: isapnp.h:43
_In_ UCHAR _In_ UCHAR MinorFunction
Definition: wdfdevice.h:1699

◆ _Dispatch_type_() [3/7]

_Dispatch_type_ ( IRP_MJ_PNP  )

Definition at line 1331 of file isapnp.c.

1341{
1343 PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension;
1344
1345 PAGED_CODE();
1346
1347 if (DevExt->Signature == IsaPnpBus)
1348 return IsaFdoPnp((PISAPNP_FDO_EXTENSION)DevExt, Irp, IrpSp);
1349 else
1350 return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp);
1351}
NTSTATUS IsaFdoPnp(_In_ PISAPNP_FDO_EXTENSION FdoExt, _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp)
Definition: fdo.c:123
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
NTSTATUS IsaPdoPnp(_In_ PISAPNP_PDO_EXTENSION PdoDeviceExtension, _Inout_ PIRP Irp, _In_ PIO_STACK_LOCATION IrpSp)
Definition: pdo.c:867

◆ _Dispatch_type_() [4/7]

_Dispatch_type_ ( IRP_MJ_POWER  )

Definition at line 1293 of file isapnp.c.

1302{
1303 PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension;
1305
1306 if (DevExt->Signature != IsaPnpBus)
1307 {
1309 {
1310 case IRP_MN_SET_POWER:
1311 case IRP_MN_QUERY_POWER:
1313 Irp->IoStatus.Status = Status;
1314 break;
1315
1316 default:
1317 Status = Irp->IoStatus.Status;
1318 break;
1319 }
1320
1323 return Status;
1324 }
1325
1328 return PoCallDriver(((PISAPNP_FDO_EXTENSION)DevExt)->Ldo, Irp);
1329}
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:758
#define IRP_MN_SET_POWER
#define IRP_MN_QUERY_POWER

◆ _Dispatch_type_() [5/7]

_Dispatch_type_ ( IRP_MJ_READ  )

Definition at line 3505 of file read.c.

3507 {
3508 device_extension* Vcb = DeviceObject->DeviceExtension;
3511 ULONG bytes_read = 0;
3513 bool top_level;
3514 fcb* fcb;
3515 ccb* ccb;
3516 bool acquired_fcb_lock = false, wait;
3517
3519
3520 top_level = is_top_level(Irp);
3521
3522 TRACE("read\n");
3523
3524 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
3526 goto exit2;
3527 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
3529 goto end;
3530 }
3531
3532 Irp->IoStatus.Information = 0;
3533
3535 CcMdlReadComplete(IrpSp->FileObject, Irp->MdlAddress);
3536
3537 Irp->MdlAddress = NULL;
3539
3540 goto exit;
3541 }
3542
3543 fcb = FileObject->FsContext;
3544
3545 if (!fcb) {
3546 ERR("fcb was NULL\n");
3548 goto exit;
3549 }
3550
3551 ccb = FileObject->FsContext2;
3552
3553 if (!ccb) {
3554 ERR("ccb was NULL\n");
3556 goto exit;
3557 }
3558
3559 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_READ_DATA)) {
3560 WARN("insufficient privileges\n");
3562 goto exit;
3563 }
3564
3565 if (fcb == Vcb->volume_fcb) {
3566 TRACE("reading volume FCB\n");
3567
3569
3570 Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
3571
3572 goto exit2;
3573 }
3574
3575 if (!(Irp->Flags & IRP_PAGING_IO))
3577
3579
3580 // Don't offload jobs when doing paging IO - otherwise this can lead to
3581 // deadlocks in CcCopyRead.
3582 if (Irp->Flags & IRP_PAGING_IO)
3583 wait = true;
3584
3585 if (!(Irp->Flags & IRP_PAGING_IO) && FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->DataSectionObject) {
3587
3588 CcFlushCache(FileObject->SectionObjectPointer, &IrpSp->Parameters.Read.ByteOffset, IrpSp->Parameters.Read.Length, &iosb);
3589 if (!NT_SUCCESS(iosb.Status)) {
3590 ERR("CcFlushCache returned %08lx\n", iosb.Status);
3591 return iosb.Status;
3592 }
3593 }
3594
3595 if (!ExIsResourceAcquiredSharedLite(fcb->Header.Resource)) {
3596 if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
3599 goto exit;
3600 }
3601
3602 acquired_fcb_lock = true;
3603 }
3604
3605 Status = do_read(Irp, wait, &bytes_read);
3606
3607 if (acquired_fcb_lock)
3608 ExReleaseResourceLite(fcb->Header.Resource);
3609
3610exit:
3611 if (FileObject->Flags & FO_SYNCHRONOUS_IO && !(Irp->Flags & IRP_PAGING_IO))
3612 FileObject->CurrentByteOffset.QuadPart = IrpSp->Parameters.Read.ByteOffset.QuadPart + (NT_SUCCESS(Status) ? bytes_read : 0);
3613
3614end:
3615 Irp->IoStatus.Status = Status;
3616
3617 TRACE("Irp->IoStatus.Status = %08lx\n", Irp->IoStatus.Status);
3618 TRACE("Irp->IoStatus.Information = %Iu\n", Irp->IoStatus.Information);
3619 TRACE("returning %08lx\n", Status);
3620
3621 if (Status != STATUS_PENDING)
3623 else {
3624 if (!add_thread_job(Vcb, Irp))
3626 }
3627
3628exit2:
3629 if (top_level)
3631
3633
3634 return Status;
3635}
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:689
bool add_thread_job(device_extension *Vcb, PIRP Irp)
struct _fcb fcb
Definition: btrfs_drv.h:1364
#define VCB_TYPE_FS
Definition: btrfs_drv.h:687
NTSTATUS do_read_job(PIRP Irp)
Definition: worker-thread.c:26
NTSTATUS vol_read(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: volume.c:144
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1677
struct _ccb ccb
VOID NTAPI CcMdlReadComplete(IN PFILE_OBJECT FileObject, IN PMDL MdlChain)
Definition: mdlsup.c:75
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:278
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
NTSTATUS do_read(PIRP Irp, bool wait, ULONG *bytes_read)
Definition: read.c:3328
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
GLuint GLuint end
Definition: gl.h:1545
IoMarkIrpPending(Irp)
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
#define UserMode
Definition: asm.h:35
#define FILE_READ_DATA
Definition: nt_native.h:628
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
ULONG NTAPI ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1663
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1170
#define Vcb
Definition: cdprocs.h:1415
#define exit(n)
Definition: config.h:202
#define TRACE(s)
Definition: solgame.cpp:4
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1579 Parameters
struct _IO_STACK_LOCATION::@3978::@3982 Read
ACCESS_MASK access
Definition: btrfs_drv.h:382
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
#define IRP_MN_COMPLETE
Definition: iotypes.h:4420
#define IRP_PAGING_IO
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776

◆ _Dispatch_type_() [6/7]

_Dispatch_type_ ( IRP_MJ_SHUTDOWN  )

Definition at line 5510 of file btrfs.c.

5512 {
5514 bool top_level;
5515 device_extension* Vcb = DeviceObject->DeviceExtension;
5516
5518
5519 TRACE("shutdown\n");
5520
5521 top_level = is_top_level(Irp);
5522
5523 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
5525 goto end;
5526 }
5527
5529
5531
5532end:
5533 Irp->IoStatus.Status = Status;
5534 Irp->IoStatus.Information = 0;
5535
5537
5538 if (top_level)
5540
5542
5543 return Status;
5544}
void do_shutdown(PIRP Irp)
Definition: btrfs.c:5392
return STATUS_SUCCESS
Definition: btrfs.c:3080
InsertTailList & Vcb
Definition: btrfs.c:3044
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138

◆ _Dispatch_type_() [7/7]

_Dispatch_type_ ( IRP_MJ_SYSTEM_CONTROL  )

Definition at line 5748 of file btrfs.c.

5750 {
5752 device_extension* Vcb = DeviceObject->DeviceExtension;
5753 bool top_level;
5754
5756
5757 top_level = is_top_level(Irp);
5758
5759 Irp->IoStatus.Information = 0;
5760
5761 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
5762 volume_device_extension* vde = DeviceObject->DeviceExtension;
5763
5765
5767
5768 goto exit;
5769 } else if (Vcb && Vcb->type == VCB_TYPE_FS) {
5771
5772 Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
5773
5774 goto exit;
5775 } else if (Vcb && Vcb->type == VCB_TYPE_BUS) {
5776 bus_device_extension* bde = DeviceObject->DeviceExtension;
5777
5779
5781
5782 goto exit;
5783 }
5784
5785 Status = Irp->IoStatus.Status;
5787
5788exit:
5789 if (top_level)
5791
5793
5794 return Status;
5795}
#define VCB_TYPE_BUS
Definition: btrfs_drv.h:691
PDEVICE_OBJECT attached_device
Definition: btrfs_drv.h:880
PDEVICE_OBJECT attached_device
Definition: btrfs_drv.h:849

◆ _In_reads_bytes_()

_In_ PTRANSFER_PACKET _In_ ULONG _In_reads_bytes_ ( Length  )

◆ _IRQL_requires_()

_IRQL_requires_ ( PASSIVE_LEVEL  )

Sends a synchronous IOCTL to the specified device object.

Parameters
[in]IoControlCodeThe IOCTL to send to the device.
[in]DeviceObjectPointer to the device object that will handle the IOCTL.
[in]InputBufferOptional pointer to a buffer containing input data for the IOCTL. When specified, the buffer should be at least of InputBufferLength size.
[in]InputBufferLengthSize in bytes, of the buffer pointed by InputBuffer.
[out]OutputBufferOptional pointer to a buffer that will receive output data from the IOCTL. When specified, the buffer should be at least of OutputBufferLength size.
[in]OutputBufferLengthSize in bytes, of the buffer pointed by OutputBuffer.
[in]FileObjectOptional pointer to a file object that may be necessary for the IOCTL.
Returns
An NTSTATUS code indicating success or failure of this function.
Note
Must be called at PASSIVE_LEVEL with all APCs enabled.

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 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
ULONG MaxTokenOperationListIdentifier
Definition: class.c:107
_IRQL_requires_same_ NTSTATUS ClasspGetBlockDeviceTokenLimitsInfo(_Inout_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:13220
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
Definition: ps.c:97
#define NT_ASSERT
Definition: rtlfuncs.h:3327

◆ _IRQL_requires_max_() [1/2]

_IRQL_requires_max_ ( APC_LEVEL  )

Definition at line 37 of file cddata.c.

254{
255 THREAD_CONTEXT ThreadContext = {0};
256 PIRP_CONTEXT IrpContext = NULL;
258
259#ifdef CD_SANITY
260 PVOID PreviousTopLevel;
261#endif
262
264
265#if DBG
266
267 KIRQL SaveIrql = KeGetCurrentIrql();
268
269#endif
270
272
274
276
277#ifdef CD_SANITY
278 PreviousTopLevel = IoGetTopLevelIrp();
279#endif
280
281 //
282 // Loop until this request has been completed or posted.
283 //
284
285 do {
286
287 //
288 // Use a try-except to handle the exception cases.
289 //
290
291 _SEH2_TRY {
292
293 //
294 // If the IrpContext is NULL then this is the first pass through
295 // this loop.
296 //
297
298 if (IrpContext == NULL) {
299
300 //
301 // Decide if this request is waitable an allocate the IrpContext.
302 // If the file object in the stack location is NULL then this
303 // is a mount which is always waitable. Otherwise we look at
304 // the file object flags.
305 //
306
308
309 Wait = TRUE;
310
311 } else {
312
313 Wait = CanFsdWait( Irp );
314 }
315
316 IrpContext = CdCreateIrpContext( Irp, Wait );
317
318 //
319 // Update the thread context information.
320 //
321
322 CdSetThreadContext( IrpContext, &ThreadContext );
323
324#ifdef CD_SANITY
325 NT_ASSERT( !CdTestTopLevel ||
326 SafeNodeType( IrpContext->TopLevel ) == CDFS_NTC_IRP_CONTEXT );
327#endif
328
329 //
330 // Otherwise cleanup the IrpContext for the retry.
331 //
332
333 } else {
334
335 //
336 // Set the MORE_PROCESSING flag to make sure the IrpContext
337 // isn't inadvertently deleted here. Then cleanup the
338 // IrpContext to perform the retry.
339 //
340
341 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
342 CdCleanupIrpContext( IrpContext, FALSE );
343 }
344
345 //
346 // Case on the major irp code.
347 //
348
349 switch (IrpContext->MajorFunction) {
350
351 case IRP_MJ_CREATE :
352
353 Status = CdCommonCreate( IrpContext, Irp );
354 break;
355
356 case IRP_MJ_CLOSE :
357
358 Status = CdCommonClose( IrpContext, Irp );
359 break;
360
361 case IRP_MJ_READ :
362
363 //
364 // If this is an Mdl complete request, don't go through
365 // common read.
366 //
367
368 if (FlagOn( IrpContext->MinorFunction, IRP_MN_COMPLETE )) {
369
370 Status = CdCompleteMdl( IrpContext, Irp );
371
372 } else {
373
374 Status = CdCommonRead( IrpContext, Irp );
375 }
376
377 break;
378
379 case IRP_MJ_WRITE :
380
381 Status = CdCommonWrite( IrpContext, Irp );
382 break;
383
385
386 Status = CdCommonQueryInfo( IrpContext, Irp );
387 break;
388
390
391 Status = CdCommonSetInfo( IrpContext, Irp );
392 break;
393
395
396 Status = CdCommonQueryVolInfo( IrpContext, Irp );
397 break;
398
400
401 Status = CdCommonDirControl( IrpContext, Irp );
402 break;
403
405
406 Status = CdCommonFsControl( IrpContext, Irp );
407 break;
408
410
411 Status = CdCommonDevControl( IrpContext, Irp );
412 break;
413
415
416 Status = CdCommonLockControl( IrpContext, Irp );
417 break;
418
419 case IRP_MJ_CLEANUP :
420
421 Status = CdCommonCleanup( IrpContext, Irp );
422 break;
423
424 case IRP_MJ_PNP :
425
426 Status = CdCommonPnp( IrpContext, Irp );
427 break;
428
429 case IRP_MJ_SHUTDOWN :
430
431 Status = CdCommonShutdown( IrpContext, Irp );
432 break;
433
434 default :
435
437 CdCompleteRequest( IrpContext, Irp, Status );
438 }
439
441
442 Status = CdProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
443 } _SEH2_END;
444
445 } while (Status == STATUS_CANT_WAIT);
446
447#ifdef CD_SANITY
448 NT_ASSERT( !CdTestTopLevel ||
449 (PreviousTopLevel == IoGetTopLevelIrp()) );
450#endif
451
453
454 NT_ASSERT( SaveIrql == KeGetCurrentIrql( ));
455
456 return Status;
457}
unsigned char BOOLEAN
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
LONG CdExceptionFilter(_Inout_ PIRP_CONTEXT IrpContext, _In_ PEXCEPTION_POINTERS ExceptionPointer)
Definition: cddata.c:525
VOID CdSetThreadContext(_Inout_ PIRP_CONTEXT IrpContext, _In_ PTHREAD_CONTEXT ThreadContext)
Definition: cddata.c:981
#define ASSERT_OPTIONAL_IRP(I)
Definition: cddata.h:251
NTSTATUS CdCompleteMdl(_In_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: cachesup.c:411
VOID CdCleanupIrpContext(_In_ PIRP_CONTEXT IrpContext, _In_ BOOLEAN Post)
Definition: strucsup.c:1733
#define CanFsdWait(I)
Definition: cdprocs.h:2001
NTSTATUS CdCommonLockControl(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: lockctrl.c:35
NTSTATUS CdCommonDevControl(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: devctrl.c:46
_Ret_valid_ PIRP_CONTEXT CdCreateIrpContext(_In_ PIRP Irp, _In_ BOOLEAN Wait)
Definition: strucsup.c:1573
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
#define IRP_CONTEXT_FLAG_MORE_PROCESSING
Definition: cdstruc.h:1214
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CDFS_NTC_IRP_CONTEXT
Definition: nodetype.h:34
#define SafeNodeType(Ptr)
Definition: nodetype.h:54
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
#define STATUS_CANT_WAIT
Definition: ntstatus.h:452
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
#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_QUERY_VOLUME_INFORMATION
Definition: rdpdr.c:50
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define IRP_MJ_SHUTDOWN
#define IRP_MJ_CLEANUP

◆ _IRQL_requires_max_() [2/2]

_IRQL_requires_max_ ( PASSIVE_LEVEL  )

Definition at line 923 of file Messaging.c.

75{
76 PFLT_SERVER_PORT_OBJECT PortObject;
78
79 /* The caller must allow at least one connection */
80 if (MaxConnections == 0)
81 {
83 }
84
85 /* The request must be for a kernel handle */
86 if (!(ObjectAttributes->Attributes & OBJ_KERNEL_HANDLE))
87 {
89 }
90
91 /*
92 * Get rundown protection on the target to stop the owner
93 * from unloading whilst this port object is open. It gets
94 * removed in the FltpServerPortClose callback
95 */
97 if (!NT_SUCCESS(Status))
98 {
99 return Status;
100 }
101
102 /* Create the server port object for this filter */
107 NULL,
109 0,
110 0,
111 (PVOID *)&PortObject);
112 if (NT_SUCCESS(Status))
113 {
114 /* Zero out the struct */
115 RtlZeroMemory(PortObject, sizeof(FLT_SERVER_PORT_OBJECT));
116
117 /* Increment the ref count on the target filter */
119
120 /* Setup the filter port object */
121 PortObject->Filter = Filter;
125 PortObject->Cookie = ServerPortCookie;
126 PortObject->MaxConnections = MaxConnections;
127
128 /* Insert the object */
129 Status = ObInsertObject(PortObject,
130 NULL,
132 0,
133 NULL,
135 if (NT_SUCCESS(Status))
136 {
137 /* Lock the connection list */
139
140 /* Add the new port object to the connection list and increment the count */
143
144 /* Unlock the connection list*/
146 }
147 }
148
149 if (!NT_SUCCESS(Status))
150 {
151 /* Allow the filter to be cleaned up */
153 }
154
155 return Status;
156}
static const INTERNET_PORT ServerPort
Definition: CWebService.cpp:11
POBJECT_TYPE ServerPortObjectType
Definition: Messaging.c:24
VOID FLTAPI FltObjectDereference(_Inout_ PVOID Object)
Definition: Object.c:53
NTSTATUS FLTAPI FltObjectReference(_Inout_ PVOID Object)
Definition: Object.c:41
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ _In_opt_ PFLT_FILTER Filter
Definition: fltkernel.h:1801
_Must_inspect_result_ _Outptr_ PFLT_PORT _In_ POBJECT_ATTRIBUTES _In_opt_ PVOID _In_ PFLT_CONNECT_NOTIFY _In_ PFLT_DISCONNECT_NOTIFY _In_opt_ PFLT_MESSAGE_NOTIFY MessageNotifyCallback
Definition: fltkernel.h:1877
_Must_inspect_result_ _Outptr_ PFLT_PORT _In_ POBJECT_ATTRIBUTES _In_opt_ PVOID _In_ PFLT_CONNECT_NOTIFY ConnectNotifyCallback
Definition: fltkernel.h:1875
_Must_inspect_result_ _Outptr_ PFLT_PORT _In_ POBJECT_ATTRIBUTES _In_opt_ PVOID ServerPortCookie
Definition: fltkernel.h:1874
_Must_inspect_result_ _Outptr_ PFLT_PORT _In_ POBJECT_ATTRIBUTES _In_opt_ PVOID _In_ PFLT_CONNECT_NOTIFY _In_ PFLT_DISCONNECT_NOTIFY DisconnectNotifyCallback
Definition: fltkernel.h:1876
ULONG FltpObjectPointerReference(_In_ PFLT_OBJECT Object)
Definition: Object.c:322
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
static LONG MaxConnections
#define KernelMode
Definition: asm.h:34
#define STANDARD_RIGHTS_ALL
Definition: nt_native.h:69
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1039
FLT_MUTEX_LIST_HEAD ConnectionList
Definition: fltmgrint.h:121
LIST_ENTRY mList
Definition: fltmgrint.h:56
FAST_MUTEX mLock
Definition: fltmgrint.h:55
PFLT_DISCONNECT_NOTIFY DisconnectNotify
Definition: fltmgrint.h:192
PFLT_MESSAGE_NOTIFY MessageNotify
Definition: fltmgrint.h:193
PFLT_CONNECT_NOTIFY ConnectNotify
Definition: fltmgrint.h:191
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

◆ AllocateDictionaryEntry()

NTSTATUS AllocateDictionaryEntry ( IN PDICTIONARY  Dictionary,
IN ULONGLONG  Key,
IN ULONG  Size,
IN ULONG  Tag,
OUT PVOID Entry 
)

Referenced by ClasspCreateClose().

◆ BuildDeviceInputMdl()

PMDL BuildDeviceInputMdl ( PVOID  Buffer,
ULONG  BufferLen 
)

Definition at line 609 of file utils.c.

610{
611 return ClasspBuildDeviceMdl(Buffer, BufferLen, FALSE);
612}
Definition: bufpool.h:45
PMDL ClasspBuildDeviceMdl(PVOID Buffer, ULONG BufferLen, BOOLEAN WriteToDevice)
Definition: utils.c:582

Referenced by ClasspModeSelect(), ClasspModeSense(), and ClassReadDriveCapacity().

◆ C_ASSERT()

◆ 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

◆ ClassDeviceGetLBProvisioningResources()

NTSTATUS ClassDeviceGetLBProvisioningResources ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 5087 of file utils.c.

5113{
5116 PSTORAGE_LB_PROVISIONING_MAP_RESOURCES mapResources = (PSTORAGE_LB_PROVISIONING_MAP_RESOURCES)Irp->AssociatedIrp.SystemBuffer;
5117
5119 Srb,
5120 irpStack->Parameters.DeviceIoControl.OutputBufferLength,
5121 mapResources);
5122
5123 if (NT_SUCCESS(status)) {
5124 Irp->IoStatus.Information = mapResources->Size;
5125 } else {
5126 Irp->IoStatus.Information = 0;
5127 }
5128
5129 Irp->IoStatus.Status = status;
5132
5133 return status;
5134}
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
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
NTSTATUS ClassGetLBProvisioningResources(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG ResourcesSize, _Inout_ PSTORAGE_LB_PROVISIONING_MAP_RESOURCES Resources)
Definition: utils.c:4958
struct _STORAGE_LB_PROVISIONING_MAP_RESOURCES * PSTORAGE_LB_PROVISIONING_MAP_RESOURCES
struct _IO_STACK_LOCATION::@1579::@1580 DeviceIoControl

Referenced by ClassDeviceControl().

◆ ClassDeviceHwFirmwareActivateProcess()

NTSTATUS ClassDeviceHwFirmwareActivateProcess ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 8902 of file utils.c.

8907{
8909
8910#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
8911
8912 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8913 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
8914
8916 PSTORAGE_HW_FIRMWARE_ACTIVATE firmwareActivate = (PSTORAGE_HW_FIRMWARE_ACTIVATE)Irp->AssociatedIrp.SystemBuffer;
8917 BOOLEAN passDown = FALSE;
8918 PCDB cdb = NULL;
8919 ULONG i;
8920 BOOLEAN lockHeld = FALSE;
8921 KLOCK_QUEUE_HANDLE lockHandle;
8922
8923
8924 //
8925 // Input buffer is not big enough to contain required input information.
8926 //
8927 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_HW_FIRMWARE_ACTIVATE)) {
8928
8930 goto Exit_Firmware_Activate;
8931 }
8932
8933 //
8934 // Input buffer basic validation.
8935 //
8936 if ((firmwareActivate->Version < sizeof(STORAGE_HW_FIRMWARE_ACTIVATE)) ||
8937 (firmwareActivate->Size > irpStack->Parameters.DeviceIoControl.InputBufferLength)) {
8938
8940 goto Exit_Firmware_Activate;
8941 }
8942
8943 //
8944 // Only process the request for a supported port driver.
8945 //
8948 goto Exit_Firmware_Activate;
8949 }
8950
8951 //
8952 // Buffer "FunctionSupportInfo" is allocated during start device process. Following check defends against the situation
8953 // of receiving this IOCTL when the device is created but not started, or device start failed but did not get removed yet.
8954 //
8955 if (commonExtension->IsFdo && (fdoExtension->FunctionSupportInfo == NULL)) {
8956
8958 goto Exit_Firmware_Activate;
8959 }
8960
8961 //
8962 // Process the situation that request should be forwarded to lower level.
8963 //
8964 if (!commonExtension->IsFdo) {
8965 passDown = TRUE;
8966 }
8967
8968 if ((firmwareActivate->Flags & STORAGE_HW_FIRMWARE_REQUEST_FLAG_CONTROLLER) != 0) {
8969 passDown = TRUE;
8970 }
8971
8972 if (passDown) {
8973
8975
8977 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8978 FREE_POOL(Srb);
8979 return status;
8980 }
8981
8982 //
8983 // If firmware information hasn't been cached in classpnp, retrieve it.
8984 //
8985 if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo == NULL) {
8986 if (fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport == NotSupported) {
8988 goto Exit_Firmware_Activate;
8989 } else {
8990 //
8991 // If this is the first time of retrieving firmware information,
8992 // send request to lower level to get it.
8993 //
8995
8996 if (!NT_SUCCESS(status)) {
8997 goto Exit_Firmware_Activate;
8998 }
8999 }
9000 }
9001
9002 //
9003 // Fail the request if the firmware information cannot be retrieved.
9004 //
9005 if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo == NULL) {
9006 if (fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport == NotSupported) {
9008 } else {
9010 }
9011
9012 goto Exit_Firmware_Activate;
9013 }
9014
9015 //
9016 // Acquire the SyncLock to ensure the HwFirmwareInfo pointer doesn't change
9017 // while we're dereferencing it.
9018 //
9019 lockHeld = TRUE;
9020 KeAcquireInStackQueuedSpinLock(&fdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
9021
9022 //
9023 // Validate the device support
9024 //
9025 if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SupportUpgrade == FALSE) {
9027 goto Exit_Firmware_Activate;
9028 }
9029
9030 //
9031 // Check if the slot number is valid.
9032 //
9033 for (i = 0; i < fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SlotCount; i++) {
9034 if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo->Slot[i].SlotNumber == firmwareActivate->Slot) {
9035 break;
9036 }
9037 }
9038
9039 if (i >= fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SlotCount) {
9040 //
9041 // Either the slot number is out of scope or the slot is read-only.
9042 //
9044 goto Exit_Firmware_Activate;
9045 }
9046
9047 //
9048 // We're done accessing HwFirmwareInfo at this point so we can release
9049 // the SyncLock.
9050 //
9051 NT_ASSERT(lockHeld);
9052 KeReleaseInStackQueuedSpinLock(&lockHandle);
9053 lockHeld = FALSE;
9054
9055 //
9056 // Process the request by translating it into WRITE BUFFER command.
9057 //
9058 //
9059 // Setup the CDB. This should be an untagged request.
9060 //
9062 cdb = SrbGetCdb(Srb);
9063 cdb->WRITE_BUFFER.OperationCode = SCSIOP_WRITE_DATA_BUFF;
9064 cdb->WRITE_BUFFER.Mode = SCSI_WRITE_BUFFER_MODE_ACTIVATE_DEFERRED_MICROCODE;
9065 cdb->WRITE_BUFFER.ModeSpecific = 0; //Reserved for Mode 0x0F
9066 cdb->WRITE_BUFFER.BufferID = firmwareActivate->Slot; //NOTE: this field will be ignored by SCSI device.
9067
9068 //
9069 // Set timeout value.
9070 //
9072
9073 //
9074 // This routine uses a completion routine - ClassIoComplete() so we don't want to release
9075 // the remove lock until then.
9076 //
9078 Srb,
9079 Irp,
9080 NULL,
9081 0,
9082 FALSE);
9083
9084 if (status != STATUS_PENDING) {
9085 //
9086 // If the irp cannot be sent down, the Srb has been freed. NULL it to prevent from freeing it again.
9087 //
9088 Srb = NULL;
9089
9090 goto Exit_Firmware_Activate;
9091 }
9092
9093 return status;
9094
9095Exit_Firmware_Activate:
9096
9097 //
9098 // Release the SyncLock if it's still held.
9099 // This should only happen in the failure path.
9100 //
9101 if (lockHeld) {
9102 KeReleaseInStackQueuedSpinLock(&lockHandle);
9103 lockHeld = FALSE;
9104 }
9105
9106 //
9107 // Firmware Activate request will be failed.
9108 //
9110
9111 Irp->IoStatus.Status = status;
9112
9113#else
9115 Irp->IoStatus.Status = status;
9116#endif // #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
9117
9120
9121 FREE_POOL(Srb);
9122 return status;
9123}
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
#define CDB10GENERIC_LENGTH
Definition: cdrw_hw.h:831
#define SCSIOP_WRITE_DATA_BUFF
Definition: cdrw_hw.h:922
@ NotSupported
Definition: classpnp.h:734
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)
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
NTSTATUS ClasspGetHwFirmwareInfo(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:8190
#define FIRMWARE_ACTIVATE_TIMEOUT_VALUE
Definition: utils.c:37
__inline BOOLEAN ClassDeviceHwFirmwareIsPortDriverSupported(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:8330
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
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
if(dx< 0)
Definition: linetemp.h:194
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
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
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
Definition: cdrw_hw.h:28
#define SrbGetCdb(srb)
Definition: usbstor.h:18

Referenced by ClassDeviceControl().

◆ ClassDeviceHwFirmwareDownloadProcess()

NTSTATUS ClassDeviceHwFirmwareDownloadProcess ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 8541 of file utils.c.

8546{
8548
8549#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
8550
8551 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8552 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
8553
8555 PSTORAGE_HW_FIRMWARE_DOWNLOAD firmwareDownload = (PSTORAGE_HW_FIRMWARE_DOWNLOAD)Irp->AssociatedIrp.SystemBuffer;
8556 BOOLEAN passDown = FALSE;
8557 ULONG i;
8558 ULONG bufferSize = 0;
8559 PUCHAR firmwareImageBuffer = NULL;
8560 PIRP irp2 = NULL;
8561 PIO_STACK_LOCATION newStack = NULL;
8562 PCDB cdb = NULL;
8563 BOOLEAN lockHeld = FALSE;
8564 KLOCK_QUEUE_HANDLE lockHandle;
8565
8566
8567 //
8568 // Input buffer is not big enough to contain required input information.
8569 //
8570 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_HW_FIRMWARE_DOWNLOAD)) {
8571
8573 goto Exit_Firmware_Download;
8574 }
8575
8576 //
8577 // Input buffer basic validation.
8578 //
8579 if ((firmwareDownload->Version < sizeof(STORAGE_HW_FIRMWARE_DOWNLOAD)) ||
8580 (firmwareDownload->Size > irpStack->Parameters.DeviceIoControl.InputBufferLength) ||
8581 ((firmwareDownload->BufferSize + FIELD_OFFSET(STORAGE_HW_FIRMWARE_DOWNLOAD, ImageBuffer)) > firmwareDownload->Size)) {
8582
8584 goto Exit_Firmware_Download;
8585 }
8586
8587 //
8588 // Only process the request for a supported port driver.
8589 //
8592 goto Exit_Firmware_Download;
8593 }
8594
8595 //
8596 // Buffer "FunctionSupportInfo" is allocated during start device process. Following check defends against the situation
8597 // of receiving this IOCTL when the device is created but not started, or device start failed but did not get removed yet.
8598 //
8599 if (commonExtension->IsFdo && (fdoExtension->FunctionSupportInfo == NULL)) {
8600
8602 goto Exit_Firmware_Download;
8603 }
8604
8605 //
8606 // Process the situation that request should be forwarded to lower level.
8607 //
8608 if (!commonExtension->IsFdo) {
8609 passDown = TRUE;
8610 }
8611
8612 if ((firmwareDownload->Flags & STORAGE_HW_FIRMWARE_REQUEST_FLAG_CONTROLLER) != 0) {
8613 passDown = TRUE;
8614 }
8615
8616 if (passDown) {
8617
8619
8621 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8622 FREE_POOL(Srb);
8623 return status;
8624 }
8625
8626 //
8627 // If firmware information hasn't been cached in classpnp, retrieve it.
8628 //
8629 if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo == NULL) {
8630 if (fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport == NotSupported) {
8632 goto Exit_Firmware_Download;
8633 } else {
8634 //
8635 // If this is the first time of retrieving firmware information,
8636 // send request to lower level to get it.
8637 //
8639
8640 if (!NT_SUCCESS(status)) {
8641 goto Exit_Firmware_Download;
8642 }
8643 }
8644 }
8645
8646 //
8647 // Fail the request if the firmware information cannot be retrieved.
8648 //
8649 if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo == NULL) {
8650 if (fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport == NotSupported) {
8652 } else {
8654 }
8655
8656 goto Exit_Firmware_Download;
8657 }
8658
8659 //
8660 // Acquire the SyncLock to ensure the HwFirmwareInfo pointer doesn't change
8661 // while we're dereferencing it.
8662 //
8663 lockHeld = TRUE;
8664 KeAcquireInStackQueuedSpinLock(&fdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
8665
8666 //
8667 // Validate the device support
8668 //
8669 if ((fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SupportUpgrade == FALSE) ||
8670 (fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadAlignment == 0)) {
8672 goto Exit_Firmware_Download;
8673 }
8674
8675 //
8676 // Check if the slot can be used to hold firmware image.
8677 //
8678 for (i = 0; i < fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SlotCount; i++) {
8679 if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo->Slot[i].SlotNumber == firmwareDownload->Slot) {
8680 break;
8681 }
8682 }
8683
8684 if ((i >= fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SlotCount) ||
8685 (fdoExtension->FunctionSupportInfo->HwFirmwareInfo->Slot[i].ReadOnly == TRUE)) {
8686 //
8687 // Either the slot number is out of scope or the slot is read-only.
8688 //
8690 goto Exit_Firmware_Download;
8691 }
8692
8693 //
8694 // Buffer size and alignment validation.
8695 // Max Offset and Buffer Size can be represented by SCSI command is max value for 3 bytes.
8696 //
8697 if ((firmwareDownload->BufferSize == 0) ||
8698 ((firmwareDownload->BufferSize % fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadAlignment) != 0) ||
8699 (firmwareDownload->BufferSize > fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadMaxSize) ||
8700 (firmwareDownload->BufferSize > fdoExtension->AdapterDescriptor->MaximumTransferLength) ||
8701 ((firmwareDownload->Offset % fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadAlignment) != 0) ||
8702 (firmwareDownload->Offset > 0xFFFFFF) ||
8703 (firmwareDownload->BufferSize > 0xFFFFFF)) {
8704
8706 goto Exit_Firmware_Download;
8707 }
8708
8709
8710 //
8711 // Process the request by translating it into WRITE BUFFER command.
8712 //
8713 if (((ULONG_PTR)firmwareDownload->ImageBuffer % fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadAlignment) != 0) {
8714 //
8715 // Allocate buffer aligns to ImagePayloadAlignment to accommodate the alignment requirement.
8716 //
8717 bufferSize = ALIGN_UP_BY(firmwareDownload->BufferSize, fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadAlignment);
8718
8719 //
8720 // We're done accessing HwFirmwareInfo at this point so we can release
8721 // the SyncLock.
8722 //
8723 NT_ASSERT(lockHeld);
8724 KeReleaseInStackQueuedSpinLock(&lockHandle);
8725 lockHeld = FALSE;
8726
8727#ifdef _MSC_VER
8728#pragma prefast(suppress:6014, "The allocated memory that firmwareImageBuffer points to will be freed in ClassHwFirmwareDownloadComplete().")
8729#endif
8730 firmwareImageBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, bufferSize, CLASSPNP_POOL_TAG_FIRMWARE);
8731
8732 if (firmwareImageBuffer == NULL) {
8734 goto Exit_Firmware_Download;
8735 }
8736
8737 RtlZeroMemory(firmwareImageBuffer, bufferSize);
8738
8739 RtlCopyMemory(firmwareImageBuffer, firmwareDownload->ImageBuffer, (ULONG)firmwareDownload->BufferSize);
8740
8741 } else {
8742 NT_ASSERT(lockHeld);
8743 KeReleaseInStackQueuedSpinLock(&lockHandle);
8744 lockHeld = FALSE;
8745
8746 firmwareImageBuffer = firmwareDownload->ImageBuffer;
8747 bufferSize = (ULONG)firmwareDownload->BufferSize;
8748 }
8749
8750 //
8751 // Allocate a new irp to send the WRITE BUFFER command down.
8752 // Similar process as IOCTL_STORAGE_CHECK_VERIFY.
8753 //
8754 irp2 = IoAllocateIrp((CCHAR)(DeviceObject->StackSize + 3), FALSE);
8755
8756 if (irp2 == NULL) {
8758
8759 if (firmwareImageBuffer != firmwareDownload->ImageBuffer) {
8760 FREE_POOL(firmwareImageBuffer);
8761 }
8762
8763 goto Exit_Firmware_Download;
8764 }
8765
8766 //
8767 // Make sure to acquire the lock for the new irp.
8768 //
8770
8771 irp2->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
8773
8774 //
8775 // Set the top stack location and shove the master Irp into the
8776 // top location
8777 //
8778 newStack = IoGetCurrentIrpStackLocation(irp2);
8779 newStack->Parameters.Others.Argument1 = Irp;
8780 newStack->DeviceObject = DeviceObject;
8781
8782 //
8783 // Stick the firmware download completion routine onto the stack
8784 // and prepare the irp for the port driver
8785 //
8787 ClassHwFirmwareDownloadComplete,
8788 (firmwareImageBuffer != firmwareDownload->ImageBuffer) ? firmwareImageBuffer : NULL,
8789 TRUE,
8790 TRUE,
8791 TRUE);
8792
8794 newStack = IoGetCurrentIrpStackLocation(irp2);
8795 newStack->DeviceObject = DeviceObject;
8796 newStack->MajorFunction = irpStack->MajorFunction;
8797 newStack->MinorFunction = irpStack->MinorFunction;
8798 newStack->Flags = irpStack->Flags;
8799
8800
8801 //
8802 // Mark the master irp as pending - whether the lower level
8803 // driver completes it immediately or not this should allow it
8804 // to go all the way back up.
8805 //
8807
8808 //
8809 // Setup the CDB.
8810 //
8812 cdb = SrbGetCdb(Srb);
8813 cdb->WRITE_BUFFER.OperationCode = SCSIOP_WRITE_DATA_BUFF;
8814 cdb->WRITE_BUFFER.Mode = SCSI_WRITE_BUFFER_MODE_DOWNLOAD_MICROCODE_WITH_OFFSETS_SAVE_DEFER_ACTIVATE;
8815 cdb->WRITE_BUFFER.ModeSpecific = 0; //Reserved for Mode 0x0E
8816 cdb->WRITE_BUFFER.BufferID = firmwareDownload->Slot;
8817
8818 cdb->WRITE_BUFFER.BufferOffset[0] = *((PCHAR)&firmwareDownload->Offset + 2);
8819 cdb->WRITE_BUFFER.BufferOffset[1] = *((PCHAR)&firmwareDownload->Offset + 1);
8820 cdb->WRITE_BUFFER.BufferOffset[2] = *((PCHAR)&firmwareDownload->Offset);
8821
8822 cdb->WRITE_BUFFER.ParameterListLength[0] = *((PCHAR)&bufferSize + 2);
8823 cdb->WRITE_BUFFER.ParameterListLength[1] = *((PCHAR)&bufferSize + 1);
8824 cdb->WRITE_BUFFER.ParameterListLength[2] = *((PCHAR)&bufferSize);
8825
8826 //
8827 // Send as a tagged command.
8828 //
8831
8832 //
8833 // Set timeout value.
8834 //
8835 SrbSetTimeOutValue(Srb, fdoExtension->TimeOutValue);
8836
8837 //
8838 // This routine uses a completion routine so we don't want to release
8839 // the remove lock until then.
8840 //
8842 Srb,
8843 irp2,
8844 firmwareImageBuffer,
8845 bufferSize,
8846 TRUE);
8847
8848 if (status != STATUS_PENDING) {
8849 //
8850 // If the new irp cannot be sent down, free allocated memory and bail out.
8851 //
8852 if (firmwareImageBuffer != firmwareDownload->ImageBuffer) {
8853 FREE_POOL(firmwareImageBuffer);
8854 }
8855
8856 //
8857 // If the irp cannot be sent down, the Srb has been freed. NULL it to prevent from freeing it again.
8858 //
8859 Srb = NULL;
8860
8862
8863 IoFreeIrp(irp2);
8864
8865 goto Exit_Firmware_Download;
8866 }
8867
8868 return status;
8869
8870Exit_Firmware_Download:
8871
8872 //
8873 // Release the SyncLock if it's still held.
8874 // This should only happen in the failure path.
8875 //
8876 if (lockHeld) {
8877 KeReleaseInStackQueuedSpinLock(&lockHandle);
8878 lockHeld = FALSE;
8879 }
8880
8881 //
8882 // Firmware Download request will be failed.
8883 //
8885
8886 Irp->IoStatus.Status = status;
8887
8888#else
8890 Irp->IoStatus.Status = status;
8891#endif // #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
8892
8895
8896 FREE_POOL(Srb);
8897
8898 return status;
8899}
#define ALIGN_UP_BY(size, align)
#define CLASSPNP_POOL_TAG_FIRMWARE
Definition: classp.h:198
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:395
#define SRB_HEAD_OF_QUEUE_TAG_REQUEST
Definition: srb.h:424
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:404
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
size_t bufferSize
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
#define PCHAR
Definition: match.c:90
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
FORCEINLINE VOID SrbSetSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:964
FORCEINLINE VOID SrbSetRequestAttribute(_In_ PVOID Srb, _In_ UCHAR RequestAttribute)
Definition: srbhelper.h:1131
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
char CCHAR
Definition: typedefs.h:51
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2680

Referenced by ClassDeviceControl().

◆ ClassDeviceHwFirmwareGetInfoProcess()

NTSTATUS ClassDeviceHwFirmwareGetInfoProcess ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp 
)

Definition at line 8366 of file utils.c.

8385{
8387
8388#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
8389
8390 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8391 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
8393 PSTORAGE_HW_FIRMWARE_INFO_QUERY query = (PSTORAGE_HW_FIRMWARE_INFO_QUERY)Irp->AssociatedIrp.SystemBuffer;
8394 BOOLEAN passDown = FALSE;
8395 BOOLEAN copyData = FALSE;
8396
8397
8398 //
8399 // Input buffer is not big enough to contain required input information.
8400 //
8401 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_HW_FIRMWARE_INFO_QUERY)) {
8402
8404 goto Exit_Firmware_Get_Info;
8405 }
8406
8407 //
8408 // Output buffer is too small to contain return data.
8409 //
8410 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_HW_FIRMWARE_INFO)) {
8411
8413 goto Exit_Firmware_Get_Info;
8414 }
8415
8416 //
8417 // Only process the request for a supported port driver.
8418 //
8421 goto Exit_Firmware_Get_Info;
8422 }
8423
8424 //
8425 // Buffer "FunctionSupportInfo" is allocated during start device process. Following check defends against the situation
8426 // of receiving this IOCTL when the device is created but not started, or device start failed but did not get removed yet.
8427 //
8428 if (commonExtension->IsFdo && (fdoExtension->FunctionSupportInfo == NULL)) {
8429
8431 goto Exit_Firmware_Get_Info;
8432 }
8433
8434 //
8435 // Process the situation that request should be forwarded to lower level.
8436 //
8437 if (!commonExtension->IsFdo) {
8438 passDown = TRUE;
8439 }
8440
8441 if ((query->Flags & STORAGE_HW_FIRMWARE_REQUEST_FLAG_CONTROLLER) != 0) {
8442 passDown = TRUE;
8443 }
8444
8445 if (passDown) {
8446
8448
8450 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8451 return status;
8452 }
8453
8454 //
8455 // The request is for a FDO. Process the request.
8456 //
8457 if (fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport == NotSupported) {
8459 goto Exit_Firmware_Get_Info;
8460 } else {
8461 //
8462 // Retrieve information from lower layer for the request. The cached information is not used
8463 // in case device firmware information changed.
8464 //
8466 copyData = NT_SUCCESS(status);
8467 }
8468
8469Exit_Firmware_Get_Info:
8470
8471 if (copyData) {
8472 //
8473 // Firmware information is already cached in classpnp. Return a copy.
8474 //
8475 KLOCK_QUEUE_HANDLE lockHandle;
8476 KeAcquireInStackQueuedSpinLock(&fdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
8477
8478 ULONG dataLength = min(irpStack->Parameters.DeviceIoControl.OutputBufferLength, fdoExtension->FunctionSupportInfo->HwFirmwareInfo->Size);
8479
8480 memcpy(Irp->AssociatedIrp.SystemBuffer, fdoExtension->FunctionSupportInfo->HwFirmwareInfo, dataLength);
8481
8482 KeReleaseInStackQueuedSpinLock(&lockHandle);
8483
8484 Irp->IoStatus.Information = dataLength;
8485 }
8486
8487 Irp->IoStatus.Status = status;
8488
8489#else
8491 Irp->IoStatus.Status = status;
8492#endif // #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
8493
8496
8497 return status;
8498}
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define min(a, b)
Definition: monoChain.cc:55
ULONG dataLength
Definition: scsi.h:3751
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69

Referenced by ClassDeviceControl().

◆ ClassFreeOrReuseSrb()

VOID ClassFreeOrReuseSrb ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN __drv_freesMem(mem) PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 882 of file obsolete.c.

905{
906 PCOMMON_DEVICE_EXTENSION commonExt = &FdoExtension->CommonExtension;
907
908 // This function is obsolete, but still called by DISK.SYS .
909 // TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassFreeOrReuseSrb is OBSOLETE !"));
910
911 //
912 // safety net. this should never occur. if it does, it's a potential
913 // memory leak.
914 //
916
917 if (commonExt->IsSrbLookasideListInitialized){
918 /*
919 * Put the SRB back in our lookaside list.
920 *
921 * Note: Some class drivers use ClassIoComplete
922 * to complete SRBs that they themselves allocated.
923 * So we may be putting a "foreign" SRB
924 * (e.g. with a different pool tag) into our lookaside list.
925 */
927 }
928 else {
929 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,"ClassFreeOrReuseSrb: someone is trying to use an uninitialized SrbLookasideList !!!"));
930 FREE_POOL(Srb);
931 }
932}
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define ClasspFreeSrb(ext, srb)
Definition: classpnp.h:150
#define SRB_FLAGS_FREE_SENSE_BUFFER
Definition: srb.h:406
@ FdoExtension
Definition: precomp.h:48
FORCEINLINE ULONG SrbGetSrbFlags(_In_ PVOID Srb)
Definition: srbhelper.h:927
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
BOOLEAN IsSrbLookasideListInitialized
Definition: classpnp.h:610

Referenced by _Success_(), ClassIoComplete(), ClassIoCompleteAssociated(), and ClasspEjectionControl().

◆ 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 CLASS_DRIVER_EXTENSION_KEY
Definition: classpnp.h:94
#define ASSERT_PDO(x)
Definition: pci.h:38
#define _Analysis_assume_
Definition: no_sal2.h:388
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1904
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
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().

◆ ClassInitializeDispatchTables()

VOID ClassInitializeDispatchTables ( PCLASS_DRIVER_EXTENSION  DriverExtension)

Definition at line 38 of file dispatch.c.

41{
42 ULONG idx;
43
44 PAGED_CODE();
45
46 //
47 // Initialize the standard device dispatch table
48 //
49
50 for (idx = 0; idx <= IRP_MJ_MAXIMUM_FUNCTION; idx++) {
51 DriverExtension->DeviceMajorFunctionTable[idx] = ClassDispatchUnimplemented;
52 }
53
54 DriverExtension->DeviceMajorFunctionTable[IRP_MJ_CREATE] = ClassCreateClose;
55 DriverExtension->DeviceMajorFunctionTable[IRP_MJ_CLOSE] = ClassCreateClose;
56 DriverExtension->DeviceMajorFunctionTable[IRP_MJ_READ] = ClassReadWrite;
57 DriverExtension->DeviceMajorFunctionTable[IRP_MJ_WRITE] = ClassReadWrite;
59 DriverExtension->DeviceMajorFunctionTable[IRP_MJ_SCSI] = ClassInternalIoControl;
60 DriverExtension->DeviceMajorFunctionTable[IRP_MJ_SHUTDOWN] = ClassShutdownFlush;
61 DriverExtension->DeviceMajorFunctionTable[IRP_MJ_FLUSH_BUFFERS] = ClassShutdownFlush;
62 DriverExtension->DeviceMajorFunctionTable[IRP_MJ_PNP] = ClassDispatchPnp;
63 DriverExtension->DeviceMajorFunctionTable[IRP_MJ_POWER] = ClassDispatchPower;
64 DriverExtension->DeviceMajorFunctionTable[IRP_MJ_SYSTEM_CONTROL] = ClassSystemControl;
65
66
67 return;
68}
NTSTATUS NTAPI ClassSystemControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: classwmi.c:221
unsigned int idx
Definition: utils.c:41
NTSTATUS NTAPI ClassInternalIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: class.c:9394
NTSTATUS NTAPI ClassReadWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: class.c:2431
NTSTATUS NTAPI ClassDeviceControlDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: class.c:7258
NTSTATUS NTAPI ClassDispatchPnp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: class.c:894
NTSTATUS NTAPI ClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: class.c:8773
NTSTATUS NTAPI ClassCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: create.c:57
DRIVER_DISPATCH ClassDispatchUnimplemented
Definition: dispatch.c:30
NTSTATUS NTAPI ClassDispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: power.c:105
PPCI_DRIVER_EXTENSION DriverExtension
Definition: pci.c:31
#define IRP_MJ_SCSI
#define IRP_MJ_SYSTEM_CONTROL
#define IRP_MJ_FLUSH_BUFFERS
#define IRP_MJ_POWER
#define IRP_MJ_MAXIMUM_FUNCTION

Referenced by _IRQL_requires_max_().

◆ ClassIoCompletion()

NTSTATUS ClassIoCompletion ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context 
)

◆ ClassMinimalPowerHandler()

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

Definition at line 1890 of file power.c.

1894{
1895 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
1898
1901
1902 switch (irpStack->MinorFunction)
1903 {
1904 case IRP_MN_SET_POWER:
1905 {
1906 switch (irpStack->Parameters.Power.ShutdownType)
1907 {
1908 case PowerActionNone:
1909 case PowerActionSleep:
1911 {
1912 if (TEST_FLAG(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA))
1913 {
1915 {
1916 //
1917 // This flag will cause the filesystem to verify the
1918 // volume when coming out of hibernation or standby or runtime power
1919 //
1921 }
1922 }
1923 }
1924 break;
1925 }
1926 }
1927
1928 //
1929 // Fall through
1930 //
1931
1932 case IRP_MN_QUERY_POWER:
1933 {
1934 if (!commonExtension->IsFdo)
1935 {
1936 Irp->IoStatus.Status = STATUS_SUCCESS;
1937 Irp->IoStatus.Information = 0;
1938 }
1939 }
1940 break;
1941 }
1942
1943 if (commonExtension->IsFdo)
1944 {
1946 status = PoCallDriver(commonExtension->LowerDeviceObject, Irp);
1947 }
1948 else
1949 {
1950 status = Irp->IoStatus.Status;
1952 }
1953
1954 return status;
1955} // end ClassMinimalPowerHandler()
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
PVPB NTAPI ClassGetVpb(_In_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:11473
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
@ PowerActionNone
Definition: ntpoapi.h:123
@ PowerActionHibernate
Definition: ntpoapi.h:126
@ PowerActionSleep
Definition: ntpoapi.h:125
struct _IO_STACK_LOCATION::@3978::@4014 Power
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define VPB_MOUNTED
Definition: iotypes.h:1807

Referenced by _IRQL_requires_max_().

◆ ClasspAccessAlignmentProperty()

NTSTATUS ClasspAccessAlignmentProperty ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 1700 of file utils.c.

1709{
1711
1712 PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1714 PSTORAGE_PROPERTY_QUERY query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
1716 ULONG length = 0;
1717 ULONG information = 0;
1718
1720
1721 //
1722 // check registry setting and fail the IOCTL if it's required.
1723 // this registry setting can be used to work around issues which upper layer doesn't support large physical sector size.
1724 //
1725 if (fdoExtension->FunctionSupportInfo->RegAccessAlignmentQueryNotSupported) {
1727 goto Exit;
1728 }
1729
1730 if ( (DeviceObject->DeviceType != FILE_DEVICE_DISK) ||
1731 (TEST_FLAG(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE)) ||
1732 (fdoExtension->FunctionSupportInfo->LowerLayerSupport.AccessAlignmentProperty == Supported) ) {
1733 // if it's not disk, forward the request to lower layer,
1734 // if the IOCTL is supported by lower stack, forward it down.
1736
1738 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1739 return status;
1740 }
1741
1742 //
1743 // Check proper query type.
1744 //
1745
1746 if (query->QueryType == PropertyExistsQuery) {
1748 goto Exit;
1749 } else if (query->QueryType != PropertyStandardQuery) {
1751 goto Exit;
1752 }
1753
1754 //
1755 // Request validation.
1756 // Note that InputBufferLength and IsFdo have been validated before entering this routine.
1757 //
1758
1762 goto Exit;
1763 }
1764
1765 // do not touch this buffer because it can still be used as input buffer for lower layer in 'SupportUnknown' case.
1766 accessAlignment = (PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1767
1768 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
1769
1771
1772 if (length >= sizeof(STORAGE_DESCRIPTOR_HEADER)) {
1773
1775 accessAlignment->Version = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
1776 accessAlignment->Size = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
1778 goto Exit;
1779 }
1780
1782 goto Exit;
1783 }
1784
1785 // not support Cache Line,
1786 // 'BytesPerCacheLine' and 'BytesOffsetForCacheAlignment' fields are zero-ed.
1787
1788 //
1789 // note that 'Supported' case has been handled at the beginning of this function.
1790 //
1791 switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.AccessAlignmentProperty) {
1792 case SupportUnknown: {
1793 // send down request and wait for the request to complete.
1794 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1795
1797 // case 1: the request is not supported by lower layer, sends down command
1798 // some port drivers (or filter drivers) return STATUS_INVALID_DEVICE_REQUEST if a request is not supported.
1799
1800 // ClassReadCapacity16() will either return status from cached data or send command to retrieve the information.
1801 if (ClasspIsObsoletePortDriver(fdoExtension) == FALSE) {
1802 status = ClassReadCapacity16(fdoExtension, Srb);
1803 } else {
1804 fdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus = status;
1805 }
1806
1807 // data is ready in fdoExtension
1808 // set the support status after the SCSI command is executed to avoid racing condition between multiple same type of requests.
1809 fdoExtension->FunctionSupportInfo->LowerLayerSupport.AccessAlignmentProperty = NotSupported;
1810
1811 if (NT_SUCCESS(status)) {
1812 // fill output buffer
1813 RtlZeroMemory(accessAlignment, length);
1814 accessAlignment->Version = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
1815 accessAlignment->Size = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
1816 accessAlignment->BytesPerLogicalSector = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerLogicalSector;
1817 accessAlignment->BytesPerPhysicalSector = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerPhysicalSector;
1818 accessAlignment->BytesOffsetForSectorAlignment = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesOffsetForSectorAlignment;
1819
1820 // set returned data length
1822 } else {
1823 information = 0;
1824 }
1825
1826 } else {
1827 // case 2: the request is supported and it completes successfully
1828 // case 3: the request is supported by lower stack but other failure status is returned.
1829 // from now on, the same request will be send down to lower stack directly.
1830 fdoExtension->FunctionSupportInfo->LowerLayerSupport.AccessAlignmentProperty = Supported;
1831 information = (ULONG)Irp->IoStatus.Information;
1832
1833
1834 }
1835
1836
1837 goto Exit;
1838
1839 break;
1840 }
1841
1842 case NotSupported: {
1843
1844 // ClassReadCapacity16() will either return status from cached data or send command to retrieve the information.
1845 status = ClassReadCapacity16(fdoExtension, Srb);
1846
1847 if (NT_SUCCESS(status)) {
1848 RtlZeroMemory(accessAlignment, length);
1849 accessAlignment->Version = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
1850 accessAlignment->Size = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR);
1851 accessAlignment->BytesPerLogicalSector = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerLogicalSector;
1852 accessAlignment->BytesPerPhysicalSector = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerPhysicalSector;
1853 accessAlignment->BytesOffsetForSectorAlignment = fdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesOffsetForSectorAlignment;
1854
1856 } else {
1857 information = 0;
1858 }
1859 goto Exit;
1860
1861 break;
1862 }
1863
1864 case Supported: {
1865 NT_ASSERT(FALSE); // this case is handled at the beginning of the function.
1867 break;
1868 }
1869
1870 } // end of switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.AccessAlignmentProperty)
1871
1872Exit:
1873
1874 //
1875 // Set the size and status in IRP
1876 //
1877 Irp->IoStatus.Information = information;
1878 Irp->IoStatus.Status = status;
1879
1882
1883 return status;
1884}
FORCEINLINE BOOLEAN ClasspLowerLayerNotSupport(_In_ NTSTATUS Status)
Definition: classp.h:2638
FORCEINLINE BOOLEAN ClasspIsObsoletePortDriver(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classp.h:1335
@ Supported
Definition: classpnp.h:733
@ SupportUnknown
Definition: classpnp.h:732
static PDB_INFORMATION information
Definition: db.cpp:178
struct _COMMON_DEVICE_EXTENSION * PCOMMON_DEVICE_EXTENSION
NTSTATUS NTAPI ClassForwardIrpSynchronous(_In_ PCOMMON_DEVICE_EXTENSION CommonExtension, _In_ PIRP Irp)
Definition: class.c:11343
NTSTATUS ClassReadCapacity16(_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:1568
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
#define FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
STORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
Definition: ntddstor.h:609
* PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
Definition: ntddstor.h:609
struct _STORAGE_PROPERTY_QUERY * PSTORAGE_PROPERTY_QUERY
@ PropertyExistsQuery
Definition: ntddstor.h:506
@ PropertyStandardQuery
Definition: ntddstor.h:505
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
static void Exit(void)
Definition: sock.c:1330

Referenced by ClassDeviceControl().

◆ ClasspAllocatePowerProcessIrp()

NTSTATUS ClasspAllocatePowerProcessIrp ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

◆ ClasspAllocateReleaseQueueIrp()

NTSTATUS ClasspAllocateReleaseQueueIrp ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

◆ 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()
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
KSPIN_LOCK ReleaseQueueSpinLock
Definition: classpnp.h:911
SCSI_REQUEST_BLOCK ReleaseQueueSrb
Definition: classpnp.h:913
USHORT Length
Definition: srb.h:249
_Must_inspect_result_ _In_ WDFDEVICE Fdo
Definition: wdffdo.h:461

◆ ClasspBinaryToAscii()

_IRQL_requires_same_ PUCHAR ClasspBinaryToAscii ( _In_reads_(Length) PUCHAR  HexBuffer,
_In_ ULONG  Length,
_Inout_ PULONG  UpdateLength 
)

Definition at line 7717 of file utils.c.

7744{
7745 static const UCHAR integerTable[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
7746 ULONG i;
7747 ULONG j;
7748 ULONG actualLength;
7749 PUCHAR buffer = NULL;
7750 UCHAR highWord;
7751 UCHAR lowWord;
7752
7753 TracePrint((TRACE_LEVEL_VERBOSE,
7754 TRACE_FLAG_IOCTL,
7755 "ClasspBinaryToAscii (HexBuff %p): Entering function.\n",
7756 HexBuffer));
7757
7758 if (!HexBuffer || Length == 0) {
7759 *UpdateLength = 0;
7760 goto __ClasspBinaryToAscii_Exit;
7761 }
7762
7763 //
7764 // Each byte converts into 2 chars:
7765 // e.g. 0x05 => '0' '5'
7766 // 0x0C => '0' 'C'
7767 // 0x12 => '1' '2'
7768 // And we need a terminating NULL for the string.
7769 //
7770 actualLength = (Length * 2) + 1;
7771
7772 //
7773 // Allocate the buffer.
7774 //
7775 buffer = ExAllocatePoolWithTag(NonPagedPoolNx, actualLength, CLASSPNP_POOL_TAG_TOKEN_OPERATION);
7776 if (!buffer) {
7777
7778 TracePrint((TRACE_LEVEL_ERROR,
7779 TRACE_FLAG_IOCTL,
7780 "ClasspBinaryToAscii (HexBuff %p): Failed to allocate buffer for ASCII equivalent.\n",
7781 HexBuffer));
7782
7783 *UpdateLength = 0;
7784 goto __ClasspBinaryToAscii_Exit;
7785 }
7786
7787 RtlZeroMemory(buffer, actualLength);
7788
7789 for (i = 0, j = 0; i < Length; i++) {
7790
7791 //
7792 // Split out each nibble from the binary byte.
7793 //
7794 highWord = HexBuffer[i] >> 4;
7795 lowWord = HexBuffer[i] & 0x0F;
7796
7797 //
7798 // Using the lookup table, convert and stuff into
7799 // the ascii buffer.
7800 //
7801 buffer[j++] = integerTable[highWord];
7802#ifdef _MSC_VER
7803#pragma warning(suppress: 6386) // PREFast bug means it doesn't see that Length < actualLength
7804#endif
7805 buffer[j++] = integerTable[lowWord];
7806 }
7807
7808 //
7809 // Update the caller's length field.
7810 //
7811 *UpdateLength = actualLength;
7812
7813__ClasspBinaryToAscii_Exit:
7814
7815 TracePrint((TRACE_LEVEL_VERBOSE,
7816 TRACE_FLAG_IOCTL,
7817 "ClasspBinaryToAscii (HexBuff %p): Exiting function with buffer %s.\n",
7818 HexBuffer,
7819 (buffer == NULL) ? "" : (const char*)buffer));
7820
7821 return buffer;
7822}
#define CLASSPNP_POOL_TAG_TOKEN_OPERATION
Definition: classp.h:193
GLuint buffer
Definition: glext.h:5915
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 GLint GLint j
Definition: glfuncs.h:250
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by ClasspContinueOffloadWrite(), and ClasspReceivePopulateTokenInformationTransferPacketDone().

◆ 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

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

◆ ClasspBuildDeviceMdl()

PMDL ClasspBuildDeviceMdl ( PVOID  Buffer,
ULONG  BufferLen,
BOOLEAN  WriteToDevice 
)

Definition at line 582 of file utils.c.

583{
584 PMDL mdl;
585
586 mdl = IoAllocateMdl(Buffer, BufferLen, FALSE, FALSE, NULL);
587 if (mdl){
588 _SEH2_TRY {
590#ifdef _MSC_VER
591 #pragma warning(suppress: 6320) // We want to handle any exception that MmProbeAndLockPages might throw
592#endif
595
596 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClasspBuildDeviceMdl: MmProbeAndLockPages failed with %xh.", status));
597 IoFreeMdl(mdl);
598 mdl = NULL;
599 } _SEH2_END;
600 }
601 else {
602 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClasspBuildDeviceMdl: IoAllocateMdl failed"));
603 }
604
605 return mdl;
606}
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:992
MDL * mdl
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
#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
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864

Referenced by BuildDeviceInputMdl().

◆ ClasspBuildRequestEx()

VOID ClasspBuildRequestEx ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
_In_ PIRP  Irp,
_In_ __drv_aliasesMem PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 537 of file obsolete.c.

575{
578
579 LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
580
581 PCDB cdb;
582 ULONG logicalBlockAddress;
583 USHORT transferBlocks;
586
587 // This function is obsolete, but still called by CDROM.SYS .
588 // TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClasspBuildRequestEx is OBSOLETE !"));
589
590 if (Srb == NULL) {
592 return;
593 }
594
595 //
596 // Calculate relative sector address.
597 //
598
599 logicalBlockAddress =
600 (ULONG)(Int64ShrlMod32(startingOffset.QuadPart,
601 FdoExtension->SectorShift));
602
603 //
604 // Prepare the SRB.
605 // NOTE - for extended SRB, size used is based on allocation in ClasspAllocateSrb.
606 //
607
608 if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
612 1,
614 if (!NT_SUCCESS(status)) {
616 return;
617 }
618
620 } else {
622
623 //
624 // Write length to SRB.
625 //
626
627 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
628
630 }
631
632
633 //
634 // Set up IRP Address.
635 //
636
637 SrbSetOriginalRequest(srbHeader, Irp);
638
639 //
640 // Set up data buffer
641 //
642
643 SrbSetDataBuffer(srbHeader,
644 MmGetMdlVirtualAddress(Irp->MdlAddress));
645
646 //
647 // Save byte count of transfer in SRB Extension.
648 //
649
650 SrbSetDataTransferLength(srbHeader,
651 currentIrpStack->Parameters.Read.Length);
652
653 //
654 // Initialize the queue actions field.
655 //
656
658
659 //
660 // Queue sort key is Relative Block Address.
661 //
662
663 SrbSetQueueSortKey(srbHeader, logicalBlockAddress);
664
665 //
666 // Indicate auto request sense by specifying buffer and size.
667 //
668
669 SrbSetSenseInfoBuffer(srbHeader, FdoExtension->SenseData);
671
672 //
673 // Set timeout value of one unit per 64k bytes of data.
674 //
675
676 SrbSetTimeOutValue(srbHeader,
677 ((SrbGetDataTransferLength(srbHeader) + 0xFFFF) >> 16) *
678 FdoExtension->TimeOutValue);
679
680 //
681 // Indicate that 10-byte CDB's will be used.
682 //
683
684 SrbSetCdbLength(srbHeader, 10);
685
686 //
687 // Fill in CDB fields.
688 //
689
690 cdb = SrbGetCdb(srbHeader);
691 NT_ASSERT(cdb != NULL);
692
693 transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >>
694 FdoExtension->SectorShift);
695
696 //
697 // Move little endian values into CDB in big endian format.
698 //
699
700 cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3;
701 cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2;
702 cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1;
703 cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0;
704
705 cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1;
706 cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0;
707
708 //
709 // Set transfer direction flag and Cdb command.
710 //
711
712 if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
713
714 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "ClassBuildRequest: Read Command\n"));
715
717 cdb->CDB10.OperationCode = SCSIOP_READ;
718
719 } else {
720
721 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "ClassBuildRequest: Write Command\n"));
722
724 cdb->CDB10.OperationCode = SCSIOP_WRITE;
725
726 }
727
728 //
729 // If this is not a write-through request, then allow caching.
730 //
731
732 if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) {
733
735
736 } else {
737
738 //
739 // If write caching is enable then force media access in the
740 // cdb.
741 //
742
743 cdb->CDB10.ForceUnitAccess = FdoExtension->CdbForceUnitAccess;
744 }
745
748 }
749
750 //
751 // OR in the default flags from the device object.
752 //
753
754 SrbSetSrbFlags(srbHeader, FdoExtension->SrbFlags);
755
756 //
757 // Set up major SCSI function.
758 //
759
760 nextIrpStack->MajorFunction = IRP_MJ_SCSI;
761
762 //
763 // Save SRB address in next stack for port driver.
764 //
765
766 nextIrpStack->Parameters.Scsi.Srb = Srb;
767
768 //
769 // Save retry count in current IRP stack.
770 //
771
772 currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
773
774 //
775 // Set up IoCompletion routine address.
776 //
777
779
780}
#define MAXIMUM_RETRIES
Definition: cdrom.h:124
#define SRB_CLASS_FLAGS_PAGING
Definition: cdrom.h:165
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
#define SCSIOP_READ
Definition: cdrw_hw.h:905
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
FORCEINLINE UCHAR GET_FDO_EXTENSON_SENSE_DATA_LENGTH(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classpnp.h:1437
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
NTSTATUS NTAPI ClassIoComplete(IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN PVOID Context)
Definition: class.c:3768
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:401
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:423
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
#define SRB_FLAGS_ADAPTER_CACHE_ENABLE
Definition: srb.h:405
struct _FOUR_BYTE * PFOUR_BYTE
#define Int64ShrlMod32(a, b)
unsigned short USHORT
Definition: pedump.c:61
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:664
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:666
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:661
@ SrbExDataTypeScsiCdb16
Definition: srb.h:459
struct SRB_ALIGN _STORAGE_REQUEST_BLOCK_HEADER * PSTORAGE_REQUEST_BLOCK_HEADER
FORCEINLINE VOID SrbSetQueueSortKey(_In_ PVOID Srb, _In_ ULONG QueueSortKey)
Definition: srbhelper.h:839
FORCEINLINE VOID SrbSetDataTransferLength(_In_ PVOID Srb, _In_ ULONG DataTransferLength)
Definition: srbhelper.h:784
FORCEINLINE VOID SrbSetOriginalRequest(_In_ PVOID Srb, _In_opt_ PVOID OriginalRequest)
Definition: srbhelper.h:710
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
FORCEINLINE VOID SrbSetDataBuffer(_In_ PVOID Srb, _In_opt_ __drv_aliasesMem PVOID DataBuffer)
Definition: srbhelper.h:747
FORCEINLINE ULONG SrbGetDataTransferLength(_In_ PVOID Srb)
Definition: srbhelper.h:765
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
struct _IO_STACK_LOCATION::@3978::@4017 Others
struct _IO_STACK_LOCATION::@3978::@4000 Scsi
UCHAR Function
Definition: srb.h:250
void * PVOID
Definition: typedefs.h:50
struct _CDB::_CDB10 CDB10
LONGLONG QuadPart
Definition: typedefs.h:114
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define SL_WRITE_THROUGH
Definition: iotypes.h:1824
#define IRP_SYNCHRONOUS_PAGING_IO
#define MmGetMdlVirtualAddress(_Mdl)

Referenced by ClassBuildRequest().

◆ ClasspCalculateLogicalSectorSize()

ULONG ClasspCalculateLogicalSectorSize ( _In_ PDEVICE_OBJECT  Fdo,
_In_ ULONG  BytesPerBlockInBigEndian 
)

Definition at line 1483 of file utils.c.

1492{
1493 ULONG logicalSectorSize;
1494
1495 REVERSE_BYTES(&logicalSectorSize, &BytesPerBlockInBigEndian);
1496
1497 if (logicalSectorSize == 0) {
1498 logicalSectorSize = 512;
1499 } else {
1500 //
1501 // Clear all but the highest set bit.
1502 // That will give us a bytesPerSector value that is a power of 2.
1503 //
1504 if (logicalSectorSize & (logicalSectorSize-1)) {
1505 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "FDO %ph has non-standard sector size 0x%x.", Fdo, logicalSectorSize));
1506 do {
1507 logicalSectorSize &= logicalSectorSize-1;
1508 }
1509 while (logicalSectorSize & (logicalSectorSize-1));
1510 }
1511 }
1512
1513 return logicalSectorSize;
1514}
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465

Referenced by InterpretCapacityData(), and InterpretReadCapacity16Data().

◆ 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().

◆ ClasspCleanupProtectedLocks()

VOID ClasspCleanupProtectedLocks ( IN PFILE_OBJECT_EXTENSION  FsContext)

Definition at line 296 of file create.c.

299{
300 PCOMMON_DEVICE_EXTENSION commonExtension =
301 FsContext->DeviceObject->DeviceExtension;
302
303 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
304 commonExtension->PartitionZeroExtension;
305
306 ULONG newDeviceLockCount = 1;
307
308 PAGED_CODE();
309
310 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
311 "ClasspCleanupProtectedLocks called for %p\n",
312 FsContext->DeviceObject));
313 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
314 "ClasspCleanupProtectedLocks - FsContext %p is locked "
315 "%d times\n", FsContext, FsContext->LockCount));
316
318
319 //
320 // Synchronize with ejection and ejection control requests.
321 //
322
327 FALSE,
328 NULL);
329
330 //
331 // For each secure lock on this handle decrement the secured lock count
332 // for the FDO. Keep track of the new value.
333 //
334
335 if (FsContext->LockCount != 0) {
336
337 do {
338
339 InterlockedDecrement((volatile LONG *)&FsContext->LockCount);
340
341 newDeviceLockCount =
343
344 } while (FsContext->LockCount > 0);
345
346 //
347 // If the new lock count has been dropped to zero then issue a lock
348 // command to the device.
349 //
350
351 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
352 "ClasspCleanupProtectedLocks: FDO secured lock count = %d "
353 "lock count = %d\n",
354 fdoExtension->ProtectedLockCount,
355 fdoExtension->LockCount));
356
357 if ((newDeviceLockCount == 0) && (fdoExtension->LockCount == 0)) {
358
359 SCSI_REQUEST_BLOCK srb = {0};
360 UCHAR srbExBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE] = {0};
362 PCDB cdb = NULL;
364 PSCSI_REQUEST_BLOCK srbPtr;
365
366 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
367 "ClasspCleanupProtectedLocks: FDO lock count dropped "
368 "to zero\n"));
369
370 if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
371#ifdef _MSC_VER
372 #pragma prefast(suppress:26015, "InitializeStorageRequestBlock ensures buffer access is bounded")
373#endif
376 sizeof(srbExBuffer),
377 1,
379 if (NT_SUCCESS(status)) {
380 srbEx->TimeOutValue = fdoExtension->TimeOutValue;
381 SrbSetCdbLength(srbEx, 6);
382 cdb = SrbGetCdb(srbEx);
383 srbPtr = (PSCSI_REQUEST_BLOCK)srbEx;
384 } else {
385 //
386 // Should not happen. Revert to legacy SRB.
387 //
389 srb.TimeOutValue = fdoExtension->TimeOutValue;
390 srb.CdbLength = 6;
391 cdb = (PCDB) &(srb.Cdb);
392 srbPtr = &srb;
393 }
394
395 } else {
396
397 srb.TimeOutValue = fdoExtension->TimeOutValue;
398 srb.CdbLength = 6;
399 cdb = (PCDB) &(srb.Cdb);
400 srbPtr = &srb;
401
402 }
403
404 cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
405
406 //
407 // TRUE - prevent media removal.
408 // FALSE - allow media removal.
409 //
410
411 cdb->MEDIA_REMOVAL.Prevent = FALSE;
412
414 srbPtr,
415 NULL,
416 0,
417 FALSE);
418
419 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
420 "ClasspCleanupProtectedLocks: unlock request to drive "
421 "returned status %lx\n", status));
422 }
423 }
424
427 FALSE);
429 return;
430}
#define VOID
Definition: acefi.h:82
#define InterlockedDecrement
Definition: armddk.h:52
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
union _CDB * PCDB
PAGED_CODE()
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
ULONG BreakOnClose
Definition: create.c:32
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2239
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
long LONG
Definition: pedump.c:60
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
ULONG TimeOutValue
Definition: srb.h:262
UCHAR CdbLength
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:279
struct _CDB::_MEDIA_REMOVAL MEDIA_REMOVAL
@ UserRequest
Definition: ketypes.h:421

Referenced by ClasspCreateClose().

◆ ClasspCompleteIdleRequest()

VOID ClasspCompleteIdleRequest ( PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 713 of file clntirp.c.

716{
717 PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
718
719 //
720 // Issue the next idle request if there are any left in the queue, there are
721 // no non-idle requests outstanding, there are less than max idle requests
722 // outstanding, and it has been long enough since the completion of the last
723 // non-idle request.
724 //
725 if ((fdoData->IdleIoCount > 0) &&
726 (fdoData->ActiveIdleIoCount < fdoData->IdleActiveIoMax) &&
727 (fdoData->ActiveIoCount <= 0) &&
729 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_TIMER, "ClasspCompleteIdleRequest: Service next idle reqeusts\n"));
731 }
732
733 return;
734}
VOID ClasspServiceIdleRequest(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, BOOLEAN PostToDpc)
Definition: clntirp.c:757
LOGICAL ClasspIdleDurationSufficient(IN PCLASS_PRIVATE_FDO_DATA FdoData, OUT LARGE_INTEGER **CurrentTimeIn)
Definition: clntirp.c:406

Referenced by TransferPktComplete().

◆ 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 ClasspCompleteOffloadRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ NTSTATUS CompletionStatus)
Definition: class.c:13632
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
ULONG BytesPerSector
Definition: ntdddisk.h:404
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
uint64_t ULONGLONG
Definition: typedefs.h:67

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
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:391
#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
#define L(x)
Definition: ntvdm.h:50
PVOID DeviceExtension
Definition: env_spec_w32.h:418
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 InterlockedIncrement
Definition: armddk.h:53
#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
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:680
#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
#define REVERSE_BYTES_QUAD(Destination, Source)
Definition: scsi.h:3452
#define REVERSE_BYTES_SHORT(Destination, Source)
Definition: scsi.h:3474
ULONGLONG LengthInBytes
Definition: ntddstor.h:768
LONGLONG StartingOffset
Definition: ntddstor.h:767
STORAGE_OFFLOAD_TOKEN Token
Definition: ntddstor.h:1048
IO_STATUS_BLOCK IoStatus
_In_opt_ PVOID _In_ ULONG bufferLength
Definition: wdfdriver.h:109

Referenced by ClasspReceiveWriteUsingTokenInformationDone().

◆ ClasspConvertToScsiRequestBlock()

VOID ClasspConvertToScsiRequestBlock ( _Out_ PSCSI_REQUEST_BLOCK  Srb,
_In_ PSTORAGE_REQUEST_BLOCK  SrbEx 
)

Definition at line 6559 of file utils.c.

6563{
6564 PSTOR_ADDR_BTL8 storAddrBtl8;
6565 ULONG i;
6566 BOOLEAN foundEntry = FALSE;
6567 PSRBEX_DATA srbExData;
6568
6569 if ((Srb == NULL) || (SrbEx == NULL)) {
6570 return;
6571 }
6572
6574
6575 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
6576 Srb->Function = (UCHAR)SrbEx->SrbFunction;
6577 Srb->SrbStatus = SrbEx->SrbStatus;
6578 Srb->QueueTag = (UCHAR)SrbEx->RequestTag;
6579 Srb->QueueAction = (UCHAR)SrbEx->RequestAttribute;
6580 Srb->SrbFlags = SrbEx->SrbFlags;
6581 Srb->DataTransferLength = SrbEx->DataTransferLength;
6582 Srb->TimeOutValue = SrbEx->TimeOutValue;
6583 Srb->DataBuffer = SrbEx->DataBuffer;
6584 Srb->OriginalRequest = SrbEx->OriginalRequest;
6585 Srb->SrbExtension = SrbEx->MiniportContext;
6586 Srb->InternalStatus = SrbEx->SystemStatus;
6587
6588 //
6589 // Handle address fields
6590 //
6591 if (SrbEx->AddressOffset >= sizeof(STORAGE_REQUEST_BLOCK)) {
6592 storAddrBtl8 = (PSTOR_ADDR_BTL8)((PCHAR)SrbEx + SrbEx->AddressOffset);
6593
6594 if (storAddrBtl8->Type == STOR_ADDRESS_TYPE_BTL8) {
6595 Srb->PathId = storAddrBtl8->Path;
6596 Srb->TargetId = storAddrBtl8->Target;
6597 Srb->Lun = storAddrBtl8->Lun;
6598 } else {
6599 // Catch unsupported address types
6601 }
6602 }
6603
6604 //
6605 // Handle SRB function specific fields
6606 //
6607 if (SrbEx->NumSrbExData > 0) {
6608
6609 for (i = 0; i < SrbEx->NumSrbExData; i++) {
6610
6611 if ((SrbEx->SrbExDataOffset[i] == 0) ||
6612 (SrbEx->SrbExDataOffset[i] < sizeof(STORAGE_REQUEST_BLOCK))) {
6613 // Catch invalid offsets
6615 continue;
6616 }
6617
6618 srbExData = (PSRBEX_DATA)((PCHAR)SrbEx + SrbEx->SrbExDataOffset[i]);
6619
6620 switch (SrbEx->SrbFunction) {
6621
6623
6624 switch (srbExData->Type) {
6625
6627 Srb->ScsiStatus = ((PSRBEX_DATA_SCSI_CDB16)srbExData)->ScsiStatus;
6628 Srb->CdbLength = ((PSRBEX_DATA_SCSI_CDB16)srbExData)->CdbLength;
6629 Srb->SenseInfoBufferLength = ((PSRBEX_DATA_SCSI_CDB16)srbExData)->SenseInfoBufferLength;
6630 Srb->SenseInfoBuffer = ((PSRBEX_DATA_SCSI_CDB16)srbExData)->SenseInfoBuffer;
6631 RtlCopyMemory(Srb->Cdb, ((PSRBEX_DATA_SCSI_CDB16)srbExData)->Cdb, sizeof(Srb->Cdb));
6632 foundEntry = TRUE;
6633 break;
6634
6636 Srb->ScsiStatus = ((PSRBEX_DATA_SCSI_CDB32)srbExData)->ScsiStatus;
6637 Srb->CdbLength = ((PSRBEX_DATA_SCSI_CDB32)srbExData)->CdbLength;
6638 Srb->SenseInfoBufferLength = ((PSRBEX_DATA_SCSI_CDB32)srbExData)->SenseInfoBufferLength;
6639 Srb->SenseInfoBuffer = ((PSRBEX_DATA_SCSI_CDB32)srbExData)->SenseInfoBuffer;
6640
6641 // Copy only the first 16 bytes
6642 RtlCopyMemory(Srb->Cdb, ((PSRBEX_DATA_SCSI_CDB32)srbExData)->Cdb, sizeof(Srb->Cdb));
6643 foundEntry = TRUE;
6644 break;
6645
6647 Srb->ScsiStatus = ((PSRBEX_DATA_SCSI_CDB_VAR)srbExData)->ScsiStatus;
6648 Srb->CdbLength = (UCHAR)((PSRBEX_DATA_SCSI_CDB_VAR)srbExData)->CdbLength;
6649 Srb->SenseInfoBufferLength = ((PSRBEX_DATA_SCSI_CDB_VAR)srbExData)->SenseInfoBufferLength;
6650 Srb->SenseInfoBuffer = ((PSRBEX_DATA_SCSI_CDB_VAR)srbExData)->SenseInfoBuffer;
6651
6652 // Copy only the first 16 bytes
6653 RtlCopyMemory(Srb->Cdb, ((PSRBEX_DATA_SCSI_CDB_VAR)srbExData)->Cdb, sizeof(Srb->Cdb));
6654 foundEntry = TRUE;
6655 break;
6656
6657 default:
6658 break;
6659
6660 }
6661 break;
6662
6663 case SRB_FUNCTION_WMI:
6664
6665 if (srbExData->Type == SrbExDataTypeWmi) {
6666 ((PSCSI_WMI_REQUEST_BLOCK)Srb)->WMISubFunction = ((PSRBEX_DATA_WMI)srbExData)->WMISubFunction;
6667 ((PSCSI_WMI_REQUEST_BLOCK)Srb)->WMIFlags = ((PSRBEX_DATA_WMI)srbExData)->WMIFlags;
6668 ((PSCSI_WMI_REQUEST_BLOCK)Srb)->DataPath = ((PSRBEX_DATA_WMI)srbExData)->DataPath;
6669 foundEntry = TRUE;
6670 }
6671 break;
6672
6673 case SRB_FUNCTION_PNP:
6674
6675 if (srbExData->Type == SrbExDataTypePnP) {
6676 ((PSCSI_PNP_REQUEST_BLOCK)Srb)->PnPAction = ((PSRBEX_DATA_PNP)srbExData)->PnPAction;
6677 ((PSCSI_PNP_REQUEST_BLOCK)Srb)->PnPSubFunction = ((PSRBEX_DATA_PNP)srbExData)->PnPSubFunction;
6678 ((PSCSI_PNP_REQUEST_BLOCK)Srb)->SrbPnPFlags = ((PSRBEX_DATA_PNP)srbExData)->SrbPnPFlags;
6679 foundEntry = TRUE;
6680 }
6681 break;
6682
6683 case SRB_FUNCTION_POWER:
6684
6685 if (srbExData->Type == SrbExDataTypePower) {
6686 ((PSCSI_POWER_REQUEST_BLOCK)Srb)->DevicePowerState = ((PSRBEX_DATA_POWER)srbExData)->DevicePowerState;
6687 ((PSCSI_POWER_REQUEST_BLOCK)Srb)->PowerAction = ((PSRBEX_DATA_POWER)srbExData)->PowerAction;
6688 ((PSCSI_POWER_REQUEST_BLOCK)Srb)->SrbPowerFlags = ((PSRBEX_DATA_POWER)srbExData)->SrbPowerFlags;
6689 foundEntry = TRUE;
6690 }
6691 break;
6692
6693 default:
6694 break;
6695
6696 }
6697
6698 //
6699 // Quit on first match
6700 //
6701 if (foundEntry) {
6702 break;
6703 }
6704 }
6705 }
6706
6707 return;
6708}
#define SRB_FUNCTION_WMI
Definition: srb.h:331
struct _SCSI_WMI_REQUEST_BLOCK * PSCSI_WMI_REQUEST_BLOCK
struct STOR_ADDRESS_ALIGN _STOR_ADDR_BTL8 * PSTOR_ADDR_BTL8
#define STOR_ADDRESS_TYPE_BTL8
Definition: scsi.h:3525
struct _SCSI_PNP_REQUEST_BLOCK * PSCSI_PNP_REQUEST_BLOCK
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB_VAR * PSRBEX_DATA_SCSI_CDB_VAR
#define SRB_FUNCTION_POWER
Definition: srb.h:104
struct _SCSI_POWER_REQUEST_BLOCK * PSCSI_POWER_REQUEST_BLOCK
#define SRB_FUNCTION_PNP
Definition: srb.h:105
struct SRB_ALIGN _SRBEX_DATA * PSRBEX_DATA
@ SrbExDataTypeWmi
Definition: srb.h:462
@ SrbExDataTypeScsiCdb32
Definition: srb.h:460
@ SrbExDataTypePower
Definition: srb.h:463
@ SrbExDataTypeScsiCdbVar
Definition: srb.h:461
@ SrbExDataTypePnP
Definition: srb.h:464
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB16 * PSRBEX_DATA_SCSI_CDB16
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB32 * PSRBEX_DATA_SCSI_CDB32
STORAGE_REQUEST_BLOCK
Definition: srb.h:661
struct SRB_ALIGN _SRBEX_DATA_POWER * PSRBEX_DATA_POWER
struct SRB_ALIGN _SRBEX_DATA_WMI * PSRBEX_DATA_WMI
struct SRB_ALIGN _SRBEX_DATA_PNP * PSRBEX_DATA_PNP
UCHAR QueueTag
Definition: srb.h:256
UCHAR TargetId
Definition: srb.h:254
PVOID OriginalRequest
Definition: srb.h:266
UCHAR SenseInfoBufferLength
Definition: srb.h:259
PVOID DataBuffer
Definition: srb.h:263
UCHAR PathId
Definition: srb.h:253
UCHAR QueueAction
Definition: srb.h:257
PVOID SenseInfoBuffer
Definition: srb.h:264
UCHAR ScsiStatus
Definition: srb.h:252
ULONG DataTransferLength
Definition: srb.h:261
PVOID SrbExtension
Definition: srb.h:267
ULONG InternalStatus
Definition: srb.h:269
ULONG SrbFlags
Definition: srb.h:260
UCHAR SrbStatus
Definition: srb.h:251
char * PCHAR
Definition: typedefs.h:51

Referenced by ClassInterpretSenseInfo(), InterpretSenseInfoWithoutHistory(), and InterpretTransferPacketError().

◆ ClasspCreateClose()

NTSTATUS ClasspCreateClose ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 123 of file create.c.

148{
149 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
151
152 PFILE_OBJECT fileObject = irpStack->FileObject;
153
155
156 PAGED_CODE();
157
158
159 //
160 // ISSUE-2000/3/28-henrygab - if lower stack fails create/close, we end up
161 // in an inconsistent state. re-write to verify all args and allocate all
162 // required resources, then pass the irp down, then complete the
163 // transaction. this is because we also cannot forward the irp, then fail
164 // it after it has succeeded a lower-level driver.
165 //
166
167 if(irpStack->MajorFunction == IRP_MJ_CREATE) {
168
169 PIO_SECURITY_CONTEXT securityContext =
170 irpStack->Parameters.Create.SecurityContext;
171 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
172 "ClasspCREATEClose: create received for device %p\n",
173 DeviceObject));
174 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
175 "ClasspCREATEClose: desired access %lx\n",
176 securityContext->DesiredAccess));
177 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
178 "ClasspCREATEClose: file object %p\n",
179 irpStack->FileObject));
180
182
183 if(irpStack->FileObject != NULL) {
184
185 PFILE_OBJECT_EXTENSION fsContext;
186
187 //
188 // Allocate our own file object extension for this device object.
189 //
190
192 &commonExtension->FileObjectDictionary,
193 (ULONGLONG) irpStack->FileObject,
194 sizeof(FILE_OBJECT_EXTENSION),
196 (PVOID *)&fsContext);
197
198 if(NT_SUCCESS(status)) {
199
200 RtlZeroMemory(fsContext,
201 sizeof(FILE_OBJECT_EXTENSION));
202
203 fsContext->FileObject = irpStack->FileObject;
204 fsContext->DeviceObject = DeviceObject;
205 } else if (status == STATUS_OBJECT_NAME_COLLISION) {
207 }
208 }
209
210 } else {
211
212 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
213 "ClasspCreateCLOSE: close received for device %p\n",
214 DeviceObject));
215 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
216 "ClasspCreateCLOSE: file object %p\n",
217 fileObject));
218
219 if(irpStack->FileObject != NULL) {
220
221 PFILE_OBJECT_EXTENSION fsContext =
222 ClassGetFsContext(commonExtension, irpStack->FileObject);
223
224 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
225 "ClasspCreateCLOSE: file extension %p\n",
226 fsContext));
227
228 if(fsContext != NULL) {
229
230 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
231 "ClasspCreateCLOSE: extension is ours - "
232 "freeing\n"));
234
236
237 ClasspCleanupDisableMcn(fsContext);
238
239 FreeDictionaryEntry(&(commonExtension->FileObjectDictionary),
240 fsContext);
241 }
242 }
243 }
244
245 //
246 // Notify the lower levels about the create or close operation - give them
247 // a chance to cleanup too.
248 //
249
250 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
251 "ClasspCreateClose: %s for devobj %p\n",
252 (NT_SUCCESS(status) ? "Success" : "FAILED"),
253 DeviceObject));
254
255
256 if(NT_SUCCESS(status)) {
257
259
260 //
261 // Set up the event to wait on
262 //
263
265
268 TRUE, TRUE, TRUE);
269
270 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
271
272 if(status == STATUS_PENDING) {
274 Executive,
276 FALSE,
277 NULL);
278 status = Irp->IoStatus.Status;
279 }
280
281 if (!NT_SUCCESS(status)) {
282 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
283 "ClasspCreateClose: Lower driver failed, but we "
284 "succeeded. This is a problem, lock counts will be "
285 "out of sync between levels.\n"));
286 }
287
288 }
289
290
291 return status;
292}
VOID FreeDictionaryEntry(IN PDICTIONARY Dictionary, IN PVOID Entry)
Definition: dictlib.c:189
NTSTATUS AllocateDictionaryEntry(IN PDICTIONARY Dictionary, IN ULONGLONG Key, IN ULONG Size, IN ULONG Tag, OUT PVOID *Entry)
IO_COMPLETION_ROUTINE ClassSignalCompletion
Definition: classpnp.h:1330
#define CLASS_TAG_FILE_OBJECT_EXTENSION
Definition: classpnp.h:78
VOID ClasspCleanupDisableMcn(IN PFILE_OBJECT_EXTENSION FsContext)
Definition: create.c:434
VOID ClasspCleanupProtectedLocks(IN PFILE_OBJECT_EXTENSION FsContext)
Definition: create.c:296
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
struct _cl_event * event
Definition: glext.h:7739
@ SynchronizationEvent
DICTIONARY FileObjectDictionary
Definition: classpnp.h:631
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:550
PFILE_OBJECT FileObject
Definition: classpnp.h:549
ACCESS_MASK DesiredAccess
Definition: iotypes.h:2868
struct _IO_STACK_LOCATION::@3978::@3979 Create
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
@ Executive
Definition: ketypes.h:415

Referenced by ClassCreateClose().

◆ ClasspDeleteTimer()

VOID ClasspDeleteTimer ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 3798 of file autorun.c.

3817{
3818 PCLASS_PRIVATE_FDO_DATA fdoData = NULL;
3819
3820 if (FdoExtension->CommonExtension.IsFdo) {
3821 fdoData = FdoExtension->PrivateFdoData;
3822 if (fdoData != NULL) {
3823#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3824 if (fdoData->TickTimer != NULL) {
3825 EXT_DELETE_PARAMETERS parameters;
3826 ExInitializeDeleteTimerParameters(&parameters);
3827 ExDeleteTimer(fdoData->TickTimer, TRUE, FALSE, &parameters);
3828 fdoData->TickTimer = NULL;
3829 }
3830#endif
3831 fdoData->TimerInitialized = FALSE;
3832 fdoData->TickTimerEnabled = FALSE;
3833 }
3834 }
3835}
BOOLEAN TickTimerEnabled
Definition: classp.h:813
PEX_TIMER TickTimer
Definition: classp.h:676
BOOLEAN TimerInitialized
Definition: classp.h:752
NTKERNELAPI BOOLEAN NTAPI ExDeleteTimer(_In_ PEX_TIMER Timer, _In_ BOOLEAN Cancel, _In_ BOOLEAN Wait, _In_opt_ PEXT_DELETE_PARAMETERS Parameters)

Referenced by ClassPnpStartDevice().

◆ ClasspDeviceGetBlockDeviceCharacteristicsVPDPage()

NTSTATUS ClasspDeviceGetBlockDeviceCharacteristicsVPDPage ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  fdoExtension,
_In_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 2072 of file utils.c.

2095{
2097 PCDB cdb;
2098 UCHAR bufferLength = sizeof(VPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE); // data is 64 bytes
2099 ULONG allocationBufferLength = bufferLength;
2101
2102
2103#if defined(_ARM_) || defined(_ARM64_)
2104 //
2105 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
2106 // based platforms. We are taking the conservative approach here.
2107 //
2108 allocationBufferLength = ALIGN_UP_BY(allocationBufferLength,KeGetRecommendedSharedDataAlignment());
2110 allocationBufferLength,
2111 '5CcS'
2112 );
2113#else
2114
2117 '5CcS'
2118 );
2119#endif
2120 if (dataBuffer == NULL) {
2122 goto Exit;
2123 }
2124
2125 RtlZeroMemory(dataBuffer, allocationBufferLength);
2126
2127 // prepare the Srb
2128 SrbSetTimeOutValue(Srb, fdoExtension->TimeOutValue);
2131 SrbAssignSrbFlags(Srb, fdoExtension->SrbFlags);
2132
2133 SrbSetCdbLength(Srb, 6);
2134
2135 cdb = SrbGetCdb(Srb);
2136 cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY;
2137 cdb->CDB6INQUIRY3.EnableVitalProductData = 1; //EVPD bit
2139 cdb->CDB6INQUIRY3.AllocationLength = bufferLength; //AllocationLength field in CDB6INQUIRY3 is only one byte.
2140
2141 status = ClassSendSrbSynchronous(fdoExtension->CommonExtension.DeviceObject,
2142 Srb,
2143 dataBuffer,
2144 allocationBufferLength,
2145 FALSE);
2146 if (NT_SUCCESS(status)) {
2147 if (SrbGetDataTransferLength(Srb) < 0x8) {
2148 // the device should return at least 8 bytes of data for use.
2150 } else if ( (dataBuffer->PageLength != 0x3C) || (dataBuffer->PageCode != VPD_BLOCK_DEVICE_CHARACTERISTICS) ) {
2151 // 'PageLength' shall be 0x3C; and 'PageCode' shall match.
2153 } else {
2154 // cache data into fdoExtension
2155 fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.MediumRotationRate = (dataBuffer->MediumRotationRateMsb << 8) |
2156 dataBuffer->MediumRotationRateLsb;
2157 fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.MediumProductType = dataBuffer->MediumProductType;
2158 fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.NominalFormFactor = dataBuffer->NominalFormFactor;
2159 }
2160 } else {
2161 // the command failed, surface up the command error from 'status' variable. Nothing to do here.
2162 }
2163
2164Exit:
2165 if (dataBuffer != NULL) {
2167 }
2168
2169 return status;
2170}
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
#define SP_UNTAGGED
Definition: srb.h:233
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
PVOID dataBuffer
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:710
#define VPD_BLOCK_DEVICE_CHARACTERISTICS
Definition: scsi.h:2417
struct _VPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE VPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE
struct _VPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE * PVPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE
FORCEINLINE VOID SrbAssignSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:946
#define SrbSetRequestTag
Definition: srbhelper.h:869
struct _CDB::_CDB6INQUIRY3 CDB6INQUIRY3

Referenced by ClasspDeviceMediaTypeProperty(), and ClasspDeviceSeekPenaltyProperty().

◆ ClasspDeviceGetBlockLimitsVPDPage()

NTSTATUS ClasspDeviceGetBlockLimitsVPDPage ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
_Inout_bytecount_(SrbSize) PSCSI_REQUEST_BLOCK  Srb,
_In_ ULONG  SrbSize,
_Out_ PCLASS_VPD_B0_DATA  BlockLimitsData 
)

Definition at line 2521 of file utils.c.

2527{
2530 UCHAR bufferLength = VPD_MAX_BUFFER_SIZE; // use biggest buffer possible
2531 ULONG allocationBufferLength = bufferLength;
2532 PCDB cdb;
2533 PVPD_BLOCK_LIMITS_PAGE blockLimits = NULL;
2534 ULONG dataTransferLength = 0;
2535
2536 //
2537 // Set default values for UNMAP parameters based upon UNMAP support or lack
2538 // thereof.
2539 //
2540 if (FdoExtension->FunctionSupportInfo->LBProvisioningData.LBPU) {
2541 //
2542 // If UNMAP is supported, we default to the maximum LBA count and
2543 // block descriptor count. We also default the UNMAP granularity to
2544 // a single block and specify no granularity alignment.
2545 //
2546 BlockLimitsData->MaxUnmapLbaCount = (ULONG)-1;
2547 BlockLimitsData->MaxUnmapBlockDescrCount = (ULONG)-1;
2548 BlockLimitsData->OptimalUnmapGranularity = 1;
2549 BlockLimitsData->UnmapGranularityAlignment = 0;
2550 BlockLimitsData->UGAVALID = FALSE;
2551 } else {
2552 BlockLimitsData->MaxUnmapLbaCount = 0;
2553 BlockLimitsData->MaxUnmapBlockDescrCount = 0;
2554 BlockLimitsData->OptimalUnmapGranularity = 0;
2555 BlockLimitsData->UnmapGranularityAlignment = 0;
2556 BlockLimitsData->UGAVALID = FALSE;
2557 }
2558
2559 //
2560 // Try to get the Block Limits VPD page (0xB0), if it is supported.
2561 //
2562 if (FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockLimits == TRUE)
2563 {
2564#if defined(_ARM_) || defined(_ARM64_)
2565 //
2566 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
2567 // based platforms. We are taking the conservative approach here.
2568 //
2569 allocationBufferLength = ALIGN_UP_BY(allocationBufferLength, KeGetRecommendedSharedDataAlignment());
2570 dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, allocationBufferLength, '0CcS');
2571#else
2572 dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, bufferLength, '0CcS');
2573#endif
2574 if (dataBuffer == NULL)
2575 {
2576 // return without updating FdoExtension->FunctionSupportInfo->BlockLimitsData.CommandStatus
2577 // the field will remain value as "-1", so that the command will be attempted next time this function is called.
2579 goto Exit;
2580 }
2581
2582 blockLimits = (PVPD_BLOCK_LIMITS_PAGE)dataBuffer;
2583
2584 RtlZeroMemory(dataBuffer, allocationBufferLength);
2585
2586 if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
2587
2588#ifdef _MSC_VER
2589 #pragma prefast(suppress:26015, "InitializeStorageRequestBlock ensures buffer access is bounded")
2590#endif
2593 SrbSize,
2594 1,
2596
2597 if (NT_SUCCESS(status)) {
2599 } else {
2600 //
2601 // Should not occur.
2602 //
2604 }
2605 } else {
2607 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
2610 }
2611
2612 if (NT_SUCCESS(status)) {
2613 // prepare the Srb
2614 SrbSetTimeOutValue(Srb, FdoExtension->TimeOutValue);
2618
2619 SrbSetCdbLength(Srb, 6);
2620
2621 cdb = SrbGetCdb(Srb);
2622 cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY;
2623 cdb->CDB6INQUIRY3.EnableVitalProductData = 1; //EVPD bit
2624 cdb->CDB6INQUIRY3.PageCode = VPD_BLOCK_LIMITS;
2625 cdb->CDB6INQUIRY3.AllocationLength = bufferLength; //AllocationLength field in CDB6INQUIRY3 is only one byte.
2626
2628 Srb,
2629 dataBuffer,
2630 allocationBufferLength,
2631 FALSE);
2632 dataTransferLength = SrbGetDataTransferLength(Srb);
2633 }
2634
2635 //
2636 // Handle the case where we get back STATUS_DATA_OVERRUN b/c the input
2637 // buffer was larger than necessary.
2638 //
2639
2640 if (status == STATUS_DATA_OVERRUN && dataTransferLength < bufferLength)
2641 {
2643 }
2644
2645 if (NT_SUCCESS(status))
2646 {
2647 USHORT pageLength;
2648 REVERSE_BYTES_SHORT(&pageLength, &(blockLimits->PageLength));
2649
2650 //
2651 // Regardless of the device's support for unmap, cache away at least the basic block limits information
2652 //
2653 if (dataTransferLength >= 0x10 && blockLimits->PageCode == VPD_BLOCK_LIMITS) {
2654
2655 // (6:7) OPTIMAL TRANSFER LENGTH GRANULARITY
2656 REVERSE_BYTES_SHORT(&BlockLimitsData->OptimalTransferLengthGranularity, &blockLimits->OptimalTransferLengthGranularity);
2657 // (8:11) MAXIMUM TRANSFER LENGTH
2658 REVERSE_BYTES(&BlockLimitsData->MaximumTransferLength, &blockLimits->MaximumTransferLength);
2659 // (12:15) OPTIMAL TRANSFER LENGTH
2660 REVERSE_BYTES(&BlockLimitsData->OptimalTransferLength, &blockLimits->OptimalTransferLength);
2661 }
2662
2663 if ((dataTransferLength < 0x24) ||
2665 (blockLimits->PageCode != VPD_BLOCK_LIMITS))
2666 {
2667 // the device should return at least 36 bytes of data for use.
2668 // 'PageCode' shall match and we need all the relevant data after the header.
2670 }
2671 }
2672
2673 if (NT_SUCCESS(status))
2674 {
2675 // cache data into FdoExtension
2676 // (20:23) MAXIMUM UNMAP LBA COUNT
2677 REVERSE_BYTES(&BlockLimitsData->MaxUnmapLbaCount, &blockLimits->MaximumUnmapLBACount);
2678 // (24:27) MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT
2679 REVERSE_BYTES(&BlockLimitsData->MaxUnmapBlockDescrCount, &blockLimits->MaximumUnmapBlockDescriptorCount);
2680 // (28:31) OPTIMAL UNMAP GRANULARITY
2681 REVERSE_BYTES(&BlockLimitsData->OptimalUnmapGranularity, &blockLimits->OptimalUnmapGranularity);
2682
2683 // (32:35) UNMAP GRANULARITY ALIGNMENT; (32) bit7: UGAVALID
2684 BlockLimitsData->UGAVALID = blockLimits->UGAValid;
2685 if (BlockLimitsData->UGAVALID == TRUE) {
2686 REVERSE_BYTES(&BlockLimitsData->UnmapGranularityAlignment, &blockLimits->UnmapGranularityAlignment);
2687 BlockLimitsData->UnmapGranularityAlignment &= 0x7FFFFFFF; // remove value of UGAVALID bit.
2688 } else {
2689 BlockLimitsData->UnmapGranularityAlignment = 0;
2690 }
2691
2692 TracePrint((TRACE_LEVEL_INFORMATION,
2693 TRACE_FLAG_PNP,
2694 "ClasspDeviceGetBlockLimitsVPDPage (%p): %s %s (rev %s) reported following parameters: \
2695 \n\t\t\tOptimalTransferLengthGranularity: %u \
2696 \n\t\t\tMaximumTransferLength: %u \
2697 \n\t\t\tOptimalTransferLength: %u \
2698 \n\t\t\tMaximumUnmapLBACount: %u \
2699 \n\t\t\tMaximumUnmapBlockDescriptorCount: %u \
2700 \n\t\t\tOptimalUnmapGranularity: %u \
2701 \n\t\t\tUGAValid: %u \
2702 \n\t\t\tUnmapGranularityAlignment: %u\n",
2703 FdoExtension->DeviceObject,
2704 (PCSZ)(((PUCHAR)FdoExtension->DeviceDescriptor) + FdoExtension->DeviceDescriptor->VendorIdOffset),
2705 (PCSZ)(((PUCHAR)FdoExtension->DeviceDescriptor) + FdoExtension->DeviceDescriptor->ProductIdOffset),
2706 (PCSZ)(((PUCHAR)FdoExtension->DeviceDescriptor) + FdoExtension->DeviceDescriptor->ProductRevisionOffset),
2707 BlockLimitsData->OptimalTransferLengthGranularity,
2708 BlockLimitsData->MaximumTransferLength,
2709 BlockLimitsData->OptimalTransferLength,
2710 BlockLimitsData->MaxUnmapLbaCount,
2711 BlockLimitsData->MaxUnmapBlockDescrCount,
2712 BlockLimitsData->OptimalUnmapGranularity,
2713 BlockLimitsData->UGAVALID,
2714 BlockLimitsData->UnmapGranularityAlignment));
2715
2716 }
2717 } else {
2719 }
2720
2721 BlockLimitsData->CommandStatus = status;
2722
2723Exit:
2725
2726 return status;
2727}
@ Reserved1
Definition: bcd.h:201
#define VPD_MAX_BUFFER_SIZE
Definition: scsi.h:2402
struct _VPD_BLOCK_LIMITS_PAGE * PVPD_BLOCK_LIMITS_PAGE
#define VPD_BLOCK_LIMITS
Definition: scsi.h:2416
UCHAR MaximumTransferLength[4]
Definition: scsi.h:2537
UCHAR OptimalUnmapGranularity[4]
Definition: scsi.h:2542
UCHAR OptimalTransferLengthGranularity[2]
Definition: scsi.h:2536
UCHAR MaximumUnmapLBACount[4]
Definition: scsi.h:2540
UCHAR OptimalTransferLength[4]
Definition: scsi.h:2538
UCHAR MaximumUnmapBlockDescriptorCount[4]
Definition: scsi.h:2541
UCHAR PageLength[2]
Definition: scsi.h:2531
UCHAR UnmapGranularityAlignment[4]
Definition: scsi.h:2551
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
CONST char * PCSZ
Definition: umtypes.h:125

Referenced by ClasspGetLBProvisioningInfo(), and ClasspRefreshFunctionSupportInfo().

◆ ClasspDeviceGetLBAStatus()

NTSTATUS ClasspDeviceGetLBAStatus ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 3861 of file utils.c.

3911{
3914 PDEVICE_MANAGE_DATA_SET_ATTRIBUTES dsmAttributes = (PDEVICE_MANAGE_DATA_SET_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer;
3915 PDEVICE_DATA_SET_RANGE dataSetRanges = NULL;
3917 ULONG dsmOutputLength;
3918 NTSTATUS finalStatus;
3919 NTSTATUS getLBAWorkerStatus;
3920 ULONG retryCount;
3921 ULONG retryCountMax;
3922 CLASS_VPD_B0_DATA blockLimitsData;
3923 ULONG generationCount1;
3924 ULONG generationCount2;
3925 BOOLEAN blockLimitsDataMayHaveChanged;
3927 LONGLONG startingOffset;
3928 ULONGLONG lengthInBytes;
3929 BOOLEAN consolidateableBlocksOnly = FALSE;
3930 ULONG outputVersion;
3931
3932 //
3933 // Basic parameter validation.
3934 // Note that InputBufferLength and IsFdo have been validated beforing entering this routine.
3935 //
3936 if (dsmOutput == NULL ||
3937 dsmAttributes == NULL)
3938 {
3939 finalStatus = STATUS_INVALID_PARAMETER;
3940 goto Exit;
3941 }
3942
3944 //
3945 // The caller wants the mapping status of the entire disk.
3946 //
3947 ULONG unmapGranularityAlignment = 0;
3948 if (fdoExtension->FunctionSupportInfo->BlockLimitsData.UGAVALID) {
3949 unmapGranularityAlignment = fdoExtension->FunctionSupportInfo->BlockLimitsData.UnmapGranularityAlignment;
3950 }
3951 startingOffset = unmapGranularityAlignment;
3952 lengthInBytes = (ULONGLONG)fdoExtension->CommonExtension.PartitionLength.QuadPart - (ULONGLONG)startingOffset;
3953 } else {
3954 if (dsmAttributes->DataSetRangesOffset == 0 ||
3955 dsmAttributes->DataSetRangesLength == 0) {
3956 finalStatus = STATUS_INVALID_PARAMETER;
3957 goto Exit;
3958 }
3959
3960 //
3961 // We only service the first dataset range specified.
3962 //
3963 dataSetRanges = (PDEVICE_DATA_SET_RANGE)((PUCHAR)dsmAttributes + dsmAttributes->DataSetRangesOffset);
3964 startingOffset = dataSetRanges[0].StartingOffset;
3965 lengthInBytes = dataSetRanges[0].LengthInBytes;
3966 }
3967
3968
3969 //
3970 // See if the sender is requesting a specific version of the output data
3971 // structure. Othwerwise, default to V1.
3972 //
3974#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3975 if ((dsmAttributes->ParameterBlockOffset >= sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES)) &&
3976 (dsmAttributes->ParameterBlockLength >= sizeof(DEVICE_DATA_SET_LBP_STATE_PARAMETERS))) {
3977 PDEVICE_DATA_SET_LBP_STATE_PARAMETERS parameters = Add2Ptr(dsmAttributes, dsmAttributes->ParameterBlockOffset);
3978 if ((parameters->Version == DEVICE_DATA_SET_LBP_STATE_PARAMETERS_VERSION_V1) &&
3979 (parameters->Size >= sizeof(DEVICE_DATA_SET_LBP_STATE_PARAMETERS))) {
3980
3981 outputVersion = parameters->OutputVersion;
3982
3983 if ((outputVersion != DEVICE_DATA_SET_LB_PROVISIONING_STATE_VERSION_V1) &&
3985 finalStatus = STATUS_INVALID_PARAMETER;
3986 goto Exit;
3987 }
3988 }
3989 }
3990#endif
3991
3992 //
3993 // Take a snapshot of the block limits data for the worker function to use.
3994 // We need to fail the request if we fail to get updated block limits data
3995 // since we need an accurate Optimal Unmap Granularity value to properly
3996 // convert the returned mapping descriptors into a bitmap.
3997 //
3998 finalStatus = ClasspBlockLimitsDataSnapshot(fdoExtension,
3999 TRUE,
4000 &blockLimitsData,
4001 &generationCount1);
4002
4003 if (!NT_SUCCESS(finalStatus)) {
4004 information = 0;
4005 goto Exit;
4006 }
4007
4009 consolidateableBlocksOnly = TRUE;
4010 }
4011
4012 //
4013 // The retry logic is to handle the case when block limits data changes during rare occasions
4014 // (e.g. diff-VHD fork or merge).
4015 //
4016 retryCountMax = GET_LBA_STATUS_RETRY_COUNT_MAX;
4017 for (retryCount = 0; retryCount < retryCountMax; retryCount++) {
4018
4019 dsmOutputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
4020 getLBAWorkerStatus = ClasspDeviceGetLBAStatusWorker(DeviceObject,
4021 &blockLimitsData,
4022 startingOffset,
4023 lengthInBytes,
4024 dsmOutput,
4025 &dsmOutputLength,
4026 Srb,
4027 consolidateableBlocksOnly,
4028 outputVersion,
4029 &blockLimitsDataMayHaveChanged);
4030
4031 if (!NT_SUCCESS(getLBAWorkerStatus) && !blockLimitsDataMayHaveChanged) {
4032 information = 0;
4033 finalStatus = getLBAWorkerStatus;
4034 break;
4035 }
4036
4037 //
4038 // Again, we need to fail the request if we fail to get updated block
4039 // limits data since we need an accurate Optimal Unmap Granularity value.
4040 //
4041 finalStatus = ClasspBlockLimitsDataSnapshot(fdoExtension,
4042 TRUE,
4043 &blockLimitsData,
4044 &generationCount2);
4045 if (!NT_SUCCESS(finalStatus)) {
4046 information = 0;
4047 goto Exit;
4048 }
4049
4050 if (generationCount1 == generationCount2) {
4051 //
4052 // Block limits data stays the same during the call to ClasspDeviceGetLBAStatusWorker()
4053 // The result from ClasspDeviceGetLBAStatusWorker() is valid.
4054 //
4055 finalStatus = getLBAWorkerStatus;
4056 if (NT_SUCCESS(finalStatus)) {
4057 information = dsmOutputLength;
4058 }
4059 break;
4060 }
4061
4062 //
4063 // Try again with the latest block limits data
4064 //
4065 generationCount1 = generationCount2;
4066 information = 0;
4067 finalStatus = STATUS_DEVICE_DATA_ERROR;
4068 }
4069
4070Exit:
4071 Irp->IoStatus.Information = information;
4072 Irp->IoStatus.Status = finalStatus;
4075 return finalStatus;
4076}
#define GET_LBA_STATUS_RETRY_COUNT_MAX
Definition: classp.h:229
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
NTSTATUS ClasspBlockLimitsDataSnapshot(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ BOOLEAN ForceQuery, _Out_ PCLASS_VPD_B0_DATA BlockLimitsData, _Out_ PULONG GenerationCount)
Definition: class.c:16504
NTSTATUS ClasspDeviceGetLBAStatusWorker(_In_ PDEVICE_OBJECT DeviceObject, _In_ PCLASS_VPD_B0_DATA BlockLimitsData, _In_ ULONGLONG StartingOffset, _In_ ULONGLONG LengthInBytes, _Out_ PDEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT DsmOutput, _Inout_ PULONG DsmOutputLength, _Inout_ PSCSI_REQUEST_BLOCK Srb, _In_ BOOLEAN ConsolidateableBlocksOnly, _In_ ULONG OutputVersion, _Out_ PBOOLEAN BlockLimitsDataMayHaveChanged)
Definition: utils.c:4079
#define Add2Ptr(PTR, INC)
#define DEVICE_DATA_SET_LB_PROVISIONING_STATE_VERSION_V1
Definition: ntddstor.h:939
#define DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE
Definition: ntddstor.h:306
struct _DEVICE_DATA_SET_RANGE * PDEVICE_DATA_SET_RANGE
#define DEVICE_DSM_FLAG_ALLOCATION_CONSOLIDATEABLE_ONLY
Definition: ntddstor.h:963
struct _DEVICE_MANAGE_DATA_SET_ATTRIBUTES * PDEVICE_MANAGE_DATA_SET_ATTRIBUTES
#define DEVICE_DATA_SET_LB_PROVISIONING_STATE_VERSION_V2
Definition: ntddstor.h:953
LARGE_INTEGER PartitionLength
Definition: classpnp.h:618
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
int64_t LONGLONG
Definition: typedefs.h:68
#define STATUS_DEVICE_DATA_ERROR
Definition: udferr_usr.h:159

Referenced by ClassDeviceControl().

◆ ClasspDeviceGetLBAStatusWorker()

NTSTATUS ClasspDeviceGetLBAStatusWorker ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PCLASS_VPD_B0_DATA  BlockLimitsData,
_In_ ULONGLONG  StartingOffset,
_In_ ULONGLONG  LengthInBytes,
_Out_ PDEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT  DsmOutput,
_Inout_ PULONG  DsmOutputLength,
_Inout_ PSCSI_REQUEST_BLOCK  Srb,
_In_ BOOLEAN  ConsolidateableBlocksOnly,
_In_ ULONG  OutputVersion,
_Out_ PBOOLEAN  BlockLimitsDataMayHaveChanged 
)

Definition at line 4079 of file utils.c.

4147{
4149
4151
4153 ULONG bitMapGranularityInBits = FIELD_SIZE(DEVICE_DATA_SET_LB_PROVISIONING_STATE,SlabAllocationBitMap[0]) * 8;
4154 ULONG requiredOutputLength;
4155 ULONG outputLength = *DsmOutputLength;
4156
4157 ULONG blocksPerSlab;
4158 ULONGLONG bytesPerSlab;
4159 ULONGLONG alignmentInBytes = 0;
4160 ULONG alignmentInBlocks = 0;
4161 ULONG maxBufferSize;
4162 ULONG maxSlabs;
4163 ULONGLONG requestedSlabs; // Total number of slabs requested by the caller.
4164 ULONGLONG startingLBA;
4165 ULONGLONG startingOffsetDelta;
4166 ULONG totalProcessedSlabs = 0; // Total number of slabs we processed.
4167 ULONGLONG slabsPerCommand; // Number of slabs we can ask for in one Get LBA Status command.
4168 BOOLEAN doneProcessing = FALSE; // Indicates we should break out of the Get LBA Status loop.
4169
4170 ULONG lbaStatusSize;
4171 PLBA_STATUS_LIST_HEADER lbaStatusListHeader = NULL;
4172
4173 //
4174 // This function can fail if the block limits data on the device changes.
4175 // This flag tells the caller if it should retry with a newer block limits data
4176 //
4177 *BlockLimitsDataMayHaveChanged = FALSE;
4178
4179 //
4180 // Make sure we're running at PASSIVE_LEVEL
4181 //
4183 {
4186 goto Exit;
4187 }
4188
4189 //
4190 // Don't send down a Get LBA Status command if UNMAP isn't supported.
4191 //
4192 if (!fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPU)
4193 {
4194 return STATUS_NOT_SUPPORTED;
4195 goto Exit;
4196 }
4197
4198 //
4199 // Make sure we have a non-zero value for the number of bytes per block.
4200 // Otherwise we will end up dividing by zero later on.
4201 //
4202 if (fdoExtension->DiskGeometry.BytesPerSector == 0)
4203 {
4205 if(!NT_SUCCESS(status) || fdoExtension->DiskGeometry.BytesPerSector == 0)
4206 {
4208 goto Exit;
4209 }
4210 }
4211
4212 //
4213 // We only service the first dataset range specified.
4214 //
4215 if (BlockLimitsData->UGAVALID == TRUE) {
4216 alignmentInBlocks = BlockLimitsData->UnmapGranularityAlignment;
4217 alignmentInBytes = (ULONGLONG)alignmentInBlocks * (ULONGLONG)fdoExtension->DiskGeometry.BytesPerSector;
4218 }
4219
4220 //
4221 // Make sure the specified range is valid. The Unmap Granularity Alignment
4222 // defines a region at the beginning of the disk that cannot be
4223 // mapped/unmapped so the specified range should not include any part of that
4224 // region.
4225 //
4226 if (LengthInBytes == 0 ||
4227 StartingOffset < alignmentInBytes ||
4228 StartingOffset + LengthInBytes > (ULONGLONG)fdoExtension->CommonExtension.PartitionLength.QuadPart)
4229 {
4230 TracePrint((TRACE_LEVEL_ERROR,
4231 TRACE_FLAG_IOCTL,
4232 "ClasspDeviceGetLBAStatusWorker (%p): Invalid range, length is %I64u bytes, starting offset is %I64u bytes, Unmap alignment is %I64u bytes, and disk size is %I64u bytes\n",
4234 LengthInBytes,
4236 alignmentInBytes,
4238
4240 goto Exit;
4241 }
4242
4243 //
4244 // Calculate the number of bytes per slab so that we can convert (and
4245 // possibly align) the given offset (given in bytes) to slabs.
4246 //
4247 blocksPerSlab = BlockLimitsData->OptimalUnmapGranularity;
4248 bytesPerSlab = (ULONGLONG)blocksPerSlab * (ULONGLONG)fdoExtension->DiskGeometry.BytesPerSector;
4249
4250 //
4251 // If the starting offset is not slab-aligned, we need to adjust it to
4252 // be aligned with the next highest slab. We also need to save the delta
4253 // to return to the user later.
4254 //
4255 if (((StartingOffset - alignmentInBytes) % bytesPerSlab) != 0)
4256 {
4257 startingLBA = (((StartingOffset - alignmentInBytes) / bytesPerSlab) + 1) * (ULONGLONG)blocksPerSlab + alignmentInBlocks;
4258 startingOffsetDelta = (startingLBA * fdoExtension->DiskGeometry.BytesPerSector) - StartingOffset;
4259 }
4260 else
4261 {
4262 startingLBA = ((StartingOffset - alignmentInBytes) / bytesPerSlab) * (ULONGLONG)blocksPerSlab + alignmentInBlocks;
4263 startingOffsetDelta = 0;
4264 }
4265
4266 //
4267 // Caclulate the number of slabs the caller requested.
4268 //
4269 if ((LengthInBytes % bytesPerSlab) == 0) {
4270 requestedSlabs = (LengthInBytes / bytesPerSlab);
4271 } else {
4272 //
4273 // Round up the number of requested slabs if the length indicates a
4274 // partial slab. This should cover the case where the user specifies
4275 // a dataset range for the whole disk, but the size of the disk is not
4276 // a slab-multiple. Rounding up allows us to return the status of the
4277 // partial slab
4278 //
4279 requestedSlabs = (LengthInBytes / bytesPerSlab) + 1;
4280 }
4281
4282 //
4283 // If the caller asked for no slabs then return STATUS_INVALID_PARAMETER.
4284 //
4285 if (requestedSlabs == 0)
4286 {
4287 TracePrint((TRACE_LEVEL_ERROR,
4288 TRACE_FLAG_IOCTL,
4289 "ClasspDeviceGetLBAStatusWorker (%p): Invalid number (%I64u) of slabs requested\n",
4291 requestedSlabs));
4292
4294 goto Exit;
4295 }
4296
4297 //
4298 // Cap requested slabs at MAXULONG since SlabAllocationBitMapBitCount
4299 // is a 4-byte field. We may return less data than requested, but the
4300 // caller can simply re-query for the omitted portion(s).
4301 //
4302 requestedSlabs = min(requestedSlabs, MAXULONG);
4303
4304 //
4305 // Calculate the required size of the output buffer based upon the desired
4306 // version of the output structure.
4307 // In the worst case, Get LBA Status returns a descriptor for each slab
4308 // requested, thus the required output buffer length is equal to:
4309 // 1. The size of DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT; plus
4310 // 2. The size of DEVICE_DATA_SET_LB_PROVISIONING_STATE(_V2); plus
4311 // 3. The size of a ULONG array large enough to hold a bit for each slab requested.
4312 // (The first element is already allocated in DEVICE_DATA_SET_LB_PROVISIONING_STATE(_V2).)
4313 //
4314#if (NTDDI_VERSION >= NTDDI_WINBLUE)
4316
4317 requiredOutputLength = (ULONG)(sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT)
4319 + (((requestedSlabs - 1) / bitMapGranularityInBits))
4320 * FIELD_SIZE(DEVICE_DATA_SET_LB_PROVISIONING_STATE_V2, SlabAllocationBitMap[0]));
4321
4322 } else
4323#else
4324 UNREFERENCED_PARAMETER(OutputVersion);
4325#endif
4326 {
4327
4328 requiredOutputLength = (ULONG)(sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT)
4330 + (((requestedSlabs - 1) / bitMapGranularityInBits))
4331 * FIELD_SIZE(DEVICE_DATA_SET_LB_PROVISIONING_STATE, SlabAllocationBitMap[0]));
4332 }
4333
4334 //
4335 // The output buffer is not big enough to hold the requested data.
4336 // Inform the caller of the correct buffer size.
4337 //
4338 if (outputLength < requiredOutputLength)
4339 {
4341
4342 TracePrint((TRACE_LEVEL_ERROR,
4343 TRACE_FLAG_IOCTL,
4344 "ClasspDeviceGetLBAStatusWorker (%p): Given output buffer is %u bytes, needs to be %u bytes\n",
4346 outputLength,
4347 requiredOutputLength));
4348
4349 //
4350 // If the output buffer is big enough, write the required buffer
4351 // length to the first ULONG bytes of the output buffer.
4352 //
4353 if (outputLength >= sizeof(ULONG))
4354 {
4355 *((PULONG)DsmOutput) = requiredOutputLength;
4356 }
4357
4358 goto Exit;
4359 }
4360
4361 //
4362 // Calculate the maximum number of slabs that could be returned by a single
4363 // Get LBA Status command. The max buffer size could either be capped by
4364 // the Parameter Data Length field or the Max Transfer Length of the
4365 // adapter.
4366 // The number of slabs we actually ask for in a single command is the
4367 // smaller of the number of slabs requested by the user or the max number
4368 // of slabs we can theoretically ask for in a single command.
4369 //
4370 maxBufferSize = MIN(MAXULONG, fdoExtension->PrivateFdoData->HwMaxXferLen);
4371 maxSlabs = (maxBufferSize - sizeof(LBA_STATUS_LIST_HEADER)) / sizeof(LBA_STATUS_DESCRIPTOR);
4372 slabsPerCommand = min(requestedSlabs, maxSlabs);
4373
4374 //
4375 // Allocate the buffer that will contain the returned LBA Status Descriptors.
4376 // Assume that in the worst case every other slab has a different mapping
4377 // status. That means that there may be a descriptor for every slab requested.
4378 //
4379 lbaStatusSize = (ULONG)(sizeof(LBA_STATUS_LIST_HEADER) + (slabsPerCommand * sizeof(LBA_STATUS_DESCRIPTOR)));
4380#if defined(_ARM_) || defined(_ARM64_)
4381 //
4382 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
4383 // based platforms. We are taking the conservative approach here.
4384 //
4385 lbaStatusSize = ALIGN_UP_BY(lbaStatusSize,KeGetRecommendedSharedDataAlignment());
4386 lbaStatusListHeader = (PLBA_STATUS_LIST_HEADER)ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, lbaStatusSize, CLASS_TAG_LB_PROVISIONING);
4387#else
4388 lbaStatusListHeader = (PLBA_STATUS_LIST_HEADER)ExAllocatePoolWithTag(NonPagedPoolNx, lbaStatusSize, CLASS_TAG_LB_PROVISIONING);
4389#endif
4390
4391 if (lbaStatusListHeader == NULL)
4392 {
4393 TracePrint((TRACE_LEVEL_ERROR,
4394 TRACE_FLAG_IOCTL,
4395 "ClasspDeviceGetLBAStatusWorker (%p): Failed to allocate %u bytes for descriptors\n",
4397 lbaStatusSize));
4398
4399 NT_ASSERT(lbaStatusListHeader != NULL);
4401 goto Exit;
4402 }
4403
4404 //
4405 // Set default values for the output buffer.
4406 // If we process at least one slab from the device we will update the
4407 // offset and lengths accordingly.
4408 //
4409 DsmOutput->Action = DeviceDsmAction_Allocation;
4410 DsmOutput->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT);
4411 DsmOutput->OutputBlockOffset = 0;
4412 DsmOutput->OutputBlockLength = 0;
4413 *DsmOutputLength = DsmOutput->Size;
4414
4415 //
4416 // The returned DEVICE_DATA_SET_LB_PROVISIONING_STATE is at the end of the
4417 // DSM output structure. Zero it out before we start to fill it in.
4418 //
4419 lbpState = Add2Ptr(DsmOutput, sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT));
4420 RtlZeroMemory(lbpState, requiredOutputLength - sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT));
4421
4422 do {
4423 //
4424 // Send down GetLBAStatus for the current range.
4425 //
4426 status = GetLBAStatus(fdoExtension,
4427 Srb,
4428 startingLBA,
4429 lbaStatusListHeader,
4430 lbaStatusSize,
4431 ConsolidateableBlocksOnly);
4432
4433 if (NT_SUCCESS(status))
4434 {
4435 ULONG descrIndex = 0;
4436 ULONG descrSize = 0;
4437 ULONG descrSizeOverhead;
4438 ULONG descrCount = 0;
4439 ULONGLONG expectedStartingLBA;
4440 BOOLEAN processCurrentDescriptor = TRUE;
4441 ULONG commandProcessedSlabs = 0; // Number of slabs processed for this command.
4442
4443 descrSizeOverhead = FIELD_OFFSET(LBA_STATUS_LIST_HEADER, Descriptors[0]) -
4445 REVERSE_BYTES(&descrSize, &(lbaStatusListHeader->ParameterLength));
4446
4447 //
4448 // If the returned Parameter Data Length field describes more
4449 // descriptors than we allocated space for then make sure we don't
4450 // try to process more descriptors than are actually present.
4451 //
4452 if (descrSize > (lbaStatusSize - RTL_SIZEOF_THROUGH_FIELD(LBA_STATUS_LIST_HEADER, ParameterLength))) {
4453 descrSize = (lbaStatusSize - RTL_SIZEOF_THROUGH_FIELD(LBA_STATUS_LIST_HEADER, ParameterLength));
4454 }
4455
4456 if (descrSize >= descrSizeOverhead) {
4457 descrSize -= descrSizeOverhead;
4458 descrCount = descrSize / sizeof(LBA_STATUS_DESCRIPTOR);
4459
4460 //
4461 // Make sure at least one descriptor was returned.
4462 //
4463 if (descrCount > 0) {
4464 //
4465 // We expect the first starting LBA returned by the device to be the
4466 // same starting LBA we specified in the command.
4467 //
4468 expectedStartingLBA = startingLBA;
4469
4470 //
4471 // Translate the returned LBA status descriptors into a bitmap where each bit represents
4472 // a slab. The slab size is represented by the Optimal Unmap Granularity.
4473 // 1 = The slab is mapped.
4474 // 0 = The slab is unmapped (deallocated or anchored).
4475 //
4476 for (descrIndex = 0; descrIndex < descrCount && totalProcessedSlabs < requestedSlabs && !doneProcessing; descrIndex++)
4477 {
4478 PLBA_STATUS_DESCRIPTOR lbaStatusDescr = &(lbaStatusListHeader->Descriptors[descrIndex]);
4479 ULONGLONG returnedStartingLBA;
4480 ULONG mapped = (lbaStatusDescr->ProvisioningStatus != LBA_STATUS_MAPPED) ? 0x0 : 0x1;
4481 ULONG lbaCount = 0;
4482
4483 REVERSE_BYTES_QUAD(&returnedStartingLBA, &(lbaStatusDescr->StartingLBA));
4484 REVERSE_BYTES(&lbaCount, &(lbaStatusDescr->LogicalBlockCount));
4485
4486 if (returnedStartingLBA != expectedStartingLBA)
4487 {
4488 //
4489 // We expect the descriptors will express a contiguous range of LBAs.
4490 // If the starting LBA is not contiguous with the LBA range from the
4491 // previous descriptor then we should not process any more descriptors,
4492 // including the current one.
4493 //
4494 TracePrint((TRACE_LEVEL_ERROR,
4495 TRACE_FLAG_IOCTL,
4496 "ClasspDeviceGetLBAStatusWorker (%p): Device returned starting LBA = %I64x when %I64x was expected.\n",
4498 returnedStartingLBA,
4499 startingLBA));
4500
4501 doneProcessing = TRUE;
4502 processCurrentDescriptor = FALSE;
4503 *BlockLimitsDataMayHaveChanged = TRUE;
4504 }
4505 else if (lbaCount > 0 && lbaCount % blocksPerSlab != 0)
4506 {
4507 //
4508 // If the device returned an LBA count with a partial slab, round
4509 // the LBA count up to the nearest slab and set a flag to stop
4510 // processing further descriptors. This is mainly to handle the
4511 // case where disk size may not be slab-aligned and thus the last
4512 // "slab" is actually a partial slab.
4513 //
4514 TracePrint((TRACE_LEVEL_WARNING,
4515 TRACE_FLAG_IOCTL,
4516 "ClasspDeviceGetLBAStatusWorker (%p): Device returned an LBA count (%u) that is not a multiple of the slab size (%u)\n",
4518 lbaCount,
4519 blocksPerSlab));
4520
4521 lbaCount = ((lbaCount / blocksPerSlab) + 1) * blocksPerSlab;
4522
4523 doneProcessing = TRUE;
4524 processCurrentDescriptor = TRUE;
4525 }
4526 else if (lbaCount == 0)
4527 {
4528 //
4529 // If the LBA count is 0, just skip this descriptor.
4530 //
4531 TracePrint((TRACE_LEVEL_WARNING,
4532 TRACE_FLAG_IOCTL,
4533 "ClasspDeviceGetLBAStatusWorker (%p): Device returned a zero LBA count\n",
4534 DeviceObject));
4535
4536 processCurrentDescriptor = FALSE;
4537 }
4538
4539 //
4540 // Generate bits for the slabs described in the current descriptor.
4541 // It's possible the device may have returned more slabs than requested
4542 // so we make sure to stop once we've processed all we need.
4543 //
4544 if (processCurrentDescriptor)
4545 {
4546 ULONG descrSlabs = lbaCount / blocksPerSlab; // Number of slabs in this descriptor.
4547
4548 for(; 0 < descrSlabs && totalProcessedSlabs < requestedSlabs; descrSlabs--, commandProcessedSlabs++, totalProcessedSlabs++)
4549 {
4550 ULONG bitMapIndex = totalProcessedSlabs / bitMapGranularityInBits;
4551 ULONG bitPos = totalProcessedSlabs % bitMapGranularityInBits;
4552
4553 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
4555 ((PDEVICE_DATA_SET_LB_PROVISIONING_STATE_V2)lbpState)->SlabAllocationBitMap[bitMapIndex] |= (mapped << bitPos);
4556 } else
4557 #endif
4558 {
4559 lbpState->SlabAllocationBitMap[bitMapIndex] |= (mapped << bitPos);
4560 }
4561 }
4562 }
4563
4564 //
4565 // Calculate the next expected starting LBA.
4566 //
4567 expectedStartingLBA = returnedStartingLBA + lbaCount;
4568 }
4569
4570 if (commandProcessedSlabs > 0) {
4571
4572 //
4573 // Calculate the starting LBA we'll use for the next command.
4574 //
4575 startingLBA += ((ULONGLONG)commandProcessedSlabs * (ULONGLONG)blocksPerSlab);
4576
4577 } else {
4578 //
4579 // This should never happen, but we should handle it gracefully anyway.
4580 //
4581 TracePrint((TRACE_LEVEL_ERROR,
4582 TRACE_FLAG_IOCTL,
4583 "ClasspDeviceGetLBAStatusWorker (%p): The slab allocation bitmap has zero length.\n",
4584 DeviceObject));
4585
4586 NT_ASSERT(commandProcessedSlabs != 0);
4587 doneProcessing = TRUE;
4589 }
4590 } else {
4591 TracePrint((TRACE_LEVEL_ERROR,
4592 TRACE_FLAG_IOCTL,
4593 "ClasspDeviceGetLBAStatusWorker (%p): Device returned no LBA Status Descriptors.\n",
4594 DeviceObject));
4595
4596 doneProcessing = TRUE;
4598 }
4599 } else {
4600 TracePrint((TRACE_LEVEL_ERROR,
4601 TRACE_FLAG_IOCTL,
4602 "ClasspDeviceGetLBAStatusWorker (%p): not enough bytes returned\n",
4603 DeviceObject));
4604
4605 doneProcessing = TRUE;
4607 }
4608 }
4609
4610 //
4611 // Loop until we encounter some error or we've processed all the requested slabs.
4612 //
4613 } while (NT_SUCCESS(status) &&
4614 !doneProcessing &&
4615 (totalProcessedSlabs < requestedSlabs));
4616
4617 //
4618 // At least one slab was returned by the device and processed, which we
4619 // consider success. It's up to the caller to detect truncation.
4620 // Update the output buffer sizes, offsets, etc. accordingly.
4621 //
4622 if (totalProcessedSlabs > 0) {
4623
4624 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
4627
4628 lbpStateV2->SlabSizeInBytes = bytesPerSlab;
4629 lbpStateV2->SlabOffsetDeltaInBytes = startingOffsetDelta;
4630 lbpStateV2->SlabAllocationBitMapBitCount = totalProcessedSlabs;
4631 lbpStateV2->SlabAllocationBitMapLength = ((totalProcessedSlabs - 1) / (ULONGLONG)bitMapGranularityInBits) + 1;
4633
4634 //
4635 // Note that there is already one element of the bitmap array allocated
4636 // in the DEVICE_DATA_SET_LB_PROVISIONING_STATE_V2 structure itself, which
4637 // is why we subtract 1 from SlabAllocationBitMapLength.
4638 //
4640 + ((lbpStateV2->SlabAllocationBitMapLength - 1) * sizeof(lbpStateV2->SlabAllocationBitMap[0]));
4641
4642 } else
4643 #endif
4644 {
4645
4646 lbpState->SlabSizeInBytes = bytesPerSlab;
4647 lbpState->SlabOffsetDeltaInBytes = (ULONG)startingOffsetDelta;
4648 lbpState->SlabAllocationBitMapBitCount = totalProcessedSlabs;
4649 lbpState->SlabAllocationBitMapLength = ((totalProcessedSlabs - 1) / bitMapGranularityInBits) + 1;
4651
4652 //
4653 // Note that there is already one element of the bitmap array allocated
4654 // in the DEVICE_DATA_SET_LB_PROVISIONING_STATE structure itself, which
4655 // is why we subtract 1 from SlabAllocationBitMapLength.
4656 //
4657 lbpState->Size = sizeof(DEVICE_DATA_SET_LB_PROVISIONING_STATE)
4658 + ((lbpState->SlabAllocationBitMapLength - 1) * sizeof(lbpState->SlabAllocationBitMap[0]));
4659 }
4660
4661 DsmOutput->OutputBlockLength = lbpState->Size; // Size is at the same offset in all versions of the structure.
4662 DsmOutput->OutputBlockOffset = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT);
4663 *DsmOutputLength = DsmOutput->Size + DsmOutput->OutputBlockLength;
4664
4666 }
4667
4668 TracePrint((TRACE_LEVEL_INFORMATION,
4669 TRACE_FLAG_IOCTL,
4670 "ClasspDeviceGetLBAStatusWorker (%p): Processed a total of %u slabs\n",
4672 totalProcessedSlabs));
4673Exit:
4674
4675 FREE_POOL(lbaStatusListHeader);
4676 return status;
4677}
#define MIN(x, y)
Definition: rdesktop.h:171
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
#define CLASS_TAG_LB_PROVISIONING
Definition: classpnp.h:89
_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:2742
NTSTATUS GetLBAStatus(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONGLONG StartingLBA, _Inout_ PLBA_STATUS_LIST_HEADER LBAStatusHeader, _In_ ULONG LBAStatusSize, _In_ BOOLEAN ConsolidateableBlocksOnly)
Definition: utils.c:3772
struct _DEVICE_DATA_SET_LB_PROVISIONING_STATE DEVICE_DATA_SET_LB_PROVISIONING_STATE
#define DeviceDsmAction_Allocation
Definition: ntddstor.h:280
struct _DEVICE_DATA_SET_LB_PROVISIONING_STATE_V2 * PDEVICE_DATA_SET_LB_PROVISIONING_STATE_V2
struct _DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT
struct _DEVICE_DATA_SET_LB_PROVISIONING_STATE_V2 DEVICE_DATA_SET_LB_PROVISIONING_STATE_V2
struct _LBA_STATUS_LIST_HEADER LBA_STATUS_LIST_HEADER
#define LBA_STATUS_MAPPED
Definition: scsi.h:2786
struct _LBA_STATUS_DESCRIPTOR LBA_STATUS_DESCRIPTOR
struct _LBA_STATUS_LIST_HEADER * PLBA_STATUS_LIST_HEADER
ULONG SlabAllocationBitMap[ANYSIZE_ARRAY]
Definition: ntddstor.h:948
ULONGLONG StartingLBA
Definition: scsi.h:2773
UCHAR ProvisioningStatus
Definition: scsi.h:2775
ULONG LogicalBlockCount
Definition: scsi.h:2774
LBA_STATUS_DESCRIPTOR Descriptors[0]
Definition: scsi.h:2783
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
_In_ ULONG ParameterLength
Definition: usbdlib.h:206
#define FIELD_SIZE(type, field)

Referenced by ClasspDeviceGetLBAStatus().

◆ ClasspDeviceGetLBProvisioningVPDPage()

NTSTATUS ClasspDeviceGetLBProvisioningVPDPage ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_opt_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 2350 of file utils.c.

2354{
2357 USHORT pageLength = 0;
2358
2360 UCHAR bufferLength = VPD_MAX_BUFFER_SIZE; // use biggest buffer possible
2361 ULONG allocationBufferLength = bufferLength; // Since the CDB size may differ from the actual buffer allocation
2362 PCDB cdb;
2363 ULONG dataTransferLength = 0;
2365
2366 //
2367 // if the informaiton has been attempted to retrieve, return the cached status.
2368 //
2369 if (fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus != -1) {
2370 // get cached NTSTATUS from previous call.
2371 return fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus;
2372 }
2373
2374 //
2375 // Initialize LBProvisioningData fields to 'unsupported' defaults.
2376 //
2377 fdoExtension->FunctionSupportInfo->LBProvisioningData.ProvisioningType = PROVISIONING_TYPE_UNKNOWN;
2378 fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPRZ = FALSE;
2379 fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPU = FALSE;
2380 fdoExtension->FunctionSupportInfo->LBProvisioningData.ANC_SUP = FALSE;
2381 fdoExtension->FunctionSupportInfo->LBProvisioningData.ThresholdExponent = 0;
2382
2383 //
2384 // Try to get the Thin Provisioning VPD page (0xB2), if it is supported.
2385 //
2386 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning == TRUE &&
2387 Srb != NULL)
2388 {
2389#if defined(_ARM_) || defined(_ARM64_)
2390 //
2391 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
2392 // based platforms. We are taking the conservative approach here.
2393 //
2394 //
2395 allocationBufferLength = ALIGN_UP_BY(allocationBufferLength,KeGetRecommendedSharedDataAlignment());
2396 dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, allocationBufferLength,'0CcS');
2397#else
2398 dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, bufferLength,'0CcS');
2399#endif
2400 if (dataBuffer == NULL) {
2401 // return without updating FdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus
2402 // the field will remain value as "-1", so that the command will be attempted next time this function is called.
2404 goto Exit;
2405 }
2406
2408
2409 RtlZeroMemory(dataBuffer, allocationBufferLength);
2410
2411 if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
2415 1,
2417 if (NT_SUCCESS(status)) {
2419 } else {
2420 //
2421 // Should not occur.
2422 //
2424 }
2425 } else {
2427 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
2430 }
2431
2432 if (NT_SUCCESS(status)) {
2433 // prepare the Srb
2434 SrbSetTimeOutValue(Srb, fdoExtension->TimeOutValue);
2437 SrbAssignSrbFlags(Srb, fdoExtension->SrbFlags);
2438
2439 SrbSetCdbLength(Srb, 6);
2440
2441 cdb = SrbGetCdb(Srb);
2442 cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY;
2443 cdb->CDB6INQUIRY3.EnableVitalProductData = 1; //EVPD bit
2444 cdb->CDB6INQUIRY3.PageCode = VPD_LOGICAL_BLOCK_PROVISIONING;
2445 cdb->CDB6INQUIRY3.AllocationLength = bufferLength; //AllocationLength field in CDB6INQUIRY3 is only one byte.
2446
2448 Srb,
2449 dataBuffer,
2450 allocationBufferLength,
2451 FALSE);
2452
2453 dataTransferLength = SrbGetDataTransferLength(Srb);
2454 }
2455
2456 //
2457 // Handle the case where we get back STATUS_DATA_OVERRUN b/c the input
2458 // buffer was larger than necessary.
2459 //
2460 if (status == STATUS_DATA_OVERRUN && dataTransferLength < bufferLength)
2461 {
2463 }
2464
2465 if (NT_SUCCESS(status)) {
2466 REVERSE_BYTES_SHORT(&pageLength, &(lbProvisioning->PageLength));
2467 }
2468
2469 if ( NT_SUCCESS(status) &&
2470 ((dataTransferLength < 0x08) ||
2472 (lbProvisioning->PageCode != VPD_LOGICAL_BLOCK_PROVISIONING)) ) {
2473 // the device should return at least 8 bytes of data for use.
2474 // 'PageCode' shall match and we need all the relevant data after the header.
2476 }
2477
2478 //
2479 // Fill in the FDO extension with either the data from the VPD page, or
2480 // use defaults if there was an error.
2481 //
2482 if (NT_SUCCESS(status))
2483 {
2484 fdoExtension->FunctionSupportInfo->LBProvisioningData.ProvisioningType = lbProvisioning->ProvisioningType;
2485 fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPRZ = lbProvisioning->LBPRZ;
2486 fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPU = lbProvisioning->LBPU;
2487 fdoExtension->FunctionSupportInfo->LBProvisioningData.ANC_SUP = lbProvisioning->ANC_SUP;
2488 fdoExtension->FunctionSupportInfo->LBProvisioningData.ThresholdExponent = lbProvisioning->ThresholdExponent;
2489
2490 TracePrint((TRACE_LEVEL_INFORMATION,
2491 TRACE_FLAG_PNP,
2492 "ClasspDeviceGetLBProvisioningVPDPage (%p): %s %s (rev %s) reported following parameters: \
2493 \n\t\t\tProvisioningType: %u \
2494 \n\t\t\tLBPRZ: %u \
2495 \n\t\t\tLBPU: %u \
2496 \n\t\t\tANC_SUP: %I64u \
2497 \n\t\t\tThresholdExponent: %u\n",
2499 (PCSZ)(((PUCHAR)fdoExtension->DeviceDescriptor) + fdoExtension->DeviceDescriptor->VendorIdOffset),
2500 (PCSZ)(((PUCHAR)fdoExtension->DeviceDescriptor) + fdoExtension->DeviceDescriptor->ProductIdOffset),
2501 (PCSZ)(((PUCHAR)fdoExtension->DeviceDescriptor) + fdoExtension->DeviceDescriptor->ProductRevisionOffset),
2502 lbProvisioning->ProvisioningType,
2503 lbProvisioning->LBPRZ,
2504 lbProvisioning->LBPU,
2505 lbProvisioning->ANC_SUP,
2506 lbProvisioning->ThresholdExponent));
2507 }
2508 } else {
2510 }
2511
2512 fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus = status;
2513
2514Exit:
2516
2517 return status;
2518}
@ Reserved2
Definition: bcd.h:202
#define VPD_LOGICAL_BLOCK_PROVISIONING
Definition: scsi.h:2418
struct _VPD_LOGICAL_BLOCK_PROVISIONING_PAGE * PVPD_LOGICAL_BLOCK_PROVISIONING_PAGE
#define PROVISIONING_TYPE_UNKNOWN
Definition: scsi.h:2588
PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: classpnp.h:876

Referenced by ClasspGetLBProvisioningInfo().

◆ ClasspDeviceLBProvisioningProperty()

NTSTATUS ClasspDeviceLBProvisioningProperty ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 2894 of file utils.c.

2899{
2901 NTSTATUS blockLimitsStatus;
2903 PSTORAGE_PROPERTY_QUERY query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
2905 ULONG length = 0;
2906 ULONG information = 0;
2907 CLASS_VPD_B0_DATA blockLimitsData;
2908 ULONG generationCount;
2909
2911
2913
2914 //
2915 // Check proper query type.
2916 //
2917 if (query->QueryType == PropertyExistsQuery) {
2919 goto Exit;
2920 } else if (query->QueryType != PropertyStandardQuery) {
2922 goto Exit;
2923 }
2924
2925 //
2926 // Request validation.
2927 // Note that InputBufferLength and IsFdo have been validated beforing entering this routine.
2928 //
2929
2933 goto Exit;
2934 }
2935
2936 lbpDescr = (PDEVICE_LB_PROVISIONING_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
2937
2938 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
2939
2940 RtlZeroMemory(lbpDescr, length);
2941
2943
2944 if (length >= sizeof(STORAGE_DESCRIPTOR_HEADER)) {
2945
2947 lbpDescr->Version = sizeof(DEVICE_LB_PROVISIONING_DESCRIPTOR);
2948 lbpDescr->Size = sizeof(DEVICE_LB_PROVISIONING_DESCRIPTOR);
2950 goto Exit;
2951 }
2952
2954 goto Exit;
2955 }
2956
2957 //
2958 // Set the structure version/size based upon the size of the given output
2959 // buffer. We may be working with an older component that was built with
2960 // the V1 structure definition.
2961 //
2966 } else {
2967 lbpDescr->Version = sizeof(DEVICE_LB_PROVISIONING_DESCRIPTOR);
2968 lbpDescr->Size = sizeof(DEVICE_LB_PROVISIONING_DESCRIPTOR);
2970 }
2971
2972 //
2973 // Take a snapshot of the block limits data since it can change.
2974 // If we failed to get the block limits data, we'll just set the Optimal
2975 // Unmap Granularity (and alignment) will default to 0. We don't want to
2976 // fail the request outright since there is some non-block limits data that
2977 // we can return.
2978 //
2979 blockLimitsStatus = ClasspBlockLimitsDataSnapshot(fdoExtension,
2980 TRUE,
2981 &blockLimitsData,
2982 &generationCount);
2983
2984 //
2985 // Fill in the output buffer. All data is copied from the FDO extension where we
2986 // cached Logical Block Provisioning info when the device was first initialized.
2987 //
2988
2989 lbpDescr->ThinProvisioningEnabled = ClasspIsThinProvisioned(fdoExtension->FunctionSupportInfo);
2990
2991 //
2992 // Make sure we have a non-zero value for the number of bytes per block.
2993 //
2994 if (fdoExtension->DiskGeometry.BytesPerSector == 0)
2995 {
2997 if(!NT_SUCCESS(status) || fdoExtension->DiskGeometry.BytesPerSector == 0)
2998 {
3000 information = 0;
3001 goto Exit;
3002 }
3003 }
3004
3005 lbpDescr->ThinProvisioningReadZeros = fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPRZ;
3006 lbpDescr->AnchorSupported = fdoExtension->FunctionSupportInfo->LBProvisioningData.ANC_SUP;
3007
3008 if (NT_SUCCESS(blockLimitsStatus)) {
3009 lbpDescr->UnmapGranularityAlignmentValid = blockLimitsData.UGAVALID;
3010
3011 //
3012 // Granularity and Alignment are given to us in units of blocks,
3013 // but we convert and return them in bytes as it is more convenient
3014 // to the caller.
3015 //
3016 lbpDescr->OptimalUnmapGranularity = (ULONGLONG)blockLimitsData.OptimalUnmapGranularity * fdoExtension->DiskGeometry.BytesPerSector;
3018
3019#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3020 //
3021 // If the output buffer is large enough (i.e. not a V1 structure) copy
3022 // over the max UNMAP LBA count and max UNMAP block descriptor count.
3023 //
3025 lbpDescr->MaxUnmapLbaCount = blockLimitsData.MaxUnmapLbaCount;
3026 lbpDescr->MaxUnmapBlockDescriptorCount = blockLimitsData.MaxUnmapBlockDescrCount;
3027 }
3028#endif
3029 }
3030
3031Exit:
3032
3033 //
3034 // Set the size and status in IRP
3035 //
3036 Irp->IoStatus.Information = information;
3037 Irp->IoStatus.Status = status;
3038
3041
3042 return status;
3043}
FORCEINLINE BOOLEAN ClasspIsThinProvisioned(_In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo)
Definition: classp.h:1317
struct _DEVICE_LB_PROVISIONING_DESCRIPTOR * PDEVICE_LB_PROVISIONING_DESCRIPTOR
struct _DEVICE_LB_PROVISIONING_DESCRIPTOR DEVICE_LB_PROVISIONING_DESCRIPTOR
#define DEVICE_LB_PROVISIONING_DESCRIPTOR_V1_SIZE
Definition: ntddstor.h:661
BOOLEAN UGAVALID
Definition: classpnp.h:754
ULONG UnmapGranularityAlignment
Definition: classpnp.h:753
ULONG MaxUnmapBlockDescrCount
Definition: classpnp.h:751
ULONG OptimalUnmapGranularity
Definition: classpnp.h:752
ULONG MaxUnmapLbaCount
Definition: classpnp.h:750

Referenced by ClassDeviceControl().

◆ ClasspDeviceMediaTypeProperty()

NTSTATUS ClasspDeviceMediaTypeProperty ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 1917 of file utils.c.

1941{
1944 PSTORAGE_PROPERTY_QUERY query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
1946 PIO_STACK_LOCATION irpStack;
1947 ULONG length = 0;
1948 ULONG information = 0;
1949
1951
1952 TracePrint((TRACE_LEVEL_VERBOSE,
1953 TRACE_FLAG_IOCTL,
1954 "ClasspDeviceMediaTypeProperty (%p): Entering function.\n",
1955 DeviceObject));
1956
1957 //
1958 // Check proper query type.
1959 //
1960 if (query->QueryType == PropertyExistsQuery) {
1961
1962 //
1963 // In order to maintain consistency with the how the rest of the properties
1964 // are handled, always return success for PropertyExistsQuery.
1965 //
1967 goto __ClasspDeviceMediaTypeProperty_Exit;
1968
1969 } else if (query->QueryType != PropertyStandardQuery) {
1970
1971 TracePrint((TRACE_LEVEL_ERROR,
1972 TRACE_FLAG_IOCTL,
1973 "ClasspDeviceMediaTypeProperty (%p): Unsupported query type %x for media type property.\n",
1975 query->QueryType));
1976
1978 goto __ClasspDeviceMediaTypeProperty_Exit;
1979 }
1980
1981 //
1982 // Validate the request.
1983 // InputBufferLength and IsFdo have already been validated.
1984 //
1985
1987
1989
1990 TracePrint((TRACE_LEVEL_ERROR,
1991 TRACE_FLAG_IOCTL,
1992 "ClasspDeviceMediaTypeProperty (%p): Query property for media type at incorrect IRQL.\n",
1993 DeviceObject));
1994
1996 goto __ClasspDeviceMediaTypeProperty_Exit;
1997 }
1998
1999 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
2000
2001 if (length >= sizeof(STORAGE_DESCRIPTOR_HEADER)) {
2002
2004 pDesc->Version = sizeof(STORAGE_MEDIUM_PRODUCT_TYPE_DESCRIPTOR);
2005 pDesc->Size = sizeof(STORAGE_MEDIUM_PRODUCT_TYPE_DESCRIPTOR);
2006 } else {
2007
2009 goto __ClasspDeviceMediaTypeProperty_Exit;
2010 }
2011
2013
2015 goto __ClasspDeviceMediaTypeProperty_Exit;
2016 }
2017
2018 //
2019 // Only query BlockDeviceCharacteristics VPD page if device support has been confirmed.
2020 //
2021 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceCharacteristics == TRUE) {
2023 } else {
2024 //
2025 // Otherwise device was previously found lacking support for this VPD page. Fail the request.
2026 //
2028 goto __ClasspDeviceMediaTypeProperty_Exit;
2029 }
2030
2031 if (!NT_SUCCESS(status)) {
2032
2033 status = fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.CommandStatus;
2034 information = 0;
2035
2036 TracePrint((TRACE_LEVEL_ERROR,
2037 TRACE_FLAG_IOCTL,
2038 "ClasspDeviceGetBlockDeviceCharacteristicsVPDPage (%p): VPD retrieval fails with %x.\n",
2040 status));
2041
2042 goto __ClasspDeviceMediaTypeProperty_Exit;
2043 }
2044
2045 //
2046 // Fill in the output buffer. All data is copied from the FDO extension, cached
2047 // from device response to earlier VPD_BLOCK_DEVICE_CHARACTERISTICS query.
2048 //
2049 pDesc->MediumProductType = fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.MediumProductType;
2051
2052__ClasspDeviceMediaTypeProperty_Exit:
2053
2054 //
2055 // Set the size and status in IRP
2056 //
2057 Irp->IoStatus.Information = information;
2058 Irp->IoStatus.Status = status;
2059
2062
2063 TracePrint((TRACE_LEVEL_VERBOSE,
2064 TRACE_FLAG_IOCTL,
2065 "ClasspDeviceMediaTypeProperty (%p): Exiting function with status %x.\n",
2067 status));
2068
2069 return status;
2070}
NTSTATUS ClasspDeviceGetBlockDeviceCharacteristicsVPDPage(_In_ PFUNCTIONAL_DEVICE_EXTENSION fdoExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:2072
STORAGE_MEDIUM_PRODUCT_TYPE_DESCRIPTOR
Definition: ntddstor.h:615
* PSTORAGE_MEDIUM_PRODUCT_TYPE_DESCRIPTOR
Definition: ntddstor.h:615

Referenced by ClassDeviceControl().

◆ ClasspDeviceSeekPenaltyProperty()

NTSTATUS ClasspDeviceSeekPenaltyProperty ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 2172 of file utils.c.

2181{
2183
2184 PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
2186 PSTORAGE_PROPERTY_QUERY query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
2188 ULONG length = 0;
2189 ULONG information = 0;
2190 BOOLEAN incursSeekPenalty = TRUE;
2192
2193 if ( (DeviceObject->DeviceType != FILE_DEVICE_DISK) ||
2194 (TEST_FLAG(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE)) ||
2195 (fdoExtension->FunctionSupportInfo->LowerLayerSupport.SeekPenaltyProperty == Supported) ) {
2196 // if it's not disk, forward the request to lower layer,
2197 // if the IOCTL is supported by lower stack, forward it down.
2199
2201 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
2202 return status;
2203 }
2204
2205 //
2206 // Check proper query type.
2207 //
2208
2209 if (query->QueryType == PropertyExistsQuery) {
2211 goto Exit;
2212 } else if (query->QueryType != PropertyStandardQuery) {
2214 goto Exit;
2215 }
2216
2217 //
2218 // Request validation.
2219 // Note that InputBufferLength and IsFdo have been validated beforing entering this routine.
2220 //
2221
2225 goto Exit;
2226 }
2227
2228 // do not touch this buffer because it can still be used as input buffer for lower layer in 'SupportUnknown' case.
2229 seekPenalty = (PDEVICE_SEEK_PENALTY_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
2230
2231 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
2232
2234
2235 if (length >= sizeof(STORAGE_DESCRIPTOR_HEADER)) {
2236
2238 seekPenalty->Version = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR);
2239 seekPenalty->Size = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR);
2241 goto Exit;
2242 }
2243
2245 goto Exit;
2246 }
2247
2248 //
2249 // note that 'Supported' case has been handled at the beginning of this function.
2250 //
2251 switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.SeekPenaltyProperty) {
2252 case SupportUnknown: {
2253 // send down request and wait for the request to complete.
2254 status = ClassForwardIrpSynchronous(commonExtension, Irp);
2255
2257 // case 1: the request is not supported by lower layer, sends down command
2258 // some port drivers (or filter drivers) return STATUS_INVALID_DEVICE_REQUEST if a request is not supported.
2259
2260 // send INQUIRY command if the VPD page is supported.
2261 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceCharacteristics == TRUE) {
2263 } else {
2264 // the INQUIRY - VPD page command to discover the info is not supported, fail the request.
2266 }
2267
2268 if (NT_SUCCESS(status)) {
2269 status = IncursSeekPenalty(fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.MediumRotationRate, &incursSeekPenalty);
2270 }
2271
2272 fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.CommandStatus = status;
2273
2274 // data is ready in fdoExtension
2275 // set the support status after the SCSI command is executed to avoid racing condition between multiple same type of requests.
2276 fdoExtension->FunctionSupportInfo->LowerLayerSupport.SeekPenaltyProperty = NotSupported;
2277
2278 // fill output buffer
2279 if (NT_SUCCESS(status)) {
2280 RtlZeroMemory(seekPenalty, length);
2281 seekPenalty->Version = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR);
2282 seekPenalty->Size = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR);
2283 seekPenalty->IncursSeekPenalty = incursSeekPenalty;
2285
2286
2287 } else {
2288 information = 0;
2289 }
2290
2291 } else {
2292 // case 2: the request is supported and it completes successfully
2293 // case 3: the request is supported by lower stack but other failure status is returned.
2294 // from now on, the same request will be send down to lower stack directly.
2295 fdoExtension->FunctionSupportInfo->LowerLayerSupport.SeekPenaltyProperty = Supported;
2296 information = (ULONG)Irp->IoStatus.Information;
2297
2298 }
2299
2300
2301 goto Exit;
2302
2303 break;
2304 }
2305
2306 case NotSupported: {
2307 status = fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.CommandStatus;
2308
2309 if (NT_SUCCESS(status)) {
2310 status = IncursSeekPenalty(fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.MediumRotationRate, &incursSeekPenalty);
2311 }
2312
2313 if (NT_SUCCESS(status)) {
2314 RtlZeroMemory(seekPenalty, length);
2315 seekPenalty->Version = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR);
2316 seekPenalty->Size = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR);
2317 seekPenalty->IncursSeekPenalty = incursSeekPenalty;
2319
2320 } else {
2321 information = 0;
2322 }
2323
2324 goto Exit;
2325
2326 break;
2327 }
2328
2329 case Supported: {
2330 NT_ASSERT(FALSE); // this case is handled at the begining of the function.
2331 break;
2332 }
2333
2334 } // end of switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.SeekPenaltyProperty)
2335
2336Exit:
2337
2338 //
2339 // Set the size and status in IRP
2340 //
2341 Irp->IoStatus.Information = information;;
2342 Irp->IoStatus.Status = status;
2343
2346
2347 return status;
2348}
static NTSTATUS IncursSeekPenalty(_In_ USHORT MediumRotationRate, _In_ PBOOLEAN IncursSeekPenalty)
Definition: utils.c:1888
struct _DEVICE_SEEK_PENALTY_DESCRIPTOR DEVICE_SEEK_PENALTY_DESCRIPTOR
struct _DEVICE_SEEK_PENALTY_DESCRIPTOR * PDEVICE_SEEK_PENALTY_DESCRIPTOR

Referenced by ClassDeviceControl().

◆ ClasspDeviceTrimProcess()

NTSTATUS ClasspDeviceTrimProcess ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_In_ PGUID  ActivityId,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 3476 of file utils.c.

3487{
3489
3490 PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
3492
3493 PDEVICE_MANAGE_DATA_SET_ATTRIBUTES dsmAttributes = Irp->AssociatedIrp.SystemBuffer;
3494
3495 PDEVICE_DATA_SET_RANGE dataSetRanges;
3496 ULONG dataSetRangesCount;
3497 DEVICE_DATA_SET_RANGE entireDataSetRange = {0};
3498 ULONG i;
3499 ULONGLONG granularityAlignmentInBytes;
3500 ULONG granularityInBlocks;
3501 ULONG srbFlags = 0;
3502
3503 CLASS_VPD_B0_DATA blockLimitsData;
3504 ULONG generationCount;
3505
3506
3507 if ( (DeviceObject->DeviceType != FILE_DEVICE_DISK) ||
3508 (TEST_FLAG(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE)) ||
3509 (fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProcess == Supported) ) {
3510 // if it's not disk, forward the request to lower layer,
3511 // if the IOCTL is supported by lower stack, forward it down.
3513
3514 TracePrint((TRACE_LEVEL_INFORMATION,
3515 TRACE_FLAG_GENERAL,
3516 "ClasspDeviceTrimProcess (%p): Lower layer supports Trim DSM IOCTL, forwarding IOCTL.\n",
3517 DeviceObject));
3518
3520 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
3521 return status;
3522 }
3523
3524 //
3525 // Request validation.
3526 // Note that InputBufferLength and IsFdo have been validated beforing entering this routine.
3527 //
3528
3532 goto Exit;
3533 }
3534
3535
3536 //
3537 // If the caller has not set the "entire dataset range" flag then at least
3538 // one dataset range should be specified. However, if the caller *has* set
3539 // the flag, then there should not be any dataset ranges specified.
3540 //
3541 if ((!TEST_FLAG(dsmAttributes->Flags, DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE) &&
3542 (dsmAttributes->DataSetRangesOffset == 0 ||
3543 dsmAttributes->DataSetRangesLength == 0)) ||
3545 (dsmAttributes->DataSetRangesOffset != 0 ||
3546 dsmAttributes->DataSetRangesLength != 0))) {
3547
3549 goto Exit;
3550 }
3551
3552 //
3553 // note that 'Supported' case has been handled at the beginning of this function.
3554 //
3555 switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProcess) {
3556 case SupportUnknown: {
3557 // send down request and wait for the request to complete.
3558 status = ClassForwardIrpSynchronous(commonExtension, Irp);
3559
3560 TracePrint((TRACE_LEVEL_INFORMATION,
3561 TRACE_FLAG_GENERAL,
3562 "ClasspDeviceTrimProcess (%p): Trim DSM IOCTL support unknown. Forwarded IOCTL and received NTSTATUS %!STATUS!.\n",
3564 status));
3565
3567 // case 1: the request is not supported by lower layer, sends down command
3568 // some port drivers (or filter drivers) return STATUS_INVALID_DEVICE_REQUEST if a request is not supported.
3569 // In this case we'll just fall through to the NotSupported case so that we can handle it ourselves.
3570
3571 //
3572 // VPD pages 0xB2 and 0xB0 should have been cached in Start Device phase - ClassPnpStartDevice.
3573 // 0xB2 page: fdoExtension->FunctionSupportInfo->LBProvisioningData;
3574 // 0xB0 page: fdoExtension->FunctionSupportInfo->BlockLimitsData
3575 //
3576 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning == TRUE) {
3577 NT_ASSERT(fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus != -1);
3578 }
3579
3580 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockLimits == TRUE) {
3581 NT_ASSERT(fdoExtension->FunctionSupportInfo->BlockLimitsData.CommandStatus != -1);
3582 }
3583
3584 } else {
3585
3586 // case 2: the request is supported and it completes successfully
3587 // case 3: the request is supported by lower stack but other failure status is returned.
3588 // from now on, the same request will be send down to lower stack directly.
3589 fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProcess = Supported;
3590 goto Exit;
3591 }
3592 }
3593
3594 case NotSupported: {
3595
3596 // send UNMAP command if it is supported. don't need to check 'status' value.
3597 if (ClasspSupportsUnmap(fdoExtension->FunctionSupportInfo))
3598 {
3599 //
3600 // Make sure that we know the bytes per sector (logical block) as it's
3601 // necessary for calculations involving granularity and alignment.
3602 //
3603 if (fdoExtension->DiskGeometry.BytesPerSector == 0) {
3604 status = ClassReadDriveCapacity(fdoExtension->DeviceObject);
3605 if(!NT_SUCCESS(status) || fdoExtension->DiskGeometry.BytesPerSector == 0) {
3607 goto Exit;
3608 }
3609 }
3610
3611 //
3612 // Take a snapshot of the block limits data since it can change.
3613 // It's acceptable if the block limits data is outdated since
3614 // there isn't a hard requirement on the unmap granularity.
3615 //
3616 ClasspBlockLimitsDataSnapshot(fdoExtension,
3617 FALSE,
3618 &blockLimitsData,
3619 &generationCount);
3620
3621 //
3622 // Check to see if the Optimal Unmap Granularity and Unmap Granularity
3623 // Alignment have been specified. If not, default the granularity to
3624 // one block and the alignment to zero.
3625 //
3626 if (blockLimitsData.OptimalUnmapGranularity != 0)
3627 {
3628 granularityInBlocks = blockLimitsData.OptimalUnmapGranularity;
3629 }
3630 else
3631 {
3632 granularityInBlocks = 1;
3633
3634 TracePrint((TRACE_LEVEL_INFORMATION,
3635 TRACE_FLAG_GENERAL,
3636 "ClasspDeviceTrimProcess (%p): Optimal Unmap Granularity not provided, defaulted to 1.\n",
3637 DeviceObject));
3638 }
3639
3640 if (blockLimitsData.UGAVALID == TRUE)
3641 {
3642 granularityAlignmentInBytes = (ULONGLONG)blockLimitsData.UnmapGranularityAlignment * fdoExtension->DiskGeometry.BytesPerSector;
3643 }
3644 else
3645 {
3646 granularityAlignmentInBytes = 0;
3647
3648 TracePrint((TRACE_LEVEL_INFORMATION,
3649 TRACE_FLAG_GENERAL,
3650 "ClasspDeviceTrimProcess (%p): Unmap Granularity Alignment not provided, defaulted to 0.\n",
3651 DeviceObject));
3652 }
3653
3655 {
3656 //
3657 // The caller wants to UNMAP the entire disk so we need to build a single
3658 // dataset range that represents the entire disk.
3659 //
3660 entireDataSetRange.StartingOffset = granularityAlignmentInBytes;
3661 entireDataSetRange.LengthInBytes = (ULONGLONG)fdoExtension->CommonExtension.PartitionLength.QuadPart - (ULONGLONG)entireDataSetRange.StartingOffset;
3662
3663 dataSetRanges = &entireDataSetRange;
3664 dataSetRangesCount = 1;
3665 }
3666 else
3667 {
3668
3669 dataSetRanges = (PDEVICE_DATA_SET_RANGE)((PUCHAR)dsmAttributes + dsmAttributes->DataSetRangesOffset);
3670 dataSetRangesCount = dsmAttributes->DataSetRangesLength / sizeof(DEVICE_DATA_SET_RANGE);
3671
3672 //
3673 // Validate the data ranges. Make sure the range is block-aligned,
3674 // falls in a valid portion of the disk, and is non-zero.
3675 //
3676 for (i = 0; i < dataSetRangesCount; i++)
3677 {
3678 if ((dataSetRanges[i].StartingOffset % fdoExtension->DiskGeometry.BytesPerSector != 0) ||
3679 (dataSetRanges[i].LengthInBytes % fdoExtension->DiskGeometry.BytesPerSector != 0) ||
3680 (dataSetRanges[i].StartingOffset < (LONGLONG)granularityAlignmentInBytes) ||
3681 (dataSetRanges[i].LengthInBytes == 0) ||
3682 ((ULONGLONG)dataSetRanges[i].StartingOffset + dataSetRanges[i].LengthInBytes > (ULONGLONG)fdoExtension->CommonExtension.PartitionLength.QuadPart))
3683 {
3684 TracePrint((TRACE_LEVEL_ERROR,
3685 TRACE_FLAG_IOCTL,
3686 "ClasspDeviceTrimProcess (%p): Invalid dataset range. StartingOffset = %I64x, LengthInBytes = %I64x\n",
3688 dataSetRanges[i].StartingOffset,
3689 dataSetRanges[i].LengthInBytes));
3690
3692 goto Exit;
3693 }
3694 }
3695 }
3696
3697
3699 {
3700 {
3701 //
3702 // For security reasons, file-level TRIM must be forwarded on only
3703 // if reading the unmapped blocks' contents will return back zeros.
3704 // This is because if LBPRZ bit is not set, it indicates that a read
3705 // of unmapped blocks may return "any" data thus potentially leaking
3706 // in data (into the read buffer) from other blocks.
3707 //
3708 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning &&
3709 !fdoExtension->FunctionSupportInfo->LBProvisioningData.LBPRZ) {
3710
3711 TracePrint((TRACE_LEVEL_ERROR,
3712 TRACE_FLAG_IOCTL,
3713 "ClasspDeviceTrimProcess (%p): Device does not support file level TRIM.\n",
3714 DeviceObject));
3715
3717 goto Exit;
3718 }
3719 }
3720 }
3721
3722 // process DSM IOCTL
3723 status = DeviceProcessDsmTrimRequest(fdoExtension,
3724 dataSetRanges,
3725 dataSetRangesCount,
3726 granularityInBlocks,
3727 srbFlags,
3728 Irp,
3729 ActivityId,
3730 Srb);
3731 } else {
3732 // DSM IOCTL should be completed as not supported
3733
3734 TracePrint((TRACE_LEVEL_ERROR,
3735 TRACE_FLAG_IOCTL,
3736 "ClasspDeviceTrimProcess (%p): Device does not support UNMAP.\n",
3737 DeviceObject));
3738
3740 }
3741
3742 // set the support status after the SCSI command is executed to avoid racing condition between multiple same type of requests.
3743 fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProcess = NotSupported;
3744
3745 break;
3746 }
3747
3748 case Supported: {
3749 NT_ASSERT(FALSE); // this case is handled at the begining of the function.
3750 break;
3751 }
3752
3753 } // end of switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProcess)
3754
3755Exit:
3756
3757 //
3758 // Set the size and status in IRP
3759 //
3760 Irp->IoStatus.Information = 0;
3761 Irp->IoStatus.Status = status;
3762
3763
3764
3767
3768 return status;
3769}
FORCEINLINE BOOLEAN ClasspSupportsUnmap(_In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo)
Definition: classp.h:1308
NTSTATUS DeviceProcessDsmTrimRequest(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PDEVICE_DATA_SET_RANGE DataSetRanges, _In_ ULONG DataSetRangesCount, _In_ ULONG UnmapGranularity, _In_ ULONG SrbFlags, _In_ PIRP Irp, _In_ PGUID ActivityId, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:3164
#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED
Definition: ntddstor.h:764
struct _DEVICE_DATA_SET_RANGE DEVICE_DATA_SET_RANGE
#define STATUS_TRIM_READ_ZERO_NOT_SUPPORTED
Definition: ntstatus.h:1000
_In_ PCEVENT_DESCRIPTOR _In_opt_ LPCGUID ActivityId
Definition: wmifuncs.h:120

Referenced by ClassDeviceControl().

◆ ClasspDeviceTrimProperty()

NTSTATUS ClasspDeviceTrimProperty ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 2730 of file utils.c.

2739{
2741
2742 PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
2744 PSTORAGE_PROPERTY_QUERY query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
2746 ULONG length = 0;
2747 ULONG information = 0;
2748
2749 PDEVICE_TRIM_DESCRIPTOR trimDescr;
2750
2752
2753 if ( (DeviceObject->DeviceType != FILE_DEVICE_DISK) ||
2754 (TEST_FLAG(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE)) ||
2755 (fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProperty == Supported) ) {
2756 // if it's not disk, forward the request to lower layer,
2757 // if the IOCTL is supported by lower stack, forward it down.
2759
2761 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
2762 return status;
2763 }
2764
2765 //
2766 // Check proper query type.
2767 //
2768
2769 if (query->QueryType == PropertyExistsQuery) {
2771 goto Exit;
2772 } else if (query->QueryType != PropertyStandardQuery) {
2774 goto Exit;
2775 }
2776
2777 //
2778 // Request validation.
2779 // Note that InputBufferLength and IsFdo have been validated beforing entering this routine.
2780 //
2781
2785 goto Exit;
2786 }
2787
2788 // do not touch this buffer because it can still be used as input buffer for lower layer in 'SupportUnknown' case.
2789 trimDescr = (PDEVICE_TRIM_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
2790
2791 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
2792
2793 if (length < sizeof(DEVICE_TRIM_DESCRIPTOR)) {
2794
2795 if (length >= sizeof(STORAGE_DESCRIPTOR_HEADER)) {
2796
2798 trimDescr->Version = sizeof(DEVICE_TRIM_DESCRIPTOR);
2799 trimDescr->Size = sizeof(DEVICE_TRIM_DESCRIPTOR);
2801 goto Exit;
2802 }
2803
2805 goto Exit;
2806 }
2807
2808 //
2809 // note that 'Supported' case has been handled at the beginning of this function.
2810 //
2811 switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProperty) {
2812 case SupportUnknown: {
2813 // send down request and wait for the request to complete.
2814 status = ClassForwardIrpSynchronous(commonExtension, Irp);
2815
2816 if ( (status == STATUS_NOT_SUPPORTED) ||
2820 // case 1: the request is not supported by lower layer, sends down command
2821 // some port drivers (or filter drivers) return STATUS_INVALID_DEVICE_REQUEST if a request is not supported.
2822 status = fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus;
2823 NT_ASSERT(status != -1);
2824
2825 // data is ready in fdoExtension
2826 // set the support status after the SCSI command is executed to avoid racing condition between multiple same type of requests.
2827 fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProperty = NotSupported;
2828
2829 if (NT_SUCCESS(status)) {
2830 // fill output buffer
2831 RtlZeroMemory(trimDescr, length);
2832 trimDescr->Version = sizeof(DEVICE_TRIM_DESCRIPTOR);
2833 trimDescr->Size = sizeof(DEVICE_TRIM_DESCRIPTOR);
2834 trimDescr->TrimEnabled = ClasspSupportsUnmap(fdoExtension->FunctionSupportInfo);
2835
2836 // set returned data length
2838 } else {
2839 // there was error retrieving TrimProperty. Surface the error up from 'status' variable.
2840 information = 0;
2841 }
2842 goto Exit;
2843 } else {
2844 // case 2: the request is supported and it completes successfully
2845 // case 3: the request is supported by lower stack but other failure status is returned.
2846 // from now on, the same request will be send down to lower stack directly.
2847 fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProperty = Supported;
2848 information = (ULONG)Irp->IoStatus.Information;
2849 goto Exit;
2850 }
2851 break;
2852 }
2853
2854 case NotSupported: {
2855 status = fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus;
2856 NT_ASSERT(status != -1);
2857
2858 if (NT_SUCCESS(status)) {
2859 RtlZeroMemory(trimDescr, length);
2860 trimDescr->Version = sizeof(DEVICE_TRIM_DESCRIPTOR);
2861 trimDescr->Size = sizeof(DEVICE_TRIM_DESCRIPTOR);
2862 trimDescr->TrimEnabled = ClasspSupportsUnmap(fdoExtension->FunctionSupportInfo);
2863
2865 } else {
2866 information = 0;
2867 }
2868 goto Exit;
2869
2870 break;
2871 }
2872
2873 case Supported: {
2874 NT_ASSERT(FALSE); // this case is handled at the begining of the function.
2875 break;
2876 }
2877
2878 } // end of switch (fdoExtension->FunctionSupportInfo->LowerLayerSupport.TrimProperty)
2879
2880Exit:
2881
2882 //
2883 // Set the size and status in IRP
2884 //
2885 Irp->IoStatus.Information = information;
2886 Irp->IoStatus.Status = status;
2887
2890
2891 return status;
2892}
struct _DEVICE_TRIM_DESCRIPTOR DEVICE_TRIM_DESCRIPTOR
struct _DEVICE_TRIM_DESCRIPTOR * PDEVICE_TRIM_DESCRIPTOR
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475

Referenced by ClassDeviceControl().

◆ ClasspDisablePowerNotification()

VOID ClasspDisablePowerNotification ( PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

◆ ClasspDisableTimer()

VOID ClasspDisableTimer ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 3956 of file autorun.c.

3959{
3960 PCLASS_PRIVATE_FDO_DATA fdoData = NULL;
3961
3962 if (FdoExtension->CommonExtension.IsFdo) {
3963 fdoData = FdoExtension->PrivateFdoData;
3964 }
3965
3966 if (fdoData && fdoData->TimerInitialized == TRUE) {
3967
3968 //
3969 // we are only going to stop the actual timer in remove device routine
3970 // or when done transitioning to D3 (timer will be started again when
3971 // done transitioning to D0).
3972 //
3973 // it is the responsibility of the code within the timer routine to
3974 // check if the device is removed and not processing io for the final
3975 // call.
3976 // this keeps the code clean and prevents lots of bugs.
3977 //
3978#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3979 NT_ASSERT(fdoData->TickTimer != NULL);
3980 ExCancelTimer(fdoData->TickTimer, NULL);
3981#else
3982 KeCancelTimer(&fdoData->TickTimer);
3983#endif
3984 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspDisableTimer: Periodic tick timer disabled "
3985 "for device %p\n", FdoExtension->DeviceObject));
3986 fdoData->TickTimerEnabled = FALSE;
3987
3988 } else {
3989
3990 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, "ClasspDisableTimer: Timer never initialized\n"));
3991
3992 }
3993
3994 return;
3995} // end ClasspDisableTimer()
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
NTKERNELAPI BOOLEAN NTAPI ExCancelTimer(_Inout_ PEX_TIMER Timer, _In_opt_ PEXT_CANCEL_PARAMETERS Parameters)

Referenced by ClassDispatchPnp(), and ClasspPowerHandler().

◆ ClasspDuidQueryProperty()

NTSTATUS ClasspDuidQueryProperty ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 997 of file utils.c.

1001{
1002 PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;
1003 PSTORAGE_DESCRIPTOR_HEADER descHeader;
1005
1007
1008 ULONG outLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
1009
1010 BOOLEAN includeOptionalIds;
1011 BOOLEAN overflow = FALSE;
1012 BOOLEAN infoFound = FALSE;
1013 BOOLEAN useStatus = TRUE; // Use the status directly instead of relying on overflow and infoFound flags.
1014
1015 //
1016 // Must run at less then dispatch.
1017 //
1018
1020
1023 goto FnExit;
1024 }
1025
1026 //
1027 // Check proper query type.
1028 //
1029
1030 if (query->QueryType == PropertyExistsQuery) {
1031 Irp->IoStatus.Information = 0;
1033 goto FnExit;
1034 }
1035
1036 if (query->QueryType != PropertyStandardQuery) {
1038 goto FnExit;
1039 }
1040
1041 //
1042 // Check AdditionalParameters validity.
1043 //
1044
1045 if (query->AdditionalParameters[0] == DUID_INCLUDE_SOFTWARE_IDS) {
1046 includeOptionalIds = TRUE;
1047 } else if (query->AdditionalParameters[0] == DUID_HARDWARE_IDS_ONLY) {
1048 includeOptionalIds = FALSE;
1049 } else {
1051 goto FnExit;
1052 }
1053
1054 //
1055 // Verify output parameters.
1056 //
1057
1058 if (outLength < sizeof(STORAGE_DESCRIPTOR_HEADER)) {
1059
1061 goto FnExit;
1062 }
1063
1064 //
1065 // From this point forward the status depends on the overflow
1066 // and infoFound flags.
1067 //
1068
1069 useStatus = FALSE;
1070
1071 descHeader = Irp->AssociatedIrp.SystemBuffer;
1072 RtlZeroMemory(descHeader, outLength);
1073
1074 descHeader->Version = DUID_VERSION_1;
1075 descHeader->Size = sizeof(STORAGE_DEVICE_UNIQUE_IDENTIFIER);
1076
1077 //
1078 // Try to build device unique id from StorageDeviceIdProperty.
1079 //
1080
1082 Irp);
1083
1085 overflow = TRUE;
1086 }
1087
1088 if (NT_SUCCESS(status)) {
1089 infoFound = TRUE;
1090 }
1091
1092 //
1093 // Try to build device unique id from StorageDeviceProperty.
1094 //
1095
1097 Irp);
1098
1100 overflow = TRUE;
1101 }
1102
1103 if (NT_SUCCESS(status)) {
1104 infoFound = TRUE;
1105 }
1106
1107 //
1108 // The following portion is optional and only included if the
1109 // caller requested software IDs.
1110 //
1111
1112 if (!includeOptionalIds) {
1113 goto FnExit;
1114 }
1115
1116 //
1117 // Try to build device unique id from drive layout signature (disk
1118 // devices only).
1119 //
1120
1122 Irp);
1123
1125 overflow = TRUE;
1126 }
1127
1128 if (NT_SUCCESS(status)) {
1129 infoFound = TRUE;
1130 }
1131
1132FnExit:
1133
1134 if (!useStatus) {
1135
1136 //
1137 // Return overflow, success, or a generic error.
1138 //
1139
1140 if (overflow) {
1141
1142 //
1143 // If output buffer is STORAGE_DESCRIPTOR_HEADER, then return
1144 // success to the user. Otherwise, send an error so the user
1145 // knows a larger buffer is required.
1146 //
1147
1148 if (outLength == sizeof(STORAGE_DESCRIPTOR_HEADER)) {
1150 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
1151 } else {
1153 }
1154
1155 } else if (infoFound) {
1157
1158 //
1159 // Exercise the compare routine. This should always succeed.
1160 //
1161
1162 NT_ASSERT(DuidExactMatch == CompareStorageDuids(Irp->AssociatedIrp.SystemBuffer,
1163 Irp->AssociatedIrp.SystemBuffer));
1164
1165 } else {
1167 }
1168 }
1169
1170 Irp->IoStatus.Status = status;
1171
1174
1175 return status;
1176}
NTSTATUS ClasspDuidGetDeviceProperty(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: utils.c:782
NTSTATUS ClasspDuidGetDriveLayout(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: utils.c:875
NTSTATUS ClasspDuidGetDeviceIdProperty(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: utils.c:689
* PSTORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
FORCEINLINE DUID_MATCH_STATUS CompareStorageDuids(_In_ PSTORAGE_DEVICE_UNIQUE_IDENTIFIER Duid1, _In_ PSTORAGE_DEVICE_UNIQUE_IDENTIFIER Duid2)
Definition: storduid.h:56
struct _STORAGE_DEVICE_UNIQUE_IDENTIFIER STORAGE_DEVICE_UNIQUE_IDENTIFIER
#define DUID_INCLUDE_SOFTWARE_IDS
Definition: storduid.h:23
#define DUID_VERSION_1
Definition: storduid.h:20
@ DuidExactMatch
Definition: storduid.h:6
#define DUID_HARDWARE_IDS_ONLY
Definition: storduid.h:22

Referenced by ClassDeviceControl().

◆ ClasspEjectionControl()

NTSTATUS ClasspEjectionControl ( IN PDEVICE_OBJECT  Fdo,
IN PIRP  Irp,
IN MEDIA_LOCK_TYPE  LockType,
IN BOOLEAN  Lock 
)

Definition at line 474 of file create.c.

480{
482 PCOMMON_DEVICE_EXTENSION commonExtension =
484
485 PFILE_OBJECT_EXTENSION fsContext = NULL;
488 BOOLEAN countChanged = FALSE;
489
490 PAGED_CODE();
491
492 /*
493 * Ensure that the user thread is not suspended while we are holding EjectSynchronizationEvent.
494 */
496
498 &(FdoExtension->EjectSynchronizationEvent),
501 FALSE,
502 NULL);
503
505
506 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
507 "ClasspEjectionControl: "
508 "Received request for %s lock type\n",
510 ));
511
512 _SEH2_TRY {
513 PCDB cdb = NULL;
514
515 //
516 // Determine if this is a "secured" request.
517 //
518
519 if (LockType == SecureMediaLock) {
520
522 PFILE_OBJECT fileObject = irpStack->FileObject;
523
524 //
525 // Make sure that the file object we are supplied has a
526 // proper FsContext before we try doing a secured lock.
527 //
528
529 if (fileObject != NULL) {
530 fsContext = ClassGetFsContext(commonExtension, fileObject);
531 }
532
533 if (fsContext == NULL) {
534
535 //
536 // This handle isn't setup correctly. We can't let the
537 // operation go.
538 //
539
542 }
543 }
544
545 if (Lock) {
546
547 //
548 // This is a lock command. Reissue the command in case bus or
549 // device was reset and the lock was cleared.
550 // note: may need to decrement count if actual lock operation
551 // failed....
552 //
553
554 switch (LockType) {
555
556 case SimpleMediaLock: {
557 FdoExtension->LockCount++;
558 countChanged = TRUE;
559 break;
560 }
561
562 case SecureMediaLock: {
563 fsContext->LockCount++;
564 FdoExtension->ProtectedLockCount++;
565 countChanged = TRUE;
566 break;
567 }
568
569 case InternalMediaLock: {
570 FdoExtension->InternalLockCount++;
571 countChanged = TRUE;
572 break;
573 }
574 }
575
576 } else {
577
578 //
579 // This is an unlock command. If it's a secured one then make sure
580 // the caller has a lock outstanding or return an error.
581 // note: may need to re-increment the count if actual unlock
582 // operation fails....
583 //
584
585 switch (LockType) {
586
587 case SimpleMediaLock: {
588 if(FdoExtension->LockCount != 0) {
589 FdoExtension->LockCount--;
590 countChanged = TRUE;
591 }
592 break;
593 }
594
595 case SecureMediaLock: {
596 if(fsContext->LockCount == 0) {
599 }
600 fsContext->LockCount--;
601 FdoExtension->ProtectedLockCount--;
602 countChanged = TRUE;
603 break;
604 }
605
606 case InternalMediaLock: {
607 NT_ASSERT(FdoExtension->InternalLockCount != 0);
608 FdoExtension->InternalLockCount--;
609 countChanged = TRUE;
610 break;
611 }
612 }
613
614 //
615 // We only send an unlock command to the drive if both the
616 // secured and unsecured lock counts have dropped to zero.
617 //
618
619 if ((FdoExtension->ProtectedLockCount != 0) ||
620 (FdoExtension->InternalLockCount != 0) ||
621 (FdoExtension->LockCount != 0)) {
622
625 }
626 }
627
629 if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
630
632
633 if (srb == NULL) {
636 }
637
638 if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
639
640 //
641 // NOTE - this is based on size used in ClasspAllocateSrb
642 //
643
647 1,
649 if (!NT_SUCCESS(status)) {
652 }
653
654 } else {
655 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
656 }
657
658 SrbSetCdbLength(srb, 6);
659 cdb = SrbGetCdb(srb);
660 NT_ASSERT(cdb != NULL);
661
662 cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
663
664 //
665 // TRUE - prevent media removal.
666 // FALSE - allow media removal.
667 //
668
669 cdb->MEDIA_REMOVAL.Prevent = Lock;
670
671 //
672 // Set timeout value.
673 //
674
675 SrbSetTimeOutValue(srb, FdoExtension->TimeOutValue);
676
677 //
678 // The actual lock operation on the device isn't so important
679 // as the internal lock counts. Ignore failures.
680 //
681
683 srb,
684 NULL,
685 0,
686 FALSE);
687 }
688
689 } _SEH2_FINALLY {
690
691 if (!NT_SUCCESS(status)) {
692 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
693 "ClasspEjectionControl: FAILED status %x -- "
694 "reverting lock counts\n", status));
695
696 if (countChanged) {
697
698 //
699 // have to revert to previous counts if the
700 // lock/unlock operation actually failed.
701 //
702
703 if (Lock) {
704
705 switch (LockType) {
706
707 case SimpleMediaLock: {
708 FdoExtension->LockCount--;
709 break;
710 }
711
712 case SecureMediaLock: {
713 fsContext->LockCount--;
714 FdoExtension->ProtectedLockCount--;
715 break;
716 }
717
718 case InternalMediaLock: {
719 FdoExtension->InternalLockCount--;
720 break;
721 }
722 }
723
724 } else {
725
726 switch (LockType) {
727
728 case SimpleMediaLock: {
729 FdoExtension->LockCount++;
730 break;
731 }
732
733 case SecureMediaLock: {
734 fsContext->LockCount++;
735 FdoExtension->ProtectedLockCount++;
736 break;
737 }
738
739 case InternalMediaLock: {
740 FdoExtension->InternalLockCount++;
741 break;
742 }
743 }
744 }
745
746 }
747
748 } else {
749
750 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
751 "ClasspEjectionControl: Succeeded\n"));
752
753 }
754
755 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
756 "ClasspEjectionControl: "
757 "Current Counts: Internal: %x Secure: %x Simple: %x\n",
758 FdoExtension->InternalLockCount,
759 FdoExtension->ProtectedLockCount,
760 FdoExtension->LockCount
761 ));
762
763 KeSetEvent(&(FdoExtension->EjectSynchronizationEvent),
765 FALSE);
767
768 if (srb) {
770 }
771
772 } _SEH2_END;
773 return status;
774}
_In_ WDFREQUEST _In_ MEDIA_LOCK_TYPE LockType
Definition: cdrom.h:1335
@ SimpleMediaLock
Definition: cdromp.h:289
@ InternalMediaLock
Definition: cdromp.h:291
@ SecureMediaLock
Definition: cdromp.h:290
VOID ClassFreeOrReuseSrb(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN __drv_freesMem(mem) PSCSI_REQUEST_BLOCK Srb)
Definition: obsolete.c:882
#define ClasspAllocateSrb(ext)
Definition: classpnp.h:146
const PCSZ LockTypeStrings[]
Definition: create.c:34
#define _SEH2_FINALLY
Definition: pseh2_64.h:114
#define _SEH2_LEAVE
Definition: pseh2_64.h:167
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127

Referenced by ClassDeviceControl(), and ClassDispatchPnp().

◆ ClasspEnableIdlePower()

_IRQL_requires_same_ NTSTATUS ClasspEnableIdlePower ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 2550 of file power.c.

2573{
2575 ULONG d3ColdDisabledByUser = FALSE;
2577 ULONG idleTimeoutOverrideInSeconds = 0;
2578
2579 //
2580 // This function should only be called once.
2581 //
2582 NT_ASSERT(fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled == FALSE);
2583
2584 ClassGetDeviceParameter(fdoExtension,
2587 &d3ColdDisabledByUser);
2588
2589 //
2590 // If the device is hot-pluggable or the user has explicitly
2591 // disabled D3Cold, do not enable D3Cold for this device.
2592 //
2593 if (d3ColdDisabledByUser || fdoExtension->PrivateFdoData->HotplugInfo.DeviceHotplug) {
2594 fdoExtension->FunctionSupportInfo->IdlePower.D3ColdSupported = 0;
2595 }
2596
2597 ClassGetDeviceParameter(fdoExtension,
2600 &idleTimeoutOverrideInSeconds);
2601
2602 //
2603 // Set the idle timeout. If the user has not specified an override value,
2604 // this will either be a default value or will have been updated by the
2605 // power setting notification callback.
2606 //
2607 if (idleTimeoutOverrideInSeconds != 0) {
2608 fdoExtension->FunctionSupportInfo->IdlePower.D3IdleTimeout = (idleTimeoutOverrideInSeconds * 1000);
2609 fdoExtension->FunctionSupportInfo->IdlePower.D3IdleTimeoutOverridden = TRUE;
2610 } else {
2611 fdoExtension->FunctionSupportInfo->IdlePower.D3IdleTimeout = DiskIdleTimeoutInMS;
2612 }
2613
2614 //
2615 // We don't allow disks to be wakeable.
2616 //
2617 fdoExtension->FunctionSupportInfo->IdlePower.DeviceWakeable = FALSE;
2618
2619 //
2620 // Send IOCTL_STORAGE_ENABLE_IDLE_POWER to the port driver to enable idle
2621 // power management by the port driver.
2622 //
2624
2625 if (NT_SUCCESS(status)) {
2627
2628 //
2629 // Put this FDO on the list of devices that are idle power managed.
2630 //
2631 fdoEntry = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(IDLE_POWER_FDO_LIST_ENTRY), CLASS_TAG_POWER);
2632 if (fdoEntry) {
2633
2634 fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled = TRUE;
2635
2636 fdoEntry->Fdo = DeviceObject;
2637
2641
2642 //
2643 // If not registered already, register for disk idle timeout power
2644 // setting notifications. The power manager will call our power
2645 // setting callback very soon to set the idle timeout to the actual
2646 // value.
2647 //
2650 &GUID_DISK_IDLE_TIMEOUT,
2652 NULL,
2654 }
2655 } else {
2656 fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled = FALSE;
2658 }
2659 }
2660
2661 return status;
2662}
#define CLASSP_REG_SUBKEY_NAME
Definition: cdromp.h:120
#define CLASSP_REG_IDLE_TIMEOUT_IN_SECONDS
Definition: classp.h:124
#define CLASSP_REG_DISABLE_D3COLD
Definition: classp.h:125
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
Definition: classp.h:1619
KGUARDED_MUTEX IdlePowerFDOListMutex
Definition: class.c:114
ULONG DiskIdleTimeoutInMS
Definition: class.c:132
PVOID PowerSettingNotificationHandle
Definition: class.c:119
LIST_ENTRY IdlePowerFDOList
Definition: class.c:113
#define CLASS_TAG_POWER
Definition: power.c:37
_IRQL_requires_same_ NTSTATUS ClasspSendEnableIdlePowerIoctl(_In_ PDEVICE_OBJECT DeviceObject)
Definition: power.c:2333
#define InsertHeadList(ListHead, Entry)
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
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
Definition: classp.h:1033
LIST_ENTRY ListEntry
Definition: classp.h:1034
PDEVICE_OBJECT Fdo
Definition: classp.h:1035

◆ ClasspEnableTimer()

VOID ClasspEnableTimer ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 3857 of file autorun.c.

3860{
3861 PCLASS_PRIVATE_FDO_DATA fdoData = NULL;
3862
3863 if (FdoExtension->CommonExtension.IsFdo) {
3864 fdoData = FdoExtension->PrivateFdoData;
3865 }
3866
3867 if (fdoData != NULL) {
3868 //
3869 // The timer should have already been initialized, but if that's not
3870 // the case it's not the end of the world. We can attempt to
3871 // initialize it now.
3872 //
3873 NT_ASSERT(fdoData->TimerInitialized);
3874 if (fdoData->TimerInitialized == FALSE) {
3877 if (NT_SUCCESS(status) == FALSE) {
3878 return;
3879 }
3880 }
3881
3882#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3883 if (fdoData->TickTimer != NULL) {
3884 EXT_SET_PARAMETERS parameters;
3885 LONGLONG period = TICK_TIMER_PERIOD_IN_MSEC * (10 * 1000); // Convert to units of 100ns.
3886 LONGLONG dueTime = period * (-1); // Negative sign indicates dueTime is relative.
3887
3888 ExInitializeSetTimerParameters(&parameters);
3889
3890 //
3891 // Set the no-wake tolerance to "unlimited" if the conditions below
3892 // are met. An "unlimited" no-wake tolerance means that the timer
3893 // will *never* wake the processor if the processor is in a
3894 // low-power state.
3895 // 1. The screen is off.
3896 // 2. The class driver is *not* a consumer of the tick timer (ClassTick is NULL).
3897 // 3. This is a disk device.
3898 // Otherwise the tolerance is set to the normal tolerable delay.
3899 //
3900 if (ClasspScreenOff &&
3901 FdoExtension->CommonExtension.DriverExtension->InitData.ClassTick == NULL &&
3902 FdoExtension->DeviceObject->DeviceType == FILE_DEVICE_DISK) {
3904 } else {
3905 parameters.NoWakeTolerance = TICK_TIMER_DELAY_IN_MSEC * (10 * 1000);
3906 }
3907
3908 fdoData->CurrentNoWakeTolerance = parameters.NoWakeTolerance;
3909
3910 ExSetTimer(fdoData->TickTimer,
3911 dueTime,
3912 period,
3913 &parameters);
3914
3915 fdoData->TickTimerEnabled = TRUE;
3916 } else {
3917 NT_ASSERT(fdoData->TickTimer != NULL);
3918 }
3919#else
3920 //
3921 // Start the periodic tick timer using a coalescable timer with some delay
3922 //
3923 {
3925 timeout.QuadPart = TICK_TIMER_PERIOD_IN_MSEC * (10 * 1000) * (-1);
3926 KeSetCoalescableTimer(&fdoData->TickTimer,
3928 &fdoData->TickTimerDpc);
3929 fdoData->TickTimerEnabled = TRUE;
3930 }
3931#endif
3932
3933 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspEnableTimer: Periodic tick timer enabled "
3934 "for device %p\n", FdoExtension->DeviceObject));
3935
3936 }
3937
3938} // end ClasspEnableTimer()
NTSTATUS ClasspInitializeTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3737
#define TICK_TIMER_DELAY_IN_MSEC
Definition: autorun.c:130
#define TICK_TIMER_PERIOD_IN_MSEC
Definition: autorun.c:129
BOOLEAN ClasspScreenOff
Definition: autorun.c:124
LONGLONG CurrentNoWakeTolerance
Definition: classp.h:677
LONGLONG NoWakeTolerance
Definition: extypes.h:286
Definition: dhcpd.h:245
NTKERNELAPI BOOLEAN NTAPI ExSetTimer(_In_ PEX_TIMER Timer, _In_ LONGLONG DueTime, _In_ LONGLONG Period, _In_opt_ PEXT_SET_PARAMETERS Parameters)
#define EX_TIMER_UNLIMITED_TOLERANCE
Definition: exfuncs.h:957
FORCEINLINE VOID ExInitializeSetTimerParameters(_Out_ PEXT_SET_PARAMETERS Parameters)
Definition: exfuncs.h:995

Referenced by ClasspDeviceLockFailurePowerIrpCompletion(), and ClasspPowerUpCompletion().

◆ ClasspEnqueueIdleRequest()

NTSTATUS ClasspEnqueueIdleRequest ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 576 of file clntirp.c.

580{
581 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
582 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
583 KIRQL oldIrql;
584 BOOLEAN issueRequest = TRUE;
585 LARGE_INTEGER currentTime;
586 LARGE_INTEGER* pCurrentTime;
587
588 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_TIMER, "ClasspEnqueueIdleRequest: Queue idle request %p\n", Irp));
589
591
592 //
593 // Reset issueRequest if the idle duration is not sufficient.
594 //
595 pCurrentTime = &currentTime;
596 if (ClasspIdleDurationSufficient(fdoData, &pCurrentTime) == FALSE) {
597 issueRequest = FALSE;
598 }
599
600 //
601 // If there are already max active idle requests in the port driver, then
602 // queue this idle request.
603 //
604 if (fdoData->ActiveIdleIoCount >= fdoData->IdleActiveIoMax) {
605 issueRequest = FALSE;
606 }
607
608
609 KeAcquireSpinLock(&fdoData->IdleListLock, &oldIrql);
610 if (IsListEmpty(&fdoData->IdleIrpList)) {
611 NT_ASSERT(fdoData->IdleIoCount == 0);
612 }
613 InsertTailList(&fdoData->IdleIrpList, &Irp->Tail.Overlay.ListEntry);
614
615
616 fdoData->IdleIoCount++;
617 if (!fdoData->IdleTimerStarted) {
618 ClasspStartIdleTimer(fdoData);
619 }
620
621 if (fdoData->IdleIoCount != 1) {
622 issueRequest = FALSE;
623 }
624
625
626 KeReleaseSpinLock(&fdoData->IdleListLock, oldIrql);
627
628 if (issueRequest) {
629 ClasspServiceIdleRequest(fdoExtension, FALSE);
630 }
631
632 return STATUS_PENDING;
633}
VOID ClasspStartIdleTimer(IN PCLASS_PRIVATE_FDO_DATA FdoData)
Definition: clntirp.c:261
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
LIST_ENTRY IdleIrpList
Definition: classp.h:882
KSPIN_LOCK IdleListLock
Definition: classp.h:877

Referenced by ClassReadWrite().

◆ ClasspFailurePredictionPeriodMissed()

BOOLEAN ClasspFailurePredictionPeriodMissed ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 4391 of file autorun.c.

4412{
4413 LARGE_INTEGER currentTime;
4414 LARGE_INTEGER timeDifference;
4415 BOOLEAN missedPeriod = FALSE;
4416
4418 NT_ASSERT(FdoExtension->FailurePredictionInfo);
4419 NT_ASSERT(FdoExtension->FailurePredictionInfo->Method != FailurePredictionNone);
4420
4421 //
4422 // Find the difference between the last failure prediction
4423 // query and the current time and convert it to seconds.
4424 //
4425 KeQuerySystemTime(&currentTime);
4426 timeDifference.QuadPart = currentTime.QuadPart - FdoExtension->FailurePredictionInfo->LastFailurePredictionQueryTime.QuadPart;
4427 timeDifference.QuadPart /= (10LL * 1000LL * 1000LL);
4428
4429 if (timeDifference.QuadPart >= FdoExtension->FailurePredictionInfo->Period) {
4430 missedPeriod = TRUE;
4431 }
4432
4433 return missedPeriod;
4434}
@ FailurePredictionNone
Definition: classpnp.h:234
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570

Referenced by _Function_class_(), ClasspDeviceLockFailurePowerIrpCompletion(), and ClasspPowerUpCompletion().

◆ ClasspFreeDeviceMdl()

VOID ClasspFreeDeviceMdl ( PMDL  Mdl)

Definition at line 615 of file utils.c.

616{
618 IoFreeMdl(Mdl);
619}
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl

Referenced by ClasspCleanupOffloadReadContext(), ClasspCleanupOffloadWriteContext(), and FreeDeviceInputMdl().

◆ 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 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
#define STATUS_DEVICE_FEATURE_NOT_SUPPORTED
Definition: ntstatus.h:985
struct _VPD_THIRD_PARTY_COPY_PAGE * PVPD_THIRD_PARTY_COPY_PAGE
#define BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR_TYPE_WINDOWS
Definition: scsi.h:2523
UCHAR descriptorLength
Definition: scsi.h:4078
struct _WINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR * PWINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR
#define VPD_THIRD_PARTY_COPY
Definition: scsi.h:2415
UCHAR ThirdPartyCopyDescriptors[ANYSIZE_ARRAY]
Definition: scsi.h:2508

Referenced by _IRQL_requires_().

◆ ClasspGetCurrentTime()

FORCEINLINE LARGE_INTEGER ClasspGetCurrentTime ( VOID  )

Definition at line 1280 of file classp.h.

1283{
1284 LARGE_INTEGER currentTime;
1285
1286#ifndef __REACTOS__
1287 currentTime.QuadPart = KeQueryUnbiasedInterruptTimePrecise((ULONG64*)&currentTime.QuadPart);
1288#else
1289 currentTime = KeQueryPerformanceCounter(NULL);
1290#endif
1291
1292 return currentTime;
1293}
LARGE_INTEGER NTAPI KeQueryPerformanceCounter(IN PLARGE_INTEGER PerformanceFreq)
Definition: timer.c:138
unsigned __int64 ULONG64
Definition: imports.h:198

Referenced by ClasspIdleDurationSufficient(), ClasspIdleTimerDpc(), ClasspStartIdleTimer(), ClassReadWrite(), and TransferPktComplete().

◆ 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}
#define SCSI_REQUEST_BLOCK_SIZE
Definition: srb.h:282
#define VPD_SUPPORTED_PAGES
Definition: scsi.h:2404
PDEVICE_OBJECT DeviceObject
Definition: pci.h:46
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

◆ ClasspGetMaxUsableBufferLengthFromOffset()

FORCEINLINE ULONG ClasspGetMaxUsableBufferLengthFromOffset ( _In_ PVOID  BaseAddress,
_In_ ULONG  OffsetInBytes,
_In_ ULONG  BaseStructureSizeInBytes 
)

Definition at line 2585 of file classp.h.

2612{
2613
2614 ULONG_PTR offsetAddress = ((ULONG_PTR)BaseAddress + OffsetInBytes);
2615
2616 if (offsetAddress < (ULONG_PTR)BaseAddress) {
2617 //
2618 // This means BaseAddress + OffsetInBytes > ULONG_PTR_MAX.
2619 //
2620 return 0;
2621 }
2622
2623 if (OffsetInBytes > BaseStructureSizeInBytes) {
2624 return 0;
2625 }
2626
2627 return BaseStructureSizeInBytes - OffsetInBytes;
2628}
#define ULONG_PTR
Definition: config.h:101
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404

◆ ClasspGetTokenOperationCommandBufferLength()

_IRQL_requires_same_ NTSTATUS ClasspGetTokenOperationCommandBufferLength ( _In_ PDEVICE_OBJECT  Fdo,
_In_ ULONG  ServiceAction,
_Inout_ PULONG  CommandBufferLength,
_Out_opt_ PULONG  TokenOperationBufferLength,
_Out_opt_ PULONG  ReceiveTokenInformationBufferLength 
)

Definition at line 7356 of file utils.c.

7385{
7386 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
7387 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
7388 ULONG tokenOperationBufferLength;
7389 ULONG receiveTokenInformationBufferLength;
7390 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
7391 PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExtension->PartitionZeroExtension->AdapterDescriptor;
7392 ULONG hwMaxXferLen;
7393 ULONG bufferLength = 0;
7394 ULONG tokenOperationHeaderSize;
7395 ULONG responseSize;
7396
7397 TracePrint((TRACE_LEVEL_VERBOSE,
7398 TRACE_FLAG_IOCTL,
7399 "ClasspGetTokenOperationCommandBufferLengths (%p): Entering function.\n",
7400 Fdo));
7401
7402 NT_ASSERT(fdoExt->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits &&
7403 NT_SUCCESS(fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus));
7404
7405 if (ServiceAction == SERVICE_ACTION_POPULATE_TOKEN) {
7406 tokenOperationHeaderSize = FIELD_OFFSET(POPULATE_TOKEN_HEADER, BlockDeviceRangeDescriptor);
7408 } else {
7409 tokenOperationHeaderSize = FIELD_OFFSET(WRITE_USING_TOKEN_HEADER, BlockDeviceRangeDescriptor);
7410 responseSize = 0;
7411 }
7412
7413 //
7414 // The TokenOperation command can specify a parameter length of max 2^16.
7415 // If the device has a max limit on the number of range descriptors that can be specified in
7416 // the TokenOperation command, we are limited to the lesser of these two values.
7417 //
7418 if (fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumRangeDescriptors == 0) {
7419
7420 tokenOperationBufferLength = MAX_TOKEN_OPERATION_PARAMETER_DATA_LENGTH;
7421
7422 } else {
7423
7424 tokenOperationBufferLength = MIN(tokenOperationHeaderSize + fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumRangeDescriptors * sizeof(BLOCK_DEVICE_RANGE_DESCRIPTOR),
7426 }
7427
7428
7429 //
7430 // The ReceiveTokenInformation command can specify a parameter length of max 2 ^ 32
7431 // Also, since the sense data can be of variable size, we'll use MAX_SENSE_BUFFER_SIZE.
7432 //
7433 receiveTokenInformationBufferLength = MIN(FIELD_OFFSET(RECEIVE_TOKEN_INFORMATION_HEADER, SenseData) + MAX_SENSE_BUFFER_SIZE + responseSize,
7435
7436 //
7437 // Since we're going to reuse the buffer for both the TokenOperation and the ReceiveTokenInformation
7438 // commands, the buffer length needs to handle both operations.
7439 //
7440 bufferLength = MAX(tokenOperationBufferLength, receiveTokenInformationBufferLength);
7441
7442 //
7443 // The buffer length needs to be further limited to the adapter's capability though.
7444 //
7445 hwMaxXferLen = MIN(fdoData->HwMaxXferLen, adapterDesc->MaximumTransferLength);
7446 bufferLength = MIN(bufferLength, hwMaxXferLen);
7447
7448 *CommandBufferLength = bufferLength;
7449
7450 if (TokenOperationBufferLength) {
7451 *TokenOperationBufferLength = tokenOperationBufferLength;
7452 }
7453
7454 if (ReceiveTokenInformationBufferLength) {
7455 *ReceiveTokenInformationBufferLength = receiveTokenInformationBufferLength;
7456 }
7457
7458 TracePrint((TRACE_LEVEL_VERBOSE,
7459 TRACE_FLAG_IOCTL,
7460 "ClasspGetTokenOperationCommandBufferLengths (%p): Exiting function with bufferLength %u (tokenOpBufLen %u, recTokenInfoBufLen %u).\n",
7461 Fdo,
7463 tokenOperationBufferLength,
7464 receiveTokenInformationBufferLength));
7465
7466 return STATUS_SUCCESS;
7467}
#define MAX(x, y)
Definition: rdesktop.h:175
#define MAX_RECEIVE_TOKEN_INFORMATION_PARAMETER_DATA_LENGTH
Definition: classp.h:208
* PSTORAGE_ADAPTER_DESCRIPTOR
Definition: ntddstor.h:599
#define SERVICE_ACTION_POPULATE_TOKEN
Definition: scsi.h:442
#define MAX_SENSE_BUFFER_SIZE
Definition: scsi.h:598

◆ ClasspGetTokenOperationDescriptorLimits()

_IRQL_requires_same_ NTSTATUS ClasspGetTokenOperationDescriptorLimits ( _In_ PDEVICE_OBJECT  Fdo,
_In_ ULONG  ServiceAction,
_In_ ULONG  MaxParameterBufferLength,
_Out_ PULONG  MaxBlockDescriptorsCount,
_Out_ PULONGLONG  MaxBlockDescriptorsLength 
)

Definition at line 7472 of file utils.c.

7501{
7502 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
7503 ULONG tokenOperationHeaderSize = (ServiceAction == SERVICE_ACTION_POPULATE_TOKEN) ?
7504 FIELD_OFFSET(POPULATE_TOKEN_HEADER, BlockDeviceRangeDescriptor) :
7505 FIELD_OFFSET(WRITE_USING_TOKEN_HEADER, BlockDeviceRangeDescriptor);
7506
7507 TracePrint((TRACE_LEVEL_VERBOSE,
7508 TRACE_FLAG_IOCTL,
7509 "ClasspGetTokenOperationDescriptorLimits (%p): Entering function.\n",
7510 Fdo));
7511
7512 NT_ASSERT(fdoExt->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits &&
7513 NT_SUCCESS(fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus));
7514
7515 *MaxBlockDescriptorsCount = (MaxParameterBufferLength - tokenOperationHeaderSize) / sizeof(BLOCK_DEVICE_RANGE_DESCRIPTOR);
7516 *MaxBlockDescriptorsLength = (fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumTokenTransferSize == 0) ?
7517 MAX_TOKEN_TRANSFER_SIZE : fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumTokenTransferSize;
7518
7519 TracePrint((TRACE_LEVEL_VERBOSE,
7520 TRACE_FLAG_IOCTL,
7521 "ClasspGetTokenOperationDescriptorLimits (%p): Exiting function with MaxDescr %u, MaxXferBlocks %I64u.\n",
7522 Fdo,
7523 *MaxBlockDescriptorsCount,
7524 *MaxBlockDescriptorsLength));
7525
7526 return STATUS_SUCCESS;
7527}
#define MAX_TOKEN_TRANSFER_SIZE
Definition: classp.h:209

◆ ClasspInitializeGesn()

NTSTATUS ClasspInitializeGesn ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN PMEDIA_CHANGE_DETECTION_INFO  Info 
)

Definition at line 1990 of file autorun.c.

1994{
1997 PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor;
1999 PIRP irp;
2000 KEVENT event;
2001 BOOLEAN retryImmediately;
2002 ULONG i;
2003 ULONG atapiResets;
2004 ULONG srbFlags;
2005
2006 PAGED_CODE();
2007 NT_ASSERT(Info == FdoExtension->MediaChangeDetectionInfo);
2008
2009 //
2010 // read if we already know the abilities of the device
2011 //
2012
2013 ClassGetDeviceParameter(FdoExtension,
2016 (PULONG)&detectionState);
2017
2018 if (detectionState == ClassDetectionUnsupported) {
2019 goto ExitWithError;
2020 }
2021
2022 //
2023 // check if the device has a hack flag saying never to try this.
2024 //
2025
2026 if (TEST_FLAG(FdoExtension->PrivateFdoData->HackFlags,
2028
2029 ClassSetDeviceParameter(FdoExtension,
2033 goto ExitWithError;
2034
2035 }
2036
2037
2038 //
2039 // else go through the process since we allocate buffers and
2040 // get all sorts of device settings.
2041 //
2042
2043 if (Info->Gesn.Buffer == NULL) {
2044 Info->Gesn.Buffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
2046 '??cS');
2047 }
2048 if (Info->Gesn.Buffer == NULL) {
2050 goto ExitWithError;
2051 }
2052 if (Info->Gesn.Mdl != NULL) {
2053 IoFreeMdl(Info->Gesn.Mdl);
2054 }
2055 Info->Gesn.Mdl = IoAllocateMdl(Info->Gesn.Buffer,
2057 FALSE, FALSE, NULL);
2058 if (Info->Gesn.Mdl == NULL) {
2060 goto ExitWithError;
2061 }
2062
2064 Info->Gesn.BufferSize = GESN_BUFFER_SIZE;
2065 Info->Gesn.EventMask = 0;
2066
2067 //
2068 // all items are prepared to use GESN (except the event mask, so don't
2069 // optimize this part out!).
2070 //
2071 // now see if it really works. we have to loop through this because
2072 // many SAMSUNG (and one COMPAQ) drives timeout when requesting
2073 // NOT_READY events, even when the IMMEDIATE bit is set. :(
2074 //
2075 // using a drive list is cumbersome, so this might fix the problem.
2076 //
2077
2078 deviceDescriptor = FdoExtension->DeviceDescriptor;
2079 atapiResets = 0;
2080 retryImmediately = TRUE;
2081 for (i = 0; i < 16 && retryImmediately == TRUE; i++) {
2082
2084 if (irp == NULL) {
2086 goto ExitWithError;
2087 }
2088
2089 if (Info->MediaChangeSrb.Srb.Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) {
2090 srbFlags = Info->MediaChangeSrb.SrbEx.SrbFlags;
2091 } else {
2092 srbFlags = Info->MediaChangeSrb.Srb.SrbFlags;
2093 }
2095
2096 //
2097 // replace the completion routine with a different one this time...
2098 //
2099
2103 &event,
2104 TRUE, TRUE, TRUE);
2105
2106 status = IoCallDriver(FdoExtension->CommonExtension.LowerDeviceObject, irp);
2107
2108 if (status == STATUS_PENDING) {
2110 Executive,
2111 KernelMode,
2112 FALSE,
2113 NULL);
2115 }
2116 ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
2117
2118 if (SRB_STATUS(Info->MediaChangeSrb.Srb.SrbStatus) != SRB_STATUS_SUCCESS) {
2119
2121 irp,
2122 &(Info->MediaChangeSrb.Srb),
2124 0,
2125 0,
2126 &status,
2127 NULL);
2128 }
2129
2130 if ((deviceDescriptor->BusType == BusTypeAtapi) &&
2131 (Info->MediaChangeSrb.Srb.SrbStatus == SRB_STATUS_BUS_RESET)
2132 ) {
2133
2134 //
2135 // ATAPI unfortunately returns SRB_STATUS_BUS_RESET instead
2136 // of SRB_STATUS_TIMEOUT, so we cannot differentiate between
2137 // the two. if we get this status four time consecutively,
2138 // stop trying this command. it is too late to change ATAPI
2139 // at this point, so special-case this here. (07/10/2001)
2140 // NOTE: any value more than 4 may cause the device to be
2141 // marked missing.
2142 //
2143
2144 atapiResets++;
2145 if (atapiResets >= 4) {
2147 goto ExitWithError;
2148 }
2149 }
2150
2151 if (status == STATUS_DATA_OVERRUN) {
2153 }
2154
2156 (status == STATUS_TIMEOUT) ||
2159 ) {
2160
2161 //
2162 // with these error codes, we don't ever want to try this command
2163 // again on this device, since it reacts poorly.
2164 //
2165
2166 ClassSetDeviceParameter(FdoExtension,
2170 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
2171 "Classpnp => GESN test failed %x for fdo %p\n",
2172 status, FdoExtension->DeviceObject));
2173 goto ExitWithError;
2174
2175
2176 }
2177
2178 if (!NT_SUCCESS(status)) {
2179
2180 //
2181 // this may be other errors that should not disable GESN
2182 // for all future start_device calls.
2183 //
2184
2185 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
2186 "Classpnp => GESN test failed %x for fdo %p\n",
2187 status, FdoExtension->DeviceObject));
2188 goto ExitWithError;
2189 }
2190
2191 if (i == 0) {
2192
2193 //
2194 // the first time, the request was just retrieving a mask of
2195 // available bits. use this to mask future requests.
2196 //
2197
2199
2200 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2201 "Classpnp => Fdo %p supports event mask %x\n",
2202 FdoExtension->DeviceObject, header->SupportedEventClasses));
2203
2204
2205 if (TEST_FLAG(header->SupportedEventClasses,
2207 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2208 "Classpnp => GESN supports MCN\n"));
2209 }
2210 if (TEST_FLAG(header->SupportedEventClasses,
2212 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2213 "Classpnp => GESN supports DeviceBusy\n"));
2214 }
2215 if (TEST_FLAG(header->SupportedEventClasses,
2217
2218 if (TEST_FLAG(FdoExtension->PrivateFdoData->HackFlags,
2220 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2221 "Classpnp => GESN supports OpChange, but "
2222 "must ignore these events for compatibility\n"));
2223 CLEAR_FLAG(header->SupportedEventClasses,
2225 } else {
2226 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2227 "Classpnp => GESN supports OpChange\n"));
2228 }
2229 }
2230 Info->Gesn.EventMask = header->SupportedEventClasses;
2231
2232 //
2233 // realistically, we are only considering the following events:
2234 // EXTERNAL REQUEST - this is being tested for play/stop/etc.
2235 // MEDIA STATUS - autorun and ejection requests.
2236 // DEVICE BUSY - to allow us to predict when media will be ready.
2237 // therefore, we should not bother querying for the other,
2238 // unknown events. clear all but the above flags.
2239 //
2240
2241 Info->Gesn.EventMask &=
2246
2247
2248 //
2249 // HACKHACK - REF #0001
2250 // Some devices will *never* report an event if we've also requested
2251 // that it report lower-priority events. this is due to a
2252 // misunderstanding in the specification wherein a "No Change" is
2253 // interpreted to be a real event. what should occur is that the
2254 // device should ignore "No Change" events when multiple event types
2255 // are requested unless there are no other events waiting. this
2256 // greatly reduces the number of requests that the host must send
2257 // to determine if an event has occurred. Since we must work on all
2258 // drives, default to enabling the hack until we find evidence of
2259 // proper firmware.
2260 //
2261 if (Info->Gesn.EventMask == 0) {
2262
2263 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2264 "Classpnp => GESN supported, but not mask we care "
2265 "about (%x) for FDO %p\n",
2266 header->SupportedEventClasses,
2267 FdoExtension->DeviceObject));
2268 goto ExitWithError;
2269
2270 } else if (CountOfSetBitsUChar(Info->Gesn.EventMask) == 1) {
2271
2272 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2273 "Classpnp => GESN hack not required for FDO %p\n",
2274 FdoExtension->DeviceObject));
2275
2276 } else {
2277
2278 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2279 "Classpnp => GESN hack enabled for FDO %p\n",
2280 FdoExtension->DeviceObject));
2281 Info->Gesn.HackEventMask = 1;
2282
2283 }
2284
2285 } else {
2286
2287 //
2288 // not the first time looping through, so interpret the results.
2289 //
2290
2292 (PVOID)Info->Gesn.Buffer,
2293 &retryImmediately);
2294
2295 if (!NT_SUCCESS(status)) {
2296
2297 //
2298 // This drive does not support GESN correctly
2299 //
2300
2301 ClassSetDeviceParameter(FdoExtension,
2305 goto ExitWithError;
2306 }
2307 }
2308
2309 } // end loop of GESN requests....
2310
2311 //
2312 // we can only use this if it can be relied upon for media changes,
2313 // since we are (by definition) no longer going to be polling via
2314 // a TEST_UNIT_READY irp, and drives will not report UNIT ATTENTION
2315 // for this command (although a filter driver, such as one for burning
2316 // cd's, might still fake those errors).
2317 //
2318 // since we also rely upon NOT_READY events to change the cursor
2319 // into a "wait" cursor; GESN is still more reliable than other
2320 // methods, and includes eject button requests, so we'll use it
2321 // without DEVICE_BUSY in Windows Vista.
2322 //
2323
2324 if (TEST_FLAG(Info->Gesn.EventMask, NOTIFICATION_MEDIA_STATUS_CLASS_MASK)) {
2325
2326 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2327 "Classpnp => Enabling GESN support for fdo %p\n",
2328 FdoExtension->DeviceObject));
2329 Info->Gesn.Supported = TRUE;
2330
2331 ClassSetDeviceParameter(FdoExtension,
2335
2336 return STATUS_SUCCESS;
2337
2338 }
2339
2340 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2341 "Classpnp => GESN available but not enabled for fdo %p\n",
2342 FdoExtension->DeviceObject));
2343 goto ExitWithError;
2344
2345 // fall through...
2346
2347ExitWithError:
2348 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
2349 "Classpnp => GESN support detection failed for fdo %p with status %08x\n",
2350 FdoExtension->DeviceObject, status));
2351
2352
2353 if (Info->Gesn.Mdl) {
2354 IoFreeMdl(Info->Gesn.Mdl);
2355 Info->Gesn.Mdl = NULL;
2356 }
2357 FREE_POOL(Info->Gesn.Buffer);
2358 Info->Gesn.Supported = 0;
2359 Info->Gesn.EventMask = 0;
2360 Info->Gesn.BufferSize = 0;
2361 return STATUS_NOT_SUPPORTED;
2362
2363}
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
FORCEINLINE ULONG CountOfSetBitsUChar(UCHAR _X)
Definition: cdrom.h:1500
#define CLASSP_REG_MMC_DETECTION_VALUE_NAME
Definition: cdromp.h:123
#define FDO_HACK_GESN_IGNORE_OPCHANGE
Definition: cdromp.h:136
#define FDO_HACK_GESN_IS_BAD
Definition: cdromp.h:134
#define GESN_BUFFER_SIZE
Definition: autorun.c:32
PIRP ClasspPrepareMcnIrp(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info, IN BOOLEAN UseGesn)
Definition: autorun.c:1310
NTSTATUS ClasspInterpretGesnData(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PNOTIFICATION_EVENT_STATUS_HEADER Header, OUT PBOOLEAN ResendImmediately)
Definition: autorun.c:251
#define STATUS_TIMEOUT
Definition: d3dkmdt.h:49
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 SRB_STATUS_BUS_RESET
Definition: srb.h:353
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:424
@ BusTypeAtapi
Definition: ntddstor.h:440
* PSTORAGE_DEVICE_DESCRIPTOR
Definition: ntddstor.h:576
#define NOTIFICATION_MEDIA_STATUS_CLASS_MASK
Definition: scsi.h:37
#define NOTIFICATION_EXTERNAL_REQUEST_CLASS_MASK
Definition: scsi.h:36
#define NOTIFICATION_OPERATIONAL_CHANGE_CLASS_MASK
Definition: scsi.h:34
struct _NOTIFICATION_EVENT_STATUS_HEADER * PNOTIFICATION_EVENT_STATUS_HEADER
#define NOTIFICATION_DEVICE_BUSY_CLASS_MASK
Definition: scsi.h:39
#define SRB_FUNCTION_STORAGE_REQUEST_BLOCK
Definition: srb.h:108
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690

Referenced by ClasspInitializePolling().

◆ 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 CLASSP_REG_WRITE_CACHE_VALUE_NAME
Definition: cdromp.h:124
#define FDO_HACK_CANNOT_LOCK_MEDIA
Definition: cdromp.h:133
#define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME
Definition: cdromp.h:126
struct _STORAGE_HOTPLUG_INFO STORAGE_HOTPLUG_INFO
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
STORAGE_HOTPLUG_INFO HotplugInfo
Definition: classp.h:739
BOOLEAN WriteCacheEnableOverride
Definition: imports.h:249
BOOLEAN MediaRemovable
Definition: imports.h:246
BOOLEAN DeviceHotplug
Definition: imports.h:248
BOOLEAN MediaHotplug
Definition: imports.h:247
enum _DEVICE_REMOVAL_POLICY DEVICE_REMOVAL_POLICY
@ DevicePropertyRemovalPolicy
Definition: iotypes.h:1214
@ RemovalPolicyExpectSurpriseRemoval
Definition: iotypes.h:842
@ RemovalPolicyExpectOrderlyRemoval
Definition: iotypes.h:841

Referenced by ClassPnpStartDevice().

◆ ClasspInitializeIdleTimer()

VOID ClasspInitializeIdleTimer ( PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 175 of file clntirp.c.

178{
179 PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
180 ULONG idleInterval = CLASS_IDLE_INTERVAL;
181 ULONG idlePrioritySupported = TRUE;
182 ULONG activeIdleIoMax = 1;
183
184 ClassGetDeviceParameter(FdoExtension,
187 &idlePrioritySupported);
188
189
190 if (idlePrioritySupported == FALSE) {
191 //
192 // User has set the registry to disable idle priority for this disk.
193 // No need to initialize any further.
194 // Always ensure that none of the other fields used for idle priority
195 // io are ever used without checking if it is supported.
196 //
197 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_TIMER, "ClasspInitializeIdleTimer: Idle priority not supported for disk %p\n", FdoExtension));
198 fdoData->IdlePrioritySupported = FALSE;
199 fdoData->IdleIoCount = 0;
200 fdoData->ActiveIoCount = 0;
201 return;
202 }
203
204 ClassGetDeviceParameter(FdoExtension,
207 &idleInterval);
208
209 if ((idleInterval < CLASS_IDLE_INTERVAL_MIN) || (idleInterval > USHORT_MAX)) {
210 //
211 // If the interval is too low or too high, reset it to the default value.
212 //
213 idleInterval = CLASS_IDLE_INTERVAL;
214 }
215
216 fdoData->IdlePrioritySupported = TRUE;
218 KeInitializeTimer(&fdoData->IdleTimer);
221 fdoData->IdleTimerStarted = FALSE;
223 fdoData->IdleInterval = (USHORT)(idleInterval);
224 fdoData->IdleIoCount = 0;
225 fdoData->ActiveIoCount = 0;
226 fdoData->ActiveIdleIoCount = 0;
227
228 ClassGetDeviceParameter(FdoExtension,
231 &activeIdleIoMax);
232
233 activeIdleIoMax = max(activeIdleIoMax, 1);
234 activeIdleIoMax = min(activeIdleIoMax, USHORT_MAX);
235
236 fdoData->IdleActiveIoMax = (USHORT)activeIdleIoMax;
237
238 return;
239}
#define CLASSP_REG_IDLE_ACTIVE_MAX
Definition: classp.h:120
#define CLASSP_REG_IDLE_INTERVAL_NAME
Definition: classp.h:119
#define CLASS_IDLE_INTERVAL
Definition: classp.h:1199
#define CLASS_STARVATION_INTERVAL
Definition: classp.h:1200
#define CLASS_IDLE_INTERVAL_MIN
Definition: classp.h:1198
#define CLASSP_REG_IDLE_PRIORITY_SUPPORTED
Definition: classp.h:121
KDEFERRED_ROUTINE ClasspIdleTimerDpc
Definition: clntirp.c:42
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define USHORT_MAX
Definition: intsafe.h:147
BOOLEAN IdlePrioritySupported
Definition: classp.h:808
USHORT StarvationDuration
Definition: classp.h:915
#define max(a, b)
Definition: svc.c:63
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233

◆ ClasspInitializeRemoveTracking()

VOID ClasspInitializeRemoveTracking ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 500 of file lock.c.

503{
504 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
505
506 #if DBG
508
509 commonExtension->RemoveTrackingList = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(RTL_GENERIC_TABLE), CLASS_TAG_LOCK_TRACKING);
510
511 if (commonExtension->RemoveTrackingList != NULL)
512 {
517 NULL);
518 }
519 #else
520
522
523 commonExtension->RemoveTrackingSpinlock = (ULONG_PTR) -1;
524 commonExtension->RemoveTrackingList = NULL;
525 #endif
526}
RTL_GENERIC_FREE_ROUTINE RemoveTrackingFreeRoutine
Definition: classp.h:2404
RTL_GENERIC_ALLOCATE_ROUTINE RemoveTrackingAllocateRoutine
Definition: classp.h:2402
RTL_GENERIC_COMPARE_ROUTINE RemoveTrackingCompareRoutine
Definition: classp.h:2400
#define CLASS_TAG_LOCK_TRACKING
Definition: classpnp.h:88
VOID NTAPI RtlInitializeGenericTable(IN PRTL_GENERIC_TABLE Table, IN PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine, IN PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine, IN PRTL_GENERIC_FREE_ROUTINE FreeRoutine, IN PVOID TableContext)
Definition: generictable.c:100
KSPIN_LOCK RemoveTrackingSpinlock
Definition: classpnp.h:603

◆ ClasspInitializeTimer()

NTSTATUS ClasspInitializeTimer ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 3737 of file autorun.c.

3764{
3765 PCLASS_PRIVATE_FDO_DATA fdoData = NULL;
3766
3767 if (FdoExtension->CommonExtension.IsFdo) {
3768 fdoData = FdoExtension->PrivateFdoData;
3769 }
3770
3771 if (fdoData == NULL) {
3772 return STATUS_UNSUCCESSFUL;
3773 }
3774
3775 if (fdoData->TimerInitialized == FALSE) {
3776#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3777 NT_ASSERT(fdoData->TickTimer == NULL);
3778 //
3779 // The tick timer is a no-wake timer, which means it will not wake
3780 // the processor while the processor is in a low power state until
3781 // the timer's no-wake tolerance is reached.
3782 //
3784 if (fdoData->TickTimer == NULL) {
3786 }
3787#else
3788 KeInitializeDpc(&fdoData->TickTimerDpc, ClasspTimerTick, FdoExtension);
3789 KeInitializeTimer(&fdoData->TickTimer);
3790#endif
3791 fdoData->TimerInitialized = TRUE;
3792 }
3793
3794 return STATUS_SUCCESS;
3795}
KDEFERRED_ROUTINE ClasspTimerTick
Definition: autorun.c:118
EXT_CALLBACK ClasspTimerTickEx
Definition: autorun.c:121
#define EX_TIMER_NO_WAKE
Definition: exfuncs.h:956
NTKERNELAPI PEX_TIMER NTAPI ExAllocateTimer(_In_opt_ PEXT_CALLBACK Callback, _In_opt_ PVOID CallbackContext, _In_ ULONG Attributes)

Referenced by ClasspEnableTimer(), and ClassPnpStartDevice().

◆ ClasspIsIdleRequest()

FORCEINLINE BOOLEAN ClasspIsIdleRequest ( PIRP  Irp)

Definition at line 1268 of file classp.h.

1271{
1272#ifdef _MSC_VER
1273#pragma warning(suppress:4305) // truncation is not an issue for this use case
1274#endif
1275 return ((BOOLEAN)Irp->Tail.Overlay.DriverContext[1]);
1276}

Referenced by SubmitTransferPacket(), and TransferPktComplete().

◆ ClasspIsIdleRequestSupported()

FORCEINLINE BOOLEAN ClasspIsIdleRequestSupported ( PCLASS_PRIVATE_FDO_DATA  FdoData,
PIRP  Irp 
)

Definition at line 1236 of file classp.h.

1240{
1241#ifndef __REACTOS__
1243 return ((ioPriority <= IoPriorityLow) && (FdoData->IdlePrioritySupported == TRUE));
1244#else
1245 return (FdoData->IdlePrioritySupported == TRUE);
1246#endif
1247}
NTKRNLVISTAAPI IO_PRIORITY_HINT NTAPI IoGetIoPriorityHint(_In_ PIRP Irp)
Definition: io.c:123
@ IoPriorityLow
Definition: iotypes.h:1232
enum _IO_PRIORITY_HINT IO_PRIORITY_HINT

Referenced by ClassReadWrite().

◆ ClasspIsObsoletePortDriver()

FORCEINLINE BOOLEAN ClasspIsObsoletePortDriver ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 1335 of file classp.h.

1338{
1339 if ( (FdoExtension->MiniportDescriptor != NULL) &&
1340 (FdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetSCSIport) ) {
1341 return TRUE;
1342 }
1343
1344 return FALSE;
1345}
@ StoragePortCodeSetSCSIport
Definition: ntddstor.h:620

Referenced by ClasspAccessAlignmentProperty(), and ClassReadCapacity16().

◆ ClasspIsOffloadDataTransferCommand()

FORCEINLINE BOOLEAN ClasspIsOffloadDataTransferCommand ( _In_ PCDB  Cdb)

Definition at line 2087 of file classp.h.

2090{
2092
2093 return offloadCommand;
2094}
FORCEINLINE BOOLEAN ClasspIsReceiveTokenInformation(_In_ PCDB Cdb)
Definition: classp.h:2066
FORCEINLINE BOOLEAN ClasspIsTokenOperation(_In_ PCDB Cdb)
Definition: classp.h:2044
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN _In_ PCDB Cdb
Definition: scratch.h:159

Referenced by ClassInterpretSenseInfo(), and InterpretTransferPacketError().

◆ 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
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
@ BusTypeiScsi
Definition: ntddstor.h:447
@ BusTypeRAID
Definition: ntddstor.h:446
@ BusTypeFibre
Definition: ntddstor.h:444

Referenced by ClassPnpStartDevice().

◆ ClasspIsReceiveTokenInformation()

FORCEINLINE BOOLEAN ClasspIsReceiveTokenInformation ( _In_ PCDB  Cdb)

Definition at line 2066 of file classp.h.

2069{
2070 BOOLEAN receiveTokenInformation = FALSE;
2071
2072 if (Cdb) {
2073 ULONG opCode = Cdb->AsByte[0];
2074 ULONG serviceAction = Cdb->AsByte[1];
2075
2077
2078 receiveTokenInformation = TRUE;
2079 }
2080 }
2081
2082 return receiveTokenInformation;
2083}
#define SCSIOP_RECEIVE_ROD_TOKEN_INFORMATION
Definition: scsi.h:343
#define SERVICE_ACTION_RECEIVE_TOKEN_INFORMATION
Definition: scsi.h:447
UCHAR AsByte[16]
Definition: scsi.h:1988

Referenced by ClassInterpretSenseInfo(), ClasspIsOffloadDataTransferCommand(), and ClasspTransferPacketGetNumberOfRetriesDone().

◆ ClasspIsThinProvisioned()

FORCEINLINE BOOLEAN ClasspIsThinProvisioned ( _In_ PCLASS_FUNCTION_SUPPORT_INFO  SupportInfo)

Definition at line 1317 of file classp.h.

1320{
1321 //
1322 // We only support thinly provisioned devices that also support UNMAP.
1323 //
1324 if (SupportInfo->LBProvisioningData.ProvisioningType == PROVISIONING_TYPE_THIN &&
1325 SupportInfo->LBProvisioningData.LBPU == TRUE)
1326 {
1327 return TRUE;
1328 }
1329
1330 return FALSE;
1331}
#define PROVISIONING_TYPE_THIN
Definition: scsi.h:2590

Referenced by ClasspDeviceLBProvisioningProperty().

◆ ClasspIsThinProvisioningError()

BOOLEAN ClasspIsThinProvisioningError ( _In_ PSCSI_REQUEST_BLOCK  _Srb)

Definition at line 9127 of file utils.c.

9146{
9148 PVOID senseBuffer = SrbGetSenseInfoBuffer(Srb);
9149 if (senseBuffer) {
9150 UCHAR senseKey = 0;
9151 UCHAR addlSenseCode = 0;
9152 UCHAR addlSenseCodeQual = 0;
9153 BOOLEAN validSense = ScsiGetSenseKeyAndCodes(senseBuffer,
9156 &senseKey,
9157 &addlSenseCode,
9158 &addlSenseCodeQual);
9159
9160 return (validSense
9162 && (addlSenseCode == SCSI_ADSENSE_LB_PROVISIONING)
9163 && (addlSenseCodeQual == SCSI_SENSEQ_SOFT_THRESHOLD_REACHED));
9164 }
9165 }
9166 return FALSE;
9167}
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:387
#define SCSI_ADSENSE_LB_PROVISIONING
Definition: scsi.h:680
#define SCSI_SENSEQ_SOFT_THRESHOLD_REACHED
Definition: scsi.h:828
UCHAR senseKey
Definition: scsi.h:4019
#define SCSI_SENSE_OPTIONS_NONE
Definition: scsi.h:3838
BOOLEAN validSense
Definition: scsi.h:4018
FORCEINLINE PVOID SrbGetSenseInfoBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:619
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638

Referenced by RetryTransferPacket().

◆ ClasspIsTokenOperation()

FORCEINLINE BOOLEAN ClasspIsTokenOperation ( _In_ PCDB  Cdb)

Definition at line 2044 of file classp.h.

2047{
2048 BOOLEAN tokenOperation = FALSE;
2049
2050 if (Cdb) {
2051 ULONG opCode = Cdb->AsByte[0];
2052 ULONG serviceAction = Cdb->AsByte[1];
2053
2054 if ((opCode == SCSIOP_POPULATE_TOKEN && serviceAction == SERVICE_ACTION_POPULATE_TOKEN) ||
2055 (opCode == SCSIOP_WRITE_USING_TOKEN && serviceAction == SERVICE_ACTION_WRITE_USING_TOKEN)) {
2056
2057 tokenOperation = TRUE;
2058 }
2059 }
2060
2061 return tokenOperation;
2062}
#define SCSIOP_POPULATE_TOKEN
Definition: scsi.h:340
#define SCSIOP_WRITE_USING_TOKEN
Definition: scsi.h:341
#define SERVICE_ACTION_WRITE_USING_TOKEN
Definition: scsi.h:443

Referenced by ClasspIsOffloadDataTransferCommand(), and InterpretTransferPacketError().

◆ ClasspIsTokenOperationComplete()

FORCEINLINE BOOLEAN ClasspIsTokenOperationComplete ( _In_ ULONG  CurrentStatus)

Definition at line 2023 of file classp.h.

2026{
2027 BOOLEAN operationCompleted = FALSE;
2028
2029 switch (CurrentStatus) {
2033 case OPERATION_TERMINATED: {
2034
2035 operationCompleted = TRUE;
2036 }
2037 }
2038
2039 return operationCompleted;
2040}
@ 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

Referenced by ClasspReceivePopulateTokenInformationTransferPacketDone(), and ClasspReceiveWriteUsingTokenInformationTransferPacketDone().

◆ ClasspLogSystemEventWithDeviceNumber()

NTSTATUS ClasspLogSystemEventWithDeviceNumber ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ NTSTATUS  IoErrorCode 
)

Definition at line 5354 of file utils.c.

5374{
5377 PIO_ERROR_LOG_PACKET errorLogEntry = NULL;
5378 ULONG logEntrySize = sizeof(IO_ERROR_LOG_PACKET);
5379 PWCHAR stringIndex = NULL;
5380 LONG stringSize = 0;
5381
5382 //
5383 // We need to allocate enough space for one insertion string: a ULONG
5384 // representing the disk number in decimal, which means a max of 10 digits,
5385 // plus one for the NULL character.
5386 // Make sure we do not exceed the max error log size or the max size of a
5387 // UCHAR since the size gets truncated to a UCHAR when we pass it to
5388 // IoAllocateErrorLogEntry().
5389 //
5390 logEntrySize = sizeof(IO_ERROR_LOG_PACKET) + (11 * sizeof(WCHAR));
5391 logEntrySize = min(logEntrySize, ERROR_LOG_MAXIMUM_SIZE);
5392 logEntrySize = min(logEntrySize, MAXUCHAR);
5393
5394 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(DeviceObject, (UCHAR)logEntrySize);
5395 if (errorLogEntry) {
5396
5397 RtlZeroMemory(errorLogEntry, logEntrySize);
5398 errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
5399 errorLogEntry->ErrorCode = IoErrorCode;
5400
5401 stringIndex = (PWCHAR)((ULONG_PTR)errorLogEntry + sizeof(IO_ERROR_LOG_PACKET));
5402 stringSize = logEntrySize - sizeof(IO_ERROR_LOG_PACKET);
5403
5404 //
5405 // Add the disk number to the insertion strings.
5406 //
5407 status = RtlStringCbPrintfW(stringIndex, stringSize, L"%d", fdoExtension->DeviceNumber);
5408
5409 if (NT_SUCCESS(status)) {
5410 errorLogEntry->NumberOfStrings++;
5411 }
5412
5413 //
5414 // Write the error log packet to the system error logging thread.
5415 // It will be freed automatically.
5416 //
5417 IoWriteErrorLogEntry(errorLogEntry);
5418
5420 }
5421
5422 return status;
5423}
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:628
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:528
NTSTRSAFEVAPI RtlStringCbPrintfW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1173
uint16_t * PWCHAR
Definition: typedefs.h:56
#define MAXUCHAR
Definition: umtypes.h:117
#define ERROR_LOG_MAXIMUM_SIZE
Definition: iotypes.h:2042
struct _IO_ERROR_LOG_PACKET * PIO_ERROR_LOG_PACKET
struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by ClassDispatchPnp(), and ClassIoComplete().

◆ ClasspLowerLayerNotSupport()

◆ ClasspMarkIrpAsIdle()

FORCEINLINE VOID ClasspMarkIrpAsIdle ( PIRP  Irp,
BOOLEAN  Idle 
)

Definition at line 1251 of file classp.h.

1255{
1256#ifndef __REACTOS__
1257// truncation is not an issue for this use case
1258// nonstandard extension used is not an issue for this use case
1259#pragma warning(suppress:4305; suppress:4213)
1260 ((BOOLEAN)Irp->Tail.Overlay.DriverContext[1]) = Idle;
1261#else
1262 ((PULONG_PTR)Irp->Tail.Overlay.DriverContext)[1] = Idle;
1263#endif
1264}
@ Idle
Definition: ntdd8042.h:62
#define BOOLEAN
Definition: pedump.c:73
uint32_t * PULONG_PTR
Definition: typedefs.h:65

Referenced by ClassReadWrite().

◆ ClasspMcnControl()

NTSTATUS ClasspMcnControl ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN PIRP  Irp,
IN PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 3276 of file autorun.c.

3281{
3282 PCOMMON_DEVICE_EXTENSION commonExtension =
3284
3286 PPREVENT_MEDIA_REMOVAL request = Irp->AssociatedIrp.SystemBuffer;
3287
3288 PFILE_OBJECT fileObject = irpStack->FileObject;
3289 PFILE_OBJECT_EXTENSION fsContext = NULL;
3290
3292
3293 PAGED_CODE();
3294
3295 //
3296 // Check to make sure we have a file object extension to keep track of this
3297 // request. If not we'll fail it before synchronizing.
3298 //
3299
3300 TRY {
3301
3302 if(fileObject != NULL) {
3303 fsContext = ClassGetFsContext(commonExtension, fileObject);
3304 }else if(Irp->RequestorMode == KernelMode) { // && fileObject == NULL
3305 fsContext = &FdoExtension->KernelModeMcnContext;
3306 }
3307
3308 if (fsContext == NULL) {
3309
3310 //
3311 // This handle isn't setup correctly. We can't let the
3312 // operation go.
3313 //
3314
3316 LEAVE;
3317 }
3318
3319 if(request->PreventMediaRemoval) {
3320
3321 //
3322 // This is a lock command. Reissue the command in case bus or
3323 // device was reset and the lock was cleared.
3324 //
3325
3326 ClassDisableMediaChangeDetection(FdoExtension);
3327 InterlockedIncrement((volatile LONG *)&(fsContext->McnDisableCount));
3328
3329 } else {
3330
3331 if(fsContext->McnDisableCount == 0) {
3333 LEAVE;
3334 }
3335
3336 InterlockedDecrement((volatile LONG *)&(fsContext->McnDisableCount));
3337 ClassEnableMediaChangeDetection(FdoExtension);
3338 }
3339
3340 } FINALLY {
3341
3342 Irp->IoStatus.Status = status;
3343
3344 FREE_POOL(Srb);
3345
3346 ClassReleaseRemoveLock(FdoExtension->DeviceObject, Irp);
3347 ClassCompleteRequest(FdoExtension->DeviceObject,
3348 Irp,
3350 }
3351 return status;
3352} // end ClasspMcnControl(
#define FINALLY
Definition: classpnp.h:116
#define LEAVE
Definition: classpnp.h:115
Definition: tftpd.h:86
#define TRY(sps, bps)

Referenced by ClassDeviceControl().

◆ ClasspMediaChangeCompletion()

NTSTATUS ClasspMediaChangeCompletion ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp,
PVOID  Context 
)

◆ 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

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}
_In_ size_t _In_ UCHAR PageMode
Definition: cdrom.h:1326
_In_ ULONG _In_ UCHAR _In_ UCHAR PageControl
Definition: cdrom.h:1319
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().

◆ ClasspMyStringMatches()

BOOLEAN ClasspMyStringMatches ( _In_opt_z_ PCHAR  StringToMatch,
_In_z_ PCHAR  TargetString 
)

Definition at line 51 of file utils.c.

52{
53 ULONG length; // strlen returns an int, not size_t (!)
54 PAGED_CODE();
56 // if no match requested, return TRUE
57 if (StringToMatch == NULL) {
58 return TRUE;
59 }
60 // cache the string length for efficiency
61 length = (ULONG)strlen(StringToMatch);
62 // ZERO-length strings may only match zero-length strings
63 if (length == 0) {
64 return (strlen(TargetString) == 0);
65 }
66 // strncmp returns zero if the strings match
67 return (strncmp(StringToMatch, TargetString, length) == 0);
68}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
_In_z_ PCHAR TargetString
Definition: cdrom.h:954

◆ 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()
NTSTATUS ClassRetrieveDeviceRelations(IN PDEVICE_OBJECT Fdo, IN DEVICE_RELATION_TYPE RelationType, OUT PDEVICE_RELATIONS *DeviceRelations)
Definition: class.c:10005
PCLASS_ENUM_DEVICE ClassEnumerateDevice
Definition: classpnp.h:541
@ BusRelations
Definition: iotypes.h:2152

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
#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
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
VOID ClasspEnableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3857
VOID ClasspDeleteTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3798
VOID ClasspDisableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3956
struct _CLASS_FUNCTION_SUPPORT_INFO * PCLASS_FUNCTION_SUPPORT_INFO
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
GLdouble GLdouble t
Definition: gl.h:2047
#define FILE_PORTABLE_DEVICE
Definition: winternl.h:1855
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
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:47
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
CLASS_DEV_INFO FdoData
Definition: classpnp.h:538
CLASS_DEV_INFO PdoData
Definition: classpnp.h:539
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
#define IRP_MN_START_DEVICE
#define WMIREG_ACTION_REGISTER

Referenced by ClassDispatchPnp().

◆ ClasspPagingNotificationCompletion()

NTSTATUS ClasspPagingNotificationCompletion ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PDEVICE_OBJECT  RealDeviceObject 
)

◆ ClasspPerfIncrementErrorCount()

VOID ClasspPerfIncrementErrorCount ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 432 of file utils.c.

435{
436 PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
437 KIRQL oldIrql;
438 ULONG errors;
439
440 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
441
442 fdoData->Perf.SuccessfulIO = 0; // implicit interlock
443 errors = InterlockedIncrement((volatile LONG *)&FdoExtension->ErrorCount);
444
445 if (!fdoData->DisableThrottling) {
446
447 if (errors >= CLASS_ERROR_LEVEL_1) {
448
449 //
450 // If the error count has exceeded the error limit, then disable
451 // any tagged queuing, multiple requests per lu queueing
452 // and sychronous data transfers.
453 //
454 // Clearing the no queue freeze flag prevents the port driver
455 // from sending multiple requests per logical unit.
456 //
457
460
462
463 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClasspPerfIncrementErrorCount: "
464 "Too many errors; disabling tagged queuing and "
465 "synchronous data tranfers.\n"));
466
467 }
468
469 if (errors >= CLASS_ERROR_LEVEL_2) {
470
471 //
472 // If a second threshold is reached, disable disconnects.
473 //
474
476 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClasspPerfIncrementErrorCount: "
477 "Too many errors; disabling disconnects.\n"));
478 }
479 }
480
481 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
482 return;
483}
#define CLASS_ERROR_LEVEL_2
Definition: cdromp.h:131
#define CLASS_ERROR_LEVEL_1
Definition: cdromp.h:130
#define SRB_FLAGS_DISABLE_DISCONNECT
Definition: srb.h:396
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
struct _CLASS_PRIVATE_FDO_DATA::@1065 Perf
KSPIN_LOCK SpinLock
Definition: classp.h:795
BOOLEAN DisableThrottling
Definition: classp.h:981

Referenced by ClassInterpretSenseInfo().

◆ ClasspPerfIncrementSuccessfulIo()

VOID ClasspPerfIncrementSuccessfulIo ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 486 of file utils.c.

489{
490 PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
491 KIRQL oldIrql;
492 ULONG errors;
493 ULONG succeeded = 0;
494
495 //
496 // don't take a hit from the interlocked op unless we're in
497 // a degraded state and we've got a threshold to hit.
498 //
499
500 if (FdoExtension->ErrorCount == 0) {
501 return;
502 }
503
504 if (fdoData->Perf.ReEnableThreshhold == 0) {
505 return;
506 }
507
508 succeeded = InterlockedIncrement((volatile LONG *)&fdoData->Perf.SuccessfulIO);
509 if (succeeded < fdoData->Perf.ReEnableThreshhold) {
510 return;
511 }
512
513 //
514 // if we hit the threshold, grab the spinlock and verify we've
515 // actually done so. this allows us to ignore the spinlock 99%
516 // of the time.
517 //
518
519 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
520
521 //
522 // re-read the value, so we don't run this multiple times
523 // for a single threshhold being hit. this keeps errorcount
524 // somewhat useful.
525 //
526
527 succeeded = fdoData->Perf.SuccessfulIO;
528
529 if ((FdoExtension->ErrorCount != 0) &&
530 (fdoData->Perf.ReEnableThreshhold <= succeeded)
531 ) {
532
533 fdoData->Perf.SuccessfulIO = 0; // implicit interlock
534
535 NT_ASSERT(FdoExtension->ErrorCount > 0);
536 errors = InterlockedDecrement((volatile LONG *)&FdoExtension->ErrorCount);
537
538 //
539 // note: do in reverse order of the sets "just in case"
540 //
541
542 if (errors < CLASS_ERROR_LEVEL_2) {
543 if (errors == CLASS_ERROR_LEVEL_2 - 1) {
544 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClasspPerfIncrementSuccessfulIo: "
545 "Error level 2 no longer required.\n"));
546 }
547 if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
549 CLEAR_FLAG(FdoExtension->SrbFlags,
551 }
552 }
553
554 if (errors < CLASS_ERROR_LEVEL_1) {
555 if (errors == CLASS_ERROR_LEVEL_1 - 1) {
556 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClasspPerfIncrementSuccessfulIo: "
557 "Error level 1 no longer required.\n"));
558 }
559 if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
561 CLEAR_FLAG(FdoExtension->SrbFlags,
563 }
564 if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
566 SET_FLAG(FdoExtension->SrbFlags,
568 }
569 if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
571 SET_FLAG(FdoExtension->SrbFlags,
573 }
574 }
575 } // end of threshhold definitely being hit for first time
576
577 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
578 return;
579}

Referenced by ClassIoComplete(), and TransferPktComplete().

◆ ClasspPersistentReserve()

NTSTATUS ClasspPersistentReserve ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 6211 of file utils.c.

6216{
6218 PCDB cdb = NULL;
6219 PPERSISTENT_RESERVE_COMMAND prCommand = Irp->AssociatedIrp.SystemBuffer;
6220 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
6221
6223
6224 ULONG dataBufLen;
6225 ULONG controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
6226
6227 BOOLEAN writeToDevice;
6228
6229 //
6230 // Check common input buffer parameters.
6231 //
6232
6233 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
6235 prCommand->Size < sizeof(PERSISTENT_RESERVE_COMMAND)) {
6236
6238 Irp->IoStatus.Status = status;
6239 Irp->IoStatus.Information = 0;
6240
6241 FREE_POOL(Srb);
6242
6245 goto ClasspPersistentReserve_Exit;
6246 }
6247
6248 //
6249 // Check buffer alignment. Only an issue if another kernel mode component
6250 // (not the I/O manager) allocates the buffer.
6251 //
6252
6253 if ((ULONG_PTR)prCommand & fdoExtension->AdapterDescriptor->AlignmentMask) {
6254
6256 Irp->IoStatus.Status = status;
6257 Irp->IoStatus.Information = 0;
6258
6259 FREE_POOL(Srb);
6260
6263 goto ClasspPersistentReserve_Exit;
6264 }
6265
6266 //
6267 // Check additional parameters.
6268 //
6269
6271
6272 SrbSetCdbLength(Srb, 10);
6273 cdb = SrbGetCdb(Srb);
6274
6275 if (controlCode == IOCTL_STORAGE_PERSISTENT_RESERVE_IN) {
6276
6277 //
6278 // Check output buffer for PR In.
6279 //
6280
6281 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
6282 prCommand->PR_IN.AllocationLength) {
6283
6285 }
6286
6287 switch (prCommand->PR_IN.ServiceAction) {
6288
6290
6291 if (prCommand->PR_IN.AllocationLength < sizeof(PRI_REGISTRATION_LIST)) {
6292
6294 }
6295
6296 break;
6297
6299
6300 if (prCommand->PR_IN.AllocationLength < sizeof(PRI_RESERVATION_LIST)) {
6301
6303 }
6304
6305 break;
6306
6307 default:
6308
6310 break;
6311 }
6312
6313 if (!NT_SUCCESS(status)) {
6314
6315 Irp->IoStatus.Status = status;
6316 Irp->IoStatus.Information = 0;
6317
6318 FREE_POOL(Srb);
6319
6322 goto ClasspPersistentReserve_Exit;
6323 }
6324
6325 //
6326 // Fill in the CDB.
6327 //
6328
6330 cdb->PERSISTENT_RESERVE_IN.ServiceAction = prCommand->PR_IN.ServiceAction;
6331
6332 REVERSE_BYTES_SHORT(&(cdb->PERSISTENT_RESERVE_IN.AllocationLength),
6333 &(prCommand->PR_IN.AllocationLength));
6334
6335 dataBufLen = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
6336 writeToDevice = FALSE;
6337
6338
6339 } else {
6340
6341 //
6342 // Verify ServiceAction, Scope, and Type
6343 //
6344
6345 switch (prCommand->PR_OUT.ServiceAction) {
6346
6350
6351 // Scope and type ignored.
6352
6353 break;
6354
6359
6360 if (!ValidPersistentReserveScope(prCommand->PR_OUT.Scope) ||
6361 !ValidPersistentReserveType(prCommand->PR_OUT.Type)) {
6362
6364
6365 }
6366
6367 break;
6368
6369 default:
6370
6372
6373 break;
6374 }
6375
6376 //
6377 // Check input buffer for PR Out.
6378 // Caller must include the PR parameter list.
6379 //
6380
6381 if (NT_SUCCESS(status)) {
6382
6383 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
6385 sizeof(PRO_PARAMETER_LIST)) ||
6386 prCommand->Size <
6387 irpStack->Parameters.DeviceIoControl.InputBufferLength) {
6388
6390
6391 }
6392 }
6393
6394
6395 if (!NT_SUCCESS(status)) {
6396
6397 Irp->IoStatus.Status = status;
6398 Irp->IoStatus.Information = 0;
6399
6400 FREE_POOL(Srb);
6401
6404 goto ClasspPersistentReserve_Exit;
6405 }
6406
6407 //
6408 // Fill in the CDB.
6409 //
6410
6412 cdb->PERSISTENT_RESERVE_OUT.ServiceAction = prCommand->PR_OUT.ServiceAction;
6413 cdb->PERSISTENT_RESERVE_OUT.Scope = prCommand->PR_OUT.Scope;
6414 cdb->PERSISTENT_RESERVE_OUT.Type = prCommand->PR_OUT.Type;
6415
6416 cdb->PERSISTENT_RESERVE_OUT.ParameterListLength[1] = (UCHAR)sizeof(PRO_PARAMETER_LIST);
6417
6418 //
6419 // Move the parameter list to the beginning of the data buffer (so it is aligned
6420 // correctly and that the MDL describes it correctly).
6421 //
6422
6423 RtlMoveMemory(prCommand,
6424 prCommand->PR_OUT.ParameterList,
6425 sizeof(PRO_PARAMETER_LIST));
6426
6427 dataBufLen = sizeof(PRO_PARAMETER_LIST);
6428 writeToDevice = TRUE;
6429 }
6430
6431 //
6432 // Fill in the SRB
6433 //
6434
6435 //
6436 // Set timeout value.
6437 //
6438
6439 SrbSetTimeOutValue(Srb, fdoExtension->TimeOutValue);
6440
6441 //
6442 // Send as a tagged request.
6443 //
6444
6447
6449 Srb,
6450 Irp,
6451 prCommand,
6452 dataBufLen,
6453 writeToDevice);
6454
6455ClasspPersistentReserve_Exit:
6456
6457 return status;
6458
6459}
static BOOLEAN ValidPersistentReserveScope(UCHAR Scope)
Definition: utils.c:6152
static BOOLEAN ValidPersistentReserveType(UCHAR Type)
Definition: utils.c:6171
#define IOCTL_STORAGE_PERSISTENT_RESERVE_IN
Definition: ntddstor.h:169
#define RESERVATION_ACTION_REGISTER
Definition: scsi.h:579
#define RESERVATION_ACTION_RESERVE
Definition: scsi.h:580
#define RESERVATION_ACTION_RELEASE
Definition: scsi.h:581
#define RESERVATION_ACTION_REGISTER_IGNORE_EXISTING
Definition: scsi.h:585
#define RESERVATION_ACTION_READ_KEYS
Definition: scsi.h:576
#define RESERVATION_ACTION_PREEMPT_ABORT
Definition: scsi.h:584
#define RESERVATION_ACTION_CLEAR
Definition: scsi.h:582
#define SCSIOP_PERSISTENT_RESERVE_IN
Definition: scsi.h:329
#define RESERVATION_ACTION_PREEMPT
Definition: scsi.h:583
struct _PRO_PARAMETER_LIST PRO_PARAMETER_LIST
#define SCSIOP_PERSISTENT_RESERVE_OUT
Definition: scsi.h:330
#define RESERVATION_ACTION_READ_RESERVATIONS
Definition: scsi.h:577
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
struct _CDB::_PERSISTENT_RESERVE_OUT PERSISTENT_RESERVE_OUT
struct _CDB::_PERSISTENT_RESERVE_IN PERSISTENT_RESERVE_IN

Referenced by ClassDeviceControl().

◆ 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_().

◆ ClasspPriorityHint()

NTSTATUS ClasspPriorityHint ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 6480 of file utils.c.

6484{
6485 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
6486 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
6487 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
6488 PSTORAGE_PRIORITY_HINT_SUPPORT priSupport = Irp->AssociatedIrp.SystemBuffer;
6491
6492 Irp->IoStatus.Information = 0;
6493
6494 //
6495 // Check whether this device supports idle priority.
6496 //
6497 if (!fdoData->IdlePrioritySupported) {
6499 goto PriorityHintExit;
6500 }
6501
6502 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
6504
6506 goto PriorityHintExit;
6507 }
6508
6509 RtlZeroMemory(priSupport, sizeof(STORAGE_PRIORITY_HINT_SUPPORT));
6510
6511 status = ClassForwardIrpSynchronous(commonExtension, Irp);
6512 if (!NT_SUCCESS(status)) {
6513 //
6514 // If I/O priority is not supported by lower drivers, just set the
6515 // priorities supported by class driver.
6516 //
6517 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_IOCTL, "ClasspPriorityHint: I/O priority not supported by port driver.\n"));
6518 priSupport->SupportFlags = 0;
6520 }
6521
6522 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_IOCTL, "ClasspPriorityHint: I/O priorities supported by port driver: %X\n", priSupport->SupportFlags));
6523
6524 priSupport->SupportFlags |= (1 << IoPriorityVeryLow) |
6525 (1 << IoPriorityLow) |
6526 (1 << IoPriorityNormal) ;
6527
6528 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_IOCTL, "ClasspPriorityHint: I/O priorities supported: %X\n", priSupport->SupportFlags));
6529 Irp->IoStatus.Information = sizeof(STORAGE_PRIORITY_HINT_SUPPORT);
6530
6531PriorityHintExit:
6532
6533 Irp->IoStatus.Status = status;
6536 return status;
6537}
struct _STORAGE_PRIORITY_HINT_SUPPORT STORAGE_PRIORITY_HINT_SUPPORT
#define TRACE_LEVEL_FATAL
Definition: storswtr.h:26
@ IoPriorityNormal
Definition: iotypes.h:1233
@ IoPriorityVeryLow
Definition: iotypes.h:1231

Referenced by ClassDeviceControl().

◆ ClasspQueueLogIOEventWithContextWorker()

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 at line 6010 of file utils.c.

6041{
6042 PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)(DeviceObject->DeviceExtension);
6044 POPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER ioLogMessageContextHeader = NULL;
6045 PVOID senseData = NULL;
6046 PIO_WORKITEM workItem = NULL;
6047 ULONG senseBufferSize = 0;
6048 LARGE_INTEGER lba = {0};
6049
6050 if (!commonExtension->IsFdo) {
6051 return;
6052 }
6053
6054 if (!Cdb) {
6055 return;
6056 }
6057
6058 workItem = IoAllocateWorkItem(DeviceObject);
6059 if (!workItem) {
6060 goto __ClasspQueueLogIOEventWithContextWorker_ExitWithMessage;
6061 }
6062
6063 if (SenseBufferSize) {
6064 senseData = ExAllocatePoolWithTag(NonPagedPoolNx, SenseBufferSize, CLASSPNP_POOL_TAG_LOG_MESSAGE);
6065 if (senseData) {
6066 senseBufferSize = SenseBufferSize;
6067 }
6068 }
6069
6070 if (CdbLength == 16) {
6071 REVERSE_BYTES_QUAD(&lba, Cdb->CDB16.LogicalBlock);
6072 } else {
6073 ((PFOUR_BYTE)&lba.LowPart)->Byte3 = Cdb->CDB10.LogicalBlockByte0;
6074 ((PFOUR_BYTE)&lba.LowPart)->Byte2 = Cdb->CDB10.LogicalBlockByte1;
6075 ((PFOUR_BYTE)&lba.LowPart)->Byte1 = Cdb->CDB10.LogicalBlockByte2;
6076 ((PFOUR_BYTE)&lba.LowPart)->Byte0 = Cdb->CDB10.LogicalBlockByte3;
6077 }
6078
6079 //
6080 // Calculate the amount of buffer required for the insertion strings.
6081 //
6082 switch (ErrorCode) {
6085
6086 PIO_RETRIED_LOG_MESSAGE_CONTEXT ioLogMessageContext = NULL;
6087
6088 ioLogMessageContext = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(IO_RETRIED_LOG_MESSAGE_CONTEXT), CLASSPNP_POOL_TAG_LOG_MESSAGE);
6089 if (!ioLogMessageContext) {
6090 goto __ClasspQueueLogIOEventWithContextWorker_ExitWithMessage;
6091 }
6092
6093 ioLogMessageContext->Lba.QuadPart = lba.QuadPart;
6094 ioLogMessageContext->DeviceNumber = fdoExtension->DeviceNumber;
6095
6096 ioLogMessageContextHeader = (POPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER)ioLogMessageContext;
6097
6098 break;
6099 }
6100
6101 default: goto __ClasspQueueLogIOEventWithContextWorker_Exit;
6102 }
6103
6104 TracePrint((TRACE_LEVEL_INFORMATION,
6105 TRACE_FLAG_GENERAL,
6106 "ClasspQueueLogIOEventWithContextWorker: DO (%p), Pkt (%p), Queueing IO retried event log message work item.\n",
6108 Pkt));
6109
6110 ioLogMessageContextHeader->WorkItem = workItem;
6111 if (senseData) {
6112 RtlCopyMemory(senseData, SenseData, SenseBufferSize);
6113 }
6114 ioLogMessageContextHeader->SenseData = senseData;
6115 ioLogMessageContextHeader->SenseDataSize = senseBufferSize;
6116 ioLogMessageContextHeader->SrbStatus = SrbStatus;
6117 ioLogMessageContextHeader->ScsiStatus = ScsiStatus;
6118 ioLogMessageContextHeader->OpCode = Cdb->CDB6GENERIC.OperationCode;
6119 ioLogMessageContextHeader->Reserved = 0;
6120 ioLogMessageContextHeader->ErrorCode = ErrorCode;
6121
6123
6124 //
6125 // Queue a work item to write the system event log.
6126 //
6127 IoQueueWorkItem(workItem, ClasspLogIOEventWithContext, DelayedWorkQueue, ioLogMessageContextHeader);
6128
6129 return;
6130
6131__ClasspQueueLogIOEventWithContextWorker_ExitWithMessage:
6132
6133 TracePrint((TRACE_LEVEL_ERROR,
6134 TRACE_FLAG_GENERAL,
6135 "ClasspQueueLogIOEventWithContextWorker: DO (%p), Failed to allocate memory for the log message.\n",
6136 DeviceObject));
6137
6138__ClasspQueueLogIOEventWithContextWorker_Exit:
6139 if (senseData) {
6140 ExFreePool(senseData);
6141 }
6142 if (workItem) {
6143 IoFreeWorkItem(workItem);
6144 }
6145 if (ioLogMessageContextHeader) {
6146 ExFreePool(ioLogMessageContextHeader);
6147 }
6148}
#define CLASSPNP_POOL_TAG_LOG_MESSAGE
Definition: classp.h:196
struct _OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER * POPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER
_In_ PTRANSFER_PACKET Pkt
Definition: classp.h:1754
IO_WORKITEM_ROUTINE ClasspLogIOEventWithContext
Definition: classp.h:1905
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
#define IO_WARNING_IO_OPERATION_RETRIED
Definition: ntiologc.h:114
#define IO_ERROR_IO_HARDWARE_ERROR
Definition: ntiologc.h:115
#define lba
struct _CDB::_CDB6GENERIC CDB6GENERIC
struct _CDB::_CDB16 CDB16
@ DelayedWorkQueue
Definition: extypes.h:190

Referenced by ClassInterpretSenseInfo().

◆ 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}
FORCEINLINE UCHAR SrbGetCdbLength(_In_ PVOID Srb)
Definition: srbhelper.h:1074
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
#define SRB_STATUS_ERROR
Definition: srb.h:344
struct BLOCK_DEVICE_TOKEN_DESCRIPTOR * PBLOCK_DEVICE_TOKEN_DESCRIPTOR
struct RECEIVE_TOKEN_INFORMATION_HEADER * PRECEIVE_TOKEN_INFORMATION_HEADER
struct RECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER * PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER
@ TRANSFER_COUNT_UNITS_NUMBER_BLOCKS
Definition: scsi.h:3668
FORCEINLINE VOID SrbSetScsiStatus(_In_ PVOID Srb, _In_ UCHAR ScsiStatus)
Definition: srbhelper.h:1056
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 STATUS_INVALID_TOKEN
Definition: ntstatus.h:987

◆ 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}
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 RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
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
UNICODE_STRING MountedDeviceInterfaceName
Definition: classpnp.h:628
PDEVICE_OBJECT LowerPdo
Definition: classpnp.h:875

◆ ClasspReleaseQueue()

VOID ClasspReleaseQueue ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  ReleaseQueueIrp 
)

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
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
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
#define KeQueryTickCount(CurrentCount)
Definition: ke.h:43
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().

◆ 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_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#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 RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#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
uint16_t * PWSTR
Definition: typedefs.h:56
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2786
#define RTL_QUERY_REGISTRY_TYPECHECK
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT

Referenced by ClassPnpStartDevice().

◆ ClasspSrbSetOriginalIrp()

FORCEINLINE VOID ClasspSrbSetOriginalIrp ( _In_ PSTORAGE_REQUEST_BLOCK_HEADER  Srb,
_In_ PIRP  Irp 
)

Definition at line 2530 of file classp.h.

2534{
2535 if (Srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK)
2536 {
2537 ((PSTORAGE_REQUEST_BLOCK)Srb)->MiniportContext = (PVOID)Irp;
2538 }
2539 else
2540 {
2541 ((PSCSI_REQUEST_BLOCK)Srb)->SrbExtension = (PVOID)Irp;
2542 }
2543}
_Inout_ PIRP _Inout_ PSCSI_REQUEST_BLOCK Srb
Definition: classp.h:1950

Referenced by SubmitTransferPacket().

◆ ClasspStorageEventNotification()

_IRQL_requires_same_ NTSTATUS ClasspStorageEventNotification ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp 
)

Definition at line 7826 of file utils.c.

7849{
7850 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
7851 PIO_STACK_LOCATION irpStack;
7852 PSTORAGE_EVENT_NOTIFICATION storageEvents;
7854
7855 TracePrint((TRACE_LEVEL_VERBOSE,
7856 TRACE_FLAG_IOCTL,
7857 "ClasspStorageEventNotification (%p): Entering function Irp %p.\n",
7859 Irp));
7860
7861 fdoExtension = DeviceObject->DeviceExtension;
7862 irpStack = IoGetCurrentIrpStackLocation (Irp);
7863 storageEvents = Irp->AssociatedIrp.SystemBuffer;
7865
7866 if (!storageEvents) {
7867
7868 TracePrint((TRACE_LEVEL_ERROR,
7869 TRACE_FLAG_IOCTL,
7870 "ClasspStorageEventNotification (%p): NULL storage events passed in.\n",
7871 DeviceObject));
7872
7874 goto __ClasspStorageEventNotification_Exit;
7875 }
7876
7877 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_EVENT_NOTIFICATION)) {
7878
7879 TracePrint((TRACE_LEVEL_ERROR,
7880 TRACE_FLAG_IOCTL,
7881 "ClasspStorageEventNotification (%p): Input buffer size (%u) too small.\n",
7883 irpStack->Parameters.DeviceIoControl.InputBufferLength));
7884
7886 goto __ClasspStorageEventNotification_Exit;
7887 }
7888
7889 if ((storageEvents->Version != STORAGE_EVENT_NOTIFICATION_VERSION_V1) ||
7890 (storageEvents->Size != sizeof(STORAGE_EVENT_NOTIFICATION))) {
7891
7892 TracePrint((TRACE_LEVEL_ERROR,
7893 TRACE_FLAG_IOCTL,
7894 "ClasspStorageEventNotification (%p): Invalid version/size [version %u, size %u].\n",
7896 storageEvents->Version,
7897 storageEvents->Size));
7898
7900 goto __ClasspStorageEventNotification_Exit;
7901 }
7902
7903 //
7904 // Handle a media status event.
7905 //
7906 if (storageEvents->Events & STORAGE_EVENT_MEDIA_STATUS) {
7907
7908 //
7909 // Only initiate operation if underlying port driver supports asynchronous notification
7910 // and this is the FDO.
7911 //
7912 if ((fdoExtension->CommonExtension.IsFdo == TRUE) &&
7913 (fdoExtension->FunctionSupportInfo->AsynchronousNotificationSupported)) {
7914 ClassCheckMediaState(fdoExtension);
7915 } else {
7917 }
7918
7919 }
7920
7921__ClasspStorageEventNotification_Exit:
7922 TracePrint((TRACE_LEVEL_VERBOSE,
7923 TRACE_FLAG_IOCTL,
7924 "ClasspStorageEventNotification (%p): Exiting function Irp %p with status %x.\n",
7926 Irp,
7927 status));
7928
7929 Irp->IoStatus.Information = 0;
7930 Irp->IoStatus.Status = status;
7933
7934 return status;
7935}
VOID NTAPI ClassCheckMediaState(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:1752
#define STORAGE_EVENT_NOTIFICATION_VERSION_V1
Definition: ntddstor.h:979
#define STORAGE_EVENT_MEDIA_STATUS
Definition: ntddstor.h:981

Referenced by ClassDeviceControl().

◆ ClasspSupportsUnmap()

FORCEINLINE BOOLEAN ClasspSupportsUnmap ( _In_ PCLASS_FUNCTION_SUPPORT_INFO  SupportInfo)

Definition at line 1308 of file classp.h.

1311{
1312 return SupportInfo->LBProvisioningData.LBPU;
1313}

Referenced by ClasspDeviceTrimProcess(), and ClasspDeviceTrimProperty().

◆ ClasspTimeDiffToMs()

FORCEINLINE ULONGLONG ClasspTimeDiffToMs ( ULONGLONG  TimeDiff)

Definition at line 1297 of file classp.h.

1300{
1301 TimeDiff /= (10 * 1000);
1302
1303 return TimeDiff;
1304}

Referenced by ClasspGetIdleTime(), and ClasspIdleTimerDpc().

◆ ClasspTransferPacketGetCdb()

FORCEINLINE PCDB ClasspTransferPacketGetCdb ( _In_ PTRANSFER_PACKET  Pkt)

Definition at line 2445 of file classp.h.

2448{
2449 return SrbGetCdb(Pkt->Srb);
2450}

Referenced by InterpretTransferPacketError().

◆ ClasspTransferPacketGetNumberOfRetriesDone()

FORCEINLINE BOOLEAN ClasspTransferPacketGetNumberOfRetriesDone ( _In_ PTRANSFER_PACKET  Pkt,
_In_ PCDB  Cdb,
_Out_ PULONG  TimesAlreadyRetried 
)

Definition at line 2459 of file classp.h.

2464{
2466 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
2467
2468 if (Cdb->MEDIA_REMOVAL.OperationCode == SCSIOP_MEDIUM_REMOVAL)
2469 {
2470 *TimesAlreadyRetried = NUM_LOCKMEDIAREMOVAL_RETRIES - Pkt->NumRetries;
2471 }
2472 else if ((Cdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE) ||
2473 (Cdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE10))
2474 {
2475 *TimesAlreadyRetried = NUM_MODESENSE_RETRIES - Pkt->NumRetries;
2476 }
2477 else if ((Cdb->CDB10.OperationCode == SCSIOP_READ_CAPACITY) ||
2478 (Cdb->CDB16.OperationCode == SCSIOP_READ_CAPACITY16))
2479 {
2480 *TimesAlreadyRetried = NUM_DRIVECAPACITY_RETRIES - Pkt->NumRetries;
2481 }
2482 else if (IS_SCSIOP_READWRITE(Cdb->CDB10.OperationCode))
2483 {
2484 *TimesAlreadyRetried = fdoData->MaxNumberOfIoRetries - Pkt->NumRetries;
2485 }
2486 else if (Cdb->TOKEN_OPERATION.OperationCode == SCSIOP_POPULATE_TOKEN &&
2488 {
2489 *TimesAlreadyRetried = NUM_POPULATE_TOKEN_RETRIES - Pkt->NumRetries;
2490 }
2491 else if (Cdb->TOKEN_OPERATION.OperationCode == SCSIOP_WRITE_USING_TOKEN &&
2493 {
2494 *TimesAlreadyRetried = NUM_WRITE_USING_TOKEN_RETRIES - Pkt->NumRetries;
2495 }
2497 {
2498 *TimesAlreadyRetried = NUM_RECEIVE_TOKEN_INFORMATION_RETRIES - Pkt->NumRetries;
2499 }
2500
2501 else
2502 {
2503 *TimesAlreadyRetried = 0;
2504 return FALSE;
2505 }
2506
2507
2508 return TRUE;
2509}
#define IS_SCSIOP_READWRITE(opCode)
Definition: cdrom.h:803
#define SCSIOP_MODE_SENSE10
Definition: cdrw_hw.h:946
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define NUM_WRITE_USING_TOKEN_RETRIES
Definition: classp.h:205
#define NUM_DRIVECAPACITY_RETRIES
Definition: classp.h:161
#define NUM_LOCKMEDIAREMOVAL_RETRIES
Definition: classp.h:158
#define NUM_RECEIVE_TOKEN_INFORMATION_RETRIES
Definition: classp.h:206
#define NUM_MODESENSE_RETRIES
Definition: classp.h:159
#define NUM_POPULATE_TOKEN_RETRIES
Definition: classp.h:204
#define SCSIOP_READ_CAPACITY16
Definition: scsi.h:364
UCHAR MaxNumberOfIoRetries
Definition: classp.h:976
UCHAR NumRetries
Definition: classp.h:516
PDEVICE_OBJECT Fdo
Definition: classp.h:503
struct _CDB::_TOKEN_OPERATION TOKEN_OPERATION
struct _CDB::_MODE_SENSE MODE_SENSE

Referenced by InterpretTransferPacketError().

◆ ClasspTransferPacketGetSenseInfoBuffer()

FORCEINLINE PVOID ClasspTransferPacketGetSenseInfoBuffer ( _In_ PTRANSFER_PACKET  Pkt)

Definition at line 2513 of file classp.h.

2516{
2517 return SrbGetSenseInfoBuffer(Pkt->Srb);
2518}

Referenced by HistoryLogReturnedPacket(), and InterpretTransferPacketError().

◆ ClasspTransferPacketGetSenseInfoBufferLength()

FORCEINLINE UCHAR ClasspTransferPacketGetSenseInfoBufferLength ( _In_ PTRANSFER_PACKET  Pkt)

Definition at line 2521 of file classp.h.

2524{
2526}

Referenced by HistoryLogReturnedPacket(), and InterpretTransferPacketError().

◆ ClasspUninitializeRemoveTracking()

VOID ClasspUninitializeRemoveTracking ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 529 of file lock.c.

532{
533 #if DBG
534 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
535 PRTL_GENERIC_TABLE removeTrackingList = commonExtension->RemoveTrackingList;
536
537 ASSERTMSG("Removing the device while still holding remove locks",
538 commonExtension->RemoveTrackingUntrackedCount == 0 &&
539 removeTrackingList != NULL ? RtlNumberGenericTableElements(removeTrackingList) == 0 : TRUE);
540
541 if (removeTrackingList != NULL)
542 {
543 KIRQL oldIrql;
544 KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock, &oldIrql);
545
546 FREE_POOL(removeTrackingList);
547 commonExtension->RemoveTrackingList = NULL;
548
549 KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, oldIrql);
550 }
551
552 #else
553
555 #endif
556}
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
NTSYSAPI ULONG NTAPI RtlNumberGenericTableElements(_In_ PRTL_GENERIC_TABLE Table)

◆ ClasspUpdateTimerNoWakeTolerance()

BOOLEAN ClasspUpdateTimerNoWakeTolerance ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 3653 of file autorun.c.

3680{
3681 PCLASS_PRIVATE_FDO_DATA fdoData = NULL;
3682
3683 if (FdoExtension->CommonExtension.IsFdo) {
3684 fdoData = FdoExtension->PrivateFdoData;
3685 }
3686
3687 if (fdoData != NULL &&
3688 fdoData->TickTimer != NULL &&
3689 fdoData->TimerInitialized &&
3690 fdoData->TickTimerEnabled) {
3691
3692 LONGLONG noWakeTolerance = TICK_TIMER_DELAY_IN_MSEC * (10 * 1000);
3693
3694 //
3695 // Set the no-wake tolerance to "unlimited" if the conditions below
3696 // are met. An "unlimited" no-wake tolerance means that the timer
3697 // will *never* wake the processor if the processor is in a
3698 // low-power state.
3699 // 1. The screen is off.
3700 // 2. The class driver is *not* a consumer of the tick timer (ClassTick is NULL).
3701 // 3. This is a disk device.
3702 // Otherwise the tolerance is set to the normal, default tolerable delay.
3703 //
3704 if (ClasspScreenOff &&
3705 FdoExtension->CommonExtension.DriverExtension->InitData.ClassTick == NULL &&
3706 FdoExtension->DeviceObject->DeviceType == FILE_DEVICE_DISK) {
3707 noWakeTolerance = EX_TIMER_UNLIMITED_TOLERANCE;
3708 }
3709
3710 //
3711 // The new tolerance is different from the current tolerance so we need
3712 // to set/reset the timer with the new tolerance value.
3713 //
3714 if (fdoData->CurrentNoWakeTolerance != noWakeTolerance) {
3715 EXT_SET_PARAMETERS parameters;
3716 LONGLONG period = TICK_TIMER_PERIOD_IN_MSEC * (10 * 1000); // Convert to units of 100ns.
3717 LONGLONG dueTime = period * (-1); // Negative sign indicates dueTime is relative.
3718
3719 ExInitializeSetTimerParameters(&parameters);
3720 parameters.NoWakeTolerance = noWakeTolerance;
3721 fdoData->CurrentNoWakeTolerance = noWakeTolerance;
3722
3723 ExSetTimer(fdoData->TickTimer,
3724 dueTime,
3725 period,
3726 &parameters);
3727
3728 return TRUE;
3729 }
3730 }
3731
3732 return FALSE;
3733}

Referenced by _Function_class_().

◆ ClasspWriteCacheProperty()

NTSTATUS ClasspWriteCacheProperty ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 1199 of file utils.c.

1204{
1205 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
1207 PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;
1209 PMODE_PARAMETER_HEADER modeData = NULL;
1210 PMODE_CACHING_PAGE pageData = NULL;
1213 PCDB cdb;
1214
1215 //
1216 // Must run at less then dispatch.
1217 //
1218
1220
1223 goto WriteCacheExit;
1224 }
1225
1226 //
1227 // Check proper query type.
1228 //
1229
1230 if (query->QueryType == PropertyExistsQuery) {
1232 goto WriteCacheExit;
1233 }
1234
1235 if (query->QueryType != PropertyStandardQuery) {
1237 goto WriteCacheExit;
1238 }
1239
1240 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
1241
1242 if (length < sizeof(STORAGE_DESCRIPTOR_HEADER)) {
1244 goto WriteCacheExit;
1245 }
1246
1247 writeCache = (PSTORAGE_WRITE_CACHE_PROPERTY) Irp->AssociatedIrp.SystemBuffer;
1248 RtlZeroMemory(writeCache, length);
1249
1250 //
1251 // Set version and required size.
1252 //
1253
1254 writeCache->Version = sizeof(STORAGE_WRITE_CACHE_PROPERTY);
1255 writeCache->Size = sizeof(STORAGE_WRITE_CACHE_PROPERTY);
1256
1257 if (length < sizeof(STORAGE_WRITE_CACHE_PROPERTY)) {
1260 goto WriteCacheExit;
1261 }
1262
1263 //
1264 // Set known values
1265 //
1266
1267 writeCache->NVCacheEnabled = FALSE;
1268 writeCache->UserDefinedPowerProtection = TEST_FLAG(fdoExtension->DeviceFlags, DEV_POWER_PROTECTED);
1269
1270 //
1271 // Check for flush cache support by sending a sync cache command
1272 // to the device.
1273 //
1274
1275 //
1276 // Set timeout value and mark the request as not being a tagged request.
1277 //
1278 SrbSetTimeOutValue(Srb, fdoExtension->TimeOutValue * 4);
1281 SrbAssignSrbFlags(Srb, fdoExtension->SrbFlags);
1282
1283 SrbSetCdbLength(Srb, 10);
1284 cdb = SrbGetCdb(Srb);
1285 cdb->CDB10.OperationCode = SCSIOP_SYNCHRONIZE_CACHE;
1286
1288 Srb,
1289 NULL,
1290 0,
1291 TRUE);
1292 if (NT_SUCCESS(status)) {
1293 writeCache->FlushCacheSupported = TRUE;
1294 } else {
1295 //
1296 // Device does not support sync cache
1297 //
1298
1299 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClasspWriteCacheProperty: Synchronize cache failed with status 0x%X\n", status));
1300 writeCache->FlushCacheSupported = FALSE;
1301 //
1302 // Reset the status if there was any failure
1303 //
1305 }
1306
1307 modeData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
1310
1311 if (modeData == NULL) {
1312 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "ClasspWriteCacheProperty: Unable to allocate mode data buffer\n"));
1314 goto WriteCacheExit;
1315 }
1316
1318
1320 (PCHAR) modeData,
1323
1324 if (length < sizeof(MODE_PARAMETER_HEADER)) {
1325
1326 //
1327 // Retry the request in case of a check condition.
1328 //
1329
1331 (PCHAR) modeData,
1334
1335 if (length < sizeof(MODE_PARAMETER_HEADER)) {
1336 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "ClasspWriteCacheProperty: Mode Sense failed\n"));
1338 goto WriteCacheExit;
1339 }
1340 }
1341
1342 //
1343 // If the length is greater than length indicated by the mode data reset
1344 // the data to the mode data.
1345 //
1346
1347 if (length > (ULONG) (modeData->ModeDataLength + 1)) {
1348 length = modeData->ModeDataLength + 1;
1349 }
1350
1351 //
1352 // Look for caching page in the returned mode page data.
1353 //
1354
1355 pageData = ClassFindModePage((PCHAR) modeData,
1356 length,
1358 TRUE);
1359
1360 //
1361 // Check if valid caching page exists.
1362 //
1363
1364 if (pageData == NULL) {
1365
1366 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClasspWriteCacheProperty: Unable to find caching mode page.\n"));
1367 //
1368 // Set write cache value as unknown.
1369 //
1370 writeCache->WriteCacheEnabled = WriteCacheEnableUnknown;
1371 writeCache->WriteCacheType = WriteCacheTypeUnknown;
1372 } else {
1373 writeCache->WriteCacheEnabled = pageData->WriteCacheEnable ?
1375
1376 writeCache->WriteCacheType = pageData->WriteCacheEnable ?
1378 }
1379
1380 //
1381 // Check write through support. If the device previously failed a write request
1382 // with FUA bit is set, then CLASS_SPECIAL_FUA_NOT_SUPPORTED will be set,
1383 // which means write through is not support by the device.
1384 //
1385
1388 writeCache->WriteThroughSupported = WriteThroughSupported;
1389 } else {
1390 writeCache->WriteThroughSupported = WriteThroughNotSupported;
1391 }
1392
1393 //
1394 // Get the changeable caching mode page and check write cache is changeable.
1395 //
1396
1398
1400 (PCHAR) modeData,
1404
1405 if (length < sizeof(MODE_PARAMETER_HEADER)) {
1406
1407 //
1408 // Retry the request in case of a check condition.
1409 //
1410
1412 (PCHAR) modeData,
1416
1417 if (length < sizeof(MODE_PARAMETER_HEADER)) {
1418
1419 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClasspWriteCacheProperty: Mode Sense failed\n"));
1420
1421 //
1422 // If the device fails to return changeable pages, then
1423 // set the write cache changeable value to unknown.
1424 //
1425
1426 writeCache->WriteCacheChangeable = WriteCacheChangeUnknown;
1428 goto WriteCacheExit;
1429 }
1430 }
1431
1432 //
1433 // If the length is greater than length indicated by the mode data reset
1434 // the data to the mode data.
1435 //
1436
1437 if (length > (ULONG) (modeData->ModeDataLength + 1)) {
1438 length = modeData->ModeDataLength + 1;
1439 }
1440
1441 //
1442 // Look for caching page in the returned mode page data.
1443 //
1444
1445 pageData = ClassFindModePage((PCHAR) modeData,
1446 length,
1448 TRUE);
1449 //
1450 // Check if valid caching page exists.
1451 //
1452
1453 if (pageData == NULL) {
1454 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClasspWriteCacheProperty: Unable to find caching mode page.\n"));
1455 //
1456 // Set write cache changeable value to unknown.
1457 //
1458 writeCache->WriteCacheChangeable = WriteCacheChangeUnknown;
1459 } else {
1460 writeCache->WriteCacheChangeable = pageData->WriteCacheEnable ?
1462 }
1463
1465
1466WriteCacheExit:
1467
1468 FREE_POOL(modeData);
1469
1470 //
1471 // Set the size and status in IRP
1472 //
1473 Irp->IoStatus.Information = information;;
1474 Irp->IoStatus.Status = status;
1475
1478
1479 return status;
1480}
#define DEV_POWER_PROTECTED
Definition: cdrom.h:143
#define MODE_PAGE_DATA_SIZE
Definition: cdromp.h:376
#define MODE_DSP_FUA_SUPPORTED
Definition: cdrw_hw.h:2522
#define MODE_SENSE_CHANGEABLE_VALUES
Definition: cdrw_hw.h:860
#define MODE_PAGE_CACHING
Definition: cdrw_hw.h:846
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
#define CLASS_TAG_MODE_DATA
Definition: classpnp.h:86
#define CLASS_SPECIAL_FUA_NOT_SUPPORTED
Definition: classpnp.h:174
PVOID NTAPI ClassFindModePage(_In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ BOOLEAN Use6Byte)
Definition: class.c:6798
ULONG NTAPI ClassModeSense(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode)
Definition: class.c:6637
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
@ WriteThroughSupported
Definition: ntddstor.h:885
@ WriteThroughNotSupported
Definition: ntddstor.h:884
* PSTORAGE_WRITE_CACHE_PROPERTY
Definition: ntddstor.h:898
@ WriteCacheChangeUnknown
Definition: ntddstor.h:877
@ WriteCacheChangeable
Definition: ntddstor.h:879
@ WriteCacheNotChangeable
Definition: ntddstor.h:878
@ WriteCacheTypeWriteBack
Definition: ntddstor.h:866
@ WriteCacheTypeUnknown
Definition: ntddstor.h:864
@ WriteCacheEnableUnknown
Definition: ntddstor.h:871
@ WriteCacheDisabled
Definition: ntddstor.h:872
@ WriteCacheEnabled
Definition: ntddstor.h:873
STORAGE_WRITE_CACHE_PROPERTY
Definition: ntddstor.h:898
UCHAR WriteCacheEnable
Definition: cdrw_hw.h:2779
UCHAR DeviceSpecificParameter
Definition: cdrw_hw.h:2507

Referenced by ClassDeviceControl().

◆ 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

◆ ClasspZeroQERR()

VOID ClasspZeroQERR ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 7938 of file utils.c.

7957{
7958 PMODE_PARAMETER_HEADER modeData = NULL;
7959 PMODE_CONTROL_PAGE pageData = NULL;
7960 ULONG size = 0;
7961
7962 modeData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
7965
7966 if (modeData == NULL) {
7967 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_SCSI, "ClasspZeroQERR: Unable to allocate mode data buffer\n"));
7968 goto ClasspZeroQERR_Exit;
7969 }
7970
7972
7974 (PCHAR) modeData,
7977
7978 if (size < sizeof(MODE_PARAMETER_HEADER)) {
7979
7980 //
7981 // Retry the request in case of a check condition.
7982 //
7983
7985 (PCHAR) modeData,
7988
7989 if (size < sizeof(MODE_PARAMETER_HEADER)) {
7990 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_SCSI, "ClasspZeroQERR: Mode Sense failed\n"));
7991 goto ClasspZeroQERR_Exit;
7992 }
7993 }
7994
7995 //
7996 // If the size is greater than size indicated by the mode data reset
7997 // the data to the mode data.
7998 //
7999
8000 if (size > (ULONG) (modeData->ModeDataLength + 1)) {
8001 size = modeData->ModeDataLength + 1;
8002 }
8003
8004 //
8005 // Look for control page in the returned mode page data.
8006 //
8007
8008 pageData = ClassFindModePage((PCHAR) modeData,
8009 size,
8011 TRUE);
8012
8013 if (pageData) {
8014 TracePrint((TRACE_LEVEL_VERBOSE,
8015 TRACE_FLAG_SCSI,
8016 "ClasspZeroQERR (%p): Current settings: QERR = %u, TST = %u, TAS = %u.\n",
8018 pageData->QERR,
8019 pageData->TST,
8020 pageData->TAS));
8021
8022 if (pageData->QERR != 0) {
8024 UCHAR pageSavable = 0;
8025
8026 //
8027 // Set QERR to 0 with a Mode Select command. Re-use the modeData
8028 // and pageData structures.
8029 //
8030 pageData->QERR = 0;
8031
8032 //
8033 // We use the original Page Savable (PS) value for the Save Pages
8034 // (SP) bit due to behavior described under the MODE SELECT(6)
8035 // section of SPC-4.
8036 //
8037 pageSavable = pageData->PageSavable;
8038
8040 (PCHAR)modeData,
8041 size,
8042 pageSavable);
8043
8044 if (!NT_SUCCESS(status)) {
8045 TracePrint((TRACE_LEVEL_WARNING,
8046 TRACE_FLAG_SCSI,
8047 "ClasspZeroQERR (%p): Failed to set QERR = 0 with status %x\n",
8049 status));
8050 }
8051 }
8052 }
8053
8054ClasspZeroQERR_Exit:
8055
8056 if (modeData != NULL) {
8057 ExFreePool(modeData);
8058 }
8059}
NTSTATUS ClasspModeSelect(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSelectBuffer, _In_ ULONG Length, _In_ BOOLEAN SavePages)
Definition: class.c:6919
#define MODE_PAGE_CONTROL
Definition: scsi.h:202
UCHAR PageSavable
Definition: scsi.h:3388

◆ ClassQueryPnpCapabilities()

NTSTATUS ClassQueryPnpCapabilities ( IN PDEVICE_OBJECT  PhysicalDeviceObject,
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().

◆ ClassQueueCapacityChangedEventWorker()

VOID ClassQueueCapacityChangedEventWorker ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 5637 of file utils.c.

5650{
5651 PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)(DeviceObject->DeviceExtension);
5652 PIO_WORKITEM workItem = NULL;
5653
5654 if (commonExtension->IsFdo)
5655 {
5656 workItem = IoAllocateWorkItem(DeviceObject);
5657
5658 if (workItem)
5659 {
5660
5661 TracePrint((TRACE_LEVEL_INFORMATION,
5662 TRACE_FLAG_GENERAL,
5663 "ClassQueueCapacityChangedEventWorker: DO (%p), Queueing capacity changed event work item.\n",
5664 DeviceObject));
5665
5667
5668 //
5669 // Queue a work item to write the threshold notification to the
5670 // system event log.
5671 //
5672 IoQueueWorkItem(workItem, ClassLogCapacityChangedProcess, DelayedWorkQueue, workItem);
5673 }
5674 else
5675 {
5676 TracePrint((TRACE_LEVEL_ERROR,
5677 TRACE_FLAG_GENERAL,
5678 "ClassQueueCapacityChangedEventWorker: DO (%p), Failed to allocate memory for the work item.\n",
5679 DeviceObject));
5680 }
5681 }
5682}

Referenced by ClassInterpretSenseInfo().

◆ ClassQueueProvisioningTypeChangedEventWorker()

VOID ClassQueueProvisioningTypeChangedEventWorker ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 5726 of file utils.c.

5739{
5740 PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)(DeviceObject->DeviceExtension);
5741 PIO_WORKITEM workItem = NULL;
5742
5743 if (commonExtension->IsFdo)
5744 {
5745 workItem = IoAllocateWorkItem(DeviceObject);
5746
5747 if (workItem)
5748 {
5749
5750 TracePrint((TRACE_LEVEL_INFORMATION,
5751 TRACE_FLAG_GENERAL,
5752 "ClassQueueProvisioningTypeChangedEventWorker: DO (%p), Queueing LB provisioning type changed event work item.\n",
5753 DeviceObject));
5754
5756
5757 //
5758 // Queue a work item to write the threshold notification to the
5759 // system event log.
5760 //
5761 IoQueueWorkItem(workItem, ClassLogProvisioningTypeChangedEvent, DelayedWorkQueue, workItem);
5762 }
5763 else
5764 {
5765 TracePrint((TRACE_LEVEL_ERROR,
5766 TRACE_FLAG_GENERAL,
5767 "ClassQueueProvisioningTypeChangedEventWorker: DO (%p), Failed to allocate memory for the work item.\n",
5768 DeviceObject));
5769 }
5770 }
5771}

Referenced by ClassInterpretSenseInfo().

◆ ClassQueueResourceExhaustionEventWorker()

VOID ClassQueueResourceExhaustionEventWorker ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 5528 of file utils.c.

5543{
5544 PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)(DeviceObject->DeviceExtension);
5545 PIO_WORKITEM workItem = NULL;
5546
5547 if (commonExtension->IsFdo)
5548 {
5549 workItem = IoAllocateWorkItem(DeviceObject);
5550
5551 if (workItem)
5552 {
5553
5554 TracePrint((TRACE_LEVEL_INFORMATION,
5555 TRACE_FLAG_GENERAL,
5556 "ClassQueueResourceExhaustionEventWorker: DO (%p), Queueing permanent resource exhaustion event work item.\n",
5557 DeviceObject));
5558
5560
5561 //
5562 // Queue a work item to write the threshold notification to the
5563 // system event log.
5564 //
5566 }
5567 else
5568 {
5569 TracePrint((TRACE_LEVEL_ERROR,
5570 TRACE_FLAG_GENERAL,
5571 "ClassQueueResourceExhaustionEventWorker: DO (%p), Failed to allocate memory for the work item.\n",
5572 DeviceObject));
5573 }
5574 }
5575}
IO_WORKITEM_ROUTINE ClassLogResourceExhaustionEvent
Definition: classp.h:2306

Referenced by ClassInterpretSenseInfo().

◆ ClassQueueThresholdEventWorker()

VOID ClassQueueThresholdEventWorker ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 5471 of file utils.c.

5485{
5486 PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)(DeviceObject->DeviceExtension);
5488 PIO_WORKITEM workItem = NULL;
5489
5490 if (commonExtension->IsFdo &&
5491 InterlockedCompareExchange((PLONG)&(fdoExtension->FunctionSupportInfo->LBProvisioningData.SoftThresholdEventPending), 1, 0) == 0)
5492 {
5493 workItem = IoAllocateWorkItem(DeviceObject);
5494
5495 if (workItem)
5496 {
5497
5498 TracePrint((TRACE_LEVEL_INFORMATION,
5499 TRACE_FLAG_GENERAL,
5500 "ClassQueueThresholdEventWorker: DO (%p), Queueing soft threshold notification work item.\n",
5501 DeviceObject));
5502
5503
5505
5506 //
5507 // Queue a work item to write the threshold notification to the
5508 // system event log.
5509 //
5511 }
5512 else
5513 {
5514 //
5515 // Clear the soft threshold event pending flag since this is normally
5516 // done when the work item completes.
5517 //
5518 InterlockedExchange((PLONG)&(fdoExtension->FunctionSupportInfo->LBProvisioningData.SoftThresholdEventPending), 0);
5519
5520 TracePrint((TRACE_LEVEL_ERROR,
5521 TRACE_FLAG_GENERAL,
5522 "ClassQueueThresholdEventWorker: DO (%p), Failed to allocate memory for the work item.\n",
5523 DeviceObject));
5524 }
5525 }
5526}
#define InterlockedExchange
Definition: armddk.h:54
IO_WORKITEM_ROUTINE ClassLogThresholdEvent
Definition: classp.h:2298
int32_t * PLONG
Definition: typedefs.h:58

Referenced by ClassInterpretSenseInfo().

◆ ClassReadCapacity16()

NTSTATUS ClassReadCapacity16 ( _Inout_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
_Inout_ PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 1568 of file utils.c.

1583{
1587 ULONG allocationBufferLength = bufferLength; //DMA buffer size for alignment
1588 PCDB cdb;
1589 ULONG dataTransferLength = 0;
1590
1591 //
1592 // If the information retrieval has already been attempted, return the cached status.
1593 //
1594 if (FdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus != -1) {
1595 // get cached NTSTATUS from previous call.
1596 return FdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus;
1597 }
1598
1600 FdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus = STATUS_NOT_IMPLEMENTED;
1602 }
1603
1604#if defined(_ARM_) || defined(_ARM64_)
1605 //
1606 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
1607 // based platforms. We are taking the conservative approach here.
1608 //
1609 allocationBufferLength = ALIGN_UP_BY(allocationBufferLength,KeGetRecommendedSharedDataAlignment());
1610 dataBuffer = (PREAD_CAPACITY16_DATA)ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, allocationBufferLength, '4CcS');
1611#else
1613#endif
1614
1615 if (dataBuffer == NULL) {
1616 // return without updating FdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus
1617 // the field will remain value as "-1", so that the command will be attempted next time this function is called.
1619 }
1620
1621 RtlZeroMemory(dataBuffer, allocationBufferLength);
1622
1623 //
1624 // Initialize the SRB.
1625 //
1626 if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1630 1,
1632 if (NT_SUCCESS(status)) {
1634 } else {
1635 //
1636 // Should not occur.
1637 //
1639 }
1640 } else {
1642 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
1644 }
1645
1646 //prepare the Srb
1647 if (NT_SUCCESS(status))
1648 {
1649
1650 SrbSetTimeOutValue(Srb, FdoExtension->TimeOutValue);
1654
1655 SrbSetCdbLength(Srb, 16);
1656
1657 cdb = SrbGetCdb(Srb);
1658 cdb->READ_CAPACITY16.OperationCode = SCSIOP_READ_CAPACITY16;
1660 cdb->READ_CAPACITY16.AllocationLength[3] = bufferLength;
1661
1663 Srb,
1664 dataBuffer,
1665 allocationBufferLength,
1666 FALSE);
1667
1668 dataTransferLength = SrbGetDataTransferLength(Srb);
1669 }
1670
1671 if (NT_SUCCESS(status) && (dataTransferLength < 16))
1672 {
1673 // the device should return at least 16 bytes of data for this command.
1675 }
1676
1677 //
1678 // Handle the case where we get back STATUS_DATA_OVERRUN b/c the input
1679 // buffer was larger than necessary.
1680 //
1681 if (status == STATUS_DATA_OVERRUN && dataTransferLength < bufferLength)
1682 {
1684 }
1685
1686 if (NT_SUCCESS(status))
1687 {
1688 // cache data into FdoExtension
1690 }
1691
1692 // cache the status indicates that this funciton has been called.
1693 FdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus = status;
1694
1696
1697 return status;
1698}
NTSTATUS InterpretReadCapacity16Data(_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PREAD_CAPACITY16_DATA ReadCapacity16Data)
Definition: utils.c:1517
struct _READ_CAPACITY16_DATA READ_CAPACITY16_DATA
struct _READ_CAPACITY16_DATA * PREAD_CAPACITY16_DATA
#define SERVICE_ACTION_READ_CAPACITY16
Definition: scsi.h:474
struct _CDB::_READ_CAPACITY16 READ_CAPACITY16

Referenced by ClasspAccessAlignmentProperty().

◆ 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()

◆ 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()
#define PagedPool
Definition: env_spec_w32.h:308
GLuint GLuint GLsizei count
Definition: gl.h:1545
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:381
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:650
_In_ DEVICE_RELATION_TYPE RelationType
Definition: wdfdevice.h:1059
struct _DEVICE_RELATIONS DEVICE_RELATIONS
#define NT_ASSERTMSG
Definition: rtlfuncs.h:3328

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
KIRQL irql
Definition: wave.h:1
VOID ClasspRetryDpcTimer(IN PCLASS_PRIVATE_FDO_DATA FdoData)
Definition: class.c:12457
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
struct _CLASS_PRIVATE_FDO_DATA::@1066 Retry
struct _CLASS_RETRY_INFO * Next
Definition: classp.h:408

Referenced by RetryPowerRequest(), and RetryRequest().

◆ ClassSendEjectionNotification()

VOID ClassSendEjectionNotification ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 155 of file autorun.c.

158{
159 //
160 // For post-NT5.1 work, need to move EjectSynchronizationEvent
161 // to be a MUTEX so we can attempt to grab it here and benefit
162 // from deadlock detection. This will allow checking if the media
163 // has been locked by programs before broadcasting these events.
164 // (what's the point of broadcasting if the media is not locked?)
165 //
166 // This would currently only be a slight optimization. For post-NT5.1,
167 // it would allow us to send a single PERSISTENT_PREVENT to MMC devices,
168 // thereby cleaning up a lot of the ejection code. Then, when the
169 // ejection request occured, we could see if any locks for the media
170 // existed. if locked, broadcast. if not, we send the eject irp.
171 //
172
173 //
174 // for now, just always broadcast. make this a public routine,
175 // so class drivers can add special hacks to broadcast this for their
176 // non-MMC-compliant devices also from sense codes.
177 //
178
179 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassSendEjectionNotification: media EJECT_REQUEST"));
180 ClassSendNotification(FdoExtension,
181 &GUID_IO_MEDIA_EJECT_REQUEST,
182 0,
183 NULL);
184 return;
185}

Referenced by ClassInterpretSenseInfo(), and ClasspInterpretGesnData().

◆ CleanupTransferPacketToWorkingSetSize()

VOID CleanupTransferPacketToWorkingSetSize ( _In_ PDEVICE_OBJECT  Fdo,
_In_ BOOLEAN  LimitNumPktToDelete,
_In_ ULONG  Node 
)

Definition at line 1615 of file xferpkt.c.

1634{
1635 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
1636 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1637 KIRQL oldIrql;
1638 SINGLE_LIST_ENTRY pktList;
1639 PSINGLE_LIST_ENTRY slistEntry;
1640 PTRANSFER_PACKET pktToDelete;
1641 ULONG requiredNumPktToDelete = fdoData->FreeTransferPacketsLists[Node].NumTotalTransferPackets -
1643
1644 if (LimitNumPktToDelete) {
1645 requiredNumPktToDelete = MIN(requiredNumPktToDelete, MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE);
1646 }
1647
1648 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "CleanupTransferPacketToWorkingSetSize (%p): Exiting stress, block freeing %d packets.", Fdo, requiredNumPktToDelete));
1649
1650 /*
1651 * Check the counter again with lock held. This eliminates a race condition
1652 * while still allowing us to not grab the spinlock in the common codepath.
1653 *
1654 * Note that the spinlock does not synchronize with threads dequeuing free
1655 * packets to send (DequeueFreeTransferPacket does that with a lightweight
1656 * interlocked exchange); the spinlock prevents multiple threads in this function
1657 * from deciding to free too many extra packets at once.
1658 */
1659 SimpleInitSlistHdr(&pktList);
1660 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
1663 (requiredNumPktToDelete--)){
1664
1665 pktToDelete = DequeueFreeTransferPacketEx(Fdo, FALSE, Node);
1666 if (pktToDelete){
1667 SimplePushSlist(&pktList,
1668 (PSINGLE_LIST_ENTRY)&pktToDelete->SlistEntry);
1670 } else {
1671 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW,
1672 "Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (1). Node=%d",
1674 Fdo,
1676 Node));
1677 break;
1678 }
1679 }
1680 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
1681
1682 slistEntry = SimplePopSlist(&pktList);
1683 while (slistEntry) {
1684 pktToDelete = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
1685 DestroyTransferPacket(pktToDelete);
1686 slistEntry = SimplePopSlist(&pktList);
1687 }
1688
1689 return;
1690}
FORCEINLINE VOID SimpleInitSlistHdr(SINGLE_LIST_ENTRY *SListHdr)
Definition: classp.h:1211
#define MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE
Definition: classp.h:639
FORCEINLINE SINGLE_LIST_ENTRY * SimplePopSlist(SINGLE_LIST_ENTRY *SListHdr)
Definition: classp.h:1220
FORCEINLINE VOID SimplePushSlist(SINGLE_LIST_ENTRY *SListHdr, SINGLE_LIST_ENTRY *SListEntry)
Definition: classp.h:1215
union node Node
Definition: types.h:1255
ULONG LocalMaxWorkingSetTransferPackets
Definition: classp.h:712
PPNL_SLIST_HEADER FreeTransferPacketsLists
Definition: classp.h:772
DECLSPEC_CACHEALIGN ULONG NumFreeTransferPackets
Definition: classp.h:645
ULONG NumTotalTransferPackets
Definition: classp.h:646
Definition: ntbasedef.h:636
SLIST_ENTRY SlistEntry
Definition: classp.h:500
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
Definition: dlist.c:348
VOID DestroyTransferPacket(_In_ __drv_freesMem(mem) PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:500
PTRANSFER_PACKET DequeueFreeTransferPacketEx(_In_ PDEVICE_OBJECT Fdo, _In_ BOOLEAN AllocIfNeeded, _In_ ULONG Node)
Definition: xferpkt.c:661

Referenced by CleanupTransferPacketToWorkingSetSizeWorker(), and EnqueueFreeTransferPacket().

◆ CreateStorageRequestBlock()

NTSTATUS CreateStorageRequestBlock ( _Inout_ PSTORAGE_REQUEST_BLOCK Srb,
_In_ USHORT  AddressType,
_In_opt_ PSRB_ALLOCATE_ROUTINE  AllocateRoutine,
_Inout_opt_ ULONG ByteSize,
_In_ ULONG  NumSrbExData,
  ... 
)

Definition at line 249 of file srblib.c.

283{
284 ULONG sizeNeeded = 0;
285 va_list ap;
286 ULONG i;
288
289 // Ensure SrbExData offsets are pointer type aligned
290 sizeNeeded = sizeof(STORAGE_REQUEST_BLOCK);
291 if (NumSrbExData > 0) {
292 sizeNeeded += ((NumSrbExData - 1) * sizeof(ULONG));
293 if (sizeNeeded % sizeof(PVOID)) {
294 sizeNeeded += (sizeof(PVOID) - (sizeNeeded % sizeof(PVOID)));
295 }
296 }
297
298 if (AddressType == STORAGE_ADDRESS_TYPE_BTL8)
299 {
300 sizeNeeded += sizeof(STOR_ADDR_BTL8);
301 } else
302 {
304 }
305
306 va_start(ap, NumSrbExData);
307
308 for (i = 0; i < NumSrbExData && status == STATUS_SUCCESS; i++)
309 {
310 switch (va_arg(ap, SRBEXDATATYPE))
311 {
313 sizeNeeded += sizeof(SRBEX_DATA_BIDIRECTIONAL);
314 break;
316 sizeNeeded += sizeof(SRBEX_DATA_SCSI_CDB16);
317 break;
319 sizeNeeded += sizeof(SRBEX_DATA_SCSI_CDB32);
320 break;
322 sizeNeeded += sizeof(SRBEX_DATA_SCSI_CDB_VAR) + va_arg(ap, ULONG);
323 break;
324 case SrbExDataTypeWmi:
325 sizeNeeded += sizeof(SRBEX_DATA_WMI);
326 break;
328 sizeNeeded += sizeof(SRBEX_DATA_POWER);
329 break;
330 case SrbExDataTypePnP:
331 sizeNeeded += sizeof(SRBEX_DATA_PNP);
332 break;
334 sizeNeeded += sizeof(SRBEX_DATA_IO_INFO);
335 break;
336 default:
338 break;
339 }
340 }
341 va_end(ap);
342
343 if (status == STATUS_SUCCESS)
344 {
345 if (AllocateRoutine)
346 {
347 *Srb = AllocateRoutine(sizeNeeded);
348 if (*Srb == NULL)
349 {
351 }
352 }
353
354 if (ByteSize != NULL)
355 {
356 *ByteSize = sizeNeeded;
357 }
358
359 if (*Srb)
360 {
361 va_start(ap, NumSrbExData);
362#ifdef _MSC_VER
363 #pragma prefast(suppress:26015, "pInitializeStorageRequestBlock will set the SrbLength field")
364#endif
365 status = pInitializeStorageRequestBlock(*Srb, AddressType, sizeNeeded, NumSrbExData, ap);
366 va_end(ap);
367 }
368
369 }
370
371 return status;
372}
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define va_arg(ap, T)
Definition: acmsvcex.h:89
struct STOR_ADDRESS_ALIGN _STOR_ADDR_BTL8 STOR_ADDR_BTL8
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB_VAR SRBEX_DATA_SCSI_CDB_VAR
struct SRB_ALIGN _SRBEX_DATA_IO_INFO SRBEX_DATA_IO_INFO
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB16 SRBEX_DATA_SCSI_CDB16
struct SRB_ALIGN _SRBEX_DATA_PNP SRBEX_DATA_PNP
struct SRB_ALIGN _SRBEX_DATA_WMI SRBEX_DATA_WMI
struct SRB_ALIGN _SRBEX_DATA_POWER SRBEX_DATA_POWER
@ SrbExDataTypeBidirectional
Definition: srb.h:458
@ SrbExDataTypeIoInfo
Definition: srb.h:465
struct SRB_ALIGN _SRBEX_DATA_BIDIRECTIONAL SRBEX_DATA_BIDIRECTIONAL
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB32 SRBEX_DATA_SCSI_CDB32
enum _SRBEXDATATYPE SRBEXDATATYPE
NTSTATUS pInitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData, _In_ va_list ap)
Definition: srblib.c:52
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36
_In_ PRTL_GENERIC_COMPARE_ROUTINE _In_ PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine
Definition: rtlfuncs.h:1106
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:412

Referenced by __drv_allocatesMem(), and InitializeTransferPackets().

◆ DefaultStorageRequestBlockAllocateRoutine()

PVOID DefaultStorageRequestBlockAllocateRoutine ( _In_ CLONG  ByteSize)

Definition at line 28 of file srblib.c.

46{
47 return ExAllocatePoolWithTag(NonPagedPoolNx, ByteSize, '+brs');
48}

Referenced by __drv_allocatesMem(), and InitializeTransferPackets().

◆ DequeueDeferredClientIrp()

PIRP DequeueDeferredClientIrp ( PDEVICE_OBJECT  Fdo)

Definition at line 113 of file clntirp.c.

116{
117 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
118 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
119 PIRP irp;
120
121 //
122 // The DeferredClientIrpList is almost always empty.
123 // We don't want to grab the spinlock every time we check it (which is on every xfer completion)
124 // so check once first before we grab the spinlock.
125 //
126 if (IsListEmpty(&fdoData->DeferredClientIrpList)){
127 irp = NULL;
128 }
129 else {
130 PLIST_ENTRY listEntry;
131 KIRQL oldIrql;
132
133 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
134 if (IsListEmpty(&fdoData->DeferredClientIrpList)){
135 listEntry = NULL;
136 }
137 else {
138 listEntry = RemoveHeadList(&fdoData->DeferredClientIrpList);
139 }
140 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
141
142 if (listEntry == NULL) {
143 irp = NULL;
144 }
145 else {
146 irp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
147 NT_ASSERT(irp->Type == IO_TYPE_IRP);
148
149
150 InitializeListHead(&irp->Tail.Overlay.ListEntry);
151 }
152 }
153
154 return irp;
155}
PLIST_ENTRY ListEntry()
Definition: fxirpum.cpp:535
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
LIST_ENTRY DeferredClientIrpList
Definition: classp.h:777
Definition: typedefs.h:120
#define IO_TYPE_IRP

Referenced by TransferPktComplete().

◆ DequeueFreeTransferPacket()

PTRANSFER_PACKET DequeueFreeTransferPacket ( PDEVICE_OBJECT  Fdo,
BOOLEAN  AllocIfNeeded 
)

◆ DequeueFreeTransferPacketEx()

PTRANSFER_PACKET DequeueFreeTransferPacketEx ( _In_ PDEVICE_OBJECT  Fdo,
_In_ BOOLEAN  AllocIfNeeded,
_In_ ULONG  Node 
)

Definition at line 661 of file xferpkt.c.

665{
666 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
667 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
669 PSLIST_ENTRY slistEntry;
670
672
673 if (slistEntry) {
674 slistEntry->Next = NULL;
675 pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
677
678 // when dequeuing the packet, also reset the history data
680
681 } else {
682 if (AllocIfNeeded) {
683 /*
684 * We are in stress and have run out of lookaside packets.
685 * In order to service the current transfer,
686 * allocate an extra packet.
687 * We will free it lazily when we are out of stress.
688 */
689 pkt = NewTransferPacket(Fdo);
690 if (pkt) {
695 } else {
696 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "DequeueFreeTransferPacket: packet allocation failed"));
697 }
698 } else {
699 pkt = NULL;
700 }
701 }
702
703 return pkt;
704}
#define HISTORYINITIALIZERETRYLOGS(_packet)
Definition: classp.h:2330
ULONG DbgPeakNumTransferPackets
Definition: classp.h:647
DECLSPEC_CACHEALIGN SLIST_HEADER SListHeader
Definition: classp.h:644
#define InterlockedPopEntrySList(SListHead)
Definition: rtlfuncs.h:3409
#define PSLIST_ENTRY
Definition: rtltypes.h:134

Referenced by CleanupTransferPacketToWorkingSetSize(), DequeueFreeTransferPacket(), DestroyAllTransferPackets(), and EnqueueFreeTransferPacket().

◆ DestroyAllTransferPackets()

VOID DestroyAllTransferPackets ( PDEVICE_OBJECT  Fdo)

Definition at line 288 of file xferpkt.c.

289{
290 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
291 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
292 TRANSFER_PACKET *pkt;
293 ULONG index;
294 ULONG arraySize;
295
296 PAGED_CODE();
297
298 //
299 // fdoData->FreeTransferPacketsLists could be NULL if
300 // there was an error during start device.
301 //
302 if (fdoData->FreeTransferPacketsLists != NULL) {
303
305
306 arraySize = KeQueryHighestNodeNumber() + 1;
307 for (index = 0; index < arraySize; index++) {
309 while (pkt) {
313 }
314
316 }
317 }
318
319 FREE_POOL(fdoData->SrbTemplate);
320}
#define index(s, c)
Definition: various.h:29
GLuint index
Definition: glext.h:6031
NTKRNLVISTAAPI USHORT NTAPI KeQueryHighestNodeNumber()
Definition: ke.c:32
PSTORAGE_REQUEST_BLOCK_HEADER SrbTemplate
Definition: classp.h:790

◆ DestroyTransferPacket()

VOID DestroyTransferPacket ( _In_ __drv_freesMem(mem) PTRANSFER_PACKET  Pkt)

Definition at line 500 of file xferpkt.c.

501{
503 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
504 KIRQL oldIrql;
505
506 NT_ASSERT(!Pkt->SlistEntry.Next);
507// NT_ASSERT(!Pkt->OriginalIrp);
508
509 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
510
511 /*
512 * Delete the packet from our all-packets queue.
513 */
518
519 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
520
522 IoFreeIrp(Pkt->Irp);
524 FREE_POOL(Pkt->Srb);
525 FREE_POOL(Pkt);
526}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
LIST_ENTRY AllTransferPacketsList
Definition: classp.h:771
PMDL PartialMdl
Definition: classp.h:596
PSRB_HISTORY RetryHistory
Definition: classp.h:598
LIST_ENTRY AllPktsListEntry
Definition: classp.h:499

Referenced by CleanupTransferPacketToWorkingSetSize(), DestroyAllTransferPackets(), and EnqueueFreeTransferPacket().

◆ EnqueueDeferredClientIrp()

VOID EnqueueDeferredClientIrp ( PDEVICE_OBJECT  Fdo,
PIRP  Irp 
)

Definition at line 78 of file clntirp.c.

82{
83 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
84 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
85 KIRQL oldIrql;
86
87
88 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
89 InsertTailList(&fdoData->DeferredClientIrpList, &Irp->Tail.Overlay.ListEntry);
90
91
92 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
93}

Referenced by ServiceTransferRequest().

◆ EnqueueFreeTransferPacket()

VOID EnqueueFreeTransferPacket ( PDEVICE_OBJECT  Fdo,
__drv_aliasesMem PTRANSFER_PACKET  Pkt 
)

Definition at line 529 of file xferpkt.c.

530{
531 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
532 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
533 ULONG allocateNode;
534 KIRQL oldIrql;
535
536 NT_ASSERT(!Pkt->SlistEntry.Next);
537
538 allocateNode = Pkt->AllocateNode;
540 InterlockedIncrement((volatile LONG *)&(fdoData->FreeTransferPacketsLists[allocateNode].NumFreeTransferPackets));
541
542 /*
543 * If the total number of packets is larger than LocalMinWorkingSetTransferPackets,
544 * that means that we've been in stress. If all those packets are now
545 * free, then we are now out of stress and can free the extra packets.
546 * Attempt to free down to LocalMaxWorkingSetTransferPackets immediately, and
547 * down to LocalMinWorkingSetTransferPackets lazily (one at a time).
548 * However, since we're at DPC, do this is a work item. If the device is removed
549 * or we are unable to allocate the work item, do NOT free more than
550 * MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE. Subsequent IO completions will end up freeing
551 * up the rest, even if it is MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE at a time.
552 */
553 if (fdoData->FreeTransferPacketsLists[allocateNode].NumFreeTransferPackets >=
554 fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets) {
555
556 /*
557 * 1. Immediately snap down to our UPPER threshold.
558 */
559 if (fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets >
561
562 ULONG isRemoved;
563 PIO_WORKITEM workItem = NULL;
564
565 workItem = IoAllocateWorkItem(Fdo);
566
567 //
568 // Acquire a remove lock in order to make sure the device object and its
569 // private data structures will exist when the workitem fires.
570 // The remove lock will be released by the workitem (CleanupTransferPacketToWorkingSetSize).
571 //
572 isRemoved = ClassAcquireRemoveLock(Fdo, (PIRP)workItem);
573
574 if (workItem && !isRemoved) {
575
576 TracePrint((TRACE_LEVEL_INFORMATION,
577 TRACE_FLAG_GENERAL,
578 "EnqueueFreeTransferPacket: Device (%p), queuing work item to clean up free transfer packets.\n",
579 Fdo));
580
581 //
582 // Queue a work item to trim down the total number of transfer packets to with the
583 // working size.
584 //
586
587 } else {
588
589 if (workItem) {
590 IoFreeWorkItem(workItem);
591 }
592
593 if (isRemoved != REMOVE_COMPLETE) {
594 ClassReleaseRemoveLock(Fdo, (PIRP)workItem);
595 }
596
597 TracePrint((TRACE_LEVEL_ERROR,
598 TRACE_FLAG_GENERAL,
599 "EnqueueFreeTransferPacket: Device (%p), Failed to allocate memory for the work item.\n",
600 Fdo));
601
603 }
604 }
605
606 /*
607 * 2. Lazily work down to our LOWER threshold (by only freeing one packet at a time).
608 */
609 if (fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets >
611 /*
612 * Check the counter again with lock held. This eliminates a race condition
613 * while still allowing us to not grab the spinlock in the common codepath.
614 *
615 * Note that the spinlock does not synchronize with threads dequeuing free
616 * packets to send (DequeueFreeTransferPacket does that with a lightweight
617 * interlocked exchange); the spinlock prevents multiple threads in this function
618 * from deciding to free too many extra packets at once.
619 */
620 PTRANSFER_PACKET pktToDelete = NULL;
621
622 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "Exiting stress, lazily freeing one of %d/%d packets from node %d.",
625 allocateNode));
626
627 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
628 if ((fdoData->FreeTransferPacketsLists[allocateNode].NumFreeTransferPackets >=
629 fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets) &&
630 (fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets >
632
633 pktToDelete = DequeueFreeTransferPacketEx(Fdo, FALSE, allocateNode);
634 if (pktToDelete) {
635 InterlockedDecrement((volatile LONG *)&(fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets));
636 } else {
637 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW,
638 "Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (2). Node=%d",
640 Fdo,
642 allocateNode));
643 }
644 }
645 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
646
647 if (pktToDelete) {
648 DestroyTransferPacket(pktToDelete);
649 }
650 }
651
652 }
653
654}
IO_WORKITEM_ROUTINE_EX CleanupTransferPacketToWorkingSetSizeWorker
Definition: classp.h:1745
#define REMOVE_COMPLETE
Definition: classpnp.h:98
NTKRNLVISTAAPI VOID NTAPI IoQueueWorkItemEx(_Inout_ PIO_WORKITEM IoWorkItem, _In_ PIO_WORKITEM_ROUTINE_EX WorkerRoutine, _In_ WORK_QUEUE_TYPE QueueType, _In_opt_ __drv_aliasesMem PVOID Context)
Definition: io.c:55
ULONG LocalMinWorkingSetTransferPackets
Definition: classp.h:711
ULONG AllocateNode
Definition: classp.h:611
#define InterlockedPushEntrySList(SListHead, SListEntry)
Definition: rtlfuncs.h:3406
VOID CleanupTransferPacketToWorkingSetSize(_In_ PDEVICE_OBJECT Fdo, _In_ BOOLEAN LimitNumPktToDelete, _In_ ULONG Node)
Definition: xferpkt.c:1615

Referenced by InitializeTransferPackets(), ServiceTransferRequest(), and TransferPktComplete().

◆ FREE_PORT_ALLOCATED_SENSE_BUFFER_EX()

◆ FreeDeviceInputMdl()

VOID FreeDeviceInputMdl ( PMDL  Mdl)

Definition at line 622 of file utils.c.

623{
625 return;
626}
VOID ClasspFreeDeviceMdl(PMDL Mdl)
Definition: utils.c:615

Referenced by ClasspModeSelect(), ClasspModeSense(), and ClassReadDriveCapacity().

◆ FreeDictionaryEntry()

VOID FreeDictionaryEntry ( IN PDICTIONARY  Dictionary,
IN PVOID  Entry 
)

Definition at line 189 of file dictlib.c.

193{
196 KIRQL oldIrql;
197 BOOLEAN found;
198
199 found = FALSE;
201
202 KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
203
204 entry = &(Dictionary->List);
205 while(*entry != NULL) {
206
207 if(*entry == header) {
208 *entry = header->Next;
209 found = TRUE;
210 break;
211 } else {
212 entry = &(*entry)->Next;
213 }
214 }
215
216 KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
217
218 //
219 // calling this w/an invalid pointer invalidates the dictionary system,
220 // so NT_ASSERT() that we never try to Free something not in the list
221 //
222
223 NT_ASSERT(found);
224 if (found) {
226 }
227
228 return;
229
230}
uint32_t entry
Definition: isohybrid.c:63
base of all file and directory entries
Definition: entries.h:83

Referenced by ClasspCreateClose().

◆ GetDictionaryEntry()

PVOID GetDictionaryEntry ( IN PDICTIONARY  Dictionary,
IN ULONGLONG  Key 
)

Definition at line 157 of file dictlib.c.

161{
163 PVOID data;
164 KIRQL oldIrql;
165
166
167 data = NULL;
168
169 KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
170
171 entry = Dictionary->List;
172 while (entry != NULL) {
173
174 if (entry->Key == Key) {
175 data = entry->Data;
176 break;
177 } else {
178 entry = entry->Next;
179 }
180 }
181
182 KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
183
184 return data;
185}
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950

Referenced by _IRQL_requires_max_().

◆ HistoryInitializeRetryLogs()

VOID HistoryInitializeRetryLogs ( _Out_ PSRB_HISTORY  History,
ULONG  HistoryCount 
)

Definition at line 36 of file history.c.

36 {
37 ULONG tmpSize = HistoryCount * sizeof(SRB_HISTORY_ITEM);
38 tmpSize += sizeof(SRB_HISTORY) - sizeof(SRB_HISTORY_ITEM);
39 RtlZeroMemory(History, tmpSize);
40 History->TotalHistoryCount = HistoryCount;
41 return;
42}
VOID History(INT dir, LPTSTR commandline)
Definition: history.c:326
struct _SRB_HISTORY SRB_HISTORY
struct _SRB_HISTORY_ITEM SRB_HISTORY_ITEM

Referenced by __drv_allocatesMem().

◆ HistoryLogReturnedPacket()

VOID HistoryLogReturnedPacket ( TRANSFER_PACKET Pkt)

Definition at line 83 of file history.c.

83 {
84
85 PSRB_HISTORY history;
87 UCHAR senseSize;
89 UCHAR senseInfoBufferLength;
90 SENSE_DATA convertedSenseBuffer = {0};
92
94 history = Pkt->RetryHistory;
95 NT_ASSERT( history->UsedHistoryCount <= history->TotalHistoryCount );
96 item = &( history->History[ history->UsedHistoryCount-1 ] );
97
98 // Query the tick count and store in the history
99 KeQueryTickCount(&item->TickCountCompleted);
100
101 // Copy the SRB Status...
102 item->SrbStatus = Pkt->Srb->SrbStatus;
103
104 //
105 // Process sense data
106 //
107
109 senseInfoBufferLength = ClasspTransferPacketGetSenseInfoBufferLength(Pkt);
110
112
113 validSense = ScsiConvertToFixedSenseFormat(senseInfoBuffer,
114 senseInfoBufferLength,
115 (PVOID)&convertedSenseBuffer,
116 sizeof(convertedSenseBuffer));
117
118 if (validSense) {
119 senseInfoBuffer = (PVOID)&convertedSenseBuffer;
120 senseInfoBufferLength = sizeof(convertedSenseBuffer);
121 }
122 }
123
124 RtlZeroMemory(&(item->NormalizedSenseData), sizeof(item->NormalizedSenseData));
125
126 if (validSense) {
127
128 // Determine the amount of valid sense data
129
130 if (!ScsiGetTotalSenseByteCountIndicated(senseInfoBuffer,
131 senseInfoBufferLength,
132 &senseSize)) {
133 senseSize = senseInfoBufferLength;
134 }
135
136 // Normalize the sense data copy in the history
137 senseSize = min(senseSize, sizeof(item->NormalizedSenseData));
138 RtlCopyMemory(&(item->NormalizedSenseData),
140 senseSize
141 );
142 }
143
144 return;
145}
FORCEINLINE PVOID ClasspTransferPacketGetSenseInfoBuffer(_In_ PTRANSFER_PACKET Pkt)
Definition: classp.h:2513
FORCEINLINE UCHAR ClasspTransferPacketGetSenseInfoBufferLength(_In_ PTRANSFER_PACKET Pkt)
Definition: classp.h:2521
static ATOM item
Definition: dde.c:856
PFIXED_SENSE_DATA senseInfoBuffer
Definition: scsi.h:3710
#define IsDescriptorSenseDataFormat(SenseInfoBuffer)
Definition: scsi.h:3685

◆ HistoryLogSendPacket()

VOID HistoryLogSendPacket ( TRANSFER_PACKET Pkt)

Definition at line 45 of file history.c.

45 {
46
47 PSRB_HISTORY history;
49
51 history = Pkt->RetryHistory;
52 // sending a packet implies a new history unit is to be used.
53 NT_ASSERT( history->UsedHistoryCount <= history->TotalHistoryCount );
54
55 // if already all used up, request class driver to remove at least one history unit
56 if (history->UsedHistoryCount == history->TotalHistoryCount )
57 {
59 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
60 NT_ASSERT( fdoData->InterpretSenseInfo != NULL );
62 fdoData->InterpretSenseInfo->Compress( fdoExtension->DeviceObject, history );
63 NT_ASSERT( history->UsedHistoryCount < history->TotalHistoryCount );
64 }
65
66 // thus, since we are about to increment the count, it must now be less...
67 NT_ASSERT( history->UsedHistoryCount < history->TotalHistoryCount );
68
69 // increment the number of history units in use
70 history->UsedHistoryCount++;
71
72 // determine index to use
73 item = &( history->History[ history->UsedHistoryCount-1 ] );
74
75 // zero out the history item
77
78 // Query the tick count and store in the history
79 KeQueryTickCount(&item->TickCountSent);
80 return;
81}
__callback PCLASS_COMPRESS_RETRY_HISTORY_DATA Compress
Definition: classpnp.h:565
PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo
Definition: classp.h:958

◆ InitializeDictionary()

VOID InitializeDictionary ( IN PDICTIONARY  Dictionary)

Definition at line 58 of file dictlib.c.

61{
62 RtlZeroMemory(Dictionary, sizeof(DICTIONARY));
63 Dictionary->Signature = DICTIONARY_SIGNATURE;
64 KeInitializeSpinLock(&Dictionary->SpinLock);
65 return;
66}
#define DICTIONARY_SIGNATURE
Definition: dictlib.c:38

◆ InitializeStorageRequestBlock()

◆ InitializeTransferPackets()

NTSTATUS InitializeTransferPackets ( PDEVICE_OBJECT  Fdo)

Definition at line 45 of file xferpkt.c.

46{
47 PCOMMON_DEVICE_EXTENSION commonExt = Fdo->DeviceExtension;
48 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
49 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
50 PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExt->PartitionZeroExtension->AdapterDescriptor;
52 STORAGE_PROPERTY_ID propertyId;
53 OSVERSIONINFOEXW osVersionInfo;
54 ULONG hwMaxPages;
55 ULONG arraySize;
57 ULONG maxOutstandingIOPerLUN;
58 ULONG minWorkingSetTransferPackets;
59 ULONG maxWorkingSetTransferPackets;
60
62
63 PAGED_CODE();
64
65 //
66 // Precompute the maximum transfer length
67 //
68 NT_ASSERT(adapterDesc->MaximumTransferLength);
69
70 hwMaxPages = adapterDesc->MaximumPhysicalPages ? adapterDesc->MaximumPhysicalPages-1 : 0;
71
72 fdoData->HwMaxXferLen = MIN(adapterDesc->MaximumTransferLength, hwMaxPages << PAGE_SHIFT);
73 fdoData->HwMaxXferLen = MAX(fdoData->HwMaxXferLen, PAGE_SIZE);
74
75 //
76 // Allocate per-node free packet lists
77 //
78 arraySize = KeQueryHighestNodeNumber() + 1;
80 ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
81 sizeof(PNL_SLIST_HEADER) * arraySize,
83
84 if (fdoData->FreeTransferPacketsLists == NULL) {
86 return status;
87 }
88
89 for (index = 0; index < arraySize; index++) {
93 }
94
96
97 //
98 // Set the packet threshold numbers based on the Windows Client or Server SKU.
99 //
100
101 osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
102 status = RtlGetVersion((POSVERSIONINFOW) &osVersionInfo);
103
105
106 //
107 // Retrieve info on IO capability supported by port drivers
108 //
109
111 status = ClassGetDescriptor(fdoExt->CommonExtension.LowerDeviceObject,
112 &propertyId,
113 (PVOID *)&devIoCapabilityDesc);
114
115 if (NT_SUCCESS(status) && (devIoCapabilityDesc != NULL)) {
116 maxOutstandingIOPerLUN = devIoCapabilityDesc->LunMaxIoCount;
117 FREE_POOL(devIoCapabilityDesc);
118
119#if DBG
120 fdoData->MaxOutstandingIOPerLUN = maxOutstandingIOPerLUN;
121#endif
122
123 } else {
124 maxOutstandingIOPerLUN = MAX_OUTSTANDING_IO_PER_LUN_DEFAULT;
125
126#if DBG
127 fdoData->MaxOutstandingIOPerLUN = 0;
128#endif
129
130 }
131
132 //
133 // StorageDeviceIoCapabilityProperty support is optional so
134 // ignore any failures.
135 //
136
138
139
140 if ((osVersionInfo.wProductType != VER_NT_DOMAIN_CONTROLLER) &&
141 (osVersionInfo.wProductType != VER_NT_SERVER)) {
142
143 // this is Client SKU
144
145 minWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Client;
146
147 // Note: the reason we use max here is to guarantee a reasonable large max number
148 // in the case where the port driver may return a very small supported outstanding
149 // IOs. For example, even EMMC drive only reports 1 outstanding IO supported, we
150 // may still want to set this value to be at least
151 // MAX_WORKINGSET_TRANSFER_PACKETS_Client.
152 maxWorkingSetTransferPackets = max(MAX_WORKINGSET_TRANSFER_PACKETS_Client,
153 2 * maxOutstandingIOPerLUN);
154
155 } else {
156
157 // this is Server SKU
158 // Note: the addition max here to make sure we set the min to be at least
159 // MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound no matter what maxOutstandingIOPerLUN
160 // reported. We shouldn't set this value to be smaller than client system.
161 // In other words, the minWorkingSetTransferPackets for server will always between
162 // MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound and MIN_WORKINGSET_TRANSFER_PACKETS_Server_UpperBound
163
164 minWorkingSetTransferPackets =
167 maxOutstandingIOPerLUN));
168
169 maxWorkingSetTransferPackets = max(MAX_WORKINGSET_TRANSFER_PACKETS_Server,
170 2 * maxOutstandingIOPerLUN);
171 }
172
173
174 fdoData->LocalMinWorkingSetTransferPackets = minWorkingSetTransferPackets;
175 fdoData->LocalMaxWorkingSetTransferPackets = maxWorkingSetTransferPackets;
176
177 //
178 // Allow class driver to override the settings
179 //
180 if (commonExt->DriverExtension->WorkingSet != NULL) {
181 PCLASS_WORKING_SET workingSet = commonExt->DriverExtension->WorkingSet;
182
183 // override only if non-zero
184 if (workingSet->XferPacketsWorkingSetMinimum != 0)
185 {
186 fdoData->LocalMinWorkingSetTransferPackets = workingSet->XferPacketsWorkingSetMinimum;
187 // adjust maximum upwards if needed
189 {
191 }
192 }
193 // override only if non-zero
194 if (workingSet->XferPacketsWorkingSetMaximum != 0)
195 {
196 fdoData->LocalMaxWorkingSetTransferPackets = workingSet->XferPacketsWorkingSetMaximum;
197 // adjust minimum downwards if needed
199 {
201 }
202 }
203 // that's all the adjustments required/allowed
204 } // end working set size special code
205
206 for (index = 0; index < arraySize; index++) {
208 PTRANSFER_PACKET pkt = NewTransferPacket(Fdo);
209 if (pkt) {
211 pkt->AllocateNode = index;
213 } else {
215 break;
216 }
217 }
219 }
220
221 //
222 // Pre-initialize our SCSI_REQUEST_BLOCK template with all
223 // the constant fields. This will save a little time for each xfer.
224 // NOTE: a CdbLength field of 10 may not always be appropriate
225 //
226
227 if (NT_SUCCESS(status)) {
228 if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
229 ULONG ByteSize = 0;
230
231 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
232 if ((fdoExt->MiniportDescriptor != NULL) &&
233 (fdoExt->MiniportDescriptor->Size >= RTL_SIZEOF_THROUGH_FIELD(STORAGE_MINIPORT_DESCRIPTOR, ExtraIoInfoSupported)) &&
234 (fdoExt->MiniportDescriptor->ExtraIoInfoSupported == TRUE)) {
236 fdoExt->AdapterDescriptor->AddressType,
238 &ByteSize,
239 2,
242 );
243 } else {
245 fdoExt->AdapterDescriptor->AddressType,
247 &ByteSize,
248 1,
250 );
251 }
252 #else
254 fdoExt->AdapterDescriptor->AddressType,
256 &ByteSize,
257 1,
259 );
260 #endif
261 if (NT_SUCCESS(status)) {
263 } else {
265 }
266 } else {
267 fdoData->SrbTemplate = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(SCSI_REQUEST_BLOCK), '-brs');
268 if (fdoData->SrbTemplate == NULL) {
270 } else {
272 fdoData->SrbTemplate->Length = sizeof(SCSI_REQUEST_BLOCK);
273 fdoData->SrbTemplate->Function = SRB_FUNCTION_EXECUTE_SCSI;
274 }
275 }
276 }
277
278 if (status == STATUS_SUCCESS) {
281 SrbSetCdbLength(fdoData->SrbTemplate, 10);
282 }
283
284 return status;
285}
NTSTATUS CreateStorageRequestBlock(_Inout_ PSTORAGE_REQUEST_BLOCK *Srb, _In_ USHORT AddressType, _In_opt_ PSRB_ALLOCATE_ROUTINE AllocateRoutine, _Inout_opt_ ULONG *ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:249
#define MAX_OUTSTANDING_IO_PER_LUN_DEFAULT
Definition: classp.h:638
#define MAX_WORKINGSET_TRANSFER_PACKETS_Client
Definition: classp.h:632
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound
Definition: classp.h:634
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server_UpperBound
Definition: classp.h:633
#define MIN_INITIAL_TRANSFER_PACKETS
Definition: classp.h:630
#define MAX_WORKINGSET_TRANSFER_PACKETS_Server
Definition: classp.h:635
PVOID DefaultStorageRequestBlockAllocateRoutine(_In_ CLONG ByteSize)
Definition: srblib.c:28
#define MIN_WORKINGSET_TRANSFER_PACKETS_Client
Definition: classp.h:631
NTSTATUS NTAPI RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)
Definition: version.c:158
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
@ StorageDeviceIoCapabilityProperty
Definition: ntddstor.h:534
* PSTORAGE_DEVICE_IO_CAPABILITY_DESCRIPTOR
Definition: ntddstor.h:695
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:596
PCLASS_WORKING_SET WorkingSet
Definition: classpnp.h:588
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
ULONG dwOSVersionInfoSize
Definition: rtltypes.h:269
UCHAR wProductType
Definition: rtltypes.h:278
FORCEINLINE VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3368
#define VER_NT_SERVER
#define VER_NT_DOMAIN_CONTROLLER
struct _OSVERSIONINFOEXW OSVERSIONINFOEXW
VOID EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, __drv_aliasesMem PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:529

Referenced by ClassPnpStartDevice().

◆ InitLowMemRetry()

VOID InitLowMemRetry ( PTRANSFER_PACKET  Pkt,
PVOID  BufPtr,
ULONG  Len,
LARGE_INTEGER  TargetLocation 
)

Definition at line 670 of file retry.c.

671{
672 NT_ASSERT(Len > 0);
674
676 {
677 /*
678 * special case: StartIO-based writing must stay serialized for performance
679 * and proper operations (i.e. sequential writing mode). If need more than
680 * one transfer to perform this operation, and it's a StartIO-based driver
681 * (such as CDROM), then just use a single packet and use the retry logic
682 * that's already built-in to the packet engine. Note that low-mem retry
683 * cannot be used directly because some write methods do not work if the
684 * writes are only PAGE_SIZE (i.e. packet writing may corrupt data).
685 */
687 }
688 else
689 {
691 }
695}
#define Len
Definition: deflate.h:82
PUCHAR LowMemRetry_remainingBufPtr
Definition: classp.h:545
LARGE_INTEGER LowMemRetry_nextChunkTargetLocation
Definition: classp.h:547
BOOLEAN DriverUsesStartIO
Definition: classp.h:543
ULONG LowMemRetry_remainingBufLen
Definition: classp.h:546
BOOLEAN InLowMemRetry
Definition: classp.h:544

Referenced by RetryTransferPacket(), and ServiceTransferRequest().

◆ 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
@ RemovableMedia
Definition: ntdddisk.h:382
@ FixedMedia
Definition: ntdddisk.h:383
#define WHICH_BIT(Data, Bit)
Definition: tools.h:80
MEDIA_TYPE MediaType
Definition: ntdddisk.h:401
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:400
ULONG TracksPerCylinder
Definition: ntdddisk.h:402
ULONG SectorsPerTrack
Definition: ntdddisk.h:403
LARGE_INTEGER LogicalBlockAddress
Definition: scsi.h:2749

Referenced by ClassReadDriveCapacity().

◆ InterpretReadCapacity16Data()

NTSTATUS InterpretReadCapacity16Data ( _Inout_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
_In_ PREAD_CAPACITY16_DATA  ReadCapacity16Data 
)

Definition at line 1517 of file utils.c.

1521{
1523 USHORT lowestAlignedBlock;
1524 USHORT logicalBlocksPerPhysicalBlock;
1525 PCLASS_READ_CAPACITY16_DATA cachedData = &(FdoExtension->FunctionSupportInfo->ReadCapacity16Data);
1526
1527 // use Logical Sector Size from DiskGeometry to avoid duplicated calculation.
1528 FdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerLogicalSector = ClasspCalculateLogicalSectorSize(FdoExtension->DeviceObject, ReadCapacity16Data->BytesPerBlock);
1529
1530 // FdoExtension->DiskGeometry.BytesPerSector might be 0 for class drivers that don't get READ CAPACITY info yet.
1531 NT_ASSERT( (FdoExtension->DiskGeometry.BytesPerSector == 0) ||
1532 (FdoExtension->DiskGeometry.BytesPerSector == FdoExtension->FunctionSupportInfo->ReadCapacity16Data.BytesPerLogicalSector) );
1533
1534 logicalBlocksPerPhysicalBlock = 1 << ReadCapacity16Data->LogicalPerPhysicalExponent;
1535 lowestAlignedBlock = (ReadCapacity16Data->LowestAlignedBlock_MSB << 8) | ReadCapacity16Data->LowestAlignedBlock_LSB;
1536
1537 if (lowestAlignedBlock > logicalBlocksPerPhysicalBlock) {
1538 // we get garbage data
1540 } else {
1541 // value of lowestAlignedBlock (from T10 spec) needs to be converted.
1542 lowestAlignedBlock = (logicalBlocksPerPhysicalBlock - lowestAlignedBlock) % logicalBlocksPerPhysicalBlock;
1543 }
1544
1545 if (NT_SUCCESS(status)) {
1546 // fill output buffer
1547 cachedData->BytesPerPhysicalSector = cachedData->BytesPerLogicalSector * logicalBlocksPerPhysicalBlock;
1548 cachedData->BytesOffsetForSectorAlignment = cachedData->BytesPerLogicalSector * lowestAlignedBlock;
1549
1550 //
1551 // Fill in the Logical Block Provisioning info. Note that we do not
1552 // use these fields; we use the Provisioning Type and LBPRZ fields from
1553 // the Logical Block Provisioning VPD page (0xB2).
1554 //
1555 cachedData->LBProvisioningEnabled = ReadCapacity16Data->LBPME;
1556 cachedData->LBProvisioningReadZeros = ReadCapacity16Data->LBPRZ;
1557
1558 TracePrint((TRACE_LEVEL_INFORMATION,
1559 TRACE_FLAG_INIT,
1560 "InterpretReadCapacity16Data: Device\'s LBP enabled = %d\n",
1561 cachedData->LBProvisioningEnabled));
1562 }
1563
1564 return status;
1565}
ULONG ClasspCalculateLogicalSectorSize(_In_ PDEVICE_OBJECT Fdo, _In_ ULONG BytesPerBlockInBigEndian)
Definition: utils.c:1483

Referenced by ClassReadCapacity16().

◆ 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
VOID ClasspConvertToScsiRequestBlock(_Out_ PSCSI_REQUEST_BLOCK Srb, _In_ PSTORAGE_REQUEST_BLOCK SrbEx)
Definition: utils.c:6559
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR MajorFunctionCode
Definition: classpnp.h:484
#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
_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

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

◆ InterpretTransferPacketError()

BOOLEAN InterpretTransferPacketError ( PTRANSFER_PACKET  Pkt)

Definition at line 40 of file retry.c.

41{
43 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
44 ULONG timesAlreadyRetried;
45 BOOLEAN shouldRetry = FALSE;
47
48 /*
49 * Interpret the error using the returned sense info first.
50 */
51 Pkt->RetryIn100nsUnits = 0;
52
53
54 /*
55 * Pre-calculate the number of times the IO has already been
56 * retried, so that all InterpretSenseInfo routines get the right value.
57 */
58 if (ClasspTransferPacketGetNumberOfRetriesDone(Pkt, pCdb, &timesAlreadyRetried) == FALSE)
59 {
60 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "Unhandled SRB Function %xh in error path for packet %p (did miniport change Srb.Cdb.OperationCode ?)", (ULONG)pCdb->CDB10.OperationCode, Pkt));
61 }
62
63 if (fdoData->InterpretSenseInfo != NULL) {
64
65 SCSI_REQUEST_BLOCK tempSrb = { 0 };
67
68 // SAL annotation and ClassInitializeEx() both validate this
70
71 //
72 // If class driver does not support extended SRB and this is
73 // an extended SRB, convert to legacy SRB and pass to class
74 // driver.
75 //
76 if ((Pkt->Srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) &&
80 srbPtr = &tempSrb;
81 }
82
83 shouldRetry = fdoData->InterpretSenseInfo->Interpret(Pkt->Fdo,
85 srbPtr,
87 0,
88 timesAlreadyRetried,
91 &Pkt->RetryIn100nsUnits);
92
93
94 } else {
95
96 //
97 // In this case, fdoData->InterpretSenseInfo == NULL so we must do our
98 // own error code and sense info processing.
99 //
100
104 UCHAR senseKey = 0;
106 UCHAR additionalSenseQual = 0;
107
109
110 validSense = ScsiGetSenseKeyAndCodes(senseInfoBuffer,
111 senseInfoBufferLength,
113 &senseKey,
115 &additionalSenseQual);
116
117 if (pCdb->MEDIA_REMOVAL.OperationCode == SCSIOP_MEDIUM_REMOVAL) {
118
119 ULONG retryIntervalSeconds = 0;
120 /*
121 * This is an Ejection Control SRB. Interpret its sense info specially.
122 */
123 shouldRetry = ClassInterpretSenseInfo(
124 Pkt->Fdo,
127 0,
128 timesAlreadyRetried,
130 &retryIntervalSeconds);
131
132 if (shouldRetry) {
133 /*
134 * If the device is not ready, wait at least 2 seconds before retrying.
135 */
136 BOOLEAN setRetryIntervalSeconds = FALSE;
137
138 if (validSense) {
139
142 setRetryIntervalSeconds = TRUE;
143 }
144 }
145
146 if (!setRetryIntervalSeconds && (SRB_STATUS(Pkt->Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)) {
147 setRetryIntervalSeconds = TRUE;
148 }
149
150 if (setRetryIntervalSeconds) {
151 retryIntervalSeconds = MAX(retryIntervalSeconds, 2);
152 }
153 }
154
155 if (shouldRetry)
156 {
157 Pkt->RetryIn100nsUnits = retryIntervalSeconds;
158 Pkt->RetryIn100nsUnits *= 1000 * 1000 * 10;
159 }
160
161 }
162 else if ((pCdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE) ||
163 (pCdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE10)) {
164
165 ULONG retryIntervalSeconds = 0;
166 /*
167 * This is an Mode Sense SRB. Interpret its sense info specially.
168 */
169 shouldRetry = ClassInterpretSenseInfo(
170 Pkt->Fdo,
173 0,
174 timesAlreadyRetried,
176 &retryIntervalSeconds);
177 if (shouldRetry) {
178 /*
179 * If the device is not ready, wait at least 2 seconds before retrying.
180 */
181 BOOLEAN setRetryIntervalSeconds = FALSE;
182
183 if (validSense) {
186 setRetryIntervalSeconds = TRUE;
187 }
188 }
189
190 if (!setRetryIntervalSeconds && (SRB_STATUS(Pkt->Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)) {
191 setRetryIntervalSeconds = TRUE;
192 }
193
194 if (setRetryIntervalSeconds) {
195 retryIntervalSeconds = MAX(retryIntervalSeconds, 2);
196 }
197 }
198
199 /*
200 * Some special cases for mode sense.
201 */
203 shouldRetry = TRUE;
204 }
205 else if (SRB_STATUS(Pkt->Srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
206 /*
207 * This is a HACK.
208 * Atapi returns SRB_STATUS_DATA_OVERRUN when it really means
209 * underrun (i.e. success, and the buffer is longer than needed).
210 * So treat this as a success.
211 * When the caller of this function sees that the status was changed to success,
212 * it will add the transferred length to the original irp.
213 */
215 shouldRetry = FALSE;
216 }
217
218 if (shouldRetry)
219 {
220 Pkt->RetryIn100nsUnits = retryIntervalSeconds;
221 Pkt->RetryIn100nsUnits *= 1000 * 1000 * 10;
222 }
223
224 }
225 else if ((pCdb->CDB10.OperationCode == SCSIOP_READ_CAPACITY) ||
226 (pCdb->CDB16.OperationCode == SCSIOP_READ_CAPACITY16)) {
227
228 ULONG retryIntervalSeconds = 0;
229
230 /*
231 * This is a Drive Capacity SRB. Interpret its sense info specially.
232 */
233 shouldRetry = ClassInterpretSenseInfo(
234 Pkt->Fdo,
237 0,
238 timesAlreadyRetried,
240 &retryIntervalSeconds);
242 shouldRetry = TRUE;
243 }
244#if (NTDDI_VERSION >= NTDDI_WINBLUE)
245 else if (ClasspSrbTimeOutStatus(Pkt->Srb)) {
246
247 Pkt->TimedOut = TRUE;
248
249 if (shouldRetry) {
250 //
251 // For requests that have timed-out we may only perform a limited
252 // number of retries. This is typically less than the general
253 // number of retries allowed.
254 //
255 if (Pkt->NumIoTimeoutRetries == 0) {
256 shouldRetry = FALSE;
257 } else {
259 //
260 // We expect to be able to retry if there are some general retries remaining.
261 //
262 }
263 }
264 }
265#endif
266
267 if (shouldRetry)
268 {
269 Pkt->RetryIn100nsUnits = retryIntervalSeconds;
270 Pkt->RetryIn100nsUnits *= 1000 * 1000 * 10;
271 }
272
273 }
274 else if (IS_SCSIOP_READWRITE(pCdb->CDB10.OperationCode)) {
275
276 ULONG retryIntervalSeconds = 0;
277 /*
278 * This is a Read/Write Data packet.
279 */
281
282 shouldRetry = ClassInterpretSenseInfo(Pkt->Fdo,
284 origCurrentSp->MajorFunction,
285 0,
286 timesAlreadyRetried,
288 &retryIntervalSeconds);
289
290 /*
291 * Deal with some special cases.
292 */
294 /*
295 * We are in extreme low-memory stress.
296 * We will retry in smaller chunks.
297 */
298 shouldRetry = TRUE;
299 }
300 else if (TEST_FLAG(origCurrentSp->Flags, SL_OVERRIDE_VERIFY_VOLUME) &&
302 /*
303 * We are still verifying a (possibly) reloaded disk/cdrom.
304 * So retry the request.
305 */
307 shouldRetry = TRUE;
308
309 }
310#if (NTDDI_VERSION >= NTDDI_WINBLUE)
311 else if (ClasspSrbTimeOutStatus(Pkt->Srb)) {
312
313 Pkt->TimedOut = TRUE;
314
315 if (shouldRetry) {
316 //
317 // For requests that have timed-out we may only perform a limited
318 // number of retries. This is typically less than the general
319 // number of retries allowed.
320 //
321 if (Pkt->NumIoTimeoutRetries == 0) {
322 shouldRetry = FALSE;
323 } else {
325 //
326 // We expect to be able to retry if there are some general retries remaining.
327 //
328 }
329 }
330 }
331#endif
332
333 if (shouldRetry)
334 {
335 Pkt->RetryIn100nsUnits = retryIntervalSeconds;
336 Pkt->RetryIn100nsUnits *= 1000 * 1000 * 10;
337 }
338
339 } else if (ClasspIsOffloadDataTransferCommand(pCdb)) {
340
341 ULONG retryIntervalSeconds = 0;
342
343 Pkt->TransferCount = 0;
344
345 shouldRetry = ClassInterpretSenseInfo(
346 Pkt->Fdo,
349 0,
350 timesAlreadyRetried,
352 &retryIntervalSeconds);
353
354 if (shouldRetry) {
355
356 Pkt->RetryIn100nsUnits = retryIntervalSeconds;
357 Pkt->RetryIn100nsUnits *= 1000 * 1000 * 10;
358
359 } else {
360
361 if (ClasspIsTokenOperation(pCdb)) {
362
363 BOOLEAN isInformationValid = FALSE;
365
366 if (validSense) {
367
368 //
369 // If this is a data underrun condition (i.e. target truncated the offload data transfer),
370 // the SenseData's Information field may have the TransferCount.
371 //
374
375 //
376 // Sense data in Descriptor format
377 //
379
380 PVOID startBuffer = NULL;
381 UCHAR startBufferLength = 0;
382
383
384 if (ScsiGetSenseDescriptor(senseInfoBuffer,
386 &startBuffer,
387 &startBufferLength)) {
388 UCHAR outType;
390 UCHAR outBufferLength = 0;
391
393
394 if (ScsiGetNextSenseDescriptorByType(startBuffer,
395 startBufferLength,
396 typeList,
397 ARRAYSIZE(typeList),
398 &outType,
399 &outBuffer,
400 &outBufferLength)) {
401
403
404 if (ScsiValidateInformationSenseDescriptor(outBuffer, outBufferLength)) {
406 isInformationValid = TRUE;
407 }
408
409 } else {
410
411 //
412 // ScsiGetNextDescriptorByType should only return a type that is specified by us.
413 //
415 }
416 }
417 }
418 } else {
419
420 //
421 // Sense data in Fixed format
422 //
424 isInformationValid = TRUE;
425 }
426
427 if (isInformationValid) {
429 }
430 }
431 }
432 }
433 }
434
435 }
436 else {
437 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "Unhandled SRB Function %xh in error path for packet %p (did miniport change Srb.Cdb.OperationCode ?)", (ULONG)pCdb->CDB10.OperationCode, Pkt));
438 }
439 }
440
441 return shouldRetry;
442}
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define SCSI_SENSE_COPY_ABORTED
Definition: cdrw_hw.h:1197
#define SCSI_SENSE_ABORTED_COMMAND
Definition: cdrw_hw.h:1198
FORCEINLINE BOOLEAN ClasspIsOffloadDataTransferCommand(_In_ PCDB Cdb)
Definition: classp.h:2087
FORCEINLINE BOOLEAN ClasspTransferPacketGetNumberOfRetriesDone(_In_ PTRANSFER_PACKET Pkt, _In_ PCDB Cdb, _Out_ PULONG TimesAlreadyRetried)
Definition: classp.h:2459
FORCEINLINE PCDB ClasspTransferPacketGetCdb(_In_ PTRANSFER_PACKET Pkt)
Definition: classp.h:2445
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
UCHAR additionalSenseCode
Definition: scsi.h:4020
#define SCSI_SENSE_DESCRIPTOR_TYPE_INFORMATION
Definition: scsi.h:630
#define SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED
Definition: scsi.h:3839
#define SCSI_ADSENSE_COPY_TARGET_DEVICE_ERROR
Definition: scsi.h:657
#define SCSI_SENSEQ_DATA_UNDERRUN
Definition: scsi.h:761
PFIXED_SENSE_DATA outBuffer
Definition: scsi.h:4022
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
UCHAR NumIoTimeoutRetries
Definition: classp.h:518
PIRP OriginalIrp
Definition: classp.h:509
UCHAR TimedOut
Definition: classp.h:519
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823

Referenced by TransferPktComplete().

◆ PORT_ALLOCATED_SENSE_EX()

◆ RetryRequest()

VOID RetryRequest ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp,
PSCSI_REQUEST_BLOCK  Srb,
BOOLEAN  Associated,
LONGLONG  TimeDelta100ns 
)

Definition at line 359 of file obsolete.c.

366{
369 ULONG transferByteCount;
370 ULONG dataTransferLength;
372
373 // This function is obsolete but is still used by some of our class drivers.
374 // TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "RetryRequest is OBSOLETE !"));
375
376 //
377 // Determine the transfer count of the request. If this is a read or a
378 // write then the transfer count is in the Irp stack. Otherwise assume
379 // the MDL contains the correct length. If there is no MDL then the
380 // transfer length must be zero.
381 //
382
383 dataTransferLength = SrbGetDataTransferLength(srbHeader);
384 if (currentIrpStack->MajorFunction == IRP_MJ_READ ||
385 currentIrpStack->MajorFunction == IRP_MJ_WRITE) {
386
387 _Analysis_assume_(currentIrpStack->Parameters.Read.Length <= dataTransferLength);
388 transferByteCount = currentIrpStack->Parameters.Read.Length;
389
390 } else if (Irp->MdlAddress != NULL) {
391
392 //
393 // Note this assumes that only read and write requests are spilt and
394 // other request do not need to be. If the data buffer address in
395 // the MDL and the SRB don't match then transfer length is most
396 // likely incorrect.
397 //
398
399 NT_ASSERT(SrbGetDataBuffer(srbHeader) == MmGetMdlVirtualAddress(Irp->MdlAddress));
400 _Analysis_assume_(Irp->MdlAddress->ByteCount <= dataTransferLength);
401 transferByteCount = Irp->MdlAddress->ByteCount;
402
403 } else {
404
405 transferByteCount = 0;
406 }
407
408 //
409 // this is a safety net. this should not normally be hit, since we are
410 // not guaranteed to be an fdoExtension
411 //
412
414
415 //
416 // Reset byte count of transfer in SRB Extension.
417 //
418
419 SrbSetDataTransferLength(srbHeader, transferByteCount);
420
421 //
422 // Zero SRB statuses.
423 //
424
425 srbHeader->SrbStatus = 0;
426 SrbSetScsiStatus(srbHeader, 0);
427
428 //
429 // If this is the last retry, then disable all the special flags.
430 //
431
432 if ( 0 == (ULONG)(ULONG_PTR)currentIrpStack->Parameters.Others.Argument4 ) {
433 //
434 // Set the no disconnect flag, disable synchronous data transfers and
435 // disable tagged queuing. This fixes some errors.
436 // NOTE: Cannot clear these flags, just add to them
437 //
438
439 SrbSetSrbFlags(srbHeader,
442
443 SrbSetQueueTag(srbHeader, SP_UNTAGGED);
444 }
445
446
447 //
448 // Set up major SCSI function.
449 //
450
451 nextIrpStack->MajorFunction = IRP_MJ_SCSI;
452
453 //
454 // Save SRB address in next stack for port driver.
455 //
456
457 nextIrpStack->Parameters.Scsi.Srb = Srb;
458
459 if (Associated){
461 }
462 else {
464 }
465
466 ClassRetryRequest(DeviceObject, Irp, TimeDelta100ns);
467 return;
468} // end RetryRequest()
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: class.c:12317
NTSTATUS NTAPI ClassIoCompleteAssociated(IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN PVOID Context)
Definition: obsolete.c:111
FORCEINLINE VOID SrbSetQueueTag(_In_ PVOID Srb, _In_ ULONG QueueTag)
Definition: srbhelper.h:853
FORCEINLINE PVOID SrbGetDataBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:728

Referenced by ClassIoComplete(), ClassIoCompleteAssociated(), and ClassReadDriveCapacity().

◆ RetryTransferPacket()

BOOLEAN RetryTransferPacket ( PTRANSFER_PACKET  Pkt)

Definition at line 453 of file retry.c.

454{
455 BOOLEAN packetDone;
456 BOOLEAN scaleDown = FALSE;
458 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
459 PCDB pCdb = SrbGetCdb(Pkt->Srb);
460
461#if !defined(__REACTOS__) && NTDDI_VERSION >= NTDDI_WINBLUE
463 (pCdb != NULL) && IS_SCSIOP_READWRITE(pCdb->CDB10.OperationCode)) {
464
466 //We've already retried this the maximum times. Bail out.
467 return TRUE;
468 }
470 }
471 else {
473 Pkt->NumRetries--;
474 }
475#else
477 Pkt->NumRetries--;
478#endif
479
480 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "retrying failed transfer (pkt=%ph, op=%s)", Pkt, DBGGETSCSIOPSTR(Pkt->Srb)));
481
482 if (!fdoData->DisableThrottling) {
483
484 //
485 // If this is the last retry, then turn off disconnect, sync transfer,
486 // and tagged queuing. On all other retries, leave the original settings.
487 // Do not apply this for thin provisioning soft threshold errors, since
488 // they should succeed as soon as they're retried on the right IT nexus.
489 //
491 scaleDown = TRUE;
492 }
493
494#if (NTDDI_VERSION >= NTDDI_WINBLUE)
495 //
496 // If this request previously timed-out and there are no more retries left
497 // for timed-out requests, then we should also apply the scale down.
498 //
499 if (Pkt->TimedOut && Pkt->NumIoTimeoutRetries == 0) {
500 scaleDown = TRUE;
501 }
502#endif
503 }
504
505
506 if (scaleDown) {
507 /*
508 * Tone down performance on the retry.
509 * This increases the chance for success on the retry.
510 * We've seen instances of drives that fail consistently but then start working
511 * once this scale-down is applied.
512 */
517 }
518
520
521 UCHAR cdbOpcode = 0;
522 BOOLEAN isReadWrite = FALSE;
523
524 if (pCdb) {
525 cdbOpcode = pCdb->CDB10.OperationCode;
526 isReadWrite = IS_SCSIOP_READWRITE(cdbOpcode);
527 }
528
529 if ((Pkt->DriverUsesStartIO) &&
530 ( (cdbOpcode == SCSIOP_WRITE6 ) ||
531 (cdbOpcode == SCSIOP_WRITE ) ||
532 (cdbOpcode == SCSIOP_WRITE12) ||
533 (cdbOpcode == SCSIOP_WRITE16) )) {
534
535 /* don't retry writes in super-low-memory conditions if the
536 * driver must serialize against StartIO. This is because
537 * some write methods used in such drivers cannot accept
538 * random-sized writes. (i.e CD-RW in packet writing mode)
539 * Reads, however, are always safe to split up.
540 */
541 SET_FLAG(fdoData->TrackingFlags, TRACKING_FORWARD_PROGRESS_PATH1);
542 packetDone = TRUE;
543 }
544 else if (Pkt->InLowMemRetry || !isReadWrite){
545 /*
546 * This should never happen under normal circumstances.
547 * The memory manager guarantees that at least four pages will
548 * be available to allow forward progress in the port driver.
549 * So a one-page transfer should never fail with insufficient resources.
550 *
551 * However, it is possible to get in here with virtual storage
552 * or thin provisioned storage for example.
553 * A single sector write can trigger an allocation request and
554 * presently a forward progress guarantee is not provided.
555 * VHD also may have some limitations in forward progress guarantee.
556 * And USB too might also fall into this category.
557 */
558 SET_FLAG(fdoData->TrackingFlags, TRACKING_FORWARD_PROGRESS_PATH2);
559 packetDone = TRUE;
560 }
561 else {
562 /*
563 * We are in low-memory stress.
564 * Start the low-memory retry state machine, which tries to
565 * resend the packet in little one-page chunks.
566 */
567 SET_FLAG(fdoData->TrackingFlags, TRACKING_FORWARD_PROGRESS_PATH3);
573 packetDone = FALSE;
574 }
575 }
576 else {
577 /*
578 * Retry the packet by simply resending it after a delay.
579 * Put the packet back in the pending queue and
580 * schedule a timer to retry the transfer.
581 *
582 * Do not call SetupReadWriteTransferPacket again because:
583 * (1) The minidriver may have set some bits
584 * in the SRB that it needs again and
585 * (2) doing so would reset numRetries.
586 *
587 * BECAUSE we do not call SetupReadWriteTransferPacket again,
588 * we have to reset a couple fields in the SRB that
589 * some miniports overwrite when they fail an SRB.
590 */
591
594
596
597 packetDone = FALSE;
598 }
599
600 return packetDone;
601}
#define SCSIOP_WRITE6
Definition: cdrw_hw.h:876
#define SCSIOP_WRITE12
Definition: cdrw_hw.h:957
#define NUM_THIN_PROVISIONING_RETRIES
Definition: classp.h:162
#define TRACKING_FORWARD_PROGRESS_PATH3
Definition: classp.h:2387
BOOLEAN ClasspIsThinProvisioningError(_In_ PSCSI_REQUEST_BLOCK _Srb)
Definition: utils.c:9127
#define TRACKING_FORWARD_PROGRESS_PATH2
Definition: classp.h:2386
#define TRACKING_FORWARD_PROGRESS_PATH1
Definition: classp.h:2385
#define DBGGETSCSIOPSTR(_pSrb)
Definition: debug.h:26
#define SCSIOP_WRITE16
Definition: scsi.h:915
BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt)
Definition: retry.c:706
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
LARGE_INTEGER TargetLocationCopy
Definition: classp.h:564
UCHAR NumThinProvisioningRetries
Definition: classp.h:517
ULONG BufLenCopy
Definition: classp.h:563
PUCHAR BufPtrCopy
Definition: classp.h:562

Referenced by TransferPktComplete().

◆ 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}
BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt)
Definition: retry.c:706
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
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
static int priority
Definition: timer.c:163
#define IsKeyReadCopyNumber(_k)
Definition: ntddstor.h:1072
IO_PAGING_PRIORITY FASTCALL IoGetPagingIoPriority(IN PIRP Irp)
Definition: irp.c:1748
#define STATUS_FT_READ_FROM_COPY
Definition: ntstatus.h:167
PDRIVER_STARTIO ClassStartIo
Definition: classpnp.h:543
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
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().

◆ SetupDriveCapacityTransferPacket()

VOID SetupDriveCapacityTransferPacket ( TRANSFER_PACKET Pkt,
PVOID  ReadCapacityBuffer,
ULONG  ReadCapacityBufferLen,
PKEVENT  SyncEventPtr,
PIRP  OriginalIrp,
BOOLEAN  Use16ByteCdb 
)

Definition at line 1480 of file xferpkt.c.

1486{
1488 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1489 PCDB pCdb;
1490 ULONG srbLength;
1491 ULONG timeoutValue = fdoExt->TimeOutValue;
1492
1493 if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1494 srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1495 NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1496 } else {
1497 srbLength = fdoData->SrbTemplate->Length;
1498 }
1499 RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1500
1505
1506
1507 SrbSetTimeOutValue(Pkt->Srb, timeoutValue);
1509 SrbSetDataTransferLength(Pkt->Srb, ReadCapacityBufferLen);
1510
1512
1513 pCdb = SrbGetCdb(Pkt->Srb);
1514 if (pCdb) {
1515 if (Use16ByteCdb == TRUE) {
1516 NT_ASSERT(ReadCapacityBufferLen >= sizeof(READ_CAPACITY_DATA_EX));
1517 SrbSetCdbLength(Pkt->Srb, 16);
1518 pCdb->CDB16.OperationCode = SCSIOP_READ_CAPACITY16;
1519 REVERSE_BYTES(&pCdb->CDB16.TransferLength, &ReadCapacityBufferLen);
1520 pCdb->AsByte[1] = 0x10; // Service Action
1521 } else {
1522 SrbSetCdbLength(Pkt->Srb, 10);
1523 pCdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
1524 }
1525 }
1526
1528 Pkt->BufLenCopy = ReadCapacityBufferLen;
1529
1532#if !defined(__REACTOS__) && NTDDI_VERSION >= NTDDI_WINBLUE
1534#endif
1535
1536 Pkt->SyncEventPtr = SyncEventPtr;
1538}
_In_ PREAD_CAPACITY_DATA ReadCapacityBuffer
Definition: cdrom.h:1103
_In_ PTRANSFER_PACKET _In_ ULONG _In_ PIRP OriginalIrp
Definition: classp.h:1757
SENSE_DATA_EX SrbErrorSenseData
Definition: classp.h:570
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes
Definition: classp.h:510
PKEVENT SyncEventPtr
Definition: classp.h:535

Referenced by ClassReadDriveCapacity().

◆ SetupEjectionTransferPacket()

VOID SetupEjectionTransferPacket ( TRANSFER_PACKET Pkt,
BOOLEAN  PreventMediaRemoval,
PKEVENT  SyncEventPtr,
PIRP  OriginalIrp 
)

Definition at line 1315 of file xferpkt.c.

1319{
1321 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1322 PCDB pCdb;
1323 ULONG srbLength;
1324
1325 PAGED_CODE();
1326
1327 if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1328 srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1329 NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1330 } else {
1331 srbLength = fdoData->SrbTemplate->Length;
1332 }
1333 RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1334
1336 SrbSetCdbLength(Pkt->Srb, 6);
1341
1343
1344 pCdb = SrbGetCdb(Pkt->Srb);
1345 if (pCdb) {
1346 pCdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
1347 pCdb->MEDIA_REMOVAL.Prevent = PreventMediaRemoval;
1348 }
1349
1350 Pkt->BufPtrCopy = NULL;
1351 Pkt->BufLenCopy = 0;
1352
1355 Pkt->SyncEventPtr = SyncEventPtr;
1357}

◆ SetupModeSelectTransferPacket()

VOID SetupModeSelectTransferPacket ( TRANSFER_PACKET Pkt,
PKEVENT  SyncEventPtr,
PVOID  ModeSelectBuffer,
UCHAR  ModeSelectBufferLen,
BOOLEAN  SavePages,
PIRP  OriginalIrp 
)

Definition at line 1425 of file xferpkt.c.

1432{
1434 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1435 PCDB pCdb;
1436 ULONG srbLength;
1437
1438 if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1439 srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1440 NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1441 } else {
1442 srbLength = fdoData->SrbTemplate->Length;
1443 }
1444 RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1445
1447 SrbSetCdbLength(Pkt->Srb, 6);
1452 SrbSetDataBuffer(Pkt->Srb, ModeSelectBuffer);
1453 SrbSetDataTransferLength(Pkt->Srb, ModeSelectBufferLen);
1454
1456
1457 pCdb = SrbGetCdb(Pkt->Srb);
1458 if (pCdb) {
1459 pCdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
1460 pCdb->MODE_SELECT.SPBit = SavePages;
1461 pCdb->MODE_SELECT.PFBit = 1;
1462 pCdb->MODE_SELECT.ParameterListLength = (UCHAR)ModeSelectBufferLen;
1463 }
1464
1465 Pkt->BufPtrCopy = ModeSelectBuffer;
1466 Pkt->BufLenCopy = ModeSelectBufferLen;
1467
1470 Pkt->SyncEventPtr = SyncEventPtr;
1472}
#define SCSIOP_MODE_SELECT
Definition: cdrw_hw.h:891
#define NUM_MODESELECT_RETRIES
Definition: classp.h:160
struct _CDB::_MODE_SELECT MODE_SELECT

Referenced by ClasspModeSelect().

◆ SetupModeSenseTransferPacket()

VOID SetupModeSenseTransferPacket ( TRANSFER_PACKET Pkt,
PKEVENT  SyncEventPtr,
PVOID  ModeSenseBuffer,
UCHAR  ModeSenseBufferLen,
UCHAR  PageMode,
UCHAR  SubPage,
PIRP  OriginalIrp,
UCHAR  PageControl 
)

Definition at line 1365 of file xferpkt.c.

1374{
1376 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1377 PCDB pCdb;
1378 ULONG srbLength;
1379
1380 PAGED_CODE();
1381
1382 if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1383 srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1384 NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1385 } else {
1386 srbLength = fdoData->SrbTemplate->Length;
1387 }
1388 RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1389
1391 SrbSetCdbLength(Pkt->Srb, 6);
1396 SrbSetDataBuffer(Pkt->Srb, ModeSenseBuffer);
1397 SrbSetDataTransferLength(Pkt->Srb, ModeSenseBufferLen);
1398
1399
1401
1402 pCdb = SrbGetCdb(Pkt->Srb);
1403 if (pCdb) {
1404 pCdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
1405 pCdb->MODE_SENSE.PageCode = PageMode;
1406 pCdb->MODE_SENSE.SubPageCode = SubPage;
1407 pCdb->MODE_SENSE.Pc = PageControl;
1408 pCdb->MODE_SENSE.AllocationLength = (UCHAR)ModeSenseBufferLen;
1409 }
1410
1411 Pkt->BufPtrCopy = ModeSenseBuffer;
1412 Pkt->BufLenCopy = ModeSenseBufferLen;
1413
1416 Pkt->SyncEventPtr = SyncEventPtr;
1418}

Referenced by ClasspModeSense().

◆ SetupReadWriteTransferPacket()

VOID SetupReadWriteTransferPacket ( PTRANSFER_PACKET  pkt,
PVOID  Buf,
ULONG  Len,
LARGE_INTEGER  DiskLocation,
PIRP  OriginalIrp 
)

Definition at line 718 of file xferpkt.c.

723{
726 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
728 UCHAR majorFunc = origCurSp->MajorFunction;
729 LARGE_INTEGER logicalBlockAddr;
730 ULONG numTransferBlocks;
731 PCDB pCdb;
732 ULONG srbLength;
733 ULONG timeoutValue = fdoExt->TimeOutValue;
734
735 logicalBlockAddr.QuadPart = Int64ShrlMod32(DiskLocation.QuadPart, fdoExt->SectorShift);
736 numTransferBlocks = Len >> fdoExt->SectorShift;
737
738 /*
739 * This field is useful when debugging, since low-memory conditions are
740 * handled differently for CDROM (which is the only driver using StartIO)
741 */
743
744 /*
745 * Slap the constant SRB fields in from our pre-initialized template.
746 * We'll then only have to fill in the unique fields for this transfer.
747 * Tell lower drivers to sort the SRBs by the logical block address
748 * so that disk seeks are minimized.
749 */
750 if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
751 srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
752 NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
753 } else {
754 srbLength = fdoData->SrbTemplate->Length;
755 }
756 RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
757 SrbSetDataBuffer(Pkt->Srb, Buf);
759 SrbSetQueueSortKey(Pkt->Srb, logicalBlockAddr.LowPart);
760 if (logicalBlockAddr.QuadPart > 0xFFFFFFFF) {
761 //
762 // If the requested LBA is more than max ULONG set the
763 // QueueSortKey to the maximum value, so that these
764 // requests can be added towards the end of the queue.
765 //
766
767 SrbSetQueueSortKey(Pkt->Srb, 0xFFFFFFFF);
768 }
771
772
773 SrbSetTimeOutValue(Pkt->Srb, timeoutValue);
774
775 /*
776 * Arrange values in CDB in big-endian format.
777 */
778 pCdb = SrbGetCdb(Pkt->Srb);
779 if (pCdb) {
781 REVERSE_BYTES_QUAD(&pCdb->CDB16.LogicalBlock, &logicalBlockAddr);
782 REVERSE_BYTES(&pCdb->CDB16.TransferLength, &numTransferBlocks);
783 pCdb->CDB16.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ16 : SCSIOP_WRITE16;
784 SrbSetCdbLength(Pkt->Srb, 16);
785 } else {
786 pCdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte3;
787 pCdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte2;
788 pCdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte1;
789 pCdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte0;
790 pCdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1;
791 pCdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0;
792 pCdb->CDB10.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ : SCSIOP_WRITE;
793 }
794 }
795
796 /*
797 * Set SRB and IRP flags
798 */
800 if (TEST_FLAG(OriginalIrp->Flags, IRP_PAGING_IO) ||
803 }
805
806 /*
807 * Allow caching only if this is not a write-through request.
808 * If write-through and caching is enabled on the device, force
809 * media access.
810 * Ignore SL_WRITE_THROUGH for reads; it's only set because the file handle was opened with WRITE_THROUGH.
811 */
812 if ((majorFunc == IRP_MJ_WRITE) && TEST_FLAG(origCurSp->Flags, SL_WRITE_THROUGH) && pCdb) {
813 pCdb->CDB10.ForceUnitAccess = fdoExt->CdbForceUnitAccess;
814 } else {
816 }
817
818 /*
819 * Remember the buf and len in the SRB because miniports
820 * can overwrite SRB.DataTransferLength and we may need it again
821 * for the retry.
822 */
823 Pkt->BufPtrCopy = Buf;
824 Pkt->BufLenCopy = Len;
825 Pkt->TargetLocationCopy = DiskLocation;
826
831#if !defined(__REACTOS__) && NTDDI_VERSION >= NTDDI_WINBLUE
834#endif
835
836
837 if (pCdb) {
838 DBGLOGFLUSHINFO(fdoData, TRUE, (BOOLEAN)(pCdb->CDB10.ForceUnitAccess), FALSE);
839 } else {
840 DBGLOGFLUSHINFO(fdoData, TRUE, FALSE, FALSE);
841 }
842}
#define DEV_USE_16BYTE_CDB
Definition: classpnp.h:183
#define DBGLOGFLUSHINFO(_fdoData, _isIO, _isFUA, _isFlush)
Definition: debug.h:129
#define SCSIOP_READ16
Definition: scsi.h:914
ULONG LowPart
Definition: typedefs.h:106

Referenced by ServiceTransferRequest(), and StepLowMemRetry().

◆ SimpleInitSlistHdr()

FORCEINLINE VOID SimpleInitSlistHdr ( SINGLE_LIST_ENTRY SListHdr)

Definition at line 1211 of file classp.h.

1212{
1213 SListHdr->Next = NULL;
1214}
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:637

Referenced by CleanupTransferPacketToWorkingSetSize(), and ServiceTransferRequest().

◆ SimpleIsSlistEmpty()

FORCEINLINE BOOLEAN SimpleIsSlistEmpty ( SINGLE_LIST_ENTRY SListHdr)

Definition at line 1229 of file classp.h.

1230{
1231 return (SListHdr->Next == NULL);
1232}

Referenced by ServiceTransferRequest().

◆ SimplePopSlist()

FORCEINLINE SINGLE_LIST_ENTRY * SimplePopSlist ( SINGLE_LIST_ENTRY SListHdr)

Definition at line 1220 of file classp.h.

1221{
1222 SINGLE_LIST_ENTRY *sListEntry = SListHdr->Next;
1223 if (sListEntry){
1224 SListHdr->Next = sListEntry->Next;
1225 sListEntry->Next = NULL;
1226 }
1227 return sListEntry;
1228}

Referenced by CleanupTransferPacketToWorkingSetSize(), and ServiceTransferRequest().

◆ SimplePushSlist()

FORCEINLINE VOID SimplePushSlist ( SINGLE_LIST_ENTRY SListHdr,
SINGLE_LIST_ENTRY SListEntry 
)

Definition at line 1215 of file classp.h.

1216{
1217 SListEntry->Next = SListHdr->Next;
1218 SListHdr->Next = SListEntry;
1219}

Referenced by CleanupTransferPacketToWorkingSetSize(), and ServiceTransferRequest().

◆ StepLowMemRetry()

BOOLEAN StepLowMemRetry ( PTRANSFER_PACKET  Pkt)

Definition at line 706 of file retry.c.

707{
708 BOOLEAN packetDone;
709
711 packetDone = TRUE;
712 }
713 else {
714 ULONG thisChunkLen;
716 {
717 /*
718 * Need the fdoData for the HwMaxXferLen
719 */
721 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
722
723 /*
724 * Need the adapterDesc to limit transfers based on byte count
725 */
727 PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExtension->PartitionZeroExtension->AdapterDescriptor;
728
729 ULONG hwMaxXferLen;
730
731 /*
732 * special case: StartIO-based writing must stay serialized for performance
733 * and proper operations (i.e. sequential writing mode). If need more than
734 * one transfer to perform this operation, and it's a StartIO-based driver
735 * (such as CDROM), then just use a single packet and use the retry logic
736 * that's already built-in to the packet engine. Note that low-mem retry
737 * cannot be used directly because some write methods do not work if the
738 * writes are only PAGE_SIZE (i.e. packet writing may corrupt data).
739 */
741
742 /*
743 * We precomputed fdoData->HwMaxXferLen using (MaximumPhysicalPages-1).
744 * If the buffer is page-aligned, that's one less page crossing so we can add the page back in.
745 * Note: adapters that return MaximumPhysicalPages=0x10 depend on this to
746 * transfer aligned 64K requests in one piece.
747 * Also note: make sure adding PAGE_SIZE back in doesn't wrap to zero.
748 */
749
750 if (((ULONG_PTR)(Pkt->LowMemRetry_remainingBufPtr) & (PAGE_SIZE-1)) || (fdoData->HwMaxXferLen > 0xffffffff-PAGE_SIZE)){
751 hwMaxXferLen = fdoData->HwMaxXferLen;
752 }
753 else {
755 hwMaxXferLen = min(fdoData->HwMaxXferLen+PAGE_SIZE, adapterDesc->MaximumTransferLength);
756 }
757 thisChunkLen = MIN(Pkt->LowMemRetry_remainingBufLen, hwMaxXferLen);
758 }
759 else {
760 /*
761 * Make sure the little chunk we send is <= a page length
762 * AND that it does not cross any page boundaries.
763 */
764 ULONG bytesToNextPageBoundary;
765 bytesToNextPageBoundary = PAGE_SIZE-(ULONG)((ULONG_PTR)Pkt->LowMemRetry_remainingBufPtr%PAGE_SIZE);
766 thisChunkLen = MIN(Pkt->LowMemRetry_remainingBufLen, bytesToNextPageBoundary);
768 }
769
770
771 /*
772 * Set up the transfer packet for the new little chunk.
773 * This will reset numRetries so that we retry each chunk as required.
774 */
777 thisChunkLen,
780
781 Pkt->LowMemRetry_remainingBufPtr += thisChunkLen;
782 Pkt->LowMemRetry_remainingBufLen -= thisChunkLen;
784
785 //
786 // When running in low-memory stress, always use a partial MDL.
787 // This allows lower drivers to potentially map a smaller buffer.
788 //
790
792
793 packetDone = FALSE;
794 }
795
796 return packetDone;
797}

Referenced by RetryTransferPacket(), ServiceTransferRequest(), and TransferPktComplete().

◆ SubmitTransferPacket()

NTSTATUS SubmitTransferPacket ( PTRANSFER_PACKET  Pkt)

Definition at line 850 of file xferpkt.c.

851{
853 PDEVICE_OBJECT nextDevObj = commonExtension->LowerDeviceObject;
855 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
856 BOOLEAN idleRequest = FALSE;
857 PIO_STACK_LOCATION nextSp;
858
859 NT_ASSERT(Pkt->Irp->CurrentLocation == Pkt->Irp->StackCount+1);
860
861 /*
862 * Attach the SRB to the IRP.
863 * The reused IRP's stack location has to be rewritten for each retry
864 * call because IoCompleteRequest clears the stack locations.
865 */
867
868
870 nextSp->MajorFunction = IRP_MJ_SCSI;
871 nextSp->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)Pkt->Srb;
872
874 Pkt->Srb->SrbStatus = 0;
876
878 /*
879 * Only dereference the "original IRP"'s stack location
880 * if its a real client irp (as opposed to a static irp
881 * we're using just for result status for one of the non-IO scsi commands).
882 *
883 * For read/write, propagate the storage-specific IRP stack location flags
884 * (e.g. SL_OVERRIDE_VERIFY_VOLUME, SL_WRITE_THROUGH).
885 */
887 nextSp->Flags = origCurSp->Flags;
888 }
889
890 //
891 // If the request is not split, we can use the original IRP MDL. If the
892 // request needs to be split, we need to use a partial MDL. The partial MDL
893 // is needed because more than one driver might be mapping the same MDL
894 // and this causes problems.
895 //
896 if (Pkt->UsePartialMdl == FALSE) {
897 Pkt->Irp->MdlAddress = Pkt->OriginalIrp->MdlAddress;
898 } else {
900 Pkt->Irp->MdlAddress = Pkt->PartialMdl;
901 }
902
903
906
907 //
908 // Set the original irp here for SFIO.
909 //
911
912 //
913 // No need to lock for IdlePrioritySupported, since it will
914 // be modified only at initialization time.
915 //
916 if (fdoData->IdlePrioritySupported == TRUE) {
917 idleRequest = ClasspIsIdleRequest(Pkt->OriginalIrp);
918 if (idleRequest) {
920 } else {
922 }
923 }
924
926 return IoCallDriver(nextDevObj, Pkt->Irp);
927}
IO_COMPLETION_ROUTINE TransferPktComplete
Definition: classp.h:1724
FORCEINLINE BOOLEAN ClasspIsIdleRequest(PIRP Irp)
Definition: classp.h:1268
#define HISTORYLOGSENDPACKET(_packet)
Definition: classp.h:2345
FORCEINLINE VOID ClasspSrbSetOriginalIrp(_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb, _In_ PIRP Irp)
Definition: classp.h:2530
#define DBGLOGSENDPACKET(_pkt)
Definition: debug.h:127
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
Definition: iomdl.c:96
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971

Referenced by ClasspContinueOffloadWrite(), ClasspModeSelect(), ClasspModeSense(), ClasspReceivePopulateTokenInformation(), ClasspReceiveWriteUsingTokenInformation(), ClassReadDriveCapacity(), ServiceTransferRequest(), and TransferPacketRetryTimerDpc().

◆ TestDictionarySignature()

BOOLEAN TestDictionarySignature ( IN PDICTIONARY  Dictionary)

Definition at line 70 of file dictlib.c.

73{
74 return Dictionary->Signature == DICTIONARY_SIGNATURE;
75}

◆ TransferPacketQueueRetryDpc()

VOID TransferPacketQueueRetryDpc ( PTRANSFER_PACKET  Pkt)

Definition at line 604 of file retry.c.

605{
607
608 if (Pkt->RetryIn100nsUnits == 0){
610 }
611 else {
612 LARGE_INTEGER timerPeriod;
613
614 NT_ASSERT(Pkt->RetryIn100nsUnits < 100 * 1000 * 1000 * 10); // sanity check -- 100 seconds is normally too long
615 timerPeriod.QuadPart = -(Pkt->RetryIn100nsUnits);
617 KeSetTimer(&Pkt->RetryTimer, timerPeriod, &Pkt->RetryTimerDPC);
618 }
619}
KDEFERRED_ROUTINE TransferPacketRetryTimerDpc
Definition: classp.h:1727
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
KDPC RetryTimerDPC
Definition: classp.h:524
KTIMER RetryTimer
Definition: classp.h:523
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281

Referenced by RetryTransferPacket(), ServiceTransferRequest(), and StepLowMemRetry().

Variable Documentation

◆ AllFdosList

LIST_ENTRY AllFdosList
extern

Definition at line 29 of file data.c.

Referenced by ClassPnpStartDevice().

◆ BlockDescr

_In_ PVOID BlockDescr

Definition at line 1996 of file classp.h.

Referenced by ConvertDataSetRangeToUnmapBlockDescr().

◆ ClassAddDevice

DRIVER_ADD_DEVICE ClassAddDevice

Definition at line 1408 of file classp.h.

◆ ClassBadItems

CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[]
extern

Definition at line 43 of file data.c.

Referenced by ClassPnpStartDevice().

◆ ClassGuidQueryRegInfoEx

GUID ClassGuidQueryRegInfoEx
extern

Definition at line 215 of file data.c.

◆ ClassGuidSenseInfo2

GUID ClassGuidSenseInfo2
extern

Definition at line 216 of file data.c.

◆ ClassGuidSrbSupport

GUID ClassGuidSrbSupport
extern

Definition at line 218 of file data.c.

◆ ClassGuidWorkingSet

GUID ClassGuidWorkingSet
extern

Definition at line 217 of file data.c.

◆ ClassLogResourceExhaustionEvent

IO_WORKITEM_ROUTINE ClassLogResourceExhaustionEvent

Definition at line 2306 of file classp.h.

Referenced by ClassQueueResourceExhaustionEventWorker().

◆ ClassLogThresholdEvent

IO_WORKITEM_ROUTINE ClassLogThresholdEvent

Definition at line 2298 of file classp.h.

Referenced by ClassQueueThresholdEventWorker().

◆ ClassMaxInterleavePerCriticalIo

ULONG ClassMaxInterleavePerCriticalIo
extern

Definition at line 88 of file class.c.

Referenced by ServiceTransferRequest(), and TransferPktComplete().

◆ ClasspLogIOEventWithContext

IO_WORKITEM_ROUTINE ClasspLogIOEventWithContext

Definition at line 1905 of file classp.h.

◆ ClasspPowerSettingCallback

POWER_SETTING_CALLBACK ClasspPowerSettingCallback

Definition at line 1619 of file classp.h.

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

◆ ClasspRetryRequestDpc

KDEFERRED_ROUTINE ClasspRetryRequestDpc

Definition at line 1644 of file classp.h.

Referenced by ClassPnpStartDevice().

◆ ClasspScreenOff

◆ ClasspSendSynchronousCompletion

IO_COMPLETION_ROUTINE ClasspSendSynchronousCompletion

Definition at line 1410 of file classp.h.

Referenced by ClassSendSrbSynchronous().

◆ ClasspStartIo

DRIVER_STARTIO ClasspStartIo

Definition at line 1454 of file classp.h.

Referenced by _IRQL_requires_max_(), and ClasspStartIo().

◆ ClasspUpdateDiskProperties

IO_WORKITEM_ROUTINE ClasspUpdateDiskProperties

Definition at line 1714 of file classp.h.

Referenced by ClasspInternalSetMediaChangeState(), and ClassReadDriveCapacity().

◆ ClassReleaseQueueCompletion

IO_COMPLETION_ROUTINE ClassReleaseQueueCompletion

Definition at line 1586 of file classp.h.

Referenced by ClasspReleaseQueue().

◆ ClassUnload

DRIVER_UNLOAD ClassUnload

Definition at line 1356 of file classp.h.

Referenced by _IRQL_requires_max_().

◆ CleanupTransferPacketToWorkingSetSizeWorker

IO_WORKITEM_ROUTINE_EX CleanupTransferPacketToWorkingSetSizeWorker

Definition at line 1745 of file classp.h.

Referenced by EnqueueFreeTransferPacket().

◆ CurrentBlockDescrIndex

_In_ PVOID _Inout_ PULONG CurrentBlockDescrIndex

Definition at line 1997 of file classp.h.

Referenced by ConvertDataSetRangeToUnmapBlockDescr().

◆ CurrentLbaCount

Definition at line 1999 of file classp.h.

Referenced by ConvertDataSetRangeToUnmapBlockDescr().

◆ DataSetRange

◆ DiskIdleTimeoutInMS

ULONG DiskIdleTimeoutInMS
extern

Definition at line 132 of file class.c.

Referenced by _Function_class_(), and ClasspEnableIdlePower().

◆ DriverEntry

DRIVER_INITIALIZE DriverEntry

Definition at line 1354 of file classp.h.

◆ IdlePowerFDOList

LIST_ENTRY IdlePowerFDOList
extern

Definition at line 113 of file class.c.

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

◆ IdlePowerFDOListMutex

KGUARDED_MUTEX IdlePowerFDOListMutex
extern

Definition at line 114 of file class.c.

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

◆ Irp

Definition at line 1948 of file classp.h.

◆ Length

Definition at line 1755 of file classp.h.

◆ ListIdentifier

Definition at line 1758 of file classp.h.

Referenced by _IRQL_requires_max_(), and CRYPT_AsnDecodeCTL().

◆ Magic10000

CONST LARGE_INTEGER Magic10000
extern

Definition at line 89 of file class.c.

◆ MaxBlockDescrCount

_In_ PVOID _Inout_ PULONG _In_ ULONG MaxBlockDescrCount

Definition at line 1998 of file classp.h.

◆ MaxDuration

_In_z_ PWSTR _Out_ PULONG MaxDuration

Definition at line 1939 of file classp.h.

◆ MaximumListIdentifier

_In_z_ PWSTR _Out_ PULONG MaximumListIdentifier

Definition at line 1931 of file classp.h.

◆ MaxLbaCount

◆ MaxTokenOperationListIdentifier

ULONG MaxTokenOperationListIdentifier
extern

Definition at line 107 of file class.c.

Referenced by _IRQL_requires_(), and ClasspContinueOffloadWrite().

◆ OriginalIrp

◆ Pkt

◆ PowerSettingNotificationHandle

PVOID PowerSettingNotificationHandle
extern

Definition at line 119 of file class.c.

Referenced by ClasspEnableIdlePower(), and DllUnload().

◆ RegistryPath

Definition at line 1930 of file classp.h.

◆ RemoveTrackingAllocateRoutine

RTL_GENERIC_ALLOCATE_ROUTINE RemoveTrackingAllocateRoutine

Definition at line 2402 of file classp.h.

Referenced by ClasspInitializeRemoveTracking().

◆ RemoveTrackingCompareRoutine

RTL_GENERIC_COMPARE_ROUTINE RemoveTrackingCompareRoutine

Definition at line 2400 of file classp.h.

Referenced by ClasspInitializeRemoveTracking().

◆ RemoveTrackingFreeRoutine

RTL_GENERIC_FREE_ROUTINE RemoveTrackingFreeRoutine

Definition at line 2404 of file classp.h.

Referenced by ClasspInitializeRemoveTracking().

◆ ScreenStateNotificationHandle

PVOID ScreenStateNotificationHandle
extern

Definition at line 124 of file class.c.

Referenced by ClasspInitializePolling(), and DllUnload().

◆ Srb

◆ TokenOperationListIdentifier

volatile ULONG TokenOperationListIdentifier
extern

Definition at line 108 of file class.c.

Referenced by ClasspContinueOffloadWrite().

◆ TotalSectorsProcessed

◆ TransferPacketRetryTimerDpc

KDEFERRED_ROUTINE TransferPacketRetryTimerDpc

Definition at line 1727 of file classp.h.

Referenced by TransferPacketQueueRetryDpc().

◆ TransferPktComplete

IO_COMPLETION_ROUTINE TransferPktComplete

Definition at line 1724 of file classp.h.

Referenced by SubmitTransferPacket().