reactos操作系统实现(58)
格式化磁盘主要做什么样的工作呢?根据用户选择的文件系统,把格式化的数据和分区表写到磁盘,然后判断引导分区,写入引导代码到引导分区。具代实现代码如下: #001 static ULONG #002 FormatPartitionPage (PINPUT_RECORD Ir) #003 { #004 WCHAR PathBuffer[MAX_PATH]; #005 PDISKENTRY DiskEntry; #006 PPARTENTRY PartEntry; #007 NTSTATUS Status; #008 #009 #ifndef NDEBUG #010 ULONG Line; #011 ULONG i; #012 PLIST_ENTRY Entry; #013 #endif #014 #015 MUIDisplayPage(FORMAT_PARTITION_PAGE); #016 #017 if (PartitionList == NULL || #018 PartitionList->CurrentDisk == NULL || #019 PartitionList->CurrentPartition == NULL) #020 { #021 /* FIXME: show an error dialog */ #022 return QUIT_PAGE; #023 } #024 #025 DiskEntry = PartitionList->CurrentDisk; #026 PartEntry = PartitionList->CurrentPartition; #027
循环响应键盘事件。 #028 while(TRUE) #029 { #030 if (!IsUnattendedSetup) #031 { #032 CONSOLE_ConInKey(Ir); #033 } #034 #035 if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && #036 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ #037 { #038 if (ConfirmQuit (Ir) == TRUE) #039 { #040 return QUIT_PAGE; #041 } #042 #043 break; #044 } #045 else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */ #046 { #047 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT)); #048 #049 if (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED) #050 { #051 if (wcscmp(FileSystemList->Selected->FileSystem,L"FAT") == 0) #052 { #053 if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (4200LL * 1024LL)) #054 { #055 /* FAT12 CHS partition (disk is smaller than 4.1MB) */ #056 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT_12; #057 } #058 else if (PartEntry->PartInfo[0].StartingOffset.QuadPart < (1024LL * 255LL * 63LL * 512LL)) #059 { #060 /* Partition starts below the 8.4GB boundary ==> CHS partition */ #061 #062 if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (32LL * 1024LL * 1024LL)) #063 { #064 /* FAT16 CHS partition (partiton size < 32MB) */ #065 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT_16; #066 } #067 else if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL)) #068 { #069 /* FAT16 CHS partition (partition size < 512MB) */ #070 PartEntry->PartInfo[0].PartitionType = PARTITION_HUGE; #071 } #072 else #073 { #074 /* FAT32 CHS partition (partition size >= 512MB) */ #075 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT32; #076 } #077 } #078 else #079 { #080 /* Partition starts above the 8.4GB boundary ==> LBA partition */ #081 #082 if (PartEntry->PartInfo[0].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL)) #083 { #084 /* FAT16 LBA partition (partition size < 512MB) */ #085 PartEntry->PartInfo[0].PartitionType = PARTITION_XINT13; #086 } #087 else #088 { #089 /* FAT32 LBA partition (partition size >= 512MB) */ #090 PartEntry->PartInfo[0].PartitionType = PARTITION_FAT32_XINT13; #091 } #092 } #093 } #094 else if (wcscmp(FileSystemList->Selected->FileSystem,L"EXT2") == 0) #095 PartEntry->PartInfo[0].PartitionType = PARTITION_EXT2; #096 else if (!FileSystemList->Selected->FormatFunc) #097 return QUIT_PAGE; #098 } #099
检查是否有引导分区。 #100 CheckActiveBootPartition (PartitionList); #101 #102 #ifndef NDEBUG #103 CONSOLE_PrintTextXY(6,12, #104 "Disk: %I64u Cylinder: %I64u Track: %I64u", #105 DiskEntry->DiskSize, #106 DiskEntry->CylinderSize, #107 DiskEntry->TrackSize); #108 #109 Line = 13; #110 DiskEntry = PartitionList->CurrentDisk; #111 Entry = DiskEntry->PartListHead.Flink; #112 #113 while (Entry != &DiskEntry->PartListHead) #114 { #115 PartEntry = CONTAINING_RECORD(Entry,PARTENTRY,ListEntry); #116 #117 if (PartEntry->Unpartitioned == FALSE) #118 { #119 for (i = 0; i < 4; i++) #120 { #121 CONSOLE_PrintTextXY(6,Line, #122 "%2u: %2u %c %12I64u %12I64u %2u %c", #123 i, #124 PartEntry->PartInfo[i].PartitionNumber, #125 PartEntry->PartInfo[i].BootIndicator ? 'A' : '-', #126 PartEntry->PartInfo[i].StartingOffset.QuadPart, #127 PartEntry->PartInfo[i].PartitionLength.QuadPart, #128 PartEntry->PartInfo[i].PartitionType, #129 PartEntry->PartInfo[i].RewritePartition ? '*' : ' '); #130 #131 Line++; #132 } #133 #134 Line++; #135 } #136 #137 Entry = Entry->Flink; #138 } #139 #140 /* Restore the old entry */ #141 PartEntry = PartitionList->CurrentPartition; #142 #endif #143
这里把所有分区表的数据写到磁盘里保存起来。 #144 if (WritePartitionsToDisk (PartitionList) == FALSE) #145 { #146 DPRINT ("WritePartitionsToDisk() failed/n"); #147 MUIDisplayError(ERROR_WRITE_PTABLE,Ir,POPUP_WAIT_ENTER); #148 return QUIT_PAGE; #149 } #150
设置目标的路径。 #151 /* Set DestinationRootPath */ #152 RtlFreeUnicodeString (&DestinationRootPath); #153 swprintf (PathBuffer, #154 L"//Device//Harddisk%lu//Partition%lu", #155 PartitionList->CurrentDisk->DiskNumber, #156 PartitionList->CurrentPartition->PartInfo[0].PartitionNumber); #157 RtlCreateUnicodeString (&DestinationRootPath, #158 PathBuffer); #159 DPRINT ("DestinationRootPath: %wZ/n",&DestinationRootPath); #160 #161 #162 /* Set SystemRootPath */ #163 RtlFreeUnicodeString (&SystemRootPath); #164 swprintf (PathBuffer, #165 L"//Device//Harddisk%lu//Partition%lu", #166 PartitionList->ActiveBootDisk->DiskNumber, #167 PartitionList->ActiveBootPartition->PartInfo[0].PartitionNumber); #168 RtlCreateUnicodeString (&SystemRootPath, #169 PathBuffer); #170 DPRINT ("SystemRootPath: %wZ/n",&SystemRootPath); #171 #172 #173 if (FileSystemList->Selected->FormatFunc) #174 {
开始格式化磁盘。 #175 Status = FormatPartition(&DestinationRootPath,FileSystemList->Selected); #176 if (!NT_SUCCESS(Status)) #177 { #178 DPRINT1("FormatPartition() failed with status 0x%08lx/n",Status); #179 /* FIXME: show an error dialog */ #180 return QUIT_PAGE; #181 } #182 #183 PartEntry->New = FALSE; #184 #185 CheckActiveBootPartition(PartitionList); #186 } #187 #188 if (wcscmp(FileSystemList->Selected->FileSystem,L"FAT") == 0) #189 { #190 /* FIXME: Install boot code. This is a hack! */ #191 if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13) || #192 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32)) #193 { #194 wcscpy(PathBuffer,SourceRootPath.Buffer); #195 wcscat(PathBuffer,L"//loader//fat32.bin"); #196 #197 DPRINT("Install FAT32 bootcode: %S ==> %S/n",PathBuffer, #198 DestinationRootPath.Buffer);
安装引导代码到引导分区。 #199 Status = InstallFat32BootCodeToDisk(PathBuffer, #200 DestinationRootPath.Buffer); #201 #202 if (!NT_SUCCESS(Status)) #203 { #204 DPRINT1("InstallFat32BootCodeToDisk() failed with status 0x%08lx/n",Status); #205 /* FIXME: show an error dialog */ #206 DestroyFileSystemList(FileSystemList); #207 FileSystemList = NULL; #208 return QUIT_PAGE; #209 } #210 } #211 else #212 { #213 wcscpy(PathBuffer,SourceRootPath.Buffer); #214 wcscat(PathBuffer,L"//loader//fat.bin"); #215 #216 DPRINT("Install FAT bootcode: %S ==> %S/n", #217 DestinationRootPath.Buffer); #218 Status = InstallFat16BootCodeToDisk(PathBuffer, #219 DestinationRootPath.Buffer); #220 #221 if (!NT_SUCCESS(Status)) #222 { #223 DPRINT1("InstallFat16BootCodeToDisk() failed with status 0x%.08x/n",Status); #224 /* FIXME: show an error dialog */ #225 DestroyFileSystemList(FileSystemList); #226 FileSystemList = NULL; #227 return QUIT_PAGE; #228 } #229 } #230 } #231 else if (wcscmp(FileSystemList->Selected->FileSystem,L"EXT2") == 0) #232 { #233 wcscpy(PathBuffer,SourceRootPath.Buffer); #234 wcscat(PathBuffer,L"//loader//ext2.bin"); #235 #236 DPRINT("Install EXT2 bootcode: %S ==> %S/n", #237 DestinationRootPath.Buffer); #238 Status = InstallFat32BootCodeToDisk(PathBuffer, #239 DestinationRootPath.Buffer); #240 #241 if (!NT_SUCCESS(Status)) #242 { #243 DPRINT1("InstallFat32BootCodeToDisk() failed with status 0x%08lx/n",Status); #244 /* FIXME: show an error dialog */ #245 DestroyFileSystemList(FileSystemList); #246 FileSystemList = NULL; #247 return QUIT_PAGE; #248 } #249 } #250 else if (FileSystemList->Selected->FormatFunc) #251 { #252 DestroyFileSystemList(FileSystemList); #253 FileSystemList = NULL; #254 return QUIT_PAGE; #255 } #256 #257 #ifndef NDEBUG #258 CONSOLE_SetStatusText(" Done. Press any key ..."); #259 CONSOLE_ConInKey(Ir); #260 #endif #261 #262 DestroyFileSystemList(FileSystemList); #263 FileSystemList = NULL; #264 return INSTALL_DIRECTORY_PAGE; #265 } #266 } #267 #268 return FORMAT_PARTITION_PAGE; #269 } 在这个函数里,调用函数WritePartitionsToDisk来把分区表数据写到磁盘里,下面是这个函数的实现代码,如下: #001 BOOLEAN #002 WritePartitionsToDisk (PPARTLIST List) #003 { #004 PDRIVE_LAYOUT_INFORMATION DriveLayout; #005 OBJECT_ATTRIBUTES ObjectAttributes; #006 IO_STATUS_BLOCK Iosb; #007 WCHAR SrcPath[MAX_PATH]; #008 WCHAR DstPath[MAX_PATH]; #009 UNICODE_STRING Name; #010 HANDLE FileHandle; #011 PDISKENTRY DiskEntry1; #012 PDISKENTRY DiskEntry2; #013 PPARTENTRY PartEntry; #014 PLIST_ENTRY Entry1; #015 PLIST_ENTRY Entry2; #016 ULONG PartitionCount; #017 ULONG DriveLayoutSize; #018 ULONG Index; #019 NTSTATUS Status; #020 #021 if (List == NULL) #022 { #023 return TRUE; #024 } #025
取得分区表的列表头。 #026 Entry1 = List->DiskListHead.Flink; #027 while (Entry1 != &List->DiskListHead) #028 { #029 DiskEntry1 = CONTAINING_RECORD (Entry1, #030 DISKENTRY, #031 ListEntry); #032 #033 if (DiskEntry1->Modified == TRUE) #034 { #035 /* Count partitioned entries */ #036 PartitionCount = 0; #037 Entry2 = DiskEntry1->PartListHead.Flink; #038 while (Entry2 != &DiskEntry1->PartListHead) #039 { #040 PartEntry = CONTAINING_RECORD (Entry2, #041 PARTENTRY, #042 ListEntry); #043 if (PartEntry->Unpartitioned == FALSE) #044 { #045 PartitionCount += 4; #046 } #047 #048 Entry2 = Entry2->Flink; #049 } #050 if (PartitionCount == 0) #051 { #052 DriveLayoutSize = sizeof (DRIVE_LAYOUT_INFORMATION) + #053 ((4 - 1) * sizeof (PARTITION_INFORMATION)); #054 } #055 else #056 { #057 DriveLayoutSize = sizeof (DRIVE_LAYOUT_INFORMATION) + #058 ((PartitionCount - 1) * sizeof (PARTITION_INFORMATION)); #059 } #060 DriveLayout = (PDRIVE_LAYOUT_INFORMATION)RtlAllocateHeap (ProcessHeap, #061 0, #062 DriveLayoutSize); #063 if (DriveLayout == NULL) #064 { #065 DPRINT1 ("RtlAllocateHeap() failed/n"); #066 return FALSE; #067 } #068 #069 RtlZeroMemory (DriveLayout, #070 DriveLayoutSize); #071 #072 if (PartitionCount == 0) #073 { #074 /* delete all partitions in the mbr */ #075 DriveLayout->PartitionCount = 4; #076 for (Index = 0; Index < 4; Index++) #077 { #078 DriveLayout->PartitionEntry[Index].RewritePartition = TRUE; #079 } #080 } #081 else #082 { #083 DriveLayout->PartitionCount = PartitionCount; #084 #085 Index = 0; #086 Entry2 = DiskEntry1->PartListHead.Flink; #087 while (Entry2 != &DiskEntry1->PartListHead) #088 { #089 PartEntry = CONTAINING_RECORD (Entry2, #090 PARTENTRY, #091 ListEntry); #092 if (PartEntry->Unpartitioned == FALSE) #093 { #094 RtlCopyMemory (&DriveLayout->PartitionEntry[Index], #095 &PartEntry->PartInfo[0], #096 4 * sizeof (PARTITION_INFORMATION)); #097 Index += 4; #098 } #099 #100 Entry2 = Entry2->Flink; #101 } #102 } #103 if (DiskEntry1->Signature == 0) #104 { #105 LARGE_INTEGER SystemTime; #106 TIME_FIELDS TimeFields; #107 PUCHAR Buffer; #108 Buffer = (PUCHAR)&DiskEntry1->Signature; #109
下面开始循环地把分区表写到磁盘。 #110 while (1) #111 {
获取系统时间。 #112 NtQuerySystemTime (&SystemTime); #113 RtlTimeToTimeFields (&SystemTime,&TimeFields); #114 #115 Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF); #116 Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF); #117 Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF); #118 Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF); #119 #120 if (DiskEntry1->Signature == 0) #121 { #122 continue; #123 } #124 #125 /* check if the signature already exist */ #126 /* FIXME: #127 * Check also signatures from disks,which are #128 * not visible (bootable) by the bios. #129 */ #130 Entry2 = List->DiskListHead.Flink; #131 while (Entry2 != &List->DiskListHead) #132 { #133 DiskEntry2 = CONTAINING_RECORD(Entry2,DISKENTRY,ListEntry); #134 if (DiskEntry1 != DiskEntry2 && #135 DiskEntry1->Signature == DiskEntry2->Signature) #136 { #137 break; #138 } #139 Entry2 = Entry2->Flink; #140 } #141 if (Entry2 == &List->DiskListHead) #142 { #143 break; #144 } #145 } #146 #147 /* set one partition entry to dirty,this will update the signature */ #148 DriveLayout->PartitionEntry[0].RewritePartition = TRUE; #149 #150 } #151 #152 DriveLayout->Signature = DiskEntry1->Signature; #153 #154
获取磁盘的路径。 #155 swprintf (DstPath, #156 L"//Device//Harddisk%d//Partition0", #157 DiskEntry1->DiskNumber); #158 RtlInitUnicodeString (&Name, #159 DstPath); #160 InitializeObjectAttributes (&ObjectAttributes, #161 &Name, #162 0, #163 NULL, #164 NULL); #165
通过磁盘的路径打开磁盘对象。 #166 Status = NtOpenFile (&FileHandle, #167 FILE_ALL_ACCESS, #168 &ObjectAttributes, #169 &Iosb, #170 0, #171 FILE_SYNCHRONOUS_IO_NONALERT); #172 #173 if (!NT_SUCCESS (Status)) #174 { #175 DPRINT1 ("NtOpenFile() failed (Status %lx)/n",Status); #176 return FALSE; #177 } #178
把磁盘的格式化数据写到分区。 #179 Status = NtDeviceIoControlFile (FileHandle, #180 NULL, #181 NULL, #182 NULL, #183 &Iosb, #184 IOCTL_DISK_SET_DRIVE_LAYOUT, #185 DriveLayout, #186 DriveLayoutSize, #187 NULL, #188 0); #189 if (!NT_SUCCESS (Status)) #190 { #191 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)/n",Status); #192 NtClose (FileHandle); #193 return FALSE; #194 } #195 #196 RtlFreeHeap (ProcessHeap, #197 0, #198 DriveLayout); #199 #200 NtClose (FileHandle); #201 #202 /* Install MBR code if the disk is new */ #203 if (DiskEntry1->NewDisk == TRUE && #204 DiskEntry1->BiosDiskNumber == 0) #205 { #206 wcscpy (SrcPath,SourceRootPath.Buffer); #207 wcscat (SrcPath,L"//loader//dosmbr.bin"); #208 #209 DPRINT ("Install MBR bootcode: %S ==> %S/n", #210 SrcPath,DstPath); #211
安装磁盘分区表到主引导分区。 #212 /* Install MBR bootcode */ #213 Status = InstallMbrBootCodeToDisk (SrcPath, #214 DstPath); #215 if (!NT_SUCCESS (Status)) #216 { #217 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)/n", #218 Status); #219 return FALSE; #220 } #221 #222 DiskEntry1->NewDisk = FALSE; #223 } #224 } #225 #226 Entry1 = Entry1->Flink; #227 } #228 #229 return TRUE; #230 } 通过这个函数,就可以把磁盘分区表写到主引导区,并且把相应的分区表写到各自的分区表,然后把引导程序写到引导分区,还把分区表里每个分区的格式化数据写进去,这样就相当于把一个磁盘格式化了。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |