ARC命名是Windows NT系统用来定位其引导分区所在的路径,也就是利用它指明引导分区在哪一个磁盘控制器,哪一个硬盘,哪一个分区内。ARC命名可分为两大类,以scsi为首或以multi为首,现分别说明如下: scsi(x)disk(y)rdisk(0)partition(z): 以scsi为首,表明该磁盘控制器为SCSI卡,并且该卡上的BIOS被设置为禁用(disable) scsi(x):表示第几个控制卡,x以0为起始数字。 disk(y):表示该控制卡下的第几块物理磁盘,y以0为起始数字。 partition(z):表示该物理磁盘上第几个分区,z以1为起始数字。 注意:以scsi为首的ARC命名的rdisk项总是rdisk(0)。 multi(x)disk(0)rdisk(y)partition(z): 以multi为首,表明该磁盘控制器是IDE,ESDI,或是BIOS允许使用(enable)的SCSI卡。 multi(x):表示第几个控制卡,x以0为起始数字。 rdisk(y):表示该控制卡下的第几块物理磁盘,y以0为起始数字。 partition(z):表示该物理磁盘上第几个分区,z以1为起始数字。 注意:以multi为首的ARC命名的disk项总是disk(0)。 还有一点必须注意的是,系统给NT分区编号时,主分区的编号永远排在扩展分区前。例题 windows2000安装在D盘下,D盘为扩展分区的一个逻辑驱动器,系统可以正常启动。后来,又添加了一个分区。重启时发现系统无法引导了,是何原因,如何解决。 分析:一个磁盘上最多只能有一个扩展分区,则新添加的分区为主分区,而主分区的编号排在扩展分区前,所以D盘的实际ARC路径的partition值增加了1,而boot.ini文件的内容没变,这样再利用原来的ARC路径就找不到D盘的系统目录了。解决的方法就是修改boot.ini文件。 ARC命名是Windows NT系统用来定位其引导分区所在的路径,也就是利用它指明引导分区在哪一个磁盘控制器,哪一个硬盘,哪一个分区内。 ARC命名可分为两大类,以scsi为首或以multi为首,现分别说明如下: scsi(x)disk(y)rdisk(0)partition(z): 以scsi为首,表明该磁盘控制器为SCSI卡,并且该卡上的BIOS被设置为禁用(disable) scsi(x):表示第几个控制卡,x以0为起始数字。 disk(y):表示该控制卡下的第几块物理磁盘,y以0为起始数字。 partition(z):表示该物理磁盘上第几个分区,z以1为起始数字。 注意:以scsi为首的ARC命名的rdisk项总是rdisk(0)。 multi(x)disk(0)rdisk(y)partition(z): 以multi为首,表明该磁盘控制器是IDE,ESDI,或是BIOS允许使用(enable)的SCSI卡。 multi(x):表示第几个控制卡,x以0为起始数字。 rdisk(y):表示该控制卡下的第几块物理磁盘,y以0为起始数字。 partition(z):表示该物理磁盘上第几个分区,z以1为起始数字。 注意:以multi为首的ARC命名的disk项总是disk(0)。 还有一点必须注意的是,系统给NT分区编号时,主分区的编号永远排在扩展分区前,故当引导分区处于原硬盘的剩余磁盘空间时,必须将此磁盘空间设为主分区(已存在扩展分区),该分区虽然后编号,但其编号反而在原来扩展分区中的逻辑分区编号之前。
#001 NTSTATUS
#002 INIT_FUNCTION
#003 NTAPI
#004 IopCreateArcNames(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
#005 {
获取配置信息。
#006 PCONFIGURATION_INFORMATION ConfigInfo = IoGetConfigurationInformation();
获取Freeloader的参数。
#007 PARC_DISK_INFORMATION ArcDiskInfo = LoaderBlock->ArcDiskInformation;
#008 CHAR Buffer[128];
#009 ANSI_STRING ArcBootString,ArcSystemString,ArcString;
#010 UNICODE_STRING ArcName,BootPath,DeviceName;
#011 BOOLEAN SingleDisk;
#012 ULONG i,j,Length;
#013 PDEVICE_OBJECT DeviceObject;
#014 ULONG Signature,Checksum,PartitionCount;
#015 PLIST_ENTRY NextEntry;
#016 PARC_DISK_SIGNATURE ArcDiskEntry;
#017 NTSTATUS Status;
#018 BOOLEAN FoundBoot = FALSE;
#019 PULONG PartitionBuffer;
#020
检查这台电脑是否只有一个磁盘。
#021 /* Check if we only have one disk on the machine */
#022 SingleDisk = ArcDiskInfo->DiskSignatureListHead.Flink->Flink ==
#023 (&ArcDiskInfo->DiskSignatureListHead);
#024
创建硬件抽像层的分区名称。
#025 /* Create the global HAL partition name */
#026 sprintf(Buffer,"//ArcName//%s",LoaderBlock->ArcHalDeviceName);
#027 RtlInitAnsiString(&ArcString,Buffer);
#028 RtlAnsiStringToUnicodeString(&IoArcHalDeviceName,&ArcString,TRUE);
#029
创建系统分区的名称。
#030 /* Create the global system partition name */
#031 sprintf(Buffer,LoaderBlock->ArcBootDeviceName);
#032 RtlInitAnsiString(&ArcString,Buffer);
#033 RtlAnsiStringToUnicodeString(&IoArcBootDeviceName,TRUE);
#034
为字符串分配内存大小。
#035 /* Allocate memory for the string */
#036 Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL);
#037 IoLoaderArcBootDeviceName = ExAllocatePoolWithTag(PagedPool,
#038 Length,
#039 TAG_IO);
#040 if (IoLoaderArcBootDeviceName)
#041 {
#042 /* Copy the name */
#043 RtlCopyMemory(IoLoaderArcBootDeviceName,
#044 LoaderBlock->ArcBootDeviceName,
#045 Length);
#046 }
#047
检查是否有一个磁盘,但系统是从CD-ROM引导的。
#048 /* Check if we only found a disk,but we're booting from CD-ROM */
#049 if ((SingleDisk) && strstr(LoaderBlock->ArcBootDeviceName,"cdrom"))
#050 {
#051 /* Then disable single-disk mode,since there's a CD drive out there */
#052 SingleDisk = FALSE;
#053 }
#054
创建引导的字符串。
#055 /* Build the boot strings */
#056 RtlInitAnsiString(&ArcBootString,LoaderBlock->ArcBootDeviceName);
#057 RtlInitAnsiString(&ArcSystemString,LoaderBlock->ArcHalDeviceName);
#058
循环地创建每个磁盘的ARC的名称。
#059 /* Loop every detected disk */
#060 for (i = 0; i < ConfigInfo->DiskCount; i++)
#061 {
#062 /* Get information about the disk */
#063 if (!IopGetDiskInformation(i,
#064 &Checksum,
#065 &Signature,
#066 &PartitionCount,
#067 &DeviceObject))
#068 {
#069 /* Skip this disk */
#070 continue;
#071 }
#072
#073 /* Loop ARC disks */
#074 for (NextEntry = ArcDiskInfo->DiskSignatureListHead.Flink;
#075 NextEntry != &ArcDiskInfo->DiskSignatureListHead;
#076 NextEntry = NextEntry->Flink)
#077 {
#078 /* Get the current ARC disk signature entry */
#079 ArcDiskEntry = CONTAINING_RECORD(NextEntry,
#080 ARC_DISK_SIGNATURE,
#081 ListEntry);
#082
#083 /*
#084 * Now check if the signature and checksum match,unless this is
#085 * the only disk that was in the ARC list,and also in the device
#086 * tree,in which case the check is bypassed and we accept the disk
#087 */
#088 if (((SingleDisk) && (ConfigInfo->DiskCount == 1)) ||
#089 ((Checksum == ArcDiskEntry->CheckSum) &&
#090 (Signature == ArcDiskEntry->Signature)))
#091 {
创建NT设备名称。
#092 /* Build the NT Device Name */
#093 sprintf(Buffer,"//Device//Harddisk%lu//Partition0",i);
#094
转换UNICODE表示。
#095 /* Convert it to Unicode */
#096 RtlInitAnsiString(&ArcString,Buffer);
#097 Status = RtlAnsiStringToUnicodeString(&DeviceName,
#098 &ArcString,
#099 TRUE);
#100 if (!NT_SUCCESS(Status)) continue;
#101
创建ARC设备名称。
#102 /* Build the ARC Device Name */
#103 sprintf(Buffer,ArcDiskEntry->ArcName);
#104
#105 /* Convert it to Unicode */
#106 RtlInitAnsiString(&ArcString,Buffer);
#107 Status = RtlAnsiStringToUnicodeString(&ArcName,
#108 &ArcString,
#109 TRUE);
#110 if (!NT_SUCCESS(Status)) continue;
#111
为设备创建符号连接。
#112 /* Create the symbolic link and free the strings */
#113 IoAssignArcName(&ArcName,&DeviceName);
#114 RtlFreeUnicodeString(&ArcName);
#115 RtlFreeUnicodeString(&DeviceName);
#116
创建所有分区ARC名称。
#117 /* Loop all the partitions */
#118 for (j = 0; j < PartitionCount; j++)
#119 {
#120 /* Build the partition device name */
#121 sprintf(Buffer,
#122 "//Device//Harddisk%lu//Partition%lu",
#123 i,
#124 j + 1);
#125
#126 /* Convert it to Unicode */
#127 RtlInitAnsiString(&ArcString,Buffer);
#128 Status = RtlAnsiStringToUnicodeString(&DeviceName,
#129 &ArcString,
#130 TRUE);
#131 if (!NT_SUCCESS(Status)) continue;
#132
#133 /* Build the partial ARC name for this partition */
#134 sprintf(Buffer,
#135 "%spartition(%lu)",
#136 ArcDiskEntry->ArcName,
#137 j + 1);
#138 RtlInitAnsiString(&ArcString,Buffer);
#139
#140 /* Check if this is the boot device */
#141 if (RtlEqualString(&ArcString,&ArcBootString,TRUE))
#142 {
#143 /* Remember that we found a Hard Disk Boot Device */
#144 FoundBoot = TRUE;
#145 }
#146
#147 /* Check if it's the system boot partition */
#148 if (RtlEqualString(&ArcString,&ArcSystemString,TRUE))
#149 {
#150 /* It is,create a Unicode string for it */
#151 RtlInitAnsiString(&ArcString,
#152 LoaderBlock->NtHalPathName);
#153 Status = RtlAnsiStringToUnicodeString(&BootPath,
#154 &ArcString,
#155 TRUE);
#156 if (NT_SUCCESS(Status))
#157 {
#158 /* FIXME: Save in registry */
#159
#160 /* Free the string now */
#161 RtlFreeUnicodeString(&BootPath);
#162 }
#163 }
#164
#165 /* Build the full ARC name */
#166 sprintf(Buffer,
#167 "//ArcName//%spartition(%lu)",
#168 ArcDiskEntry->ArcName,
#169 j + 1);
#170
#171 /* Convert it to Unicode */
#172 RtlInitAnsiString(&ArcString,Buffer);
#173 Status = RtlAnsiStringToUnicodeString(&ArcName,
#174 &ArcString,
#175 TRUE);
#176 if (!NT_SUCCESS(Status)) continue;
#177
#178 /* Create the symbolic link and free the strings */
#179 IoAssignArcName(&ArcName,&DeviceName);
#180 RtlFreeUnicodeString(&ArcName);
#181 RtlFreeUnicodeString(&DeviceName);
#182 }
#183 }
#184 }
#185 }
#186
检查是否找到引导磁盘。
#187 /* Check if we didn't find the boot disk */
#188 if (!FoundBoot)
#189 {
如果没有找到引导磁盘,就分配CD-ROM的MBR内存。
#190 /* Allocate a buffer for the CD-ROM MBR */
#191 PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool,2048,TAG_IO);
#192 if (!PartitionBuffer) return STATUS_INSUFFICIENT_RESOURCES;
#193
创建CDROM的ARC设备名称。
#194 /* Loop every CD-ROM */
#195 for (i = 0; i < ConfigInfo->CdRomCount; i++)
#196 {
#197 /* Give it an ARC name */
#198 if (IopAssignArcNamesToCdrom(PartitionBuffer,i)) break;
#199 }
#200
#201 /* Free the buffer */
#202 ExFreePoolWithTag(PartitionBuffer,TAG_IO);
#203 }
#204
#205 /* Return success */
#206 return STATUS_SUCCESS;
#207}