ReactOS 0.4.15-dev-8100-g1887773
utils.c File Reference
#include "classp.h"
#include "debug.h"
#include <ntiologc.h>
Include dependency graph for utils.c:

Go to the source code of this file.

Macros

#define FIRMWARE_ACTIVATE_TIMEOUT_VALUE   30
 

Functions

BOOLEAN ClasspMyStringMatches (_In_opt_z_ PCHAR StringToMatch, _In_z_ PCHAR TargetString)
 
 _IRQL_requires_max_ (PASSIVE_LEVEL)
 
VOID ClasspPerfIncrementErrorCount (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClasspPerfIncrementSuccessfulIo (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
PMDL ClasspBuildDeviceMdl (PVOID Buffer, ULONG BufferLen, BOOLEAN WriteToDevice)
 
PMDL BuildDeviceInputMdl (PVOID Buffer, ULONG BufferLen)
 
VOID ClasspFreeDeviceMdl (PMDL Mdl)
 
VOID FreeDeviceInputMdl (PMDL Mdl)
 
NTSTATUS ClasspDuidGetDeviceIdProperty (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS ClasspDuidGetDeviceProperty (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
NTSTATUS ClasspDuidGetDriveLayout (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
NTSTATUS ClasspDuidQueryProperty (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
NTSTATUS ClasspWriteCacheProperty (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
ULONG ClasspCalculateLogicalSectorSize (_In_ PDEVICE_OBJECT Fdo, _In_ ULONG BytesPerBlockInBigEndian)
 
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 ClasspAccessAlignmentProperty (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
static NTSTATUS IncursSeekPenalty (_In_ USHORT MediumRotationRate, _In_ PBOOLEAN IncursSeekPenalty)
 
NTSTATUS ClasspDeviceMediaTypeProperty (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspDeviceGetBlockDeviceCharacteristicsVPDPage (_In_ PFUNCTIONAL_DEVICE_EXTENSION fdoExtension, _In_ 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 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)
 
VOID ConvertDataSetRangeToUnmapBlockDescr (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PUNMAP_BLOCK_DESCRIPTOR BlockDescr, _Inout_ PULONG CurrentBlockDescrIndex, _In_ ULONG MaxBlockDescrIndex, _Inout_ PULONGLONG CurrentLbaCount, _In_ ULONGLONG MaxLbaCount, _Inout_ PDEVICE_DATA_SET_RANGE DataSetRange)
 
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)
 
NTSTATUS ClasspDeviceTrimProcess (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PGUID ActivityId, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
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)
 
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)
 
NTSTATUS ClassGetLBProvisioningLogPage (_In_ PDEVICE_OBJECT DeviceObject, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG LogPageSize, _Inout_ PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING LogPage)
 
NTSTATUS ClassInterpretLBProvisioningLogPage (_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG LogPageSize, _In_ PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING LogPage, _In_ ULONG ResourcesSize, _Out_ PSTORAGE_LB_PROVISIONING_MAP_RESOURCES Resources)
 
NTSTATUS ClassGetLBProvisioningResources (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG ResourcesSize, _Inout_ PSTORAGE_LB_PROVISIONING_MAP_RESOURCES Resources)
 
NTSTATUS ClassDeviceGetLBProvisioningResources (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
 _Function_class_ (IO_WORKITEM_ROUTINE)
 
NTSTATUS ClasspLogSystemEventWithDeviceNumber (_In_ PDEVICE_OBJECT DeviceObject, _In_ NTSTATUS IoErrorCode)
 
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)
 
static BOOLEAN ValidPersistentReserveScope (UCHAR Scope)
 
static BOOLEAN ValidPersistentReserveType (UCHAR Type)
 
NTSTATUS ClasspPersistentReserve (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
 
NTSTATUS ClasspPriorityHint (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
VOID ClasspConvertToScsiRequestBlock (_Out_ PSCSI_REQUEST_BLOCK Srb, _In_ PSTORAGE_REQUEST_BLOCK SrbEx)
 
 _IRQL_requires_max_ (APC_LEVEL)
 
_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)
 
_IRQL_requires_same_ PUCHAR ClasspBinaryToAscii (_In_reads_(Length) PUCHAR HexBuffer, _In_ ULONG Length, _Inout_ PULONG UpdateLength)
 
_IRQL_requires_same_ NTSTATUS ClasspStorageEventNotification (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
 
VOID ClasspZeroQERR (_In_ PDEVICE_OBJECT DeviceObject)
 
NTSTATUS ClasspGetHwFirmwareInfo (_In_ PDEVICE_OBJECT DeviceObject)
 
__inline BOOLEAN ClassDeviceHwFirmwareIsPortDriverSupported (_In_ PDEVICE_OBJECT DeviceObject)
 
NTSTATUS ClassDeviceHwFirmwareGetInfoProcess (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
 
_IRQL_requires_same_ _IRQL_requires_max_ (DISPATCH_LEVEL)
 
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)
 
BOOLEAN ClasspIsThinProvisioningError (_In_ PSCSI_REQUEST_BLOCK Srb)
 

Macro Definition Documentation

◆ FIRMWARE_ACTIVATE_TIMEOUT_VALUE

#define FIRMWARE_ACTIVATE_TIMEOUT_VALUE   30

Definition at line 37 of file utils.c.

Function Documentation

◆ _Function_class_()

_Function_class_ ( IO_WORKITEM_ROUTINE  )

Definition at line 5136 of file utils.c.

5157{
5159 PIO_WORKITEM workItem = (PIO_WORKITEM)Context;
5163 ULONG resourcesSize = sizeof(STORAGE_LB_PROVISIONING_MAP_RESOURCES);
5164 PIO_ERROR_LOG_PACKET errorLogEntry = NULL;
5165 ULONG logEntrySize = sizeof(IO_ERROR_LOG_PACKET);
5166 PWCHAR stringIndex = NULL;
5167 LONG stringSize = 0;
5168 ULONG srbSize;
5169
5170 //
5171 // Allocate an SRB for getting the LBP log page.
5172 //
5173 if ((fdoExtension->AdapterDescriptor != NULL) &&
5174 (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
5176 } else {
5177 srbSize = sizeof(SCSI_REQUEST_BLOCK);
5178 }
5179
5180 srb = ExAllocatePoolWithTag(NonPagedPoolNx,
5181 srbSize,
5182 'ACcS');
5183 if (srb != NULL) {
5184
5185 //
5186 // Try to get the LBP resources from the device so we can report them in
5187 // the system event log.
5188 //
5190 srb,
5191 resourcesSize,
5192 &resources);
5193
5194 //
5195 // We need to allocate enough space for 3 insertion strings:
5196 // The first is a ULONG representing the disk number in decimal, which means
5197 // a max of 10 digits, plus one for the NULL character.
5198 // The second and third are ULONGLONGs representing the used and available
5199 // bytes, which means a max of 20 digits, plus one for the NULL character.
5200 // Make sure we do not exceed the max error log size or the max size of a
5201 // UCHAR since the size gets truncated to a UCHAR when we pass it to
5202 // IoAllocateErrorLogEntry().
5203 //
5204 logEntrySize = sizeof(IO_ERROR_LOG_PACKET) + (11 * sizeof(WCHAR)) + (2 * (21 * sizeof(WCHAR)));
5205 logEntrySize = min(logEntrySize, ERROR_LOG_MAXIMUM_SIZE);
5206 logEntrySize = min(logEntrySize, MAXUCHAR);
5207
5208 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(DeviceObject, (UCHAR)logEntrySize);
5209 if (errorLogEntry != NULL)
5210 {
5211 //
5212 // There are two event IDs we can use here. Both use the disk number,
5213 // but one reports the available and used bytes while the other does not.
5214 // We fall back on the latter if we failed to obtain the available and
5215 // used byte counts from the LBP log page.
5216 //
5217 // The event insertion strings need to be in this order:
5218 // 1. The disk number. (Both event IDs use this.)
5219 // 2. Bytes used.
5220 // 3. Bytes available.
5221 //
5222
5223 RtlZeroMemory(errorLogEntry, logEntrySize);
5224 errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
5225
5226 stringIndex = (PWCHAR)((ULONG_PTR)errorLogEntry + sizeof(IO_ERROR_LOG_PACKET));
5227 stringSize = logEntrySize - sizeof(IO_ERROR_LOG_PACKET);
5228
5229 //
5230 // Add the disk number to the insertion strings.
5231 //
5232 status = RtlStringCbPrintfW(stringIndex, stringSize, L"%d", fdoExtension->DeviceNumber);
5233
5234 if (NT_SUCCESS(status) )
5235 {
5236 errorLogEntry->NumberOfStrings++;
5237
5238 if (resources.UsedMappingResourcesValid &&
5239 resources.AvailableMappingResourcesValid)
5240 {
5241 //
5242 // Add the used mapping resources to the insertion strings.
5243 //
5244 stringIndex += (wcslen(stringIndex) + 1);
5245 stringSize -= (LONG)(wcslen(stringIndex) + 1) * sizeof(WCHAR);
5246
5247 status = RtlStringCbPrintfW(stringIndex, stringSize, L"%I64u", resources.UsedMappingResources);
5248
5249 if (NT_SUCCESS(status))
5250 {
5251 errorLogEntry->NumberOfStrings++;
5252
5253 //
5254 // Add the available mapping resources to the insertion strings.
5255 //
5256 stringIndex += (wcslen(stringIndex) + 1);
5257 stringSize -= (LONG)(wcslen(stringIndex) + 1) * sizeof(WCHAR);
5258
5259 status = RtlStringCbPrintfW(stringIndex, stringSize, L"%I64u", resources.AvailableMappingResources);
5260
5261 if (NT_SUCCESS(status))
5262 {
5263 errorLogEntry->NumberOfStrings++;
5264 }
5265 }
5266 }
5267 else
5268 {
5269 TracePrint((TRACE_LEVEL_WARNING,
5270 TRACE_FLAG_GENERAL,
5271 "ClassLogThresholdEvent: DO (%p), Used and available mapping resources were unavailable.\n",
5272 DeviceObject));
5273 }
5274 }
5275
5276 //
5277 // If we were able to successfully assemble all 3 insertion strings,
5278 // then we can use one of the "extended" event IDs. Otherwise, use the basic
5279 // event ID, which only requires the disk number.
5280 //
5281 if (errorLogEntry->NumberOfStrings == 3)
5282 {
5283 if (resources.UsedMappingResourcesScope == LOG_PAGE_LBP_RESOURCE_SCOPE_DEDICATED_TO_LUN &&
5284 resources.AvailableMappingResourcesScope == LOG_PAGE_LBP_RESOURCE_SCOPE_DEDICATED_TO_LUN) {
5285
5287
5288 } else if (resources.UsedMappingResourcesScope == LOG_PAGE_LBP_RESOURCE_SCOPE_DEDICATED_TO_LUN &&
5289 resources.AvailableMappingResourcesScope == LOG_PAGE_LBP_RESOURCE_SCOPE_NOT_DEDICATED_TO_LUN) {
5290
5292
5293 } else if (resources.UsedMappingResourcesScope == LOG_PAGE_LBP_RESOURCE_SCOPE_NOT_DEDICATED_TO_LUN &&
5294 resources.AvailableMappingResourcesScope == LOG_PAGE_LBP_RESOURCE_SCOPE_DEDICATED_TO_LUN) {
5295
5297
5298 } else if (resources.UsedMappingResourcesScope == LOG_PAGE_LBP_RESOURCE_SCOPE_NOT_DEDICATED_TO_LUN &&
5299 resources.AvailableMappingResourcesScope == LOG_PAGE_LBP_RESOURCE_SCOPE_NOT_DEDICATED_TO_LUN) {
5300
5302
5303 } else {
5304
5306 }
5307 }
5308 else
5309 {
5311 }
5312
5313 //
5314 // Write the error log packet to the system error logging thread.
5315 // It will be freed automatically.
5316 //
5317 IoWriteErrorLogEntry(errorLogEntry);
5318
5319 TracePrint((TRACE_LEVEL_INFORMATION,
5320 TRACE_FLAG_GENERAL,
5321 "ClassLogThresholdEvent: DO (%p), Soft threshold notification logged.\n",
5322 DeviceObject));
5323 }
5324 else
5325 {
5326 TracePrint((TRACE_LEVEL_ERROR,
5327 TRACE_FLAG_GENERAL,
5328 "ClassLogThresholdEvent: DO (%p), Failed to allocate memory for error log entry.\n",
5329 DeviceObject));
5330 }
5331 } else {
5332 TracePrint((TRACE_LEVEL_ERROR,
5333 TRACE_FLAG_GENERAL,
5334 "ClassLogThresholdEvent: DO (%p), Failed to allocate memory for SRB.\n",
5335 DeviceObject));
5336 }
5337
5338
5339 //
5340 // Clear the soft threshold event pending flag so that another can be queued.
5341 //
5342 InterlockedExchange((PLONG)&(fdoExtension->FunctionSupportInfo->LBProvisioningData.SoftThresholdEventPending), 0);
5343
5345
5346 FREE_POOL(srb);
5347
5348 if (workItem != NULL) {
5349 IoFreeWorkItem(workItem);
5350 }
5351}
#define InterlockedExchange
Definition: armddk.h:54
LONG NTSTATUS
Definition: precomp.h:26
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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 _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
FxCmResList * resources
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
#define min(a, b)
Definition: monoChain.cc:55
struct _STORAGE_LB_PROVISIONING_MAP_RESOURCES STORAGE_LB_PROVISIONING_MAP_RESOURCES
#define IO_WARNING_SOFT_THRESHOLD_REACHED_EX_LUN_POOL
Definition: ntiologc.h:108
#define IO_WARNING_SOFT_THRESHOLD_REACHED_EX
Definition: ntiologc.h:106
#define IO_WARNING_SOFT_THRESHOLD_REACHED_EX_POOL_POOL
Definition: ntiologc.h:110
#define IO_WARNING_SOFT_THRESHOLD_REACHED_EX_POOL_LUN
Definition: ntiologc.h:109
#define IO_WARNING_SOFT_THRESHOLD_REACHED_EX_LUN_LUN
Definition: ntiologc.h:107
#define IO_WARNING_SOFT_THRESHOLD_REACHED
Definition: ntiologc.h:105
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
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
#define LOG_PAGE_LBP_RESOURCE_SCOPE_NOT_DEDICATED_TO_LUN
Definition: scsi.h:3364
#define LOG_PAGE_LBP_RESOURCE_SCOPE_DEDICATED_TO_LUN
Definition: scsi.h:3363
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:664
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
NTSTATUS ErrorCode
Definition: iotypes.h:2007
USHORT NumberOfStrings
Definition: iotypes.h:2004
Definition: ps.c:97
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
int32_t * PLONG
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define MAXUCHAR
Definition: umtypes.h:117
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define ERROR_LOG_MAXIMUM_SIZE
Definition: iotypes.h:2042
struct _IO_WORKITEM * PIO_WORKITEM
Definition: iotypes.h:506
struct _IO_ERROR_LOG_PACKET * PIO_ERROR_LOG_PACKET
struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180

◆ _IRQL_requires_max_() [1/3]

_IRQL_requires_max_ ( APC_LEVEL  )

Definition at line 6894 of file utils.c.

6924{
6926 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
6928 PIO_STACK_LOCATION irpStack;
6929 ULONG length;
6931 PDEVICE_COPY_OFFLOAD_DESCRIPTOR copyOffloadDescr = (PDEVICE_COPY_OFFLOAD_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
6932
6934
6935 PAGED_CODE();
6936
6937 fdoExtension = DeviceObject->DeviceExtension;
6938 query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
6940 length = 0;
6941 information = 0;
6942
6943 TracePrint((TRACE_LEVEL_VERBOSE,
6944 TRACE_FLAG_IOCTL,
6945 "ClasspDeviceCopyOffloadProperty (%p): Entering function.\n",
6946 DeviceObject));
6947
6948 //
6949 // Check proper query type.
6950 //
6951 if (query->QueryType == PropertyExistsQuery) {
6952
6953 //
6954 // In order to maintain consistency with the how the rest of the properties
6955 // are handled, we shall always return success for PropertyExistsQuery.
6956 //
6958 goto __ClasspDeviceCopyOffloadProperty_Exit;
6959
6960 } else if (query->QueryType != PropertyStandardQuery) {
6961
6962 TracePrint((TRACE_LEVEL_ERROR,
6963 TRACE_FLAG_IOCTL,
6964 "ClasspDeviceCopyOffloadProperty (%p): Unsupported query type %x for Copy Offload property.\n",
6966 query->QueryType));
6967
6969 goto __ClasspDeviceCopyOffloadProperty_Exit;
6970 }
6971
6972 //
6973 // Request validation.
6974 // Note that InputBufferLength and IsFdo have been validated beforing entering this routine.
6975 //
6976
6978
6980
6981 TracePrint((TRACE_LEVEL_ERROR,
6982 TRACE_FLAG_IOCTL,
6983 "ClasspDeviceCopyOffloadProperty (%p): Query property for Copy Offload called at incorrect IRQL.\n",
6984 DeviceObject));
6985
6987 goto __ClasspDeviceCopyOffloadProperty_Exit;
6988 }
6989
6990 length = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
6991
6992 if (length < sizeof(DEVICE_COPY_OFFLOAD_DESCRIPTOR)) {
6993
6994 if (length >= sizeof(STORAGE_DESCRIPTOR_HEADER)) {
6995
6996 TracePrint((TRACE_LEVEL_WARNING,
6997 TRACE_FLAG_IOCTL,
6998 "ClasspDeviceCopyOffloadProperty (%p): Length %u specified for Copy Offload property enough only for header.\n",
7000 length));
7001
7003 copyOffloadDescr->Version = sizeof(DEVICE_COPY_OFFLOAD_DESCRIPTOR);
7004 copyOffloadDescr->Size = sizeof(DEVICE_COPY_OFFLOAD_DESCRIPTOR);
7005
7007 goto __ClasspDeviceCopyOffloadProperty_Exit;
7008 }
7009
7010 TracePrint((TRACE_LEVEL_ERROR,
7011 TRACE_FLAG_IOCTL,
7012 "ClasspDeviceCopyOffloadProperty (%p): Incorrect length %u specified for Copy Offload property.\n",
7014 length));
7015
7017 goto __ClasspDeviceCopyOffloadProperty_Exit;
7018 }
7019
7020 if (!fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits) {
7021
7022 TracePrint((TRACE_LEVEL_ERROR,
7023 TRACE_FLAG_IOCTL,
7024 "ClasspDeviceCopyOffloadProperty (%p): Command not supported on this device.\n",
7025 DeviceObject));
7026
7028 goto __ClasspDeviceCopyOffloadProperty_Exit;
7029 }
7030
7031 if (!NT_SUCCESS(fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus)) {
7032
7033 status = fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus;
7034
7035 TracePrint((TRACE_LEVEL_ERROR,
7036 TRACE_FLAG_IOCTL,
7037 "ClasspDeviceCopyOffloadProperty (%p): VPD retrieval had failed with %x.\n",
7039 status));
7040
7041 goto __ClasspDeviceCopyOffloadProperty_Exit;
7042 }
7043
7044 //
7045 // Fill in the output buffer. All data is copied from the FDO extension where we
7046 // cached Block Limits and Block Device Token Limits info when the device was first initialized.
7047 //
7048 RtlZeroMemory(copyOffloadDescr, length);
7049 copyOffloadDescr->Version = 1;
7050 copyOffloadDescr->Size = sizeof(DEVICE_COPY_OFFLOAD_DESCRIPTOR);
7051 copyOffloadDescr->MaximumTokenLifetime = fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer;
7052 copyOffloadDescr->DefaultTokenLifetime = fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.DefaultInactivityTimer;
7053 copyOffloadDescr->MaximumTransferSize = fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumTokenTransferSize;
7054 copyOffloadDescr->OptimalTransferCount = fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount;
7055 copyOffloadDescr->MaximumDataDescriptors = fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumRangeDescriptors;
7056
7057 if (NT_SUCCESS(fdoExtension->FunctionSupportInfo->BlockLimitsData.CommandStatus)) {
7058
7059 copyOffloadDescr->MaximumTransferLengthPerDescriptor = fdoExtension->FunctionSupportInfo->BlockLimitsData.MaximumTransferLength;
7060 copyOffloadDescr->OptimalTransferLengthPerDescriptor = fdoExtension->FunctionSupportInfo->BlockLimitsData.OptimalTransferLength;
7061 copyOffloadDescr->OptimalTransferLengthGranularity = fdoExtension->FunctionSupportInfo->BlockLimitsData.OptimalTransferLengthGranularity;
7062 }
7063
7066
7067__ClasspDeviceCopyOffloadProperty_Exit:
7068
7069 //
7070 // Set the size and status in IRP
7071 //
7072 Irp->IoStatus.Information = information;
7073 Irp->IoStatus.Status = status;
7074
7077
7078 TracePrint((TRACE_LEVEL_VERBOSE,
7079 TRACE_FLAG_IOCTL,
7080 "ClasspDeviceCopyOffloadProperty (%p): Exiting function with status %x.\n",
7082 status));
7083
7084 return status;
7085}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
_In_ PIRP Irp
Definition: csq.h:116
static PDB_INFORMATION information
Definition: db.cpp:178
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
STORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
struct _DEVICE_COPY_OFFLOAD_DESCRIPTOR DEVICE_COPY_OFFLOAD_DESCRIPTOR
struct _DEVICE_COPY_OFFLOAD_DESCRIPTOR * PDEVICE_COPY_OFFLOAD_DESCRIPTOR
struct _STORAGE_PROPERTY_QUERY * PSTORAGE_PROPERTY_QUERY
@ PropertyExistsQuery
Definition: ntddstor.h:506
@ PropertyStandardQuery
Definition: ntddstor.h:505
#define STATUS_DEVICE_FEATURE_NOT_SUPPORTED
Definition: ntstatus.h:985
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
union _IO_STACK_LOCATION::@1567 Parameters
struct _IO_STACK_LOCATION::@1567::@1568 DeviceIoControl
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define NT_ASSERT
Definition: rtlfuncs.h:3310

◆ _IRQL_requires_max_() [2/3]

_IRQL_requires_same_ _IRQL_requires_max_ ( DISPATCH_LEVEL  )

Definition at line 8503 of file utils.c.

8510{
8512
8513 PIRP originalIrp;
8514
8515 //
8516 // Free the allocated buffer for firmware image.
8517 //
8518 if (Context != NULL) {
8520 }
8521
8522 originalIrp = irpStack->Parameters.Others.Argument1;
8523
8524 NT_ASSERT(originalIrp != NULL);
8525
8526 originalIrp->IoStatus.Status = Irp->IoStatus.Status;
8527 originalIrp->IoStatus.Information = Irp->IoStatus.Information;
8528
8529 ClassReleaseRemoveLock(Fdo, originalIrp);
8531
8532 IoFreeIrp(Irp);
8533
8535
8536} // end ClassHwFirmwareDownloadComplete()
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
struct _IO_STACK_LOCATION::@3982::@4021 Others
IO_STATUS_BLOCK IoStatus
_Must_inspect_result_ _In_ WDFDEVICE Fdo
Definition: wdffdo.h:461
#define IO_DISK_INCREMENT
Definition: iotypes.h:600

◆ _IRQL_requires_max_() [3/3]

_IRQL_requires_max_ ( PASSIVE_LEVEL  )

Definition at line 71 of file utils.c.

80{
82 RTL_QUERY_REGISTRY_TABLE queryTable[2] = {0};
83 HANDLE deviceParameterHandle = NULL;
84 HANDLE deviceSubkeyHandle = NULL;
85 ULONG defaultParameterValue;
86
87 PAGED_CODE();
88
89 //
90 // open the given parameter
91 //
92
96 &deviceParameterHandle);
97
98 if (NT_SUCCESS(status) && (SubkeyName != NULL)) {
99
100 UNICODE_STRING subkeyName;
101 OBJECT_ATTRIBUTES objectAttributes = {0};
102
103 RtlInitUnicodeString(&subkeyName, SubkeyName);
104 InitializeObjectAttributes(&objectAttributes,
105 &subkeyName,
107 deviceParameterHandle,
108 NULL);
109
110 status = ZwOpenKey(&deviceSubkeyHandle,
111 KEY_READ,
112 &objectAttributes);
113 if (!NT_SUCCESS(status)) {
114 ZwClose(deviceParameterHandle);
115 }
116
117 }
118
119 if (NT_SUCCESS(status)) {
120
121 defaultParameterValue = *ParameterValue;
122
124 queryTable->Name = ParameterName;
125 queryTable->EntryContext = ParameterValue;
127 queryTable->DefaultData = NULL;
128 queryTable->DefaultLength = 0;
129
131 (PWSTR)(SubkeyName ?
132 deviceSubkeyHandle :
133 deviceParameterHandle),
134 queryTable,
135 NULL,
136 NULL);
137 if (!NT_SUCCESS(status)) {
138 *ParameterValue = defaultParameterValue; // use default value
139 }
140
141 //
142 // close what we open
143 //
144
145 if (SubkeyName) {
146 ZwClose(deviceSubkeyHandle);
147 }
148
149 ZwClose(deviceParameterHandle);
150 }
151
152 if (!NT_SUCCESS(status)) {
153
154 //
155 // Windows 2000 SP3 uses the driver-specific key, so look in there
156 //
157
160 KEY_READ,
161 &deviceParameterHandle);
162
163 if (NT_SUCCESS(status) && (SubkeyName != NULL)) {
164
165 UNICODE_STRING subkeyName;
166 OBJECT_ATTRIBUTES objectAttributes = {0};
167
168 RtlInitUnicodeString(&subkeyName, SubkeyName);
169 InitializeObjectAttributes(&objectAttributes,
170 &subkeyName,
172 deviceParameterHandle,
173 NULL);
174
175 status = ZwOpenKey(&deviceSubkeyHandle, KEY_READ, &objectAttributes);
176
177 if (!NT_SUCCESS(status)) {
178 ZwClose(deviceParameterHandle);
179 }
180 }
181
182 if (NT_SUCCESS(status)) {
183
184 defaultParameterValue = *ParameterValue;
185
187 queryTable->Name = ParameterName;
188 queryTable->EntryContext = ParameterValue;
190 queryTable->DefaultData = NULL;
191 queryTable->DefaultLength = 0;
192
194 (PWSTR)(SubkeyName ?
195 deviceSubkeyHandle :
196 deviceParameterHandle),
197 queryTable,
198 NULL,
199 NULL);
200 if (NT_SUCCESS(status)) {
201
202 //
203 // Migrate the value over to the device-specific key
204 //
205
206 ClassSetDeviceParameter(FdoExtension, SubkeyName, ParameterName, *ParameterValue);
207
208 } else {
209
210 //
211 // Use the default value
212 //
213
214 *ParameterValue = defaultParameterValue;
215 }
216
217 if (SubkeyName) {
218 ZwClose(deviceSubkeyHandle);
219 }
220
221 ZwClose(deviceParameterHandle);
222 }
223 }
224
225 return;
226
227} // end ClassGetDeviceParameter()
_In_opt_ PWSTR _In_ PWSTR ParameterName
Definition: cdrom.h:961
_In_opt_ PWSTR _In_ PWSTR _Inout_ PULONG ParameterValue
Definition: cdrom.h:963
_In_opt_ PWSTR SubkeyName
Definition: cdrom.h:960
@ FdoExtension
Definition: precomp.h:48
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#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
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define REG_NONE
Definition: nt_native.h:1492
#define 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_DRIVER
Definition: usbd.c:42
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2786
#define RTL_QUERY_REGISTRY_TYPECHECK
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT

◆ 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
#define FALSE
Definition: types.h:117
PMDL ClasspBuildDeviceMdl(PVOID Buffer, ULONG BufferLen, BOOLEAN WriteToDevice)
Definition: utils.c:582

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

◆ 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}
struct _STORAGE_LB_PROVISIONING_MAP_RESOURCES * PSTORAGE_LB_PROVISIONING_MAP_RESOURCES

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}
unsigned char BOOLEAN
#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 TRUE
Definition: types.h:120
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
#define IoCallDriver
Definition: irp.c:1225
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
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_INVALID_PARAMETER
Definition: udferr_usr.h:135
#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
size_t bufferSize
IoMarkIrpPending(Irp)
#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
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
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
ULONG dataLength
Definition: scsi.h:3751

Referenced by ClassDeviceControl().

◆ ClassDeviceHwFirmwareIsPortDriverSupported()

__inline BOOLEAN ClassDeviceHwFirmwareIsPortDriverSupported ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 8330 of file utils.c.

8346{
8347 //
8348 // If the request is for a FDO, process the request for Storport, SDstor and Spaceport only.
8349 // Don't process it if we don't have a miniport descriptor.
8350 //
8351 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8352 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
8353
8354 BOOLEAN isSupported = FALSE;
8355 if (commonExtension->IsFdo && (fdoExtension->MiniportDescriptor != NULL)) {
8356 isSupported = ((fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetStorport) ||
8357 (fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetSpaceport) ||
8358 (fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetSDport ));
8359 }
8360
8361 return isSupported;
8362}
@ StoragePortCodeSetStorport
Definition: ntddstor.h:619
@ StoragePortCodeSetSpaceport
Definition: ntddstor.h:621
@ StoragePortCodeSetSDport
Definition: ntddstor.h:625

Referenced by ClassDeviceHwFirmwareActivateProcess(), ClassDeviceHwFirmwareDownloadProcess(), and ClassDeviceHwFirmwareGetInfoProcess().

◆ ClassGetLBProvisioningLogPage()

NTSTATUS ClassGetLBProvisioningLogPage ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ ULONG  LogPageSize,
_Inout_ PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING  LogPage 
)

Definition at line 4679 of file utils.c.

4707{
4710 PCDB cdb = NULL;
4711
4712 //
4713 // Make sure the caller passed in an adequate output buffer. The Allocation
4714 // Length field in the Log Sense command is only 2 bytes so we need to also
4715 // make sure that the given log page size isn't larger than MAXUSHORT.
4716 //
4717 if (LogPage == NULL ||
4718 LogPageSize < sizeof(LOG_PAGE_LOGICAL_BLOCK_PROVISIONING) ||
4719 LogPageSize > MAXUSHORT)
4720 {
4721 TracePrint((TRACE_LEVEL_ERROR,
4722 TRACE_FLAG_GENERAL,
4723 "ClassGetLBProvisioningLogPage: DO (%p), Invalid parameter, LogPage = %p, LogPageSize = %u.\n",
4725 LogPage,
4726 LogPageSize));
4727
4729 }
4730
4731 //
4732 // Initialize the SRB.
4733 //
4734 if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
4738 1,
4740 if (NT_SUCCESS(status)) {
4742 } else {
4743 //
4744 // Should not occur.
4745 //
4747 }
4748 } else {
4750 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
4752 }
4753
4754 //
4755 // Build and send down the Log Sense command.
4756 //
4757 SrbSetTimeOutValue(Srb, fdoExtension->TimeOutValue);
4760 SrbAssignSrbFlags(Srb, fdoExtension->SrbFlags);
4761 SrbSetCdbLength(Srb, sizeof(cdb->LOGSENSE));
4762
4763 cdb = SrbGetCdb(Srb);
4764 cdb->LOGSENSE.OperationCode = SCSIOP_LOG_SENSE;
4765 cdb->LOGSENSE.PageCode = LOG_PAGE_CODE_LOGICAL_BLOCK_PROVISIONING;
4766 cdb->LOGSENSE.PCBit = 0;
4767 cdb->LOGSENSE.ParameterPointer[0] = 0;
4768 cdb->LOGSENSE.ParameterPointer[1] = 0;
4769 REVERSE_BYTES_SHORT(&(cdb->LOGSENSE.AllocationLength), &LogPageSize);
4770
4772 Srb,
4773 LogPage,
4774 LogPageSize,
4775 FALSE);
4776
4777 //
4778 // Handle the case where we get back STATUS_DATA_OVERRUN b/c the input
4779 // buffer was larger than necessary.
4780 //
4781 if (status == STATUS_DATA_OVERRUN &&
4782 SrbGetDataTransferLength(Srb) < LogPageSize)
4783 {
4785 }
4786
4787 //
4788 // Log the command.
4789 //
4790 TracePrint((TRACE_LEVEL_INFORMATION,
4791 TRACE_FLAG_IOCTL,
4792 "ClassGetLBProvisioningLogPage: DO (%p), LogSense command issued for LBP log page. NT Status: %!STATUS!.\n",
4794 status
4795 ));
4796
4797 return status;
4798}
#define SCSIOP_LOG_SENSE
Definition: cdrw_hw.h:937
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
NTSTATUS NTAPI ClassSendSrbSynchronous(_In_ PDEVICE_OBJECT Fdo, _Inout_ PSCSI_REQUEST_BLOCK _Srb, _In_reads_bytes_opt_(BufferLength) PVOID BufferAddress, _In_ ULONG BufferLength, _In_ BOOLEAN WriteToDevice)
Definition: class.c:4042
#define SP_UNTAGGED
Definition: srb.h:233
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:423
#define LOG_PAGE_CODE_LOGICAL_BLOCK_PROVISIONING
Definition: scsi.h:3262
#define REVERSE_BYTES_SHORT(Destination, Source)
Definition: scsi.h:3474
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:666
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:661
@ SrbExDataTypeScsiCdb16
Definition: srb.h:459
FORCEINLINE VOID SrbAssignSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:946
#define SrbSetRequestTag
Definition: srbhelper.h:869
FORCEINLINE ULONG SrbGetDataTransferLength(_In_ PVOID Srb)
Definition: srbhelper.h:765
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
UCHAR Function
Definition: srb.h:250
USHORT Length
Definition: srb.h:249
#define MAXUSHORT
Definition: typedefs.h:83
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152

