+ /* 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);