Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

442 lines
13 KiB

/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name:
parttype.h
Abstract:
Header file for routines used to determine the correct
partition type to use for a partition.
Author:
Ted Miller (tedm) 5 Feb 1997
Revision History:
--*/
#if _MSC_VER > 1000
#pragma once
#endif
//
// Define classes of partitions meaningful to partition type APIs.
//
typedef enum {
GenPartitionClassExtended, // container partition (type 5 or f)
GenPartitionClassFat12Or16, // fat (types 1,4,6,e)
GenPartitionClassFat32, // fat32 (types b,c)
GenPartitionClassNonFat, // type 7
GenPartitionClassMax
} GenPartitionClass;
//
// Flags for partition type APIs.
//
#define GENPARTTYPE_DISALLOW_XINT13 0x00000002
#define GENPARTTYPE_FORCE_XINT13 0x00000004
#ifdef __cplusplus
extern "C" {
#endif
//
// Routines.
//
NTSTATUS
GeneratePartitionType(
IN LPCWSTR NtDevicePath, OPTIONAL
IN HANDLE DeviceHandle, OPTIONAL
IN ULONGLONG StartSector,
IN ULONGLONG SectorCount,
IN GenPartitionClass PartitionClass,
IN ULONG Flags,
IN ULONG Reserved,
OUT PUCHAR Type
);
//
// Helper macros.
//
// (TedM) The mechanism for determining whether extended int13 is actually
// available on a drive is TBD. It is believed that the DISK_GEOMETRY structure
// will change to add an extra field or two to provide this information.
// Also, currently the disk drivers will increase the cylinder count if
// the drive reports more sectors than int13 function 8 reported. So for now
// we just see whether the partition ends on a cylinder > 1023. Both of these
// macros will need to be changed when the code to detect and report xint13 stuff
// becomes available in the system.
// (NorbertK) The right way to determine whether or not to use XINT13 is to just
// check where the partition lies. We should continue to use the old int13 for
// partitions that are contained in the first 1024 cylinders.
//
#define XINT13_DESIRED(geom,endsect) \
\
(((endsect) / ((geom)->TracksPerCylinder * (geom)->SectorsPerTrack)) > 1023)
#define XINT13_AVAILABLE(geom) TRUE
__inline
NTSTATUS
GeneratePartitionTypeWorker(
IN ULONGLONG StartSector,
IN ULONGLONG SectorCount,
IN GenPartitionClass PartitionClass,
IN ULONG Flags,
IN PDISK_GEOMETRY Geometry,
OUT PUCHAR Type
)
/*++
Routine Description:
Worker routine for GeneratePartitionType and RegeneratePartitionType.
Arguments:
StartSector - supplies start sector for partition
SectorCount - supplies number of sectors in the partition
PartitionClass - supplies class indicating intended use for the
partition.
Flags - supplies flags controlling operation.
Geometry - supplies disk geometry information for the disk.
Type - if successful, receives the type to be used.
Return Value:
NT Status code indicating outcome.
--*/
{
BOOLEAN UseXInt13;
if(!StartSector || !SectorCount) {
return(STATUS_INVALID_PARAMETER);
}
//
// Figure out whether extended int13 is desired for this drive.
//
if(Flags & GENPARTTYPE_DISALLOW_XINT13) {
UseXInt13 = FALSE;
} else {
if(Flags & GENPARTTYPE_FORCE_XINT13) {
UseXInt13 = TRUE;
} else {
//
// Need to figure it out.
//
UseXInt13 = FALSE;
if(XINT13_DESIRED(Geometry,StartSector+SectorCount-1) && XINT13_AVAILABLE(Geometry)) {
UseXInt13 = TRUE;
}
}
}
switch(PartitionClass) {
case GenPartitionClassExtended:
*Type = UseXInt13 ? PARTITION_XINT13_EXTENDED : PARTITION_EXTENDED;
break;
case GenPartitionClassFat12Or16:
if(UseXInt13) {
*Type = PARTITION_XINT13;
} else {
//
// Need to figure out which of the 3 FAT types to use.
//
if(SectorCount < 32680) {
*Type = PARTITION_FAT_12;
} else {
*Type = (SectorCount < 65536) ? PARTITION_FAT_16 : PARTITION_HUGE;
}
}
break;
case GenPartitionClassFat32:
*Type = UseXInt13 ? PARTITION_FAT32_XINT13 : PARTITION_FAT32;
break;
case GenPartitionClassNonFat:
*Type = PARTITION_IFS;
break;
default:
return(STATUS_INVALID_PARAMETER);
}
return(STATUS_SUCCESS);
}
__inline
NTSTATUS
pOpenDevice(
IN LPCWSTR NtPath,
OUT PHANDLE DeviceHandle
)
/*++
Routine Description:
Open an NT-style path, which is assumed to be for a disk device
or a partition. The open is share read/share write, for synch i/o
and read access.
Arguments:
NtPath - supplies nt-style pathname to open.
DeviceHandle - if successful, receives NT handle of open device.
Return Value:
NT Status code indicating outcome.
--*/
{
UNICODE_STRING UnicodeString;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
RtlInitUnicodeString(&UnicodeString,NtPath);
InitializeObjectAttributes(
&ObjectAttributes,
&UnicodeString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtCreateFile(
DeviceHandle,
STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_ALERT,
NULL,
0
);
return(Status);
}
__inline
NTSTATUS
RegeneratePartitionType(
IN LPCWSTR NtPartitionPath, OPTIONAL
IN HANDLE PartitionHandle, OPTIONAL
IN GenPartitionClass PartitionClass,
IN ULONG Flags,
IN ULONG Reserved,
OUT PUCHAR Type
)
/*++
Routine Description:
This routine determines the proper partition type to be used for an
existing partition, for example if the partition is being reformatted.
Arguments:
NtPartitionPath - supplies the NT-style path of the partition
whose type is to be recalculated, such as \Device\Harddisk1\Partition2.
This routine should not be called for partition0. If not specified,
PartitionHandle must be.
PartitionHandle - Supplies a handle to the partition whose type is to be
recalculated. The caller should have opened the partition for at least
FILE_READ_DATA and FILE_READ_ATTRIBUTES access. Ignored if
NtPartitionPath is specified.
PartitionClass - supplies a value indicating the intended use of the
partition.
GenPartitionClassExtended - inavalid with this routine.
GenPartitionClassFat12Or16 - indicates that the partition will be
used for a 12 or 16 bit FAT volume. The returned type will be
PARTITION_FAT_12 (1), PARTITION_FAT_16 (4), PARTITION_HUGE (6),
or PARTITION_XINT13 (e), depending on size and placement of the
partition, availability of extended int13 for the drive,
and the Flags parameter.
GenPartitionClassFat32 - indicates that the partition will be used
for a FAT32 volume. The returned type will be PARTITION_FAT32 (b)
or PARTITION_FAT32_XINT13 (c), depending on placement of the
partition, availability of extended int13 for the drive,
and the Flags parameter.
GenPartitionNonFat - indicates that the partition will be used for
a non-FAT volume. The returned type will be PARTITION_IFS (7).
It is advisable to call this routine even for type 7 partitions
since in the future additional partition types could be returned
in this case.
Flags - Supplies flags that further control operation of this routine.
GENPARTTYPE_DISALLOW_XINT13 - disallow extended int13 partition types.
If this flag is set, PARTITION_FAT32_XINT13 (c),
PARTITION_XINT13 (e), and PARTITION_XINT13_EXTENDED (f) will not
be returned as the partition type to be used. Not valid with
GENPARTTYPE_FORCE_XINT13.
GENPARTTYPE_FORCE_XINT13 - forces use of extended int13 partition types
even if not necessary for the partition being created. Not valid
with GENPARTTYPE_DISALLOW_XINT13.
Reserved - reserved, must be 0.
Type - if this routine succeeds, this value receives the partition type
to be used for the partition.
Return Value:
NT Status code indicating outcome. If NO_ERROR, Type is filled in with
the resulting partition type to be used.
--*/
{
NTSTATUS Status;
HANDLE DeviceHandle;
DISK_GEOMETRY Geometry;
IO_STATUS_BLOCK IoStatusBlock;
PARTITION_INFORMATION_EX PartitionInfo;
//
// Validate parameters.
//
if((Flags & GENPARTTYPE_DISALLOW_XINT13) && (Flags & GENPARTTYPE_FORCE_XINT13)) {
return(STATUS_INVALID_PARAMETER_3);
}
if((PartitionClass >= GenPartitionClassMax) || (PartitionClass == GenPartitionClassExtended)) {
return(STATUS_INVALID_PARAMETER_2);
}
if(Reserved) {
return(STATUS_INVALID_PARAMETER_4);
}
//
// Open the device if the caller specified a name. Otherwise use
// the handle the caller passed in.
//
if(NtPartitionPath) {
Status = pOpenDevice(NtPartitionPath,&DeviceHandle);
if(!NT_SUCCESS(Status)) {
return(Status);
}
} else {
DeviceHandle = PartitionHandle;
}
//
// Get drive geometry for the device.
//
Status = NtDeviceIoControlFile(
DeviceHandle,
NULL,NULL,NULL, // synchronous io
&IoStatusBlock,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,0, // no input buffer
&Geometry,
sizeof(DISK_GEOMETRY)
);
if(NT_SUCCESS(Status)) {
//
// Get partition info. We care about the start offset and size
// of the partition.
//
Status = NtDeviceIoControlFile(
DeviceHandle,
NULL,NULL,NULL, // synchronous io
&IoStatusBlock,
IOCTL_DISK_GET_PARTITION_INFO_EX,
NULL,0, // no input buffer
&PartitionInfo,
sizeof(PartitionInfo)
);
if (!NT_SUCCESS(Status)) {
if (Status == STATUS_INVALID_DEVICE_REQUEST) {
GET_LENGTH_INFORMATION LengthInfo;
Status = NtDeviceIoControlFile(DeviceHandle, 0, NULL, NULL,
&IoStatusBlock,
IOCTL_DISK_GET_LENGTH_INFO,
NULL, 0, &LengthInfo,
sizeof(GET_LENGTH_INFORMATION));
if (NT_SUCCESS(Status)) {
//
// GET_PARTITION_INFO_EX will fail outright on an EFI Dynamic
// Volume. In this case, just make up the starting offset
// so that FORMAT can proceed normally.
//
PartitionInfo.StartingOffset.QuadPart = 0x7E00;
PartitionInfo.PartitionLength.QuadPart = LengthInfo.Length.QuadPart;
}
}
}
if(NT_SUCCESS(Status)) {
//
// Call the worker routine to do the work.
//
Status = GeneratePartitionTypeWorker(
PartitionInfo.StartingOffset.QuadPart / Geometry.BytesPerSector,
PartitionInfo.PartitionLength.QuadPart / Geometry.BytesPerSector,
PartitionClass,
Flags,
&Geometry,
Type
);
}
}
if(NtPartitionPath) {
NtClose(DeviceHandle);
}
return(Status);
}
#ifdef __cplusplus
}
#endif