Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

drivesup.c File Reference

#include "ntos.h"
#include "zwapi.h"
#include "hal.h"
#include "ntdddisk.h"
#include "haldisp.h"
#include "ntddft.h"
#include "mountmgr.h"
#include "stdio.h"
#include <setupblk.h>
#include "drivesup.h"

Go to the source code of this file.

Classes

struct  _BOOT_SECTOR_INFO

Defines

#define DebugPrint(x)   DrivesupDebugPrint x
#define GET_STARTING_SECTOR(p)
#define GET_PARTITION_LENGTH(p)
#define BOOTABLE_PARTITION   0
#define PRIMARY_PARTITION   1
#define LOGICAL_PARTITION   2
#define FT_PARTITION   3
#define OTHER_PARTITION   4
#define GET_STARTING_SECTOR(p)
#define WHICH_BIT(Data, Bit)
#define WHICH_BIT(Data, Bit)

Typedefs

typedef _BOOT_SECTOR_INFO BOOT_SECTOR_INFO
typedef _BOOT_SECTOR_INFOPBOOT_SECTOR_INFO

Functions

VOID DrivesupDebugPrint (ULONG DebugPrintLevel, PCCHAR DebugMessage,...)
VOID HalpCalculateChsValues (IN PLARGE_INTEGER PartitionOffset, IN PLARGE_INTEGER PartitionLength, IN CCHAR ShiftCount, IN ULONG SectorsPerTrack, IN ULONG NumberOfTracks, IN ULONG ConventionalCylinders, OUT PPARTITION_DESCRIPTOR PartitionDescriptor)
NTSTATUS HalpQueryPartitionType (IN PUNICODE_STRING DeviceName, IN PDRIVE_LAYOUT_INFORMATION DriveLayout, OUT PULONG PartitionType)
NTSTATUS HalpQueryDriveLayout (IN PUNICODE_STRING DeviceName, OUT PDRIVE_LAYOUT_INFORMATION *DriveLayout)
VOID FASTCALL xHalGetPartialGeometry (IN PDEVICE_OBJECT DeviceObject, IN PULONG ConventionalCylinders, IN PLONGLONG DiskSize)
NTSTATUS HalpGetFullGeometry (IN PDEVICE_OBJECT DeviceObject, IN PDISK_GEOMETRY Geometry, OUT PULONGLONG RealSectorCount)
BOOLEAN HalpIsValidPartitionEntry (PPARTITION_DESCRIPTOR Entry, ULONGLONG MaxOffset, ULONGLONG MaxSector)
NTSTATUS HalpNextMountLetter (IN PUNICODE_STRING DeviceName, OUT PUCHAR DriveLetter)
UCHAR HalpNextDriveLetter (IN PUNICODE_STRING DeviceName, IN PSTRING NtDeviceName, OUT PUCHAR NtSystemPath, IN BOOLEAN UseHardLinksIfNecessary)
VOID HalpEnableAutomaticDriveLetterAssignment ()
NTSTATUS HalpSetMountLetter (IN PUNICODE_STRING DeviceName, IN UCHAR DriveLetter)
BOOLEAN HalpIsOldStyleFloppy (IN PUNICODE_STRING DeviceName)
VOID FASTCALL xHalExamineMBR (IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG MBRTypeIdentifier, OUT PVOID *Buffer)
VOID FASTCALL xHalIoAssignDriveLetters (IN struct _LOADER_PARAMETER_BLOCK *LoaderBlock, IN PSTRING NtDeviceName, OUT PUCHAR NtSystemPath, OUT PSTRING NtSystemPathString)
NTSTATUS FASTCALL xHalIoReadPartitionTable (IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, OUT struct _DRIVE_LAYOUT_INFORMATION **PartitionBuffer)
NTSTATUS FASTCALL xHalIoSetPartitionInformation (IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
NTSTATUS FASTCALL xHalIoWritePartitionTable (IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN struct _DRIVE_LAYOUT_INFORMATION *PartitionBuffer)
NTSTATUS FASTCALL xHalIoClearPartitionTable (IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads)

Variables

ULONG DrivesupDebug = 0
ULONG DrivesupBreakIn = FALSE
PUCHAR DiskPartitionName = "\\Device\\Harddisk%d\\Partition%d"
PUCHAR RegistryKeyName = DISK_REGISTRY_KEY


Define Documentation

#define BOOTABLE_PARTITION   0
 

Definition at line 699 of file drivesup.c.

Referenced by HalpQueryPartitionType(), and xHalIoAssignDriveLetters().

#define DebugPrint  )     DrivesupDebugPrint x
 

Definition at line 52 of file drivesup.c.

Referenced by Calc323Dim_Data8To8_Lut16(), Calc324Dim_Data8To8_Lut16(), Calc423Dim_Data8To8_Lut16(), Calc424Dim_Data8To8_Lut16(), CalcNDim_Data8To8_Lut16(), CMMConcatInitPrivate(), CMMInitPrivate(), CombiMatrix(), CreateCombi(), DoMatrixForCube16(), DoOnlyMatrixForCube(), DoOnlyMatrixForCube16(), Extract_MFT_Xlut(), Extract_TRC_Alut(), ExtractAllLuts(), Fill_inverse_byte_ALUT_from_CurveTag(), Fill_inverse_ushort_ALUT_from_CurveTag(), FindCalcRoutine(), HalpIsValidPartitionEntry(), IopCallDriverAddDevice(), IopCallDriverAddDeviceQueryRoutine(), IopChangeDeviceObjectFromRegistryProperties(), IopProcessCriticalDevice(), IopProcessCriticalDeviceRoutine(), IopProcessNewDeviceNode(), MapperCallback(), MapperConstructRootEnumTree(), MapperMarkKey(), MapperPeripheralCallback(), MapperPhantomizeDetectedComPorts(), MapperProcessFirmwareTree(), MapperSeedKey(), MapperTranslatePnPId(), MyAdd_NL_AToB0Tag_mft1(), MyAdd_NL_AToB0Tag_mft2(), MyAdd_NL_CopyrightTag(), PnPBiosCheckForHardwareDisabled(), PnPBiosCopyDeviceParamKey(), PnPBiosCopyIoDecode(), PnPBiosEliminateDupes(), PnPBiosFindMatchingDevNode(), PnPBiosGetBiosInfo(), PnPBiosIoResourceListToCmResourceList(), PnPBiosTranslateInfo(), PnPBiosWriteInfo(), PrepareCombiLUTs(), and xHalIoReadPartitionTable().

#define FT_PARTITION   3
 

Definition at line 702 of file drivesup.c.

Referenced by HalpQueryPartitionType(), and xHalIoAssignDriveLetters().

#define GET_PARTITION_LENGTH  ) 
 

Value:

( \ (ULONG) (p->PartitionLengthLsb0) + \ (ULONG) (p->PartitionLengthLsb1 << 8) + \ (ULONG) (p->PartitionLengthMsb0 << 16) + \ (ULONG) (p->PartitionLengthMsb1 << 24) )

Definition at line 64 of file drivesup.c.

Referenced by HalpIsValidPartitionEntry(), and xHalIoReadPartitionTable().

#define GET_STARTING_SECTOR  ) 
 

Value:

( \ (ULONG) (p->StartingSectorLsb0) + \ (ULONG) (p->StartingSectorLsb1 << 8) + \ (ULONG) (p->StartingSectorMsb0 << 16) + \ (ULONG) (p->StartingSectorMsb1 << 24) )

Definition at line 58 of file drivesup.c.

#define GET_STARTING_SECTOR  ) 
 

Value:

( \ (ULONG) (p->StartingSectorLsb0) + \ (ULONG) (p->StartingSectorLsb1 << 8) + \ (ULONG) (p->StartingSectorMsb0 << 16) + \ (ULONG) (p->StartingSectorMsb1 << 24) )

Definition at line 58 of file drivesup.c.

Referenced by HalpIsValidPartitionEntry(), xHalIoReadPartitionTable(), and xHalIoSetPartitionInformation().

#define LOGICAL_PARTITION   2
 

Definition at line 701 of file drivesup.c.

Referenced by HalpQueryPartitionType(), and xHalIoAssignDriveLetters().

#define OTHER_PARTITION   4
 

Definition at line 703 of file drivesup.c.

Referenced by HalpQueryPartitionType().

#define PRIMARY_PARTITION   1
 

Definition at line 700 of file drivesup.c.

Referenced by HalpQueryPartitionType(), and xHalIoAssignDriveLetters().

#define WHICH_BIT Data,
Bit   ) 
 

Value:

{ \ for (Bit = 0; Bit < 32; Bit++) { \ if ((Data >> Bit) == 1) { \ break; \ } \ } \ }

#define WHICH_BIT Data,
Bit   ) 
 

Value:

{ \ for (Bit = 0; Bit < 32; Bit++) { \ if ((Data >> Bit) == 1) { \ break; \ } \ } \ }

Referenced by xHalIoClearPartitionTable(), and xHalIoWritePartitionTable().


Typedef Documentation

typedef struct _BOOT_SECTOR_INFO BOOT_SECTOR_INFO
 

typedef struct _BOOT_SECTOR_INFO * PBOOT_SECTOR_INFO
 

Referenced by xHalIoReadPartitionTable().


Function Documentation

VOID DrivesupDebugPrint ULONG  DebugPrintLevel,
PCCHAR  DebugMessage,
  ...
 

Definition at line 3882 of file drivesup.c.

References DbgPrint, DebugMessage, and DrivesupDebug.

03889 : 03890 03891 Debug print for all SCSI drivers 03892 03893 Arguments: 03894 03895 Debug print level between 0 and 3, with 3 being the most verbose. 03896 03897 Return Value: 03898 03899 None 03900 03901 --*/ 03902 03903 { 03904 UCHAR DrivesupBuffer[256]; 03905 03906 va_list ap; 03907 03908 va_start(ap, DebugMessage); 03909 03910 03911 if (DebugPrintLevel <= DrivesupDebug) { 03912 03913 _vsnprintf(DrivesupBuffer, 256, DebugMessage, ap); 03914 03915 DbgPrint(DrivesupBuffer); 03916 } 03917 03918 va_end(ap); 03919 03920 } // end DrivesupDebugPrint() } // end DrivesupDebugPrint()

VOID HalpCalculateChsValues IN PLARGE_INTEGER  PartitionOffset,
IN PLARGE_INTEGER  PartitionLength,
IN CCHAR  ShiftCount,
IN ULONG  SectorsPerTrack,
IN ULONG  NumberOfTracks,
IN ULONG  ConventionalCylinders,
OUT PPARTITION_DESCRIPTOR  PartitionDescriptor
 

Definition at line 546 of file drivesup.c.

References PAGED_CODE.

Referenced by xHalIoWritePartitionTable().

00558 : 00559 00560 This routine will determine the cylinder, head, and sector (CHS) values 00561 that should be placed in a partition table entry, given the partition's 00562 location on the disk and its size. The values calculated are packed into 00563 int13 format -- the high two bits of the sector byte contain bits 8 and 9 00564 of the 10 bit cylinder value, the low 6 bits of the sector byte contain 00565 the 6 bit sector value; the cylinder byte contains the low 8 bits 00566 of the cylinder value; and the head byte contains the 8-bit head value. 00567 Both the start and end CHS values are calculated. 00568 00569 Arguments: 00570 00571 PartitionOffset - Byte offset of the partition, relative to the entire 00572 physical disk. 00573 00574 PartitionLength - Size in bytes of the partition. 00575 00576 ShiftCount - Shift count to convert from byte counts to sector counts. 00577 00578 SectorsPerTrack - Number of sectors in a track on the media on which 00579 the partition resides. 00580 00581 NumberOfTracks - Number of tracks in a cylinder on the media on which 00582 the partition resides. 00583 00584 ConventionalCylinders - The "normalized" disk cylinders. We will never 00585 set the cylinders greater than this. 00586 00587 PartitionDescriptor - Structure to be filled in with the start and 00588 end CHS values. Other fields in the structure are not referenced 00589 or modified. 00590 00591 Return Value: 00592 00593 None. 00594 00595 Note: 00596 00597 The Cylinder and Head values are 0-based but the Sector value is 1-based. 00598 00599 If the start or end cylinder overflows 10 bits (ie, > 1023), CHS values 00600 will be set to all 1's. 00601 00602 No checking is done on the SectorsPerTrack and NumberOfTrack values. 00603 00604 --*/ 00605 00606 { 00607 ULONG startSector, sectorCount, endSector; 00608 ULONG sectorsPerCylinder; 00609 ULONG remainder; 00610 ULONG startC, startH, startS, endC, endH, endS; 00611 LARGE_INTEGER tempInt; 00612 00613 PAGED_CODE(); 00614 00615 // 00616 // Calculate the number of sectors in a cylinder. This is the 00617 // number of heads multiplied by the number of sectors per track. 00618 // 00619 00620 sectorsPerCylinder = SectorsPerTrack * NumberOfTracks; 00621 00622 // 00623 // Convert byte offset/count to sector offset/count. 00624 // 00625 00626 tempInt.QuadPart = PartitionOffset->QuadPart >> ShiftCount; 00627 startSector = tempInt.LowPart; 00628 00629 tempInt.QuadPart = PartitionLength->QuadPart >> ShiftCount; 00630 sectorCount = tempInt.LowPart; 00631 00632 endSector = startSector + sectorCount - 1; 00633 00634 startC = startSector / sectorsPerCylinder; 00635 endC = endSector / sectorsPerCylinder; 00636 00637 if (!ConventionalCylinders) { 00638 00639 ConventionalCylinders = 1024; 00640 00641 } 00642 00643 // 00644 // Set these values so that win95 is happy. 00645 // 00646 00647 if (startC >= ConventionalCylinders) { 00648 00649 startC = ConventionalCylinders - 1; 00650 00651 } 00652 00653 if (endC >= ConventionalCylinders) { 00654 00655 endC = ConventionalCylinders - 1; 00656 00657 } 00658 00659 // 00660 // Calculate the starting track and sector. 00661 // 00662 00663 remainder = startSector % sectorsPerCylinder; 00664 startH = remainder / SectorsPerTrack; 00665 startS = remainder % SectorsPerTrack; 00666 00667 // 00668 // Calculate the ending track and sector. 00669 // 00670 00671 remainder = endSector % sectorsPerCylinder; 00672 endH = remainder / SectorsPerTrack; 00673 endS = remainder % SectorsPerTrack; 00674 00675 // 00676 // Pack the result into the caller's structure. 00677 // 00678 00679 // low 8 bits of the cylinder => C value 00680 00681 PartitionDescriptor->StartingCylinderMsb = (UCHAR) startC; 00682 PartitionDescriptor->EndingCylinderMsb = (UCHAR) endC; 00683 00684 // 8 bits of head value => H value 00685 00686 PartitionDescriptor->StartingTrack = (UCHAR) startH; 00687 PartitionDescriptor->EndingTrack = (UCHAR) endH; 00688 00689 // bits 8-9 of cylinder and 6 bits of the sector => S value 00690 00691 PartitionDescriptor->StartingCylinderLsb = (UCHAR) (((startS + 1) & 0x3f) 00692 | ((startC >> 2) & 0xc0)); 00693 00694 PartitionDescriptor->EndingCylinderLsb = (UCHAR) (((endS + 1) & 0x3f) 00695 | ((endC >> 2) & 0xc0)); 00696 }

VOID HalpEnableAutomaticDriveLetterAssignment  ) 
 

Definition at line 1022 of file drivesup.c.

References Executive, FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetDeviceObjectPointer(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, and RtlInitUnicodeString().

Referenced by xHalIoAssignDriveLetters().

01027 : 01028 01029 This routine enables automatic drive letter assignment by the mount 01030 point manager. 01031 01032 Arguments: 01033 01034 None. 01035 01036 Return Value: 01037 01038 None. 01039 01040 --*/ 01041 01042 { 01043 UNICODE_STRING name; 01044 PFILE_OBJECT fileObject; 01045 PDEVICE_OBJECT deviceObject; 01046 KEVENT event; 01047 PIRP irp; 01048 IO_STATUS_BLOCK ioStatus; 01049 NTSTATUS status; 01050 01051 RtlInitUnicodeString(&name, MOUNTMGR_DEVICE_NAME); 01052 status = IoGetDeviceObjectPointer(&name, FILE_READ_ATTRIBUTES, &fileObject, 01053 &deviceObject); 01054 if (!NT_SUCCESS(status)) { 01055 return; 01056 } 01057 01058 KeInitializeEvent(&event, NotificationEvent, FALSE); 01059 irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS, 01060 deviceObject, NULL, 0, NULL, 0, FALSE, 01061 &event, &ioStatus); 01062 if (!irp) { 01063 ObDereferenceObject(fileObject); 01064 return; 01065 } 01066 01067 status = IoCallDriver(deviceObject, irp); 01068 if (status == STATUS_PENDING) { 01069 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); 01070 status = ioStatus.Status; 01071 } 01072 01073 ObDereferenceObject(fileObject); 01074 }