Referenced by ClassGetLBProvisioningResources().

◆ ClassGetLBProvisioningResources()

NTSTATUS ClassGetLBProvisioningResources ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PSCSI_REQUEST_BLOCK  Srb,
_In_ ULONG  ResourcesSize,
_Inout_ PSTORAGE_LB_PROVISIONING_MAP_RESOURCES  Resources 
)

Definition at line 4958 of file utils.c.

4995{
4998 ULONG logPageSize;
5000
5001 //
5002 // This functionality is only supported for devices that support logical
5003 // block provisioning.
5004 //
5005 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning == FALSE)
5006 {
5007 TracePrint((TRACE_LEVEL_ERROR,
5008 TRACE_FLAG_GENERAL,
5009 "ClassGetLBProvisioningResources: DO (%p), Device does not support logical block provisioning.\n",
5010 DeviceObject));
5011
5012 return STATUS_NOT_SUPPORTED;
5013 }
5014
5015 //
5016 // Validate the output buffer.
5017 //
5018 if (Resources == NULL ||
5019 ResourcesSize < sizeof(STORAGE_LB_PROVISIONING_MAP_RESOURCES))
5020 {
5021 TracePrint((TRACE_LEVEL_ERROR,
5022 TRACE_FLAG_GENERAL,
5023 "ClassGetLBProvisioningResources: DO (%p), Invalid parameter, Resources = %p, ResourcesSize = %u.\n",
5025 Resources,
5026 ResourcesSize));
5027
5029 }
5030
5031 //
5032 // Allocate a buffer for the log page. Currently the log page contains:
5033 // 1. Log page header
5034 // 2. Log page parameter for used resources
5035 // 3. Log page parameter for available resources
5036 //
5038
5039#if defined(_ARM_) || defined(_ARM64_)
5040 //
5041 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
5042 // based platforms. We are taking the conservative approach here.
5043 //
5044 logPageSize = ALIGN_UP_BY(logPageSize, KeGetRecommendedSharedDataAlignment());
5045 logPage = (PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING)ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, logPageSize, CLASS_TAG_LB_PROVISIONING);
5046#else
5048#endif
5049 if (logPage != NULL)
5050 {
5051 //
5052 // Get the LBP log page from the device.
5053 //
5055 Srb,
5056 logPageSize,
5057 logPage);
5058
5059 if (NT_SUCCESS(status))
5060 {
5061 //
5062 // Interpret the log page and fill in the output buffer.
5063 //
5065 logPageSize,
5066 logPage,
5067 ResourcesSize,
5068 Resources);
5069 }
5070
5071 ExFreePool(logPage);
5072 }
5073 else
5074 {
5075 TracePrint((TRACE_LEVEL_ERROR,
5076 TRACE_FLAG_GENERAL,
5077 "ClassGetLBProvisioningResources: DO (%p), Failed to allocate memory for LBP log page.\n",
5078 DeviceObject));
5079
5081 }
5082
5083 return status;
5084}
#define CLASS_TAG_LB_PROVISIONING
Definition: classpnp.h:89
NTSTATUS ClassInterpretLBProvisioningLogPage(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG LogPageSize, _In_ PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING LogPage, _In_ ULONG ResourcesSize, _Out_ PSTORAGE_LB_PROVISIONING_MAP_RESOURCES Resources)
Definition: utils.c:4800
NTSTATUS ClassGetLBProvisioningLogPage(_In_ PDEVICE_OBJECT DeviceObject, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG LogPageSize, _Inout_ PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING LogPage)
Definition: utils.c:4679
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:710
struct _LOG_PAGE_LOGICAL_BLOCK_PROVISIONING * PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING
struct _LOG_PAGE_LOGICAL_BLOCK_PROVISIONING LOG_PAGE_LOGICAL_BLOCK_PROVISIONING

Referenced by ClassDeviceGetLBProvisioningResources().

◆ ClassInterpretLBProvisioningLogPage()

NTSTATUS ClassInterpretLBProvisioningLogPage ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ ULONG  LogPageSize,
_In_ PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING  LogPage,
_In_ ULONG  ResourcesSize,
_Out_ PSTORAGE_LB_PROVISIONING_MAP_RESOURCES  Resources 
)

Definition at line 4800 of file utils.c.

4838{
4840 USHORT pageLength;
4841 PLOG_PARAMETER_HEADER parameter;
4842 PVOID endOfPage;
4843 USHORT parameterCode;
4844 ULONG resourceCount;
4845 UCHAR thresholdExponent = fdoExtension->FunctionSupportInfo->LBProvisioningData.ThresholdExponent;
4846 ULONGLONG thresholdSetSize;
4847
4848 //
4849 // SBC-3 states that the threshold exponent (from the 0xB2 VPD page), must
4850 // be non-zero and less than or equal to 32.
4851 //
4852 if (thresholdExponent < 0 || thresholdExponent > 32)
4853 {
4854 TracePrint((TRACE_LEVEL_ERROR,
4855 TRACE_FLAG_GENERAL,
4856 "ClassInterpretLBProvisioningLogPage: DO (%p), Threshold Exponent (%u) is invalid.\n",
4858 thresholdExponent));
4859
4860 return STATUS_NOT_SUPPORTED;
4861 }
4862
4863 if (Resources == NULL ||
4864 ResourcesSize < sizeof(STORAGE_LB_PROVISIONING_MAP_RESOURCES) ||
4865 LogPage == NULL ||
4866 LogPageSize < sizeof(LOG_PAGE_LOGICAL_BLOCK_PROVISIONING))
4867 {
4868 TracePrint((TRACE_LEVEL_ERROR,
4869 TRACE_FLAG_GENERAL,
4870 "ClassInterpretLBProvisioningLogPage: DO (%p), Invalid parameter, Resources = %p, ResourcesSize = %u, LogPage = %p, LogPageSize = %u.\n",
4872 Resources,
4873 ResourcesSize,
4874 LogPage,
4875 LogPageSize));
4876
4878 }
4879
4880 //
4881 // Calculate the threshold set size (in LBAs).
4882 //
4883 thresholdSetSize = 1ULL << thresholdExponent;
4884
4885 REVERSE_BYTES_SHORT(&pageLength, &(LogPage->PageLength));
4886
4887 //
4888 // Initialize the output buffer.
4889 //
4893
4894 //
4895 // Make sure we don't walk off the end of the log page buffer
4896 // if pageLength is somehow longer than the buffer itself.
4897 //
4898 pageLength = (USHORT)min(pageLength, (LogPageSize - FIELD_OFFSET(LOG_PAGE_LOGICAL_BLOCK_PROVISIONING, Parameters)));
4899
4901 endOfPage = (PVOID)((PUCHAR)parameter + pageLength);
4902
4903 //
4904 // Walk the parameters.
4905 //
4906 while ((PVOID)parameter < endOfPage)
4907 {
4908 if (parameter->ParameterLength > 0)
4909 {
4910 REVERSE_BYTES_SHORT(&parameterCode, &(parameter->ParameterCode));
4911 switch(parameterCode)
4912 {
4914 {
4916 Resources->AvailableMappingResources = (ULONGLONG)resourceCount * thresholdSetSize * (ULONGLONG)fdoExtension->DiskGeometry.BytesPerSector;
4917 Resources->AvailableMappingResourcesValid = TRUE;
4918
4919 //
4920 // Devices that implement SBC-3 revisions older than r27 will not specify
4921 // an LBP log page parameter that has fields beyond ResourceCount.
4922 //
4923 if (parameter->ParameterLength > FIELD_OFFSET(LOG_PARAMETER_THRESHOLD_RESOURCE_COUNT, ResourceCount[3])) {
4924 Resources->AvailableMappingResourcesScope = ((PLOG_PARAMETER_THRESHOLD_RESOURCE_COUNT)parameter)->Scope;
4925 }
4926
4927 break;
4928 }
4929
4931 {
4933 Resources->UsedMappingResources = (ULONGLONG)resourceCount * thresholdSetSize * (ULONGLONG)fdoExtension->DiskGeometry.BytesPerSector;
4934 Resources->UsedMappingResourcesValid = TRUE;
4935
4936 //
4937 // Devices that implement SBC-3 revisions older than r27 will not specify
4938 // an LBP log page parameter that has fields beyond ResourceCount.
4939 //
4940 if (parameter->ParameterLength > FIELD_OFFSET(LOG_PARAMETER_THRESHOLD_RESOURCE_COUNT, ResourceCount[3])) {
4941 Resources->UsedMappingResourcesScope = ((PLOG_PARAMETER_THRESHOLD_RESOURCE_COUNT)parameter)->Scope;
4942 }
4943
4944 break;
4945 }
4946 }
4947 }
4948
4949 //
4950 // Move to the next parameter.
4951 //
4952 parameter = (PLOG_PARAMETER_HEADER)((PUCHAR)parameter + sizeof(LOG_PARAMETER_HEADER) + parameter->ParameterLength);
4953 }
4954
4955 return STATUS_SUCCESS;
4956}
static ULONG ResourceCount
Definition: inbv.c:50
unsigned short USHORT
Definition: pedump.c:61
struct _LOG_PARAMETER_HEADER LOG_PARAMETER_HEADER
#define LOG_PAGE_LBP_PARAMETER_CODE_USED
Definition: scsi.h:3360
struct _LOG_PARAMETER_THRESHOLD_RESOURCE_COUNT * PLOG_PARAMETER_THRESHOLD_RESOURCE_COUNT
struct _LOG_PARAMETER_HEADER * PLOG_PARAMETER_HEADER
#define LOG_PAGE_LBP_PARAMETER_CODE_AVAILABLE
Definition: scsi.h:3359
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
ULONG BytesPerSector
Definition: ntdddisk.h:409
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
void * PVOID
Definition: typedefs.h:50
uint64_t ULONGLONG
Definition: typedefs.h:67
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:869

Referenced by ClassGetLBProvisioningResources().

◆ 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}
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
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
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 FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
Definition: ntddstor.h:609
* PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
Definition: ntddstor.h:609
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
static void Exit(void)
Definition: sock.c:1330

Referenced by ClassDeviceControl().

◆ 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

Referenced by ClasspContinueOffloadWrite(), and ClasspReceivePopulateTokenInformationTransferPacketDone().

◆ 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
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
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 KernelMode
Definition: asm.h:34
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864

Referenced by BuildDeviceInputMdl().

◆ 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}

Referenced by InterpretCapacityData(), and InterpretReadCapacity16Data().

◆ 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
ULONG TimeOutValue
Definition: srb.h:262
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
UCHAR CdbLength
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:279
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().

◆ 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
PVOID dataBuffer
#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
struct _CDB::_CDB6INQUIRY3 CDB6INQUIRY3
_In_opt_ PVOID _In_ ULONG bufferLength
Definition: wdfdriver.h:109

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_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
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
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
LONGLONG QuadPart
Definition: typedefs.h:114

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
_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
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
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
#define REVERSE_BYTES_QUAD(Destination, Source)
Definition: scsi.h:3452
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
ULONGLONG LengthInBytes
Definition: ntddstor.h:768
LONGLONG StartingOffset
Definition: ntddstor.h:767
_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().

