ReactOS  0.4.15-dev-1201-gb2cf5a4
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)
 
__inline 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)
 
__inline BOOLEAN ValidPersistentReserveScope (UCHAR Scope)
 
__inline 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;
5161  PSCSI_REQUEST_BLOCK srb = NULL;
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 SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
LONG NTSTATUS
Definition: precomp.h:26
#define MAXUCHAR
Definition: umtypes.h:117
uint16_t * PWCHAR
Definition: typedefs.h:56
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:628
#define IO_WARNING_SOFT_THRESHOLD_REACHED_EX_POOL_LUN
Definition: ntiologc.h:109
uint32_t ULONG_PTR
Definition: typedefs.h:65
struct _STORAGE_LB_PROVISIONING_MAP_RESOURCES STORAGE_LB_PROVISIONING_MAP_RESOURCES
NTSTATUS ErrorCode
Definition: iotypes.h:1987
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
long LONG
Definition: pedump.c:60
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
static struct resource resources[16]
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
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET
#define ERROR_LOG_MAXIMUM_SIZE
Definition: iotypes.h:2022
#define LOG_PAGE_LBP_RESOURCE_SCOPE_DEDICATED_TO_LUN
Definition: scsi.h:3363
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:528
#define IO_WARNING_SOFT_THRESHOLD_REACHED
Definition: ntiologc.h:105
USHORT NumberOfStrings
Definition: iotypes.h:1984
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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 LOG_PAGE_LBP_RESOURCE_SCOPE_NOT_DEDICATED_TO_LUN
Definition: scsi.h:3364
#define IO_WARNING_SOFT_THRESHOLD_REACHED_EX_LUN_POOL
Definition: ntiologc.h:108
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
static const WCHAR L[]
Definition: oid.c:1250
#define InterlockedExchange
Definition: armddk.h:54
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define min(a, b)
Definition: monoChain.cc:55
#define IO_WARNING_SOFT_THRESHOLD_REACHED_EX
Definition: ntiologc.h:106
struct _IO_ERROR_LOG_PACKET * PIO_ERROR_LOG_PACKET
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
return STATUS_SUCCESS
Definition: btrfs.c:3014
signed int * PLONG
Definition: retypes.h:5
struct _IO_WORKITEM * PIO_WORKITEM
Definition: iotypes.h:489
#define IO_WARNING_SOFT_THRESHOLD_REACHED_EX_LUN_LUN
Definition: ntiologc.h:107
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define IO_WARNING_SOFT_THRESHOLD_REACHED_EX_POOL_POOL
Definition: ntiologc.h:110
Definition: ps.c:97

◆ _IRQL_requires_max_() [1/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 
95  KEY_READ,
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()
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2782
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
smooth NULL
Definition: ftsmooth.c:416
#define RTL_QUERY_REGISTRY_TYPECHECK
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
_In_opt_ PWSTR _In_ PWSTR ParameterName
Definition: cdrom.h:960
#define PLUGPLAY_REGKEY_DRIVER
Definition: usbd.c:42
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
_In_opt_ PWSTR _In_ PWSTR _Inout_ PULONG ParameterValue
Definition: cdrom.h:960
_In_opt_ PWSTR SubkeyName
Definition: cdrom.h:960
NTSTATUS NTAPI IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject, IN ULONG DevInstKeyType, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DevInstRegKey)
Definition: pnpmgr.c:2335
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define REG_NONE
Definition: nt_native.h:1492
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define REG_DWORD
Definition: sdbapi.c:596
static SERVICE_STATUS status
Definition: service.c:31
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define PAGED_CODE()
Definition: ps.c:97

◆ _IRQL_requires_max_() [2/3]

_IRQL_requires_max_ ( APC_LEVEL  )

Definition at line 6894 of file utils.c.

6924 {
6925  NTSTATUS status;
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;
6939  irpStack = IoGetCurrentIrpStackLocation(Irp);
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",
6965  DeviceObject,
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 
6977  if (KeGetCurrentIrql() >= DISPATCH_LEVEL) {
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",
6999  DeviceObject,
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",
7013  DeviceObject,
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",
7038  DeviceObject,
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",
7081  DeviceObject,
7082  status));
7083 
7084  return status;
7085 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
struct _DEVICE_COPY_OFFLOAD_DESCRIPTOR * PDEVICE_COPY_OFFLOAD_DESCRIPTOR
struct _DEVICE_COPY_OFFLOAD_DESCRIPTOR DEVICE_COPY_OFFLOAD_DESCRIPTOR
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
struct _STORAGE_PROPERTY_QUERY * PSTORAGE_PROPERTY_QUERY
STORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
#define STATUS_DEVICE_FEATURE_NOT_SUPPORTED
Definition: ntstatus.h:985
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
static PDB_INFORMATION information
Definition: db.cpp:176
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
static SERVICE_STATUS status
Definition: service.c:31
GLenum query
Definition: glext.h:7781
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ _IRQL_requires_max_() [3/3]

_IRQL_requires_same_ _IRQL_requires_max_ ( DISPATCH_LEVEL  )

Definition at line 8501 of file utils.c.

8508 {
8510 
8511  PIRP originalIrp;
8512 
8513  //
8514  // Free the allocated buffer for firmware image.
8515  //
8516  if (Context != NULL) {
8517  FREE_POOL(Context);
8518  }
8519 
8520  originalIrp = irpStack->Parameters.Others.Argument1;
8521 
8522  NT_ASSERT(originalIrp != NULL);
8523 
8524  originalIrp->IoStatus.Status = Irp->IoStatus.Status;
8525  originalIrp->IoStatus.Information = Irp->IoStatus.Information;
8526 
8527  ClassReleaseRemoveLock(Fdo, originalIrp);
8528  ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT);
8529 
8530  IoFreeIrp(Irp);
8531 
8533 
8534 } // end ClassHwFirmwareDownloadComplete()
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
_In_ PIRP Irp
Definition: csq.h:116
IO_STATUS_BLOCK IoStatus
#define IO_DISK_INCREMENT
Definition: iotypes.h:583
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
#define NT_ASSERT
Definition: rtlfuncs.h:3312

◆ BuildDeviceInputMdl()

PMDL BuildDeviceInputMdl ( PVOID  Buffer,
ULONG  BufferLen 
)

Definition at line 609 of file utils.c.

