📄 arcname.c
字号:
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/io/iomgr/arcname.c
* PURPOSE: ARC Path Initialization Functions
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl (ekohl@rz-online.de)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
UNICODE_STRING IoArcHalDeviceName, IoArcBootDeviceName;
PCHAR IoLoaderArcBootDeviceName;
/* FUNCTIONS *****************************************************************/
BOOLEAN
INIT_FUNCTION
NTAPI
IopApplyRosCdromArcHack(IN ULONG i)
{
ULONG DeviceNumber = -1;
OBJECT_ATTRIBUTES ObjectAttributes;
ANSI_STRING InstallName;
UNICODE_STRING DeviceName;
CHAR Buffer[128];
FILE_BASIC_INFORMATION FileInfo;
NTSTATUS Status;
PCHAR p, q;
PCONFIGURATION_INFORMATION ConfigInfo = IoGetConfigurationInformation();
extern BOOLEAN InitIsWinPEMode, ExpInTextModeSetup;
/* Only ARC Name left - Build full ARC Name */
p = strstr(KeLoaderBlock->ArcBootDeviceName, "cdrom");
if (p)
{
/* Build installer name */
sprintf(Buffer, "\\Device\\CdRom%lu\\reactos\\ntoskrnl.exe", i);
RtlInitAnsiString(&InstallName, Buffer);
Status = RtlAnsiStringToUnicodeString(&DeviceName, &InstallName, TRUE);
if (!NT_SUCCESS(Status)) return FALSE;
/* Try to find the installer */
InitializeObjectAttributes(&ObjectAttributes,
&DeviceName,
0,
NULL,
NULL);
Status = ZwQueryAttributesFile(&ObjectAttributes, &FileInfo);
/* Free the string */
RtlFreeUnicodeString(&DeviceName);
/* Check if we found the file */
if (NT_SUCCESS(Status))
{
/* We did, save the device number */
DeviceNumber = i;
}
else
{
/* Build live CD kernel name */
sprintf(Buffer,
"\\Device\\CdRom%lu\\reactos\\system32\\ntoskrnl.exe",
i);
RtlInitAnsiString(&InstallName, Buffer);
Status = RtlAnsiStringToUnicodeString(&DeviceName,
&InstallName,
TRUE);
if (!NT_SUCCESS(Status)) return FALSE;
/* Try to find it */
InitializeObjectAttributes(&ObjectAttributes,
&DeviceName,
0,
NULL,
NULL);
Status = ZwQueryAttributesFile(&ObjectAttributes, &FileInfo);
if (NT_SUCCESS(Status)) DeviceNumber = i;
/* Free the string */
RtlFreeUnicodeString(&DeviceName);
}
if (!InitIsWinPEMode)
{
/* Build the name */
sprintf(p, "cdrom(%lu)", DeviceNumber);
/* Adjust original command line */
q = strchr(p, ')');
if (q)
{
q++;
strcpy(Buffer, q);
sprintf(p, "cdrom(%lu)", DeviceNumber);
strcat(p, Buffer);
}
}
}
/* OK, how many disks are there? */
DeviceNumber += ConfigInfo->DiskCount;
/* Return whether this is the CD or not */
if ((InitIsWinPEMode) || (ExpInTextModeSetup))
{
/* Hack until IoAssignDriveLetters is fixed */
swprintf(SharedUserData->NtSystemRoot, L"%c:\\reactos", 'C' + DeviceNumber);
return TRUE;
}
/* Failed */
return FALSE;
}
BOOLEAN
INIT_FUNCTION
NTAPI
IopGetDiskInformation(IN ULONG i,
OUT PULONG CheckSum,
OUT PULONG Signature,
OUT PULONG PartitionCount,
OUT PDEVICE_OBJECT *DiskDeviceObject)
{
ULONG j, Checksum;
ANSI_STRING TempString;
CHAR Buffer[128];
UNICODE_STRING DeviceName;
NTSTATUS Status;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
DISK_GEOMETRY DiskGeometry;
PDRIVE_LAYOUT_INFORMATION DriveLayout;
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK StatusBlock;
LARGE_INTEGER PartitionOffset;
PULONG PartitionBuffer;
/* Build the name */
sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", i);
/* Convert it to Unicode */
RtlInitAnsiString(&TempString, Buffer);
Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
if (!NT_SUCCESS(Status)) return FALSE;
/* Get the device pointer */
Status = IoGetDeviceObjectPointer(&DeviceName,
FILE_READ_DATA,
&FileObject,
&DeviceObject);
*DiskDeviceObject = DeviceObject;
/* Free the string */
RtlFreeUnicodeString(&DeviceName);
/* Move on if we failed */
if (!NT_SUCCESS(Status)) return FALSE;
/* Build an IRP to determine the sector size */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
DeviceObject,
NULL,
0,
&DiskGeometry,
sizeof(DISK_GEOMETRY),
FALSE,
&Event,
&StatusBlock);
if (!Irp)
{
/* Try again */
ObDereferenceObject(FileObject);
return FALSE;
}
/* Call the driver and check if we have to wait on it */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
/* Wait on the driver */
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = StatusBlock.Status;
}
/* Check if we failed */
if (!NT_SUCCESS(Status))
{
/* Try again */
ObDereferenceObject(FileObject);
return FALSE;
}
/* Read the partition table */
Status = IoReadPartitionTable(DeviceObject,
DiskGeometry.BytesPerSector,
TRUE,
&DriveLayout);
/* Dereference the file object */
ObDereferenceObject(FileObject);
if (!NT_SUCCESS(Status)) return FALSE;
/* Set the offset to 0 */
PartitionOffset.QuadPart = 0;
/* Allocate a buffer for the partition */
PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool,
DiskGeometry.BytesPerSector,
TAG_IO);
if (!PartitionBuffer) return FALSE;
/* Build an IRP to read the partition sector */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
DeviceObject,
PartitionBuffer,
DiskGeometry.BytesPerSector,
&PartitionOffset,
&Event,
&StatusBlock);
/* Call the driver and check if we have to wait */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
/* Wait for completion */
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = StatusBlock.Status;
}
/* Check if we failed */
if (!NT_SUCCESS(Status))
{
/* Try again */
ExFreePool(PartitionBuffer);
ExFreePool(DriveLayout);
return FALSE;
}
/* Calculate the MBR checksum */
Checksum = 0;
for (j = 0; j < 128; j++) Checksum += PartitionBuffer[j];
/* Save the signature and checksum */
*CheckSum = ~Checksum + 1;
*Signature = DriveLayout->Signature;
*PartitionCount = DriveLayout->PartitionCount;
/* Free the buffer */
ExFreePool(PartitionBuffer);
ExFreePool(DriveLayout);
return TRUE;
}
BOOLEAN
INIT_FUNCTION
NTAPI
IopAssignArcNamesToCdrom(IN PULONG Buffer,
IN ULONG DiskNumber)
{
CHAR ArcBuffer[128];
ANSI_STRING TempString;
UNICODE_STRING DeviceName, ArcName;
NTSTATUS Status;
LARGE_INTEGER PartitionOffset;
KEVENT Event;
IO_STATUS_BLOCK IoStatusBlock;
PIRP Irp;
ULONG i, CheckSum = 0;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
/* Build the device name */
sprintf(ArcBuffer, "\\Device\\CdRom%lu", DiskNumber);
/* Convert it to Unicode */
RtlInitAnsiString(&TempString, ArcBuffer);
Status = RtlAnsiStringToUnicodeString(&DeviceName, &TempString, TRUE);
if (!NT_SUCCESS(Status)) return FALSE;
/* Get the device for it */
Status = IoGetDeviceObjectPointer(&DeviceName,
FILE_READ_ATTRIBUTES,
&FileObject,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
/* Free the string and fail */
RtlFreeUnicodeString(&DeviceName);
return FALSE;
}
/* Setup the event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* Set the offset and build the read IRP */
PartitionOffset.QuadPart = 0x8000;
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
DeviceObject,
Buffer,
2048,
&PartitionOffset,
&Event,
&IoStatusBlock);
if (!Irp)
{
/* Free the string and fail */
RtlFreeUnicodeString(&DeviceName);
return FALSE;
}
/* Call the driver and check if we have to wait on it */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
/* Wait for completion */
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatusBlock.Status;
}
/* Dereference the file object */
ObDereferenceObject(FileObject);
if (!NT_SUCCESS(Status)) return FALSE;
/* Now calculate the checksum */
for (i = 0; i < 2048 / sizeof(ULONG); i++) CheckSum += Buffer[i];
/*
* FIXME: In normal conditions, NTLDR/FreeLdr sends the *proper* CDROM
* ARC Path name, and what happens here is a comparision of both checksums
* in order to see if this is the actual boot CD.
*
* In ReactOS this doesn't currently happen, instead we have a hack on top
* of this file which scans the CD for the ntoskrnl.exe file, then modifies
* the LoaderBlock's ARC Path with the right CDROM path. Consequently, we
* get the same state as if NTLDR had properly booted us, except that we do
* not actually need to check the signature, since the hack already did the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -