ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

partlist.c
Go to the documentation of this file.
00001 /*
00002  *  ReactOS kernel
00003  *  Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 /* COPYRIGHT:       See COPYING in the top level directory
00020  * PROJECT:         ReactOS text-mode setup
00021  * FILE:            subsys/system/usetup/partlist.c
00022  * PURPOSE:         Partition list functions
00023  * PROGRAMMER:      Eric Kohl
00024  *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
00025  */
00026 
00027 #include "usetup.h"
00028 
00029 #define NDEBUG
00030 #include <debug.h>
00031 
00032 /* FUNCTIONS ****************************************************************/
00033 
00034 static VOID
00035 GetDriverName (PDISKENTRY DiskEntry)
00036 {
00037   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
00038   WCHAR KeyName[32];
00039   NTSTATUS Status;
00040 
00041   RtlInitUnicodeString (&DiskEntry->DriverName,
00042                         NULL);
00043 
00044   swprintf (KeyName,
00045             L"\\Scsi\\Scsi Port %lu",
00046             DiskEntry->Port);
00047 
00048   RtlZeroMemory (&QueryTable,
00049                  sizeof(QueryTable));
00050 
00051   QueryTable[0].Name = L"Driver";
00052   QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
00053   QueryTable[0].EntryContext = &DiskEntry->DriverName;
00054 
00055   Status = RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP,
00056                                    KeyName,
00057                                    QueryTable,
00058                                    NULL,
00059                                    NULL);
00060   if (!NT_SUCCESS (Status))
00061   {
00062     DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
00063   }
00064 }
00065 
00066 
00067 static VOID
00068 AssignDriverLetters (PPARTLIST List)
00069 {
00070   PDISKENTRY DiskEntry;
00071   PPARTENTRY PartEntry;
00072   PLIST_ENTRY Entry1;
00073   //PLIST_ENTRY Entry2;
00074   CHAR Letter;
00075   UCHAR i;
00076 
00077   Letter = 'C';
00078 
00079   /* Assign drive letters to primary partitions */
00080   Entry1 = List->DiskListHead.Flink;
00081   while (Entry1 != &List->DiskListHead)
00082   {
00083     DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
00084 
00085     if (!IsListEmpty (&DiskEntry->PartListHead))
00086     {
00087       PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink,
00088                                      PARTENTRY,
00089                                      ListEntry);
00090 
00091       for (i=0; i<4; i++)
00092         PartEntry->DriveLetter[i] = 0;
00093 
00094       if (PartEntry->Unpartitioned == FALSE)
00095       {
00096         for (i=0; i<4; i++)
00097         {
00098           if (IsContainerPartition (PartEntry->PartInfo[i].PartitionType))
00099             continue;
00100 
00101           if (IsRecognizedPartition (PartEntry->PartInfo[i].PartitionType) ||
00102              (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED &&
00103              PartEntry->PartInfo[i].PartitionLength.QuadPart != 0LL))
00104           {
00105             if (Letter <= 'Z')
00106             {
00107               PartEntry->DriveLetter[i] = Letter;
00108               Letter++;
00109             }
00110           }
00111         }
00112       }
00113     }
00114 
00115     Entry1 = Entry1->Flink;
00116   }
00117 
00118   /* Assign drive letters to logical drives */
00119 #if 0
00120   Entry1 = List->DiskListHead.Flink;
00121   while (Entry1 != &List->DiskListHead)
00122   {
00123     DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
00124 
00125     Entry2 = DiskEntry->PartListHead.Flink;
00126     if (Entry2 != &DiskEntry->PartListHead)
00127     {
00128       Entry2 = Entry2->Flink;
00129       while (Entry2 != &DiskEntry->PartListHead)
00130       {
00131         PartEntry = CONTAINING_RECORD (Entry2,
00132                                        PARTENTRY,
00133                                        ListEntry);
00134 
00135         PartEntry->DriveLetter = 0;
00136 
00137         if (PartEntry->Unpartitioned == FALSE &&
00138             !IsContainerPartition (PartEntry->PartInfo[0].PartitionType))
00139         {
00140           if (IsRecognizedPartition (PartEntry->PartInfo[0].PartitionType) ||
00141              (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED &&
00142               PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL))
00143           {
00144             if (Letter <= 'Z')
00145             {
00146               PartEntry->DriveLetter = Letter;
00147               Letter++;
00148             }
00149           }
00150         }
00151 
00152         Entry2 = Entry2->Flink;
00153       }
00154     }
00155 
00156     Entry1 = Entry1->Flink;
00157   }
00158 #endif
00159 }
00160 
00161 
00162 static VOID
00163 UpdatePartitionNumbers (PDISKENTRY DiskEntry)
00164 {
00165   PPARTENTRY PartEntry;
00166   PLIST_ENTRY Entry;
00167   ULONG PartNumber;
00168   ULONG i;
00169 
00170   PartNumber = 1;
00171   Entry = DiskEntry->PartListHead.Flink;
00172   while (Entry != &DiskEntry->PartListHead)
00173   {
00174     PartEntry = CONTAINING_RECORD (Entry,
00175                                    PARTENTRY,
00176                                    ListEntry);
00177 
00178     if (PartEntry->Unpartitioned == TRUE)
00179     {
00180       for (i = 0; i < 4; i++)
00181       {
00182         PartEntry->PartInfo[i].PartitionNumber = 0;
00183       }
00184     }
00185     else
00186     {
00187       for (i = 0; i < 4; i++)
00188       {
00189         if (IsContainerPartition (PartEntry->PartInfo[i].PartitionType))
00190         {
00191           PartEntry->PartInfo[i].PartitionNumber = 0;
00192         }
00193         else if (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED &&
00194                  PartEntry->PartInfo[i].PartitionLength.QuadPart == 0ULL)
00195         {
00196           PartEntry->PartInfo[i].PartitionNumber = 0;
00197         }
00198         else
00199         {
00200           PartEntry->PartInfo[i].PartitionNumber = PartNumber;
00201           PartNumber++;
00202         }
00203       }
00204     }
00205 
00206     Entry = Entry->Flink;
00207   }
00208 }
00209 
00210 
00211 static VOID
00212 AddPartitionToList (ULONG DiskNumber,
00213                     PDISKENTRY DiskEntry,
00214                     DRIVE_LAYOUT_INFORMATION *LayoutBuffer)
00215 {
00216   PPARTENTRY PartEntry;
00217   ULONG i;
00218   ULONG j;
00219 
00220   for (i = 0; i < LayoutBuffer->PartitionCount; i += 4)
00221   {
00222     for (j = 0; j < 4; j++)
00223     {
00224       if (LayoutBuffer->PartitionEntry[i+j].PartitionType != PARTITION_ENTRY_UNUSED ||
00225           LayoutBuffer->PartitionEntry[i+j].PartitionLength.QuadPart != 0ULL)
00226       {
00227         break;
00228       }
00229     }
00230     if (j >= 4)
00231     {
00232       continue;
00233     }
00234 
00235     PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
00236                  0,
00237                  sizeof(PARTENTRY));
00238     if (PartEntry == NULL)
00239     {
00240       return;
00241     }
00242 
00243     RtlZeroMemory (PartEntry,
00244                    sizeof(PARTENTRY));
00245 
00246     PartEntry->Unpartitioned = FALSE;
00247 
00248     for (j = 0; j < 4; j++)
00249     {
00250       RtlCopyMemory (&PartEntry->PartInfo[j],
00251                      &LayoutBuffer->PartitionEntry[i+j],
00252                      sizeof(PARTITION_INFORMATION));
00253     }
00254 
00255     if (IsContainerPartition(PartEntry->PartInfo[0].PartitionType))
00256     {
00257       PartEntry->FormatState = Unformatted;
00258     }
00259     else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
00260             (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
00261             (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
00262             (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13) ||
00263             (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
00264             (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
00265     {
00266 #if 0
00267       if (CheckFatFormat())
00268       {
00269         PartEntry->FormatState = Preformatted;
00270       }
00271       else
00272       {
00273         PartEntry->FormatState = Unformatted;
00274       }
00275 #endif
00276       PartEntry->FormatState = Preformatted;
00277     }
00278     else if (PartEntry->PartInfo[0].PartitionType == PARTITION_EXT2)
00279     {
00280 #if 0
00281       if (CheckExt2Format())
00282       {
00283         PartEntry->FormatState = Preformatted;
00284       }
00285       else
00286       {
00287         PartEntry->FormatState = Unformatted;
00288       }
00289 #endif
00290       PartEntry->FormatState = Preformatted;
00291     }
00292     else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
00293     {
00294 #if 0
00295       if (CheckNtfsFormat())
00296       {
00297         PartEntry->FormatState = Preformatted;
00298       }
00299       else if (CheckHpfsFormat())
00300       {
00301         PartEntry->FormatState = Preformatted;
00302       }
00303       else
00304       {
00305         PartEntry->FormatState = Unformatted;
00306       }
00307 #endif
00308       PartEntry->FormatState = Preformatted;
00309     }
00310     else
00311     {
00312       PartEntry->FormatState = UnknownFormat;
00313     }
00314 
00315     InsertTailList (&DiskEntry->PartListHead,
00316                     &PartEntry->ListEntry);
00317   }
00318 }
00319 
00320 
00321 static VOID
00322 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry)
00323 {
00324   ULONGLONG LastStartingOffset;
00325   ULONGLONG LastPartitionLength;
00326   ULONGLONG LastUnusedPartitionLength;
00327   PPARTENTRY PartEntry;
00328   PPARTENTRY NewPartEntry;
00329   PLIST_ENTRY Entry;
00330   ULONG i;
00331   ULONG j;
00332 
00333   if (IsListEmpty (&DiskEntry->PartListHead))
00334   {
00335     /* Create a partition table that represents the empty disk */
00336     PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
00337                  0,
00338                  sizeof(PARTENTRY));
00339     if (PartEntry == NULL)
00340       return;
00341 
00342     RtlZeroMemory (PartEntry,
00343                    sizeof(PARTENTRY));
00344 
00345     PartEntry->Unpartitioned = TRUE;
00346     PartEntry->UnpartitionedOffset = 0ULL;
00347     PartEntry->UnpartitionedLength = DiskEntry->DiskSize;
00348 
00349     PartEntry->FormatState = Unformatted;
00350 
00351     InsertTailList (&DiskEntry->PartListHead,
00352                     &PartEntry->ListEntry);
00353   }
00354   else
00355   {
00356     /* Start partition at head 1, cylinder 0 */
00357     LastStartingOffset = DiskEntry->TrackSize;
00358     LastPartitionLength = 0ULL;
00359     LastUnusedPartitionLength = 0ULL;
00360 
00361     i = 0;
00362     Entry = DiskEntry->PartListHead.Flink;
00363     while (Entry != &DiskEntry->PartListHead)
00364     {
00365       PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);
00366 
00367       for (j = 0; j < 4; j++)
00368       {
00369         if ((!IsContainerPartition (PartEntry->PartInfo[j].PartitionType)) &&
00370             (PartEntry->PartInfo[j].PartitionType != PARTITION_ENTRY_UNUSED ||
00371              PartEntry->PartInfo[j].PartitionLength.QuadPart != 0LL))
00372         {
00373           LastUnusedPartitionLength =
00374           PartEntry->PartInfo[j].StartingOffset.QuadPart -
00375           (LastStartingOffset + LastPartitionLength);
00376 
00377           if (PartEntry->PartInfo[j].StartingOffset.QuadPart > (LastStartingOffset + LastPartitionLength) &&
00378               LastUnusedPartitionLength >= DiskEntry->CylinderSize)
00379           {
00380             DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);
00381 
00382             NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
00383                             0,
00384                             sizeof(PARTENTRY));
00385             if (NewPartEntry == NULL)
00386               return;
00387 
00388             RtlZeroMemory (NewPartEntry,
00389                            sizeof(PARTENTRY));
00390 
00391             NewPartEntry->Unpartitioned = TRUE;
00392             NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
00393             NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
00394             if (j == 0)
00395               NewPartEntry->UnpartitionedLength -= DiskEntry->TrackSize;
00396 
00397             NewPartEntry->FormatState = Unformatted;
00398 
00399             /* Insert the table into the list */
00400             InsertTailList (&PartEntry->ListEntry,
00401                             &NewPartEntry->ListEntry);
00402           }
00403 
00404           LastStartingOffset = PartEntry->PartInfo[j].StartingOffset.QuadPart;
00405           LastPartitionLength = PartEntry->PartInfo[j].PartitionLength.QuadPart;
00406         }
00407       }
00408 
00409       i += 4;
00410       Entry = Entry->Flink;
00411     }
00412 
00413     /* Check for trailing unpartitioned disk space */
00414     if (DiskEntry->DiskSize > (LastStartingOffset + LastPartitionLength))
00415     {
00416       /* Round-down to cylinder size */
00417       LastUnusedPartitionLength =
00418         (DiskEntry->DiskSize - (LastStartingOffset + LastPartitionLength))
00419         & ~(DiskEntry->CylinderSize - 1);
00420 
00421       if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
00422       {
00423         DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);
00424 
00425         NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
00426                                                     0,
00427                                                     sizeof(PARTENTRY));
00428         if (NewPartEntry == NULL)
00429           return;
00430 
00431         RtlZeroMemory (NewPartEntry,
00432                        sizeof(PARTENTRY));
00433 
00434         NewPartEntry->Unpartitioned = TRUE;
00435         NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
00436         NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
00437 
00438         /* Append the table to the list */
00439         InsertTailList (&DiskEntry->PartListHead,
00440                         &NewPartEntry->ListEntry);
00441       }
00442     }
00443   }
00444 }
00445 
00446 NTSTATUS
00447 NTAPI
00448 DiskIdentifierQueryRoutine(PWSTR ValueName,
00449                            ULONG ValueType,
00450                            PVOID ValueData,
00451                            ULONG ValueLength,
00452                            PVOID Context,
00453                            PVOID EntryContext)
00454 {
00455   PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
00456   UNICODE_STRING NameU;
00457 
00458   if (ValueType == REG_SZ &&
00459       ValueLength == 20 * sizeof(WCHAR))
00460   {
00461     NameU.Buffer = (PWCHAR)ValueData;
00462     NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
00463     RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
00464 
00465     NameU.Buffer = (PWCHAR)ValueData + 9;
00466     RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
00467 
00468     return STATUS_SUCCESS;
00469   }
00470   return STATUS_UNSUCCESSFUL;
00471 }
00472 
00473 NTSTATUS
00474 NTAPI
00475 DiskConfigurationDataQueryRoutine(PWSTR ValueName,
00476                                   ULONG ValueType,
00477                                   PVOID ValueData,
00478                                   ULONG ValueLength,
00479                                   PVOID Context,
00480                                   PVOID EntryContext)
00481 {
00482   PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
00483   PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
00484   PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
00485   ULONG i;
00486 
00487   if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
00488       ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
00489     return STATUS_UNSUCCESSFUL;
00490 
00491   FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
00492   /* Hm. Version and Revision are not set on Microsoft Windows XP... */
00493   /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
00494     FullResourceDescriptor->PartialResourceList.Revision != 1)
00495     return STATUS_UNSUCCESSFUL;*/
00496 
00497   for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
00498   {
00499     if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
00500         FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize != sizeof(CM_DISK_GEOMETRY_DEVICE_DATA))
00501       continue;
00502 
00503     DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1];
00504     BiosDiskEntry->DiskGeometry = *DiskGeometry;
00505 
00506     return STATUS_SUCCESS;
00507   }
00508   return STATUS_UNSUCCESSFUL;
00509 }
00510 
00511 NTSTATUS
00512 NTAPI
00513 SystemConfigurationDataQueryRoutine(PWSTR ValueName,
00514                                     ULONG ValueType,
00515                                     PVOID ValueData,
00516                                     ULONG ValueLength,
00517                                     PVOID Context,
00518                                     PVOID EntryContext)
00519 {
00520   PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
00521   PCM_INT13_DRIVE_PARAMETER* Int13Drives = (PCM_INT13_DRIVE_PARAMETER*)Context;
00522   ULONG i;
00523 
00524   if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
00525       ValueLength < sizeof (CM_FULL_RESOURCE_DESCRIPTOR))
00526     return STATUS_UNSUCCESSFUL;
00527 
00528   FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
00529   /* Hm. Version and Revision are not set on Microsoft Windows XP... */
00530   /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
00531     FullResourceDescriptor->PartialResourceList.Revision != 1)
00532     return STATUS_UNSUCCESSFUL;*/
00533 
00534   for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
00535   {
00536     if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
00537         FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
00538       continue;
00539 
00540     *Int13Drives = (CM_INT13_DRIVE_PARAMETER*) RtlAllocateHeap(ProcessHeap, 0, FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
00541     if (*Int13Drives == NULL)
00542       return STATUS_NO_MEMORY;
00543     memcpy(*Int13Drives,
00544            &FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1],
00545            FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
00546     return STATUS_SUCCESS;
00547   }
00548   return STATUS_UNSUCCESSFUL;
00549 }
00550 #define ROOT_NAME   L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
00551 
00552 static VOID
00553 EnumerateBiosDiskEntries(PPARTLIST PartList)
00554 {
00555   RTL_QUERY_REGISTRY_TABLE QueryTable[3];
00556   WCHAR Name[120];
00557   ULONG AdapterCount;
00558   ULONG DiskCount;
00559   NTSTATUS Status;
00560   PCM_INT13_DRIVE_PARAMETER Int13Drives;
00561   PBIOSDISKENTRY BiosDiskEntry;
00562 
00563   memset(QueryTable, 0, sizeof(QueryTable));
00564 
00565   QueryTable[1].Name = L"Configuration Data";
00566   QueryTable[1].QueryRoutine = SystemConfigurationDataQueryRoutine;
00567   Int13Drives = NULL;
00568   Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
00569                                   L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
00570                                   &QueryTable[1],
00571                                   (PVOID)&Int13Drives,
00572                                   NULL);
00573   if (!NT_SUCCESS(Status))
00574   {
00575     DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status);
00576     return;
00577   }
00578 
00579   AdapterCount = 0;
00580   while (1)
00581   {
00582     swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
00583     Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
00584                                     Name,
00585                                     &QueryTable[2],
00586                                     NULL,
00587                                     NULL);
00588     if (!NT_SUCCESS(Status))
00589     {
00590       break;
00591     }
00592 
00593     swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
00594     Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
00595                                     Name,
00596                                     &QueryTable[2],
00597                                     NULL,
00598                                     NULL);
00599     if (NT_SUCCESS(Status))
00600     {
00601       while (1)
00602       {
00603         swprintf(Name, L"%s\\%lu\\DiskController\\0", ROOT_NAME, AdapterCount);
00604         Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
00605                                         Name,
00606                                         &QueryTable[2],
00607                                         NULL,
00608                                         NULL);
00609         if (!NT_SUCCESS(Status))
00610         {
00611           RtlFreeHeap(ProcessHeap, 0, Int13Drives);
00612           return;
00613         }
00614 
00615         swprintf(Name, L"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME, AdapterCount);
00616         Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
00617                                         Name,
00618                                         &QueryTable[2],
00619                                         NULL,
00620                                         NULL);
00621         if (NT_SUCCESS(Status))
00622         {
00623           QueryTable[0].Name = L"Identifier";
00624           QueryTable[0].QueryRoutine = DiskIdentifierQueryRoutine;
00625           QueryTable[1].Name = L"Configuration Data";
00626           QueryTable[1].QueryRoutine = DiskConfigurationDataQueryRoutine;
00627           DiskCount = 0;
00628           while (1)
00629           {
00630             BiosDiskEntry = (BIOSDISKENTRY*) RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
00631             if (BiosDiskEntry == NULL)
00632             {
00633               break;
00634             }
00635             swprintf(Name, L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, DiskCount);
00636             Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
00637                                             Name,
00638                                             QueryTable,
00639                                             (PVOID)BiosDiskEntry,
00640                                             NULL);
00641             if (!NT_SUCCESS(Status))
00642             {
00643               RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
00644               break;
00645             }
00646             BiosDiskEntry->DiskNumber = DiskCount;
00647             BiosDiskEntry->Recognized = FALSE;
00648 
00649             if (DiskCount < Int13Drives[0].NumberDrives)
00650             {
00651               BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount];
00652             }
00653             else
00654             {
00655               DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
00656             }
00657 
00658 
00659             InsertTailList(&PartList->BiosDiskListHead, &BiosDiskEntry->ListEntry);
00660 
00661             DPRINT("DiskNumber:        %lu\n", BiosDiskEntry->DiskNumber);
00662             DPRINT("Signature:         %08lx\n", BiosDiskEntry->Signature);
00663             DPRINT("Checksum:          %08lx\n", BiosDiskEntry->Checksum);
00664             DPRINT("BytesPerSector:    %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector);
00665             DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders);
00666             DPRINT("NumberOfHeads:     %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads);
00667             DPRINT("DriveSelect:       %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect);
00668             DPRINT("MaxCylinders:      %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders);
00669             DPRINT("SectorsPerTrack:   %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
00670             DPRINT("MaxHeads:          %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
00671             DPRINT("NumberDrives:      %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
00672 
00673             DiskCount++;
00674           }
00675         }
00676         RtlFreeHeap(ProcessHeap, 0, Int13Drives);
00677         return;
00678       }
00679     }
00680     AdapterCount++;
00681   }
00682   RtlFreeHeap(ProcessHeap, 0, Int13Drives);
00683 }
00684 
00685 static VOID
00686 AddDiskToList (HANDLE FileHandle,
00687                ULONG DiskNumber,
00688                PPARTLIST List)
00689 {
00690   DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
00691   DISK_GEOMETRY DiskGeometry;
00692   SCSI_ADDRESS ScsiAddress;
00693   PDISKENTRY DiskEntry;
00694   IO_STATUS_BLOCK Iosb;
00695   NTSTATUS Status;
00696   PPARTITION_SECTOR Mbr;
00697   PULONG Buffer;
00698   LARGE_INTEGER FileOffset;
00699   WCHAR Identifier[20];
00700   ULONG Checksum;
00701   ULONG Signature;
00702   ULONG i;
00703   PLIST_ENTRY ListEntry;
00704   PBIOSDISKENTRY BiosDiskEntry;
00705   ULONG LayoutBufferSize;
00706 
00707   Status = NtDeviceIoControlFile (FileHandle,
00708                                   NULL,
00709                                   NULL,
00710                                   NULL,
00711                                   &Iosb,
00712                                   IOCTL_DISK_GET_DRIVE_GEOMETRY,
00713                                   NULL,
00714                                   0,
00715                                   &DiskGeometry,
00716                                   sizeof(DISK_GEOMETRY));
00717   if (!NT_SUCCESS (Status))
00718   {
00719     return;
00720   }
00721 
00722   if (DiskGeometry.MediaType != FixedMedia &&
00723       DiskGeometry.MediaType != RemovableMedia)
00724   {
00725     return;
00726   }
00727 
00728   Status = NtDeviceIoControlFile (FileHandle,
00729                                   NULL,
00730                                   NULL,
00731                                   NULL,
00732                                   &Iosb,
00733                                   IOCTL_SCSI_GET_ADDRESS,
00734                                   NULL,
00735                                   0,
00736                                   &ScsiAddress,
00737                                   sizeof(SCSI_ADDRESS));
00738   if (!NT_SUCCESS(Status))
00739   {
00740     return;
00741   }
00742 
00743   Mbr = (PARTITION_SECTOR*) RtlAllocateHeap(ProcessHeap,
00744                                             0,
00745                                             DiskGeometry.BytesPerSector);
00746 
00747   if (Mbr == NULL)
00748   {
00749     return;
00750   }
00751 
00752   FileOffset.QuadPart = 0;
00753   Status = NtReadFile(FileHandle,
00754                       NULL,
00755                       NULL,
00756                       NULL,
00757                       &Iosb,
00758                       (PVOID)Mbr,
00759                       DiskGeometry.BytesPerSector,
00760                       &FileOffset,
00761                       NULL);
00762   if (!NT_SUCCESS(Status))
00763   {
00764     RtlFreeHeap(ProcessHeap,
00765                 0,
00766                 Mbr);
00767     DPRINT1("NtReadFile failed, status=%x\n", Status);
00768     return;
00769   }
00770   Signature = Mbr->Signature;
00771 
00772   /* Calculate the MBR checksum */
00773   Checksum = 0;
00774   Buffer = (PULONG)Mbr;
00775   for (i = 0; i < 128; i++)
00776   {
00777     Checksum += Buffer[i];
00778   }
00779   Checksum = ~Checksum + 1;
00780 
00781   swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
00782   DPRINT("Identifier: %S\n", Identifier);
00783 
00784   DiskEntry = (PDISKENTRY)RtlAllocateHeap (ProcessHeap,
00785                                            0,
00786                                            sizeof(DISKENTRY));
00787   if (DiskEntry == NULL)
00788   {
00789     return;
00790   }
00791 
00792   DiskEntry->Checksum = Checksum;
00793   DiskEntry->Signature = Signature;
00794   if (Signature == 0)
00795   {
00796     /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
00797     DiskEntry->Modified = TRUE;
00798   }
00799   DiskEntry->BiosFound = FALSE;
00800 
00801   /* Check if this disk has a valid MBR */
00802   if (Mbr->BootCode[0] == 0 && Mbr->BootCode[1] == 0)
00803     DiskEntry->NoMbr = TRUE;
00804   else
00805     DiskEntry->NoMbr = FALSE;
00806 
00807   /* Free Mbr sector buffer */
00808   RtlFreeHeap (ProcessHeap,
00809                0,
00810                Mbr);
00811 
00812   ListEntry = List->BiosDiskListHead.Flink;
00813   while(ListEntry != &List->BiosDiskListHead)
00814   {
00815     BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
00816     /* FIXME:
00817      *   Compare the size from bios and the reported size from driver.
00818      *   If we have more than one disk with a zero or with the same signatur
00819      *   we must create new signatures and reboot. After the reboot,
00820      *   it is possible to identify the disks.
00821      */
00822     if (BiosDiskEntry->Signature == Signature &&
00823         BiosDiskEntry->Checksum == Checksum &&
00824         !BiosDiskEntry->Recognized)
00825     {
00826       if (!DiskEntry->BiosFound)
00827       {
00828         DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
00829         DiskEntry->BiosFound = TRUE;
00830         BiosDiskEntry->Recognized = TRUE;
00831       }
00832       else
00833       {
00834       }
00835     }
00836     ListEntry = ListEntry->Flink;
00837   }
00838 
00839   if (!DiskEntry->BiosFound)
00840   {
00841 #if 0
00842     RtlFreeHeap(ProcessHeap, 0, DiskEntry);
00843     return;
00844 #else
00845     DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
00846 #endif
00847   }
00848 
00849   InitializeListHead (&DiskEntry->PartListHead);
00850 
00851   DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
00852   DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
00853   DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
00854   DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
00855 
00856   DPRINT ("Cylinders %I64u\n", DiskEntry->Cylinders);
00857   DPRINT ("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder);
00858   DPRINT ("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack);
00859   DPRINT ("BytesPerSector %I64u\n", DiskEntry->BytesPerSector);
00860 
00861   DiskEntry->TrackSize =
00862     (ULONGLONG)DiskGeometry.SectorsPerTrack *
00863     (ULONGLONG)DiskGeometry.BytesPerSector;
00864   DiskEntry->CylinderSize =
00865     (ULONGLONG)DiskGeometry.TracksPerCylinder *
00866     DiskEntry->TrackSize;
00867   DiskEntry->DiskSize =
00868     DiskGeometry.Cylinders.QuadPart *
00869     DiskEntry->CylinderSize;
00870 
00871   DiskEntry->DiskNumber = DiskNumber;
00872   DiskEntry->Port = ScsiAddress.PortNumber;
00873   DiskEntry->Bus = ScsiAddress.PathId;
00874   DiskEntry->Id = ScsiAddress.TargetId;
00875 
00876   GetDriverName (DiskEntry);
00877 
00878   InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
00879 
00880   /*
00881    * Allocate a buffer for 26 logical drives (2 entries each == 52) 
00882    * plus the main partiton table (4 entries). Total 56 entries.
00883    */
00884   LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
00885                      ((56 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
00886   LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap (ProcessHeap,
00887                   0,
00888                   LayoutBufferSize);
00889   if (LayoutBuffer == NULL)
00890   {
00891     return;
00892   }
00893 
00894   Status = NtDeviceIoControlFile (FileHandle,
00895                                   NULL,
00896                                   NULL,
00897                                   NULL,
00898                                   &Iosb,
00899                                   IOCTL_DISK_GET_DRIVE_LAYOUT,
00900                                   NULL,
00901                                   0,
00902                                   LayoutBuffer,
00903                                   LayoutBufferSize);
00904   if (NT_SUCCESS (Status))
00905   {
00906     if (LayoutBuffer->PartitionCount == 0)
00907     {
00908       DiskEntry->NewDisk = TRUE;
00909     }
00910 
00911     AddPartitionToList (DiskNumber,
00912                         DiskEntry,
00913                         LayoutBuffer);
00914 
00915     ScanForUnpartitionedDiskSpace (DiskEntry);
00916   }
00917 
00918   RtlFreeHeap (ProcessHeap,
00919                0,
00920                LayoutBuffer);
00921 }
00922 
00923 
00924 PPARTLIST
00925 CreatePartitionList (SHORT Left,
00926                      SHORT Top,
00927                      SHORT Right,
00928                      SHORT Bottom)
00929 {
00930   PPARTLIST List;
00931   OBJECT_ATTRIBUTES ObjectAttributes;
00932   SYSTEM_DEVICE_INFORMATION Sdi;
00933   IO_STATUS_BLOCK Iosb;
00934   ULONG ReturnSize;
00935   NTSTATUS Status;
00936   ULONG DiskNumber;
00937   WCHAR Buffer[MAX_PATH];
00938   UNICODE_STRING Name;
00939   HANDLE FileHandle;
00940 
00941   List = (PPARTLIST)RtlAllocateHeap (ProcessHeap,
00942                                      0,
00943                                      sizeof (PARTLIST));
00944   if (List == NULL)
00945     return NULL;
00946 
00947   List->Left = Left;
00948   List->Top = Top;
00949   List->Right = Right;
00950   List->Bottom = Bottom;
00951 
00952   List->Line = 0;
00953   List->Offset = 0;
00954 
00955   List->TopDisk = (ULONG)-1;
00956   List->TopPartition = (ULONG)-1;
00957 
00958   List->CurrentDisk = NULL;
00959   List->CurrentPartition = NULL;
00960   List->CurrentPartitionNumber = 0;
00961 
00962   InitializeListHead (&List->DiskListHead);
00963   InitializeListHead (&List->BiosDiskListHead);
00964 
00965   EnumerateBiosDiskEntries(List);
00966 
00967   Status = NtQuerySystemInformation (SystemDeviceInformation,
00968                                      &Sdi,
00969                                      sizeof(SYSTEM_DEVICE_INFORMATION),
00970                                      &ReturnSize);
00971   if (!NT_SUCCESS (Status))
00972   {
00973     RtlFreeHeap (ProcessHeap, 0, List);
00974     return NULL;
00975   }
00976 
00977   for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
00978   {
00979     swprintf (Buffer,
00980               L"\\Device\\Harddisk%d\\Partition0",
00981               DiskNumber);
00982     RtlInitUnicodeString (&Name,
00983                           Buffer);
00984 
00985     InitializeObjectAttributes (&ObjectAttributes,
00986                                 &Name,
00987                                 0,
00988                                 NULL,
00989                                 NULL);
00990 
00991     Status = NtOpenFile (&FileHandle,
00992                          FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
00993                          &ObjectAttributes,
00994                          &Iosb,
00995                          FILE_SHARE_READ,
00996                          FILE_SYNCHRONOUS_IO_NONALERT);
00997     if (NT_SUCCESS(Status))
00998     {
00999       AddDiskToList (FileHandle,
01000                      DiskNumber,
01001                      List);
01002 
01003       NtClose(FileHandle);
01004     }
01005   }
01006 
01007   AssignDriverLetters (List);
01008 
01009   List->TopDisk = 0;
01010   List->TopPartition = 0;
01011 
01012   /* Search for first usable disk and partition */
01013   if (IsListEmpty (&List->DiskListHead))
01014   {
01015     List->CurrentDisk = NULL;
01016     List->CurrentPartition = NULL;
01017     List->CurrentPartitionNumber = 0;
01018   }
01019   else
01020   {
01021     List->CurrentDisk =
01022       CONTAINING_RECORD (List->DiskListHead.Flink,
01023                          DISKENTRY,
01024                          ListEntry);
01025 
01026     if (IsListEmpty (&List->CurrentDisk->PartListHead))
01027     {
01028       List->CurrentPartition = 0;
01029       List->CurrentPartitionNumber = 0;
01030     }
01031     else
01032     {
01033       List->CurrentPartition =
01034         CONTAINING_RECORD (List->CurrentDisk->PartListHead.Flink,
01035                            PARTENTRY,
01036                            ListEntry);
01037       List->CurrentPartitionNumber = 0;
01038     }
01039   }
01040 
01041   return List;
01042 }
01043 
01044 
01045 VOID
01046 DestroyPartitionList (PPARTLIST List)
01047 {
01048   PDISKENTRY DiskEntry;
01049   PBIOSDISKENTRY BiosDiskEntry;
01050   PPARTENTRY PartEntry;
01051   PLIST_ENTRY Entry;
01052 
01053   /* Release disk and partition info */
01054   while (!IsListEmpty (&List->DiskListHead))
01055   {
01056     Entry = RemoveHeadList (&List->DiskListHead);
01057     DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
01058 
01059     /* Release driver name */
01060     RtlFreeUnicodeString(&DiskEntry->DriverName);
01061 
01062     /* Release partition array */
01063     while (!IsListEmpty (&DiskEntry->PartListHead))
01064     {
01065       Entry = RemoveHeadList (&DiskEntry->PartListHead);
01066       PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);
01067 
01068       RtlFreeHeap (ProcessHeap,
01069                    0,
01070                    PartEntry);
01071     }
01072 
01073     /* Release disk entry */
01074     RtlFreeHeap (ProcessHeap, 0, DiskEntry);
01075   }
01076 
01077   /* release the bios disk info */
01078   while(!IsListEmpty(&List->BiosDiskListHead))
01079   {
01080     Entry = RemoveHeadList(&List->BiosDiskListHead);
01081     BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
01082 
01083     RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
01084   }
01085 
01086   /* Release list head */
01087   RtlFreeHeap (ProcessHeap, 0, List);
01088 }
01089 
01090 
01091 static VOID
01092 PrintEmptyLine (PPARTLIST List)
01093 {
01094   COORD coPos;
01095   DWORD Written;
01096   USHORT Width;
01097   USHORT Height;
01098 
01099   Width = List->Right - List->Left - 1;
01100   Height = List->Bottom - List->Top - 2;
01101 
01102 
01103   coPos.X = List->Left + 1;
01104   coPos.Y = List->Top + 1 + List->Line;
01105 
01106   if (List->Line >= 0 && List->Line <= Height)
01107   {
01108     FillConsoleOutputAttribute (StdOutput,
01109                                 FOREGROUND_WHITE | BACKGROUND_BLUE,
01110                                 Width,
01111                                 coPos,
01112                                 &Written);
01113 
01114     FillConsoleOutputCharacterA (StdOutput,
01115                                  ' ',
01116                                  Width,
01117                                  coPos,
01118                                  &Written);
01119   }
01120   List->Line++;
01121 }
01122 
01123 
01124 static VOID
01125 PrintPartitionData (PPARTLIST List,
01126                     PDISKENTRY DiskEntry,
01127                     PPARTENTRY PartEntry,
01128                     ULONG PartNumber)
01129 {
01130   CHAR LineBuffer[128];
01131   COORD coPos;
01132   DWORD Written;
01133   USHORT Width;
01134   USHORT Height;
01135 
01136   LARGE_INTEGER PartSize;
01137   PCHAR Unit;
01138   UCHAR Attribute;
01139   PCHAR PartType;
01140 
01141   Width = List->Right - List->Left - 1;
01142   Height = List->Bottom - List->Top - 2;
01143 
01144 
01145   coPos.X = List->Left + 1;
01146   coPos.Y = List->Top + 1 + List->Line;
01147 
01148   if (PartEntry->Unpartitioned == TRUE)
01149   {
01150 #if 0
01151     if (PartEntry->UnpartitionledLength >= 0x280000000ULL) /* 10 GB */
01152     {
01153       PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 29)) >> 30;
01154       Unit = MUIGetString(STRING_GB);
01155     }
01156     else
01157 #endif
01158       if (PartEntry->UnpartitionedLength >= 0xA00000ULL) /* 10 MB */
01159       {
01160         PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20;
01161         Unit = MUIGetString(STRING_MB);
01162       }
01163       else
01164       {
01165         PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 9)) >> 10;
01166         Unit = MUIGetString(STRING_KB);
01167       }
01168 
01169       sprintf (LineBuffer,
01170                MUIGetString(STRING_UNPSPACE),
01171                PartSize.u.LowPart,
01172                Unit);
01173   }
01174   else
01175   {
01176     /* Determine partition type */
01177     PartType = NULL;
01178     if (PartEntry->New == TRUE)
01179     {
01180       PartType = MUIGetString(STRING_UNFORMATTED);
01181     }
01182     else if (PartEntry->Unpartitioned == FALSE)
01183     {
01184       if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_12) ||
01185           (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_16) ||
01186           (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_HUGE) ||
01187           (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_XINT13))
01188       {
01189         PartType = "FAT";
01190       }
01191       else if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32) ||
01192                (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32_XINT13))
01193       {
01194         PartType = "FAT32";
01195       }
01196       else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_EXT2)
01197       {
01198         PartType = "EXT2";
01199       }
01200       else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_IFS)
01201       {
01202         PartType = "NTFS"; /* FIXME: Not quite correct! */
01203       }
01204     }
01205 
01206 #if 0
01207     if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
01208     {
01209       PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 29)) >> 30;
01210       Unit = MUIGetString(STRING_GB);
01211     }
01212     else
01213 #endif
01214     if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0xA00000LL) /* 10 MB */
01215     {
01216       PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 19)) >> 20;
01217       Unit = MUIGetString(STRING_MB);
01218     }
01219     else
01220     {
01221       PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 9)) >> 10;
01222       Unit = MUIGetString(STRING_KB);
01223     }
01224 
01225     if (PartType == NULL)
01226     {
01227       sprintf (LineBuffer,
01228                MUIGetString(STRING_HDDINFOUNK5),
01229                (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
01230                (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
01231                PartEntry->PartInfo[PartNumber].PartitionType,
01232                PartSize.u.LowPart,
01233                Unit);
01234     }
01235     else
01236     {
01237       sprintf (LineBuffer,
01238                "%c%c  %-24s         %6lu %s",
01239                (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
01240                (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
01241                PartType,
01242                PartSize.u.LowPart,
01243                Unit);
01244     }
01245   }
01246 
01247   Attribute = (List->CurrentDisk == DiskEntry &&
01248                List->CurrentPartition == PartEntry &&
01249                List->CurrentPartitionNumber == PartNumber) ?
01250                FOREGROUND_BLUE | BACKGROUND_WHITE :
01251                FOREGROUND_WHITE | BACKGROUND_BLUE;
01252 
01253   if (List->Line >= 0 && List->Line <= Height)
01254   {
01255     FillConsoleOutputCharacterA (StdOutput,
01256                                  ' ',
01257                                  Width,
01258                                  coPos,
01259                                  &Written);
01260   }
01261   coPos.X += 4;
01262   Width -= 8;
01263   if (List->Line >= 0 && List->Line <= Height)
01264   {
01265     FillConsoleOutputAttribute (StdOutput,
01266                                 Attribute,
01267                                 Width,
01268                                 coPos,
01269                                 &Written);
01270   }
01271   coPos.X++;
01272   Width -= 2;
01273   if (List->Line >= 0 && List->Line <= Height)
01274   {
01275     WriteConsoleOutputCharacterA (StdOutput,
01276                                   LineBuffer,
01277                                   min (strlen (LineBuffer), Width),
01278                                   coPos,
01279                                   &Written);
01280   }
01281   List->Line++;
01282 }
01283 
01284 
01285 static VOID
01286 PrintDiskData (PPARTLIST List,
01287                PDISKENTRY DiskEntry)
01288 {
01289   PPARTENTRY PartEntry;
01290   PLIST_ENTRY Entry;
01291   CHAR LineBuffer[128];
01292   COORD coPos;
01293   DWORD Written;
01294   USHORT Width;
01295   USHORT Height;
01296   ULARGE_INTEGER DiskSize;
01297   PCHAR Unit;
01298   ULONG i;
01299 
01300   Width = List->Right - List->Left - 1;
01301   Height = List->Bottom - List->Top - 2;
01302 
01303 
01304   coPos.X = List->Left + 1;
01305   coPos.Y = List->Top + 1 + List->Line;
01306 
01307 #if 0
01308   if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
01309   {
01310     DiskSize.QuadPart = (DiskEntry->DiskSize + (1 << 29)) >> 30;
01311     Unit = MUIGetString(STRING_GB);
01312   }
01313   else
01314 #endif
01315   {
01316     DiskSize.QuadPart = (DiskEntry->DiskSize + (1 << 19)) >> 20;
01317     if (DiskSize.QuadPart == 0)
01318       DiskSize.QuadPart = 1;
01319     Unit = MUIGetString(STRING_MB);
01320   }
01321 
01322   if (DiskEntry->DriverName.Length > 0)
01323   {
01324     sprintf (LineBuffer,
01325              MUIGetString(STRING_HDINFOPARTSELECT),
01326              DiskSize.u.LowPart,
01327              Unit,
01328              DiskEntry->DiskNumber,
01329              DiskEntry->Port,
01330              DiskEntry->Bus,
01331              DiskEntry->Id,
01332              DiskEntry->DriverName.Buffer);
01333   }
01334   else
01335   {
01336     sprintf (LineBuffer,
01337              MUIGetString(STRING_HDDINFOUNK6),
01338              DiskSize.u.LowPart,
01339              Unit,
01340              DiskEntry->DiskNumber,
01341              DiskEntry->Port,
01342              DiskEntry->Bus,
01343              DiskEntry->Id);
01344   }
01345   if (List->Line >= 0 && List->Line <= Height)
01346   {
01347     FillConsoleOutputAttribute (StdOutput,
01348                                 FOREGROUND_WHITE | BACKGROUND_BLUE,
01349                                 Width,
01350                                 coPos,
01351                                 &Written);
01352 
01353     FillConsoleOutputCharacterA (StdOutput,
01354                                  ' ',
01355                                  Width,
01356                                  coPos,
01357                                  &Written);
01358   }
01359 
01360   coPos.X++;
01361   if (List->Line >= 0 && List->Line <= Height)
01362   {
01363     WriteConsoleOutputCharacterA (StdOutput,
01364                                   LineBuffer,
01365                                   min ((USHORT)strlen (LineBuffer), Width - 2),
01366                                   coPos,
01367                                   &Written);
01368   }
01369   List->Line++;
01370 
01371   /* Print separator line */
01372   PrintEmptyLine (List);
01373 
01374   /* Print partition lines*/
01375   Entry = DiskEntry->PartListHead.Flink;
01376   while (Entry != &DiskEntry->PartListHead)
01377   {
01378     PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
01379 
01380     /* Print disk entry */
01381     for (i=0; i<4; i++)
01382     {
01383       if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED ||
01384           PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
01385       {
01386         PrintPartitionData (List,
01387                             DiskEntry,
01388                             PartEntry,
01389                             i);
01390       }
01391     }
01392 
01393     /* Print unpartitioned entry */
01394     if (PartEntry->Unpartitioned)
01395     {
01396         PrintPartitionData (List,
01397                             DiskEntry,
01398                             PartEntry,
01399                             0);
01400     }
01401 
01402     Entry = Entry->Flink;
01403   }
01404 
01405   /* Print separator line */
01406   PrintEmptyLine (List);
01407 }
01408 
01409 
01410 VOID
01411 DrawPartitionList (PPARTLIST List)
01412 {
01413   PLIST_ENTRY Entry, Entry2;
01414   PDISKENTRY DiskEntry;
01415   PPARTENTRY PartEntry = NULL;
01416   COORD coPos;
01417   DWORD Written;
01418   SHORT i;
01419   SHORT CurrentDiskLine;
01420   SHORT CurrentPartLine;
01421   SHORT LastLine;
01422   BOOL CurrentPartLineFound = FALSE;
01423   BOOL CurrentDiskLineFound = FALSE;
01424 
01425   /* Calculate the line of the current disk and partition */
01426   CurrentDiskLine = 0;
01427   CurrentPartLine = 0;
01428   LastLine = 0;
01429   Entry = List->DiskListHead.Flink;
01430   while (Entry != &List->DiskListHead)
01431   {
01432     DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
01433     LastLine += 2;
01434     if (CurrentPartLineFound == FALSE)
01435     {
01436       CurrentPartLine += 2;
01437     }
01438     Entry2 = DiskEntry->PartListHead.Flink;
01439     while (Entry2 != &DiskEntry->PartListHead)
01440     {
01441       PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
01442       if (PartEntry == List->CurrentPartition)
01443       {
01444         CurrentPartLineFound = TRUE;
01445       }
01446       Entry2 = Entry2->Flink;
01447       if (CurrentPartLineFound == FALSE)
01448       {
01449         CurrentPartLine++;
01450       }
01451       LastLine++;
01452     }
01453     if (DiskEntry == List->CurrentDisk)
01454     {
01455       CurrentDiskLineFound = TRUE;
01456     }
01457     Entry = Entry->Flink;
01458     if (Entry != &List->DiskListHead)
01459     {
01460       if (CurrentDiskLineFound == FALSE)
01461       {
01462         CurrentPartLine ++;
01463         CurrentDiskLine = CurrentPartLine;
01464       }
01465       LastLine++;
01466     }
01467     else
01468     {
01469       LastLine--;
01470     }
01471   }
01472 
01473   /* If it possible, make the disk name visible */
01474   if (CurrentPartLine < List->Offset)
01475   {
01476     List->Offset = CurrentPartLine;
01477   }
01478   else if (CurrentPartLine - List->Offset > List->Bottom - List->Top - 2)
01479   {
01480     List->Offset = CurrentPartLine - (List->Bottom - List->Top - 2);
01481   }
01482   if (CurrentDiskLine < List->Offset && CurrentPartLine - CurrentDiskLine < List->Bottom - List->Top - 2)
01483   {
01484     List->Offset = CurrentDiskLine;
01485   }
01486 
01487 
01488   /* draw upper left corner */
01489   coPos.X = List->Left;
01490   coPos.Y = List->Top;
01491   FillConsoleOutputCharacterA (StdOutput,
01492                                0xDA, // '+',
01493                                1,
01494                                coPos,
01495                                &Written);
01496 
01497   /* draw upper edge */
01498   coPos.X = List->Left + 1;
01499   coPos.Y = List->Top;
01500   if (List->Offset == 0)
01501   {
01502     FillConsoleOutputCharacterA (StdOutput,
01503                                  0xC4, // '-',
01504                                  List->Right - List->Left - 1,
01505                                  coPos,
01506                                  &Written);
01507   }
01508   else
01509   {
01510     FillConsoleOutputCharacterA (StdOutput,
01511                                  0xC4, // '-',
01512                                  List->Right - List->Left - 5,
01513                                  coPos,
01514                                  &Written);
01515     coPos.X = List->Right - 5;
01516     WriteConsoleOutputCharacterA (StdOutput,
01517                                   "(\x18)", // "(up)"
01518                                   3,
01519                                   coPos,
01520                                   &Written);
01521     coPos.X = List->Right - 2;
01522     FillConsoleOutputCharacterA (StdOutput,
01523                                  0xC4, // '-',
01524                                  2,
01525                                  coPos,
01526                                  &Written);
01527   }
01528 
01529   /* draw upper right corner */
01530   coPos.X = List->Right;
01531   coPos.Y = List->Top;
01532   FillConsoleOutputCharacterA (StdOutput,
01533                                0xBF, // '+',
01534                                1,
01535                                coPos,
01536                                &Written);
01537 
01538   /* draw left and right edge */
01539   for (i = List->Top + 1; i < List->Bottom; i++)
01540   {
01541     coPos.X = List->Left;
01542     coPos.Y = i;
01543     FillConsoleOutputCharacterA (StdOutput,
01544                                  0xB3, // '|',
01545                                  1,
01546                                  coPos,
01547                                  &Written);
01548 
01549     coPos.X = List->Right;
01550     FillConsoleOutputCharacterA (StdOutput,
01551                                  0xB3, //'|',
01552                                  1,
01553                                  coPos,
01554                                  &Written);
01555   }
01556 
01557   /* draw lower left corner */
01558   coPos.X = List->Left;
01559   coPos.Y = List->Bottom;
01560   FillConsoleOutputCharacterA (StdOutput,
01561                                0xC0, // '+',
01562                                1,
01563                                coPos,
01564                                &Written);
01565 
01566   /* draw lower edge */
01567   coPos.X = List->Left + 1;
01568   coPos.Y = List->Bottom;
01569   if (LastLine - List->Offset <= List->Bottom - List->Top - 2)
01570   {
01571     FillConsoleOutputCharacterA (StdOutput,
01572                                  0xC4, // '-',
01573                                  List->Right - List->Left - 1,
01574                                  coPos,
01575                                  &Written);
01576   }
01577   else
01578   {
01579     FillConsoleOutputCharacterA (StdOutput,
01580                                  0xC4, // '-',
01581                                  List->Right - List->Left - 5,
01582                                  coPos,
01583                                  &Written);
01584     coPos.X = List->Right - 5;
01585     WriteConsoleOutputCharacterA (StdOutput,
01586                                  "(\x19)", // "(down)"
01587                                  3,
01588                                  coPos,
01589                                  &Written);
01590     coPos.X = List->Right - 2;
01591     FillConsoleOutputCharacterA (StdOutput,
01592                                  0xC4, // '-',
01593                                  2,
01594                                  coPos,
01595                                  &Written);
01596   }
01597 
01598   /* draw lower right corner */
01599   coPos.X = List->Right;
01600   coPos.Y = List->Bottom;
01601   FillConsoleOutputCharacterA (StdOutput,
01602                                0xD9, // '+',
01603                                1,
01604                                coPos,
01605                                &Written);
01606 
01607   /* print list entries */
01608   List->Line = - List->Offset;
01609 
01610   Entry = List->DiskListHead.Flink;
01611   while (Entry != &List->DiskListHead)
01612   {
01613     DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
01614 
01615     /* Print disk entry */
01616     PrintDiskData (List,
01617                    DiskEntry);
01618 
01619     Entry = Entry->Flink;
01620   }
01621 }
01622 
01623 
01624 DWORD
01625 SelectPartition(PPARTLIST List, ULONG DiskNumber, ULONG PartitionNumber)
01626 {
01627   PDISKENTRY DiskEntry;
01628   PPARTENTRY PartEntry;
01629   PLIST_ENTRY Entry1;
01630   PLIST_ENTRY Entry2;
01631   UCHAR i;
01632 
01633   /* Check for empty disks */
01634   if (IsListEmpty (&List->DiskListHead))
01635     return FALSE;
01636 
01637   /* Check for first usable entry on next disk */
01638   Entry1 = List->CurrentDisk->ListEntry.Flink;
01639   while (Entry1 != &List->DiskListHead)
01640   {
01641     DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
01642 
01643     if (DiskEntry->DiskNumber == DiskNumber)
01644     {
01645       Entry2 = DiskEntry->PartListHead.Flink;
01646       while (Entry2 != &DiskEntry->PartListHead)
01647       {
01648         PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
01649 
01650         for (i = 0; i < 4; i++)
01651         {
01652           if (PartEntry->PartInfo[i].PartitionNumber == PartitionNumber)
01653           {
01654             List->CurrentDisk = DiskEntry;
01655             List->CurrentPartition = PartEntry;
01656             List->CurrentPartitionNumber = i;
01657             DrawPartitionList (List);
01658             return TRUE;
01659           }
01660         }
01661         Entry2 = Entry2->Flink;
01662       }
01663       return FALSE;
01664     }
01665     Entry1 = Entry1->Flink;
01666   }
01667   return FALSE;
01668 }
01669 
01670 
01671 VOID
01672 ScrollDownPartitionList (PPARTLIST List)
01673 {
01674   PDISKENTRY DiskEntry;
01675   PPARTENTRY PartEntry;
01676   PLIST_ENTRY Entry1;
01677   PLIST_ENTRY Entry2;
01678   UCHAR i;
01679 
01680   /* Check for empty disks */
01681   if (IsListEmpty (&List->DiskListHead))
01682     return;
01683 
01684   /* Check for next usable entry on current disk */
01685   if (List->CurrentPartition != NULL)
01686   {
01687     Entry2 = &List->CurrentPartition->ListEntry;
01688     PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
01689 
01690     /* Check if we can move inside primary partitions */
01691     for (i = List->CurrentPartitionNumber + 1; i < 4; i++)
01692     {
01693         if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
01694             break;
01695     }
01696 
01697     if (i == 4)
01698     {
01699         /* We're out of partitions in the current partition table.
01700            Try to move to the next one if possible. */
01701         Entry2 = Entry2->Flink;
01702     }
01703     else
01704     {
01705         /* Just advance to the next partition */
01706         List->CurrentPartitionNumber = i;
01707         DrawPartitionList (List);
01708         return;
01709     }
01710 
01711     while (Entry2 != &List->CurrentDisk->PartListHead)
01712     {
01713       PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
01714 
01715 //    if (PartEntry->HidePartEntry == FALSE)
01716       {
01717         List->CurrentPartition = PartEntry;
01718         List->CurrentPartitionNumber = 0;
01719         DrawPartitionList (List);
01720         return;
01721       }
01722       Entry2 = Entry2->Flink;
01723     }
01724   }
01725 
01726   /* Check for first usable entry on next disk */
01727   if (List->CurrentDisk != NULL)
01728   {
01729     Entry1 = List->CurrentDisk->ListEntry.Flink;
01730     while (Entry1 != &List->DiskListHead)
01731     {
01732       DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
01733 
01734       Entry2 = DiskEntry->PartListHead.Flink;
01735       while (Entry2 != &DiskEntry->PartListHead)
01736       {
01737         PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
01738 
01739 //        if (PartEntry->HidePartEntry == FALSE)
01740         {
01741           List->CurrentDisk = DiskEntry;
01742           List->CurrentPartition = PartEntry;
01743           List->CurrentPartitionNumber = 0;
01744           DrawPartitionList (List);
01745           return;
01746         }
01747 
01748         Entry2 = Entry2->Flink;
01749       }
01750 
01751       Entry1 = Entry1->Flink;
01752     }
01753   }
01754 }
01755 
01756 
01757 VOID
01758 ScrollUpPartitionList (PPARTLIST List)
01759 {
01760   PDISKENTRY DiskEntry;
01761   PPARTENTRY PartEntry;
01762   PLIST_ENTRY Entry1;
01763   PLIST_ENTRY Entry2;
01764   UCHAR i;
01765 
01766   /* Check for empty disks */
01767   if (IsListEmpty (&List->DiskListHead))
01768     return;
01769 
01770   /* check for previous usable entry on current disk */
01771   if (List->CurrentPartition != NULL)
01772   {
01773     Entry2 = &List->CurrentPartition->ListEntry;
01774     PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
01775 
01776     /* Check if we can move inside primary partitions */
01777     if (List->CurrentPartitionNumber > 0)
01778     {
01779         /* Find a previous partition */
01780         for (i = List->CurrentPartitionNumber - 1; i > 0; i--)
01781         {
01782             if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
01783                 break;
01784         }
01785 
01786         /* Move to it and return */
01787         List->CurrentPartitionNumber = i;
01788         DrawPartitionList (List);
01789         return;
01790     }
01791 
01792     /* Move to the previous entry */
01793     Entry2 = Entry2->Blink;
01794 
01795     while (Entry2 != &List->CurrentDisk->PartListHead)
01796     {
01797       PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
01798 
01799 //    if (PartEntry->HidePartEntry == FALSE)
01800       {
01801         List->CurrentPartition = PartEntry;
01802 
01803         /* Find last existing partition in the table */
01804         for (i = 3; i > 0; i--)
01805         {
01806             if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
01807                 break;
01808         }
01809 
01810         /* Move to it */
01811         List->CurrentPartitionNumber = i;
01812 
01813         /* Draw partition list and return */
01814         DrawPartitionList (List);
01815         return;
01816       }
01817       Entry2 = Entry2->Blink;
01818     }
01819   }
01820 
01821 
01822   /* check for last usable entry on previous disk */
01823   if (List->CurrentDisk != NULL)
01824   {
01825     Entry1 = List->CurrentDisk->ListEntry.Blink;
01826     while (Entry1 != &List->DiskListHead)
01827     {
01828       DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
01829 
01830       Entry2 = DiskEntry->PartListHead.Blink;
01831       while (Entry2 != &DiskEntry->PartListHead)
01832       {
01833         PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
01834 
01835 //        if (PartEntry->HidePartEntry == FALSE)
01836         {
01837           List->CurrentDisk = DiskEntry;
01838           List->CurrentPartition = PartEntry;
01839 
01840           /* Find last existing partition in the table */
01841           for (i = 3; i > 0; i--)
01842           {
01843             if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
01844               break;
01845           }
01846 
01847           /* Move to it */
01848           List->CurrentPartitionNumber = i;
01849 
01850           /* Draw partition list and return */
01851           DrawPartitionList (List);
01852           return;
01853         }
01854 
01855         Entry2 = Entry2->Blink;
01856       }
01857 
01858       Entry1 = Entry1->Blink;
01859     }
01860   }
01861 }
01862 
01863 
01864 static PPARTENTRY
01865 GetPrevPartitionedEntry (PDISKENTRY DiskEntry,
01866                          PPARTENTRY CurrentEntry)
01867 {
01868   PPARTENTRY PrevEntry;
01869   PLIST_ENTRY Entry;
01870 
01871   if (CurrentEntry->ListEntry.Blink == &DiskEntry->PartListHead)
01872     return NULL;
01873 
01874   Entry = CurrentEntry->ListEntry.Blink;
01875   while (Entry != &DiskEntry->PartListHead)
01876   {
01877     PrevEntry = CONTAINING_RECORD (Entry,
01878                                    PARTENTRY,
01879                                    ListEntry);
01880     if (PrevEntry->Unpartitioned == FALSE)
01881       return PrevEntry;
01882 
01883     Entry = Entry->Blink;
01884   }
01885 
01886   return NULL;
01887 }
01888 
01889 
01890 static PPARTENTRY
01891 GetNextPartitionedEntry (PDISKENTRY DiskEntry,
01892                          PPARTENTRY CurrentEntry)
01893 {
01894   PPARTENTRY NextEntry;
01895   PLIST_ENTRY Entry;
01896 
01897   if (CurrentEntry->ListEntry.Flink == &DiskEntry->PartListHead)
01898     return NULL;
01899 
01900   Entry = CurrentEntry->ListEntry.Flink;
01901   while (Entry != &DiskEntry->PartListHead)
01902   {
01903     NextEntry = CONTAINING_RECORD (Entry,
01904                                    PARTENTRY,
01905                                    ListEntry);
01906     if (NextEntry->Unpartitioned == FALSE)
01907       return NextEntry;
01908 
01909     Entry = Entry->Flink;
01910   }
01911 
01912   return NULL;
01913 }
01914 
01915 
01916 static PPARTENTRY
01917 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry,
01918                            PPARTENTRY PartEntry)
01919 {
01920   PPARTENTRY PrevPartEntry;
01921 
01922   if (PartEntry->ListEntry.Blink != &DiskEntry->PartListHead)
01923   {
01924     PrevPartEntry = CONTAINING_RECORD (PartEntry->ListEntry.Blink,
01925                                        PARTENTRY,
01926                                        ListEntry);
01927     if (PrevPartEntry->Unpartitioned == TRUE)
01928       return PrevPartEntry;
01929   }
01930 
01931   return NULL;
01932 }
01933 
01934 
01935 static PPARTENTRY
01936 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry,
01937                            PPARTENTRY PartEntry)
01938 {
01939   PPARTENTRY NextPartEntry;
01940 
01941   if (PartEntry->ListEntry.Flink != &DiskEntry->PartListHead)
01942   {
01943     NextPartEntry = CONTAINING_RECORD (PartEntry->ListEntry.Flink,
01944                                        PARTENTRY,
01945                                        ListEntry);
01946     if (NextPartEntry->Unpartitioned == TRUE)
01947       return NextPartEntry;
01948   }
01949 
01950   return NULL;
01951 }
01952 
01953 
01954 VOID
01955 CreateNewPartition (PPARTLIST List,
01956                     ULONGLONG PartitionSize,
01957                     BOOLEAN AutoCreate)
01958 {
01959   PDISKENTRY DiskEntry;
01960   PPARTENTRY PartEntry;
01961   PPARTENTRY PrevPartEntry;
01962   PPARTENTRY NextPartEntry;
01963   PPARTENTRY NewPartEntry;
01964 
01965   if (List == NULL ||
01966       List->CurrentDisk == NULL ||
01967       List->CurrentPartition == NULL ||
01968       List->CurrentPartition->Unpartitioned == FALSE)
01969   {
01970     return;
01971   }
01972 
01973   DiskEntry = List->CurrentDisk;
01974   PartEntry = List->CurrentPartition;
01975 
01976   if (AutoCreate == TRUE ||
01977       PartitionSize == PartEntry->UnpartitionedLength)
01978   {
01979     /* Convert current entry to 'new (unformatted)' */
01980     PartEntry->FormatState = Unformatted;
01981     PartEntry->PartInfo[0].StartingOffset.QuadPart =
01982       PartEntry->UnpartitionedOffset + DiskEntry->TrackSize;
01983     PartEntry->PartInfo[0].HiddenSectors = 
01984       (ULONG)(PartEntry->PartInfo[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
01985     PartEntry->PartInfo[0].PartitionLength.QuadPart =
01986       PartEntry->UnpartitionedLength - DiskEntry->TrackSize;
01987     PartEntry->PartInfo[0].PartitionType = PARTITION_ENTRY_UNUSED;
01988     PartEntry->PartInfo[0].BootIndicator = FALSE; /* FIXME */
01989     PartEntry->PartInfo[0].RewritePartition = TRUE;
01990     PartEntry->PartInfo[1].RewritePartition = TRUE;
01991     PartEntry->PartInfo[2].RewritePartition = TRUE;
01992     PartEntry->PartInfo[3].RewritePartition = TRUE;
01993 
01994     /* Get previous and next partition entries */
01995     PrevPartEntry = GetPrevPartitionedEntry (DiskEntry,
01996                                              PartEntry);
01997     NextPartEntry = GetNextPartitionedEntry (DiskEntry,
01998                                              PartEntry);
01999 
02000     if (PrevPartEntry != NULL && NextPartEntry != NULL)
02001     {
02002       /* Current entry is in the middle of the list */
02003 
02004       /* Copy previous container partition data to current entry */
02005       RtlCopyMemory (&PartEntry->PartInfo[1],
02006                      &PrevPartEntry->PartInfo[1],
02007                      sizeof(PARTITION_INFORMATION));
02008       PartEntry->PartInfo[1].RewritePartition = TRUE;
02009 
02010       /* Update previous container partition data */
02011 
02012       PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
02013         PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
02014       PrevPartEntry->PartInfo[1].HiddenSectors = 
02015         (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
02016 
02017       if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
02018       {
02019         /* Special case - previous partition is first partition */
02020         PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
02021           DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
02022       }
02023       else
02024       {
02025         PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
02026           PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
02027       }
02028 
02029       PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
02030     }
02031     else if (PrevPartEntry == NULL && NextPartEntry != NULL)
02032     {
02033       /* Current entry is the first entry */
02034       return;
02035     }
02036     else if (PrevPartEntry != NULL && NextPartEntry == NULL)
02037     {
02038       /* Current entry is the last entry */
02039 
02040       PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
02041         PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
02042       PrevPartEntry->PartInfo[1].HiddenSectors = 
02043         (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
02044 
02045       if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
02046       {
02047         /* Special case - previous partition is first partition */
02048         PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
02049           DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
02050       }
02051       else
02052       {
02053         PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
02054           PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
02055       }
02056 
02057       if ((PartEntry->PartInfo[1].StartingOffset.QuadPart +
02058            PartEntry->PartInfo[1].PartitionLength.QuadPart) <
02059           (1024LL * 255LL * 63LL * 512LL))
02060       {
02061         PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
02062       }
02063       else
02064       {
02065         PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED;
02066       }
02067 
02068       PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
02069       PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
02070     }
02071 
02072     PartEntry->AutoCreate = AutoCreate;
02073     PartEntry->New = TRUE;
02074     PartEntry->Unpartitioned = FALSE;
02075     PartEntry->UnpartitionedOffset = 0ULL;
02076     PartEntry->UnpartitionedLength = 0ULL;
02077   }
02078   else
02079   {
02080     /* Insert an initialize a new partition entry */
02081     NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
02082                                                 0,
02083                                                 sizeof(PARTENTRY));
02084     if (NewPartEntry == NULL)
02085       return;
02086 
02087     RtlZeroMemory (NewPartEntry,
02088                    sizeof(PARTENTRY));
02089 
02090     /* Insert the new entry into the list */
02091     InsertTailList (&PartEntry->ListEntry,
02092                     &NewPartEntry->ListEntry);
02093 
02094     NewPartEntry->New = TRUE;
02095 
02096     NewPartEntry->FormatState = Unformatted;
02097     NewPartEntry->PartInfo[0].StartingOffset.QuadPart =
02098       PartEntry->UnpartitionedOffset + DiskEntry->TrackSize;
02099     NewPartEntry->PartInfo[0].HiddenSectors = 
02100       (ULONG)(NewPartEntry->PartInfo[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
02101     NewPartEntry->PartInfo[0].PartitionLength.QuadPart =
02102       PartitionSize - DiskEntry->TrackSize;
02103     NewPartEntry->PartInfo[0].PartitionType = PARTITION_ENTRY_UNUSED;
02104     NewPartEntry->PartInfo[0].BootIndicator = FALSE; /* FIXME */
02105     NewPartEntry->PartInfo[0].RewritePartition = TRUE;
02106     NewPartEntry->PartInfo[1].RewritePartition = TRUE;
02107     NewPartEntry->PartInfo[2].RewritePartition = TRUE;
02108     NewPartEntry->PartInfo[3].RewritePartition = TRUE;
02109 
02110     /* Get previous and next partition entries */
02111     PrevPartEntry = GetPrevPartitionedEntry (DiskEntry,
02112                                              NewPartEntry);
02113     NextPartEntry = GetNextPartitionedEntry (DiskEntry,
02114                                              NewPartEntry);
02115 
02116     if (PrevPartEntry != NULL && NextPartEntry != NULL)
02117     {
02118       /* Current entry is in the middle of the list */
02119 
02120       /* Copy previous container partition data to current entry */
02121       RtlCopyMemory (&NewPartEntry->PartInfo[1],
02122                      &PrevPartEntry->PartInfo[1],
02123                      sizeof(PARTITION_INFORMATION));
02124       NewPartEntry->PartInfo[1].RewritePartition = TRUE;
02125 
02126       /* Update previous container partition data */
02127 
02128       PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
02129         NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
02130       PrevPartEntry->PartInfo[1].HiddenSectors = 
02131         (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
02132 
02133       if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
02134       {
02135         /* Special case - previous partition is first partition */
02136         PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
02137           DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
02138       }
02139       else
02140       {
02141         PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
02142           NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
02143       }
02144 
02145       PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
02146     }
02147     else if (PrevPartEntry == NULL && NextPartEntry != NULL)
02148     {
02149       /* Current entry is the first entry */
02150       return;
02151     }
02152     else if (PrevPartEntry != NULL && NextPartEntry == NULL)
02153     {
02154       /* Current entry is the last entry */
02155 
02156       PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
02157         NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
02158       PrevPartEntry->PartInfo[1].HiddenSectors = 
02159         (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
02160 
02161       if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
02162       {
02163         /* Special case - previous partition is first partition */
02164         PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
02165           DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
02166       }
02167       else
02168       {
02169         PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
02170           NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
02171       }
02172 
02173       if ((PartEntry->PartInfo[1].StartingOffset.QuadPart +
02174            PartEntry->PartInfo[1].PartitionLength.QuadPart) <
02175           (1024LL * 255LL * 63LL * 512LL))
02176       {
02177         PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
02178       }
02179       else
02180       {
02181         PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED;
02182       }
02183 
02184       PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
02185       PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
02186     }
02187 
02188     /* Update offset and size of the remaining unpartitioned disk space */
02189     PartEntry->UnpartitionedOffset += PartitionSize;
02190     PartEntry->UnpartitionedLength -= PartitionSize;
02191   }
02192 
02193   DiskEntry->Modified = TRUE;
02194 
02195   UpdatePartitionNumbers (DiskEntry);
02196 
02197   AssignDriverLetters (List);
02198 }
02199 
02200 
02201 VOID
02202 DeleteCurrentPartition (PPARTLIST List)
02203 {
02204   PDISKENTRY DiskEntry;
02205   PPARTENTRY PartEntry;
02206   PPARTENTRY PrevPartEntry;
02207   PPARTENTRY NextPartEntry;
02208 
02209   if (List == NULL ||
02210       List->CurrentDisk == NULL ||
02211       List->CurrentPartition == NULL ||
02212       List->CurrentPartition->Unpartitioned == TRUE)
02213   {
02214     return;
02215   }
02216 
02217   DiskEntry = List->CurrentDisk;
02218   PartEntry = List->CurrentPartition;
02219 
02220   /* Adjust container partition entries */
02221 
02222   /* Get previous and next partition entries */
02223   PrevPartEntry = GetPrevPartitionedEntry (DiskEntry,
02224                                            PartEntry);
02225   NextPartEntry = GetNextPartitionedEntry (DiskEntry,
02226                                            PartEntry);
02227 
02228   if (PrevPartEntry != NULL && NextPartEntry != NULL)
02229   {
02230     /* Current entry is in the middle of the list */
02231 
02232     /*
02233      * The first extended partition can not be deleted
02234      * as long as other extended partitions are present.
02235      */
02236     if (PrevPartEntry->ListEntry.Blink == &DiskEntry->PartListHead)
02237       return;
02238 
02239     /* Copy previous container partition data to current entry */
02240     RtlCopyMemory (&PrevPartEntry->PartInfo[1],
02241                    &PartEntry->PartInfo[1],
02242                    sizeof(PARTITION_INFORMATION));
02243     PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
02244   }
02245   else if (PrevPartEntry == NULL && NextPartEntry != NULL)
02246   {
02247     /*
02248      * A primary partition can not be deleted as long as
02249      * extended partitions are present.
02250      */
02251     return;
02252   }
02253   else if (PrevPartEntry != NULL && NextPartEntry == NULL)
02254   {
02255     /* Current entry is the last entry */
02256     RtlZeroMemory (&PrevPartEntry->PartInfo[1],
02257                    sizeof(PARTITION_INFORMATION));
02258     PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
02259   }
02260 
02261 
02262   /* Adjust unpartitioned disk space entries */
02263 
02264   /* Get pointer to previous and next unpartitioned entries */
02265   PrevPartEntry = GetPrevUnpartitionedEntry (DiskEntry,
02266                                              PartEntry);
02267 
02268   NextPartEntry = GetNextUnpartitionedEntry (DiskEntry,
02269                                              PartEntry);
02270 
02271   if (PrevPartEntry != NULL && NextPartEntry != NULL)
02272   {
02273     /* Merge previous, current and next unpartitioned entry */
02274 
02275     /* Adjust the previous entries length */
02276     PrevPartEntry->UnpartitionedLength +=
02277       (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize +
02278       NextPartEntry->UnpartitionedLength);
02279 
02280     /* Remove the current entry */
02281     RemoveEntryList (&PartEntry->ListEntry);
02282     RtlFreeHeap (ProcessHeap,
02283                  0,
02284                  PartEntry);
02285 
02286     /* Remove the next entry */
02287     RemoveEntryList (&NextPartEntry->ListEntry);
02288     RtlFreeHeap (ProcessHeap,
02289                  0,
02290     NextPartEntry);
02291 
02292     /* Update current partition */
02293     List->CurrentPartition = PrevPartEntry;
02294   }
02295   else if (PrevPartEntry != NULL && NextPartEntry == NULL)
02296   {
02297     /* Merge current and previous unpartitioned entry */
02298 
02299     /* Adjust the previous entries length */
02300     PrevPartEntry->UnpartitionedLength +=
02301       (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
02302 
02303     /* Remove the current entry */
02304     RemoveEntryList (&PartEntry->ListEntry);
02305     RtlFreeHeap (ProcessHeap,
02306                  0,
02307                  PartEntry);
02308 
02309     /* Update current partition */
02310     List->CurrentPartition = PrevPartEntry;
02311   }
02312   else if (PrevPartEntry == NULL && NextPartEntry != NULL)
02313   {
02314     /* Merge current and next unpartitioned entry */
02315 
02316     /* Adjust the next entries offset and length */
02317     NextPartEntry->UnpartitionedOffset =
02318       PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
02319     NextPartEntry->UnpartitionedLength +=
02320       (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
02321 
02322     /* Remove the current entry */
02323     RemoveEntryList (&PartEntry->ListEntry);
02324     RtlFreeHeap (ProcessHeap,
02325                  0,
02326                  PartEntry);
02327 
02328     /* Update current partition */
02329     List->CurrentPartition = NextPartEntry;
02330   }
02331   else
02332   {
02333     /* Nothing to merge but change current entry */
02334     PartEntry->New = FALSE;
02335     PartEntry->Unpartitioned = TRUE;
02336     PartEntry->UnpartitionedOffset =
02337       PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
02338     PartEntry->UnpartitionedLength =
02339       PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
02340 
02341     /* Wipe the partition table */
02342     RtlZeroMemory (&PartEntry->PartInfo,
02343                    sizeof(PartEntry->PartInfo));
02344   }
02345 
02346   DiskEntry->Modified = TRUE;
02347 
02348   UpdatePartitionNumbers (DiskEntry);
02349 
02350   AssignDriverLetters (List);
02351 }
02352 
02353 
02354 VOID
02355 CheckActiveBootPartition (PPARTLIST List)
02356 {
02357   PDISKENTRY DiskEntry;
02358   PPARTENTRY PartEntry;
02359   PLIST_ENTRY ListEntry;
02360   UCHAR i;
02361 
02362   /* Check for empty disk list */
02363   if (IsListEmpty (&List->DiskListHead))
02364   {
02365     List->ActiveBootDisk = NULL;
02366     List->ActiveBootPartition = NULL;
02367     List->ActiveBootPartitionNumber = 0;
02368     return;
02369   }
02370 
02371 #if 0
02372   if (List->ActiveBootDisk != NULL &&
02373       List->ActiveBootPartition != NULL)
02374   {
02375     /* We already have an active boot partition */
02376     return;
02377   }
02378 #endif
02379 
02380   /* Choose the currently selected disk */
02381   DiskEntry = List->CurrentDisk;
02382 
02383   /* Check for empty partition list */
02384   if (IsListEmpty (&DiskEntry->PartListHead))
02385   {
02386     List->ActiveBootDisk = NULL;
02387     List->ActiveBootPartition = NULL;
02388     List->ActiveBootPartitionNumber = 0;
02389     return;
02390   }
02391 
02392   PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink,
02393                                  PARTENTRY,
02394                                  ListEntry);
02395 
02396   /* Set active boot partition */
02397   if ((DiskEntry->NewDisk == TRUE) ||
02398       (PartEntry->PartInfo[0].BootIndicator == FALSE &&
02399        PartEntry->PartInfo[1].BootIndicator == FALSE &&
02400        PartEntry->PartInfo[2].BootIndicator == FALSE &&
02401        PartEntry->PartInfo[3].BootIndicator == FALSE))
02402   {
02403     PartEntry->PartInfo[0].BootIndicator = TRUE;
02404     PartEntry->PartInfo[0].RewritePartition = TRUE;
02405     DiskEntry->Modified = TRUE;
02406 
02407     /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
02408     List->ActiveBootDisk = DiskEntry;
02409     List->ActiveBootPartition = PartEntry;
02410     List->ActiveBootPartitionNumber = 0;
02411 
02412     return;
02413   }
02414 
02415   /* Disk is not new, scan all partitions to find a bootable one */
02416   List->ActiveBootDisk = NULL;
02417   List->ActiveBootPartition = NULL;
02418   List->ActiveBootPartitionNumber = 0;
02419 
02420   ListEntry = DiskEntry->PartListHead.Flink;
02421   while (ListEntry != &DiskEntry->PartListHead)
02422   {
02423     PartEntry = CONTAINING_RECORD(ListEntry,
02424                                   PARTENTRY,
02425                                   ListEntry);
02426 
02427     /* Check if it's partitioned */
02428     if (!PartEntry->Unpartitioned)
02429     {
02430       /* Go through all of its 4 partitions */
02431       for (i=0; i<4; i++)
02432       {
02433         if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED &&
02434             PartEntry->PartInfo[i].BootIndicator)
02435         {
02436           /* Yes, we found it */
02437           List->ActiveBootDisk = DiskEntry;
02438           List->ActiveBootPartition = PartEntry;
02439           List->ActiveBootPartitionNumber = i;
02440 
02441           DPRINT("Found bootable partition disk %d, drive letter %c\n",
02442               DiskEntry->DiskNumber, PartEntry->DriveLetter[i]);
02443 
02444           break;
02445         }
02446       }
02447     }
02448     /* Go to the next one */
02449     ListEntry = ListEntry->Flink;
02450   }
02451 }
02452 
02453 
02454 BOOLEAN
02455 CheckForLinuxFdiskPartitions (PPARTLIST List)
02456 {
02457   PDISKENTRY DiskEntry;
02458   PPARTENTRY PartEntry;
02459   PLIST_ENTRY Entry1;
02460   PLIST_ENTRY Entry2;
02461   ULONG PartitionCount;
02462   ULONG i;
02463 
02464   Entry1 = List->DiskListHead.Flink;
02465   while (Entry1 != &List->DiskListHead)
02466   {
02467     DiskEntry = CONTAINING_RECORD (Entry1,
02468                                    DISKENTRY,
02469                                    ListEntry);
02470 
02471     Entry2 = DiskEntry->PartListHead.Flink;
02472     while (Entry2 != &DiskEntry->PartListHead)
02473     {
02474       PartEntry = CONTAINING_RECORD (Entry2,
02475                                      PARTENTRY,
02476                                      ListEntry);
02477 
02478       if (PartEntry->Unpartitioned == FALSE)
02479       {
02480         PartitionCount = 0;
02481 
02482         for (i = 0; i < 4; i++)
02483         {
02484           if (!IsContainerPartition (PartEntry->PartInfo[i].PartitionType) &&
02485               PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
02486           {
02487             PartitionCount++;
02488           }
02489         }
02490 
02491         if (PartitionCount > 1)
02492         {
02493           return TRUE;
02494         }
02495       }
02496 
02497       Entry2 = Entry2->Flink;
02498     }
02499 
02500     Entry1 = Entry1->Flink;
02501   }
02502 
02503   return FALSE;
02504 }
02505 
02506 
02507 BOOLEAN
02508 WritePartitionsToDisk (PPARTLIST List)
02509 {
02510   PDRIVE_LAYOUT_INFORMATION DriveLayout;
02511   OBJECT_ATTRIBUTES ObjectAttributes;
02512   IO_STATUS_BLOCK Iosb;
02513   WCHAR DstPath[MAX_PATH];
02514   UNICODE_STRING Name;
02515   HANDLE FileHandle;
02516   PDISKENTRY DiskEntry1;
02517   PDISKENTRY DiskEntry2;
02518   PPARTENTRY PartEntry;
02519   PLIST_ENTRY Entry1;
02520   PLIST_ENTRY Entry2;
02521   ULONG PartitionCount;
02522   ULONG DriveLayoutSize;
02523   ULONG Index;
02524   NTSTATUS Status;
02525 
02526   if (List == NULL)
02527   {
02528     return TRUE;
02529   }
02530 
02531   Entry1 = List->DiskListHead.Flink;
02532   while (Entry1 != &List->DiskListHead)
02533   {
02534     DiskEntry1 = CONTAINING_RECORD (Entry1,
02535                                     DISKENTRY,
02536                                     ListEntry);
02537 
02538     if (DiskEntry1->Modified == TRUE)
02539     {
02540       /* Count partitioned entries */
02541       PartitionCount = 0;
02542       Entry2 = DiskEntry1->PartListHead.Flink;
02543       while (Entry2 != &DiskEntry1->PartListHead)
02544       {
02545         PartEntry = CONTAINING_RECORD (Entry2,
02546                                        PARTENTRY,
02547                                        ListEntry);
02548         if (PartEntry->Unpartitioned == FALSE)
02549         {
02550           PartitionCount += 4;
02551         }
02552 
02553         Entry2 = Entry2->Flink;
02554       }
02555       if (PartitionCount == 0)
02556       {
02557         DriveLayoutSize = sizeof (DRIVE_LAYOUT_INFORMATION) +
02558           ((4 - 1) * sizeof (PARTITION_INFORMATION));
02559       }
02560       else
02561       {
02562         DriveLayoutSize = sizeof (DRIVE_LAYOUT_INFORMATION) +
02563           ((PartitionCount - 1) * sizeof (PARTITION_INFORMATION));
02564       }
02565       DriveLayout = (PDRIVE_LAYOUT_INFORMATION)RtlAllocateHeap (ProcessHeap,
02566                                                                 0,
02567                                                                 DriveLayoutSize);
02568       if (DriveLayout == NULL)
02569       {
02570         DPRINT1 ("RtlAllocateHeap() failed\n");
02571         return FALSE;
02572       }
02573 
02574       RtlZeroMemory (DriveLayout,
02575                      DriveLayoutSize);
02576 
02577       if (PartitionCount == 0)
02578       {
02579         /* delete all partitions in the mbr */
02580         DriveLayout->PartitionCount = 4;
02581         for (Index = 0; Index < 4; Index++)
02582         {
02583           DriveLayout->PartitionEntry[Index].RewritePartition = TRUE;
02584         }
02585       }
02586       else
02587       {
02588         DriveLayout->PartitionCount = PartitionCount;
02589 
02590         Index = 0;
02591         Entry2 = DiskEntry1->PartListHead.Flink;
02592         while (Entry2 != &DiskEntry1->PartListHead)
02593         {
02594           PartEntry = CONTAINING_RECORD (Entry2,
02595                                          PARTENTRY,
02596                                          ListEntry);
02597           if (PartEntry->Unpartitioned == FALSE)
02598           {
02599             RtlCopyMemory (&DriveLayout->PartitionEntry[Index],
02600                            &PartEntry->PartInfo[0],
02601                            4 * sizeof (PARTITION_INFORMATION));
02602             Index += 4;
02603           }
02604 
02605           Entry2 = Entry2->Flink;
02606         }
02607       }
02608       if (DiskEntry1->Signature == 0)
02609       {
02610         LARGE_INTEGER SystemTime;
02611         TIME_FIELDS TimeFields;
02612         PUCHAR Buffer;
02613         Buffer = (PUCHAR)&DiskEntry1->Signature;
02614 
02615         while (1)
02616         {
02617           NtQuerySystemTime (&SystemTime);
02618           RtlTimeToTimeFields (&SystemTime, &TimeFields);
02619 
02620           Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
02621           Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
02622           Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
02623           Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
02624 
02625           if (DiskEntry1->Signature == 0)
02626           {
02627             continue;
02628           }
02629 
02630           /* check if the signature already exist */
02631           /* FIXME:
02632            *   Check also signatures from disks, which are
02633            *   not visible (bootable) by the bios.
02634            */
02635           Entry2 = List->DiskListHead.Flink;
02636           while (Entry2 != &List->DiskListHead)
02637           {
02638             DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
02639             if (DiskEntry1 != DiskEntry2 &&
02640                 DiskEntry1->Signature == DiskEntry2->Signature)
02641             {
02642               break;
02643             }
02644             Entry2 = Entry2->Flink;
02645           }
02646           if (Entry2 == &List->DiskListHead)
02647           {
02648             break;
02649           }
02650         }
02651 
02652         /* set one partition entry to dirty, this will update the signature */
02653         DriveLayout->PartitionEntry[0].RewritePartition = TRUE;
02654 
02655       }
02656 
02657       DriveLayout->Signature = DiskEntry1->Signature;
02658 
02659 
02660       swprintf (DstPath,
02661                 L"\\Device\\Harddisk%d\\Partition0",
02662                 DiskEntry1->DiskNumber);
02663       RtlInitUnicodeString (&Name,
02664                             DstPath);
02665       InitializeObjectAttributes (&ObjectAttributes,
02666                                   &Name,
02667                                   0,
02668                                   NULL,
02669                                   NULL);
02670 
02671       Status = NtOpenFile (&FileHandle,
02672                            FILE_ALL_ACCESS,
02673                            &ObjectAttributes,
02674                            &Iosb,
02675                            0,
02676                            FILE_SYNCHRONOUS_IO_NONALERT);
02677 
02678       if (!NT_SUCCESS (Status))
02679       {
02680         DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status);
02681         return FALSE;
02682       }
02683 
02684       Status = NtDeviceIoControlFile (FileHandle,
02685                                       NULL,
02686                                       NULL,
02687                                       NULL,
02688                                       &Iosb,
02689                                       IOCTL_DISK_SET_DRIVE_LAYOUT,
02690                                       DriveLayout,
02691                                       DriveLayoutSize,
02692                                       NULL,
02693                                       0);
02694       if (!NT_SUCCESS (Status))
02695       {
02696         DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status);
02697         NtClose (FileHandle);
02698         return FALSE;
02699       }
02700 
02701       RtlFreeHeap (ProcessHeap,
02702                    0,
02703                    DriveLayout);
02704 
02705       NtClose (FileHandle);
02706     }
02707 
02708     Entry1 = Entry1->Flink;
02709   }
02710 
02711   return TRUE;
02712 }
02713 
02714 BOOL SetMountedDeviceValues(PPARTLIST List)
02715 {
02716   PLIST_ENTRY Entry1, Entry2;
02717   PDISKENTRY DiskEntry;
02718   PPARTENTRY PartEntry;
02719   UCHAR i;
02720 
02721   if (List == NULL)
02722   {
02723     return FALSE;
02724   }
02725 
02726   Entry1 = List->DiskListHead.Flink;
02727   while (Entry1 != &List->DiskListHead)
02728   {
02729     DiskEntry = CONTAINING_RECORD (Entry1,
02730                                    DISKENTRY,
02731                                    ListEntry);
02732 
02733     Entry2 = DiskEntry->PartListHead.Flink;
02734     while (Entry2 != &DiskEntry->PartListHead)
02735     {
02736       PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
02737       if (!PartEntry->Unpartitioned)
02738       {
02739         for (i=0; i<4; i++)
02740         {
02741           if (PartEntry->DriveLetter[i])
02742           {
02743             if (!SetMountedDeviceValue(PartEntry->DriveLetter[i], DiskEntry->Signature, PartEntry->PartInfo[i].StartingOffset))
02744             {
02745               return FALSE;
02746             }
02747           }
02748         }
02749       }
02750       Entry2 = Entry2->Flink;
02751     }
02752     Entry1 = Entry1->Flink;
02753   }
02754   return TRUE;
02755 }
02756 
02757 
02758 
02759 /* EOF */

Generated on Fri May 25 2012 04:16:26 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.