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

Go to the source code of this file.

Macros

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

Functions

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

Variables

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

Macro Definition Documentation

◆ CLASS_INIT_GUID

#define CLASS_INIT_GUID   1

Definition at line 24 of file class.c.

◆ DEBUG_MAIN_SOURCE

#define DEBUG_MAIN_SOURCE   1

Definition at line 25 of file class.c.

◆ FirstDriveLetter

#define FirstDriveLetter   'C'

Definition at line 92 of file class.c.

◆ LastDriveLetter

#define LastDriveLetter   'Z'

Definition at line 93 of file class.c.

Function Documentation

◆ _IRQL_requires_()

_IRQL_requires_ ( PASSIVE_LEVEL  ) ==NDIS_MEMORY_NONCACHED

Definition at line 13147 of file class.c.

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

◆ _IRQL_requires_max_() [1/3]

_IRQL_requires_max_ ( PASSIVE_LEVEL  )

Definition at line 207 of file class.c.

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

◆ _IRQL_requires_max_() [2/3]

__drv_aliasesMem _IRQL_requires_max_ ( DISPATCH_LEVEL  )

Definition at line 10631 of file class.c.

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

◆ _IRQL_requires_max_() [3/3]

_IRQL_requires_max_ ( APC_LEVEL  )

Definition at line 13463 of file class.c.

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

◆ _Success_()

_Success_ ( return  = STATUS_PENDING)

Definition at line 7019 of file class.c.

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

◆ ClassAddChild()

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

Definition at line 12058 of file class.c.

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

◆ ClassAddDevice()

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

Definition at line 851 of file class.c.

855 {
856 #ifdef _MSC_VER
857 #pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
858 #endif
860 
862 
863  PAGED_CODE();
864 
865 
866  status = driverExtension->InitData.ClassAddDevice(DriverObject,
868 
869  return status;
870 } // end ClassAddDevice()
#define CLASS_DRIVER_EXTENSION_KEY
Definition: classpnp.h:94
LONG NTSTATUS
Definition: precomp.h:26
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1155
PCLASS_ADD_DEVICE ClassAddDevice
Definition: classpnp.h:540
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1890
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
static SERVICE_STATUS status
Definition: service.c:31
#define PAGED_CODE()
Definition: ps.c:97

Referenced by _IRQL_requires_max_().

◆ ClassAsynchronousCompletion()

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

Definition at line 3246 of file class.c.

3251 {
3253  PSCSI_REQUEST_BLOCK srb;
3254  ULONG srbFunction;
3255  ULONG srbFlags;
3256 
3257  if (context == NULL) {
3258  return STATUS_INVALID_PARAMETER;
3259  }
3260 
3261  if (DeviceObject == NULL) {
3262 
3263  DeviceObject = context->DeviceObject;
3264  }
3265 
3266  srb = &context->Srb.Srb;
3267 
3269  srbFunction = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFunction;
3270  srbFlags = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFlags;
3271  } else {
3272  srbFunction = srb->Function;
3273  srbFlags = srb->SrbFlags;
3274  }
3275 
3276  //
3277  // If this is an execute srb, then check the return status and make sure.
3278  // the queue is not frozen.
3279  //
3280 
3281  if (srbFunction == SRB_FUNCTION_EXECUTE_SCSI) {
3282 
3283  //
3284  // Check for a frozen queue.
3285  //
3286 
3287  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
3288 
3289  //
3290  // Unfreeze the queue getting the device object from the context.
3291  //
3292 
3293  ClassReleaseQueue(context->DeviceObject);
3294  }
3295  }
3296 
3297  { // free port-allocated sense buffer if we can detect
3298 
3299  if (((PCOMMON_DEVICE_EXTENSION)(DeviceObject->DeviceExtension))->IsFdo) {
3300 
3301  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
3302  if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
3303  FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
3304  }
3305 
3306  } else {
3307 
3309 
3310  }
3311  }
3312 
3313 
3314  //
3315  // Free the context and the Irp.
3316  //
3317 
3318  if (Irp->MdlAddress != NULL) {
3319  MmUnlockPages(Irp->MdlAddress);
3320  IoFreeMdl(Irp->MdlAddress);
3321 
3322  Irp->MdlAddress = NULL;
3323  }
3324 
3326 
3327  FREE_POOL(context);
3328 
3329  IoFreeIrp(Irp);
3330 
3331  //
3332  // Indicate the I/O system should stop processing the Irp completion.
3333  //
3334 
3336 
3337 } // end ClassAsynchronousCompletion()
ULONG SrbFlags
Definition: srb.h:252
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
Definition: http.c:7094
#define SRB_FLAGS_FREE_SENSE_BUFFER
Definition: srb.h:398
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
VOID NTAPI ClassReleaseQueue(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:11589
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1439
UCHAR SrbStatus
Definition: srb.h:243
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ PIRP Irp
Definition: csq.h:116
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
__inline VOID FREE_PORT_ALLOCATED_SENSE_BUFFER(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: cdrom.h:839
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
UCHAR Function
Definition: srb.h:242
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define SRB_FUNCTION_STORAGE_REQUEST_BLOCK
Definition: srb.h:99
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
__inline BOOLEAN PORT_ALLOCATED_SENSE(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: cdrom.h:826
#define NULL
Definition: types.h:112
struct tagContext Context
Definition: acpixf.h:1034
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
unsigned int ULONG
Definition: retypes.h:1
#define NT_ASSERT
Definition: rtlfuncs.h:3312

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

◆ ClassCheckVerifyComplete()

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

Definition at line 9578 of file class.c.

9583 {
9585  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
9586 
9587  PIRP originalIrp;
9588 
9590 
9591  ASSERT_FDO(Fdo);
9592 
9593  originalIrp = irpStack->Parameters.Others.Argument1;
9594 
9595  //
9596  // Copy the media change count and status
9597  //
9598 
9599  *((PULONG) (originalIrp->AssociatedIrp.SystemBuffer)) =
9600  fdoExtension->MediaChangeCount;
9601 
9602  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClassCheckVerifyComplete - Media change count for"
9603  "device %d is %lx - saved as %lx\n",
9604  fdoExtension->DeviceNumber,
9605  fdoExtension->MediaChangeCount,
9606  *((PULONG) originalIrp->AssociatedIrp.SystemBuffer)));
9607 
9608  originalIrp->IoStatus.Status = Irp->IoStatus.Status;
9609  originalIrp->IoStatus.Information = sizeof(ULONG);
9610 
9611  ClassReleaseRemoveLock(Fdo, originalIrp);
9613 
9614  IoFreeIrp(Irp);
9615 
9617 
9618 } // end ClassCheckVerifyComplete()
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
IO_STATUS_BLOCK IoStatus
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define ASSERT_FDO(x)
Definition: pci.h:37
#define IO_DISK_INCREMENT
Definition: iotypes.h:583
_In_ PIRP Irp
Definition: csq.h:116
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
_Must_inspect_result_ _In_ WDFDEVICE Fdo
Definition: wdffdo.h:461
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
unsigned int * PULONG
Definition: retypes.h:1
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
unsigned int ULONG
Definition: retypes.h:1
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

◆ ClassDeviceControl()

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

Definition at line 7317 of file class.c.

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

◆ ClassDeviceControlDispatch()

NTSTATUS NTAPI ClassDeviceControlDispatch ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 7258 of file class.c.

7262 {
7263 
7264  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
7265  ULONG isRemoved;
7266 
7267  isRemoved = ClassAcquireRemoveLock(DeviceObject, Irp);
7268  _Analysis_assume_(isRemoved);
7269  if(isRemoved) {
7270 
7272 
7273  Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
7276  }
7277 
7278  //
7279  // Call the class specific driver DeviceControl routine.
7280  // If it doesn't handle it, it will call back into ClassDeviceControl.
7281  //
7282 
7283  NT_ASSERT(commonExtension->DevInfo->ClassDeviceControl);
7284 
7285  return commonExtension->DevInfo->ClassDeviceControl(DeviceObject,Irp);
7286 } // end ClassDeviceControlDispatch()
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
PCLASS_DEVICE_CONTROL ClassDeviceControl
Definition: classpnp.h:524
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ PIRP Irp
Definition: csq.h:116
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
PCLASS_DEV_INFO DevInfo
Definition: classpnp.h:620
#define _Analysis_assume_
Definition: no_sal2.h:388
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
#define NT_ASSERT
Definition: rtlfuncs.h:3312

Referenced by ClassInitializeDispatchTables().

◆ ClassDispatchPnp()

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

Definition at line 894 of file class.c.

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

Referenced by ClassInitializeDispatchTables().

◆ ClassFindModePage()

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

Definition at line 6798 of file class.c.

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

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

◆ ClassForwardIrpSynchronous()

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

Definition at line 11343 of file class.c.

11347 {
11349  return ClassSendIrpSynchronous(CommonExtension->LowerDeviceObject, Irp);
11350 } // end Class