Enabled reading of multiple sectors.
[reactos.git] / reactos / drivers / storage / disk / disk.c
1 /* $Id: disk.c,v 1.7 2002/03/04 22:31:35 ekohl Exp $
2 *
3 */
4
5 /* INCLUDES *****************************************************************/
6
7 #include <ddk/ntddk.h>
8
9 #include "../include/scsi.h"
10 #include "../include/class2.h"
11 #include "../include/ntddscsi.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 #define VERSION "V0.0.1"
17
18
19 typedef struct _DISK_DATA
20 {
21 ULONG HiddenSectors;
22 ULONG PartitionNumber;
23 UCHAR PartitionType;
24 BOOLEAN BootIndicator;
25 BOOLEAN DriveNotReady;
26 } DISK_DATA, *PDISK_DATA;
27
28
29 BOOLEAN STDCALL
30 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
31 PUNICODE_STRING RegistryPath,
32 PCLASS_INIT_DATA InitializationData,
33 PDEVICE_OBJECT PortDeviceObject,
34 ULONG PortNumber);
35
36 BOOLEAN STDCALL
37 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData);
38
39 NTSTATUS STDCALL
40 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
41 IN PIRP Irp);
42
43
44 static NTSTATUS
45 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
46 IN PUNICODE_STRING RegistryPath, /* what's this used for? */
47 IN PDEVICE_OBJECT PortDeviceObject,
48 IN ULONG PortNumber,
49 IN ULONG DiskNumber,
50 IN PIO_SCSI_CAPABILITIES Capabilities,
51 IN PSCSI_INQUIRY_DATA InquiryData,
52 IN PCLASS_INIT_DATA InitializationData);
53
54 NTSTATUS STDCALL
55 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
56 IN PIRP Irp);
57
58 NTSTATUS STDCALL
59 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
60 IN PIRP Irp);
61
62
63
64 /* FUNCTIONS ****************************************************************/
65
66 // DriverEntry
67 //
68 // DESCRIPTION:
69 // This function initializes the driver, locates and claims
70 // hardware resources, and creates various NT objects needed
71 // to process I/O requests.
72 //
73 // RUN LEVEL:
74 // PASSIVE_LEVEL
75 //
76 // ARGUMENTS:
77 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
78 // for this driver
79 // IN PUNICODE_STRING RegistryPath Name of registry driver service
80 // key
81 //
82 // RETURNS:
83 // NTSTATUS
84
85 NTSTATUS STDCALL
86 DriverEntry(IN PDRIVER_OBJECT DriverObject,
87 IN PUNICODE_STRING RegistryPath)
88 {
89 CLASS_INIT_DATA InitData;
90
91 DbgPrint("Disk Class Driver %s\n",
92 VERSION);
93 DPRINT("RegistryPath '%wZ'\n",
94 RegistryPath);
95
96 RtlZeroMemory(&InitData,
97 sizeof(CLASS_INIT_DATA));
98
99 InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
100 InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA);
101 InitData.DeviceType = FILE_DEVICE_DISK;
102 InitData.DeviceCharacteristics = 0;
103
104 InitData.ClassError = NULL; // DiskClassProcessError;
105 InitData.ClassReadWriteVerification = DiskClassCheckReadWrite;
106 InitData.ClassFindDeviceCallBack = DiskClassCheckDevice;
107 InitData.ClassFindDevices = DiskClassFindDevices;
108 InitData.ClassDeviceControl = DiskClassDeviceControl;
109 InitData.ClassShutdownFlush = DiskClassShutdownFlush;
110 InitData.ClassCreateClose = NULL;
111 InitData.ClassStartIo = NULL;
112
113 return(ScsiClassInitialize(DriverObject,
114 RegistryPath,
115 &InitData));
116 }
117
118
119 /**********************************************************************
120 * NAME EXPORTED
121 * DiskClassFindDevices
122 *
123 * DESCRIPTION
124 * This function searches for device that are attached to the
125 * given scsi port.
126 *
127 * RUN LEVEL
128 * PASSIVE_LEVEL
129 *
130 * ARGUMENTS
131 * DriverObject
132 * System allocated Driver Object for this driver
133 *
134 * RegistryPath
135 * Name of registry driver service key
136 *
137 * InitializationData
138 * Pointer to the main initialization data
139 *
140 * PortDeviceObject
141 * Pointer to the port Device Object
142 *
143 * PortNumber
144 * Port number
145 *
146 * RETURN VALUE
147 * TRUE: At least one disk drive was found
148 * FALSE: No disk drive found
149 */
150
151 BOOLEAN STDCALL
152 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
153 PUNICODE_STRING RegistryPath,
154 PCLASS_INIT_DATA InitializationData,
155 PDEVICE_OBJECT PortDeviceObject,
156 ULONG PortNumber)
157 {
158 PCONFIGURATION_INFORMATION ConfigInfo;
159 PIO_SCSI_CAPABILITIES PortCapabilities;
160 PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
161 PSCSI_INQUIRY_DATA UnitInfo;
162 PINQUIRYDATA InquiryData;
163 PCHAR Buffer;
164 ULONG Bus;
165 ULONG DeviceCount;
166 BOOLEAN FoundDevice;
167 NTSTATUS Status;
168
169 DPRINT("DiskClassFindDevices() called.\n");
170
171 /* Get port capabilities */
172 Status = ScsiClassGetCapabilities(PortDeviceObject,
173 &PortCapabilities);
174 if (!NT_SUCCESS(Status))
175 {
176 DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status);
177 return(FALSE);
178 }
179
180 DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength);
181
182 /* Get inquiry data */
183 Status = ScsiClassGetInquiryData(PortDeviceObject,
184 (PSCSI_ADAPTER_BUS_INFO *)&Buffer);
185 if (!NT_SUCCESS(Status))
186 {
187 DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status);
188 return(FALSE);
189 }
190
191 /* Check whether there are unclaimed devices */
192 AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
193 DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData,
194 AdapterBusInfo);
195 if (DeviceCount == 0)
196 {
197 DPRINT1("No unclaimed devices!\n");
198 return(FALSE);
199 }
200
201 DPRINT1("Found %lu unclaimed devices!\n", DeviceCount);
202
203 ConfigInfo = IoGetConfigurationInformation();
204
205 /* Search each bus of this adapter */
206 for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++)
207 {
208 DPRINT("Searching bus %lu\n", Bus);
209
210 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset);
211
212 while (AdapterBusInfo->BusData[Bus].InquiryDataOffset)
213 {
214 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
215
216 if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
217 (InquiryData->DeviceType == OPTICAL_DEVICE)) &&
218 (InquiryData->DeviceTypeQualifier == 0) &&
219 (UnitInfo->DeviceClaimed == FALSE))
220 {
221 DPRINT1("Vendor: '%.24s'\n",
222 InquiryData->VendorId);
223
224 /* Create device objects for disk */
225 Status = DiskClassCreateDeviceObject(DriverObject,
226 RegistryPath,
227 PortDeviceObject,
228 PortNumber,
229 ConfigInfo->DiskCount,
230 PortCapabilities,
231 UnitInfo,
232 InitializationData);
233 if (NT_SUCCESS(Status))
234 {
235 ConfigInfo->DiskCount++;
236 FoundDevice = TRUE;
237 }
238 }
239
240 if (UnitInfo->NextInquiryDataOffset == 0)
241 break;
242
243 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset);
244 }
245 }
246
247 ExFreePool(Buffer);
248 ExFreePool(PortCapabilities);
249
250 DPRINT("DiskClassFindDevices() done\n");
251
252 return(FoundDevice);
253 }
254
255
256 /**********************************************************************
257 * NAME EXPORTED
258 * DiskClassCheckDevice
259 *
260 * DESCRIPTION
261 * This function checks the InquiryData for the correct device
262 * type and qualifier.
263 *
264 * RUN LEVEL
265 * PASSIVE_LEVEL
266 *
267 * ARGUMENTS
268 * InquiryData
269 * Pointer to the inquiry data for the device in question.
270 *
271 * RETURN VALUE
272 * TRUE: A disk device was found.
273 * FALSE: Otherwise.
274 */
275
276 BOOLEAN STDCALL
277 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData)
278 {
279 return((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE ||
280 InquiryData->DeviceType == OPTICAL_DEVICE) &&
281 InquiryData->DeviceTypeQualifier == 0);
282 }
283
284
285 NTSTATUS STDCALL
286 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
287 IN PIRP Irp)
288 {
289 DPRINT("DiskClassCheckReadWrite() called\n");
290
291 return(STATUS_SUCCESS);
292 }
293
294
295 // DiskClassCreateDeviceObject
296 //
297 // DESCRIPTION:
298 // Create the raw device and any partition devices on this drive
299 //
300 // RUN LEVEL:
301 // PASSIVE_LEVEL
302 //
303 // ARGUMENTS:
304 // IN PDRIVER_OBJECT DriverObject The system created driver object
305 // IN PCONTROLLER_OBJECT ControllerObject
306 // IN PIDE_CONTROLLER_EXTENSION ControllerExtension
307 // The IDE controller extension for
308 // this device
309 // IN int DriveIdx The index of the drive on this
310 // controller
311 // IN int HarddiskIdx The NT device number for this
312 // drive
313 //
314 // RETURNS:
315 // TRUE Drive exists and devices were created
316 // FALSE no devices were created for this device
317 //
318
319 static NTSTATUS
320 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
321 IN PUNICODE_STRING RegistryPath, /* what's this used for? */
322 IN PDEVICE_OBJECT PortDeviceObject,
323 IN ULONG PortNumber,
324 IN ULONG DiskNumber,
325 IN PIO_SCSI_CAPABILITIES Capabilities,
326 IN PSCSI_INQUIRY_DATA InquiryData,
327 IN PCLASS_INIT_DATA InitializationData)
328 {
329 OBJECT_ATTRIBUTES ObjectAttributes;
330 UNICODE_STRING UnicodeDeviceDirName;
331 WCHAR NameBuffer[80];
332 CHAR NameBuffer2[80];
333 PDEVICE_OBJECT DiskDeviceObject;
334 PDEVICE_OBJECT PartitionDeviceObject;
335 PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */
336 PDEVICE_EXTENSION PartitionDeviceExtension; /* defined in class2.h */
337 PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
338 HANDLE Handle;
339 PPARTITION_INFORMATION PartitionEntry;
340 PDISK_DATA DiskData;
341 ULONG PartitionNumber;
342 NTSTATUS Status;
343
344 WCHAR ArcNameBuffer[120];
345 UNICODE_STRING ArcName;
346 ANSI_STRING DeviceNameA;
347 UNICODE_STRING DeviceName;
348
349 DPRINT1("DiskClassCreateDeviceObject() called\n");
350
351 /* Create the harddisk device directory */
352 swprintf(NameBuffer,
353 L"\\Device\\Harddisk%lu",
354 DiskNumber);
355 RtlInitUnicodeString(&UnicodeDeviceDirName,
356 NameBuffer);
357 InitializeObjectAttributes(&ObjectAttributes,
358 &UnicodeDeviceDirName,
359 0,
360 NULL,
361 NULL);
362 Status = ZwCreateDirectoryObject(&Handle,
363 0,
364 &ObjectAttributes);
365 if (!NT_SUCCESS(Status))
366 {
367 DbgPrint("Could not create device dir object\n");
368 return(Status);
369 }
370
371 /* Claim the disk device */
372 Status = ScsiClassClaimDevice(PortDeviceObject,
373 InquiryData,
374 FALSE,
375 &PortDeviceObject);
376 if (!NT_SUCCESS(Status))
377 {
378 DbgPrint("Could not claim disk device\n");
379
380 ZwMakeTemporaryObject(Handle);
381 ZwClose(Handle);
382
383 return(Status);
384 }
385
386 /* Create disk device (Partition 0) */
387 sprintf(NameBuffer2,
388 "\\Device\\Harddisk%lu\\Partition0",
389 DiskNumber);
390
391 Status = ScsiClassCreateDeviceObject(DriverObject,
392 NameBuffer2,
393 NULL,
394 &DiskDeviceObject,
395 InitializationData);
396 if (!NT_SUCCESS(Status))
397 {
398 DPRINT1("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status);
399
400 /* Release (unclaim) the disk */
401 ScsiClassClaimDevice(PortDeviceObject,
402 InquiryData,
403 TRUE,
404 NULL);
405
406 /* Delete the harddisk device directory */
407 ZwMakeTemporaryObject(Handle);
408 ZwClose(Handle);
409
410 return(Status);
411 }
412
413 DiskDeviceObject->Flags |= DO_DIRECT_IO;
414 if (((PINQUIRYDATA)InquiryData->InquiryData)->RemovableMedia)
415 {
416 DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
417 }
418 DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;
419
420 if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement)
421 {
422 DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
423 }
424
425 DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
426 DiskDeviceExtension->LockCount = 0;
427 DiskDeviceExtension->DeviceNumber = DiskNumber;
428 DiskDeviceExtension->PortDeviceObject = PortDeviceObject;
429
430 /* FIXME: Not yet! Will cause pointer corruption! */
431 // DiskDeviceExtension->PortCapabilities = PortCapabilities;
432
433 DiskDeviceExtension->StartingOffset.QuadPart = 0;
434 DiskDeviceExtension->PortNumber = (UCHAR)PortNumber;
435 DiskDeviceExtension->PathId = InquiryData->PathId;
436 DiskDeviceExtension->TargetId = InquiryData->TargetId;
437 DiskDeviceExtension->Lun = InquiryData->Lun;
438
439 /* zero-out disk data */
440 DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);
441 RtlZeroMemory(DiskData,
442 sizeof(DISK_DATA));
443
444 /* Get disk geometry */
445 DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
446 sizeof(DISK_GEOMETRY));
447 if (DiskDeviceExtension->DiskGeometry == NULL)
448 {
449 DPRINT1("Failed to allocate geometry buffer!\n");
450
451 IoDeleteDevice(DiskDeviceObject);
452
453 /* Release (unclaim) the disk */
454 ScsiClassClaimDevice(PortDeviceObject,
455 InquiryData,
456 TRUE,
457 NULL);
458
459 /* Delete the harddisk device directory */
460 ZwMakeTemporaryObject(Handle);
461 ZwClose(Handle);
462
463 return(STATUS_INSUFFICIENT_RESOURCES);
464 }
465
466 /* Read the drive's capacity */
467 Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
468 if (!NT_SUCCESS(Status) &&
469 (DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0)
470 {
471 DPRINT1("Failed to retrieve drive capacity!\n");
472 return(STATUS_SUCCESS);
473 }
474 else
475 {
476 /* Clear the verify flag for non-removable media drives. */
477 DiskDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
478 }
479
480 DPRINT1("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector);
481
482 /* assign arc name */
483 RtlInitAnsiString(&DeviceNameA,
484 NameBuffer2);
485 RtlAnsiStringToUnicodeString(&DeviceName,
486 &DeviceNameA,
487 TRUE);
488 swprintf(ArcNameBuffer,
489 L"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
490 DiskNumber);
491 RtlInitUnicodeString(&ArcName,
492 ArcNameBuffer);
493 DPRINT1("ArcNameBuffer '%S'\n", ArcNameBuffer);
494 DPRINT1("%wZ ==> %wZ\n", &ArcName, &DeviceName);
495 Status = IoAssignArcName(&ArcName,
496 &DeviceName);
497 RtlFreeUnicodeString(&DeviceName);
498
499 if (!NT_SUCCESS(Status))
500 {
501 DbgPrint("IoAssignArcName (%wZ) failed (Status %x)\n", &ArcName, Status);
502 KeBugCheck(0);
503 }
504
505
506 /* Read partition table */
507 Status = IoReadPartitionTable(DiskDeviceObject,
508 DiskDeviceExtension->DiskGeometry->BytesPerSector,
509 TRUE,
510 &PartitionList);
511
512 DPRINT1("IoReadPartitionTable(): Status: %lx\n", Status);
513
514 if ((!NT_SUCCESS(Status) || PartitionList->PartitionCount == 0) &&
515 DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
516 {
517 if (!NT_SUCCESS(Status))
518 {
519 /* Drive is not ready. */
520 DPRINT1("Drive not ready\n");
521 DiskData->DriveNotReady = TRUE;
522 }
523 else
524 {
525 ExFreePool(PartitionList);
526 }
527
528 /* Allocate a partition list for a single entry. */
529 PartitionList = ExAllocatePool(NonPagedPool,
530 sizeof(DRIVE_LAYOUT_INFORMATION));
531 if (PartitionList != NULL)
532 {
533 RtlZeroMemory(PartitionList,
534 sizeof(DRIVE_LAYOUT_INFORMATION));
535 PartitionList->PartitionCount = 1;
536
537 Status = STATUS_SUCCESS;
538 }
539 }
540
541 if (NT_SUCCESS(Status))
542 {
543 DPRINT1("Read partition table!\n");
544
545 DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount);
546
547 for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
548 {
549 PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];
550
551 DPRINT1("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
552 PartitionNumber,
553 PartitionEntry->PartitionNumber,
554 PartitionEntry->BootIndicator,
555 PartitionEntry->PartitionType,
556 PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
557 PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
558
559 /* Create partition device (Partition 0) */
560 sprintf(NameBuffer2,
561 "\\Device\\Harddisk%lu\\Partition%lu",
562 DiskNumber,
563 PartitionNumber + 1);
564
565 Status = ScsiClassCreateDeviceObject(DriverObject,
566 NameBuffer2,
567 DiskDeviceObject,
568 &PartitionDeviceObject,
569 InitializationData);
570 DPRINT1("ScsiClassCreateDeviceObject(): Status %x\n", Status);
571 if (NT_SUCCESS(Status))
572 {
573 PartitionDeviceObject->Flags = DiskDeviceObject->Flags;
574 PartitionDeviceObject->Characteristics = DiskDeviceObject->Characteristics;
575 PartitionDeviceObject->StackSize = DiskDeviceObject->StackSize;
576 PartitionDeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
577
578 PartitionDeviceExtension = PartitionDeviceObject->DeviceExtension;
579 PartitionDeviceExtension->LockCount = 0;
580 PartitionDeviceExtension->DeviceNumber = DiskNumber;
581 PartitionDeviceExtension->PortDeviceObject = PortDeviceObject;
582 PartitionDeviceExtension->DiskGeometry = DiskDeviceExtension->DiskGeometry;
583
584 /* FIXME: Not yet! Will cause pointer corruption! */
585 // PartitionDeviceExtension->PortCapabilities = PortCapabilities;
586
587 PartitionDeviceExtension->StartingOffset.QuadPart =
588 PartitionEntry->StartingOffset.QuadPart;
589 PartitionDeviceExtension->PartitionLength.QuadPart =
590 PartitionEntry->PartitionLength.QuadPart;
591 PartitionDeviceExtension->PortNumber = (UCHAR)PortNumber;
592 PartitionDeviceExtension->PathId = InquiryData->PathId;
593 PartitionDeviceExtension->TargetId = InquiryData->TargetId;
594 PartitionDeviceExtension->Lun = InquiryData->Lun;
595
596 DiskData = (PDISK_DATA)(PartitionDeviceExtension + 1);
597 DiskData->PartitionType = PartitionEntry->PartitionType;
598 DiskData->PartitionNumber = PartitionNumber + 1;
599 DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
600 DiskData->BootIndicator = PartitionEntry->BootIndicator;
601 DiskData->DriveNotReady = FALSE;
602
603
604 /* assign arc name */
605 RtlInitAnsiString(&DeviceNameA,
606 NameBuffer2);
607 RtlAnsiStringToUnicodeString(&DeviceName,
608 &DeviceNameA,
609 TRUE);
610 swprintf(ArcNameBuffer,
611 L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)",
612 DiskNumber,
613 PartitionNumber + 1);
614 RtlInitUnicodeString(&ArcName,
615 ArcNameBuffer);
616 DPRINT1("ArcNameBuffer '%S'\n", ArcNameBuffer);
617 DPRINT1("%wZ ==> %wZ\n", &ArcName, &DeviceName);
618 Status = IoAssignArcName(&ArcName,
619 &DeviceName);
620 RtlFreeUnicodeString(&DeviceName);
621
622 if (!NT_SUCCESS(Status))
623 {
624 DbgPrint("IoAssignArcName (%wZ) failed (Status %x)\n", &ArcName, Status);
625 KeBugCheck(0);
626 }
627
628 }
629 else
630 {
631 DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status);
632
633 break;
634 }
635 }
636
637
638 }
639
640 if (PartitionList != NULL)
641 ExFreePool(PartitionList);
642
643 DPRINT1("DiskClassCreateDeviceObjects() done\n");
644
645 return(STATUS_SUCCESS);
646 }
647
648
649
650
651
652 // DiskClassDeviceControl
653 //
654 // DESCRIPTION:
655 // Answer requests for device control calls
656 //
657 // RUN LEVEL:
658 // PASSIVE_LEVEL
659 //
660 // ARGUMENTS:
661 // Standard dispatch arguments
662 //
663 // RETURNS:
664 // NTSTATUS
665 //
666
667 NTSTATUS STDCALL
668 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
669 IN PIRP Irp)
670 {
671 PDEVICE_EXTENSION DeviceExtension;
672 PIO_STACK_LOCATION IrpStack;
673 ULONG ControlCode, InputLength, OutputLength;
674 PDISK_DATA DiskData;
675 NTSTATUS Status;
676
677 DPRINT1("DiskClassDeviceControl() called!\n");
678
679 Status = STATUS_SUCCESS;
680 IrpStack = IoGetCurrentIrpStackLocation(Irp);
681 ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
682 InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
683 OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
684 DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
685 DiskData = (PDISK_DATA)(DeviceExtension + 1);
686
687 /* A huge switch statement in a Windows program?! who would have thought? */
688 switch (ControlCode)
689 {
690 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
691 DPRINT1("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
692 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
693 {
694 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
695 Irp->IoStatus.Information = 0;
696 }
697 else if (DeviceExtension->DiskGeometry == NULL)
698 {
699 DPRINT1("No disk geometry available!\n");
700 Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
701 Irp->IoStatus.Information = 0;
702 }
703 else
704 {
705 PDISK_GEOMETRY Geometry;
706
707 Geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
708 RtlMoveMemory(Geometry,
709 DeviceExtension->DiskGeometry,
710 sizeof(DISK_GEOMETRY));
711
712 #if 0
713
714 RtlCopyMemory(DiskData->Geometry,
715 DiskDeviceExtension->DiskGeometry,
716 sizeof(DISK_GEOMETRY));
717 Geometry->MediaType = FixedMedia;
718 // FIXME: should report for RawDevice even on partition
719 Geometry->Cylinders.QuadPart = DeviceExtension->Size /
720 DeviceExtension->SectorsPerLogCyl;
721 Geometry->TracksPerCylinder = DeviceExtension->SectorsPerLogTrk /
722 DeviceExtension->SectorsPerLogCyl;
723 Geometry->SectorsPerTrack = DeviceExtension->SectorsPerLogTrk;
724 Geometry->BytesPerSector = DeviceExtension->BytesPerSector;
725 #endif
726 Irp->IoStatus.Status = STATUS_SUCCESS;
727 Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
728 }
729 break;
730
731 case IOCTL_DISK_GET_PARTITION_INFO:
732 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO\n");
733 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
734 sizeof(PARTITION_INFORMATION))
735 {
736 Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH;
737 Irp->IoStatus.Information = 0;
738 }
739 else if (DiskData->PartitionNumber == 0)
740 {
741 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
742 Irp->IoStatus.Information = 0;
743 }
744 else
745 {
746 PPARTITION_INFORMATION PartitionInfo;
747
748 PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
749
750 PartitionInfo->PartitionType = DiskData->PartitionType;
751 PartitionInfo->StartingOffset = DeviceExtension->StartingOffset;
752 PartitionInfo->PartitionLength = DeviceExtension->PartitionLength;
753 PartitionInfo->HiddenSectors = DiskData->HiddenSectors;
754 PartitionInfo->PartitionNumber = DiskData->PartitionNumber;
755 PartitionInfo->BootIndicator = DiskData->BootIndicator;
756 PartitionInfo->RewritePartition = FALSE;
757 PartitionInfo->RecognizedPartition =
758 IsRecognizedPartition(DiskData->PartitionType);
759
760 Irp->IoStatus.Status = STATUS_SUCCESS;
761 Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
762 }
763 break;
764
765 case IOCTL_DISK_SET_PARTITION_INFO:
766 case IOCTL_DISK_GET_DRIVE_LAYOUT:
767 case IOCTL_DISK_SET_DRIVE_LAYOUT:
768 case IOCTL_DISK_VERIFY:
769 case IOCTL_DISK_FORMAT_TRACKS:
770 case IOCTL_DISK_PERFORMANCE:
771 case IOCTL_DISK_IS_WRITABLE:
772 case IOCTL_DISK_LOGGING:
773 case IOCTL_DISK_FORMAT_TRACKS_EX:
774 case IOCTL_DISK_HISTOGRAM_STRUCTURE:
775 case IOCTL_DISK_HISTOGRAM_DATA:
776 case IOCTL_DISK_HISTOGRAM_RESET:
777 case IOCTL_DISK_REQUEST_STRUCTURE:
778 case IOCTL_DISK_REQUEST_DATA:
779
780 /* If we get here, something went wrong. inform the requestor */
781 default:
782 DPRINT1("Unhandled control code: %lx\n", ControlCode);
783 Status = STATUS_INVALID_DEVICE_REQUEST;
784 Irp->IoStatus.Status = Status;
785 Irp->IoStatus.Information = 0;
786 break;
787 }
788
789 IoCompleteRequest(Irp,
790 IO_NO_INCREMENT);
791
792 return(Status);
793 }
794
795
796 // DiskClassShutdownFlush
797 //
798 // DESCRIPTION:
799 // Answer requests for shutdown and flush calls
800 //
801 // RUN LEVEL:
802 // PASSIVE_LEVEL
803 //
804 // ARGUMENTS:
805 // Standard dispatch arguments
806 //
807 // RETURNS:
808 // NTSTATUS
809 //
810
811 NTSTATUS STDCALL
812 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
813 IN PIRP Irp)
814 {
815 DPRINT("DiskClassShutdownFlush() called!\n");
816
817 Irp->IoStatus.Status = STATUS_SUCCESS;
818 Irp->IoStatus.Information = 0;
819 IoCompleteRequest(Irp, IO_NO_INCREMENT);
820
821 return(STATUS_SUCCESS);
822 }
823
824
825 /* EOF */