⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arcname.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
* 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 + -