NTSTATUS HalpGetFullGeometry IN PDEVICE_OBJECT  DeviceObject,
IN PDISK_GEOMETRY  Geometry,
OUT PULONGLONG  RealSectorCount
 

Definition at line 3735 of file drivesup.c.

References ExAllocatePoolWithTag, Executive, ExFreePool(), FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and VOID().

Referenced by xHalIoReadPartitionTable().

03743 : 03744 03745 We need this routine to get the number of cylinders that the disk driver 03746 thinks is on the drive. We will need this to calculate CHS values 03747 when we fill in the partition table entries. 03748 03749 Arguments: 03750 03751 DeviceObject - The device object describing the entire drive. 03752 03753 Geometry - The geometry of the drive 03754 03755 RealSectorCount - the actual number of sectors reported by the drive ( 03756 this may be less than the size computed by the geometry) 03757 03758 Return Value: 03759 03760 None. 03761 03762 --*/ 03763 03764 { 03765 PIRP localIrp; 03766 IO_STATUS_BLOCK iosb; 03767 PKEVENT eventPtr; 03768 NTSTATUS status; 03769 03770 PAGED_CODE(); 03771 03772 eventPtr = ExAllocatePoolWithTag( 03773 NonPagedPool, 03774 sizeof(KEVENT), 03775 'btsF' 03776 ); 03777 03778 if (!eventPtr) { 03779 return STATUS_INSUFFICIENT_RESOURCES; 03780 } 03781 03782 KeInitializeEvent( 03783 eventPtr, 03784 NotificationEvent, 03785 FALSE 03786 ); 03787 03788 localIrp = IoBuildDeviceIoControlRequest( 03789 IOCTL_DISK_GET_DRIVE_GEOMETRY, 03790 DeviceObject, 03791 NULL, 03792 0UL, 03793 Geometry, 03794 sizeof(DISK_GEOMETRY), 03795 FALSE, 03796 eventPtr, 03797 &iosb 03798 ); 03799 03800 if (!localIrp) { 03801 ExFreePool(eventPtr); 03802 return STATUS_INSUFFICIENT_RESOURCES; 03803 } 03804 03805 03806 // 03807 // Call the lower level driver, wait for the opertion 03808 // to finish. 03809 // 03810 03811 status = IoCallDriver( 03812 DeviceObject, 03813 localIrp 03814 ); 03815 03816 if (status == STATUS_PENDING) { 03817 (VOID) KeWaitForSingleObject( 03818 eventPtr, 03819 Executive, 03820 KernelMode, 03821 FALSE, 03822 (PLARGE_INTEGER) NULL 03823 ); 03824 status = iosb.Status; 03825 } 03826 03827 if(NT_SUCCESS(status)) { 03828 03829 PARTITION_INFORMATION partitionInfo; 03830 03831 localIrp = IoBuildDeviceIoControlRequest( 03832 IOCTL_DISK_GET_PARTITION_INFO, 03833 DeviceObject, 03834 NULL, 03835 0UL, 03836 &partitionInfo, 03837 sizeof(PARTITION_INFORMATION), 03838 FALSE, 03839 eventPtr, 03840 &iosb 03841 ); 03842 03843 if (!localIrp) { 03844 ExFreePool(eventPtr); 03845 return STATUS_INSUFFICIENT_RESOURCES; 03846 } 03847 03848 03849 // 03850 // Call the lower level driver, wait for the opertion 03851 // to finish. 03852 // 03853 03854 status = IoCallDriver( 03855 DeviceObject, 03856 localIrp 03857 ); 03858 03859 if (status == STATUS_PENDING) { 03860 (VOID) KeWaitForSingleObject( 03861 eventPtr, 03862 Executive, 03863 KernelMode, 03864 FALSE, 03865 (PLARGE_INTEGER) NULL 03866 ); 03867 status = iosb.Status; 03868 } 03869 03870 if(NT_SUCCESS(status)) { 03871 *RealSectorCount = (partitionInfo.PartitionLength.QuadPart / 03872 Geometry->BytesPerSector); 03873 } 03874 } 03875 03876 ExFreePool(eventPtr); 03877 return status; 03878 }

BOOLEAN HalpIsOldStyleFloppy IN PUNICODE_STRING  DeviceName  ) 
 

Definition at line 1171 of file drivesup.c.

References _FILE_OBJECT::DeviceObject, Executive, FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetAttachedDeviceReference(), IoGetDeviceObjectPointer(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, PAGED_CODE, and TRUE.

Referenced by xHalIoAssignDriveLetters().

01177 : 01178 01179 This routine determines whether or not the given device is an old style 01180 floppy. That is, a floppy controlled by a traditional floppy controller. 01181 These floppies have precedent in the drive letter ordering. 01182 01183 Arguments: 01184 01185 DeviceName - Supplies the device name. 01186 01187 Return Value: 01188 01189 FALSE - The given device is not an old style floppy. 01190 01191 TRUE - The given device is an old style floppy. 01192 01193 --*/ 01194 01195 { 01196 PFILE_OBJECT fileObject; 01197 PDEVICE_OBJECT deviceObject; 01198 KEVENT event; 01199 PIRP irp; 01200 MOUNTDEV_NAME name; 01201 IO_STATUS_BLOCK ioStatus; 01202 NTSTATUS status; 01203 01204 PAGED_CODE(); 01205 01206 status = IoGetDeviceObjectPointer(DeviceName, FILE_READ_ATTRIBUTES, 01207 &fileObject, &deviceObject); 01208 if (!NT_SUCCESS(status)) { 01209 return FALSE; 01210 } 01211 deviceObject = IoGetAttachedDeviceReference(fileObject->DeviceObject); 01212 ObDereferenceObject(fileObject); 01213 01214 01215 KeInitializeEvent(&event, NotificationEvent, FALSE); 01216 irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, 01217 deviceObject, NULL, 0, &name, 01218 sizeof(name), FALSE, &event, 01219 &ioStatus); 01220 if (!irp) { 01221 ObDereferenceObject(deviceObject); 01222 return FALSE; 01223 } 01224 01225 status = IoCallDriver(deviceObject, irp); 01226 if (status == STATUS_PENDING) { 01227 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); 01228 status = ioStatus.Status; 01229 } 01230 01231 ObDereferenceObject(deviceObject); 01232 01233 if (status == STATUS_BUFFER_OVERFLOW) { 01234 return FALSE; 01235 } 01236 01237 return TRUE; 01238 }

BOOLEAN HalpIsValidPartitionEntry PPARTITION_DESCRIPTOR  Entry,
ULONGLONG  MaxOffset,
ULONGLONG  MaxSector
 

Definition at line 3425 of file drivesup.c.

References DebugPrint, FALSE, GET_PARTITION_LENGTH, GET_STARTING_SECTOR, PAGED_CODE, _PARTITION_DESCRIPTOR::PartitionType, and TRUE.

Referenced by xHalIoReadPartitionTable().

03430 { 03431 ULONGLONG endingSector; 03432 03433 PAGED_CODE(); 03434 03435 if(Entry->PartitionType == PARTITION_ENTRY_UNUSED) { 03436 03437 // 03438 // Unused partition entries are always valid. 03439 // 03440 03441 return TRUE; 03442 03443 } 03444 03445 // 03446 // Container partition entries and normal partition entries are valid iff 03447 // the partition they describe can possibly fit on the disk. We add 03448 // the base sector, the sector offset of the partition and the partition 03449 // length. If they exceed the sector count then this partition entry 03450 // is considered invalid. 03451 // 03452 03453 endingSector = GET_STARTING_SECTOR(Entry) + 03454 GET_PARTITION_LENGTH(Entry); 03455 03456 if(endingSector > MaxSector) { 03457 03458 DebugPrint((1, "HalpIsValidPartitionEntry: entry is invalid\n")); 03459 DebugPrint((1, "\tHalpIsValidPartitionEntry: offset %#08lx\n", 03460 GET_STARTING_SECTOR(Entry))); 03461 DebugPrint((1, "\tHalpIsValidPartitionEntry: length %#08lx\n", 03462 GET_PARTITION_LENGTH(Entry))); 03463 DebugPrint((1, "\tHalpIsValidPartitionEntry: end %#I64x\n", endingSector)); 03464 DebugPrint((1, "\tHalpIsValidPartitionEntry: max %#I64x\n", MaxSector)); 03465 03466 return FALSE; 03467 } else if(GET_STARTING_SECTOR(Entry) > MaxOffset) { 03468 03469 DebugPrint((1, "HalpIsValidPartitionEntry: entry is invalid\n")); 03470 DebugPrint((1, "\tHalpIsValidPartitionEntry: offset %#08lx\n", 03471 GET_STARTING_SECTOR(Entry))); 03472 DebugPrint((1, "\tHalpIsValidPartitionEntry: length %#08lx\n", 03473 GET_PARTITION_LENGTH(Entry))); 03474 DebugPrint((1, "\tHalpIsValidPartitionEntry: end %#I64x\n", endingSector)); 03475 DebugPrint((1, "\tHalpIsValidPartitionEntry: maxOffset %#I64x\n", MaxOffset)); 03476 03477 return FALSE; 03478 } 03479 03480 return TRUE; 03481 }

UCHAR HalpNextDriveLetter IN PUNICODE_STRING  DeviceName,
IN PSTRING  NtDeviceName,
OUT PUCHAR  NtSystemPath,
IN BOOLEAN  UseHardLinksIfNecessary
 

Definition at line 934 of file drivesup.c.

References HalpNextMountLetter(), HalpSetMountLetter(), IoCreateSymbolicLink(), L, NT_SUCCESS, NTSTATUS(), RtlAnsiStringToUnicodeString(), RtlEqualUnicodeString(), RtlFreeUnicodeString(), RtlInitUnicodeString(), RtlPrefixUnicodeString(), and TRUE.

Referenced by xHalIoAssignDriveLetters().

00943 : 00944 00945 This routine gives the device the next available drive letter. 00946 00947 Arguments: 00948 00949 DeviceName - Supplies the device name. 00950 00951 NtDeviceName - Supplies the NT device name. 00952 00953 NtSystemPath - Supplies the NT system path. 00954 00955 Return Value: 00956 00957 The drive letter assigned or 0. 00958 00959 --*/ 00960 00961 { 00962 NTSTATUS status; 00963 UCHAR firstDriveLetter, driveLetter; 00964 WCHAR name[40]; 00965 UNICODE_STRING symName; 00966 UNICODE_STRING unicodeString, floppyPrefix, cdromPrefix; 00967 00968 status = HalpNextMountLetter(DeviceName, &driveLetter); 00969 if (NT_SUCCESS(status)) { 00970 return driveLetter; 00971 } 00972 00973 if (!NtDeviceName || !NtSystemPath) { 00974 return 0xFF; 00975 } 00976 00977 RtlInitUnicodeString(&floppyPrefix, L"\\Device\\Floppy"); 00978 RtlInitUnicodeString(&cdromPrefix, L"\\Device\\CdRom"); 00979 if (RtlPrefixUnicodeString(&floppyPrefix, DeviceName, TRUE)) { 00980 firstDriveLetter = 'A'; 00981 } else if (RtlPrefixUnicodeString(&cdromPrefix, DeviceName, TRUE)) { 00982 firstDriveLetter = 'D'; 00983 } else { 00984 firstDriveLetter = 'C'; 00985 } 00986 00987 for (driveLetter = firstDriveLetter; driveLetter <= 'Z'; driveLetter++) { 00988 status = HalpSetMountLetter(DeviceName, driveLetter); 00989 if (NT_SUCCESS(status)) { 00990 RtlAnsiStringToUnicodeString(&unicodeString, NtDeviceName, TRUE); 00991 if (RtlEqualUnicodeString(&unicodeString, DeviceName, TRUE)) { 00992 NtSystemPath[0] = driveLetter; 00993 } 00994 RtlFreeUnicodeString(&unicodeString); 00995 return driveLetter; 00996 } 00997 } 00998 00999 if (!UseHardLinksIfNecessary) { 01000 return 0; 01001 } 01002 01003 for (driveLetter = firstDriveLetter; driveLetter <= 'Z'; driveLetter++) { 01004 swprintf(name, L"\\DosDevices\\%c:", driveLetter); 01005 RtlInitUnicodeString(&symName, name); 01006 status = IoCreateSymbolicLink(&symName, DeviceName); 01007 if (NT_SUCCESS(status)) { 01008 RtlAnsiStringToUnicodeString(&unicodeString, NtDeviceName, TRUE); 01009 if (RtlEqualUnicodeString(&unicodeString, DeviceName, TRUE)) { 01010 NtSystemPath[0] = driveLetter; 01011 } 01012 RtlFreeUnicodeString(&unicodeString); 01013 return driveLetter; 01014 } 01015 } 01016 01017 return 0; 01018 }

NTSTATUS HalpNextMountLetter IN PUNICODE_STRING  DeviceName,
OUT PUCHAR  DriveLetter
 

Definition at line 851 of file drivesup.c.

References ExAllocatePoolWithTag, Executive, ExFreePool(), FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetDeviceObjectPointer(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, PagedPool, and RtlInitUnicodeString().

Referenced by HalpNextDriveLetter().

00858 : 00859 00860 This routine gives the device the next available drive letter. 00861 00862 Arguments: 00863 00864 DeviceName - Supplies the device name. 00865 00866 DriveLetter - Returns the drive letter assigned or 0. 00867 00868 Return Value: 00869 00870 NTSTATUS 00871 00872 --*/ 00873 00874 { 00875 UNICODE_STRING name; 00876 PFILE_OBJECT fileObject; 00877 PDEVICE_OBJECT deviceObject; 00878 PMOUNTMGR_DRIVE_LETTER_TARGET input; 00879 KEVENT event; 00880 PIRP irp; 00881 MOUNTMGR_DRIVE_LETTER_INFORMATION output; 00882 IO_STATUS_BLOCK ioStatus; 00883 NTSTATUS status; 00884 00885 RtlInitUnicodeString(&name, MOUNTMGR_DEVICE_NAME); 00886 status = IoGetDeviceObjectPointer(&name, FILE_READ_ATTRIBUTES, &fileObject, 00887 &deviceObject); 00888 if (!NT_SUCCESS(status)) { 00889 return status; 00890 } 00891 00892 input = ExAllocatePoolWithTag(PagedPool, 00893 (sizeof(MOUNTMGR_DRIVE_LETTER_TARGET) + 00894 DeviceName->Length), 00895 'btsF' 00896 ); 00897 00898 if (!input) { 00899 ObDereferenceObject(fileObject); 00900 return STATUS_INSUFFICIENT_RESOURCES; 00901 } 00902 00903 input->DeviceNameLength = DeviceName->Length; 00904 RtlCopyMemory(input->DeviceName, DeviceName->Buffer, DeviceName->Length); 00905 00906 KeInitializeEvent(&event, NotificationEvent, FALSE); 00907 irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER, 00908 deviceObject, input, 00909 sizeof(MOUNTMGR_DRIVE_LETTER_TARGET) + 00910 DeviceName->Length, &output, 00911 sizeof(output), FALSE, &event, 00912 &ioStatus); 00913 if (!irp) { 00914 ExFreePool(input); 00915 ObDereferenceObject(fileObject); 00916 return STATUS_INSUFFICIENT_RESOURCES; 00917 } 00918 00919 status = IoCallDriver(deviceObject, irp); 00920 if (status == STATUS_PENDING) { 00921 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); 00922 status = ioStatus.Status; 00923 } 00924 00925 ExFreePool(input); 00926 ObDereferenceObject(fileObject); 00927 00928 *DriveLetter = output.CurrentDriveLetter; 00929 00930 return status; 00931 }

NTSTATUS HalpQueryDriveLayout IN PUNICODE_STRING  DeviceName,
OUT PDRIVE_LAYOUT_INFORMATION *  DriveLayout
 

Definition at line 792 of file drivesup.c.

References _DEVICE_OBJECT::Characteristics, _FILE_OBJECT::DeviceObject, Executive, FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetAttachedDeviceReference(), IoGetDeviceObjectPointer(), IoReadPartitionTable(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NT_SUCCESS, NTSTATUS(), NULL, and ObDereferenceObject.

Referenced by xHalIoAssignDriveLetters().

00797 { 00798 NTSTATUS status; 00799 PFILE_OBJECT fileObject; 00800 PDEVICE_OBJECT deviceObject; 00801 KEVENT event; 00802 PIRP irp; 00803 DISK_GEOMETRY geometry; 00804 IO_STATUS_BLOCK ioStatus; 00805 00806 status = IoGetDeviceObjectPointer(DeviceName, FILE_READ_ATTRIBUTES, 00807 &fileObject, &deviceObject); 00808 if (!NT_SUCCESS(status)) { 00809 return status; 00810 } 00811 deviceObject = IoGetAttachedDeviceReference(fileObject->DeviceObject); 00812 ObDereferenceObject(fileObject); 00813 00814 if (deviceObject->Characteristics&FILE_REMOVABLE_MEDIA) { 00815 ObDereferenceObject(deviceObject); 00816 return STATUS_NO_MEDIA; 00817 } 00818 00819 KeInitializeEvent(&event, NotificationEvent, FALSE); 00820 00821 irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, 00822 deviceObject, NULL, 0, &geometry, 00823 sizeof(geometry), FALSE, &event, 00824 &ioStatus); 00825 if (!irp) { 00826 ObDereferenceObject(deviceObject); 00827 return STATUS_INSUFFICIENT_RESOURCES; 00828 } 00829 00830 status = IoCallDriver(deviceObject, irp); 00831 if (status == STATUS_PENDING) { 00832 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); 00833 status = ioStatus.Status; 00834 } 00835 00836 if (!NT_SUCCESS(status)) { 00837 ObDereferenceObject(deviceObject); 00838 return status; 00839 } 00840 00841 status = IoReadPartitionTable(deviceObject, geometry.BytesPerSector, 00842 FALSE, DriveLayout); 00843 00844 ObDereferenceObject(deviceObject); 00845 00846 return status; 00847 }

