3 * Copyright (C) 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: disk.c,v 1.28 2003/04/29 18:06:26 ekohl Exp $
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/storage/disk/disk.c
24 * PURPOSE: disk class driver
25 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
28 /* INCLUDES *****************************************************************/
30 #include <ddk/ntddk.h>
32 #include <ddk/class2.h>
33 #include <ddk/ntddscsi.h>
38 #define VERSION "0.0.1"
41 typedef struct _DISK_DATA
43 PDEVICE_EXTENSION NextPartition
;
47 ULONG PartitionNumber
;
48 ULONG PartitionOrdinal
;
50 BOOLEAN BootIndicator
;
51 BOOLEAN DriveNotReady
;
52 } DISK_DATA
, *PDISK_DATA
;
56 DiskClassFindDevices(PDRIVER_OBJECT DriverObject
,
57 PUNICODE_STRING RegistryPath
,
58 PCLASS_INIT_DATA InitializationData
,
59 PDEVICE_OBJECT PortDeviceObject
,
63 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData
);
66 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject
,
71 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
72 IN PUNICODE_STRING RegistryPath
, /* what's this used for? */
73 IN PDEVICE_OBJECT PortDeviceObject
,
76 IN PIO_SCSI_CAPABILITIES Capabilities
,
77 IN PSCSI_INQUIRY_DATA InquiryData
,
78 IN PCLASS_INIT_DATA InitializationData
);
81 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
85 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
89 ScsiDiskSearchForDisk(IN PDEVICE_EXTENSION DeviceExtension
,
91 OUT PULONG DetectedDiskNumber
);
94 DiskClassUpdatePartitionDeviceObjects (IN PDEVICE_OBJECT DeviceObject
,
98 ScsiDiskUpdateFixedDiskGeometry(IN PDEVICE_EXTENSION DeviceExtension
);
101 ScsiDiskCalcMbrCheckSum(IN PDEVICE_EXTENSION DeviceExtension
,
102 OUT PULONG Checksum
);
105 /* FUNCTIONS ****************************************************************/
107 /**********************************************************************
112 * This function initializes the driver, locates and claims
113 * hardware resources, and creates various NT objects needed
114 * to process I/O requests.
121 * System allocated Driver Object for this driver
124 * Name of registry driver service key
131 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
132 IN PUNICODE_STRING RegistryPath
)
134 CLASS_INIT_DATA InitData
;
136 DPRINT("Disk Class Driver %s\n",
138 DPRINT("RegistryPath '%wZ'\n",
141 RtlZeroMemory(&InitData
,
142 sizeof(CLASS_INIT_DATA
));
144 InitData
.InitializationDataSize
= sizeof(CLASS_INIT_DATA
);
145 InitData
.DeviceExtensionSize
= sizeof(DEVICE_EXTENSION
) + sizeof(DISK_DATA
);
146 InitData
.DeviceType
= FILE_DEVICE_DISK
;
147 InitData
.DeviceCharacteristics
= 0;
149 InitData
.ClassError
= NULL
; // DiskClassProcessError;
150 InitData
.ClassReadWriteVerification
= DiskClassCheckReadWrite
;
151 InitData
.ClassFindDeviceCallBack
= DiskClassCheckDevice
;
152 InitData
.ClassFindDevices
= DiskClassFindDevices
;
153 InitData
.ClassDeviceControl
= DiskClassDeviceControl
;
154 InitData
.ClassShutdownFlush
= DiskClassShutdownFlush
;
155 InitData
.ClassCreateClose
= NULL
;
156 InitData
.ClassStartIo
= NULL
;
158 ScsiClassInitialize(DriverObject
,
162 DPRINT1("*** System stopped ***\n");
165 return(ScsiClassInitialize(DriverObject
,
171 /**********************************************************************
173 * DiskClassFindDevices
176 * This function searches for device that are attached to the
184 * System allocated Driver Object for this driver
187 * Name of registry driver service key
190 * Pointer to the main initialization data
193 * Pointer to the port Device Object
199 * TRUE: At least one disk drive was found
200 * FALSE: No disk drive found
204 DiskClassFindDevices(PDRIVER_OBJECT DriverObject
,
205 PUNICODE_STRING RegistryPath
,
206 PCLASS_INIT_DATA InitializationData
,
207 PDEVICE_OBJECT PortDeviceObject
,
210 PCONFIGURATION_INFORMATION ConfigInfo
;
211 PIO_SCSI_CAPABILITIES PortCapabilities
;
212 PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
;
213 PSCSI_INQUIRY_DATA UnitInfo
;
214 PINQUIRYDATA InquiryData
;
221 DPRINT("DiskClassFindDevices() called.\n");
223 /* Get port capabilities */
224 Status
= ScsiClassGetCapabilities(PortDeviceObject
,
226 if (!NT_SUCCESS(Status
))
228 DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status
);
232 DPRINT("PortCapabilities: %p\n", PortCapabilities
);
233 DPRINT("MaximumTransferLength: %lu\n", PortCapabilities
->MaximumTransferLength
);
234 DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities
->MaximumPhysicalPages
);
236 /* Get inquiry data */
237 Status
= ScsiClassGetInquiryData(PortDeviceObject
,
238 (PSCSI_ADAPTER_BUS_INFO
*)&Buffer
);
239 if (!NT_SUCCESS(Status
))
241 DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status
);
245 /* Check whether there are unclaimed devices */
246 AdapterBusInfo
= (PSCSI_ADAPTER_BUS_INFO
)Buffer
;
247 DeviceCount
= ScsiClassFindUnclaimedDevices(InitializationData
,
249 if (DeviceCount
== 0)
251 DPRINT("No unclaimed devices!\n");
255 DPRINT("Found %lu unclaimed devices!\n", DeviceCount
);
257 ConfigInfo
= IoGetConfigurationInformation();
259 /* Search each bus of this adapter */
260 for (Bus
= 0; Bus
< (ULONG
)AdapterBusInfo
->NumberOfBuses
; Bus
++)
262 DPRINT("Searching bus %lu\n", Bus
);
264 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
);
266 while (AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
)
268 InquiryData
= (PINQUIRYDATA
)UnitInfo
->InquiryData
;
270 if (((InquiryData
->DeviceType
== DIRECT_ACCESS_DEVICE
) ||
271 (InquiryData
->DeviceType
== OPTICAL_DEVICE
)) &&
272 (InquiryData
->DeviceTypeQualifier
== 0) &&
273 (UnitInfo
->DeviceClaimed
== FALSE
))
275 DPRINT("Vendor: '%.24s'\n",
276 InquiryData
->VendorId
);
278 /* Create device objects for disk */
279 Status
= DiskClassCreateDeviceObject(DriverObject
,
283 ConfigInfo
->DiskCount
,
287 if (NT_SUCCESS(Status
))
289 ConfigInfo
->DiskCount
++;
294 if (UnitInfo
->NextInquiryDataOffset
== 0)
297 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ UnitInfo
->NextInquiryDataOffset
);
303 DPRINT("DiskClassFindDevices() done\n");
309 /**********************************************************************
311 * DiskClassCheckDevice
314 * This function checks the InquiryData for the correct device
315 * type and qualifier.
322 * Pointer to the inquiry data for the device in question.
325 * TRUE: A disk device was found.
330 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData
)
332 return((InquiryData
->DeviceType
== DIRECT_ACCESS_DEVICE
||
333 InquiryData
->DeviceType
== OPTICAL_DEVICE
) &&
334 InquiryData
->DeviceTypeQualifier
== 0);
338 /**********************************************************************
340 * DiskClassCheckReadWrite
343 * This function checks the given IRP for correct data.
350 * Pointer to the device.
356 * STATUS_SUCCESS: The IRP matches the requirements of the given device.
361 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject
,
364 PDEVICE_EXTENSION DeviceExtension
;
367 DPRINT("DiskClassCheckReadWrite() called\n");
369 DeviceExtension
= DeviceObject
->DeviceExtension
;
370 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
372 if (DiskData
->DriveNotReady
== TRUE
)
374 Irp
->IoStatus
.Status
= STATUS_DEVICE_NOT_READY
;
375 IoSetHardErrorOrVerifyDevice(Irp
,
377 return(STATUS_INVALID_PARAMETER
);
380 return(STATUS_SUCCESS
);
384 /**********************************************************************
386 * DiskClassCreateDeviceObject
389 * Create the raw device and any partition devices on this drive
396 * The system created driver object
406 * STATUS_SUCCESS: Device objects for disk and partitions were created.
411 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
412 IN PUNICODE_STRING RegistryPath
, /* what's this used for? */
413 IN PDEVICE_OBJECT PortDeviceObject
,
416 IN PIO_SCSI_CAPABILITIES Capabilities
,
417 IN PSCSI_INQUIRY_DATA InquiryData
,
418 IN PCLASS_INIT_DATA InitializationData
)
420 OBJECT_ATTRIBUTES ObjectAttributes
;
421 UNICODE_STRING UnicodeDeviceDirName
;
422 WCHAR NameBuffer
[80];
423 CHAR NameBuffer2
[80];
424 PDEVICE_OBJECT DiskDeviceObject
;
425 PDEVICE_OBJECT PartitionDeviceObject
;
426 PDEVICE_EXTENSION DiskDeviceExtension
; /* defined in class2.h */
427 PDEVICE_EXTENSION PartitionDeviceExtension
; /* defined in class2.h */
428 PDRIVE_LAYOUT_INFORMATION PartitionList
= NULL
;
430 PPARTITION_INFORMATION PartitionEntry
;
432 ULONG PartitionNumber
;
436 DPRINT("DiskClassCreateDeviceObject() called\n");
438 /* Create the harddisk device directory */
440 L
"\\Device\\Harddisk%lu",
442 RtlInitUnicodeString(&UnicodeDeviceDirName
,
444 InitializeObjectAttributes(&ObjectAttributes
,
445 &UnicodeDeviceDirName
,
449 Status
= ZwCreateDirectoryObject(&Handle
,
452 if (!NT_SUCCESS(Status
))
454 DbgPrint("Could not create device dir object\n");
458 /* Claim the disk device */
459 Status
= ScsiClassClaimDevice(PortDeviceObject
,
463 if (!NT_SUCCESS(Status
))
465 DbgPrint("Could not claim disk device\n");
467 ZwMakeTemporaryObject(Handle
);
473 /* Create disk device (Partition 0) */
475 "\\Device\\Harddisk%lu\\Partition0",
478 Status
= ScsiClassCreateDeviceObject(DriverObject
,
483 if (!NT_SUCCESS(Status
))
485 DPRINT("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status
);
487 /* Release (unclaim) the disk */
488 ScsiClassClaimDevice(PortDeviceObject
,
493 /* Delete the harddisk device directory */
494 ZwMakeTemporaryObject(Handle
);
500 DiskDeviceObject
->Flags
|= DO_DIRECT_IO
;
501 if (((PINQUIRYDATA
)InquiryData
->InquiryData
)->RemovableMedia
)
503 DiskDeviceObject
->Characteristics
|= FILE_REMOVABLE_MEDIA
;
505 DiskDeviceObject
->StackSize
= (CCHAR
)PortDeviceObject
->StackSize
+ 1;
507 if (PortDeviceObject
->AlignmentRequirement
> DiskDeviceObject
->AlignmentRequirement
)
509 DiskDeviceObject
->AlignmentRequirement
= PortDeviceObject
->AlignmentRequirement
;
512 DiskDeviceExtension
= DiskDeviceObject
->DeviceExtension
;
513 DiskDeviceExtension
->LockCount
= 0;
514 DiskDeviceExtension
->DeviceNumber
= DiskNumber
;
515 DiskDeviceExtension
->DeviceObject
= DiskDeviceObject
;
516 DiskDeviceExtension
->PortDeviceObject
= PortDeviceObject
;
517 DiskDeviceExtension
->PhysicalDevice
= DiskDeviceObject
;
518 DiskDeviceExtension
->PortCapabilities
= Capabilities
;
519 DiskDeviceExtension
->StartingOffset
.QuadPart
= 0;
520 DiskDeviceExtension
->PortNumber
= (UCHAR
)PortNumber
;
521 DiskDeviceExtension
->PathId
= InquiryData
->PathId
;
522 DiskDeviceExtension
->TargetId
= InquiryData
->TargetId
;
523 DiskDeviceExtension
->Lun
= InquiryData
->Lun
;
525 /* Initialize the lookaside list for SRBs */
526 ScsiClassInitializeSrbLookasideList(DiskDeviceExtension
,
529 /* zero-out disk data */
530 DiskData
= (PDISK_DATA
)(DiskDeviceExtension
+ 1);
531 RtlZeroMemory(DiskData
,
534 /* Get disk geometry */
535 DiskDeviceExtension
->DiskGeometry
= ExAllocatePool(NonPagedPool
,
536 sizeof(DISK_GEOMETRY
));
537 if (DiskDeviceExtension
->DiskGeometry
== NULL
)
539 DPRINT("Failed to allocate geometry buffer!\n");
541 ExDeleteNPagedLookasideList(&DiskDeviceExtension
->SrbLookasideListHead
);
543 IoDeleteDevice(DiskDeviceObject
);
545 /* Release (unclaim) the disk */
546 ScsiClassClaimDevice(PortDeviceObject
,
551 /* Delete the harddisk device directory */
552 ZwMakeTemporaryObject(Handle
);
555 return(STATUS_INSUFFICIENT_RESOURCES
);
558 /* Read the drive's capacity */
559 Status
= ScsiClassReadDriveCapacity(DiskDeviceObject
);
560 if (!NT_SUCCESS(Status
) &&
561 (DiskDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
) == 0)
563 DPRINT1("Failed to retrieve drive capacity!\n");
564 return(STATUS_SUCCESS
);
568 /* Clear the verify flag for removable media drives. */
569 DiskDeviceObject
->Flags
&= ~DO_VERIFY_VOLUME
;
572 DPRINT("SectorSize: %lu\n", DiskDeviceExtension
->DiskGeometry
->BytesPerSector
);
574 /* Check disk for presence of a disk manager */
575 HalExamineMBR(DiskDeviceObject
,
576 DiskDeviceExtension
->DiskGeometry
->BytesPerSector
,
579 if (MbrBuffer
!= NULL
)
581 /* Start disk at sector 63 if the Ontrack Disk Manager was found */
582 DPRINT("Found 'Ontrack Disk Manager'!\n");
584 DiskDeviceExtension
->DMSkew
= 63;
585 DiskDeviceExtension
->DMByteSkew
=
586 63 * DiskDeviceExtension
->DiskGeometry
->BytesPerSector
;
587 DiskDeviceExtension
->DMActive
= TRUE
;
589 ExFreePool(MbrBuffer
);
593 if ((DiskDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
) &&
594 (DiskDeviceExtension
->DiskGeometry
->MediaType
== RemovableMedia
))
596 /* Allocate a partition list for a single entry. */
597 PartitionList
= ExAllocatePool(NonPagedPool
,
598 sizeof(DRIVE_LAYOUT_INFORMATION
));
599 if (PartitionList
!= NULL
)
601 RtlZeroMemory(PartitionList
,
602 sizeof(DRIVE_LAYOUT_INFORMATION
));
603 PartitionList
->PartitionCount
= 1;
605 DiskData
->DriveNotReady
= TRUE
;
606 Status
= STATUS_SUCCESS
;
611 /* Read partition table */
612 Status
= IoReadPartitionTable(DiskDeviceObject
,
613 DiskDeviceExtension
->DiskGeometry
->BytesPerSector
,
617 DPRINT("IoReadPartitionTable(): Status: %lx\n", Status
);
619 if ((!NT_SUCCESS(Status
) || PartitionList
->PartitionCount
== 0) &&
620 DiskDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
622 if (!NT_SUCCESS(Status
))
624 /* Drive is not ready. */
625 DPRINT("Drive not ready\n");
626 DiskData
->DriveNotReady
= TRUE
;
630 ExFreePool(PartitionList
);
633 /* Allocate a partition list for a single entry. */
634 PartitionList
= ExAllocatePool(NonPagedPool
,
635 sizeof(DRIVE_LAYOUT_INFORMATION
));
636 if (PartitionList
!= NULL
)
638 RtlZeroMemory(PartitionList
,
639 sizeof(DRIVE_LAYOUT_INFORMATION
));
640 PartitionList
->PartitionCount
= 1;
642 Status
= STATUS_SUCCESS
;
647 if (NT_SUCCESS(Status
))
649 DPRINT("Read partition table!\n");
650 DPRINT(" Number of partitions: %u\n", PartitionList
->PartitionCount
);
652 /* Set disk signature */
653 DiskData
->Signature
= PartitionList
->Signature
;
655 /* Calculate MBR checksum if disk got no signature */
656 if (DiskData
->Signature
== 0)
658 if (!ScsiDiskCalcMbrCheckSum(DiskDeviceExtension
,
659 &DiskData
->MbrCheckSum
))
661 DPRINT1("MBR checksum calculation failed for disk %lu\n",
662 DiskDeviceExtension
->DeviceNumber
);
666 DPRINT1("MBR checksum for disk %lu is %lx\n",
667 DiskDeviceExtension
->DeviceNumber
,
668 DiskData
->MbrCheckSum
);
673 DPRINT1("Signature on disk %lu is %lx\n",
674 DiskDeviceExtension
->DeviceNumber
,
675 DiskData
->Signature
);
678 /* Update disk geometry if disk is visible to the BIOS */
679 ScsiDiskUpdateFixedDiskGeometry(DiskDeviceExtension
);
681 for (PartitionNumber
= 0; PartitionNumber
< PartitionList
->PartitionCount
; PartitionNumber
++)
683 PartitionEntry
= &PartitionList
->PartitionEntry
[PartitionNumber
];
685 DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
687 PartitionEntry
->PartitionNumber
,
688 PartitionEntry
->BootIndicator
,
689 PartitionEntry
->PartitionType
,
690 PartitionEntry
->StartingOffset
.QuadPart
/ 512 /*DrvParms.BytesPerSector*/,
691 PartitionEntry
->PartitionLength
.QuadPart
/ 512 /* DrvParms.BytesPerSector*/);
693 /* Create partition device object */
695 "\\Device\\Harddisk%lu\\Partition%lu",
697 PartitionNumber
+ 1);
699 Status
= ScsiClassCreateDeviceObject(DriverObject
,
702 &PartitionDeviceObject
,
704 DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status
);
705 if (NT_SUCCESS(Status
))
707 PartitionDeviceObject
->Flags
= DiskDeviceObject
->Flags
;
708 PartitionDeviceObject
->Characteristics
= DiskDeviceObject
->Characteristics
;
709 PartitionDeviceObject
->StackSize
= DiskDeviceObject
->StackSize
;
710 PartitionDeviceObject
->AlignmentRequirement
= DiskDeviceObject
->AlignmentRequirement
;
712 PartitionDeviceExtension
= PartitionDeviceObject
->DeviceExtension
;
713 PartitionDeviceExtension
->LockCount
= 0;
714 PartitionDeviceExtension
->DeviceNumber
= DiskNumber
;
715 PartitionDeviceExtension
->DeviceObject
= PartitionDeviceObject
;
716 PartitionDeviceExtension
->PortDeviceObject
= PortDeviceObject
;
717 PartitionDeviceExtension
->DiskGeometry
= DiskDeviceExtension
->DiskGeometry
;
718 PartitionDeviceExtension
->PhysicalDevice
= DiskDeviceExtension
->PhysicalDevice
;
719 PartitionDeviceExtension
->PortCapabilities
= Capabilities
;
720 PartitionDeviceExtension
->StartingOffset
.QuadPart
=
721 PartitionEntry
->StartingOffset
.QuadPart
;
722 PartitionDeviceExtension
->PartitionLength
.QuadPart
=
723 PartitionEntry
->PartitionLength
.QuadPart
;
724 PartitionDeviceExtension
->DMSkew
= DiskDeviceExtension
->DMSkew
;
725 PartitionDeviceExtension
->DMByteSkew
= DiskDeviceExtension
->DMByteSkew
;
726 PartitionDeviceExtension
->DMActive
= DiskDeviceExtension
->DMActive
;
727 PartitionDeviceExtension
->PortNumber
= (UCHAR
)PortNumber
;
728 PartitionDeviceExtension
->PathId
= InquiryData
->PathId
;
729 PartitionDeviceExtension
->TargetId
= InquiryData
->TargetId
;
730 PartitionDeviceExtension
->Lun
= InquiryData
->Lun
;
731 PartitionDeviceExtension
->SectorShift
= DiskDeviceExtension
->SectorShift
;
733 /* Initialize lookaside list for SRBs */
734 ScsiClassInitializeSrbLookasideList(PartitionDeviceExtension
,
737 /* Link current partition device extension to previous disk data */
738 DiskData
->NextPartition
= PartitionDeviceExtension
;
740 /* Initialize current disk data */
741 DiskData
= (PDISK_DATA
)(PartitionDeviceExtension
+ 1);
742 DiskData
->NextPartition
= NULL
;
743 DiskData
->PartitionType
= PartitionEntry
->PartitionType
;
744 DiskData
->PartitionNumber
= PartitionNumber
+ 1;
745 DiskData
->PartitionOrdinal
= PartitionNumber
+ 1;
746 DiskData
->HiddenSectors
= PartitionEntry
->HiddenSectors
;
747 DiskData
->BootIndicator
= PartitionEntry
->BootIndicator
;
748 DiskData
->DriveNotReady
= FALSE
;
752 DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status
);
759 if (PartitionList
!= NULL
)
760 ExFreePool(PartitionList
);
762 DPRINT("DiskClassCreateDeviceObjects() done\n");
764 return(STATUS_SUCCESS
);
768 /**********************************************************************
770 * DiskClassDeviceControl
773 * Answer requests for device control calls
779 * Standard dispatch arguments
786 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
789 PDEVICE_EXTENSION DeviceExtension
;
790 PIO_STACK_LOCATION IrpStack
;
791 ULONG ControlCode
, InputLength
, OutputLength
;
796 DPRINT("DiskClassDeviceControl() called!\n");
798 Status
= STATUS_INVALID_DEVICE_REQUEST
;
800 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
801 ControlCode
= IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
802 InputLength
= IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
;
803 OutputLength
= IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
804 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
805 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
809 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
810 DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
811 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(DISK_GEOMETRY
))
813 Status
= STATUS_INVALID_PARAMETER
;
817 PDISK_GEOMETRY Geometry
;
819 if (DeviceExtension
->DiskGeometry
== NULL
)
821 DPRINT("No disk geometry available!\n");
822 DeviceExtension
->DiskGeometry
= ExAllocatePool(NonPagedPool
,
823 sizeof(DISK_GEOMETRY
));
825 Status
= ScsiClassReadDriveCapacity(DeviceObject
);
826 DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status
);
827 if (NT_SUCCESS(Status
))
829 Geometry
= (PDISK_GEOMETRY
)Irp
->AssociatedIrp
.SystemBuffer
;
830 RtlMoveMemory(Geometry
,
831 DeviceExtension
->DiskGeometry
,
832 sizeof(DISK_GEOMETRY
));
834 Status
= STATUS_SUCCESS
;
835 Information
= sizeof(DISK_GEOMETRY
);
840 case IOCTL_DISK_GET_PARTITION_INFO
:
841 DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n");
842 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
843 sizeof(PARTITION_INFORMATION
))
845 Status
= STATUS_INFO_LENGTH_MISMATCH
;
847 else if (DiskData
->PartitionNumber
== 0)
849 Status
= STATUS_INVALID_DEVICE_REQUEST
;
853 PPARTITION_INFORMATION PartitionInfo
;
855 PartitionInfo
= (PPARTITION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
857 PartitionInfo
->PartitionType
= DiskData
->PartitionType
;
858 PartitionInfo
->StartingOffset
= DeviceExtension
->StartingOffset
;
859 PartitionInfo
->PartitionLength
= DeviceExtension
->PartitionLength
;
860 PartitionInfo
->HiddenSectors
= DiskData
->HiddenSectors
;
861 PartitionInfo
->PartitionNumber
= DiskData
->PartitionNumber
;
862 PartitionInfo
->BootIndicator
= DiskData
->BootIndicator
;
863 PartitionInfo
->RewritePartition
= FALSE
;
864 PartitionInfo
->RecognizedPartition
=
865 IsRecognizedPartition(DiskData
->PartitionType
);
867 Status
= STATUS_SUCCESS
;
868 Information
= sizeof(PARTITION_INFORMATION
);
872 case IOCTL_DISK_SET_PARTITION_INFO
:
873 if (IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
874 sizeof(SET_PARTITION_INFORMATION
))
876 Status
= STATUS_INFO_LENGTH_MISMATCH
;
878 else if (DiskData
->PartitionNumber
== 0)
880 Status
= STATUS_INVALID_DEVICE_REQUEST
;
884 PSET_PARTITION_INFORMATION PartitionInfo
;
886 PartitionInfo
= (PSET_PARTITION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
888 Status
= IoSetPartitionInformation(DeviceExtension
->PhysicalDevice
,
889 DeviceExtension
->DiskGeometry
->BytesPerSector
,
890 DiskData
->PartitionOrdinal
,
891 PartitionInfo
->PartitionType
);
892 if (NT_SUCCESS(Status
))
894 DiskData
->PartitionType
= PartitionInfo
->PartitionType
;
899 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
900 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
901 sizeof(DRIVE_LAYOUT_INFORMATION
))
903 Status
= STATUS_BUFFER_TOO_SMALL
;
907 PDRIVE_LAYOUT_INFORMATION PartitionList
;
909 Status
= IoReadPartitionTable(DeviceExtension
->PhysicalDevice
,
910 DeviceExtension
->DiskGeometry
->BytesPerSector
,
913 if (NT_SUCCESS(Status
))
917 BufferSize
= FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION
,
919 BufferSize
+= PartitionList
->PartitionCount
* sizeof(PARTITION_INFORMATION
);
921 if (BufferSize
> IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
923 Status
= STATUS_BUFFER_TOO_SMALL
;
927 RtlMoveMemory(Irp
->AssociatedIrp
.SystemBuffer
,
930 Status
= STATUS_SUCCESS
;
931 Information
= BufferSize
;
933 ExFreePool(PartitionList
);
938 case IOCTL_DISK_SET_DRIVE_LAYOUT
:
939 if (IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
940 sizeof(DRIVE_LAYOUT_INFORMATION
))
942 Status
= STATUS_INFO_LENGTH_MISMATCH
;
944 else if (DeviceExtension
->PhysicalDevice
->DeviceExtension
!= DeviceExtension
)
946 Status
= STATUS_INVALID_PARAMETER
;
950 PDRIVE_LAYOUT_INFORMATION PartitionList
;
953 PartitionList
= Irp
->AssociatedIrp
.SystemBuffer
;
954 TableSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
955 ((PartitionList
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
957 if (IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
< TableSize
)
959 Status
= STATUS_BUFFER_TOO_SMALL
;
963 /* Update partition device objects */
964 DiskClassUpdatePartitionDeviceObjects (DeviceObject
,
967 /* Write partition table */
968 Status
= IoWritePartitionTable(DeviceExtension
->PhysicalDevice
,
969 DeviceExtension
->DiskGeometry
->BytesPerSector
,
970 DeviceExtension
->DiskGeometry
->SectorsPerTrack
,
971 DeviceExtension
->DiskGeometry
->TracksPerCylinder
,
973 if (NT_SUCCESS(Status
))
975 Information
= TableSize
;
981 case IOCTL_DISK_VERIFY
:
982 case IOCTL_DISK_FORMAT_TRACKS
:
983 case IOCTL_DISK_PERFORMANCE
:
984 case IOCTL_DISK_IS_WRITABLE
:
985 case IOCTL_DISK_LOGGING
:
986 case IOCTL_DISK_FORMAT_TRACKS_EX
:
987 case IOCTL_DISK_HISTOGRAM_STRUCTURE
:
988 case IOCTL_DISK_HISTOGRAM_DATA
:
989 case IOCTL_DISK_HISTOGRAM_RESET
:
990 case IOCTL_DISK_REQUEST_STRUCTURE
:
991 case IOCTL_DISK_REQUEST_DATA
:
992 /* If we get here, something went wrong. Inform the requestor */
993 DPRINT1("Unhandled control code: %lx\n", ControlCode
);
994 Status
= STATUS_INVALID_DEVICE_REQUEST
;
999 /* Call the common device control function */
1000 return(ScsiClassDeviceControl(DeviceObject
, Irp
));
1003 /* Verify the device if the user caused the error */
1004 if (!NT_SUCCESS(Status
) && IoIsErrorUserInduced(Status
))
1006 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
1009 Irp
->IoStatus
.Status
= Status
;
1010 Irp
->IoStatus
.Information
= Information
;
1011 IoCompleteRequest(Irp
,
1018 /**********************************************************************
1020 * DiskClassShutdownFlush
1023 * Answer requests for shutdown and flush calls.
1030 * Pointer to the device.
1033 * Pointer to the IRP
1040 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
1043 PDEVICE_EXTENSION DeviceExtension
;
1044 PIO_STACK_LOCATION IrpStack
;
1045 PSCSI_REQUEST_BLOCK Srb
;
1047 DPRINT("DiskClassShutdownFlush() called!\n");
1049 DeviceExtension
= DeviceObject
->DeviceExtension
;
1052 Srb
= ExAllocatePool(NonPagedPool
,
1053 sizeof(SCSI_REQUEST_BLOCK
));
1056 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1057 Irp
->IoStatus
.Information
= 0;
1058 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1060 return(STATUS_INSUFFICIENT_RESOURCES
);
1063 /* Initialize SRB */
1064 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
1065 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
1067 /* Set device IDs */
1068 Srb
->PathId
= DeviceExtension
->PathId
;
1069 Srb
->TargetId
= DeviceExtension
->TargetId
;
1070 Srb
->Lun
= DeviceExtension
->Lun
;
1072 /* Flush write cache */
1073 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1074 Srb
->SrbFlags
= SRB_FLAGS_NO_DATA_TRANSFER
;
1075 Srb
->CdbLength
= 10;
1076 Srb
->Cdb
[0] = SCSIOP_SYNCHRONIZE_CACHE
;
1077 ScsiClassSendSrbSynchronous(DeviceObject
,
1083 /* Get current stack location */
1084 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1086 /* FIXME: Unlock removable media upon shutdown */
1090 IrpStack
->Parameters
.Others
.Argument4
= (PVOID
)0;
1092 /* Send shutdown or flush request to the port driver */
1094 if (IrpStack
->MajorFunction
== IRP_MJ_SHUTDOWN
)
1095 Srb
->Function
= SRB_FUNCTION_SHUTDOWN
;
1097 Srb
->Function
= SRB_FUNCTION_FLUSH
;
1099 /* Init completion routine */
1100 IoSetCompletionRoutine(Irp
,
1101 ScsiClassIoComplete
,
1107 /* Prepare next stack location for a call to the port driver */
1108 IrpStack
= IoGetNextIrpStackLocation(Irp
);
1109 IrpStack
->MajorFunction
= IRP_MJ_SCSI
;
1110 IrpStack
->Parameters
.Scsi
.Srb
= Srb
;
1111 Srb
->OriginalRequest
= Irp
;
1113 /* Call port driver */
1114 return(IoCallDriver(DeviceExtension
->PortDeviceObject
, Irp
));
1118 /**********************************************************************
1120 * DiskClassUpdatePartitionDeviceObjects
1123 * Deletes, modifies or creates partition device objects.
1130 * Pointer to the device.
1133 * Pointer to the IRP
1140 DiskClassUpdatePartitionDeviceObjects(IN PDEVICE_OBJECT DiskDeviceObject
,
1143 PDRIVE_LAYOUT_INFORMATION PartitionList
;
1144 PPARTITION_INFORMATION PartitionEntry
;
1145 PDEVICE_EXTENSION DeviceExtension
;
1146 PDEVICE_EXTENSION DiskDeviceExtension
;
1147 PDISK_DATA DiskData
;
1148 ULONG PartitionCount
;
1149 ULONG PartitionOrdinal
;
1150 ULONG PartitionNumber
;
1151 ULONG LastPartitionNumber
;
1154 WCHAR NameBuffer
[MAX_PATH
];
1155 UNICODE_STRING DeviceName
;
1156 PDEVICE_OBJECT DeviceObject
;
1159 DPRINT("ScsiDiskUpdatePartitionDeviceObjects() called\n");
1161 /* Get partition list */
1162 PartitionList
= Irp
->AssociatedIrp
.SystemBuffer
;
1164 /* Round partition count up by 4 */
1165 PartitionCount
= ((PartitionList
->PartitionCount
+ 3) / 4) * 4;
1167 /* Remove the partition numbers from the partition list */
1168 for (i
= 0; i
< PartitionCount
; i
++)
1170 PartitionList
->PartitionEntry
[i
].PartitionNumber
= 0;
1173 DiskDeviceExtension
= DiskDeviceObject
->DeviceExtension
;
1175 /* Traverse on-disk partition list */
1176 LastPartitionNumber
= 0;
1177 DeviceExtension
= DiskDeviceExtension
;
1178 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
1181 DeviceExtension
= DiskData
->NextPartition
;
1182 if (DeviceExtension
== NULL
)
1186 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
1188 /* Update last partition number */
1189 if (DiskData
->PartitionNumber
> LastPartitionNumber
)
1190 LastPartitionNumber
= DiskData
->PartitionNumber
;
1192 /* Ignore unused on-disk partitions */
1193 if (DeviceExtension
->PartitionLength
.QuadPart
== 0ULL)
1197 PartitionOrdinal
= 0;
1198 for (i
= 0; i
< PartitionCount
; i
++)
1200 /* Get current partition entry */
1201 PartitionEntry
= &PartitionList
->PartitionEntry
[i
];
1203 /* Ignore empty (aka unused) or extended partitions */
1204 if (PartitionEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
||
1205 IsContainerPartition (PartitionEntry
->PartitionType
))
1210 /* Check for matching partition start offset and length */
1211 if ((PartitionEntry
->StartingOffset
.QuadPart
!=
1212 DeviceExtension
->StartingOffset
.QuadPart
) ||
1213 (PartitionEntry
->PartitionLength
.QuadPart
!=
1214 DeviceExtension
->PartitionLength
.QuadPart
))
1217 DPRINT1("Found matching partition entry for partition %lu\n",
1218 DiskData
->PartitionNumber
);
1220 /* Found matching partition */
1223 /* Update partition number in partition list */
1224 PartitionEntry
->PartitionNumber
= DiskData
->PartitionNumber
;
1230 /* Get disk data for current partition */
1231 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
1233 /* Update partition type if partiton will be rewritten */
1234 if (PartitionEntry
->RewritePartition
== TRUE
)
1235 DiskData
->PartitionType
= PartitionEntry
->PartitionType
;
1237 /* Assign new partiton ordinal */
1238 DiskData
->PartitionOrdinal
= PartitionOrdinal
;
1240 DPRINT("Partition ordinal %lu was assigned to partition %lu\n",
1241 DiskData
->PartitionOrdinal
,
1242 DiskData
->PartitionNumber
);
1246 /* Delete this partition */
1247 DeviceExtension
->PartitionLength
.QuadPart
= 0ULL;
1249 DPRINT("Deleting partition %lu\n",
1250 DiskData
->PartitionNumber
);
1254 /* Traverse partiton list and create new partiton devices */
1255 PartitionOrdinal
= 0;
1256 for (i
= 0; i
< PartitionCount
; i
++)
1258 /* Get current partition entry */
1259 PartitionEntry
= &PartitionList
->PartitionEntry
[i
];
1261 /* Ignore empty (aka unused) or extended partitions */
1262 if (PartitionEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
||
1263 IsContainerPartition (PartitionEntry
->PartitionType
))
1268 /* Ignore unchanged partition entries */
1269 if (PartitionEntry
->RewritePartition
== FALSE
)
1272 /* Check for an unused device object */
1273 PartitionNumber
= 0;
1274 DeviceExtension
= DiskDeviceExtension
;
1275 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
1278 DeviceExtension
= DiskData
->NextPartition
;
1279 if (DeviceExtension
== NULL
)
1282 /* Get partition disk data */
1283 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
1285 /* Found a free (unused) partition (device object) */
1286 if (DeviceExtension
->PartitionLength
.QuadPart
== 0ULL)
1288 PartitionNumber
= DiskData
->PartitionNumber
;
1293 if (PartitionNumber
== 0)
1295 /* Create a new partition device object */
1296 DPRINT("Create new partition device object\n");
1298 /* Get new partiton number */
1299 LastPartitionNumber
++;
1300 PartitionNumber
= LastPartitionNumber
;
1302 /* Create partition device object */
1303 swprintf(NameBuffer
,
1304 L
"\\Device\\Harddisk%lu\\Partition%lu",
1305 DiskDeviceExtension
->DeviceNumber
,
1307 RtlInitUnicodeString(&DeviceName
,
1310 Status
= IoCreateDevice(DiskDeviceObject
->DriverObject
,
1311 sizeof(DEVICE_EXTENSION
) + sizeof(DISK_DATA
),
1317 if (!NT_SUCCESS(Status
))
1319 DPRINT1("IoCreateDevice() failed (Status %lx)\n", Status
);
1323 DeviceObject
->Flags
|= DO_DIRECT_IO
;
1324 DeviceObject
->StackSize
= DiskDeviceObject
->StackSize
;
1325 DeviceObject
->Characteristics
= DiskDeviceObject
->Characteristics
;
1326 DeviceObject
->AlignmentRequirement
= DiskDeviceObject
->AlignmentRequirement
;
1328 /* Initialize device extension */
1329 DeviceExtension
= DeviceObject
->DeviceExtension
;
1330 RtlCopyMemory(DeviceExtension
,
1331 DiskDeviceObject
->DeviceExtension
,
1332 sizeof(DEVICE_EXTENSION
));
1333 DeviceExtension
->DeviceObject
= DeviceObject
;
1335 /* Initialize lookaside list for SRBs */
1336 ScsiClassInitializeSrbLookasideList(DeviceExtension
,
1339 /* Link current partition device extension to previous disk data */
1340 DiskData
->NextPartition
= DeviceExtension
;
1341 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
1342 DiskData
->NextPartition
= NULL
;
1346 /* Reuse an existing partition device object */
1347 DPRINT("Reuse an exisiting partition device object\n");
1348 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
1351 /* Update partition data and device extension */
1352 DiskData
->PartitionNumber
= PartitionNumber
;
1353 DiskData
->PartitionOrdinal
= PartitionOrdinal
;
1354 DiskData
->PartitionType
= PartitionEntry
->PartitionType
;
1355 DiskData
->BootIndicator
= PartitionEntry
->BootIndicator
;
1356 DiskData
->HiddenSectors
= PartitionEntry
->HiddenSectors
;
1357 DeviceExtension
->StartingOffset
= PartitionEntry
->StartingOffset
;
1358 DeviceExtension
->PartitionLength
= PartitionEntry
->PartitionLength
;
1360 /* Update partition number in the partition list */
1361 PartitionEntry
->PartitionNumber
= PartitionNumber
;
1363 DPRINT("Partition ordinal %lu was assigned to partition %lu\n",
1364 DiskData
->PartitionOrdinal
,
1365 DiskData
->PartitionNumber
);
1368 DPRINT("ScsiDiskUpdatePartitionDeviceObjects() done\n");
1372 /**********************************************************************
1374 * ScsiDiskSearchForDisk
1377 * Searches the hardware tree for the given disk.
1384 * Disk device extension.
1387 * Handle to the hardware bus key.
1389 * DetectedDiskNumber
1390 * Returned disk number.
1393 * TRUE: Disk was found.
1394 * FALSE: Search failed.
1398 ScsiDiskSearchForDisk(IN PDEVICE_EXTENSION DeviceExtension
,
1400 OUT PULONG DetectedDiskNumber
)
1402 PKEY_VALUE_FULL_INFORMATION ValueData
;
1403 OBJECT_ATTRIBUTES ObjectAttributes
;
1404 PDISK_DATA DiskData
;
1405 UNICODE_STRING IdentifierString
;
1406 UNICODE_STRING NameString
;
1407 HANDLE BusInstanceKey
;
1408 HANDLE ControllerKey
;
1410 HANDLE DiskInstanceKey
;
1412 ULONG ControllerNumber
;
1419 DPRINT("ScsiDiskSearchForDiskData() called\n");
1423 /* Enumerate buses */
1424 for (BusNumber
= 0; ; BusNumber
++)
1426 /* Open bus instance subkey */
1431 RtlInitUnicodeString(&NameString
,
1434 InitializeObjectAttributes(&ObjectAttributes
,
1436 OBJ_CASE_INSENSITIVE
,
1440 Status
= ZwOpenKey(&BusInstanceKey
,
1443 if (!NT_SUCCESS(Status
))
1448 /* Open 'DiskController' subkey */
1449 RtlInitUnicodeString(&NameString
,
1452 InitializeObjectAttributes(&ObjectAttributes
,
1454 OBJ_CASE_INSENSITIVE
,
1458 Status
= ZwOpenKey(&ControllerKey
,
1461 if (!NT_SUCCESS(Status
))
1463 ZwClose(BusInstanceKey
);
1467 /* Enumerate controllers */
1468 for (ControllerNumber
= 0; ; ControllerNumber
++)
1470 /* Open 'DiskPeripheral' subkey */
1472 L
"%lu\\DiskPeripheral",
1475 RtlInitUnicodeString(&NameString
,
1478 InitializeObjectAttributes(&ObjectAttributes
,
1480 OBJ_CASE_INSENSITIVE
,
1484 Status
= ZwOpenKey(&DiskKey
,
1487 if (!NT_SUCCESS(Status
))
1492 /* Enumerate disks */
1493 for (DiskNumber
= 0; ; DiskNumber
++)
1495 /* Open disk instance subkey */
1500 RtlInitUnicodeString(&NameString
,
1503 InitializeObjectAttributes(&ObjectAttributes
,
1505 OBJ_CASE_INSENSITIVE
,
1509 Status
= ZwOpenKey(&DiskInstanceKey
,
1512 if (!NT_SUCCESS(Status
))
1517 DPRINT("Found disk key: bus %lu controller %lu disk %lu\n",
1522 /* Allocate data buffer */
1523 ValueData
= ExAllocatePool(PagedPool
,
1525 if (ValueData
== NULL
)
1527 ZwClose(DiskInstanceKey
);
1531 /* Get the 'Identifier' value */
1532 RtlInitUnicodeString(&NameString
,
1534 Status
= ZwQueryValueKey(DiskInstanceKey
,
1536 KeyValueFullInformation
,
1541 ZwClose(DiskInstanceKey
);
1542 if (!NT_SUCCESS(Status
))
1544 ExFreePool(ValueData
);
1548 IdentifierString
.Buffer
=
1549 (PWSTR
)((PUCHAR
)ValueData
+ ValueData
->DataOffset
);
1550 IdentifierString
.Length
= (USHORT
)ValueData
->DataLength
- 2;
1551 IdentifierString
.MaximumLength
= (USHORT
)ValueData
->DataLength
;
1553 DPRINT("DiskIdentifier: %wZ\n",
1556 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
1557 if (DiskData
->Signature
!= 0)
1559 /* Comapre disk signature */
1562 DiskData
->Signature
);
1563 if (!_wcsnicmp(Buffer
, &IdentifierString
.Buffer
[9], 8))
1565 DPRINT("Found disk %lu\n", DiskNumber
);
1567 *DetectedDiskNumber
= DiskNumber
;
1572 /* Comapre mbr checksum */
1575 DiskData
->MbrCheckSum
);
1576 if (!_wcsnicmp(Buffer
, &IdentifierString
.Buffer
[0], 8))
1578 DPRINT("Found disk %lu\n", DiskNumber
);
1580 *DetectedDiskNumber
= DiskNumber
;
1584 ExFreePool(ValueData
);
1586 ZwClose(DiskInstanceKey
);
1588 if (DiskFound
== TRUE
)
1595 ZwClose(ControllerKey
);
1596 ZwClose(BusInstanceKey
);
1599 DPRINT("ScsiDiskSearchForDisk() done\n");
1605 /**********************************************************************
1607 * DiskClassUpdateFixedDiskGeometry
1610 * Updated the geometry of a disk if the disk can be accessed
1618 * Disk device extension.
1625 ScsiDiskUpdateFixedDiskGeometry(IN PDEVICE_EXTENSION DeviceExtension
)
1627 PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1628 PCM_INT13_DRIVE_PARAMETER DriveParameters
;
1629 PKEY_VALUE_FULL_INFORMATION ValueBuffer
;
1630 OBJECT_ATTRIBUTES ObjectAttributes
;
1631 UNICODE_STRING KeyName
;
1632 UNICODE_STRING ValueName
;
1640 ULONG SectorsPerTrack
;
1641 ULONG TracksPerCylinder
;
1644 DPRINT("ScsiDiskUpdateFixedDiskGeometry() called\n");
1646 RtlInitUnicodeString(&KeyName
,
1647 L
"\\Registry\\Machine\\Hardware\\Description\\System");
1649 InitializeObjectAttributes(&ObjectAttributes
,
1651 OBJ_CASE_INSENSITIVE
,
1655 /* Open the adapter key */
1656 Status
= ZwOpenKey(&SystemKey
,
1659 if (!NT_SUCCESS(Status
))
1661 DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status
);
1665 /* Allocate value buffer */
1666 ValueBuffer
= ExAllocatePool(PagedPool
,
1668 if (ValueBuffer
== NULL
)
1670 DPRINT1("Failed to allocate value buffer\n");
1675 RtlInitUnicodeString(&ValueName
,
1676 L
"Configuration Data");
1678 /* Query 'Configuration Data' value */
1679 Status
= ZwQueryValueKey(SystemKey
,
1681 KeyValueFullInformation
,
1685 if (!NT_SUCCESS(Status
))
1687 DPRINT1("ZwQueryValueKey() failed (Status %lx)\n", Status
);
1688 ExFreePool(ValueBuffer
);
1693 /* Open the 'MultifunctionAdapter' subkey */
1694 RtlInitUnicodeString(&KeyName
,
1695 L
"MultifunctionAdapter");
1697 InitializeObjectAttributes(&ObjectAttributes
,
1699 OBJ_CASE_INSENSITIVE
,
1703 Status
= ZwOpenKey(&BusKey
,
1707 if (!NT_SUCCESS(Status
))
1709 DPRINT1("ZwQueryValueKey() failed (Status %lx)\n", Status
);
1710 ExFreePool(ValueBuffer
);
1714 if (!ScsiDiskSearchForDisk(DeviceExtension
, BusKey
, &DiskNumber
))
1716 DPRINT1("ScsiDiskSearchForDisk() failed\n");
1718 ExFreePool(ValueBuffer
);
1724 ResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)
1725 ((PUCHAR
)ValueBuffer
+ ValueBuffer
->DataOffset
);
1727 DriveParameters
= (PCM_INT13_DRIVE_PARAMETER
)
1728 ((PUCHAR
)ResourceDescriptor
+ sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
1731 for (i
= 0; i
< DriveParameters
[0].NumberDrives
; i
++)
1733 DPRINT1("Drive %lu: %lu Cylinders %hu Heads %hu Sectors\n",
1735 DriveParameters
[i
].MaxCylinders
,
1736 DriveParameters
[i
].MaxHeads
,
1737 DriveParameters
[i
].SectorsPerTrack
);
1741 Cylinders
= DriveParameters
[DiskNumber
].MaxCylinders
+ 1;
1742 TracksPerCylinder
= DriveParameters
[DiskNumber
].MaxHeads
+1;
1743 SectorsPerTrack
= DriveParameters
[DiskNumber
].SectorsPerTrack
;
1745 DPRINT1("BIOS geometry: %lu Cylinders %hu Heads %hu Sectors\n",
1751 (DeviceExtension
->PartitionLength
.QuadPart
>> DeviceExtension
->SectorShift
);
1753 DPRINT("Physical sectors: %lu\n",
1756 Length
= TracksPerCylinder
* SectorsPerTrack
;
1759 DPRINT1("Invalid track length 0\n");
1760 ExFreePool(ValueBuffer
);
1764 Cylinders
= Sectors
/ Length
;
1766 DPRINT1("Logical geometry: %lu Cylinders %hu Heads %hu Sectors\n",
1771 /* Update the disk geometry */
1772 DeviceExtension
->DiskGeometry
->SectorsPerTrack
= SectorsPerTrack
;
1773 DeviceExtension
->DiskGeometry
->TracksPerCylinder
= TracksPerCylinder
;
1774 DeviceExtension
->DiskGeometry
->Cylinders
.QuadPart
= (ULONGLONG
)Cylinders
;
1776 if (DeviceExtension
->DMActive
)
1778 DPRINT1("FIXME: Update geometry with respect to the installed disk manager!\n");
1780 /* FIXME: Update geometry for disk managers */
1784 ExFreePool(ValueBuffer
);
1786 DPRINT("ScsiDiskUpdateFixedDiskGeometry() done\n");
1790 /**********************************************************************
1792 * ScsiDiskCalcMbrCheckSum
1795 * Calculates the Checksum from drives MBR.
1802 * Disk device extension.
1805 * Pointer to the caller supplied cecksum variable.
1808 * TRUE: Checksum was calculated.
1809 * FALSE: Calculation failed.
1813 ScsiDiskCalcMbrCheckSum(IN PDEVICE_EXTENSION DeviceExtension
,
1814 OUT PULONG Checksum
)
1816 IO_STATUS_BLOCK IoStatusBlock
;
1817 LARGE_INTEGER SectorOffset
;
1826 KeInitializeEvent(&Event
,
1830 /* Get the disk sector size */
1831 SectorSize
= DeviceExtension
->DiskGeometry
->BytesPerSector
;
1832 if (SectorSize
< 512)
1837 /* Allocate MBR buffer */
1838 MbrBuffer
= ExAllocatePool(NonPagedPool
,
1840 if (MbrBuffer
== NULL
)
1845 /* Allocate an IRP */
1846 SectorOffset
.QuadPart
= 0ULL;
1847 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1848 DeviceExtension
->DeviceObject
,
1856 ExFreePool(MbrBuffer
);
1860 /* Call the miniport driver */
1861 Status
= IoCallDriver(DeviceExtension
->DeviceObject
,
1863 if (Status
== STATUS_PENDING
)
1865 KeWaitForSingleObject(&Event
,
1870 Status
= IoStatusBlock
.Status
;
1873 if (!NT_SUCCESS(Status
))
1875 ExFreePool(MbrBuffer
);
1879 /* Calculate MBR checksum */
1881 for (i
= 0; i
< 128; i
++)
1883 Sum
+= MbrBuffer
[i
];
1885 *Checksum
= ~Sum
+ 1;
1887 ExFreePool(MbrBuffer
);