- Do only allow to install reactos on disks which are visible by the bios.
[reactos.git] / reactos / subsys / system / usetup / partlist.c
index 394ae95..3de2448 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2002, 2003 ReactOS Team
+ *  Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: partlist.c,v 1.22 2003/08/25 11:56:07 ekohl Exp $
+/* $Id$
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS text-mode setup
  * FILE:            subsys/system/usetup/partlist.c
  * PURPOSE:         Partition list functions
  * PROGRAMMER:      Eric Kohl
  *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *                  Hartmut Birr
  */
 
-#include <ddk/ntddk.h>
-#include <ddk/ntddscsi.h>
-
-#include <ntdll/rtl.h>
-
-#include <ntos/minmax.h>
-
-#include "usetup.h"
-#include "console.h"
-#include "partlist.h"
-#include "drivesup.h"
+#include <usetup.h>
 
+#define NDEBUG
+#include <debug.h>
 
 /* FUNCTIONS ****************************************************************/
 
@@ -429,6 +422,128 @@ ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry)
     }
 }
 
+NTSTATUS
+STDCALL
+DiskQueryRoutine(PWSTR ValueName,
+                 ULONG ValueType,
+                 PVOID ValueData,
+                 ULONG ValueLength,
+                 PVOID Context,
+                 PVOID EntryContext)
+{
+  PLIST_ENTRY ListHead = (PLIST_ENTRY)Context;
+  PULONG GlobalDiskCount = (PULONG)EntryContext;
+  PBIOSDISKENTRY BiosDiskEntry;
+  UNICODE_STRING NameU;
+
+  if (ValueType == REG_SZ &&
+        ValueLength == 20 * sizeof(WCHAR))
+    {
+      BiosDiskEntry = RtlAllocateHeap(ProcessHeap, 0, sizeof(BIOSDISKENTRY));
+      if (BiosDiskEntry == NULL)
+        {
+            return STATUS_NO_MEMORY;
+        }
+      BiosDiskEntry->DiskNumber = (*GlobalDiskCount)++;
+
+      NameU.Buffer = (PWCHAR)ValueData;
+      NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
+      RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
+
+      NameU.Buffer = (PWCHAR)ValueData + 9;
+      RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
+
+      InsertTailList(ListHead, &BiosDiskEntry->ListEntry);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+#define ROOT_NAME   L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
+
+STATIC VOID
+EnumerateBiosDiskEntries(PPARTLIST PartList)
+{
+  RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+  WCHAR Name[100];
+  ULONG AdapterCount;
+  ULONG ControllerCount;
+  ULONG DiskCount;
+  NTSTATUS Status;
+  ULONG GlobalDiskCount=0;
+
+  memset(QueryTable, 0, sizeof(QueryTable));
+  QueryTable[0].Name = L"Identifier";
+  QueryTable[0].QueryRoutine = DiskQueryRoutine;
+  QueryTable[0].EntryContext = (PVOID)&GlobalDiskCount;
+
+  AdapterCount = 0;
+  while (1)
+    {
+      swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
+      Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+                                      Name,
+                                      &QueryTable[1],
+                                      NULL,
+                                      NULL);
+      if (!NT_SUCCESS(Status))
+        {
+          break;
+        }
+        
+      swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
+      Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+                                      Name,
+                                      &QueryTable[1],
+                                      NULL,
+                                      NULL);
+      if (NT_SUCCESS(Status))
+        {
+          ControllerCount = 0;
+          while (1)
+            {
+              swprintf(Name, L"%s\\%lu\\DiskController\\%lu", ROOT_NAME, AdapterCount, ControllerCount);
+              Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+                                              Name,
+                                              &QueryTable[1],
+                                              NULL,
+                                              NULL);
+              if (!NT_SUCCESS(Status))
+                {
+                  break;
+                }
+                
+              swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral", ROOT_NAME, AdapterCount, ControllerCount);
+              Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+                                              Name,
+                                              &QueryTable[1],
+                                              NULL,
+                                              NULL);
+              if (NT_SUCCESS(Status))
+                {
+                  DiskCount = 0;
+                  while (1)
+                    {
+                      swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
+                      Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+                                                      Name,
+                                                      QueryTable,
+                                                      (PVOID)&PartList->BiosDiskListHead,
+                                                      NULL);
+                      if (!NT_SUCCESS(Status))
+                        {
+                          break;
+                        }
+                      DiskCount++;
+                    }
+                }
+              ControllerCount++;
+            }
+        }
+      AdapterCount++;
+    }
+}
 
 static VOID
 AddDiskToList (HANDLE FileHandle,
@@ -441,6 +556,15 @@ AddDiskToList (HANDLE FileHandle,
   PDISKENTRY DiskEntry;
   IO_STATUS_BLOCK Iosb;
   NTSTATUS Status;
+  PPARTITION_SECTOR Mbr;
+  PULONG Buffer;
+  LARGE_INTEGER FileOffset;
+  WCHAR Identifier[20];
+  ULONG Checksum;
+  ULONG Signature;
+  ULONG i;
+  PLIST_ENTRY ListEntry;
+  PBIOSDISKENTRY BiosDiskEntry;
 
   Status = NtDeviceIoControlFile (FileHandle,
                                  NULL,
@@ -477,6 +601,51 @@ AddDiskToList (HANDLE FileHandle,
       return;
     }
 
+  Mbr = RtlAllocateHeap(ProcessHeap,
+                        0,
+                        DiskGeometry.BytesPerSector);
+
+  if (Mbr == NULL)
+    {
+      return;
+    }
+  
+  FileOffset.QuadPart = 0;
+  Status = NtReadFile(FileHandle,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &Iosb,
+                      (PVOID)Mbr,
+                      DiskGeometry.BytesPerSector,
+                      &FileOffset,
+                      NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      RtlFreeHeap(ProcessHeap,
+                  0,
+                  Mbr);
+      DPRINT1("NtReadFile failed, status=%x\n", Status);
+      return;
+    }
+  Signature = Mbr->Signature;
+
+  /* Calculate the MBR checksum */
+  Checksum = 0;
+  Buffer = (PULONG)Mbr;
+  for (i = 0; i < 128; i++)
+    {
+      Checksum += Buffer[i];
+    }
+  Checksum = ~Checksum + 1;
+
+  RtlFreeHeap (ProcessHeap,
+              0,
+              Mbr);
+
+  swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
+  DPRINT("Identifier: %S\n", Identifier);
+
   DiskEntry = (PDISKENTRY)RtlAllocateHeap (ProcessHeap,
                                           0,
                                           sizeof(DISKENTRY));
@@ -485,6 +654,35 @@ AddDiskToList (HANDLE FileHandle,
       return;
     }
 
+  DiskEntry->Checksum = Checksum;
+  DiskEntry->Signature = Signature;
+  DiskEntry->BiosFound = FALSE;
+
+  ListEntry = List->BiosDiskListHead.Flink;
+  while(ListEntry != &List->BiosDiskListHead)
+  {
+     BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
+     if (BiosDiskEntry->Signature == Signature &&
+         BiosDiskEntry->Checksum == Checksum)
+     {
+        if (!DiskEntry->BiosFound)
+        {
+           DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
+           DiskEntry->BiosFound = TRUE;
+        }
+        else
+        {
+        }
+     }
+     ListEntry = ListEntry->Flink;
+  }
+
+  if (!DiskEntry->BiosFound)
+  {
+     RtlFreeHeap(ProcessHeap, 0, DiskEntry);
+     return;
+  }
+
   InitializeListHead (&DiskEntry->PartListHead);
 
   DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
@@ -517,8 +715,7 @@ AddDiskToList (HANDLE FileHandle,
 
   GetDriverName (DiskEntry);
 
-  InsertTailList (&List->DiskListHead,
-                 &DiskEntry->ListEntry);
+  InsertAscendingList(&List->DiskListHead, DISKENTRY, ListEntry, DiskEntry, BiosDiskNumber);
 
   LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap (ProcessHeap,
                                                             0,
@@ -567,7 +764,6 @@ CreatePartitionList (SHORT Left,
   PPARTLIST List;
   OBJECT_ATTRIBUTES ObjectAttributes;
   SYSTEM_DEVICE_INFORMATION Sdi;
-  DISK_GEOMETRY DiskGeometry;
   IO_STATUS_BLOCK Iosb;
   ULONG ReturnSize;
   NTSTATUS Status;
@@ -596,6 +792,9 @@ CreatePartitionList (SHORT Left,
   List->CurrentPartition = NULL;
 
   InitializeListHead (&List->DiskListHead);
+  InitializeListHead (&List->BiosDiskListHead);
+
+  EnumerateBiosDiskEntries(List);
 
   Status = NtQuerySystemInformation (SystemDeviceInformation,
                                     &Sdi,
@@ -676,6 +875,7 @@ VOID
 DestroyPartitionList (PPARTLIST List)
 {
   PDISKENTRY DiskEntry;
+  PBIOSDISKENTRY BiosDiskEntry;
   PPARTENTRY PartEntry;
   PLIST_ENTRY Entry;
 
@@ -703,6 +903,15 @@ DestroyPartitionList (PPARTLIST List)
       RtlFreeHeap (ProcessHeap, 0, DiskEntry);
     }
 
+  /* release the bios disk info */
+  while(!IsListEmpty(&List->BiosDiskListHead))
+    {
+      Entry = RemoveHeadList(&List->BiosDiskListHead);
+      BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
+      
+      RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
+    }
+
   /* Release list head */
   RtlFreeHeap (ProcessHeap, 0, List);
 }
@@ -717,24 +926,24 @@ PrintEmptyLine (PPARTLIST List)
   USHORT Height;
 
   Width = List->Right - List->Left - 1;
-  Height = List->Bottom - List->Top - 1;
+  Height = List->Bottom - List->Top - 2;
 
-  if (List->Line < 0 || List->Line > Height)
-    return;
 
   coPos.X = List->Left + 1;
   coPos.Y = List->Top + 1 + List->Line;
 
-  FillConsoleOutputAttribute (0x17,
-                             Width,
-                             coPos,
-                             &Written);
-
-  FillConsoleOutputCharacter (' ',
-                             Width,
-                             coPos,
-                             &Written);
-
+  if (List->Line >= 0 && List->Line <= Height)
+    {
+      FillConsoleOutputAttribute (0x17,
+                                 Width,
+                                 coPos,
+                                 &Written);
+
+      FillConsoleOutputCharacter (' ',
+                                 Width,
+                                 coPos,
+                                 &Written);
+    }
   List->Line++;
 }
 
@@ -756,10 +965,8 @@ PrintPartitionData (PPARTLIST List,
   PCHAR PartType;
 
   Width = List->Right - List->Left - 1;
-  Height = List->Bottom - List->Top - 1;
+  Height = List->Bottom - List->Top - 2;
 
-  if (List->Line < 0 || List->Line > Height)
-    return;
 
   coPos.X = List->Left + 1;
   coPos.Y = List->Top + 1 + List->Line;
@@ -819,14 +1026,14 @@ PrintPartitionData (PPARTLIST List,
        }
 
 #if 0
-      if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0x280000000ULL) /* 10 GB */
+      if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
        {
          PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 29)) >> 30;
          Unit = "GB";
        }
       else
 #endif
-      if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0xA00000ULL) /* 10 MB */
+      if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0xA00000LL) /* 10 MB */
        {
          PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 19)) >> 20;
          Unit = "MB";
@@ -840,7 +1047,7 @@ PrintPartitionData (PPARTLIST List,
       if (PartType == NULL)
        {
          sprintf (LineBuffer,
-                  "%c%c  Type %-3lu                         %6I64u %s",
+                  "%c%c  Type %-3u                         %6I64u %s",
                   (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
                   (PartEntry->DriveLetter == 0) ? '-' : ':',
                   PartEntry->PartInfo[0].PartitionType,
@@ -862,24 +1069,30 @@ PrintPartitionData (PPARTLIST List,
   Attribute = (List->CurrentDisk == DiskEntry &&
               List->CurrentPartition == PartEntry) ? 0x71 : 0x17;
 
-  FillConsoleOutputCharacter (' ',
-                             Width,
-                             coPos,
-                             &Written);
-
+  if (List->Line >= 0 && List->Line <= Height)
+    {
+      FillConsoleOutputCharacter (' ',
+                                 Width,
+                                 coPos,
+                                 &Written);
+    }
   coPos.X += 4;
   Width -= 8;
-  FillConsoleOutputAttribute (Attribute,
-                             Width,
-                             coPos,
-                             &Written);
-
+  if (List->Line >= 0 && List->Line <= Height)
+    {
+      FillConsoleOutputAttribute (Attribute,
+                                 Width,
+                                 coPos,
+                                 &Written);
+    }
   coPos.X++;
   Width -= 2;
-  WriteConsoleOutputCharacters (LineBuffer,
-                               min (strlen (LineBuffer), Width),
-                               coPos);
-
+  if (List->Line >= 0 && List->Line <= Height)
+    {
+      WriteConsoleOutputCharacters (LineBuffer,
+                                   min (strlen (LineBuffer), Width),
+                                   coPos);
+    }
   List->Line++;
 }
 
@@ -897,13 +1110,10 @@ PrintDiskData (PPARTLIST List,
   USHORT Height;
   ULONGLONG DiskSize;
   PCHAR Unit;
-  SHORT PartIndex;
 
   Width = List->Right - List->Left - 1;
-  Height = List->Bottom - List->Top - 1;
+  Height = List->Bottom - List->Top - 2;
 
-  if (List->Line < 0 || List->Line > Height)
-    return;
 
   coPos.X = List->Left + 1;
   coPos.Y = List->Top + 1 + List->Line;
@@ -946,22 +1156,26 @@ PrintDiskData (PPARTLIST List,
               DiskEntry->Bus,
               DiskEntry->Id);
     }
-
-  FillConsoleOutputAttribute (0x17,
-                             Width,
-                             coPos,
-                             &Written);
-
-  FillConsoleOutputCharacter (' ',
-                             Width,
-                             coPos,
-                             &Written);
+  if (List->Line >= 0 && List->Line <= Height)
+    {
+      FillConsoleOutputAttribute (0x17,
+                                 Width,
+                                 coPos,
+                                 &Written);
+
+      FillConsoleOutputCharacter (' ',
+                                 Width,
+                                 coPos,
+                                 &Written);
+    }
 
   coPos.X++;
-  WriteConsoleOutputCharacters (LineBuffer,
-                               min (strlen (LineBuffer), Width - 2),
-                               coPos);
-
+  if (List->Line >= 0 && List->Line <= Height)
+    {
+      WriteConsoleOutputCharacters (LineBuffer,
+                                   min (strlen (LineBuffer), Width - 2),
+                                   coPos);
+    }
   List->Line++;
 
   /* Print separator line */
@@ -989,13 +1203,80 @@ PrintDiskData (PPARTLIST List,
 VOID
 DrawPartitionList (PPARTLIST List)
 {
-  PLIST_ENTRY Entry;
+  PLIST_ENTRY Entry, Entry2;
   PDISKENTRY DiskEntry;
-  CHAR LineBuffer[128];
+  PPARTENTRY PartEntry = NULL;
   COORD coPos;
   ULONG Written;
   SHORT i;
-  SHORT DiskIndex;
+  SHORT CurrentDiskLine;
+  SHORT CurrentPartLine;
+  SHORT LastLine;
+  BOOL CurrentPartLineFound = FALSE;
+  BOOL CurrentDiskLineFound = FALSE;
+
+  /* Calculate the line of the current disk and partition */
+  CurrentDiskLine = 0;
+  CurrentPartLine = 0;
+  LastLine = 0;
+  Entry = List->DiskListHead.Flink;
+  while (Entry != &List->DiskListHead)
+    {
+      DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
+      LastLine += 2;
+      if (CurrentPartLineFound == FALSE)
+        {
+          CurrentPartLine += 2;
+       }
+      Entry2 = DiskEntry->PartListHead.Flink;
+      while (Entry2 != &DiskEntry->PartListHead)
+       {
+         PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
+         if (PartEntry == List->CurrentPartition)
+           {
+             CurrentPartLineFound = TRUE;
+           }
+          Entry2 = Entry2->Flink;
+         if (CurrentPartLineFound == FALSE)
+           {
+             CurrentPartLine++;
+           }
+         LastLine++;
+       }
+      if (DiskEntry == List->CurrentDisk)
+        {
+         CurrentDiskLineFound = TRUE;
+       }
+      Entry = Entry->Flink;
+      if (Entry != &List->DiskListHead)
+        {
+         if (CurrentDiskLineFound == FALSE)
+           {
+             CurrentPartLine ++;
+             CurrentDiskLine = CurrentPartLine;
+           }
+         LastLine++;
+       }
+      else
+        {
+         LastLine--;
+       }
+    }
+
+  /* If it possible, make the disk name visible */
+  if (CurrentPartLine < List->Offset)
+    {
+      List->Offset = CurrentPartLine;
+    }
+  else if (CurrentPartLine - List->Offset > List->Bottom - List->Top - 2)
+    {
+      List->Offset = CurrentPartLine - (List->Bottom - List->Top - 2);
+    }
+  if (CurrentDiskLine < List->Offset && CurrentPartLine - CurrentDiskLine < List->Bottom - List->Top - 2)
+    {
+      List->Offset = CurrentDiskLine;
+    }
+
 
   /* draw upper left corner */
   coPos.X = List->Left;
@@ -1008,10 +1289,29 @@ DrawPartitionList (PPARTLIST List)
   /* draw upper edge */
   coPos.X = List->Left + 1;
   coPos.Y = List->Top;
-  FillConsoleOutputCharacter (0xC4, // '-',
-                             List->Right - List->Left - 1,
-                             coPos,
-                             &Written);
+  if (List->Offset == 0)
+    {
+      FillConsoleOutputCharacter (0xC4, // '-',
+                                 List->Right - List->Left - 1,
+                                 coPos,
+                                 &Written);
+    }
+  else
+    {
+      FillConsoleOutputCharacter (0xC4, // '-',
+                                 List->Right - List->Left - 5,
+                                 coPos,
+                                 &Written);
+      coPos.X = List->Right - 5;
+      WriteConsoleOutputCharacters ("(\x18)", // "(up)"
+                                   3,
+                                   coPos);
+      coPos.X = List->Right - 2;
+      FillConsoleOutputCharacter (0xC4, // '-',
+                                 2,
+                                 coPos,
+                                 &Written);
+    }
 
   /* draw upper right corner */
   coPos.X = List->Right;
@@ -1049,10 +1349,29 @@ DrawPartitionList (PPARTLIST List)
   /* draw lower edge */
   coPos.X = List->Left + 1;
   coPos.Y = List->Bottom;
-  FillConsoleOutputCharacter (0xC4, // '-',
-                             List->Right - List->Left - 1,
-                             coPos,
-                             &Written);
+  if (LastLine - List->Offset <= List->Bottom - List->Top - 2)
+    {
+      FillConsoleOutputCharacter (0xC4, // '-',
+                                 List->Right - List->Left - 1,
+                                 coPos,
+                                 &Written);
+    }
+  else
+    {
+      FillConsoleOutputCharacter (0xC4, // '-',
+                                 List->Right - List->Left - 5,
+                                 coPos,
+                                 &Written);
+      coPos.X = List->Right - 5;
+      WriteConsoleOutputCharacters ("(\x19)", // "(down)"
+                                   3,
+                                   coPos);
+      coPos.X = List->Right - 2;
+      FillConsoleOutputCharacter (0xC4, // '-',
+                                 2,
+                                 coPos,
+                                 &Written);
+    }
 
   /* draw lower right corner */
   coPos.X = List->Right;
@@ -1063,7 +1382,7 @@ DrawPartitionList (PPARTLIST List)
                              &Written);
 
   /* print list entries */
-  List->Line = 0;
+  List->Line = - List->Offset;
 
   Entry = List->DiskListHead.Flink;
   while (Entry != &List->DiskListHead)
@@ -1079,6 +1398,51 @@ DrawPartitionList (PPARTLIST List)
 }
 
 
+VOID
+SelectPartition(PPARTLIST List, ULONG DiskNumber, ULONG PartitionNumber)
+{
+  PDISKENTRY DiskEntry;
+  PPARTENTRY PartEntry;
+  PLIST_ENTRY Entry1;
+  PLIST_ENTRY Entry2;
+  ULONG i;
+
+  /* Check for empty disks */
+  if (IsListEmpty (&List->DiskListHead))
+    return;
+
+  /* Check for first usable entry on next disk */
+  Entry1 = List->CurrentDisk->ListEntry.Flink;
+  while (Entry1 != &List->DiskListHead)
+    {
+      DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
+
+      if (DiskEntry->DiskNumber == DiskNumber)
+        {
+          Entry2 = DiskEntry->PartListHead.Flink;
+          while (Entry2 != &DiskEntry->PartListHead)
+            {
+              PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
+
+              for (i = 0; i < 4; i++)
+                {
+                  if (PartEntry->PartInfo[i].PartitionNumber == PartitionNumber)
+                   {
+                     List->CurrentDisk = DiskEntry;
+                     List->CurrentPartition = PartEntry;
+                      DrawPartitionList (List);
+                     return;
+                   }
+                }
+              Entry2 = Entry2->Flink;
+            }
+          return;
+        }
+      Entry1 = Entry1->Flink;
+    }
+}
+
+
 VOID
 ScrollDownPartitionList (PPARTLIST List)
 {
@@ -1146,7 +1510,6 @@ ScrollUpPartitionList (PPARTLIST List)
   PPARTENTRY PartEntry;
   PLIST_ENTRY Entry1;
   PLIST_ENTRY Entry2;
-  ULONG i;
 
   /* Check for empty disks */
   if (IsListEmpty (&List->DiskListHead))
@@ -1367,8 +1730,7 @@ CreateNewPartition (PPARTLIST List,
       else if (PrevPartEntry == NULL && NextPartEntry != NULL)
        {
          /* Current entry is the first entry */
-
-         /* FIXME: Update extended partition entries */
+         return;
        }
       else if (PrevPartEntry != NULL && NextPartEntry == NULL)
        {
@@ -1391,7 +1753,7 @@ CreateNewPartition (PPARTLIST List,
 
          if ((PartEntry->PartInfo[1].StartingOffset.QuadPart +
               PartEntry->PartInfo[1].PartitionLength.QuadPart) <
-              (1024ULL * 255ULL * 63ULL * 512ULL))
+              (1024LL * 255LL * 63LL * 512LL))
            {
              PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
            }
@@ -1478,8 +1840,7 @@ CreateNewPartition (PPARTLIST List,
       else if (PrevPartEntry == NULL && NextPartEntry != NULL)
        {
          /* Current entry is the first entry */
-
-         /* FIXME: Update extended partition entries */
+         return;
        }
       else if (PrevPartEntry != NULL && NextPartEntry == NULL)
        {
@@ -1502,7 +1863,7 @@ CreateNewPartition (PPARTLIST List,
 
          if ((PartEntry->PartInfo[1].StartingOffset.QuadPart +
               PartEntry->PartInfo[1].PartitionLength.QuadPart) <
-              (1024ULL * 255ULL * 63ULL * 512ULL))
+              (1024LL * 255LL * 63LL * 512LL))
            {
              PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
            }
@@ -1558,6 +1919,14 @@ DeleteCurrentPartition (PPARTLIST List)
   if (PrevPartEntry != NULL && NextPartEntry != NULL)
     {
       /* Current entry is in the middle of the list */
+
+      /*
+       * The first extended partition can not be deleted
+       * as long as other extended partitions are present.
+       */
+      if (PrevPartEntry->ListEntry.Blink == &DiskEntry->PartListHead)
+       return;
+
       /* Copy previous container partition data to current entry */
       RtlCopyMemory (&PrevPartEntry->PartInfo[1],
                     &PartEntry->PartInfo[1],
@@ -1566,9 +1935,11 @@ DeleteCurrentPartition (PPARTLIST List)
     }
   else if (PrevPartEntry == NULL && NextPartEntry != NULL)
     {
-      /* Current entry is the first entry */
-
-      /* FIXME: Update extended partition entries */
+      /*
+       * A primary partition can not be deleted as long as
+       * extended partitions are present.
+       */
+      return;
     }
   else if (PrevPartEntry != NULL && NextPartEntry == NULL)
     {
@@ -1593,7 +1964,7 @@ DeleteCurrentPartition (PPARTLIST List)
       /* Merge previous, current and next unpartitioned entry */
 
       /* Adjust the previous entries length */
-      PrevPartEntry->UnpartitionedLength += 
+      PrevPartEntry->UnpartitionedLength +=
        (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize +
         NextPartEntry->UnpartitionedLength);
 
@@ -1617,7 +1988,7 @@ DeleteCurrentPartition (PPARTLIST List)
       /* Merge current and previous unpartitioned entry */
 
       /* Adjust the previous entries length */
-      PrevPartEntry->UnpartitionedLength += 
+      PrevPartEntry->UnpartitionedLength +=
        (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
 
       /* Remove the current entry */
@@ -1634,9 +2005,9 @@ DeleteCurrentPartition (PPARTLIST List)
       /* Merge current and next unpartitioned entry */
 
       /* Adjust the next entries offset and length */
-      NextPartEntry->UnpartitionedOffset = 
+      NextPartEntry->UnpartitionedOffset =
        PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
-      NextPartEntry->UnpartitionedLength += 
+      NextPartEntry->UnpartitionedLength +=
        (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
 
       /* Remove the current entry */
@@ -1653,9 +2024,9 @@ DeleteCurrentPartition (PPARTLIST List)
       /* Nothing to merge but change current entry */
       PartEntry->New = FALSE;
       PartEntry->Unpartitioned = TRUE;
-      PartEntry->UnpartitionedOffset = 
+      PartEntry->UnpartitionedOffset =
        PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
-      PartEntry->UnpartitionedLength = 
+      PartEntry->UnpartitionedLength =
        PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
 
       /* Wipe the partition table */
@@ -1847,7 +2218,29 @@ WritePartitionsToDisk (PPARTLIST List)
                             DriveLayoutSize);
 
              DriveLayout->PartitionCount = PartitionCount;
+              if (DiskEntry->Signature == 0)
+                {
+                  LARGE_INTEGER SystemTime;
+                  TIME_FIELDS TimeFields;
+                  PUCHAR Buffer;
+
+                  NtQuerySystemTime (&SystemTime);
+                  RtlTimeToTimeFields (&SystemTime, &TimeFields);
+
+                  Buffer = (PUCHAR)&DiskEntry->Signature;
+                  Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
+                  Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
+                  Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
+                  Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
 
+                  /* FIXME:
+                   *   check for an existing signature 
+                   */
+
+                }
+
+              DriveLayout->Signature = DiskEntry->Signature;
+              
              Index = 0;
              Entry2 = DiskEntry->PartListHead.Flink;
              while (Entry2 != &DiskEntry->PartListHead)
@@ -1942,4 +2335,42 @@ WritePartitionsToDisk (PPARTLIST List)
   return TRUE;
 }
 
+BOOL SetMountedDeviceValues(PPARTLIST List)
+{
+  PLIST_ENTRY Entry1, Entry2;
+  PDISKENTRY DiskEntry;
+  PPARTENTRY PartEntry;
+
+  if (List == NULL)
+    {
+      return FALSE;
+    }
+
+  Entry1 = List->DiskListHead.Flink;
+  while (Entry1 != &List->DiskListHead)
+    {
+      DiskEntry = CONTAINING_RECORD (Entry1,
+                                    DISKENTRY,
+                                    ListEntry);
+
+      Entry2 = DiskEntry->PartListHead.Flink;
+      while (Entry2 != &DiskEntry->PartListHead)
+        {
+          PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+          if (!PartEntry->Unpartitioned && PartEntry->DriveLetter)
+            {
+              if (!SetMountedDeviceValue(PartEntry->DriveLetter, DiskEntry->Signature, PartEntry->PartInfo[0].StartingOffset))
+                {
+                  return FALSE;
+                }
+            }
+          Entry2 = Entry2->Flink;
+        }
+      Entry1 = Entry1->Flink;
+    }
+  return TRUE;
+}
+
+
+
 /* EOF */