⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 partlist.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 *  ReactOS kernel
 *  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
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/* 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)
 */

#include "usetup.h"

#define NDEBUG
#include <debug.h>

/* FUNCTIONS ****************************************************************/

static VOID
GetDriverName (PDISKENTRY DiskEntry)
{
  RTL_QUERY_REGISTRY_TABLE QueryTable[2];
  WCHAR KeyName[32];
  NTSTATUS Status;

  RtlInitUnicodeString (&DiskEntry->DriverName,
			NULL);

  swprintf (KeyName,
	    L"\\Scsi\\Scsi Port %lu",
	    DiskEntry->Port);

  RtlZeroMemory (&QueryTable,
		 sizeof(QueryTable));

  QueryTable[0].Name = L"Driver";
  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  QueryTable[0].EntryContext = &DiskEntry->DriverName;

  Status = RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP,
				   KeyName,
				   QueryTable,
				   NULL,
				   NULL);
  if (!NT_SUCCESS (Status))
    {
      DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
    }
}


static VOID
AssignDriverLetters (PPARTLIST List)
{
  PDISKENTRY DiskEntry;
  PPARTENTRY PartEntry;
  PLIST_ENTRY Entry1;
  PLIST_ENTRY Entry2;
  CHAR Letter;

  Letter = 'C';

  /* Assign drive letters to primary partitions */
  Entry1 = List->DiskListHead.Flink;
  while (Entry1 != &List->DiskListHead)
    {
      DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);

      if (!IsListEmpty (&DiskEntry->PartListHead))
	{
	  PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink,
					 PARTENTRY,
					 ListEntry);

	  PartEntry->DriveLetter = 0;

	  if (PartEntry->Unpartitioned == FALSE &&
	      !IsContainerPartition (PartEntry->PartInfo[0].PartitionType))
	    {
	      if (IsRecognizedPartition (PartEntry->PartInfo[0].PartitionType) ||
		  (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED &&
		   PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL))
		{
		  if (Letter <= 'Z')
		    {
		      PartEntry->DriveLetter = Letter;
		      Letter++;
		    }
		}
	    }
	}

      Entry1 = Entry1->Flink;
    }


  /* Assign drive letters to logical drives */
  Entry1 = List->DiskListHead.Flink;
  while (Entry1 != &List->DiskListHead)
    {
      DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);

      Entry2 = DiskEntry->PartListHead.Flink;
      if (Entry2 != &DiskEntry->PartListHead)
	{
	  Entry2 = Entry2->Flink;
	  while (Entry2 != &DiskEntry->PartListHead)
	    {
	      PartEntry = CONTAINING_RECORD (Entry2,
					     PARTENTRY,
					     ListEntry);

	      PartEntry->DriveLetter = 0;

	      if (PartEntry->Unpartitioned == FALSE &&
		  !IsContainerPartition (PartEntry->PartInfo[0].PartitionType))
		{
		  if (IsRecognizedPartition (PartEntry->PartInfo[0].PartitionType) ||
		      (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED &&
		       PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL))
		    {
		      if (Letter <= 'Z')
			{
			  PartEntry->DriveLetter = Letter;
			  Letter++;
			}
		    }
		}

	      Entry2 = Entry2->Flink;
	    }
	}

      Entry1 = Entry1->Flink;
    }
}


