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