ReactOS  0.4.15-dev-1054-gd029a62
diskwmi.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (C) Microsoft Corporation, 1991 - 2010
4 
5 Module Name:
6 
7  diskwmi.c
8 
9 Abstract:
10 
11  SCSI disk class driver - WMI support routines
12 
13 Environment:
14 
15  kernel mode only
16 
17 Notes:
18 
19 Revision History:
20 
21 --*/
22 
23 #include "disk.h"
24 
25 #ifdef DEBUG_USE_WPP
26 #include "diskwmi.tmh"
27 #endif
28 
32  PSTORAGE_PREDICT_FAILURE checkFailure
33  );
34 
38  PBOOLEAN SupportSmart
39  );
40 
44  PFAILURE_PREDICTION_METHOD FailurePredictCapability,
45  BOOLEAN ScsiAddressAvailable
46  );
47 
51  PSTORAGE_FAILURE_PREDICT_THRESHOLDS DiskSmartThresholds
52  );
53 
58  IN UCHAR LogAddress,
60  );
61 
66  IN UCHAR LogAddress,
68  );
69 
70 IO_WORKITEM_ROUTINE DiskReregWorker;
71 
72 IO_COMPLETION_ROUTINE DiskInfoExceptionComplete;
73 
74 //
75 // WMI reregistration globals
76 //
77 // Since it will take too long to do a mode sense on some drive, we
78 // need a good way to effect the mode sense for the info exceptions
79 // mode page so that we can determine if SMART is supported and enabled
80 // for the drive. So the strategy is to do an asynchronous mode sense
81 // when the device starts and then look at the info exceptions mode
82 // page within the completion routine. Now within the completion
83 // routine we cannot call IoWMIRegistrationControl since we are at DPC
84 // level, so we create a stack of device objects that will be processed
85 // by a single work item that is fired off only when the stack
86 // transitions from empty to non empty.
87 //
91 
93 {
94  {
96  1,
97  0
98  },
99 
100  {
102  1,
104  },
105 
106  {
108  1,
110  },
111 
112  {
114  1,
116  },
117 
118  {
120  1,
122  },
123 
124  {
126  1,
128  },
129 
130  {
132  1,
133  0
134  }
135 };
136 
137 
139 
140 #define DiskGeometryGuid 0
141 #define SmartStatusGuid 1
142 #define SmartDataGuid 2
143 #define SmartPerformFunction 3
144  #define AllowDisallowPerformanceHit 1
145  #define EnableDisableHardwareFailurePrediction 2
146  #define EnableDisableFailurePredictionPolling 3
147  #define GetFailurePredictionCapability 4
148  #define EnableOfflineDiags 5
149 
150 #define SmartEventGuid 4
151 #define SmartThresholdsGuid 5
152 #define ScsiInfoExceptionsGuid 6
153 
154 #ifdef ALLOC_PRAGMA
155 
156 #pragma alloc_text(PAGE, DiskWmiFunctionControl)
157 #pragma alloc_text(PAGE, DiskFdoQueryWmiRegInfo)
158 #pragma alloc_text(PAGE, DiskFdoQueryWmiDataBlock)
159 #pragma alloc_text(PAGE, DiskFdoSetWmiDataBlock)
160 #pragma alloc_text(PAGE, DiskFdoSetWmiDataItem)
161 #pragma alloc_text(PAGE, DiskFdoExecuteWmiMethod)
162 
163 #pragma alloc_text(PAGE, DiskDetectFailurePrediction)
164 #pragma alloc_text(PAGE, DiskEnableDisableFailurePrediction)
165 #pragma alloc_text(PAGE, DiskEnableDisableFailurePredictPolling)
166 #pragma alloc_text(PAGE, DiskReadFailurePredictStatus)
167 #pragma alloc_text(PAGE, DiskReadFailurePredictData)
168 #pragma alloc_text(PAGE, DiskReadFailurePredictThresholds)
169 #pragma alloc_text(PAGE, DiskGetIdentifyInfo)
170 #pragma alloc_text(PAGE, DiskReadSmartLog)
171 #pragma alloc_text(PAGE, DiskWriteSmartLog)
172 #pragma alloc_text(PAGE, DiskPerformSmartCommand)
173 #pragma alloc_text(PAGE, DiskSendFailurePredictIoctl)
174 #pragma alloc_text(PAGE, DiskReregWorker)
175 #pragma alloc_text(PAGE, DiskInitializeReregistration)
176 
177 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
178 #pragma alloc_text(PAGE, DiskGetModePage)
179 #pragma alloc_text(PAGE, DiskEnableInfoExceptions)
180 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
181 
182 #endif
183 
184 
185 //
186 // Note:
187 // Some port drivers assume that the SENDCMDINPARAMS structure will always be atleast
188 // sizeof(SENDCMDINPARAMS). So do not adjust for the [pBuffer] if it isn't being used
189 //
190 
191 //
192 // SMART/IDE specific routines
193 //
194 
195 //
196 // Read SMART data attributes.
197 // SrbControl should be : sizeof(SRB_IO_CONTROL) + MAX[ sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE ]
198 // Attribute data returned at &SendCmdOutParams->bBuffer[0]
199 //
200 #define DiskReadSmartData(FdoExtension, \
201  SrbControl, \
202  BufferSize) \
203  DiskPerformSmartCommand(FdoExtension, \
204  IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS, \
205  SMART_CMD, \
206  READ_ATTRIBUTES, \
207  0, \
208  0, \
209  (SrbControl), \
210  (BufferSize))
211 
212 
213 //
214 // Read SMART data thresholds.
215 // SrbControl should be : sizeof(SRB_IO_CONTROL) + MAX[ sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE ]
216 // Attribute data returned at &SendCmdOutParams->bBuffer[0]
217 //
218 #define DiskReadSmartThresholds(FdoExtension, \
219  SrbControl, \
220  BufferSize) \
221  DiskPerformSmartCommand(FdoExtension, \
222  IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS, \
223  SMART_CMD, \
224  READ_THRESHOLDS, \
225  0, \
226  0, \
227  (SrbControl), \
228  (BufferSize))
229 
230 
231 //
232 // Read SMART status
233 // SrbControl should be : sizeof(SRB_IO_CONTROL) + MAX[ sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS) ]
234 // Failure predicted if SendCmdOutParams->bBuffer[3] == 0xf4 and SendCmdOutParams->bBuffer[4] == 0x2c
235 //
236 #define DiskReadSmartStatus(FdoExtension, \
237  SrbControl, \
238  BufferSize) \
239  DiskPerformSmartCommand(FdoExtension, \
240  IOCTL_SCSI_MINIPORT_RETURN_STATUS, \
241  SMART_CMD, \
242  RETURN_SMART_STATUS, \
243  0, \
244  0, \
245  (SrbControl), \
246  (BufferSize))
247 
248 
249 //
250 // Read disks IDENTIFY data
251 // SrbControl should be : sizeof(SRB_IO_CONTROL) + MAX[ sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE ]
252 // Identify data returned at &SendCmdOutParams->bBuffer[0]
253 //
254 #define DiskGetIdentifyData(FdoExtension, \
255  SrbControl, \
256  BufferSize) \
257  DiskPerformSmartCommand(FdoExtension, \
258  IOCTL_SCSI_MINIPORT_IDENTIFY, \
259  ID_CMD, \
260  0, \
261  0, \
262  0, \
263  (SrbControl), \
264  (BufferSize))
265 
266 
267 //
268 // Enable SMART
269 //
270 _inline NTSTATUS
273  )
274 {
275  UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)] = {0};
276  ULONG bufferSize = sizeof(srbControl);
277 
280  SMART_CMD,
281  ENABLE_SMART,
282  0,
283  0,
284  (PSRB_IO_CONTROL)srbControl,
285  &bufferSize);
286 }
287 
288 
289 //
290 // Disable SMART
291 //
292 _inline NTSTATUS
295  )
296 {
297  UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)] = {0};
298  ULONG bufferSize = sizeof(srbControl);
299 
302  SMART_CMD,
304  0,
305  0,
306  (PSRB_IO_CONTROL)srbControl,
307  &bufferSize);
308 }
309 
310 
311 //
312 // Enable Attribute Autosave
313 //
314 _inline NTSTATUS
317  )
318 {
319  UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)] = {0};
320  ULONG bufferSize = sizeof(srbControl);
321 
324  SMART_CMD,
326  0xf1,
327  0,
328  (PSRB_IO_CONTROL)srbControl,
329  &bufferSize);
330 }
331 
332 
333 //
334 // Disable Attribute Autosave
335 //
336 _inline NTSTATUS
339  )
340 {
341  UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)] = {0};
342  ULONG bufferSize = sizeof(srbControl);
343 
346  SMART_CMD,
348  0x00,
349  0,
350  (PSRB_IO_CONTROL)srbControl,
351  &bufferSize);
352 }
353 
354 
355 //
356 // Initialize execution of SMART online diagnostics
357 //
358 _inline NTSTATUS
361  UCHAR Subcommand
362  )
363 {
364  UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)] = {0};
365  ULONG bufferSize = sizeof(srbControl);
366 
369  SMART_CMD,
371  0,
372  Subcommand,
373  (PSRB_IO_CONTROL)srbControl,
374  &bufferSize);
375 }
376 
377 
378 NTSTATUS
382  IN UCHAR LogAddress,
384  )
385 {
386  PSRB_IO_CONTROL srbControl;
388  PSENDCMDOUTPARAMS sendCmdOutParams;
389  ULONG logSize, bufferSize;
390 
391  PAGED_CODE();
392 
394  bufferSize = sizeof(SRB_IO_CONTROL) + max( sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + logSize );
395 
396  srbControl = ExAllocatePoolWithTag(NonPagedPoolNx,
397  bufferSize,
399 
400  if (srbControl != NULL)
401  {
404  SMART_CMD,
406  SectorCount,
407  LogAddress,
408  srbControl,
409  &bufferSize);
410 
411  if (NT_SUCCESS(status))
412  {
413  sendCmdOutParams = (PSENDCMDOUTPARAMS)((PUCHAR)srbControl +
414  sizeof(SRB_IO_CONTROL));
416  &sendCmdOutParams->bBuffer[0],
417  logSize);
418  }
419 
420  FREE_POOL(srbControl);
421  } else {
423  }
424  return(status);
425 }
426 
427 
428 NTSTATUS
432  IN UCHAR LogAddress,
434  )
435 {
436  PSRB_IO_CONTROL srbControl;
438  PSENDCMDINPARAMS sendCmdInParams;
439  ULONG logSize, bufferSize;
440 
441  PAGED_CODE();
442 
444  bufferSize = sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1 +
445  logSize;
446 
447  srbControl = ExAllocatePoolWithTag(NonPagedPoolNx,
448  bufferSize,
450 
451  if (srbControl != NULL)
452  {
453  sendCmdInParams = (PSENDCMDINPARAMS)((PUCHAR)srbControl +
454  sizeof(SRB_IO_CONTROL));
455  RtlCopyMemory(&sendCmdInParams->bBuffer[0],
456  Buffer,
457  logSize);
460  SMART_CMD,
462  SectorCount,
463  LogAddress,
464  srbControl,
465  &bufferSize);
466 
467  FREE_POOL(srbControl);
468  } else {
470  }
471  return(status);
472 }
473 
474 
475 NTSTATUS
478  IN ULONG SrbControlCode,
479  IN UCHAR Command,
480  IN UCHAR Feature,
482  IN UCHAR SectorNumber,
483  IN OUT PSRB_IO_CONTROL SrbControl,
485  )
486 /*++
487 
488 Routine Description:
489 
490  This routine will perform some SMART command
491 
492 Arguments:
493 
494  FdoExtension is the FDO device extension
495 
496  SrbControlCode is the SRB control code to use for the request
497 
498  Command is the SMART command to be executed. It may be SMART_CMD or
499  ID_CMD.
500 
501  Feature is the value to place in the IDE feature register.
502 
503  SectorCount is the value to place in the IDE SectorCount register
504 
505  SrbControl is the buffer used to build the SRB_IO_CONTROL and pass
506  any input parameters. It also returns the output parameters.
507 
508  *BufferSize on entry has total size of SrbControl and on return has
509  the size used in SrbControl.
510 
511 
512 
513 Return Value:
514 
515  status
516 
517 --*/
518 {
520  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
521  PUCHAR buffer;
522  PSENDCMDINPARAMS cmdInParameters;
524  ULONG availableBufferSize;
525  KEVENT event;
526  PIRP irp;
527  IO_STATUS_BLOCK ioStatus = { 0 };
528  SCSI_REQUEST_BLOCK srb = {0};
529  LARGE_INTEGER startingOffset;
530  ULONG length;
531  PIO_STACK_LOCATION irpStack;
532  UCHAR srbExBuffer[CLASS_SRBEX_NO_SRBEX_DATA_BUFFER_SIZE] = {0};
533  PSTORAGE_REQUEST_BLOCK srbEx = (PSTORAGE_REQUEST_BLOCK)srbExBuffer;
534  PSTOR_ADDR_BTL8 storAddrBtl8;
535 
536  PAGED_CODE();
537 
538  //
539  // Point to the 'buffer' portion of the SRB_CONTROL and compute how
540  // much room we have left in the srb control. Abort if the buffer
541  // isn't at least the size of SRB_IO_CONTROL.
542  //
543 
544  buffer = (PUCHAR)SrbControl + sizeof(SRB_IO_CONTROL);
545 
546  cmdInParameters = (PSENDCMDINPARAMS)buffer;
547 
548  if (*BufferSize >= sizeof(SRB_IO_CONTROL)) {
549  availableBufferSize = *BufferSize - sizeof(SRB_IO_CONTROL);
550  } else {
552  }
553 
554 #if DBG
555 
556  //
557  // Ensure control codes and buffer lengths passed are correct
558  //
559  {
560  ULONG controlCode = 0;
561  ULONG lengthNeeded = sizeof(SENDCMDINPARAMS);
562 
563  if (Command == SMART_CMD)
564  {
565  switch (Feature)
566  {
567  case ENABLE_SMART:
568  {
569  controlCode = IOCTL_SCSI_MINIPORT_ENABLE_SMART;
570  break;
571  }
572 
573  case DISABLE_SMART:
574  {
575  controlCode = IOCTL_SCSI_MINIPORT_DISABLE_SMART;
576  break;
577  }
578 
579  case RETURN_SMART_STATUS:
580  {
581  controlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS;
582  lengthNeeded = max( lengthNeeded, sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS) );
583  break;
584  }
585 
587  {
589  break;
590  }
591 
593  {
595  break;
596  }
597 
598 
600  {
602  break;
603  }
604 
605  case READ_ATTRIBUTES:
606  {
608  lengthNeeded = max( lengthNeeded, sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE );
609  break;
610  }
611 
612  case READ_THRESHOLDS:
613  {
615  lengthNeeded = max( lengthNeeded, sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE );
616  break;
617  }
618 
619  case SMART_READ_LOG:
620  {
622  lengthNeeded = max( lengthNeeded, sizeof(SENDCMDOUTPARAMS) - 1 + (SectorCount * SMART_LOG_SECTOR_SIZE) );
623  break;
624  }
625 
626  case SMART_WRITE_LOG:
627  {
629  lengthNeeded = lengthNeeded - 1 + (SectorCount * SMART_LOG_SECTOR_SIZE);
630  break;
631  }
632 
633  }
634 
635  } else if (Command == ID_CMD) {
636 
637  controlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
638  lengthNeeded = max( lengthNeeded, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE );
639 
640  } else {
641 
642  NT_ASSERT(FALSE);
643  }
644 
645  NT_ASSERT(controlCode == SrbControlCode);
646  NT_ASSERT(availableBufferSize >= lengthNeeded);
647  }
648 
649 #endif
650 
651  //
652  // Build SrbControl and input to SMART command
653  //
654  SrbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
655  RtlMoveMemory (SrbControl->Signature, "SCSIDISK", 8);
656  SrbControl->Timeout = FdoExtension->TimeOutValue;
657  SrbControl->Length = availableBufferSize;
658  SrbControl->ControlCode = SrbControlCode;
659 
660  cmdInParameters->cBufferSize = sizeof(SENDCMDINPARAMS);
661  cmdInParameters->bDriveNumber = diskData->ScsiAddress.TargetId;
662  cmdInParameters->irDriveRegs.bFeaturesReg = Feature;
663  cmdInParameters->irDriveRegs.bSectorCountReg = SectorCount;
664  cmdInParameters->irDriveRegs.bSectorNumberReg = SectorNumber;
665  cmdInParameters->irDriveRegs.bCylLowReg = SMART_CYL_LOW;
666  cmdInParameters->irDriveRegs.bCylHighReg = SMART_CYL_HI;
667  cmdInParameters->irDriveRegs.bCommandReg = Command;
668 
669  //
670  // Create and send irp
671  //
673 
674  startingOffset.QuadPart = (LONGLONG) 1;
675 
676  length = SrbControl->HeaderLength + SrbControl->Length;
677 
679  IRP_MJ_SCSI,
680  commonExtension->LowerDeviceObject,
681  SrbControl,
682  length,
683  &startingOffset,
684  &event,
685  &ioStatus);
686 
687  if (irp == NULL) {
689  }
690 
691  irpStack = IoGetNextIrpStackLocation(irp);
692 
693  //
694  // Set major and minor codes.
695  //
696 
697  irpStack->MajorFunction = IRP_MJ_SCSI;
698  irpStack->MinorFunction = 1;
699 
700  //
701  // Fill in SRB fields.
702  //
703 
704  if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
705  irpStack->Parameters.Others.Argument1 = srbEx;
706 
707  //
708  // Set up STORAGE_REQUEST_BLOCK fields
709  //
710 
711  srbEx->Length = FIELD_OFFSET(STORAGE_REQUEST_BLOCK, Signature);
712  srbEx->Function = SRB_FUNCTION_STORAGE_REQUEST_BLOCK;
713  srbEx->Signature = SRB_SIGNATURE;
714  srbEx->Version = STORAGE_REQUEST_BLOCK_VERSION_1;
715  srbEx->SrbLength = sizeof(srbExBuffer);
716  srbEx->SrbFunction = SRB_FUNCTION_IO_CONTROL;
717  srbEx->RequestPriority = IoGetIoPriorityHint(irp);
718  srbEx->AddressOffset = sizeof(STORAGE_REQUEST_BLOCK);
719 
720  srbEx->SrbFlags = FdoExtension->SrbFlags;
721  SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_DATA_IN);
722  SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
723  SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_NO_KEEP_AWAKE);
724 
725  srbEx->RequestAttribute = SRB_SIMPLE_TAG_REQUEST;
726  srbEx->RequestTag = SP_UNTAGGED;
727 
728  srbEx->OriginalRequest = irp;
729 
730  //
731  // Set timeout to requested value.
732  //
733 
734  srbEx->TimeOutValue = SrbControl->Timeout;
735 
736  //
737  // Set the data buffer.
738  //
739 
740  srbEx->DataBuffer = SrbControl;
741  srbEx->DataTransferLength = length;
742 
743  //
744  // Set up address fields
745  //
746 
747  storAddrBtl8 = (PSTOR_ADDR_BTL8) ((PUCHAR)srbEx + srbEx->AddressOffset);
748  storAddrBtl8->Type = STOR_ADDRESS_TYPE_BTL8;
749  storAddrBtl8->AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
750  storAddrBtl8->Path = diskData->ScsiAddress.PathId;
751  storAddrBtl8->Target = diskData->ScsiAddress.TargetId;
752  storAddrBtl8->Lun = srb.Lun = diskData->ScsiAddress.Lun;
753 
754  } else {
755  irpStack->Parameters.Others.Argument1 = &srb;
756 
757  srb.PathId = diskData->ScsiAddress.PathId;
758  srb.TargetId = diskData->ScsiAddress.TargetId;
759  srb.Lun = diskData->ScsiAddress.Lun;
760 
762  srb.Length = sizeof(SCSI_REQUEST_BLOCK);
763 
764  srb.SrbFlags = FdoExtension->SrbFlags;
768 
770  srb.QueueTag = SP_UNTAGGED;
771 
772  srb.OriginalRequest = irp;
773 
774  //
775  // Set timeout to requested value.
776  //
777 
778  srb.TimeOutValue = SrbControl->Timeout;
779 
780  //
781  // Set the data buffer.
782  //
783 
784  srb.DataBuffer = SrbControl;
786  }
787 
788  //
789  // Flush the data buffer for output. This will insure that the data is
790  // written back to memory. Since the data-in flag is the the port driver
791  // will flush the data again for input which will ensure the data is not
792  // in the cache.
793  //
794 
795  KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
796 
797  //
798  // Call port driver to handle this request.
799  //
800 
801  status = IoCallDriver(commonExtension->LowerDeviceObject, irp);
802 
803  if (status == STATUS_PENDING) {
805  status = ioStatus.Status;
806  }
807 
808  return status;
809 }
810 
811 
812 NTSTATUS
815  PBOOLEAN SupportSmart
816  )
817 {
818  UCHAR outBuffer[sizeof(SRB_IO_CONTROL) + max( sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE )] = {0};
819  ULONG outBufferSize = sizeof(outBuffer);
821 
822  PAGED_CODE();
823 
826  &outBufferSize);
827 
828  if (NT_SUCCESS(status))
829  {
830  PUSHORT identifyData = (PUSHORT)&(outBuffer[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1]);
831  USHORT commandSetSupported = identifyData[82];
832 
833  *SupportSmart = ((commandSetSupported != 0xffff) &&
834  (commandSetSupported != 0) &&
835  ((commandSetSupported & 1) == 1));
836  } else {
837  *SupportSmart = FALSE;
838  }
839 
840  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DiskGetIdentifyInfo: SMART %s supported for device %p, status %lx\n",
841  *SupportSmart ? "is" : "is not",
842  FdoExtension->DeviceObject,
843  status));
844 
845  return status;
846 }
847 
848 
849 //
850 // FP Ioctl specific routines
851 //
852 
853 NTSTATUS
856  PSTORAGE_PREDICT_FAILURE checkFailure
857  )
858 {
859  KEVENT event;
860  PDEVICE_OBJECT deviceObject;
861  IO_STATUS_BLOCK ioStatus = { 0 };
862  PIRP irp;
864 
865  PAGED_CODE();
866 
868 
869  deviceObject = IoGetAttachedDeviceReference(FdoExtension->DeviceObject);
870 
873  deviceObject,
874  NULL,
875  0,
876  checkFailure,
877  sizeof(STORAGE_PREDICT_FAILURE),
878  FALSE,
879  &event,
880  &ioStatus);
881 
882  if (irp != NULL)
883  {
884  status = IoCallDriver(deviceObject, irp);
885  if (status == STATUS_PENDING)
886  {
888  status = ioStatus.Status;
889  }
890 
891  } else {
893  }
894 
895  ObDereferenceObject(deviceObject);
896 
897  return status;
898 }
899 
900 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
901 
902 NTSTATUS
904  _In_ PDEVICE_OBJECT Fdo,
905  _In_ UCHAR PageMode,
906  _In_ UCHAR PageControl,
907  _In_ PMODE_PARAMETER_HEADER ModeData,
908  _Inout_ PULONG ModeDataSize,
909  _Out_ PVOID* PageData
910  )
911 {
912  ULONG size = 0;
913  PVOID pageData = NULL;
914 
915  PAGED_CODE();
916 
917  if (ModeData == NULL ||
918  ModeDataSize == NULL ||
919  *ModeDataSize < sizeof(MODE_PARAMETER_HEADER) ||
920  PageData == NULL) {
922  }
923 
924  RtlZeroMemory (ModeData, *ModeDataSize);
925 
926  size = ClassModeSenseEx(Fdo,
927  (PCHAR) ModeData,
928  *ModeDataSize,
929  PageMode,
930  PageControl);
931 
932  if (size < sizeof(MODE_PARAMETER_HEADER)) {
933 
934  //
935  // Retry the request in case of a check condition.
936  //
937  size = ClassModeSenseEx(Fdo,
938  (PCHAR) ModeData,
939  *ModeDataSize,
940  PageMode,
941  PageControl);
942 
943  if (size < sizeof(MODE_PARAMETER_HEADER)) {
944  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_WMI, "DiskGetModePage: Mode Sense for Page Mode %d with Page Control %d failed\n",
945  PageMode, PageControl));
946  *ModeDataSize = 0;
947  return STATUS_IO_DEVICE_ERROR;
948  }
949  }
950 
951  //
952  // If the length is greater than length indicated by the mode data reset
953  // the data to the mode data.
954  //
955  if (size > (ULONG) (ModeData->ModeDataLength + 1)) {
956  size = ModeData->ModeDataLength + 1;
957  }
958 
959  *ModeDataSize = size;
960 
961  //
962  // Find the mode page
963  //
964  pageData = ClassFindModePage((PCHAR) ModeData,
965  size,
966  PageMode,
967  TRUE);
968 
969  if (pageData) {
970  *PageData = pageData;
971  return STATUS_SUCCESS;
972  } else {
973  *PageData = NULL;
974  return STATUS_NOT_SUPPORTED;
975  }
976 }
977 
978 NTSTATUS
982  )
983 {
984  PDISK_DATA diskData = (PDISK_DATA)(FdoExtension->CommonExtension.DriverData);
986  PMODE_PARAMETER_HEADER modeData;
987  PMODE_INFO_EXCEPTIONS pageData;
988  MODE_INFO_EXCEPTIONS changeablePageData;
989  ULONG modeDataSize;
990 
991  PAGED_CODE();
992 
993  modeDataSize = MODE_DATA_SIZE;
994 
995  modeData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
996  modeDataSize,
998 
999  if (modeData == NULL) {
1000 
1001  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_WMI, "DiskEnableInfoExceptions: Unable to allocate mode "
1002  "data buffer\n"));
1004  }
1005 
1006  //
1007  // First see which data is actually changeable.
1008  //
1009  status = DiskGetModePage(FdoExtension->DeviceObject,
1011  1, // Page Control = 1 indicates we want changeable values.
1012  modeData,
1013  &modeDataSize,
1014  (PVOID*)&pageData);
1015 
1016  if (!NT_SUCCESS(status) || pageData == NULL) {
1017  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskEnableInfoExceptions: does NOT support SMART for device %p\n",
1018  FdoExtension->DeviceObject));
1019  FREE_POOL(modeData);
1020  return STATUS_NOT_SUPPORTED;
1021  }
1022 
1023  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskEnableInfoExceptions: DOES support SMART for device %p\n",
1024  FdoExtension->DeviceObject));
1025 
1026  //
1027  // At the very least, the DEXCPT bit must be changeable.
1028  // If it's not, bail out now.
1029  //
1030  if (pageData->Dexcpt == 0) {
1031  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskEnableInfoExceptions: does NOT support DEXCPT bit for device %p\n",
1032  FdoExtension->DeviceObject));
1033  FREE_POOL(modeData);
1034  return STATUS_NOT_SUPPORTED;
1035  }
1036 
1037  //
1038  // Cache away which values are changeable.
1039  //
1040  RtlCopyMemory(&changeablePageData, pageData, sizeof(MODE_INFO_EXCEPTIONS));
1041 
1042  //
1043  // Now get the current values.
1044  //
1045  status = DiskGetModePage(FdoExtension->DeviceObject,
1047  0, // Page Control = 0 indicates we want current values.
1048  modeData,
1049  &modeDataSize,
1050  (PVOID*)&pageData);
1051 
1052  if (!NT_SUCCESS(status) || pageData == NULL) {
1053  //
1054  // At this point we know the device supports this mode page so
1055  // assert if something goes wrong here.
1056  //
1057  NT_ASSERT(NT_SUCCESS(status) && pageData);
1058  FREE_POOL(modeData);
1059  return STATUS_NOT_SUPPORTED;
1060  }
1061 
1062  //
1063  // If the device is currently configured to not report any informational
1064  // exceptions and we cannot change the value of that field, there's
1065  // nothing to be done.
1066  //
1067  if (pageData->ReportMethod == 0 && changeablePageData.ReportMethod == 0) {
1068  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskEnableInfoExceptions: MRIE field is 0 and is not changeable for device %p\n",
1069  FdoExtension->DeviceObject));
1070  FREE_POOL(modeData);
1071  return STATUS_NOT_SUPPORTED;
1072  }
1073 
1074  //
1075  // If the PERF bit is changeable, set it now.
1076  //
1077  if (changeablePageData.Perf) {
1078  pageData->Perf = diskData->AllowFPPerfHit ? 0 : 1;
1079  }
1080 
1081  //
1082  // If the MRIE field is changeable, set it to 4 so that informational
1083  // exceptions get reported with the "Recovered Error" sense key.
1084  //
1085  if (changeablePageData.ReportMethod) {
1086  pageData->ReportMethod = 4;
1087  }
1088 
1089  //
1090  // Finally, set the DEXCPT bit appropriately to enable/disable
1091  // informational exception reporting and send the Mode Select.
1092  //
1093  pageData->Dexcpt = !Enable;
1094 
1095  status = ClassModeSelect(FdoExtension->DeviceObject,
1096  (PCHAR)modeData,
1097  modeDataSize,
1098  pageData->PSBit);
1099 
1100  //
1101  // Update the failure prediction state. Note that for this particular
1102  // mode FailurePredictionNone is used when it's not enabled.
1103  //
1104  if (NT_SUCCESS(status)) {
1105  if (Enable) {
1107  diskData->FailurePredictionEnabled = TRUE;
1108  } else {
1110  diskData->FailurePredictionEnabled = FALSE;
1111  }
1112  }
1113 
1114  FREE_POOL(modeData);
1115 
1116  return status;
1117 }
1118 #endif
1119 
1120 
1121 //
1122 // FP type independent routines
1123 //
1124 
1125 NTSTATUS
1128  BOOLEAN Enable
1129  )
1130 /*++
1131 
1132 Routine Description:
1133 
1134  Enable or disable failure prediction at the hardware level
1135 
1136 Arguments:
1137 
1138  FdoExtension
1139 
1140  Enable
1141 
1142 Return Value:
1143 
1144  NT Status
1145 
1146 --*/
1147 {
1148  NTSTATUS status;
1149  PCOMMON_DEVICE_EXTENSION commonExtension = &(FdoExtension->CommonExtension);
1150  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1151 
1152  PAGED_CODE();
1153 
1154  switch(diskData->FailurePredictionCapability)
1155  {
1157  {
1158  if (Enable)
1159  {
1161  } else {
1163  }
1164 
1165  if (NT_SUCCESS(status)) {
1166  diskData->FailurePredictionEnabled = Enable;
1167  }
1168 
1169  break;
1170  }
1171 
1174  {
1175  //
1176  // We assume that the drive is already setup properly for
1177  // failure prediction
1178  //
1180  break;
1181  }
1182 
1183  default:
1184  {
1186  }
1187  }
1188  return status;
1189 }
1190 
1191 
1192 NTSTATUS
1195  BOOLEAN Enable,
1196  ULONG PollTimeInSeconds
1197  )
1198 /*++
1199 
1200 Routine Description:
1201 
1202  Enable or disable polling for hardware failure detection
1203 
1204 Arguments:
1205 
1206  FdoExtension
1207 
1208  Enable
1209 
1210  PollTimeInSeconds - if 0 then no change to current polling timer
1211 
1212 Return Value:
1213 
1214  NT Status
1215 
1216 --*/
1217 {
1218  NTSTATUS status;
1220  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1221 
1222  PAGED_CODE();
1223 
1224  if (Enable)
1225  {
1227  Enable);
1228  } else {
1230  }
1231 
1232  if (NT_SUCCESS(status))
1233  {
1234  status = ClassSetFailurePredictionPoll(FdoExtension,
1235  Enable ? diskData->FailurePredictionCapability :
1237  PollTimeInSeconds);
1238 
1239  //
1240  // Even if this failed we do not want to disable FP on the
1241  // hardware. FP is only ever disabled on the hardware by
1242  // specific command of the user.
1243  //
1244  }
1245 
1246  return status;
1247 }
1248 
1249 
1250 NTSTATUS
1253  PSTORAGE_FAILURE_PREDICT_STATUS DiskSmartStatus
1254  )
1255 /*++
1256 
1257 Routine Description:
1258 
1259  Obtains current failure prediction status
1260 
1261 Arguments:
1262 
1263  FdoExtension
1264 
1265  DiskSmartStatus
1266 
1267 Return Value:
1268 
1269  NT Status
1270 
1271 --*/
1272 {
1274  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1275  NTSTATUS status;
1276 
1277  PAGED_CODE();
1278 
1279  DiskSmartStatus->PredictFailure = FALSE;
1280 
1281  switch(diskData->FailurePredictionCapability)
1282  {
1284  {
1285  UCHAR outBuffer[sizeof(SRB_IO_CONTROL) + max( sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS) )] = {0};
1286  ULONG outBufferSize = sizeof(outBuffer);
1287  PSENDCMDOUTPARAMS cmdOutParameters;
1288 
1291  &outBufferSize);
1292 
1293  if (NT_SUCCESS(status))
1294  {
1295  cmdOutParameters = (PSENDCMDOUTPARAMS)(outBuffer +
1296  sizeof(SRB_IO_CONTROL));
1297 
1298  DiskSmartStatus->Reason = 0; // Unknown;
1299  DiskSmartStatus->PredictFailure = ((cmdOutParameters->bBuffer[3] == 0xf4) &&
1300  (cmdOutParameters->bBuffer[4] == 0x2c));
1301  }
1302  break;
1303  }
1304 
1306  {
1307  DiskSmartStatus->Reason = FdoExtension->FailureReason;
1308  DiskSmartStatus->PredictFailure = FdoExtension->FailurePredicted;
1310  break;
1311  }
1312 
1314  case FailurePredictionNone:
1315  default:
1316  {
1318  break;
1319  }
1320  }
1321 
1322  return status;
1323 }
1324 
1325 
1326 NTSTATUS
1329  PSTORAGE_FAILURE_PREDICT_DATA DiskSmartData
1330  )
1331 /*++
1332 
1333 Routine Description:
1334 
1335  Obtains current failure prediction data. Not available for
1336  FAILURE_PREDICT_SENSE types.
1337 
1338 Arguments:
1339 
1340  FdoExtension
1341 
1342  DiskSmartData
1343 
1344 Return Value:
1345 
1346  NT Status
1347 
1348 --*/
1349 {
1351  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1352  NTSTATUS status;
1353 
1354  PAGED_CODE();
1355 
1356  switch(diskData->FailurePredictionCapability)
1357  {
1359  {
1360  PUCHAR outBuffer;
1361  ULONG outBufferSize;
1362  PSENDCMDOUTPARAMS cmdOutParameters;
1363 
1364  outBufferSize = sizeof(SRB_IO_CONTROL) + max( sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE );
1365 
1366  outBuffer = ExAllocatePoolWithTag(NonPagedPoolNx,
1367  outBufferSize,
1368  DISK_TAG_SMART);
1369 
1370  if (outBuffer != NULL)
1371  {
1374  &outBufferSize);
1375 
1376  if (NT_SUCCESS(status))
1377  {
1378  cmdOutParameters = (PSENDCMDOUTPARAMS)(outBuffer +
1379  sizeof(SRB_IO_CONTROL));
1380 
1381  DiskSmartData->Length = READ_ATTRIBUTE_BUFFER_SIZE;
1382  RtlCopyMemory(DiskSmartData->VendorSpecific,
1383  cmdOutParameters->bBuffer,
1384  min(READ_ATTRIBUTE_BUFFER_SIZE, sizeof(DiskSmartData->VendorSpecific)));
1385  }
1387  } else {
1389  }
1390 
1391  break;
1392  }
1393 
1395  {
1396  DiskSmartData->Length = sizeof(ULONG);
1397  *((PULONG)DiskSmartData->VendorSpecific) = FdoExtension->FailureReason;
1398 
1400  break;
1401  }
1402 
1404  case FailurePredictionNone:
1405  default:
1406  {
1408  break;
1409  }
1410  }
1411 
1412  return status;
1413 }
1414 
1415 
1416 NTSTATUS
1419  PSTORAGE_FAILURE_PREDICT_THRESHOLDS DiskSmartThresholds
1420  )
1421 /*++
1422 
1423 Routine Description:
1424 
1425  Obtains current failure prediction thresholds. Not available for
1426  FAILURE_PREDICT_SENSE types.
1427 
1428 Arguments:
1429 
1430  FdoExtension
1431 
1432  DiskSmartData
1433 
1434 Return Value:
1435 
1436  NT Status
1437 
1438 --*/
1439 {
1441  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1442  NTSTATUS status;
1443 
1444  PAGED_CODE();
1445 
1446  switch(diskData->FailurePredictionCapability)
1447  {
1449  {
1450  PUCHAR outBuffer;
1451  PSENDCMDOUTPARAMS cmdOutParameters;
1452  ULONG outBufferSize;
1453 
1454  outBufferSize = sizeof(SRB_IO_CONTROL) + max( sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE );
1455 
1456  outBuffer = ExAllocatePoolWithTag(NonPagedPoolNx,
1457  outBufferSize,
1458  DISK_TAG_SMART);
1459 
1460  if (outBuffer != NULL)
1461  {
1464  &outBufferSize);
1465 
1466  if (NT_SUCCESS(status))
1467  {
1468  cmdOutParameters = (PSENDCMDOUTPARAMS)(outBuffer +
1469  sizeof(SRB_IO_CONTROL));
1470 
1471  RtlCopyMemory(DiskSmartThresholds->VendorSpecific,
1472  cmdOutParameters->bBuffer,
1473  min(READ_THRESHOLD_BUFFER_SIZE, sizeof(DiskSmartThresholds->VendorSpecific)));
1474  }
1476  } else {
1478  }
1479 
1480  break;
1481  }
1482 
1485  case FailurePredictionNone:
1486  default:
1487  {
1489  break;
1490  }
1491  }
1492 
1493  return status;
1494 }
1495 
1496 
1497 VOID
1498 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1500  IN PDEVICE_OBJECT DevObject,
1501  IN PVOID Context
1502  )
1503 {
1504  PDISKREREGREQUEST reregRequest;
1505  NTSTATUS status;
1506  PDEVICE_OBJECT deviceObject;
1507  PIRP irp;
1508 
1509  PAGED_CODE();
1510  UNREFERENCED_PARAMETER(DevObject);
1511 
1512  NT_ASSERT(Context != NULL);
1514 
1515  do
1516  {
1518  &DiskReregHead,
1520 
1521  if (reregRequest != NULL)
1522  {
1523  deviceObject = reregRequest->DeviceObject;
1524  irp = reregRequest->Irp;
1525 
1526  status = IoWMIRegistrationControl(deviceObject,
1528 
1529  //
1530  // Release remove lock and free irp, now that we are done
1531  // processing this
1532  //
1533  ClassReleaseRemoveLock(deviceObject, irp);
1534 
1535  IoFreeMdl(irp->MdlAddress);
1536  IoFreeIrp(irp);
1537 
1538  FREE_POOL(reregRequest);
1539 
1540  } else {
1541 
1542  NT_ASSERTMSG("Disk Re-registration request list should not be empty", FALSE);
1543 
1545  }
1546 
1547  if (!NT_SUCCESS(status))
1548  {
1549  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskReregWorker: Reregistration failed %x\n",
1550  status));
1551  }
1552 
1554 
1556 }
1557 
1558 
1559 NTSTATUS
1561  VOID
1562  )
1563 {
1564  PAGED_CODE();
1565 
1566  //
1567  // Initialize the spinlock used to manage the
1568  // list of disks reregistering their guids
1569  //
1571 
1572  return(STATUS_SUCCESS);
1573 }
1574 
1575 
1576 NTSTATUS
1579  PIRP Irp
1580  )
1581 {
1582  PDISKREREGREQUEST reregRequest;
1583  PIO_WORKITEM workItem;
1584  NTSTATUS status;
1585 
1586  workItem = IoAllocateWorkItem(DeviceObject);
1587 
1588  if (!workItem) {
1590  }
1591 
1592  reregRequest = ExAllocatePoolWithTag(NonPagedPoolNx,
1593  sizeof(DISKREREGREQUEST),
1594  DISK_TAG_SMART);
1595  if (reregRequest != NULL)
1596  {
1597  //
1598  // add the disk that needs reregistration to the stack of disks
1599  // to reregister. If the list is transitioning from empty to
1600  // non empty then also kick off the work item so that the
1601  // reregistration worker can do the reregister.
1602  //
1603  reregRequest->DeviceObject = DeviceObject;
1604  reregRequest->Irp = Irp;
1606  &DiskReregHead,
1607  &reregRequest->Next,
1609 
1611  {
1612  //
1613  // There is no worker routine running, queue this one.
1614  // When the work item runs, it will process the reregistration
1615  // list.
1616  //
1617 
1618  IoQueueWorkItem(workItem,
1621  workItem);
1622  } else {
1623 
1624  //
1625  // There is a worker routine already running, so we
1626  // can free this unused work item.
1627  //
1628 
1629  IoFreeWorkItem(workItem);
1630  }
1631 
1633 
1634  } else {
1635 
1636  IoFreeWorkItem(workItem);
1637  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskPostReregisterRequest: could not allocate reregRequest for %p\n",
1638  DeviceObject));
1640  }
1641 
1642  return(status);
1643 }
1644 
1645 
1646 NTSTATUS
1647 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1650  PIRP Irp,
1651  PVOID Context
1652  )
1653 {
1654  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
1655  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1659  NTSTATUS status;
1660  BOOLEAN retry;
1661  ULONG retryInterval;
1662  ULONG srbStatus;
1663  BOOLEAN freeLockAndIrp = TRUE;
1664  PVOID originalSenseInfoBuffer = irpStack->Parameters.Others.Argument3;
1665  PSTORAGE_REQUEST_BLOCK srbEx = NULL;
1666  PVOID dataBuffer = NULL;
1667  ULONG dataLength = 0;
1668  PVOID senseBuffer = NULL;
1669  UCHAR cdbLength8 = 0;
1670  ULONG cdbLength32 = 0;
1671  UCHAR senseBufferLength = 0;
1672 
1673  srbStatus = SRB_STATUS(srb->SrbStatus);
1674 
1676  srbEx = (PSTORAGE_REQUEST_BLOCK)srb;
1677  dataBuffer = srbEx->DataBuffer;
1678  dataLength = srbEx->DataTransferLength;
1679  if ((srbEx->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI) &&
1680  (srbEx->NumSrbExData > 0)) {
1681  (void)GetSrbScsiData(srbEx, &cdbLength8, &cdbLength32, NULL, &senseBuffer, &senseBufferLength);
1682  }
1683  } else {
1684  dataBuffer = srb->DataBuffer;
1686  senseBuffer = srb->SenseInfoBuffer;
1687  }
1688 
1689  //
1690  // Check SRB status for success of completing request.
1691  // SRB_STATUS_DATA_OVERRUN also indicates success.
1692  //
1693  if ((srbStatus != SRB_STATUS_SUCCESS) &&
1694  (srbStatus != SRB_STATUS_DATA_OVERRUN))
1695  {
1696  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskInfoExceptionComplete: IRP %p, SRB %p\n", Irp, srb));
1697 
1699  {
1701  }
1702 
1703  retry = ClassInterpretSenseInfo(
1704  DeviceObject,
1705  srb,
1706  irpStack->MajorFunction,
1707  0,
1708  MAXIMUM_RETRIES -
1709  ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4),
1710  &status,
1711  &retryInterval);
1712 
1713  //
1714  // If the status is verified required and the this request
1715  // should bypass verify required then retry the request.
1716  //
1717 
1718  if (TEST_FLAG(irpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME) &&
1720  {
1722  retry = TRUE;
1723  }
1724 
1725  retry = retry && irpStack->Parameters.Others.Argument4;
1726 
1727  irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4 - 1);
1728 
1729  if (retry)
1730  {
1731  //
1732  // Retry request.
1733  //
1734 
1735  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskInfoExceptionComplete: Retry request %p\n", Irp));
1736 
1737  NT_ASSERT(dataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress));
1738 
1740 
1741  //
1742  // Reset byte count of transfer in SRB Extension.
1743  //
1744  srbEx->DataTransferLength = Irp->MdlAddress->ByteCount;
1745 
1746  //
1747  // Zero SRB statuses.
1748  //
1749 
1750  srbEx->SrbStatus = 0;
1751  if ((srbEx->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI) &&
1752  (srbEx->NumSrbExData > 0)) {
1753  SetSrbScsiData(srbEx, cdbLength8, cdbLength32, 0, senseBuffer, senseBufferLength);
1754  }
1755 
1756  //
1757  // Set the no disconnect flag, disable synchronous data transfers and
1758  // disable tagged queuing. This fixes some errors.
1759  //
1760 
1761  SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
1762  SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
1763  CLEAR_FLAG(srbEx->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
1764 
1765  srbEx->RequestAttribute = SRB_SIMPLE_TAG_REQUEST;
1766  srbEx->RequestTag = SP_UNTAGGED;
1767 
1768  } else {
1769 
1770  //
1771  // Reset byte count of transfer in SRB Extension.
1772  //
1773  srb->DataTransferLength = Irp->MdlAddress->ByteCount;
1774 
1775  //
1776  // Zero SRB statuses.
1777  //
1778 
1779  srb->SrbStatus = srb->ScsiStatus = 0;
1780 
1781  //
1782  // Set the no disconnect flag, disable synchronous data transfers and
1783  // disable tagged queuing. This fixes some errors.
1784  //
1785 
1789 
1791  srb->QueueTag = SP_UNTAGGED;
1792  }
1793 
1794  //
1795  // Set up major SCSI function.
1796  //
1797 
1798  nextIrpStack->MajorFunction = IRP_MJ_SCSI;
1799 
1800  //
1801  // Save SRB address in next stack for port driver.
1802  //
1803 
1804  nextIrpStack->Parameters.Scsi.Srb = srb;
1805 
1806 
1809  srb,
1810  TRUE, TRUE, TRUE);
1811 
1812  (VOID)IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1813 
1815  }
1816 
1817  } else {
1818 
1819  //
1820  // Get the results from the mode sense
1821  //
1822  PMODE_INFO_EXCEPTIONS pageData;
1823  PMODE_PARAMETER_HEADER modeData;
1824  ULONG modeDataLength;
1825 
1826  modeData = dataBuffer;
1827  modeDataLength = dataLength;
1828 
1829  pageData = ClassFindModePage((PCHAR)modeData,
1830  modeDataLength,
1832  TRUE);
1833  if (pageData != NULL)
1834  {
1835  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskInfoExceptionComplete: %p supports SMART\n",
1836  DeviceObject));
1837 
1838  diskData->ScsiInfoExceptionsSupported = TRUE;
1839 
1840  //
1841  // The DEXCPT bit must be 0 and the MRIE field must be valid.
1842  //
1843  if (pageData->Dexcpt == 0 &&
1844  pageData->ReportMethod >= 2 &&
1845  pageData->ReportMethod <= 6)
1846  {
1848  diskData->FailurePredictionEnabled = TRUE;
1850 
1851  if (NT_SUCCESS(status))
1852  {
1853  //
1854  // Make sure we won't free the remove lock and the irp
1855  // since we need to keep these until after the work
1856  // item has completed running
1857  //
1858  freeLockAndIrp = FALSE;
1859  }
1860  } else {
1861  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionComplete: %p is not enabled for SMART\n",
1862  DeviceObject));
1863 
1864  }
1865 
1866  } else {
1867  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionComplete: %p does not supports SMART\n",
1868  DeviceObject));
1869 
1870  }
1871 
1872  //
1873  // Set status for successful request
1874  //
1875 
1877 
1878  } // end if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS)
1879 
1880  //
1881  // Free the srb
1882  //
1883  if (senseBuffer != originalSenseInfoBuffer)
1884  {
1885  //
1886  // Free the original sense info buffer in case the port driver has overwritten it
1887  //
1888  FREE_POOL(originalSenseInfoBuffer);
1889  }
1890 
1891  FREE_POOL(senseBuffer);
1892  FREE_POOL(dataBuffer);
1893  FREE_POOL(srb);
1894 
1895  if (freeLockAndIrp)
1896  {
1897  //
1898  // Set status in completing IRP.
1899  //
1900 
1901  Irp->IoStatus.Status = status;
1902 
1903  //
1904  // If pending has be returned for this irp then mark the current stack as
1905  // pending.
1906  //
1907 
1908  if (Irp->PendingReturned) {
1910  }
1911 
1913  IoFreeMdl(Irp->MdlAddress);
1914  IoFreeIrp(Irp);
1915  }
1916 
1918 }
1919 
1920 
1921 NTSTATUS
1924  )
1925 {
1926  PUCHAR modeData;
1927  PSCSI_REQUEST_BLOCK srb;
1928  PCDB cdb;
1929  PIRP irp;
1930  PIO_STACK_LOCATION irpStack;
1932  UCHAR senseInfoBufferLength = 0;
1933  ULONG isRemoved;
1934  ULONG srbSize;
1935  PSTORAGE_REQUEST_BLOCK srbEx = NULL;
1936  PSTOR_ADDR_BTL8 storAddrBtl8 = NULL;
1937  PSRBEX_DATA_SCSI_CDB16 srbExDataCdb16 = NULL;
1938 
1939  modeData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
1942  if (modeData == NULL)
1943  {
1944  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionCheck: Can't allocate mode data "
1945  "buffer\n"));
1947  }
1948 
1949  if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1951  } else {
1952  srbSize = SCSI_REQUEST_BLOCK_SIZE;
1953  }
1954  srb = ExAllocatePoolWithTag(NonPagedPoolNx,
1955  srbSize,
1956  DISK_TAG_SRB);
1957  if (srb == NULL)
1958  {
1959  FREE_POOL(modeData);
1960  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionCheck: Can't allocate srb "
1961  "buffer\n"));
1963  }
1964  RtlZeroMemory(srb, srbSize);
1965 
1966  //
1967  // Sense buffer is in aligned nonpaged pool.
1968  //
1969 
1970  senseInfoBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
1972  '7CcS');
1973 
1974  if (senseInfoBuffer == NULL)
1975  {
1976  FREE_POOL(srb);
1977  FREE_POOL(modeData);
1978  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionCheck: Can't allocate request sense "
1979  "buffer\n"));
1981  }
1982 
1983  senseInfoBufferLength = SENSE_BUFFER_SIZE_EX;
1984 
1985  //
1986  // Build device I/O control request with METHOD_NEITHER data transfer.
1987  // We'll queue a completion routine to cleanup the MDL's and such ourself.
1988  //
1989 
1990  irp = IoAllocateIrp(
1991  (CCHAR) (FdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1),
1992  FALSE);
1993 
1994  if (irp == NULL)
1995  {
1997  FREE_POOL(srb);
1998  FREE_POOL(modeData);
1999  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionCheck: Can't allocate Irp\n"));
2001  }
2002 
2003  isRemoved = ClassAcquireRemoveLock(FdoExtension->DeviceObject, irp);
2004 
2005  if (isRemoved)
2006  {
2007  ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
2008  IoFreeIrp(irp);
2010  FREE_POOL(srb);
2011  FREE_POOL(modeData);
2012  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionCheck: RemoveLock says isRemoved\n"));
2014  }
2015 
2016  //
2017  // Get next stack location.
2018  //
2019 
2021  irpStack = IoGetCurrentIrpStackLocation(irp);
2022  irpStack->DeviceObject = FdoExtension->DeviceObject;
2023 
2024  //
2025  // Save retry count in current Irp stack.
2026  //
2027  irpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
2028 
2029  //
2030  // Save allocated sense info buffer in case the port driver overwrites it
2031  //
2032  irpStack->Parameters.Others.Argument3 = senseInfoBuffer;
2033 
2034  irpStack = IoGetNextIrpStackLocation(irp);
2035 
2036  //
2037  // Set up SRB for execute scsi request. Save SRB address in next stack
2038  // for the port driver.
2039  //
2040 
2041  irpStack->MajorFunction = IRP_MJ_SCSI;
2042  irpStack->Parameters.Scsi.Srb = srb;
2043 
2046  srb,
2047  TRUE,
2048  TRUE,
2049  TRUE);
2050 
2051  irp->MdlAddress = IoAllocateMdl( modeData,
2053  FALSE,
2054  FALSE,
2055  irp );
2056  if (irp->MdlAddress == NULL)
2057  {
2058  ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
2059  FREE_POOL(srb);
2060  FREE_POOL(modeData);
2062  IoFreeIrp( irp );
2063  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskINfoExceptionCheck: Can't allocate MDL\n"));
2065  }
2066 
2067  MmBuildMdlForNonPagedPool(irp->MdlAddress);
2068 
2069  //
2070  // Build the MODE SENSE CDB.
2071  //
2072 
2073  if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
2074 
2075  //
2076  // Set up STORAGE_REQUEST_BLOCK fields
2077  //
2078 
2079  srbEx = (PSTORAGE_REQUEST_BLOCK)srb;
2081  srbEx->Function = SRB_FUNCTION_STORAGE_REQUEST_BLOCK;
2082  srbEx->Signature = SRB_SIGNATURE;
2083  srbEx->Version = STORAGE_REQUEST_BLOCK_VERSION_1;
2084  srbEx->SrbLength = srbSize;
2085  srbEx->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
2086  srbEx->RequestPriority = IoGetIoPriorityHint(irp);
2087  srbEx->AddressOffset = sizeof(STORAGE_REQUEST_BLOCK);
2088  srbEx->NumSrbExData = 1;
2089 
2090  // Set timeout value from device extension.
2091  srbEx->TimeOutValue = FdoExtension->TimeOutValue;
2092 
2093  // Set the transfer length.
2094  srbEx->DataTransferLength = MODE_DATA_SIZE;
2095  srbEx->DataBuffer = modeData;
2096 
2097  srbEx->SrbFlags = FdoExtension->SrbFlags;
2098 
2099  SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_DATA_IN);
2100 
2101  //
2102  // Disable synchronous transfer for these requests.
2103  //
2104  SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
2105 
2106  //
2107  // Don't freeze the queue on an error
2108  //
2109  SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
2110 
2111  srbEx->RequestAttribute = SRB_SIMPLE_TAG_REQUEST;
2112  srbEx->RequestTag = SP_UNTAGGED;
2113 
2114  // Set up IRP Address.
2115  srbEx->OriginalRequest = irp;
2116 
2117  //
2118  // Set up address fields
2119  //
2120 
2121  storAddrBtl8 = (PSTOR_ADDR_BTL8) ((PUCHAR)srbEx + srbEx->AddressOffset);
2122  storAddrBtl8->Type = STOR_ADDRESS_TYPE_BTL8;
2123  storAddrBtl8->AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
2124 
2125  //
2126  // Set up SCSI SRB extended data fields
2127  //
2128 
2129  srbEx->SrbExDataOffset[0] = sizeof(STORAGE_REQUEST_BLOCK) +
2130  sizeof(STOR_ADDR_BTL8);
2131  if ((srbEx->SrbExDataOffset[0] + sizeof(SRBEX_DATA_SCSI_CDB16)) <= srbEx->SrbLength) {
2132  srbExDataCdb16 = (PSRBEX_DATA_SCSI_CDB16)((PUCHAR)srbEx + srbEx->SrbExDataOffset[0]);
2133  srbExDataCdb16->Type = SrbExDataTypeScsiCdb16;
2134  srbExDataCdb16->Length = SRBEX_DATA_SCSI_CDB16_LENGTH;
2135  srbExDataCdb16->CdbLength = 6;
2136 
2137  // Enable auto request sense.
2138  srbExDataCdb16->SenseInfoBufferLength = senseInfoBufferLength;
2139  srbExDataCdb16->SenseInfoBuffer = senseInfoBuffer;
2140 
2141  cdb = (PCDB)srbExDataCdb16->Cdb;
2142  } else {
2143  // Should not happen
2144  NT_ASSERT(FALSE);
2145 
2146  ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
2147  FREE_POOL(srb);
2148  FREE_POOL(modeData);
2150  IoFreeIrp( irp );
2151  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskINfoExceptionCheck: Insufficient extended SRB size\n"));
2152  return STATUS_INTERNAL_ERROR;
2153  }
2154 
2155  } else {
2156 
2157  //
2158  // Write length to SRB.
2159  //
2161 
2162  //
2163  // Set SCSI bus address.
2164  //
2165 
2167 
2168  //
2169  // Enable auto request sense.
2170  //
2171 
2172  srb->SenseInfoBufferLength = senseInfoBufferLength;
2174 
2175  //
2176  // Set timeout value from device extension.
2177  //
2178  srb->TimeOutValue = FdoExtension->TimeOutValue;
2179 
2180  //
2181  // Set the transfer length.
2182  //
2184  srb->DataBuffer = modeData;
2185 
2186  srb->SrbFlags = FdoExtension->SrbFlags;
2187 
2189 
2190  //
2191  // Disable synchronous transfer for these requests.
2192  //
2194 
2195  //
2196  // Don't freeze the queue on an error
2197  //
2199 
2201  srb->QueueTag = SP_UNTAGGED;
2202 
2203  //
2204  // Set up IRP Address.
2205  //
2206  srb->OriginalRequest = irp;
2207 
2208  srb->CdbLength = 6;
2209  cdb = (PCDB)srb->Cdb;
2210 
2211  }
2212 
2213  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
2214  cdb->MODE_SENSE.PageCode = MODE_PAGE_FAULT_REPORTING;
2215  cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
2216 
2217  //
2218  // Call the port driver with the request and wait for it to complete.
2219  //
2220 
2221  IoMarkIrpPending(irp);
2222  IoCallDriver(FdoExtension->CommonExtension.LowerDeviceObject,
2223  irp);
2224 
2225  return(STATUS_PENDING);
2226 }
2227 
2228 
2229 NTSTATUS
2232  PFAILURE_PREDICTION_METHOD FailurePredictCapability,
2233  BOOLEAN ScsiAddressAvailable
2234  )
2235 /*++
2236 
2237 Routine Description:
2238 
2239  Detect if device has any failure prediction capabilities. First we
2240  check for IDE SMART capability. This is done by sending the drive an
2241  IDENTIFY command and checking if the SMART command set bit is set.
2242 
2243  Next we check if SCSI SMART (aka Information Exception Control Page,
2244  X3T10/94-190 Rev 4). This is done by querying for the Information
2245  Exception mode page.
2246 
2247  Lastly we check if the device has IOCTL failure prediction. This mechanism
2248  a filter driver implements IOCTL_STORAGE_PREDICT_FAILURE and will respond
2249  with the information in the IOCTL. We do this by sending the ioctl and
2250  if the status returned is STATUS_SUCCESS we assume that it is supported.
2251 
2252 Arguments:
2253 
2254  FdoExtension
2255 
2256  *FailurePredictCapability
2257 
2258  ScsiAddressAvailable TRUE if there is a valid SCSI_ADDRESS available
2259  for this device, FALSE otherwise.
2260  If FALSE we do not allow SMART IOCTLs (FailurePredictionSmart capability)
2261  which require a valid SCSI_ADDRESS. The other capabilities
2262  <FailurePredictionIoctl, FailurePredictionSense) do not requere
2263  SCSI_ADDRESS so we'll still try to initialize them.
2264 
2265 Return Value:
2266 
2267  NT Status
2268 
2269 --*/
2270 {
2272  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
2273  BOOLEAN supportFP;
2274  NTSTATUS status;
2275  STORAGE_PREDICT_FAILURE checkFailure;
2276  STORAGE_FAILURE_PREDICT_STATUS diskSmartStatus;
2277 
2278  PAGED_CODE();
2279 
2280  //
2281  // Assume no failure predict mechanisms
2282  //
2283  *FailurePredictCapability = FailurePredictionNone;
2284 
2285  //
2286  // See if this is an IDE drive that supports SMART. If so enable SMART
2287  // and then ensure that it suports the SMART READ STATUS command
2288  //
2289 
2290  if (ScsiAddressAvailable)
2291  {
2292  DiskGetIdentifyInfo(FdoExtension, &supportFP);
2293 
2294  if (supportFP)
2295  {
2297  if (NT_SUCCESS(status))
2298  {
2299  *FailurePredictCapability = FailurePredictionSmart;
2300  diskData->FailurePredictionEnabled = TRUE;
2301 
2303  &diskSmartStatus);
2304 
2305  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: Device %p %s IDE SMART\n",
2306  FdoExtension->DeviceObject,
2307  NT_SUCCESS(status) ? "does" : "does not"));
2308 
2309  if (!NT_SUCCESS(status))
2310  {
2311  *FailurePredictCapability = FailurePredictionNone;
2312  diskData->FailurePredictionEnabled = FALSE;
2313  }
2314  }
2315  return(status);
2316  }
2317  }
2318  //
2319  // See if there is a a filter driver to intercept
2320  // IOCTL_STORAGE_PREDICT_FAILURE
2321  //
2323  &checkFailure);
2324 
2325  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: Device %p %s IOCTL_STORAGE_FAILURE_PREDICT\n",
2326  FdoExtension->DeviceObject,
2327  NT_SUCCESS(status) ? "does" : "does not"));
2328 
2329  if (NT_SUCCESS(status))
2330  {
2331  *FailurePredictCapability = FailurePredictionIoctl;
2332  diskData->FailurePredictionEnabled = TRUE;
2333  if (checkFailure.PredictFailure)
2334  {
2335  checkFailure.PredictFailure = 512;
2336  ClassNotifyFailurePredicted(FdoExtension,
2337  (PUCHAR)&checkFailure,
2338  sizeof(checkFailure),
2339  (BOOLEAN)(FdoExtension->FailurePredicted == FALSE),
2340  0x11,
2341  diskData->ScsiAddress.PathId,
2342  diskData->ScsiAddress.TargetId,
2343  diskData->ScsiAddress.Lun);
2344 
2345  FdoExtension->FailurePredicted = TRUE;
2346  }
2347  return(status);
2348  }
2349 
2350  //
2351  // Finally we assume it will not be a scsi smart drive. but
2352  // we'll also send off an asynchronous mode sense so that if
2353  // it is SMART we'll reregister the device object
2354  //
2355 
2356  *FailurePredictCapability = FailurePredictionNone;
2357 
2359 
2360  return(STATUS_SUCCESS);
2361 }
2362 
2363 
2364 NTSTATUS
2365 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2368  IN PIRP Irp,
2369  IN ULONG GuidIndex,
2371  IN BOOLEAN Enable
2372  )
2373 /*++
2374 
2375 Routine Description:
2376 
2377  This routine is a callback into the driver to enabled or disable event
2378  generation or data block collection. A device should only expect a
2379  single enable when the first event or data consumer enables events or
2380  data collection and a single disable when the last event or data
2381  consumer disables events or data collection. Data blocks will only
2382  receive collection enable/disable if they were registered as requiring
2383  it.
2384 
2385 
2386  When NT boots, failure prediction is not automatically enabled, although
2387  it may have been persistantly enabled on a previous boot. Polling is also
2388  not automatically enabled. When the first data block that accesses SMART
2389  such as SmartStatusGuid, SmartDataGuid, SmartPerformFunction, or
2390  SmartEventGuid is accessed then SMART is automatically enabled in the
2391  hardware. Polling is enabled when SmartEventGuid is enabled and disabled
2392  when it is disabled. Hardware SMART is only disabled when the DisableSmart
2393  method is called. Polling is also disabled when this is called regardless
2394  of the status of the other guids or events.
2395 
2396 Arguments:
2397 
2398  DeviceObject is the device whose data block is being queried
2399 
2400  GuidIndex is the index into the list of guids provided when the
2401  device registered
2402 
2403  Function specifies which functionality is being enabled or disabled
2404 
2405  Enable is TRUE then the function is being enabled else disabled
2406 
2407 Return Value:
2408 
2409  status
2410 
2411 --*/
2412 {
2414  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
2415 
2416  PAGED_CODE();
2417 
2418  if ((Function == DataBlockCollection) && Enable)
2419  {
2420  if ((GuidIndex == SmartStatusGuid) ||
2421  (GuidIndex == SmartDataGuid) ||
2424  {
2426  TRUE);
2427  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DeviceObject %p, Irp %p Enable -> %lx\n",
2428  DeviceObject,
2429  Irp,
2430  status));
2431 
2432  } else {
2433  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DeviceObject %p, Irp %p, GuidIndex %d %s for Collection\n",
2434  DeviceObject, Irp,
2435  GuidIndex,
2436  Enable ? "Enabled" : "Disabled"));
2437  }
2438  } else if (Function == EventGeneration) {
2439  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DeviceObject %p, Irp %p, GuidIndex %d %s for Event Generation\n",
2440  DeviceObject, Irp,
2441  GuidIndex,
2442  Enable ? "Enabled" : "Disabled"));
2443 
2444 
2445  if ((GuidIndex == SmartEventGuid) && Enable)
2446  {
2448  Enable,
2449  0);
2450  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DeviceObject %p, Irp %p %s -> %lx\n",
2451  DeviceObject,
2452  Irp,
2453  Enable ? "DiskEnableSmartPolling" : "DiskDisableSmartPolling",
2454  status));
2455  }
2456 
2457 #if DBG
2458  } else {
2459  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DeviceObject %p, Irp %p, GuidIndex %d %s for function %d\n",
2460  DeviceObject, Irp,
2461  GuidIndex,
2462  Enable ? "Enabled" : "Disabled",
2463  Function));
2464 #endif
2465  }
2466 
2468  Irp,
2469  status,
2470  0,
2471  IO_NO_INCREMENT);
2472  return status;
2473 }
2474 
2475 
2476 
2477 NTSTATUS
2478 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2481  OUT ULONG *RegFlags,
2483  )
2484 /*++
2485 
2486 Routine Description:
2487 
2488  This routine is a callback into the driver to retrieve the list of
2489  guids or data blocks that the driver wants to register with WMI. This
2490  routine may not pend or block. Driver should NOT call
2491  ClassWmiCompleteRequest.
2492 
2493 Arguments:
2494 
2495  DeviceObject is the device whose data block is being queried
2496 
2497  *RegFlags returns with a set of flags that describe the guids being
2498  registered for this device. If the device wants enable and disable
2499  collection callbacks before receiving queries for the registered
2500  guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
2501  returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
2502  the instance name is determined from the PDO associated with the
2503  device object. Note that the PDO must have an associated devnode. If
2504  WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
2505  name for the device.
2506 
2507  InstanceName returns with the instance name for the guids if
2508  WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
2509  caller will call ExFreePool with the buffer returned.
2510 
2511 
2512 Return Value:
2513 
2514  status
2515 
2516 --*/
2517 {
2518  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
2519  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
2520 
2521  PAGED_CODE();
2523 
2526 
2527  switch (diskData->FailurePredictionCapability)
2528  {
2530  {
2532  //
2533  // Fall Through
2534  //
2535  }
2537  {
2542 
2543  break;
2544  }
2545 
2547  {
2553  break;
2554  }
2555 
2556 
2557  default:
2558  {
2563  break;
2564  }
2565  }
2566 
2567  //
2568  // Use devnode for FDOs
2570 
2571  return STATUS_SUCCESS;
2572 }
2573 
2574 
2575 NTSTATUS
2576 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2579  OUT ULONG *RegFlags,
2581  OUT PUNICODE_STRING MofName
2582  )
2583 /*++
2584 
2585 Routine Description:
2586 
2587  This routine is a callback into the driver to retrieve the list of
2588  guids or data blocks that the driver wants to register with WMI. This
2589  routine may not pend or block. Driver should NOT call
2590  ClassWmiCompleteRequest.
2591 
2592 Arguments:
2593 
2594  DeviceObject is the device whose data block is being queried
2595 
2596  *RegFlags returns with a set of flags that describe the guids being
2597  registered for this device. If the device wants enable and disable
2598  collection callbacks before receiving queries for the registered
2599  guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
2600  returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
2601  the instance name is determined from the PDO associated with the
2602  device object. Note that the PDO must have an associated devnode. If
2603  WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
2604  name for the device.
2605 
2606  InstanceName returns with the instance name for the guids if
2607  WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
2608  caller will call ExFreePool with the buffer returned.
2609 
2610  MofName returns initialized with the mof resource name for the
2611  binary mof resource attached to the driver's image file. If the
2612  driver does not have a mof resource then it should leave this
2613  parameter untouched.
2614 
2615 Return Value:
2616 
2617  status
2618 
2619 --*/
2620 {
2621  NTSTATUS status;
2622 
2623  UNREFERENCED_PARAMETER(MofName);
2624 
2626  RegFlags,
2627  InstanceName);
2628 
2629  //
2630  // Leave MofName alone since disk doesn't have one
2631  //
2632  return(status);
2633 }
2634 
2635 
2636 NTSTATUS
2637 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2640  IN PIRP Irp,
2641  IN ULONG GuidIndex,
2643  OUT PUCHAR Buffer
2644  )
2645 /*++
2646 
2647 Routine Description:
2648 
2649  This routine is a callback into the driver to query for the contents of
2650  a data block. When the driver has finished filling the data block it
2651  must call ClassWmiCompleteRequest to complete the irp. The driver can
2652  return STATUS_PENDING if the irp cannot be completed immediately.
2653 
2654 Arguments:
2655 
2656  DeviceObject is the device whose data block is being queried
2657 
2658  Irp is the Irp that makes this request
2659 
2660  GuidIndex is the index into the list of guids provided when the
2661  device registered
2662 
2663  BufferAvail on has the maximum size available to write the data
2664  block.
2665 
2666  Buffer on return is filled with the returned data block
2667 
2668 
2669 Return Value:
2670 
2671  status
2672 
2673 --*/
2674 {
2675  NTSTATUS status;
2676  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
2677  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
2678  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
2679  ULONG sizeNeeded;
2680 
2681  PAGED_CODE();
2682 
2683  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskQueryWmiDataBlock, Device %p, Irp %p, GuiIndex %d\n"
2684  " BufferAvail %lx Buffer %p\n",
2685  DeviceObject, Irp,
2687 
2688  switch (GuidIndex)
2689  {
2690  case DiskGeometryGuid:
2691  {
2692  sizeNeeded = sizeof(DISK_GEOMETRY);
2693  if (BufferAvail >= sizeNeeded)
2694  {
2695  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
2696  {
2697  //
2698  // Issue ReadCapacity to update device extension
2699  // with information for current media.
2700  status = DiskReadDriveCapacity(commonExtension->PartitionZeroExtension->DeviceObject);
2701 
2702  //
2703  // Note whether the drive is ready.
2704  diskData->ReadyStatus = status;
2705 
2706  if (!NT_SUCCESS(status))
2707  {
2708  break;
2709  }
2710  }
2711 
2712  //
2713  // Copy drive geometry information from device extension.
2715  &(fdoExtension->DiskGeometry),
2716  sizeof(DISK_GEOMETRY));
2717 
2719  } else {
2721  }
2722  break;
2723  }
2724 
2725  case SmartStatusGuid:
2726  {
2727  PSTORAGE_FAILURE_PREDICT_STATUS diskSmartStatus;
2728 
2730 
2731  sizeNeeded = sizeof(STORAGE_FAILURE_PREDICT_STATUS);
2732  if (BufferAvail >= sizeNeeded)
2733  {
2734  STORAGE_PREDICT_FAILURE checkFailure;
2735 
2736  diskSmartStatus = (PSTORAGE_FAILURE_PREDICT_STATUS)Buffer;
2737 
2738  status = DiskSendFailurePredictIoctl(fdoExtension,
2739  &checkFailure);
2740 
2741  if (NT_SUCCESS(status))
2742  {
2743  if (diskData->FailurePredictionCapability ==
2745  {
2746  diskSmartStatus->Reason = *((PULONG)checkFailure.VendorSpecific);
2747  } else {
2748  diskSmartStatus->Reason = 0; // unknown
2749  }
2750 
2751  diskSmartStatus->PredictFailure = (checkFailure.PredictFailure != 0);
2752  }
2753  } else {
2755  }
2756  break;
2757  }
2758 
2759  case SmartDataGuid:
2760  {
2761  PSTORAGE_FAILURE_PREDICT_DATA diskSmartData;
2762 
2765  (diskData->FailurePredictionCapability ==
2767 
2768  sizeNeeded = sizeof(STORAGE_FAILURE_PREDICT_DATA);
2769  if (BufferAvail >= sizeNeeded)
2770  {
2772 
2773  diskSmartData = (PSTORAGE_FAILURE_PREDICT_DATA)Buffer;
2774 
2775  status = DiskSendFailurePredictIoctl(fdoExtension,
2776  checkFailure);
2777 
2778  if (NT_SUCCESS(status))
2779  {
2780  diskSmartData->Length = 512;
2781  }
2782  } else {
2784  }
2785 
2786  break;
2787  }
2788 
2789  case SmartThresholdsGuid:
2790  {
2791  PSTORAGE_FAILURE_PREDICT_THRESHOLDS diskSmartThresholds;
2792 
2795 
2796  sizeNeeded = sizeof(STORAGE_FAILURE_PREDICT_THRESHOLDS);
2797  if (BufferAvail >= sizeNeeded)
2798  {
2799  diskSmartThresholds = (PSTORAGE_FAILURE_PREDICT_THRESHOLDS)Buffer;
2801  diskSmartThresholds);
2802  } else {
2804  }
2805 
2806  break;
2807  }
2808 
2809  case SmartPerformFunction:
2810  {
2811  sizeNeeded = 0;
2813  break;
2814  }
2815 
2817  {
2818  PSTORAGE_SCSI_INFO_EXCEPTIONS infoExceptions;
2819  MODE_INFO_EXCEPTIONS modeInfo;
2820 
2823 
2824  sizeNeeded = sizeof(STORAGE_SCSI_INFO_EXCEPTIONS);
2825  if (BufferAvail >= sizeNeeded)
2826  {
2827  infoExceptions = (PSTORAGE_SCSI_INFO_EXCEPTIONS)Buffer;
2828  status = DiskGetInfoExceptionInformation(fdoExtension,
2829  &modeInfo);
2830  if (NT_SUCCESS(status))
2831  {
2832  infoExceptions->PageSavable = modeInfo.PSBit;
2833  infoExceptions->Flags = modeInfo.Flags;
2834  infoExceptions->MRIE = modeInfo.ReportMethod;
2835  infoExceptions->Padding = 0;
2836  REVERSE_BYTES(&infoExceptions->IntervalTimer,
2837  &modeInfo.IntervalTimer);
2838  REVERSE_BYTES(&infoExceptions->ReportCount,
2839  &modeInfo.ReportCount)
2840  }
2841  } else {
2843  }
2844 
2845  break;
2846  }
2847 
2848  default:
2849  {
2850  sizeNeeded = 0;
2852  }
2853  }
2854  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskQueryWmiDataBlock Device %p, Irp %p returns %lx\n",
2855  DeviceObject, Irp, status));
2856 
2858  Irp,
2859  status,
2860  sizeNeeded,
2861  IO_NO_INCREMENT);
2862 
2863  return status;
2864 }
2865 
2866 
2867 NTSTATUS
2868 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2871  IN PIRP Irp,
2872  IN ULONG GuidIndex,
2874  IN PUCHAR Buffer
2875  )
2876 /*++
2877 
2878 Routine Description:
2879 
2880  This routine is a callback into the driver to query for the contents of
2881  a data block. When the driver has finished filling the data block it
2882  must call ClassWmiCompleteRequest to complete the irp. The driver can
2883  return STATUS_PENDING if the irp cannot be completed immediately.
2884 
2885 Arguments:
2886 
2887  DeviceObject is the device whose data block is being queried
2888 
2889  Irp is the Irp that makes this request
2890 
2891  GuidIndex is the index into the list of guids provided when the
2892  device registered
2893 
2894  BufferSize has the size of the data block passed
2895 
2896  Buffer has the new values for the data block
2897 
2898 
2899 Return Value:
2900 
2901  status
2902 
2903 --*/
2904 {
2905  NTSTATUS status;
2906  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
2907  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
2908  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
2909 
2910  PAGED_CODE();
2911 
2912  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskSetWmiDataBlock, Device %p, Irp %p, GuiIndex %d\n"
2913  " BufferSize %#x Buffer %p\n",
2914  DeviceObject, Irp,
2916 
2918  {
2919  PSTORAGE_SCSI_INFO_EXCEPTIONS infoExceptions;
2920  MODE_INFO_EXCEPTIONS modeInfo = {0};
2921 
2923  {
2924  infoExceptions = (PSTORAGE_SCSI_INFO_EXCEPTIONS)Buffer;
2925 
2927  modeInfo.PageLength = sizeof(MODE_INFO_EXCEPTIONS) - 2;
2928 
2929  modeInfo.PSBit = 0;
2930  modeInfo.Flags = infoExceptions->Flags;
2931 
2932  modeInfo.ReportMethod = infoExceptions->MRIE;
2933 
2934  REVERSE_BYTES(&modeInfo.IntervalTimer[0],
2935  &infoExceptions->IntervalTimer);
2936 
2937  REVERSE_BYTES(&modeInfo.ReportCount[0],
2938  &infoExceptions->ReportCount);
2939 
2940  if (modeInfo.Perf == 1)
2941  {
2942  diskData->AllowFPPerfHit = FALSE;
2943  } else {
2944  diskData->AllowFPPerfHit = TRUE;
2945  }
2946 
2947  status = DiskSetInfoExceptionInformation(fdoExtension,
2948  &modeInfo);
2949  } else {
2951  }
2952 
2953  } else if (GuidIndex <= SmartThresholdsGuid)
2954  {
2956  } else {
2958  }
2959 
2960  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskSetWmiDataBlock Device %p, Irp %p returns %lx\n",
2961  DeviceObject, Irp, status));
2962 
2964  Irp,
2965  status,
2966  0,
2967  IO_NO_INCREMENT);
2968 
2969  return status;
2970 }
2971 
2972 
2973 NTSTATUS
2974 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2977  IN PIRP Irp,
2978  IN ULONG GuidIndex,
2981  IN PUCHAR Buffer
2982  )
2983 /*++
2984 
2985 Routine Description:
2986 
2987  This routine is a callback into the driver to query for the contents of
2988  a data block. When the driver has finished filling the data block it
2989  must call ClassWmiCompleteRequest to complete the irp. The driver can
2990  return STATUS_PENDING if the irp cannot be completed immediately.
2991 
2992 Arguments:
2993 
2994  DeviceObject is the device whose data block is being queried
2995 
2996  Irp is the Irp that makes this request
2997 
2998  GuidIndex is the index into the list of guids provided when the
2999  device registered
3000 
3001  DataItemId has the id of the data item being set
3002 
3003  BufferSize has the size of the data item passed
3004 
3005  Buffer has the new values for the data item
3006 
3007 
3008 Return Value:
3009 
3010  status
3011 
3012 --*/
3013 {
3014  NTSTATUS status;
3015 
3016  PAGED_CODE();
3017 
3018  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskSetWmiDataItem, Device %p, Irp %p, GuiIndex %d, DataId %d\n"
3019  " BufferSize %#x Buffer %p\n",
3020  DeviceObject, Irp,
3022 
3024  {
3026  } else {
3028  }
3029 
3030  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskSetWmiDataItem Device %p, Irp %p returns %lx\n",
3031  DeviceObject, Irp, status));
3032 
3034  Irp,
3035  status,
3036  0,
3037  IO_NO_INCREMENT);
3038 
3039  return status;
3040 }
3041 
3042 
3043 NTSTATUS
3044 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3047  IN PIRP Irp,
3048  IN ULONG GuidIndex,
3049  IN ULONG MethodId,
3052  IN PUCHAR Buffer
3053  )
3054 /*++
3055 
3056 Routine Description:
3057 
3058  This routine is a callback into the driver to execute a method. When the
3059  driver has finished filling the data block it must call
3060  ClassWmiCompleteRequest to complete the irp. The driver can
3061  return STATUS_PENDING if the irp cannot be completed immediately.
3062 
3063 Arguments:
3064 
3065  DeviceObject is the device whose data block is being queried
3066 
3067  Irp is the Irp that makes this request
3068 
3069  GuidIndex is the index into the list of guids provided when the
3070  device registered
3071 
3072  MethodId has the id of the method being called
3073 
3074  InBufferSize has the size of the data block passed in as the input to
3075  the method.
3076 
3077  OutBufferSize on entry has the maximum size available to write the
3078  returned data block.
3079 
3080  Buffer is filled with the returned data block
3081 
3082 
3083 Return Value:
3084 
3085  status
3086 
3087 --*/
3088 {
3089  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
3090  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
3091  PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
3092  ULONG sizeNeeded = 0;
3093  NTSTATUS status;
3094 
3095  PAGED_CODE();
3096 
3097  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskExecuteWmiMethod, DeviceObject %p, Irp %p, Guid Id %d, MethodId %d\n"
3098  " InBufferSize %#x, OutBufferSize %#x, Buffer %p\n",
3099  DeviceObject, Irp,
3101 
3102  switch(GuidIndex)
3103  {
3104  case SmartPerformFunction:
3105  {
3106 
3109  (diskData->FailurePredictionCapability ==
3111  (diskData->FailurePredictionCapability ==
3113 
3114 
3115  switch(MethodId)
3116  {
3117  //
3118  // void AllowPerformanceHit([in] boolean Allow)
3119  //
3121  {
3122  BOOLEAN allowPerfHit;
3123 
3124  sizeNeeded = 0;
3125  if (InBufferSize >= sizeof(BOOLEAN))
3126  {
3128 
3129  allowPerfHit = *((PBOOLEAN)Buffer);
3130  if (diskData->AllowFPPerfHit != allowPerfHit)
3131  {
3132  diskData->AllowFPPerfHit = allowPerfHit;
3133  if (diskData->FailurePredictionCapability ==
3135  {
3136  MODE_INFO_EXCEPTIONS modeInfo;
3137 
3138  status = DiskGetInfoExceptionInformation(fdoExtension,
3139  &modeInfo);
3140  if (NT_SUCCESS(status))
3141  {
3142  modeInfo.Perf = allowPerfHit ? 0 : 1;
3143  status = DiskSetInfoExceptionInformation(fdoExtension,
3144  &modeInfo);
3145  }
3146  }
3147  else
3148  {
3150  }
3151  }
3152 
3153  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskFdoWmiExecuteMethod: AllowPerformanceHit %x for device %p --> %lx\n",
3154  allowPerfHit,
3155  fdoExtension->DeviceObject,
3156  status));
3157  } else {
3159  }
3160  break;
3161  }
3162 
3163  //
3164  // void EnableDisableHardwareFailurePrediction([in] boolean Enable)
3165  //
3167  {
3168  BOOLEAN enable;
3169 
3170  sizeNeeded = 0;
3171  if (InBufferSize >= sizeof(BOOLEAN))
3172  {
3174  enable = *((PBOOLEAN)Buffer);
3175  if (!enable)
3176  {
3177  //
3178  // If we are disabling we need to also disable
3179  // polling
3180  //
3182  fdoExtension,
3183  enable,
3184  0);
3185  }
3186 
3188  fdoExtension,
3189  enable);
3190 
3191  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskFdoWmiExecuteMethod: EnableDisableHardwareFailurePrediction: %x for device %p --> %lx\n",
3192  enable,
3193  fdoExtension->DeviceObject,
3194  status));
3195  } else {
3197  }
3198  break;
3199  }
3200 
3201  //
3202  // void EnableDisableFailurePredictionPolling(
3203  // [in] uint32 Period,
3204  // [in] boolean Enable)
3205  //
3207  {
3208  BOOLEAN enable;
3209  ULONG period;
3210 
3211  sizeNeeded = 0;
3212  if (InBufferSize >= (sizeof(ULONG) + sizeof(BOOLEAN)))
3213  {
3214  period = *((PULONG)Buffer);
3215  Buffer += sizeof(ULONG);
3216  enable = *((PBOOLEAN)Buffer);
3217 
3219  fdoExtension,
3220  enable,
3221  period);
3222 
3223  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskFdoWmiExecuteMethod: EnableDisableFailurePredictionPolling: %x %x for device %p --> %lx\n",
3224  enable,
3225  period,
3226  fdoExtension->DeviceObject,
3227  status));
3228  } else {
3230  }
3231  break;
3232  }
3233 
3234  //
3235  // void GetFailurePredictionCapability([out] uint32 Capability)
3236  //
3238  {
3239  sizeNeeded = sizeof(ULONG);
3240  if (OutBufferSize >= sizeNeeded)
3241  {
3244  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskFdoWmiExecuteMethod: GetFailurePredictionCapability: %x for device %p --> %lx\n",
3246  fdoExtension->DeviceObject,
3247  status));
3248  } else {
3250  }
3251  break;
3252  }
3253 
3254  //
3255  // void EnableOfflineDiags([out] boolean Success);
3256  //
3257  case EnableOfflineDiags:
3258  {
3259  sizeNeeded = sizeof(BOOLEAN);
3260  if (OutBufferSize >= sizeNeeded)
3261  {
3262  if (diskData->FailurePredictionCapability ==
3264  {
3265  //
3266  // Initiate or resume offline diagnostics.
3267  // This may cause a loss of performance
3268  // to the disk, but mayincrease the amount
3269  // of disk checking.
3270  //
3271  status = DiskExecuteSmartDiagnostics(fdoExtension,
3272  0);
3273 
3274  } else {
3276  }
3277 
3279 
3280  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskFdoWmiExecuteMethod: EnableOfflineDiags for device %p --> %lx\n",
3281  fdoExtension->DeviceObject,
3282  status));
3283  } else {
3285  }
3286  break;
3287  }
3288 
3289  //
3290  // void ReadLogSectors([in] uint8 LogAddress,
3291  // [in] uint8 SectorCount,
3292  // [out] uint32 Length,
3293  // [out, WmiSizeIs("Length")] uint8 LogSectors[]
3294  // );
3295  //
3296  case ReadLogSectors:
3297  {
3298  if (diskData->FailurePredictionCapability ==
3300  {
3301  if (InBufferSize >= sizeof(READ_LOG_SECTORS_IN))
3302  {
3303  PREAD_LOG_SECTORS_IN inParams;
3304  PREAD_LOG_SECTORS_OUT outParams;
3305  ULONG readSize;
3306 
3307  inParams = (PREAD_LOG_SECTORS_IN)Buffer;
3308  readSize = inParams->SectorCount * SMART_LOG_SECTOR_SIZE;
3309  sizeNeeded = FIELD_OFFSET(READ_LOG_SECTORS_OUT,
3310  LogSectors) + readSize;
3311 
3312  if (OutBufferSize >= sizeNeeded)
3313  {
3314  outParams = (PREAD_LOG_SECTORS_OUT)Buffer;
3315  status = DiskReadSmartLog(fdoExtension,
3316  inParams->SectorCount,
3317  inParams->LogAddress,
3318  outParams->LogSectors);
3319 
3320  if (NT_SUCCESS(status))
3321  {
3322  outParams->Length = readSize;
3323  } else {
3324  //
3325  // SMART command failure is
3326  // indicated by successful
3327  // execution, but no data returned
3328  //
3329  outParams->Length = 0;
3331  }
3332  } else {
3334  }
3335 
3336  } else {
3338  }
3339  } else {
3341  }
3342  break;
3343  }
3344 
3345  // void WriteLogSectors([in] uint8 LogAddress,
3346  // [in] uint8 SectorCount,
3347  // [in] uint32 Length,
3348  // [in, WmiSizeIs("Length")] uint8 LogSectors[],
3349  // [out] boolean Success
3350  // );
3351  case WriteLogSectors:
3352  {
3353  if (diskData->FailurePredictionCapability ==
3355  {
3357  LogSectors))
3358  {
3359  PWRITE_LOG_SECTORS_IN inParams;
3360  PWRITE_LOG_SECTORS_OUT outParams;
3361  ULONG writeSize;
3362 
3363  inParams = (PWRITE_LOG_SECTORS_IN)Buffer;
3364  writeSize = inParams->SectorCount * SMART_LOG_SECTOR_SIZE;
3366  LogSectors) +
3367  writeSize))
3368  {
3369  sizeNeeded = sizeof(WRITE_LOG_SECTORS_OUT);
3370 
3371  if (OutBufferSize >= sizeNeeded)
3372  {
3373  outParams = (PWRITE_LOG_SECTORS_OUT)Buffer;
3374  status = DiskWriteSmartLog(fdoExtension,
3375  inParams->SectorCount,
3376  inParams->LogAddress,
3377  inParams->LogSectors);
3378 
3379  if (NT_SUCCESS(status))
3380  {
3381  outParams->Success = TRUE;
3382  } else {
3383  outParams->Success = FALSE;
3385  }
3386  } else {
3388  }
3389  } else {
3391  }
3392  } else {
3394  }
3395  } else {
3397  }
3398  break;
3399  }
3400 
3401  // void ExecuteSelfTest([in] uint8 Subcommand,
3402  // [out,
3403  // Values{"0", "1", "2"},
3404  // ValueMap{"Successful Completion",
3405  // "Captive Mode Required",
3406  // "Unsuccessful Completion"}
3407  // ]
3408  // uint32 ReturnCode);
3409  case ExecuteSelfTest:
3410  {
3411  if (diskData->FailurePredictionCapability ==
3413  {
3414  if (InBufferSize >= sizeof(EXECUTE_SELF_TEST_IN))
3415  {
3416  sizeNeeded = sizeof(EXECUTE_SELF_TEST_OUT);
3417  if (OutBufferSize >= sizeNeeded)
3418  {
3419  PEXECUTE_SELF_TEST_IN inParam;
3420  PEXECUTE_SELF_TEST_OUT outParam;
3421 
3422  inParam = (PEXECUTE_SELF_TEST_IN)Buffer;
3423  outParam = (PEXECUTE_SELF_TEST_OUT)Buffer;
3424 
3425  if (DiskIsValidSmartSelfTest(inParam->Subcommand))
3426  {
3427  status = DiskExecuteSmartDiagnostics(fdoExtension,
3428  inParam->Subcommand);
3429  if (NT_SUCCESS(status))
3430  {
3431  //
3432  // Return self test executed
3433  // without a problem
3434  //
3435  outParam->ReturnCode = 0;
3436  } else {
3437  //
3438  // Return Self test execution
3439  // failed status
3440  //
3441  outParam->ReturnCode = 2;
3443  }
3444  } else {
3445  //
3446  // If self test subcommand requires
3447  // captive mode then return that
3448  // status
3449  //
3450  outParam->ReturnCode = 1;
3452  }
3453 
3454  } else {
3456  }
3457 
3458  } else {
3460  }
3461  } else {
3463  }
3464 
3465  break;
3466  }
3467 
3468  default :
3469  {
3470  sizeNeeded = 0;
3472  break;
3473  }
3474  }
3475 
3476  break;
3477  }
3478 
3479  case DiskGeometryGuid:
3480  case SmartStatusGuid:
3481  case SmartDataGuid:
3482  case SmartEventGuid:
3483  case SmartThresholdsGuid:
3485  {
3486  sizeNeeded = 0;
3488  break;
3489  }
3490 
3491  default:
3492  {
3493  sizeNeeded = 0;
3495  }
3496  }
3497 
3498  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskExecuteMethod Device %p, Irp %p returns %lx\n",
3499  DeviceObject, Irp, status));
3500 
3502  Irp,
3503  status,
3504  sizeNeeded,
3505  IO_NO_INCREMENT);
3506 
3507  return status;
3508 }
3509 
3510 
UCHAR PathId
Definition: scsi_port.h:149
ULONG cBufferSize
Definition: helper.h:31
struct _STORAGE_FAILURE_PREDICT_THRESHOLDS STORAGE_FAILURE_PREDICT_THRESHOLDS
signed char * PCHAR
Definition: retypes.h:7
#define STOR_ADDRESS_TYPE_BTL8
Definition: scsi.h:3525
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
KSPIN_LOCK DiskReregSpinlock
Definition: diskwmi.c:89
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
#define NT_ASSERTMSG
Definition: rtlfuncs.h:3313
#define SMART_LOG_SECTOR_SIZE
Definition: ntdddisk.h:705
#define MODE_PAGE_FAULT_REPORTING
Definition: scsi.h:218
#define DiskReadSmartThresholds(FdoExtension, SrbControl, BufferSize)
Definition: diskwmi.c:218
struct _DISK_DATA * PDISK_DATA
#define IN
Definition: typedefs.h:39
#define max(a, b)
Definition: svc.c:63
UCHAR IntervalTimer[4]
Definition: scsi.h:3028
struct _STORAGE_SCSI_INFO_EXCEPTIONS * PSTORAGE_SCSI_INFO_EXCEPTIONS
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define WriteLogSectors
Definition: wmidata.h:3387
#define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
Definition: cdrw_hw.h:1459
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
ULONG SrbFlags
Definition: srb.h:252
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
_In_ LPCGUID _In_ SIZE_T InBufferSize
Definition: potypes.h:547
struct _SENDCMDOUTPARAMS * PSENDCMDOUTPARAMS
UCHAR bSectorNumberReg
Definition: helper.h:11
#define STATUS_WMI_GUID_NOT_FOUND
Definition: ntstatus.h:776
PVOID OriginalRequest
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:271
UCHAR bBuffer[1]
Definition: helper.h:36
NTSTATUS DiskReadFailurePredictStatus(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, PSTORAGE_FAILURE_PREDICT_STATUS DiskSmartStatus)
Definition: diskwmi.c:1251
#define STORAGE_REQUEST_BLOCK_VERSION_1
Definition: srb.h:608
struct _STORAGE_FAILURE_PREDICT_DATA STORAGE_FAILURE_PREDICT_DATA
Definition: ntbasedef.h:629
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define MmGetMdlVirtualAddress(_Mdl)
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1069
#define TEST_FLAG(Flags, Bit)
Definition: classpnp.h:159
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
struct STOR_ADDRESS_ALIGN _STOR_ADDR_BTL8 * PSTOR_ADDR_BTL8
_In_ PIRP Irp
Definition: csq.h:116
_In_ PIRP _In_ ULONG _In_ ULONG DataItemId
Definition: classpnp.h:436
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define TRUE
Definition: types.h:120
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
BOOLEAN NTAPI ClassInterpretSenseInfo(_In_ PDEVICE_OBJECT Fdo, _In_ PSCSI_REQUEST_BLOCK _Srb, _In_ UCHAR MajorFunctionCode, _In_ ULONG IoDeviceCode, _In_ ULONG RetryCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, 100) ULONG *RetryInterval)
Definition: class.c:4452
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
PVOID DataBuffer
Definition: srb.h:255
#define SMART_CYL_LOW
Definition: ntdddisk.h:650
#define SmartEventGuid
Definition: diskwmi.c:150
unsigned char * PUCHAR
Definition: retypes.h:3
NTSTATUS ReadyStatus
Definition: disk.h:319
ULONG DataTransferLength
Definition: srb.h:253
PDEVICE_OBJECT DeviceObject
Definition: disk.h:431
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:428
#define DiskReadSmartStatus(FdoExtension, SrbControl, BufferSize)
Definition: diskwmi.c:236
#define ENABLE_DISABLE_AUTOSAVE
Definition: ntdddisk.h:717
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
PSINGLE_LIST_ENTRY NTAPI ExInterlockedPushEntryList(IN OUT PSINGLE_LIST_ENTRY ListHead, IN OUT PSINGLE_LIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:227
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:140
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
#define WMIREG_FLAG_EVENT_ONLY_GUID
Definition: wmistr.h:75
VOID NTAPI ClassReleaseQueue(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:11589
SCSI_ADDRESS ScsiAddress
Definition: disk.h:325
NTSTATUS DiskInfoExceptionCheck(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: diskwmi.c:1922
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
struct _SENDCMDOUTPARAMS SENDCMDOUTPARAMS
NTSTATUS NTAPI ClassModeSelect(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSelectBuffer, _In_ ULONG Length, _In_ BOOLEAN SavePages)
Definition: class.c:6873
struct _STORAGE_FAILURE_PREDICT_STATUS STORAGE_FAILURE_PREDICT_STATUS
UCHAR CdbLength
Definition: srb.h:250
NTSTATUS DiskEnableInfoExceptions(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ BOOLEAN Enable)
Definition: diskwmi.c:979
GLuint buffer
Definition: glext.h:5915
struct _STORAGE_FAILURE_PREDICT_DATA * PSTORAGE_FAILURE_PREDICT_DATA
GUIDREGINFO DiskWmiFdoGuidList[]
Definition: diskwmi.c:92
#define IDENTIFY_BUFFER_SIZE
Definition: ntdddisk.h:703
struct _STORAGE_FAILURE_PREDICT_THRESHOLDS * PSTORAGE_FAILURE_PREDICT_THRESHOLDS
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define DISABLE_SMART
Definition: ntdddisk.h:723
Definition: shell.h:41
UCHAR QueueAction
Definition: srb.h:249
struct _WRITE_LOG_SECTORS_OUT * PWRITE_LOG_SECTORS_OUT
#define STATUS_WMI_READ_ONLY
Definition: ntstatus.h:818
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define WMI_STORAGE_FAILURE_PREDICT_DATA_GUID
Definition: wmidata.h:332
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
ULONG TimeOutValue
Definition: srb.h:254
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
NTSTATUS DiskReadFailurePredictData(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, PSTORAGE_FAILURE_PREDICT_DATA DiskSmartData)
Definition: diskwmi.c:1327
UCHAR TargetId
Definition: scsi_port.h:150
UCHAR SrbStatus
Definition: srb.h:243
UCHAR bSectorCountReg
Definition: helper.h:10
#define DiskGeometryGuid
Definition: diskwmi.c:140
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
#define SRB_STATUS(Status)
Definition: srb.h:381
NTSTATUS NTAPI DiskFdoQueryWmiRegInfo(IN PDEVICE_OBJECT DeviceObject, OUT ULONG *RegFlags, OUT PUNICODE_STRING InstanceName)
Definition: diskwmi.c:2479
LONG DiskReregWorkItems
Definition: diskwmi.c:90
BOOLEAN AllowFPPerfHit
Definition: disk.h:332
#define ENABLE_SMART
Definition: ntdddisk.h:722
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
struct _STORAGE_FAILURE_PREDICT_STATUS * PSTORAGE_FAILURE_PREDICT_STATUS
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define SP_UNTAGGED
Definition: srb.h:225
#define IRP_MJ_SCSI
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define DISK_TAG_INFO_EXCEPTION
Definition: disk.h:55
NTSTATUS NTAPI DiskFdoQueryWmiDataBlock(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG BufferAvail, OUT PUCHAR Buffer)
Definition: diskwmi.c:2638
struct _SENDCMDINPARAMS SENDCMDINPARAMS
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
NTSTATUS DiskSetInfoExceptionInformation(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMODE_INFO_EXCEPTIONS PageData)
Definition: disk.c:2981
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB16 SRBEX_DATA_SCSI_CDB16
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
Definition: cdrw_hw.h:1464
struct _EXECUTE_SELF_TEST_OUT * PEXECUTE_SELF_TEST_OUT
#define FALSE
Definition: types.h:117
static LPOVERLAPPED_COMPLETION_ROUTINE Function
Definition: sync.c:681
long LONG
Definition: pedump.c:60
ULONG dataLength
Definition: scsi.h:3751
BOOLEAN FailurePredictionEnabled
Definition: disk.h:346
NTSTATUS DiskReadFailurePredictThresholds(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, PSTORAGE_FAILURE_PREDICT_THRESHOLDS DiskSmartThresholds)
Definition: diskwmi.c:1417
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
NTSTATUS DiskInitializeReregistration(VOID)
Definition: diskwmi.c:1560
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
NTSTATUS DiskPostReregisterRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: diskwmi.c:1577
UCHAR ScsiStatus
Definition: srb.h:244
#define CLEAR_FLAG(Flags, Bit)
Definition: classpnp.h:158
#define STOR_ADDR_BTL8_ADDRESS_LENGTH
Definition: scsi.h:3528
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:238
#define ScsiInfoExceptionsGuid
Definition: diskwmi.c:152
NTSTATUS NTAPI DiskFdoQueryWmiRegInfoEx(IN PDEVICE_OBJECT DeviceObject, OUT ULONG *RegFlags, OUT PUNICODE_STRING InstanceName, OUT PUNICODE_STRING MofName)
Definition: diskwmi.c:2577
NTSTATUS NTAPI DiskFdoExecuteWmiMethod(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG MethodId, IN ULONG InBufferSize, IN ULONG OutBufferSize, IN PUCHAR Buffer)
Definition: diskwmi.c:3045
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
_Out_ ULONG * RegFlags
Definition: classpnp.h:403
NTSTATUS DiskGetInfoExceptionInformation(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMODE_INFO_EXCEPTIONS ReturnPageData)
Definition: disk.c:2892
struct SRB_ALIGN _SRBEX_DATA_SCSI_CDB16 * PSRBEX_DATA_SCSI_CDB16
smooth NULL
Definition: ftsmooth.c:416
#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
Definition: cdrw_hw.h:1460
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
union _CDB * PCDB
#define WMI_STORAGE_FAILURE_PREDICT_STATUS_GUID
Definition: wmidata.h:334
#define _Out_
Definition: no_sal2.h:323
_In_ PIRP _In_ ULONG GuidIndex
Definition: classpnp.h:418
struct _STORAGE_PREDICT_FAILURE * PSTORAGE_PREDICT_FAILURE
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1803
#define WMIREG_FLAG_INSTANCE_PDO
Definition: wmistr.h:69
#define WMI_STORAGE_FAILURE_PREDICT_THRESHOLDS_GUID
Definition: wmidata.h:335
_inline NTSTATUS DiskExecuteSmartDiagnostics(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, UCHAR Subcommand)
Definition: diskwmi.c:359
Definition: bufpool.h:45
#define READ_THRESHOLD_BUFFER_SIZE
Definition: ntdddisk.h:704
#define ReadLogSectors
Definition: wmidata.h:3374
void * PVOID
Definition: retypes.h:9
UCHAR QueueTag
Definition: srb.h:248
NTSTATUS DiskDetectFailurePrediction(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, PFAILURE_PREDICTION_METHOD FailurePredictCapability, BOOLEAN ScsiAddressAvailable)
Definition: diskwmi.c:2230
UCHAR TargetId
Definition: srb.h:246
#define RETURN_SMART_STATUS
Definition: ntdddisk.h:724
#define READ_ATTRIBUTE_BUFFER_SIZE
Definition: ntdddisk.h:702
NTSTATUS NTAPI DiskWmiFunctionControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN CLASSENABLEDISABLEFUNCTION Function, IN BOOLEAN Enable)
Definition: diskwmi.c:2366
#define ExecuteSelfTest
Definition: wmidata.h:3407
#define MAXIMUM_RETRIES
Definition: class2.h:14
struct _EXECUTE_SELF_TEST_IN * PEXECUTE_SELF_TEST_IN
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
#define EXECUTE_OFFLINE_DIAGS
Definition: ntdddisk.h:719
_inline NTSTATUS DiskEnableSmart(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: diskwmi.c:271
NTSTATUS NTAPI IoWMIRegistrationControl(IN PDEVICE_OBJECT DeviceObject, IN ULONG Action)
Definition: wmi.c:68
struct _CDB::_MODE_SENSE MODE_SENSE
NTSTATUS DiskWriteSmartLog(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN UCHAR SectorCount, IN UCHAR LogAddress, IN PUCHAR Buffer)
Definition: diskwmi.c:429
_In_ PIRP _In_ ULONG _In_ ULONG MethodId
Definition: classpnp.h:446
int64_t LONGLONG
Definition: typedefs.h:68
PSINGLE_LIST_ENTRY NTAPI ExInterlockedPopEntryList(IN OUT PSINGLE_LIST_ENTRY ListHead, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:201
NTSTATUS NTAPI DiskFdoSetWmiDataBlock(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG BufferSize, IN PUCHAR Buffer)
Definition: diskwmi.c:2869
#define ID_CMD
Definition: helper.h:20
#define READ_THRESHOLDS
Definition: ntdddisk.h:716
GLsizeiptr size
Definition: glext.h:5919
#define SAVE_ATTRIBUTE_VALUES
Definition: ntdddisk.h:718
IDEREGS irDriveRegs
Definition: helper.h:32
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
GUID DiskPredictFailureEventGuid
Definition: diskwmi.c:138
PVOID NTAPI ClassFindModePage(_In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ BOOLEAN Use6Byte)
Definition: class.c:6798
#define WMIREG_FLAG_REMOVE_GUID
Definition: wmistr.h:70
char CCHAR
Definition: typedefs.h:51
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define DiskReadDriveCapacity(Fdo)
Definition: disk.h:814
struct Command Command
#define DiskIsValidSmartSelfTest(Subcommand)
Definition: disk.h:615
UCHAR Function
Definition: srb.h:242
#define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
Definition: cdrw_hw.h:1466
#define IOCTL_SCSI_MINIPORT_RETURN_STATUS
Definition: cdrw_hw.h:1463
struct _EXECUTE_SELF_TEST_OUT EXECUTE_SELF_TEST_OUT
UCHAR bCommandReg
Definition: helper.h:15
PFIXED_SENSE_DATA senseInfoBuffer
Definition: scsi.h:3710
struct _COMMON_DEVICE_EXTENSION * PCOMMON_DEVICE_EXTENSION
enum FAILURE_PREDICTION_METHOD * PFAILURE_PREDICTION_METHOD
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:596
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
#define BufferSize
Definition: classpnp.h:436
#define SRB_FLAGS_NO_KEEP_AWAKE
Definition: srb.h:404
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3202
#define IOCTL_SCSI_MINIPORT_ENABLE_SMART
Definition: cdrw_hw.h:1461
USHORT Length
Definition: srb.h:241
#define SmartStatusGuid
Definition: diskwmi.c:141
#define _Inout_
Definition: no_sal2.h:244
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:349
#define READ_ATTRIBUTES
Definition: ntdddisk.h:715
BOOLEAN ScsiInfoExceptionsSupported
Definition: disk.h:340
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define WMI_STORAGE_FAILURE_PREDICT_FUNCTION_GUID
Definition: wmidata.h:333
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
NTSTATUS DiskEnableDisableFailurePredictPolling(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, BOOLEAN Enable, ULONG PollTimeInSeconds)
Definition: diskwmi.c:1193
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
#define IOCTL_SCSI_MINIPORT_READ_SMART_LOG
Definition: scsi.h:1420
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
Definition: cdrw_hw.h:1465
__inline PCDB GetSrbScsiData(_In_ PSTORAGE_REQUEST_BLOCK SrbEx, _In_opt_ PUCHAR CdbLength8, _In_opt_ PULONG CdbLength32, _In_opt_ PUCHAR ScsiStatus, _In_opt_ PVOID *SenseInfoBuffer, _In_opt_ PUCHAR SenseInfoBufferLength)
Definition: disk.h:990
#define SRB_FLAGS_DISABLE_DISCONNECT
Definition: srb.h:388
#define SRB_FUNCTION_STORAGE_REQUEST_BLOCK
Definition: srb.h:99
unsigned char UCHAR
Definition: xmlstorage.h:181
NTSTATUS NTAPI DiskFdoSetWmiDataItem(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG DataItemId, IN ULONG BufferSize, IN PUCHAR Buffer)
Definition: diskwmi.c:2975
char * PBOOLEAN
Definition: retypes.h:11
NTSTATUS DiskPerformSmartCommand(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN ULONG SrbControlCode, IN UCHAR Command, IN UCHAR Feature, IN UCHAR SectorCount, IN UCHAR SectorNumber, IN OUT PSRB_IO_CONTROL SrbControl, OUT PULONG BufferSize)
Definition: diskwmi.c:476
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
#define EnableDisableFailurePredictionPolling
Definition: diskwmi.c:146
#define InterlockedDecrement
Definition: armddk.h:52
SINGLE_LIST_ENTRY Next
Definition: disk.h:430
CLASSENABLEDISABLEFUNCTION
Definition: classpnp.h:228
#define EnableDisableHardwareFailurePrediction
Definition: diskwmi.c:145
#define SRB_FUNCTION_IO_CONTROL
Definition: srb.h:309
UCHAR bCylLowReg
Definition: helper.h:12
#define SmartThresholdsGuid
Definition: diskwmi.c:151
#define VOID
Definition: acefi.h:82
#define SRB_SIGNATURE
Definition: srb.h:607
FAILURE_PREDICTION_METHOD FailurePredictionCapability
Definition: disk.h:331
struct _STORAGE_SCSI_INFO_EXCEPTIONS STORAGE_SCSI_INFO_EXCEPTIONS
_In_ PIRP _In_ ULONG _In_ ULONG BufferAvail
Definition: classpnp.h:418
#define FREE_POOL(_PoolPtr)
Definition: classpnp.h:63
struct _cl_event * event
Definition: glext.h:7739
ULONG SectorCount
Definition: part_xbox.c:31
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
NTSTATUS DiskEnableDisableFailurePrediction(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, BOOLEAN Enable)
Definition: diskwmi.c:1126
PFIXED_SENSE_DATA outBuffer
Definition: scsi.h:4022
#define DISK_TAG_SMART
Definition: disk.h:54
#define WMIREG_ACTION_UPDATE_GUIDS
__inline VOID SetSrbScsiData(_In_ PSTORAGE_REQUEST_BLOCK SrbEx, _In_ UCHAR CdbLength8, _In_ ULONG CdbLength32, _In_ UCHAR ScsiStatus, _In_opt_ PVOID SenseInfoBuffer, _In_ UCHAR SenseInfoBufferLength)
Definition: disk.h:1180
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:157
SINGLE_LIST_ENTRY DiskReregHead
Definition: diskwmi.c:88
#define SMART_CMD
Definition: helper.h:21
_inline NTSTATUS DiskDisableSmartAttributeAutosave(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: diskwmi.c:337
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
UCHAR bFeaturesReg
Definition: helper.h:9
#define SMART_CYL_HI
Definition: ntdddisk.h:651
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
#define _In_
Definition: no_sal2.h:204
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
UCHAR SenseInfoBufferLength
Definition: srb.h:251
UCHAR VendorSpecific[512]
Definition: ntddstor.h:501
#define AllowDisallowPerformanceHit
Definition: diskwmi.c:144
struct _DISK_GEOMETRY DISK_GEOMETRY
struct _READ_LOG_SECTORS_IN * PREAD_LOG_SECTORS_IN
#define IOCTL_STORAGE_PREDICT_FAILURE
Definition: ntddstor.h:146
#define WMI_STORAGE_PREDICT_FAILURE_EVENT_GUID
Definition: wmidata.h:336
IO_COMPLETION_ROUTINE DiskInfoExceptionComplete
Definition: diskwmi.c:72
GLboolean enable
Definition: glext.h:11120
#define KeFlushIoBuffers(_Mdl, _ReadOperation, _DmaOperation)
Definition: ke.h:170
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
NTSTATUS DiskReadSmartLog(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN UCHAR SectorCount, IN UCHAR LogAddress, OUT PUCHAR Buffer)
Definition: diskwmi.c:379
UCHAR PathId
Definition: srb.h:245
SCSIPORT_API NTSTATUS NTAPI ClassWmiCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _In_ NTSTATUS Status, _In_ ULONG BufferUsed, _In_ CCHAR PriorityBoost)
Definition: classwmi.c:1009
unsigned short USHORT
Definition: pedump.c:61
_inline NTSTATUS DiskEnableSmartAttributeAutosave(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: diskwmi.c:315
struct _SRB_IO_CONTROL SRB_IO_CONTROL
STORAGE_REQUEST_BLOCK
Definition: srb.h:652
UCHAR ReportCount[4]
Definition: scsi.h:3029
#define DiskReadSmartData(FdoExtension, SrbControl, BufferSize)
Definition: diskwmi.c:200
#define DiskGetIdentifyData(FdoExtension, SrbControl, BufferSize)
Definition: diskwmi.c:254
#define IOCTL_SCSI_MINIPORT_IDENTIFY
Definition: cdrw_hw.h:1458
#define CLASS_SRBEX_NO_SRBEX_DATA_BUFFER_SIZE
Definition: classpnp.h:696
#define IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
Definition: scsi.h:1421
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
struct _WRITE_LOG_SECTORS_IN * PWRITE_LOG_SECTORS_IN
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
#define SCSI_REQUEST_BLOCK_SIZE
Definition: srb.h:274
_In_ LPCGUID _In_ SIZE_T _In_ SIZE_T OutBufferSize
Definition: potypes.h:549
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define SMART_READ_LOG
Definition: ntdddisk.h:720
unsigned int * PULONG
Definition: retypes.h:1
struct _MODE_INFO_EXCEPTIONS MODE_INFO_EXCEPTIONS
#define min(a, b)
Definition: monoChain.cc:55
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
UCHAR bCylHighReg
Definition: helper.h:13
#define DISK_TAG_SRB
Definition: disk.h:67
NTKRNLVISTAAPI IO_PRIORITY_HINT NTAPI IoGetIoPriorityHint(_In_ PIRP Irp)
Definition: io.c:123
NTSTATUS DiskGetModePage(_In_ PDEVICE_OBJECT Fdo, _In_ UCHAR PageMode, _In_ UCHAR PageControl, _In_ PMODE_PARAMETER_HEADER ModeData, _Inout_ PULONG ModeDataSize, _Out_ PVOID *PageData)
Definition: diskwmi.c:903
NTSTATUS DiskGetIdentifyInfo(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, PBOOLEAN SupportSmart)
Definition: diskwmi.c:813
struct STOR_ADDRESS_ALIGN _STOR_ADDR_BTL8 STOR_ADDR_BTL8
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
UCHAR bBuffer[1]
Definition: helper.h:27
#define WMI_STORAGE_SCSI_INFO_EXCEPTIONS_GUID
Definition: wmidata.h:337
struct _READ_LOG_SECTORS_OUT * PREAD_LOG_SECTORS_OUT
IO_WORKITEM_ROUTINE DiskReregWorker
Definition: diskwmi.c:70
PVOID SenseInfoBuffer
Definition: srb.h:256
struct DISKREREGREQUEST * PDISKREREGREQUEST
_Must_inspect_result_ _Inout_ PFLT_VOLUME _In_opt_ PCUNICODE_STRING InstanceName
Definition: fltkernel.h:1162
NTSTATUS DiskSendFailurePredictIoctl(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, PSTORAGE_PREDICT_FAILURE checkFailure)
Definition: diskwmi.c:854
#define BOOLEAN
Definition: pedump.c:73
#define OUT
Definition: typedefs.h:40
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define MODE_DATA_SIZE
Definition: cdrom.c:173
_inline NTSTATUS DiskDisableSmart(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: diskwmi.c:293
#define SmartPerformFunction
Definition: diskwmi.c:143
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
#define SmartDataGuid
Definition: diskwmi.c:142
#define STATUS_WMI_ITEMID_NOT_FOUND
Definition: ntstatus.h:778
struct tagContext Context
Definition: acpixf.h:1034
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
#define SMART_WRITE_LOG
Definition: ntdddisk.h:721
#define WMI_DISK_GEOMETRY_GUID
Definition: ntdddisk.h:366
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define IOCTL_SCSI_MINIPORT_DISABLE_SMART
Definition: cdrw_hw.h:1462
UCHAR bDriveNumber
Definition: helper.h:33
#define EnableOfflineDiags
Definition: diskwmi.c:148
#define GetFailurePredictionCapability
Definition: diskwmi.c:147
ULONG NTAPI ClassModeSenseEx(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ UCHAR PageControl)
Definition: class.c:6656
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
static const WCHAR Signature[]
Definition: parser.c:141
IoMarkIrpPending(Irp)
Definition: helper.h:8
static SERVICE_STATUS status
Definition: service.c:31
#define SRBEX_DATA_SCSI_CDB16_LENGTH
Definition: srb.h:480
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2676
unsigned short * PUSHORT
Definition: retypes.h:2
#define WMIREG_FLAG_EXPENSIVE
Definition: wmistr.h:66
struct _WRITE_LOG_SECTORS_OUT WRITE_LOG_SECTORS_OUT
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:387
LONGLONG QuadPart
Definition: typedefs.h:114
#define _Analysis_assume_(expr)
Definition: no_sal2.h:10
struct _SENDCMDINPARAMS * PSENDCMDINPARAMS
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97