3 * Copyright (C) 2001, 2002 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.22 2003/02/26 16:25:40 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
44 ULONG PartitionNumber
;
45 ULONG PartitionOrdinal
;
47 BOOLEAN BootIndicator
;
48 BOOLEAN DriveNotReady
;
49 } DISK_DATA
, *PDISK_DATA
;
53 DiskClassFindDevices(PDRIVER_OBJECT DriverObject
,
54 PUNICODE_STRING RegistryPath
,
55 PCLASS_INIT_DATA InitializationData
,
56 PDEVICE_OBJECT PortDeviceObject
,
60 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData
);
63 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject
,
68 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
69 IN PUNICODE_STRING RegistryPath
, /* what's this used for? */
70 IN PDEVICE_OBJECT PortDeviceObject
,
73 IN PIO_SCSI_CAPABILITIES Capabilities
,
74 IN PSCSI_INQUIRY_DATA InquiryData
,
75 IN PCLASS_INIT_DATA InitializationData
);
78 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
82 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
87 /* FUNCTIONS ****************************************************************/
92 // This function initializes the driver, locates and claims
93 // hardware resources, and creates various NT objects needed
94 // to process I/O requests.
100 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
102 // IN PUNICODE_STRING RegistryPath Name of registry driver service
109 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
110 IN PUNICODE_STRING RegistryPath
)
112 CLASS_INIT_DATA InitData
;
114 DPRINT("Disk Class Driver %s\n",
116 DPRINT("RegistryPath '%wZ'\n",
119 RtlZeroMemory(&InitData
,
120 sizeof(CLASS_INIT_DATA
));
122 InitData
.InitializationDataSize
= sizeof(CLASS_INIT_DATA
);
123 InitData
.DeviceExtensionSize
= sizeof(DEVICE_EXTENSION
) + sizeof(DISK_DATA
);
124 InitData
.DeviceType
= FILE_DEVICE_DISK
;
125 InitData
.DeviceCharacteristics
= 0;
127 InitData
.ClassError
= NULL
; // DiskClassProcessError;
128 InitData
.ClassReadWriteVerification
= DiskClassCheckReadWrite
;
129 InitData
.ClassFindDeviceCallBack
= DiskClassCheckDevice
;
130 InitData
.ClassFindDevices
= DiskClassFindDevices
;
131 InitData
.ClassDeviceControl
= DiskClassDeviceControl
;
132 InitData
.ClassShutdownFlush
= DiskClassShutdownFlush
;
133 InitData
.ClassCreateClose
= NULL
;
134 InitData
.ClassStartIo
= NULL
;
136 return(ScsiClassInitialize(DriverObject
,
142 /**********************************************************************
144 * DiskClassFindDevices
147 * This function searches for device that are attached to the
155 * System allocated Driver Object for this driver
158 * Name of registry driver service key
161 * Pointer to the main initialization data
164 * Pointer to the port Device Object
170 * TRUE: At least one disk drive was found
171 * FALSE: No disk drive found
175 DiskClassFindDevices(PDRIVER_OBJECT DriverObject
,
176 PUNICODE_STRING RegistryPath
,
177 PCLASS_INIT_DATA InitializationData
,
178 PDEVICE_OBJECT PortDeviceObject
,
181 PCONFIGURATION_INFORMATION ConfigInfo
;
182 PIO_SCSI_CAPABILITIES PortCapabilities
;
183 PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
;
184 PSCSI_INQUIRY_DATA UnitInfo
;
185 PINQUIRYDATA InquiryData
;
192 DPRINT("DiskClassFindDevices() called.\n");
194 /* Get port capabilities */
195 Status
= ScsiClassGetCapabilities(PortDeviceObject
,
197 if (!NT_SUCCESS(Status
))
199 DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status
);
203 DPRINT("PortCapabilities: %p\n", PortCapabilities
);
204 DPRINT("MaximumTransferLength: %lu\n", PortCapabilities
->MaximumTransferLength
);
205 DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities
->MaximumPhysicalPages
);
207 /* Get inquiry data */
208 Status
= ScsiClassGetInquiryData(PortDeviceObject
,
209 (PSCSI_ADAPTER_BUS_INFO
*)&Buffer
);
210 if (!NT_SUCCESS(Status
))
212 DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status
);
216 /* Check whether there are unclaimed devices */
217 AdapterBusInfo
= (PSCSI_ADAPTER_BUS_INFO
)Buffer
;
218 DeviceCount
= ScsiClassFindUnclaimedDevices(InitializationData
,
220 if (DeviceCount
== 0)
222 DPRINT("No unclaimed devices!\n");
226 DPRINT("Found %lu unclaimed devices!\n", DeviceCount
);
228 ConfigInfo
= IoGetConfigurationInformation();
230 /* Search each bus of this adapter */
231 for (Bus
= 0; Bus
< (ULONG
)AdapterBusInfo
->NumberOfBuses
; Bus
++)
233 DPRINT("Searching bus %lu\n", Bus
);
235 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
);
237 while (AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
)
239 InquiryData
= (PINQUIRYDATA
)UnitInfo
->InquiryData
;
241 if (((InquiryData
->DeviceType
== DIRECT_ACCESS_DEVICE
) ||
242 (InquiryData
->DeviceType
== OPTICAL_DEVICE
)) &&
243 (InquiryData
->DeviceTypeQualifier
== 0) &&
244 (UnitInfo
->DeviceClaimed
== FALSE
))
246 DPRINT("Vendor: '%.24s'\n",
247 InquiryData
->VendorId
);
249 /* Create device objects for disk */
250 Status
= DiskClassCreateDeviceObject(DriverObject
,
254 ConfigInfo
->DiskCount
,
258 if (NT_SUCCESS(Status
))
260 ConfigInfo
->DiskCount
++;
265 if (UnitInfo
->NextInquiryDataOffset
== 0)
268 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ UnitInfo
->NextInquiryDataOffset
);
274 DPRINT("DiskClassFindDevices() done\n");
280 /**********************************************************************
282 * DiskClassCheckDevice
285 * This function checks the InquiryData for the correct device
286 * type and qualifier.
293 * Pointer to the inquiry data for the device in question.
296 * TRUE: A disk device was found.
301 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData
)
303 return((InquiryData
->DeviceType
== DIRECT_ACCESS_DEVICE
||
304 InquiryData
->DeviceType
== OPTICAL_DEVICE
) &&
305 InquiryData
->DeviceTypeQualifier
== 0);
309 /**********************************************************************
311 * DiskClassCheckReadWrite
314 * This function checks the given IRP for correct data.
321 * Pointer to the device.
327 * STATUS_SUCCESS: The IRP matches the requirements of the given device.
332 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject
,
335 PDEVICE_EXTENSION DeviceExtension
;
338 DPRINT("DiskClassCheckReadWrite() called\n");
340 DeviceExtension
= DeviceObject
->DeviceExtension
;
341 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
343 if (DiskData
->DriveNotReady
== TRUE
)
345 Irp
->IoStatus
.Status
= STATUS_DEVICE_NOT_READY
;
346 IoSetHardErrorOrVerifyDevice(Irp
,
348 return(STATUS_INVALID_PARAMETER
);
351 return(STATUS_SUCCESS
);
355 /**********************************************************************
357 * DiskClassCreateDeviceObject
360 * Create the raw device and any partition devices on this drive
367 * The system created driver object
377 * STATUS_SUCCESS: Device objects for disk and partitions were created.
382 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
383 IN PUNICODE_STRING RegistryPath
, /* what's this used for? */
384 IN PDEVICE_OBJECT PortDeviceObject
,
387 IN PIO_SCSI_CAPABILITIES Capabilities
,
388 IN PSCSI_INQUIRY_DATA InquiryData
,
389 IN PCLASS_INIT_DATA InitializationData
)
391 OBJECT_ATTRIBUTES ObjectAttributes
;
392 UNICODE_STRING UnicodeDeviceDirName
;
393 WCHAR NameBuffer
[80];
394 CHAR NameBuffer2
[80];
395 PDEVICE_OBJECT DiskDeviceObject
;
396 PDEVICE_OBJECT PartitionDeviceObject
;
397 PDEVICE_EXTENSION DiskDeviceExtension
; /* defined in class2.h */
398 PDEVICE_EXTENSION PartitionDeviceExtension
; /* defined in class2.h */
399 PDRIVE_LAYOUT_INFORMATION PartitionList
= NULL
;
401 PPARTITION_INFORMATION PartitionEntry
;
403 ULONG PartitionNumber
;
407 DPRINT("DiskClassCreateDeviceObject() called\n");
409 /* Create the harddisk device directory */
411 L
"\\Device\\Harddisk%lu",
413 RtlInitUnicodeString(&UnicodeDeviceDirName
,
415 InitializeObjectAttributes(&ObjectAttributes
,
416 &UnicodeDeviceDirName
,
420 Status
= ZwCreateDirectoryObject(&Handle
,
423 if (!NT_SUCCESS(Status
))
425 DbgPrint("Could not create device dir object\n");
429 /* Claim the disk device */
430 Status
= ScsiClassClaimDevice(PortDeviceObject
,
434 if (!NT_SUCCESS(Status
))
436 DbgPrint("Could not claim disk device\n");
438 ZwMakeTemporaryObject(Handle
);
444 /* Create disk device (Partition 0) */
446 "\\Device\\Harddisk%lu\\Partition0",
449 Status
= ScsiClassCreateDeviceObject(DriverObject
,
454 if (!NT_SUCCESS(Status
))
456 DPRINT("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status
);
458 /* Release (unclaim) the disk */
459 ScsiClassClaimDevice(PortDeviceObject
,
464 /* Delete the harddisk device directory */
465 ZwMakeTemporaryObject(Handle
);
471 DiskDeviceObject
->Flags
|= DO_DIRECT_IO
;
472 if (((PINQUIRYDATA
)InquiryData
->InquiryData
)->RemovableMedia
)
474 DiskDeviceObject
->Characteristics
|= FILE_REMOVABLE_MEDIA
;
476 DiskDeviceObject
->StackSize
= (CCHAR
)PortDeviceObject
->StackSize
+ 1;
478 if (PortDeviceObject
->AlignmentRequirement
> DiskDeviceObject
->AlignmentRequirement
)
480 DiskDeviceObject
->AlignmentRequirement
= PortDeviceObject
->AlignmentRequirement
;
483 DiskDeviceExtension
= DiskDeviceObject
->DeviceExtension
;
484 DiskDeviceExtension
->LockCount
= 0;
485 DiskDeviceExtension
->DeviceNumber
= DiskNumber
;
486 DiskDeviceExtension
->PortDeviceObject
= PortDeviceObject
;
487 DiskDeviceExtension
->PhysicalDevice
= DiskDeviceObject
;
488 DiskDeviceExtension
->PortCapabilities
= Capabilities
;
489 DiskDeviceExtension
->StartingOffset
.QuadPart
= 0;
490 DiskDeviceExtension
->PortNumber
= (UCHAR
)PortNumber
;
491 DiskDeviceExtension
->PathId
= InquiryData
->PathId
;
492 DiskDeviceExtension
->TargetId
= InquiryData
->TargetId
;
493 DiskDeviceExtension
->Lun
= InquiryData
->Lun
;
495 /* Initialize the lookaside list for SRBs */
496 ScsiClassInitializeSrbLookasideList(DiskDeviceExtension
,
499 /* zero-out disk data */
500 DiskData
= (PDISK_DATA
)(DiskDeviceExtension
+ 1);
501 RtlZeroMemory(DiskData
,
504 /* Get disk geometry */
505 DiskDeviceExtension
->DiskGeometry
= ExAllocatePool(NonPagedPool
,
506 sizeof(DISK_GEOMETRY
));
507 if (DiskDeviceExtension
->DiskGeometry
== NULL
)
509 DPRINT("Failed to allocate geometry buffer!\n");
511 ExDeleteNPagedLookasideList(&DiskDeviceExtension
->SrbLookasideListHead
);
513 IoDeleteDevice(DiskDeviceObject
);
515 /* Release (unclaim) the disk */
516 ScsiClassClaimDevice(PortDeviceObject
,
521 /* Delete the harddisk device directory */
522 ZwMakeTemporaryObject(Handle
);
525 return(STATUS_INSUFFICIENT_RESOURCES
);
528 /* Read the drive's capacity */
529 Status
= ScsiClassReadDriveCapacity(DiskDeviceObject
);
530 if (!NT_SUCCESS(Status
) &&
531 (DiskDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
) == 0)
533 DPRINT1("Failed to retrieve drive capacity!\n");
534 return(STATUS_SUCCESS
);
538 /* Clear the verify flag for removable media drives. */
539 DiskDeviceObject
->Flags
&= ~DO_VERIFY_VOLUME
;
542 DPRINT("SectorSize: %lu\n", DiskDeviceExtension
->DiskGeometry
->BytesPerSector
);
544 /* Check disk for presence of a disk manager */
545 HalExamineMBR(DiskDeviceObject
,
546 DiskDeviceExtension
->DiskGeometry
->BytesPerSector
,
549 if (MbrBuffer
!= NULL
)
551 DPRINT1("Found 'Ontrack Disk Manager'!\n");
554 ExFreePool(MbrBuffer
);
558 HalExamineMBR(DiskDeviceObject
,
559 DiskDeviceExtension
->DiskGeometry
->BytesPerSector
,
562 if (MbrBuffer
!= NULL
)
564 DPRINT1("Found 'EZ-Drive' disk manager!\n");
567 ExFreePool(MbrBuffer
);
572 if ((DiskDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
) &&
573 (DiskDeviceExtension
->DiskGeometry
->MediaType
== RemovableMedia
))
575 /* Allocate a partition list for a single entry. */
576 PartitionList
= ExAllocatePool(NonPagedPool
,
577 sizeof(DRIVE_LAYOUT_INFORMATION
));
578 if (PartitionList
!= NULL
)
580 RtlZeroMemory(PartitionList
,
581 sizeof(DRIVE_LAYOUT_INFORMATION
));
582 PartitionList
->PartitionCount
= 1;
584 DiskData
->DriveNotReady
= TRUE
;
585 Status
= STATUS_SUCCESS
;
590 /* Read partition table */
591 Status
= IoReadPartitionTable(DiskDeviceObject
,
592 DiskDeviceExtension
->DiskGeometry
->BytesPerSector
,
596 DPRINT("IoReadPartitionTable(): Status: %lx\n", Status
);
598 if ((!NT_SUCCESS(Status
) || PartitionList
->PartitionCount
== 0) &&
599 DiskDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
601 if (!NT_SUCCESS(Status
))
603 /* Drive is not ready. */
604 DPRINT("Drive not ready\n");
605 DiskData
->DriveNotReady
= TRUE
;
609 ExFreePool(PartitionList
);
612 /* Allocate a partition list for a single entry. */
613 PartitionList
= ExAllocatePool(NonPagedPool
,
614 sizeof(DRIVE_LAYOUT_INFORMATION
));
615 if (PartitionList
!= NULL
)
617 RtlZeroMemory(PartitionList
,
618 sizeof(DRIVE_LAYOUT_INFORMATION
));
619 PartitionList
->PartitionCount
= 1;
621 Status
= STATUS_SUCCESS
;
626 if (NT_SUCCESS(Status
))
628 DPRINT("Read partition table!\n");
630 DPRINT(" Number of partitions: %u\n", PartitionList
->PartitionCount
);
632 for (PartitionNumber
= 0; PartitionNumber
< PartitionList
->PartitionCount
; PartitionNumber
++)
634 PartitionEntry
= &PartitionList
->PartitionEntry
[PartitionNumber
];
636 DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
638 PartitionEntry
->PartitionNumber
,
639 PartitionEntry
->BootIndicator
,
640 PartitionEntry
->PartitionType
,
641 PartitionEntry
->StartingOffset
.QuadPart
/ 512 /*DrvParms.BytesPerSector*/,
642 PartitionEntry
->PartitionLength
.QuadPart
/ 512 /* DrvParms.BytesPerSector*/);
644 /* Create partition device object */
646 "\\Device\\Harddisk%lu\\Partition%lu",
648 PartitionNumber
+ 1);
650 Status
= ScsiClassCreateDeviceObject(DriverObject
,
653 &PartitionDeviceObject
,
655 DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status
);
656 if (NT_SUCCESS(Status
))
658 PartitionDeviceObject
->Flags
= DiskDeviceObject
->Flags
;
659 PartitionDeviceObject
->Characteristics
= DiskDeviceObject
->Characteristics
;
660 PartitionDeviceObject
->StackSize
= DiskDeviceObject
->StackSize
;
661 PartitionDeviceObject
->AlignmentRequirement
= DiskDeviceObject
->AlignmentRequirement
;
663 PartitionDeviceExtension
= PartitionDeviceObject
->DeviceExtension
;
664 PartitionDeviceExtension
->LockCount
= 0;
665 PartitionDeviceExtension
->DeviceNumber
= DiskNumber
;
666 PartitionDeviceExtension
->PortDeviceObject
= PortDeviceObject
;
667 PartitionDeviceExtension
->DiskGeometry
= DiskDeviceExtension
->DiskGeometry
;
668 PartitionDeviceExtension
->PhysicalDevice
= DiskDeviceExtension
->PhysicalDevice
;
669 PartitionDeviceExtension
->PortCapabilities
= Capabilities
;
670 PartitionDeviceExtension
->StartingOffset
.QuadPart
=
671 PartitionEntry
->StartingOffset
.QuadPart
;
672 PartitionDeviceExtension
->PartitionLength
.QuadPart
=
673 PartitionEntry
->PartitionLength
.QuadPart
;
674 PartitionDeviceExtension
->PortNumber
= (UCHAR
)PortNumber
;
675 PartitionDeviceExtension
->PathId
= InquiryData
->PathId
;
676 PartitionDeviceExtension
->TargetId
= InquiryData
->TargetId
;
677 PartitionDeviceExtension
->Lun
= InquiryData
->Lun
;
678 PartitionDeviceExtension
->SectorShift
= DiskDeviceExtension
->SectorShift
;
680 /* Initialize lookaside list for SRBs */
681 ScsiClassInitializeSrbLookasideList(PartitionDeviceExtension
,
684 DiskData
= (PDISK_DATA
)(PartitionDeviceExtension
+ 1);
685 DiskData
->PartitionType
= PartitionEntry
->PartitionType
;
686 DiskData
->PartitionNumber
= PartitionNumber
+ 1;
687 DiskData
->PartitionOrdinal
= PartitionNumber
+ 1;
688 DiskData
->HiddenSectors
= PartitionEntry
->HiddenSectors
;
689 DiskData
->BootIndicator
= PartitionEntry
->BootIndicator
;
690 DiskData
->DriveNotReady
= FALSE
;
694 DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status
);
701 if (PartitionList
!= NULL
)
702 ExFreePool(PartitionList
);
704 DPRINT("DiskClassCreateDeviceObjects() done\n");
706 return(STATUS_SUCCESS
);
710 /**********************************************************************
712 * DiskClassDeviceControl
715 * Answer requests for device control calls
721 * Standard dispatch arguments
728 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
731 PDEVICE_EXTENSION DeviceExtension
;
732 PIO_STACK_LOCATION IrpStack
;
733 ULONG ControlCode
, InputLength
, OutputLength
;
738 DPRINT("DiskClassDeviceControl() called!\n");
740 Status
= STATUS_INVALID_DEVICE_REQUEST
;
742 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
743 ControlCode
= IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
744 InputLength
= IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
;
745 OutputLength
= IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
746 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
747 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
751 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
752 DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
753 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(DISK_GEOMETRY
))
755 Status
= STATUS_INVALID_PARAMETER
;
759 PDISK_GEOMETRY Geometry
;
761 if (DeviceExtension
->DiskGeometry
== NULL
)
763 DPRINT("No disk geometry available!\n");
764 DeviceExtension
->DiskGeometry
= ExAllocatePool(NonPagedPool
,
765 sizeof(DISK_GEOMETRY
));
767 Status
= ScsiClassReadDriveCapacity(DeviceObject
);
768 DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status
);
769 if (NT_SUCCESS(Status
))
771 Geometry
= (PDISK_GEOMETRY
)Irp
->AssociatedIrp
.SystemBuffer
;
772 RtlMoveMemory(Geometry
,
773 DeviceExtension
->DiskGeometry
,
774 sizeof(DISK_GEOMETRY
));
776 Status
= STATUS_SUCCESS
;
777 Information
= sizeof(DISK_GEOMETRY
);
782 case IOCTL_DISK_GET_PARTITION_INFO
:
783 DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n");
784 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
785 sizeof(PARTITION_INFORMATION
))
787 Status
= STATUS_INFO_LENGTH_MISMATCH
;
789 else if (DiskData
->PartitionNumber
== 0)
791 Status
= STATUS_INVALID_DEVICE_REQUEST
;
795 PPARTITION_INFORMATION PartitionInfo
;
797 PartitionInfo
= (PPARTITION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
799 PartitionInfo
->PartitionType
= DiskData
->PartitionType
;
800 PartitionInfo
->StartingOffset
= DeviceExtension
->StartingOffset
;
801 PartitionInfo
->PartitionLength
= DeviceExtension
->PartitionLength
;
802 PartitionInfo
->HiddenSectors
= DiskData
->HiddenSectors
;
803 PartitionInfo
->PartitionNumber
= DiskData
->PartitionNumber
;
804 PartitionInfo
->BootIndicator
= DiskData
->BootIndicator
;
805 PartitionInfo
->RewritePartition
= FALSE
;
806 PartitionInfo
->RecognizedPartition
=
807 IsRecognizedPartition(DiskData
->PartitionType
);
809 Status
= STATUS_SUCCESS
;
810 Information
= sizeof(PARTITION_INFORMATION
);
814 case IOCTL_DISK_SET_PARTITION_INFO
:
815 if (IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
816 sizeof(SET_PARTITION_INFORMATION
))
818 Status
= STATUS_INFO_LENGTH_MISMATCH
;
820 else if (DiskData
->PartitionNumber
== 0)
822 Status
= STATUS_INVALID_DEVICE_REQUEST
;
826 PSET_PARTITION_INFORMATION PartitionInfo
;
828 PartitionInfo
= (PSET_PARTITION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
830 Status
= IoSetPartitionInformation(DeviceExtension
->PhysicalDevice
,
831 DeviceExtension
->DiskGeometry
->BytesPerSector
,
832 DiskData
->PartitionOrdinal
,
833 PartitionInfo
->PartitionType
);
834 if (NT_SUCCESS(Status
))
836 DiskData
->PartitionType
= PartitionInfo
->PartitionType
;
841 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
842 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
843 sizeof(DRIVE_LAYOUT_INFORMATION
))
845 Status
= STATUS_BUFFER_TOO_SMALL
;
849 PDRIVE_LAYOUT_INFORMATION PartitionList
;
851 Status
= IoReadPartitionTable(DeviceExtension
->PhysicalDevice
,
852 DeviceExtension
->DiskGeometry
->BytesPerSector
,
855 if (NT_SUCCESS(Status
))
859 BufferSize
= FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION
,
861 BufferSize
+= PartitionList
->PartitionCount
* sizeof(PARTITION_INFORMATION
);
863 if (BufferSize
> IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
865 Status
= STATUS_BUFFER_TOO_SMALL
;
869 RtlMoveMemory(Irp
->AssociatedIrp
.SystemBuffer
,
872 Status
= STATUS_SUCCESS
;
873 Information
= BufferSize
;
875 ExFreePool(PartitionList
);
880 case IOCTL_DISK_SET_DRIVE_LAYOUT
:
881 if (IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
882 sizeof(DRIVE_LAYOUT_INFORMATION
))
884 Status
= STATUS_INFO_LENGTH_MISMATCH
;
886 else if (DeviceExtension
->PhysicalDevice
->DeviceExtension
!= DeviceExtension
)
888 Status
= STATUS_INVALID_PARAMETER
;
892 PDRIVE_LAYOUT_INFORMATION PartitionList
;
895 PartitionList
= Irp
->AssociatedIrp
.SystemBuffer
;
896 TableSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
897 ((PartitionList
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
899 if (IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
< TableSize
)
901 Status
= STATUS_BUFFER_TOO_SMALL
;
905 Status
= IoWritePartitionTable(DeviceExtension
->DeviceObject
,
906 DeviceExtension
->DiskGeometry
->BytesPerSector
,
907 DeviceExtension
->DiskGeometry
->SectorsPerTrack
,
908 DeviceExtension
->DiskGeometry
->TracksPerCylinder
,
910 if (NT_SUCCESS(Status
))
912 /* FIXME: Update partition device objects */
914 Information
= TableSize
;
920 case IOCTL_DISK_VERIFY
:
921 case IOCTL_DISK_FORMAT_TRACKS
:
922 case IOCTL_DISK_PERFORMANCE
:
923 case IOCTL_DISK_IS_WRITABLE
:
924 case IOCTL_DISK_LOGGING
:
925 case IOCTL_DISK_FORMAT_TRACKS_EX
:
926 case IOCTL_DISK_HISTOGRAM_STRUCTURE
:
927 case IOCTL_DISK_HISTOGRAM_DATA
:
928 case IOCTL_DISK_HISTOGRAM_RESET
:
929 case IOCTL_DISK_REQUEST_STRUCTURE
:
930 case IOCTL_DISK_REQUEST_DATA
:
931 /* If we get here, something went wrong. Inform the requestor */
932 DPRINT1("Unhandled control code: %lx\n", ControlCode
);
933 Status
= STATUS_INVALID_DEVICE_REQUEST
;
938 /* Call the common device control function */
939 return(ScsiClassDeviceControl(DeviceObject
, Irp
));
942 /* Verify the device if the user caused the error */
943 if (!NT_SUCCESS(Status
) && IoIsErrorUserInduced(Status
))
945 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
948 Irp
->IoStatus
.Status
= Status
;
949 Irp
->IoStatus
.Information
= Information
;
950 IoCompleteRequest(Irp
,
957 /**********************************************************************
959 * DiskClassShutdownFlush
962 * Answer requests for shutdown and flush calls.
969 * Pointer to the device.
979 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
982 PDEVICE_EXTENSION DeviceExtension
;
983 PIO_STACK_LOCATION IrpStack
;
984 PSCSI_REQUEST_BLOCK Srb
;
986 DPRINT("DiskClassShutdownFlush() called!\n");
988 DeviceExtension
= DeviceObject
->DeviceExtension
;
991 Srb
= ExAllocatePool(NonPagedPool
,
992 sizeof(SCSI_REQUEST_BLOCK
));
995 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
996 Irp
->IoStatus
.Information
= 0;
997 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
999 return(STATUS_INSUFFICIENT_RESOURCES
);
1002 /* Initialize SRB */
1003 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
1004 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
1006 /* Set device IDs */
1007 Srb
->PathId
= DeviceExtension
->PathId
;
1008 Srb
->TargetId
= DeviceExtension
->TargetId
;
1009 Srb
->Lun
= DeviceExtension
->Lun
;
1011 /* Flush write cache */
1012 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1013 Srb
->SrbFlags
= SRB_FLAGS_NO_DATA_TRANSFER
;
1014 Srb
->CdbLength
= 10;
1015 Srb
->Cdb
[0] = SCSIOP_SYNCHRONIZE_CACHE
;
1016 ScsiClassSendSrbSynchronous(DeviceObject
,
1022 /* Get current stack location */
1023 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1025 /* FIXME: Unlock removable media upon shutdown */
1029 IrpStack
->Parameters
.Others
.Argument4
= (PVOID
)0;
1031 /* Send shutdown or flush request to the port driver */
1033 if (IrpStack
->MajorFunction
== IRP_MJ_SHUTDOWN
)
1034 Srb
->Function
= SRB_FUNCTION_SHUTDOWN
;
1036 Srb
->Function
= SRB_FUNCTION_FLUSH
;
1038 /* Init completion routine */
1039 IoSetCompletionRoutine(Irp
,
1040 ScsiClassIoComplete
,
1046 /* Prepare next stack location for a call to the port driver */
1047 IrpStack
= IoGetNextIrpStackLocation(Irp
);
1048 IrpStack
->MajorFunction
= IRP_MJ_SCSI
;
1049 IrpStack
->Parameters
.Scsi
.Srb
= Srb
;
1050 Srb
->OriginalRequest
= Irp
;
1052 /* Call port driver */
1053 return(IoCallDriver(DeviceExtension
->PortDeviceObject
, Irp
));