610 {
611  return ClasspBuildDeviceMdl(Buffer, BufferLen, FALSE);
612 }
#define FALSE
Definition: types.h:117
Definition: bufpool.h:45
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 {
5114  NTSTATUS status;
5116  PSTORAGE_LB_PROVISIONING_MAP_RESOURCES mapResources = (PSTORAGE_LB_PROVISIONING_MAP_RESOURCES)Irp->AssociatedIrp.SystemBuffer;
5117 
5119  Srb,
5120  irpStack->Parameters.DeviceIoControl.OutputBufferLength,
5121  mapResources);
5122 
5123  if (NT_SUCCESS(status)) {
5124  Irp->IoStatus.Information = mapResources->Size;
5125  } else {
5126  Irp->IoStatus.Information = 0;
5127  }
5128 
5129  Irp->IoStatus.Status = status;
5132 
5133  return status;
5134 }
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
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
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
struct _STORAGE_LB_PROVISIONING_MAP_RESOURCES * PSTORAGE_LB_PROVISIONING_MAP_RESOURCES
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define IO_NO_INCREMENT
Definition: iotypes.h:581
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

Referenced by ClassDeviceControl().

◆ ClassDeviceHwFirmwareActivateProcess()

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

Definition at line 8900 of file utils.c.

8905 {
8907 
8908 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
8909 
8910  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8911  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
8912 
8914  PSTORAGE_HW_FIRMWARE_ACTIVATE firmwareActivate = (PSTORAGE_HW_FIRMWARE_ACTIVATE)Irp->AssociatedIrp.SystemBuffer;
8915  BOOLEAN passDown = FALSE;
8916  PCDB cdb = NULL;
8917  ULONG i;
8918  BOOLEAN lockHeld = FALSE;
8919  KLOCK_QUEUE_HANDLE lockHandle;
8920 
8921 
8922  //
8923  // Input buffer is not big enough to contain required input information.
8924  //
8925  if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_HW_FIRMWARE_ACTIVATE)) {
8926 
8928  goto Exit_Firmware_Activate;
8929  }
8930 
8931  //
8932  // Input buffer basic validation.
8933  //
8934  if ((firmwareActivate->Version < sizeof(STORAGE_HW_FIRMWARE_ACTIVATE)) ||
8935  (firmwareActivate->Size > irpStack->Parameters.DeviceIoControl.InputBufferLength)) {
8936 
8938  goto Exit_Firmware_Activate;
8939  }
8940 
8941  //
8942  // Only process the request for a supported port driver.
8943  //
8946  goto Exit_Firmware_Activate;
8947  }
8948 
8949  //
8950  // Buffer "FunctionSupportInfo" is allocated during start device process. Following check defends against the situation
8951  // of receiving this IOCTL when the device is created but not started, or device start failed but did not get removed yet.
8952  //
8953  if (commonExtension->IsFdo && (fdoExtension->FunctionSupportInfo == NULL)) {
8954 
8956  goto Exit_Firmware_Activate;
8957  }
8958 
8959  //
8960  // Process the situation that request should be forwarded to lower level.
8961  //
8962  if (!commonExtension->IsFdo) {
8963  passDown = TRUE;
8964  }
8965 
8966  if ((firmwareActivate->Flags & STORAGE_HW_FIRMWARE_REQUEST_FLAG_CONTROLLER) != 0) {
8967  passDown = TRUE;
8968  }
8969 
8970  if (passDown) {
8971 
8973 
8975  status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8976  FREE_POOL(Srb);
8977  return status;
8978  }
8979 
8980  //
8981  // If firmware information hasn't been cached in classpnp, retrieve it.
8982  //
8983  if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo == NULL) {
8984  if (fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport == NotSupported) {
8986  goto Exit_Firmware_Activate;
8987  } else {
8988  //
8989  // If this is the first time of retrieving firmware information,
8990  // send request to lower level to get it.
8991  //
8993 
8994  if (!NT_SUCCESS(status)) {
8995  goto Exit_Firmware_Activate;
8996  }
8997  }
8998  }
8999 
9000  //
9001  // Fail the request if the firmware information cannot be retrieved.
9002  //
9003  if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo == NULL) {
9004  if (fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport == NotSupported) {
9006  } else {
9008  }
9009 
9010  goto Exit_Firmware_Activate;
9011  }
9012 
9013  //
9014  // Acquire the SyncLock to ensure the HwFirmwareInfo pointer doesn't change
9015  // while we're dereferencing it.
9016  //
9017  lockHeld = TRUE;
9018  KeAcquireInStackQueuedSpinLock(&fdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
9019 
9020  //
9021  // Validate the device support
9022  //
9023  if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SupportUpgrade == FALSE) {
9025  goto Exit_Firmware_Activate;
9026  }
9027 
9028  //
9029  // Check if the slot number is valid.
9030  //
9031  for (i = 0; i < fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SlotCount; i++) {
9032  if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo->Slot[i].SlotNumber == firmwareActivate->Slot) {
9033  break;
9034  }
9035  }
9036 
9037  if (i >= fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SlotCount) {
9038  //
9039  // Either the slot number is out of scope or the slot is read-only.
9040  //
9042  goto Exit_Firmware_Activate;
9043  }
9044 
9045  //
9046  // We're done accessing HwFirmwareInfo at this point so we can release
9047  // the SyncLock.
9048  //
9049  NT_ASSERT(lockHeld);
9050  KeReleaseInStackQueuedSpinLock(&lockHandle);
9051  lockHeld = FALSE;
9052 
9053  //
9054  // Process the request by translating it into WRITE BUFFER command.
9055  //
9056  //
9057  // Setup the CDB. This should be an untagged request.
9058  //
9060  cdb = SrbGetCdb(Srb);
9061  cdb->WRITE_BUFFER.OperationCode = SCSIOP_WRITE_DATA_BUFF;
9062  cdb->WRITE_BUFFER.Mode = SCSI_WRITE_BUFFER_MODE_ACTIVATE_DEFERRED_MICROCODE;
9063  cdb->WRITE_BUFFER.ModeSpecific = 0; //Reserved for Mode 0x0F
9064  cdb->WRITE_BUFFER.BufferID = firmwareActivate->Slot; //NOTE: this field will be ignored by SCSI device.
9065 
9066  //
9067  // Set timeout value.
9068  //
9070 
9071  //
9072  // This routine uses a completion routine - ClassIoComplete() so we don't want to release
9073  // the remove lock until then.
9074  //
9076  Srb,
9077  Irp,
9078  NULL,
9079  0,
9080  FALSE);
9081 
9082  if (status != STATUS_PENDING) {
9083  //
9084  // If the irp cannot be sent down, the Srb has been freed. NULL it to prevent from freeing it again.
9085  //
9086  Srb = NULL;
9087 
9088  goto Exit_Firmware_Activate;
9089  }
9090 
9091  return status;
9092 
9093 Exit_Firmware_Activate:
9094 
9095  //
9096  // Release the SyncLock if it's still held.
9097  // This should only happen in the failure path.
9098  //
9099  if (lockHeld) {
9100  KeReleaseInStackQueuedSpinLock(&lockHandle);
9101  lockHeld = FALSE;
9102  }
9103 
9104  //
9105  // Firmware Activate request will be failed.
9106  //
9108 
9109  Irp->IoStatus.Status = status;
9110 
9111 #else
9113  Irp->IoStatus.Status = status;
9114 #endif // #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
9115 
9118 
9119  FREE_POOL(Srb);
9120  return status;
9121 }
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define SCSIOP_WRITE_DATA_BUFF
Definition: cdrw_hw.h:922
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
_In_ PIRP Irp
Definition: csq.h:116
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE PCDB SrbGetCdb(_In_ PVOID Srb)
Definition: srbhelper.h:583
VOID FASTCALL KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:130
FORCEINLINE VOID IoCopyCurrentIrpStackLocationToNext(_Inout_ PIRP Irp)
Definition: iofuncs.h:2864
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define FALSE
Definition: types.h:117
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
VOID FASTCALL KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:166
#define FIRMWARE_ACTIVATE_TIMEOUT_VALUE
Definition: utils.c:37
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
__inline BOOLEAN ClassDeviceHwFirmwareIsPortDriverSupported(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:8329
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
NTSTATUS ClasspGetHwFirmwareInfo(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:8190
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
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)
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
static SERVICE_STATUS status
Definition: service.c:31
#define CDB10GENERIC_LENGTH
Definition: cdrw_hw.h:831
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

Referenced by ClassDeviceControl().

◆ ClassDeviceHwFirmwareDownloadProcess()

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

Definition at line 8539 of file utils.c.

8544 {
8546 
8547 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
8548 
8549  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8550  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
8551 
8553  PSTORAGE_HW_FIRMWARE_DOWNLOAD firmwareDownload = (PSTORAGE_HW_FIRMWARE_DOWNLOAD)Irp->AssociatedIrp.SystemBuffer;
8554  BOOLEAN passDown = FALSE;
8555  ULONG i;
8556  ULONG bufferSize = 0;
8557  PUCHAR firmwareImageBuffer = NULL;
8558  PIRP irp2 = NULL;
8559  PIO_STACK_LOCATION newStack = NULL;
8560  PCDB cdb = NULL;
8561  BOOLEAN lockHeld = FALSE;
8562  KLOCK_QUEUE_HANDLE lockHandle;
8563 
8564 
8565  //
8566  // Input buffer is not big enough to contain required input information.
8567  //
8568  if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_HW_FIRMWARE_DOWNLOAD)) {
8569 
8571  goto Exit_Firmware_Download;
8572  }
8573 
8574  //
8575  // Input buffer basic validation.
8576  //
8577  if ((firmwareDownload->Version < sizeof(STORAGE_HW_FIRMWARE_DOWNLOAD)) ||
8578  (firmwareDownload->Size > irpStack->Parameters.DeviceIoControl.InputBufferLength) ||
8579  ((firmwareDownload->BufferSize + FIELD_OFFSET(STORAGE_HW_FIRMWARE_DOWNLOAD, ImageBuffer)) > firmwareDownload->Size)) {
8580 
8582  goto Exit_Firmware_Download;
8583  }
8584 
8585  //
8586  // Only process the request for a supported port driver.
8587  //
8590  goto Exit_Firmware_Download;
8591  }
8592 
8593  //
8594  // Buffer "FunctionSupportInfo" is allocated during start device process. Following check defends against the situation
8595  // of receiving this IOCTL when the device is created but not started, or device start failed but did not get removed yet.
8596  //
8597  if (commonExtension->IsFdo && (fdoExtension->FunctionSupportInfo == NULL)) {
8598 
8600  goto Exit_Firmware_Download;
8601  }
8602 
8603  //
8604  // Process the situation that request should be forwarded to lower level.
8605  //
8606  if (!commonExtension->IsFdo) {
8607  passDown = TRUE;
8608  }
8609 
8610  if ((firmwareDownload->Flags & STORAGE_HW_FIRMWARE_REQUEST_FLAG_CONTROLLER) != 0) {
8611  passDown = TRUE;
8612  }
8613 
8614  if (passDown) {
8615 
8617 
8619  status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8620  FREE_POOL(Srb);
8621  return status;
8622  }
8623 
8624  //
8625  // If firmware information hasn't been cached in classpnp, retrieve it.
8626  //
8627  if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo == NULL) {
8628  if (fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport == NotSupported) {
8630  goto Exit_Firmware_Download;
8631  } else {
8632  //
8633  // If this is the first time of retrieving firmware information,
8634  // send request to lower level to get it.
8635  //
8637 
8638  if (!NT_SUCCESS(status)) {
8639  goto Exit_Firmware_Download;
8640  }
8641  }
8642  }
8643 
8644  //
8645  // Fail the request if the firmware information cannot be retrieved.
8646  //
8647  if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo == NULL) {
8648  if (fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport == NotSupported) {
8650  } else {
8652  }
8653 
8654  goto Exit_Firmware_Download;
8655  }
8656 
8657  //
8658  // Acquire the SyncLock to ensure the HwFirmwareInfo pointer doesn't change
8659  // while we're dereferencing it.
8660  //
8661  lockHeld = TRUE;
8662  KeAcquireInStackQueuedSpinLock(&fdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
8663 
8664  //
8665  // Validate the device support
8666  //
8667  if ((fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SupportUpgrade == FALSE) ||
8668  (fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadAlignment == 0)) {
8670  goto Exit_Firmware_Download;
8671  }
8672 
8673  //
8674  // Check if the slot can be used to hold firmware image.
8675  //
8676  for (i = 0; i < fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SlotCount; i++) {
8677  if (fdoExtension->FunctionSupportInfo->HwFirmwareInfo->Slot[i].SlotNumber == firmwareDownload->Slot) {
8678  break;
8679  }
8680  }
8681 
8682  if ((i >= fdoExtension->FunctionSupportInfo->HwFirmwareInfo->SlotCount) ||
8683  (fdoExtension->FunctionSupportInfo->HwFirmwareInfo->Slot[i].ReadOnly == TRUE)) {
8684  //
8685  // Either the slot number is out of scope or the slot is read-only.
8686  //
8688  goto Exit_Firmware_Download;
8689  }
8690 
8691  //
8692  // Buffer size and alignment validation.
8693  // Max Offset and Buffer Size can be represented by SCSI command is max value for 3 bytes.
8694  //
8695  if ((firmwareDownload->BufferSize == 0) ||
8696  ((firmwareDownload->BufferSize % fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadAlignment) != 0) ||
8697  (firmwareDownload->BufferSize > fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadMaxSize) ||
8698  (firmwareDownload->BufferSize > fdoExtension->AdapterDescriptor->MaximumTransferLength) ||
8699  ((firmwareDownload->Offset % fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadAlignment) != 0) ||
8700  (firmwareDownload->Offset > 0xFFFFFF) ||
8701  (firmwareDownload->BufferSize > 0xFFFFFF)) {
8702 
8704  goto Exit_Firmware_Download;
8705  }
8706 
8707 
8708  //
8709  // Process the request by translating it into WRITE BUFFER command.
8710  //
8711  if (((ULONG_PTR)firmwareDownload->ImageBuffer % fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadAlignment) != 0) {
8712  //
8713  // Allocate buffer aligns to ImagePayloadAlignment to accommodate the alignment requirement.
8714  //
8715  bufferSize = ALIGN_UP_BY(firmwareDownload->BufferSize, fdoExtension->FunctionSupportInfo->HwFirmwareInfo->ImagePayloadAlignment);
8716 
8717  //
8718  // We're done accessing HwFirmwareInfo at this point so we can release
8719  // the SyncLock.
8720  //
8721  NT_ASSERT(lockHeld);
8722  KeReleaseInStackQueuedSpinLock(&lockHandle);
8723  lockHeld = FALSE;
8724 
8725 #ifdef _MSC_VER
8726 #pragma prefast(suppress:6014, "The allocated memory that firmwareImageBuffer points to will be freed in ClassHwFirmwareDownloadComplete().")
8727 #endif
8728  firmwareImageBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, bufferSize, CLASSPNP_POOL_TAG_FIRMWARE);
8729 
8730  if (firmwareImageBuffer == NULL) {
8732  goto Exit_Firmware_Download;
8733  }
8734 
8735  RtlZeroMemory(firmwareImageBuffer, bufferSize);
8736 
8737  RtlCopyMemory(firmwareImageBuffer, firmwareDownload->ImageBuffer, (ULONG)firmwareDownload->BufferSize);
8738 
8739  } else {
8740  NT_ASSERT(lockHeld);
8741  KeReleaseInStackQueuedSpinLock(&lockHandle);
8742  lockHeld = FALSE;
8743 
8744  firmwareImageBuffer = firmwareDownload->ImageBuffer;
8745  bufferSize = (ULONG)firmwareDownload->BufferSize;
8746  }
8747 
8748  //
8749  // Allocate a new irp to send the WRITE BUFFER command down.
8750  // Similar process as IOCTL_STORAGE_CHECK_VERIFY.
8751  //
8752  irp2 = IoAllocateIrp((CCHAR)(DeviceObject->StackSize + 3), FALSE);
8753 
8754  if (irp2 == NULL) {
8756 
8757  if (firmwareImageBuffer != firmwareDownload->ImageBuffer) {
8758  FREE_POOL(firmwareImageBuffer);
8759  }
8760 
8761  goto Exit_Firmware_Download;
8762  }
8763 
8764  //
8765  // Make sure to acquire the lock for the new irp.
8766  //
8768 
8769  irp2->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
8771 
8772  //
8773  // Set the top stack location and shove the master Irp into the
8774  // top location
8775  //
8776  newStack = IoGetCurrentIrpStackLocation(irp2);
8777  newStack->Parameters.Others.Argument1 = Irp;
8778  newStack->DeviceObject = DeviceObject;
8779 
8780  //
8781  // Stick the firmware download completion routine onto the stack
8782  // and prepare the irp for the port driver
8783  //
8785  ClassHwFirmwareDownloadComplete,
8786  (firmwareImageBuffer != firmwareDownload->ImageBuffer) ? firmwareImageBuffer : NULL,
8787  TRUE,
8788  TRUE,
8789  TRUE);
8790 
8792  newStack = IoGetCurrentIrpStackLocation(irp2);
8793  newStack->DeviceObject = DeviceObject;
8794  newStack->MajorFunction = irpStack->MajorFunction;
8795  newStack->MinorFunction = irpStack->MinorFunction;
8796  newStack->Flags = irpStack->Flags;
8797 
8798 
8799  //
8800  // Mark the master irp as pending - whether the lower level
8801  // driver completes it immediately or not this should allow it
8802  // to go all the way back up.
8803  //
8805 
8806  //
8807  // Setup the CDB.
8808  //
8810  cdb = SrbGetCdb(Srb);
8811  cdb->WRITE_BUFFER.OperationCode = SCSIOP_WRITE_DATA_BUFF;
8812  cdb->WRITE_BUFFER.Mode = SCSI_WRITE_BUFFER_MODE_DOWNLOAD_MICROCODE_WITH_OFFSETS_SAVE_DEFER_ACTIVATE;
8813  cdb->WRITE_BUFFER.ModeSpecific = 0; //Reserved for Mode 0x0E
8814  cdb->WRITE_BUFFER.BufferID = firmwareDownload->Slot;
8815 
8816  cdb->WRITE_BUFFER.BufferOffset[0] = *((PCHAR)&firmwareDownload->Offset + 2);
8817  cdb->WRITE_BUFFER.BufferOffset[1] = *((PCHAR)&firmwareDownload->Offset + 1);
8818  cdb->WRITE_BUFFER.BufferOffset[2] = *((PCHAR)&firmwareDownload->Offset);
8819 
8820  cdb->WRITE_BUFFER.ParameterListLength[0] = *((PCHAR)&bufferSize + 2);
8821  cdb->WRITE_BUFFER.ParameterListLength[1] = *((PCHAR)&bufferSize + 1);
8822  cdb->WRITE_BUFFER.ParameterListLength[2] = *((PCHAR)&bufferSize);
8823 
8824  //
8825  // Send as a tagged command.
8826  //
8829 
8830  //
8831  // Set timeout value.
8832  //
8833  SrbSetTimeOutValue(Srb, fdoExtension->TimeOutValue);
8834 
8835  //
8836  // This routine uses a completion routine so we don't want to release
8837  // the remove lock until then.
8838  //
8840  Srb,
8841  irp2,
8842  firmwareImageBuffer,
8843  bufferSize,
8844  TRUE);
8845 
8846  if (status != STATUS_PENDING) {
8847  //
8848  // If the new irp cannot be sent down, free allocated memory and bail out.
8849  //
8850  if (firmwareImageBuffer != firmwareDownload->ImageBuffer) {
8851  FREE_POOL(firmwareImageBuffer);
8852  }
8853 
8854  //
8855  // If the irp cannot be sent down, the Srb has been freed. NULL it to prevent from freeing it again.
8856  //
8857  Srb = NULL;
8858 
8860 
8861  IoFreeIrp(irp2);
8862 
8863  goto Exit_Firmware_Download;
8864  }
8865 
8866  return status;
8867 
8868 Exit_Firmware_Download:
8869 
8870  //
8871  // Release the SyncLock if it's still held.
8872  // This should only happen in the failure path.
8873  //
8874  if (lockHeld) {
8875  KeReleaseInStackQueuedSpinLock(&lockHandle);
8876  lockHeld = FALSE;
8877  }
8878 
8879  //
8880  // Firmware Download request will be failed.
8881  //
8883 
8884  Irp->IoStatus.Status = status;
8885 
8886 #else
8888  Irp->IoStatus.Status = status;
8889 #endif // #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
8890 
8893 
8894  FREE_POOL(Srb);
8895 
8896  return status;
8897 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define SCSIOP_WRITE_DATA_BUFF
Definition: cdrw_hw.h:922
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
_In_ PIRP Irp
Definition: csq.h:116
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
unsigned char * PUCHAR
Definition: retypes.h:3
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
#define CLASSPNP_POOL_TAG_FIRMWARE
Definition: classp.h:198
FORCEINLINE PCDB SrbGetCdb(_In_ PVOID Srb)
Definition: srbhelper.h:583
VOID FASTCALL KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:130
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
uint32_t ULONG_PTR
Definition: typedefs.h:65
FORCEINLINE VOID IoCopyCurrentIrpStackLocationToNext(_Inout_ PIRP Irp)
Definition: iofuncs.h:2864
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define FALSE
Definition: types.h:117
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
#define PCHAR
Definition: match.c:90
VOID FASTCALL KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:166
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
char CCHAR
Definition: typedefs.h:51
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
__inline BOOLEAN ClassDeviceHwFirmwareIsPortDriverSupported(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:8329
FORCEINLINE VOID SrbSetRequestAttribute(_In_ PVOID Srb, _In_ UCHAR RequestAttribute)
Definition: srbhelper.h:1131
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
NTSTATUS ClasspGetHwFirmwareInfo(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:8190
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define SRB_HEAD_OF_QUEUE_TAG_REQUEST
Definition: srb.h:416
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
FORCEINLINE VOID SrbSetSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:964
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ALIGN_UP_BY(size, align)
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
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)
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
IoMarkIrpPending(Irp)
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
static SERVICE_STATUS status
Definition: service.c:31
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2676
#define CDB10GENERIC_LENGTH
Definition: cdrw_hw.h:831
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:387
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

Referenced by ClassDeviceControl().

◆ ClassDeviceHwFirmwareGetInfoProcess()

NTSTATUS ClassDeviceHwFirmwareGetInfoProcess ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp 
)

