ReactOS  0.4.15-dev-2721-g5912c11
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 #ifdef _MSC_VER
136 #pragma prefast(suppress:6309, "We don't have QueryRoutine so Context doesn't make any sense")
137 #endif
139  diskKey,
140  queryTable,
141  NULL,
142  NULL);
143 
144  if(!NT_SUCCESS(status)) {
145  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskAddDevice: Error %#08lx reading value from "
146  "disk key %p for pdo %p\n",
147  status, diskKey, PhysicalDeviceObject));
148  }
149 
150  ZwClose(diskKey);
151 
152  } FINALLY {
153 
154  //
155  // Do nothing.
156  //
157 
158  if(!NT_SUCCESS(status)) {
159  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskAddDevice: Will %sallow file system to mount on "
160  "partition zero of disk %p\n",
161  (rootPartitionMountable ? "" : "not "),
163  }
164  }
165 
166  //
167  // Create device objects for disk
168  //
169 
170  diskCount = 0;
171 
173  DriverObject,
175  &diskCount,
176  (BOOLEAN) !rootPartitionMountable
177  );
178 
179  //
180  // Get the number of disks already initialized.
181  //
182 
183  configurationInformation = IoGetConfigurationInformation();
184 
185  if (NT_SUCCESS(status)) {
186 
187  //
188  // Increment system disk device count.
189  //
190 
191  configurationInformation->DiskCount++;
192 
193  }
194 
195  return status;
196 
197 } // end DiskAddDevice()
198 
199 
200 NTSTATUS
201 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
204  )
205 
206 /*++
207 
208 Routine Description:
209 
210  This routine is called to do one-time initialization of new device objects
211 
212 
213 Arguments:
214 
215  Fdo - a pointer to the functional device object for this device
216 
217 Return Value:
218 
219  status
220 
221 --*/
222 
223 {
224  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
225  PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData;
226 
227  ULONG srbFlags = 0;
228  ULONG timeOut = 0;
229  ULONG bytesPerSector;
230 
231  PULONG dmSkew;
232 
234 
235  PAGED_CODE();
236 
237  //
238  // Build the lookaside list for srb's for the physical disk. Should only
239  // need a couple. If this fails then we don't have an emergency SRB so
240  // fail the call to initialize.
241  //
242 
243  ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION) fdoExtension,
245 
246  if (fdoExtension->DeviceDescriptor->RemovableMedia)
247  {
248  SET_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA);
249  }
250 
251  //
252  // Initialize the srb flags.
253  //
254 
255  //
256  // Because all requests share a common sense buffer, it is possible
257  // for the buffer to be overwritten if the port driver completes
258  // multiple failed requests that require a request sense before the
259  // class driver's completion routine can consume the data in the buffer.
260  // To prevent this, we allow the port driver to allocate a unique sense
261  // buffer each time it needs one. We are responsible for freeing this
262  // buffer. This also allows the adapter to be configured to support
263  // additional sense data beyond the minimum 18 bytes.
264  //
265 
266  SET_FLAG(fdoExtension->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE);
267 
268  if (fdoExtension->DeviceDescriptor->CommandQueueing &&
269  fdoExtension->AdapterDescriptor->CommandQueueing) {
270 
271  SET_FLAG(fdoExtension->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
272 
273  }
274 
275  //
276  // Look for controllers that require special flags.
277  //
278 
279  ClassScanForSpecial(fdoExtension, DiskBadControllers, DiskSetSpecialHacks);
280 
281  //
282  // Clear buffer for drive geometry.
283  //
284 
285  RtlZeroMemory(&(fdoExtension->DiskGeometry),
286  sizeof(DISK_GEOMETRY));
287 
288  //
289  // Allocate request sense buffer.
290  //
291 
292  fdoExtension->SenseData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
295 
296  if (fdoExtension->SenseData == NULL) {
297 
298  //
299  // The buffer can not be allocated.
300  //
301 
302  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskInitFdo: Can not allocate request sense buffer\n"));
303 
305  return status;
306  }
307 
308  //
309  // Set the buffer size of SenseData
310  //
311 
312  fdoExtension->SenseDataLength = SENSE_BUFFER_SIZE_EX;
313 
314  //
315  // Physical device object will describe the entire
316  // device, starting at byte offset 0.
317  //
318 
319  fdoExtension->CommonExtension.StartingOffset.QuadPart = (LONGLONG)(0);
320 
321  //
322  // Set timeout value in seconds.
323  //
324  if ( (fdoExtension->MiniportDescriptor != NULL) &&
325  (fdoExtension->MiniportDescriptor->IoTimeoutValue > 0) ) {
326  //
327  // use the value set by Storport miniport driver
328  //
329  fdoExtension->TimeOutValue = fdoExtension->MiniportDescriptor->IoTimeoutValue;
330  } else {
331  //
332  // get timeout value from registry
333  //
334  timeOut = ClassQueryTimeOutRegistryValue(Fdo);
335 
336  if (timeOut) {
337  fdoExtension->TimeOutValue = timeOut;
338  } else {
339  fdoExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
340  }
341  }
342  //
343  // If this is a removable drive, build an entry in devicemap\scsi
344  // indicating it's physicaldriveN name, set up the appropriate
345  // update partitions routine and set the flags correctly.
346  // note: only do this after the timeout value is set, above.
347  //
348 
349  if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
350 
351  ClassUpdateInformationInRegistry( Fdo,
352  "PhysicalDrive",
353  fdoExtension->DeviceNumber,
354  NULL,
355  0);
356  //
357  // Enable media change notification for removable disks
358  //
359  ClassInitializeMediaChangeDetection(fdoExtension,
360  (PUCHAR)"Disk");
361 
362  } else {
363 
364  SET_FLAG(fdoExtension->DeviceFlags, DEV_SAFE_START_UNIT);
365  SET_FLAG(fdoExtension->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
366 
367  }
368 
369  //
370  // The commands we send during the init could cause the flags to change
371  // in case of any error. Save the SRB flags locally and restore it at
372  // the end of this function, so that the class driver can get it.
373  //
374 
375  srbFlags = fdoExtension->SrbFlags;
376 
377 
378  //
379  // Read the drive capacity. Don't use the disk version of the routine here
380  // since we don't know the disk signature yet - the disk version will
381  // attempt to determine the BIOS reported geometry.
382  //
383 
385 
386  //
387  // Set up sector size fields.
388  //
389  // Stack variables will be used to update
390  // the partition device extensions.
391  //
392  // The device extension field SectorShift is
393  // used to calculate sectors in I/O transfers.
394  //
395  // The DiskGeometry structure is used to service
396  // IOCTls used by the format utility.
397  //
398 
399  bytesPerSector = fdoExtension->DiskGeometry.BytesPerSector;
400 
401  //
402  // Make sure sector size is not zero.
403  //
404 
405  if (bytesPerSector == 0) {
406 
407  //
408  // Default sector size for disk is 512.
409  //
410 
411  bytesPerSector = fdoExtension->DiskGeometry.BytesPerSector = 512;
412  fdoExtension->SectorShift = 9;
413  }
414 
415  //
416  // Determine is DM Driver is loaded on an IDE drive that is
417  // under control of Atapi - this could be either a crashdump or
418  // an Atapi device is sharing the controller with an IDE disk.
419  //
420 
421  HalExamineMBR(fdoExtension->CommonExtension.DeviceObject,
422  fdoExtension->DiskGeometry.BytesPerSector,
423  (ULONG)0x54,
424  (PVOID *)&dmSkew);
425 
426  if (dmSkew) {
427 
428  //
429  // Update the device extension, so that the call to IoReadPartitionTable
430  // will get the correct information. Any I/O to this disk will have
431  // to be skewed by *dmSkew sectors aka DMByteSkew.
432  //
433 
434  fdoExtension->DMSkew = *dmSkew;
435  fdoExtension->DMActive = TRUE;
436  fdoExtension->DMByteSkew = fdoExtension->DMSkew * bytesPerSector;
437 
438  FREE_POOL(dmSkew);
439  }
440 
441 #if defined(_X86_) || defined(_AMD64_)
442 
443  //
444  // Try to read the signature off the disk and determine the correct drive
445  // geometry based on that. This requires rereading the disk size to get
446  // the cylinder count updated correctly.
447  //
448 
449  if(!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
450 
451  DiskReadSignature(Fdo);
453 
454  if (diskData->GeometrySource == DiskGeometryUnknown)
455  {
456  //
457  // Neither the BIOS nor the port driver could provide us with a reliable
458  // geometry. Before we use the default, look to see if it was partitioned
459  // under Windows NT4 [or earlier] and apply the one that was used back then
460  //
461 
462  if (DiskIsNT4Geometry(fdoExtension))
463  {
464  diskData->RealGeometry = fdoExtension->DiskGeometry;
465  diskData->RealGeometry.SectorsPerTrack = 0x20;
466  diskData->RealGeometry.TracksPerCylinder = 0x40;
467  fdoExtension->DiskGeometry = diskData->RealGeometry;
468 
469  diskData->GeometrySource = DiskGeometryFromNT4;
470  }
471  }
472  }
473 
474 #endif
475 
477 
478  //
479  // Get the SCSI address if it's available for use with SMART ioctls.
480  // SMART ioctls are used for failure prediction, so we need to get
481  // the SCSI address before initializing failure prediction.
482  //
483 
484  {
485  PIRP irp;
486  KEVENT event;
487  IO_STATUS_BLOCK statusBlock = { 0 };
488 
490 
492  fdoExtension->CommonExtension.LowerDeviceObject,
493  NULL,
494  0L,
495  &(diskData->ScsiAddress),
496  sizeof(SCSI_ADDRESS),
497  FALSE,
498  &event,
499  &statusBlock);
500 
502 
503  if(irp != NULL) {
504 
505  status = IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, irp);
506 
507  if(status == STATUS_PENDING) {
509  Executive,
510  KernelMode,
511  FALSE,
512  NULL);
513  status = statusBlock.Status;
514  }
515  }
516  }
517 
518  //
519  // Determine the type of disk and enable failure prediction in the hardware
520  // and enable failure prediction polling.
521  //
522 
523  if (InitSafeBootMode == 0) // __REACTOS__
524  {
525  DiskDetectFailurePrediction(fdoExtension,
526  &diskData->FailurePredictionCapability,
527  NT_SUCCESS(status));
528 
530  {
531  //
532  // Cool, we've got some sort of failure prediction, enable it
533  // at the hardware and then enable polling for it
534  //
535 
536  //
537  // By default we allow performance to be degradeded if failure
538  // prediction is enabled.
539  //
540 
541  diskData->AllowFPPerfHit = TRUE;
542 
543  //
544  // Enable polling only after Atapi and SBP2 add support for the new
545  // SRB flag that indicates that the request should not reset the
546  // drive spin down idle timer.
547  //
548 
550  TRUE,
552 
553  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskInitFdo: Failure Prediction Poll enabled as "
554  "%d for device %p, Status = %lx\n",
555  diskData->FailurePredictionCapability,
556  Fdo,
557  status));
558  }
559  } else {
560 
561  //
562  // In safe boot mode we do not enable failure prediction, as perhaps
563  // it is the reason why normal boot does not work
564  //
565 
567 
568  }
569 
570  //
571  // Initialize the verify mutex
572  //
573 
575 
576  //
577  // Initialize the flush group context
578  //
579 
580  RtlZeroMemory(&diskData->FlushContext, sizeof(DISK_GROUP_CONTEXT));
581 
584 
587 
588 
589  //
590  // Restore the saved value
591  //
592  fdoExtension->SrbFlags = srbFlags;
593 
594  return STATUS_SUCCESS;
595 
596 } // end DiskInitFdo()
597 
598 NTSTATUS
599 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
602  IN UCHAR Type
603  )
604 
605 {
608  return STATUS_SUCCESS;
609 }
610 
611 NTSTATUS
614  OUT PCCHAR *RawName
615  )
616 
617 /*++
618 
619 Routine Description:
620 
621  This routine will allocate a unicode string buffer and then fill it in
622  with a generated name for the specified device object.
623 
624  It is the responsibility of the user to allocate a UNICODE_STRING structure
625  to pass in and to free UnicodeName->Buffer when done with it.
626 
627 Arguments:
628 
629  DeviceObject - a pointer to the device object
630 
631  UnicodeName - a unicode string to put the name buffer into
632 
633 Return Value:
634 
635  status
636 
637 --*/
638 
639 #define FDO_NAME_FORMAT "\\Device\\Harddisk%d\\DR%d"
640 
641 {
642  CHAR rawName[64] = { 0 };
644 
645  PAGED_CODE();
646 
647  status = RtlStringCchPrintfA(rawName, sizeof(rawName) - 1, FDO_NAME_FORMAT, DeviceNumber,
649  if (!NT_SUCCESS(status)) {
650  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskGenerateDeviceName: Format FDO name failed with error: 0x%X\n", status));
651  return status;
652  }
653 
654  *RawName = ExAllocatePoolWithTag(PagedPool,
655  strlen(rawName) + 1,
656  DISK_TAG_NAME);
657 
658  if(*RawName == NULL) {
660  }
661 
662  status = RtlStringCchCopyA(*RawName, strlen(rawName) + 1, rawName);
663  if (!NT_SUCCESS(status)) {
664  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskGenerateDeviceName: Device name copy failed with error: 0x%X\n", status));
665  FREE_POOL(*RawName);
666  return status;
667  }
668 
669  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskGenerateDeviceName: generated \"%s\"\n", rawName));
670 
671  return STATUS_SUCCESS;
672 }
673 
674 
675 VOID
678  )
679 
680 /*++
681 
682 Routine Description:
683 
684  This routine will generate a symbolic link for the specified device object
685  using the well known form \\Device\HarddiskX\PartitionY, where X and Y is
686  always 0 which represents the entire disk object.
687 
688  This routine will not try to delete any previous symbolic link for the
689  same generated name - the caller must make sure the symbolic link has
690  been broken before calling this routine.
691 
692 Arguments:
693 
694  DeviceObject - the device object to make a well known name for
695 
696 Return Value:
697 
698  STATUS
699 
700 --*/
701 
702 {
703  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
704  PDISK_DATA diskData = commonExtension->DriverData;
705 
706  WCHAR wideSourceName[64] = { 0 };
707  UNICODE_STRING unicodeSourceName;
708 
710 
711  PAGED_CODE();
712 
713  //
714  // Build the destination for the link first using the device name
715  // stored in the device object
716  //
717 
718  NT_ASSERT(commonExtension->DeviceName.Buffer);
719 
720  if(!diskData->LinkStatus.WellKnownNameCreated) {
721  //
722  // Put together the source name using the partition and device number
723  // in the device extension and disk data segment
724  //
725 
726  status = RtlStringCchPrintfW(wideSourceName, sizeof(wideSourceName) / sizeof(wideSourceName[0]) - 1,
727  L"\\Device\\Harddisk%d\\Partition0",
728  commonExtension->PartitionZeroExtension->DeviceNumber);
729 
730  if (NT_SUCCESS(status)) {
731 
732  RtlInitUnicodeString(&unicodeSourceName, wideSourceName);
733 
734  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskCreateSymbolicLink: Linking %wZ to %wZ\n",
735  &unicodeSourceName,
736  &commonExtension->DeviceName));
737 
738  status = IoCreateSymbolicLink(&unicodeSourceName,
739  &commonExtension->DeviceName);
740 
741  if(NT_SUCCESS(status)){
742  diskData->LinkStatus.WellKnownNameCreated = TRUE;
743  }
744  }
745  }
746 
747  if (!diskData->LinkStatus.PhysicalDriveLinkCreated) {
748 
749  //
750  // Create a physical drive N link using the device number we saved
751  // away during AddDevice.
752  //
753 
754  status = RtlStringCchPrintfW(wideSourceName, sizeof(wideSourceName) / sizeof(wideSourceName[0]) - 1,
755  L"\\DosDevices\\PhysicalDrive%d",
756  commonExtension->PartitionZeroExtension->DeviceNumber);
757  if (NT_SUCCESS(status)) {
758 
759  RtlInitUnicodeString(&unicodeSourceName, wideSourceName);
760 
761  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskCreateSymbolicLink: Linking %wZ to %wZ\n",
762  &unicodeSourceName,
763  &(commonExtension->DeviceName)));
764 
765  status = IoCreateSymbolicLink(&unicodeSourceName,
766  &(commonExtension->DeviceName));
767 
768  if(NT_SUCCESS(status)) {
769  diskData->LinkStatus.PhysicalDriveLinkCreated = TRUE;
770  }
771  }
772  }
773 
774 
775  return;
776 }
777 
778 
779 VOID
782  )
783 
784 /*++
785 
786 Routine Description:
787 
788  This routine will delete the well known name (symlink) for the specified
789  device. It generates the link name using information stored in the
790  device extension
791 
792 Arguments:
793 
794  DeviceObject - the device object we are unlinking
795 
796 Return Value:
797 
798  status
799 
800 --*/
801 
802 {
803  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
804  PDISK_DATA diskData = commonExtension->DriverData;
805 
806  WCHAR wideLinkName[64] = { 0 };
807  UNICODE_STRING unicodeLinkName;
809 
810  PAGED_CODE();
811 
812  if(diskData->LinkStatus.WellKnownNameCreated) {
813 
814  status = RtlStringCchPrintfW(wideLinkName, sizeof(wideLinkName) / sizeof(wideLinkName[0]) - 1,
815  L"\\Device\\Harddisk%d\\Partition0",
816  commonExtension->PartitionZeroExtension->DeviceNumber);
817  if (NT_SUCCESS(status)) {
818  RtlInitUnicodeString(&unicodeLinkName, wideLinkName);
819  IoDeleteSymbolicLink(&unicodeLinkName);
820  }
821  diskData->LinkStatus.WellKnownNameCreated = FALSE;
822  }
823 
824  if(diskData->LinkStatus.PhysicalDriveLinkCreated) {
825 
826  status = RtlStringCchPrintfW(wideLinkName, sizeof(wideLinkName) / sizeof(wideLinkName[0]) - 1,
827  L"\\DosDevices\\PhysicalDrive%d",
828  commonExtension->PartitionZeroExtension->DeviceNumber);
829  if (NT_SUCCESS(status)) {
830  RtlInitUnicodeString(&unicodeLinkName, wideLinkName);
831  IoDeleteSymbolicLink(&unicodeLinkName);
832  }
833  diskData->LinkStatus.PhysicalDriveLinkCreated = FALSE;
834  }
835 
836 
837  return;
838 }
839 
840 
841 NTSTATUS
842 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
845  IN UCHAR Type
846  )
847 
848 /*++
849 
850 Routine Description:
851 
852  This routine will release any resources the device may have allocated for
853  this device object and return.
854 
855 Arguments:
856 
857  DeviceObject - the device object being removed
858 
859 Return Value:
860 
861  status
862 
863 --*/
864 
865 {
866  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
867  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
868 
869  PAGED_CODE();
870 
871  //
872  // Handle query and cancel
873  //
874 
877  return STATUS_SUCCESS;
878  }
879 
880  //
881  // Delete our object directory.
882  //
883 
884  if(fdoExtension->DeviceDirectory != NULL) {
885  ZwMakeTemporaryObject(fdoExtension->DeviceDirectory);
886  ZwClose(fdoExtension->DeviceDirectory);
887  fdoExtension->DeviceDirectory = NULL;
888  }
889 
890  if(Type == IRP_MN_REMOVE_DEVICE) {
891 
892  FREE_POOL(fdoExtension->SenseData);
893 
895 
896  }
897 
899 
900  if (Type == IRP_MN_REMOVE_DEVICE)
901  {
902  ClassDeleteSrbLookasideList(commonExtension);
903  }
904 
905  return STATUS_SUCCESS;
906 }
907 
908 
909 NTSTATUS
910 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
913  )
914 
915 /*++
916 
917 Routine Description:
918 
919  This routine will query the underlying device for any information necessary
920  to complete initialization of the device. This will include physical
921  disk geometry, mode sense information and such.
922 
923  This routine does not perform partition enumeration - that is left to the
924  re-enumeration routine
925 
926  If this routine fails it will return an error value. It does not clean up
927  any resources - that is left for the Stop/Remove routine.
928 
929 Arguments:
930 
931  Fdo - a pointer to the functional device object for this device
932 
933 Return Value:
934 
935  status
936 
937 --*/
938 
939 {
940  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
941  PCOMMON_DEVICE_EXTENSION commonExtension = &(fdoExtension->CommonExtension);
942  PDISK_DATA diskData = commonExtension->DriverData;
943  STORAGE_HOTPLUG_INFO hotplugInfo = { 0 };
944  DISK_CACHE_INFORMATION cacheInfo = { 0 };
945  ULONG isPowerProtected = 0;
947 
948  PAGED_CODE();
949 
950  //
951  // Get the hotplug information, so we can turn off write cache if needed
952  //
953  // NOTE: Capabilities info is not good enough to determine hotplugedness
954  // as we cannot determine device relations information and other
955  // dependencies. Get the hotplug info instead
956  //
957 
958  {
959  PIRP irp;
960  KEVENT event;
961  IO_STATUS_BLOCK statusBlock = { 0 };
962 
964 
966  Fdo,
967  NULL,
968  0L,
969  &hotplugInfo,
970  sizeof(STORAGE_HOTPLUG_INFO),
971  FALSE,
972  &event,
973  &statusBlock);
974 
975  if (irp != NULL) {
976 
977  // send to self -- classpnp handles this
979  if (status == STATUS_PENDING) {
981  Executive,
982  KernelMode,
983  FALSE,
984  NULL);
985 
986  status = statusBlock.Status;
987  }
989  }
990  }
991 
992  //
993  // Clear the DEV_WRITE_CACHE flag now and set
994  // it below only if we read that from the disk
995  //
996  CLEAR_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
997  ADJUST_FUA_FLAG(fdoExtension);
998 
1000 
1001  //
1002  // Look into the registry to see if the user
1003  // has chosen to override the default setting
1004  //
1005  ClassGetDeviceParameter(fdoExtension,
1008  (PULONG)&diskData->WriteCacheOverride);
1009 
1010  if (diskData->WriteCacheOverride == DiskWriteCacheDefault)
1011  {
1012  //
1013  // The user has not overridden the default settings
1014  //
1016  {
1017  //
1018  // This flag indicates that we have faulty firmware and this
1019  // may cause the filesystem to refuse to mount on this media
1020  //
1021  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to a firmware issue\n", Fdo));
1022 
1024  }
1025  else if (hotplugInfo.DeviceHotplug && !hotplugInfo.WriteCacheEnableOverride)
1026  {
1027  //
1028  // This flag indicates that the device is hotpluggable making it unsafe to enable caching
1029  //
1030  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to hotpluggable device\n", Fdo));
1031 
1033  }
1034  else if (hotplugInfo.MediaHotplug)
1035  {
1036  //
1037  // This flag indicates that the media in the device cannot be reliably locked
1038  //
1039  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to unlockable media\n", Fdo));
1040 
1042  }
1043  else
1044  {
1045  //
1046  // Even though the device does not seem to have any obvious problems
1047  // we leave it to the user to modify the previous write cache setting
1048  //
1049  }
1050  }
1051 
1052  //
1053  // Query the disk to see if write cache is enabled
1054  // and set the DEV_WRITE_CACHE flag appropriately
1055  //
1056 
1057  status = DiskGetCacheInformation(fdoExtension, &cacheInfo);
1058 
1059  if (NT_SUCCESS(status))
1060  {
1061  if (cacheInfo.WriteCacheEnabled == TRUE)
1062  {
1063  SET_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
1064  ADJUST_FUA_FLAG(fdoExtension);
1065 
1066  if (diskData->WriteCacheOverride == DiskWriteCacheDisable)
1067  {
1068  //
1069  // Write cache is currently enabled on this
1070  // device, but we would like to turn it off
1071  //
1072  cacheInfo.WriteCacheEnabled = FALSE;
1073 
1074  DiskSetCacheInformation(fdoExtension, &cacheInfo);
1075  }
1076  }
1077  else
1078  {
1079  if (diskData->WriteCacheOverride == DiskWriteCacheEnable)
1080  {
1081  //
1082  // Write cache is currently disabled on this
1083  // device, but we would like to turn it on
1084  //
1085  cacheInfo.WriteCacheEnabled = TRUE;
1086 
1087  DiskSetCacheInformation(fdoExtension, &cacheInfo);
1088  }
1089  }
1090  }
1091 
1092  //
1093  // Query the registry to see if this disk is power-protected or not
1094  //
1095 
1096  CLEAR_FLAG(fdoExtension->DeviceFlags, DEV_POWER_PROTECTED);
1097 
1098  ClassGetDeviceParameter(fdoExtension, DiskDeviceParameterSubkey, DiskDeviceCacheIsPowerProtected, &isPowerProtected);
1099 
1100  if (isPowerProtected == 1)
1101  {
1102  SET_FLAG(fdoExtension->DeviceFlags, DEV_POWER_PROTECTED);
1103  }
1104 
1105  ADJUST_FUA_FLAG(fdoExtension);
1106 
1107  return STATUS_SUCCESS;
1108 
1109 } // end DiskStartFdo()
1110 
#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
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:2786
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:2602
CLASSPNP_SCAN_FOR_SPECIAL_INFO DiskBadControllers[]
Definition: data.c:42
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:202
LIST_ENTRY CurrList
Definition: disk.h:108
NTSTATUS NTAPI DiskStopDevice(IN PDEVICE_OBJECT DeviceObject, IN UCHAR Type)
Definition: pnp.c:600
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:612
#define DEV_WRITE_CACHE
Definition: class2.h:21
_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:2742
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
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:676
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:780
DISK_USER_WRITE_CACHE_SETTING WriteCacheOverride
Definition: disk.h:385
KEVENT Event
Definition: disk.h:148
#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
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
#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
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:818
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:596
Type
Definition: Type.h:6
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
_Must_inspect_result_ _In_ WDFDEVICE Fdo
Definition: wdffdo.h:461
#define DISK_TAG_NAME
Definition: disk.h:64
NTSTATUS NTAPI DiskRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN UCHAR Type)
Definition: pnp.c:843
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:3019
#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
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
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:2192
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:2681
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSTATUS NTAPI DiskStartFdo(IN PDEVICE_OBJECT Fdo)
Definition: pnp.c:911
NTSTATUS NTAPI DiskSetCacheInformation(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PDISK_CACHE_INFORMATION CacheInfo)
Definition: disk.c:3167
NTSTRSAFEAPI RtlStringCchCopyA(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:110
struct _DISK_DATA::@1030 LinkStatus
#define STATUS_SUCCESS
Definition: shellext.h:65
#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
#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
FxIrp * irp
#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