|
|
#if defined(REMOTE_BOOT)
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
sminit.c
Abstract:
Session Manager Initialization
Author:
Mark Lucovsky (markl) 04-Oct-1989
Revision History:
--*/
#include "smsrvp.h"
#include <stdio.h>
#include <string.h>
#include <safeboot.h>
#include <ntdddisk.h>
VOID SmpGetHarddiskBootPartition( OUT PULONG DiskNumber, OUT PULONG PartitionNumber ) /*++
Routine Description:
This routine searches the each partition on each hard disk for one which has the active bit set, returning the first one encountered.
Arguments:
DiskNumber - The harddisk number.
PartitionNumber - The partition number.
Return Value:
None
--*/
{ PARTITION_INFORMATION PartitionInfo; WCHAR NameBuffer[80]; HANDLE Handle; NTSTATUS Status; IO_STATUS_BLOCK IoStatus; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString;
*DiskNumber = 0; while (TRUE) {
//
// First check if there is any disk there at all by opening partition 0
//
*PartitionNumber = 0;
swprintf(NameBuffer, L"\\Device\\Harddisk%d\\Partition%d", *DiskNumber, *PartitionNumber);
RtlInitUnicodeString(&UnicodeString, NameBuffer);
InitializeObjectAttributes( &ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtCreateFile( &Handle, (ACCESS_MASK)FILE_GENERIC_READ, &ObjectAttributes, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
if (!NT_SUCCESS(Status)) { KdPrint(("SMSS: GetBootPartition: Harddisk%d\\Partition0 for read failed (Status 0x%x).\n", *DiskNumber, Status)); *PartitionNumber = 1; *DiskNumber = 0; return; }
NtClose(Handle);
//
// Now, for each partition, check if it is marked 'active'
//
while (TRUE) {
*PartitionNumber = *PartitionNumber + 1;
swprintf(NameBuffer, L"\\Device\\Harddisk%d\\Partition%d", *DiskNumber, *PartitionNumber);
RtlInitUnicodeString(&UnicodeString, NameBuffer);
InitializeObjectAttributes( &ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtCreateFile( &Handle, (ACCESS_MASK)FILE_GENERIC_READ, &ObjectAttributes, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
if (!NT_SUCCESS(Status)) { break; }
Status = NtDeviceIoControlFile(Handle, NULL, NULL, NULL, &IoStatus, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &PartitionInfo, sizeof(PARTITION_INFORMATION) );
NtClose(Handle);
if (!NT_SUCCESS(Status)) { break; }
if (PartitionInfo.BootIndicator) { return; }
} *DiskNumber = *DiskNumber + 1; }
}
VOID SmpPartitionDisk( IN ULONG DiskNumber, OUT PULONG PartitionNumber ) /*++
Routine Description:
This routine
Arguments:
DiskNumber - The harddisk number.
PartitionNumber - The partition number.
Return Value:
None
--*/
{ OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString; HANDLE Handle; IO_STATUS_BLOCK IoStatusBlock; PUCHAR AlignedBuffer; ULONG Length; PDRIVE_LAYOUT_INFORMATION DriveLayout; PDRIVE_LAYOUT_INFORMATION OrigDriveLayout; PPARTITION_INFORMATION Pte; PPARTITION_INFORMATION StartPte; ULONG LargestPart; ULONG StartPart; ULONG Part; LARGE_INTEGER LargestBlock; LARGE_INTEGER OffsetEnd; UCHAR TmpBuffer[80]; NTSTATUS Status; BOOLEAN MadeChanges; BOOLEAN WasEnabled;
//
// Get the layout of the drive.
//
swprintf((PWSTR)TmpBuffer, L"\\Device\\Harddisk%d\\Partition0", DiskNumber);
RtlInitUnicodeString(&UnicodeString, (PWSTR)TmpBuffer);
InitializeObjectAttributes( &ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtCreateFile( &Handle, (ACCESS_MASK)FILE_GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
if (!NT_SUCCESS(Status)) { KdPrint(("SMSS: Could not open Harddisk%d\\Partition0 for read (Status 0x%x).\n", DiskNumber, Status)); return; }
//
// We really only need 4 partition numbers worth, but for debugging
// purposes I want to see more than just the first 4, so get the first 20.
//
Length = sizeof(DRIVE_LAYOUT_INFORMATION) + 20 * sizeof(PARTITION_INFORMATION);
DriveLayout = (PDRIVE_LAYOUT_INFORMATION)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( INIT_TAG ), Length );
if (DriveLayout == NULL) { KdPrint(("SMSS: Could not allocate memory for drive layout (Status 0x%x).\n", Status)); NtClose(Handle); return; }
OrigDriveLayout = (PDRIVE_LAYOUT_INFORMATION)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( INIT_TAG ), Length );
if (OrigDriveLayout == NULL) { KdPrint(("SMSS: Could not allocate memory for drive layout 2 (Status 0x%x).\n", Status)); RtlFreeHeap( RtlProcessHeap(), 0, DriveLayout ); NtClose(Handle); return; }
Status = NtDeviceIoControlFile( Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_DRIVE_LAYOUT, NULL, 0, (PUCHAR)DriveLayout, Length );
if (!NT_SUCCESS(Status)) { KdPrint(("SMSS: Could not get drive layout (Status 0x%x).\n", Status)); RtlFreeHeap( RtlProcessHeap(), 0, OrigDriveLayout ); RtlFreeHeap( RtlProcessHeap(), 0, DriveLayout ); NtClose(Handle); return; }
memcpy(OrigDriveLayout, DriveLayout, Length);
#if DBG
KdPrint(("SMSS:Starting drive layout\n")); for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
Pte = &(DriveLayout->PartitionEntry[Part]);
KdPrint(("SMSS: Partition: %d\n", Part + 1)); KdPrint(("SMSS: Pte->PartitionType = 0x%x\n", Pte->PartitionType)); KdPrint(("SMSS: Pte->StartingOffset = 0x%x\n", Pte->StartingOffset)); KdPrint(("SMSS: Pte->PartitionLength = 0x%x\n", Pte->PartitionLength)); KdPrint(("SMSS: Pte->HiddenSectors = 0x%x\n", Pte->HiddenSectors)); KdPrint(("SMSS: Pte->PartitionNumber = 0x%x\n", Pte->PartitionNumber)); KdPrint(("SMSS: Pte->BootIndicator = 0x%x\n", Pte->BootIndicator)); KdPrint(("SMSS: Pte->RecognizedPartition = 0x%x\n\n", Pte->RecognizedPartition));
}
#endif
//
// Just ignore extended partitions
//
DriveLayout->PartitionCount = 4;
//
// Go thru the partitions, and for any recognized type, label it as unused.
//
for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
Pte = &(DriveLayout->PartitionEntry[Part]);
if (!IsRecognizedPartition(Pte->PartitionType) && !IsContainerPartition(Pte->PartitionType)) { continue; }
Pte->PartitionType = PARTITION_ENTRY_UNUSED; Pte->BootIndicator = FALSE; }
#if DBG
KdPrint(("SMSS: Layout after clearing known partitions.\n")); for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
Pte = &(DriveLayout->PartitionEntry[Part]);
KdPrint(("SMSS: Partition: %d\n", Part + 1)); KdPrint(("SMSS: Pte->PartitionType = 0x%x\n", Pte->PartitionType)); KdPrint(("SMSS: Pte->StartingOffset = 0x%x\n", Pte->StartingOffset)); KdPrint(("SMSS: Pte->PartitionLength = 0x%x\n", Pte->PartitionLength)); KdPrint(("SMSS: Pte->HiddenSectors = 0x%x\n", Pte->HiddenSectors)); KdPrint(("SMSS: Pte->PartitionNumber = 0x%x\n", Pte->PartitionNumber)); KdPrint(("SMSS: Pte->BootIndicator = 0x%x\n", Pte->BootIndicator)); KdPrint(("SMSS: Pte->RecognizedPartition = 0x%x\n\n", Pte->RecognizedPartition));
}
#endif
//
// Merge unused partitions that are adjacent.
//
for (StartPart = 0; StartPart < DriveLayout->PartitionCount; StartPart++) {
StartPte = &(DriveLayout->PartitionEntry[StartPart]);
if ((StartPte->PartitionType != PARTITION_ENTRY_UNUSED) || RtlLargeIntegerEqualTo(StartPte->PartitionLength, RtlConvertUlongToLargeInteger(0))) { continue; }
OffsetEnd = RtlLargeIntegerAdd(StartPte->StartingOffset, StartPte->PartitionLength);
for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
if (Part == StartPart) { continue; }
Pte = &(DriveLayout->PartitionEntry[Part]);
if (RtlLargeIntegerEqualTo(OffsetEnd, Pte->StartingOffset)) {
//
// Merge the blocks
//
StartPte->PartitionLength = RtlLargeIntegerAdd(StartPte->PartitionLength, Pte->PartitionLength ); OffsetEnd = RtlLargeIntegerAdd(OffsetEnd, Pte->PartitionLength);
Pte->PartitionType = PARTITION_ENTRY_UNUSED; Pte->StartingOffset = RtlConvertUlongToLargeInteger(0); Pte->PartitionLength = RtlConvertUlongToLargeInteger(0); Pte->HiddenSectors = 0; Pte->PartitionNumber = 0; Pte->BootIndicator = FALSE; Pte->RecognizedPartition = FALSE; Part = (ULONG)-1; // will get ++'d to 0 at the bottom of the loop.
} }
}
//
// Find the largest block that is unused.
//
LargestPart = 0; LargestBlock = RtlConvertUlongToLargeInteger(0); for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
Pte = &(DriveLayout->PartitionEntry[Part]);
if ((Pte->PartitionType == PARTITION_ENTRY_UNUSED) && RtlLargeIntegerGreaterThan(Pte->PartitionLength, LargestBlock)) { LargestPart = Part; LargestBlock = Pte->PartitionLength; }
}
#if DBG
KdPrint(("SMSS: Layout after merging largest block.\n")); for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
Pte = &(DriveLayout->PartitionEntry[Part]);
KdPrint(("SMSS: Partition: %d\n", Part + 1)); KdPrint(("SMSS: Pte->PartitionType = 0x%x\n", Pte->PartitionType)); KdPrint(("SMSS: Pte->StartingOffset = 0x%x\n", Pte->StartingOffset)); KdPrint(("SMSS: Pte->PartitionLength = 0x%x\n", Pte->PartitionLength)); KdPrint(("SMSS: Pte->HiddenSectors = 0x%x\n", Pte->HiddenSectors)); KdPrint(("SMSS: Pte->PartitionNumber = 0x%x\n", Pte->PartitionNumber)); KdPrint(("SMSS: Pte->BootIndicator = 0x%x\n", Pte->BootIndicator)); KdPrint(("SMSS: Pte->RecognizedPartition = 0x%x\n\n", Pte->RecognizedPartition));
}
#endif
//
// Set the partition type for the new partition
//
DriveLayout->PartitionEntry[LargestPart].PartitionType = PARTITION_IFS; DriveLayout->PartitionEntry[LargestPart].BootIndicator = TRUE;
#if DBG
KdPrint(("SMSS: Final Layout\n")); for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
Pte = &(DriveLayout->PartitionEntry[Part]);
KdPrint(("SMSS: Partition: %d\n", Part + 1)); KdPrint(("SMSS: Pte->PartitionType = 0x%x\n", Pte->PartitionType)); KdPrint(("SMSS: Pte->StartingOffset = 0x%x\n", Pte->StartingOffset)); KdPrint(("SMSS: Pte->PartitionLength = 0x%x\n", Pte->PartitionLength)); KdPrint(("SMSS: Pte->HiddenSectors = 0x%x\n", Pte->HiddenSectors)); KdPrint(("SMSS: Pte->PartitionNumber = 0x%x\n", Pte->PartitionNumber)); KdPrint(("SMSS: Pte->BootIndicator = 0x%x\n", Pte->BootIndicator)); KdPrint(("SMSS: Pte->RecognizedPartition = 0x%x\n\n", Pte->RecognizedPartition));
}
#endif
MadeChanges = FALSE; for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
if (memcmp(&(DriveLayout->PartitionEntry[Part]), &(OrigDriveLayout->PartitionEntry[Part]), sizeof(PARTITION_INFORMATION))) { MadeChanges = TRUE; break; }
}
if (MadeChanges) {
KdPrint(("SMSS: Repartitioning disk.\n"));
//
// Mark partitions for rewrite.
//
for (Part = 0; Part < DriveLayout->PartitionCount; Part++) { DriveLayout->PartitionEntry[Part].RewritePartition = TRUE; }
//
// Submit IOCTL to set new partition information
//
Status = NtDeviceIoControlFile( Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_SET_DRIVE_LAYOUT, DriveLayout, Length, NULL, 0 );
if (!NT_SUCCESS(Status)) { RtlFreeHeap( RtlProcessHeap(), 0, OrigDriveLayout ); RtlFreeHeap( RtlProcessHeap(), 0, DriveLayout ); NtClose(Handle); KdPrint(("SMSS: Could not set drive layout (Status 0x%x).\n", Status)); return; } }
*PartitionNumber = DriveLayout->PartitionEntry[LargestPart].PartitionNumber;
RtlFreeHeap( RtlProcessHeap(), 0, OrigDriveLayout ); RtlFreeHeap( RtlProcessHeap(), 0, DriveLayout ); NtClose(Handle); return; }
VOID SmpFindCSCPartition( IN ULONG DiskNumber, OUT PULONG PartitionNumber ) /*++
Routine Description:
This routine searches the each partition on each hard disk for one which has the CSC directory.
Arguments:
DiskNumber - The harddisk number.
PartitionNumber - The partition number. Will be 0 if no CSC directory is found on the disk.
Return Value:
None
--*/
{ WCHAR NameBuffer[80]; HANDLE Handle; NTSTATUS Status; IO_STATUS_BLOCK IoStatus; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString; ULONG Part;
Part = 0; *PartitionNumber = 0; while (TRUE) {
Part++;
//
// First see if the partition exists by opening it.
//
swprintf(NameBuffer, L"\\Device\\Harddisk%d\\Partition%d", DiskNumber, Part );
RtlInitUnicodeString(&UnicodeString, NameBuffer);
InitializeObjectAttributes( &ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtCreateFile( &Handle, (ACCESS_MASK)FILE_GENERIC_READ, &ObjectAttributes, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
if (!NT_SUCCESS(Status)) { return; }
NtClose(Handle);
wcscat(NameBuffer, REMOTE_BOOT_IMIRROR_PATH_W REMOTE_BOOT_CSC_SUBDIR_W);
RtlInitUnicodeString(&UnicodeString, NameBuffer);
InitializeObjectAttributes( &ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtOpenFile(&Handle, FILE_READ_DATA | SYNCHRONIZE, &ObjectAttributes, &IoStatus, FILE_SHARE_READ, FILE_DIRECTORY_FILE );
if (NT_SUCCESS(Status)) { NtClose(Handle); *PartitionNumber = Part; return; }
}
} #endif // defined(REMOTE_BOOT)
|