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 
89 #define MAXIMUM_RETRIES 4
90 
91 #define CLASS_DRIVER_EXTENSION_KEY ((PVOID) ClassInitialize)
92 
93 #define NO_REMOVE                         0
94 #define REMOVE_PENDING                    1
95 #define REMOVE_COMPLETE                   2
96 
97 #define ClassAcquireRemoveLock(devobj, tag) \
98   ClassAcquireRemoveLockEx(devobj, tag, __FILE__, __LINE__)
99 
100 #ifdef TRY
101 #undef TRY
102 #endif
103 #ifdef LEAVE
104 #undef LEAVE
105 #endif
106 
107 #ifdef FINALLY
108 #undef FINALLY
109 #endif
110 
111 #define TRY
112 #define LEAVE             goto __tryLabel;
113 #define FINALLY           __tryLabel:
114 
115 #if defined DebugPrint
116 #undef DebugPrint
117 #endif
118 
119 #if DBG
120 #define DebugPrint(x) ClassDebugPrint x
121 #else
122 #define DebugPrint(x)
123 #endif
124 
125 #define DEBUG_BUFFER_LENGTH                        256
126 
127 #define START_UNIT_TIMEOUT                         (60 * 4)
128 
129 #define MEDIA_CHANGE_DEFAULT_TIME                  1
130 #define MEDIA_CHANGE_TIMEOUT_TIME                  300
131 
132 #define MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS 0x3b9aca00
133 
134 #ifdef ALLOCATE_SRB_FROM_POOL
135 
136 #define ClasspAllocateSrb(ext)                      \
137   ExAllocatePoolWithTag(NonPagedPool,               \
138                         sizeof(SCSI_REQUEST_BLOCK), \
139                         'sBRS')
140 
141 #define ClasspFreeSrb(ext, srb) ExFreePool((srb));
142 
143 #else /* ALLOCATE_SRB_FROM_POOL */
144 
145 #define ClasspAllocateSrb(ext)                      \
146   ExAllocateFromNPagedLookasideList(                \
147       &((ext)->CommonExtension.SrbLookasideList))
148 
149 #define ClasspFreeSrb(ext, srb)                   \
150   ExFreeToNPagedLookasideList(                    \
151       &((ext)->CommonExtension.SrbLookasideList), \
152       (srb))
153 
154 #endif /* ALLOCATE_SRB_FROM_POOL */
155 
156 #define SET_FLAG(Flags, Bit)    ((Flags) |= (Bit))
157 #define CLEAR_FLAG(Flags, Bit)  ((Flags) &= ~(Bit))
158 #define TEST_FLAG(Flags, Bit)   (((Flags) & (Bit)) != 0)
159 
160 #define CLASS_WORKING_SET_MAXIMUM                         2048
161 
162 #define CLASS_INTERPRET_SENSE_INFO2_MAXIMUM_HISTORY_COUNT 30000
163 
164 #define CLASS_SPECIAL_DISABLE_SPIN_DOWN                 0x00000001
165 #define CLASS_SPECIAL_DISABLE_SPIN_UP                   0x00000002
166 #define CLASS_SPECIAL_NO_QUEUE_LOCK                     0x00000008
167 #define CLASS_SPECIAL_DISABLE_WRITE_CACHE               0x00000010
168 #define CLASS_SPECIAL_CAUSE_NOT_REPORTABLE_HACK         0x00000020
169 #if ((NTDDI_VERSION == NTDDI_WIN2KSP3) || (OSVER(NTDDI_VERSION) == NTDDI_WINXP))
170 #define CLASS_SPECIAL_DISABLE_WRITE_CACHE_NOT_SUPPORTED 0x00000040
171 #endif
172 #define CLASS_SPECIAL_MODIFY_CACHE_UNSUCCESSFUL         0x00000040
173 #define CLASS_SPECIAL_FUA_NOT_SUPPORTED                 0x00000080
174 #define CLASS_SPECIAL_VALID_MASK                        0x000000FB
175 #define CLASS_SPECIAL_RESERVED         (~CLASS_SPECIAL_VALID_MASK)
176 
177 #define DEV_WRITE_CACHE                                 0x00000001
178 #define DEV_USE_SCSI1                                   0x00000002
179 #define DEV_SAFE_START_UNIT                             0x00000004
180 #define DEV_NO_12BYTE_CDB                               0x00000008
181 #define DEV_POWER_PROTECTED                             0x00000010
182 #define DEV_USE_16BYTE_CDB                              0x00000020
183 
184 #define GUID_CLASSPNP_QUERY_REGINFOEX {0x00e34b11, 0x2444, 0x4745, {0xa5, 0x3d, 0x62, 0x01, 0x00, 0xcd, 0x82, 0xf7}}
185 #define GUID_CLASSPNP_SENSEINFO2      {0x509a8c5f, 0x71d7, 0x48f6, {0x82, 0x1e, 0x17, 0x3c, 0x49, 0xbf, 0x2f, 0x18}}
186 #define GUID_CLASSPNP_WORKING_SET     {0x105701b0, 0x9e9b, 0x47cb, {0x97, 0x80, 0x81, 0x19, 0x8a, 0xf7, 0xb5, 0x24}}
187 
188 #define DEFAULT_FAILURE_PREDICTION_PERIOD 60 * 60 * 1
189 
CountOfSetBitsUChar(UCHAR _X)190 static inline ULONG CountOfSetBitsUChar(UCHAR _X)
191 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsULong(ULONG _X)192 static inline ULONG CountOfSetBitsULong(ULONG _X)
193 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsULong32(ULONG32 _X)194 static inline ULONG CountOfSetBitsULong32(ULONG32 _X)
195 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsULong64(ULONG64 _X)196 static inline ULONG CountOfSetBitsULong64(ULONG64 _X)
197 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsUlongPtr(ULONG_PTR _X)198 static inline ULONG CountOfSetBitsUlongPtr(ULONG_PTR _X)
199 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
200 
201 typedef enum _MEDIA_CHANGE_DETECTION_STATE {
202   MediaUnknown,
203   MediaPresent,
204   MediaNotPresent,
205   MediaUnavailable
206 } MEDIA_CHANGE_DETECTION_STATE, *PMEDIA_CHANGE_DETECTION_STATE;
207 
208 typedef enum _CLASS_DEBUG_LEVEL {
209   ClassDebugError = 0,
210   ClassDebugWarning = 1,
211   ClassDebugTrace = 2,
212   ClassDebugInfo = 3,
213   ClassDebugMediaLocks = 8,
214   ClassDebugMCN = 9,
215   ClassDebugDelayedRetry = 10,
216   ClassDebugSenseInfo = 11,
217   ClassDebugRemoveLock = 12,
218   ClassDebugExternal4 = 13,
219   ClassDebugExternal3 = 14,
220   ClassDebugExternal2 = 15,
221   ClassDebugExternal1 = 16
222 } CLASS_DEBUG_LEVEL, *PCLASS_DEBUG_LEVEL;
223 
224 typedef enum {
225   EventGeneration,
226   DataBlockCollection
227 } CLASSENABLEDISABLEFUNCTION;
228 
229 typedef enum {
230   FailurePredictionNone = 0,
231   FailurePredictionIoctl,
232   FailurePredictionSmart,
233   FailurePredictionSense
234 } FAILURE_PREDICTION_METHOD, *PFAILURE_PREDICTION_METHOD;
235 
236 typedef enum {
237   PowerDownDeviceInitial,
238   PowerDownDeviceLocked,
239   PowerDownDeviceStopped,
240   PowerDownDeviceOff,
241   PowerDownDeviceUnlocked
242 } CLASS_POWER_DOWN_STATE;
243 
244 typedef enum {
245   PowerDownDeviceInitial2,
246   PowerDownDeviceLocked2,
247   PowerDownDeviceFlushed2,
248   PowerDownDeviceStopped2,
249   PowerDownDeviceOff2,
250   PowerDownDeviceUnlocked2
251 } CLASS_POWER_DOWN_STATE2;
252 
253 typedef enum {
254   PowerUpDeviceInitial,
255   PowerUpDeviceLocked,
256   PowerUpDeviceOn,
257   PowerUpDeviceStarted,
258   PowerUpDeviceUnlocked
259 } CLASS_POWER_UP_STATE;
260 
261 struct _CLASS_INIT_DATA;
262 typedef struct _CLASS_INIT_DATA CLASS_INIT_DATA, *PCLASS_INIT_DATA;
263 
264 struct _CLASS_PRIVATE_FDO_DATA;
265 typedef struct _CLASS_PRIVATE_FDO_DATA CLASS_PRIVATE_FDO_DATA, *PCLASS_PRIVATE_FDO_DATA;
266 
267 struct _CLASS_PRIVATE_PDO_DATA;
268 typedef struct _CLASS_PRIVATE_PDO_DATA CLASS_PRIVATE_PDO_DATA, *PCLASS_PRIVATE_PDO_DATA;
269 
270 struct _CLASS_PRIVATE_COMMON_DATA;
271 typedef struct _CLASS_PRIVATE_COMMON_DATA CLASS_PRIVATE_COMMON_DATA, *PCLASS_PRIVATE_COMMON_DATA;
272 
273 struct _MEDIA_CHANGE_DETECTION_INFO;
274 typedef struct _MEDIA_CHANGE_DETECTION_INFO MEDIA_CHANGE_DETECTION_INFO, *PMEDIA_CHANGE_DETECTION_INFO;
275 
276 typedef struct _DICTIONARY {
277   ULONGLONG Signature;
278   struct _DICTIONARY_HEADER* List;
279   KSPIN_LOCK SpinLock;
280 } DICTIONARY, *PDICTIONARY;
281 
282 typedef struct _CLASSPNP_SCAN_FOR_SPECIAL_INFO {
283   PCHAR VendorId;
284   PCHAR ProductId;
285   PCHAR ProductRevision;
286   ULONG_PTR Data;
287 } CLASSPNP_SCAN_FOR_SPECIAL_INFO, *PCLASSPNP_SCAN_FOR_SPECIAL_INFO;
288 
289 typedef VOID
290 (NTAPI *PCLASS_ERROR)(
291   PDEVICE_OBJECT DeviceObject,
292   PSCSI_REQUEST_BLOCK Srb,
293   NTSTATUS *Status,
294   BOOLEAN *Retry);
295 
296 typedef NTSTATUS
297 (NTAPI *PCLASS_ADD_DEVICE)(
298   PDRIVER_OBJECT DriverObject,
299   PDEVICE_OBJECT Pdo);
300 
301 typedef NTSTATUS
302 (NTAPI *PCLASS_POWER_DEVICE)(
303   PDEVICE_OBJECT DeviceObject,
304   PIRP Irp);
305 
306 typedef NTSTATUS
307 (NTAPI *PCLASS_START_DEVICE)(
308   PDEVICE_OBJECT DeviceObject);
309 
310 typedef NTSTATUS
311 (NTAPI *PCLASS_STOP_DEVICE)(
312   PDEVICE_OBJECT DeviceObject,
313   UCHAR Type);
314 
315 typedef NTSTATUS
316 (NTAPI *PCLASS_INIT_DEVICE)(
317   PDEVICE_OBJECT DeviceObject);
318 
319 typedef NTSTATUS
320 (NTAPI *PCLASS_ENUM_DEVICE)(
321   PDEVICE_OBJECT DeviceObject);
322 
323 typedef NTSTATUS
324 (NTAPI *PCLASS_READ_WRITE)(
325   PDEVICE_OBJECT DeviceObject,
326   PIRP Irp);
327 
328 typedef NTSTATUS
329 (NTAPI *PCLASS_DEVICE_CONTROL)(
330   PDEVICE_OBJECT DeviceObject,
331   PIRP Irp);
332 
333 typedef NTSTATUS
334 (NTAPI *PCLASS_SHUTDOWN_FLUSH)(
335   PDEVICE_OBJECT DeviceObject,
336   PIRP Irp);
337 
338 typedef NTSTATUS
339 (NTAPI *PCLASS_CREATE_CLOSE)(
340   PDEVICE_OBJECT DeviceObject,
341   PIRP Irp);
342 
343 typedef NTSTATUS
344 (NTAPI *PCLASS_QUERY_ID)(
345   PDEVICE_OBJECT DeviceObject,
346   BUS_QUERY_ID_TYPE IdType,
347   PUNICODE_STRING IdString);
348 
349 typedef NTSTATUS
350 (NTAPI *PCLASS_REMOVE_DEVICE)(
351   PDEVICE_OBJECT DeviceObject,
352   UCHAR Type);
353 
354 typedef VOID
355 (NTAPI *PCLASS_UNLOAD)(
356   PDRIVER_OBJECT DriverObject);
357 
358 typedef NTSTATUS
359 (NTAPI *PCLASS_QUERY_PNP_CAPABILITIES)(
360   PDEVICE_OBJECT PhysicalDeviceObject,
361   PDEVICE_CAPABILITIES Capabilities);
362 
363 typedef VOID
364 (NTAPI *PCLASS_TICK)(
365   PDEVICE_OBJECT DeviceObject);
366 
367 typedef NTSTATUS
368 (NTAPI *PCLASS_QUERY_WMI_REGINFO_EX)(
369   PDEVICE_OBJECT DeviceObject,
370   ULONG *RegFlags,
371   PUNICODE_STRING Name,
372   PUNICODE_STRING MofResouceName);
373 
374 typedef NTSTATUS
375 (NTAPI *PCLASS_QUERY_WMI_REGINFO)(
376   PDEVICE_OBJECT DeviceObject,
377   ULONG *RegFlags,
378   PUNICODE_STRING Name);
379 
380 typedef NTSTATUS
381 (NTAPI *PCLASS_QUERY_WMI_DATABLOCK)(
382   PDEVICE_OBJECT DeviceObject,
383   PIRP Irp,
384   ULONG GuidIndex,
385   ULONG BufferAvail,
386   PUCHAR Buffer);
387 
388 typedef NTSTATUS
389 (NTAPI *PCLASS_SET_WMI_DATABLOCK)(
390   PDEVICE_OBJECT DeviceObject,
391   PIRP Irp,
392   ULONG GuidIndex,
393   ULONG BufferSize,
394   PUCHAR Buffer);
395 
396 typedef NTSTATUS
397 (NTAPI *PCLASS_SET_WMI_DATAITEM)(
398   PDEVICE_OBJECT DeviceObject,
399   PIRP Irp,
400   ULONG GuidIndex,
401   ULONG DataItemId,
402   ULONG BufferSize,
403   PUCHAR Buffer);
404 
405 typedef NTSTATUS
406 (NTAPI *PCLASS_EXECUTE_WMI_METHOD)(
407   PDEVICE_OBJECT DeviceObject,
408   PIRP Irp,
409   ULONG GuidIndex,
410   ULONG MethodId,
411   ULONG InBufferSize,
412   ULONG OutBufferSize,
413   PUCHAR Buffer);
414 
415 typedef NTSTATUS
416 (NTAPI *PCLASS_WMI_FUNCTION_CONTROL)(
417   PDEVICE_OBJECT DeviceObject,
418   PIRP Irp,
419   ULONG GuidIndex,
420   CLASSENABLEDISABLEFUNCTION Function,
421   BOOLEAN Enable);
422 
423 typedef struct _SRB_HISTORY_ITEM {
424   LARGE_INTEGER TickCountSent;
425   LARGE_INTEGER TickCountCompleted;
426   ULONG MillisecondsDelayOnRetry;
427   SENSE_DATA NormalizedSenseData;
428   UCHAR SrbStatus;
429   UCHAR ClassDriverUse;
430 } SRB_HISTORY_ITEM, *PSRB_HISTORY_ITEM;
431 
432 typedef struct _SRB_HISTORY {
433   ULONG_PTR ClassDriverUse[4];
434   ULONG TotalHistoryCount;
435   ULONG UsedHistoryCount;
436   SRB_HISTORY_ITEM History[1];
437 } SRB_HISTORY, *PSRB_HISTORY;
438 
439 typedef BOOLEAN
440 (NTAPI *PCLASS_INTERPRET_SENSE_INFO)(
441   PDEVICE_OBJECT Fdo,
442   PIRP OriginalRequest,
443   PSCSI_REQUEST_BLOCK Srb,
444   UCHAR MajorFunctionCode,
445   ULONG IoDeviceCode,
446   ULONG PreviousRetryCount,
447   SRB_HISTORY *RequestHistory,
448   NTSTATUS *Status,
449   LONGLONG *RetryIn100nsUnits);
450 
451 typedef VOID
452 (NTAPI *PCLASS_COMPRESS_RETRY_HISTORY_DATA)(
453   PDEVICE_OBJECT DeviceObject,
454   PSRB_HISTORY RequestHistory);
455 
456 typedef struct {
457   GUID Guid;
458   ULONG InstanceCount;
459   ULONG Flags;
460 } GUIDREGINFO, *PGUIDREGINFO;
461 
462 typedef struct _CLASS_WMI_INFO {
463   ULONG GuidCount;
464   PGUIDREGINFO GuidRegInfo;
465   PCLASS_QUERY_WMI_REGINFO ClassQueryWmiRegInfo;
466   PCLASS_QUERY_WMI_DATABLOCK ClassQueryWmiDataBlock;
467   PCLASS_SET_WMI_DATABLOCK ClassSetWmiDataBlock;
468   PCLASS_SET_WMI_DATAITEM ClassSetWmiDataItem;
469   PCLASS_EXECUTE_WMI_METHOD ClassExecuteWmiMethod;
470   PCLASS_WMI_FUNCTION_CONTROL ClassWmiFunctionControl;
471 } CLASS_WMI_INFO, *PCLASS_WMI_INFO;
472 
473 typedef struct _CLASS_DEV_INFO {
474   ULONG DeviceExtensionSize;
475   DEVICE_TYPE DeviceType;
476   UCHAR StackSize;
477   ULONG DeviceCharacteristics;
478   PCLASS_ERROR ClassError;
479   PCLASS_READ_WRITE ClassReadWriteVerification;
480   PCLASS_DEVICE_CONTROL ClassDeviceControl;
481   PCLASS_SHUTDOWN_FLUSH ClassShutdownFlush;
482   PCLASS_CREATE_CLOSE ClassCreateClose;
483   PCLASS_INIT_DEVICE ClassInitDevice;
484   PCLASS_START_DEVICE ClassStartDevice;
485   PCLASS_POWER_DEVICE ClassPowerDevice;
486   PCLASS_STOP_DEVICE ClassStopDevice;
487   PCLASS_REMOVE_DEVICE ClassRemoveDevice;
488   PCLASS_QUERY_PNP_CAPABILITIES ClassQueryPnpCapabilities;
489   CLASS_WMI_INFO ClassWmiInfo;
490 } CLASS_DEV_INFO, *PCLASS_DEV_INFO;
491 
492 struct _CLASS_INIT_DATA {
493   ULONG InitializationDataSize;
494   CLASS_DEV_INFO FdoData;
495   CLASS_DEV_INFO PdoData;
496   PCLASS_ADD_DEVICE ClassAddDevice;
497   PCLASS_ENUM_DEVICE ClassEnumerateDevice;
498   PCLASS_QUERY_ID ClassQueryId;
499   PDRIVER_STARTIO ClassStartIo;
500   PCLASS_UNLOAD ClassUnload;
501   PCLASS_TICK ClassTick;
502 };
503 
504 typedef struct _FILE_OBJECT_EXTENSION {
505   PFILE_OBJECT FileObject;
506   PDEVICE_OBJECT DeviceObject;
507   ULONG LockCount;
508   ULONG McnDisableCount;
509 } FILE_OBJECT_EXTENSION, *PFILE_OBJECT_EXTENSION;
510 
511 typedef struct _CLASS_WORKING_SET {
512   ULONG Size;
513   ULONG XferPacketsWorkingSetMaximum;
514   ULONG XferPacketsWorkingSetMinimum;
515 } CLASS_WORKING_SET, *PCLASS_WORKING_SET;
516 
517 typedef struct _CLASS_INTERPRET_SENSE_INFO2 {
518   ULONG Size;
519   ULONG HistoryCount;
520   PCLASS_COMPRESS_RETRY_HISTORY_DATA Compress;
521   PCLASS_INTERPRET_SENSE_INFO Interpret;
522 } CLASS_INTERPRET_SENSE_INFO2, *PCLASS_INTERPRET_SENSE_INFO2;
523 
524 C_ASSERT((MAXULONG - sizeof(SRB_HISTORY)) / 30000 >= sizeof(SRB_HISTORY_ITEM));
525 
526 typedef struct _CLASS_DRIVER_EXTENSION {
527   UNICODE_STRING RegistryPath;
528   CLASS_INIT_DATA InitData;
529   ULONG DeviceCount;
530 #if (NTDDI_VERSION >= NTDDI_WINXP)
531   PCLASS_QUERY_WMI_REGINFO_EX ClassFdoQueryWmiRegInfoEx;
532   PCLASS_QUERY_WMI_REGINFO_EX ClassPdoQueryWmiRegInfoEx;
533 #endif
534 #if (NTDDI_VERSION >= NTDDI_VISTA)
535   REGHANDLE EtwHandle;
536   PDRIVER_DISPATCH DeviceMajorFunctionTable[IRP_MJ_MAXIMUM_FUNCTION + 1];
537   PDRIVER_DISPATCH MpDeviceMajorFunctionTable[IRP_MJ_MAXIMUM_FUNCTION + 1];
538   PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo;
539   PCLASS_WORKING_SET WorkingSet;
540 #endif
541 } CLASS_DRIVER_EXTENSION, *PCLASS_DRIVER_EXTENSION;
542 
543 typedef struct _COMMON_DEVICE_EXTENSION {
544   ULONG Version;
545   PDEVICE_OBJECT DeviceObject;
546   PDEVICE_OBJECT LowerDeviceObject;
547   struct _FUNCTIONAL_DEVICE_EXTENSION *PartitionZeroExtension;
548   PCLASS_DRIVER_EXTENSION DriverExtension;
549   LONG RemoveLock;
550   KEVENT RemoveEvent;
551   KSPIN_LOCK RemoveTrackingSpinlock;
552   PVOID RemoveTrackingList;
553   LONG RemoveTrackingUntrackedCount;
554   PVOID DriverData;
555   _ANONYMOUS_STRUCT struct {
556     BOOLEAN IsFdo:1;
557     BOOLEAN IsInitialized:1;
558     BOOLEAN IsSrbLookasideListInitialized:1;
559   } DUMMYSTRUCTNAME;
560   UCHAR PreviousState;
561   UCHAR CurrentState;
562   ULONG IsRemoved;
563   UNICODE_STRING DeviceName;
564   struct _PHYSICAL_DEVICE_EXTENSION *ChildList;
565   ULONG PartitionNumber;
566   LARGE_INTEGER PartitionLength;
567   LARGE_INTEGER StartingOffset;
568   PCLASS_DEV_INFO DevInfo;
569   ULONG PagingPathCount;
570   ULONG DumpPathCount;
571   ULONG HibernationPathCount;
572   KEVENT PathCountEvent;
573 #ifndef ALLOCATE_SRB_FROM_POOL
574   NPAGED_LOOKASIDE_LIST SrbLookasideList;
575 #endif
576   UNICODE_STRING MountedDeviceInterfaceName;
577   ULONG GuidCount;
578   PGUIDREGINFO GuidRegInfo;
579   DICTIONARY FileObjectDictionary;
580 #if (NTDDI_VERSION >= NTDDI_WINXP)
581   PCLASS_PRIVATE_COMMON_DATA PrivateCommonData;
582 #else
583   ULONG_PTR Reserved1;
584 #endif
585 #if (NTDDI_VERSION >= NTDDI_VISTA)
586   PDRIVER_DISPATCH *DispatchTable;
587 #else
588   ULONG_PTR Reserved2;
589 #endif
590   ULONG_PTR Reserved3;
591   ULONG_PTR Reserved4;
592 } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
593 
594 typedef struct _PHYSICAL_DEVICE_EXTENSION {
595   _ANONYMOUS_UNION union {
596     _ANONYMOUS_STRUCT struct {
597       ULONG Version;
598       PDEVICE_OBJECT DeviceObject;
599     } DUMMYSTRUCTNAME;
600     COMMON_DEVICE_EXTENSION CommonExtension;
601   } DUMMYUNIONNAME;
602   BOOLEAN IsMissing;
603   BOOLEAN IsEnumerated;
604 #if (NTDDI_VERSION >= NTDDI_WINXP)
605   PCLASS_PRIVATE_PDO_DATA PrivatePdoData;
606 #else
607   ULONG_PTR Reserved1;
608 #endif
609   ULONG_PTR Reserved2;
610   ULONG_PTR Reserved3;
611   ULONG_PTR Reserved4;
612 } PHYSICAL_DEVICE_EXTENSION, *PPHYSICAL_DEVICE_EXTENSION;
613 
614 typedef struct _CLASS_POWER_OPTIONS {
615   ULONG PowerDown:1;
616   ULONG LockQueue:1;
617   ULONG HandleSpinDown:1;
618   ULONG HandleSpinUp:1;
619   ULONG Reserved:27;
620 } CLASS_POWER_OPTIONS, *PCLASS_POWER_OPTIONS;
621 
622 typedef struct _CLASS_POWER_CONTEXT {
623   union {
624     CLASS_POWER_DOWN_STATE PowerDown;
625     CLASS_POWER_DOWN_STATE2 PowerDown2;
626     CLASS_POWER_UP_STATE PowerUp;
627   } PowerChangeState;
628   CLASS_POWER_OPTIONS Options;
629   BOOLEAN InUse;
630   BOOLEAN QueueLocked;
631   NTSTATUS FinalStatus;
632   ULONG RetryCount;
633   ULONG RetryInterval;
634   PIO_COMPLETION_ROUTINE CompletionRoutine;
635   PDEVICE_OBJECT DeviceObject;
636   PIRP Irp;
637   SCSI_REQUEST_BLOCK Srb;
638 } CLASS_POWER_CONTEXT, *PCLASS_POWER_CONTEXT;
639 
640 typedef struct _COMPLETION_CONTEXT {
641   PDEVICE_OBJECT DeviceObject;
642   SCSI_REQUEST_BLOCK Srb;
643 } COMPLETION_CONTEXT, *PCOMPLETION_CONTEXT;
644 
645 SCSIPORTAPI
646 ULONG
647 NTAPI
648 ClassInitialize(
649   PVOID Argument1,
650   PVOID Argument2,
651   PCLASS_INIT_DATA InitializationData);
652 
653 typedef struct _CLASS_QUERY_WMI_REGINFO_EX_LIST {
654   ULONG Size;
655   PCLASS_QUERY_WMI_REGINFO_EX ClassFdoQueryWmiRegInfoEx;
656   PCLASS_QUERY_WMI_REGINFO_EX ClassPdoQueryWmiRegInfoEx;
657 } CLASS_QUERY_WMI_REGINFO_EX_LIST, *PCLASS_QUERY_WMI_REGINFO_EX_LIST;
658 
659 typedef struct _FUNCTIONAL_DEVICE_EXTENSION {
660   _ANONYMOUS_UNION union {
661     _ANONYMOUS_STRUCT struct {
662       ULONG Version;
663       PDEVICE_OBJECT DeviceObject;
664     } DUMMYSTRUCTNAME;
665     COMMON_DEVICE_EXTENSION CommonExtension;
666   } DUMMYUNIONNAME;
667   PDEVICE_OBJECT LowerPdo;
668   PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor;
669   PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor;
670   DEVICE_POWER_STATE DevicePowerState;
671   ULONG DMByteSkew;
672   ULONG DMSkew;
673   BOOLEAN DMActive;
674   DISK_GEOMETRY DiskGeometry;
675   PSENSE_DATA SenseData;
676   ULONG TimeOutValue;
677   ULONG DeviceNumber;
678   ULONG SrbFlags;
679   ULONG ErrorCount;
680   LONG LockCount;
681   LONG ProtectedLockCount;
682   LONG InternalLockCount;
683   KEVENT EjectSynchronizationEvent;
684   USHORT DeviceFlags;
685   UCHAR SectorShift;
686 #if (NTDDI_VERSION >= NTDDI_VISTA)
687   UCHAR CdbForceUnitAccess;
688 #else
689   UCHAR ReservedByte;
690 #endif
691   PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo;
692   PKEVENT Unused1;
693   HANDLE Unused2;
694   FILE_OBJECT_EXTENSION KernelModeMcnContext;
695   ULONG MediaChangeCount;
696   HANDLE DeviceDirectory;
697   KSPIN_LOCK ReleaseQueueSpinLock;
698   PIRP ReleaseQueueIrp;
699   SCSI_REQUEST_BLOCK ReleaseQueueSrb;
700   BOOLEAN ReleaseQueueNeeded;
701   BOOLEAN ReleaseQueueInProgress;
702   BOOLEAN ReleaseQueueIrpFromPool;
703   BOOLEAN FailurePredicted;
704   ULONG FailureReason;
705   struct _FAILURE_PREDICTION_INFO* FailurePredictionInfo;
706   BOOLEAN PowerDownInProgress;
707   ULONG EnumerationInterlock;
708   KEVENT ChildLock;
709   PKTHREAD ChildLockOwner;
710   ULONG ChildLockAcquisitionCount;
711   ULONG ScanForSpecialFlags;
712   KDPC PowerRetryDpc;
713   KTIMER PowerRetryTimer;
714   CLASS_POWER_CONTEXT PowerContext;
715 
716 #if (NTDDI_VERSION <= NTDDI_WIN2K)
717 
718 #if (SPVER(NTDDI_VERSION) < 2))
719   ULONG_PTR Reserved1;
720   ULONG_PTR Reserved2;
721   ULONG_PTR Reserved3;
722   ULONG_PTR Reserved4;
723 #else
724   ULONG CompletionSuccessCount;
725   ULONG SavedSrbFlags;
726   ULONG SavedErrorCount;
727   ULONG_PTR Reserved1;
728 #endif
729 
730 #else /* (NTDDI_VERSION <= NTDDI_WIN2K) */
731 
732   PCLASS_PRIVATE_FDO_DATA PrivateFdoData;
733   ULONG_PTR Reserved2;
734   ULONG_PTR Reserved3;
735   ULONG_PTR Reserved4;
736 
737 #endif /* (NTDDI_VERSION <= NTDDI_WIN2K) */
738 
739 } FUNCTIONAL_DEVICE_EXTENSION, *PFUNCTIONAL_DEVICE_EXTENSION;
740 
741 SCSIPORTAPI
742 ULONG
743 NTAPI
744 ClassInitializeEx(
745   PDRIVER_OBJECT DriverObject,
746   LPGUID Guid,
747   PVOID Data);
748 
749 SCSIPORTAPI
750 NTSTATUS
751 NTAPI
752 ClassCreateDeviceObject(
753   PDRIVER_OBJECT DriverObject,
754   PCCHAR ObjectNameBuffer,
755   PDEVICE_OBJECT LowerDeviceObject,
756   BOOLEAN IsFdo,
757   PDEVICE_OBJECT *DeviceObject);
758 
759 SCSIPORTAPI
760 NTSTATUS
761 NTAPI
762 ClassReadDriveCapacity(
763   PDEVICE_OBJECT DeviceObject);
764 
765 SCSIPORTAPI
766 VOID
767 NTAPI
768 ClassReleaseQueue(
769   PDEVICE_OBJECT DeviceObject);
770 
771 SCSIPORTAPI
772 VOID
773 NTAPI
774 ClassSplitRequest(
775   PDEVICE_OBJECT DeviceObject,
776   PIRP Irp,
777   ULONG MaximumBytes);
778 
779 SCSIPORTAPI
780 NTSTATUS
781 NTAPI
782 ClassDeviceControl(
783   PDEVICE_OBJECT DeviceObject,
784   PIRP Irp);
785 
786 SCSIPORTAPI
787 NTSTATUS
788 NTAPI
789 ClassIoComplete(
790   PDEVICE_OBJECT DeviceObject,
791   PIRP Irp,
792   PVOID Context);
793 
794 SCSIPORTAPI
795 NTSTATUS
796 NTAPI
797 ClassIoCompleteAssociated(
798   PDEVICE_OBJECT DeviceObject,
799   PIRP Irp,
800   PVOID Context);
801 
802 SCSIPORTAPI
803 BOOLEAN
804 NTAPI
805 ClassInterpretSenseInfo(
806   PDEVICE_OBJECT DeviceObject,
807   PSCSI_REQUEST_BLOCK Srb,
808   UCHAR MajorFunctionCode,
809   ULONG IoDeviceCode,
810   ULONG RetryCount,
811   NTSTATUS *Status,
812   ULONG *RetryInterval);
813 
814 VOID
815 NTAPI
816 ClassSendDeviceIoControlSynchronous(
817   ULONG IoControlCode,
818   PDEVICE_OBJECT TargetDeviceObject,
819   PVOID Buffer,
820   ULONG InputBufferLength,
821   ULONG OutputBufferLength,
822   BOOLEAN InternalDeviceIoControl,
823   PIO_STATUS_BLOCK IoStatus);
824 
825 SCSIPORTAPI
826 NTSTATUS
827 NTAPI
828 ClassSendIrpSynchronous(
829   PDEVICE_OBJECT TargetDeviceObject,
830   PIRP Irp);
831 
832 SCSIPORTAPI
833 NTSTATUS
834 NTAPI
835 ClassForwardIrpSynchronous(
836   PCOMMON_DEVICE_EXTENSION CommonExtension,
837   PIRP Irp);
838 
839 SCSIPORTAPI
840 NTSTATUS
841 NTAPI
842 ClassSendSrbSynchronous(
843   PDEVICE_OBJECT DeviceObject,
844   PSCSI_REQUEST_BLOCK Srb,
845   PVOID BufferAddress,
846   ULONG BufferLength,
847   BOOLEAN WriteToDevice);
848 
849 SCSIPORTAPI
850 NTSTATUS
851 NTAPI
852 ClassSendSrbAsynchronous(
853   PDEVICE_OBJECT DeviceObject,
854   PSCSI_REQUEST_BLOCK Srb,
855   PIRP Irp,
856   PVOID BufferAddress,
857   ULONG BufferLength,
858   BOOLEAN WriteToDevice);
859 
860 SCSIPORTAPI
861 NTSTATUS
862 NTAPI
863 ClassBuildRequest(
864   PDEVICE_OBJECT DeviceObject,
865   PIRP Irp);
866 
867 SCSIPORTAPI
868 ULONG
869 NTAPI
870 ClassModeSense(
871   PDEVICE_OBJECT DeviceObject,
872   PCHAR ModeSenseBuffer,
873   ULONG Length,
874   UCHAR PageMode);
875 
876 SCSIPORTAPI
877 PVOID
878 NTAPI
879 ClassFindModePage(
880   PCHAR ModeSenseBuffer,
881   ULONG Length,
882   UCHAR PageMode,
883   BOOLEAN Use6Byte);
884 
885 SCSIPORTAPI
886 NTSTATUS
887 NTAPI
888 ClassClaimDevice(
889   PDEVICE_OBJECT LowerDeviceObject,
890   BOOLEAN Release);
891 
892 SCSIPORTAPI
893 NTSTATUS
894 NTAPI
895 ClassInternalIoControl (
896   PDEVICE_OBJECT DeviceObject,
897   PIRP Irp);
898 
899 SCSIPORTAPI
900 VOID
901 NTAPI
902 ClassInitializeSrbLookasideList(
903   PCOMMON_DEVICE_EXTENSION CommonExtension,
904   ULONG NumberElements);
905 
906 SCSIPORTAPI
907 VOID
908 NTAPI
909 ClassDeleteSrbLookasideList(
910   PCOMMON_DEVICE_EXTENSION CommonExtension);
911 
912 SCSIPORTAPI
913 ULONG
914 NTAPI
915 ClassQueryTimeOutRegistryValue(
916   PDEVICE_OBJECT DeviceObject);
917 
918 SCSIPORTAPI
919 NTSTATUS
920 NTAPI
921 ClassGetDescriptor(
922   PDEVICE_OBJECT DeviceObject,
923   PSTORAGE_PROPERTY_ID PropertyId,
924   PSTORAGE_DESCRIPTOR_HEADER *Descriptor);
925 
926 SCSIPORTAPI
927 VOID
928 NTAPI
929 ClassInvalidateBusRelations(
930   PDEVICE_OBJECT Fdo);
931 
932 SCSIPORTAPI
933 VOID
934 NTAPI
935 ClassMarkChildrenMissing(
936   PFUNCTIONAL_DEVICE_EXTENSION Fdo);
937 
938 SCSIPORTAPI
939 BOOLEAN
940 NTAPI
941 ClassMarkChildMissing(
942   PPHYSICAL_DEVICE_EXTENSION PdoExtension,
943   BOOLEAN AcquireChildLock);
944 
945 SCSIPORTAPI
946 VOID
947 ClassDebugPrint(
948   CLASS_DEBUG_LEVEL DebugPrintLevel,
949   PCCHAR DebugMessage,
950   ...);
951 
952 SCSIPORTAPI
953 PCLASS_DRIVER_EXTENSION
954 NTAPI
955 ClassGetDriverExtension(
956   PDRIVER_OBJECT DriverObject);
957 
958 SCSIPORTAPI
959 VOID
960 NTAPI
961 ClassCompleteRequest(
962   PDEVICE_OBJECT DeviceObject,
963   PIRP Irp,
964   CCHAR PriorityBoost);
965 
966 SCSIPORTAPI
967 VOID
968 NTAPI
969 ClassReleaseRemoveLock(
970   PDEVICE_OBJECT DeviceObject,
971   PIRP Tag);
972 
973 SCSIPORTAPI
974 ULONG
975 NTAPI
976 ClassAcquireRemoveLockEx(
977   PDEVICE_OBJECT DeviceObject,
978   PVOID Tag,
979   PCSTR File,
980   ULONG Line);
981 
982 SCSIPORTAPI
983 VOID
984 NTAPI
985 ClassUpdateInformationInRegistry(
986   PDEVICE_OBJECT Fdo,
987   PCHAR DeviceName,
988   ULONG DeviceNumber,
989   PINQUIRYDATA InquiryData,
990   ULONG InquiryDataLength);
991 
992 SCSIPORTAPI
993 NTSTATUS
994 NTAPI
995 ClassWmiCompleteRequest(
996   PDEVICE_OBJECT DeviceObject,
997   PIRP Irp,
998   NTSTATUS Status,
999   ULONG BufferUsed,
1000   CCHAR PriorityBoost);
1001 
1002 SCSIPORTAPI
1003 NTSTATUS
1004 NTAPI
1005 ClassWmiFireEvent(
1006   PDEVICE_OBJECT DeviceObject,
1007   LPGUID Guid,
1008   ULONG InstanceIndex,
1009   ULONG EventDataSize,
1010   PVOID EventData);
1011 
1012 SCSIPORTAPI
1013 VOID
1014 NTAPI
1015 ClassResetMediaChangeTimer(
1016   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1017 
1018 SCSIPORTAPI
1019 VOID
1020 NTAPI
1021 ClassInitializeMediaChangeDetection(
1022   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1023   PUCHAR EventPrefix);
1024 
1025 SCSIPORTAPI
1026 NTSTATUS
1027 NTAPI
1028 ClassInitializeTestUnitPolling(
1029   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1030   BOOLEAN AllowDriveToSleep);
1031 
1032 SCSIPORTAPI
1033 PVPB
1034 NTAPI
1035 ClassGetVpb(
1036   PDEVICE_OBJECT DeviceObject);
1037 
1038 SCSIPORTAPI
1039 NTSTATUS
1040 NTAPI
1041 ClassSpinDownPowerHandler(
1042   PDEVICE_OBJECT DeviceObject,
1043   PIRP Irp);
1044 
1045 NTSTATUS
1046 NTAPI
1047 ClassStopUnitPowerHandler(
1048   PDEVICE_OBJECT DeviceObject,
1049   PIRP Irp);
1050 
1051 NTSTATUS
1052 NTAPI
1053 ClassSetFailurePredictionPoll(
1054   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1055   FAILURE_PREDICTION_METHOD FailurePredictionMethod,
1056   ULONG PollingPeriod);
1057 
1058 VOID
1059 NTAPI
1060 ClassNotifyFailurePredicted(
1061   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1062   PUCHAR Buffer,
1063   ULONG BufferSize,
1064   BOOLEAN LogError,
1065   ULONG UniqueErrorValue,
1066   UCHAR PathId,
1067   UCHAR TargetId,
1068   UCHAR Lun);
1069 
1070 SCSIPORTAPI
1071 VOID
1072 NTAPI
1073 ClassAcquireChildLock(
1074   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1075 
1076 SCSIPORTAPI
1077 VOID
1078 NTAPI
1079 ClassReleaseChildLock(
1080   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1081 
1082 NTSTATUS
1083 NTAPI
1084 ClassSignalCompletion(
1085   PDEVICE_OBJECT DeviceObject,
1086   PIRP Irp,
1087   PKEVENT Event);
1088 
1089 VOID
1090 NTAPI
1091 ClassSendStartUnit(
1092   PDEVICE_OBJECT DeviceObject);
1093 
1094 SCSIPORTAPI
1095 NTSTATUS
1096 NTAPI
1097 ClassRemoveDevice(
1098   PDEVICE_OBJECT DeviceObject,
1099   UCHAR RemoveType);
1100 
1101 SCSIPORTAPI
1102 NTSTATUS
1103 NTAPI
1104 ClassAsynchronousCompletion(
1105   PDEVICE_OBJECT DeviceObject,
1106   PIRP Irp,
1107   PVOID Event);
1108 
1109 SCSIPORTAPI
1110 VOID
1111 NTAPI
1112 ClassCheckMediaState(
1113   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1114 
1115 SCSIPORTAPI
1116 NTSTATUS
1117 NTAPI
1118 ClassCheckVerifyComplete(
1119   PDEVICE_OBJECT DeviceObject,
1120   PIRP Irp,
1121   PVOID Context);
1122 
1123 SCSIPORTAPI
1124 VOID
1125 NTAPI
1126 ClassSetMediaChangeState(
1127   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1128   MEDIA_CHANGE_DETECTION_STATE State,
1129   BOOLEAN Wait);
1130 
1131 SCSIPORTAPI
1132 VOID
1133 NTAPI
1134 ClassEnableMediaChangeDetection(
1135   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1136 
1137 SCSIPORTAPI
1138 VOID
1139 NTAPI
1140 ClassDisableMediaChangeDetection(
1141   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1142 
1143 SCSIPORTAPI
1144 VOID
1145 NTAPI
1146 ClassCleanupMediaChangeDetection(
1147   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension);
1148 
1149 VOID
1150 NTAPI
1151 ClassGetDeviceParameter(
1152   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1153   PWSTR SubkeyName,
1154   PWSTR ParameterName,
1155   PULONG ParameterValue);
1156 
1157 NTSTATUS
1158 NTAPI
1159 ClassSetDeviceParameter(
1160   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1161   PWSTR SubkeyName,
1162   PWSTR ParameterName,
1163   ULONG ParameterValue);
1164 
1165 #if (NTDDI_VERSION >= NTDDI_VISTA)
1166 
1167 PFILE_OBJECT_EXTENSION
1168 NTAPI
1169 ClassGetFsContext(
1170   PCOMMON_DEVICE_EXTENSION CommonExtension,
1171   PFILE_OBJECT FileObject);
1172 
1173 VOID
1174 NTAPI
1175 ClassSendNotification(
1176   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1177   const GUID *Guid,
1178   ULONG ExtraDataSize,
1179   PVOID ExtraData);
1180 
1181 #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */
1182 
1183 static __inline
1184 BOOLEAN
PORT_ALLOCATED_SENSE(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,PSCSI_REQUEST_BLOCK Srb)1185 PORT_ALLOCATED_SENSE(
1186   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1187   PSCSI_REQUEST_BLOCK Srb)
1188 {
1189   return ((BOOLEAN)((TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE) &&
1190           TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER))                &&
1191           (Srb->SenseInfoBuffer != FdoExtension->SenseData)));
1192 }
1193 
1194 static __inline
1195 VOID
FREE_PORT_ALLOCATED_SENSE_BUFFER(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,PSCSI_REQUEST_BLOCK Srb)1196 FREE_PORT_ALLOCATED_SENSE_BUFFER(
1197   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1198   PSCSI_REQUEST_BLOCK Srb)
1199 {
1200   ASSERT(TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
1201   ASSERT(TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
1202   ASSERT(Srb->SenseInfoBuffer != FdoExtension->SenseData);
1203 
1204   ExFreePool(Srb->SenseInfoBuffer);
1205   Srb->SenseInfoBuffer = FdoExtension->SenseData;
1206   Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1207   CLEAR_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER);
1208   return;
1209 }
1210 
1211 typedef VOID
1212 (NTAPI *PCLASS_SCAN_FOR_SPECIAL_HANDLER)(
1213   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1214   ULONG_PTR Data);
1215 
1216 VOID
1217 NTAPI
1218 ClassScanForSpecial(
1219   PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1220   CLASSPNP_SCAN_FOR_SPECIAL_INFO DeviceList[],
1221   PCLASS_SCAN_FOR_SPECIAL_HANDLER Function);
1222