ReactOS  0.4.15-dev-1206-g731eddf
pnp.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (C) Microsoft Corporation, 1991 - 1999
4 
5 Module Name:
6 
7  pnp.c
8 
9 Abstract:
10 
11  SCSI disk class driver
12 
13 Environment:
14 
15  kernel mode only
16 
17 Notes:
18 
19 Revision History:
20 
21 --*/
22 
23 #include "disk.h"
24 
25 
26 #ifdef DEBUG_USE_WPP
27 #include "pnp.tmh"
28 #endif
29 
30 #ifndef __REACTOS__
32 #else
34 #endif
37 
38 
39 #ifdef ALLOC_PRAGMA
40 
41 #pragma alloc_text(PAGE, DiskAddDevice)
42 #pragma alloc_text(PAGE, DiskInitFdo)
43 #pragma alloc_text(PAGE, DiskStartFdo)
44 #pragma alloc_text(PAGE, DiskGenerateDeviceName)
45 #pragma alloc_text(PAGE, DiskCreateSymbolicLinks)
46 #pragma alloc_text(PAGE, DiskDeleteSymbolicLinks)
47 #pragma alloc_text(PAGE, DiskRemoveDevice)
48 #endif
49 
50 
52 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
56  )
57 
58 /*++
59 
60 Routine Description:
61 
62  This routine gets a port drivers capabilities, obtains the
63  inquiry data, searches the SCSI bus for the port driver and creates
64  the device objects for the disks found.
65 
66 Arguments:
67 
68  DriverObject - Pointer to driver object created by system.
69 
70  Pdo - Device object use to send requests to port driver.
71 
72 Return Value:
73 
74  True is returned if one disk was found and successfully created.
75 
76 --*/
77 
78 {
79  ULONG rootPartitionMountable = FALSE;
80 
81  PCONFIGURATION_INFORMATION configurationInformation;
82  ULONG diskCount;
83 
85 
86  PAGED_CODE();
87 
88  //
89  // See if we should be allowing file systems to mount on partition zero.
90  //
91 
92  TRY {
93  HANDLE deviceKey = NULL;
94 
95  UNICODE_STRING diskKeyName;
96  OBJECT_ATTRIBUTES objectAttributes = {0};
97  HANDLE diskKey;
98 
99  RTL_QUERY_REGISTRY_TABLE queryTable[2] = { 0 };
100 
103  KEY_READ,
104  &deviceKey);
105 
106  if(!NT_SUCCESS(status)) {
107  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskAddDevice: Error %#08lx opening device key "
108  "for pdo %p\n",
110  LEAVE;
111  }
112 
113  RtlInitUnicodeString(&diskKeyName, L"Disk");
114  InitializeObjectAttributes(&objectAttributes,
115  &diskKeyName,
117  deviceKey,
118  NULL);
119 
120  status = ZwOpenKey(&diskKey, KEY_READ, &objectAttributes);
121  ZwClose(deviceKey);
122 
123  if(!NT_SUCCESS(status)) {
124  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskAddDevice: Error %#08lx opening disk key "
125  "for pdo %p device key %p\n",
126  status, PhysicalDeviceObject, deviceKey));
127  LEAVE;
128  }
129 
131  queryTable[0].Name = L"RootPartitionMountable";
132  queryTable[0].EntryContext = &(rootPartitionMountable);
134 
135 #pragma prefast(suppress:6309, "We don't have QueryRoutine so Context doesn't make any sense")
137  diskKey,
138  queryTable,
139  NULL,
140  NULL);
141 
142  if(!NT_SUCCESS(status)) {
143  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskAddDevice: Error %#08lx reading value from "
144  "disk key %p for pdo %p\n",
145  status, diskKey, PhysicalDeviceObject));
146  }
147 
148  ZwClose(diskKey);
149 
150  } FINALLY {
151 
152  //
153  // Do nothing.
154  //
155 
156  if(!NT_SUCCESS(status)) {
157  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskAddDevice: Will %sallow file system to mount on "
158  "partition zero of disk %p\n",
159  (rootPartitionMountable ? "" : "not "),
161  }
162  }
163 
164  //
165  // Create device objects for disk
166  //
167 
168  diskCount = 0;
169 
171  DriverObject,
173  &diskCount,
174  (BOOLEAN) !rootPartitionMountable
175  );
176 
177  //
178  // Get the number of disks already initialized.
179  //
180 
181  configurationInformation = IoGetConfigurationInformation();
182 
183  if (NT_SUCCESS(status)) {
184 
185  //
186  // Increment system disk device count.
187  //
188 
189  configurationInformation->DiskCount++;
190 
191  }
192 
193  return status;
194 
195 } // end DiskAddDevice()
196 
197 
198 NTSTATUS
199 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
201  IN PDEVICE_OBJECT Fdo
202  )
203 
204 /*++
205 
206 Routine Description:
207 
208  This routine is called to do one-time initialization of new device objects
209 
210 
211 Arguments:
212 
213  Fdo - a pointer to the functional device object for this device
214 
215 Return Value:
216 
217  status
218 
219 --*/
220 
221 {
222  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
223  PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData;
224 
225  ULONG srbFlags = 0;
226  ULONG timeOut = 0;
227  ULONG bytesPerSector;
228 
229  PULONG dmSkew;
230 
232 
233  PAGED_CODE();
234 
235  //
236  // Build the lookaside list for srb's for the physical disk. Should only
237  // need a couple. If this fails then we don't have an emergency SRB so
238  // fail the call to initialize.
239  //
240 
241  ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION) fdoExtension,
243 
244  if (fdoExtension->DeviceDescriptor->RemovableMedia)
245  {
246  SET_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA);
247  }
248 
249  //
250  // Initialize the srb flags.
251  //
252 
253  //
254  // Because all requests share a common sense buffer, it is possible
255  // for the buffer to be overwritten if the port driver completes
256  // multiple failed requests that require a request sense before the
257  // class driver's completion routine can consume the data in the buffer.
258  // To prevent this, we allow the port driver to allocate a unique sense
259  // buffer each time it needs one. We are responsible for freeing this
260  // buffer. This also allows the adapter to be configured to support
261  // additional sense data beyond the minimum 18 bytes.
262  //
263 
264  SET_FLAG(fdoExtension->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE);
265 
266  if (fdoExtension->DeviceDescriptor->CommandQueueing &&
267  fdoExtension->AdapterDescriptor->CommandQueueing) {
268 
269  SET_FLAG(fdoExtension->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
270 
271  }
272 
273  //
274  // Look for controllers that require special flags.
275  //
276 
277  ClassScanForSpecial(fdoExtension, DiskBadControllers, DiskSetSpecialHacks);
278 
279  //
280  // Clear buffer for drive geometry.
281  //
282 
283  RtlZeroMemory(&(fdoExtension->DiskGeometry),
284  sizeof(DISK_GEOMETRY));
285 
286  //
287  // Allocate request sense buffer.
288  //
289 
290  fdoExtension->SenseData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
293 
294  if (fdoExtension->SenseData == NULL) {
295 
296  //
297  // The buffer can not be allocated.
298  //
299 
300  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskInitFdo: Can not allocate request sense buffer\n"));
301 
303  return status;
304  }
305 
306  //
307  // Set the buffer size of SenseData
308  //
309 
310  fdoExtension->SenseDataLength = SENSE_BUFFER_SIZE_EX;
311 
312  //
313  // Physical device object will describe the entire
314  // device, starting at byte offset 0.
315  //
316 
317  fdoExtension->CommonExtension.StartingOffset.QuadPart = (LONGLONG)(0);
318 
319  //
320  // Set timeout value in seconds.
321  //
322  if ( (fdoExtension->MiniportDescriptor != NULL) &&
323  (fdoExtension->MiniportDescriptor->IoTimeoutValue > 0) ) {
324  //
325  // use the value set by Storport miniport driver
326  //
327  fdoExtension->TimeOutValue = fdoExtension->MiniportDescriptor->IoTimeoutValue;
328  } else {
329  //
330  // get timeout value from registry
331  //
332  timeOut = ClassQueryTimeOutRegistryValue(Fdo);
333 
334  if (timeOut) {
335  fdoExtension->TimeOutValue = timeOut;
336  } else {
337  fdoExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
338  }
339  }
340  //
341  // If this is a removable drive, build an entry in devicemap\scsi
342  // indicating it's physicaldriveN name, set up the appropriate
343  // update partitions routine and set the flags correctly.
344  // note: only do this after the timeout value is set, above.
345  //
346 
347  if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
348 
349  ClassUpdateInformationInRegistry( Fdo,
350  "PhysicalDrive",
351  fdoExtension->DeviceNumber,
352  NULL,
353  0);
354  //
355  // Enable media change notification for removable disks
356  //
357  ClassInitializeMediaChangeDetection(fdoExtension,
358  (PUCHAR)"Disk");
359 
360  } else {
361 
362  SET_FLAG(fdoExtension->DeviceFlags, DEV_SAFE_START_UNIT);
363  SET_FLAG(fdoExtension->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
364 
365  }
366 
367  //
368  // The commands we send during the init could cause the flags to change
369  // in case of any error. Save the SRB flags locally and restore it at
370  // the end of this function, so that the class driver can get it.
371  //
372 
373  srbFlags = fdoExtension->SrbFlags;
374 
375 
376  //
377  // Read the drive capacity. Don't use the disk version of the routine here
378  // since we don't know the disk signature yet - the disk version will
379  // attempt to determine the BIOS reported geometry.
380  //
381 
383 
384  //
385  // Set up sector size fields.
386  //
387  // Stack variables will be used to update
388  // the partition device extensions.
389  //
390  // The device extension field SectorShift is
391  // used to calculate sectors in I/O transfers.
392  //
393  // The DiskGeometry structure is used to service
394  // IOCTls used by the format utility.
395  //
396 
397  bytesPerSector = fdoExtension->DiskGeometry.BytesPerSector;
398 
399  //
400  // Make sure sector size is not zero.
401  //
402 
403  if (bytesPerSector == 0) {
404 
405  //
406  // Default sector size for disk is 512.
407  //
408 
409  bytesPerSector = fdoExtension->DiskGeometry.BytesPerSector = 512;
410  fdoExtension->SectorShift = 9;
411  }
412 
413  //
414  // Determine is DM Driver is loaded on an IDE drive that is
415  // under control of Atapi - this could be either a crashdump or
416  // an Atapi device is sharing the controller with an IDE disk.
417  //
418 
419  HalExamineMBR(fdoExtension->CommonExtension.DeviceObject,
420  fdoExtension->DiskGeometry.BytesPerSector,
421  (ULONG)0x54,
422  (PVOID *)&dmSkew);
423 
424  if (dmSkew) {
425 
426  //
427  // Update the device extension, so that the call to IoReadPartitionTable
428  // will get the correct information. Any I/O to this disk will have
429  // to be skewed by *dmSkew sectors aka DMByteSkew.
430  //
431 
432  fdoExtension->DMSkew = *dmSkew;
433  fdoExtension->DMActive = TRUE;
434  fdoExtension->DMByteSkew = fdoExtension->DMSkew * bytesPerSector;
435 
436  FREE_POOL(dmSkew);
437  }
438 
439 #if defined(_X86_) || defined(_AMD64_)
440 
441  //
442  // Try to read the signature off the disk and determine the correct drive
443  // geometry based on that. This requires rereading the disk size to get
444  // the cylinder count updated correctly.
445  //
446 
447  if(!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
448 
449  DiskReadSignature(Fdo);
451 
452  if (diskData->GeometrySource == DiskGeometryUnknown)
453  {
454  //
455  // Neither the BIOS nor the port driver could provide us with a reliable
456  // geometry. Before we use the default, look to see if it was partitioned
457  // under Windows NT4 [or earlier] and apply the one that was used back then
458  //
459 
460  if (DiskIsNT4Geometry(fdoExtension))
461  {
462  diskData->RealGeometry = fdoExtension->DiskGeometry;
463  diskData->RealGeometry.SectorsPerTrack = 0x20;
464  diskData->RealGeometry.TracksPerCylinder = 0x40;
465  fdoExtension->DiskGeometry = diskData->RealGeometry;
466 
467  diskData->GeometrySource = DiskGeometryFromNT4;
468  }
469  }
470  }
471 
472 #endif
473 
475 
476  //
477  // Get the SCSI address if it's available for use with SMART ioctls.
478  // SMART ioctls are used for failure prediction, so we need to get
479  // the SCSI address before initializing failure prediction.
480  //
481 
482  {
483  PIRP irp;
484  KEVENT event;
485  IO_STATUS_BLOCK statusBlock = { 0 };
486 
488 
490  fdoExtension->CommonExtension.LowerDeviceObject,
491  NULL,
492  0L,
493  &(diskData->ScsiAddress),
494  sizeof(SCSI_ADDRESS),
495  FALSE,
496  &event,
497  &statusBlock);
498 
500 
501  if(irp != NULL) {
502 
503  status = IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, irp);
504 
505  if(status == STATUS_PENDING) {
507  Executive,
508  KernelMode,
509  FALSE,
510  NULL);
511  status = statusBlock.Status;
512  }
513  }
514  }
515 
516  //
517  // Determine the type of disk and enable failure prediction in the hardware
518  // and enable failure prediction polling.
519  //
520 
521  if (InitSafeBootMode == 0) // __REACTOS__
522  {
523  DiskDetectFailurePrediction(fdoExtension,
524  &diskData->FailurePredictionCapability,
525  NT_SUCCESS(status));
526 
528  {
529  //
530  // Cool, we've got some sort of failure prediction, enable it
531  // at the hardware and then enable polling for it
532  //
533 
534  //
535  // By default we allow performance to be degradeded if failure
536  // prediction is enabled.
537  //
538 
539  diskData->AllowFPPerfHit = TRUE;
540 
541  //
542  // Enable polling only after Atapi and SBP2 add support for the new
543  // SRB flag that indicates that the request should not reset the
544  // drive spin down idle timer.
545  //
546 
548  TRUE,
550 
551  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskInitFdo: Failure Prediction Poll enabled as "
552  "%d for device %p, Status = %lx\n",
553  diskData->FailurePredictionCapability,
554  Fdo,
555  status));
556  }
557  } else {
558 
559  //
560  // In safe boot mode we do not enable failure prediction, as perhaps
561  // it is the reason why normal boot does not work
562  //
563 
565 
566  }
567 
568  //
569  // Initialize the verify mutex
570  //
571 
573 
574  //
575  // Initialize the flush group context
576  //
577 
578  RtlZeroMemory(&diskData->FlushContext, sizeof(DISK_GROUP_CONTEXT));
579 
582 
585 
586 
587  //
588  // Restore the saved value
589  //
590  fdoExtension->SrbFlags = srbFlags;
591 
592  return STATUS_SUCCESS;
593 
594 } // end DiskInitFdo()
595 
596 NTSTATUS
597 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
600  IN UCHAR Type
601  )
602 
603 {
606  return STATUS_SUCCESS;
607 }
608 
609 NTSTATUS
612  OUT PCCHAR *RawName
613  )
614 
615 /*++
616 
617 Routine Description:
618 
619  This routine will allocate a unicode string buffer and then fill it in
620  with a generated name for the specified device object.
621 
622  It is the responsibility of the user to allocate a UNICODE_STRING structure
623  to pass in and to free UnicodeName->Buffer when done with it.
624 
625 Arguments:
626 
627  DeviceObject - a pointer to the device object
628 
629  UnicodeName - a unicode string to put the name buffer into
630 
631 Return Value:
632 
633  status
634 
635 --*/
636 
637 #define FDO_NAME_FORMAT "\\Device\\Harddisk%d\\DR%d"
638 
639 {
640  CHAR rawName[64] = { 0 };
642 
643  PAGED_CODE();
644 
645  status = RtlStringCchPrintfA(rawName, sizeof(rawName) - 1, FDO_NAME_FORMAT, DeviceNumber,
647  if (!NT_SUCCESS(status)) {
648  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskGenerateDeviceName: Format FDO name failed with error: 0x%X\n", status));
649  return status;
650  }
651 
652  *RawName = ExAllocatePoolWithTag(PagedPool,
653  strlen(rawName) + 1,
654  DISK_TAG_NAME);
655 
656  if(*RawName == NULL) {
658  }
659 
660  status = RtlStringCchCopyA(*RawName, strlen(rawName) + 1, rawName);
661  if (!NT_SUCCESS(status)) {
662  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskGenerateDeviceName: Device name copy failed with error: 0x%X\n", status));
663  FREE_POOL(*RawName);
664  return status;
665  }
666 
667  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskGenerateDeviceName: generated \"%s\"\n", rawName));
668 
669  return STATUS_SUCCESS;
670 }
671 
672 
673 VOID
676  )
677 
678 /*++
679 
680 Routine Description:
681 
682  This routine will generate a symbolic link for the specified device object
683  using the well known form \\Device\HarddiskX\PartitionY, where X and Y is
684  always 0 which represents the entire disk object.
685 
686  This routine will not try to delete any previous symbolic link for the
687  same generated name - the caller must make sure the symbolic link has
688  been broken before calling this routine.
689 
690 Arguments:
691 
692  DeviceObject - the device object to make a well known name for
693 
694 Return Value:
695 
696  STATUS
697 
698 --*/
699 
700 {
701  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
702  PDISK_DATA diskData = commonExtension->DriverData;
703 
704  WCHAR wideSourceName[64] = { 0 };
705  UNICODE_STRING unicodeSourceName;
706 
708 
709  PAGED_CODE();
710 
711  //
712  // Build the destination for the link first using the device name
713  // stored in the device object
714  //
715 
716  NT_ASSERT(commonExtension->DeviceName.Buffer);
717 
718  if(!diskData->LinkStatus.WellKnownNameCreated) {
719  //
720  // Put together the source name using the partition and device number
721  // in the device extension and disk data segment
722  //
723 
724  status = RtlStringCchPrintfW(wideSourceName, sizeof(wideSourceName) / sizeof(wideSourceName[0]) - 1,
725  L"\\Device\\Harddisk%d\\Partition0",
726  commonExtension->PartitionZeroExtension->DeviceNumber);
727 
728  if (NT_SUCCESS(status)) {
729 
730  RtlInitUnicodeString(&unicodeSourceName, wideSourceName);
731 
732  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskCreateSymbolicLink: Linking %wZ to %wZ\n",
733  &unicodeSourceName,
734  &commonExtension->DeviceName));
735 
736  status = IoCreateSymbolicLink(&unicodeSourceName,
737  &commonExtension->DeviceName);
738 
739  if(NT_SUCCESS(status)){
740  diskData->LinkStatus.WellKnownNameCreated = TRUE;
741  }
742  }
743  }
744 
745  if (!diskData->LinkStatus.PhysicalDriveLinkCreated) {
746 
747  //
748  // Create a physical drive N link using the device number we saved
749  // away during AddDevice.
750  //
751 
752  status = RtlStringCchPrintfW(wideSourceName, sizeof(wideSourceName) / sizeof(wideSourceName[0]) - 1,
753  L"\\DosDevices\\PhysicalDrive%d",
754  commonExtension->PartitionZeroExtension->DeviceNumber);
755  if (NT_SUCCESS(status)) {
756 
757  RtlInitUnicodeString(&unicodeSourceName, wideSourceName);
758 
759  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskCreateSymbolicLink: Linking %wZ to %wZ\n",
760  &unicodeSourceName,
761  &(commonExtension->DeviceName)));
762 
763  status = IoCreateSymbolicLink(&unicodeSourceName,
764  &(commonExtension->DeviceName));
765 
766  if(NT_SUCCESS(status)) {
767  diskData->LinkStatus.PhysicalDriveLinkCreated = TRUE;
768  }
769  }
770  }
771 
772 
773  return;
774 }
775 
776 
777 VOID
780  )
781 
782 /*++
783 
784 Routine Description:
785 
786  This routine will delete the well known name (symlink) for the specified
787  device. It generates the link name using information stored in the
788  device extension
789 
790 Arguments:
791 
792  DeviceObject - the device object we are unlinking
793 
794 Return Value:
795 
796  status
797 
798 --*/
799 
800 {
801  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
802  PDISK_DATA diskData = commonExtension->DriverData;
803 
804  WCHAR wideLinkName[64] = { 0 };
805  UNICODE_STRING unicodeLinkName;
807 
808  PAGED_CODE();
809 
810  if(diskData->LinkStatus.WellKnownNameCreated) {
811 
812  status = RtlStringCchPrintfW(wideLinkName, sizeof(wideLinkName) / sizeof(wideLinkName[0]) - 1,
813  L"\\Device\\Harddisk%d\\Partition0",
814  commonExtension->PartitionZeroExtension->DeviceNumber);
815  if (NT_SUCCESS(status)) {
816  RtlInitUnicodeString(&unicodeLinkName, wideLinkName);
817  IoDeleteSymbolicLink(&unicodeLinkName);
818  }
819  diskData->LinkStatus.WellKnownNameCreated = FALSE;
820  }
821 
822  if(diskData->LinkStatus.PhysicalDriveLinkCreated) {
823 
824  status = RtlStringCchPrintfW(wideLinkName, sizeof(wideLinkName) / sizeof(wideLinkName[0]) - 1,
825  L"\\DosDevices\\PhysicalDrive%d",
826  commonExtension->PartitionZeroExtension->DeviceNumber);
827  if (NT_SUCCESS(status)) {
828  RtlInitUnicodeString(&unicodeLinkName, wideLinkName);
829  IoDeleteSymbolicLink(&unicodeLinkName);
830  }
831  diskData->LinkStatus.PhysicalDriveLinkCreated = FALSE;
832  }
833 
834 
835  return;
836 }
837 
838 
839 NTSTATUS
840 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
843  IN UCHAR Type
844  )
845 
846 /*++
847 
848 Routine Description:
849 
850  This routine will release any resources the device may have allocated for
851  this device object and return.
852 
853 Arguments:
854 
855  DeviceObject - the device object being removed
856 
857 Return Value:
858 
859  status
860 
861 --*/
862 
863 {
864  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
865  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
866 
867  PAGED_CODE();
868 
869  //
870  // Handle query and cancel
871  //
872 
875  return STATUS_SUCCESS;
876  }
877 
878  //
879  // Delete our object directory.
880  //
881 
882  if(fdoExtension->DeviceDirectory != NULL) {
883  ZwMakeTemporaryObject(fdoExtension->DeviceDirectory);
884  ZwClose(fdoExtension->DeviceDirectory);
885  fdoExtension->DeviceDirectory = NULL;
886  }
887 
888  if(Type == IRP_MN_REMOVE_DEVICE) {
889 
890  FREE_POOL(fdoExtension->SenseData);
891 
893 
894  }
895 
897 
898  if (Type == IRP_MN_REMOVE_DEVICE)
899  {
900  ClassDeleteSrbLookasideList(commonExtension);
901  }
902 
903  return STATUS_SUCCESS;
904 }
905 
906 
907 NTSTATUS
908 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
910  IN PDEVICE_OBJECT Fdo
911  )
912 
913 /*++
914 
915 Routine Description:
916 
917  This routine will query the underlying device for any information necessary
918  to complete initialization of the device. This will include physical
919  disk geometry, mode sense information and such.
920 
921  This routine does not perform partition enumeration - that is left to the
922  re-enumeration routine
923 
924  If this routine fails it will return an error value. It does not clean up
925  any resources - that is left for the Stop/Remove routine.
926 
927 Arguments:
928 
929  Fdo - a pointer to the functional device object for this device
930 
931 Return Value:
932 
933  status
934 
935 --*/
936 
937 {
938  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
939  PCOMMON_DEVICE_EXTENSION commonExtension = &(fdoExtension->CommonExtension);
940  PDISK_DATA diskData = commonExtension->DriverData;
941  STORAGE_HOTPLUG_INFO hotplugInfo = { 0 };
942  DISK_CACHE_INFORMATION cacheInfo = { 0 };
943  ULONG isPowerProtected = 0;
945 
946  PAGED_CODE();
947 
948  //
949  // Get the hotplug information, so we can turn off write cache if needed
950  //
951  // NOTE: Capabilities info is not good enough to determine hotplugedness
952  // as we cannot determine device relations information and other
953  // dependencies. Get the hotplug info instead
954  //
955 
956  {
957  PIRP irp;
958  KEVENT event;
959  IO_STATUS_BLOCK statusBlock = { 0 };
960 
962 
964  Fdo,
965  NULL,
966  0L,
967  &hotplugInfo,
968  sizeof(STORAGE_HOTPLUG_INFO),
969  FALSE,
970  &event,
971  &statusBlock);
972 
973  if (irp != NULL) {
974 
975  // send to self -- classpnp handles this
976  status = IoCallDriver(Fdo, irp);
977  if (status == STATUS_PENDING) {
979  Executive,
980  KernelMode,
981  FALSE,
982  NULL);
983 
984  status = statusBlock.Status;
985  }
987  }
988  }
989 
990  //
991  // Clear the DEV_WRITE_CACHE flag now and set
992  // it below only if we read that from the disk
993  //
994  CLEAR_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
995  ADJUST_FUA_FLAG(fdoExtension);
996 
998 
999  //
1000  // Look into the registry to see if the user
1001  // has chosen to override the default setting
1002  //
1003  ClassGetDeviceParameter(fdoExtension,
1006  (PULONG)&diskData->WriteCacheOverride);
1007 
1008  if (diskData->WriteCacheOverride == DiskWriteCacheDefault)
1009  {
1010  //
1011  // The user has not overridden the default settings
1012  //
1014  {
1015  //
1016  // This flag indicates that we have faulty firmware and this
1017  // may cause the filesystem to refuse to mount on this media
1018  //
1019  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to a firmware issue\n", Fdo));
1020 
1022  }
1023  else if (hotplugInfo.DeviceHotplug && !hotplugInfo.WriteCacheEnableOverride)
1024  {
1025  //
1026  // This flag indicates that the device is hotpluggable making it unsafe to enable caching
1027  //
1028  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to hotpluggable device\n", Fdo));
1029 
1031  }
1032  else if (hotplugInfo.MediaHotplug)
1033  {
1034  //
1035  // This flag indicates that the media in the device cannot be reliably locked
1036  //
1037  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to unlockable media\n", Fdo));
1038 
1040  }
1041  else
1042  {
1043  //
1044  // Even though the device does not seem to have any obvious problems
1045  // we leave it to the user to modify the previous write cache setting
1046  //
1047  }
1048  }
1049 
1050  //
1051  // Query the disk to see if write cache is enabled
1052  // and set the DEV_WRITE_CACHE flag appropriately
1053  //
1054 
1055  status = DiskGetCacheInformation(fdoExtension, &cacheInfo);
1056 
1057  if (NT_SUCCESS(status))
1058  {
1059  if (cacheInfo.WriteCacheEnabled == TRUE)
1060  {
1061  SET_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
1062  ADJUST_FUA_FLAG(fdoExtension);
1063 
1064  if (diskData->WriteCacheOverride == DiskWriteCacheDisable)
1065  {
1066  //
1067  // Write cache is currently enabled on this
1068  // device, but we would like to turn it off
1069  //
1070  cacheInfo.WriteCacheEnabled = FALSE;
1071 
1072  DiskSetCacheInformation(fdoExtension, &cacheInfo);
1073  }
1074  }
1075  else
1076  {
1077  if (diskData->WriteCacheOverride == DiskWriteCacheEnable)
1078  {
1079  //
1080  // Write cache is currently disabled on this
1081  // device, but we would like to turn it on
1082  //
1083  cacheInfo.WriteCacheEnabled = TRUE;
1084 
1085  DiskSetCacheInformation(fdoExtension, &cacheInfo);
1086  }
1087  }
1088  }
1089 
1090  //
1091  // Query the registry to see if this disk is power-protected or not
1092  //
1093 
1094  CLEAR_FLAG(fdoExtension->DeviceFlags, DEV_POWER_PROTECTED);
1095 
1096  ClassGetDeviceParameter(fdoExtension, DiskDeviceParameterSubkey, DiskDeviceCacheIsPowerProtected, &isPowerProtected);
1097 
1098  if (isPowerProtected == 1)
1099  {
1100  SET_FLAG(fdoExtension->DeviceFlags, DEV_POWER_PROTECTED);
1101  }
1102 
1103  ADJUST_FUA_FLAG(fdoExtension);
1104 
1105  return STATUS_SUCCESS;
1106 
1107 } // end DiskStartFdo()
1108 
#define FINALLY
Definition: classpnp.h:116
#define IRP_MN_CANCEL_REMOVE_DEVICE
struct _DISK_DATA * PDISK_DATA
#define IN
Definition: typedefs.h:39
#define IRP_MN_REMOVE_DEVICE
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
Type
Definition: Type.h:6
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Definition: iorsrce.c:830
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2782
BOOLEAN DeviceHotplug
Definition: imports.h:248
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSTATUS NTAPI DiskAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)
Definition: pnp.c:53
VOID NTAPI DiskSetSpecialHacks(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN ULONG_PTR Data)
Definition: disk.c:2598
CLASSPNP_SCAN_FOR_SPECIAL_INFO DiskBadControllers[]
Definition: data.c:38
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
LONG NTSTATUS
Definition: precomp.h:26
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
#define LEAVE
Definition: classpnp.h:115
#define TRY(sps, bps)
#define DISK_DEFAULT_FAILURE_POLLING_PERIOD
Definition: disk.h:456
#define IOCTL_STORAGE_GET_HOTPLUG_INFO
Definition: imports.h:238
SCSI_ADDRESS ScsiAddress
Definition: disk.h:325
NTSTATUS NTAPI DiskInitFdo(IN PDEVICE_OBJECT Fdo)
Definition: pnp.c:200
LIST_ENTRY CurrList
Definition: disk.h:108
NTSTATUS NTAPI DiskStopDevice(IN PDEVICE_OBJECT DeviceObject, IN UCHAR Type)
Definition: pnp.c:598
KSPIN_LOCK Spinlock
Definition: disk.h:143
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1155
#define DISK_TAG_START
Definition: disk.h:68
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
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
#define NTSYSAPI
Definition: ntoskrnl.h:14
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
BOOLEAN AllowFPPerfHit
Definition: disk.h:332
NTSTATUS DiskGenerateDeviceName(IN ULONG DeviceNumber, OUT PCCHAR *RawName)
Definition: pnp.c:610
#define DEV_WRITE_CACHE
Definition: class2.h:21
_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:2742
BOOLEAN MediaHotplug
Definition: imports.h:247
#define DiskDeviceParameterSubkey
Definition: disk.h:403
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define CLASS_SPECIAL_DISABLE_WRITE_CACHE
Definition: classpnp.h:168
#define FALSE
Definition: types.h:117
#define IRP_MN_QUERY_REMOVE_DEVICE
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define ADJUST_FUA_FLAG(fdoExt)
Definition: classpnp.h:53
VOID DiskCreateSymbolicLinks(IN PDEVICE_OBJECT DeviceObject)
Definition: pnp.c:674
NTSTRSAFEVAPI RtlStringCchPrintfA(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1085
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:238
unsigned char BOOLEAN
#define MAX_SECTORS_PER_VERIFY
Definition: disk.h:435
VOID DiskDeleteSymbolicLinks(IN PDEVICE_OBJECT DeviceObject)
Definition: pnp.c:778
smooth NULL
Definition: ftsmooth.c:416
DISK_USER_WRITE_CACHE_SETTING WriteCacheOverride
Definition: disk.h:385
KEVENT Event
Definition: disk.h:148
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
#define RTL_QUERY_REGISTRY_TYPECHECK
#define SCSI_DISK_TIMEOUT
Definition: disk.c:166
#define DEV_SAFE_START_UNIT
Definition: cdrom.h:139
UNICODE_STRING DeviceName
Definition: classpnp.h:615
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
NTSTATUS DiskEnableDisableFailurePredictPolling(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, BOOLEAN Enable, ULONG PollTimeInSeconds)
Definition: diskwmi.c:1193
LARGE_INTEGER StartingOffset
Definition: classpnp.h:619
#define FDO_NAME_FORMAT
int64_t LONGLONG
Definition: typedefs.h:68
PDEVICE_OBJECT DeviceObject
Definition: pci.h:43
NTSTATUS DiskCreateFdo(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject, IN PULONG DeviceCount, IN BOOLEAN DasdAccessOnly)
Definition: disk.c:307
struct _DISK_DATA::@1038 LinkStatus
BOOLEAN WriteCacheEnableOverride
Definition: imports.h:249
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define DiskReadDriveCapacity(Fdo)
Definition: disk.h:814
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:596
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define DISK_TAG_NAME
Definition: disk.h:64
NTSTATUS NTAPI DiskRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN UCHAR Type)
Definition: pnp.c:841
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID NTAPI KeInitializeMutex(IN PKMUTEX Mutex, IN ULONG Level)
Definition: mutex.c:67
NTSTATUS NTAPI DiskGetCacheInformation(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PDISK_CACHE_INFORMATION CacheInfo)
Definition: disk.c:3015
#define PARTITION0_LIST_SIZE
Definition: disk.c:167
static const WCHAR L[]
Definition: oid.c:1250
#define VOID
Definition: acefi.h:82
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
FAILURE_PREDICTION_METHOD FailurePredictionCapability
Definition: disk.h:331
struct _cl_event * event
Definition: glext.h:7739
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define DEV_POWER_PROTECTED
Definition: cdrom.h:143
PULONG InitSafeBootMode
Definition: init.c:69
#define SRB_FLAGS_PORT_DRIVER_ALLOCSENSE
Definition: srb.h:405
LIST_ENTRY NextList
Definition: disk.h:118
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
DISK_GROUP_CONTEXT FlushContext
Definition: disk.h:379
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DiskDeviceUserWriteCacheSetting
Definition: disk.h:404
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
unsigned int * PULONG
Definition: retypes.h:1
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
NTSTATUS NTAPI IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject, IN ULONG DevInstKeyType, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DevInstRegKey)
Definition: pnpmgr.c:2335
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
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
VOID FASTCALL HalExamineMBR(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG MbrTypeIdentifier, OUT PVOID *MbrBuffer)
Definition: disksup.c:2688
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSTATUS NTAPI DiskStartFdo(IN PDEVICE_OBJECT Fdo)
Definition: pnp.c:909
NTSTATUS NTAPI DiskSetCacheInformation(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PDISK_CACHE_INFORMATION CacheInfo)
Definition: disk.c:3163
NTSTRSAFEAPI RtlStringCchCopyA(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:110
#define REG_NONE
Definition: nt_native.h:1492
_In_ PCHAR _In_ ULONG DeviceNumber
Definition: classpnp.h:1229
#define DiskDeviceCacheIsPowerProtected
Definition: disk.h:405
KMUTEX VerifyMutex
Definition: disk.h:372
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define REG_DWORD
Definition: sdbapi.c:596
static SERVICE_STATUS status
Definition: service.c:31
NTSYSAPI NTSTATUS NTAPI ZwMakeTemporaryObject(_In_ HANDLE Handle)
NTSTATUS DiskDetectFailurePrediction(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, PFAILURE_PREDICTION_METHOD FailurePredictCapability, BOOLEAN ScsiAddressAvailable)
Definition: diskwmi.c:2230
BOOLEAN DiskIsPastReinit
Definition: disk.c:81
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:387
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG diskDeviceSequenceNumber
Definition: pnp.c:35
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97