335 lines
9.6 KiB
C
335 lines
9.6 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
drivesup.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the subroutines for drive support. This includes
|
|||
|
such things as how drive letters are assigned on a particular platform,
|
|||
|
how device partitioning works, etc.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Darryl E. Havens (darrylh) 23-Apr-1992
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "halp.h"
|
|||
|
#include "bugcodes.h"
|
|||
|
|
|||
|
#include "ntddft.h"
|
|||
|
#include "ntdddisk.h"
|
|||
|
#include "ntdskreg.h"
|
|||
|
#include "stdio.h"
|
|||
|
#include "string.h"
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, IoAssignDriveLetters)
|
|||
|
#pragma alloc_text(PAGE, IoReadPartitionTable)
|
|||
|
#pragma alloc_text(PAGE, IoSetPartitionInformation)
|
|||
|
#pragma alloc_text(PAGE, IoWritePartitionTable)
|
|||
|
#endif
|
|||
|
|
|||
|
VOID
|
|||
|
IoAssignDriveLetters(
|
|||
|
PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|||
|
PSTRING NtDeviceName,
|
|||
|
OUT PUCHAR NtSystemPath,
|
|||
|
OUT PSTRING NtSystemPathString
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine assigns DOS drive letters to eligible disk partitions
|
|||
|
and CDROM drives. It also maps the partition containing the NT
|
|||
|
boot path to \SystemRoot. In NT, objects are built for all partition
|
|||
|
types except 0 (unused) and 5 (extended). But drive letters are assigned
|
|||
|
only to recognized partition types (1, 4, 6, and 7).
|
|||
|
|
|||
|
Drive letter assignment is done in several stages:
|
|||
|
|
|||
|
1) For each CdRom:
|
|||
|
Determine if sticky letters are assigned and reserve the letter.
|
|||
|
|
|||
|
2) For each disk:
|
|||
|
Determine how many primary partitions and which is bootable.
|
|||
|
Determine which partitions already have 'sticky letters'
|
|||
|
and create their symbolic links.
|
|||
|
Create a bit map for each disk that idicates which partitions
|
|||
|
require default drive letter assignments.
|
|||
|
|
|||
|
3) For each disk:
|
|||
|
Assign default drive letters for the bootable
|
|||
|
primary partition or the first nonbootable primary partition.
|
|||
|
|
|||
|
4) For each disk:
|
|||
|
Assign default drive letters for the partitions in
|
|||
|
extended volumes.
|
|||
|
|
|||
|
5) For each disk:
|
|||
|
Assign default drive letters for the remaining (ENHANCED)
|
|||
|
primary partitions.
|
|||
|
|
|||
|
6) Assign A: and B: to the first two floppies in the system if they
|
|||
|
exist. Then assign remaining floppies next available drive letters.
|
|||
|
|
|||
|
7) Assign drive letters to CdRoms (either sticky or default).
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LoaderBlock - pointer to a loader parameter block.
|
|||
|
|
|||
|
NtDeviceName - pointer to the boot device name string used
|
|||
|
to resolve NtSystemPath.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Stub to call extensible routine in ke so that hal vendors
|
|||
|
// don't have to support.
|
|||
|
//
|
|||
|
|
|||
|
HalIoAssignDriveLetters(
|
|||
|
LoaderBlock,
|
|||
|
NtDeviceName,
|
|||
|
NtSystemPath,
|
|||
|
NtSystemPathString
|
|||
|
);
|
|||
|
|
|||
|
} // end IoAssignDriveLetters()
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
IoReadPartitionTable(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN ULONG SectorSize,
|
|||
|
IN BOOLEAN ReturnRecognizedPartitions,
|
|||
|
OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine walks the disk reading the partition tables and creates
|
|||
|
an entry in the partition list buffer for each partition.
|
|||
|
|
|||
|
The algorithm used by this routine is two-fold:
|
|||
|
|
|||
|
1) Read each partition table and for each valid, recognized
|
|||
|
partition found, to build a descriptor in a partition list.
|
|||
|
Extended partitions are located in order to find other
|
|||
|
partition tables, but no descriptors are built for these.
|
|||
|
The partition list is built in nonpaged pool that is allocated
|
|||
|
by this routine. It is the caller's responsibility to free
|
|||
|
this pool after it has gathered the appropriate information
|
|||
|
from the list.
|
|||
|
|
|||
|
2) Read each partition table and for each and every entry, build
|
|||
|
a descriptor in the partition list. Extended partitions are
|
|||
|
located to find each partition table on the disk, and entries
|
|||
|
are built for these as well. The partition list is build in
|
|||
|
nonpaged pool that is allocated by this routine. It is the
|
|||
|
caller's responsibility to free this pool after it has copied
|
|||
|
the information back to its caller.
|
|||
|
|
|||
|
The first algorithm is used when the ReturnRecognizedPartitions flag
|
|||
|
is set. This is used to determine how many partition device objects
|
|||
|
the device driver is to create, and where each lives on the drive.
|
|||
|
|
|||
|
The second algorithm is used when the ReturnRecognizedPartitions flag
|
|||
|
is clear. This is used to find all of the partition tables and their
|
|||
|
entries for a utility such as fdisk, that would like to revamp where
|
|||
|
the partitions live.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceObject - Pointer to device object for this disk.
|
|||
|
|
|||
|
SectorSize - Sector size on the device.
|
|||
|
|
|||
|
ReturnRecognizedPartitions - A flag indicated whether only recognized
|
|||
|
partition descriptors are to be returned, or whether all partition
|
|||
|
entries are to be returned.
|
|||
|
|
|||
|
PartitionBuffer - Pointer to the pointer of the buffer in which the list
|
|||
|
of partition will be stored.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The functional value is STATUS_SUCCESS if at least one sector table was
|
|||
|
read.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
It is the responsibility of the caller to deallocate the partition list
|
|||
|
buffer allocated by this routine.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// Stub to call extensible routine in ke so that hal vendors
|
|||
|
// don't have to support.
|
|||
|
//
|
|||
|
|
|||
|
return HalIoReadPartitionTable(
|
|||
|
DeviceObject,
|
|||
|
SectorSize,
|
|||
|
ReturnRecognizedPartitions,
|
|||
|
PartitionBuffer
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
IoSetPartitionInformation(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN ULONG SectorSize,
|
|||
|
IN ULONG PartitionNumber,
|
|||
|
IN ULONG PartitionType
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is invoked when a disk device driver is asked to set the
|
|||
|
partition type in a partition table entry via an I/O control code. This
|
|||
|
control code is generally issued by the format utility just after it
|
|||
|
has formatted the partition. The format utility performs the I/O control
|
|||
|
function on the partition and the driver passes the address of the base
|
|||
|
physical device object and the number of the partition associated with
|
|||
|
the device object that the format utility has open. If this routine
|
|||
|
returns success, then the disk driver should updates its notion of the
|
|||
|
partition type for this partition in its device extension.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceObject - Pointer to the base physical device object for the device
|
|||
|
on which the partition type is to be set.
|
|||
|
|
|||
|
SectorSize - Supplies the size of a sector on the disk in bytes.
|
|||
|
|
|||
|
PartitionNumber - Specifies the partition number on the device whose
|
|||
|
partition type is to be changed.
|
|||
|
|
|||
|
PartitionType - Specifies the new type for the partition.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The function value is the final status of the operation.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
This routine is synchronous. Therefore, it MUST be invoked by the disk
|
|||
|
driver's dispatch routine, or by a disk driver's thread. Likewise, all
|
|||
|
users, FSP threads, etc., must be prepared to enter a wait state when
|
|||
|
issuing the I/O control code to set the partition type for the device.
|
|||
|
|
|||
|
Note also that this routine assumes that the partition number passed
|
|||
|
in by the disk driver actually exists since the driver itself supplies
|
|||
|
this parameter.
|
|||
|
|
|||
|
Finally, note that this routine may NOT be invoked at APC_LEVEL. It
|
|||
|
must be invoked at PASSIVE_LEVEL. This is due to the fact that this
|
|||
|
routine uses a kernel event object to synchronize I/O completion on the
|
|||
|
device. The event cannot be set to the signaled state without queueing
|
|||
|
the I/O system's special kernel APC routine for I/O completion and
|
|||
|
executing it. (This rules is a bit esoteric since it only holds true
|
|||
|
if the device driver returns something other than STATUS_PENDING, which
|
|||
|
it will probably never do.)
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// Stub to call extensible routine in ke so that hal vendors
|
|||
|
// don't have to support.
|
|||
|
//
|
|||
|
|
|||
|
return HalIoSetPartitionInformation(
|
|||
|
DeviceObject,
|
|||
|
SectorSize,
|
|||
|
PartitionNumber,
|
|||
|
PartitionType
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
IoWritePartitionTable(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN ULONG SectorSize,
|
|||
|
IN ULONG SectorsPerTrack,
|
|||
|
IN ULONG NumberOfHeads,
|
|||
|
IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine walks the disk writing the partition tables from
|
|||
|
the entries in the partition list buffer for each partition.
|
|||
|
|
|||
|
Applications that create and delete partitions should issue a
|
|||
|
IoReadPartitionTable call with the 'return recognized partitions'
|
|||
|
boolean set to false to get a full description of the system.
|
|||
|
|
|||
|
Then the drive layout structure can be modified by the application to
|
|||
|
reflect the new configuration of the disk and then is written back
|
|||
|
to the disk using this routine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceObject - Pointer to device object for this disk.
|
|||
|
|
|||
|
SectorSize - Sector size on the device.
|
|||
|
|
|||
|
SectorsPerTrack - Track size on the device.
|
|||
|
|
|||
|
NumberOfHeads - Same as tracks per cylinder.
|
|||
|
|
|||
|
PartitionBuffer - Pointer drive layout buffer.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The functional value is STATUS_SUCCESS if all writes are completed
|
|||
|
without error.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Stub to call extensible routine in ke so that hal vendors
|
|||
|
// don't have to support.
|
|||
|
//
|
|||
|
|
|||
|
return HalIoWritePartitionTable(
|
|||
|
DeviceObject,
|
|||
|
SectorSize,
|
|||
|
SectorsPerTrack,
|
|||
|
NumberOfHeads,
|
|||
|
PartitionBuffer
|
|||
|
);
|
|||
|
}
|