NTSTATUS HalpQueryPartitionType IN PUNICODE_STRING  DeviceName,
IN PDRIVE_LAYOUT_INFORMATION  DriveLayout,
OUT PULONG  PartitionType
 

Definition at line 706 of file drivesup.c.

References BOOTABLE_PARTITION, _DEVICE_OBJECT::Characteristics, _FILE_OBJECT::DeviceObject, Executive, FALSE, FT_PARTITION, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetAttachedDeviceReference(), IoGetDeviceObjectPointer(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), LOGICAL_PARTITION, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, OTHER_PARTITION, and PRIMARY_PARTITION.

Referenced by xHalIoAssignDriveLetters().

00712 { 00713 NTSTATUS status; 00714 PFILE_OBJECT fileObject; 00715 PDEVICE_OBJECT deviceObject; 00716 KEVENT event; 00717 PIRP irp; 00718 PARTITION_INFORMATION partInfo; 00719 IO_STATUS_BLOCK ioStatus; 00720 ULONG i; 00721 00722 status = IoGetDeviceObjectPointer(DeviceName, 00723 FILE_READ_ATTRIBUTES, 00724 &fileObject, &deviceObject); 00725 if (!NT_SUCCESS(status)) { 00726 return status; 00727 } 00728 deviceObject = IoGetAttachedDeviceReference(fileObject->DeviceObject); 00729 ObDereferenceObject(fileObject); 00730 00731 if ((deviceObject->Characteristics&FILE_REMOVABLE_MEDIA) || 00732 !DriveLayout) { 00733 00734 ObDereferenceObject(deviceObject); 00735 *PartitionType = LOGICAL_PARTITION; 00736 return STATUS_SUCCESS; 00737 } 00738 00739 KeInitializeEvent(&event, NotificationEvent, FALSE); 00740 00741 irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO, 00742 deviceObject, NULL, 0, &partInfo, 00743 sizeof(partInfo), FALSE, &event, 00744 &ioStatus); 00745 if (!irp) { 00746 ObDereferenceObject(deviceObject); 00747 return STATUS_INSUFFICIENT_RESOURCES; 00748 } 00749 00750 status = IoCallDriver(deviceObject, irp); 00751 if (status == STATUS_PENDING) { 00752 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); 00753 status = ioStatus.Status; 00754 } 00755 00756 ObDereferenceObject(deviceObject); 00757 00758 if (!NT_SUCCESS(status)) { 00759 return status; 00760 } 00761 00762 if (!IsRecognizedPartition(partInfo.PartitionType)) { 00763 *PartitionType = OTHER_PARTITION; 00764 return STATUS_SUCCESS; 00765 } 00766 00767 if (partInfo.PartitionType&0x80) { 00768 *PartitionType = FT_PARTITION; 00769 return STATUS_SUCCESS; 00770 } 00771 00772 for (i = 0; i < 4; i++) { 00773 if (partInfo.StartingOffset.QuadPart == 00774 DriveLayout->PartitionEntry[i].StartingOffset.QuadPart) { 00775 00776 if (partInfo.BootIndicator) { 00777 *PartitionType = BOOTABLE_PARTITION; 00778 } else { 00779 *PartitionType = PRIMARY_PARTITION; 00780 } 00781 00782 return STATUS_SUCCESS; 00783 } 00784 } 00785 00786 *PartitionType = LOGICAL_PARTITION; 00787 return STATUS_SUCCESS; 00788 }

NTSTATUS HalpSetMountLetter IN PUNICODE_STRING  DeviceName,
IN UCHAR  DriveLetter
 

Definition at line 1078 of file drivesup.c.

References ExAllocatePoolWithTag, Executive, ExFreePool(), FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetDeviceObjectPointer(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), L, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, PagedPool, and RtlInitUnicodeString().

Referenced by HalpNextDriveLetter(), and xHalIoAssignDriveLetters().

01085 : 01086 01087 This routine sets the drive letter for the given device. 01088 01089 Arguments: 01090 01091 DeviceName - Supplies the device name. 01092 01093 DriveLetter - Supplies the drive letter. 01094 01095 Return Value: 01096 01097 NTSTATUS 01098 01099 --*/ 01100 01101 { 01102 WCHAR dosBuffer[30]; 01103 UNICODE_STRING dosName; 01104 ULONG createPointSize; 01105 PMOUNTMGR_CREATE_POINT_INPUT createPoint; 01106 UNICODE_STRING name; 01107 NTSTATUS status; 01108 PFILE_OBJECT fileObject; 01109 PDEVICE_OBJECT deviceObject; 01110 KEVENT event; 01111 PIRP irp; 01112 IO_STATUS_BLOCK ioStatus; 01113 01114 swprintf(dosBuffer, L"\\DosDevices\\%c:", DriveLetter); 01115 RtlInitUnicodeString(&dosName, dosBuffer); 01116 01117 createPointSize = sizeof(MOUNTMGR_CREATE_POINT_INPUT) + 01118 dosName.Length + DeviceName->Length; 01119 01120 createPoint = (PMOUNTMGR_CREATE_POINT_INPUT) 01121 ExAllocatePoolWithTag(PagedPool, createPointSize, 'btsF'); 01122 if (!createPoint) { 01123 return STATUS_INSUFFICIENT_RESOURCES; 01124 } 01125 01126 createPoint->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT); 01127 createPoint->SymbolicLinkNameLength = dosName.Length; 01128 createPoint->DeviceNameOffset = createPoint->SymbolicLinkNameOffset + 01129 createPoint->SymbolicLinkNameLength; 01130 createPoint->DeviceNameLength = DeviceName->Length; 01131 01132 RtlCopyMemory((PCHAR) createPoint + createPoint->SymbolicLinkNameOffset, 01133 dosName.Buffer, dosName.Length); 01134 RtlCopyMemory((PCHAR) createPoint + createPoint->DeviceNameOffset, 01135 DeviceName->Buffer, DeviceName->Length); 01136 01137 RtlInitUnicodeString(&name, MOUNTMGR_DEVICE_NAME); 01138 status = IoGetDeviceObjectPointer(&name, FILE_READ_ATTRIBUTES, &fileObject, 01139 &deviceObject); 01140 if (!NT_SUCCESS(status)) { 01141 ExFreePool(createPoint); 01142 return status; 01143 } 01144 01145 KeInitializeEvent(&event, NotificationEvent, FALSE); 01146 irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_CREATE_POINT, 01147 deviceObject, createPoint, 01148 createPointSize, NULL, 0, FALSE, 01149 &event, &ioStatus); 01150 if (!irp) { 01151 ObDereferenceObject(fileObject); 01152 ExFreePool(createPoint); 01153 return STATUS_INSUFFICIENT_RESOURCES; 01154 } 01155 01156 status = IoCallDriver(deviceObject, irp); 01157 if (status == STATUS_PENDING) { 01158 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); 01159 status = ioStatus.Status; 01160 } 01161 01162 ObDereferenceObject(fileObject); 01163 ExFreePool(createPoint); 01164 01165 return status; 01166 }

VOID FASTCALL xHalExamineMBR IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  SectorSize,
IN ULONG  MBRTypeIdentifier,
OUT PVOID *  Buffer
 

Definition at line 190 of file drivesup.c.

References ASSERT, BOOT_RECORD_SIGNATURE, BOOT_SIGNATURE_OFFSET, Buffer, ExAllocatePoolWithTag, Executive, ExFreePool(), FALSE, _IO_STACK_LOCATION::Flags, IoBuildSynchronousFsdRequest(), IoCallDriver, IoGetNextIrpStackLocation, IRP_MJ_READ, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NonPagedPoolCacheAligned, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, PARTITION_TABLE_OFFSET, _PARTITION_DESCRIPTOR::PartitionType, PUSHORT, SectorSize, SL_OVERRIDE_VERIFY_VOLUME, and VOID().

