1 /*++
2 
3 Copyright (C) Microsoft Corporation, 1991 - 2010
4 
5 Module Name:
6 
7     classp.h
8 
9 Abstract:
10 
11     Private header file for classpnp.sys modules.  This contains private
12     structure and function declarations as well as constant values which do
13     not need to be exported.
14 
15 Author:
16 
17 Environment:
18 
19     kernel mode only
20 
21 Notes:
22 
23 
24 Revision History:
25 
26 --*/
27 
28 #define RTL_USE_AVL_TABLES 0
29 
30 #include <stddef.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33 
34 #include <ntddk.h>
35 
36 #ifdef __REACTOS__
37 #include <pseh/pseh2.h>
38 #endif
39 
40 #include <scsi.h>
41 
42 #include <wmidata.h>
43 #include <classpnp.h>
44 #include <storduid.h>
45 
46 #if CLASS_INIT_GUID
47 #include <initguid.h>
48 #endif
49 
50 #include <mountdev.h>
51 #include <ioevent.h>
52 #include <ntstrsafe.h>
53 #include <ntintsafe.h>
54 
55 #include <wdmguid.h>
56 
57 #if (NTDDI_VERSION >= NTDDI_WIN8)
58 
59 #include <ntpoapi.h>
60 
61 #include <srbhelper.h>
62 
63 #endif
64 
65 #ifdef __REACTOS__
66 #undef MdlMappingNoExecute
67 #define MdlMappingNoExecute 0
68 #define NonPagedPoolNx NonPagedPool
69 #define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned
70 #undef POOL_NX_ALLOCATION
71 #define POOL_NX_ALLOCATION 0
72 #endif
73 
74 //
75 // Set component ID for DbgPrintEx calls
76 //
77 #ifndef DEBUG_COMP_ID
78 #define DEBUG_COMP_ID   DPFLTR_CLASSPNP_ID
79 #endif
80 
81 //
82 // Include header file and setup GUID for tracing
83 //
84 #include <storswtr.h>
85 #define WPP_GUID_CLASSPNP       (FA8DE7C4, ACDE, 4443, 9994, C4E2359A9EDB)
86 #ifndef WPP_CONTROL_GUIDS
87 #define WPP_CONTROL_GUIDS       WPP_CONTROL_GUIDS_NORMAL_FLAGS(WPP_GUID_CLASSPNP)
88 #endif
89 
90 /*
91  *  IA64 requires 8-byte alignment for pointers, but the IA64 NT kernel expects 16-byte alignment
92  */
93 #ifdef _WIN64
94     #define PTRALIGN                DECLSPEC_ALIGN(16)
95 #else
96     #define PTRALIGN
97 #endif
98 
99 
100 extern CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[];
101 
102 extern GUID ClassGuidQueryRegInfoEx;
103 extern GUID ClassGuidSenseInfo2;
104 extern GUID ClassGuidWorkingSet;
105 extern GUID ClassGuidSrbSupport;
106 
107 extern ULONG ClassMaxInterleavePerCriticalIo;
108 
109 
110 #define Add2Ptr(P,I)                                ((PVOID)((PUCHAR)(P) + (I)))
111 
112 #define CLASSP_REG_SUBKEY_NAME                      (L"Classpnp")
113 
114 #define CLASSP_REG_HACK_VALUE_NAME                  (L"HackMask")
115 #define CLASSP_REG_MMC_DETECTION_VALUE_NAME         (L"MMCDetectionState")
116 #define CLASSP_REG_WRITE_CACHE_VALUE_NAME           (L"WriteCacheEnableOverride")
117 #define CLASSP_REG_PERF_RESTORE_VALUE_NAME          (L"RestorePerfAtCount")
118 #define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME        (L"UserRemovalPolicy")
119 #define CLASSP_REG_IDLE_INTERVAL_NAME               (L"IdleInterval")
120 #define CLASSP_REG_IDLE_ACTIVE_MAX                  (L"IdleOutstandingIoMax")
121 #define CLASSP_REG_IDLE_PRIORITY_SUPPORTED          (L"IdlePrioritySupported")
122 #define CLASSP_REG_ACCESS_ALIGNMENT_NOT_SUPPORTED   (L"AccessAlignmentQueryNotSupported")
123 #define CLASSP_REG_DISBALE_IDLE_POWER_NAME          (L"DisableIdlePowerManagement")
124 #define CLASSP_REG_IDLE_TIMEOUT_IN_SECONDS          (L"IdleTimeoutInSeconds")
125 #define CLASSP_REG_DISABLE_D3COLD                   (L"DisableD3Cold")
126 #define CLASSP_REG_QERR_OVERRIDE_MODE               (L"QERROverrideMode")
127 #define CLASSP_REG_LEGACY_ERROR_HANDLING            (L"LegacyErrorHandling")
128 #define CLASSP_REG_COPY_OFFLOAD_MAX_TARGET_DURATION (L"CopyOffloadMaxTargetDuration")
129 
130 #define CLASS_PERF_RESTORE_MINIMUM                  (0x10)
131 #define CLASS_ERROR_LEVEL_1                         (0x4)
132 #define CLASS_ERROR_LEVEL_2                         (0x8)
133 #define CLASS_MAX_INTERLEAVE_PER_CRITICAL_IO        (0x4)
134 
135 #define FDO_HACK_CANNOT_LOCK_MEDIA                  (0x00000001)
136 #define FDO_HACK_GESN_IS_BAD                        (0x00000002)
137 #define FDO_HACK_NO_SYNC_CACHE                      (0x00000004)
138 #define FDO_HACK_NO_RESERVE6                        (0x00000008)
139 #define FDO_HACK_GESN_IGNORE_OPCHANGE               (0x00000010)
140 
141 #define FDO_HACK_VALID_FLAGS                        (0x0000001F)
142 #define FDO_HACK_INVALID_FLAGS                      (~FDO_HACK_VALID_FLAGS)
143 
144 /*
145  *  Lots of retries of synchronized SCSI commands that devices may not
146  *  even support really slows down the system (especially while booting).
147  *  (Even GetDriveCapacity may be failed on purpose if an external disk is powered off).
148  *  If a disk cannot return a small initialization buffer at startup
149  *  in two attempts (with delay interval) then we cannot expect it to return
150  *  data consistently with four retries.
151  *  So don't set the retry counts as high here as for data SRBs.
152  *
153  *  If we find that these requests are failing consecutively,
154  *  despite the retry interval, on otherwise reliable media,
155  *  then we should either increase the retry interval for
156  *  that failure or (by all means) increase these retry counts as appropriate.
157  */
158 #define NUM_LOCKMEDIAREMOVAL_RETRIES    1
159 #define NUM_MODESENSE_RETRIES           1
160 #define NUM_MODESELECT_RETRIES          1
161 #define NUM_DRIVECAPACITY_RETRIES       1
162 #define NUM_THIN_PROVISIONING_RETRIES   32
163 
164 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
165 
166 //
167 // New code should use the MAXIMUM_RETRIES value.
168 //
169 #define NUM_IO_RETRIES MAXIMUM_RETRIES
170 #define LEGACY_NUM_IO_RETRIES 8
171 
172 #else
173 
174 /*
175  *  We retry failed I/O requests at 1-second intervals.
176  *  In the case of a failure due to bus reset, we want to make sure that we retry after the allowable
177  *  reset time.  For SCSI, the allowable reset time is 5 seconds.  ScsiPort queues requests during
178  *  a bus reset, which should cause us to retry after the reset is over; but the requests queued in
179  *  the miniport are failed all the way back to us immediately.  In any event, in order to make
180  *  extra sure that our retries span the allowable reset time, we should retry more than 5 times.
181  */
182 #define NUM_IO_RETRIES      8
183 
184 #endif // NTDDI_VERSION >= NTDDI_WINBLUE
185 
186 #define CLASS_FILE_OBJECT_EXTENSION_KEY             'eteP'
187 #define CLASSP_VOLUME_VERIFY_CHECKED                0x34
188 
189 #define CLASS_TAG_PRIVATE_DATA                      'CPcS'
190 #define CLASS_TAG_SENSE2                            '2ScS'
191 #define CLASS_TAG_WORKING_SET                       'sWcS'
192 #define CLASSPNP_POOL_TAG_GENERIC                   'pCcS'
193 #define CLASSPNP_POOL_TAG_TOKEN_OPERATION           'oTcS'
194 #define CLASSPNP_POOL_TAG_SRB                       'rScS'
195 #define CLASSPNP_POOL_TAG_VPD                       'pVcS'
196 #define CLASSPNP_POOL_TAG_LOG_MESSAGE               'mlcS'
197 #define CLASSPNP_POOL_TAG_ADDITIONAL_DATA           'DAcS'
198 #define CLASSPNP_POOL_TAG_FIRMWARE                  'wFcS'
199 
200 //
201 // Macros related to Token Operation commands
202 //
203 #define MAX_LIST_IDENTIFIER                                         MAXULONG
204 #define NUM_POPULATE_TOKEN_RETRIES                                  1
205 #define NUM_WRITE_USING_TOKEN_RETRIES                               2
206 #define NUM_RECEIVE_TOKEN_INFORMATION_RETRIES                       2
207 #define MAX_TOKEN_OPERATION_PARAMETER_DATA_LENGTH                   MAXUSHORT
208 #define MAX_RECEIVE_TOKEN_INFORMATION_PARAMETER_DATA_LENGTH         MAXULONG
209 #define MAX_TOKEN_TRANSFER_SIZE                                     MAXULONGLONG
210 #define MAX_NUMBER_BLOCKS_PER_BLOCK_DEVICE_RANGE_DESCRIPTOR         MAXULONG
211 #define DEFAULT_MAX_TARGET_DURATION                                 4 // 4sec
212 #define DEFAULT_MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN         (64ULL * 1024 * 1024)  // 64MB
213 #define MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN                 (256ULL * 1024 * 1024) // 256MB
214 #define MIN_TOKEN_LIST_IDENTIFIERS                                  256
215 #define MAX_TOKEN_LIST_IDENTIFIERS                                  MAXULONG
216 #define MAX_NUMBER_BLOCK_DEVICE_DESCRIPTORS                         64
217 
218 #define REG_DISK_CLASS_CONTROL                                      L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\DISK"
219 #define REG_MAX_LIST_IDENTIFIER_VALUE                               L"MaximumListIdentifier"
220 
221 #define VPD_PAGE_HEADER_SIZE                                        0x04
222 
223 
224 //
225 // Number of times to retry get LBA status in case of an error
226 // that can be caused by VPD data change
227 //
228 
229 #define GET_LBA_STATUS_RETRY_COUNT_MAX                              (2)
230 
231 extern ULONG MaxTokenOperationListIdentifier;
232 extern volatile ULONG TokenOperationListIdentifier;
233 
234 extern LIST_ENTRY IdlePowerFDOList;
235 extern PVOID PowerSettingNotificationHandle;
236 extern PVOID ScreenStateNotificationHandle;
237 extern BOOLEAN ClasspScreenOff;
238 extern KGUARDED_MUTEX IdlePowerFDOListMutex;
239 extern ULONG DiskIdleTimeoutInMS;
240 
241 //
242 // Definitions from ntos\rtl\time.c
243 //
244 
245 extern CONST LARGE_INTEGER Magic10000;
246 #define SHIFT10000               13
247 
248 //
249 // Constant to help wih various time conversions
250 //
251 #define CONST_MSECS_PER_SEC                 1000
252 
253 #define Convert100nsToMilliseconds(LARGE_INTEGER)                       \
254     (                                                                   \
255     RtlExtendedMagicDivide((LARGE_INTEGER), Magic10000, SHIFT10000)     \
256     )
257 
258 #define ConvertMillisecondsTo100ns(MILLISECONDS) (                      \
259     RtlExtendedIntegerMultiply ((MILLISECONDS), 10000)                  \
260     )
261 
262 typedef struct _MEDIA_CHANGE_DETECTION_INFO {
263 
264     //
265     // Mutex to synchronize enable/disable requests and media state changes
266     //
267 
268     KMUTEX MediaChangeMutex;
269 
270     //
271     // The current state of the media (present, not present, unknown)
272     // protected by MediaChangeSynchronizationEvent
273     //
274 
275     MEDIA_CHANGE_DETECTION_STATE MediaChangeDetectionState;
276 
277     //
278     // This is a count of how many time MCD has been disabled.  if it is
279     // set to zero, then we'll poll the device for MCN events with the
280     // then-current method (ie. TEST UNIT READY or GESN).  this is
281     // protected by MediaChangeMutex
282     //
283 
284     LONG MediaChangeDetectionDisableCount;
285 
286 
287     //
288     // The timer value to support media change events.  This is a countdown
289     // value used to determine when to poll the device for a media change.
290     // The max value for the timer is 255 seconds.  This is not protected
291     // by an event -- simply InterlockedExchanged() as needed.
292     //
293 
294     LONG MediaChangeCountDown;
295 
296     //
297     // recent changes allowed instant retries of the MCN irp.  Since this
298     // could cause an infinite loop, keep a count of how many times we've
299     // retried immediately so that we can catch if the count exceeds an
300     // arbitrary limit.
301     //
302 
303     LONG MediaChangeRetryCount;
304 
305     //
306     // use GESN if it's available
307     //
308 
309     struct {
310         BOOLEAN Supported;
311         BOOLEAN HackEventMask;
312         UCHAR   EventMask;
313         UCHAR   NoChangeEventMask;
314         PUCHAR  Buffer;
315         PMDL    Mdl;
316         ULONG   BufferSize;
317     } Gesn;
318 
319     //
320     // If this value is one, then the irp is currently in use.
321     // If this value is zero, then the irp is available.
322     // Use InterlockedCompareExchange() to set from "available" to "in use".
323     // ASSERT that InterlockedCompareExchange() showed previous value of
324     //    "in use" when changing back to "available" state.
325     // This also implicitly protects the MediaChangeSrb and SenseBuffer
326     //
327 
328     LONG MediaChangeIrpInUse;
329 
330     //
331     // Pointer to the irp to be used for media change detection.
332     // protected by Interlocked MediaChangeIrpInUse
333     //
334 
335     PIRP MediaChangeIrp;
336 
337     //
338     // The srb for the media change detection.
339     // protected by Interlocked MediaChangeIrpInUse
340     //
341 
342 #if (NTDDI_VERSION >= NTDDI_WIN8)
343     union {
344         SCSI_REQUEST_BLOCK Srb;
345         STORAGE_REQUEST_BLOCK SrbEx;
346         UCHAR SrbExBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE];
347     } MediaChangeSrb;
348 #else
349     SCSI_REQUEST_BLOCK MediaChangeSrb;
350 #endif
351     PUCHAR SenseBuffer;
352     ULONG SrbFlags;
353 
354     //
355     // Second timer to keep track of how long the media change IRP has been
356     // in use.  If this value exceeds the timeout (#defined) then we should
357     // print out a message to the user and set the MediaChangeIrpLost flag
358     // protected by using Interlocked() operations in ClasspSendMediaStateIrp,
359     // the only routine which should modify this value.
360     //
361 
362     LONG MediaChangeIrpTimeInUse;
363 
364     //
365     // Set by CdRomTickHandler when we determine that the media change irp has
366     // been lost
367     //
368 
369     BOOLEAN MediaChangeIrpLost;
370 
371     //
372     // Buffer size of SenseBuffer
373     //
374     UCHAR SenseBufferLength;
375 
376 } MEDIA_CHANGE_DETECTION_INFO, *PMEDIA_CHANGE_DETECTION_INFO;
377 
378 typedef enum {
379     SimpleMediaLock,
380     SecureMediaLock,
381     InternalMediaLock
382 } MEDIA_LOCK_TYPE, *PMEDIA_LOCK_TYPE;
383 
384 typedef struct _FAILURE_PREDICTION_INFO {
385     FAILURE_PREDICTION_METHOD Method;
386     ULONG CountDown;                // Countdown timer
387     ULONG Period;                   // Countdown period
388 
389     PIO_WORKITEM WorkQueueItem;
390 
391     KEVENT Event;
392 
393     //
394     // Timestamp of last time the failure prediction info was queried.
395     //
396     LARGE_INTEGER LastFailurePredictionQueryTime;
397 
398 } FAILURE_PREDICTION_INFO, *PFAILURE_PREDICTION_INFO;
399 
400 
401 
402 //
403 // This struct must always fit within four PVOIDs of info,
404 // as it uses the irp's "PVOID DriverContext[4]" to store
405 // this info
406 //
407 typedef struct _CLASS_RETRY_INFO {
408     struct _CLASS_RETRY_INFO *Next;
409 } CLASS_RETRY_INFO, *PCLASS_RETRY_INFO;
410 
411 typedef struct _CSCAN_LIST {
412 
413     //
414     // The current block which has an outstanding request.
415     //
416 
417     ULONGLONG BlockNumber;
418 
419     //
420     // The list of blocks past the CurrentBlock to which we're going to do
421     // i/o.  This list is maintained in sorted order.
422     //
423 
424     LIST_ENTRY CurrentSweep;
425 
426     //
427     // The list of blocks behind the current block for which we'll have to
428     // wait until the next scan across the disk.  This is kept as a stack,
429     // the cost of sorting it is taken when it's moved over to be the
430     // running list.
431     //
432 
433     LIST_ENTRY NextSweep;
434 
435 } CSCAN_LIST, *PCSCAN_LIST;
436 
437 //
438 // add to the front of this structure to help prevent illegal
439 // snooping by other utilities.
440 //
441 
442 
443 
444 typedef enum _CLASS_DETECTION_STATE {
445     ClassDetectionUnknown = 0,
446     ClassDetectionUnsupported = 1,
447     ClassDetectionSupported = 2
448 } CLASS_DETECTION_STATE, *PCLASS_DETECTION_STATE;
449 
450 #if _MSC_VER >= 1600
451 #pragma warning(push)
452 #pragma warning(disable:4214) // bit field types other than int
453 #endif
454 //
455 // CLASS_ERROR_LOG_DATA will still use SCSI_REQUEST_BLOCK even
456 // when using extended SRB as an extended SRB is too large to
457 // fit into. Should revisit this code once classpnp starts to
458 // use greater than 16 byte CDB.
459 //
460 typedef struct _CLASS_ERROR_LOG_DATA {
461     LARGE_INTEGER TickCount;        // Offset 0x00
462     ULONG PortNumber;               // Offset 0x08
463 
464     UCHAR ErrorPaging    : 1;       // Offset 0x0c
465     UCHAR ErrorRetried   : 1;
466     UCHAR ErrorUnhandled : 1;
467     UCHAR ErrorReserved  : 5;
468 
469     UCHAR Reserved[3];
470 
471     SCSI_REQUEST_BLOCK Srb;     // Offset 0x10
472 
473     /*
474      *  We define the SenseData as the default length.
475      *  Since the sense data returned by the port driver may be longer,
476      *  SenseData must be at the end of this structure.
477      *  For our internal error log, we only log the default length.
478      */
479     SENSE_DATA SenseData;     // Offset 0x50 for x86 (or 0x68 for ia64) (ULONG32 Alignment required!)
480 
481 } CLASS_ERROR_LOG_DATA, *PCLASS_ERROR_LOG_DATA;
482 #if _MSC_VER >= 1600
483 #pragma warning(pop)
484 #endif
485 
486 #define NUM_ERROR_LOG_ENTRIES   16
487 #define DBG_NUM_PACKET_LOG_ENTRIES (64*2)   // 64 send&receive's
488 
489 #if (NTDDI_VERSION >= NTDDI_WIN8)
490 typedef
491 VOID
492 (*PCONTINUATION_ROUTINE)(
493     _In_ PVOID Context
494     );
495 #endif
496 
497 typedef struct _TRANSFER_PACKET {
498 
499         LIST_ENTRY AllPktsListEntry;    // entry in fdoData's static AllTransferPacketsList
500         SLIST_ENTRY SlistEntry;         // for when in free list (use fast slist)
501 
502         PIRP Irp;
503         PDEVICE_OBJECT Fdo;
504 
505         /*
506          *  This is the client IRP that this TRANSFER_PACKET is currently
507          *  servicing.
508          */
509         PIRP OriginalIrp;
510         BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes;
511 
512         /*
513          *  Stuff for retrying the transfer.
514          */
515 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
516         UCHAR NumRetries; // Total number of retries remaining.
517         UCHAR NumThinProvisioningRetries; //Number of retries carried out so far for a request failed with THIN_PROVISIONING_SOFT_THRESHOLD_ERROR
518         UCHAR NumIoTimeoutRetries; // Number of retries remaining for a timed-out request.
519         UCHAR TimedOut; // Indicates if this packet has timed-out.
520 #else
521         ULONG NumRetries;
522 #endif
523         KTIMER RetryTimer;
524         KDPC RetryTimerDPC;
525 
526         _Field_range_(0,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
527         LONGLONG RetryIn100nsUnits;
528 
529         /*
530          *  Event for synchronizing the transfer (optional).
531          *  (Note that we can't have the event in the packet itself because
532          *  by the time a thread waits on an event the packet may have
533          *  been completed and re-issued.
534          */
535         PKEVENT SyncEventPtr;
536 
537         /*
538          *  Stuff for retrying during extreme low-memory stress
539          *  (when we retry 1 page at a time).
540          *  NOTE: These fields are also used for StartIO-based
541          *  class drivers, even when not in low memory conditions.
542          */
543         BOOLEAN DriverUsesStartIO; // if this is set, then the below low-mem flags are always used
544         BOOLEAN InLowMemRetry;
545         PUCHAR LowMemRetry_remainingBufPtr;
546         ULONG LowMemRetry_remainingBufLen;
547         LARGE_INTEGER LowMemRetry_nextChunkTargetLocation;
548 
549         /*
550          *  Fields used for cancelling the packet.
551          */
552         // BOOLEAN Cancelled;
553         // KEVENT CancelledEvent;
554 
555         /*
556          *  We keep the buffer and length values here as well
557          *  as in the SRB because some miniports return
558          *  the transferred length in SRB.DataTransferLength,
559          *  and if the SRB failed we need that value again for the retry.
560          *  We don't trust the lower stack to preserve any of these values in the SRB.
561          */
562         PUCHAR BufPtrCopy;
563         ULONG BufLenCopy;
564         LARGE_INTEGER TargetLocationCopy;
565 
566         /*
567          *  This is a standard SCSI structure that receives a detailed
568          *  report about a SCSI error on the hardware.
569          */
570         SENSE_DATA_EX SrbErrorSenseData;
571 
572         /*
573          *  This is the SRB block for this TRANSFER_PACKET.
574          *  For IOCTLs, the SRB block includes two DWORDs for
575          *  device object and ioctl code; so these must
576          *  immediately follow the SRB block.
577          */
578 
579 #if (NTDDI_VERSION >= NTDDI_WIN8)
580         PSTORAGE_REQUEST_BLOCK_HEADER Srb;
581 #else
582         SCSI_REQUEST_BLOCK Srb;
583 #endif
584         // ULONG SrbIoctlDevObj;        // not handling ioctls yet
585         // ULONG SrbIoctlCode;
586 
587         #if DBG
588             LARGE_INTEGER DbgTimeSent;
589             LARGE_INTEGER DbgTimeReturned;
590             ULONG DbgPktId;
591             IRP DbgOriginalIrpCopy;
592             MDL DbgMdlCopy;
593         #endif
594 
595         BOOLEAN UsePartialMdl;
596         PMDL PartialMdl;
597 
598         PSRB_HISTORY RetryHistory;
599 
600         // The time at which this request was sent to port driver.
601         ULONGLONG RequestStartTime;
602 
603 #if (NTDDI_VERSION >= NTDDI_WIN8)
604         // ActivityId that is associated with the IRP that this transfer packet services.
605         GUID ActivityId;
606 
607         // If non-NULL, called at packet completion with this context.
608         PCONTINUATION_ROUTINE ContinuationRoutine;
609         PVOID ContinuationContext;
610         ULONGLONG TransferCount;
611         ULONG AllocateNode;
612 #endif
613 } TRANSFER_PACKET, *PTRANSFER_PACKET;
614 
615 /*
616  *  MIN_INITIAL_TRANSFER_PACKETS is the minimum number of packets that
617  *  we preallocate at startup for each device (we need at least one packet
618  *  to guarantee forward progress during memory stress).
619  *  MIN_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
620  *  we allow to build up and remain for each device;
621  *  we _lazily_ work down to this number when they're not needed.
622  *  MAX_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
623  *  that we _immediately_ reduce to when they are not needed.
624  *
625  *  The absolute maximum number of packets that we will allocate is
626  *  whatever is required by the current activity, up to the memory limit;
627  *  as soon as stress ends, we snap down to MAX_WORKINGSET_TRANSFER_PACKETS;
628  *  we then lazily work down to MIN_WORKINGSET_TRANSFER_PACKETS.
629  */
630 #define MIN_INITIAL_TRANSFER_PACKETS                        1
631 #define MIN_WORKINGSET_TRANSFER_PACKETS_Client              16
632 #define MAX_WORKINGSET_TRANSFER_PACKETS_Client              32
633 #define MIN_WORKINGSET_TRANSFER_PACKETS_Server_UpperBound   256
634 #define MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound   32
635 #define MAX_WORKINGSET_TRANSFER_PACKETS_Server              1024
636 #define MIN_WORKINGSET_TRANSFER_PACKETS_SPACES              512
637 #define MAX_WORKINGSET_TRANSFER_PACKETS_SPACES              2048
638 #define MAX_OUTSTANDING_IO_PER_LUN_DEFAULT                  16
639 #define MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE                8192
640 
641 
642 
643 typedef struct _PNL_SLIST_HEADER {
644     DECLSPEC_CACHEALIGN SLIST_HEADER SListHeader;
645     DECLSPEC_CACHEALIGN ULONG NumFreeTransferPackets;
646     ULONG NumTotalTransferPackets;
647     ULONG DbgPeakNumTransferPackets;
648 } PNL_SLIST_HEADER, *PPNL_SLIST_HEADER;
649 
650 //
651 // !!! WARNING !!!
652 // DO NOT use the following structure in code outside of classpnp
653 // as structure will not be guaranteed between OS versions.
654 //
655 // add to the front of this structure to help prevent illegal
656 // snooping by other utilities.
657 //
658 struct _CLASS_PRIVATE_FDO_DATA {
659 
660     //
661     // The amount of time allowed for a target to complete a copy offload
662     // operation, in seconds.  Default is 4s, but it can be modified via
663     // registry key.
664     //
665     ULONG CopyOffloadMaxTargetDuration;
666 
667 
668 #if (NTDDI_VERSION >= NTDDI_WIN8)
669 
670     //
671     // Periodic timer for polling for media change detection, failure prediction
672     // and class tick function.
673     //
674 
675 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
676     PEX_TIMER TickTimer;
677     LONGLONG CurrentNoWakeTolerance;
678 #else
679     KTIMER TickTimer;
680     KDPC TickTimerDpc;
681 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
682 
683     //
684     // Power related and release queue SRBs
685     //
686     union {
687         STORAGE_REQUEST_BLOCK SrbEx;
688         UCHAR PowerSrbBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE];
689     } PowerSrb;
690 
691     union {
692         STORAGE_REQUEST_BLOCK SrbEx;
693         UCHAR ReleaseQueueSrbBuffer[CLASS_SRBEX_NO_SRBEX_DATA_BUFFER_SIZE];
694     } ReleaseQueueSrb;
695 
696 #endif
697 
698     ULONG TrackingFlags;
699 
700     /*
701      * Flag to detect recursion caused by devices
702      * reporting different capacity per each request
703      */
704     ULONG UpdateDiskPropertiesWorkItemActive;
705 
706     //
707     // Local equivalents of MinWorkingSetTransferPackets and MaxWorkingSetTransferPackets.
708     // These values are initialized by the global equivalents but are then adjusted as
709     // requested by the class driver.
710     //
711     ULONG LocalMinWorkingSetTransferPackets;
712     ULONG LocalMaxWorkingSetTransferPackets;
713 
714 #if DBG
715 
716     ULONG MaxOutstandingIOPerLUN;
717 
718 #endif
719 
720     /*
721      *  Entry in static list used by debug extension to quickly find all class FDOs.
722      */
723     LIST_ENTRY AllFdosListEntry;
724 
725     //
726     // this private structure allows us to
727     // dynamically re-enable the perf benefits
728     // lost due to transient error conditions.
729     // in w2k, a reboot was required. :(
730     //
731     struct {
732         ULONG      OriginalSrbFlags;
733         ULONG      SuccessfulIO;
734         ULONG      ReEnableThreshhold; // 0 means never
735     } Perf;
736 
737     ULONG_PTR HackFlags;
738 
739     STORAGE_HOTPLUG_INFO HotplugInfo;
740 
741     // Legacy.  Still used by obsolete legacy code.
742     struct {
743         LARGE_INTEGER     Delta;       // in ticks
744         LARGE_INTEGER     Tick;        // when it should fire
745         PCLASS_RETRY_INFO ListHead;    // singly-linked list
746         ULONG             Granularity; // static
747         KSPIN_LOCK        Lock;        // protective spin lock
748         KDPC              Dpc;         // DPC routine object
749         KTIMER            Timer;       // timer to fire DPC
750     } Retry;
751 
752     BOOLEAN TimerInitialized;
753     BOOLEAN LoggedTURFailureSinceLastIO;
754     BOOLEAN LoggedSYNCFailure;
755 
756     //
757     // privately allocated release queue irp
758     // protected by fdoExtension->ReleaseQueueSpinLock
759     //
760     BOOLEAN ReleaseQueueIrpAllocated;
761     PIRP ReleaseQueueIrp;
762 
763     /*
764      *  Queues for TRANSFER_PACKETs that contextualize the IRPs and SRBs
765      *  that we send down to the port driver.
766      *  (The free list is an slist so that we can use fast
767      *   interlocked operations on it; but the relatively-static
768      *   AllTransferPacketsList list has to be
769      *   a doubly-linked list since we have to dequeue from the middle).
770      */
771     LIST_ENTRY AllTransferPacketsList;
772     PPNL_SLIST_HEADER FreeTransferPacketsLists;
773 
774     /*
775      *  Queue for deferred client irps
776      */
777     LIST_ENTRY DeferredClientIrpList;
778 
779     /*
780      *  Precomputed maximum transfer length for the hardware.
781      */
782     ULONG HwMaxXferLen;
783 
784     /*
785      *  SCSI_REQUEST_BLOCK template preconfigured with the constant values.
786      *  This is slapped into the SRB in the TRANSFER_PACKET for each transfer.
787      */
788 
789 #if (NTDDI_VERSION >= NTDDI_WIN8)
790     PSTORAGE_REQUEST_BLOCK_HEADER SrbTemplate;
791 #else
792     SCSI_REQUEST_BLOCK SrbTemplate;
793 #endif
794 
795     KSPIN_LOCK SpinLock;
796 
797     /*
798      *  For non-removable media, we read the drive capacity at start time and cache it.
799      *  This is so that ReadDriveCapacity failures at runtime (e.g. due to memory stress)
800      *  don't cause I/O on the paging disk to start failing.
801      */
802     READ_CAPACITY_DATA_EX LastKnownDriveCapacityData;
803     BOOLEAN IsCachedDriveCapDataValid;
804 
805     //
806     // Idle priority support flag
807     //
808     BOOLEAN IdlePrioritySupported;
809 
810     //
811     // Tick timer enabled
812     //
813     BOOLEAN TickTimerEnabled;
814 
815     BOOLEAN ReservedBoolean;
816 
817     /*
818      *  Circular array of timestamped logs of errors that occurred on this device.
819      */
820     ULONG ErrorLogNextIndex;
821     CLASS_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES];
822 
823     //
824     // Number of outstanding critical Io requests from Mm
825     //
826     ULONG NumHighPriorityPagingIo;
827 
828     //
829     // Maximum number of normal Io requests that can be interleaved with the critical ones
830     //
831     ULONG MaxInterleavedNormalIo;
832 
833     //
834     // The timestamp when entering throttle mode
835     //
836     LARGE_INTEGER ThrottleStartTime;
837 
838     //
839     // The timestamp when exiting throttle mode
840     //
841     LARGE_INTEGER ThrottleStopTime;
842 
843     //
844     // The longest time ever spent in throttle mode
845     //
846     LARGE_INTEGER LongestThrottlePeriod;
847 
848     #if DBG
849         ULONG DbgMaxPktId;
850 
851         /*
852          *  Logging fields for ForceUnitAccess and Flush
853          */
854         BOOLEAN DbgInitFlushLogging;         // must reset this to 1 for each logging session
855         ULONG DbgNumIORequests;
856         ULONG DbgNumFUAs;       // num I/O requests with ForceUnitAccess bit set
857         ULONG DbgNumFlushes;    // num SRB_FUNCTION_FLUSH_QUEUE
858         ULONG DbgIOsSinceFUA;
859         ULONG DbgIOsSinceFlush;
860         ULONG DbgAveIOsToFUA;      // average number of I/O requests between FUAs
861         ULONG DbgAveIOsToFlush;   // ...
862         ULONG DbgMaxIOsToFUA;
863         ULONG DbgMaxIOsToFlush;
864         ULONG DbgMinIOsToFUA;
865         ULONG DbgMinIOsToFlush;
866 
867         /*
868          *  Debug log of previously sent packets (including retries).
869          */
870         ULONG DbgPacketLogNextIndex;
871         TRANSFER_PACKET DbgPacketLogs[DBG_NUM_PACKET_LOG_ENTRIES];
872     #endif
873 
874     //
875     // Spin lock for low priority I/O list
876     //
877     KSPIN_LOCK IdleListLock;
878 
879     //
880     // Queue for low priority I/O
881     //
882     LIST_ENTRY IdleIrpList;
883 
884     //
885     // Timer for low priority I/O
886     //
887     KTIMER IdleTimer;
888 
889     //
890     // DPC for low priority I/O
891     //
892     KDPC IdleDpc;
893 
894 #if (NTDDI_VERSION >= NTDDI_WIN8)
895 
896     //
897     // Time (ms) since the completion of the last non-idle request before the
898     // first idle request should be issued. Due to the coarseness of the idle
899     // timer frequency, some variability in the idle interval will be tolerated
900     // such that it is the desired idle interval on average.
901     //
902     USHORT IdleInterval;
903 
904     //
905     // Max number of active idle requests.
906     //
907     USHORT IdleActiveIoMax;
908 
909 #endif
910 
911     //
912     // Idle duration required to process idle request
913     // to avoid starvation
914     //
915     USHORT StarvationDuration;
916 
917     //
918     // Idle I/O count
919     //
920     ULONG IdleIoCount;
921 
922     //
923     // Flag to indicate timer status
924     //
925     LONG IdleTimerStarted;
926 
927     //
928     // Time when the Idle timer was started
929     //
930     LARGE_INTEGER AntiStarvationStartTime;
931 
932     //
933     // Normal priority I/O time
934     //
935     LARGE_INTEGER LastNonIdleIoTime;
936 
937     //
938     // Time when the last IO of any priority completed.
939     //
940     LARGE_INTEGER LastIoCompletionTime;
941 
942     //
943     // Count of active normal priority I/O
944     //
945     LONG ActiveIoCount;
946 
947     //
948     // Count of active idle priority I/O
949     //
950     LONG ActiveIdleIoCount;
951 
952     //
953     // Support for class drivers to extend
954     // the interpret sense information routine
955     // and retry history per-packet.  Copy of
956     // values in driver extension.
957     //
958     PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo;
959 
960     //
961     // power process parameters. they work closely with CLASS_POWER_CONTEXT structure.
962     //
963     ULONG MaxPowerOperationRetryCount;
964     PIRP  PowerProcessIrp;
965 
966     //
967     // Indicates legacy error handling should be used.
968     // This means:
969     //  - Max number of retries for an IO request is 8 (instead of 4).
970     //
971     BOOLEAN LegacyErrorHandling;
972 
973     //
974     // Maximum number of retries allowed for IO requests for this device.
975     //
976     UCHAR MaxNumberOfIoRetries;
977 
978     //
979     // Disable All Throttling in case of Error
980     //
981     BOOLEAN DisableThrottling;
982 
983 };
984 
985 //
986 // !!! WARNING !!!
987 // DO NOT use the following structure in code outside of classpnp
988 // as structure will not be guaranteed between OS versions.
989 //
990 // EX_RUNDOWN_REF_CACHE_AWARE is variable size and follows
991 // RemoveLockFailAcquire. EX_RUNDOWN_REF_CACHE_AWARE must be part
992 // of the device extension allocation to avoid issues with a device
993 // that has been PNP remove but still has outstanding references.
994 // In this case, the removed object may still receive incoming requests.
995 //
996 // There are code dependencies on the structure layout. To minimize
997 // code changes, new fields to _CLASS_PRIVATE_COMMON_DATA should be
998 // added based on the following guidance.
999 // - Fixed size: beginning of _CLASS_PRIVATE_COMMON_DATA
1000 // - Variable size: at the end of _CLASS_PRIVATE_COMMON_DATA after the
1001 //   last variable size field.
1002 //
1003 
1004 struct _CLASS_PRIVATE_COMMON_DATA {
1005 
1006     //
1007     // Cacheaware rundown lock reference
1008     //
1009 
1010     LONG RemoveLockFailAcquire;
1011 
1012     //
1013     // N.B. EX_RUNDOWN_REF_CACHE_AWARE begins with a pointer-sized item that is
1014     //      accessed interlocked, and must be aligned on ARM platforms. In order
1015     //      for this to work on ARM64, an additional 32-bit slot must be allocated.
1016     //
1017 
1018 #if defined(_WIN64)
1019     LONG Align;
1020 #endif
1021 
1022     // EX_RUNDOWN_REF_CACHE_AWARE (variable size) follows
1023 
1024 };
1025 
1026 //
1027 // Verify that the size of _CLASS_PRIVATE_COMMON_DATA is pointer size aligned
1028 // to ensure the EX_RUNDOWN_REF_CACHE_AWARE following it is properly aligned.
1029 //
1030 
1031 C_ASSERT((sizeof(struct _CLASS_PRIVATE_COMMON_DATA) % sizeof(PVOID)) == 0);
1032 
1033 typedef struct _IDLE_POWER_FDO_LIST_ENTRY {
1034     LIST_ENTRY ListEntry;
1035     PDEVICE_OBJECT Fdo;
1036 } IDLE_POWER_FDO_LIST_ENTRY, *PIDLE_POWER_FDO_LIST_ENTRY;
1037 
1038 typedef struct _OFFLOAD_READ_CONTEXT {
1039 
1040     PDEVICE_OBJECT Fdo;
1041 
1042     //
1043     // Upper offload read DSM irp.
1044     //
1045 
1046     PIRP OffloadReadDsmIrp;
1047 
1048     //
1049     // A pseudo-irp is used despite the operation being async.  This is in
1050     // contrast to normal read and write, which let TransferPktComplete()
1051     // complete the upper IRP directly.  Offload requests are enough different
1052     // that it makes more sense to let them manage their own async steps with
1053     // minimal help from TransferPktComplete() (just a continuation function
1054     // call during TransferPktComplete()).
1055     //
1056 
1057     IRP PseudoIrp;
1058 
1059     //
1060     // The offload read context tracks one packet in flight at a time - it'll be
1061     // the POPULATE TOKEN packet first, then RECEIVE ROD TOKEN INFORMATION.
1062     //
1063     // This field exists only for debug purposes.
1064     //
1065 
1066     PTRANSFER_PACKET Pkt;
1067 
1068     PMDL PopulateTokenMdl;
1069 
1070     ULONG BufferLength;
1071 
1072     ULONG ListIdentifier;
1073 
1074     ULONG ReceiveTokenInformationBufferLength;
1075 
1076     //
1077     // Total sectors that the operation is attempting to process.
1078     //
1079 
1080     ULONGLONG TotalSectorsToProcess;
1081 
1082     //
1083     // Total sectors actually processed.
1084     //
1085 
1086     ULONGLONG TotalSectorsProcessed;
1087 
1088     //
1089     // Total upper request size in bytes.
1090     //
1091 
1092     ULONGLONG EntireXferLen;
1093 
1094     //
1095     // Just a cached copy of what was in the transfer packet.
1096     //
1097 
1098     SCSI_REQUEST_BLOCK Srb;
1099 
1100     //
1101     // Pointer into the token part of the SCSI buffer (the buffer immediately
1102     // after this struct), for easy reference.
1103     //
1104 
1105     PUCHAR Token;
1106 
1107     // The SCSI buffer (in/out buffer, not CDB) for the commands immediately
1108     // follows this struct, so no need to have a field redundantly pointing to
1109     // the buffer.
1110 } OFFLOAD_READ_CONTEXT, *POFFLOAD_READ_CONTEXT;
1111 
1112 
1113 typedef struct _OFFLOAD_WRITE_CONTEXT {
1114 
1115     PDEVICE_OBJECT Fdo;
1116 
1117     PIRP OffloadWriteDsmIrp;
1118 
1119     ULONGLONG EntireXferLen;
1120     ULONGLONG TotalRequestSizeSectors;
1121 
1122     ULONG DataSetRangesCount;
1123 
1124     PDEVICE_MANAGE_DATA_SET_ATTRIBUTES DsmAttributes;
1125     PDEVICE_DATA_SET_RANGE DataSetRanges;
1126     PDEVICE_DSM_OFFLOAD_WRITE_PARAMETERS OffloadWriteParameters;
1127     ULONGLONG LogicalBlockOffset;
1128 
1129     ULONG MaxBlockDescrCount;
1130     ULONGLONG MaxLbaCount;
1131 
1132     ULONG BufferLength;
1133     ULONG ReceiveTokenInformationBufferLength;
1134 
1135     IRP PseudoIrp;
1136 
1137     PMDL WriteUsingTokenMdl;
1138 
1139     ULONGLONG TotalSectorsProcessedSuccessfully;
1140     ULONG DataSetRangeIndex;
1141     ULONGLONG DataSetRangeByteOffset;
1142 
1143     PTRANSFER_PACKET Pkt;
1144 
1145     //
1146     // Per-WUT (WRITE USING TOKEN), not overall.
1147     //
1148 
1149     ULONGLONG TotalSectorsToProcess;
1150     ULONGLONG TotalSectorsProcessed;
1151 
1152     ULONG ListIdentifier;
1153 
1154     BOOLEAN TokenInvalidated;
1155 
1156     //
1157     // Just a cached copy of what was in the transfer packet.
1158     //
1159 
1160     SCSI_REQUEST_BLOCK Srb;
1161 
1162     ULONGLONG OperationStartTime;
1163 
1164 } OFFLOAD_WRITE_CONTEXT, *POFFLOAD_WRITE_CONTEXT;
1165 
1166 
1167 typedef struct _OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER {
1168     PIO_WORKITEM WorkItem;
1169     PVOID SenseData;
1170     ULONG SenseDataSize;
1171     UCHAR SrbStatus;
1172     UCHAR ScsiStatus;
1173     UCHAR OpCode;
1174     UCHAR Reserved;
1175     ULONG ErrorCode;
1176 } OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER, *POPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER;
1177 
1178 typedef struct _IO_RETRIED_LOG_MESSAGE_CONTEXT {
1179     OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER ContextHeader;
1180     LARGE_INTEGER Lba;
1181     ULONG DeviceNumber;
1182 } IO_RETRIED_LOG_MESSAGE_CONTEXT, *PIO_RETRIED_LOG_MESSAGE_CONTEXT;
1183 
1184 
1185 #define QERR_SET_ZERO_ODX_OR_TP_ONLY 0
1186 #define QERR_SET_ZERO_ALWAYS         1
1187 #define QERR_SET_ZERO_NEVER          2
1188 
1189 
1190 #define MIN(a, b)   ((a) < (b) ? (a) : (b))
1191 #define MAX(a, b)   ((a) > (b) ? (a) : (b))
1192 
1193 
1194 #define NOT_READY_RETRY_INTERVAL    10
1195 #define MINIMUM_RETRY_UNITS         ((LONGLONG)32)
1196 #define MODE_PAGE_DATA_SIZE         192
1197 
1198 #define CLASS_IDLE_INTERVAL_MIN     12          // 12 milliseconds
1199 #define CLASS_IDLE_INTERVAL         12          // 12 milliseconds
1200 #define CLASS_STARVATION_INTERVAL   500         // 500 milliseconds
1201 
1202 //
1203 // Value of 50 milliseconds in 100 nanoseconds units
1204 //
1205 #define FIFTY_MS_IN_100NS_UNITS     50 * 100
1206 
1207 
1208 /*
1209  *  Simple singly-linked-list queuing macros, with no synchronization.
1210  */
SimpleInitSlistHdr(SINGLE_LIST_ENTRY * SListHdr)1211 FORCEINLINE VOID SimpleInitSlistHdr(SINGLE_LIST_ENTRY *SListHdr)
1212 {
1213     SListHdr->Next = NULL;
1214 }
SimplePushSlist(SINGLE_LIST_ENTRY * SListHdr,SINGLE_LIST_ENTRY * SListEntry)1215 FORCEINLINE VOID SimplePushSlist(SINGLE_LIST_ENTRY *SListHdr, SINGLE_LIST_ENTRY *SListEntry)
1216 {
1217     SListEntry->Next = SListHdr->Next;
1218     SListHdr->Next = SListEntry;
1219 }
SimplePopSlist(SINGLE_LIST_ENTRY * SListHdr)1220 FORCEINLINE SINGLE_LIST_ENTRY *SimplePopSlist(SINGLE_LIST_ENTRY *SListHdr)
1221 {
1222     SINGLE_LIST_ENTRY *sListEntry = SListHdr->Next;
1223     if (sListEntry){
1224         SListHdr->Next = sListEntry->Next;
1225         sListEntry->Next = NULL;
1226     }
1227     return sListEntry;
1228 }
SimpleIsSlistEmpty(SINGLE_LIST_ENTRY * SListHdr)1229 FORCEINLINE BOOLEAN SimpleIsSlistEmpty(SINGLE_LIST_ENTRY *SListHdr)
1230 {
1231     return (SListHdr->Next == NULL);
1232 }
1233 
1234 FORCEINLINE
1235 BOOLEAN
ClasspIsIdleRequestSupported(PCLASS_PRIVATE_FDO_DATA FdoData,PIRP Irp)1236 ClasspIsIdleRequestSupported(
1237     PCLASS_PRIVATE_FDO_DATA FdoData,
1238     PIRP Irp
1239     )
1240 {
1241 #ifndef __REACTOS__
1242     IO_PRIORITY_HINT ioPriority = IoGetIoPriorityHint(Irp);
1243     return ((ioPriority <= IoPriorityLow) && (FdoData->IdlePrioritySupported == TRUE));
1244 #else
1245     return (FdoData->IdlePrioritySupported == TRUE);
1246 #endif
1247 }
1248 
1249 FORCEINLINE
1250 VOID
ClasspMarkIrpAsIdle(PIRP Irp,BOOLEAN Idle)1251 ClasspMarkIrpAsIdle(
1252     PIRP Irp,
1253     BOOLEAN Idle
1254     )
1255 {
1256 #ifndef __REACTOS__
1257 // truncation is not an issue for this use case
1258 // nonstandard extension used is not an issue for this use case
1259 #pragma warning(suppress:4305; suppress:4213)
1260     ((BOOLEAN)Irp->Tail.Overlay.DriverContext[1]) = Idle;
1261 #else
1262     ((PULONG_PTR)Irp->Tail.Overlay.DriverContext)[1] = Idle;
1263 #endif
1264 }
1265 
1266 FORCEINLINE
1267 BOOLEAN
ClasspIsIdleRequest(PIRP Irp)1268 ClasspIsIdleRequest(
1269     PIRP Irp
1270     )
1271 {
1272 #ifdef _MSC_VER
1273 #pragma warning(suppress:4305) // truncation is not an issue for this use case
1274 #endif
1275     return ((BOOLEAN)Irp->Tail.Overlay.DriverContext[1]);
1276 }
1277 
1278 FORCEINLINE
1279 LARGE_INTEGER
ClasspGetCurrentTime(VOID)1280 ClasspGetCurrentTime(
1281     VOID
1282     )
1283 {
1284     LARGE_INTEGER currentTime;
1285 
1286 #ifndef __REACTOS__
1287     currentTime.QuadPart = KeQueryUnbiasedInterruptTimePrecise((ULONG64*)&currentTime.QuadPart);
1288 #else
1289     currentTime = KeQueryPerformanceCounter(NULL);
1290 #endif
1291 
1292     return currentTime;
1293 }
1294 
1295 FORCEINLINE
1296 ULONGLONG
ClasspTimeDiffToMs(ULONGLONG TimeDiff)1297 ClasspTimeDiffToMs(
1298     ULONGLONG TimeDiff
1299     )
1300 {
1301     TimeDiff /= (10 * 1000);
1302 
1303     return TimeDiff;
1304 }
1305 
1306 FORCEINLINE
1307 BOOLEAN
ClasspSupportsUnmap(_In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo)1308 ClasspSupportsUnmap(
1309     _In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo
1310     )
1311 {
1312     return SupportInfo->LBProvisioningData.LBPU;
1313 }
1314 
1315 FORCEINLINE
1316 BOOLEAN
ClasspIsThinProvisioned(_In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo)1317 ClasspIsThinProvisioned(
1318     _In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo
1319     )
1320 {
1321     //
1322     // We only support thinly provisioned devices that also support UNMAP.
1323     //
1324     if (SupportInfo->LBProvisioningData.ProvisioningType == PROVISIONING_TYPE_THIN &&
1325         SupportInfo->LBProvisioningData.LBPU == TRUE)
1326     {
1327         return TRUE;
1328     }
1329 
1330     return FALSE;
1331 }
1332 
1333 FORCEINLINE
1334 BOOLEAN
ClasspIsObsoletePortDriver(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)1335 ClasspIsObsoletePortDriver(
1336     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1337     )
1338 {
1339     if ( (FdoExtension->MiniportDescriptor != NULL) &&
1340          (FdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetSCSIport) ) {
1341         return TRUE;
1342     }
1343 
1344     return FALSE;
1345 }
1346 
1347 
1348 ULONG
1349 ClasspCalculateLogicalSectorSize (
1350     _In_ PDEVICE_OBJECT Fdo,
1351     _In_ ULONG          BytesPerBlockInBigEndian
1352     );
1353 
1354 DRIVER_INITIALIZE DriverEntry;
1355 
1356 DRIVER_UNLOAD ClassUnload;
1357 
1358 _Dispatch_type_(IRP_MJ_CREATE)
1359 _Dispatch_type_(IRP_MJ_CLOSE)
1360 DRIVER_DISPATCH ClassCreateClose;
1361 
1362 NTSTATUS
1363 ClasspCreateClose(
1364     IN PDEVICE_OBJECT DeviceObject,
1365     IN PIRP Irp
1366     );
1367 
1368 VOID
1369 ClasspCleanupProtectedLocks(
1370     IN PFILE_OBJECT_EXTENSION FsContext
1371     );
1372 
1373 NTSTATUS
1374 ClasspEjectionControl(
1375     IN PDEVICE_OBJECT Fdo,
1376     IN PIRP Irp,
1377     IN MEDIA_LOCK_TYPE LockType,
1378     IN BOOLEAN Lock
1379     );
1380 
1381 _Dispatch_type_(IRP_MJ_READ)
1382 _Dispatch_type_(IRP_MJ_WRITE)
1383 DRIVER_DISPATCH ClassReadWrite;
1384 
1385 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
1386 DRIVER_DISPATCH ClassDeviceControlDispatch;
1387 
1388 _Dispatch_type_(IRP_MJ_PNP)
1389 DRIVER_DISPATCH ClassDispatchPnp;
1390 
1391 NTSTATUS
1392 ClassPnpStartDevice(
1393     IN PDEVICE_OBJECT DeviceObject
1394     );
1395 
1396 _Dispatch_type_(IRP_MJ_SHUTDOWN)
1397 _Dispatch_type_(IRP_MJ_FLUSH_BUFFERS)
1398 DRIVER_DISPATCH ClassShutdownFlush;
1399 
1400 _Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
1401 DRIVER_DISPATCH ClassSystemControl;
1402 
1403 
1404 //
1405 // Class internal routines
1406 //
1407 
1408 DRIVER_ADD_DEVICE ClassAddDevice;
1409 
1410 IO_COMPLETION_ROUTINE ClasspSendSynchronousCompletion;
1411 
1412 VOID
1413 RetryRequest(
1414     PDEVICE_OBJECT DeviceObject,
1415     PIRP Irp,
1416     PSCSI_REQUEST_BLOCK Srb,
1417     BOOLEAN Associated,
1418     LONGLONG TimeDelta100ns
1419     );
1420 
1421 NTSTATUS
1422 ClassIoCompletion(
1423     IN PDEVICE_OBJECT DeviceObject,
1424     IN PIRP Irp,
1425     IN PVOID Context
1426     );
1427 
1428 NTSTATUS
1429 ClassPnpQueryFdoRelations(
1430     IN PDEVICE_OBJECT Fdo,
1431     IN PIRP Irp
1432     );
1433 
1434 NTSTATUS
1435 ClassRetrieveDeviceRelations(
1436     IN PDEVICE_OBJECT Fdo,
1437     IN DEVICE_RELATION_TYPE RelationType,
1438     OUT PDEVICE_RELATIONS *DeviceRelations
1439     );
1440 
1441 NTSTATUS
1442 ClassGetPdoId(
1443     IN PDEVICE_OBJECT Pdo,
1444     IN BUS_QUERY_ID_TYPE IdType,
1445     IN PUNICODE_STRING IdString
1446     );
1447 
1448 NTSTATUS
1449 ClassQueryPnpCapabilities(
1450     IN PDEVICE_OBJECT PhysicalDeviceObject,
1451     IN PDEVICE_CAPABILITIES Capabilities
1452     );
1453 
1454 DRIVER_STARTIO ClasspStartIo;
1455 
1456 NTSTATUS
1457 ClasspPagingNotificationCompletion(
1458     IN PDEVICE_OBJECT DeviceObject,
1459     IN PIRP Irp,
1460     IN PDEVICE_OBJECT RealDeviceObject
1461     );
1462 
1463 NTSTATUS
1464 ClasspMediaChangeCompletion(
1465     PDEVICE_OBJECT DeviceObject,
1466     PIRP Irp,
1467     PVOID Context
1468     );
1469 
1470 NTSTATUS
1471 ClasspMcnControl(
1472     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1473     IN PIRP Irp,
1474     IN PSCSI_REQUEST_BLOCK Srb
1475     );
1476 
1477 VOID
1478 ClasspRegisterMountedDeviceInterface(
1479     IN PDEVICE_OBJECT DeviceObject
1480     );
1481 
1482 VOID
1483 ClasspDisableTimer(
1484     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1485     );
1486 
1487 VOID
1488 ClasspEnableTimer(
1489     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1490     );
1491 
1492 NTSTATUS
1493 ClasspInitializeTimer(
1494     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1495 );
1496 
1497 VOID
1498 ClasspDeleteTimer(
1499     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1500 );
1501 
1502 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
1503 BOOLEAN
1504 ClasspUpdateTimerNoWakeTolerance(
1505     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1506 );
1507 #endif
1508 
1509 NTSTATUS
1510 ClasspDuidQueryProperty(
1511     PDEVICE_OBJECT DeviceObject,
1512     PIRP Irp
1513     );
1514 
1515 _Dispatch_type_(IRP_MJ_CREATE)
1516 _Dispatch_type_(IRP_MJ_CLOSE)
1517 _Dispatch_type_(IRP_MJ_READ)
1518 _Dispatch_type_(IRP_MJ_WRITE)
1519 _Dispatch_type_(IRP_MJ_SCSI)
1520 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
1521 _Dispatch_type_(IRP_MJ_SHUTDOWN)
1522 _Dispatch_type_(IRP_MJ_FLUSH_BUFFERS)
1523 _Dispatch_type_(IRP_MJ_PNP)
1524 _Dispatch_type_(IRP_MJ_POWER)
1525 _Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
1526 DRIVER_DISPATCH ClassGlobalDispatch;
1527 
1528 VOID
1529 ClassInitializeDispatchTables(
1530     PCLASS_DRIVER_EXTENSION DriverExtension
1531     );
1532 
1533 NTSTATUS
1534 ClasspPersistentReserve(
1535     _In_ PDEVICE_OBJECT DeviceObject,
1536     _In_ PIRP Irp,
1537     _Inout_ PSCSI_REQUEST_BLOCK Srb
1538     );
1539 
1540 //
1541 // routines for dictionary list support
1542 //
1543 
1544 VOID
1545 InitializeDictionary(
1546     IN PDICTIONARY Dictionary
1547     );
1548 
1549 BOOLEAN
1550 TestDictionarySignature(
1551     IN PDICTIONARY Dictionary
1552     );
1553 
1554 NTSTATUS
1555 AllocateDictionaryEntry(
1556     IN PDICTIONARY Dictionary,
1557     IN ULONGLONG Key,
1558     IN ULONG Size,
1559     IN ULONG Tag,
1560     OUT PVOID *Entry
1561     );
1562 
1563 PVOID
1564 GetDictionaryEntry(
1565     IN PDICTIONARY Dictionary,
1566     IN ULONGLONG Key
1567     );
1568 
1569 VOID
1570 FreeDictionaryEntry(
1571     IN PDICTIONARY Dictionary,
1572     IN PVOID Entry
1573     );
1574 
1575 
1576 NTSTATUS
1577 ClasspAllocateReleaseRequest(
1578     IN PDEVICE_OBJECT Fdo
1579     );
1580 
1581 VOID
1582 ClasspFreeReleaseRequest(
1583     IN PDEVICE_OBJECT Fdo
1584     );
1585 
1586 IO_COMPLETION_ROUTINE ClassReleaseQueueCompletion;
1587 
1588 VOID
1589 ClasspReleaseQueue(
1590     IN PDEVICE_OBJECT DeviceObject,
1591     IN PIRP ReleaseQueueIrp
1592     );
1593 
1594 VOID
1595 ClasspDisablePowerNotification(
1596     PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1597 );
1598 
1599 //
1600 // class power routines
1601 //
1602 
1603 _Dispatch_type_(IRP_MJ_POWER)
1604 DRIVER_DISPATCH ClassDispatchPower;
1605 
1606 NTSTATUS
1607 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1608 ClassMinimalPowerHandler(
1609     IN PDEVICE_OBJECT DeviceObject,
1610     IN PIRP Irp
1611     );
1612 
1613 _IRQL_requires_same_
1614 NTSTATUS
1615 ClasspEnableIdlePower(
1616     _In_ PDEVICE_OBJECT DeviceObject
1617     );
1618 
1619 POWER_SETTING_CALLBACK ClasspPowerSettingCallback;
1620 
1621 //
1622 // Child list routines
1623 //
1624 
1625 VOID
1626 ClassAddChild(
1627     _In_ PFUNCTIONAL_DEVICE_EXTENSION Parent,
1628     _In_ PPHYSICAL_DEVICE_EXTENSION Child,
1629     _In_ BOOLEAN AcquireLock
1630     );
1631 
1632 PPHYSICAL_DEVICE_EXTENSION
1633 ClassRemoveChild(
1634     IN PFUNCTIONAL_DEVICE_EXTENSION Parent,
1635     IN PPHYSICAL_DEVICE_EXTENSION Child,
1636     IN BOOLEAN AcquireLock
1637     );
1638 
1639 VOID
1640 ClasspRetryDpcTimer(
1641     IN PCLASS_PRIVATE_FDO_DATA FdoData
1642     );
1643 
1644 KDEFERRED_ROUTINE ClasspRetryRequestDpc;
1645 
1646 VOID
1647 ClassFreeOrReuseSrb(
1648     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1649     IN __drv_freesMem(mem) PSCSI_REQUEST_BLOCK Srb
1650     );
1651 
1652 VOID
1653 ClassRetryRequest(
1654     IN PDEVICE_OBJECT SelfDeviceObject,
1655     IN PIRP           Irp,
1656     _In_ _In_range_(0,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) // this is 100 seconds; already an assert in classpnp based on this
1657     IN LONGLONG       TimeDelta100ns // in 100ns units
1658     );
1659 
1660 VOID
1661 ClasspBuildRequestEx(
1662     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1663     _In_ PIRP Irp,
1664     _In_ __drv_aliasesMem PSCSI_REQUEST_BLOCK Srb
1665     );
1666 
1667 NTSTATUS
1668 ClasspAllocateReleaseQueueIrp(
1669     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1670     );
1671 
1672 NTSTATUS
1673 ClasspAllocatePowerProcessIrp(
1674     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1675     );
1676 
1677 NTSTATUS
1678 ClasspInitializeGesn(
1679     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1680     IN PMEDIA_CHANGE_DETECTION_INFO Info
1681     );
1682 
1683 VOID
1684 ClassSendEjectionNotification(
1685     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1686     );
1687 
1688 VOID
1689 ClasspScanForSpecialInRegistry(
1690     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1691     );
1692 
1693 VOID
1694 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1695 ClasspScanForClassHacks(
1696     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1697     IN ULONG_PTR Data
1698     );
1699 
1700 NTSTATUS
1701 ClasspInitializeHotplugInfo(
1702     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1703     );
1704 
1705 VOID
1706 ClasspPerfIncrementErrorCount(
1707     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1708     );
1709 VOID
1710 ClasspPerfIncrementSuccessfulIo(
1711     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1712     );
1713 
1714 IO_WORKITEM_ROUTINE ClasspUpdateDiskProperties;
1715 
1716 __drv_allocatesMem(Mem)
1717 PTRANSFER_PACKET NewTransferPacket(PDEVICE_OBJECT Fdo);
1718 VOID DestroyTransferPacket(_In_ __drv_freesMem(mem) PTRANSFER_PACKET Pkt);
1719 VOID EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, __drv_aliasesMem PTRANSFER_PACKET Pkt);
1720 PTRANSFER_PACKET DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded);
1721 PTRANSFER_PACKET DequeueFreeTransferPacketEx(_In_ PDEVICE_OBJECT Fdo, _In_ BOOLEAN AllocIfNeeded, _In_ ULONG Node);
1722 VOID SetupReadWriteTransferPacket(PTRANSFER_PACKET pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp);
1723 NTSTATUS SubmitTransferPacket(PTRANSFER_PACKET Pkt);
1724 IO_COMPLETION_ROUTINE TransferPktComplete;
1725 NTSTATUS ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp, BOOLEAN PostToDpc);
1726 VOID TransferPacketQueueRetryDpc(PTRANSFER_PACKET Pkt);
1727 KDEFERRED_ROUTINE TransferPacketRetryTimerDpc;
1728 BOOLEAN InterpretTransferPacketError(PTRANSFER_PACKET Pkt);
1729 BOOLEAN RetryTransferPacket(PTRANSFER_PACKET Pkt);
1730 VOID EnqueueDeferredClientIrp(PDEVICE_OBJECT Fdo, PIRP Irp);
1731 PIRP DequeueDeferredClientIrp(PDEVICE_OBJECT Fdo);
1732 VOID InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation);
1733 BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt);
1734 VOID SetupEjectionTransferPacket(TRANSFER_PACKET *Pkt, BOOLEAN PreventMediaRemoval, PKEVENT SyncEventPtr, PIRP OriginalIrp);
1735 VOID SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, UCHAR SubPage, PIRP OriginalIrp, UCHAR PageControl);
1736 VOID SetupModeSelectTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSelectBuffer, UCHAR ModeSelectBufferLen, BOOLEAN SavePages, PIRP OriginalIrp);
1737 VOID SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp, BOOLEAN Use16ByteCdb);
1738 PMDL BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen);
1739 PMDL ClasspBuildDeviceMdl(PVOID Buffer, ULONG BufferLen, BOOLEAN WriteToDevice);
1740 VOID FreeDeviceInputMdl(PMDL Mdl);
1741 VOID ClasspFreeDeviceMdl(PMDL Mdl);
1742 NTSTATUS InitializeTransferPackets(PDEVICE_OBJECT Fdo);
1743 VOID DestroyAllTransferPackets(PDEVICE_OBJECT Fdo);
1744 VOID InterpretCapacityData(PDEVICE_OBJECT Fdo, PREAD_CAPACITY_DATA_EX ReadCapacityData);
1745 IO_WORKITEM_ROUTINE_EX CleanupTransferPacketToWorkingSetSizeWorker;
1746 VOID CleanupTransferPacketToWorkingSetSize(_In_ PDEVICE_OBJECT Fdo, _In_ BOOLEAN LimitNumPktToDelete, _In_ ULONG Node);
1747 
1748 _IRQL_requires_max_(APC_LEVEL)
1749 _IRQL_requires_min_(PASSIVE_LEVEL)
1750 _IRQL_requires_same_
1751 VOID
1752 ClasspSetupPopulateTokenTransferPacket(
1753     _In_ __drv_aliasesMem POFFLOAD_READ_CONTEXT OffloadReadContext,
1754     _In_ PTRANSFER_PACKET Pkt,
1755     _In_ ULONG Length,
1756     _In_reads_bytes_(Length) PUCHAR PopulateTokenBuffer,
1757     _In_ PIRP OriginalIrp,
1758     _In_ ULONG ListIdentifier
1759     );
1760 
1761 _IRQL_requires_max_(APC_LEVEL)
1762 _IRQL_requires_min_(PASSIVE_LEVEL)
1763 _IRQL_requires_same_
1764 VOID
1765 ClasspSetupReceivePopulateTokenInformationTransferPacket(
1766     _In_ POFFLOAD_READ_CONTEXT OffloadReadContext,
1767     _In_ PTRANSFER_PACKET Pkt,
1768     _In_ ULONG Length,
1769     _In_reads_bytes_(Length) PUCHAR ReceivePopulateTokenInformationBuffer,
1770     _In_ PIRP OriginalIrp,
1771     _In_ ULONG ListIdentifier
1772     );
1773 
1774 _IRQL_requires_max_(APC_LEVEL)
1775 _IRQL_requires_min_(PASSIVE_LEVEL)
1776 _IRQL_requires_same_
1777 VOID
1778 ClasspSetupWriteUsingTokenTransferPacket(
1779     _In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
1780     _In_ PTRANSFER_PACKET Pkt,
1781     _In_ ULONG Length,
1782     _In_reads_bytes_(Length) PUCHAR WriteUsingTokenBuffer,
1783     _In_ PIRP OriginalIrp,
1784     _In_ ULONG ListIdentifier
1785     );
1786 
1787 _IRQL_requires_max_(APC_LEVEL)
1788 _IRQL_requires_min_(PASSIVE_LEVEL)
1789 _IRQL_requires_same_
1790 VOID
1791 ClasspSetupReceiveWriteUsingTokenInformationTransferPacket(
1792     _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
1793     _In_ PTRANSFER_PACKET Pkt,
1794     _In_ ULONG Length,
1795     _In_reads_bytes_(Length) PUCHAR ReceiveWriteUsingTokenInformationBuffer,
1796     _In_ PIRP OriginalIrp,
1797     _In_ ULONG ListIdentifier
1798     );
1799 
1800 ULONG ClasspModeSense(
1801     _In_ PDEVICE_OBJECT Fdo,
1802     _In_reads_bytes_(Length) PCHAR ModeSenseBuffer,
1803     _In_ ULONG Length,
1804     _In_ UCHAR PageMode,
1805     _In_ UCHAR PageControl
1806     );
1807 
1808 NTSTATUS
1809 ClasspModeSelect(
1810     _In_ PDEVICE_OBJECT Fdo,
1811     _In_reads_bytes_(Length) PCHAR ModeSelectBuffer,
1812     _In_ ULONG Length,
1813     _In_ BOOLEAN SavePages
1814     );
1815 
1816 NTSTATUS ClasspWriteCacheProperty(
1817     _In_ PDEVICE_OBJECT DeviceObject,
1818     _In_ PIRP Irp,
1819     _Inout_ PSCSI_REQUEST_BLOCK Srb
1820     );
1821 
1822 NTSTATUS ClasspAccessAlignmentProperty(
1823     _In_ PDEVICE_OBJECT DeviceObject,
1824     _In_ PIRP Irp,
1825     _Inout_ PSCSI_REQUEST_BLOCK Srb
1826     );
1827 
1828 NTSTATUS ClasspDeviceSeekPenaltyProperty(
1829     _In_ PDEVICE_OBJECT DeviceObject,
1830     _In_ PIRP Irp,
1831     _Inout_ PSCSI_REQUEST_BLOCK Srb
1832     );
1833 
1834 NTSTATUS ClasspDeviceGetLBProvisioningVPDPage(
1835     _In_ PDEVICE_OBJECT DeviceObject,
1836     _Inout_opt_ PSCSI_REQUEST_BLOCK Srb
1837     );
1838 
1839 NTSTATUS ClasspDeviceGetBlockDeviceCharacteristicsVPDPage(
1840     _In_ PFUNCTIONAL_DEVICE_EXTENSION fdoExtension,
1841     _In_ PSCSI_REQUEST_BLOCK Srb
1842     );
1843 
1844 NTSTATUS ClasspDeviceGetBlockLimitsVPDPage(
1845     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1846     _Inout_bytecount_(SrbSize) PSCSI_REQUEST_BLOCK Srb,
1847     _In_ ULONG SrbSize,
1848     _Out_ PCLASS_VPD_B0_DATA BlockLimitsData
1849     );
1850 
1851 NTSTATUS ClasspDeviceTrimProperty(
1852     _In_ PDEVICE_OBJECT DeviceObject,
1853     _In_ PIRP Irp,
1854     _Inout_ PSCSI_REQUEST_BLOCK Srb
1855     );
1856 
1857 NTSTATUS ClasspDeviceLBProvisioningProperty(
1858     _In_ PDEVICE_OBJECT DeviceObject,
1859     _Inout_ PIRP Irp,
1860     _Inout_ PSCSI_REQUEST_BLOCK Srb
1861     );
1862 
1863 NTSTATUS ClasspDeviceTrimProcess(
1864     _In_ PDEVICE_OBJECT DeviceObject,
1865     _In_ PIRP Irp,
1866     _In_ PGUID ActivityId,
1867     _Inout_ PSCSI_REQUEST_BLOCK Srb
1868     );
1869 
1870 NTSTATUS ClasspDeviceGetLBAStatus(
1871     _In_ PDEVICE_OBJECT DeviceObject,
1872     _Inout_ PIRP Irp,
1873     _Inout_ PSCSI_REQUEST_BLOCK Srb
1874     );
1875 
1876 NTSTATUS ClasspDeviceGetLBAStatusWorker(
1877     _In_ PDEVICE_OBJECT DeviceObject,
1878     _In_ PCLASS_VPD_B0_DATA BlockLimitsData,
1879     _In_ ULONGLONG StartingOffset,
1880     _In_ ULONGLONG LengthInBytes,
1881     _Out_ PDEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT DsmOutput,
1882     _Inout_ PULONG DsmOutputLength,
1883     _Inout_ PSCSI_REQUEST_BLOCK Srb,
1884     _In_ BOOLEAN ConsolidateableBlocksOnly,
1885     _In_ ULONG OutputVersion,
1886     _Out_ PBOOLEAN BlockLimitsDataMayHaveChanged
1887     );
1888 
1889 VOID ClassQueueThresholdEventWorker(
1890     _In_ PDEVICE_OBJECT DeviceObject
1891     );
1892 
1893 VOID ClassQueueResourceExhaustionEventWorker(
1894     _In_ PDEVICE_OBJECT DeviceObject
1895     );
1896 
1897 VOID ClassQueueCapacityChangedEventWorker(
1898     _In_ PDEVICE_OBJECT DeviceObject
1899     );
1900 
1901 VOID ClassQueueProvisioningTypeChangedEventWorker(
1902     _In_ PDEVICE_OBJECT DeviceObject
1903     );
1904 
1905 IO_WORKITEM_ROUTINE ClasspLogIOEventWithContext;
1906 
1907 VOID
1908 ClasspQueueLogIOEventWithContextWorker(
1909     _In_ PDEVICE_OBJECT DeviceObject,
1910     _In_ ULONG SenseBufferSize,
1911     _In_ PVOID SenseData,
1912     _In_ UCHAR SrbStatus,
1913     _In_ UCHAR ScsiStatus,
1914     _In_ ULONG ErrorCode,
1915     _In_ ULONG CdbLength,
1916     _In_opt_ PCDB Cdb,
1917     _In_opt_ PTRANSFER_PACKET Pkt
1918     );
1919 
1920 VOID
1921 ClasspZeroQERR(
1922     _In_ PDEVICE_OBJECT DeviceObject
1923     );
1924 
1925 
1926 _IRQL_requires_max_(PASSIVE_LEVEL)
1927 NTSTATUS
1928 ClasspGetMaximumTokenListIdentifier(
1929     _In_ PDEVICE_OBJECT DeviceObject,
1930     _In_z_ PWSTR RegistryPath,
1931     _Out_ PULONG MaximumListIdentifier
1932     );
1933 
1934 _IRQL_requires_max_(PASSIVE_LEVEL)
1935 NTSTATUS
1936 ClasspGetCopyOffloadMaxDuration(
1937     _In_ PDEVICE_OBJECT DeviceObject,
1938     _In_z_ PWSTR RegistryPath,
1939     _Out_ PULONG MaxDuration
1940     );
1941 
1942 _IRQL_requires_max_(APC_LEVEL)
1943 _IRQL_requires_min_(PASSIVE_LEVEL)
1944 _IRQL_requires_same_
1945 NTSTATUS
1946 ClasspDeviceCopyOffloadProperty(
1947     _In_ PDEVICE_OBJECT DeviceObject,
1948     _Inout_ PIRP Irp,
1949     _Inout_ PSCSI_REQUEST_BLOCK Srb
1950     );
1951 
1952 _IRQL_requires_max_(APC_LEVEL)
1953 _IRQL_requires_min_(PASSIVE_LEVEL)
1954 _IRQL_requires_same_
1955 NTSTATUS
1956 ClasspValidateOffloadSupported(
1957     _In_ PDEVICE_OBJECT DeviceObject,
1958     _In_ PIRP Irp
1959     );
1960 
1961 _IRQL_requires_max_(APC_LEVEL)
1962 _IRQL_requires_min_(PASSIVE_LEVEL)
1963 _IRQL_requires_same_
1964 NTSTATUS
1965 ClasspValidateOffloadInputParameters(
1966     _In_ PDEVICE_OBJECT DeviceObject,
1967     _In_ PIRP Irp
1968     );
1969 
1970 _IRQL_requires_same_
1971 NTSTATUS
1972 ClasspGetTokenOperationCommandBufferLength(
1973     _In_ PDEVICE_OBJECT Fdo,
1974     _In_ ULONG ServiceAction,
1975     _Inout_ PULONG CommandBufferLength,
1976     _Out_opt_ PULONG TokenOperationBufferLength,
1977     _Out_opt_ PULONG ReceiveTokenInformationBufferLength
1978     );
1979 
1980 _IRQL_requires_same_
1981 NTSTATUS
1982 ClasspGetTokenOperationDescriptorLimits(
1983     _In_ PDEVICE_OBJECT Fdo,
1984     _In_ ULONG ServiceAction,
1985     _In_ ULONG MaxParameterBufferLength,
1986     _Out_ PULONG MaxBlockDescriptorsCount,
1987     _Out_ PULONGLONG MaxBlockDescriptorsLength
1988     );
1989 
1990 _IRQL_requires_max_(APC_LEVEL)
1991 _IRQL_requires_min_(PASSIVE_LEVEL)
1992 _IRQL_requires_same_
1993 VOID
1994 ClasspConvertDataSetRangeToBlockDescr(
1995     _In_    PDEVICE_OBJECT Fdo,
1996     _In_    PVOID BlockDescr,
1997     _Inout_ PULONG CurrentBlockDescrIndex,
1998     _In_    ULONG MaxBlockDescrCount,
1999     _Inout_ PULONG CurrentLbaCount,
2000     _In_    ULONGLONG MaxLbaCount,
2001     _Inout_ PDEVICE_DATA_SET_RANGE DataSetRange,
2002     _Inout_ PULONGLONG TotalSectorsProcessed
2003     );
2004 
2005 NTSTATUS
2006 ClasspDeviceMediaTypeProperty(
2007     _In_ PDEVICE_OBJECT DeviceObject,
2008     _Inout_ PIRP Irp,
2009     _Inout_ PSCSI_REQUEST_BLOCK Srb
2010     );
2011 
2012 
2013 _IRQL_requires_same_
2014 PUCHAR
2015 ClasspBinaryToAscii(
2016     _In_reads_(Length) PUCHAR HexBuffer,
2017     _In_ ULONG Length,
2018     _Inout_ PULONG UpdateLength
2019     );
2020 
2021 FORCEINLINE
2022 BOOLEAN
ClasspIsTokenOperationComplete(_In_ ULONG CurrentStatus)2023 ClasspIsTokenOperationComplete(
2024     _In_ ULONG CurrentStatus
2025     )
2026 {
2027     BOOLEAN operationCompleted = FALSE;
2028 
2029     switch (CurrentStatus) {
2030         case OPERATION_COMPLETED_WITH_SUCCESS:
2031         case OPERATION_COMPLETED_WITH_ERROR:
2032         case OPERATION_COMPLETED_WITH_RESIDUAL_DATA:
2033         case OPERATION_TERMINATED: {
2034 
2035             operationCompleted = TRUE;
2036         }
2037     }
2038 
2039     return operationCompleted;
2040 }
2041 
2042 FORCEINLINE
2043 BOOLEAN
ClasspIsTokenOperation(_In_ PCDB Cdb)2044 ClasspIsTokenOperation(
2045     _In_ PCDB Cdb
2046     )
2047 {
2048     BOOLEAN tokenOperation = FALSE;
2049 
2050     if (Cdb) {
2051         ULONG opCode = Cdb->AsByte[0];
2052         ULONG serviceAction = Cdb->AsByte[1];
2053 
2054         if ((opCode == SCSIOP_POPULATE_TOKEN && serviceAction == SERVICE_ACTION_POPULATE_TOKEN) ||
2055             (opCode == SCSIOP_WRITE_USING_TOKEN && serviceAction == SERVICE_ACTION_WRITE_USING_TOKEN)) {
2056 
2057             tokenOperation = TRUE;
2058         }
2059     }
2060 
2061     return tokenOperation;
2062 }
2063 
2064 FORCEINLINE
2065 BOOLEAN
ClasspIsReceiveTokenInformation(_In_ PCDB Cdb)2066 ClasspIsReceiveTokenInformation(
2067     _In_ PCDB Cdb
2068     )
2069 {
2070     BOOLEAN receiveTokenInformation = FALSE;
2071 
2072     if (Cdb) {
2073         ULONG opCode = Cdb->AsByte[0];
2074         ULONG serviceAction = Cdb->AsByte[1];
2075 
2076         if (opCode == SCSIOP_RECEIVE_ROD_TOKEN_INFORMATION && serviceAction == SERVICE_ACTION_RECEIVE_TOKEN_INFORMATION) {
2077 
2078             receiveTokenInformation = TRUE;
2079         }
2080     }
2081 
2082     return receiveTokenInformation;
2083 }
2084 
2085 FORCEINLINE
2086 BOOLEAN
ClasspIsOffloadDataTransferCommand(_In_ PCDB Cdb)2087 ClasspIsOffloadDataTransferCommand(
2088     _In_ PCDB Cdb
2089     )
2090 {
2091     BOOLEAN offloadCommand = (ClasspIsTokenOperation(Cdb) || ClasspIsReceiveTokenInformation(Cdb)) ? TRUE : FALSE;
2092 
2093     return offloadCommand;
2094 }
2095 
2096 extern LIST_ENTRY AllFdosList;
2097 
2098 
2099 VOID
2100 ClasspInitializeIdleTimer(
2101     PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
2102     );
2103 
2104 NTSTATUS
2105 ClasspIsPortable(
2106     _In_ PFUNCTIONAL_DEVICE_EXTENSION   FdoExtension,
2107     _Out_ PBOOLEAN                      IsPortable
2108     );
2109 
2110 VOID
2111 ClasspGetInquiryVpdSupportInfo(
2112     _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
2113     );
2114 
2115 NTSTATUS
2116 ClasspGetLBProvisioningInfo(
2117     _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
2118     );
2119 
2120 
2121 _IRQL_requires_(PASSIVE_LEVEL)
2122 _IRQL_requires_same_
2123 NTSTATUS
2124 ClassDetermineTokenOperationCommandSupport(
2125     _In_ PDEVICE_OBJECT DeviceObject
2126     );
2127 
2128 _IRQL_requires_same_
2129 NTSTATUS
2130 ClasspGetBlockDeviceTokenLimitsInfo(
2131     _Inout_ PDEVICE_OBJECT DeviceObject
2132     );
2133 
2134 _IRQL_requires_max_(APC_LEVEL)
2135 _IRQL_requires_min_(PASSIVE_LEVEL)
2136 _IRQL_requires_same_
2137 NTSTATUS
2138 ClassDeviceProcessOffloadRead(
2139     _In_ PDEVICE_OBJECT DeviceObject,
2140     _In_ PIRP Irp,
2141     _Inout_ PSCSI_REQUEST_BLOCK Srb
2142     );
2143 
2144 _IRQL_requires_max_(APC_LEVEL)
2145 _IRQL_requires_min_(PASSIVE_LEVEL)
2146 _IRQL_requires_same_
2147 NTSTATUS
2148 ClassDeviceProcessOffloadWrite(
2149     _In_ PDEVICE_OBJECT DeviceObject,
2150     _In_ PIRP Irp,
2151     _Inout_ PSCSI_REQUEST_BLOCK Srb
2152     );
2153 
2154 _IRQL_requires_max_(APC_LEVEL)
2155 _IRQL_requires_min_(PASSIVE_LEVEL)
2156 _IRQL_requires_same_
2157 NTSTATUS
2158 ClasspServicePopulateTokenTransferRequest(
2159     _In_ PDEVICE_OBJECT Fdo,
2160     _In_ PIRP Irp
2161     );
2162 
2163 _IRQL_requires_same_
2164 VOID
2165 ClasspReceivePopulateTokenInformation(
2166     _In_ POFFLOAD_READ_CONTEXT OffloadReadContext
2167     );
2168 
2169 _IRQL_requires_max_(APC_LEVEL)
2170 _IRQL_requires_min_(PASSIVE_LEVEL)
2171 _IRQL_requires_same_
2172 NTSTATUS
2173 ClasspServiceWriteUsingTokenTransferRequest(
2174     _In_ PDEVICE_OBJECT Fdo,
2175     _In_ PIRP Irp
2176     );
2177 
2178 _IRQL_requires_same_
2179 VOID
2180 ClasspReceiveWriteUsingTokenInformation(
2181     _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext
2182     );
2183 
2184 VOID
2185 ClasspCompleteOffloadRequest(
2186     _In_ PDEVICE_OBJECT DeviceObject,
2187     _In_ PIRP Irp,
2188     _In_ NTSTATUS CompletionStatus
2189     );
2190 
2191 VOID
2192 ClasspCleanupOffloadReadContext(
2193     _In_ __drv_freesMem(mem) POFFLOAD_READ_CONTEXT OffloadReadContext
2194     );
2195 
2196 VOID
2197 ClasspCompleteOffloadRead(
2198     _In_ POFFLOAD_READ_CONTEXT OffloadReadContext,
2199     _In_ NTSTATUS CompletionStatus
2200     );
2201 
2202 // PCONTINUATION_ROUTINE
2203 VOID
2204 ClasspPopulateTokenTransferPacketDone(
2205     _In_ PVOID Context
2206     );
2207 
2208 // PCONTINUATION_ROUTINE
2209 VOID
2210 ClasspReceivePopulateTokenInformationTransferPacketDone(
2211     _In_ PVOID Context
2212     );
2213 
2214 VOID
2215 ClasspContinueOffloadWrite(
2216     _In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT OffloadWriteContext
2217     );
2218 
2219 VOID
2220 ClasspCleanupOffloadWriteContext(
2221     _In_ __drv_freesMem(mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext
2222     );
2223 
2224 VOID
2225 ClasspCompleteOffloadWrite(
2226     _In_ __drv_freesMem(Mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
2227     _In_ NTSTATUS CompletionCausingStatus
2228     );
2229 
2230 VOID
2231 ClasspReceiveWriteUsingTokenInformationDone(
2232     _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
2233     _In_ NTSTATUS CompletionCausingStatus
2234     );
2235 
2236 VOID
2237 ClasspWriteUsingTokenTransferPacketDone(
2238     _In_ PVOID Context
2239     );
2240 
2241 VOID
2242 ClasspReceiveWriteUsingTokenInformationTransferPacketDone(
2243     _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext
2244     );
2245 
2246 NTSTATUS
2247 ClasspRefreshFunctionSupportInfo(
2248     _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2249     _In_ BOOLEAN ForceQuery
2250     );
2251 
2252 NTSTATUS
2253 ClasspBlockLimitsDataSnapshot(
2254     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2255     _In_ BOOLEAN ForceQuery,
2256     _Out_ PCLASS_VPD_B0_DATA BlockLimitsData,
2257     _Out_ PULONG GenerationCount
2258     );
2259 
2260 NTSTATUS
2261 InterpretReadCapacity16Data (
2262     _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2263     _In_ PREAD_CAPACITY16_DATA ReadCapacity16Data
2264     );
2265 
2266 NTSTATUS
2267 ClassReadCapacity16 (
2268     _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2269     _Inout_ PSCSI_REQUEST_BLOCK Srb
2270     );
2271 
2272 NTSTATUS
2273 ClassDeviceGetLBProvisioningResources(
2274     _In_ PDEVICE_OBJECT DeviceObject,
2275     _Inout_ PIRP Irp,
2276     _Inout_ PSCSI_REQUEST_BLOCK Srb
2277     );
2278 
2279 _IRQL_requires_same_
2280 NTSTATUS
2281 ClasspStorageEventNotification(
2282     _In_ PDEVICE_OBJECT DeviceObject,
2283     _In_ PIRP Irp
2284     );
2285 
2286 _IRQL_requires_max_(PASSIVE_LEVEL)
2287 NTSTATUS
2288 ClasspPowerActivateDevice(
2289     _In_ PDEVICE_OBJECT DeviceObject
2290     );
2291 
2292 _IRQL_requires_max_(PASSIVE_LEVEL)
2293 NTSTATUS
2294 ClasspPowerIdleDevice(
2295     _In_ PDEVICE_OBJECT DeviceObject
2296     );
2297 
2298 IO_WORKITEM_ROUTINE ClassLogThresholdEvent;
2299 
2300 NTSTATUS
2301 ClasspLogSystemEventWithDeviceNumber(
2302     _In_ PDEVICE_OBJECT DeviceObject,
2303     _In_ NTSTATUS IoErrorCode
2304     );
2305 
2306 IO_WORKITEM_ROUTINE ClassLogResourceExhaustionEvent;
2307 
2308 NTSTATUS
2309 ClasspEnqueueIdleRequest(
2310     PDEVICE_OBJECT DeviceObject,
2311     PIRP Irp
2312     );
2313 
2314 VOID
2315 ClasspCompleteIdleRequest(
2316     PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
2317     );
2318 
2319 NTSTATUS
2320 ClasspPriorityHint(
2321     PDEVICE_OBJECT DeviceObject,
2322     PIRP Irp
2323     );
2324 
2325 VOID
2326 HistoryInitializeRetryLogs(
2327     _Out_ PSRB_HISTORY History,
2328     ULONG HistoryCount
2329     );
2330 #define HISTORYINITIALIZERETRYLOGS(_packet)               \
2331     {                                                     \
2332         if (_packet->RetryHistory != NULL)                \
2333         {                                                 \
2334             HistoryInitializeRetryLogs(                   \
2335                 _packet->RetryHistory,                    \
2336                 _packet->RetryHistory->TotalHistoryCount  \
2337                 );                                        \
2338         }                                                 \
2339     }
2340 
2341 VOID
2342 HistoryLogSendPacket(
2343     TRANSFER_PACKET *Pkt
2344     );
2345 #define HISTORYLOGSENDPACKET(_packet)        \
2346     {                                        \
2347         if (_packet->RetryHistory != NULL) { \
2348             HistoryLogSendPacket(_packet);   \
2349         }                                    \
2350     }
2351 
2352 VOID
2353 HistoryLogReturnedPacket(
2354     TRANSFER_PACKET *Pkt
2355     );
2356 
2357 #define HISTORYLOGRETURNEDPACKET(_packet)      \
2358     {                                          \
2359         if (_packet->RetryHistory != NULL) {   \
2360             HistoryLogReturnedPacket(_packet); \
2361         }                                      \
2362     }
2363 
2364 BOOLEAN
2365 InterpretSenseInfoWithoutHistory(
2366     _In_  PDEVICE_OBJECT Fdo,
2367     _In_opt_  PIRP OriginalRequest,
2368     _In_  PSCSI_REQUEST_BLOCK Srb,
2369           UCHAR MajorFunctionCode,
2370           ULONG IoDeviceCode,
2371           ULONG PreviousRetryCount,
2372     _Out_ NTSTATUS * Status,
2373     _Out_opt_ _Deref_out_range_(0,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
2374           LONGLONG * RetryIn100nsUnits
2375     );
2376 
2377 BOOLEAN
2378 ClasspMyStringMatches(
2379     _In_opt_z_ PCHAR StringToMatch,
2380     _In_z_ PCHAR TargetString
2381     );
2382 
2383 
2384 
2385 #define TRACKING_FORWARD_PROGRESS_PATH1                  (0x00000001)
2386 #define TRACKING_FORWARD_PROGRESS_PATH2                  (0x00000002)
2387 #define TRACKING_FORWARD_PROGRESS_PATH3                  (0x00000004)
2388 
2389 
2390 VOID
2391 ClasspInitializeRemoveTracking(
2392     _In_ PDEVICE_OBJECT DeviceObject
2393     );
2394 
2395 VOID
2396 ClasspUninitializeRemoveTracking(
2397     _In_ PDEVICE_OBJECT DeviceObject
2398     );
2399 
2400 RTL_GENERIC_COMPARE_ROUTINE RemoveTrackingCompareRoutine;
2401 
2402 RTL_GENERIC_ALLOCATE_ROUTINE RemoveTrackingAllocateRoutine;
2403 
2404 RTL_GENERIC_FREE_ROUTINE RemoveTrackingFreeRoutine;
2405 
2406 #if (NTDDI_VERSION >= NTDDI_WIN8)
2407 
2408 typedef PVOID
2409 (*PSRB_ALLOCATE_ROUTINE) (
2410     _In_ CLONG  ByteSize
2411     );
2412 
2413 PVOID
2414 DefaultStorageRequestBlockAllocateRoutine(
2415     _In_ CLONG ByteSize
2416     );
2417 
2418 
2419 NTSTATUS
2420 CreateStorageRequestBlock(
2421     _Inout_ PSTORAGE_REQUEST_BLOCK *Srb,
2422     _In_ USHORT AddressType,
2423     _In_opt_ PSRB_ALLOCATE_ROUTINE AllocateRoutine,
2424     _Inout_opt_ ULONG *ByteSize,
2425     _In_ ULONG NumSrbExData,
2426     ...
2427     );
2428 
2429 NTSTATUS
2430 InitializeStorageRequestBlock(
2431     _Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb,
2432     _In_ USHORT AddressType,
2433     _In_ ULONG ByteSize,
2434     _In_ ULONG NumSrbExData,
2435     ...
2436     );
2437 
2438 VOID
2439 ClasspConvertToScsiRequestBlock(
2440     _Out_ PSCSI_REQUEST_BLOCK Srb,
2441     _In_ PSTORAGE_REQUEST_BLOCK SrbEx
2442     );
2443 
2444 FORCEINLINE PCDB
ClasspTransferPacketGetCdb(_In_ PTRANSFER_PACKET Pkt)2445 ClasspTransferPacketGetCdb(
2446     _In_ PTRANSFER_PACKET Pkt
2447     )
2448 {
2449     return SrbGetCdb(Pkt->Srb);
2450 }
2451 
2452 //
2453 // This inline function calculates number of retries already happened till now for known operation codes
2454 // and set the out parameter - TimesAlreadyRetried with the value,  returns True
2455 //
2456 // For unknown operation codes this function will return false and will set TimesAlreadyRetried with zero
2457 //
2458 FORCEINLINE BOOLEAN
ClasspTransferPacketGetNumberOfRetriesDone(_In_ PTRANSFER_PACKET Pkt,_In_ PCDB Cdb,_Out_ PULONG TimesAlreadyRetried)2459 ClasspTransferPacketGetNumberOfRetriesDone(
2460     _In_ PTRANSFER_PACKET Pkt,
2461     _In_ PCDB Cdb,
2462     _Out_ PULONG TimesAlreadyRetried
2463     )
2464 {
2465     PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Pkt->Fdo->DeviceExtension;
2466     PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
2467 
2468     if (Cdb->MEDIA_REMOVAL.OperationCode == SCSIOP_MEDIUM_REMOVAL)
2469     {
2470         *TimesAlreadyRetried = NUM_LOCKMEDIAREMOVAL_RETRIES - Pkt->NumRetries;
2471     }
2472     else if ((Cdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE) ||
2473                (Cdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE10))
2474     {
2475         *TimesAlreadyRetried = NUM_MODESENSE_RETRIES - Pkt->NumRetries;
2476     }
2477     else if ((Cdb->CDB10.OperationCode == SCSIOP_READ_CAPACITY) ||
2478                (Cdb->CDB16.OperationCode == SCSIOP_READ_CAPACITY16))
2479     {
2480         *TimesAlreadyRetried = NUM_DRIVECAPACITY_RETRIES - Pkt->NumRetries;
2481     }
2482     else if (IS_SCSIOP_READWRITE(Cdb->CDB10.OperationCode))
2483     {
2484         *TimesAlreadyRetried = fdoData->MaxNumberOfIoRetries - Pkt->NumRetries;
2485     }
2486     else if (Cdb->TOKEN_OPERATION.OperationCode == SCSIOP_POPULATE_TOKEN &&
2487                Cdb->TOKEN_OPERATION.ServiceAction == SERVICE_ACTION_POPULATE_TOKEN)
2488     {
2489         *TimesAlreadyRetried = NUM_POPULATE_TOKEN_RETRIES - Pkt->NumRetries;
2490     }
2491     else if (Cdb->TOKEN_OPERATION.OperationCode == SCSIOP_WRITE_USING_TOKEN &&
2492                Cdb->TOKEN_OPERATION.ServiceAction == SERVICE_ACTION_WRITE_USING_TOKEN)
2493     {
2494         *TimesAlreadyRetried = NUM_WRITE_USING_TOKEN_RETRIES - Pkt->NumRetries;
2495     }
2496     else if (ClasspIsReceiveTokenInformation(Cdb))
2497     {
2498         *TimesAlreadyRetried = NUM_RECEIVE_TOKEN_INFORMATION_RETRIES - Pkt->NumRetries;
2499     }
2500 
2501     else
2502     {
2503         *TimesAlreadyRetried = 0;
2504         return FALSE;
2505     }
2506 
2507 
2508     return TRUE;
2509 }
2510 
2511 
2512 FORCEINLINE PVOID
ClasspTransferPacketGetSenseInfoBuffer(_In_ PTRANSFER_PACKET Pkt)2513 ClasspTransferPacketGetSenseInfoBuffer(
2514     _In_ PTRANSFER_PACKET Pkt
2515     )
2516 {
2517     return SrbGetSenseInfoBuffer(Pkt->Srb);
2518 }
2519 
2520 FORCEINLINE UCHAR
ClasspTransferPacketGetSenseInfoBufferLength(_In_ PTRANSFER_PACKET Pkt)2521 ClasspTransferPacketGetSenseInfoBufferLength(
2522     _In_ PTRANSFER_PACKET Pkt
2523     )
2524 {
2525     return SrbGetSenseInfoBufferLength(Pkt->Srb);
2526 }
2527 
2528 
2529 FORCEINLINE VOID
ClasspSrbSetOriginalIrp(_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb,_In_ PIRP Irp)2530 ClasspSrbSetOriginalIrp(
2531     _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb,
2532     _In_ PIRP Irp
2533     )
2534 {
2535     if (Srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK)
2536     {
2537         ((PSTORAGE_REQUEST_BLOCK)Srb)->MiniportContext = (PVOID)Irp;
2538     }
2539     else
2540     {
2541         ((PSCSI_REQUEST_BLOCK)Srb)->SrbExtension = (PVOID)Irp;
2542     }
2543 }
2544 
2545 FORCEINLINE
2546 BOOLEAN
PORT_ALLOCATED_SENSE_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)2547 PORT_ALLOCATED_SENSE_EX(
2548     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2549     _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb
2550     )
2551 {
2552     return ((BOOLEAN)((TEST_FLAG(SrbGetSrbFlags(Srb), SRB_FLAGS_PORT_DRIVER_ALLOCSENSE) &&
2553              TEST_FLAG(SrbGetSrbFlags(Srb), SRB_FLAGS_FREE_SENSE_BUFFER)) &&
2554             (SrbGetSenseInfoBuffer(Srb) != FdoExtension->SenseData))
2555             );
2556 }
2557 
2558 FORCEINLINE
2559 VOID
FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)2560 FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(
2561     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2562     _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb
2563     )
2564 {
2565     NT_ASSERT(TEST_FLAG(SrbGetSrbFlags(Srb), SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
2566     NT_ASSERT(TEST_FLAG(SrbGetSrbFlags(Srb), SRB_FLAGS_FREE_SENSE_BUFFER));
2567     NT_ASSERT(SrbGetSenseInfoBuffer(Srb) != FdoExtension->SenseData);
2568 
2569     ExFreePool(SrbGetSenseInfoBuffer(Srb));
2570     SrbSetSenseInfoBuffer(Srb, FdoExtension->SenseData);
2571     SrbSetSenseInfoBufferLength(Srb, GET_FDO_EXTENSON_SENSE_DATA_LENGTH(FdoExtension));
2572     SrbClearSrbFlags(Srb, SRB_FLAGS_FREE_SENSE_BUFFER);
2573     return;
2574 }
2575 
2576 #endif //NTDDI_WIN8
2577 
2578 BOOLEAN
2579 ClasspFailurePredictionPeriodMissed(
2580     _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
2581     );
2582 
2583 FORCEINLINE
2584 ULONG
ClasspGetMaxUsableBufferLengthFromOffset(_In_ PVOID BaseAddress,_In_ ULONG OffsetInBytes,_In_ ULONG BaseStructureSizeInBytes)2585 ClasspGetMaxUsableBufferLengthFromOffset(
2586     _In_ PVOID BaseAddress,
2587     _In_ ULONG OffsetInBytes,
2588     _In_ ULONG BaseStructureSizeInBytes
2589     )
2590 /*++
2591 
2592 Routine Description:
2593 
2594     This routine returns the maximum size of a buffer that starts at a given offset,
2595     based on the size of the containing structure.
2596 
2597 Arguments:
2598 
2599     BaseAddress - The base address of the structure. The offset is computed relative to this.
2600 
2601     OffsetInBytes - (BaseAddress + OffsetInBytes) points to the beginning of the buffer.
2602 
2603     BaseStructureSizeInBytes - The size of the structure which contains the buffer.
2604 
2605 Return Value:
2606 
2607     max(BaseStructureSizeInBytes - OffsetInBytes, 0). If any operations wrap around,
2608     the return value is 0.
2609 
2610 --*/
2611 
2612 {
2613 
2614     ULONG_PTR offsetAddress = ((ULONG_PTR)BaseAddress + OffsetInBytes);
2615 
2616     if (offsetAddress < (ULONG_PTR)BaseAddress) {
2617         //
2618         // This means BaseAddress + OffsetInBytes > ULONG_PTR_MAX.
2619         //
2620         return 0;
2621     }
2622 
2623     if (OffsetInBytes > BaseStructureSizeInBytes) {
2624         return 0;
2625     }
2626 
2627     return BaseStructureSizeInBytes - OffsetInBytes;
2628 }
2629 
2630 
2631 BOOLEAN
2632 ClasspIsThinProvisioningError (
2633     _In_ PSCSI_REQUEST_BLOCK _Srb
2634     );
2635 
2636 FORCEINLINE
2637 BOOLEAN
ClasspLowerLayerNotSupport(_In_ NTSTATUS Status)2638 ClasspLowerLayerNotSupport (
2639     _In_ NTSTATUS Status
2640     )
2641 {
2642     return ((Status == STATUS_NOT_SUPPORTED) ||
2643             (Status == STATUS_NOT_IMPLEMENTED) ||
2644             (Status == STATUS_INVALID_DEVICE_REQUEST) ||
2645             (Status == STATUS_INVALID_PARAMETER_1));
2646 }
2647 
2648 #if defined(__REACTOS__) && (NTDDI_VERSION >= NTDDI_WINBLUE)
2649 FORCEINLINE
2650 BOOLEAN
ClasspSrbTimeOutStatus(_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)2651 ClasspSrbTimeOutStatus (
2652     _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb
2653     )
2654 {
2655     UCHAR srbStatus = SrbGetSrbStatus(Srb);
2656     return ((srbStatus == SRB_STATUS_BUS_RESET) ||
2657             (srbStatus == SRB_STATUS_TIMEOUT) ||
2658             (srbStatus == SRB_STATUS_COMMAND_TIMEOUT) ||
2659             (srbStatus == SRB_STATUS_ABORTED));
2660 }
2661 #endif
2662 
2663 NTSTATUS
2664 ClassDeviceHwFirmwareGetInfoProcess(
2665     _In_ PDEVICE_OBJECT DeviceObject,
2666     _Inout_ PIRP Irp
2667     );
2668 
2669 NTSTATUS
2670 ClassDeviceHwFirmwareDownloadProcess(
2671     _In_ PDEVICE_OBJECT DeviceObject,
2672     _Inout_ PIRP Irp,
2673     _Inout_ PSCSI_REQUEST_BLOCK Srb
2674     );
2675 
2676 NTSTATUS
2677 ClassDeviceHwFirmwareActivateProcess(
2678     _In_ PDEVICE_OBJECT DeviceObject,
2679     _Inout_ PIRP Irp,
2680     _Inout_ PSCSI_REQUEST_BLOCK Srb
2681     );
2682 
2683