格式化磁盘主要做什么样的工作呢?根据用户选择的文件系统,把格式化的数据和分区表写到磁盘,然后判断引导分区,写入引导代码到引导分区。具代实现代码如下:
#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", PathBuffer,
#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", PathBuffer,
#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