Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenarcname.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/io/iomgr/arcname.c 00005 * PURPOSE: ARC Path Initialization Functions 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Eric Kohl 00008 * Pierre Schweitzer (pierre.schweitzer@reactos.org) 00009 */ 00010 00011 /* INCLUDES ******************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 #define NDEBUG 00015 #include <debug.h> 00016 00017 /* GLOBALS *******************************************************************/ 00018 00019 UNICODE_STRING IoArcHalDeviceName, IoArcBootDeviceName; 00020 PCHAR IoLoaderArcBootDeviceName; 00021 extern BOOLEAN IoRemoteBootClient; 00022 00023 /* FUNCTIONS *****************************************************************/ 00024 00025 NTSTATUS 00026 INIT_FUNCTION 00027 NTAPI 00028 IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock 00029 ); 00030 00031 NTSTATUS 00032 INIT_FUNCTION 00033 NTAPI 00034 IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00035 IN BOOLEAN SingleDisk, 00036 IN PBOOLEAN FoundBoot 00037 ); 00038 00039 NTSTATUS 00040 INIT_FUNCTION 00041 NTAPI 00042 IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00043 { 00044 SIZE_T Length; 00045 NTSTATUS Status; 00046 CHAR Buffer[128]; 00047 BOOLEAN SingleDisk; 00048 BOOLEAN FoundBoot = FALSE; 00049 UNICODE_STRING SystemDevice, LoaderPathNameW, BootDeviceName; 00050 PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation; 00051 ANSI_STRING ArcSystemString, ArcString, LanmanRedirector, LoaderPathNameA; 00052 00053 /* Check if we only have one disk on the machine */ 00054 SingleDisk = ArcDiskInfo->DiskSignatureListHead.Flink->Flink == 00055 (&ArcDiskInfo->DiskSignatureListHead); 00056 00057 /* Create the global HAL partition name */ 00058 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName); 00059 RtlInitAnsiString(&ArcString, Buffer); 00060 RtlAnsiStringToUnicodeString(&IoArcHalDeviceName, &ArcString, TRUE); 00061 00062 /* Create the global system partition name */ 00063 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName); 00064 RtlInitAnsiString(&ArcString, Buffer); 00065 RtlAnsiStringToUnicodeString(&IoArcBootDeviceName, &ArcString, TRUE); 00066 00067 /* Allocate memory for the string */ 00068 Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL); 00069 IoLoaderArcBootDeviceName = ExAllocatePoolWithTag(PagedPool, 00070 Length, 00071 TAG_IO); 00072 if (IoLoaderArcBootDeviceName) 00073 { 00074 /* Copy the name */ 00075 RtlCopyMemory(IoLoaderArcBootDeviceName, 00076 LoaderBlock->ArcBootDeviceName, 00077 Length); 00078 } 00079 00080 /* Check if we only found a disk, but we're booting from CD-ROM */ 00081 if ((SingleDisk) && strstr(LoaderBlock->ArcBootDeviceName, "cdrom")) 00082 { 00083 /* Then disable single-disk mode, since there's a CD drive out there */ 00084 SingleDisk = FALSE; 00085 } 00086 00087 /* Build the boot strings */ 00088 RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName); 00089 00090 /* If we are doing remote booting */ 00091 if (IoRemoteBootClient) 00092 { 00093 /* Yes, we have found boot device */ 00094 FoundBoot = TRUE; 00095 00096 /* Get NT device name */ 00097 RtlInitAnsiString(&LanmanRedirector, "\\Device\\LanmanRedirector"); 00098 Status = RtlAnsiStringToUnicodeString(&SystemDevice, &LanmanRedirector, TRUE); 00099 if (!NT_SUCCESS(Status)) 00100 { 00101 return Status; 00102 } 00103 00104 /* Get ARC booting device name (in net(0) something) */ 00105 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName); 00106 RtlInitAnsiString(&ArcString, Buffer); 00107 Status = RtlAnsiStringToUnicodeString(&BootDeviceName, &ArcString, TRUE); 00108 if (NT_SUCCESS(Status)) 00109 { 00110 /* Map ARC to NT name */ 00111 IoAssignArcName(&BootDeviceName, &SystemDevice); 00112 RtlFreeUnicodeString(&BootDeviceName); 00113 00114 /* Now, get loader path name */ 00115 RtlInitAnsiString(&LoaderPathNameA, LoaderBlock->NtHalPathName); 00116 Status = RtlAnsiStringToUnicodeString(&LoaderPathNameW, &LoaderPathNameA, TRUE); 00117 if (!NT_SUCCESS(Status)) 00118 { 00119 RtlFreeUnicodeString(&SystemDevice); 00120 return Status; 00121 } 00122 00123 /* And set it has system partition */ 00124 IopStoreSystemPartitionInformation(&SystemDevice, &LoaderPathNameW); 00125 } 00126 00127 RtlFreeUnicodeString(&SystemDevice); 00128 00129 /* Don't quit here, even if everything went fine! 00130 * We need IopCreateArcNamesDisk to properly map 00131 * devices with symlinks. 00132 * It will return success if the mapping process went fine 00133 * even if it didn't find boot device. 00134 * It won't reset boot device finding status as well. 00135 */ 00136 } 00137 00138 /* Loop every disk and try to find boot disk */ 00139 Status = IopCreateArcNamesDisk(LoaderBlock, SingleDisk, &FoundBoot); 00140 /* If it succeed but we didn't find boot device, try to browse Cds */ 00141 if (NT_SUCCESS(Status) && !FoundBoot) 00142 { 00143 Status = IopCreateArcNamesCd(LoaderBlock); 00144 } 00145 00146 /* Return success */ 00147 return Status; 00148 } 00149 00150 NTSTATUS 00151 INIT_FUNCTION 00152 NTAPI 00153 IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00154 { 00155 PIRP Irp; 00156 KEVENT Event; 00157 NTSTATUS Status; 00158 PLIST_ENTRY NextEntry; 00159 PFILE_OBJECT FileObject; 00160 PDEVICE_OBJECT DeviceObject; 00161 LARGE_INTEGER StartingOffset; 00162 IO_STATUS_BLOCK IoStatusBlock; 00163 PULONG PartitionBuffer = NULL; 00164 CHAR Buffer[128], ArcBuffer[128]; 00165 BOOLEAN NotEnabledPresent = FALSE; 00166 STORAGE_DEVICE_NUMBER DeviceNumber; 00167 ANSI_STRING DeviceStringA, ArcNameStringA; 00168 PWSTR SymbolicLinkList, lSymbolicLinkList; 00169 PARC_DISK_SIGNATURE ArcDiskSignature = NULL; 00170 UNICODE_STRING DeviceStringW, ArcNameStringW; 00171 ULONG DiskNumber, CdRomCount, CheckSum, i, EnabledDisks = 0; 00172 PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation; 00173 00174 /* Get all the Cds present in the system */ 00175 CdRomCount = IoGetConfigurationInformation()->CdRomCount; 00176 00177 /* Get enabled Cds and check if result matches 00178 * For the record, enabled Cds (or even disk) are Cds/disks 00179 * that have been successfully handled by MountMgr driver 00180 * and that already own their device name. This is the "new" way 00181 * to handle them, that came with NT5. 00182 * Currently, Windows 2003 provides an arc names creation based 00183 * on both enabled drives and not enabled drives (lack from 00184 * the driver). 00185 * Given the current ReactOS state, that's good for us. 00186 * To sum up, this is NOT a hack or whatsoever. 00187 */ 00188 Status = IopFetchConfigurationInformation(&SymbolicLinkList, 00189 GUID_DEVINTERFACE_CDROM, 00190 CdRomCount, 00191 &EnabledDisks); 00192 if (!NT_SUCCESS(Status)) 00193 { 00194 NotEnabledPresent = TRUE; 00195 } 00196 /* Save symbolic link list address in order to free it after */ 00197 lSymbolicLinkList = SymbolicLinkList; 00198 /* For the moment, we won't fail */ 00199 Status = STATUS_SUCCESS; 00200 00201 /* Browse all the ARC devices trying to find the one matching boot device */ 00202 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink; 00203 NextEntry != &ArcDiskInformation->DiskSignatureListHead; 00204 NextEntry = NextEntry->Flink) 00205 { 00206 ArcDiskSignature = CONTAINING_RECORD(NextEntry, 00207 ARC_DISK_SIGNATURE, 00208 ListEntry); 00209 00210 if (strcmp(LoaderBlock->ArcBootDeviceName, ArcDiskSignature->ArcName) == 0) 00211 { 00212 break; 00213 } 00214 00215 ArcDiskSignature = NULL; 00216 } 00217 00218 /* Not found... Not booting from a Cd */ 00219 if (!ArcDiskSignature) 00220 { 00221 DPRINT("Failed finding a cd that could match current boot device\n"); 00222 goto Cleanup; 00223 } 00224 00225 /* Allocate needed space for reading Cd */ 00226 PartitionBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, 2048, TAG_IO); 00227 if (!PartitionBuffer) 00228 { 00229 DPRINT("Failed allocating resources!\n"); 00230 /* Here, we fail, BUT we return success, some Microsoft joke */ 00231 goto Cleanup; 00232 } 00233 00234 /* If we have more enabled Cds, take that into account */ 00235 if (EnabledDisks > CdRomCount) 00236 { 00237 CdRomCount = EnabledDisks; 00238 } 00239 00240 /* If we'll have to browse for none enabled Cds, fix higher count */ 00241 if (NotEnabledPresent && !EnabledDisks) 00242 { 00243 CdRomCount += 5; 00244 } 00245 00246 /* Finally, if in spite of all that work, we still don't have Cds, leave */ 00247 if (!CdRomCount) 00248 { 00249 goto Cleanup; 00250 } 00251 00252 /* Start browsing Cds */ 00253 for (DiskNumber = 0, EnabledDisks = 0; DiskNumber < CdRomCount; DiskNumber++) 00254 { 00255 /* Check if we have an enabled disk */ 00256 if (SymbolicLinkList && *SymbolicLinkList != UNICODE_NULL) 00257 { 00258 /* Create its device name using first symbolic link */ 00259 RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList); 00260 /* Then, update symbolic links list */ 00261 lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); 00262 00263 /* Get its associated device object and file object */ 00264 Status = IoGetDeviceObjectPointer(&DeviceStringW, 00265 FILE_READ_ATTRIBUTES, 00266 &FileObject, 00267 &DeviceObject); 00268 /* Failure? Good bye! */ 00269 if (!NT_SUCCESS(Status)) 00270 { 00271 goto Cleanup; 00272 } 00273 00274 /* Now, we'll ask the device its device number */ 00275 Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER, 00276 DeviceObject, 00277 NULL, 00278 0, 00279 &DeviceNumber, 00280 sizeof(STORAGE_DEVICE_NUMBER), 00281 FALSE, 00282 &Event, 00283 &IoStatusBlock); 00284 /* Failure? Good bye! */ 00285 if (!Irp) 00286 { 00287 /* Dereference file object before leaving */ 00288 ObDereferenceObject(FileObject); 00289 Status = STATUS_INSUFFICIENT_RESOURCES; 00290 goto Cleanup; 00291 } 00292 00293 /* Call the driver, and wait for it if needed */ 00294 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00295 Status = IoCallDriver(DeviceObject, Irp); 00296 if (Status == STATUS_PENDING) 00297 { 00298 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00299 Status = IoStatusBlock.Status; 00300 } 00301 if (!NT_SUCCESS(Status)) 00302 { 00303 ObDereferenceObject(FileObject); 00304 goto Cleanup; 00305 } 00306 00307 /* Finally, build proper device name */ 00308 sprintf(Buffer, "\\Device\\CdRom%lu", DeviceNumber.DeviceNumber); 00309 RtlInitAnsiString(&DeviceStringA, Buffer); 00310 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); 00311 if (!NT_SUCCESS(Status)) 00312 { 00313 ObDereferenceObject(FileObject); 00314 goto Cleanup; 00315 } 00316 } 00317 else 00318 { 00319 /* Create device name for the cd */ 00320 sprintf(Buffer, "\\Device\\CdRom%lu", EnabledDisks++); 00321 RtlInitAnsiString(&DeviceStringA, Buffer); 00322 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); 00323 if (!NT_SUCCESS(Status)) 00324 { 00325 goto Cleanup; 00326 } 00327 00328 /* Get its device object */ 00329 Status = IoGetDeviceObjectPointer(&DeviceStringW, 00330 FILE_READ_ATTRIBUTES, 00331 &FileObject, 00332 &DeviceObject); 00333 if (!NT_SUCCESS(Status)) 00334 { 00335 RtlFreeUnicodeString(&DeviceStringW); 00336 goto Cleanup; 00337 } 00338 } 00339 00340 /* Initiate data for reading cd and compute checksum */ 00341 StartingOffset.QuadPart = 0x8000; 00342 CheckSum = 0; 00343 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 00344 DeviceObject, 00345 PartitionBuffer, 00346 2048, 00347 &StartingOffset, 00348 &Event, 00349 &IoStatusBlock); 00350 if (Irp) 00351 { 00352 /* Call the driver, and wait for it if needed */ 00353 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00354 Status = IoCallDriver(DeviceObject, Irp); 00355 if (Status == STATUS_PENDING) 00356 { 00357 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00358 Status = IoStatusBlock.Status; 00359 } 00360 00361 /* Reading succeed, compute checksum by adding data, 2048 bytes checksum */ 00362 if (NT_SUCCESS(Status)) 00363 { 00364 for (i = 0; i < 2048 / sizeof(ULONG); i++) 00365 { 00366 CheckSum += PartitionBuffer[i]; 00367 } 00368 } 00369 } 00370 00371 /* Dereference file object */ 00372 ObDereferenceObject(FileObject); 00373 00374 /* If checksums are matching, we have the proper cd */ 00375 if (CheckSum + ArcDiskSignature->CheckSum == 0) 00376 { 00377 /* Create ARC name */ 00378 sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName); 00379 RtlInitAnsiString(&ArcNameStringA, ArcBuffer); 00380 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE); 00381 if (NT_SUCCESS(Status)) 00382 { 00383 /* Create symbolic link */ 00384 IoAssignArcName(&ArcNameStringW, &DeviceStringW); 00385 RtlFreeUnicodeString(&ArcNameStringW); 00386 DPRINT1("Boot device found\n"); 00387 } 00388 00389 /* And quit, whatever happens */ 00390 RtlFreeUnicodeString(&DeviceStringW); 00391 goto Cleanup; 00392 } 00393 00394 /* Free string before trying another disk */ 00395 RtlFreeUnicodeString(&DeviceStringW); 00396 } 00397 00398 Cleanup: 00399 if (PartitionBuffer) 00400 { 00401 ExFreePoolWithTag(PartitionBuffer, TAG_IO); 00402 } 00403 00404 if (SymbolicLinkList) 00405 { 00406 ExFreePool(SymbolicLinkList); 00407 } 00408 00409 return Status; 00410 } 00411 00412 NTSTATUS 00413 INIT_FUNCTION 00414 NTAPI 00415 IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00416 IN BOOLEAN SingleDisk, 00417 IN PBOOLEAN FoundBoot) 00418 { 00419 PIRP Irp; 00420 PVOID Data; 00421 KEVENT Event; 00422 NTSTATUS Status; 00423 PLIST_ENTRY NextEntry; 00424 PFILE_OBJECT FileObject; 00425 DISK_GEOMETRY DiskGeometry; 00426 PDEVICE_OBJECT DeviceObject; 00427 LARGE_INTEGER StartingOffset; 00428 PULONG PartitionBuffer = NULL; 00429 IO_STATUS_BLOCK IoStatusBlock; 00430 CHAR Buffer[128], ArcBuffer[128]; 00431 BOOLEAN NotEnabledPresent = FALSE; 00432 STORAGE_DEVICE_NUMBER DeviceNumber; 00433 PARC_DISK_SIGNATURE ArcDiskSignature; 00434 PWSTR SymbolicLinkList, lSymbolicLinkList; 00435 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL; 00436 UNICODE_STRING DeviceStringW, ArcNameStringW, HalPathStringW; 00437 ULONG DiskNumber, DiskCount, CheckSum, i, Signature, EnabledDisks = 0; 00438 PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation; 00439 ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA, HalPathStringA; 00440 00441 /* Initialise device number */ 00442 DeviceNumber.DeviceNumber = ULONG_MAX; 00443 /* Get all the disks present in the system */ 00444 DiskCount = IoGetConfigurationInformation()->DiskCount; 00445 00446 /* Get enabled disks and check if result matches */ 00447 Status = IopFetchConfigurationInformation(&SymbolicLinkList, 00448 GUID_DEVINTERFACE_DISK, 00449 DiskCount, 00450 &EnabledDisks); 00451 if (!NT_SUCCESS(Status)) 00452 { 00453 NotEnabledPresent = TRUE; 00454 } 00455 00456 /* Save symbolic link list address in order to free it after */ 00457 lSymbolicLinkList = SymbolicLinkList; 00458 00459 /* Build the boot strings */ 00460 RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName); 00461 RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName); 00462 00463 /* If we have more enabled disks, take that into account */ 00464 if (EnabledDisks > DiskCount) 00465 { 00466 DiskCount = EnabledDisks; 00467 } 00468 00469 /* If we'll have to browse for none enabled disks, fix higher count */ 00470 if (NotEnabledPresent && !EnabledDisks) 00471 { 00472 DiskCount += 20; 00473 } 00474 00475 /* Finally, if in spite of all that work, we still don't have disks, leave */ 00476 if (!DiskCount) 00477 { 00478 goto Cleanup; 00479 } 00480 00481 /* Start browsing disks */ 00482 for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++) 00483 { 00484 /* Check if we have an enabled disk */ 00485 if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL) 00486 { 00487 /* Create its device name using first symbolic link */ 00488 RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList); 00489 /* Then, update symbolic links list */ 00490 lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); 00491 00492 /* Get its associated device object and file object */ 00493 Status = IoGetDeviceObjectPointer(&DeviceStringW, 00494 FILE_READ_ATTRIBUTES, 00495 &FileObject, 00496 &DeviceObject); 00497 if (NT_SUCCESS(Status)) 00498 { 00499 /* Now, we'll ask the device its device number */ 00500 Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER, 00501 DeviceObject, 00502 NULL, 00503 0, 00504 &DeviceNumber, 00505 sizeof(STORAGE_DEVICE_NUMBER), 00506 FALSE, 00507 &Event, 00508 &IoStatusBlock); 00509 /* Missing resources is a shame... No need to go farther */ 00510 if (!Irp) 00511 { 00512 ObDereferenceObject(FileObject); 00513 Status = STATUS_INSUFFICIENT_RESOURCES; 00514 goto Cleanup; 00515 } 00516 00517 /* Call the driver, and wait for it if needed */ 00518 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00519 Status = IoCallDriver(DeviceObject, Irp); 00520 if (Status == STATUS_PENDING) 00521 { 00522 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00523 Status = IoStatusBlock.Status; 00524 } 00525 00526 /* If we didn't get the appriopriate data, just skip that disk */ 00527 if (!NT_SUCCESS(Status)) 00528 { 00529 ObDereferenceObject(FileObject); 00530 continue; 00531 } 00532 } 00533 00534 /* End of enabled disks enumeration */ 00535 if (NotEnabledPresent && *lSymbolicLinkList == UNICODE_NULL) 00536 { 00537 /* No enabled disk worked, reset field */ 00538 if (DeviceNumber.DeviceNumber == ULONG_MAX) 00539 { 00540 DeviceNumber.DeviceNumber = 0; 00541 } 00542 00543 /* Update disk number to enable the following not enabled disks */ 00544 if (DeviceNumber.DeviceNumber > DiskNumber) 00545 { 00546 DiskNumber = DeviceNumber.DeviceNumber; 00547 } 00548 00549 /* Increase a bit more */ 00550 DiskCount = DiskNumber + 20; 00551 } 00552 } 00553 else 00554 { 00555 /* Create device name for the disk */ 00556 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber); 00557 RtlInitAnsiString(&DeviceStringA, Buffer); 00558 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); 00559 if (!NT_SUCCESS(Status)) 00560 { 00561 goto Cleanup; 00562 } 00563 00564 /* Get its device object */ 00565 Status = IoGetDeviceObjectPointer(&DeviceStringW, 00566 FILE_READ_ATTRIBUTES, 00567 &FileObject, 00568 &DeviceObject); 00569 00570 RtlFreeUnicodeString(&DeviceStringW); 00571 /* This is a security measure, to ensure DiskNumber will be used */ 00572 DeviceNumber.DeviceNumber = ULONG_MAX; 00573 } 00574 00575 /* Something failed somewhere earlier, just skip the disk */ 00576 if (!NT_SUCCESS(Status)) 00577 { 00578 continue; 00579 } 00580 00581 /* Let's ask the disk for its geometry */ 00582 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, 00583 DeviceObject, 00584 NULL, 00585 0, 00586 &DiskGeometry, 00587 sizeof(DISK_GEOMETRY), 00588 FALSE, 00589 &Event, 00590 &IoStatusBlock); 00591 /* Missing resources is a shame... No need to go farther */ 00592 if (!Irp) 00593 { 00594 ObDereferenceObject(FileObject); 00595 Status = STATUS_INSUFFICIENT_RESOURCES; 00596 goto Cleanup; 00597 } 00598 00599 /* Call the driver, and wait for it if needed */ 00600 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00601 Status = IoCallDriver(DeviceObject, Irp); 00602 if (Status == STATUS_PENDING) 00603 { 00604 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00605 Status = IoStatusBlock.Status; 00606 } 00607 /* Failure, skip disk */ 00608 if (!NT_SUCCESS(Status)) 00609 { 00610 ObDereferenceObject(FileObject); 00611 continue; 00612 } 00613 00614 /* Read the partition table */ 00615 Status = IoReadPartitionTableEx(DeviceObject, 00616 &DriveLayout); 00617 if (!NT_SUCCESS(Status)) 00618 { 00619 ObDereferenceObject(FileObject); 00620 continue; 00621 } 00622 00623 /* Ensure we have at least 512 bytes per sector */ 00624 if (DiskGeometry.BytesPerSector < 512) 00625 { 00626 DiskGeometry.BytesPerSector = 512; 00627 } 00628 00629 /* Check MBR type against EZ Drive type */ 00630 StartingOffset.QuadPart = 0; 00631 HalExamineMBR(DeviceObject, DiskGeometry.BytesPerSector, 0x55, &Data); 00632 if (Data) 00633 { 00634 /* If MBR is of the EZ Drive type, we'll read after it */ 00635 StartingOffset.QuadPart = DiskGeometry.BytesPerSector; 00636 ExFreePool(Data); 00637 } 00638 00639 /* Allocate for reading enough data for checksum */ 00640 PartitionBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, DiskGeometry.BytesPerSector, TAG_IO); 00641 if (!PartitionBuffer) 00642 { 00643 ObDereferenceObject(FileObject); 00644 Status = STATUS_INSUFFICIENT_RESOURCES; 00645 goto Cleanup; 00646 } 00647 00648 /* Read a sector for computing checksum */ 00649 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 00650 DeviceObject, 00651 PartitionBuffer, 00652 DiskGeometry.BytesPerSector, 00653 &StartingOffset, 00654 &Event, 00655 &IoStatusBlock); 00656 if (!Irp) 00657 { 00658 ObDereferenceObject(FileObject); 00659 Status = STATUS_INSUFFICIENT_RESOURCES; 00660 goto Cleanup; 00661 } 00662 00663 /* Call the driver to perform reading */ 00664 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00665 Status = IoCallDriver(DeviceObject, Irp); 00666 if (Status == STATUS_PENDING) 00667 { 00668 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00669 Status = IoStatusBlock.Status; 00670 } 00671 if (!NT_SUCCESS(Status)) 00672 { 00673 ExFreePool(DriveLayout); 00674 ExFreePoolWithTag(PartitionBuffer, TAG_IO); 00675 ObDereferenceObject(FileObject); 00676 continue; 00677 } 00678 00679 ObDereferenceObject(FileObject); 00680 00681 /* Calculate checksum, that's an easy computation, just adds read data */ 00682 for (i = 0, CheckSum = 0; i < 512 / sizeof(ULONG) ; i++) 00683 { 00684 CheckSum += PartitionBuffer[i]; 00685 } 00686 00687 /* Browse each ARC disk */ 00688 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink; 00689 NextEntry != &ArcDiskInformation->DiskSignatureListHead; 00690 NextEntry = NextEntry->Flink) 00691 { 00692 ArcDiskSignature = CONTAINING_RECORD(NextEntry, 00693 ARC_DISK_SIGNATURE, 00694 ListEntry); 00695 00696 /* If they matches, ie 00697 * - There's only one disk for both BIOS and detected/enabled 00698 * - Signatures are matching 00699 * - Checksums are matching 00700 * - This is MBR 00701 */ 00702 if (((SingleDisk && DiskCount == 1) || 00703 (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature) && 00704 (ArcDiskSignature->CheckSum + CheckSum == 0))) && 00705 (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)) 00706 { 00707 /* Create device name */ 00708 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber); 00709 RtlInitAnsiString(&DeviceStringA, Buffer); 00710 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); 00711 if (!NT_SUCCESS(Status)) 00712 { 00713 goto Cleanup; 00714 } 00715 00716 /* Create ARC name */ 00717 sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName); 00718 RtlInitAnsiString(&ArcNameStringA, ArcBuffer); 00719 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE); 00720 if (!NT_SUCCESS(Status)) 00721 { 00722 RtlFreeUnicodeString(&DeviceStringW); 00723 goto Cleanup; 00724 } 00725 00726 /* Link both */ 00727 IoAssignArcName(&ArcNameStringW, &DeviceStringW); 00728 00729 /* And release resources */ 00730 RtlFreeUnicodeString(&ArcNameStringW); 00731 RtlFreeUnicodeString(&DeviceStringW); 00732 00733 /* Now, browse for every partition */ 00734 for (i = 1; i <= DriveLayout->PartitionCount; i++) 00735 { 00736 /* Create device name */ 00737 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", (DeviceNumber.DeviceNumber != ULONG_MAX) ? DeviceNumber.DeviceNumber : DiskNumber, i); 00738 RtlInitAnsiString(&DeviceStringA, Buffer); 00739 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); 00740 if (!NT_SUCCESS(Status)) 00741 { 00742 goto Cleanup; 00743 } 00744 00745 /* Create partial ARC name */ 00746 sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, i); 00747 RtlInitAnsiString(&ArcNameStringA, ArcBuffer); 00748 00749 /* Is that boot device? */ 00750 if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE)) 00751 { 00752 DPRINT("Found boot device\n"); 00753 *FoundBoot = TRUE; 00754 } 00755 00756 /* Is that system partition? */ 00757 if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE)) 00758 { 00759 /* Create HAL path name */ 00760 RtlInitAnsiString(&HalPathStringA, LoaderBlock->NtHalPathName); 00761 Status = RtlAnsiStringToUnicodeString(&HalPathStringW, &HalPathStringA, TRUE); 00762 if (!NT_SUCCESS(Status)) 00763 { 00764 RtlFreeUnicodeString(&DeviceStringW); 00765 goto Cleanup; 00766 } 00767 00768 /* Then store those information to registry */ 00769 IopStoreSystemPartitionInformation(&DeviceStringW, &HalPathStringW); 00770 RtlFreeUnicodeString(&HalPathStringW); 00771 } 00772 00773 /* Create complete ARC name */ 00774 sprintf(ArcBuffer, "\\ArcName\\%spartition(%lu)", ArcDiskSignature->ArcName, i); 00775 RtlInitAnsiString(&ArcNameStringA, ArcBuffer); 00776 Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE); 00777 if (!NT_SUCCESS(Status)) 00778 { 00779 RtlFreeUnicodeString(&DeviceStringW); 00780 goto Cleanup; 00781 } 00782 00783 /* Link device name & ARC name */ 00784 IoAssignArcName(&ArcNameStringW, &DeviceStringW); 00785 00786 /* Release strings */ 00787 RtlFreeUnicodeString(&ArcNameStringW); 00788 RtlFreeUnicodeString(&DeviceStringW); 00789 } 00790 } 00791 else 00792 { 00793 /* In case there's a valid partition, a matching signature, 00794 BUT a none matching checksum, or there's a duplicate 00795 signature, or even worse a virus played with partition 00796 table */ 00797 if (ArcDiskSignature->Signature == Signature && 00798 (ArcDiskSignature->CheckSum + CheckSum != 0) && 00799 ArcDiskSignature->ValidPartitionTable) 00800 { 00801 DPRINT("Be careful, or you have a duplicate disk signature, or a virus altered your MBR!\n"); 00802 } 00803 } 00804 } 00805 00806 /* Release memory before jumping to next item */ 00807 ExFreePool(DriveLayout); 00808 DriveLayout = NULL; 00809 ExFreePoolWithTag(PartitionBuffer, TAG_IO); 00810 PartitionBuffer = NULL; 00811 } 00812 00813 Status = STATUS_SUCCESS; 00814 00815 Cleanup: 00816 if (SymbolicLinkList) 00817 { 00818 ExFreePool(SymbolicLinkList); 00819 } 00820 00821 if (DriveLayout) 00822 { 00823 ExFreePool(DriveLayout); 00824 } 00825 00826 if (PartitionBuffer) 00827 { 00828 ExFreePoolWithTag(PartitionBuffer, TAG_IO); 00829 } 00830 00831 return Status; 00832 } 00833 00834 NTSTATUS 00835 NTAPI 00836 INIT_FUNCTION 00837 IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00838 OUT PANSI_STRING NtBootPath) 00839 { 00840 OBJECT_ATTRIBUTES ObjectAttributes; 00841 NTSTATUS Status; 00842 CHAR Buffer[256], AnsiBuffer[256]; 00843 WCHAR ArcNameBuffer[64]; 00844 ANSI_STRING TargetString, ArcString, TempString; 00845 UNICODE_STRING LinkName, TargetName, ArcName; 00846 HANDLE LinkHandle; 00847 00848 /* Create the Unicode name for the current ARC boot device */ 00849 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName); 00850 RtlInitAnsiString(&TargetString, Buffer); 00851 Status = RtlAnsiStringToUnicodeString(&TargetName, &TargetString, TRUE); 00852 if (!NT_SUCCESS(Status)) return FALSE; 00853 00854 /* Initialize the attributes and open the link */ 00855 InitializeObjectAttributes(&ObjectAttributes, 00856 &TargetName, 00857 OBJ_CASE_INSENSITIVE, 00858 NULL, 00859 NULL); 00860 Status = NtOpenSymbolicLinkObject(&LinkHandle, 00861 SYMBOLIC_LINK_ALL_ACCESS, 00862 &ObjectAttributes); 00863 if (!NT_SUCCESS(Status)) 00864 { 00865 /* We failed, free the string */ 00866 RtlFreeUnicodeString(&TargetName); 00867 return FALSE; 00868 } 00869 00870 /* Query the current \\SystemRoot */ 00871 ArcName.Buffer = ArcNameBuffer; 00872 ArcName.Length = 0; 00873 ArcName.MaximumLength = sizeof(ArcNameBuffer); 00874 Status = NtQuerySymbolicLinkObject(LinkHandle, &ArcName, NULL); 00875 if (!NT_SUCCESS(Status)) 00876 { 00877 /* We failed, free the string */ 00878 RtlFreeUnicodeString(&TargetName); 00879 return FALSE; 00880 } 00881 00882 /* Convert it to Ansi */ 00883 ArcString.Buffer = AnsiBuffer; 00884 ArcString.Length = 0; 00885 ArcString.MaximumLength = sizeof(AnsiBuffer); 00886 Status = RtlUnicodeStringToAnsiString(&ArcString, &ArcName, FALSE); 00887 AnsiBuffer[ArcString.Length] = ANSI_NULL; 00888 00889 /* Close the link handle and free the name */ 00890 ObCloseHandle(LinkHandle, KernelMode); 00891 RtlFreeUnicodeString(&TargetName); 00892 00893 /* Setup the system root name again */ 00894 RtlInitAnsiString(&TempString, "\\SystemRoot"); 00895 Status = RtlAnsiStringToUnicodeString(&LinkName, &TempString, TRUE); 00896 if (!NT_SUCCESS(Status)) return FALSE; 00897 00898 /* Open the symbolic link for it */ 00899 InitializeObjectAttributes(&ObjectAttributes, 00900 &LinkName, 00901 OBJ_CASE_INSENSITIVE, 00902 NULL, 00903 NULL); 00904 Status = NtOpenSymbolicLinkObject(&LinkHandle, 00905 SYMBOLIC_LINK_ALL_ACCESS, 00906 &ObjectAttributes); 00907 if (!NT_SUCCESS(Status)) return FALSE; 00908 00909 /* Destroy it */ 00910 NtMakeTemporaryObject(LinkHandle); 00911 ObCloseHandle(LinkHandle, KernelMode); 00912 00913 /* Now create the new name for it */ 00914 sprintf(Buffer, "%s%s", ArcString.Buffer, LoaderBlock->NtBootPathName); 00915 00916 /* Copy it into the passed parameter and null-terminate it */ 00917 RtlCopyString(NtBootPath, &ArcString); 00918 Buffer[strlen(Buffer) - 1] = ANSI_NULL; 00919 00920 /* Setup the Unicode-name for the new symbolic link value */ 00921 RtlInitAnsiString(&TargetString, Buffer); 00922 InitializeObjectAttributes(&ObjectAttributes, 00923 &LinkName, 00924 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 00925 NULL, 00926 NULL); 00927 Status = RtlAnsiStringToUnicodeString(&ArcName, &TargetString, TRUE); 00928 if (!NT_SUCCESS(Status)) return FALSE; 00929 00930 /* Create it */ 00931 Status = NtCreateSymbolicLinkObject(&LinkHandle, 00932 SYMBOLIC_LINK_ALL_ACCESS, 00933 &ObjectAttributes, 00934 &ArcName); 00935 00936 /* Free all the strings and close the handle and return success */ 00937 RtlFreeUnicodeString(&ArcName); 00938 RtlFreeUnicodeString(&LinkName); 00939 ObCloseHandle(LinkHandle, KernelMode); 00940 return TRUE; 00941 } 00942 00943 BOOLEAN 00944 NTAPI 00945 IopVerifyDiskSignature(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout, 00946 IN PARC_DISK_SIGNATURE ArcDiskSignature, 00947 OUT PULONG Signature) 00948 { 00949 /* First condition: having a valid partition table */ 00950 if (!ArcDiskSignature->ValidPartitionTable) 00951 { 00952 return FALSE; 00953 } 00954 00955 /* If that partition table is the MBR */ 00956 if (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR) 00957 { 00958 /* Then check MBR signature */ 00959 if (DriveLayout->Mbr.Signature == ArcDiskSignature->Signature) 00960 { 00961 /* And return it */ 00962 if (Signature) 00963 { 00964 *Signature = DriveLayout->Mbr.Signature; 00965 } 00966 00967 return TRUE; 00968 } 00969 } 00970 /* If that partition table is the GPT */ 00971 else if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT) 00972 { 00973 /* Check we are using GPT and compare GUID */ 00974 if (ArcDiskSignature->IsGpt && 00975 (((PULONG)ArcDiskSignature->GptSignature)[0] == DriveLayout->Gpt.DiskId.Data1 && 00976 ((PUSHORT)ArcDiskSignature->GptSignature)[2] == DriveLayout->Gpt.DiskId.Data2 && 00977 ((PUSHORT)ArcDiskSignature->GptSignature)[3] == DriveLayout->Gpt.DiskId.Data3 && 00978 ((PULONGLONG)ArcDiskSignature->GptSignature)[1] == ((PULONGLONG)DriveLayout->Gpt.DiskId.Data4)[0])) 00979 { 00980 /* There's no signature to give, so we just zero output */ 00981 if (Signature) 00982 { 00983 *Signature = 0; 00984 } 00985 return TRUE; 00986 } 00987 } 00988 00989 /* If we fall here, it means that something went wrong, so return that */ 00990 return FALSE; 00991 } 00992 00993 /* EOF */ Generated on Fri May 25 2012 04:17:23 for ReactOS by
1.7.6.1
|