- Fixed the creation of arc names. Only valid partitions should be linked to an arc names. - Create arc names only for partitions on disks, which are visible by the bios. Modified: trunk/reactos/ntoskrnl/io/arcname.c _____
Modified: trunk/reactos/ntoskrnl/io/arcname.c --- trunk/reactos/ntoskrnl/io/arcname.c 2005-09-15 17:19:31 UTC (rev 17864) +++ trunk/reactos/ntoskrnl/io/arcname.c 2005-09-15 17:23:41 UTC (rev 17865) @@ -19,56 +19,197 @@
#define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION))
-/* FUNCTIONS ****************************************************************/ +/* STRUCTURES ***************************************************************/
-NTSTATUS INIT_FUNCTION -IoCreateArcNames(VOID) +typedef struct _DISKENTRY { - PCONFIGURATION_INFORMATION ConfigInfo; - PDRIVE_LAYOUT_INFORMATION LayoutInfo = NULL; - WCHAR DeviceNameBuffer[80]; - WCHAR ArcNameBuffer[80]; - UNICODE_STRING DeviceName; - UNICODE_STRING ArcName; - ULONG i, j, k; - NTSTATUS Status; - PFILE_OBJECT FileObject; + LIST_ENTRY ListEntry; + ULONG DiskNumber; + ULONG Signature; + ULONG Checksum; PDEVICE_OBJECT DeviceObject; - BOOL IsRemovableMedia; +} DISKENTRY, *PDISKENTRY;
- DPRINT("IoCreateArcNames() called\n"); +#define PARTITION_TBL_SIZE 4
- ConfigInfo = IoGetConfigurationInformation(); +#include <pshpack1.h>
- /* create ARC names for floppy drives */ - DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount); - for (i = 0; i < ConfigInfo->FloppyCount; i++) +typedef struct _PARTITION +{ + unsigned char BootFlags; /* bootable? 0=no, 128=yes */ + unsigned char StartingHead; /* beginning head number */ + unsigned char StartingSector; /* beginning sector number */ + unsigned char StartingCylinder; /* 10 bit nmbr, with high 2 bits put in begsect */ + unsigned char PartitionType; /* Operating System type indicator code */ + unsigned char EndingHead; /* ending head number */ + unsigned char EndingSector; /* ending sector number */ + unsigned char EndingCylinder; /* also a 10 bit nmbr, with same high 2 bit trick */ + unsigned int StartingBlock; /* first sector relative to start of disk */ + unsigned int SectorCount; /* number of sectors in partition */ +} PARTITION, *PPARTITION; + +typedef struct _PARTITION_SECTOR +{ + UCHAR BootCode[440]; /* 0x000 */ + ULONG Signature; /* 0x1B8 */ + UCHAR Reserved[2]; /* 0x1BC */ + PARTITION Partition[PARTITION_TBL_SIZE]; /* 0x1BE */ + USHORT Magic; /* 0x1FE */ +} PARTITION_SECTOR, *PPARTITION_SECTOR; + +#include <poppack.h> + +/* FUNCTIONS ****************************************************************/ + +STATIC +NTSTATUS +STDCALL +INIT_FUNCTION +DiskQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + PLIST_ENTRY ListHead = (PLIST_ENTRY)Context; + PULONG GlobalDiskCount = (PULONG)EntryContext; + PDISKENTRY DiskEntry; + UNICODE_STRING NameU; + + if (ValueType == REG_SZ && + ValueLength == 20 * sizeof(WCHAR)) { - swprintf(DeviceNameBuffer, - L"\Device\Floppy%lu", - i); - RtlInitUnicodeString(&DeviceName, - DeviceNameBuffer); + DiskEntry = ExAllocatePool(PagedPool, sizeof(DISKENTRY)); + if (DiskEntry == NULL) + { + return STATUS_NO_MEMORY; + } + DiskEntry->DiskNumber = (*GlobalDiskCount)++;
- swprintf(ArcNameBuffer, - L"\ArcName\multi(0)disk(0)fdisk(%lu)", - i); - RtlInitUnicodeString(&ArcName, - ArcNameBuffer); - DPRINT("%wZ ==> %wZ\n", - &ArcName, - &DeviceName); + NameU.Buffer = (PWCHAR)ValueData; + NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR); + RtlUnicodeStringToInteger(&NameU, 16, &DiskEntry->Checksum);
- Status = IoAssignArcName(&ArcName, - &DeviceName); + 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\MultifunctionAdapt er" + +STATIC VOID INIT_FUNCTION +IopEnumerateBiosDisks(PLIST_ENTRY ListHead) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + WCHAR Name[100]; + 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)) - return(Status); + { + 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++; + } + } + AdapterCount++; } +}
- /* create ARC names for hard disk drives */ - DPRINT("Disk drives: %lu\n", ConfigInfo->DiskCount); - for (i = 0, k = 0; i < ConfigInfo->DiskCount; i++) +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); @@ -88,12 +229,249 @@ 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) + { + KEBUGCHECK(0); + } + + 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) + { + KEBUGCHECK(0); + } + } + + /* 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); + } + + /* 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) + { + ExFreePool(PartitionBuffer); + } +} + +STATIC NTSTATUS INIT_FUNCTION +IopAssignArcNamesToDisk(PDEVICE_OBJECT DeviceObject, ULONG RDisk, ULONG DiskNumber) +{ + 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)) + { + DPRINT1("IoAssignArcName failed, status=%lx\n", Status); + return(Status); + } + + LayoutInfo = ExAllocatePool(PagedPool, 2 * PAGE_SIZE); + if (LayoutInfo == NULL) + { + return STATUS_NO_MEMORY; + } + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT, + DeviceObject, + NULL, + 0, + LayoutInfo, + 2 * PAGE_SIZE, + FALSE, + &Event, + &StatusBlock); + if (Irp == NULL) + { + ExFreePool(LayoutInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = StatusBlock.Status; + } + if (!NT_SUCCESS(Status)) + { + ExFreePool(LayoutInfo); + return Status; + } + + DPRINT("Number of partitions: %u\n", LayoutInfo->PartitionCount); + + PartitionNumber = 1; + for (i = 0; i < LayoutInfo->PartitionCount; i++) + { + 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++; + } + } + 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++) + { + swprintf(DeviceNameBuffer, + L"\Device\Floppy%lu", + i); + RtlInitUnicodeString(&DeviceName, + DeviceNameBuffer); + swprintf(ArcNameBuffer, - L"\ArcName\multi(0)disk(0)rdisk(%lu)partition(0)", - k); + L"\ArcName\multi(0)disk(0)fdisk(%lu)", + i); RtlInitUnicodeString(&ArcName, ArcNameBuffer); DPRINT("%wZ ==> %wZ\n", @@ -104,42 +482,44 @@ &DeviceName); if (!NT_SUCCESS(Status)) return(Status); + }
- Status = xHalQueryDriveLayout(&DeviceName, - &LayoutInfo); - if (!NT_SUCCESS(Status)) - return(Status); + /* create ARC names for hard disk drives */ + InitializeListHead(&BiosDiskListHead); + InitializeListHead(&DiskListHead); + IopEnumerateBiosDisks(&BiosDiskListHead); + IopEnumerateDisks(&DiskListHead);
- DPRINT("Number of partitions: %u\n", LayoutInfo->PartitionCount); + 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) + {
- for (j = 0;j < LayoutInfo->PartitionCount; j++) - { - swprintf(DeviceNameBuffer, - L"\Device\Harddisk%lu\Partition%lu", - i, - j + 1); - RtlInitUnicodeString(&DeviceName, - DeviceNameBuffer); + Status = IopAssignArcNamesToDisk(DiskEntry->DeviceObject, RDiskNumber, DiskEntry->DiskNumber);
- swprintf(ArcNameBuffer, - L"\ArcName\multi(0)disk(0)rdisk(%lu)partition(%lu)", - k, - j + 1); - RtlInitUnicodeString(&ArcName, - ArcNameBuffer); - DPRINT("%wZ ==> %wZ\n", - &ArcName, - &DeviceName); + RemoveEntryList(&DiskEntry->ListEntry); + ExFreePool(DiskEntry); + break; + } + Entry = Entry->Flink; + } + RDiskNumber++; + ExFreePool(BiosDiskEntry); + }
- Status = IoAssignArcName(&ArcName, - &DeviceName); - if (!NT_SUCCESS(Status)) - return(Status); - } - - ExFreePool(LayoutInfo); - LayoutInfo = NULL; - k++; + while (!IsListEmpty(&DiskListHead)) + { + Entry = RemoveHeadList(&DiskListHead); + DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry); + ExFreePool(DiskEntry); }
/* create ARC names for cdrom drives */ @@ -173,7 +553,7 @@ }
-static NTSTATUS +static NTSTATUS INIT_FUNCTION IopCheckCdromDevices(PULONG DeviceNumber) { PCONFIGURATION_INFORMATION ConfigInfo;