static VOID
UpdatePartitionNumbers (PDISKENTRY DiskEntry)
{
  PPARTENTRY PartEntry;
  PLIST_ENTRY Entry;
  ULONG PartNumber;
  ULONG i;

  PartNumber = 1;
  Entry = DiskEntry->PartListHead.Flink;
  while (Entry != &DiskEntry->PartListHead)
    {
      PartEntry = CONTAINING_RECORD (Entry,
				     PARTENTRY,
				     ListEntry);

      if (PartEntry->Unpartitioned == TRUE)
	{
	  for (i = 0; i < 4; i++)
	    {
	      PartEntry->PartInfo[i].PartitionNumber = 0;
	    }
	}
      else
	{
	  for (i = 0; i < 4; i++)
	    {
	      if (IsContainerPartition (PartEntry->PartInfo[i].PartitionType))
		{
		  PartEntry->PartInfo[i].PartitionNumber = 0;
		}
	      else if (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED &&
		       PartEntry->PartInfo[i].PartitionLength.QuadPart == 0ULL)
		{
		  PartEntry->PartInfo[i].PartitionNumber = 0;
		}
	      else
		{
		  PartEntry->PartInfo[i].PartitionNumber = PartNumber;
		  PartNumber++;
		}
	    }
	}

      Entry = Entry->Flink;
    }
}


static VOID
AddPartitionToList (ULONG DiskNumber,
		    PDISKENTRY DiskEntry,
		    DRIVE_LAYOUT_INFORMATION *LayoutBuffer)
{
  PPARTENTRY PartEntry;
  ULONG i;
  ULONG j;

  for (i = 0; i < LayoutBuffer->PartitionCount; i += 4)
    {
      for (j = 0; j < 4; j++)
	{
	  if (LayoutBuffer->PartitionEntry[i+j].PartitionType != PARTITION_ENTRY_UNUSED ||
	      LayoutBuffer->PartitionEntry[i+j].PartitionLength.QuadPart != 0ULL)
	    {
	      break;
	    }
	}
      if (j >= 4)
	{
	  continue;
	}

      PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
					       0,
					       sizeof(PARTENTRY));
      if (PartEntry == NULL)
	{
	  return;
	}

      RtlZeroMemory (PartEntry,
		     sizeof(PARTENTRY));

      PartEntry->Unpartitioned = FALSE;

      for (j = 0; j < 4; j++)
	{
	  RtlCopyMemory (&PartEntry->PartInfo[j],
			 &LayoutBuffer->PartitionEntry[i+j],
			 sizeof(PARTITION_INFORMATION));
	}

      if (IsContainerPartition(PartEntry->PartInfo[0].PartitionType))
	{
	  PartEntry->FormatState = Unformatted;
	}
      else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
	       (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
	       (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
	       (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13) ||
	       (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
	       (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
	{
#if 0
	  if (CheckFatFormat())
	    {
	      PartEntry->FormatState = Preformatted;
	    }
	  else
	    {
	      PartEntry->FormatState = Unformatted;
	    }
#endif
	  PartEntry->FormatState = Preformatted;
	}
      else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
	{
#if 0
	  if (CheckNtfsFormat())
	    {
	      PartEntry->FormatState = Preformatted;
	    }
	  else if (CheckHpfsFormat())
	    {
	      PartEntry->FormatState = Preformatted;
	    }
	  else
	    {
	      PartEntry->FormatState = Unformatted;
	    }
#endif
	  PartEntry->FormatState = Preformatted;
	}
      else
	{
	  PartEntry->FormatState = UnknownFormat;
	}

      InsertTailList (&DiskEntry->PartListHead,
		      &PartEntry->ListEntry);
    }
}


static VOID
ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry)
{
  ULONGLONG LastStartingOffset;
  ULONGLONG LastPartitionLength;
  ULONGLONG LastUnusedPartitionLength;
  PPARTENTRY PartEntry;
  PPARTENTRY NewPartEntry;
  PLIST_ENTRY Entry;
  ULONG i;
  ULONG j;

  if (IsListEmpty (&DiskEntry->PartListHead))
    {
      /* Create a partition table that represents the empty disk */
      PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
					       0,
					       sizeof(PARTENTRY));
      if (PartEntry == NULL)
	return;

      RtlZeroMemory (PartEntry,
		     sizeof(PARTENTRY));

      PartEntry->Unpartitioned = TRUE;
      PartEntry->UnpartitionedOffset = 0ULL;
      PartEntry->UnpartitionedLength = DiskEntry->DiskSize;

      PartEntry->FormatState = Unformatted;

      InsertTailList (&DiskEntry->PartListHead,
		      &PartEntry->ListEntry);
    }
  else
    {
      /* Start partition at head 1, cylinder 0 */
      LastStartingOffset = DiskEntry->TrackSize;
      LastPartitionLength = 0ULL;
      LastUnusedPartitionLength = 0ULL;

      i = 0;
      Entry = DiskEntry->PartListHead.Flink;
      while (Entry != &DiskEntry->PartListHead)
	{
	  PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);

	  for (j = 0; j < 4; j++)
	    {
	      if ((!IsContainerPartition (PartEntry->PartInfo[j].PartitionType)) &&
		  (PartEntry->PartInfo[j].PartitionType != PARTITION_ENTRY_UNUSED ||
		   PartEntry->PartInfo[j].PartitionLength.QuadPart != 0LL))
		{
		  LastUnusedPartitionLength =
		    PartEntry->PartInfo[j].StartingOffset.QuadPart -
		    (LastStartingOffset + LastPartitionLength);

		  if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
		    {
		      DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);

		      NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
								  0,
								  sizeof(PARTENTRY));
		      if (NewPartEntry == NULL)
			return;

		      RtlZeroMemory (NewPartEntry,
				     sizeof(PARTENTRY));

		      NewPartEntry->Unpartitioned = TRUE;
		      NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
		      NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
		      if (j == 0)
			NewPartEntry->UnpartitionedLength -= DiskEntry->TrackSize;

		      NewPartEntry->FormatState = Unformatted;

		      /* Insert the table into the list */
		      InsertTailList (&PartEntry->ListEntry,
				      &NewPartEntry->ListEntry);
		    }

		  LastStartingOffset = PartEntry->PartInfo[j].StartingOffset.QuadPart;
		  LastPartitionLength = PartEntry->PartInfo[j].PartitionLength.QuadPart;
		}
	    }

	  i += 4;
	  Entry = Entry->Flink;
	}

      /* Check for trailing unpartitioned disk space */
      if (DiskEntry->DiskSize > (LastStartingOffset + LastPartitionLength))
	{
	  /* Round-down to cylinder size */
	  LastUnusedPartitionLength =
	    ROUND_DOWN (DiskEntry->DiskSize - (LastStartingOffset + LastPartitionLength),
			DiskEntry->CylinderSize);

	  if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
	    {
	      DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);

	      NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
							  0,
							  sizeof(PARTENTRY));
	      if (NewPartEntry == NULL)
		return;

	      RtlZeroMemory (NewPartEntry,
			     sizeof(PARTENTRY));

	      NewPartEntry->Unpartitioned = TRUE;
	      NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
	      NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;

	      /* Append the table to the list */
	      InsertTailList (&DiskEntry->PartListHead,
			      &NewPartEntry->ListEntry);
	    }
	}
    }
}

NTSTATUS
NTAPI
DiskIdentifierQueryRoutine(PWSTR ValueName,
                           ULONG ValueType,
                           PVOID ValueData,
                           ULONG ValueLength,
                           PVOID Context,
                           PVOID EntryContext)
{
  PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
  UNICODE_STRING NameU;

  if (ValueType == REG_SZ &&
      ValueLength == 20 * sizeof(WCHAR))
    {
      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);

      return STATUS_SUCCESS;
    }
    return STATUS_UNSUCCESSFUL;
}

NTSTATUS
NTAPI
DiskConfigurationDataQueryRoutine(PWSTR ValueName,
                                  ULONG ValueType,
                                  PVOID ValueData,
                                  ULONG ValueLength,
                                  PVOID Context,
                                  PVOID EntryContext)
{
	PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
	PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
	PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
	ULONG i;

	if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
		ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
		return STATUS_UNSUCCESSFUL;

	FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
	/* Hm. Version and Revision are not set on Microsoft Windows XP... */
	/*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
		FullResourceDescriptor->PartialResourceList.Revision != 1)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -