xref: /reactos/sdk/include/ddk/classpnp.h (revision 06a6eda0)
1 
2 #pragma once
3 
4 #define _CLASS_
5 
6 #include <ntdddisk.h>
7 #include <ntddcdrm.h>
8 #include <ntddtape.h>
9 #include <ntddscsi.h>
10 #include <ntddstor.h>
11 
12 #include <stdio.h>
13 
14 #include <scsi.h>
15 
16 #define max(a,b) (((a) > (b)) ? (a) : (b))
17 #define min(a,b) (((a) < (b)) ? (a) : (b))
18 
19 #define SRB_CLASS_FLAGS_LOW_PRIORITY      0x10000000
20 #define SRB_CLASS_FLAGS_PERSISTANT        0x20000000
21 #define SRB_CLASS_FLAGS_PAGING            0x40000000
22 #define SRB_CLASS_FLAGS_FREE_MDL          0x80000000
23 
24 #define ASSERT_FDO(x) \
25   ASSERT(((PCOMMON_DEVICE_EXTENSION) (x)->DeviceExtension)->IsFdo)
26 
27 #define ASSERT_PDO(x) \
28   ASSERT(!(((PCOMMON_DEVICE_EXTENSION) (x)->DeviceExtension)->IsFdo))
29 
30 #define IS_CLEANUP_REQUEST(majorFunction)   \
31   ((majorFunction == IRP_MJ_CLOSE) ||       \
32    (majorFunction == IRP_MJ_CLEANUP) ||     \
33    (majorFunction == IRP_MJ_SHUTDOWN))
34 
35 #define DO_MCD(fdoExtension)                                 \
36   (((fdoExtension)->MediaChangeDetectionInfo != NULL) &&     \
37    ((fdoExtension)->MediaChangeDetectionInfo->MediaChangeDetectionDisableCount == 0))
38 
39 #define IS_SCSIOP_READ(opCode)     \
40   ((opCode == SCSIOP_READ6)   ||   \
41    (opCode == SCSIOP_READ)    ||   \
42    (opCode == SCSIOP_READ12)  ||   \
43    (opCode == SCSIOP_READ16))
44 
45 #define IS_SCSIOP_WRITE(opCode)     \
46   ((opCode == SCSIOP_WRITE6)   ||   \
47    (opCode == SCSIOP_WRITE)    ||   \
48    (opCode == SCSIOP_WRITE12)  ||   \
49    (opCode == SCSIOP_WRITE16))
50 
51 #define IS_SCSIOP_READWRITE(opCode) (IS_SCSIOP_READ(opCode) || IS_SCSIOP_WRITE(opCode))
52 
53 #define ADJUST_FUA_FLAG(fdoExt) {                                                       \
54     if (TEST_FLAG(fdoExt->DeviceFlags, DEV_WRITE_CACHE) &&                              \
55         !TEST_FLAG(fdoExt->DeviceFlags, DEV_POWER_PROTECTED) &&                         \
56         !TEST_FLAG(fdoExt->ScanForSpecialFlags, CLASS_SPECIAL_FUA_NOT_SUPPORTED) ) {    \
57         fdoExt->CdbForceUnitAccess = TRUE;                                              \
58     } else {                                                                            \
59         fdoExt->CdbForceUnitAccess = FALSE;                                             \
60     }                                                                                   \
61 }
62 
63 #define FREE_POOL(_PoolPtr)     \
64     if (_PoolPtr != NULL) {     \
65         ExFreePool(_PoolPtr);   \
66         _PoolPtr = NULL;        \
67     }
68 
69 #ifdef POOL_TAGGING
70 #undef ExAllocatePool
71 #undef ExAllocatePoolWithQuota
72 #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'nUcS')
73 //#define ExAllocatePool(a,b) #assert(0)
74 #define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,'nUcS')
75 #endif
76 
77 #define CLASS_TAG_AUTORUN_DISABLE           'ALcS'
78 #define CLASS_TAG_FILE_OBJECT_EXTENSION     'FLcS'
79 #define CLASS_TAG_MEDIA_CHANGE_DETECTION    'MLcS'
80 #define CLASS_TAG_MOUNT                     'mLcS'
81 #define CLASS_TAG_RELEASE_QUEUE             'qLcS'
82 #define CLASS_TAG_POWER                     'WLcS'
83 #define CLASS_TAG_WMI                       'wLcS'
84 #define CLASS_TAG_FAILURE_PREDICT           'fLcS'
85 #define CLASS_TAG_DEVICE_CONTROL            'OIcS'
86 #define CLASS_TAG_MODE_DATA                 'oLcS'
87 #define CLASS_TAG_MULTIPATH                 'mPcS'
88 #define CLASS_TAG_LOCK_TRACKING             'TLcS'
89 #define CLASS_TAG_LB_PROVISIONING           'PLcS'
90 #define CLASS_TAG_MANAGE_DATASET            'MDcS'
91 
92 #define MAXIMUM_RETRIES 4
93 
94 #define CLASS_DRIVER_EXTENSION_KEY ((PVOID) ClassInitialize)
95 
96 #define NO_REMOVE                         0
97 #define REMOVE_PENDING                    1
98 #define REMOVE_COMPLETE                   2
99 
100 #define ClassAcquireRemoveLock(devobj, tag) \
101   ClassAcquireRemoveLockEx(devobj, tag, __FILE__, __LINE__)
102 
103 #ifdef TRY
104 #undef TRY
105 #endif
106 #ifdef LEAVE
107 #undef LEAVE
108 #endif
109 
110 #ifdef FINALLY
111 #undef FINALLY
112 #endif
113 
114 #define TRY
115 #define LEAVE             goto __tryLabel;
116 #define FINALLY           __tryLabel:
117 
118 #if defined DebugPrint
119 #undef DebugPrint
120 #endif
121 
122 #if DBG
123 #define DebugPrint(x) ClassDebugPrint x
124 #else
125 #define DebugPrint(x)
126 #endif
127 
128 #define DEBUG_BUFFER_LENGTH                        256
129 
130 #define START_UNIT_TIMEOUT                         (60 * 4)
131 
132 #define MEDIA_CHANGE_DEFAULT_TIME                  1
133 #define MEDIA_CHANGE_TIMEOUT_TIME                  300
134 
135 #ifdef ALLOCATE_SRB_FROM_POOL
136 
137 #define ClasspAllocateSrb(ext)                      \
138   ExAllocatePoolWithTag(NonPagedPool,               \
139                         sizeof(SCSI_REQUEST_BLOCK), \
140                         'sBRS')
141 
142 #define ClasspFreeSrb(ext, srb) ExFreePool((srb));
143 
144 #else /* ALLOCATE_SRB_FROM_POOL */
145 
146 #define ClasspAllocateSrb(ext)                      \
147   ExAllocateFromNPagedLookasideList(                \
148       &((ext)->CommonExtension.SrbLookasideList))
149 
150 #define ClasspFreeSrb(ext, srb)                   \
151   ExFreeToNPagedLookasideList(                    \
152       &((ext)->CommonExtension.SrbLookasideList), \
153       (srb))
154 
155 #endif /* ALLOCATE_SRB_FROM_POOL */
156 
157 #define SET_FLAG(Flags, Bit)    ((Flags) |= (Bit))
158 #define CLEAR_FLAG(Flags, Bit)  ((Flags) &= ~(Bit))
159 #define TEST_FLAG(Flags, Bit)   (((Flags) & (Bit)) != 0)
160 
161 #define CLASS_WORKING_SET_MAXIMUM                         2048
162 
163 #define CLASS_INTERPRET_SENSE_INFO2_MAXIMUM_HISTORY_COUNT 30000
164 
165 #define CLASS_SPECIAL_DISABLE_SPIN_DOWN                 0x00000001
166 #define CLASS_SPECIAL_DISABLE_SPIN_UP                   0x00000002
167 #define CLASS_SPECIAL_NO_QUEUE_LOCK                     0x00000008
168 #define CLASS_SPECIAL_DISABLE_WRITE_CACHE               0x00000010
169 #define CLASS_SPECIAL_CAUSE_NOT_REPORTABLE_HACK         0x00000020
170 #if ((NTDDI_VERSION == NTDDI_WIN2KSP3) || (OSVER(NTDDI_VERSION) == NTDDI_WINXP))
171 #define CLASS_SPECIAL_DISABLE_WRITE_CACHE_NOT_SUPPORTED 0x00000040
172 #endif
173 #define CLASS_SPECIAL_MODIFY_CACHE_UNSUCCESSFUL         0x00000040
174 #define CLASS_SPECIAL_FUA_NOT_SUPPORTED                 0x00000080
175 #define CLASS_SPECIAL_VALID_MASK                        0x000000FB
176 #define CLASS_SPECIAL_RESERVED         (~CLASS_SPECIAL_VALID_MASK)
177 
178 #define DEV_WRITE_CACHE                                 0x00000001
179 #define DEV_USE_SCSI1                                   0x00000002
180 #define DEV_SAFE_START_UNIT                             0x00000004
181 #define DEV_NO_12BYTE_CDB                               0x00000008
182 #define DEV_POWER_PROTECTED                             0x00000010
183 #define DEV_USE_16BYTE_CDB                              0x00000020
184 
185 #define GUID_CLASSPNP_QUERY_REGINFOEX {0x00e34b11, 0x2444, 0x4745, {0xa5, 0x3d, 0x62, 0x01, 0x00, 0xcd, 0x82, 0xf7}}
186 #define GUID_CLASSPNP_SENSEINFO2      {0x509a8c5f, 0x71d7, 0x48f6, {0x82, 0x1e, 0x17, 0x3c, 0x49, 0xbf, 0x2f, 0x18}}
187 #define GUID_CLASSPNP_WORKING_SET     {0x105701b0, 0x9e9b, 0x47cb, {0x97, 0x80, 0x81, 0x19, 0x8a, 0xf7, 0xb5, 0x24}}
188 #define GUID_CLASSPNP_SRB_SUPPORT     {0x0a483941, 0xbdfd, 0x4f7b, {0xbe, 0x95, 0xce, 0xe2, 0xa2, 0x16, 0x09, 0x0c}}
189 
190 #define DEFAULT_FAILURE_PREDICTION_PERIOD 60 * 60 * 1
191 
192 #define MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS (0x3b9aca00)
193 
CountOfSetBitsUChar(UCHAR _X)194 static inline ULONG CountOfSetBitsUChar(UCHAR _X)
195 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsULong(ULONG _X)196 static inline ULONG CountOfSetBitsULong(ULONG _X)
197 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsULong32(ULONG32 _X)198 static inline ULONG CountOfSetBitsULong32(ULONG32 _X)
199 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsULong64(ULONG64 _X)200 static inline ULONG CountOfSetBitsULong64(ULONG64 _X)
201 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsUlongPtr(ULONG_PTR _X)202 static inline ULONG CountOfSetBitsUlongPtr(ULONG_PTR _X)
203 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
204 
205 typedef enum _MEDIA_CHANGE_DETECTION_STATE {
206   MediaUnknown,
207   MediaPresent,
208   MediaNotPresent,
209   MediaUnavailable
210 } MEDIA_CHANGE_DETECTION_STATE, *PMEDIA_CHANGE_DETECTION_STATE;
211 
212 typedef enum _CLASS_DEBUG_LEVEL {
213   ClassDebugError = 0,
214   ClassDebugWarning = 1,
215   ClassDebugTrace = 2,
216   ClassDebugInfo = 3,
217   ClassDebugMediaLocks = 8,
218   ClassDebugMCN = 9,
219   ClassDebugDelayedRetry = 10,
220   ClassDebugSenseInfo = 11,
221   ClassDebugRemoveLock = 12,
222   ClassDebugExternal4 = 13,
223   ClassDebugExternal3 = 14,
224   ClassDebugExternal2 = 15,
225   ClassDebugExternal1 = 16
226 } CLASS_DEBUG_LEVEL, *PCLASS_DEBUG_LEVEL;
227 
228 typedef enum {
229   EventGeneration,
230   DataBlockCollection
231 } CLASSENABLEDISABLEFUNCTION;
232 
233 typedef enum {
234   FailurePredictionNone = 0,
235   FailurePredictionIoctl,
236   FailurePredictionSmart,
237   FailurePredictionSense
238 } FAILURE_PREDICTION_METHOD, *PFAILURE_PREDICTION_METHOD;
239 
240 typedef enum {
241   PowerDownDeviceInitial,
242   PowerDownDeviceLocked,
243   PowerDownDeviceStopped,
244   PowerDownDeviceOff,
245   PowerDownDeviceUnlocked
246 } CLASS_POWER_DOWN_STATE;
247 
248 typedef enum {
249   PowerDownDeviceInitial2,
250   PowerDownDeviceLocked2,
251   PowerDownDeviceFlushed2,
252   PowerDownDeviceStopped2,
253   PowerDownDeviceOff2,
254   PowerDownDeviceUnlocked2
255 } CLASS_POWER_DOWN_STATE2;
256 
257 typedef enum {
258   PowerDownDeviceInitial3 = 0,
259   PowerDownDeviceLocked3,
260   PowerDownDeviceQuiesced3,
261   PowerDownDeviceFlushed3,
262   PowerDownDeviceStopped3,
263   PowerDownDeviceOff3,
264   PowerDownDeviceUnlocked3
265 } CLASS_POWER_DOWN_STATE3;
266 
267 typedef enum {
268   PowerUpDeviceInitial,
269   PowerUpDeviceLocked,
270   PowerUpDeviceOn,
271   PowerUpDeviceStarted,
272   PowerUpDeviceUnlocked
273 } CLASS_POWER_UP_STATE;
274 
275 struct _CLASS_INIT_DATA;
276 typedef struct _CLASS_INIT_DATA CLASS_INIT_DATA, *PCLASS_INIT_DATA;
277 
278 struct _CLASS_PRIVATE_FDO_DATA;
279 typedef struct _CLASS_PRIVATE_FDO_DATA CLASS_PRIVATE_FDO_DATA, *PCLASS_PRIVATE_FDO_DATA;
280 
281 struct _CLASS_PRIVATE_PDO_DATA;
282 typedef struct _CLASS_PRIVATE_PDO_DATA CLASS_PRIVATE_PDO_DATA, *PCLASS_PRIVATE_PDO_DATA;
283 
284 struct _CLASS_PRIVATE_COMMON_DATA;
285 typedef struct _CLASS_PRIVATE_COMMON_DATA CLASS_PRIVATE_COMMON_DATA, *PCLASS_PRIVATE_COMMON_DATA;
286 
287 struct _MEDIA_CHANGE_DETECTION_INFO;
288 typedef struct _MEDIA_CHANGE_DETECTION_INFO MEDIA_CHANGE_DETECTION_INFO, *PMEDIA_CHANGE_DETECTION_INFO;
289 
290 struct _DICTIONARY_HEADER;
291 typedef struct _DICTIONARY_HEADER DICTIONARY_HEADER, *PDICTIONARY_HEADER;
292 
293 typedef struct _DICTIONARY {
294   ULONGLONG Signature;
295   struct _DICTIONARY_HEADER* List;
296   KSPIN_LOCK SpinLock;
297 } DICTIONARY, *PDICTIONARY;
298 
299 typedef struct _CLASSPNP_SCAN_FOR_SPECIAL_INFO {
300   PCHAR VendorId;
301   PCHAR ProductId;
302   PCHAR ProductRevision;
303   ULONG_PTR Data;
304 } CLASSPNP_SCAN_FOR_SPECIAL_INFO, *PCLASSPNP_SCAN_FOR_SPECIAL_INFO;
305 
306 _IRQL_requires_max_(DISPATCH_LEVEL)
307 typedef VOID
308 (NTAPI *PCLASS_ERROR)(
309   _In_ PDEVICE_OBJECT DeviceObject,
310   _In_ PSCSI_REQUEST_BLOCK Srb,
311   _Out_ NTSTATUS *Status,
312   _Inout_ BOOLEAN *Retry);
313 
314 _IRQL_requires_max_(PASSIVE_LEVEL)
315 typedef NTSTATUS
316 (NTAPI *PCLASS_ADD_DEVICE)(
317   _In_ PDRIVER_OBJECT DriverObject,
318   _In_ PDEVICE_OBJECT Pdo);
319 
320 typedef NTSTATUS
321 (NTAPI *PCLASS_POWER_DEVICE)(
322   _In_ PDEVICE_OBJECT DeviceObject,
323   _In_ PIRP Irp);
324 
325 _IRQL_requires_max_(PASSIVE_LEVEL)
326 typedef NTSTATUS
327 (NTAPI *PCLASS_START_DEVICE)(
328   _In_ PDEVICE_OBJECT DeviceObject);
329 
330 _IRQL_requires_max_(PASSIVE_LEVEL)
331 typedef NTSTATUS
332 (NTAPI *PCLASS_STOP_DEVICE)(
333   _In_ PDEVICE_OBJECT DeviceObject,
334   _In_ UCHAR Type);
335 
336 _IRQL_requires_max_(PASSIVE_LEVEL)
337 typedef NTSTATUS
338 (NTAPI *PCLASS_INIT_DEVICE)(
339   _In_ PDEVICE_OBJECT DeviceObject);
340 
341 _IRQL_requires_max_(PASSIVE_LEVEL)
342 typedef NTSTATUS
343 (NTAPI *PCLASS_ENUM_DEVICE)(
344   _In_ PDEVICE_OBJECT DeviceObject);
345 
346 _IRQL_requires_max_(DISPATCH_LEVEL)
347 typedef NTSTATUS
348 (NTAPI *PCLASS_READ_WRITE)(
349   _In_ PDEVICE_OBJECT DeviceObject,
350   _In_ PIRP Irp);
351 
352 _IRQL_requires_max_(DISPATCH_LEVEL)
353 typedef NTSTATUS
354 (NTAPI *PCLASS_DEVICE_CONTROL)(
355   _In_ PDEVICE_OBJECT DeviceObject,
356   _In_ PIRP Irp);
357 
358 _IRQL_requires_max_(DISPATCH_LEVEL)
359 typedef NTSTATUS
360 (NTAPI *PCLASS_SHUTDOWN_FLUSH)(
361   _In_ PDEVICE_OBJECT DeviceObject,
362   _In_ PIRP Irp);
363 
364 _IRQL_requires_max_(PASSIVE_LEVEL)
365 typedef NTSTATUS
366 (NTAPI *PCLASS_CREATE_CLOSE)(
367   _In_ PDEVICE_OBJECT DeviceObject,
368   _In_ PIRP Irp);
369 
370 _IRQL_requires_max_(PASSIVE_LEVEL)
371 typedef NTSTATUS
372 (NTAPI *PCLASS_QUERY_ID)(
373   _In_ PDEVICE_OBJECT DeviceObject,
374   _In_ BUS_QUERY_ID_TYPE IdType,
375   _In_ PUNICODE_STRING IdString);
376 
377 _IRQL_requires_max_(PASSIVE_LEVEL)
378 typedef NTSTATUS
379 (NTAPI *PCLASS_REMOVE_DEVICE)(
380   _In_ PDEVICE_OBJECT DeviceObject,
381   _In_ UCHAR Type);
382 
383 _IRQL_requires_max_(PASSIVE_LEVEL)
384 typedef VOID
385 (NTAPI *PCLASS_UNLOAD)(
386   _In_ PDRIVER_OBJECT DriverObject);
387 
388 _IRQL_requires_max_(PASSIVE_LEVEL)
389 typedef NTSTATUS
390 (NTAPI *PCLASS_QUERY_PNP_CAPABILITIES)(
391   _In_ PDEVICE_OBJECT PhysicalDeviceObject,
392   _In_ PDEVICE_CAPABILITIES Capabilities);
393 
394 _IRQL_requires_(DISPATCH_LEVEL)
395 typedef VOID
396 (NTAPI *PCLASS_TICK)(
397   _In_ PDEVICE_OBJECT DeviceObject);
398 
399 _IRQL_requires_max_(PASSIVE_LEVEL)
400 typedef NTSTATUS
401 (NTAPI *PCLASS_QUERY_WMI_REGINFO_EX)(
402   _In_ PDEVICE_OBJECT DeviceObject,
403   _Out_ ULONG *RegFlags,
404   _Out_ PUNICODE_STRING Name,
405   _Out_ PUNICODE_STRING MofResourceName);
406 
407 _IRQL_requires_max_(PASSIVE_LEVEL)
408 typedef NTSTATUS
409 (NTAPI *PCLASS_QUERY_WMI_REGINFO)(
410   _In_ PDEVICE_OBJECT DeviceObject,
411   _Out_ ULONG *RegFlags,
412   _Out_ PUNICODE_STRING Name);
413 
414 _IRQL_requires_max_(PASSIVE_LEVEL)
415 typedef NTSTATUS
416 (NTAPI *PCLASS_QUERY_WMI_DATABLOCK)(
417   _In_ PDEVICE_OBJECT DeviceObject,
418   _In_ PIRP Irp,
419   _In_ ULONG GuidIndex,
420   _In_ ULONG BufferAvail,
421   _Out_writes_bytes_(BufferAvail) PUCHAR Buffer);
422 
423 _IRQL_requires_max_(PASSIVE_LEVEL)
424 typedef NTSTATUS
425 (NTAPI *PCLASS_SET_WMI_DATABLOCK)(
426   _In_ PDEVICE_OBJECT DeviceObject,
427   _In_ PIRP Irp,
428   _In_ ULONG GuidIndex,
429   _In_ ULONG BufferSize,
430   _In_reads_bytes_(BufferSize) PUCHAR Buffer);
431 
432 _IRQL_requires_max_(PASSIVE_LEVEL)
433 typedef NTSTATUS
434 (NTAPI *PCLASS_SET_WMI_DATAITEM)(
435   _In_ PDEVICE_OBJECT DeviceObject,
436   _In_ PIRP Irp,
437   _In_ ULONG GuidIndex,
438   _In_ ULONG DataItemId,
439   _In_ ULONG BufferSize,
440   _In_reads_bytes_(BufferSize) PUCHAR Buffer);
441 
442 _IRQL_requires_max_(PASSIVE_LEVEL)
443 typedef NTSTATUS
444 (NTAPI *PCLASS_EXECUTE_WMI_METHOD)(
445   _In_ PDEVICE_OBJECT DeviceObject,
446   _In_ PIRP Irp,
447   _In_ ULONG GuidIndex,
448   _In_ ULONG MethodId,
449   _In_ ULONG InBufferSize,
450   _In_ ULONG OutBufferSize,
451   _In_reads_(_Inexpressible_(max(InBufferSize, OutBufferSize))) PUCHAR Buffer);
452 
453 _IRQL_requires_max_(PASSIVE_LEVEL)
454 typedef NTSTATUS
455 (NTAPI *PCLASS_WMI_FUNCTION_CONTROL)(
456   _In_ PDEVICE_OBJECT DeviceObject,
457   _In_ PIRP Irp,
458   _In_ ULONG GuidIndex,
459   _In_ CLASSENABLEDISABLEFUNCTION Function,
460   _In_ BOOLEAN Enable);
461 
462 typedef struct _SRB_HISTORY_ITEM {
463   LARGE_INTEGER TickCountSent;
464   LARGE_INTEGER TickCountCompleted;
465   ULONG MillisecondsDelayOnRetry;
466   SENSE_DATA NormalizedSenseData;
467   UCHAR SrbStatus;
468   UCHAR ClassDriverUse;
469 } SRB_HISTORY_ITEM, *PSRB_HISTORY_ITEM;
470 
471 typedef struct _SRB_HISTORY {
472   ULONG_PTR ClassDriverUse[4];
473   _Field_range_(1,30000) ULONG TotalHistoryCount;
474   _Field_range_(0,TotalHistoryCount) ULONG UsedHistoryCount;
475   _Field_size_part_(TotalHistoryCount, UsedHistoryCount) SRB_HISTORY_ITEM History[1];
476 } SRB_HISTORY, *PSRB_HISTORY;
477 
478 _IRQL_requires_max_(DISPATCH_LEVEL)
479 typedef BOOLEAN
480 (NTAPI *PCLASS_INTERPRET_SENSE_INFO)(
481   _In_ PDEVICE_OBJECT Fdo,
482   _In_opt_ PIRP OriginalRequest,
483   _In_ PSCSI_REQUEST_BLOCK Srb,
484   _In_ UCHAR MajorFunctionCode,
485   _In_ ULONG IoDeviceCode,
486   _In_ ULONG PreviousRetryCount,
487   _In_opt_ SRB_HISTORY *RequestHistory,
488   _Out_ NTSTATUS *Status,
489   _Out_ _Deref_out_range_(0,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
490     LONGLONG *RetryIn100nsUnits);
491 
492 _IRQL_requires_max_(DISPATCH_LEVEL)
493 _At_(RequestHistory->UsedHistoryCount, _Pre_equal_to_(RequestHistory->TotalHistoryCount)
494    _Out_range_(0, RequestHistory->TotalHistoryCount - 1))
495 typedef VOID
496 (NTAPI *PCLASS_COMPRESS_RETRY_HISTORY_DATA)(
497   _In_ PDEVICE_OBJECT DeviceObject,
498   _Inout_ PSRB_HISTORY RequestHistory);
499 
500 typedef struct {
501   GUID Guid;
502   ULONG InstanceCount;
503   ULONG Flags;
504 } GUIDREGINFO, *PGUIDREGINFO;
505 
506 typedef struct _CLASS_WMI_INFO {
507   ULONG GuidCount;
508   PGUIDREGINFO GuidRegInfo;
509   PCLASS_QUERY_WMI_REGINFO ClassQueryWmiRegInfo;
510   PCLASS_QUERY_WMI_DATABLOCK ClassQueryWmiDataBlock;
511   PCLASS_SET_WMI_DATABLOCK ClassSetWmiDataBlock;
512   PCLASS_SET_WMI_DATAITEM ClassSetWmiDataItem;
513   PCLASS_EXECUTE_WMI_METHOD ClassExecuteWmiMethod;
514   PCLASS_WMI_FUNCTION_CONTROL ClassWmiFunctionControl;
515 } CLASS_WMI_INFO, *PCLASS_WMI_INFO;
516 
517 typedef struct _CLASS_DEV_INFO {
518   ULONG DeviceExtensionSize;
519   DEVICE_TYPE DeviceType;
520   UCHAR StackSize;
521   ULONG DeviceCharacteristics;
522   PCLASS_ERROR ClassError;
523   PCLASS_READ_WRITE ClassReadWriteVerification;
524   PCLASS_DEVICE_CONTROL ClassDeviceControl;
525   PCLASS_SHUTDOWN_FLUSH ClassShutdownFlush;
526   PCLASS_CREATE_CLOSE ClassCreateClose;
527   PCLASS_INIT_DEVICE ClassInitDevice;
528   PCLASS_START_DEVICE ClassStartDevice;
529   PCLASS_POWER_DEVICE ClassPowerDevice;
530   PCLASS_STOP_DEVICE ClassStopDevice;
531   PCLASS_REMOVE_DEVICE ClassRemoveDevice;
532   PCLASS_QUERY_PNP_CAPABILITIES ClassQueryPnpCapabilities;
533   CLASS_WMI_INFO ClassWmiInfo;
534 } CLASS_DEV_INFO, *PCLASS_DEV_INFO;
535 
536 struct _CLASS_INIT_DATA {
537   ULONG InitializationDataSize;
538   CLASS_DEV_INFO FdoData;
539   CLASS_DEV_INFO PdoData;
540   PCLASS_ADD_DEVICE ClassAddDevice;
541   PCLASS_ENUM_DEVICE ClassEnumerateDevice;
542   PCLASS_QUERY_ID ClassQueryId;
543   PDRIVER_STARTIO ClassStartIo;
544   PCLASS_UNLOAD ClassUnload;
545   PCLASS_TICK ClassTick;
546 };
547 
548 typedef struct _FILE_OBJECT_EXTENSION {
549   PFILE_OBJECT FileObject;
550   PDEVICE_OBJECT DeviceObject;
551   ULONG LockCount;
552   ULONG McnDisableCount;
553 } FILE_OBJECT_EXTENSION, *PFILE_OBJECT_EXTENSION;
554 
555 typedef struct _CLASS_WORKING_SET {
556   _Field_range_(sizeof(CLASS_WORKING_SET),sizeof(CLASS_WORKING_SET)) ULONG Size;
557   _Field_range_(0,2048) ULONG XferPacketsWorkingSetMaximum;
558   _Field_range_(0,2048) ULONG XferPacketsWorkingSetMinimum;
559 } CLASS_WORKING_SET, *PCLASS_WORKING_SET;
560 
561 typedef struct _CLASS_INTERPRET_SENSE_INFO2 {
562   _Field_range_(sizeof(CLASS_INTERPRET_SENSE_INFO),sizeof(CLASS_INTERPRET_SENSE_INFO))
563     ULONG Size;
564   _Field_range_(1,30000) ULONG HistoryCount;
565   __callback PCLASS_COMPRESS_RETRY_HISTORY_DATA Compress;
566   __callback PCLASS_INTERPRET_SENSE_INFO Interpret;
567 } CLASS_INTERPRET_SENSE_INFO2, *PCLASS_INTERPRET_SENSE_INFO2;
568 
569 C_ASSERT((MAXULONG - sizeof(SRB_HISTORY)) / 30000 >= sizeof(SRB_HISTORY_ITEM));
570 
571 // for SrbSupport
572 #define CLASS_SRB_SCSI_REQUEST_BLOCK    0x1
573 #define CLASS_SRB_STORAGE_REQUEST_BLOCK 0x2
574 
575 typedef struct _CLASS_DRIVER_EXTENSION {
576   UNICODE_STRING RegistryPath;
577   CLASS_INIT_DATA InitData;
578   ULONG DeviceCount;
579 #if (NTDDI_VERSION >= NTDDI_WINXP)
580   PCLASS_QUERY_WMI_REGINFO_EX ClassFdoQueryWmiRegInfoEx;
581   PCLASS_QUERY_WMI_REGINFO_EX ClassPdoQueryWmiRegInfoEx;
582 #endif
583 #if (NTDDI_VERSION >= NTDDI_VISTA)
584   REGHANDLE EtwHandle;
585   PDRIVER_DISPATCH DeviceMajorFunctionTable[IRP_MJ_MAXIMUM_FUNCTION + 1];
586   PDRIVER_DISPATCH MpDeviceMajorFunctionTable[IRP_MJ_MAXIMUM_FUNCTION + 1];
587   PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo;
588   PCLASS_WORKING_SET WorkingSet;
589 #endif
590 #if (NTDDI_VERSION >= NTDDI_WIN8)
591   ULONG SrbSupport;
592 #endif
593 } CLASS_DRIVER_EXTENSION, *PCLASS_DRIVER_EXTENSION;
594 
595 typedef struct _COMMON_DEVICE_EXTENSION {
596   ULONG Version;
597   PDEVICE_OBJECT DeviceObject;
598   PDEVICE_OBJECT LowerDeviceObject;
599   struct _FUNCTIONAL_DEVICE_EXTENSION *PartitionZeroExtension;
600   PCLASS_DRIVER_EXTENSION DriverExtension;
601   LONG RemoveLock;
602   KEVENT RemoveEvent;
603   KSPIN_LOCK RemoveTrackingSpinlock;
604   PVOID RemoveTrackingList;
605   LONG RemoveTrackingUntrackedCount;
606   PVOID DriverData;
607   _ANONYMOUS_STRUCT struct {
608     BOOLEAN IsFdo:1;
609     BOOLEAN IsInitialized:1;
610     BOOLEAN IsSrbLookasideListInitialized:1;
611   } DUMMYSTRUCTNAME;
612   UCHAR PreviousState;
613   UCHAR CurrentState;
614   ULONG IsRemoved;
615   UNICODE_STRING DeviceName;
616   struct _PHYSICAL_DEVICE_EXTENSION *ChildList;
617   ULONG PartitionNumber;
618   LARGE_INTEGER PartitionLength;
619   LARGE_INTEGER StartingOffset;
620   PCLASS_DEV_INFO DevInfo;
621   ULONG PagingPathCount;
622   ULONG DumpPathCount;
623   ULONG HibernationPathCount;
624   KEVENT PathCountEvent;
625 #ifndef ALLOCATE_SRB_FROM_POOL
626   NPAGED_LOOKASIDE_LIST SrbLookasideList;
627 #endif
628   UNICODE_STRING MountedDeviceInterfaceName;
629   ULONG GuidCount;
630   PGUIDREGINFO GuidRegInfo;
631   DICTIONARY FileObjectDictionary;
632 #if (NTDDI_VERSION >= NTDDI_WINXP)
633   PCLASS_PRIVATE_COMMON_DATA PrivateCommonData;
634 #else
635   ULONG_PTR Reserved1;
636 #endif
637 #if (NTDDI_VERSION >= NTDDI_VISTA)
638   PDRIVER_DISPATCH *DispatchTable;
639 #else
640   ULONG_PTR Reserved2;
641 #endif
642   ULONG_PTR Reserved3;
643   ULONG_PTR Reserved4;
644 } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
645 
646 typedef struct _PHYSICAL_DEVICE_EXTENSION {
647   _ANONYMOUS_UNION union {
648     _ANONYMOUS_STRUCT struct {
649       ULONG Version;
650       PDEVICE_OBJECT DeviceObject;
651     } DUMMYSTRUCTNAME;
652     COMMON_DEVICE_EXTENSION CommonExtension;
653   } DUMMYUNIONNAME;
654   BOOLEAN IsMissing;
655   BOOLEAN IsEnumerated;
656 #if (NTDDI_VERSION >= NTDDI_WINXP)
657   PCLASS_PRIVATE_PDO_DATA PrivatePdoData;
658 #else
659   ULONG_PTR Reserved1;
660 #endif
661   ULONG_PTR Reserved2;
662   ULONG_PTR Reserved3;
663   ULONG_PTR Reserved4;
664 } PHYSICAL_DEVICE_EXTENSION, *PPHYSICAL_DEVICE_EXTENSION;
665 
666 typedef struct _CLASS_POWER_OPTIONS {
667   ULONG PowerDown:1;
668   ULONG LockQueue:1;
669   ULONG HandleSpinDown:1;
670   ULONG HandleSpinUp:1;
671   ULONG Reserved:27;
672 } CLASS_POWER_OPTIONS, *PCLASS_POWER_OPTIONS;
673 
674 typedef struct _CLASS_POWER_CONTEXT {
675   union {
676     CLASS_POWER_DOWN_STATE PowerDown;
677     CLASS_POWER_DOWN_STATE2 PowerDown2;
678     CLASS_POWER_DOWN_STATE3 PowerDown3;
679     CLASS_POWER_UP_STATE PowerUp;
680   } PowerChangeState;
681   CLASS_POWER_OPTIONS Options;
682   BOOLEAN InUse;
683   BOOLEAN QueueLocked;
684   NTSTATUS FinalStatus;
685   ULONG RetryCount;
686   ULONG RetryInterval;
687   PIO_COMPLETION_ROUTINE CompletionRoutine;
688   PDEVICE_OBJECT DeviceObject;
689   PIRP Irp;
690   SCSI_REQUEST_BLOCK Srb;
691 } CLASS_POWER_CONTEXT, *PCLASS_POWER_CONTEXT;
692 
693 #if (NTDDI_VERSION >= NTDDI_WIN8)
694 
695 #define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE (sizeof(STORAGE_REQUEST_BLOCK) + sizeof(STOR_ADDR_BTL8) + sizeof(SRBEX_DATA_SCSI_CDB16))
696 #define CLASS_SRBEX_NO_SRBEX_DATA_BUFFER_SIZE (sizeof(STORAGE_REQUEST_BLOCK) + sizeof(STOR_ADDR_BTL8))
697 
698 #endif
699 
700 typedef struct _COMPLETION_CONTEXT {
701   PDEVICE_OBJECT DeviceObject;
702 #if (NTDDI_VERSION >= NTDDI_WIN8)
703   union
704   {
705     SCSI_REQUEST_BLOCK Srb;
706     STORAGE_REQUEST_BLOCK SrbEx;
707     UCHAR SrbExBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE];
708   } Srb;
709 #else
710   SCSI_REQUEST_BLOCK Srb;
711 #endif
712 } COMPLETION_CONTEXT, *PCOMPLETION_CONTEXT;
713 
714 _IRQL_requires_max_(PASSIVE_LEVEL)
715 _Must_inspect_result_
716 SCSIPORT_API
717 ULONG
718 NTAPI
719 ClassInitialize(
720   _In_ PVOID Argument1,
721   _In_ PVOID Argument2,
722   _In_ PCLASS_INIT_DATA InitializationData);
723 
724 typedef struct _CLASS_QUERY_WMI_REGINFO_EX_LIST {
725   ULONG Size;
726   __callback PCLASS_QUERY_WMI_REGINFO_EX ClassFdoQueryWmiRegInfoEx;
727   __callback PCLASS_QUERY_WMI_REGINFO_EX ClassPdoQueryWmiRegInfoEx;
728 } CLASS_QUERY_WMI_REGINFO_EX_LIST, *PCLASS_QUERY_WMI_REGINFO_EX_LIST;
729 
730 typedef enum
731 {
732   SupportUnknown = 0,
733   Supported,
734   NotSupported
735 } CLASS_FUNCTION_SUPPORT;
736 
737 typedef struct _CLASS_VPD_B1_DATA
738 {
739   NTSTATUS CommandStatus;
740   USHORT MediumRotationRate;
741   UCHAR NominalFormFactor;
742   UCHAR Zoned;
743   ULONG MediumProductType;
744   ULONG DepopulationTime;
745 } CLASS_VPD_B1_DATA, *PCLASS_VPD_B1_DATA;
746 
747 typedef struct _CLASS_VPD_B0_DATA
748 {
749   NTSTATUS CommandStatus;
750   ULONG MaxUnmapLbaCount;
751   ULONG MaxUnmapBlockDescrCount;
752   ULONG OptimalUnmapGranularity;
753   ULONG UnmapGranularityAlignment;
754   BOOLEAN UGAVALID;
755   UCHAR Reserved0;
756   USHORT OptimalTransferLengthGranularity;
757   ULONG MaximumTransferLength;
758   ULONG OptimalTransferLength;
759 } CLASS_VPD_B0_DATA, *PCLASS_VPD_B0_DATA;
760 
761 #ifdef _MSC_VER
762 #pragma warning(push)
763 #pragma warning(disable:4214)
764 #endif
765 typedef struct _CLASS_VPD_B2_DATA
766 {
767   NTSTATUS CommandStatus;
768   UCHAR ThresholdExponent;
769   UCHAR DP:1;
770   UCHAR ANC_SUP:1;
771   UCHAR Reserved0:2;
772   UCHAR LBPRZ:1;
773   UCHAR LBPWS10:1;
774   UCHAR LBPWS:1;
775   UCHAR LBPU:1;
776   UCHAR ProvisioningType:3;
777   UCHAR Reserved1:5;
778   ULONG SoftThresholdEventPending;
779 } CLASS_VPD_B2_DATA, *PCLASS_VPD_B2_DATA;
780 #ifdef _MSC_VER
781 #pragma warning(pop)
782 #endif
783 
784 typedef struct _CLASS_READ_CAPACITY16_DATA
785 {
786   NTSTATUS CommandStatus;
787   ULONG BytesPerLogicalSector;
788   ULONG BytesPerPhysicalSector;
789   ULONG BytesOffsetForSectorAlignment;
790   BOOLEAN LBProvisioningEnabled;
791   BOOLEAN LBProvisioningReadZeros;
792   UCHAR Reserved0[2];
793   ULONG Reserved1;
794 } CLASS_READ_CAPACITY16_DATA, *PCLASS_READ_CAPACITY16_DATA;
795 
796 typedef struct _CLASS_VPD_ECOP_BLOCK_DEVICE_ROD_LIMITS
797 {
798   NTSTATUS CommandStatus;
799   USHORT MaximumRangeDescriptors;
800   UCHAR Restricted;
801   UCHAR Reserved;
802   ULONG MaximumInactivityTimer;
803   ULONG DefaultInactivityTimer;
804   ULONGLONG MaximumTokenTransferSize;
805   ULONGLONG OptimalTransferCount;
806 } CLASS_VPD_ECOP_BLOCK_DEVICE_ROD_LIMITS, *PCLASS_VPD_ECOP_BLOCK_DEVICE_ROD_LIMITS;
807 
808 #ifdef _MSC_VER
809 #pragma warning(push)
810 #pragma warning(disable:4214)
811 #endif
812 typedef struct _CLASS_FUNCTION_SUPPORT_INFO
813 {
814   KSPIN_LOCK SyncLock;
815   ULONG GenerationCount;
816   volatile ULONG ChangeRequestCount;
817   struct
818   {
819     ULONG BlockLimits:1;
820     ULONG BlockDeviceCharacteristics:1;
821     ULONG LBProvisioning:1;
822     ULONG BlockDeviceRODLimits:1;
823     ULONG ZonedBlockDeviceCharacteristics:1;
824     ULONG Reserved:22;
825     ULONG DeviceType:5;
826   } ValidInquiryPages;
827   struct
828   {
829     CLASS_FUNCTION_SUPPORT SeekPenaltyProperty;
830     CLASS_FUNCTION_SUPPORT AccessAlignmentProperty;
831     CLASS_FUNCTION_SUPPORT TrimProperty;
832     CLASS_FUNCTION_SUPPORT TrimProcess;
833   } LowerLayerSupport;
834   BOOLEAN RegAccessAlignmentQueryNotSupported;
835   BOOLEAN AsynchronousNotificationSupported;
836 #if (NTDDI_VERSION >= NTDDI_WIN10_RS2)
837   BOOLEAN UseModeSense10;
838   UCHAR Reserved;
839 #else
840   UCHAR Reserved[2];
841 #endif
842   CLASS_VPD_B0_DATA BlockLimitsData;
843   CLASS_VPD_B1_DATA DeviceCharacteristicsData;
844   CLASS_VPD_B2_DATA LBProvisioningData;
845   CLASS_READ_CAPACITY16_DATA ReadCapacity16Data;
846   CLASS_VPD_ECOP_BLOCK_DEVICE_ROD_LIMITS BlockDeviceRODLimitsData;
847   struct
848   {
849     ULONG D3ColdSupported:1;
850     ULONG DeviceWakeable:1;
851     ULONG IdlePowerEnabled:1;
852     ULONG D3IdleTimeoutOverridden:1;
853     ULONG NoVerifyDuringIdlePower:1;
854     ULONG Reserved2:27;
855     ULONG D3IdleTimeout;
856   } IdlePower;
857 
858 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
859   CLASS_FUNCTION_SUPPORT HwFirmwareGetInfoSupport;
860   PSTORAGE_HW_FIRMWARE_INFO HwFirmwareInfo;
861 #endif
862 } CLASS_FUNCTION_SUPPORT_INFO, *PCLASS_FUNCTION_SUPPORT_INFO;
863 #ifdef _MSC_VER
864 #pragma warning(pop)
865 #endif
866 
867 typedef struct _FUNCTIONAL_DEVICE_EXTENSION {
868   _ANONYMOUS_UNION union {
869     _ANONYMOUS_STRUCT struct {
870       ULONG Version;
871       PDEVICE_OBJECT DeviceObject;
872     } DUMMYSTRUCTNAME;
873     COMMON_DEVICE_EXTENSION CommonExtension;
874   } DUMMYUNIONNAME;
875   PDEVICE_OBJECT LowerPdo;
876   PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor;
877   PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor;
878   DEVICE_POWER_STATE DevicePowerState;
879   ULONG DMByteSkew;
880   ULONG DMSkew;
881   BOOLEAN DMActive;
882 #if (NTDDI_VERSION >= NTDDI_WIN8)
883   UCHAR SenseDataLength;
884 #else
885   UCHAR Reserved;
886 #endif
887   UCHAR Reserved0[2];
888   DISK_GEOMETRY DiskGeometry;
889   PSENSE_DATA SenseData;
890   ULONG TimeOutValue;
891   ULONG DeviceNumber;
892   ULONG SrbFlags;
893   ULONG ErrorCount;
894   LONG LockCount;
895   LONG ProtectedLockCount;
896   LONG InternalLockCount;
897   KEVENT EjectSynchronizationEvent;
898   USHORT DeviceFlags;
899   UCHAR SectorShift;
900 #if (NTDDI_VERSION >= NTDDI_VISTA)
901   UCHAR CdbForceUnitAccess;
902 #else
903   UCHAR ReservedByte;
904 #endif
905   PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo;
906   PKEVENT Unused1;
907   HANDLE Unused2;
908   FILE_OBJECT_EXTENSION KernelModeMcnContext;
909   ULONG MediaChangeCount;
910   HANDLE DeviceDirectory;
911   KSPIN_LOCK ReleaseQueueSpinLock;
912   PIRP ReleaseQueueIrp;
913   SCSI_REQUEST_BLOCK ReleaseQueueSrb;
914   BOOLEAN ReleaseQueueNeeded;
915   BOOLEAN ReleaseQueueInProgress;
916   BOOLEAN ReleaseQueueIrpFromPool;
917   BOOLEAN FailurePredicted;
918   ULONG FailureReason;
919   struct _FAILURE_PREDICTION_INFO* FailurePredictionInfo;
920   BOOLEAN PowerDownInProgress;
921   ULONG EnumerationInterlock;
922   KEVENT ChildLock;
923   PKTHREAD ChildLockOwner;
924   ULONG ChildLockAcquisitionCount;
925   ULONG ScanForSpecialFlags;
926   KDPC PowerRetryDpc;
927   KTIMER PowerRetryTimer;
928   CLASS_POWER_CONTEXT PowerContext;
929 
930 #if (NTDDI_VERSION <= NTDDI_WIN2K)
931 
932 #if (SPVER(NTDDI_VERSION) < 2))
933   ULONG_PTR Reserved1;
934   ULONG_PTR Reserved2;
935   ULONG_PTR Reserved3;
936   ULONG_PTR Reserved4;
937 #else
938   ULONG CompletionSuccessCount;
939   ULONG SavedSrbFlags;
940   ULONG SavedErrorCount;
941   ULONG_PTR Reserved1;
942 #endif /* (SPVER(NTDDI_VERSION) < 2) */
943 
944 #else /* (NTDDI_VERSION <= NTDDI_WIN2K) */
945 
946   PCLASS_PRIVATE_FDO_DATA PrivateFdoData;
947 #if (NTDDI_VERSION >= NTDDI_WIN8)
948   PCLASS_FUNCTION_SUPPORT_INFO FunctionSupportInfo;
949   PSTORAGE_MINIPORT_DESCRIPTOR MiniportDescriptor;
950 #else
951   ULONG_PTR Reserved2;
952   ULONG_PTR Reserved3;
953 #endif
954 
955 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
956   PADDITIONAL_FDO_DATA AdditionalFdoData;
957 #else
958   ULONG_PTR Reserved4;
959 #endif
960 #endif /* (NTDDI_VERSION <= NTDDI_WIN2K) */
961 
962 } FUNCTIONAL_DEVICE_EXTENSION, *PFUNCTIONAL_DEVICE_EXTENSION;
963 
964 _IRQL_requires_max_(PASSIVE_LEVEL)
965 _Must_inspect_result_
966 SCSIPORT_API
967 ULONG
968 NTAPI
969 ClassInitializeEx(
970   _In_ PDRIVER_OBJECT DriverObject,
971   _In_ LPGUID Guid,
972   _In_ PVOID Data);
973 
974 _IRQL_requires_max_(PASSIVE_LEVEL)
975 _Must_inspect_result_
976 _Post_satisfies_(return <= 0)
977 SCSIPORT_API
978 NTSTATUS
979 NTAPI
980 ClassCreateDeviceObject(
981   _In_ PDRIVER_OBJECT DriverObject,
982   _In_z_ PCCHAR ObjectNameBuffer,
983   _In_ PDEVICE_OBJECT LowerDeviceObject,
984   _In_ BOOLEAN IsFdo,
985   _Outptr_result_nullonfailure_ _At_(*DeviceObject, __drv_allocatesMem(Mem) __drv_aliasesMem)
986     PDEVICE_OBJECT *DeviceObject);
987 
988 _Must_inspect_result_
989 SCSIPORT_API
990 NTSTATUS
991 NTAPI
992 ClassReadDriveCapacity(
993   _In_ PDEVICE_OBJECT DeviceObject);
994 
995 SCSIPORT_API
996 VOID
997 NTAPI
998 ClassReleaseQueue(
999   _In_ PDEVICE_OBJECT DeviceObject);
1000 
1001 SCSIPORT_API
1002 VOID
1003 NTAPI
1004 ClassSplitRequest(
1005   _In_ PDEVICE_OBJECT DeviceObject,
1006   _In_ PIRP Irp,
1007   _In_ ULONG MaximumBytes);
1008 
1009 SCSIPORT_API
1010 NTSTATUS
1011 NTAPI
1012 ClassDeviceControl(
1013   _In_ PDEVICE_OBJECT DeviceObject,
1014   _Inout_ PIRP Irp);
1015 
1016 SCSIPORT_API
1017 NTSTATUS
1018 NTAPI
1019 ClassIoComplete(
1020   PDEVICE_OBJECT DeviceObject,
1021   PIRP Irp,
1022   PVOID Context);
1023 
1024 SCSIPORT_API
1025 NTSTATUS
1026 NTAPI
1027 ClassIoCompleteAssociated(
1028   PDEVICE_OBJECT DeviceObject,
1029   PIRP Irp,
1030   PVOID Context);
1031 
1032 SCSIPORT_API
1033 BOOLEAN
1034 NTAPI
1035 ClassInterpretSenseInfo(
1036   _In_ PDEVICE_OBJECT DeviceObject,
1037   _In_ PSCSI_REQUEST_BLOCK Srb,
1038   _In_ UCHAR MajorFunctionCode,
1039   _In_ ULONG IoDeviceCode,
1040   _In_ ULONG RetryCount,
1041   _Out_ NTSTATUS *Status,
1042   _Out_opt_ _Deref_out_range_(0,100) ULONG *RetryInterval);
1043 
1044 VOID
1045 NTAPI
1046 ClassSendDeviceIoControlSynchronous(
1047   _In_ ULONG IoControlCode,
1048   _In_ PDEVICE_OBJECT TargetDeviceObject,
1049   _Inout_updates_opt_(_Inexpressible_(max(InputBufferLength, OutputBufferLength)))
1050     PVOID Buffer,
1051   _In_ ULONG InputBufferLength,
1052   _In_ ULONG OutputBufferLength,
1053   _In_ BOOLEAN InternalDeviceIoControl,
1054   _Out_ PIO_STATUS_BLOCK IoStatus);
1055 
1056 SCSIPORT_API
1057 NTSTATUS
1058 NTAPI
1059 ClassSendIrpSynchronous(
1060   _In_ PDEVICE_OBJECT TargetDeviceObject,
1061   _In_ PIRP Irp);
1062 
1063 SCSIPORT_API
1064 NTSTATUS
1065 NTAPI
1066 ClassForwardIrpSynchronous(
1067   _In_ PCOMMON_DEVICE_EXTENSION CommonExtension,
1068   _In_ PIRP Irp);
1069 
1070 SCSIPORT_API
1071 NTSTATUS
1072 NTAPI
1073 ClassSendSrbSynchronous(
1074   _In_ PDEVICE_OBJECT DeviceObject,
1075   _Inout_ PSCSI_REQUEST_BLOCK Srb,
1076   _In_reads_bytes_opt_(BufferLength) PVOID BufferAddress,
1077   _In_ ULONG BufferLength,
1078   _In_ BOOLEAN WriteToDevice);
1079 
1080 SCSIPORT_API
1081 NTSTATUS
1082 NTAPI
1083 ClassSendSrbAsynchronous(
1084   _In_ PDEVICE_OBJECT DeviceObject,
1085   _Inout_ PSCSI_REQUEST_BLOCK Srb,
1086   _In_ PIRP Irp,
1087   _In_reads_bytes_opt_(BufferLength) __drv_aliasesMem PVOID BufferAddress,
1088   _In_ ULONG BufferLength,
1089   _In_ BOOLEAN WriteToDevice);
1090 
1091 SCSIPORT_API
1092 NTSTATUS
1093 NTAPI
1094 ClassBuildRequest(
1095   _In_ PDEVICE_OBJECT DeviceObject,
1096   _In_ PIRP Irp);
1097 
1098 SCSIPORT_API
1099 ULONG
1100 NTAPI
1101 ClassModeSense(
1102   _In_ PDEVICE_OBJECT DeviceObject,
1103   _In_reads_bytes_(Length) PCHAR ModeSenseBuffer,
1104   _In_ ULONG Length,
1105   _In_ UCHAR PageMode);
1106 
1107 SCSIPORT_API
1108 PVOID
1109 NTAPI
1110 ClassFindModePage(
1111   _In_reads_bytes_(Length) PCHAR ModeSenseBuffer,
1112   _In_ ULONG Length,
1113   _In_ UCHAR PageMode,
1114   _In_ BOOLEAN Use6Byte);
1115 
1116 _IRQL_requires_max_(PASSIVE_LEVEL)
1117 SCSIPORT_API
1118 NTSTATUS
1119 NTAPI
1120 ClassClaimDevice(
1121   _In_ PDEVICE_OBJECT LowerDeviceObject,
1122   _In_ BOOLEAN Release);
1123 
1124 SCSIPORT_API
1125 NTSTATUS
1126 NTAPI
1127 ClassInternalIoControl(
1128   PDEVICE_OBJECT DeviceObject,
1129   PIRP Irp);
1130 
1131 _IRQL_requires_max_(PASSIVE_LEVEL)
1132 SCSIPORT_API
1133 VOID
1134 NTAPI
1135 ClassInitializeSrbLookasideList(
1136   _Inout_ PCOMMON_DEVICE_EXTENSION CommonExtension,
1137   _In_ ULONG NumberElements);
1138 
1139 _IRQL_requires_max_(PASSIVE_LEVEL)
1140 SCSIPORT_API
1141 VOID
1142 NTAPI
1143 ClassDeleteSrbLookasideList(
1144   _Inout_ PCOMMON_DEVICE_EXTENSION CommonExtension);
1145 
1146 _IRQL_requires_max_(PASSIVE_LEVEL)
1147 SCSIPORT_API
1148 ULONG
1149 NTAPI
1150 ClassQueryTimeOutRegistryValue(
1151   _In_ PDEVICE_OBJECT DeviceObject);
1152 
1153 _IRQL_requires_max_(PASSIVE_LEVEL)
1154 SCSIPORT_API
1155 NTSTATUS
1156 NTAPI
1157 ClassGetDescriptor(
1158   _In_ PDEVICE_OBJECT DeviceObject,
1159   _In_ PSTORAGE_PROPERTY_ID PropertyId,
1160   _Outptr_ PVOID *Descriptor);
1161 
1162 _IRQL_requires_max_(PASSIVE_LEVEL)
1163 SCSIPORT_API
1164 VOID
1165 NTAPI
1166 ClassInvalidateBusRelations(
1167   _In_ PDEVICE_OBJECT Fdo);
1168 
1169 _IRQL_requires_max_(PASSIVE_LEVEL)
1170 SCSIPORT_API
1171 VOID
1172 NTAPI
1173 ClassMarkChildrenMissing(
1174   _In_ PFUNCTIONAL_DEVICE_EXTENSION Fdo);
1175 
1176 _IRQL_requires_max_(PASSIVE_LEVEL)
1177 SCSIPORT_API
1178 BOOLEAN
1179 NTAPI
1180 ClassMarkChildMissing(
1181   _In_ PPHYSICAL_DEVICE_EXTENSION PdoExtension,
1182   _In_ BOOLEAN AcquireChildLock);
1183 
1184 SCSIPORT_API
1185 VOID
1186 ClassDebugPrint(
1187   _In_ CLASS_DEBUG_LEVEL DebugPrintLevel,
1188   _In_z_ PCCHAR DebugMessage,
1189   ...);
1190 
1191 __drv_aliasesMem
1192 _IRQL_requires_max_(DISPATCH_LEVEL)
1193 SCSIPORT_API
1194 PCLASS_DRIVER_EXTENSION
1195 NTAPI
1196 ClassGetDriverExtension(
1197   _In_ PDRIVER_OBJECT DriverObject);
1198 
1199 SCSIPORT_API
1200 VOID
1201 NTAPI
1202 ClassCompleteRequest(
1203   _In_ PDEVICE_OBJECT DeviceObject,
1204   _In_ PIRP Irp,
1205   _In_ CCHAR PriorityBoost);
1206 
1207 SCSIPORT_API
1208 VOID
1209 NTAPI
1210 ClassReleaseRemoveLock(
1211   _In_ PDEVICE_OBJECT DeviceObject,
1212   PIRP Tag);
1213 
1214 SCSIPORT_API
1215 ULONG
1216 NTAPI
1217 ClassAcquireRemoveLockEx(
1218   _In_ PDEVICE_OBJECT DeviceObject,
1219   PVOID Tag,
1220   _In_ PCSTR File,
1221   _In_ ULONG Line);
1222 
1223 _IRQL_requires_max_(PASSIVE_LEVEL)
1224 SCSIPORT_API
1225 VOID
1226 NTAPI
1227 ClassUpdateInformationInRegistry(
1228   _In_ PDEVICE_OBJECT Fdo,
1229   _In_ PCHAR DeviceName,
1230   _In_ ULONG DeviceNumber,
1231   _In_reads_bytes_opt_(InquiryDataLength) PINQUIRYDATA InquiryData,
1232   _In_ ULONG InquiryDataLength);
1233 
1234 SCSIPORT_API
1235 NTSTATUS
1236 NTAPI
1237 ClassWmiCompleteRequest(
1238   _In_ PDEVICE_OBJECT DeviceObject,
1239   _Inout_ PIRP Irp,
1240   _In_ NTSTATUS Status,
1241   _In_ ULONG BufferUsed,
1242   _In_ CCHAR PriorityBoost);
1243 
1244 _IRQL_requires_max_(DISPATCH_LEVEL)
1245 SCSIPORT_API
1246 NTSTATUS
1247 NTAPI
1248 ClassWmiFireEvent(
1249   _In_ PDEVICE_OBJECT DeviceObject,
1250   _In_ LPGUID Guid,
1251   _In_ ULONG InstanceIndex,
1252   _In_ ULONG EventDataSize,
1253   _In_reads_bytes_(EventDataSize) PVOID EventData);
1254 
1255 SCSIPORT_API
1256 VOID
1257 NTAPI
1258 ClassResetMediaChangeTimer(
1259   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1260 
1261 _IRQL_requires_max_(PASSIVE_LEVEL)
1262 SCSIPORT_API
1263 VOID
1264 NTAPI
1265 ClassInitializeMediaChangeDetection(
1266   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1267   _In_ PUCHAR EventPrefix);
1268 
1269 _IRQL_requires_max_(PASSIVE_LEVEL)
1270 SCSIPORT_API
1271 NTSTATUS
1272 NTAPI
1273 ClassInitializeTestUnitPolling(
1274   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1275   _In_ BOOLEAN AllowDriveToSleep);
1276 
1277 SCSIPORT_API
1278 PVPB
1279 NTAPI
1280 ClassGetVpb(
1281   _In_ PDEVICE_OBJECT DeviceObject);
1282 
1283 SCSIPORT_API
1284 NTSTATUS
1285 NTAPI
1286 ClassSpinDownPowerHandler(
1287   _In_ PDEVICE_OBJECT DeviceObject,
1288   _In_ PIRP Irp);
1289 
1290 NTSTATUS
1291 NTAPI
1292 ClassStopUnitPowerHandler(
1293   _In_ PDEVICE_OBJECT DeviceObject,
1294   _In_ PIRP Irp);
1295 
1296 _IRQL_requires_max_(PASSIVE_LEVEL)
1297 NTSTATUS
1298 NTAPI
1299 ClassSetFailurePredictionPoll(
1300   _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1301   _In_ FAILURE_PREDICTION_METHOD FailurePredictionMethod,
1302   _In_ ULONG PollingPeriod);
1303 
1304 _IRQL_requires_max_(DISPATCH_LEVEL)
1305 VOID
1306 NTAPI
1307 ClassNotifyFailurePredicted(
1308   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1309   _In_reads_bytes_(BufferSize) PUCHAR Buffer,
1310   _In_ ULONG BufferSize,
1311   _In_ BOOLEAN LogError,
1312   _In_ ULONG UniqueErrorValue,
1313   _In_ UCHAR PathId,
1314   _In_ UCHAR TargetId,
1315   _In_ UCHAR Lun);
1316 
1317 _IRQL_requires_max_(PASSIVE_LEVEL)
1318 SCSIPORT_API
1319 VOID
1320 NTAPI
1321 ClassAcquireChildLock(
1322   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1323 
1324 SCSIPORT_API
1325 VOID
1326 NTAPI
1327 ClassReleaseChildLock(
1328   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1329 
1330 IO_COMPLETION_ROUTINE ClassSignalCompletion;
1331 
1332 VOID
1333 NTAPI
1334 ClassSendStartUnit(
1335   _In_ PDEVICE_OBJECT DeviceObject);
1336 
1337 _IRQL_requires_max_(PASSIVE_LEVEL)
1338 SCSIPORT_API
1339 NTSTATUS
1340 NTAPI
1341 ClassRemoveDevice(
1342   _In_ PDEVICE_OBJECT DeviceObject,
1343   _In_ UCHAR RemoveType);
1344 
1345 SCSIPORT_API
1346 NTSTATUS
1347 NTAPI
1348 ClassAsynchronousCompletion(
1349   PDEVICE_OBJECT DeviceObject,
1350   PIRP Irp,
1351   PVOID Event);
1352 
1353 SCSIPORT_API
1354 VOID
1355 NTAPI
1356 ClassCheckMediaState(
1357   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1358 
1359 SCSIPORT_API
1360 NTSTATUS
1361 NTAPI
1362 ClassCheckVerifyComplete(
1363   PDEVICE_OBJECT DeviceObject,
1364   PIRP Irp,
1365   PVOID Context);
1366 
1367 _IRQL_requires_max_(PASSIVE_LEVEL)
1368 SCSIPORT_API
1369 VOID
1370 NTAPI
1371 ClassSetMediaChangeState(
1372   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1373   _In_ MEDIA_CHANGE_DETECTION_STATE State,
1374   _In_ BOOLEAN Wait);
1375 
1376 _IRQL_requires_max_(PASSIVE_LEVEL)
1377 SCSIPORT_API
1378 VOID
1379 NTAPI
1380 ClassEnableMediaChangeDetection(
1381   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1382 
1383 _IRQL_requires_max_(PASSIVE_LEVEL)
1384 SCSIPORT_API
1385 VOID
1386 NTAPI
1387 ClassDisableMediaChangeDetection(
1388   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1389 
1390 _IRQL_requires_max_(PASSIVE_LEVEL)
1391 SCSIPORT_API
1392 VOID
1393 NTAPI
1394 ClassCleanupMediaChangeDetection(
1395   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1396 
1397 _IRQL_requires_max_(PASSIVE_LEVEL)
1398 VOID
1399 NTAPI
1400 ClassGetDeviceParameter(
1401   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1402   _In_opt_ PWSTR SubkeyName,
1403   _In_ PWSTR ParameterName,
1404   _Inout_ PULONG ParameterValue);
1405 
1406 _IRQL_requires_max_(PASSIVE_LEVEL)
1407 NTSTATUS
1408 NTAPI
1409 ClassSetDeviceParameter(
1410   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1411   _In_opt_ PWSTR SubkeyName,
1412   _In_ PWSTR ParameterName,
1413   _In_ ULONG ParameterValue);
1414 
1415 #if (NTDDI_VERSION >= NTDDI_VISTA)
1416 
1417 _IRQL_requires_max_(PASSIVE_LEVEL)
1418 PFILE_OBJECT_EXTENSION
1419 NTAPI
1420 ClassGetFsContext(
1421   _In_ PCOMMON_DEVICE_EXTENSION CommonExtension,
1422   _In_ PFILE_OBJECT FileObject);
1423 
1424 _IRQL_requires_max_(DISPATCH_LEVEL)
1425 VOID
1426 NTAPI
1427 ClassSendNotification(
1428   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1429   _In_ const GUID *Guid,
1430   _In_ ULONG ExtraDataSize,
1431   _In_reads_bytes_opt_(ExtraDataSize) PVOID ExtraData);
1432 
1433 #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */
1434 
1435 FORCEINLINE
1436 UCHAR
GET_FDO_EXTENSON_SENSE_DATA_LENGTH(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)1437 GET_FDO_EXTENSON_SENSE_DATA_LENGTH (
1438   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
1439 {
1440   UCHAR SenseDataLength = 0;
1441 
1442   if (FdoExtension->SenseData != NULL)
1443   {
1444 #if (NTDDI_VERSION >= NTDDI_WIN8)
1445     if (FdoExtension->SenseDataLength > 0)
1446     {
1447         SenseDataLength = FdoExtension->SenseDataLength;
1448     }
1449     else
1450     {
1451         // For backward compatibility with Windows 7 and earlier
1452         SenseDataLength = SENSE_BUFFER_SIZE;
1453     }
1454 #else
1455     SenseDataLength = SENSE_BUFFER_SIZE;
1456 #endif
1457   }
1458 
1459   return SenseDataLength;
1460 }
1461 
1462 static __inline
1463 BOOLEAN
PORT_ALLOCATED_SENSE(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,_In_ PSCSI_REQUEST_BLOCK Srb)1464 PORT_ALLOCATED_SENSE(
1465   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1466   _In_ PSCSI_REQUEST_BLOCK Srb)
1467 {
1468   return ((BOOLEAN)((TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE) &&
1469           TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER))                &&
1470           (Srb->SenseInfoBuffer != FdoExtension->SenseData)));
1471 }
1472 
1473 static __inline
1474 VOID
FREE_PORT_ALLOCATED_SENSE_BUFFER(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,_In_ PSCSI_REQUEST_BLOCK Srb)1475 FREE_PORT_ALLOCATED_SENSE_BUFFER(
1476   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1477   _In_ PSCSI_REQUEST_BLOCK Srb)
1478 {
1479   ASSERT(TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
1480   ASSERT(TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
1481   ASSERT(Srb->SenseInfoBuffer != FdoExtension->SenseData);
1482 
1483   ExFreePool(Srb->SenseInfoBuffer);
1484   Srb->SenseInfoBuffer = FdoExtension->SenseData;
1485   Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1486   CLEAR_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER);
1487   return;
1488 }
1489 
1490 _IRQL_requires_max_(PASSIVE_LEVEL)
1491 typedef VOID
1492 (NTAPI *PCLASS_SCAN_FOR_SPECIAL_HANDLER)(
1493   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1494   _In_ ULONG_PTR Data);
1495 
1496 _IRQL_requires_max_(PASSIVE_LEVEL)
1497 VOID
1498 NTAPI
1499 ClassScanForSpecial(
1500   _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1501   _In_ CLASSPNP_SCAN_FOR_SPECIAL_INFO DeviceList[],
1502   _In_ PCLASS_SCAN_FOR_SPECIAL_HANDLER Function);
1503