微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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 }

通过这个函数,就可以把磁盘分区表写到主引导区,并且把相应的分区表写到各自的分区表,然后把引导程序写到引导分区,还把分区表里每个分区的格式化数据写进去,这样就相当于把一个磁盘格式化了。

原文地址:https://www.jb51.cc/react/308475.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