reactos操作系统实现(58)

来源:互联网 发布:剑三正太数据 编辑:程序博客网 时间:2024/04/28 21:13

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

#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 CHSpartition (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 startsbelow the 8.4GB boundary ==> CHS partition */

#061 

#062                          if(PartEntry->PartInfo[0].PartitionLength.QuadPart < (32LL * 1024LL *1024LL))

#063                          {

#064                              /* FAT16 CHSpartition (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 CHSpartition (partition size < 512MB) */

#070                             PartEntry->PartInfo[0].PartitionType = PARTITION_HUGE;

#071                          }

#072                          else

#073                          {

#074                              /* FAT32 CHSpartition (partition size >= 512MB) */

#075                             PartEntry->PartInfo[0].PartitionType = PARTITION_FAT32;

#076                          }

#077                      }

#078                      else

#079                      {

#080                          /* Partition starts above the 8.4GBboundary ==> 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 errordialog */

#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("InstallFAT32 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 status0x%08lx/n", Status);

#205                          /* FIXME: show anerror 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 FATbootcode: %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 status0x%.08x/n", Status);

#224                          /* FIXME: show anerror 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 EXT2bootcode: %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 status0x%08lx/n", Status);

#244                      /* FIXME: show an errordialog */

#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 alreadyexist */

#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  }

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

原创粉丝点击