Definition at line 8364 of file utils.c.

8383 {
8385 
8386 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
8387 
8388  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8389  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
8391  PSTORAGE_HW_FIRMWARE_INFO_QUERY query = (PSTORAGE_HW_FIRMWARE_INFO_QUERY)Irp->AssociatedIrp.SystemBuffer;
8392  BOOLEAN passDown = FALSE;
8393  BOOLEAN copyData = FALSE;
8394 
8395 
8396  //
8397  // Input buffer is not big enough to contain required input information.
8398  //
8399  if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_HW_FIRMWARE_INFO_QUERY)) {
8400 
8402  goto Exit_Firmware_Get_Info;
8403  }
8404 
8405  //
8406  // Output buffer is too small to contain return data.
8407  //
8408  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_HW_FIRMWARE_INFO)) {
8409 
8411  goto Exit_Firmware_Get_Info;
8412  }
8413 
8414  //
8415  // Only process the request for a supported port driver.
8416  //
8419  goto Exit_Firmware_Get_Info;
8420  }
8421 
8422  //
8423  // Buffer "FunctionSupportInfo" is allocated during start device process. Following check defends against the situation
8424  // of receiving this IOCTL when the device is created but not started, or device start failed but did not get removed yet.
8425  //
8426  if (commonExtension->IsFdo && (fdoExtension->FunctionSupportInfo == NULL)) {
8427 
8429  goto Exit_Firmware_Get_Info;
8430  }
8431 
8432  //
8433  // Process the situation that request should be forwarded to lower level.
8434  //
8435  if (!commonExtension->IsFdo) {
8436  passDown = TRUE;
8437  }
8438 
8439  if ((query->Flags & STORAGE_HW_FIRMWARE_REQUEST_FLAG_CONTROLLER) != 0) {
8440  passDown = TRUE;
8441  }
8442 
8443  if (passDown) {
8444 
8446 
8448  status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8449  return status;
8450  }
8451 
8452  //
8453  // The request is for a FDO. Process the request.
8454  //
8455  if (fdoExtension->FunctionSupportInfo->HwFirmwareGetInfoSupport == NotSupported) {
8457  goto Exit_Firmware_Get_Info;
8458  } else {
8459  //
8460  // Retrieve information from lower layer for the request. The cached information is not used
8461  // in case device firmware information changed.
8462  //
8464  copyData = NT_SUCCESS(status);
8465  }
8466 
8467 Exit_Firmware_Get_Info:
8468 
8469  if (copyData) {
8470  //
8471  // Firmware information is already cached in classpnp. Return a copy.
8472  //
8473  KLOCK_QUEUE_HANDLE lockHandle;
8474  KeAcquireInStackQueuedSpinLock(&fdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
8475 
8476  ULONG dataLength = min(irpStack->Parameters.DeviceIoControl.OutputBufferLength, fdoExtension->FunctionSupportInfo->HwFirmwareInfo->Size);
8477 
8478  memcpy(Irp->AssociatedIrp.SystemBuffer, fdoExtension->FunctionSupportInfo->HwFirmwareInfo, dataLength);
8479 
8480  KeReleaseInStackQueuedSpinLock(&lockHandle);
8481 
8482  Irp->IoStatus.Information = dataLength;
8483  }
8484 
8485  Irp->IoStatus.Status = status;
8486 
8487 #else
8489  Irp->IoStatus.Status = status;
8490 #endif // #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
8491 
8494 
8495  return status;
8496 }
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
_In_ PIRP Irp
Definition: csq.h:116
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
VOID FASTCALL KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:130
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
FORCEINLINE VOID IoCopyCurrentIrpStackLocationToNext(_Inout_ PIRP Irp)
Definition: iofuncs.h:2864
#define FALSE
Definition: types.h:117
ULONG dataLength
Definition: scsi.h:3751
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
VOID FASTCALL KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:166
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
__inline BOOLEAN ClassDeviceHwFirmwareIsPortDriverSupported(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:8329
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
NTSTATUS ClasspGetHwFirmwareInfo(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:8190
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define min(a, b)
Definition: monoChain.cc:55
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

Referenced by ClassDeviceControl().

◆ ClassDeviceHwFirmwareIsPortDriverSupported()

__inline BOOLEAN ClassDeviceHwFirmwareIsPortDriverSupported ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 8329 of file utils.c.

8345 {
8346  //
8347  // If the request is for a FDO, process the request for Storport, SDstor and Spaceport only.
8348  // Don't process it if we don't have a miniport descriptor.
8349  //
8350  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8351  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
8352 
8353  BOOLEAN isSupported = FALSE;
8354  if (commonExtension->IsFdo && (fdoExtension->MiniportDescriptor != NULL)) {
8355  isSupported = ((fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetStorport) ||
8356  (fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetSpaceport) ||
8357  (fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetSDport ));
8358  }
8359 
8360  return isSupported;
8361 }
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464

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",
4724  DeviceObject,
4725  LogPage,
4726  LogPageSize));
4727 
4728  return STATUS_INVALID_PARAMETER;
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  //
4746  NT_ASSERT(FALSE);
4747  }
4748  } else {
4750  Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
4751  Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
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",
4793  DeviceObject,
4794  status
4795  ));
4796 
4797  return status;
4798 }
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
FORCEINLINE VOID SrbAssignSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:946
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE PCDB SrbGetCdb(_In_ PVOID Srb)
Definition: srbhelper.h:583
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define SP_UNTAGGED
Definition: srb.h:225
#define FALSE
Definition: types.h:117
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
smooth NULL
Definition: ftsmooth.c:416
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
FORCEINLINE ULONG SrbGetDataTransferLength(_In_ PVOID Srb)
Definition: srbhelper.h:765
#define SrbSetRequestTag
Definition: srbhelper.h:869
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
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
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define LOG_PAGE_CODE_LOGICAL_BLOCK_PROVISIONING
Definition: scsi.h:3262
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:657
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
FORCEINLINE VOID SrbSetRequestAttribute(_In_ PVOID Srb, _In_ UCHAR RequestAttribute)
Definition: srbhelper.h:1131
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define REVERSE_BYTES_SHORT(Destination, Source)
Definition: scsi.h:3474
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define MAXUSHORT
Definition: typedefs.h:83
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
return STATUS_SUCCESS
Definition: btrfs.c:3014
static SERVICE_STATUS status
Definition: service.c:31
#define SCSIOP_LOG_SENSE
Definition: cdrw_hw.h:937
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

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 {
4996  NTSTATUS status;
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",
5024  DeviceObject,
5025  Resources,
5026  ResourcesSize));
5027 
5028  return STATUS_INVALID_PARAMETER;
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 STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
struct _LOG_PAGE_LOGICAL_BLOCK_PROVISIONING LOG_PAGE_LOGICAL_BLOCK_PROVISIONING
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
struct _LOG_PAGE_LOGICAL_BLOCK_PROVISIONING * PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:471
#define CLASS_TAG_LB_PROVISIONING
Definition: classpnp.h:89
#define FALSE
Definition: types.h:117
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
smooth NULL
Definition: ftsmooth.c:416
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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 ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define ALIGN_UP_BY(size, align)
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
static SERVICE_STATUS status
Definition: service.c:31
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
Definition: ps.c:97

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",
4857  DeviceObject,
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",
4871  DeviceObject,
4872  Resources,
4873  ResourcesSize,
4874  LogPage,
4875  LogPageSize));
4876 
4877  return STATUS_INVALID_PARAMETER;
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  {
4915  REVERSE_BYTES(&resourceCount, &(((PLOG_PARAMETER_THRESHOLD_RESOURCE_COUNT)parameter)->ResourceCount));
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  {
4932  REVERSE_BYTES(&resourceCount, &(((PLOG_PARAMETER_THRESHOLD_RESOURCE_COUNT)parameter)->ResourceCount));
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 }
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
unsigned char * PUCHAR
Definition: retypes.h:3
#define LOG_PAGE_LBP_PARAMETER_CODE_AVAILABLE
Definition: scsi.h:3359
#define LOG_PAGE_LBP_PARAMETER_CODE_USED
Definition: scsi.h:3360
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
ULONG BytesPerSector
Definition: ntdddisk.h:442
struct _STORAGE_LB_PROVISIONING_MAP_RESOURCES STORAGE_LB_PROVISIONING_MAP_RESOURCES
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
smooth NULL
Definition: ftsmooth.c:416
void * PVOID
Definition: retypes.h:9
#define ULL(a, b)
Definition: format_msg.c:27
if(!(yy_init))
Definition: macro.lex.yy.c:714
uint64_t ULONGLONG
Definition: typedefs.h:67
static ULONG ResourceCount
Definition: inbv.c:92
unsigned char UCHAR
Definition: xmlstorage.h:181
_In_ PPCI_DEVICE_PRESENCE_PARAMETERS Parameters
Definition: iotypes.h:887
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
struct _LOG_PARAMETER_HEADER LOG_PARAMETER_HEADER
struct _LOG_PARAMETER_THRESHOLD_RESOURCE_COUNT * PLOG_PARAMETER_THRESHOLD_RESOURCE_COUNT
unsigned short USHORT
Definition: pedump.c:61
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define REVERSE_BYTES_SHORT(Destination, Source)
Definition: scsi.h:3474
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define min(a, b)
Definition: monoChain.cc:55
struct _LOG_PARAMETER_HEADER * PLOG_PARAMETER_HEADER
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
return STATUS_SUCCESS
Definition: btrfs.c:3014

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 
1719  PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR accessAlignment;
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 
1759  if (KeGetCurrentIrql() >= DISPATCH_LEVEL) {
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 
1872 Exit:
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 KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define FILE_DEVICE_DISK
Definition: winioctl.h:112
_In_ PIRP Irp
Definition: csq.h:116
* PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
Definition: ntddstor.h:609
LONG NTSTATUS
Definition: precomp.h:26
__inline BOOLEAN ClasspIsObsoletePortDriver(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classp.h:1335
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
Definition: ntddstor.h:609
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
FORCEINLINE VOID IoCopyCurrentIrpStackLocationToNext(_Inout_ PIRP Irp)
Definition: iofuncs.h:2864
__inline BOOLEAN ClasspLowerLayerNotSupport(_In_ NTSTATUS Status)
Definition: classp.h:2638
#define FALSE
Definition: types.h:117
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
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 TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static void Exit(void)
Definition: sock.c:1331
struct _COMMON_DEVICE_EXTENSION * PCOMMON_DEVICE_EXTENSION
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
struct _STORAGE_PROPERTY_QUERY * PSTORAGE_PROPERTY_QUERY
STORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
static PDB_INFORMATION information
Definition: db.cpp:176
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
#define FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
return STATUS_SUCCESS
Definition: btrfs.c:3014
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
static SERVICE_STATUS status
Definition: service.c:31
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

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
unsigned char * PUCHAR
Definition: retypes.h:3
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 i
Definition: glfuncs.h:248
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
smooth NULL
Definition: ftsmooth.c:416
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:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

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 }
LONG NTSTATUS
Definition: precomp.h:26
_SEH2_TRY
Definition: create.c:4226
#define FALSE
Definition: types.h:117
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:989
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
_SEH2_END
Definition: create.c:4400
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:935
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
Definition: ps.c:97

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 }
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
unsigned int ULONG
Definition: retypes.h:1

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
6600  NT_ASSERT(FALSE);
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
6614  NT_ASSERT(FALSE);
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 }
signed char * PCHAR
Definition: retypes.h:7
#define STOR_ADDRESS_TYPE_BTL8
Definition: scsi.h:3525
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
struct STOR_ADDRESS_ALIGN _STOR_ADDR_BTL8 * PSTOR_ADDR_BTL8
#define TRUE
Definition: types.h:120
struct SRB_ALIGN _SRBEX_DATA * PSRBEX_DATA
#define SRB_FUNCTION_POWER
Definition: srb.h:95
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
struct _SCSI_PNP_REQUEST_BLOCK * PSCSI_PNP_REQUEST_BLOCK
#define FALSE
Definition: types.h:117
struct SRB_ALIGN _SRBEX_DATA_PNP * PSRBEX_DATA_PNP
unsigned char BOOLEAN
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB16 * PSRBEX_DATA_SCSI_CDB16
smooth NULL
Definition: ftsmooth.c:416
#define SRB_FUNCTION_WMI
Definition: srb.h:323
struct _SCSI_WMI_REQUEST_BLOCK * PSCSI_WMI_REQUEST_BLOCK
if(!(yy_init))
Definition: macro.lex.yy.c:714
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB32 * PSRBEX_DATA_SCSI_CDB32
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
unsigned char UCHAR
Definition: xmlstorage.h:181
struct SRB_ALIGN _SRBEX_DATA_POWER * PSRBEX_DATA_POWER
#define SRB_FUNCTION_PNP
Definition: srb.h:96
STORAGE_REQUEST_BLOCK
Definition: srb.h:652
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB_VAR * PSRBEX_DATA_SCSI_CDB_VAR
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
struct _SCSI_POWER_REQUEST_BLOCK * PSCSI_POWER_REQUEST_BLOCK
struct SRB_ALIGN _SRBEX_DATA_WMI * PSRBEX_DATA_WMI
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
#define NT_ASSERT
Definition: rtlfuncs.h:3312

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());
2109  dataBuffer = (PVPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE)ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
2110  allocationBufferLength,
2111  '5CcS'
2112  );
2113 #else
2114 
2116  bufferLength,
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 
2164 Exit:
2165  if (dataBuffer != NULL) {
2166  ExFreePool(dataBuffer);
2167  }
2168 
2169  return status;
2170 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
FORCEINLINE VOID SrbAssignSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:946
struct _VPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE VPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE
struct _VPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE * PVPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE PCDB SrbGetCdb(_In_ PVOID Srb)
Definition: srbhelper.h:583
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:471
#define SP_UNTAGGED
Definition: srb.h:225
#define VPD_BLOCK_DEVICE_CHARACTERISTICS
Definition: scsi.h:2417
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE ULONG SrbGetDataTransferLength(_In_ PVOID Srb)
Definition: srbhelper.h:765
#define SrbSetRequestTag
Definition: srbhelper.h:869
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
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 NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static void Exit(void)
Definition: sock.c:1331
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
FORCEINLINE VOID SrbSetRequestAttribute(_In_ PVOID Srb, _In_ UCHAR RequestAttribute)
Definition: srbhelper.h:1131
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ALIGN_UP_BY(size, align)
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
static SERVICE_STATUS status
Definition: service.c:31
struct _CDB::_CDB6INQUIRY3 CDB6INQUIRY3
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
Definition: ps.c:97

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 {
2529  PVOID dataBuffer = NULL;
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  //
2603  NT_ASSERT(FALSE);
2604  }
2605  } else {
2607  Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
2608  Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
2610  }
2611 
2612  if (NT_SUCCESS(status)) {
2613  // prepare the Srb
2614  SrbSetTimeOutValue(Srb, FdoExtension->TimeOutValue);
2617  SrbAssignSrbFlags(Srb, FdoExtension->SrbFlags);
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 
2723 Exit:
2724  FREE_POOL(dataBuffer);
2725 
2726  return status;
2727 }
CONST char * PCSZ
Definition: umtypes.h:125
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
FORCEINLINE VOID SrbAssignSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:946
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
UCHAR MaximumUnmapBlockDescriptorCount[4]
Definition: scsi.h:2541
#define TRUE
Definition: types.h:120
UCHAR OptimalTransferLength[4]
Definition: scsi.h:2538
UCHAR MaximumTransferLength[4]
Definition: scsi.h:2537
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
unsigned char * PUCHAR
Definition: retypes.h:3
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
FORCEINLINE PCDB SrbGetCdb(_In_ PVOID Srb)
Definition: srbhelper.h:583
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
UCHAR UnmapGranularityAlignment[4]
Definition: scsi.h:2551
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:471
#define SP_UNTAGGED
Definition: srb.h:225
UCHAR OptimalTransferLengthGranularity[2]
Definition: scsi.h:2536
#define FALSE
Definition: types.h:117
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
smooth NULL
Definition: ftsmooth.c:416
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
UCHAR OptimalUnmapGranularity[4]
Definition: scsi.h:2542
struct _VPD_BLOCK_LIMITS_PAGE * PVPD_BLOCK_LIMITS_PAGE
FORCEINLINE ULONG SrbGetDataTransferLength(_In_ PVOID Srb)
Definition: srbhelper.h:765
#define SrbSetRequestTag
Definition: srbhelper.h:869
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
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 NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static void Exit(void)
Definition: sock.c:1331
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:657
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
FORCEINLINE VOID SrbSetRequestAttribute(_In_ PVOID Srb, _In_ UCHAR RequestAttribute)
Definition: srbhelper.h:1131
#define VPD_MAX_BUFFER_SIZE
Definition: scsi.h:2402
unsigned short USHORT
Definition: pedump.c:61
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define REVERSE_BYTES_SHORT(Destination, Source)
Definition: scsi.h:3474
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
Definition: bcd.h:201
UCHAR MaximumUnmapLBACount[4]
Definition: scsi.h:2540
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ALIGN_UP_BY(size, align)
#define VPD_BLOCK_LIMITS
Definition: scsi.h:2416
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
UCHAR PageLength[2]
Definition: scsi.h:2531
return STATUS_SUCCESS
Definition: btrfs.c:3014
static SERVICE_STATUS status
Definition: service.c:31
struct _CDB::_CDB6INQUIRY3 CDB6INQUIRY3
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

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;
3926  ULONG_PTR information = 0;
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 
3943  if (TEST_FLAG(dsmAttributes->Flags, DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE)) {
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 
4070 Exit:
4071  Irp->IoStatus.Information = information;
4072  Irp->IoStatus.Status = finalStatus;
4075  return finalStatus;
4076 }
#define Add2Ptr(PTR, INC)
#define DEVICE_DSM_FLAG_ALLOCATION_CONSOLIDATEABLE_ONLY
Definition: ntddstor.h:963
_In_ PIRP Irp
Definition: csq.h:116
struct _DEVICE_DATA_SET_RANGE * PDEVICE_DATA_SET_RANGE
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
#define DEVICE_DATA_SET_LB_PROVISIONING_STATE_VERSION_V2
Definition: ntddstor.h:953
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define FALSE
Definition: types.h:117
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS ClasspBlockLimitsDataSnapshot(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ BOOLEAN ForceQuery, _Out_ PCLASS_VPD_B0_DATA BlockLimitsData, _Out_ PULONG GenerationCount)
Definition: class.c:16504
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
int64_t LONGLONG
Definition: typedefs.h:68
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t ULONGLONG
Definition: typedefs.h:67
static void Exit(void)
Definition: sock.c:1331
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
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
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE
Definition: ntddstor.h:306
#define GET_LBA_STATUS_RETRY_COUNT_MAX
Definition: classp.h:229
static PDB_INFORMATION information
Definition: db.cpp:176
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
struct _DEVICE_MANAGE_DATA_SET_ATTRIBUTES * PDEVICE_MANAGE_DATA_SET_ATTRIBUTES
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
#define STATUS_DEVICE_DATA_ERROR
Definition: udferr_usr.h:159
#define DEVICE_DATA_SET_LB_PROVISIONING_STATE_VERSION_V1
Definition: ntddstor.h:939

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  {
4204  status = ClassReadDriveCapacity(fdoExtension->DeviceObject);
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",
4233  DeviceObject,
4234  LengthInBytes,
4236  alignmentInBytes,
4237  (ULONGLONG)fdoExtension->CommonExtension.PartitionLength.QuadPart));
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",
4290  DeviceObject,
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)
4315  if (OutputVersion == DEVICE_DATA_SET_LB_PROVISIONING_STATE_VERSION_V2) {
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",
4345  DeviceObject,
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",
4396  DeviceObject,
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",
4497  DeviceObject,
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",
4517  DeviceObject,
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)
4554  if (OutputVersion == DEVICE_DATA_SET_LB_PROVISIONING_STATE_VERSION_V2) {
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)
4625  if (OutputVersion == DEVICE_DATA_SET_LB_PROVISIONING_STATE_VERSION_V2) {
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  //
4639  lbpStateV2->Size = sizeof(DEVICE_DATA_SET_LB_PROVISIONING_STATE_V2)
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",
4671  DeviceObject,
4672  totalProcessedSlabs));
4673 Exit:
4674 
4675  FREE_POOL(lbaStatusListHeader);
4676  return status;
4677 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define Add2Ptr(PTR, INC)
struct _DEVICE_DATA_SET_LB_PROVISIONING_STATE DEVICE_DATA_SET_LB_PROVISIONING_STATE
UCHAR ProvisioningStatus
Definition: scsi.h:2775
struct _DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT DEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:290
GLint x0
Definition: linetemp.h:95
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
ULONGLONG StartingLBA
Definition: scsi.h:2773
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
LONG NTSTATUS
Definition: precomp.h:26
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
ULONG BytesPerSector
Definition: ntdddisk.h:442
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define DEVICE_DATA_SET_LB_PROVISIONING_STATE_VERSION_V2
Definition: ntddstor.h:953
ULONG SlabAllocationBitMap[ANYSIZE_ARRAY]
Definition: ntddstor.h:948
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:471
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:2742
#define CLASS_TAG_LB_PROVISIONING
Definition: classpnp.h:89
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
T MIN(T a, T b)
Definition: polytest.cpp:79
#define FALSE
Definition: types.h:117
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
struct _LBA_STATUS_LIST_HEADER LBA_STATUS_LIST_HEADER
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
struct _LBA_STATUS_DESCRIPTOR LBA_STATUS_DESCRIPTOR
struct _DEVICE_DATA_SET_LB_PROVISIONING_STATE_V2 DEVICE_DATA_SET_LB_PROVISIONING_STATE_V2
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
LBA_STATUS_DESCRIPTOR Descriptors[0]
Definition: scsi.h:2783
#define DeviceDsmAction_Allocation
Definition: ntddstor.h:280
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t ULONGLONG
Definition: typedefs.h:67
static void Exit(void)
Definition: sock.c:1331
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:673
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
_In_ ULONG ParameterLength
Definition: usbdlib.h:206
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28