-/* $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/io/arcname.c
- * PURPOSE: Creates ARC names for boot devices
- *
- * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
- */
+/*
+* 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
+*/
-
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
-
-static NTSTATUS
-STDCALL INIT_FUNCTION
-DiskQueryRoutine(PWSTR ValueName,
- ULONG ValueType,
- PVOID ValueData,
- ULONG ValueLength,
- PVOID Context,
- PVOID EntryContext);
-
-static VOID INIT_FUNCTION
-IopEnumerateBiosDisks(PLIST_ENTRY ListHead);
-
-static VOID INIT_FUNCTION
-IopEnumerateDisks(PLIST_ENTRY ListHead);
-
-static NTSTATUS INIT_FUNCTION
-IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject, ULONG RDisk, ULONG DiskNumber);
-
-static NTSTATUS INIT_FUNCTION
-IopCheckCdromDevices(PULONG DeviceNumber);
-
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, DiskQueryRoutine)
-#pragma alloc_text(INIT, IopEnumerateBiosDisks)
-#pragma alloc_text(INIT, IopEnumerateDisks)
-#pragma alloc_text(INIT, IopAssignArcNamesToDisk)
-#pragma alloc_text(INIT, IoCreateArcNames)
-#pragma alloc_text(INIT, IopCheckCdromDevices)
-#pragma alloc_text(INIT, IoCreateSystemRootLink)
-#endif
-
+#include <debug.h>
-/* MACROS *******************************************************************/
+/* GLOBALS *******************************************************************/
-#define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
+UNICODE_STRING IoArcHalDeviceName, IoArcBootDeviceName;
+PCHAR IoLoaderArcBootDeviceName;
+extern PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
-/* FUNCTIONS ****************************************************************/
+/* FUNCTIONS *****************************************************************/
-static
-NTSTATUS
-STDCALL
+BOOLEAN
INIT_FUNCTION
-DiskQueryRoutine(PWSTR ValueName,
- ULONG ValueType,
- PVOID ValueData,
- ULONG ValueLength,
- PVOID Context,
- PVOID EntryContext)
+NTAPI
+IopApplyRosCdromArcHack(IN ULONG i)
{
- PLIST_ENTRY ListHead = (PLIST_ENTRY)Context;
- PULONG GlobalDiskCount = (PULONG)EntryContext;
- PDISKENTRY DiskEntry;
- UNICODE_STRING NameU;
-
- if (ValueType == REG_SZ &&
- ValueLength == 20 * sizeof(WCHAR))
+ ULONG DeviceNumber = -1;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ANSI_STRING InstallName;
+ UNICODE_STRING DeviceName;
+ CHAR Buffer[128], RosSysPath[16];
+ FILE_BASIC_INFORMATION FileInfo;
+ NTSTATUS Status;
+ PCHAR p, q;
+ PCONFIGURATION_INFORMATION ConfigInfo = IoGetConfigurationInformation();
+ extern BOOLEAN InitIsWinPEMode, ExpInTextModeSetup;
+
+ /* Change this if you want ROS to boot properly from another directory */
+ sprintf(RosSysPath, "%s", "reactos");
+
+ /* Only ARC Name left - Build full ARC Name */
+ p = strstr(KeLoaderBlock->ArcBootDeviceName, "cdrom");
+ if (p)
{
- DiskEntry = ExAllocatePool(PagedPool, sizeof(DISKENTRY));
- if (DiskEntry == NULL)
+ /* Build installer name */
+ sprintf(Buffer, "\\Device\\CdRom%lu\\%s\\ntoskrnl.exe", i, RosSysPath);
+ 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))
{
- return STATUS_NO_MEMORY;
+ /* We did, save the device number */
+ DeviceNumber = i;
}
- DiskEntry->DiskNumber = (*GlobalDiskCount)++;
-
- NameU.Buffer = (PWCHAR)ValueData;
- NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
- RtlUnicodeStringToInteger(&NameU, 16, &DiskEntry->Checksum);
-
- NameU.Buffer = (PWCHAR)ValueData + 9;
- RtlUnicodeStringToInteger(&NameU, 16, &DiskEntry->Signature);
-
- InsertTailList(ListHead, &DiskEntry->ListEntry);
- }
-
- return STATUS_SUCCESS;
-}
-
-#define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
-
-static VOID INIT_FUNCTION
-IopEnumerateBiosDisks(PLIST_ENTRY ListHead)
-{
- RTL_QUERY_REGISTRY_TABLE QueryTable[2];
- WCHAR Name[255];
- ULONG AdapterCount;
- ULONG ControllerCount;
- ULONG DiskCount;
- NTSTATUS Status;
- ULONG GlobalDiskCount=0;
-
-
- memset(QueryTable, 0, sizeof(QueryTable));
- QueryTable[0].Name = L"Identifier";
- QueryTable[0].QueryRoutine = DiskQueryRoutine;
- QueryTable[0].EntryContext = (PVOID)&GlobalDiskCount;
-
- AdapterCount = 0;
- while (1)
- {
- swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- Name,
- &QueryTable[1],
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
+ else
{
- break;
- }
-
- swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- Name,
- &QueryTable[1],
- NULL,
- NULL);
- if (NT_SUCCESS(Status))
- {
- ControllerCount = 0;
- while (1)
- {
- swprintf(Name, L"%s\\%lu\\DiskController\\%lu", ROOT_NAME, AdapterCount, ControllerCount);
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- Name,
- &QueryTable[1],
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- break;
- }
-
- swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral", ROOT_NAME, AdapterCount, ControllerCount);
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- Name,
- &QueryTable[1],
- NULL,
- NULL);
- if (NT_SUCCESS(Status))
- {
- DiskCount = 0;
- while (1)
- {
- swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- Name,
- QueryTable,
- (PVOID)ListHead,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- break;
- }
- DiskCount++;
- }
- }
- ControllerCount++;
- }
+ /* Build live CD kernel name */
+ sprintf(Buffer,
+ "\\Device\\CdRom%lu\\%s\\system32\\ntoskrnl.exe",
+ i, RosSysPath);
+ 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);
}
- AdapterCount++;
- }
-}
-
-static VOID INIT_FUNCTION
-IopEnumerateDisks(PLIST_ENTRY ListHead)
-{
- ULONG i, k;
- PDISKENTRY DiskEntry;
- DISK_GEOMETRY DiskGeometry;
- KEVENT Event;
- PIRP Irp;
- IO_STATUS_BLOCK StatusBlock;
- LARGE_INTEGER PartitionOffset;
- PULONG Buffer;
- WCHAR DeviceNameBuffer[80];
- UNICODE_STRING DeviceName;
- NTSTATUS Status;
- PDEVICE_OBJECT DeviceObject;
- PFILE_OBJECT FileObject;
- BOOLEAN IsRemovableMedia;
- PPARTITION_SECTOR PartitionBuffer = NULL;
- ULONG PartitionBufferSize = 0;
-
-
- for (i = 0; i < IoGetConfigurationInformation()->DiskCount; i++)
- {
-
- swprintf(DeviceNameBuffer,
- L"\\Device\\Harddisk%lu\\Partition0",
- i);
- RtlInitUnicodeString(&DeviceName,
- DeviceNameBuffer);
-
- Status = IoGetDeviceObjectPointer(&DeviceName,
- FILE_READ_DATA,
- &FileObject,
- &DeviceObject);
- if (!NT_SUCCESS(Status))
- {
- continue;
- }
- IsRemovableMedia = DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA ? TRUE : FALSE;
- ObDereferenceObject(FileObject);
- if (IsRemovableMedia)
- {
- ObDereferenceObject(DeviceObject);
- continue;
- }
- DiskEntry = ExAllocatePool(PagedPool, sizeof(DISKENTRY));
- if (DiskEntry == NULL)
- {
- KEBUGCHECK(0);
- }
- DiskEntry->DiskNumber = i;
- DiskEntry->DeviceObject = DeviceObject;
-
- /* 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 == NULL)
+ if (!InitIsWinPEMode)
{
- KEBUGCHECK(0);
- }
+ /* Build the name */
+ sprintf(p, "cdrom(%lu)", DeviceNumber);
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = StatusBlock.Status;
- }
- if (!NT_SUCCESS(Status))
- {
- KEBUGCHECK(0);
- }
- if (PartitionBuffer != NULL && PartitionBufferSize < DiskGeometry.BytesPerSector)
- {
- ExFreePool(PartitionBuffer);
- PartitionBuffer = NULL;
- }
- if (PartitionBuffer == NULL)
- {
- PartitionBufferSize = max(DiskGeometry.BytesPerSector, PAGE_SIZE);
- PartitionBuffer = ExAllocatePool(PagedPool, PartitionBufferSize);
- if (PartitionBuffer == NULL)
+ /* Adjust original command line */
+ q = strchr(p, ')');
+ if (q)
{
- KEBUGCHECK(0);
+ q++;
+ strcpy(Buffer, q);
+ sprintf(p, "cdrom(%lu)", DeviceNumber);
+ strcat(p, Buffer);
}
}
+ }
- /* read the partition sector */
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- PartitionOffset.QuadPart = 0;
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
- DeviceObject,
- PartitionBuffer,
- DiskGeometry.BytesPerSector,
- &PartitionOffset,
- &Event,
- &StatusBlock);
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = StatusBlock.Status;
- }
-
- if (!NT_SUCCESS(Status))
- {
- KEBUGCHECK(0);
- }
+ /* OK, how many disks are there? */
+ DeviceNumber += ConfigInfo->DiskCount;
- /* Calculate the MBR checksum */
- DiskEntry->Checksum = 0;
- Buffer = (PULONG)PartitionBuffer;
- for (k = 0; k < 128; k++)
- {
- DiskEntry->Checksum += Buffer[k];
- }
- DiskEntry->Checksum = ~DiskEntry->Checksum + 1;
- DiskEntry->Signature = PartitionBuffer->Signature;
-
- InsertTailList(ListHead, &DiskEntry->ListEntry);
- }
- if (PartitionBuffer)
+ /* Return whether this is the CD or not */
+ if ((InitIsWinPEMode) || (ExpInTextModeSetup))
{
- ExFreePool(PartitionBuffer);
+ return TRUE;
}
+
+ /* Failed */
+ return FALSE;
}
-static NTSTATUS INIT_FUNCTION
-IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject, ULONG RDisk, ULONG DiskNumber)
+BOOLEAN
+INIT_FUNCTION
+NTAPI
+IopGetDiskInformation(IN ULONG i,
+ OUT PULONG CheckSum,
+ OUT PULONG Signature,
+ OUT PULONG PartitionCount,
+ OUT PDEVICE_OBJECT *DiskDeviceObject)
{
- WCHAR DeviceNameBuffer[80];
- WCHAR ArcNameBuffer[80];
- UNICODE_STRING DeviceName;
- UNICODE_STRING ArcName;
- PDRIVE_LAYOUT_INFORMATION LayoutInfo = NULL;
- NTSTATUS Status;
- ULONG i;
- KEVENT Event;
- PIRP Irp;
- IO_STATUS_BLOCK StatusBlock;
- ULONG PartitionNumber;
-
- swprintf(DeviceNameBuffer,
- L"\\Device\\Harddisk%lu\\Partition0",
- DiskNumber);
- RtlInitUnicodeString(&DeviceName,
- DeviceNameBuffer);
-
- swprintf(ArcNameBuffer,
- L"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
- RDisk);
- RtlInitUnicodeString(&ArcName,
- ArcNameBuffer);
-
- DPRINT("%wZ ==> %wZ\n", &ArcName, &DeviceName);
-
- Status = IoAssignArcName(&ArcName, &DeviceName);
- if (!NT_SUCCESS(Status))
+ 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_ATTRIBUTES,
+ &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)
{
- DPRINT1("IoAssignArcName failed, status=%lx\n", Status);
- return(Status);
+ /* Try again */
+ ObDereferenceObject(FileObject);
+ return FALSE;
}
- LayoutInfo = ExAllocatePool(PagedPool, 2 * PAGE_SIZE);
- if (LayoutInfo == NULL)
+ /* Call the driver and check if we have to wait on it */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
{
- return STATUS_NO_MEMORY;
+ /* Wait on the driver */
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = StatusBlock.Status;
}
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT,
- DeviceObject,
- NULL,
- 0,
- LayoutInfo,
- 2 * PAGE_SIZE,
- FALSE,
- &Event,
- &StatusBlock);
- if (Irp == NULL)
+
+ /* Check if we failed */
+ if (!NT_SUCCESS(Status))
{
- ExFreePool(LayoutInfo);
- return STATUS_INSUFFICIENT_RESOURCES;
+ /* Try again */
+ ObDereferenceObject(FileObject);
+ return FALSE;
}
- Status = IoCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING)
+ /* 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)
{
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = StatusBlock.Status;
+ /* Try again */
+ ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
+ return FALSE;
}
- if (!NT_SUCCESS(Status))
+
+ /* Build an IRP to read the partition sector */
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+ DeviceObject,
+ PartitionBuffer,
+ DiskGeometry.BytesPerSector,
+ &PartitionOffset,
+ &Event,
+ &StatusBlock);
+ if (!Irp)
{
- ExFreePool(LayoutInfo);
- return Status;
+ /* Try again */
+ ExFreePoolWithTag(PartitionBuffer, TAG_IO);
+ ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
+ return FALSE;
}
- DPRINT("Number of partitions: %u\n", LayoutInfo->PartitionCount);
-
- PartitionNumber = 1;
- for (i = 0; i < LayoutInfo->PartitionCount; i++)
+ /* Call the driver and check if we have to wait */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
{
- if (!IsContainerPartition(LayoutInfo->PartitionEntry[i].PartitionType) &&
- LayoutInfo->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED)
- {
-
- swprintf(DeviceNameBuffer,
- L"\\Device\\Harddisk%lu\\Partition%lu",
- DiskNumber,
- PartitionNumber);
- RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
-
- swprintf(ArcNameBuffer,
- L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)",
- RDisk,
- PartitionNumber);
- RtlInitUnicodeString(&ArcName, ArcNameBuffer);
-
- DPRINT("%wZ ==> %wZ\n", &ArcName, &DeviceName);
-
- Status = IoAssignArcName(&ArcName, &DeviceName);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("IoAssignArcName failed, status=%lx\n", Status);
- ExFreePool(LayoutInfo);
- return(Status);
- }
- PartitionNumber++;
- }
+ /* Wait for completion */
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = StatusBlock.Status;
}
- ExFreePool(LayoutInfo);
- return STATUS_SUCCESS;
-}
-NTSTATUS INIT_FUNCTION
-IoCreateArcNames(VOID)
-{
- PCONFIGURATION_INFORMATION ConfigInfo;
- WCHAR DeviceNameBuffer[80];
- WCHAR ArcNameBuffer[80];
- UNICODE_STRING DeviceName;
- UNICODE_STRING ArcName;
- ULONG i, RDiskNumber;
- NTSTATUS Status;
- LIST_ENTRY BiosDiskListHead;
- LIST_ENTRY DiskListHead;
- PLIST_ENTRY Entry;
- PDISKENTRY BiosDiskEntry;
- PDISKENTRY DiskEntry;
-
- DPRINT("IoCreateArcNames() called\n");
-
- ConfigInfo = IoGetConfigurationInformation();
-
- /* create ARC names for floppy drives */
- DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount);
- for (i = 0; i < ConfigInfo->FloppyCount; i++)
+ /* Check if we failed */
+ if (!NT_SUCCESS(Status))
{
- swprintf(DeviceNameBuffer,
- L"\\Device\\Floppy%lu",
- i);
- RtlInitUnicodeString(&DeviceName,
- DeviceNameBuffer);
-
- swprintf(ArcNameBuffer,
- L"\\ArcName\\multi(0)disk(0)fdisk(%lu)",
- i);
- RtlInitUnicodeString(&ArcName,
- ArcNameBuffer);
- DPRINT("%wZ ==> %wZ\n",
- &ArcName,
- &DeviceName);
-
- Status = IoAssignArcName(&ArcName,
- &DeviceName);
- if (!NT_SUCCESS(Status))
- return(Status);
+ /* Try again */
+ ExFreePoolWithTag(PartitionBuffer, TAG_IO);
+ ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
+ return FALSE;
}
- /* create ARC names for hard disk drives */
- InitializeListHead(&BiosDiskListHead);
- InitializeListHead(&DiskListHead);
- IopEnumerateBiosDisks(&BiosDiskListHead);
- IopEnumerateDisks(&DiskListHead);
+ /* Calculate the MBR checksum */
+ Checksum = 0;
+ for (j = 0; j < 128; j++) Checksum += PartitionBuffer[j];
- RDiskNumber = 0;
- while (!IsListEmpty(&BiosDiskListHead))
- {
- Entry = RemoveHeadList(&BiosDiskListHead);
- BiosDiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- Entry = DiskListHead.Flink;
- while (Entry != &DiskListHead)
- {
- DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- if (DiskEntry->Checksum == BiosDiskEntry->Checksum &&
- DiskEntry->Signature == BiosDiskEntry->Signature)
- {
+ /* Save the signature and checksum */
+ *CheckSum = ~Checksum + 1;
+ *Signature = DriveLayout->Signature;
+ *PartitionCount = DriveLayout->PartitionCount;
- Status = IopAssignArcNamesToDisk(DiskEntry->DeviceObject, RDiskNumber, DiskEntry->DiskNumber);
+ /* Free the buffer */
+ ExFreePoolWithTag(PartitionBuffer, TAG_IO);
+ ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM);
+ return TRUE;
+}
- RemoveEntryList(&DiskEntry->ListEntry);
- ExFreePool(DiskEntry);
- break;
- }
- Entry = Entry->Flink;
- }
- RDiskNumber++;
- ExFreePool(BiosDiskEntry);
+BOOLEAN
+INIT_FUNCTION
+NTAPI
+IopAssignArcNamesToCdrom(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ 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;
+ PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
+ PLIST_ENTRY NextEntry;
+ PARC_DISK_SIGNATURE ArcDiskEntry;
+ BOOLEAN IsBootCdRom = FALSE;
+
+ /* 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;
}
- while (!IsListEmpty(&DiskListHead))
+ /* 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)
{
- Entry = RemoveHeadList(&DiskListHead);
- DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- ExFreePool(DiskEntry);
+ /* Free the string and fail */
+ RtlFreeUnicodeString(&DeviceName);
+ return FALSE;
}
- /* create ARC names for cdrom drives */
- DPRINT("CD-ROM drives: %lu\n", ConfigInfo->CdRomCount);
- for (i = 0; i < ConfigInfo->CdRomCount; i++)
+ /* Call the driver and check if we have to wait on it */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
{
- swprintf(DeviceNameBuffer,
- L"\\Device\\CdRom%lu",
- i);
- RtlInitUnicodeString(&DeviceName,
- DeviceNameBuffer);
-
- swprintf(ArcNameBuffer,
- L"\\ArcName\\multi(0)disk(0)cdrom(%lu)",
- i);
- RtlInitUnicodeString(&ArcName,
- ArcNameBuffer);
- DPRINT("%wZ ==> %wZ\n",
- &ArcName,
- &DeviceName);
-
- Status = IoAssignArcName(&ArcName,
- &DeviceName);
- if (!NT_SUCCESS(Status))
- return(Status);
+ /* Wait for completion */
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = IoStatusBlock.Status;
}
- DPRINT("IoCreateArcNames() done\n");
+ /* Dereference the file object */
+ ObDereferenceObject(FileObject);
+ if (!NT_SUCCESS(Status)) return FALSE;
- return(STATUS_SUCCESS);
-}
+ /* Now calculate the checksum */
+ for (i = 0; i < 2048 / sizeof(ULONG); i++) CheckSum += Buffer[i];
+ if (KeRosLoaderBlock) goto freeldrhack;
-static NTSTATUS INIT_FUNCTION
-IopCheckCdromDevices(PULONG DeviceNumber)
-{
- PCONFIGURATION_INFORMATION ConfigInfo;
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING DeviceName;
- WCHAR DeviceNameBuffer[MAX_PATH];
- HANDLE Handle;
- ULONG i;
- NTSTATUS Status;
- IO_STATUS_BLOCK IoStatusBlock;
-#if 0
- PFILE_FS_VOLUME_INFORMATION FileFsVolume;
- USHORT Buffer[FS_VOLUME_BUFFER_SIZE];
-
- FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
-#endif
-
- ConfigInfo = IoGetConfigurationInformation();
- for (i = 0; i < ConfigInfo->CdRomCount; i++)
+ /* Search if this device is the actual boot CD */
+ for (NextEntry = ArcDiskInfo->DiskSignatureListHead.Flink;
+ NextEntry != &ArcDiskInfo->DiskSignatureListHead;
+ NextEntry = NextEntry->Flink)
{
-#if 0
- swprintf(DeviceNameBuffer,
- L"\\Device\\CdRom%lu\\",
- i);
- RtlInitUnicodeString(&DeviceName,
- DeviceNameBuffer);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &DeviceName,
- 0,
- NULL,
- NULL);
-
- Status = ZwOpenFile(&Handle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- 0);
- DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i, Status);
- if (NT_SUCCESS(Status))
- {
- Status = ZwQueryVolumeInformationFile(Handle,
- &IoStatusBlock,
- FileFsVolume,
- FS_VOLUME_BUFFER_SIZE,
- FileFsVolumeInformation);
- DPRINT("ZwQueryVolumeInformationFile() Status %lx\n", Status);
- if (NT_SUCCESS(Status))
- {
- DPRINT("VolumeLabel: '%S'\n", FileFsVolume->VolumeLabel);
- if (_wcsicmp(FileFsVolume->VolumeLabel, L"REACTOS") == 0)
- {
- ZwClose(Handle);
- *DeviceNumber = i;
- return(STATUS_SUCCESS);
- }
- }
- ZwClose(Handle);
- }
-#endif
-
- /*
- * Check for 'reactos/ntoskrnl.exe' first...
- */
-
- swprintf(DeviceNameBuffer,
- L"\\Device\\CdRom%lu\\reactos\\ntoskrnl.exe",
- i);
- RtlInitUnicodeString(&DeviceName,
- DeviceNameBuffer);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &DeviceName,
- 0,
- NULL,
- NULL);
-
- Status = ZwOpenFile(&Handle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- 0);
- DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i, Status);
- if (NT_SUCCESS(Status))
- {
- DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i);
- ZwClose(Handle);
- *DeviceNumber = i;
- return(STATUS_SUCCESS);
- }
-
- /*
- * ...and for 'reactos/system32/ntoskrnl.exe' also.
- */
-
- swprintf(DeviceNameBuffer,
- L"\\Device\\CdRom%lu\\reactos\\system32\\ntoskrnl.exe",
- i);
- RtlInitUnicodeString(&DeviceName,
- DeviceNameBuffer);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &DeviceName,
- 0,
- NULL,
- NULL);
-
- Status = ZwOpenFile(&Handle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- 0);
- DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i, Status);
- if (NT_SUCCESS(Status))
- {
- DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i);
- ZwClose(Handle);
- *DeviceNumber = i;
- return(STATUS_SUCCESS);
- }
+ /* Get the current ARC disk signature entry */
+ ArcDiskEntry = CONTAINING_RECORD(NextEntry,
+ ARC_DISK_SIGNATURE,
+ ListEntry);
+ /* And check if checksums and arc names match */
+ if (CheckSum == ArcDiskEntry->CheckSum &&
+ strcmp(KeLoaderBlock->ArcBootDeviceName, ArcDiskEntry->ArcName) == 0)
+ {
+ IsBootCdRom = TRUE;
+ break;
+ }
}
+ goto checkbootcd;
+
+freeldrhack:
+ /*
+ * 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
+ * check for ntoskrnl.exe, which is just as good.
+ *
+ * The signature code stays however, because eventually FreeLDR will work
+ * like NTLDR, and, conversly, we do want to be able to be booted by NTLDR.
+ */
+ IsBootCdRom = IopApplyRosCdromArcHack(DiskNumber);
+
+checkbootcd:
+ if (IsBootCdRom)
+ {
+ /* This is the boot CD-ROM, build the ARC name */
+ sprintf(ArcBuffer, "\\ArcName\\%s", KeLoaderBlock->ArcBootDeviceName);
- DPRINT("Could not find ntoskrnl.exe\n");
- *DeviceNumber = (ULONG)-1;
+ /* Convert it to Unicode */
+ RtlInitAnsiString(&TempString, ArcBuffer);
+ Status = RtlAnsiStringToUnicodeString(&ArcName, &TempString, TRUE);
+ if (!NT_SUCCESS(Status)) return FALSE;
- return(STATUS_UNSUCCESSFUL);
-}
+ /* Create the symbolic link and free the strings */
+ IoAssignArcName(&ArcName, &DeviceName);
+ RtlFreeUnicodeString(&ArcName);
+ RtlFreeUnicodeString(&DeviceName);
+ /* Let caller know that we've found the boot CD */
+ return TRUE;
+ }
-NTSTATUS INIT_FUNCTION
-IoCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+ /* No boot CD found */
+ return FALSE;
+}
+
+NTSTATUS
+INIT_FUNCTION
+NTAPI
+IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\SystemRoot");
- UNICODE_STRING DeviceName;
- UNICODE_STRING ArcName;
- UNICODE_STRING BootPath;
- PCHAR ParamBuffer;
- PWCHAR ArcNameBuffer;
- PCHAR p;
- NTSTATUS Status;
- ULONG Length;
- HANDLE Handle;
-
- RtlCreateUnicodeStringFromAsciiz(&BootPath, LoaderBlock->NtBootPathName);
-
- /* Remove the trailing backslash */
- BootPath.Length -= sizeof(WCHAR);
- BootPath.MaximumLength -= sizeof(WCHAR);
-
- /* Only ARC Name left - Build full ARC Name */
- ParamBuffer = LoaderBlock->ArcBootDeviceName;
-
- p = strstr(ParamBuffer, "cdrom");
- if (p != NULL)
+ PCONFIGURATION_INFORMATION ConfigInfo = IoGetConfigurationInformation();
+ PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
+ CHAR Buffer[128];
+ ANSI_STRING ArcBootString, ArcSystemString, ArcString;
+ UNICODE_STRING ArcName, BootPath, DeviceName;
+ BOOLEAN SingleDisk;
+ ULONG i, j, Length;
+ PDEVICE_OBJECT DeviceObject;
+ ULONG Signature, Checksum, PartitionCount;
+ PLIST_ENTRY NextEntry;
+ PARC_DISK_SIGNATURE ArcDiskEntry;
+ NTSTATUS Status;
+ BOOLEAN FoundBoot = FALSE;
+ PULONG PartitionBuffer;
+
+ /* Check if we only have one disk on the machine */
+ SingleDisk = ArcDiskInfo->DiskSignatureListHead.Flink->Flink ==
+ (&ArcDiskInfo->DiskSignatureListHead);
+
+ /* Create the global HAL partition name */
+ sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName);
+ RtlInitAnsiString(&ArcString, Buffer);
+ RtlAnsiStringToUnicodeString(&IoArcHalDeviceName, &ArcString, TRUE);
+
+ /* Create the global system partition name */
+ sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
+ RtlInitAnsiString(&ArcString, Buffer);
+ RtlAnsiStringToUnicodeString(&IoArcBootDeviceName, &ArcString, TRUE);
+
+ /* Allocate memory for the string */
+ Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL);
+ IoLoaderArcBootDeviceName = ExAllocatePoolWithTag(PagedPool,
+ Length,
+ TAG_IO);
+ if (IoLoaderArcBootDeviceName)
{
- ULONG DeviceNumber;
-
- DPRINT("Booting from CD-ROM!\n");
- Status = IopCheckCdromDevices(&DeviceNumber);
- if (!NT_SUCCESS(Status))
- {
- CPRINT("Failed to find setup disk!\n");
- return(Status);
- }
-
- sprintf(p, "cdrom(%lu)", DeviceNumber);
-
- DPRINT("New ARC name: %s\n", ParamBuffer);
-
- /* Adjust original command line */
- p = strstr(LoaderBlock->ArcBootDeviceName, "cdrom");
- if (p != NULL);
- {
- char temp[256];
- char *q;
-
- q = strchr(p, ')');
- if (q != NULL)
- {
-
- q++;
- strcpy(temp, q);
- sprintf(p, "cdrom(%lu)", DeviceNumber);
- strcat(p, temp);
- }
- }
+ /* Copy the name */
+ RtlCopyMemory(IoLoaderArcBootDeviceName,
+ LoaderBlock->ArcBootDeviceName,
+ Length);
}
- /* Only arc name left - build full arc name */
- ArcNameBuffer = ExAllocatePool(PagedPool, 256 * sizeof(WCHAR));
- swprintf(ArcNameBuffer,
- L"\\ArcName\\%S", ParamBuffer);
- RtlInitUnicodeString(&ArcName, ArcNameBuffer);
-
- /* allocate device name string */
- DeviceName.Length = 0;
- DeviceName.MaximumLength = 256 * sizeof(WCHAR);
- DeviceName.Buffer = ExAllocatePool(PagedPool, 256 * sizeof(WCHAR));
-
- InitializeObjectAttributes(&ObjectAttributes,
- &ArcName,
- OBJ_OPENLINK,
- NULL,
- NULL);
-
- Status = ZwOpenSymbolicLinkObject(&Handle,
- SYMBOLIC_LINK_ALL_ACCESS,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
+ /* Check if we only found a disk, but we're booting from CD-ROM */
+ if ((SingleDisk) && strstr(LoaderBlock->ArcBootDeviceName, "cdrom"))
{
- RtlFreeUnicodeString(&BootPath);
- ExFreePool(DeviceName.Buffer);
- CPRINT("ZwOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
- &ArcName,
- Status);
- ExFreePool(ArcName.Buffer);
-
- return(Status);
+ /* Then disable single-disk mode, since there's a CD drive out there */
+ SingleDisk = FALSE;
}
- ExFreePool(ArcName.Buffer);
- Status = ZwQuerySymbolicLinkObject(Handle,
- &DeviceName,
- &Length);
- ZwClose (Handle);
- if (!NT_SUCCESS(Status))
+ /* Build the boot strings */
+ RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName);
+ RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName);
+
+ /* Loop every detected disk */
+ for (i = 0; i < ConfigInfo->DiskCount; i++)
{
- RtlFreeUnicodeString(&BootPath);
- ExFreePool(DeviceName.Buffer);
- CPRINT("ZwQuerySymbolicObject() failed (Status %x)\n",
- Status);
+ /* Get information about the disk */
+ if (!IopGetDiskInformation(i,
+ &Checksum,
+ &Signature,
+ &PartitionCount,
+ &DeviceObject))
+ {
+ /* Skip this disk */
+ continue;
+ }
- return(Status);
- }
+ /* Loop ARC disks */
+ for (NextEntry = ArcDiskInfo->DiskSignatureListHead.Flink;
+ NextEntry != &ArcDiskInfo->DiskSignatureListHead;
+ NextEntry = NextEntry->Flink)
+ {
+ /* Get the current ARC disk signature entry */
+ ArcDiskEntry = CONTAINING_RECORD(NextEntry,
+ ARC_DISK_SIGNATURE,
+ ListEntry);
+
+ /*
+ * Now check if the signature and checksum match, unless this is
+ * the only disk that was in the ARC list, and also in the device
+ * tree, in which case the check is bypassed and we accept the disk
+ */
+ if (((SingleDisk) && (ConfigInfo->DiskCount == 1)) ||
+ ((Checksum == ArcDiskEntry->CheckSum) &&
+ (Signature == ArcDiskEntry->Signature)))
+ {
+ /* Build the NT Device Name */
+ sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", i);
+
+ /* Convert it to Unicode */
+ RtlInitAnsiString(&ArcString, Buffer);
+ Status = RtlAnsiStringToUnicodeString(&DeviceName,
+ &ArcString,
+ TRUE);
+ if (!NT_SUCCESS(Status)) continue;
+
+ /* Build the ARC Device Name */
+ sprintf(Buffer, "\\ArcName\\%s", ArcDiskEntry->ArcName);
+
+ /* Convert it to Unicode */
+ RtlInitAnsiString(&ArcString, Buffer);
+ Status = RtlAnsiStringToUnicodeString(&ArcName,
+ &ArcString,
+ TRUE);
+ if (!NT_SUCCESS(Status)) continue;
+
+ /* Create the symbolic link and free the strings */
+ IoAssignArcName(&ArcName, &DeviceName);
+ RtlFreeUnicodeString(&ArcName);
+ RtlFreeUnicodeString(&DeviceName);
+
+ /* Loop all the partitions */
+ for (j = 0; j < PartitionCount; j++)
+ {
+ /* Build the partition device name */
+ sprintf(Buffer,
+ "\\Device\\Harddisk%lu\\Partition%lu",
+ i,
+ j + 1);
+
+ /* Convert it to Unicode */
+ RtlInitAnsiString(&ArcString, Buffer);
+ Status = RtlAnsiStringToUnicodeString(&DeviceName,
+ &ArcString,
+ TRUE);
+ if (!NT_SUCCESS(Status)) continue;
+
+ /* Build the partial ARC name for this partition */
+ sprintf(Buffer,
+ "%spartition(%lu)",
+ ArcDiskEntry->ArcName,
+ j + 1);
+ RtlInitAnsiString(&ArcString, Buffer);
+
+ /* Check if this is the boot device */
+ if (RtlEqualString(&ArcString, &ArcBootString, TRUE))
+ {
+ /* Remember that we found a Hard Disk Boot Device */
+ FoundBoot = TRUE;
+ }
+
+ /* Check if it's the system boot partition */
+ if (RtlEqualString(&ArcString, &ArcSystemString, TRUE))
+ {
+ /* It is, create a Unicode string for it */
+ RtlInitAnsiString(&ArcString,
+ LoaderBlock->NtHalPathName);
+ Status = RtlAnsiStringToUnicodeString(&BootPath,
+ &ArcString,
+ TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ /* FIXME: Save in registry */
- RtlAppendUnicodeStringToString(&DeviceName,
- &BootPath);
+ /* Free the string now */
+ RtlFreeUnicodeString(&BootPath);
+ }
+ }
- RtlFreeUnicodeString(&BootPath);
+ /* Build the full ARC name */
+ sprintf(Buffer,
+ "\\ArcName\\%spartition(%lu)",
+ ArcDiskEntry->ArcName,
+ j + 1);
+
+ /* Convert it to Unicode */
+ RtlInitAnsiString(&ArcString, Buffer);
+ Status = RtlAnsiStringToUnicodeString(&ArcName,
+ &ArcString,
+ TRUE);
+ if (!NT_SUCCESS(Status)) continue;
+
+ /* Create the symbolic link and free the strings */
+ IoAssignArcName(&ArcName, &DeviceName);
+ RtlFreeUnicodeString(&ArcName);
+ RtlFreeUnicodeString(&DeviceName);
+ }
+ }
+ }
+ }
- /* create the '\SystemRoot' link */
- Status = IoCreateSymbolicLink(&LinkName,
- &DeviceName);
- ExFreePool(DeviceName.Buffer);
- if (!NT_SUCCESS(Status))
+ /* Check if we didn't find the boot disk */
+ if (!FoundBoot)
{
- CPRINT("IoCreateSymbolicLink() failed (Status %x)\n",
- Status);
+ /* Allocate a buffer for the CD-ROM MBR */
+ PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool, 2048, TAG_IO);
+ if (!PartitionBuffer) return STATUS_INSUFFICIENT_RESOURCES;
- return(Status);
+ /* Loop every CD-ROM */
+ for (i = 0; i < ConfigInfo->CdRomCount; i++)
+ {
+ /* Give it an ARC name */
+ if (IopAssignArcNamesToCdrom(LoaderBlock, PartitionBuffer, i)) break;
+ }
+
+ /* Free the buffer */
+ ExFreePoolWithTag(PartitionBuffer, TAG_IO);
}
- /* Check whether '\SystemRoot'(LinkName) can be opened */
- InitializeObjectAttributes(&ObjectAttributes,
- &LinkName,
- 0,
- NULL,
- NULL);
-
- Status = ZwOpenFile(&Handle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- 0);
- if (!NT_SUCCESS(Status))
+ /* Return success */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ OUT PANSI_STRING NtBootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ CHAR Buffer[256], AnsiBuffer[256];
+ WCHAR ArcNameBuffer[64];
+ ANSI_STRING TargetString, ArcString, TempString;
+ UNICODE_STRING LinkName, TargetName, ArcName;
+ HANDLE LinkHandle;
+
+ /* Create the Unicode name for the current ARC boot device */
+ sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
+ RtlInitAnsiString(&TargetString, Buffer);
+ Status = RtlAnsiStringToUnicodeString(&TargetName, &TargetString, TRUE);
+ if (!NT_SUCCESS(Status)) return FALSE;
+
+ /* Initialize the attributes and open the link */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &TargetName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenSymbolicLinkObject(&LinkHandle,
+ SYMBOLIC_LINK_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
{
- CPRINT("ZwOpenFile() failed to open '\\SystemRoot' (Status %x)\n",
- Status);
- return(Status);
+ /* We failed, free the string */
+ RtlFreeUnicodeString(&TargetName);
+ return FALSE;
}
- ZwClose(Handle);
+ /* Query the current \\SystemRoot */
+ ArcName.Buffer = ArcNameBuffer;
+ ArcName.Length = 0;
+ ArcName.MaximumLength = sizeof(ArcNameBuffer);
+ Status = NtQuerySymbolicLinkObject(LinkHandle, &ArcName, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* We failed, free the string */
+ RtlFreeUnicodeString(&TargetName);
+ return FALSE;
+ }
- return(STATUS_SUCCESS);
+ /* Convert it to Ansi */
+ ArcString.Buffer = AnsiBuffer;
+ ArcString.Length = 0;
+ ArcString.MaximumLength = sizeof(AnsiBuffer);
+ Status = RtlUnicodeStringToAnsiString(&ArcString, &ArcName, FALSE);
+ AnsiBuffer[ArcString.Length] = ANSI_NULL;
+
+ /* Close the link handle and free the name */
+ ObCloseHandle(LinkHandle, KernelMode);
+ RtlFreeUnicodeString(&TargetName);
+
+ /* Setup the system root name again */
+ RtlInitAnsiString(&TempString, "\\SystemRoot");
+ Status = RtlAnsiStringToUnicodeString(&LinkName, &TempString, TRUE);
+ if (!NT_SUCCESS(Status)) return FALSE;
+
+ /* Open the symbolic link for it */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &LinkName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenSymbolicLinkObject(&LinkHandle,
+ SYMBOLIC_LINK_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status)) return FALSE;
+
+ /* Destroy it */
+ NtMakeTemporaryObject(LinkHandle);
+ ObCloseHandle(LinkHandle, KernelMode);
+
+ /* Now create the new name for it */
+ sprintf(Buffer, "%s%s", ArcString.Buffer, LoaderBlock->NtBootPathName);
+
+ /* Copy it into the passed parameter and null-terminate it */
+ RtlCopyString(NtBootPath, &ArcString);
+ Buffer[strlen(Buffer) - 1] = ANSI_NULL;
+
+ /* Setup the Unicode-name for the new symbolic link value */
+ RtlInitAnsiString(&TargetString, Buffer);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &LinkName,
+ OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+ NULL,
+ NULL);
+ Status = RtlAnsiStringToUnicodeString(&ArcName, &TargetString, TRUE);
+ if (!NT_SUCCESS(Status)) return FALSE;
+
+ /* Create it */
+ Status = NtCreateSymbolicLinkObject(&LinkHandle,
+ SYMBOLIC_LINK_ALL_ACCESS,
+ &ObjectAttributes,
+ &ArcName);
+
+ /* Free all the strings and close the handle and return success */
+ RtlFreeUnicodeString(&ArcName);
+ RtlFreeUnicodeString(&LinkName);
+ ObCloseHandle(LinkHandle, KernelMode);
+ return TRUE;
}
/* EOF */