00199 : 00200 00201 Given a master boot record type (MBR - the zero'th sector on the disk), 00202 read the master boot record of a disk. If the MBR is found to be of that 00203 type, allocate a structure whose layout is dependant upon that partition 00204 type, fill with the appropriate values, and return a pointer to that buffer 00205 in the output parameter. 00206 00207 The best example for a use of this routine is to support Ontrack 00208 systems DiskManager software. Ontrack software lays down a special 00209 partition describing the entire drive. The special partition type 00210 (0x54) will be recognized and a couple of longwords of data will 00211 be passed back in a buffer for a disk driver to act upon. 00212 00213 Arguments: 00214 00215 DeviceObject - The device object describing the entire drive. 00216 00217 SectorSize - The minimum number of bytes that an IO operation can 00218 fetch. 00219 00220 MBRIndentifier - A value that will be searched for in the 00221 in the MBR. This routine will understand 00222 the semantics implied by this value. 00223 00224 Buffer - Pointer to a buffer that returns data according to the 00225 type of MBR searched for. If the MBR is not of the 00226 type asked for, the buffer will not be allocated and this 00227 pointer will be NULL. It is the responsibility of the 00228 caller of HalExamineMBR to deallocate the buffer. The 00229 caller should deallocate the memory ASAP. 00230 00231 Return Value: 00232 00233 None. 00234 00235 --*/ 00236 00237 { 00238 00239 00240 LARGE_INTEGER partitionTableOffset; 00241 PUCHAR readBuffer = (PUCHAR) NULL; 00242 KEVENT event; 00243 IO_STATUS_BLOCK ioStatus; 00244 PIRP irp; 00245 PPARTITION_DESCRIPTOR partitionTableEntry; 00246 NTSTATUS status = STATUS_SUCCESS; 00247 ULONG readSize; 00248 00249 *Buffer = NULL; 00250 // 00251 // Determine the size of a read operation to ensure that at least 512 00252 // bytes are read. This will guarantee that enough data is read to 00253 // include an entire partition table. Note that this code assumes that 00254 // the actual sector size of the disk (if less than 512 bytes) is a 00255 // multiple of 2, a fairly reasonable assumption. 00256 // 00257 00258 if (SectorSize >= 512) { 00259 readSize = SectorSize; 00260 } else { 00261 readSize = 512; 00262 } 00263 00264 // 00265 // Start at sector 0 of the device. 00266 // 00267 00268 partitionTableOffset = RtlConvertUlongToLargeInteger( 0 ); 00269 00270 // 00271 // Allocate a buffer that will hold the reads. 00272 // 00273 00274 readBuffer = ExAllocatePoolWithTag( 00275 NonPagedPoolCacheAligned, 00276 PAGE_SIZE>readSize?PAGE_SIZE:readSize, 00277 'btsF' 00278 ); 00279 00280 if (readBuffer == NULL) { 00281 return; 00282 } 00283 00284 // 00285 // Read record containing partition table. 00286 // 00287 // Create a notification event object to be used while waiting for 00288 // the read request to complete. 00289 // 00290 00291 KeInitializeEvent( &event, NotificationEvent, FALSE ); 00292 00293 irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, 00294 DeviceObject, 00295 readBuffer, 00296 readSize, 00297 &partitionTableOffset, 00298 &event, 00299 &ioStatus ); 00300 00301 if (!irp) { 00302 ExFreePool(readBuffer); 00303 return; 00304 } else { 00305 PIO_STACK_LOCATION irpStack; 00306 irpStack = IoGetNextIrpStackLocation(irp); 00307 irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 00308 } 00309 00310 status = IoCallDriver( DeviceObject, irp ); 00311 00312 if (status == STATUS_PENDING) { 00313 (VOID) KeWaitForSingleObject( &event, 00314 Executive, 00315 KernelMode, 00316 FALSE, 00317 (PLARGE_INTEGER) NULL); 00318 status = ioStatus.Status; 00319 } 00320 00321 if (!NT_SUCCESS( status )) { 00322 ExFreePool(readBuffer); 00323 return; 00324 } 00325 00326 // 00327 // Check for Boot Record signature. 00328 // 00329 00330 if (((PUSHORT) readBuffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) { 00331 ExFreePool(readBuffer); 00332 return; 00333 } 00334 00335 // 00336 // Check for DM type partition. 00337 // 00338 00339 partitionTableEntry = (PPARTITION_DESCRIPTOR) &(((PUSHORT) readBuffer)[PARTITION_TABLE_OFFSET]); 00340 00341 if (partitionTableEntry->PartitionType != MBRTypeIdentifier) { 00342 00343 // 00344 // The partition type isn't what the caller cares about. 00345 // 00346 ExFreePool(readBuffer); 00347 00348 } else { 00349 00350 if (partitionTableEntry->PartitionType == 0x54) { 00351 00352 // 00353 // Rather than allocate a new piece of memory to return 00354 // the data - just use the memory allocated for the buffer. 00355 // We can assume the caller will delete this shortly. 00356 // 00357 00358 ((PULONG)readBuffer)[0] = 63; 00359 *Buffer = readBuffer; 00360 00361 } else if (partitionTableEntry->PartitionType == 0x55) { 00362 00363 // 00364 // EzDrive Parititon. Simply return the pointer to non-null 00365 // There is no skewing here. 00366 // 00367 00368 *Buffer = readBuffer; 00369 00370 } else { 00371 00372 ASSERT(partitionTableEntry->PartitionType == 0x55); 00373 00374 } 00375 00376 } 00377 00378 }

VOID FASTCALL xHalGetPartialGeometry IN PDEVICE_OBJECT  DeviceObject,
IN PULONG  ConventionalCylinders,
IN PLONGLONG  DiskSize
 

Definition at line 382 of file drivesup.c.

References ExAllocatePoolWithTag, Executive, ExFreePool(), FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, and VOID().

Referenced by xHalIoClearPartitionTable(), and xHalIoWritePartitionTable().

00390 : 00391 00392 We need this routine to get the number of cylinders that the disk driver 00393 thinks is on the drive. We will need this to calculate CHS values 00394 when we fill in the partition table entries. 00395 00396 Arguments: 00397 00398 DeviceObject - The device object describing the entire drive. 00399 00400 ConventionalCylinders - Number of cylinders on the drive. 00401 00402 Return Value: 00403 00404 None. 00405 00406 --*/ 00407 00408 { 00409 PIRP localIrp; 00410 PDISK_GEOMETRY diskGeometry; 00411 PIO_STATUS_BLOCK iosb; 00412 PKEVENT eventPtr; 00413 NTSTATUS status; 00414 00415 *ConventionalCylinders = 0UL; 00416 *DiskSize = 0UL; 00417 00418 diskGeometry = ExAllocatePoolWithTag( 00419 NonPagedPool, 00420 sizeof(DISK_GEOMETRY), 00421 'btsF' 00422 ); 00423 00424 if (!diskGeometry) { 00425 00426 return; 00427 00428 } 00429 00430 iosb = ExAllocatePoolWithTag( 00431 NonPagedPool, 00432 sizeof(IO_STATUS_BLOCK), 00433 'btsF' 00434 ); 00435 00436 if (!iosb) { 00437 00438 ExFreePool(diskGeometry); 00439 return; 00440 00441 } 00442 00443 eventPtr = ExAllocatePoolWithTag( 00444 NonPagedPool, 00445 sizeof(KEVENT), 00446 'btsF' 00447 ); 00448 00449 if (!eventPtr) { 00450 00451 ExFreePool(iosb); 00452 ExFreePool(diskGeometry); 00453 return; 00454 00455 } 00456 00457 KeInitializeEvent( 00458 eventPtr, 00459 NotificationEvent, 00460 FALSE 00461 ); 00462 00463 localIrp = IoBuildDeviceIoControlRequest( 00464 IOCTL_DISK_GET_DRIVE_GEOMETRY, 00465 DeviceObject, 00466 NULL, 00467 0UL, 00468 diskGeometry, 00469 sizeof(DISK_GEOMETRY), 00470 FALSE, 00471 eventPtr, 00472 iosb 00473 ); 00474 00475 if (!localIrp) { 00476 00477 ExFreePool(eventPtr); 00478 ExFreePool(iosb); 00479 ExFreePool(diskGeometry); 00480 return; 00481 00482 } 00483 00484 00485 // 00486 // Call the lower level driver, wait for the opertion 00487 // to finish. 00488 // 00489 00490 status = IoCallDriver( 00491 DeviceObject, 00492 localIrp 00493 ); 00494 00495 if (status == STATUS_PENDING) { 00496 (VOID) KeWaitForSingleObject( 00497 eventPtr, 00498 Executive, 00499 KernelMode, 00500 FALSE, 00501 (PLARGE_INTEGER) NULL 00502 ); 00503 status = iosb->Status; 00504 } 00505 00506 if (NT_SUCCESS(status)) { 00507 00508 // 00509 // The operation completed successfully. Get the cylinder 00510 // count of the drive. 00511 // 00512 00513 *ConventionalCylinders = diskGeometry->Cylinders.LowPart; 00514 00515 // 00516 // If the count is less than 1024 we can pass that back. Otherwise 00517 // send back the 1024 00518 // 00519 00520 if (diskGeometry->Cylinders.QuadPart >= (LONGLONG)1024) { 00521 00522 *ConventionalCylinders = 1024; 00523 00524 } 00525 00526 // 00527 // Calculate disk size from gemotry information 00528 // 00529 00530 *DiskSize = diskGeometry->Cylinders.QuadPart * 00531 diskGeometry->TracksPerCylinder * 00532 diskGeometry->SectorsPerTrack * 00533 diskGeometry->BytesPerSector; 00534 00535 } 00536 00537 ExFreePool(eventPtr); 00538 ExFreePool(iosb); 00539 ExFreePool(diskGeometry); 00540 return; 00541 00542 }

VOID FASTCALL xHalIoAssignDriveLetters IN struct _LOADER_PARAMETER_BLOCK LoaderBlock,
IN PSTRING  NtDeviceName,
OUT PUCHAR  NtSystemPath,
OUT PSTRING  NtSystemPathString
 

Definition at line 1243 of file drivesup.c.

References BOOTABLE_PARTITION, _CONFIGURATION_INFORMATION::CdRomCount, DbgPrint, _CONFIGURATION_INFORMATION::DiskCount, DiskPartitionName, ExAllocatePoolWithTag, ExFreePool(), FALSE, _CONFIGURATION_INFORMATION::FloppyCount, FT_PARTITION, HalpEnableAutomaticDriveLetterAssignment(), HalpIsOldStyleFloppy(), HalpNextDriveLetter(), HalpQueryDriveLayout(), HalpQueryPartitionType(), HalpSetMountLetter(), IoCreateSymbolicLink(), IoGetConfigurationInformation(), IoRemoteBootClient, KeBugCheck(), L, LOGICAL_PARTITION, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PCONFIGURATION_INFORMATION, PRIMARY_PARTITION, RtlAnsiStringToUnicodeString(), RtlFreeUnicodeString(), RtlInitAnsiString(), RtlInitString(), RtlInitUnicodeString(), RtlPrefixUnicodeString(), SETUPBLK_FLAGS_REMOTE_INSTALL, SETUPBLK_FLAGS_SYSPREP_INSTALL, sprintf(), strlen(), TRUE, and ZwOpenFile().

01252 : 01253 01254 This routine assigns DOS drive letters to eligible disk partitions 01255 and CDROM drives. It also maps the partition containing the NT 01256 boot path to \SystemRoot. In NT, objects are built for all partition 01257 types except 0 (unused) and 5 (extended). But drive letters are assigned 01258 only to recognized partition types (1, 4, 6, 7, e). 01259 01260 Drive letter assignment is done in several stages: 01261 01262 1) For each CdRom: 01263 Determine if sticky letters are assigned and reserve the letter. 01264 01265 2) For each disk: 01266 Determine how many primary partitions and which is bootable. 01267 Determine which partitions already have 'sticky letters' 01268 and create their symbolic links. 01269 Create a bit map for each disk that idicates which partitions 01270 require default drive letter assignments. 01271 01272 3) For each disk: 01273 Assign default drive letters for the bootable 01274 primary partition or the first nonbootable primary partition. 01275 01276 4) For each disk: 01277 Assign default drive letters for the partitions in 01278 extended volumes. 01279 01280 5) For each disk: 01281 Assign default drive letters for the remaining (ENHANCED) 01282 primary partitions. 01283 01284 6) Assign A: and B: to the first two floppies in the system if they 01285 exist. Then assign remaining floppies next available drive letters. 01286 01287 7) Assign drive letters to CdRoms (either sticky or default). 01288 01289 Arguments: 01290 01291 LoaderBlock - pointer to a loader parameter block. 01292 01293 NtDeviceName - pointer to the boot device name string used 01294 to resolve NtSystemPath. 01295 01296 Return Value: 01297 01298 None. 01299 01300 --*/ 01301 01302 { 01303 PUCHAR ntName; 01304 STRING ansiString; 01305 UNICODE_STRING unicodeString; 01306 PUCHAR ntPhysicalName; 01307 STRING ansiPhysicalString; 01308 UNICODE_STRING unicodePhysicalString; 01309 NTSTATUS status; 01310 OBJECT_ATTRIBUTES objectAttributes; 01311 PCONFIGURATION_INFORMATION configurationInformation; 01312 ULONG diskCount; 01313 ULONG floppyCount; 01314 HANDLE deviceHandle; 01315 IO_STATUS_BLOCK ioStatusBlock; 01316 ULONG diskNumber; 01317 ULONG i, j; 01318 UCHAR driveLetter; 01319 WCHAR deviceNameBuffer[50]; 01320 UNICODE_STRING deviceName, floppyPrefix, cdromPrefix; 01321 PDRIVE_LAYOUT_INFORMATION layout; 01322 BOOLEAN bootable; 01323 ULONG partitionType; 01324 ULONG skip; 01325 ULONG diskCountIncrement; 01326 ULONG actualDiskCount = 0; 01327 01328 PAGED_CODE(); 01329 01330 // 01331 // Get the count of devices from the registry. 01332 // 01333 01334 configurationInformation = IoGetConfigurationInformation(); 01335 01336 diskCount = configurationInformation->DiskCount; 01337 floppyCount = configurationInformation->FloppyCount; 01338 01339 // 01340 // Allocate general NT name buffer. 01341 // 01342 01343 ntName = ExAllocatePoolWithTag( NonPagedPool, 128, 'btsF'); 01344 01345 ntPhysicalName = ExAllocatePoolWithTag( NonPagedPool, 64, 'btsF'); 01346 01347 if (ntName == NULL || ntPhysicalName == NULL) { 01348 01349 KeBugCheck( ASSIGN_DRIVE_LETTERS_FAILED ); 01350 01351 } 01352 01353 // 01354 // If we're doing a remote boot, set NtSystemPath appropriately. 01355 // 01356 01357 if (IoRemoteBootClient) { 01358 01359 PUCHAR p; 01360 PUCHAR q; 01361 01362 // 01363 // If this is a remote boot setup boot, NtBootPathName is of the 01364 // form <server><share>\setup<install-directory><platform>. 01365 // We want the root of the X: drive to be the root of the install 01366 // directory. 01367 // 01368 // If this is a normal remote boot, NtBootPathName is of the form 01369 // <server><share>\images<machine>\winnt. We want the root of 01370 // the X: drive to be the root of the machine directory. 01371 // 01372 // Thus in either case, we need to remove all but the last element 01373 // of the path. 01374 // 01375 // Find the beginning of the last element of the path (including 01376 // the leading backslash). 01377 // 01378 01379 p = strrchr( LoaderBlock->NtBootPathName, '\\' ); // find last separator 01380 q = NULL; 01381 if ( (p != NULL) && (*(p+1) == 0) ) { 01382 01383 // 01384 // NtBootPathName ends with a backslash, so we need to back up 01385 // to the previous backslash. 01386 // 01387 01388 q = p; 01389 *q = 0; 01390 p = strrchr( LoaderBlock->NtBootPathName, '\\' ); // find last separator 01391 *q = '\\'; 01392 } 01393 if ( p == NULL ) { 01394 KeBugCheck( ASSIGN_DRIVE_LETTERS_FAILED ); 01395 } 01396 01397 // 01398 // Set NtSystemPath to X:<last element of path>. Note that the symbolic 01399 // link for X: is created in io\ioinit.c\IopInitializeBootDrivers. 01400 // 01401 // Note that we use X: for the textmode setup phase of a remote 01402 // installation. But for a true remote boot, we use C:. 01403 // 01404 01405 #if defined(REMOTE_BOOT) 01406 if ((LoaderBlock->SetupLoaderBlock->Flags & (SETUPBLK_FLAGS_REMOTE_INSTALL | 01407 SETUPBLK_FLAGS_SYSPREP_INSTALL)) == 0) { 01408 NtSystemPath[0] = 'C'; 01409 } else 01410 #endif 01411 { 01412 NtSystemPath[0] = 'X'; 01413 } 01414 NtSystemPath[1] = ':'; 01415 strcpy(&NtSystemPath[2], p ); 01416 if ( q != NULL ) { 01417 NtSystemPath[strlen(NtSystemPath)-1] = '\0'; // remove trailing backslash 01418 } 01419 RtlInitString(NtSystemPathString, NtSystemPath); 01420 01421 } 01422 01423 // 01424 // For each disk ... 01425 // 01426 01427 diskCountIncrement = 0; 01428 for (diskNumber = 0; diskNumber < diskCount; diskNumber++) { 01429 01430 // 01431 // Create ANSI name string for physical disk. 01432 // 01433 01434 sprintf( ntName, DiskPartitionName, diskNumber, 0 ); 01435 01436 // 01437 // Convert to unicode string. 01438 // 01439 01440 RtlInitAnsiString( &ansiString, ntName ); 01441 01442 RtlAnsiStringToUnicodeString( &unicodeString, &ansiString, TRUE ); 01443 01444 InitializeObjectAttributes( &objectAttributes, 01445 &unicodeString, 01446 OBJ_CASE_INSENSITIVE, 01447 NULL, 01448 NULL ); 01449 01450 // 01451 // Open device by name. 01452 // 01453 01454 status = ZwOpenFile( &deviceHandle, 01455 FILE_READ_DATA | SYNCHRONIZE, 01456 &objectAttributes, 01457 &ioStatusBlock, 01458 FILE_SHARE_READ, 01459 FILE_SYNCHRONOUS_IO_NONALERT ); 01460 01461 if (NT_SUCCESS( status )) { 01462 01463 // 01464 // The device was successfully opened. Generate a DOS device name 01465 // for the drive itself. 01466 // 01467 01468 sprintf( ntPhysicalName, "\\DosDevices\\PhysicalDrive%d", diskNumber ); 01469 01470 RtlInitAnsiString( &ansiPhysicalString, ntPhysicalName ); 01471 01472 RtlAnsiStringToUnicodeString( &unicodePhysicalString, &ansiPhysicalString, TRUE ); 01473 01474 IoCreateSymbolicLink( &unicodePhysicalString, &unicodeString ); 01475 01476 RtlFreeUnicodeString( &unicodePhysicalString ); 01477 01478 ZwClose(deviceHandle); 01479 01480 actualDiskCount = diskNumber + 1; 01481 } 01482 01483 RtlFreeUnicodeString( &unicodeString ); 01484 01485 if (!NT_SUCCESS( status )) { 01486 01487 #if DBG 01488 DbgPrint( "IoAssignDriveLetters: Failed to open %s\n", ntName ); 01489 #endif // DBG 01490 01491 // 01492 // This may be a sparse name space. Try going farther but 01493 // not forever. 01494 // 01495 01496 if (diskCountIncrement < 50) { 01497 diskCountIncrement++; 01498 diskCount++; 01499 } 01500 } 01501 01502 } // end for diskNumber ... 01503 01504 ExFreePool( ntName ); 01505 ExFreePool( ntPhysicalName ); 01506 01507 diskCount -= diskCountIncrement; 01508 if (actualDiskCount > diskCount) { 01509 diskCount = actualDiskCount; 01510 } 01511 01512 for (i = 0; i < diskCount; i++) { 01513 01514 swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition0", i); 01515 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01516 01517 status = HalpQueryDriveLayout(&deviceName, &layout); 01518 if (!NT_SUCCESS(status)) { 01519 layout = NULL; 01520 } 01521 01522 bootable = FALSE; 01523 for (j = 1; ; j++) { 01524 01525 swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition%d", 01526 i, j); 01527 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01528 01529 status = HalpQueryPartitionType(&deviceName, layout, 01530 &partitionType); 01531 if (!NT_SUCCESS(status)) { 01532 break; 01533 } 01534 01535 if (partitionType != BOOTABLE_PARTITION) { 01536 continue; 01537 } 01538 01539 bootable = TRUE; 01540 01541 HalpNextDriveLetter(&deviceName, NtDeviceName, NtSystemPath, FALSE); 01542 break; 01543 } 01544 01545 if (bootable) { 01546 if (layout) { 01547 ExFreePool(layout); 01548 } 01549 continue; 01550 } 01551 01552 for (j = 1; ; j++) { 01553 01554 swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition%d", 01555 i, j); 01556 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01557 01558 status = HalpQueryPartitionType(&deviceName, layout, 01559 &partitionType); 01560 if (!NT_SUCCESS(status)) { 01561 break; 01562 } 01563 01564 if (partitionType != PRIMARY_PARTITION) { 01565 continue; 01566 } 01567 01568 HalpNextDriveLetter(&deviceName, NtDeviceName, NtSystemPath, FALSE); 01569 break; 01570 } 01571 01572 if (layout) { 01573 ExFreePool(layout); 01574 } 01575 } 01576 01577 for (i = 0; i < diskCount; i++) { 01578 01579 swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition0", i); 01580 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01581 01582 status = HalpQueryDriveLayout(&deviceName, &layout); 01583 if (!NT_SUCCESS(status)) { 01584 layout = NULL; 01585 } 01586 01587 for (j = 1; ; j++) { 01588 01589 swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition%d", 01590 i, j); 01591 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01592 01593 status = HalpQueryPartitionType(&deviceName, layout, 01594 &partitionType); 01595 if (!NT_SUCCESS(status)) { 01596 break; 01597 } 01598 01599 if (partitionType != LOGICAL_PARTITION) { 01600 continue; 01601 } 01602 01603 HalpNextDriveLetter(&deviceName, NtDeviceName, NtSystemPath, FALSE); 01604 } 01605 01606 if (layout) { 01607 ExFreePool(layout); 01608 } 01609 } 01610 01611 for (i = 0; i < diskCount; i++) { 01612 01613 swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition0", i); 01614 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01615 01616 status = HalpQueryDriveLayout(&deviceName, &layout); 01617 if (!NT_SUCCESS(status)) { 01618 layout = NULL; 01619 } 01620 01621 skip = 0; 01622 for (j = 1; ; j++) { 01623 01624 swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition%d", 01625 i, j); 01626 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01627 01628 status = HalpQueryPartitionType(&deviceName, layout, 01629 &partitionType); 01630 if (!NT_SUCCESS(status)) { 01631 break; 01632 } 01633 01634 if (partitionType == BOOTABLE_PARTITION) { 01635 skip = j; 01636 } else if (partitionType == PRIMARY_PARTITION) { 01637 if (!skip) { 01638 skip = j; 01639 } 01640 } 01641 } 01642 01643 for (j = 1; ; j++) { 01644 01645 if (j == skip) { 01646 continue; 01647 } 01648 01649 swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition%d", 01650 i, j); 01651 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01652 01653 status = HalpQueryPartitionType(&deviceName, layout, 01654 &partitionType); 01655 if (!NT_SUCCESS(status)) { 01656 break; 01657 } 01658 01659 if (partitionType != PRIMARY_PARTITION && 01660 partitionType != FT_PARTITION) { 01661 01662 continue; 01663 } 01664 01665 HalpNextDriveLetter(&deviceName, NtDeviceName, NtSystemPath, FALSE); 01666 } 01667 01668 if (layout) { 01669 ExFreePool(layout); 01670 } 01671 } 01672 01673 for (i = 0; i < floppyCount; i++) { 01674 01675 swprintf(deviceNameBuffer, L"\\Device\\Floppy%d", i); 01676 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01677 01678 if (!HalpIsOldStyleFloppy(&deviceName)) { 01679 continue; 01680 } 01681 01682 HalpNextDriveLetter(&deviceName, NtDeviceName, NtSystemPath, TRUE); 01683 } 01684 01685 for (i = 0; i < floppyCount; i++) { 01686 01687 swprintf(deviceNameBuffer, L"\\Device\\Floppy%d", i); 01688 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01689 01690 if (HalpIsOldStyleFloppy(&deviceName)) { 01691 continue; 01692 } 01693 01694 HalpNextDriveLetter(&deviceName, NtDeviceName, NtSystemPath, TRUE); 01695 } 01696 01697 for (i = 0; i < configurationInformation->CdRomCount; i++) { 01698 01699 swprintf(deviceNameBuffer, L"\\Device\\CdRom%d", i); 01700 RtlInitUnicodeString(&deviceName, deviceNameBuffer); 01701 01702 HalpNextDriveLetter(&deviceName, NtDeviceName, NtSystemPath, TRUE); 01703 } 01704 01705 if (!IoRemoteBootClient) { 01706 RtlAnsiStringToUnicodeString(&unicodeString, NtDeviceName, TRUE); 01707 driveLetter = HalpNextDriveLetter(&unicodeString, NULL, NULL, TRUE); 01708 if (driveLetter) { 01709 if (driveLetter != 0xFF) { 01710 NtSystemPath[0] = driveLetter; 01711 } 01712 } else { 01713 RtlInitUnicodeString(&floppyPrefix, L"\\Device\\Floppy"); 01714 RtlInitUnicodeString(&cdromPrefix, L"\\Device\\CdRom"); 01715 if (RtlPrefixUnicodeString(&floppyPrefix, &unicodeString, TRUE)) { 01716 driveLetter = 'A'; 01717 } else if (RtlPrefixUnicodeString(&cdromPrefix, &unicodeString, TRUE)) { 01718 driveLetter = 'D'; 01719 } else { 01720 driveLetter = 'C'; 01721 } 01722 for (; driveLetter <= 'Z'; driveLetter++) { 01723 status = HalpSetMountLetter(&unicodeString, driveLetter); 01724 if (NT_SUCCESS(status)) { 01725 NtSystemPath[0] = driveLetter; 01726 } 01727 } 01728 } 01729 RtlFreeUnicodeString(&unicodeString); 01730 } 01731 01732 HalpEnableAutomaticDriveLetterAssignment(); 01733 01734 } // end IoAssignDriveLetters()

NTSTATUS FASTCALL xHalIoClearPartitionTable IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  SectorSize,
IN ULONG  SectorsPerTrack,
IN ULONG  NumberOfHeads
 

Definition at line 3486 of file drivesup.c.

References BOOT_RECORD_SIGNATURE, BOOT_SIGNATURE_OFFSET, ExAllocatePoolWithTag, Executive, ExFreePool(), FALSE, _IO_STACK_LOCATION::Flags, HalExamineMBR, IoBuildSynchronousFsdRequest(), IoCallDriver, IoGetNextIrpStackLocation, IRP_MJ_READ, IRP_MJ_WRITE, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NonPagedPoolCacheAligned, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, PAGED_CODE, PUSHORT, SectorSize, SL_OVERRIDE_VERIFY_VOLUME, TRUE, USHORT, VOID(), WHICH_BIT, and xHalGetPartialGeometry().

03495 : 03496 03497 This routine walks the disk writing the partition tables from 03498 the entries in the partition list buffer for each partition. 03499 03500 Applications that create and delete partitions should issue a 03501 IoReadPartitionTable call with the 'return recognized partitions' 03502 boolean set to false to get a full description of the system. 03503 03504 Then the drive layout structure can be modified by the application to 03505 reflect the new configuration of the disk and then is written back 03506 to the disk using this routine. 03507 03508 Arguments: 03509 03510 DeviceObject - Pointer to device object for this disk. 03511 03512 SectorSize - Sector size on the device. 03513 03514 SectorsPerTrack - Track size on the device. 03515 03516 NumberOfHeads - Same as tracks per cylinder. 03517 03518 Return Value: 03519 03520 The functional value is STATUS_SUCCESS if all writes are completed 03521 without error. 03522 03523 --*/ 03524 03525 { 03526 typedef struct _PARTITION_TABLE { 03527 PARTITION_INFORMATION PartitionEntry[4]; 03528 } PARTITION_TABLE, *PPARTITION_TABLE; 03529 03530 typedef struct _DISK_LAYOUT { 03531 ULONG TableCount; 03532 ULONG Signature; 03533 PARTITION_TABLE PartitionTable[1]; 03534 } DISK_LAYOUT, *PDISK_LAYOUT; 03535 03536 typedef struct _PTE { 03537 UCHAR ActiveFlag; // Bootable or not 03538 UCHAR StartingTrack; // Not used 03539 USHORT StartingCylinder; // Not used 03540 UCHAR PartitionType; // 12 bit FAT, 16 bit FAT etc. 03541 UCHAR EndingTrack; // Not used 03542 USHORT EndingCylinder; // Not used 03543 ULONG StartingSector; // Hidden sectors 03544 ULONG PartitionLength; // Sectors in this partition 03545 } PTE; 03546 typedef PTE UNALIGNED *PPTE; 03547 03548 // 03549 // This macro has the effect of Bit = log2(Data) 03550 // 03551 03552 #define WHICH_BIT(Data, Bit) { \ 03553 for (Bit = 0; Bit < 32; Bit++) { \ 03554 if ((Data >> Bit) == 1) { \ 03555 break; \ 03556 } \ 03557 } \ 03558 } 03559 03560 ULONG writeSize; 03561 PUSHORT writeBuffer = NULL; 03562 PPARTITION_TABLE partitionTable; 03563 CCHAR shiftCount; 03564 LARGE_INTEGER partitionTableOffset; 03565 LARGE_INTEGER nextRecordOffset; 03566 ULONG partitionTableCount; 03567 KEVENT event; 03568 IO_STATUS_BLOCK ioStatus; 03569 PIRP irp; 03570 BOOLEAN rewritePartition = FALSE; 03571 NTSTATUS status = STATUS_SUCCESS; 03572 LARGE_INTEGER tempInt; 03573 BOOLEAN foundEZHooker = FALSE; 03574 ULONG conventionalCylinders; 03575 LONGLONG diskSize; 03576 03577 BOOLEAN isSuperFloppy = FALSE; 03578 03579 // 03580 // Ensure that no one is calling this function illegally. 03581 // 03582 03583 PAGED_CODE(); 03584 03585 // 03586 // Determine the size of a write operation to ensure that at least 512 03587 // bytes are written. This will guarantee that enough data is written to 03588 // include an entire partition table. Note that this code assumes that 03589 // the actual sector size of the disk (if less than 512 bytes) is a 03590 // multiple of 2, a fairly reasonable assumption. 03591 // 03592 03593 if (SectorSize >= 512) { 03594 writeSize = SectorSize; 03595 } else { 03596 writeSize = 512; 03597 } 03598 03599 xHalGetPartialGeometry( DeviceObject, 03600 &conventionalCylinders, 03601 &diskSize ); 03602 03603 // 03604 // Look to see if this is an EZDrive Disk. If it is then get the 03605 // real partititon table at 1. 03606 // 03607 03608 { 03609 03610 PVOID buff; 03611 03612 HalExamineMBR( 03613 DeviceObject, 03614 writeSize, 03615 (ULONG)0x55, 03616 &buff 03617 ); 03618 03619 if (buff) { 03620 03621 foundEZHooker = TRUE; 03622 ExFreePool(buff); 03623 partitionTableOffset.QuadPart = 512; 03624 03625 } else { 03626 03627 partitionTableOffset.QuadPart = 0; 03628 03629 } 03630 03631 } 03632 03633 // 03634 // Calculate shift count for converting between byte and sector. 03635 // 03636 03637 WHICH_BIT( SectorSize, shiftCount ); 03638 03639 // 03640 // Allocate a buffer for the sector writes. 03641 // 03642 03643 writeBuffer = ExAllocatePoolWithTag( NonPagedPoolCacheAligned, PAGE_SIZE, 'btsF'); 03644 03645 if (writeBuffer == NULL) { 03646 return STATUS_INSUFFICIENT_RESOURCES; 03647 } 03648 03649 // 03650 // Read the boot record that's already there into the write buffer 03651 // and save its boot code area if the signature is valid. This way 03652 // we don't clobber any boot code that might be there already. 03653 // 03654 03655 KeInitializeEvent( &event, SynchronizationEvent, FALSE ); 03656 03657 irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, 03658 DeviceObject, 03659 writeBuffer, 03660 writeSize, 03661 &partitionTableOffset, 03662 &event, 03663 &ioStatus ); 03664 03665 if (!irp) { 03666 ExFreePool(writeBuffer); 03667 return STATUS_INSUFFICIENT_RESOURCES; 03668 } 03669 03670 status = IoCallDriver( DeviceObject, irp ); 03671 03672 if (status == STATUS_PENDING) { 03673 (VOID) KeWaitForSingleObject( &event, 03674 Executive, 03675 KernelMode, 03676 FALSE, 03677 (PLARGE_INTEGER) NULL); 03678 status = ioStatus.Status; 03679 } 03680 03681 if (!NT_SUCCESS( status )) { 03682 ExFreePool(writeBuffer); 03683 return status; 03684 } 03685 03686 // 03687 // If there's an 0xaa55 in the MBR signature, clear it out. 03688 // 03689 03690 if(writeBuffer[BOOT_SIGNATURE_OFFSET] == BOOT_RECORD_SIGNATURE) { 03691 writeBuffer[BOOT_SIGNATURE_OFFSET] += 0x1111; 03692 } 03693 03694 irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, 03695 DeviceObject, 03696 writeBuffer, 03697 writeSize, 03698 &partitionTableOffset, 03699 &event, 03700 &ioStatus ); 03701 03702 if (!irp) { 03703 ExFreePool(writeBuffer); 03704 return STATUS_INSUFFICIENT_RESOURCES; 03705 } else { 03706 PIO_STACK_LOCATION irpStack; 03707 irpStack = IoGetNextIrpStackLocation(irp); 03708 irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 03709 } 03710 03711 status = IoCallDriver( DeviceObject, irp ); 03712 03713 if (status == STATUS_PENDING) { 03714 (VOID) KeWaitForSingleObject( &event, 03715 Executive, 03716 KernelMode, 03717 FALSE, 03718 (PLARGE_INTEGER) NULL); 03719 status = ioStatus.Status; 03720 } 03721 03722 // 03723 // Deallocate write buffer if it was allocated it. 03724 // 03725 03726 ExFreePool( writeBuffer ); 03727 03728 return status; 03729 }

NTSTATUS FASTCALL xHalIoReadPartitionTable IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  SectorSize,
IN BOOLEAN  ReturnRecognizedPartitions,
OUT struct _DRIVE_LAYOUT_INFORMATION **  PartitionBuffer
 

Definition at line 1739 of file drivesup.c.

References _PARTITION_DESCRIPTOR::ActiveFlag, ASSERT, BOOT_RECORD_SIGNATURE, BOOT_SIGNATURE_OFFSET, DebugPrint, DrivesupBreakIn, ExAllocatePoolWithTag, Executive, ExFreePool(), FALSE, _IO_STACK_LOCATION::Flags, GET_PARTITION_LENGTH, GET_STARTING_SECTOR, HalExamineMBR, HalpGetFullGeometry(), HalpIsValidPartitionEntry(), IoBuildSynchronousFsdRequest(), IoCallDriver, IoGetNextIrpStackLocation, IRP_MJ_READ, _BOOT_SECTOR_INFO::JumpByte, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NonPagedPool, NonPagedPoolCacheAligned, NT_SUCCESS, NTSTATUS(), NULL, NUM_PARTITION_TABLE_ENTRIES, PAGE_SIZE, PAGED_CODE, PARTITION_ACTIVE_FLAG, PARTITION_BUFFER_SIZE, PARTITION_TABLE_OFFSET, _PARTITION_DESCRIPTOR::PartitionType, PBOOT_SECTOR_INFO, PUSHORT, SectorSize, SL_OVERRIDE_VERIFY_VOLUME, TRUE, and VOID().

01748 : 01749 01750 This routine walks the disk reading the partition tables and creates 01751 an entry in the partition list buffer for each partition. 01752 01753 The algorithm used by this routine is two-fold: 01754 01755 1) Read each partition table and for each valid, recognized 01756 partition found, to build a descriptor in a partition list. 01757 Extended partitions are located in order to find other 01758 partition tables, but no descriptors are built for these. 01759 The partition list is built in nonpaged pool that is allocated 01760 by this routine. It is the caller's responsibility to free 01761 this pool after it has gathered the appropriate information 01762 from the list. 01763 01764 2) Read each partition table and for each and every entry, build 01765 a descriptor in the partition list. Extended partitions are 01766 located to find each partition table on the disk, and entries 01767 are built for these as well. The partition list is build in 01768 nonpaged pool that is allocated by this routine. It is the 01769 caller's responsibility to free this pool after it has copied 01770 the information back to its caller. 01771 01772 The first algorithm is used when the ReturnRecognizedPartitions flag 01773 is set. This is used to determine how many partition device objects 01774 the device driver is to create, and where each lives on the drive. 01775 01776 The second algorithm is used when the ReturnRecognizedPartitions flag 01777 is clear. This is used to find all of the partition tables and their 01778 entries for a utility such as fdisk, that would like to revamp where 01779 the partitions live. 01780 01781 Arguments: 01782 01783 DeviceObject - Pointer to device object for this disk. 01784 01785 SectorSize - Sector size on the device. 01786 01787 ReturnRecognizedPartitions - A flag indicated whether only recognized 01788 partition descriptors are to be returned, or whether all partition 01789 entries are to be returned. 01790 01791 PartitionBuffer - Pointer to the pointer of the buffer in which the list 01792 of partition will be stored. 01793 01794 Return Value: 01795 01796 The functional value is STATUS_SUCCESS if at least one sector table was 01797 read. 01798 01799 Notes: 01800 01801 It is the responsibility of the caller to deallocate the partition list 01802 buffer allocated by this routine. 01803 01804 --*/ 01805 01806 { 01807 ULONG partitionBufferSize = PARTITION_BUFFER_SIZE; 01808 PDRIVE_LAYOUT_INFORMATION newPartitionBuffer = NULL; 01809 01810 LONG partitionTableCounter = -1; 01811 01812 DISK_GEOMETRY diskGeometry; 01813 ULONGLONG endSector; 01814 ULONGLONG maxSector; 01815 ULONGLONG maxOffset; 01816 01817 LARGE_INTEGER partitionTableOffset; 01818 LARGE_INTEGER volumeStartOffset; 01819 LARGE_INTEGER tempInt; 01820 BOOLEAN primaryPartitionTable; 01821 LONG partitionNumber; 01822 PUCHAR readBuffer = (PUCHAR) NULL; 01823 KEVENT event; 01824 01825 IO_STATUS_BLOCK ioStatus; 01826 PIRP irp; 01827 PPARTITION_DESCRIPTOR partitionTableEntry; 01828 CCHAR partitionEntry; 01829 NTSTATUS status = STATUS_SUCCESS; 01830 ULONG readSize; 01831 PPARTITION_INFORMATION partitionInfo; 01832 BOOLEAN foundEZHooker = FALSE; 01833 01834 BOOLEAN mbrSignatureFound = FALSE; 01835 BOOLEAN emptyPartitionTable = TRUE; 01836 01837 PAGED_CODE(); 01838 01839 // 01840 // Create the buffer that will be passed back to the driver containing 01841 // the list of partitions on the disk. 01842 // 01843 01844 *PartitionBuffer = ExAllocatePoolWithTag( NonPagedPool, 01845 partitionBufferSize, 01846 'btsF' ); 01847 01848 if (*PartitionBuffer == NULL) { 01849 return STATUS_INSUFFICIENT_RESOURCES; 01850 } 01851 01852 // 01853 // Determine the size of a read operation to ensure that at least 512 01854 // bytes are read. This will guarantee that enough data is read to 01855 // include an entire partition table. Note that this code assumes that 01856 // the actual sector size of the disk (if less than 512 bytes) is a 01857 // multiple of 2, a fairly reasonable assumption. 01858 // 01859 01860 if (SectorSize >= 512) { 01861 readSize = SectorSize; 01862 } else { 01863 readSize = 512; 01864 } 01865 01866 // 01867 // Look to see if this is an EZDrive Disk. If it is then get the 01868 // real parititon table at 1. 01869 // 01870 01871 { 01872 01873 PVOID buff; 01874 01875 HalExamineMBR( 01876 DeviceObject, 01877 readSize, 01878 (ULONG)0x55, 01879 &buff 01880 ); 01881 01882 if (buff) { 01883 01884 foundEZHooker = TRUE; 01885 ExFreePool(buff); 01886 partitionTableOffset.QuadPart = 512; 01887 01888 } else { 01889 01890 partitionTableOffset.QuadPart = 0; 01891 01892 } 01893 01894 } 01895 01896 // 01897 // Get the drive size so we can verify that the partition table is 01898 // correct. 01899 // 01900 01901 status = HalpGetFullGeometry(DeviceObject, 01902 &diskGeometry, 01903 &maxOffset); 01904 01905 if(!NT_SUCCESS(status)) { 01906 ExFreePool(*PartitionBuffer); 01907 *PartitionBuffer = NULL; 01908 return status; 01909 } 01910 01911 // 01912 // Partition offsets need to fit on the disk or we're not going to 01913 // expose them. Partition ends are generally very very sloppy so we 01914 // need to allow some slop. Adding in a cylinders worth isn't enough 01915 // so now we'll assume that all partitions end within 2x of the real end 01916 // of the disk. 01917 // 01918 01919 endSector = maxOffset; 01920 01921 maxSector = maxOffset * 2; 01922 01923 DebugPrint((2, "MaxOffset = %#I64x, maxSector = %#I64x\n", 01924 maxOffset, maxSector)); 01925 01926 // 01927 // Indicate that the primary partition table is being read and 01928 // processed. 01929 // 01930 01931 primaryPartitionTable = TRUE; 01932 01933 // 01934 // The partitions in this volume have their start sector as 0. 01935 // 01936 01937 volumeStartOffset.QuadPart = 0; 01938 01939 // 01940 // Initialize the number of partitions in the list. 01941 // 01942 01943 partitionNumber = -1; 01944 01945 // 01946 // Allocate a buffer that will hold the reads. 01947 // 01948 01949 readBuffer = ExAllocatePoolWithTag( NonPagedPoolCacheAligned, 01950 PAGE_SIZE, 01951 'btsF' ); 01952 01953 if (readBuffer == NULL) { 01954 ExFreePool( *PartitionBuffer ); 01955 return STATUS_INSUFFICIENT_RESOURCES; 01956 } 01957 01958 // 01959 // Read each partition table, create an object for the partition(s) 01960 // it represents, and then if there is a link entry to another 01961 // partition table, repeat. 01962 // 01963 01964 do { 01965 01966 BOOLEAN tableIsValid; 01967 ULONG containerPartitionCount; 01968 01969 tableIsValid = TRUE; 01970 01971 // 01972 // Read record containing partition table. 01973 // 01974 // Create a notification event object to be used while waiting for 01975 // the read request to complete. 01976 // 01977 01978 KeInitializeEvent( &event, NotificationEvent, FALSE ); 01979 01980 // 01981 // Zero out the buffer we're reading into. In case we get back 01982 // STATUS_NO_DATA_DETECTED we'll be prepared. 01983 // 01984 01985 RtlZeroMemory(readBuffer, readSize); 01986 01987 irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, 01988 DeviceObject, 01989 readBuffer, 01990 readSize, 01991 &partitionTableOffset, 01992 &event, 01993 &ioStatus ); 01994 01995 if (!irp) { 01996 status = STATUS_INSUFFICIENT_RESOURCES; 01997 break; 01998 } else { 01999 PIO_STACK_LOCATION irpStack; 02000 irpStack = IoGetNextIrpStackLocation(irp); 02001 irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 02002 } 02003 02004 status = IoCallDriver( DeviceObject, irp ); 02005 02006 if (status == STATUS_PENDING) { 02007 (VOID) KeWaitForSingleObject( &event, 02008 Executive, 02009 KernelMode, 02010 FALSE, 02011 (PLARGE_INTEGER) NULL); 02012 status = ioStatus.Status; 02013 } 02014 02015 // 02016 // Special case - if we got a blank-check reading the sector then 02017 // pretend it was just successful so we can deal with superfloppies 02018 // where noone bothered to write anything to the non-filesystem sectors 02019 // 02020 02021 if(status == STATUS_NO_DATA_DETECTED) { 02022 status = STATUS_SUCCESS; 02023 } 02024 02025 if (!NT_SUCCESS( status )) { 02026 break; 02027 } 02028 02029 // 02030 // If EZDrive is hooking the MBR then we found the first partition table 02031 // in sector 1 rather than 0. However that partition table is relative 02032 // to sector zero. So, Even though we got it from one, reset the partition 02033 // offset to 0. 02034 // 02035 02036 if (foundEZHooker && (partitionTableOffset.QuadPart == 512)) { 02037 02038 partitionTableOffset.QuadPart = 0; 02039 02040 } 02041 02042 // 02043 // Check for Boot Record signature. 02044 // 02045 02046 if (((PUSHORT) readBuffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) { 02047 02048 DebugPrint((1, "xHalIoReadPT: No 0xaa55 found in partition table %d\n", 02049 partitionTableCounter + 1)); 02050 02051 break; 02052 02053 } else { 02054 mbrSignatureFound = TRUE; 02055 } 02056 02057 // 02058 // Copy NTFT disk signature to buffer 02059 // 02060 02061 if (partitionTableOffset.QuadPart == 0) { 02062 (*PartitionBuffer)->Signature = ((PULONG) readBuffer)[PARTITION_TABLE_OFFSET/2-1]; 02063 } 02064 02065 partitionTableEntry = (PPARTITION_DESCRIPTOR) &(((PUSHORT) readBuffer)[PARTITION_TABLE_OFFSET]); 02066 02067 // 02068 // Keep count of partition tables in case we have an extended partition; 02069 // 02070 02071 partitionTableCounter++; 02072 02073 // 02074 // First create the objects corresponding to the entries in this 02075 // table that are not link entries or are unused. 02076 // 02077 02078 DebugPrint((2, "Partition Table %d:\n", partitionTableCounter)); 02079 02080 for (partitionEntry = 1, containerPartitionCount = 0; 02081 partitionEntry <= NUM_PARTITION_TABLE_ENTRIES; 02082 partitionEntry++, partitionTableEntry++) { 02083 02084 DebugPrint((2, "Partition Entry %d,%d: type %#x %s\n", 02085 partitionTableCounter, 02086 partitionEntry, 02087 partitionTableEntry->PartitionType, 02088 (partitionTableEntry->ActiveFlag) ? "Active" : "")); 02089 02090 DebugPrint((2, "\tOffset %#08lx for %#08lx Sectors\n", 02091 GET_STARTING_SECTOR(partitionTableEntry), 02092 GET_PARTITION_LENGTH(partitionTableEntry))); 02093 // 02094 // Do a quick pass over the entry to see if this table is valid. 02095 // It's only fatal if the master partition table is invalid. 02096 // 02097 02098 if((HalpIsValidPartitionEntry(partitionTableEntry, 02099 maxOffset, 02100 maxSector) == FALSE) && 02101 (partitionTableCounter == 0)) { 02102 02103 ASSERT(DrivesupBreakIn == FALSE); 02104 DrivesupBreakIn = FALSE; 02105 tableIsValid = FALSE; 02106 break; 02107 02108 } 02109 // 02110 // Only one container partition is allowed per table - any more 02111 // and it's invalid. 02112 // 02113 02114 if(IsContainerPartition(partitionTableEntry->PartitionType)) { 02115 02116 containerPartitionCount++; 02117 02118 if(containerPartitionCount != 1) { 02119 02120 DebugPrint((1, "Multiple container partitions found in " 02121 "partition table %d\n - table is invalid\n", 02122 partitionTableCounter)); 02123 tableIsValid = FALSE; 02124 break; 02125 } 02126 02127 } 02128 02129 if(emptyPartitionTable) { 02130 02131 if((GET_STARTING_SECTOR(partitionTableEntry) != 0) || 02132 (GET_PARTITION_LENGTH(partitionTableEntry) != 0)) { 02133 02134 // 02135 // There's a valid, non-empty partition here. The table 02136 // is not empty. 02137 // 02138 02139 emptyPartitionTable = FALSE; 02140 } 02141 } 02142 02143 // 02144 // If the partition entry is not used or not recognized, skip 02145 // it. Note that this is only done if the caller wanted only 02146 // recognized partition descriptors returned. 02147 // 02148 02149 if (ReturnRecognizedPartitions) { 02150 02151 // 02152 // Check if partition type is 0 (unused) or 5/f (extended). 02153 // The definition of recognized partitions has broadened 02154 // to include any partition type other than 0 or 5/f. 02155 // 02156 02157 if ((partitionTableEntry->PartitionType == PARTITION_ENTRY_UNUSED) || 02158 IsContainerPartition(partitionTableEntry->PartitionType)) { 02159 02160 continue; 02161 } 02162 } 02163 02164 // 02165 // Bump up to the next partition entry. 02166 // 02167 02168 partitionNumber++; 02169 02170 if (((partitionNumber * sizeof( PARTITION_INFORMATION )) + 02171 sizeof( DRIVE_LAYOUT_INFORMATION )) > 02172 (ULONG) partitionBufferSize) { 02173 02174 // 02175 // The partition list is too small to contain all of the 02176 // entries, so create a buffer that is twice as large to 02177 // store the partition list and copy the old buffer into 02178 // the new one. 02179 // 02180 02181 newPartitionBuffer = ExAllocatePoolWithTag( NonPagedPool, 02182 partitionBufferSize << 1, 02183 'btsF' ); 02184 02185 if (newPartitionBuffer == NULL) { 02186 --partitionNumber; 02187 status = STATUS_INSUFFICIENT_RESOURCES; 02188 break; 02189 } 02190 02191 RtlMoveMemory( newPartitionBuffer, 02192 *PartitionBuffer, 02193 partitionBufferSize ); 02194 02195 ExFreePool( *PartitionBuffer ); 02196 02197 // 02198 // Reassign the new buffer to the return parameter and 02199 // reset the size of the buffer. 02200 // 02201 02202 *PartitionBuffer = newPartitionBuffer; 02203 partitionBufferSize <<= 1; 02204 } 02205 02206 // 02207 // Describe this partition table entry in the partition list 02208 // entry being built for the driver. This includes writing 02209 // the partition type, starting offset of the partition, and 02210 // the length of the partition. 02211 // 02212 02213 partitionInfo = &(*PartitionBuffer)->PartitionEntry[partitionNumber]; 02214 02215 partitionInfo->PartitionType = partitionTableEntry->PartitionType; 02216 02217 partitionInfo->RewritePartition = FALSE; 02218 02219 if (partitionTableEntry->PartitionType != PARTITION_ENTRY_UNUSED) { 02220 LONGLONG startOffset; 02221 02222 partitionInfo->BootIndicator = 02223 partitionTableEntry->ActiveFlag & PARTITION_ACTIVE_FLAG ? 02224 (BOOLEAN) TRUE : (BOOLEAN) FALSE; 02225 02226 if (IsContainerPartition(partitionTableEntry->PartitionType)) { 02227 partitionInfo->RecognizedPartition = FALSE; 02228 startOffset = volumeStartOffset.QuadPart; 02229 } else { 02230 partitionInfo->RecognizedPartition = TRUE; 02231 startOffset = partitionTableOffset.QuadPart; 02232 } 02233 02234 partitionInfo->StartingOffset.QuadPart = startOffset + 02235 UInt32x32To64(GET_STARTING_SECTOR(partitionTableEntry), 02236 SectorSize); 02237 tempInt.QuadPart = (partitionInfo->StartingOffset.QuadPart - 02238 startOffset) / SectorSize; 02239 partitionInfo->HiddenSectors = tempInt.LowPart; 02240 02241 partitionInfo->PartitionLength.QuadPart = 02242 UInt32x32To64(GET_PARTITION_LENGTH(partitionTableEntry), 02243 SectorSize); 02244 02245 } else { 02246 02247 // 02248 // Partitions that are not used do not describe any part 02249 // of the disk. These types are recorded in the partition 02250 // list buffer when the caller requested all of the entries 02251 // be returned. Simply zero out the remaining fields in 02252 // the entry. 02253 // 02254 02255 partitionInfo->BootIndicator = FALSE; 02256 partitionInfo->RecognizedPartition = FALSE; 02257 partitionInfo->StartingOffset.QuadPart = 0; 02258 partitionInfo->PartitionLength.QuadPart = 0; 02259 partitionInfo->HiddenSectors = 0; 02260 } 02261 02262 } 02263 02264 DebugPrint((2, "\n")); 02265 02266 // 02267 // If an error occurred, leave the routine now. 02268 // 02269 02270 if (!NT_SUCCESS( status )) { 02271 break; 02272 } 02273 02274 if(tableIsValid == FALSE) { 02275 02276 // 02277 // Invalidate this partition table and stop looking for new ones. 02278 // we'll build the partition list based on the ones we found 02279 // previously. 02280 // 02281 02282 partitionTableCounter--; 02283 break; 02284 } 02285 02286 // 02287 // Now check to see if there are any link entries in this table, 02288 // and if so, set up the sector address of the next partition table. 02289 // There can only be one link entry in each partition table, and it 02290 // will point to the next table. 02291 // 02292 02293 partitionTableEntry = (PPARTITION_DESCRIPTOR) &(((PUSHORT) readBuffer)[PARTITION_TABLE_OFFSET]); 02294 02295 // 02296 // Assume that the link entry is empty. 02297 // 02298 02299 partitionTableOffset.QuadPart = 0; 02300 02301 for (partitionEntry = 1; 02302 partitionEntry <= NUM_PARTITION_TABLE_ENTRIES; 02303 partitionEntry++, partitionTableEntry++) { 02304 02305 if (IsContainerPartition(partitionTableEntry->PartitionType)) { 02306 02307 // 02308 // Obtain the address of the next partition table on the 02309 // disk. This is the number of hidden sectors added to 02310 // the beginning of the extended partition (in the case of 02311 // logical drives), since all logical drives are relative 02312 // to the extended partition. The VolumeStartSector will 02313 // be zero if this is the primary parition table. 02314 // 02315 02316 partitionTableOffset.QuadPart = volumeStartOffset.QuadPart + 02317 UInt32x32To64(GET_STARTING_SECTOR(partitionTableEntry), 02318 SectorSize); 02319 02320 // 02321 // Set the VolumeStartSector to be the begining of the 02322 // second partition (extended partition) because all of 02323 // the offsets to the partition tables of the logical drives 02324 // are relative to this extended partition. 02325 // 02326 02327 if (primaryPartitionTable) { 02328 volumeStartOffset = partitionTableOffset; 02329 } 02330 02331 // 02332 // Update the maximum sector to be the end of the container 02333 // partition. 02334 // 02335 02336 maxSector = GET_PARTITION_LENGTH(partitionTableEntry); 02337 02338 DebugPrint((2, "MaxSector now = %#08lx\n", maxSector)); 02339 02340 // 02341 // There is only ever one link entry per partition table, 02342 // exit the loop once it has been found. 02343 // 02344 02345 break; 02346 } 02347 } 02348 02349 02350 // 02351 // All the other partitions will be logical drives. 02352 // 02353 02354 primaryPartitionTable = FALSE; 02355 02356 02357 } while (partitionTableOffset.HighPart | partitionTableOffset.LowPart); 02358 02359 // 02360 // Detect super-floppy media attempt #1. 02361 // If the media is removable and has an 0xaa55 signature on it and 02362 // is empty then check to see if we can recognize the BPB. If we recognize 02363 // a jump-byte at the beginning of the media then it's a super floppy. If 02364 // we don't then it's an unpartitioned disk. 02365 // 02366 02367 DebugPrint((4, "xHalIoReadPartitionTable: RM %d PTC %d MBR %d EPT %d\n", 02368 diskGeometry.MediaType, 02369 partitionTableCounter, 02370 mbrSignatureFound, 02371 emptyPartitionTable)); 02372 02373 if((diskGeometry.MediaType == RemovableMedia) && 02374 (partitionTableCounter == 0) && 02375 (mbrSignatureFound == TRUE) && 02376 (emptyPartitionTable == TRUE)) { 02377 02378 PBOOT_SECTOR_INFO bootSector = (PBOOT_SECTOR_INFO) readBuffer; 02379 02380 if((bootSector->JumpByte[0] == 0xeb) || 02381 (bootSector->JumpByte[0] == 0xe9)) { 02382 02383 // 02384 // We've got a superfloppy of some sort. 02385 // 02386 02387 DebugPrint((1, "xHalIoReadPartitionTable: Jump byte %#x found " 02388 "along with empty partition table - disk is a " 02389 "super floppy and has no valid MBR\n", 02390 bootSector->JumpByte)); 02391 02392 partitionTableCounter = -1; 02393 } 02394 } 02395 02396 // 02397 // If the partition table count is still -1 then we didn't find any 02398 // valid partition records. In this case we'll build a partition list 02399 // that contiains one partition spanning the entire disk. 02400 // 02401 02402 if(partitionTableCounter == -1) { 02403 02404 if((mbrSignatureFound == TRUE) || 02405 (diskGeometry.MediaType == RemovableMedia)) { 02406 02407 // 02408 // Either we found a signature but the partition layout was 02409 // invalid (for all disks) or we didn't find a signature but this 02410 // is a removable disk. Either of these two cases makes a 02411 // superfloppy. 02412 // 02413 02414 DebugPrint((1, "xHalIoReadPartitionTable: Drive %#p has no valid MBR. " 02415 "Make it into a super-floppy\n", DeviceObject)); 02416 02417 DebugPrint((1, "xHalIoReadPartitionTable: Drive has %#08lx sectors " 02418 "and is %#016I64x bytes large\n", 02419 endSector, endSector * diskGeometry.BytesPerSector)); 02420 02421 if (endSector > 0) { 02422 02423 partitionInfo = &(*PartitionBuffer)->PartitionEntry[0]; 02424 02425 partitionInfo->RewritePartition = FALSE; 02426 partitionInfo->RecognizedPartition = TRUE; 02427 partitionInfo->PartitionType = PARTITION_FAT_16; 02428 partitionInfo->BootIndicator = FALSE; 02429 02430 partitionInfo->HiddenSectors = 0; 02431 02432 partitionInfo->StartingOffset.QuadPart = 0; 02433 02434 partitionInfo->PartitionLength.QuadPart = 02435 (endSector * diskGeometry.BytesPerSector); 02436 02437 (*PartitionBuffer)->Signature = 1; 02438 02439 partitionNumber = 0; 02440 } 02441 } else { 02442 02443 // 02444 // We found no partitions. Make sure the partition count is -1 02445 // so that we setup a zeroed-out partition table below. 02446 // 02447 02448 partitionNumber = -1; 02449 } 02450 } 02451 02452 // 02453 // Fill in the first field in the PartitionBuffer. This field indicates how 02454 // many partition entries there are in the PartitionBuffer. 02455 // 02456 02457 (*PartitionBuffer)->PartitionCount = ++partitionNumber; 02458 02459 if (!partitionNumber) { 02460 02461 // 02462 // Zero out disk signature. 02463 // 02464 02465 (*PartitionBuffer)->Signature = 0; 02466 } 02467 02468 // 02469 // Deallocate read buffer if it was allocated it. 02470 // 02471 02472 if (readBuffer != NULL) { 02473 ExFreePool( readBuffer ); 02474 } 02475 02476 if (!NT_SUCCESS(status)) { 02477 ExFreePool(*PartitionBuffer); 02478 *PartitionBuffer = NULL; 02479 } 02480 return status; 02481 }

NTSTATUS FASTCALL xHalIoSetPartitionInformation IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  SectorSize,
IN ULONG  PartitionNumber,
IN ULONG  PartitionType
 

Definition at line 2485 of file drivesup.c.

References BOOT_RECORD_SIGNATURE, BOOT_SIGNATURE_OFFSET, ExAllocatePoolWithTag, Executive, ExFreePool(), FALSE, _IO_STACK_LOCATION::Flags, GET_STARTING_SECTOR, HalExamineMBR, IoBuildSynchronousFsdRequest(), IoCallDriver, IoGetNextIrpStackLocation, IRP_MJ_READ, IRP_MJ_WRITE, KeInitializeEvent, KeResetEvent(), KernelMode, KeWaitForSingleObject(), NonPagedPoolCacheAligned, NT_SUCCESS, NTSTATUS(), NULL, NUM_PARTITION_TABLE_ENTRIES, PAGE_SIZE, PAGED_CODE, PARTITION_TABLE_OFFSET, _PARTITION_DESCRIPTOR::PartitionType, PUSHORT, SectorSize, SL_OVERRIDE_VERIFY_VOLUME, TRUE, and VOID().

02494 : 02495 02496 This routine is invoked when a disk device driver is asked to set the 02497 partition type in a partition table entry via an I/O control code. This 02498 control code is generally issued by the format utility just after it 02499 has formatted the partition. The format utility performs the I/O control 02500 function on the partition and the driver passes the address of the base 02501 physical device object and the number of the partition associated with 02502 the device object that the format utility has open. If this routine 02503 returns success, then the disk driver should updates its notion of the 02504 partition type for this partition in its device extension. 02505 02506 Arguments: 02507 02508 DeviceObject - Pointer to the base physical device object for the device 02509 on which the partition type is to be set. 02510 02511 SectorSize - Supplies the size of a sector on the disk in bytes. 02512 02513 PartitionNumber - Specifies the partition number on the device whose 02514 partition type is to be changed. 02515 02516 PartitionType - Specifies the new type for the partition. 02517 02518 Return Value: 02519 02520 The function value is the final status of the operation. 02521 02522 Notes: 02523 02524 This routine is synchronous. Therefore, it MUST be invoked by the disk 02525 driver's dispatch routine, or by a disk driver's thread. Likewise, all 02526 users, FSP threads, etc., must be prepared to enter a wait state when 02527 issuing the I/O control code to set the partition type for the device. 02528 02529 Note also that this routine assumes that the partition number passed 02530 in by the disk driver actually exists since the driver itself supplies 02531 this parameter. 02532 02533 Finally, note that this routine may NOT be invoked at APC_LEVEL. It 02534 must be invoked at PASSIVE_LEVEL. This is due to the fact that this 02535 routine uses a kernel event object to synchronize I/O completion on the 02536 device. The event cannot be set to the signaled state without queueing 02537 the I/O system's special kernel APC routine for I/O completion and 02538 executing it. (This rules is a bit esoteric since it only holds true 02539 if the device driver returns something other than STATUS_PENDING, which 02540 it will probably never do.) 02541 02542 --*/ 02543 02544 { 02545 02546 #define GET_STARTING_SECTOR( p ) ( \ 02547 (ULONG) (p->StartingSectorLsb0) + \ 02548 (ULONG) (p->StartingSectorLsb1 << 8) + \ 02549 (ULONG) (p->StartingSectorMsb0 << 16) + \ 02550 (ULONG) (p->StartingSectorMsb1 << 24) ) 02551 02552 PIRP irp; 02553 KEVENT event; 02554 IO_STATUS_BLOCK ioStatus; 02555 NTSTATUS status; 02556 LARGE_INTEGER partitionTableOffset; 02557 LARGE_INTEGER volumeStartOffset; 02558 PUCHAR buffer = (PUCHAR) NULL; 02559 ULONG transferSize; 02560 ULONG partitionNumber; 02561 ULONG partitionEntry; 02562 PPARTITION_DESCRIPTOR partitionTableEntry; 02563 BOOLEAN primaryPartitionTable; 02564 BOOLEAN foundEZHooker = FALSE; 02565 02566 PAGED_CODE(); 02567 02568 // 02569 // Begin by determining the size of the buffer required to read and write 02570 // the partition information to/from the disk. This is done to ensure 02571 // that at least 512 bytes are read, thereby guaranteeing that enough data 02572 // is read to include an entire partition table. Note that this code 02573 // assumes that the actual sector size of the disk (if less than 512 02574 // bytes) is a multiple of 2, a 02575 // fairly reasonable assumption. 02576 // 02577 02578 if (SectorSize >= 512) { 02579 transferSize = SectorSize; 02580 } else { 02581 transferSize = 512; 02582 } 02583 02584 02585 // 02586 // Look to see if this is an EZDrive Disk. If it is then get the 02587 // real parititon table at 1. 02588 // 02589 02590 { 02591 02592 PVOID buff; 02593 02594 HalExamineMBR( 02595 DeviceObject, 02596 transferSize, 02597 (ULONG)0x55, 02598 &buff 02599 ); 02600 02601 if (buff) { 02602 02603 foundEZHooker = TRUE; 02604 ExFreePool(buff); 02605 partitionTableOffset.QuadPart = 512; 02606 02607 } else { 02608 02609 partitionTableOffset.QuadPart = 0; 02610 02611 } 02612 02613 } 02614 02615 02616 // 02617 // The partitions in this primary partition have their start sector 0. 02618 // 02619 02620 volumeStartOffset.QuadPart = 0; 02621 02622 // 02623 // Indicate that the table being read and processed is the primary partition 02624 // table. 02625 // 02626 02627 primaryPartitionTable = TRUE; 02628 02629 // 02630 // Initialize the number of partitions found thus far. 02631 // 02632 02633 partitionNumber = 0; 02634 02635 // 02636 // Allocate a buffer that will hold the read/write data. 02637 // 02638 02639 buffer = ExAllocatePoolWithTag( NonPagedPoolCacheAligned, PAGE_SIZE, 'btsF'); 02640 if (buffer == NULL) { 02641 return STATUS_INSUFFICIENT_RESOURCES; 02642 } 02643 02644 // 02645 // Initialize a kernel event to use in synchronizing device requests 02646 // with I/O completion. 02647 // 02648 02649 KeInitializeEvent( &event, NotificationEvent, FALSE ); 02650 02651 // 02652 // Read each partition table scanning for the partition table entry that 02653 // the caller wishes to modify. 02654 // 02655 02656 do { 02657 02658 // 02659 // Read the record containing the partition table. 02660 // 02661 02662 (VOID) KeResetEvent( &event ); 02663 02664 irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, 02665 DeviceObject, 02666 buffer, 02667 transferSize, 02668 &partitionTableOffset, 02669 &event, 02670 &ioStatus ); 02671 02672 if (!irp) { 02673 status = STATUS_INSUFFICIENT_RESOURCES; 02674 break; 02675 } else { 02676 PIO_STACK_LOCATION irpStack; 02677 irpStack = IoGetNextIrpStackLocation(irp); 02678 irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 02679 } 02680 02681 status = IoCallDriver( DeviceObject, irp ); 02682 02683 if (status == STATUS_PENDING) { 02684 (VOID) KeWaitForSingleObject( &event, 02685 Executive, 02686 KernelMode, 02687 FALSE, 02688 (PLARGE_INTEGER) NULL ); 02689 status = ioStatus.Status; 02690 } 02691 02692 if (!NT_SUCCESS( status )) { 02693 break; 02694 } 02695 02696 // 02697 // If EZDrive is hooking the MBR then we found the first partition table 02698 // in sector 1 rather than 0. However that partition table is relative 02699 // to sector zero. So, Even though we got it from one, reset the partition 02700 // offset to 0. 02701 // 02702 02703 if (foundEZHooker && (partitionTableOffset.QuadPart == 512)) { 02704 02705 partitionTableOffset.QuadPart = 0; 02706 02707 } 02708 02709 // 02710 // Check for a valid Boot Record signature in the partition table 02711 // record. 02712 // 02713 02714 if (((PUSHORT) buffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) { 02715 status = STATUS_BAD_MASTER_BOOT_RECORD; 02716 break; 02717 } 02718 02719 partitionTableEntry = (PPARTITION_DESCRIPTOR) &(((PUSHORT) buffer)[PARTITION_TABLE_OFFSET]); 02720 02721 // 02722 // Scan the partition entries in this partition table to determine if 02723 // any of the entries are the desired entry. Each entry in each 02724 // table must be scanned in the same order as in IoReadPartitionTable 02725 // so that the partition table entry cooresponding to the driver's 02726 // notion of the partition number can be located. 02727 // 02728 02729 for (partitionEntry = 1; 02730 partitionEntry <= NUM_PARTITION_TABLE_ENTRIES; 02731 partitionEntry++, partitionTableEntry++) { 02732 02733 02734 // 02735 // If the partition entry is empty or for an extended, skip it. 02736 // 02737 02738 if ((partitionTableEntry->PartitionType == PARTITION_ENTRY_UNUSED) || 02739 IsContainerPartition(partitionTableEntry->PartitionType)) { 02740 continue; 02741 } 02742 02743 // 02744 // A valid partition entry that is recognized has been located. 02745 // Bump the count and check to see if this entry is the desired 02746 // entry. 02747 // 02748 02749 partitionNumber++; 02750 02751 if (partitionNumber == PartitionNumber) { 02752 02753 // 02754 // This is the desired partition that is to be changed. Simply 02755 // overwrite the partition type and write the entire partition 02756 // buffer back out to the disk. 02757 // 02758 02759 partitionTableEntry->PartitionType = (UCHAR) PartitionType; 02760 02761 (VOID) KeResetEvent( &event ); 02762 02763 irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, 02764 DeviceObject, 02765 buffer, 02766 transferSize, 02767 &partitionTableOffset, 02768 &event, 02769 &ioStatus ); 02770 02771 if (!irp) { 02772 status = STATUS_INSUFFICIENT_RESOURCES; 02773 break; 02774 } else { 02775 PIO_STACK_LOCATION irpStack; 02776 irpStack = IoGetNextIrpStackLocation(irp); 02777 irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 02778 } 02779 02780 status = IoCallDriver( DeviceObject, irp ); 02781 02782 if (status == STATUS_PENDING) { 02783 (VOID) KeWaitForSingleObject( &event, 02784 Executive, 02785 KernelMode, 02786 FALSE, 02787 (PLARGE_INTEGER) NULL ); 02788 status = ioStatus.Status; 02789 } 02790 02791 break; 02792 } 02793 } 02794 02795 // 02796 // If all of the entries in the current buffer were scanned and the 02797 // desired entry was not found, then continue. Otherwise, leave the 02798 // routine. 02799 // 02800 02801 if (partitionEntry <= NUM_PARTITION_TABLE_ENTRIES) { 02802 break; 02803 } 02804 02805 // 02806 // Now scan the current buffer to locate an extended partition entry 02807 // in the table so that its partition information can be read. There 02808 // can only be one extended partition entry in each partition table, 02809 // and it will point to the next table. 02810 // 02811 02812 partitionTableEntry = (PPARTITION_DESCRIPTOR) &(((PUSHORT) buffer)[PARTITION_TABLE_OFFSET]); 02813 02814 for (partitionEntry = 1; 02815 partitionEntry <= NUM_PARTITION_TABLE_ENTRIES; 02816 partitionEntry++, partitionTableEntry++) { 02817 02818 if (IsContainerPartition(partitionTableEntry->PartitionType)) { 02819 02820 // 02821 // Obtain the address of the next partition table on the disk. 02822 // This is the number of hidden sectors added to the beginning 02823 // of the extended partition (in the case of logical drives), 02824 // since all logical drives are relative to the extended 02825 // partition. The starting offset of the volume will be zero 02826 // if this is the primary partition table. 02827 // 02828 02829 partitionTableOffset.QuadPart = volumeStartOffset.QuadPart + 02830 UInt32x32To64(GET_STARTING_SECTOR(partitionTableEntry), 02831 SectorSize); 02832 02833 // 02834 // Set the starting offset of the volume to be the beginning of 02835 // the second partition (the extended partition) because all of 02836 // the offsets to the partition tables of the logical drives 02837 // are relative to this extended partition. 02838 // 02839 02840 if (primaryPartitionTable) { 02841 volumeStartOffset = partitionTableOffset; 02842 } 02843 02844 break; 02845 } 02846 } 02847 02848 // 02849 // Ensure that a partition entry was located that was an extended 02850 // partition, otherwise the desired partition will never be found. 02851 // 02852 02853 if (partitionEntry > NUM_PARTITION_TABLE_ENTRIES) { 02854 status = STATUS_BAD_MASTER_BOOT_RECORD; 02855 break; 02856 } 02857 02858 // 02859 // All the other partitions will be logical drives. 02860 // 02861 02862 primaryPartitionTable = FALSE; 02863 02864 } while (partitionNumber < PartitionNumber); 02865 02866 // 02867 // If a data buffer was successfully allocated, deallocate it now. 02868 // 02869 02870 if (buffer != NULL) { 02871 ExFreePool( buffer ); 02872 } 02873 02874 return status; 02875 }

NTSTATUS FASTCALL xHalIoWritePartitionTable IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  SectorSize,
IN ULONG  SectorsPerTrack,
IN ULONG  NumberOfHeads,
IN struct _DRIVE_LAYOUT_INFORMATION *  PartitionBuffer
 

Definition at line 2879 of file drivesup.c.

References BOOT_RECORD_SIGNATURE, BOOT_SIGNATURE_OFFSET, ExAllocatePoolWithTag, Executive, ExFreePool(), FALSE, _IO_STACK_LOCATION::Flags, HalExamineMBR, HalpCalculateChsValues(), IoBuildSynchronousFsdRequest(), IoCallDriver, IoGetNextIrpStackLocation, IRP_MJ_READ, IRP_MJ_WRITE, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NonPagedPoolCacheAligned, NT_SUCCESS, NTSTATUS(), NULL, NUM_PARTITION_TABLE_ENTRIES, PAGE_SIZE, PAGED_CODE, PARTITION_ACTIVE_FLAG, PARTITION_TABLE_OFFSET, PUSHORT, SectorSize, SL_OVERRIDE_VERIFY_VOLUME, TRUE, USHORT, VOID(), WHICH_BIT, and xHalGetPartialGeometry().

02889 : 02890 02891 This routine walks the disk writing the partition tables from 02892 the entries in the partition list buffer for each partition. 02893 02894 Applications that create and delete partitions should issue a 02895 IoReadPartitionTable call with the 'return recognized partitions' 02896 boolean set to false to get a full description of the system. 02897 02898 Then the drive layout structure can be modified by the application to 02899 reflect the new configuration of the disk and then is written back 02900 to the disk using this routine. 02901 02902 Arguments: 02903 02904 DeviceObject - Pointer to device object for this disk. 02905 02906 SectorSize - Sector size on the device. 02907 02908 SectorsPerTrack - Track size on the device. 02909 02910 NumberOfHeads - Same as tracks per cylinder. 02911 02912 PartitionBuffer - Pointer drive layout buffer. 02913 02914 Return Value: 02915 02916 The functional value is STATUS_SUCCESS if all writes are completed 02917 without error. 02918 02919 --*/ 02920 02921 { 02922 typedef struct _PARTITION_TABLE { 02923 PARTITION_INFORMATION PartitionEntry[4]; 02924 } PARTITION_TABLE, *PPARTITION_TABLE; 02925 02926 typedef struct _DISK_LAYOUT { 02927 ULONG TableCount; 02928 ULONG Signature; 02929 PARTITION_TABLE PartitionTable[1]; 02930 } DISK_LAYOUT, *PDISK_LAYOUT; 02931 02932 typedef struct _PTE { 02933 UCHAR ActiveFlag; // Bootable or not 02934 UCHAR StartingTrack; // Not used 02935 USHORT StartingCylinder; // Not used 02936 UCHAR PartitionType; // 12 bit FAT, 16 bit FAT etc. 02937 UCHAR EndingTrack; // Not used 02938 USHORT EndingCylinder; // Not used 02939 ULONG StartingSector; // Hidden sectors 02940 ULONG PartitionLength; // Sectors in this partition 02941 } PTE; 02942 typedef PTE UNALIGNED *PPTE; 02943 02944 // 02945 // This macro has the effect of Bit = log2(Data) 02946 // 02947 02948 #define WHICH_BIT(Data, Bit) { \ 02949 for (Bit = 0; Bit < 32; Bit++) { \ 02950 if ((Data >> Bit) == 1) { \ 02951 break; \ 02952 } \ 02953 } \ 02954 } 02955 02956 ULONG writeSize; 02957 PUSHORT writeBuffer = NULL; 02958 PPTE partitionEntry; 02959 PPARTITION_TABLE partitionTable; 02960 CCHAR shiftCount; 02961 LARGE_INTEGER partitionTableOffset; 02962 LARGE_INTEGER nextRecordOffset; 02963 ULONG partitionTableCount; 02964 ULONG partitionEntryCount; 02965 KEVENT event; 02966 IO_STATUS_BLOCK ioStatus; 02967 PIRP irp; 02968 BOOLEAN rewritePartition = FALSE; 02969 NTSTATUS status = STATUS_SUCCESS; 02970 LARGE_INTEGER tempInt; 02971 BOOLEAN foundEZHooker = FALSE; 02972 ULONG conventionalCylinders; 02973 LONGLONG diskSize; 02974 02975 BOOLEAN isSuperFloppy = FALSE; 02976 02977 // 02978 // Cast to a structure that is easier to use. 02979 // 02980 02981 PDISK_LAYOUT diskLayout = (PDISK_LAYOUT) PartitionBuffer; 02982 02983 // 02984 // Ensure that no one is calling this function illegally. 02985 // 02986 02987 PAGED_CODE(); 02988 02989 // 02990 // Determine the size of a write operation to ensure that at least 512 02991 // bytes are written. This will guarantee that enough data is written to 02992 // include an entire partition table. Note that this code assumes that 02993 // the actual sector size of the disk (if less than 512 bytes) is a 02994 // multiple of 2, a fairly reasonable assumption. 02995 // 02996 02997 if (SectorSize >= 512) { 02998 writeSize = SectorSize; 02999 } else { 03000 writeSize = 512; 03001 } 03002 03003 xHalGetPartialGeometry( DeviceObject, 03004 &conventionalCylinders, 03005 &diskSize ); 03006 03007 // 03008 // Look to see if this is an EZDrive Disk. If it is then get the 03009 // real partititon table at 1. 03010 // 03011 03012 { 03013 03014 PVOID buff; 03015 03016 HalExamineMBR( 03017 DeviceObject, 03018 writeSize, 03019 (ULONG)0x55, 03020 &buff 03021 ); 03022 03023 if (buff) { 03024 03025 foundEZHooker = TRUE; 03026 ExFreePool(buff); 03027 partitionTableOffset.QuadPart = 512; 03028 03029 } else { 03030 03031 partitionTableOffset.QuadPart = 0; 03032 03033 } 03034 03035 } 03036 03037 // 03038 // Initialize starting variables. 03039 // 03040 03041 nextRecordOffset.QuadPart = 0; 03042 03043 // 03044 // Calculate shift count for converting between byte and sector. 03045 // 03046 03047 WHICH_BIT( SectorSize, shiftCount ); 03048 03049 // 03050 // Check to see if this device is partitioned (or is being partitioned) 03051 // as a floppy. Floppys have a single partititon with hidden sector count 03052 // and partition offset equal to zero. If the disk is being partitioned 03053 // like this then we need to be sure not to write an MBR signature or 03054 // an NTFT signature to the media. 03055 // 03056 // NOTE: this is only to catch ourself when someone tries to write the 03057 // existing partition table back to disk. Any changes to the table will 03058 // result in a real MBR being written out. 03059 // 03060 03061 if(PartitionBuffer->PartitionCount == 1) { 03062 03063 PPARTITION_INFORMATION partitionEntry = PartitionBuffer->PartitionEntry; 03064 03065 if((partitionEntry->StartingOffset.QuadPart == 0) && 03066 (partitionEntry->HiddenSectors == 0)) { 03067 03068 isSuperFloppy = TRUE; 03069 03070 // 03071 // This would indeed appear to be an attempt to format a floppy. 03072 // Make sure the other parameters match the defaut values we 03073 // provide in ReadParititonTable. If they don't then fail 03074 // the write operation. 03075 // 03076 03077 if((partitionEntry->PartitionNumber != 0) || 03078 (partitionEntry->PartitionType != PARTITION_FAT_16) || 03079 (partitionEntry->BootIndicator == TRUE)) { 03080 03081 return STATUS_INVALID_PARAMETER; 03082 } 03083 03084 if(partitionEntry->RewritePartition == TRUE) { 03085 rewritePartition = TRUE; 03086 } 03087 03088 foundEZHooker = FALSE; 03089 } 03090 } 03091 03092 // 03093 // Convert partition count to partition table or boot sector count. 03094 // 03095 03096 diskLayout->TableCount = 03097 (PartitionBuffer->PartitionCount + 03098 NUM_PARTITION_TABLE_ENTRIES - 1) / 03099 NUM_PARTITION_TABLE_ENTRIES; 03100 03101 // 03102 // Allocate a buffer for the sector writes. 03103 // 03104 03105 writeBuffer = ExAllocatePoolWithTag( NonPagedPoolCacheAligned, PAGE_SIZE, 'btsF'); 03106 03107 if (writeBuffer == NULL) { 03108 return STATUS_INSUFFICIENT_RESOURCES; 03109 } 03110 03111 // 03112 // Point to the partition table entries in write buffer. 03113 // 03114 03115 partitionEntry = (PPTE) &writeBuffer[PARTITION_TABLE_OFFSET]; 03116 03117 for (partitionTableCount = 0; 03118 partitionTableCount < diskLayout->TableCount; 03119 partitionTableCount++) { 03120 03121 UCHAR partitionType; 03122 03123 // 03124 // the first partition table is in the mbr (physical sector 0). 03125 // other partition tables are in ebr's within the extended partition. 03126 // 03127 03128 BOOLEAN mbr = (BOOLEAN) (!partitionTableCount); 03129 LARGE_INTEGER extendedPartitionOffset; 03130 03131 // 03132 // Read the boot record that's already there into the write buffer 03133 // and save its boot code area if the signature is valid. This way 03134 // we don't clobber any boot code that might be there already. 03135 // 03136 03137 KeInitializeEvent( &event, NotificationEvent, FALSE ); 03138 03139 irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, 03140 DeviceObject, 03141 writeBuffer, 03142 writeSize, 03143 &partitionTableOffset, 03144 &event, 03145 &ioStatus ); 03146 03147 if (!irp) { 03148 status = STATUS_INSUFFICIENT_RESOURCES; 03149 break; 03150 } else { 03151 PIO_STACK_LOCATION irpStack; 03152 irpStack = IoGetNextIrpStackLocation(irp); 03153 irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 03154 } 03155 03156 status = IoCallDriver( DeviceObject, irp ); 03157 03158 if (status == STATUS_PENDING) { 03159 (VOID) KeWaitForSingleObject( &event, 03160 Executive, 03161 KernelMode, 03162 FALSE, 03163 (PLARGE_INTEGER) NULL); 03164 status = ioStatus.Status; 03165 } 03166 03167 if (!NT_SUCCESS( status )) { 03168 break; 03169 } 03170 03171 // 03172 // If EZDrive is hooking the MBR then we found the first partition table 03173 // in sector 1 rather than 0. However that partition table is relative 03174 // to sector zero. So, Even though we got it from one, reset the partition 03175 // offset to 0. 03176 // 03177 03178 if (foundEZHooker && (partitionTableOffset.QuadPart == 512)) { 03179 03180 partitionTableOffset.QuadPart = 0; 03181 03182 } 03183 03184 if(isSuperFloppy == FALSE) { 03185 03186 // 03187 // Write signature to last word of boot sector. 03188 // 03189 03190 writeBuffer[BOOT_SIGNATURE_OFFSET] = BOOT_RECORD_SIGNATURE; 03191 03192 // 03193 // Write NTFT disk signature if it changed and this is the MBR. 03194 // 03195 03196 rewritePartition = FALSE; 03197 if (partitionTableOffset.QuadPart == 0) { 03198 03199 if (((PULONG)writeBuffer)[PARTITION_TABLE_OFFSET/2-1] != 03200 PartitionBuffer->Signature) { 03201 03202 ((PULONG) writeBuffer)[PARTITION_TABLE_OFFSET/2-1] = 03203 PartitionBuffer->Signature; 03204 rewritePartition = TRUE; 03205 } 03206 } 03207 03208 // 03209 // Get pointer to first partition table. 03210 // 03211 03212 partitionTable = &diskLayout->PartitionTable[partitionTableCount]; 03213 03214 // 03215 // Walk table to determine whether this boot record has changed 03216 // and update partition table in write buffer in case it needs 03217 // to be written out to disk. 03218 // 03219 03220 for (partitionEntryCount = 0; 03221 partitionEntryCount < NUM_PARTITION_TABLE_ENTRIES; 03222 partitionEntryCount++) { 03223 03224 partitionType = 03225 partitionTable->PartitionEntry[partitionEntryCount].PartitionType; 03226 03227 // 03228 // If the rewrite ISN'T true then copy then just leave the data 03229 // alone that is in the on-disk table. 03230 // 03231 03232 if (partitionTable->PartitionEntry[partitionEntryCount].RewritePartition) { 03233 03234 // 03235 // This boot record needs to be written back to disk. 03236 // 03237 03238 rewritePartition = TRUE; 03239 03240 // 03241 // Copy partition type from user buffer to write buffer. 03242 // 03243 03244 partitionEntry[partitionEntryCount].PartitionType = 03245 partitionTable->PartitionEntry[partitionEntryCount].PartitionType; 03246 03247 // 03248 // Copy the partition active flag. 03249 // 03250 03251 partitionEntry[partitionEntryCount].ActiveFlag = 03252 partitionTable->PartitionEntry[partitionEntryCount].BootIndicator ? 03253 (UCHAR) PARTITION_ACTIVE_FLAG : (UCHAR) 0; 03254 03255 if (partitionType != PARTITION_ENTRY_UNUSED) { 03256 03257 LARGE_INTEGER sectorOffset; 03258 03259 // 03260 // Calculate partition offset. 03261 // If in the mbr or the entry is not a link entry, partition offset 03262 // is sectors past last boot record. Otherwise (not in the mbr and 03263 // entry is a link entry), partition offset is sectors past start 03264 // of extended partition. 03265 // 03266 03267 if (mbr || !IsContainerPartition(partitionType)) { 03268 tempInt.QuadPart = partitionTableOffset.QuadPart; 03269 } else { 03270 tempInt.QuadPart = extendedPartitionOffset.QuadPart; 03271 } 03272 03273 sectorOffset.QuadPart = 03274 partitionTable->PartitionEntry[partitionEntryCount].StartingOffset.QuadPart - 03275 tempInt.QuadPart; 03276 03277 tempInt.QuadPart = sectorOffset.QuadPart >> shiftCount; 03278 partitionEntry[partitionEntryCount].StartingSector = tempInt.LowPart; 03279 03280 // 03281 // Calculate partition length. 03282 // 03283 03284 tempInt.QuadPart = partitionTable->PartitionEntry[partitionEntryCount].PartitionLength.QuadPart >> shiftCount; 03285 partitionEntry[partitionEntryCount].PartitionLength = tempInt.LowPart; 03286 03287 // 03288 // Fill in CHS values 03289 // 03290 03291 HalpCalculateChsValues( 03292 &partitionTable->PartitionEntry[partitionEntryCount].StartingOffset, 03293 &partitionTable->PartitionEntry[partitionEntryCount].PartitionLength, 03294 shiftCount, 03295 SectorsPerTrack, 03296 NumberOfHeads, 03297 conventionalCylinders, 03298 (PPARTITION_DESCRIPTOR) &partitionEntry[partitionEntryCount]); 03299 03300 } else { 03301 03302 // 03303 // Zero out partition entry fields in case an entry 03304 // was deleted. 03305 // 03306 03307 partitionEntry[partitionEntryCount].StartingSector = 0; 03308 partitionEntry[partitionEntryCount].PartitionLength = 0; 03309 partitionEntry[partitionEntryCount].StartingTrack = 0; 03310 partitionEntry[partitionEntryCount].EndingTrack = 0; 03311 partitionEntry[partitionEntryCount].StartingCylinder = 0; 03312 partitionEntry[partitionEntryCount].EndingCylinder = 0; 03313 } 03314 03315 } 03316 03317 if (IsContainerPartition(partitionType)) { 03318 03319 // 03320 // Save next record offset. 03321 // 03322 03323 nextRecordOffset = 03324 partitionTable->PartitionEntry[partitionEntryCount].StartingOffset; 03325 } 03326 03327 } // end for partitionEntryCount ... 03328 03329 } else { 03330 03331 // 03332 // If there's an 0xaa55 in the MBR signature, clear it out. 03333 // 03334 03335 // 03336 // BUGBUG - don't do this. 03337 // 03338 03339 if(writeBuffer[BOOT_SIGNATURE_OFFSET] == BOOT_RECORD_SIGNATURE) { 03340 // writeBuffer[BOOT_SIGNATURE_OFFSET] += 0x1111; 03341 } 03342 } 03343 03344 if (rewritePartition == TRUE) { 03345 03346 rewritePartition = FALSE; 03347 03348 // 03349 // Create a notification event object to be used while waiting for 03350 // the write request to complete. 03351 // 03352 03353 KeInitializeEvent( &event, NotificationEvent, FALSE ); 03354 03355 if (foundEZHooker && (partitionTableOffset.QuadPart == 0)) { 03356 03357 partitionTableOffset.QuadPart = 512; 03358 03359 } 03360 irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, 03361 DeviceObject, 03362 writeBuffer, 03363 writeSize, 03364 &partitionTableOffset, 03365 &event, 03366 &ioStatus ); 03367 03368 if (!irp) { 03369 status = STATUS_INSUFFICIENT_RESOURCES; 03370 break; 03371 } else { 03372 PIO_STACK_LOCATION irpStack; 03373 irpStack = IoGetNextIrpStackLocation(irp); 03374 irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 03375 } 03376 03377 status = IoCallDriver( DeviceObject, irp ); 03378 03379 if (status == STATUS_PENDING) { 03380 (VOID) KeWaitForSingleObject( &event, 03381 Executive, 03382 KernelMode, 03383 FALSE, 03384 (PLARGE_INTEGER) NULL); 03385 status = ioStatus.Status; 03386 } 03387 03388 if (!NT_SUCCESS( status )) { 03389 break; 03390 } 03391 03392 03393 if (foundEZHooker && (partitionTableOffset.QuadPart == 512)) { 03394 03395 partitionTableOffset.QuadPart = 0; 03396 03397 } 03398 03399 } // end if (reWrite ... 03400 03401 // 03402 // Update partitionTableOffset to next boot record offset 03403 // 03404 03405 partitionTableOffset = nextRecordOffset; 03406 if(mbr) { 03407 extendedPartitionOffset = nextRecordOffset; 03408 } 03409 03410 } // end for partitionTableCount ... 03411 03412 // 03413 // Deallocate write buffer if it was allocated it. 03414 // 03415 03416 if (writeBuffer != NULL) { 03417 ExFreePool( writeBuffer ); 03418 } 03419 03420 return status; 03421 }


Variable Documentation

PUCHAR DiskPartitionName = "\\Device\\Harddisk%d\\Partition%d" [static]
 

Definition at line 91 of file drivesup.c.

Referenced by xHalIoAssignDriveLetters().

ULONG DrivesupBreakIn = FALSE
 

Definition at line 43 of file drivesup.c.

Referenced by xHalIoReadPartitionTable().

ULONG DrivesupDebug = 0
 

Definition at line 42 of file drivesup.c.

Referenced by DrivesupDebugPrint().

PUCHAR RegistryKeyName = DISK_REGISTRY_KEY [static]
 

Definition at line 92 of file drivesup.c.


Generated on Sat May 15 19:43:30 2004 for test by doxygen 1.3.7