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.17 2002/09/07 15:12:09 chorns 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 #define NTOS_KERNEL_MODE
32 #include <ddk/ntdddisk.h>
33 #include <ddk/ntddscsi.h>
34 #include "../include/class2.h"
39 #define VERSION "0.0.1"
42 typedef struct _DISK_DATA
45 ULONG PartitionNumber
;
46 ULONG PartitionOrdinal
;
48 BOOLEAN BootIndicator
;
49 BOOLEAN DriveNotReady
;
50 } DISK_DATA
, *PDISK_DATA
;
54 DiskClassFindDevices(PDRIVER_OBJECT DriverObject
,
55 PUNICODE_STRING RegistryPath
,
56 PCLASS_INIT_DATA InitializationData
,
57 PDEVICE_OBJECT PortDeviceObject
,
61 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData
);
64 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject
,
69 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
70 IN PUNICODE_STRING RegistryPath
, /* what's this used for? */
71 IN PDEVICE_OBJECT PortDeviceObject
,
74 IN PIO_SCSI_CAPABILITIES Capabilities
,
75 IN PSCSI_INQUIRY_DATA InquiryData
,
76 IN PCLASS_INIT_DATA InitializationData
);
79 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
83 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
88 /* FUNCTIONS ****************************************************************/
93 // This function initializes the driver, locates and claims
94 // hardware resources, and creates various NT objects needed
95 // to process I/O requests.
101 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
103 // IN PUNICODE_STRING RegistryPath Name of registry driver service
110 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
111 IN PUNICODE_STRING RegistryPath
)
113 CLASS_INIT_DATA InitData
;
115 DPRINT("Disk Class Driver %s\n",
117 DPRINT("RegistryPath '%wZ'\n",
120 RtlZeroMemory(&InitData
,
121 sizeof(CLASS_INIT_DATA
));
123 InitData
.InitializationDataSize
= sizeof(CLASS_INIT_DATA
);
124 InitData
.DeviceExtensionSize
= sizeof(DEVICE_EXTENSION
) + sizeof(DISK_DATA
);
125 InitData
.DeviceType
= FILE_DEVICE_DISK
;
126 InitData
.DeviceCharacteristics
= 0;
128 InitData
.ClassError
= NULL
; // DiskClassProcessError;
129 InitData
.ClassReadWriteVerification
= DiskClassCheckReadWrite
;
130 InitData
.ClassFindDeviceCallBack
= DiskClassCheckDevice
;
131 InitData
.ClassFindDevices
= DiskClassFindDevices
;
132 InitData
.ClassDeviceControl
= DiskClassDeviceControl
;
133 InitData
.ClassShutdownFlush
= DiskClassShutdownFlush
;
134 InitData
.ClassCreateClose
= NULL
;
135 InitData
.ClassStartIo
= NULL
;
137 return(ScsiClassInitialize(DriverObject
,
143 /**********************************************************************
145 * DiskClassFindDevices
148 * This function searches for device that are attached to the
156 * System allocated Driver Object for this driver
159 * Name of registry driver service key
162 * Pointer to the main initialization data
165 * Pointer to the port Device Object
171 * TRUE: At least one disk drive was found
172 * FALSE: No disk drive found
176 DiskClassFindDevices(PDRIVER_OBJECT DriverObject
,
177 PUNICODE_STRING RegistryPath
,
178 PCLASS_INIT_DATA InitializationData
,
179 PDEVICE_OBJECT PortDeviceObject
,
182 PCONFIGURATION_INFORMATION ConfigInfo
;
183 PIO_SCSI_CAPABILITIES PortCapabilities
;
184 PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
;
185 PSCSI_INQUIRY_DATA UnitInfo
;
186 PINQUIRYDATA InquiryData
;
193 DPRINT("DiskClassFindDevices() called.\n");
195 /* Get port capabilities */
196 Status
= ScsiClassGetCapabilities(PortDeviceObject
,
198 if (!NT_SUCCESS(Status
))
200 DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status
);
204 DPRINT("PortCapabilities: %p\n", PortCapabilities
);
205 DPRINT("MaximumTransferLength: %lu\n", PortCapabilities
->MaximumTransferLength
);
206 DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities
->MaximumPhysicalPages
);
208 /* Get inquiry data */
209 Status
= ScsiClassGetInquiryData(PortDeviceObject
,
210 (PSCSI_ADAPTER_BUS_INFO
*)&Buffer
);
211 if (!NT_SUCCESS(Status
))
213 DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status
);
217 /* Check whether there are unclaimed devices */
218 AdapterBusInfo
= (PSCSI_ADAPTER_BUS_INFO
)Buffer
;
219 DeviceCount
= ScsiClassFindUnclaimedDevices(InitializationData
,
221 if (DeviceCount
== 0)
223 DPRINT("No unclaimed devices!\n");
227 DPRINT("Found %lu unclaimed devices!\n", DeviceCount
);
229 ConfigInfo
= IoGetConfigurationInformation();
231 /* Search each bus of this adapter */
232 for (Bus
= 0; Bus
< (ULONG
)AdapterBusInfo
->NumberOfBuses
; Bus
++)
234 DPRINT("Searching bus %lu\n", Bus
);
236 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
);
238 while (AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
)
240 InquiryData
= (PINQUIRYDATA
)UnitInfo
->InquiryData
;
242 if (((InquiryData
->DeviceType
== DIRECT_ACCESS_DEVICE
) ||
243 (InquiryData
->DeviceType
== OPTICAL_DEVICE
)) &&
244 (InquiryData
->DeviceTypeQualifier
== 0) &&
245 (UnitInfo
->DeviceClaimed
== FALSE
))
247 DPRINT("Vendor: '%.24s'\n",
248 InquiryData
->VendorId
);
250 /* Create device objects for disk */
251 Status
= DiskClassCreateDeviceObject(DriverObject
,
255 ConfigInfo
->DiskCount
,
259 if (NT_SUCCESS(Status
))
261 ConfigInfo
->DiskCount
++;
266 if (UnitInfo
->NextInquiryDataOffset
== 0)
269 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ UnitInfo
->NextInquiryDataOffset
);
275 DPRINT("DiskClassFindDevices() done\n");
281 /**********************************************************************
283 * DiskClassCheckDevice
286 * This function checks the InquiryData for the correct device
287 * type and qualifier.
294 * Pointer to the inquiry data for the device in question.
297 * TRUE: A disk device was found.
302 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData
)
304 return((InquiryData
->DeviceType
== DIRECT_ACCESS_DEVICE
||
305 InquiryData
->DeviceType
== OPTICAL_DEVICE
) &&
306 InquiryData
->DeviceTypeQualifier
== 0);
310 /**********************************************************************
312 * DiskClassCheckReadWrite
315 * This function checks the given IRP for correct data.
322 * Pointer to the device.
328 * STATUS_SUCCESS: The IRP matches the requirements of the given device.
333 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject
,
336 PDEVICE_EXTENSION DeviceExtension
;
339 DPRINT("DiskClassCheckReadWrite() called\n");
341 DeviceExtension
= DeviceObject
->DeviceExtension
;
342 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
344 if (DiskData
->DriveNotReady
== TRUE
)
346 Irp
->IoStatus
.Status
= STATUS_DEVICE_NOT_READY
;
347 IoSetHardErrorOrVerifyDevice(Irp
,
349 return(STATUS_INVALID_PARAMETER
);
352 return(STATUS_SUCCESS
);
356 /**********************************************************************
358 * DiskClassCreateDeviceObject
361 * Create the raw device and any partition devices on this drive
368 * The system created driver object
378 * STATUS_SUCCESS: Device objects for disk and partitions were created.
383 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
384 IN PUNICODE_STRING RegistryPath
, /* what's this used for? */
385 IN PDEVICE_OBJECT PortDeviceObject
,
388 IN PIO_SCSI_CAPABILITIES Capabilities
,
389 IN PSCSI_INQUIRY_DATA InquiryData
,
390 IN PCLASS_INIT_DATA InitializationData
)
392 OBJECT_ATTRIBUTES ObjectAttributes
;
393 UNICODE_STRING UnicodeDeviceDirName
;
394 WCHAR NameBuffer
[80];
395 CHAR NameBuffer2
[80];
396 PDEVICE_OBJECT DiskDeviceObject
;
397 PDEVICE_OBJECT PartitionDeviceObject
;
398 PDEVICE_EXTENSION DiskDeviceExtension
; /* defined in class2.h */
399 PDEVICE_EXTENSION PartitionDeviceExtension
; /* defined in class2.h */
400 PDRIVE_LAYOUT_INFORMATION PartitionList
= NULL
;
402 PPARTITION_INFORMATION PartitionEntry
;
404 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 /* zero-out disk data */
496 DiskData
= (PDISK_DATA
)(DiskDeviceExtension
+ 1);
497 RtlZeroMemory(DiskData
,
500 /* Get disk geometry */
501 DiskDeviceExtension
->DiskGeometry
= ExAllocatePool(NonPagedPool
,
502 sizeof(DISK_GEOMETRY
));
503 if (DiskDeviceExtension
->DiskGeometry
== NULL
)
505 DPRINT("Failed to allocate geometry buffer!\n");
507 IoDeleteDevice(DiskDeviceObject
);
509 /* Release (unclaim) the disk */
510 ScsiClassClaimDevice(PortDeviceObject
,
515 /* Delete the harddisk device directory */
516 ZwMakeTemporaryObject(Handle
);
519 return(STATUS_INSUFFICIENT_RESOURCES
);
522 /* Read the drive's capacity */
523 Status
= ScsiClassReadDriveCapacity(DiskDeviceObject
);
524 if (!NT_SUCCESS(Status
) &&
525 (DiskDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
) == 0)
527 DPRINT1("Failed to retrieve drive capacity!\n");
528 return(STATUS_SUCCESS
);
532 /* Clear the verify flag for removable media drives. */
533 DiskDeviceObject
->Flags
&= ~DO_VERIFY_VOLUME
;
536 DPRINT("SectorSize: %lu\n", DiskDeviceExtension
->DiskGeometry
->BytesPerSector
);
538 if ((DiskDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
) &&
539 (DiskDeviceExtension
->DiskGeometry
->MediaType
== RemovableMedia
))
541 /* Allocate a partition list for a single entry. */
542 PartitionList
= ExAllocatePool(NonPagedPool
,
543 sizeof(DRIVE_LAYOUT_INFORMATION
));
544 if (PartitionList
!= NULL
)
546 RtlZeroMemory(PartitionList
,
547 sizeof(DRIVE_LAYOUT_INFORMATION
));
548 PartitionList
->PartitionCount
= 1;
550 DiskData
->DriveNotReady
= TRUE
;
551 Status
= STATUS_SUCCESS
;
556 /* Read partition table */
557 Status
= IoReadPartitionTable(DiskDeviceObject
,
558 DiskDeviceExtension
->DiskGeometry
->BytesPerSector
,
562 DPRINT("IoReadPartitionTable(): Status: %lx\n", Status
);
564 if ((!NT_SUCCESS(Status
) || PartitionList
->PartitionCount
== 0) &&
565 DiskDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
567 if (!NT_SUCCESS(Status
))
569 /* Drive is not ready. */
570 DPRINT("Drive not ready\n");
571 DiskData
->DriveNotReady
= TRUE
;
575 ExFreePool(PartitionList
);
578 /* Allocate a partition list for a single entry. */
579 PartitionList
= ExAllocatePool(NonPagedPool
,
580 sizeof(DRIVE_LAYOUT_INFORMATION
));
581 if (PartitionList
!= NULL
)
583 RtlZeroMemory(PartitionList
,
584 sizeof(DRIVE_LAYOUT_INFORMATION
));
585 PartitionList
->PartitionCount
= 1;
587 Status
= STATUS_SUCCESS
;
592 if (NT_SUCCESS(Status
))
594 DPRINT("Read partition table!\n");
596 DPRINT(" Number of partitions: %u\n", PartitionList
->PartitionCount
);
598 for (PartitionNumber
= 0; PartitionNumber
< PartitionList
->PartitionCount
; PartitionNumber
++)
600 PartitionEntry
= &PartitionList
->PartitionEntry
[PartitionNumber
];
602 DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
604 PartitionEntry
->PartitionNumber
,
605 PartitionEntry
->BootIndicator
,
606 PartitionEntry
->PartitionType
,
607 PartitionEntry
->StartingOffset
.QuadPart
/ 512 /*DrvParms.BytesPerSector*/,
608 PartitionEntry
->PartitionLength
.QuadPart
/ 512 /* DrvParms.BytesPerSector*/);
610 /* Create partition device object */
612 "\\Device\\Harddisk%lu\\Partition%lu",
614 PartitionNumber
+ 1);
616 Status
= ScsiClassCreateDeviceObject(DriverObject
,
619 &PartitionDeviceObject
,
621 DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status
);
622 if (NT_SUCCESS(Status
))
624 PartitionDeviceObject
->Flags
= DiskDeviceObject
->Flags
;
625 PartitionDeviceObject
->Characteristics
= DiskDeviceObject
->Characteristics
;
626 PartitionDeviceObject
->StackSize
= DiskDeviceObject
->StackSize
;
627 PartitionDeviceObject
->AlignmentRequirement
= DiskDeviceObject
->AlignmentRequirement
;
629 PartitionDeviceExtension
= PartitionDeviceObject
->DeviceExtension
;
630 PartitionDeviceExtension
->LockCount
= 0;
631 PartitionDeviceExtension
->DeviceNumber
= DiskNumber
;
632 PartitionDeviceExtension
->PortDeviceObject
= PortDeviceObject
;
633 PartitionDeviceExtension
->DiskGeometry
= DiskDeviceExtension
->DiskGeometry
;
634 PartitionDeviceExtension
->PhysicalDevice
= DiskDeviceExtension
->PhysicalDevice
;
635 PartitionDeviceExtension
->PortCapabilities
= Capabilities
;
636 PartitionDeviceExtension
->StartingOffset
.QuadPart
=
637 PartitionEntry
->StartingOffset
.QuadPart
;
638 PartitionDeviceExtension
->PartitionLength
.QuadPart
=
639 PartitionEntry
->PartitionLength
.QuadPart
;
640 PartitionDeviceExtension
->PortNumber
= (UCHAR
)PortNumber
;
641 PartitionDeviceExtension
->PathId
= InquiryData
->PathId
;
642 PartitionDeviceExtension
->TargetId
= InquiryData
->TargetId
;
643 PartitionDeviceExtension
->Lun
= InquiryData
->Lun
;
644 PartitionDeviceExtension
->SectorShift
= DiskDeviceExtension
->SectorShift
;
646 DiskData
= (PDISK_DATA
)(PartitionDeviceExtension
+ 1);
647 DiskData
->PartitionType
= PartitionEntry
->PartitionType
;
648 DiskData
->PartitionNumber
= PartitionNumber
+ 1;
649 DiskData
->PartitionOrdinal
= PartitionNumber
+ 1;
650 DiskData
->HiddenSectors
= PartitionEntry
->HiddenSectors
;
651 DiskData
->BootIndicator
= PartitionEntry
->BootIndicator
;
652 DiskData
->DriveNotReady
= FALSE
;
656 DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status
);
663 if (PartitionList
!= NULL
)
664 ExFreePool(PartitionList
);
666 DPRINT("DiskClassCreateDeviceObjects() done\n");
668 return(STATUS_SUCCESS
);
672 /**********************************************************************
674 * DiskClassDeviceControl
677 * Answer requests for device control calls
683 * Standard dispatch arguments
690 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
693 PDEVICE_EXTENSION DeviceExtension
;
694 PIO_STACK_LOCATION IrpStack
;
695 ULONG ControlCode
, InputLength
, OutputLength
;
700 DPRINT("DiskClassDeviceControl() called!\n");
702 Status
= STATUS_INVALID_DEVICE_REQUEST
;
704 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
705 ControlCode
= IrpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
706 InputLength
= IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
;
707 OutputLength
= IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
708 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
709 DiskData
= (PDISK_DATA
)(DeviceExtension
+ 1);
713 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
714 DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
715 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(DISK_GEOMETRY
))
717 Status
= STATUS_INVALID_PARAMETER
;
721 PDISK_GEOMETRY Geometry
;
723 if (DeviceExtension
->DiskGeometry
== NULL
)
725 DPRINT("No disk geometry available!\n");
726 DeviceExtension
->DiskGeometry
= ExAllocatePool(NonPagedPool
,
727 sizeof(DISK_GEOMETRY
));
729 Status
= ScsiClassReadDriveCapacity(DeviceObject
);
730 DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status
);
731 if (NT_SUCCESS(Status
))
733 Geometry
= (PDISK_GEOMETRY
)Irp
->AssociatedIrp
.SystemBuffer
;
734 RtlMoveMemory(Geometry
,
735 DeviceExtension
->DiskGeometry
,
736 sizeof(DISK_GEOMETRY
));
738 Status
= STATUS_SUCCESS
;
739 Information
= sizeof(DISK_GEOMETRY
);
744 case IOCTL_DISK_GET_PARTITION_INFO
:
745 DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n");
746 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
747 sizeof(PARTITION_INFORMATION
))
749 Status
= STATUS_INFO_LENGTH_MISMATCH
;
751 else if (DiskData
->PartitionNumber
== 0)
753 Status
= STATUS_INVALID_DEVICE_REQUEST
;
757 PPARTITION_INFORMATION PartitionInfo
;
759 PartitionInfo
= (PPARTITION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
761 PartitionInfo
->PartitionType
= DiskData
->PartitionType
;
762 PartitionInfo
->StartingOffset
= DeviceExtension
->StartingOffset
;
763 PartitionInfo
->PartitionLength
= DeviceExtension
->PartitionLength
;
764 PartitionInfo
->HiddenSectors
= DiskData
->HiddenSectors
;
765 PartitionInfo
->PartitionNumber
= DiskData
->PartitionNumber
;
766 PartitionInfo
->BootIndicator
= DiskData
->BootIndicator
;
767 PartitionInfo
->RewritePartition
= FALSE
;
768 PartitionInfo
->RecognizedPartition
=
769 IsRecognizedPartition(DiskData
->PartitionType
);
771 Status
= STATUS_SUCCESS
;
772 Information
= sizeof(PARTITION_INFORMATION
);
776 case IOCTL_DISK_SET_PARTITION_INFO
:
777 if (IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
778 sizeof(SET_PARTITION_INFORMATION
))
780 Status
= STATUS_INFO_LENGTH_MISMATCH
;
782 else if (DiskData
->PartitionNumber
== 0)
784 Status
= STATUS_INVALID_DEVICE_REQUEST
;
788 PSET_PARTITION_INFORMATION PartitionInfo
;
790 PartitionInfo
= (PSET_PARTITION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
792 Status
= IoSetPartitionInformation(DeviceExtension
->PhysicalDevice
,
793 DeviceExtension
->DiskGeometry
->BytesPerSector
,
794 DiskData
->PartitionOrdinal
,
795 PartitionInfo
->PartitionType
);
796 if (NT_SUCCESS(Status
))
798 DiskData
->PartitionType
= PartitionInfo
->PartitionType
;
803 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
804 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
805 sizeof(DRIVE_LAYOUT_INFORMATION
))
807 Status
= STATUS_BUFFER_TOO_SMALL
;
811 PDRIVE_LAYOUT_INFORMATION PartitionList
;
813 Status
= IoReadPartitionTable(DeviceExtension
->PhysicalDevice
,
814 DeviceExtension
->DiskGeometry
->BytesPerSector
,
817 if (NT_SUCCESS(Status
))
821 BufferSize
= FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION
,
823 BufferSize
+= PartitionList
->PartitionCount
* sizeof(PARTITION_INFORMATION
);
825 if (BufferSize
> IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
827 Status
= STATUS_BUFFER_TOO_SMALL
;
831 RtlMoveMemory(Irp
->AssociatedIrp
.SystemBuffer
,
834 Status
= STATUS_SUCCESS
;
835 Information
= BufferSize
;
837 ExFreePool(PartitionList
);
842 case IOCTL_DISK_SET_DRIVE_LAYOUT
:
843 case IOCTL_DISK_VERIFY
:
844 case IOCTL_DISK_FORMAT_TRACKS
:
845 case IOCTL_DISK_PERFORMANCE
:
846 case IOCTL_DISK_IS_WRITABLE
:
847 case IOCTL_DISK_LOGGING
:
848 case IOCTL_DISK_FORMAT_TRACKS_EX
:
849 case IOCTL_DISK_HISTOGRAM_STRUCTURE
:
850 case IOCTL_DISK_HISTOGRAM_DATA
:
851 case IOCTL_DISK_HISTOGRAM_RESET
:
852 case IOCTL_DISK_REQUEST_STRUCTURE
:
853 case IOCTL_DISK_REQUEST_DATA
:
854 /* If we get here, something went wrong. inform the requestor */
855 DPRINT1("Unhandled control code: %lx\n", ControlCode
);
856 Status
= STATUS_INVALID_DEVICE_REQUEST
;
861 /* Call the common device control function */
862 return(ScsiClassDeviceControl(DeviceObject
, Irp
));
865 /* Verify the device if the user caused the error */
866 if (!NT_SUCCESS(Status
) && IoIsErrorUserInduced(Status
))
868 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
871 Irp
->IoStatus
.Status
= Status
;
872 Irp
->IoStatus
.Information
= Information
;
873 IoCompleteRequest(Irp
,
880 /**********************************************************************
882 * DiskClassShutdownFlush
885 * Answer requests for shutdown and flush calls.
892 * Pointer to the device.
902 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
905 PDEVICE_EXTENSION DeviceExtension
;
906 PIO_STACK_LOCATION IrpStack
;
907 PSCSI_REQUEST_BLOCK Srb
;
909 DPRINT("DiskClassShutdownFlush() called!\n");
911 DeviceExtension
= DeviceObject
->DeviceExtension
;
914 Srb
= ExAllocatePool(NonPagedPool
,
915 sizeof(SCSI_REQUEST_BLOCK
));
918 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
919 Irp
->IoStatus
.Information
= 0;
920 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
922 return(STATUS_INSUFFICIENT_RESOURCES
);
926 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
927 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
930 Srb
->PathId
= DeviceExtension
->PathId
;
931 Srb
->TargetId
= DeviceExtension
->TargetId
;
932 Srb
->Lun
= DeviceExtension
->Lun
;
935 /* FIXME: Flush write cache */
938 /* Get current stack location */
939 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
942 /* FIXME: Unlock removable media upon shutdown */
946 IrpStack
->Parameters
.Others
.Argument4
= (PVOID
)0;
948 /* Send shutdown or flush request to the port driver */
950 if (IrpStack
->MajorFunction
== IRP_MJ_SHUTDOWN
)
951 Srb
->Function
= SRB_FUNCTION_SHUTDOWN
;
953 Srb
->Function
= SRB_FUNCTION_FLUSH
;
955 /* Init completion routine */
956 IoSetCompletionRoutine(Irp
,
963 /* Prepare next stack location for a call to the port driver */
964 IrpStack
= IoGetNextIrpStackLocation(Irp
);
965 IrpStack
->MajorFunction
= IRP_MJ_SCSI
;
966 IrpStack
->Parameters
.Scsi
.Srb
= Srb
;
967 Srb
->OriginalRequest
= Irp
;
969 /* Call port driver */
970 return(IoCallDriver(DeviceExtension
->PortDeviceObject
, Irp
));