格式化磁盘主要做什么样的工作呢?根据用户选择的文件系统,把格式化的数据和分区表写到磁盘,然后判断引导分区,写入引导代码到引导分区。具代实现代码如下:
#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 }
通过这个函数,就可以把磁盘分区表写到主引导区,并且把相应的分区表写到各自的分区表,然后把引导程序写到引导分区,还把分区表里每个分区的格式化数据写进去,这样就相当于把一个磁盘格式化了。
原文链接:https://www.f2er.com/react/308475.html