◆ ClasspDuidGetDeviceIdProperty()

NTSTATUS ClasspDuidGetDeviceIdProperty ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 689 of file utils.c.

693{
694 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
695 PSTORAGE_DEVICE_ID_DESCRIPTOR deviceIdDescriptor = NULL;
699 PUCHAR dest;
700
702
704
705 ULONG queryLength;
707
708 //
709 // Get the VPD page 83h data.
710 //
711
712 status = ClassGetDescriptor(commonExtension->LowerDeviceObject,
713 &propertyId,
714 (PVOID *)&deviceIdDescriptor);
715
716 if (!NT_SUCCESS(status) || !deviceIdDescriptor) {
717 goto FnExit;
718 }
719
720 queryLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
721 descHeader = Irp->AssociatedIrp.SystemBuffer;
722
723 //
724 // Adjust required size and potential destination location.
725 //
726
727 offset = descHeader->Size;
728 dest = (PUCHAR)descHeader + offset;
729
730 descHeader->Size += deviceIdDescriptor->Size;
731
732 if (queryLength < descHeader->Size) {
733
734 //
735 // Output buffer is too small. Return error and make sure
736 // the caller gets info about required buffer size.
737 //
738
739 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
741 goto FnExit;
742 }
743
744 storageDuid = Irp->AssociatedIrp.SystemBuffer;
745 storageDuid->StorageDeviceIdOffset = offset;
746
748 deviceIdDescriptor,
749 deviceIdDescriptor->Size);
750
751 Irp->IoStatus.Information = storageDuid->Size;
753
754FnExit:
755
756 FREE_POOL(deviceIdDescriptor);
757
758 return status;
759}
GLintptr offset
Definition: glext.h:5920
static char * dest
Definition: rtl.c:135
* PSTORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
enum _STORAGE_PROPERTY_ID STORAGE_PROPERTY_ID
@ StorageDeviceIdProperty
Definition: ntddstor.h:514
* PSTORAGE_DEVICE_ID_DESCRIPTOR
Definition: ntddstor.h:742
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by ClasspDuidQueryProperty().

◆ ClasspDuidGetDeviceProperty()

NTSTATUS ClasspDuidGetDeviceProperty ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 782 of file utils.c.

786{
787 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
788 PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor = fdoExtension->DeviceDescriptor;
792 PUCHAR dest;
793
795
796 ULONG queryLength;
798
799 //
800 // Use the StorageDeviceProperty already cached in the device extension.
801 //
802
803 if (!deviceDescriptor) {
804 goto FnExit;
805 }
806
807 queryLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
808 descHeader = Irp->AssociatedIrp.SystemBuffer;
809
810 //
811 // Use this info only if serial number is available.
812 //
813
814 if (deviceDescriptor->SerialNumberOffset == 0) {
815 goto FnExit;
816 }
817
818 //
819 // Adjust required size and potential destination location.
820 //
821
822 offset = descHeader->Size;
823 dest = (PUCHAR)descHeader + offset;
824
825 descHeader->Size += deviceDescriptor->Size;
826
827 if (queryLength < descHeader->Size) {
828
829 //
830 // Output buffer is too small. Return error and make sure
831 // the caller get info about required buffer size.
832 //
833
834 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
836 goto FnExit;
837 }
838
839 storageDuid = Irp->AssociatedIrp.SystemBuffer;
840 storageDuid->StorageDeviceOffset = offset;
841
843 deviceDescriptor,
844 deviceDescriptor->Size);
845
846 Irp->IoStatus.Information = storageDuid->Size;
848
849FnExit:
850
851 return status;
852}
* PSTORAGE_DEVICE_DESCRIPTOR
Definition: ntddstor.h:576
#define STATUS_NOT_FOUND
Definition: shellext.h:72

Referenced by ClasspDuidQueryProperty().

◆ ClasspDuidGetDriveLayout()

NTSTATUS ClasspDuidGetDriveLayout ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 875 of file utils.c.

879{
880 PDRIVE_LAYOUT_INFORMATION_EX layoutEx = NULL;
884 PSTORAGE_DEVICE_LAYOUT_SIGNATURE driveLayoutSignature;
885
887
888 ULONG queryLength;
890
891 //
892 // Only process disk-type devices.
893 //
894
895 if (DeviceObject->DeviceType != FILE_DEVICE_DISK) {
896 goto FnExit;
897 }
898
899 //
900 // Get current partition table and process only if GPT
901 // or MBR layout.
902 //
903
905
906 if (!NT_SUCCESS(status)) {
908 goto FnExit;
909 }
910
911 if (layoutEx->PartitionStyle != PARTITION_STYLE_GPT &&
912 layoutEx->PartitionStyle != PARTITION_STYLE_MBR) {
914 goto FnExit;
915 }
916
917 queryLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
918 descHeader = Irp->AssociatedIrp.SystemBuffer;
919
920 //
921 // Adjust required size and potential destination location.
922 //
923
924 offset = descHeader->Size;
925 driveLayoutSignature = (PSTORAGE_DEVICE_LAYOUT_SIGNATURE)((PUCHAR)descHeader + offset);
926
927 descHeader->Size += sizeof(STORAGE_DEVICE_LAYOUT_SIGNATURE);
928
929 if (queryLength < descHeader->Size) {
930
931 //
932 // Output buffer is too small. Return error and make sure
933 // the caller get info about required buffer size.
934 //
935
936 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
938 goto FnExit;
939 }
940
941 storageDuid = Irp->AssociatedIrp.SystemBuffer;
942
943 driveLayoutSignature->Size = sizeof(STORAGE_DEVICE_LAYOUT_SIGNATURE);
944 driveLayoutSignature->Version = DUID_VERSION_1;
945
946 if (layoutEx->PartitionStyle == PARTITION_STYLE_MBR) {
947
948 driveLayoutSignature->Mbr = TRUE;
949
950 RtlCopyMemory(&driveLayoutSignature->DeviceSpecific.MbrSignature,
951 &layoutEx->Mbr.Signature,
952 sizeof(layoutEx->Mbr.Signature));
953
954 } else {
955
956 driveLayoutSignature->Mbr = FALSE;
957
958 RtlCopyMemory(&driveLayoutSignature->DeviceSpecific.GptDiskId,
959 &layoutEx->Gpt.DiskId,
960 sizeof(layoutEx->Gpt.DiskId));
961 }
962
963 storageDuid->DriveLayoutSignatureOffset = offset;
964
965 Irp->IoStatus.Information = storageDuid->Size;
967
968
969FnExit:
970
971 FREE_POOL(layoutEx);
972
973 return status;
974}
NTSTATUS NTAPI IoReadPartitionTableEx(IN PDEVICE_OBJECT DeviceObject, IN PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: fstubex.c:2279
@ PARTITION_STYLE_GPT
Definition: imports.h:202
@ PARTITION_STYLE_MBR
Definition: imports.h:201
struct _STORAGE_DEVICE_LAYOUT_SIGNATURE STORAGE_DEVICE_LAYOUT_SIGNATURE
#define DUID_VERSION_1
Definition: storduid.h:20
struct _STORAGE_DEVICE_LAYOUT_SIGNATURE * PSTORAGE_DEVICE_LAYOUT_SIGNATURE
union _STORAGE_DEVICE_LAYOUT_SIGNATURE::@2221 DeviceSpecific

Referenced by ClasspDuidQueryProperty().

◆ 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
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
@ DuidExactMatch
Definition: storduid.h:6
#define DUID_HARDWARE_IDS_ONLY
Definition: storduid.h:22

Referenced by ClassDeviceControl().

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

◆ ClasspGetHwFirmwareInfo()

NTSTATUS ClasspGetHwFirmwareInfo ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 8190 of file utils.c.

8193{
8194 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8195 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
8196
8197 PSTORAGE_HW_FIRMWARE_INFO firmwareInfo = NULL;
8198 PSTORAGE_HW_FIRMWARE_INFO_QUERY query = NULL;
8199
8200 IO_STATUS_BLOCK ioStatus = {0};
8201 ULONG dataLength = sizeof(STORAGE_HW_FIRMWARE_INFO);
8202 ULONG iteration = 1;
8203
8204 CLASS_FUNCTION_SUPPORT oldState;
8205 KLOCK_QUEUE_HANDLE lockHandle;
8206
8207 //
8208 // Try to get firmware information that contains only one slot.
8209 // We will retry the query if the required buffer size is bigger than that.
8210 //
8211retry:
8212
8213 firmwareInfo = ExAllocatePoolWithTag(NonPagedPoolNx, dataLength, CLASSPNP_POOL_TAG_FIRMWARE);
8214
8215 if (firmwareInfo == NULL) {
8216 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClasspGetHwFirmwareInfo: cannot allocate memory to hold data. \n"));
8218 }
8219
8220 RtlZeroMemory(firmwareInfo, dataLength);
8221
8222 //
8223 // Set up query data, making sure the "Flags" field indicating the request is for device itself.
8224 //
8225 query = (PSTORAGE_HW_FIRMWARE_INFO_QUERY)firmwareInfo;
8226
8227 query->Version = sizeof(STORAGE_HW_FIRMWARE_INFO_QUERY);
8228 query->Size = sizeof(STORAGE_HW_FIRMWARE_INFO_QUERY);
8229 query->Flags = 0;
8230
8231 //
8232 // On the first pass we just want to get the first few
8233 // bytes of the descriptor so we can read it's size
8234 //
8236 commonExtension->LowerDeviceObject,
8237 query,
8238 sizeof(STORAGE_HW_FIRMWARE_INFO_QUERY),
8239 dataLength,
8240 FALSE,
8241 &ioStatus
8242 );
8243
8244 if (!NT_SUCCESS(ioStatus.Status) &&
8245 (ioStatus.Status != STATUS_BUFFER_OVERFLOW)) {
8246 if (ClasspLowerLayerNotSupport(ioStatus.Status)) {
8247 oldState = InterlockedCompareExchange((PLONG)(&fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport), (LONG)NotSupported, (ULONG)SupportUnknown);
8248 }
8249
8250 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClasspGetHwFirmwareInfo: error %lx trying to "
8251 "query hardware firmware information #%d \n", ioStatus.Status, iteration));
8252 FREE_POOL(firmwareInfo);
8253 return ioStatus.Status;
8254 }
8255
8256 //
8257 // Catch implementation issues from lower level driver.
8258 //
8259 if ((firmwareInfo->Version < sizeof(STORAGE_HW_FIRMWARE_INFO)) ||
8260 (firmwareInfo->Size < sizeof(STORAGE_HW_FIRMWARE_INFO)) ||
8261 (firmwareInfo->SlotCount == 0) ||
8262 (firmwareInfo->ImagePayloadMaxSize > fdoExtension->AdapterDescriptor->MaximumTransferLength)) {
8263
8264 oldState = InterlockedCompareExchange((PLONG)(&fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport), (LONG)NotSupported, (ULONG)SupportUnknown);
8265
8266 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClasspGetHwFirmwareInfo: error in returned data! "
8267 "Version: 0x%X, Size: 0x%X, SlotCount: 0x%X, ActiveSlot: 0x%X, PendingActiveSlot: 0x%X, ImagePayloadMaxSize: 0x%X \n",
8268 firmwareInfo->Version,
8269 firmwareInfo->Size,
8270 firmwareInfo->SlotCount,
8271 firmwareInfo->ActiveSlot,
8272 firmwareInfo->PendingActivateSlot,
8273 firmwareInfo->ImagePayloadMaxSize));
8274
8275 FREE_POOL(firmwareInfo);
8276 return STATUS_UNSUCCESSFUL;
8277 }
8278
8279 //
8280 // If the data size is bigger than sizeof(STORAGE_HW_FIRMWARE_INFO), e.g. device has more than one firmware slot,
8281 // allocate a buffer to get all the data.
8282 //
8283 if ((firmwareInfo->Size > sizeof(STORAGE_HW_FIRMWARE_INFO)) &&
8284 (iteration < 2)) {
8285
8286 dataLength = max(firmwareInfo->Size, sizeof(STORAGE_HW_FIRMWARE_INFO) + sizeof(STORAGE_HW_FIRMWARE_SLOT_INFO) * (firmwareInfo->SlotCount - 1));
8287
8288 //
8289 // Retry the query with required buffer length.
8290 //
8291 FREE_POOL(firmwareInfo);
8292 iteration++;
8293 goto retry;
8294 }
8295
8296
8297 //
8298 // Set the support status and use the memory we've allocated as caching buffer.
8299 // In case of a competing thread already set the state, it will assign the caching buffer so release the current allocated one.
8300 //
8301 KeAcquireInStackQueuedSpinLock(&fdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
8302
8303 oldState = InterlockedCompareExchange((PLONG)(&fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport), (LONG)Supported, (ULONG)SupportUnknown);
8304
8305 if (oldState == SupportUnknown) {
8306 fdoExtension->FunctionSupportInfo->HwFirmwareInfo = firmwareInfo;
8307 } else if (oldState == Supported) {
8308 //
8309 // swap the buffers to keep the latest version.
8310 //
8311 PSTORAGE_HW_FIRMWARE_INFO cachedInfo = fdoExtension->FunctionSupportInfo->HwFirmwareInfo;
8312
8313 fdoExtension->FunctionSupportInfo->HwFirmwareInfo = firmwareInfo;
8314
8315 FREE_POOL(cachedInfo);
8316 } else {
8317 FREE_POOL(firmwareInfo);
8318 }
8319
8320 KeReleaseInStackQueuedSpinLock(&lockHandle);
8321
8322 return ioStatus.Status;
8323} // end ClasspGetHwFirmwareInfo()
static int iteration
Definition: StackOverflow.c:16
CLASS_FUNCTION_SUPPORT
Definition: classpnp.h:731
VOID NTAPI ClassSendDeviceIoControlSynchronous(_In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT TargetDeviceObject, _Inout_updates_opt_(_Inexpressible_(max(InputBufferLength, OutputBufferLength))) PVOID Buffer, _In_ ULONG InputBufferLength, _In_ ULONG OutputBufferLength, _In_ BOOLEAN InternalDeviceIoControl, _Out_ PIO_STATUS_BLOCK IoStatus)
Definition: class.c:11065
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define IOCTL_STORAGE_FIRMWARE_GET_INFO
Definition: ntddstor.h:205
#define max(a, b)
Definition: svc.c:63

Referenced by ClassDeviceHwFirmwareActivateProcess(), ClassDeviceHwFirmwareDownloadProcess(), and ClassDeviceHwFirmwareGetInfoProcess().

◆ 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_TOKEN_OPERATION_PARAMETER_DATA_LENGTH
Definition: classp.h:207
#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
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599

◆ 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

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

◆ 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}

Referenced by ClassDispatchPnp(), and ClassIoComplete().

◆ 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

◆ 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 InterlockedIncrement
Definition: armddk.h:53
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#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
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
struct _CLASS_PRIVATE_FDO_DATA::@1055 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}
#define InterlockedDecrement
Definition: armddk.h:52

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

◆ 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
BOOLEAN IdlePrioritySupported
Definition: classp.h:808
@ IoPriorityNormal
Definition: iotypes.h:1233
@ IoPriorityLow
Definition: iotypes.h:1232
@ 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
struct _FOUR_BYTE * PFOUR_BYTE
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
_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
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN _In_ PCDB Cdb
Definition: scratch.h:159
#define lba
struct _CDB::_CDB10 CDB10
struct _CDB::_CDB6GENERIC CDB6GENERIC
struct _CDB::_CDB16 CDB16
@ DelayedWorkQueue
Definition: extypes.h:190

Referenced by ClassInterpretSenseInfo().

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

◆ 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
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179

Referenced by ClassDeviceControl().

◆ 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
GLsizeiptr size
Definition: glext.h:5919
#define MODE_PAGE_CONTROL
Definition: scsi.h:202
UCHAR PageSavable
Definition: scsi.h:3388

◆ 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}
IO_WORKITEM_ROUTINE ClassLogThresholdEvent
Definition: classp.h:2298

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
#define SCSIOP_READ_CAPACITY16
Definition: scsi.h:364
struct _CDB::_READ_CAPACITY16 READ_CAPACITY16

Referenced by ClasspAccessAlignmentProperty().

◆ ConvertDataSetRangeToUnmapBlockDescr()

VOID ConvertDataSetRangeToUnmapBlockDescr ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
_In_ PUNMAP_BLOCK_DESCRIPTOR  BlockDescr,
_Inout_ PULONG  CurrentBlockDescrIndex,
_In_ ULONG  MaxBlockDescrIndex,
_Inout_ PULONGLONG  CurrentLbaCount,
_In_ ULONGLONG  MaxLbaCount,
_Inout_ PDEVICE_DATA_SET_RANGE  DataSetRange 
)

Definition at line 3047 of file utils.c.

3100{
3101
3102 ULONGLONG startingSector;
3104
3105 TracePrint((TRACE_LEVEL_INFORMATION,
3106 TRACE_FLAG_IOCTL,
3107 "ConvertDataSetRangeToUnmapBlockDescr (%p): Generating UNMAP Block Descriptors from DataSetRange: \
3108 \n\t\tStartingOffset = %I64u bytes \
3109 \n\t\tLength = %I64u bytes\n",
3110 FdoExtension->DeviceObject,
3111 DataSetRange->StartingOffset,
3112 DataSetRange->LengthInBytes));
3113
3114 while ( (DataSetRange->LengthInBytes > 0) &&
3115 (*CurrentBlockDescrIndex < MaxBlockDescrIndex) &&
3117
3118 //
3119 // Convert the starting offset and length from bytes to blocks.
3120 //
3121 startingSector = (ULONGLONG)(DataSetRange->StartingOffset / FdoExtension->DiskGeometry.BytesPerSector);
3122 sectorCount = (DataSetRange->LengthInBytes / FdoExtension->DiskGeometry.BytesPerSector);
3123
3124 //
3125 // Make sure the sector count isn't more than can be specified with a
3126 // single descriptor.
3127 //
3128 if (sectorCount > MAXULONG) {
3130 }
3131
3132 //
3133 // The max LBA count is the max number of LBAs that can be unmapped with
3134 // a single UNMAP command. Make sure we don't exceed this value.
3135 //
3138 }
3139
3140 REVERSE_BYTES_QUAD(BlockDescr[*CurrentBlockDescrIndex].StartingLba, &startingSector);
3142
3143 DataSetRange->StartingOffset += sectorCount * FdoExtension->DiskGeometry.BytesPerSector;
3144 DataSetRange->LengthInBytes -= sectorCount * FdoExtension->DiskGeometry.BytesPerSector;
3145
3148
3149 TracePrint((TRACE_LEVEL_INFORMATION,
3150 TRACE_FLAG_IOCTL,
3151 "ConvertDataSetRangeToUnmapBlockDescr (%p): Generated UNMAP Block Descriptor: \
3152 \n\t\t\tStartingLBA = %I64u \
3153 \n\t\t\tLBACount = %I64u\n",
3154 FdoExtension->DeviceObject,
3155 startingSector,
3156 sectorCount));
3157 }
3158
3159 return;
3160}
_In_ PVOID BlockDescr
Definition: classp.h:1996
_In_ PVOID _Inout_ PULONG _In_ ULONG _Inout_ PULONG _In_ ULONGLONG MaxLbaCount
Definition: classp.h:2000
_In_ PVOID _Inout_ PULONG CurrentBlockDescrIndex
Definition: classp.h:1997
_In_ PVOID _Inout_ PULONG _In_ ULONG _Inout_ PULONG _In_ ULONGLONG _Inout_ PDEVICE_DATA_SET_RANGE DataSetRange
Definition: classp.h:2001
_In_ PVOID _Inout_ PULONG _In_ ULONG _Inout_ PULONG CurrentLbaCount
Definition: classp.h:1999
UINT sectorCount[1]
Definition: diskio.c:16

Referenced by DeviceProcessDsmTrimRequest().

◆ DeviceProcessDsmTrimRequest()

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

3195{
3197
3199 PUNMAP_BLOCK_DESCRIPTOR blockDescrPointer;
3201 ULONG maxBlockDescrCount;
3202 ULONG neededBlockDescrCount;
3203 ULONG i;
3204
3205 BOOLEAN allDataSetRangeFullyConverted;
3206 BOOLEAN needToSendCommand;
3207 BOOLEAN tempDataSetRangeFullyConverted;
3208
3209 ULONG dataSetRangeIndex;
3210 DEVICE_DATA_SET_RANGE tempDataSetRange;
3211
3212 ULONG blockDescrIndex;
3213 ULONGLONG lbaCount;
3214 ULONGLONG maxLbaCount;
3215 ULONGLONG maxParameterListLength;
3216
3217
3218 UNREFERENCED_PARAMETER(UnmapGranularity);
3221
3222 //
3223 // The given LBA ranges are in DEVICE_DATA_SET_RANGE format and need to be converted into UNMAP Block Descriptors.
3224 // The UNMAP command is able to carry 0xFFFF bytes (0xFFF8 in reality as there are 8 bytes of header plus n*16 bytes of Block Descriptors) of data.
3225 // The actual size will also be constrained by the Maximum LBA Count and Maximum Transfer Length.
3226 //
3227
3228 //
3229 // 1.1 Calculate how many Block Descriptors are needed to complete this request.
3230 //
3231 neededBlockDescrCount = 0;
3232 for (i = 0; i < DataSetRangesCount; i++) {
3233 lbaCount = DataSetRanges[i].LengthInBytes / FdoExtension->DiskGeometry.BytesPerSector;
3234
3235 //
3236 // 1.1.1 the UNMAP_BLOCK_DESCRIPTOR LbaCount is 32 bits, the max value is 0xFFFFFFFF
3237 //
3238 if (lbaCount > 0) {
3239 neededBlockDescrCount += (ULONG)((lbaCount - 1) / MAXULONG + 1);
3240 }
3241 }
3242
3243 //
3244 // Honor Max Unmap Block Descriptor Count if it has been specified. Otherwise,
3245 // use the maximum value that the Parameter List Length field will allow (0xFFFF).
3246 // If the count is 0xFFFFFFFF, then no maximum is specified.
3247 //
3248 if (FdoExtension->FunctionSupportInfo->BlockLimitsData.MaxUnmapBlockDescrCount != 0 &&
3249 FdoExtension->FunctionSupportInfo->BlockLimitsData.MaxUnmapBlockDescrCount != MAXULONG)
3250 {
3251 maxParameterListLength = (ULONGLONG)(FdoExtension->FunctionSupportInfo->BlockLimitsData.MaxUnmapBlockDescrCount * sizeof(UNMAP_BLOCK_DESCRIPTOR))
3252 + sizeof(UNMAP_LIST_HEADER);
3253
3254 //
3255 // In the SBC-3, the Max Unmap Block Descriptor Count field in the 0xB0
3256 // page is 4 bytes and the Parameter List Length in the UNMAP command is
3257 // 2 bytes, therefore it is possible that the Max Unmap Block Descriptor
3258 // Count could imply more bytes than can be specified in the Parameter
3259 // List Length field. Adjust for that here.
3260 //
3261 maxParameterListLength = min(maxParameterListLength, MAXUSHORT);
3262 }
3263 else
3264 {
3265 maxParameterListLength = MAXUSHORT;
3266 }
3267
3268 //
3269 // 1.2 Calculate the buffer size needed, capped by the device's limitations.
3270 //
3271 bufferLength = min(FdoExtension->PrivateFdoData->HwMaxXferLen, (ULONG)maxParameterListLength);
3272 bufferLength = min(bufferLength, (neededBlockDescrCount * sizeof(UNMAP_BLOCK_DESCRIPTOR) + sizeof(UNMAP_LIST_HEADER)));
3273
3274 maxBlockDescrCount = (bufferLength - sizeof(UNMAP_LIST_HEADER)) / sizeof(UNMAP_BLOCK_DESCRIPTOR);
3275
3276 if (maxBlockDescrCount == 0) {
3277 //
3278 // This shouldn't happen since we've already done validation.
3279 //
3280 TracePrint((TRACE_LEVEL_INFORMATION,
3281 TRACE_FLAG_IOCTL,
3282 "DeviceProcessDsmTrimRequest (%p): Max Block Descriptor count is Zero\n",
3283 FdoExtension->DeviceObject));
3284
3285 NT_ASSERT(maxBlockDescrCount != 0);
3287 goto Exit;
3288 }
3289
3290 //
3291 // The Maximum LBA Count is set during device initialization.
3292 //
3293 maxLbaCount = (ULONGLONG)FdoExtension->FunctionSupportInfo->BlockLimitsData.MaxUnmapLbaCount;
3294 if (maxLbaCount == 0) {
3295 //
3296 // This shouldn't happen since we've already done validation.
3297 //
3298 TracePrint((TRACE_LEVEL_INFORMATION,
3299 TRACE_FLAG_IOCTL,
3300 "DeviceProcessDsmTrimRequest (%p): Max LBA count is Zero\n",
3301 FdoExtension->DeviceObject));
3302
3303 NT_ASSERT(maxLbaCount != 0);
3305 goto Exit;
3306 }
3307
3308 //
3309 // Finally, allocate the buffer we'll use to send the UNMAP command.
3310 //
3311
3312#if defined(_ARM_) || defined(_ARM64_)
3313 //
3314 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
3315 // based platforms. We are taking the conservative approach here.
3316 //
3319#else
3321#endif
3322
3323 if (buffer == NULL) {
3325 goto Exit;
3326 }
3327
3329
3330 blockDescrPointer = &buffer->Descriptors[0];
3331
3332 allDataSetRangeFullyConverted = FALSE;
3333 needToSendCommand = FALSE;
3334 tempDataSetRangeFullyConverted = TRUE;
3335 dataSetRangeIndex = 0;
3336 RtlZeroMemory(&tempDataSetRange, sizeof(tempDataSetRange));
3337
3338 blockDescrIndex = 0;
3339 lbaCount = 0;
3340
3341
3342 while (!allDataSetRangeFullyConverted) {
3343
3344 //
3345 // If the previous entry conversion completed, go on to the next one;
3346 // otherwise, continue processing the current entry.
3347 //
3348 if (tempDataSetRangeFullyConverted) {
3349 tempDataSetRange.StartingOffset = DataSetRanges[dataSetRangeIndex].StartingOffset;
3350 tempDataSetRange.LengthInBytes = DataSetRanges[dataSetRangeIndex].LengthInBytes;
3351 dataSetRangeIndex++;
3352 }
3353
3355 blockDescrPointer,
3356 &blockDescrIndex,
3357 maxBlockDescrCount,
3358 &lbaCount,
3359 maxLbaCount,
3360 &tempDataSetRange
3361 );
3362
3363 tempDataSetRangeFullyConverted = (tempDataSetRange.LengthInBytes == 0) ? TRUE : FALSE;
3364
3365 allDataSetRangeFullyConverted = tempDataSetRangeFullyConverted && (dataSetRangeIndex == DataSetRangesCount);
3366
3367 //
3368 // Send the UNMAP command when the buffer is full or when all input entries are converted.
3369 //
3370 if ((blockDescrIndex == maxBlockDescrCount) || // Buffer full or block descriptor count reached
3371 (lbaCount == maxLbaCount) || // Block LBA count reached
3372 allDataSetRangeFullyConverted) { // All DataSetRanges have been converted
3373
3374 USHORT transferSize;
3375 USHORT tempSize;
3376 PCDB cdb;
3377
3378 //
3379 // Get the transfer size, including the header.
3380 //
3381 transferSize = (USHORT)(blockDescrIndex * sizeof(UNMAP_BLOCK_DESCRIPTOR) + sizeof(UNMAP_LIST_HEADER));
3382 if (transferSize > bufferLength)
3383 {
3384 //
3385 // This should never happen.
3386 //
3387 NT_ASSERT(transferSize <= bufferLength);
3389 break;
3390 }
3391
3392 tempSize = transferSize - (USHORT)FIELD_OFFSET(UNMAP_LIST_HEADER, BlockDescrDataLength);
3393 REVERSE_BYTES_SHORT(buffer->DataLength, &tempSize);
3394 tempSize = transferSize - (USHORT)FIELD_OFFSET(UNMAP_LIST_HEADER, Descriptors[0]);
3395 REVERSE_BYTES_SHORT(buffer->BlockDescrDataLength, &tempSize);
3396
3397 //
3398 // Initialize the SRB.
3399 //
3400 if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
3404 1,
3406 if (NT_SUCCESS(status)) {
3408 } else {
3409 //
3410 // Should not occur.
3411 //
3413 break;
3414 }
3415
3416 } else {
3418 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
3420 }
3421
3422 //
3423 // Prepare the Srb
3424 //
3425 SrbSetTimeOutValue(Srb, FdoExtension->TimeOutValue);
3428
3429 //
3430 // Set the SrbFlags to indicate that it's a data-out operation.
3431 // Also set any passed-in SrbFlags.
3432 //
3436 SrbSetSrbFlags(Srb, SrbFlags);
3437
3438 SrbSetCdbLength(Srb, 10);
3439
3440 cdb = SrbGetCdb(Srb);
3441 cdb->UNMAP.OperationCode = SCSIOP_UNMAP;
3442 cdb->UNMAP.Anchor = 0;
3443 cdb->UNMAP.GroupNumber = 0;
3444 cdb->UNMAP.AllocationLength[0] = (UCHAR)(transferSize >> 8);
3445 cdb->UNMAP.AllocationLength[1] = (UCHAR)transferSize;
3446
3448 Srb,
3449 buffer,
3450 transferSize,
3451 TRUE);
3452
3453 TracePrint((TRACE_LEVEL_INFORMATION,
3454 TRACE_FLAG_IOCTL,
3455 "DeviceProcessDsmTrimRequest (%p): UNMAP command issued. Returned NTSTATUS: %!STATUS!.\n",
3456 FdoExtension->DeviceObject,
3457 status
3458 ));
3459
3460 //
3461 // Clear the buffer so we can re-use it.
3462 //
3463 blockDescrIndex = 0;
3464 lbaCount = 0;
3466 }
3467 }
3468
3469Exit:
3470
3472
3473 return status;
3474}
VOID ConvertDataSetRangeToUnmapBlockDescr(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PUNMAP_BLOCK_DESCRIPTOR BlockDescr, _Inout_ PULONG CurrentBlockDescrIndex, _In_ ULONG MaxBlockDescrIndex, _Inout_ PULONGLONG CurrentLbaCount, _In_ ULONGLONG MaxLbaCount, _Inout_ PDEVICE_DATA_SET_RANGE DataSetRange)
Definition: utils.c:3047
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:401
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
#define STATUS_DATA_ERROR
Definition: ntstatus.h:298
struct _UNMAP_BLOCK_DESCRIPTOR UNMAP_BLOCK_DESCRIPTOR
struct _UNMAP_LIST_HEADER UNMAP_LIST_HEADER
#define SCSIOP_UNMAP
Definition: scsi.h:296
struct _UNMAP_LIST_HEADER * PUNMAP_LIST_HEADER
FORCEINLINE VOID SrbClearSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:982
struct _CDB::_UNMAP UNMAP

Referenced by ClasspDeviceTrimProcess().

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

◆ GetLBAStatus()

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

3800{
3802 PCDB cdb;
3803
3804 if (LBAStatusHeader == NULL || LBAStatusSize == 0)
3805 {
3807 }
3808
3809 //
3810 // Build and send down the Get LBA Status command.
3811 //
3812 SrbSetTimeOutValue(Srb, FdoExtension->TimeOutValue);
3816 SrbSetCdbLength(Srb, sizeof(cdb->GET_LBA_STATUS));
3817
3818
3819 cdb = SrbGetCdb(Srb);
3820 cdb->GET_LBA_STATUS.OperationCode = SCSIOP_GET_LBA_STATUS;
3821 cdb->GET_LBA_STATUS.ServiceAction = SERVICE_ACTION_GET_LBA_STATUS;
3822 REVERSE_BYTES_QUAD(&(cdb->GET_LBA_STATUS.StartingLBA), &StartingLBA);
3823 REVERSE_BYTES(&(cdb->GET_LBA_STATUS.AllocationLength), &LBAStatusSize);
3824
3825 TracePrint((TRACE_LEVEL_INFORMATION,
3826 TRACE_FLAG_IOCTL,
3827 "GetLBAStatus (%p): sending command with StartingLBA = 0x%I64x, AllocationLength = 0x%I64x, ConsolidateableBlocksOnly = %u\n",
3828 FdoExtension->DeviceObject,
3829 StartingLBA,
3830 LBAStatusSize,
3831 ConsolidateableBlocksOnly));
3832
3834 Srb,
3835 LBAStatusHeader,
3836 LBAStatusSize,
3837 FALSE);
3838
3839 //
3840 // Handle the case where we get back STATUS_DATA_OVERRUN b/c the input
3841 // buffer was larger than necessary.
3842 //
3843 if (status == STATUS_DATA_OVERRUN &&
3844 SrbGetDataTransferLength(Srb) < LBAStatusSize)
3845 {
3847 }
3848
3849 // log command.
3850 TracePrint((TRACE_LEVEL_INFORMATION,
3851 TRACE_FLAG_IOCTL,
3852 "GetLBAStatus (%p): command returned NT Status: %!STATUS!\n",
3853 FdoExtension->DeviceObject,
3854 status
3855 ));
3856
3857 return status;
3858}
#define SERVICE_ACTION_GET_LBA_STATUS
Definition: scsi.h:475
#define SCSIOP_GET_LBA_STATUS
Definition: scsi.h:365
struct _CDB::_GET_LBA_STATUS GET_LBA_STATUS

Referenced by ClasspDeviceGetLBAStatusWorker().

◆ IncursSeekPenalty()

static NTSTATUS IncursSeekPenalty ( _In_ USHORT  MediumRotationRate,
_In_ PBOOLEAN  IncursSeekPenalty 
)
static

Definition at line 1888 of file utils.c.

1892{
1894
1895 if (MediumRotationRate == 0x0001) {
1896 // Non-rotating media (e.g., solid state device)
1899 } else if ( (MediumRotationRate >= 0x401) &&
1900 (MediumRotationRate <= 0xFFFE) ) {
1901 // Nominal media rotation rate in rotations per minute (rpm)
1904 } else {
1905 // Unknown cases:
1906 // 0 - Rate not reported
1907 // 0002h-0400h - Reserved
1908 // FFFFh - Reserved
1910 }
1911
1912 return status;
1913}

Referenced by ClasspDeviceSeekPenaltyProperty(), and IncursSeekPenalty().

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

◆ ValidPersistentReserveScope()

static BOOLEAN ValidPersistentReserveScope ( UCHAR  Scope)
static

Definition at line 6152 of file utils.c.

6154{
6155 switch (Scope) {
6158
6159 return TRUE;
6160
6161 default:
6162
6163 break;
6164 }
6165
6166 return FALSE;
6167}
#define RESERVATION_SCOPE_ELEMENT
Definition: scsi.h:588
#define RESERVATION_SCOPE_LU
Definition: scsi.h:587

Referenced by ClasspPersistentReserve().

◆ ValidPersistentReserveType()

static BOOLEAN ValidPersistentReserveType ( UCHAR  Type)
static

Definition at line 6171 of file utils.c.

6173{
6174 switch (Type) {
6179
6180 return TRUE;
6181
6182 default:
6183
6184 break;
6185 }
6186
6187 return FALSE;
6188}
Type
Definition: Type.h:7
#define RESERVATION_TYPE_WRITE_EXCLUSIVE
Definition: scsi.h:590
#define RESERVATION_TYPE_EXCLUSIVE_REGISTRANTS
Definition: scsi.h:593
#define RESERVATION_TYPE_EXCLUSIVE
Definition: scsi.h:591
#define RESERVATION_TYPE_WRITE_EXCLUSIVE_REGISTRANTS
Definition: scsi.h:592

Referenced by ClasspPersistentReserve().