Detect and print BIOS disk geometry.
[reactos.git] / reactos / drivers / storage / disk / disk.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: disk.c,v 1.26 2003/04/27 18:10:38 ekohl Exp $
20 *
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)
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <ddk/scsi.h>
32 #include <ddk/class2.h>
33 #include <ddk/ntddscsi.h>
34
35 #define NDEBUG
36 #include <debug.h>
37
38 #define VERSION "0.0.1"
39
40
41 typedef struct _DISK_DATA
42 {
43 PDEVICE_EXTENSION NextPartition;
44 ULONG HiddenSectors;
45 ULONG PartitionNumber;
46 ULONG PartitionOrdinal;
47 UCHAR PartitionType;
48 BOOLEAN BootIndicator;
49 BOOLEAN DriveNotReady;
50 } DISK_DATA, *PDISK_DATA;
51
52
53 BOOLEAN STDCALL
54 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
55 PUNICODE_STRING RegistryPath,
56 PCLASS_INIT_DATA InitializationData,
57 PDEVICE_OBJECT PortDeviceObject,
58 ULONG PortNumber);
59
60 BOOLEAN STDCALL
61 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData);
62
63 NTSTATUS STDCALL
64 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
65 IN PIRP Irp);
66
67
68 static NTSTATUS
69 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
70 IN PUNICODE_STRING RegistryPath, /* what's this used for? */
71 IN PDEVICE_OBJECT PortDeviceObject,
72 IN ULONG PortNumber,
73 IN ULONG DiskNumber,
74 IN PIO_SCSI_CAPABILITIES Capabilities,
75 IN PSCSI_INQUIRY_DATA InquiryData,
76 IN PCLASS_INIT_DATA InitializationData);
77
78 NTSTATUS STDCALL
79 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
80 IN PIRP Irp);
81
82 NTSTATUS STDCALL
83 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
84 IN PIRP Irp);
85
86 static VOID
87 DiskClassUpdatePartitionDeviceObjects (IN PDEVICE_OBJECT DeviceObject,
88 IN PIRP Irp);
89
90 static VOID
91 ScsiDiskUpdateFixedDiskGeometry(IN PDEVICE_EXTENSION DeviceExtension);
92
93
94 /* FUNCTIONS ****************************************************************/
95
96 /**********************************************************************
97 * NAME EXPORTED
98 * DriverEntry
99 *
100 * DESCRIPTION
101 * This function initializes the driver, locates and claims
102 * hardware resources, and creates various NT objects needed
103 * to process I/O requests.
104 *
105 * RUN LEVEL
106 * PASSIVE_LEVEL
107 *
108 * ARGUMENTS
109 * DriverObject
110 * System allocated Driver Object for this driver
111 *
112 * RegistryPath
113 * Name of registry driver service key
114 *
115 * RETURN VALUE
116 * Status
117 */
118
119 NTSTATUS STDCALL
120 DriverEntry(IN PDRIVER_OBJECT DriverObject,
121 IN PUNICODE_STRING RegistryPath)
122 {
123 CLASS_INIT_DATA InitData;
124
125 DPRINT("Disk Class Driver %s\n",
126 VERSION);
127 DPRINT("RegistryPath '%wZ'\n",
128 RegistryPath);
129
130 RtlZeroMemory(&InitData,
131 sizeof(CLASS_INIT_DATA));
132
133 InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
134 InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA);
135 InitData.DeviceType = FILE_DEVICE_DISK;
136 InitData.DeviceCharacteristics = 0;
137
138 InitData.ClassError = NULL; // DiskClassProcessError;
139 InitData.ClassReadWriteVerification = DiskClassCheckReadWrite;
140 InitData.ClassFindDeviceCallBack = DiskClassCheckDevice;
141 InitData.ClassFindDevices = DiskClassFindDevices;
142 InitData.ClassDeviceControl = DiskClassDeviceControl;
143 InitData.ClassShutdownFlush = DiskClassShutdownFlush;
144 InitData.ClassCreateClose = NULL;
145 InitData.ClassStartIo = NULL;
146
147 return(ScsiClassInitialize(DriverObject,
148 RegistryPath,
149 &InitData));
150 }
151
152
153 /**********************************************************************
154 * NAME EXPORTED
155 * DiskClassFindDevices
156 *
157 * DESCRIPTION
158 * This function searches for device that are attached to the
159 * given scsi port.
160 *
161 * RUN LEVEL
162 * PASSIVE_LEVEL
163 *
164 * ARGUMENTS
165 * DriverObject
166 * System allocated Driver Object for this driver
167 *
168 * RegistryPath
169 * Name of registry driver service key
170 *
171 * InitializationData
172 * Pointer to the main initialization data
173 *
174 * PortDeviceObject
175 * Pointer to the port Device Object
176 *
177 * PortNumber
178 * Port number
179 *
180 * RETURN VALUE
181 * TRUE: At least one disk drive was found
182 * FALSE: No disk drive found
183 */
184
185 BOOLEAN STDCALL
186 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
187 PUNICODE_STRING RegistryPath,
188 PCLASS_INIT_DATA InitializationData,
189 PDEVICE_OBJECT PortDeviceObject,
190 ULONG PortNumber)
191 {
192 PCONFIGURATION_INFORMATION ConfigInfo;
193 PIO_SCSI_CAPABILITIES PortCapabilities;
194 PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
195 PSCSI_INQUIRY_DATA UnitInfo;
196 PINQUIRYDATA InquiryData;
197 PCHAR Buffer;
198 ULONG Bus;
199 ULONG DeviceCount;
200 BOOLEAN FoundDevice;
201 NTSTATUS Status;
202
203 DPRINT("DiskClassFindDevices() called.\n");
204
205 /* Get port capabilities */
206 Status = ScsiClassGetCapabilities(PortDeviceObject,
207 &PortCapabilities);
208 if (!NT_SUCCESS(Status))
209 {
210 DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status);
211 return(FALSE);
212 }
213
214 DPRINT("PortCapabilities: %p\n", PortCapabilities);
215 DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength);
216 DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities->MaximumPhysicalPages);
217
218 /* Get inquiry data */
219 Status = ScsiClassGetInquiryData(PortDeviceObject,
220 (PSCSI_ADAPTER_BUS_INFO *)&Buffer);
221 if (!NT_SUCCESS(Status))
222 {
223 DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status);
224 return(FALSE);
225 }
226
227 /* Check whether there are unclaimed devices */
228 AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
229 DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData,
230 AdapterBusInfo);
231 if (DeviceCount == 0)
232 {
233 DPRINT("No unclaimed devices!\n");
234 return(FALSE);
235 }
236
237 DPRINT("Found %lu unclaimed devices!\n", DeviceCount);
238
239 ConfigInfo = IoGetConfigurationInformation();
240
241 /* Search each bus of this adapter */
242 for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++)
243 {
244 DPRINT("Searching bus %lu\n", Bus);
245
246 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset);
247
248 while (AdapterBusInfo->BusData[Bus].InquiryDataOffset)
249 {
250 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
251
252 if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
253 (InquiryData->DeviceType == OPTICAL_DEVICE)) &&
254 (InquiryData->DeviceTypeQualifier == 0) &&
255 (UnitInfo->DeviceClaimed == FALSE))
256 {
257 DPRINT("Vendor: '%.24s'\n",
258 InquiryData->VendorId);
259
260 /* Create device objects for disk */
261 Status = DiskClassCreateDeviceObject(DriverObject,
262 RegistryPath,
263 PortDeviceObject,
264 PortNumber,
265 ConfigInfo->DiskCount,
266 PortCapabilities,
267 UnitInfo,
268 InitializationData);
269 if (NT_SUCCESS(Status))
270 {
271 ConfigInfo->DiskCount++;
272 FoundDevice = TRUE;
273 }
274 }
275
276 if (UnitInfo->NextInquiryDataOffset == 0)
277 break;
278
279 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset);
280 }
281 }
282
283 ExFreePool(Buffer);
284
285 DPRINT("DiskClassFindDevices() done\n");
286
287 return(FoundDevice);
288 }
289
290
291 /**********************************************************************
292 * NAME EXPORTED
293 * DiskClassCheckDevice
294 *
295 * DESCRIPTION
296 * This function checks the InquiryData for the correct device
297 * type and qualifier.
298 *
299 * RUN LEVEL
300 * PASSIVE_LEVEL
301 *
302 * ARGUMENTS
303 * InquiryData
304 * Pointer to the inquiry data for the device in question.
305 *
306 * RETURN VALUE
307 * TRUE: A disk device was found.
308 * FALSE: Otherwise.
309 */
310
311 BOOLEAN STDCALL
312 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData)
313 {
314 return((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE ||
315 InquiryData->DeviceType == OPTICAL_DEVICE) &&
316 InquiryData->DeviceTypeQualifier == 0);
317 }
318
319
320 /**********************************************************************
321 * NAME EXPORTED
322 * DiskClassCheckReadWrite
323 *
324 * DESCRIPTION
325 * This function checks the given IRP for correct data.
326 *
327 * RUN LEVEL
328 * PASSIVE_LEVEL
329 *
330 * ARGUMENTS
331 * DeviceObject
332 * Pointer to the device.
333 *
334 * Irp
335 * Irp to check.
336 *
337 * RETURN VALUE
338 * STATUS_SUCCESS: The IRP matches the requirements of the given device.
339 * Others: Failure.
340 */
341
342 NTSTATUS STDCALL
343 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
344 IN PIRP Irp)
345 {
346 PDEVICE_EXTENSION DeviceExtension;
347 PDISK_DATA DiskData;
348
349 DPRINT("DiskClassCheckReadWrite() called\n");
350
351 DeviceExtension = DeviceObject->DeviceExtension;
352 DiskData = (PDISK_DATA)(DeviceExtension + 1);
353
354 if (DiskData->DriveNotReady == TRUE)
355 {
356 Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
357 IoSetHardErrorOrVerifyDevice(Irp,
358 DeviceObject);
359 return(STATUS_INVALID_PARAMETER);
360 }
361
362 return(STATUS_SUCCESS);
363 }
364
365
366 /**********************************************************************
367 * NAME INTERNAL
368 * DiskClassCreateDeviceObject
369 *
370 * DESCRIPTION
371 * Create the raw device and any partition devices on this drive
372 *
373 * RUN LEVEL
374 * PASSIVE_LEVEL
375 *
376 * ARGUMENTS
377 * DriverObject
378 * The system created driver object
379 * RegistryPath
380 * PortDeviceObject
381 * PortNumber
382 * DiskNumber
383 * Capabilities
384 * InquiryData
385 * InitialzationData
386 *
387 * RETURN VALUE
388 * STATUS_SUCCESS: Device objects for disk and partitions were created.
389 * Others: Failure.
390 */
391
392 static NTSTATUS
393 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
394 IN PUNICODE_STRING RegistryPath, /* what's this used for? */
395 IN PDEVICE_OBJECT PortDeviceObject,
396 IN ULONG PortNumber,
397 IN ULONG DiskNumber,
398 IN PIO_SCSI_CAPABILITIES Capabilities,
399 IN PSCSI_INQUIRY_DATA InquiryData,
400 IN PCLASS_INIT_DATA InitializationData)
401 {
402 OBJECT_ATTRIBUTES ObjectAttributes;
403 UNICODE_STRING UnicodeDeviceDirName;
404 WCHAR NameBuffer[80];
405 CHAR NameBuffer2[80];
406 PDEVICE_OBJECT DiskDeviceObject;
407 PDEVICE_OBJECT PartitionDeviceObject;
408 PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */
409 PDEVICE_EXTENSION PartitionDeviceExtension; /* defined in class2.h */
410 PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
411 HANDLE Handle;
412 PPARTITION_INFORMATION PartitionEntry;
413 PDISK_DATA DiskData;
414 ULONG PartitionNumber;
415 PVOID MbrBuffer;
416 NTSTATUS Status;
417
418 DPRINT("DiskClassCreateDeviceObject() called\n");
419
420 /* Create the harddisk device directory */
421 swprintf(NameBuffer,
422 L"\\Device\\Harddisk%lu",
423 DiskNumber);
424 RtlInitUnicodeString(&UnicodeDeviceDirName,
425 NameBuffer);
426 InitializeObjectAttributes(&ObjectAttributes,
427 &UnicodeDeviceDirName,
428 0,
429 NULL,
430 NULL);
431 Status = ZwCreateDirectoryObject(&Handle,
432 0,
433 &ObjectAttributes);
434 if (!NT_SUCCESS(Status))
435 {
436 DbgPrint("Could not create device dir object\n");
437 return(Status);
438 }
439
440 /* Claim the disk device */
441 Status = ScsiClassClaimDevice(PortDeviceObject,
442 InquiryData,
443 FALSE,
444 &PortDeviceObject);
445 if (!NT_SUCCESS(Status))
446 {
447 DbgPrint("Could not claim disk device\n");
448
449 ZwMakeTemporaryObject(Handle);
450 ZwClose(Handle);
451
452 return(Status);
453 }
454
455 /* Create disk device (Partition 0) */
456 sprintf(NameBuffer2,
457 "\\Device\\Harddisk%lu\\Partition0",
458 DiskNumber);
459
460 Status = ScsiClassCreateDeviceObject(DriverObject,
461 NameBuffer2,
462 NULL,
463 &DiskDeviceObject,
464 InitializationData);
465 if (!NT_SUCCESS(Status))
466 {
467 DPRINT("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status);
468
469 /* Release (unclaim) the disk */
470 ScsiClassClaimDevice(PortDeviceObject,
471 InquiryData,
472 TRUE,
473 NULL);
474
475 /* Delete the harddisk device directory */
476 ZwMakeTemporaryObject(Handle);
477 ZwClose(Handle);
478
479 return(Status);
480 }
481
482 DiskDeviceObject->Flags |= DO_DIRECT_IO;
483 if (((PINQUIRYDATA)InquiryData->InquiryData)->RemovableMedia)
484 {
485 DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
486 }
487 DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;
488
489 if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement)
490 {
491 DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
492 }
493
494 DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
495 DiskDeviceExtension->LockCount = 0;
496 DiskDeviceExtension->DeviceNumber = DiskNumber;
497 DiskDeviceExtension->PortDeviceObject = PortDeviceObject;
498 DiskDeviceExtension->PhysicalDevice = DiskDeviceObject;
499 DiskDeviceExtension->PortCapabilities = Capabilities;
500 DiskDeviceExtension->StartingOffset.QuadPart = 0;
501 DiskDeviceExtension->PortNumber = (UCHAR)PortNumber;
502 DiskDeviceExtension->PathId = InquiryData->PathId;
503 DiskDeviceExtension->TargetId = InquiryData->TargetId;
504 DiskDeviceExtension->Lun = InquiryData->Lun;
505
506 /* Initialize the lookaside list for SRBs */
507 ScsiClassInitializeSrbLookasideList(DiskDeviceExtension,
508 4);
509
510 /* zero-out disk data */
511 DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);
512 RtlZeroMemory(DiskData,
513 sizeof(DISK_DATA));
514
515 /* Get disk geometry */
516 DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
517 sizeof(DISK_GEOMETRY));
518 if (DiskDeviceExtension->DiskGeometry == NULL)
519 {
520 DPRINT("Failed to allocate geometry buffer!\n");
521
522 ExDeleteNPagedLookasideList(&DiskDeviceExtension->SrbLookasideListHead);
523
524 IoDeleteDevice(DiskDeviceObject);
525
526 /* Release (unclaim) the disk */
527 ScsiClassClaimDevice(PortDeviceObject,
528 InquiryData,
529 TRUE,
530 NULL);
531
532 /* Delete the harddisk device directory */
533 ZwMakeTemporaryObject(Handle);
534 ZwClose(Handle);
535
536 return(STATUS_INSUFFICIENT_RESOURCES);
537 }
538
539 /* Read the drive's capacity */
540 Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
541 if (!NT_SUCCESS(Status) &&
542 (DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0)
543 {
544 DPRINT1("Failed to retrieve drive capacity!\n");
545 return(STATUS_SUCCESS);
546 }
547 else
548 {
549 /* Clear the verify flag for removable media drives. */
550 DiskDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
551 }
552
553 DPRINT("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector);
554
555 /* Check disk for presence of a disk manager */
556 HalExamineMBR(DiskDeviceObject,
557 DiskDeviceExtension->DiskGeometry->BytesPerSector,
558 0x54,
559 &MbrBuffer);
560 if (MbrBuffer != NULL)
561 {
562 /* Start disk at sector 63 if the Ontrack Disk Manager was found */
563 DPRINT("Found 'Ontrack Disk Manager'!\n");
564
565 DiskDeviceExtension->DMSkew = 63;
566 DiskDeviceExtension->DMByteSkew =
567 63 * DiskDeviceExtension->DiskGeometry->BytesPerSector;
568 DiskDeviceExtension->DMActive = TRUE;
569
570 ExFreePool(MbrBuffer);
571 MbrBuffer = NULL;
572 }
573
574 if ((DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
575 (DiskDeviceExtension->DiskGeometry->MediaType == RemovableMedia))
576 {
577 /* Allocate a partition list for a single entry. */
578 PartitionList = ExAllocatePool(NonPagedPool,
579 sizeof(DRIVE_LAYOUT_INFORMATION));
580 if (PartitionList != NULL)
581 {
582 RtlZeroMemory(PartitionList,
583 sizeof(DRIVE_LAYOUT_INFORMATION));
584 PartitionList->PartitionCount = 1;
585
586 DiskData->DriveNotReady = TRUE;
587 Status = STATUS_SUCCESS;
588 }
589 }
590 else
591 {
592 /* Read partition table */
593 Status = IoReadPartitionTable(DiskDeviceObject,
594 DiskDeviceExtension->DiskGeometry->BytesPerSector,
595 TRUE,
596 &PartitionList);
597
598 DPRINT("IoReadPartitionTable(): Status: %lx\n", Status);
599
600 if ((!NT_SUCCESS(Status) || PartitionList->PartitionCount == 0) &&
601 DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
602 {
603 if (!NT_SUCCESS(Status))
604 {
605 /* Drive is not ready. */
606 DPRINT("Drive not ready\n");
607 DiskData->DriveNotReady = TRUE;
608 }
609 else
610 {
611 ExFreePool(PartitionList);
612 }
613
614 /* Allocate a partition list for a single entry. */
615 PartitionList = ExAllocatePool(NonPagedPool,
616 sizeof(DRIVE_LAYOUT_INFORMATION));
617 if (PartitionList != NULL)
618 {
619 RtlZeroMemory(PartitionList,
620 sizeof(DRIVE_LAYOUT_INFORMATION));
621 PartitionList->PartitionCount = 1;
622
623 Status = STATUS_SUCCESS;
624 }
625 }
626 }
627
628 if (NT_SUCCESS(Status))
629 {
630 DPRINT("Read partition table!\n");
631
632 DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount);
633
634 ScsiDiskUpdateFixedDiskGeometry(DiskDeviceExtension);
635
636 for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
637 {
638 PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];
639
640 DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
641 PartitionNumber,
642 PartitionEntry->PartitionNumber,
643 PartitionEntry->BootIndicator,
644 PartitionEntry->PartitionType,
645 PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
646 PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
647
648 /* Create partition device object */
649 sprintf(NameBuffer2,
650 "\\Device\\Harddisk%lu\\Partition%lu",
651 DiskNumber,
652 PartitionNumber + 1);
653
654 Status = ScsiClassCreateDeviceObject(DriverObject,
655 NameBuffer2,
656 DiskDeviceObject,
657 &PartitionDeviceObject,
658 InitializationData);
659 DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status);
660 if (NT_SUCCESS(Status))
661 {
662 PartitionDeviceObject->Flags = DiskDeviceObject->Flags;
663 PartitionDeviceObject->Characteristics = DiskDeviceObject->Characteristics;
664 PartitionDeviceObject->StackSize = DiskDeviceObject->StackSize;
665 PartitionDeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
666
667 PartitionDeviceExtension = PartitionDeviceObject->DeviceExtension;
668 PartitionDeviceExtension->LockCount = 0;
669 PartitionDeviceExtension->DeviceNumber = DiskNumber;
670 PartitionDeviceExtension->PortDeviceObject = PortDeviceObject;
671 PartitionDeviceExtension->DiskGeometry = DiskDeviceExtension->DiskGeometry;
672 PartitionDeviceExtension->PhysicalDevice = DiskDeviceExtension->PhysicalDevice;
673 PartitionDeviceExtension->PortCapabilities = Capabilities;
674 PartitionDeviceExtension->StartingOffset.QuadPart =
675 PartitionEntry->StartingOffset.QuadPart;
676 PartitionDeviceExtension->PartitionLength.QuadPart =
677 PartitionEntry->PartitionLength.QuadPart;
678 PartitionDeviceExtension->DMSkew = DiskDeviceExtension->DMSkew;
679 PartitionDeviceExtension->DMByteSkew = DiskDeviceExtension->DMByteSkew;
680 PartitionDeviceExtension->DMActive = DiskDeviceExtension->DMActive;
681 PartitionDeviceExtension->PortNumber = (UCHAR)PortNumber;
682 PartitionDeviceExtension->PathId = InquiryData->PathId;
683 PartitionDeviceExtension->TargetId = InquiryData->TargetId;
684 PartitionDeviceExtension->Lun = InquiryData->Lun;
685 PartitionDeviceExtension->SectorShift = DiskDeviceExtension->SectorShift;
686
687 /* Initialize lookaside list for SRBs */
688 ScsiClassInitializeSrbLookasideList(PartitionDeviceExtension,
689 8);
690
691 /* Link current partition device extension to previous disk data */
692 DiskData->NextPartition = PartitionDeviceExtension;
693
694 /* Initialize current disk data */
695 DiskData = (PDISK_DATA)(PartitionDeviceExtension + 1);
696 DiskData->NextPartition = NULL;
697 DiskData->PartitionType = PartitionEntry->PartitionType;
698 DiskData->PartitionNumber = PartitionNumber + 1;
699 DiskData->PartitionOrdinal = PartitionNumber + 1;
700 DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
701 DiskData->BootIndicator = PartitionEntry->BootIndicator;
702 DiskData->DriveNotReady = FALSE;
703 }
704 else
705 {
706 DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status);
707
708 break;
709 }
710 }
711 }
712
713 if (PartitionList != NULL)
714 ExFreePool(PartitionList);
715
716 DPRINT("DiskClassCreateDeviceObjects() done\n");
717
718 return(STATUS_SUCCESS);
719 }
720
721
722 /**********************************************************************
723 * NAME EXPORTED
724 * DiskClassDeviceControl
725 *
726 * DESCRIPTION
727 * Answer requests for device control calls
728 *
729 * RUN LEVEL
730 * PASSIVE_LEVEL
731 *
732 * ARGUMENTS
733 * Standard dispatch arguments
734 *
735 * RETURNS
736 * Status
737 */
738
739 NTSTATUS STDCALL
740 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
741 IN PIRP Irp)
742 {
743 PDEVICE_EXTENSION DeviceExtension;
744 PIO_STACK_LOCATION IrpStack;
745 ULONG ControlCode, InputLength, OutputLength;
746 PDISK_DATA DiskData;
747 ULONG Information;
748 NTSTATUS Status;
749
750 DPRINT("DiskClassDeviceControl() called!\n");
751
752 Status = STATUS_INVALID_DEVICE_REQUEST;
753 Information = 0;
754 IrpStack = IoGetCurrentIrpStackLocation(Irp);
755 ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
756 InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
757 OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
758 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
759 DiskData = (PDISK_DATA)(DeviceExtension + 1);
760
761 switch (ControlCode)
762 {
763 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
764 DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
765 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
766 {
767 Status = STATUS_INVALID_PARAMETER;
768 }
769 else
770 {
771 PDISK_GEOMETRY Geometry;
772
773 if (DeviceExtension->DiskGeometry == NULL)
774 {
775 DPRINT("No disk geometry available!\n");
776 DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
777 sizeof(DISK_GEOMETRY));
778 }
779 Status = ScsiClassReadDriveCapacity(DeviceObject);
780 DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status);
781 if (NT_SUCCESS(Status))
782 {
783 Geometry = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer;
784 RtlMoveMemory(Geometry,
785 DeviceExtension->DiskGeometry,
786 sizeof(DISK_GEOMETRY));
787
788 Status = STATUS_SUCCESS;
789 Information = sizeof(DISK_GEOMETRY);
790 }
791 }
792 break;
793
794 case IOCTL_DISK_GET_PARTITION_INFO:
795 DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n");
796 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
797 sizeof(PARTITION_INFORMATION))
798 {
799 Status = STATUS_INFO_LENGTH_MISMATCH;
800 }
801 else if (DiskData->PartitionNumber == 0)
802 {
803 Status = STATUS_INVALID_DEVICE_REQUEST;
804 }
805 else
806 {
807 PPARTITION_INFORMATION PartitionInfo;
808
809 PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
810
811 PartitionInfo->PartitionType = DiskData->PartitionType;
812 PartitionInfo->StartingOffset = DeviceExtension->StartingOffset;
813 PartitionInfo->PartitionLength = DeviceExtension->PartitionLength;
814 PartitionInfo->HiddenSectors = DiskData->HiddenSectors;
815 PartitionInfo->PartitionNumber = DiskData->PartitionNumber;
816 PartitionInfo->BootIndicator = DiskData->BootIndicator;
817 PartitionInfo->RewritePartition = FALSE;
818 PartitionInfo->RecognizedPartition =
819 IsRecognizedPartition(DiskData->PartitionType);
820
821 Status = STATUS_SUCCESS;
822 Information = sizeof(PARTITION_INFORMATION);
823 }
824 break;
825
826 case IOCTL_DISK_SET_PARTITION_INFO:
827 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
828 sizeof(SET_PARTITION_INFORMATION))
829 {
830 Status = STATUS_INFO_LENGTH_MISMATCH;
831 }
832 else if (DiskData->PartitionNumber == 0)
833 {
834 Status = STATUS_INVALID_DEVICE_REQUEST;
835 }
836 else
837 {
838 PSET_PARTITION_INFORMATION PartitionInfo;
839
840 PartitionInfo = (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
841
842 Status = IoSetPartitionInformation(DeviceExtension->PhysicalDevice,
843 DeviceExtension->DiskGeometry->BytesPerSector,
844 DiskData->PartitionOrdinal,
845 PartitionInfo->PartitionType);
846 if (NT_SUCCESS(Status))
847 {
848 DiskData->PartitionType = PartitionInfo->PartitionType;
849 }
850 }
851 break;
852
853 case IOCTL_DISK_GET_DRIVE_LAYOUT:
854 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
855 sizeof(DRIVE_LAYOUT_INFORMATION))
856 {
857 Status = STATUS_BUFFER_TOO_SMALL;
858 }
859 else
860 {
861 PDRIVE_LAYOUT_INFORMATION PartitionList;
862
863 Status = IoReadPartitionTable(DeviceExtension->PhysicalDevice,
864 DeviceExtension->DiskGeometry->BytesPerSector,
865 FALSE,
866 &PartitionList);
867 if (NT_SUCCESS(Status))
868 {
869 ULONG BufferSize;
870
871 BufferSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,
872 PartitionEntry[0]);
873 BufferSize += PartitionList->PartitionCount * sizeof(PARTITION_INFORMATION);
874
875 if (BufferSize > IrpStack->Parameters.DeviceIoControl.OutputBufferLength)
876 {
877 Status = STATUS_BUFFER_TOO_SMALL;
878 }
879 else
880 {
881 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
882 PartitionList,
883 BufferSize);
884 Status = STATUS_SUCCESS;
885 Information = BufferSize;
886 }
887 ExFreePool(PartitionList);
888 }
889 }
890 break;
891
892 case IOCTL_DISK_SET_DRIVE_LAYOUT:
893 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
894 sizeof(DRIVE_LAYOUT_INFORMATION))
895 {
896 Status = STATUS_INFO_LENGTH_MISMATCH;
897 }
898 else if (DeviceExtension->PhysicalDevice->DeviceExtension != DeviceExtension)
899 {
900 Status = STATUS_INVALID_PARAMETER;
901 }
902 else
903 {
904 PDRIVE_LAYOUT_INFORMATION PartitionList;
905 ULONG TableSize;
906
907 PartitionList = Irp->AssociatedIrp.SystemBuffer;
908 TableSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
909 ((PartitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
910
911 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < TableSize)
912 {
913 Status = STATUS_BUFFER_TOO_SMALL;
914 }
915 else
916 {
917 /* Update partition device objects */
918 DiskClassUpdatePartitionDeviceObjects (DeviceObject,
919 Irp);
920
921 /* Write partition table */
922 Status = IoWritePartitionTable(DeviceExtension->PhysicalDevice,
923 DeviceExtension->DiskGeometry->BytesPerSector,
924 DeviceExtension->DiskGeometry->SectorsPerTrack,
925 DeviceExtension->DiskGeometry->TracksPerCylinder,
926 PartitionList);
927 if (NT_SUCCESS(Status))
928 {
929 Information = TableSize;
930 }
931 }
932 }
933 break;
934
935 case IOCTL_DISK_VERIFY:
936 case IOCTL_DISK_FORMAT_TRACKS:
937 case IOCTL_DISK_PERFORMANCE:
938 case IOCTL_DISK_IS_WRITABLE:
939 case IOCTL_DISK_LOGGING:
940 case IOCTL_DISK_FORMAT_TRACKS_EX:
941 case IOCTL_DISK_HISTOGRAM_STRUCTURE:
942 case IOCTL_DISK_HISTOGRAM_DATA:
943 case IOCTL_DISK_HISTOGRAM_RESET:
944 case IOCTL_DISK_REQUEST_STRUCTURE:
945 case IOCTL_DISK_REQUEST_DATA:
946 /* If we get here, something went wrong. Inform the requestor */
947 DPRINT1("Unhandled control code: %lx\n", ControlCode);
948 Status = STATUS_INVALID_DEVICE_REQUEST;
949 Information = 0;
950 break;
951
952 default:
953 /* Call the common device control function */
954 return(ScsiClassDeviceControl(DeviceObject, Irp));
955 }
956
957 /* Verify the device if the user caused the error */
958 if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status))
959 {
960 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
961 }
962
963 Irp->IoStatus.Status = Status;
964 Irp->IoStatus.Information = Information;
965 IoCompleteRequest(Irp,
966 IO_NO_INCREMENT);
967
968 return(Status);
969 }
970
971
972 /**********************************************************************
973 * NAME EXPORTED
974 * DiskClassShutdownFlush
975 *
976 * DESCRIPTION
977 * Answer requests for shutdown and flush calls.
978 *
979 * RUN LEVEL
980 * PASSIVE_LEVEL
981 *
982 * ARGUMENTS
983 * DeviceObject
984 * Pointer to the device.
985 *
986 * Irp
987 * Pointer to the IRP
988 *
989 * RETURN VALUE
990 * Status
991 */
992
993 NTSTATUS STDCALL
994 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
995 IN PIRP Irp)
996 {
997 PDEVICE_EXTENSION DeviceExtension;
998 PIO_STACK_LOCATION IrpStack;
999 PSCSI_REQUEST_BLOCK Srb;
1000
1001 DPRINT("DiskClassShutdownFlush() called!\n");
1002
1003 DeviceExtension = DeviceObject->DeviceExtension;
1004
1005 /* Allocate SRB */
1006 Srb = ExAllocatePool(NonPagedPool,
1007 sizeof(SCSI_REQUEST_BLOCK));
1008 if (Srb == NULL)
1009 {
1010 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1011 Irp->IoStatus.Information = 0;
1012 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1013
1014 return(STATUS_INSUFFICIENT_RESOURCES);
1015 }
1016
1017 /* Initialize SRB */
1018 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
1019 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
1020
1021 /* Set device IDs */
1022 Srb->PathId = DeviceExtension->PathId;
1023 Srb->TargetId = DeviceExtension->TargetId;
1024 Srb->Lun = DeviceExtension->Lun;
1025
1026 /* Flush write cache */
1027 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1028 Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
1029 Srb->CdbLength = 10;
1030 Srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
1031 ScsiClassSendSrbSynchronous(DeviceObject,
1032 Srb,
1033 NULL,
1034 0,
1035 TRUE);
1036
1037 /* Get current stack location */
1038 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1039
1040 /* FIXME: Unlock removable media upon shutdown */
1041
1042
1043 /* No retry */
1044 IrpStack->Parameters.Others.Argument4 = (PVOID)0;
1045
1046 /* Send shutdown or flush request to the port driver */
1047 Srb->CdbLength = 0;
1048 if (IrpStack->MajorFunction == IRP_MJ_SHUTDOWN)
1049 Srb->Function = SRB_FUNCTION_SHUTDOWN;
1050 else
1051 Srb->Function = SRB_FUNCTION_FLUSH;
1052
1053 /* Init completion routine */
1054 IoSetCompletionRoutine(Irp,
1055 ScsiClassIoComplete,
1056 Srb,
1057 TRUE,
1058 TRUE,
1059 TRUE);
1060
1061 /* Prepare next stack location for a call to the port driver */
1062 IrpStack = IoGetNextIrpStackLocation(Irp);
1063 IrpStack->MajorFunction = IRP_MJ_SCSI;
1064 IrpStack->Parameters.Scsi.Srb = Srb;
1065 Srb->OriginalRequest = Irp;
1066
1067 /* Call port driver */
1068 return(IoCallDriver(DeviceExtension->PortDeviceObject, Irp));
1069 }
1070
1071
1072 /**********************************************************************
1073 * NAME INTERNAL
1074 * DiskClassUpdatePartitionDeviceObjects
1075 *
1076 * DESCRIPTION
1077 * Deletes, modifies or creates partition device objects.
1078 *
1079 * RUN LEVEL
1080 * PASSIVE_LEVEL
1081 *
1082 * ARGUMENTS
1083 * DeviceObject
1084 * Pointer to the device.
1085 *
1086 * Irp
1087 * Pointer to the IRP
1088 *
1089 * RETURN VALUE
1090 * None
1091 */
1092
1093 static VOID
1094 DiskClassUpdatePartitionDeviceObjects(IN PDEVICE_OBJECT DiskDeviceObject,
1095 IN PIRP Irp)
1096 {
1097 PDRIVE_LAYOUT_INFORMATION PartitionList;
1098 PPARTITION_INFORMATION PartitionEntry;
1099 PDEVICE_EXTENSION DeviceExtension;
1100 PDEVICE_EXTENSION DiskDeviceExtension;
1101 PDISK_DATA DiskData;
1102 ULONG PartitionCount;
1103 ULONG PartitionOrdinal;
1104 ULONG PartitionNumber;
1105 ULONG LastPartitionNumber;
1106 ULONG i;
1107 BOOLEAN Found;
1108 WCHAR NameBuffer[MAX_PATH];
1109 UNICODE_STRING DeviceName;
1110 PDEVICE_OBJECT DeviceObject;
1111 NTSTATUS Status;
1112
1113 DPRINT("ScsiDiskUpdatePartitionDeviceObjects() called\n");
1114
1115 /* Get partition list */
1116 PartitionList = Irp->AssociatedIrp.SystemBuffer;
1117
1118 /* Round partition count up by 4 */
1119 PartitionCount = ((PartitionList->PartitionCount + 3) / 4) * 4;
1120
1121 /* Remove the partition numbers from the partition list */
1122 for (i = 0; i < PartitionCount; i++)
1123 {
1124 PartitionList->PartitionEntry[i].PartitionNumber = 0;
1125 }
1126
1127 DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
1128
1129 /* Traverse on-disk partition list */
1130 LastPartitionNumber = 0;
1131 DeviceExtension = DiskDeviceExtension;
1132 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1133 while (TRUE)
1134 {
1135 DeviceExtension = DiskData->NextPartition;
1136 if (DeviceExtension == NULL)
1137 break;
1138
1139 /* Get disk data */
1140 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1141
1142 /* Update last partition number */
1143 if (DiskData->PartitionNumber > LastPartitionNumber)
1144 LastPartitionNumber = DiskData->PartitionNumber;
1145
1146 /* Ignore unused on-disk partitions */
1147 if (DeviceExtension->PartitionLength.QuadPart == 0ULL)
1148 continue;
1149
1150 Found = FALSE;
1151 PartitionOrdinal = 0;
1152 for (i = 0; i < PartitionCount; i++)
1153 {
1154 /* Get current partition entry */
1155 PartitionEntry = &PartitionList->PartitionEntry[i];
1156
1157 /* Ignore empty (aka unused) or extended partitions */
1158 if (PartitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
1159 IsContainerPartition (PartitionEntry->PartitionType))
1160 continue;
1161
1162 PartitionOrdinal++;
1163
1164 /* Check for matching partition start offset and length */
1165 if ((PartitionEntry->StartingOffset.QuadPart !=
1166 DeviceExtension->StartingOffset.QuadPart) ||
1167 (PartitionEntry->PartitionLength.QuadPart !=
1168 DeviceExtension->PartitionLength.QuadPart))
1169 continue;
1170
1171 DPRINT1("Found matching partition entry for partition %lu\n",
1172 DiskData->PartitionNumber);
1173
1174 /* Found matching partition */
1175 Found = TRUE;
1176
1177 /* Update partition number in partition list */
1178 PartitionEntry->PartitionNumber = DiskData->PartitionNumber;
1179 break;
1180 }
1181
1182 if (Found == TRUE)
1183 {
1184 /* Get disk data for current partition */
1185 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1186
1187 /* Update partition type if partiton will be rewritten */
1188 if (PartitionEntry->RewritePartition == TRUE)
1189 DiskData->PartitionType = PartitionEntry->PartitionType;
1190
1191 /* Assign new partiton ordinal */
1192 DiskData->PartitionOrdinal = PartitionOrdinal;
1193
1194 DPRINT1("Partition ordinal %lu was assigned to partition %lu\n",
1195 DiskData->PartitionOrdinal,
1196 DiskData->PartitionNumber);
1197 }
1198 else
1199 {
1200 /* Delete this partition */
1201 DeviceExtension->PartitionLength.QuadPart = 0ULL;
1202
1203 DPRINT1("Deleting partition %lu\n",
1204 DiskData->PartitionNumber);
1205 }
1206 }
1207
1208 /* Traverse partiton list and create new partiton devices */
1209 PartitionOrdinal = 0;
1210 for (i = 0; i < PartitionCount; i++)
1211 {
1212 /* Get current partition entry */
1213 PartitionEntry = &PartitionList->PartitionEntry[i];
1214
1215 /* Ignore empty (aka unused) or extended partitions */
1216 if (PartitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
1217 IsContainerPartition (PartitionEntry->PartitionType))
1218 continue;
1219
1220 PartitionOrdinal++;
1221
1222 /* Ignore unchanged partition entries */
1223 if (PartitionEntry->RewritePartition == FALSE)
1224 continue;
1225
1226 /* Check for an unused device object */
1227 PartitionNumber = 0;
1228 DeviceExtension = DiskDeviceExtension;
1229 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1230 while (TRUE)
1231 {
1232 DeviceExtension = DiskData->NextPartition;
1233 if (DeviceExtension == NULL)
1234 break;
1235
1236 /* Get partition disk data */
1237 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1238
1239 /* Found a free (unused) partition (device object) */
1240 if (DeviceExtension->PartitionLength.QuadPart == 0ULL)
1241 {
1242 PartitionNumber = DiskData->PartitionNumber;
1243 break;
1244 }
1245 }
1246
1247 if (PartitionNumber == 0)
1248 {
1249 /* Create a new partition device object */
1250 DPRINT1("Create new partition device object\n");
1251
1252 /* Get new partiton number */
1253 LastPartitionNumber++;
1254 PartitionNumber = LastPartitionNumber;
1255
1256 /* Create partition device object */
1257 swprintf(NameBuffer,
1258 L"\\Device\\Harddisk%lu\\Partition%lu",
1259 DiskDeviceExtension->DeviceNumber,
1260 PartitionNumber);
1261 RtlInitUnicodeString(&DeviceName,
1262 NameBuffer);
1263
1264 Status = IoCreateDevice(DiskDeviceObject->DriverObject,
1265 sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA),
1266 &DeviceName,
1267 FILE_DEVICE_DISK,
1268 0,
1269 FALSE,
1270 &DeviceObject);
1271 if (!NT_SUCCESS(Status))
1272 {
1273 DPRINT1("IoCreateDevice() failed (Status %lx)\n", Status);
1274 continue;
1275 }
1276
1277 DeviceObject->Flags |= DO_DIRECT_IO;
1278 DeviceObject->StackSize = DiskDeviceObject->StackSize;
1279 DeviceObject->Characteristics = DiskDeviceObject->Characteristics;
1280 DeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
1281
1282 /* Initialize device extension */
1283 DeviceExtension = DeviceObject->DeviceExtension;
1284 RtlCopyMemory(DeviceExtension,
1285 DiskDeviceObject->DeviceExtension,
1286 sizeof(DEVICE_EXTENSION));
1287 DeviceExtension->DeviceObject = DeviceObject;
1288
1289 /* Initialize lookaside list for SRBs */
1290 ScsiClassInitializeSrbLookasideList(DeviceExtension,
1291 8);
1292
1293 /* Link current partition device extension to previous disk data */
1294 DiskData->NextPartition = DeviceExtension;
1295 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1296 DiskData->NextPartition = NULL;
1297 }
1298 else
1299 {
1300 /* Reuse an existing partition device object */
1301 DPRINT1("Reuse an exisiting partition device object\n");
1302 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1303 }
1304
1305 /* Update partition data and device extension */
1306 DiskData->PartitionNumber = PartitionNumber;
1307 DiskData->PartitionOrdinal = PartitionOrdinal;
1308 DiskData->PartitionType = PartitionEntry->PartitionType;
1309 DiskData->BootIndicator = PartitionEntry->BootIndicator;
1310 DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
1311 DeviceExtension->StartingOffset = PartitionEntry->StartingOffset;
1312 DeviceExtension->PartitionLength = PartitionEntry->PartitionLength;
1313
1314 /* Update partition number in the partition list */
1315 PartitionEntry->PartitionNumber = PartitionNumber;
1316
1317 DPRINT1("Partition ordinal %lu was assigned to partition %lu\n",
1318 DiskData->PartitionOrdinal,
1319 DiskData->PartitionNumber);
1320 }
1321
1322 DPRINT("ScsiDiskUpdatePartitionDeviceObjects() done\n");
1323 }
1324
1325
1326 /**********************************************************************
1327 * NAME INTERNAL
1328 * DiskClassUpdateFixedDiskGeometry
1329 *
1330 * DESCRIPTION
1331 * Updated the geometry of a disk if the disk can be accessed
1332 * by the BIOS.
1333 *
1334 * RUN LEVEL
1335 * PASSIVE_LEVEL
1336 *
1337 * ARGUMENTS
1338 * DeviceExtension
1339 * Disk device extension.
1340 *
1341 * RETURN VALUE
1342 * None
1343 */
1344
1345 static VOID
1346 ScsiDiskUpdateFixedDiskGeometry(IN PDEVICE_EXTENSION DeviceExtension)
1347 {
1348 PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor;
1349 PCM_INT13_DRIVE_PARAMETER DriveParameters;
1350 PKEY_VALUE_FULL_INFORMATION ValueBuffer;
1351 OBJECT_ATTRIBUTES ObjectAttributes;
1352 UNICODE_STRING KeyName;
1353 UNICODE_STRING ValueName;
1354 HANDLE SystemKey;
1355 ULONG Length;
1356 ULONG i;
1357 NTSTATUS Status;
1358
1359 DPRINT1("ScsiDiskUpdateFixedDiskGeometry() called\n");
1360
1361 RtlInitUnicodeString(&KeyName,
1362 L"\\Registry\\Machine\\Hardware\\Description\\System");
1363
1364 InitializeObjectAttributes(&ObjectAttributes,
1365 &KeyName,
1366 OBJ_CASE_INSENSITIVE,
1367 NULL,
1368 NULL);
1369
1370 /* Open the adapter key */
1371 Status = ZwOpenKey(&SystemKey,
1372 KEY_READ,
1373 &ObjectAttributes);
1374 if (!NT_SUCCESS(Status))
1375 {
1376 DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status);
1377 return;
1378 }
1379
1380 /* Allocate value buffer */
1381 ValueBuffer = ExAllocatePool(PagedPool,
1382 1024);
1383 if (ValueBuffer == NULL)
1384 {
1385 DPRINT1("Failed to allocate value buffer\n");
1386 ZwClose(SystemKey);
1387 return;
1388 }
1389
1390 RtlInitUnicodeString(&ValueName,
1391 L"Configuration Data");
1392
1393 /* Query 'Configuration Data' value */
1394 Status = ZwQueryValueKey(SystemKey,
1395 &ValueName,
1396 KeyValueFullInformation,
1397 ValueBuffer,
1398 1024,
1399 &Length);
1400 if (!NT_SUCCESS(Status))
1401 {
1402 DPRINT1("ZwQueryValueKey() failed (Status %lx)\n", Status);
1403 ExFreePool(ValueBuffer);
1404 ZwClose(SystemKey);
1405 return;
1406 }
1407
1408 ZwClose(SystemKey);
1409
1410
1411 ResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
1412 ((PUCHAR)ValueBuffer + ValueBuffer->DataOffset);
1413
1414 DriveParameters = (PCM_INT13_DRIVE_PARAMETER)
1415 ((PUCHAR)ResourceDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1416
1417 for (i = 0; i< DriveParameters[0].NumberDrives; i++)
1418 {
1419 DPRINT1("Drive %lu: %lu Cylinders %hu Heads %hu Sectors\n",
1420 i,
1421 DriveParameters[i].MaxCylinders,
1422 DriveParameters[i].MaxHeads,
1423 DriveParameters[i].SectorsPerTrack);
1424 }
1425
1426 DPRINT1("*** System stopped ***\n");
1427 for(;;);
1428
1429 ExFreePool(ValueBuffer);
1430
1431 DPRINT1("ScsiDiskUpdateFixedDiskGeometry() done\n");
1432 }
1433
1434 /* EOF */