3 Copyright (C) Microsoft Corporation, 1991 - 2010
11 SCSI disk class driver
29 #include "ntstrsafe.h"
32 // Set component ID for DbgPrintEx calls
35 #define DEBUG_COMP_ID DPFLTR_DISK_ID
39 // Include header file and setup GUID for tracing
42 #define WPP_GUID_DISK (945186BF, 3DD6, 4f3f, 9C8E, 9EDD3FC9D558)
43 #ifndef WPP_CONTROL_GUIDS
44 #define WPP_CONTROL_GUIDS WPP_CONTROL_GUIDS_NORMAL_FLAGS(WPP_GUID_DISK)
50 #define ExAllocatePool #NT_ASSERT(FALSE)
53 #define DISK_TAG_GENERAL ' DcS' // "ScD " - generic tag
54 #define DISK_TAG_SMART 'aDcS' // "ScDa" - SMART allocations
55 #define DISK_TAG_INFO_EXCEPTION 'ADcS' // "ScDA" - Info Exceptions
56 #define DISK_TAG_DISABLE_CACHE 'CDcS' // "ScDC" - disable cache paths
57 #define DISK_TAG_CCONTEXT 'cDcS' // "ScDc" - disk allocated completion context
58 #define DISK_TAG_DISK_GEOM 'GDcS' // "ScDG" - disk geometry buffer
59 #define DISK_TAG_UPDATE_GEOM 'gDcS' // "ScDg" - update disk geometry paths
60 #define DISK_TAG_SENSE_INFO 'IDcS' // "ScDI" - sense info buffers
61 #define DISK_TAG_PNP_ID 'iDcS' // "ScDp" - pnp ids
62 #define DISK_TAG_MODE_DATA 'MDcS' // "ScDM" - mode data buffer
63 #define DISK_CACHE_MBR_CHECK 'mDcS' // "ScDM" - mbr checksum code
64 #define DISK_TAG_NAME 'NDcS' // "ScDN" - disk name code
65 #define DISK_TAG_READ_CAP 'PDcS' // "ScDP" - read capacity buffer
66 #define DISK_TAG_PART_LIST 'pDcS' // "ScDp" - disk partition lists
67 #define DISK_TAG_SRB 'SDcS' // "ScDS" - srb allocation
68 #define DISK_TAG_START 'sDcS' // "ScDs" - start device paths
69 #define DISK_TAG_UPDATE_CAP 'UDcS' // "ScDU" - update capacity path
70 #define DISK_TAG_WI_CONTEXT 'WDcS' // "ScDW" - work-item context
73 #undef MdlMappingNoExecute
74 #define MdlMappingNoExecute 0
75 #define NonPagedPoolNx NonPagedPool
76 #define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned
77 #undef POOL_NX_ALLOCATION
78 #define POOL_NX_ALLOCATION 0
82 #if defined(_X86_) || defined(_AMD64_)
88 typedef enum _DISK_GEOMETRY_SOURCE
{
92 DiskGeometryFromNec98
,
93 DiskGeometryGuessedFromBios
,
94 DiskGeometryFromDefault
,
96 } DISK_GEOMETRY_SOURCE
, *PDISK_GEOMETRY_SOURCE
;
100 // Context for requests that can be combined and sent down
103 typedef struct _DISK_GROUP_CONTEXT
106 // Queue of requests whose representative is currently outstanding at the port driver
111 // The representative for the above queue
116 // Queue of requests whose representative is waiting to go down
121 // The representative for the above queue
126 // The srb associated with this group
128 #if (NTDDI_VERSION >= NTDDI_WIN8)
131 SCSI_REQUEST_BLOCK Srb
;
132 STORAGE_REQUEST_BLOCK SrbEx
;
133 UCHAR SrbExBuffer
[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
];
137 SCSI_REQUEST_BLOCK Srb
;
141 // The spinlock that will synchronize access to this context
146 // This event will allow for the requests to be sent down synchronously
154 // This counter maintains the number of requests currently tagged
155 // to the request that is waiting to go down
160 // This counter maintains the number of requests that were avoided
165 // This counter maintains the total number of times that we combined
166 // requests and the respective number of requests that were tagged
168 ULONG DbgRefCount
[64];
172 } DISK_GROUP_CONTEXT
, *PDISK_GROUP_CONTEXT
;
175 // Write cache setting as defined by the user
177 typedef enum _DISK_USER_WRITE_CACHE_SETTING
179 DiskWriteCacheDisable
= 0,
180 DiskWriteCacheEnable
= 1,
181 DiskWriteCacheDefault
= -1
183 } DISK_USER_WRITE_CACHE_SETTING
, *PDISK_USER_WRITE_CACHE_SETTING
;
185 typedef struct _DISK_DATA
{
188 // This field is the ordinal of a partition as it appears on a disk.
191 ULONG PartitionOrdinal
;
194 // How has this disk been partitioned? Either EFI or MBR.
197 PARTITION_STYLE PartitionStyle
;
204 // Disk signature (from MBR)
216 // Number of hidden sectors for BPB.
222 // Partition type of this device object
224 // This field is set by:
226 // 1. Initially set according to the partition list entry
227 // partition type returned by IoReadPartitionTable.
229 // 2. Subsequently set by the
230 // IOCTL_DISK_SET_PARTITION_INFORMATION I/O control
231 // function when IoSetPartitionInformation function
232 // successfully updates the partition type on the disk.
238 // Boot indicator - indicates whether this partition is a
239 // bootable (active) partition for this device
241 // This field is set according to the partition list entry boot
242 // indicator returned by IoReadPartitionTable.
245 BOOLEAN BootIndicator
;
252 // The DiskGUID field from the EFI partition header.
258 // Partition type of this device object.
264 // Unique partition identifier for this partition.
270 // EFI partition attributes for this partition.
276 // EFI partition name of this partition.
279 WCHAR PartitionName
[36];
284 #pragma warning(suppress: 4201) //this is intended to be an unnamed union
290 // This flag is set when the well known name is created (through
291 // DiskCreateSymbolicLinks) and cleared when destroying it
292 // (by calling DiskDeleteSymbolicLinks).
295 unsigned int WellKnownNameCreated
: 1;
298 // This flag is set when the PhysicalDriveN link is created (through
299 // DiskCreateSymbolicLinks) and is cleared when destroying it (through
300 // DiskDeleteSymbolicLinks)
303 unsigned int PhysicalDriveLinkCreated
: 1;
308 // ReadyStatus - STATUS_SUCCESS indicates that the drive is ready for
309 // use. Any error status is to be returned as an explaination for why
310 // a request is failed.
312 // This was done solely for the zero-length partition case of having no
313 // media in a removable disk drive. When that occurs, and a read is sent
314 // to the zero-length non-partition-zero PDO that was created, we had to
315 // be able to fail the request with a reasonable value. This may not have
316 // been the best way to do this, but it works.
319 NTSTATUS ReadyStatus
;
322 // SCSI address used for SMART operations.
325 SCSI_ADDRESS ScsiAddress
;
328 // What type of failure prediction mechanism is available
331 FAILURE_PREDICTION_METHOD FailurePredictionCapability
;
332 BOOLEAN AllowFPPerfHit
;
335 // Indicates that the SCSI Informational Exceptions mode page is supported.
336 // Note that this only indicates *support* and does not necessarily
337 // indicate that Informational Exception reporting via sense code is
340 BOOLEAN ScsiInfoExceptionsSupported
;
343 // Indicates if failure prediction is actually enabled (via whatever)
344 // method is applicable as indicated by FailurePredictionCapability.
346 BOOLEAN FailurePredictionEnabled
;
348 #if defined(_X86_) || defined(_AMD64_)
350 // This flag indiciates that a non-default geometry for this drive has
351 // already been determined by the disk driver. This field is ignored
352 // for removable media drives.
355 DISK_GEOMETRY_SOURCE GeometrySource
;
358 // If GeometryDetermined is TRUE this will contain the geometry which was
359 // reported by the firmware or by the BIOS. For removable media drives
360 // this will contain the last geometry used when media was present.
363 DISK_GEOMETRY RealGeometry
;
367 // This mutex prevents more than one IOCTL_DISK_VERIFY from being
368 // sent down to the disk. This greatly reduces the possibility of
369 // a Denial-of-Service attack
375 // This allows for parallel flush requests to be combined into one so as to
376 // reduce the number of outstanding requests that are sent down to the disk
379 DISK_GROUP_CONTEXT FlushContext
;
382 // The user-specified disk write cache setting
385 DISK_USER_WRITE_CACHE_SETTING WriteCacheOverride
;
388 } DISK_DATA
, *PDISK_DATA
;
391 // Define a general structure of identfing disk controllers with bad
395 #define HackDisableTaggedQueuing (0x01)
396 #define HackDisableSynchronousTransfers (0x02)
397 #define HackDisableSpinDown (0x04)
398 #define HackDisableWriteCache (0x08)
399 #define HackCauseNotReportableHack (0x10)
400 #define HackRequiresStartUnitCommand (0x20)
403 #define DiskDeviceParameterSubkey L"Disk"
404 #define DiskDeviceUserWriteCacheSetting L"UserWriteCacheSetting"
405 #define DiskDeviceCacheIsPowerProtected L"CacheIsPowerProtected"
408 #define FUNCTIONAL_EXTENSION_SIZE sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(DISK_DATA)
410 #define MODE_DATA_SIZE 192
411 #define VALUE_BUFFER_SIZE 2048
412 #define SCSI_DISK_TIMEOUT 10
413 #define PARTITION0_LIST_SIZE 4
415 #define MAX_MEDIA_TYPES 4
416 typedef struct _DISK_MEDIA_TYPES_LIST
{
420 const ULONG NumberOfTypes
;
421 const ULONG NumberOfSides
;
422 const STORAGE_MEDIA_TYPE MediaTypes
[MAX_MEDIA_TYPES
];
423 } DISK_MEDIA_TYPES_LIST
, *PDISK_MEDIA_TYPES_LIST
;
426 // WMI reregistration structures used for reregister work item
430 SINGLE_LIST_ENTRY Next
;
431 PDEVICE_OBJECT DeviceObject
;
433 } DISKREREGREQUEST
, *PDISKREREGREQUEST
;
435 #define MAX_SECTORS_PER_VERIFY 0x100
438 // This is based off 100ns units
440 #define ONE_MILLI_SECOND ((ULONGLONG)10 * 1000)
443 // Context for the work-item
445 typedef struct _DISK_VERIFY_WORKITEM_CONTEXT
448 PSCSI_REQUEST_BLOCK Srb
;
449 PIO_WORKITEM WorkItem
;
451 } DISK_VERIFY_WORKITEM_CONTEXT
, *PDISK_VERIFY_WORKITEM_CONTEXT
;
454 // Poll for Failure Prediction every hour
456 #define DISK_DEFAULT_FAILURE_POLLING_PERIOD 1 * 60 * 60
458 #define CHECK_IRQL() \
459 if (KeGetCurrentIrql() >= DISPATCH_LEVEL) { \
460 NT_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); \
461 return STATUS_INVALID_LEVEL; \
465 // Static global lookup tables.
468 extern CLASSPNP_SCAN_FOR_SPECIAL_INFO DiskBadControllers
[];
469 extern const DISK_MEDIA_TYPES_LIST DiskMediaTypes
[];
470 extern const DISK_MEDIA_TYPES_LIST DiskMediaTypesExclude
[];
472 #if defined(__REACTOS__) && defined(_MSC_VER)
473 # pragma section("PAGECONS", read)
474 # pragma section("PAGEDATA", read,write)
481 // Routine prototypes.
485 DRIVER_INITIALIZE DriverEntry
;
488 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
490 IN PDRIVER_OBJECT DriverObject
494 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
496 IN PDRIVER_OBJECT DriverObject
,
497 IN PDEVICE_OBJECT Pdo
501 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
503 IN PDEVICE_OBJECT Fdo
507 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
509 IN PDEVICE_OBJECT Fdo
513 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
515 IN PDEVICE_OBJECT DeviceObject
,
520 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
522 IN PDEVICE_OBJECT DeviceObject
,
527 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
528 DiskReadWriteVerification(
529 IN PDEVICE_OBJECT DeviceObject
,
534 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
536 IN PDEVICE_OBJECT DeviceObject
,
541 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
543 PDEVICE_OBJECT DeviceObject
,
544 PSCSI_REQUEST_BLOCK Srb
,
550 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
552 IN PDEVICE_OBJECT DeviceObject
,
557 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
558 DiskGetCacheInformation(
559 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
560 IN PDISK_CACHE_INFORMATION CacheInfo
564 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
565 DiskSetCacheInformation(
566 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
567 IN PDISK_CACHE_INFORMATION CacheInfo
571 DiskLogCacheInformation(
572 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
573 IN PDISK_CACHE_INFORMATION CacheInfo
,
578 DiskIoctlGetCacheSetting(
579 IN PDEVICE_OBJECT DeviceObject
,
584 DiskIoctlSetCacheSetting(
585 IN PDEVICE_OBJECT DeviceObject
,
589 IO_WORKITEM_ROUTINE DisableWriteCache
;
591 IO_WORKITEM_ROUTINE DiskIoctlVerifyThread
;
595 IN PDEVICE_OBJECT Fdo
,
596 IN PDISK_GROUP_CONTEXT FlushContext
599 IO_COMPLETION_ROUTINE DiskFlushComplete
;
604 IN PDEVICE_OBJECT DeviceObject
,
605 _In_reads_bytes_(Length
) PCHAR ModeSelectBuffer
,
611 // We need to validate that the self test subcommand is valid and
612 // appropriate. Right now we allow subcommands 0, 1 and 2 which are non
613 // captive mode tests. Once we figure out a way to know if it is safe to
614 // run a captive test then we can allow captive mode tests. Also if the
615 // atapi 5 spec is ever updated to denote that bit 7 is the captive
616 // mode bit, we can allow any request that does not have bit 7 set. Until
617 // that is done we want to be sure
619 #define DiskIsValidSmartSelfTest(Subcommand) \
620 ( ((Subcommand) == SMART_OFFLINE_ROUTINE_OFFLINE) || \
621 ((Subcommand) == SMART_SHORT_SELFTEST_OFFLINE) || \
622 ((Subcommand) == SMART_EXTENDED_SELFTEST_OFFLINE) )
626 DiskPerformSmartCommand(
627 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
628 IN ULONG SrbControlCode
,
631 IN UCHAR SectorCount
,
632 IN UCHAR SectorNumber
,
633 IN OUT PSRB_IO_CONTROL SrbControl
,
634 OUT PULONG BufferSize
638 DiskGetInfoExceptionInformation(
639 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
640 OUT PMODE_INFO_EXCEPTIONS ReturnPageData
644 DiskSetInfoExceptionInformation(
645 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
646 IN PMODE_INFO_EXCEPTIONS PageData
649 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
652 _In_ PDEVICE_OBJECT Fdo
,
654 _In_ UCHAR PageControl
,
655 _In_ PMODE_PARAMETER_HEADER ModeData
,
656 _Inout_ PULONG ModeDataSize
,
657 _Out_ PVOID
* PageData
661 DiskEnableInfoExceptions(
662 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
665 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
668 DiskDetectFailurePrediction(
669 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
670 PFAILURE_PREDICTION_METHOD FailurePredictCapability
,
671 BOOLEAN ScsiAddressAvailable
676 IN PDRIVER_OBJECT DriverObject
,
677 IN PDEVICE_OBJECT LowerDeviceObject
,
678 IN PULONG DeviceCount
,
679 IN BOOLEAN DasdAccessOnly
683 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
685 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
691 IN PDEVICE_OBJECT DeviceObject
695 DiskGenerateDeviceName(
696 IN ULONG DeviceNumber
,
701 DiskCreateSymbolicLinks(
702 IN PDEVICE_OBJECT DeviceObject
706 DiskDeleteSymbolicLinks(
707 IN PDEVICE_OBJECT DeviceObject
712 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
713 DiskFdoQueryWmiRegInfo(
714 IN PDEVICE_OBJECT DeviceObject
,
716 OUT PUNICODE_STRING InstanceName
720 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
721 DiskFdoQueryWmiRegInfoEx(
722 IN PDEVICE_OBJECT DeviceObject
,
724 OUT PUNICODE_STRING InstanceName
,
725 OUT PUNICODE_STRING MofName
729 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
730 DiskFdoQueryWmiDataBlock(
731 IN PDEVICE_OBJECT DeviceObject
,
734 IN ULONG BufferAvail
,
739 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
740 DiskFdoSetWmiDataBlock(
741 IN PDEVICE_OBJECT DeviceObject
,
749 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
750 DiskFdoSetWmiDataItem(
751 IN PDEVICE_OBJECT DeviceObject
,
760 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
761 DiskFdoExecuteWmiMethod(
762 IN PDEVICE_OBJECT DeviceObject
,
766 IN ULONG InBufferSize
,
767 IN ULONG OutBufferSize
,
772 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
773 DiskWmiFunctionControl(
774 IN PDEVICE_OBJECT DeviceObject
,
777 IN CLASSENABLEDISABLEFUNCTION Function
,
782 DiskReadFailurePredictStatus(
783 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
784 PSTORAGE_FAILURE_PREDICT_STATUS DiskSmartStatus
788 DiskReadFailurePredictData(
789 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
790 PSTORAGE_FAILURE_PREDICT_DATA DiskSmartData
794 DiskEnableDisableFailurePrediction(
795 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
800 DiskEnableDisableFailurePredictPolling(
801 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
803 ULONG PollTimeInSeconds
806 NTSTATUS
DiskInitializeReregistration(
810 extern GUIDREGINFO DiskWmiFdoGuidList
[];
812 #if defined(_X86_) || defined(_AMD64_)
814 DiskReadDriveCapacity(
815 IN PDEVICE_OBJECT Fdo
818 #define DiskReadDriveCapacity(Fdo) ClassReadDriveCapacity(Fdo)
822 #if defined(_X86_) || defined(_AMD64_)
826 PDRIVER_OBJECT DriverObject
830 DiskCleanupDetectInfo(
831 IN PDRIVER_OBJECT DriverObject
835 DiskDriverReinitialization (
836 IN PDRIVER_OBJECT DriverObject
,
843 #if defined(_X86_) || defined(_AMD64_)
846 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
847 OUT PDISK_DETECTION_INFO DetectInfo
852 IN PDEVICE_OBJECT Fdo
857 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
861 #define DiskGetDetectInfo(FdoExtension, DetectInfo) (STATUS_UNSUCCESSFUL)
865 #define DiskHashGuid(Guid) (((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0])
869 DiskDetermineMediaTypes(
870 IN PDEVICE_OBJECT Fdo
,
873 IN UCHAR DensityCode
,
874 IN BOOLEAN MediaPresent
,
875 IN BOOLEAN IsWritable
879 DiskIoctlGetLengthInfo(
880 IN PDEVICE_OBJECT DeviceObject
,
885 DiskIoctlGetDriveGeometry(
886 IN PDEVICE_OBJECT DeviceObject
,
891 DiskIoctlGetDriveGeometryEx(
892 IN PDEVICE_OBJECT DeviceObject
,
897 DiskIoctlGetCacheInformation(
898 IN PDEVICE_OBJECT DeviceObject
,
903 DiskIoctlSetCacheInformation(
904 IN PDEVICE_OBJECT DeviceObject
,
909 DiskIoctlGetMediaTypesEx(
910 IN PDEVICE_OBJECT DeviceObject
,
915 DiskIoctlPredictFailure(
916 IN PDEVICE_OBJECT DeviceObject
,
921 DiskIoctlEnableFailurePrediction(
922 IN PDEVICE_OBJECT DeviceObject
,
928 IN PDEVICE_OBJECT DeviceObject
,
933 DiskIoctlReassignBlocks(
934 IN PDEVICE_OBJECT DeviceObject
,
939 DiskIoctlReassignBlocksEx(
940 IN PDEVICE_OBJECT DeviceObject
,
946 IN PDEVICE_OBJECT DeviceObject
,
952 IN PDEVICE_OBJECT DeviceObject
,
957 DiskIoctlClearVerify(
958 IN PDEVICE_OBJECT DeviceObject
,
963 DiskIoctlUpdateDriveSize(
964 IN PDEVICE_OBJECT DeviceObject
,
969 DiskIoctlGetVolumeDiskExtents(
970 IN PDEVICE_OBJECT DeviceObject
,
975 DiskIoctlSmartGetVersion(
976 IN PDEVICE_OBJECT DeviceObject
,
981 DiskIoctlSmartReceiveDriveData(
982 IN PDEVICE_OBJECT DeviceObject
,
987 DiskIoctlSmartSendDriveCommand(
988 IN PDEVICE_OBJECT DeviceObject
,
992 FORCEINLINE
// __REACTOS__
995 _In_ PSTORAGE_REQUEST_BLOCK SrbEx
,
996 _In_opt_ PUCHAR CdbLength8
,
997 _In_opt_ PULONG CdbLength32
,
998 _In_opt_ PUCHAR ScsiStatus
,
999 _In_opt_ PVOID
*SenseInfoBuffer
,
1000 _In_opt_ PUCHAR SenseInfoBufferLength
1004 Routine Description:
1006 Helper function to retrieve SCSI related fields from an extended SRB. If SRB is
1007 not a SRB_FUNCTION_EXECUTE_SCSI or not an extended SRB, default values will be returned.
1011 SrbEx - Pointer to extended SRB.
1013 CdbLength8 - Pointer to buffer to hold CdbLength field value for
1014 SRBEX_DATA_SCSI_CDB16 or SRBEX_DATA_SCSI_CDB32
1016 CdbLength32 - Pointer to buffer to hold CdbLength field value for
1017 SRBEX_DATA_SCSI_CDB_VAR
1019 ScsiStatus - Pointer to buffer to hold ScsiStatus field value.
1021 SenseInfoBuffer - Pointer to buffer to hold SenseInfoBuffer value.
1023 SenseInfoBufferLength - Pointer to buffer to hold SenseInfoBufferLength value.
1027 Pointer to Cdb field or NULL if SRB is not a SRB_FUNCTION_EXECUTE_SCSI.
1033 PSRBEX_DATA SrbExData
= NULL
;
1034 BOOLEAN FoundEntry
= FALSE
;
1036 if ((SrbEx
->Function
== SRB_FUNCTION_STORAGE_REQUEST_BLOCK
) &&
1037 (SrbEx
->SrbFunction
== SRB_FUNCTION_EXECUTE_SCSI
)) {
1038 NT_ASSERT(SrbEx
->NumSrbExData
> 0);
1040 for (i
= 0; i
< SrbEx
->NumSrbExData
; i
++) {
1042 // Skip any invalid offsets
1043 if ((SrbEx
->SrbExDataOffset
[i
] < sizeof(STORAGE_REQUEST_BLOCK
)) ||
1044 (SrbEx
->SrbExDataOffset
[i
] > SrbEx
->SrbLength
)){
1045 // Catch any invalid offsets
1050 SrbExData
= (PSRBEX_DATA
)((PUCHAR
)SrbEx
+ SrbEx
->SrbExDataOffset
[i
]);
1052 switch (SrbExData
->Type
) {
1054 case SrbExDataTypeScsiCdb16
:
1055 if (SrbEx
->SrbExDataOffset
[i
] + sizeof(SRBEX_DATA_SCSI_CDB16
) <= SrbEx
->SrbLength
) {
1058 *CdbLength8
= ((PSRBEX_DATA_SCSI_CDB16
) SrbExData
)->CdbLength
;
1061 if (((PSRBEX_DATA_SCSI_CDB16
) SrbExData
)->CdbLength
> 0) {
1062 Cdb
= (PCDB
)((PSRBEX_DATA_SCSI_CDB16
) SrbExData
)->Cdb
;
1067 ((PSRBEX_DATA_SCSI_CDB16
) SrbExData
)->ScsiStatus
;
1070 if (SenseInfoBuffer
) {
1072 ((PSRBEX_DATA_SCSI_CDB16
) SrbExData
)->SenseInfoBuffer
;
1075 if (SenseInfoBufferLength
) {
1076 *SenseInfoBufferLength
=
1077 ((PSRBEX_DATA_SCSI_CDB16
) SrbExData
)->SenseInfoBufferLength
;
1081 // Catch invalid offset
1086 case SrbExDataTypeScsiCdb32
:
1087 if (SrbEx
->SrbExDataOffset
[i
] + sizeof(SRBEX_DATA_SCSI_CDB32
) <= SrbEx
->SrbLength
) {
1090 *CdbLength8
= ((PSRBEX_DATA_SCSI_CDB32
) SrbExData
)->CdbLength
;
1093 if (((PSRBEX_DATA_SCSI_CDB32
) SrbExData
)->CdbLength
> 0) {
1094 Cdb
= (PCDB
)((PSRBEX_DATA_SCSI_CDB32
) SrbExData
)->Cdb
;
1099 ((PSRBEX_DATA_SCSI_CDB32
) SrbExData
)->ScsiStatus
;
1102 if (SenseInfoBuffer
) {
1104 ((PSRBEX_DATA_SCSI_CDB32
) SrbExData
)->SenseInfoBuffer
;
1107 if (SenseInfoBufferLength
) {
1108 *SenseInfoBufferLength
=
1109 ((PSRBEX_DATA_SCSI_CDB32
) SrbExData
)->SenseInfoBufferLength
;
1113 // Catch invalid offset
1118 case SrbExDataTypeScsiCdbVar
:
1119 if (SrbEx
->SrbExDataOffset
[i
] + sizeof(SRBEX_DATA_SCSI_CDB_VAR
) <= SrbEx
->SrbLength
) {
1122 *CdbLength32
= ((PSRBEX_DATA_SCSI_CDB_VAR
) SrbExData
)->CdbLength
;
1125 if (((PSRBEX_DATA_SCSI_CDB_VAR
) SrbExData
)->CdbLength
> 0) {
1126 Cdb
= (PCDB
)((PSRBEX_DATA_SCSI_CDB_VAR
) SrbExData
)->Cdb
;
1131 ((PSRBEX_DATA_SCSI_CDB_VAR
) SrbExData
)->ScsiStatus
;
1134 if (SenseInfoBuffer
) {
1136 ((PSRBEX_DATA_SCSI_CDB_VAR
) SrbExData
)->SenseInfoBuffer
;
1139 if (SenseInfoBufferLength
) {
1140 *SenseInfoBufferLength
=
1141 ((PSRBEX_DATA_SCSI_CDB_VAR
) SrbExData
)->SenseInfoBufferLength
;
1145 // Catch invalid offset
1170 if (SenseInfoBuffer
) {
1171 *SenseInfoBuffer
= NULL
;
1174 if (SenseInfoBufferLength
) {
1175 *SenseInfoBufferLength
= 0;
1182 FORCEINLINE
// __REACTOS__
1185 _In_ PSTORAGE_REQUEST_BLOCK SrbEx
,
1186 _In_ UCHAR CdbLength8
,
1187 _In_ ULONG CdbLength32
,
1188 _In_ UCHAR ScsiStatus
,
1189 _In_opt_ PVOID SenseInfoBuffer
,
1190 _In_ UCHAR SenseInfoBufferLength
1194 Routine Description:
1196 Helper function to set SCSI related fields from an extended SRB. If SRB is
1197 not a SRB_FUNCTION_EXECUTE_SCSI or not an extended SRB, no modifications will
1202 SrbEx - Pointer to extended SRB.
1204 CdbLength8 - CdbLength field value for SRBEX_DATA_SCSI_CDB16
1205 or SRBEX_DATA_SCSI_CDB32
1207 CdbLength32 - CdbLength field value for SRBEX_DATA_SCSI_CDB_VAR
1209 ScsiStatus - ScsiStatus field value.
1211 SenseInfoBuffer - SenseInfoBuffer value.
1213 SenseInfoBufferLength - SenseInfoBufferLength value.
1222 PSRBEX_DATA SrbExData
= NULL
;
1223 BOOLEAN FoundEntry
= FALSE
;
1225 if ((SrbEx
->Function
== SRB_FUNCTION_STORAGE_REQUEST_BLOCK
) &&
1226 (SrbEx
->SrbFunction
== SRB_FUNCTION_EXECUTE_SCSI
)) {
1227 NT_ASSERT(SrbEx
->NumSrbExData
> 0);
1229 for (i
= 0; i
< SrbEx
->NumSrbExData
; i
++) {
1231 // Skip any invalid offsets
1232 if ((SrbEx
->SrbExDataOffset
[i
] < sizeof(STORAGE_REQUEST_BLOCK
)) ||
1233 (SrbEx
->SrbExDataOffset
[i
] > SrbEx
->SrbLength
)){
1234 // Catch any invalid offsets
1239 SrbExData
= (PSRBEX_DATA
)((PUCHAR
)SrbEx
+ SrbEx
->SrbExDataOffset
[i
]);
1241 switch (SrbExData
->Type
) {
1243 case SrbExDataTypeScsiCdb16
:
1244 if (SrbEx
->SrbExDataOffset
[i
] + sizeof(SRBEX_DATA_SCSI_CDB16
) <= SrbEx
->SrbLength
) {
1246 ((PSRBEX_DATA_SCSI_CDB16
) SrbExData
)->CdbLength
= CdbLength8
;
1247 ((PSRBEX_DATA_SCSI_CDB16
) SrbExData
)->ScsiStatus
= ScsiStatus
;
1248 ((PSRBEX_DATA_SCSI_CDB16
) SrbExData
)->SenseInfoBuffer
= SenseInfoBuffer
;
1249 ((PSRBEX_DATA_SCSI_CDB16
) SrbExData
)->SenseInfoBufferLength
= SenseInfoBufferLength
;
1251 // Catch invalid offset
1256 case SrbExDataTypeScsiCdb32
:
1257 if (SrbEx
->SrbExDataOffset
[i
] + sizeof(SRBEX_DATA_SCSI_CDB32
) <= SrbEx
->SrbLength
) {
1259 ((PSRBEX_DATA_SCSI_CDB32
) SrbExData
)->CdbLength
= CdbLength8
;
1260 ((PSRBEX_DATA_SCSI_CDB32
) SrbExData
)->ScsiStatus
= ScsiStatus
;
1261 ((PSRBEX_DATA_SCSI_CDB32
) SrbExData
)->SenseInfoBuffer
= SenseInfoBuffer
;
1262 ((PSRBEX_DATA_SCSI_CDB32
) SrbExData
)->SenseInfoBufferLength
= SenseInfoBufferLength
;
1264 // Catch invalid offset
1269 case SrbExDataTypeScsiCdbVar
:
1270 if (SrbEx
->SrbExDataOffset
[i
] + sizeof(SRBEX_DATA_SCSI_CDB_VAR
) <= SrbEx
->SrbLength
) {
1272 ((PSRBEX_DATA_SCSI_CDB_VAR
) SrbExData
)->CdbLength
= CdbLength32
;
1273 ((PSRBEX_DATA_SCSI_CDB_VAR
) SrbExData
)->ScsiStatus
= ScsiStatus
;
1274 ((PSRBEX_DATA_SCSI_CDB_VAR
) SrbExData
)->SenseInfoBuffer
= SenseInfoBuffer
;
1275 ((PSRBEX_DATA_SCSI_CDB_VAR
) SrbExData
)->SenseInfoBufferLength
= SenseInfoBufferLength
;
1277 // Catch invalid offset