From 6d0861e9ed4368f854068315ba3af69689976774 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Tue, 12 Oct 2010 20:29:50 +0000 Subject: [PATCH] [NTOSKRNL] Implemented IopFetchConfigurationInformation(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopVerifyDiskSignature() Removed IopApplyRosCdromArcHack(), IopGetDiskInformation(), IopAssignArcNamesToCdrom() Finally, rewritten IopCreateArcNames() To make it short, this is the rewrite of ARC names handling in the kernel. This brings our kernel to a higher state of existence. Indeed, it's leaving NT4 design for a proper NT5.2 design, with less hacks, less ROS specific stuff and such. This code handles the mount manager we don't have yet. svn path=/trunk/; revision=49131 --- reactos/lib/sdk/wdmguid/wdmguid.c | 4 + reactos/ntoskrnl/include/internal/io.h | 17 + reactos/ntoskrnl/io/iomgr/arcname.c | 1303 ++++++++++++++---------- reactos/ntoskrnl/io/iomgr/iorsrce.c | 41 + 4 files changed, 815 insertions(+), 550 deletions(-) diff --git a/reactos/lib/sdk/wdmguid/wdmguid.c b/reactos/lib/sdk/wdmguid/wdmguid.c index 44a0383e7e3..3ae2ac42bff 100644 --- a/reactos/lib/sdk/wdmguid/wdmguid.c +++ b/reactos/lib/sdk/wdmguid/wdmguid.c @@ -10,5 +10,9 @@ /* FIXME: shouldn't go there! */ DEFINE_GUID(GUID_DEVICE_SYS_BUTTON, 0x4AFA3D53L, 0x74A7, 0x11d0, 0xbe, 0x5e, 0x00, 0xA0, 0xC9, 0x06, 0x28, 0x57); +DEFINE_GUID(GUID_DEVINTERFACE_DISK, + 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(GUID_DEVINTERFACE_CDROM, + 0x53f56308L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); /* EOF */ diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index cfe700567c3..28bc779111c 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -741,6 +741,14 @@ IoInitSystem( IN PLOADER_PARAMETER_BLOCK LoaderBlock ); +BOOLEAN +NTAPI +IopVerifyDiskSignature( + IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout, + IN PARC_DISK_SIGNATURE ArcDiskSignature, + OUT PULONG Signature +); + // // Device/Volume Routines // @@ -1165,8 +1173,17 @@ IopStartRamdisk( IN PLOADER_PARAMETER_BLOCK LoaderBlock ); +// // Configuration Routines // +NTSTATUS +NTAPI +IopFetchConfigurationInformation(OUT PWSTR * SymbolicLinkList, + IN GUID Guid, + IN ULONG ExpectedInterfaces, + IN PULONG Interfaces +); + VOID NTAPI IopStoreSystemPartitionInformation(IN PUNICODE_STRING NtSystemPartitionDeviceName, diff --git a/reactos/ntoskrnl/io/iomgr/arcname.c b/reactos/ntoskrnl/io/iomgr/arcname.c index 1e08ece5563..17d242ef5c5 100644 --- a/reactos/ntoskrnl/io/iomgr/arcname.c +++ b/reactos/ntoskrnl/io/iomgr/arcname.c @@ -5,6 +5,7 @@ * PURPOSE: ARC Path Initialization Functions * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) * Eric Kohl +* Pierre Schweitzer (pierre.schweitzer@reactos.org) */ /* INCLUDES ******************************************************************/ @@ -17,429 +18,35 @@ UNICODE_STRING IoArcHalDeviceName, IoArcBootDeviceName; PCHAR IoLoaderArcBootDeviceName; -extern PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock; /* FUNCTIONS *****************************************************************/ -BOOLEAN +NTSTATUS INIT_FUNCTION NTAPI -IopApplyRosCdromArcHack(IN ULONG i) -{ - 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; +IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock +); - /* 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) - { - /* 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)) - { - /* We did, save the device number */ - DeviceNumber = i; - } - else - { - /* 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); - } - - 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)) - { - return TRUE; - } - - /* Failed */ - return FALSE; -} - -BOOLEAN +NTSTATUS 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_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) - { - /* 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) - { - /* Try again */ - ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM); - 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); - if (!Irp) - { - /* Try again */ - ExFreePoolWithTag(PartitionBuffer, TAG_IO); - ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM); - return FALSE; - } - - /* 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 */ - ExFreePoolWithTag(PartitionBuffer, TAG_IO); - ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM); - 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 */ - ExFreePoolWithTag(PartitionBuffer, TAG_IO); - ExFreePoolWithTag(DriveLayout, TAG_FILE_SYSTEM); - return TRUE; -} - -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; - } - - /* 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]; - -#ifndef _M_AMD64 - if (KeRosLoaderBlock) goto freeldrhack; -#endif - - /* Search if this device is the actual boot CD */ - 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); - /* And check if checksums and arc names match */ - if (CheckSum + ArcDiskEntry->CheckSum == 0 && - strcmp(KeLoaderBlock->ArcBootDeviceName, ArcDiskEntry->ArcName) == 0) - { - IsBootCdRom = TRUE; - break; - } - } - goto checkbootcd; - -#ifndef _M_AMD64 -freeldrhack: -#endif - /* - * 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); - - /* Convert it to Unicode */ - RtlInitAnsiString(&TempString, ArcBuffer); - Status = RtlAnsiStringToUnicodeString(&ArcName, &TempString, TRUE); - if (!NT_SUCCESS(Status)) return FALSE; - - /* 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; - } - - /* No boot CD found */ - return FALSE; -} +IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN BOOLEAN SingleDisk, + IN PBOOLEAN FoundBoot +); NTSTATUS INIT_FUNCTION NTAPI IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { - PCONFIGURATION_INFORMATION ConfigInfo = IoGetConfigurationInformation(); PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation; CHAR Buffer[128]; - ANSI_STRING ArcBootString, ArcSystemString, ArcString; - UNICODE_STRING ArcName, BootPath, DeviceName; + ANSI_STRING ArcSystemString, ArcString; BOOLEAN SingleDisk; - ULONG i, j, Length; - PDEVICE_OBJECT DeviceObject; - ULONG Signature, Checksum, PartitionCount; - PLIST_ENTRY NextEntry; - PARC_DISK_SIGNATURE ArcDiskEntry; + ULONG Length; NTSTATUS Status; BOOLEAN FoundBoot = FALSE; - PULONG PartitionBuffer; /* Check if we only have one disk on the machine */ SingleDisk = ArcDiskInfo->DiskSignatureListHead.Flink->Flink == @@ -476,158 +83,704 @@ IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock) } /* Build the boot strings */ - RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName); RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName); - /* Loop every detected disk */ - for (i = 0; i < ConfigInfo->DiskCount; i++) + /* FIXME: Handle IoRemoteBootClient here and create appropriate symbolic link */ + + /* Loop every disk and try to find boot disk */ + Status = IopCreateArcNamesDisk(LoaderBlock, SingleDisk, &FoundBoot); + /* If it succeed but we didn't find boot device, try to browse Cds */ + if (NT_SUCCESS(Status) && !FoundBoot) { - /* Get information about the disk */ - if (!IopGetDiskInformation(i, - &Checksum, - &Signature, - &PartitionCount, - &DeviceObject)) - { - /* Skip this disk */ - continue; - } - - /* 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)) - { - /* Save in registry */ - IopStoreSystemPartitionInformation(&DeviceName, &BootPath); - - /* Free the string now */ - 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); - } - } - } - } - - /* Check if we didn't find the boot disk */ - if (!FoundBoot) - { - /* Allocate a buffer for the CD-ROM MBR */ - PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool, 2048, TAG_IO); - if (!PartitionBuffer) return STATUS_INSUFFICIENT_RESOURCES; - - /* 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); + Status = IopCreateArcNamesCd(LoaderBlock); } /* Return success */ - return STATUS_SUCCESS; + return Status; +} + +NTSTATUS +INIT_FUNCTION +NTAPI +IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + PIRP Irp; + KEVENT Event; + NTSTATUS Status; + PLIST_ENTRY NextEntry; + PFILE_OBJECT FileObject; + PDEVICE_OBJECT DeviceObject; + LARGE_INTEGER StartingOffset; + IO_STATUS_BLOCK IoStatusBlock; + PULONG PartitionBuffer = NULL; + CHAR Buffer[128], ArcBuffer[128]; + BOOLEAN NotEnabledPresent = FALSE; + STORAGE_DEVICE_NUMBER DeviceNumber; + ANSI_STRING DeviceStringA, ArcNameStringA; + PWSTR SymbolicLinkList, lSymbolicLinkList; + PARC_DISK_SIGNATURE ArcDiskSignature = NULL; + UNICODE_STRING DeviceStringW, ArcNameStringW; + ULONG DiskNumber, CdRomCount, CheckSum, i, EnabledDisks = 0; + PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation; + + /* Get all the Cds present in the system */ + CdRomCount = IoGetConfigurationInformation()->CdRomCount; + + /* Get enabled Cds and check if result matches + * For the record, enabled Cds (or even disk) are Cds/disks + * that have been successfully handled by MountMgr driver + * and that already own their device name. This is the "new" way + * to handle them, that came with NT5. + * Currently, Windows 2003 provides an arc names creation based + * on both enabled drives and not enabled drives (lack from + * the driver). + * Given the current ReactOS state, that's good for us. + * To sum up, this is NOT a hack or whatsoever. + */ + Status = IopFetchConfigurationInformation(&SymbolicLinkList, + GUID_DEVINTERFACE_CDROM, + CdRomCount, + &EnabledDisks); + if (!NT_SUCCESS(Status)) + { + NotEnabledPresent = TRUE; + } + /* Save symbolic link list address in order to free it after */ + lSymbolicLinkList = SymbolicLinkList; + /* For the moment, we won't fail */ + Status = STATUS_SUCCESS; + + /* Browse all the ARC devices trying to find the one matching boot device */ + for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink; + NextEntry != &ArcDiskInformation->DiskSignatureListHead; + NextEntry = NextEntry->Flink) + { + ArcDiskSignature = CONTAINING_RECORD(NextEntry, + ARC_DISK_SIGNATURE, + ListEntry); + + if (strcmp(LoaderBlock->ArcBootDeviceName, ArcDiskSignature->ArcName) == 0) + { + break; + } + + ArcDiskSignature = NULL; + } + + /* Not found... Not booting from a Cd */ + if (!ArcDiskSignature) + { + DPRINT("Failed finding a cd that could match current boot device\n"); + goto Cleanup; + } + + /* Allocate needed space for reading Cd */ + PartitionBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, 2048, TAG_IO); + if (!PartitionBuffer) + { + DPRINT("Failed allocating resources!\n"); + /* Here, we fail, BUT we return success, some Microsoft joke */ + goto Cleanup; + } + + /* If we have more enabled Cds, take that into account */ + if (EnabledDisks > CdRomCount) + { + CdRomCount = EnabledDisks; + } + + /* If we'll have to browse for none enabled Cds, fix higher count */ + if (NotEnabledPresent && !EnabledDisks) + { + CdRomCount += 5; + } + + /* Finally, if in spite of all that work, we still don't have Cds, leave */ + if (!CdRomCount) + { + goto Cleanup; + } + + /* Start browsing Cds */ + for (DiskNumber = 0, EnabledDisks = 0; DiskNumber < CdRomCount; DiskNumber++) + { + /* Check if we have an enabled disk */ + if (SymbolicLinkList && *SymbolicLinkList != UNICODE_NULL) + { + /* Create its device name using first symbolic link */ + RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList); + /* Then, update symbolic links list */ + lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); + + /* Get its associated device object and file object */ + Status = IoGetDeviceObjectPointer(&DeviceStringW, + FILE_READ_ATTRIBUTES, + &FileObject, + &DeviceObject); + /* Failure? Good bye! */ + if (!NT_SUCCESS(Status)) + { + goto Cleanup; + } + + /* Now, we'll ask the device its device number */ + Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER, + DeviceObject, + NULL, + 0, + &DeviceNumber, + sizeof(STORAGE_DEVICE_NUMBER), + FALSE, + &Event, + &IoStatusBlock); + /* Failure? Good bye! */ + if (!Irp) + { + /* Dereference file object before leaving */ + ObDereferenceObject(FileObject); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Cleanup; + } + + /* Call the driver, and wait for it if needed */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatusBlock.Status; + } + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + goto Cleanup; + } + + /* Finally, build proper device name */ + sprintf(Buffer, "\\Device\\CdRom%lu", DeviceNumber.DeviceNumber); + RtlInitAnsiString(&DeviceStringA, Buffer); + Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + goto Cleanup; + } + } + else + { + /* Create device name for the cd */ + sprintf(Buffer, "\\Device\\CdRom%lu", EnabledDisks++); + RtlInitAnsiString(&DeviceStringA, Buffer); + Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); + if (!NT_SUCCESS(Status)) + { + goto Cleanup; + } + + /* Get its device object */ + Status = IoGetDeviceObjectPointer(&DeviceStringW, + FILE_READ_ATTRIBUTES, + &FileObject, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&DeviceStringW); + goto Cleanup; + } + } + + /* Initiate data for reading cd and compute checksum */ + StartingOffset.QuadPart = 0x8000; + CheckSum = 0; + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + PartitionBuffer, + 2048, + &StartingOffset, + &Event, + &IoStatusBlock); + if (Irp) + { + /* Call the driver, and wait for it if needed */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatusBlock.Status; + } + + /* Reading succeed, compute checksum by adding data, 2048 bytes checksum */ + if (NT_SUCCESS(Status)) + { + for (i = 0; i < 2048 / sizeof(ULONG); i++) + { + CheckSum += PartitionBuffer[i]; + } + } + } + + /* Dereference file object */ + ObDereferenceObject(FileObject); + + /* If checksums are matching, we have the proper cd */ + if (CheckSum + ArcDiskSignature->CheckSum == 0) + { + /* Create ARC name */ + sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName); + RtlInitAnsiString(&ArcNameStringA, ArcBuffer); + Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE); + if (NT_SUCCESS(Status)) + { + /* Create symbolic link */ + IoCreateSymbolicLink(&ArcNameStringW, &DeviceStringW); + RtlFreeUnicodeString(&ArcNameStringW); + DPRINT1("Boot device found\n"); + } + + /* And quit, whatever happens */ + RtlFreeUnicodeString(&DeviceStringW); + goto Cleanup; + } + + /* Free string before trying another disk */ + RtlFreeUnicodeString(&DeviceStringW); + } + +Cleanup: + if (PartitionBuffer) + { + ExFreePoolWithTag(PartitionBuffer, TAG_IO); + } + + if (SymbolicLinkList) + { + ExFreePool(SymbolicLinkList); + } + + return Status; +} + +NTSTATUS +INIT_FUNCTION +NTAPI +IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN BOOLEAN SingleDisk, + IN PBOOLEAN FoundBoot) +{ + PIRP Irp; + PVOID Data; + KEVENT Event; + NTSTATUS Status; + PLIST_ENTRY NextEntry; + PFILE_OBJECT FileObject; + DISK_GEOMETRY DiskGeometry; + PDEVICE_OBJECT DeviceObject; + LARGE_INTEGER StartingOffset; + PULONG PartitionBuffer = NULL; + IO_STATUS_BLOCK IoStatusBlock; + CHAR Buffer[128], ArcBuffer[128]; + BOOLEAN NotEnabledPresent = FALSE; + STORAGE_DEVICE_NUMBER DeviceNumber; + PARC_DISK_SIGNATURE ArcDiskSignature; + PWSTR SymbolicLinkList, lSymbolicLinkList; + PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL; + UNICODE_STRING DeviceStringW, ArcNameStringW, HalPathStringW; + ULONG DiskNumber, DiskCount, CheckSum, i, Signature, EnabledDisks = 0; + PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation; + ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA, HalPathStringA; + + /* Initialise device number */ + DeviceNumber.DeviceNumber = 0xFFFFFFFF; + /* Get all the disks present in the system */ + DiskCount = IoGetConfigurationInformation()->DiskCount; + + /* Get enabled disks and check if result matches */ + Status = IopFetchConfigurationInformation(&SymbolicLinkList, + GUID_DEVINTERFACE_DISK, + DiskCount, + &EnabledDisks); + if (!NT_SUCCESS(Status)) + { + NotEnabledPresent = TRUE; + } + + /* Save symbolic link list address in order to free it after */ + lSymbolicLinkList = SymbolicLinkList; + + /* Build the boot strings */ + RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName); + RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName); + + /* If we have more enabled disks, take that into account */ + if (EnabledDisks > DiskCount) + { + DiskCount = EnabledDisks; + } + + /* If we'll have to browse for none enabled disks, fix higher count */ + if (NotEnabledPresent && !EnabledDisks) + { + DiskCount += 20; + } + + /* Finally, if in spite of all that work, we still don't have disks, leave */ + if (!DiskCount) + { + goto Cleanup; + } + + /* Start browsing disks */ + for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++) + { + /* Check if we have an enabled disk */ + if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL) + { + /* Create its device name using first symbolic link */ + RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList); + /* Then, update symbolic links list */ + lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); + + /* Get its associated device object and file object */ + Status = IoGetDeviceObjectPointer(&DeviceStringW, + FILE_READ_ATTRIBUTES, + &FileObject, + &DeviceObject); + if (NT_SUCCESS(Status)) + { + /* Now, we'll ask the device its device number */ + Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER, + DeviceObject, + NULL, + 0, + &DeviceNumber, + sizeof(STORAGE_DEVICE_NUMBER), + FALSE, + &Event, + &IoStatusBlock); + /* Missing resources is a shame... No need to go farther */ + if (!Irp) + { + ObDereferenceObject(FileObject); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Cleanup; + } + + /* Call the driver, and wait for it if needed */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatusBlock.Status; + } + + /* If we didn't get the appriopriate data, just skip that disk */ + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + continue; + } + } + + /* End of enabled disks enumeration */ + if (NotEnabledPresent && *lSymbolicLinkList == UNICODE_NULL) + { + /* No enabled disk worked, reset field */ + if (DeviceNumber.DeviceNumber == 0xFFFFFFFF) + { + DeviceNumber.DeviceNumber = 0; + } + + /* Update disk number to enable the following not enabled disks */ + if (DeviceNumber.DeviceNumber > DiskNumber) + { + DiskNumber = DeviceNumber.DeviceNumber; + } + + /* Increase a bit more */ + DiskCount = DiskNumber + 20; + } + } + else + { + /* Create device name for the disk */ + sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber); + RtlInitAnsiString(&DeviceStringA, Buffer); + Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); + if (!NT_SUCCESS(Status)) + { + goto Cleanup; + } + + /* Get its device object */ + Status = IoGetDeviceObjectPointer(&DeviceStringW, + FILE_READ_ATTRIBUTES, + &FileObject, + &DeviceObject); + + RtlFreeUnicodeString(&DeviceStringW); + /* This is a security measure, to ensure DiskNumber will be used */ + DeviceNumber.DeviceNumber = 0xFFFFFFFF; + } + + /* Something failed somewhere earlier, just skip the disk */ + if (!NT_SUCCESS(Status)) + { + continue; + } + + /* Let's ask the disk for its geometry */ + Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, + DeviceObject, + NULL, + 0, + &DiskGeometry, + sizeof(DISK_GEOMETRY), + FALSE, + &Event, + &IoStatusBlock); + /* Missing resources is a shame... No need to go farther */ + if (!Irp) + { + ObDereferenceObject(FileObject); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Cleanup; + } + + /* Call the driver, and wait for it if needed */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatusBlock.Status; + } + /* Failure, skip disk */ + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + continue; + } + + /* Read the partition table */ + Status = IoReadPartitionTableEx(DeviceObject, + &DriveLayout); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + continue; + } + + /* Ensure we have at least 512 bytes per sector */ + if (DiskGeometry.BytesPerSector < 512) + { + DiskGeometry.BytesPerSector = 512; + } + + /* Check MBR type against EZ Drive type */ + StartingOffset.QuadPart = 0; + HalExamineMBR(DeviceObject, DiskGeometry.BytesPerSector, 0x55, &Data); + if (Data) + { + /* If MBR is of the EZ Drive type, we'll read after it */ + StartingOffset.QuadPart = DiskGeometry.BytesPerSector; + ExFreePool(Data); + } + + /* Allocate for reading enough data for checksum */ + PartitionBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, DiskGeometry.BytesPerSector, TAG_IO); + if (!PartitionBuffer) + { + ObDereferenceObject(FileObject); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Cleanup; + } + + /* Read a sector for computing checksum */ + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + PartitionBuffer, + DiskGeometry.BytesPerSector, + &StartingOffset, + &Event, + &IoStatusBlock); + if (!Irp) + { + ObDereferenceObject(FileObject); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Cleanup; + } + + /* Call the driver to perform reading */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatusBlock.Status; + } + if (!NT_SUCCESS(Status)) + { + ExFreePool(DriveLayout); + ExFreePoolWithTag(PartitionBuffer, TAG_IO); + ObDereferenceObject(FileObject); + continue; + } + + ObDereferenceObject(FileObject); + + /* Calculate checksum, that's an easy computation, just adds read data */ + for (i = 0, CheckSum = 0; i < 512 / sizeof(ULONG) ; i++) + { + CheckSum += PartitionBuffer[i]; + } + + /* Browse each ARC disk */ + for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink; + NextEntry != &ArcDiskInformation->DiskSignatureListHead; + NextEntry = NextEntry->Flink) + { + ArcDiskSignature = CONTAINING_RECORD(NextEntry, + ARC_DISK_SIGNATURE, + ListEntry); + + /* If they matches, ie + * - There's only one disk for both BIOS and detected/enabled + * - Signatures are matching + * - Checksums are matching + * - This is MBR + */ + if (((SingleDisk && DiskCount == 1) || + (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature) && + (ArcDiskSignature->CheckSum + CheckSum == 0))) && + (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)) + { + /* Create device name */ + sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", (DeviceNumber.DeviceNumber != 0xFFFFFFFF) ? DeviceNumber.DeviceNumber : DiskNumber); + RtlInitAnsiString(&DeviceStringA, Buffer); + Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); + if (!NT_SUCCESS(Status)) + { + goto Cleanup; + } + + /* Create ARC name */ + sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName); + RtlInitAnsiString(&ArcNameStringA, ArcBuffer); + Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&DeviceStringW); + goto Cleanup; + } + + /* Link both */ + IoCreateSymbolicLink(&ArcNameStringW, &DeviceStringW); + + /* And release resources */ + RtlFreeUnicodeString(&ArcNameStringW); + RtlFreeUnicodeString(&DeviceStringW); + + /* Now, browse for every partition */ + for (i = 1; i <= DriveLayout->PartitionCount; i++) + { + /* Create device name */ + sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", (DeviceNumber.DeviceNumber != 0xFFFFFFFF) ? DeviceNumber.DeviceNumber : DiskNumber, i); + RtlInitAnsiString(&DeviceStringA, Buffer); + Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); + if (!NT_SUCCESS(Status)) + { + goto Cleanup; + } + + /* Create partial ARC name */ + sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, i); + RtlInitAnsiString(&ArcNameStringA, ArcBuffer); + + /* Is that boot device? */ + if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE)) + { + DPRINT("Found boot device\n"); + *FoundBoot = TRUE; + } + + /* Is that system partition? */ + if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE)) + { + /* Create HAL path name */ + RtlInitAnsiString(&HalPathStringA, LoaderBlock->NtHalPathName); + Status = RtlAnsiStringToUnicodeString(&HalPathStringW, &HalPathStringA, TRUE); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&DeviceStringW); + goto Cleanup; + } + + /* Then store those information to registry */ + IopStoreSystemPartitionInformation(&DeviceStringW, &HalPathStringW); + RtlFreeUnicodeString(&HalPathStringW); + } + + /* Create complete ARC name */ + sprintf(ArcBuffer, "\\ArcName\\%spartition(%lu)", ArcDiskSignature->ArcName, i); + RtlInitAnsiString(&ArcNameStringA, ArcBuffer); + Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&DeviceStringW); + goto Cleanup; + } + + /* Link device name & ARC name */ + IoCreateSymbolicLink(&ArcNameStringW, &DeviceStringW); + + /* Release strings */ + RtlFreeUnicodeString(&ArcNameStringW); + RtlFreeUnicodeString(&DeviceStringW); + } + } + else + { + /* In case there's a valid partition, a matching signature, + BUT a none matching checksum, or there's a duplicate + signature, or even worse a virus played with partition + table */ + if (ArcDiskSignature->Signature == Signature && + (ArcDiskSignature->CheckSum + CheckSum != 0) && + ArcDiskSignature->ValidPartitionTable) + { + DPRINT("Be careful, or you have a duplicate disk signature, or a virus altered your MBR!\n"); + } + } + } + + /* Release memory before jumping to next item */ + ExFreePool(DriveLayout); + DriveLayout = NULL; + ExFreePoolWithTag(PartitionBuffer, TAG_IO); + PartitionBuffer = NULL; + } + + Status = STATUS_SUCCESS; + +Cleanup: + if (SymbolicLinkList) + { + ExFreePool(SymbolicLinkList); + } + + if (DriveLayout) + { + ExFreePool(DriveLayout); + } + + if (PartitionBuffer) + { + ExFreePoolWithTag(PartitionBuffer, TAG_IO); + } + + return Status; } NTSTATUS @@ -738,4 +891,54 @@ IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock, return TRUE; } +BOOLEAN +NTAPI +IopVerifyDiskSignature(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout, + IN PARC_DISK_SIGNATURE ArcDiskSignature, + OUT PULONG Signature) +{ + /* First condition: having a valid partition table */ + if (!ArcDiskSignature->ValidPartitionTable) + { + return FALSE; + } + + /* If that partition table is the MBR */ + if (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR) + { + /* Then check MBR signature */ + if (DriveLayout->Mbr.Signature == ArcDiskSignature->Signature) + { + /* And return it */ + if (Signature) + { + *Signature = DriveLayout->Mbr.Signature; + } + + return TRUE; + } + } + /* If that partition table is the GPT */ + else if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT) + { + /* Check we are using GPT and compare GUID */ + if (ArcDiskSignature->IsGpt && + (((PULONG)ArcDiskSignature->GptSignature)[0] == DriveLayout->Gpt.DiskId.Data1 && + ((PUSHORT)ArcDiskSignature->GptSignature)[2] == DriveLayout->Gpt.DiskId.Data2 && + ((PUSHORT)ArcDiskSignature->GptSignature)[3] == DriveLayout->Gpt.DiskId.Data3 && + ((PULONGLONG)ArcDiskSignature->GptSignature)[1] == ((PULONGLONG)DriveLayout->Gpt.DiskId.Data4)[0])) + { + /* There's no signature to give, so we just zero output */ + if (Signature) + { + *Signature = 0; + } + return TRUE; + } + } + + /* If we fall here, it means that something went wrong, so return that */ + return FALSE; +} + /* EOF */ diff --git a/reactos/ntoskrnl/io/iomgr/iorsrce.c b/reactos/ntoskrnl/io/iomgr/iorsrce.c index d6ac82255d9..af5913146c6 100644 --- a/reactos/ntoskrnl/io/iomgr/iorsrce.c +++ b/reactos/ntoskrnl/io/iomgr/iorsrce.c @@ -651,6 +651,47 @@ IopQueryBusDescription( return Status; } +NTSTATUS +NTAPI +IopFetchConfigurationInformation(OUT PWSTR * SymbolicLinkList, + IN GUID Guid, + IN ULONG ExpectedInterfaces, + IN PULONG Interfaces) +{ + NTSTATUS Status; + ULONG IntInterfaces = 0; + PWSTR IntSymbolicLinkList; + + /* Get the associated enabled interfaces with the given GUID */ + Status = IoGetDeviceInterfaces(&Guid, NULL, 0, SymbolicLinkList); + if (!NT_SUCCESS(Status)) + { + /* Zero output and leave */ + if (SymbolicLinkList != 0) + { + *SymbolicLinkList = 0; + } + + return STATUS_UNSUCCESSFUL; + } + + IntSymbolicLinkList = *SymbolicLinkList; + + /* Count the number of enabled interfaces by counting the number of symbolic links */ + while (*IntSymbolicLinkList != UNICODE_NULL) + { + IntInterfaces++; + IntSymbolicLinkList += wcslen(IntSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); + } + + /* Matching result will define the result */ + Status = (IntInterfaces >= ExpectedInterfaces) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; + /* Finally, give back to the caller the number of found interfaces */ + *Interfaces = IntInterfaces; + + return Status; +} + VOID NTAPI IopStoreSystemPartitionInformation(IN PUNICODE_STRING NtSystemPartitionDeviceName,