Compare commits

...

24 Commits

Author SHA1 Message Date
Hermès Bélusca-Maïto
bceeb18146 ** wip ** Continue investigations in partmgr 2025-01-28 15:33:41 +01:00
Hermès Bélusca-Maïto
90865ee872 ** INVESTIGATION ** Investigate stuff in disk.sys and classpnp.sys 2025-01-28 15:33:40 +01:00
Hermès Bélusca-Maïto
686f3f0523 ** wip ** [PARTMGR] Refactor some aspects of set-drive-layout functionality 2025-01-28 15:33:39 +01:00
Hermès Bélusca-Maïto
b063438248 ** wip ** Investigate PartitionNumber on partmgr side 2025-01-28 15:33:38 +01:00
Hermès Bélusca-Maïto
d0af99fcad fix old-annotations for *IoReadPartitionTable* 2025-01-28 15:33:38 +01:00
Hermès Bélusca-Maïto
299c3e8aed ** wip ** [NTOS:FSTUB] *ReadPartitionTable*(): PartitionNumber in the layout's PartitionEntry must be left uninitialized.
Addendum to commit e69f845dab.

This is a subtle observation.

First, it should be observed that when the partition manager driver
(or the disk class driver on Windows <= 2003) calls any of the
*ReadPartitionTable*() functions (and indirectly their helpers),
as part of IOCTL_DISK_GET_DRIVE_LAYOUT(_EX) handling, the retrieved
PartitionNumber values are reset and recalculated afterwards.
Meaning that whatever has been stored initially by the
*ReadPartitionTable*() functions is completely ignored.

Second, one should monitor (with a kernel debugger, e.g. WinDbg)
the ExAllocatePoolWithTag() calls done by the *ReadPartitionTable*()
functions themselves, when they (re-)allocate the partition buffer
that is going to be later returned to the caller. One then needs
to fill the allocated buffer (or calculate and fill only the
PartitionNumber of the layout entries) with a canary value.
Finally, once the *ReadPartitionTable*() functions return, one can
observe that the PartitionNumber have been left untouched.
On Windows, this means, left uninitialized (and filled with whatever
kernel data was present in memory from the ExAllocatePoolWithTag()
calls).

For ReactOS, we instead invalidate the PartitionNumber with -1,
a "known" value.
2025-01-28 15:33:37 +01:00
Hermès Bélusca-Maïto
5cc0ee942f ** wip ** NTOS:FSTUB Investigate the drive-letters assignment algorithm 2025-01-28 15:33:36 +01:00
Hermès Bélusca-Maïto
5004e520a5 [NTOS:FSTUB] Simplify code: GUID comparisons and saving partition info. 2025-01-28 15:33:35 +01:00
Hermès Bélusca-Maïto
1827e4e776 [NTOS:FSTUB] Improve output of the FstubDbg* helpers + fix a bug
- Compile their contents only when NDEBUG is _NOT_ defined.

- Only keep the first DPRINT in these functions in order to keep the
  file path and line number, but replace the others with DbgPrint in
  order to have a clearer printout.

- Fix a bug in FstubDbgPrintSetPartitionEx(), where PartitionNumber has
  to be used as an indicator parameter but MUST NOT be used to index the
  PartitionEntry pointer. (PartitionEntry already points to the data for
  setting the partition specified by PartitionNumber.)
  The bug certainly came from a copy-pasting error from FstubDbgPrintPartitionEx().
2025-01-28 15:33:34 +01:00
Hermès Bélusca-Maïto
8c04fdd1af [NTOS:FSTUB/IO] Unhardcode some values 2025-01-28 15:33:34 +01:00
Hermès Bélusca-Maïto
53d2bd5f87 [NTOS:FSTUB] Make some macros more "conformant"
i.e. parenthesized parameters; parenthesize compound macros, ...
2025-01-28 15:33:33 +01:00
Hermès Bélusca-Maïto
2a9984f5d1 [NTOS:FSTUB] Minor formatting improvement for disksup.c internal functions
In addition, add SAL2 annotations to them, some comments fixes,
and remove old unused definitions.
2025-01-28 15:33:32 +01:00
Hermès Bélusca-Maïto
5a034f3ede turn the partentry booleans into bitfields 2025-01-28 15:33:31 +01:00
Hermès Bélusca-Maïto
686ef2741d turn the volume booleans into bitfields 2025-01-28 15:33:30 +01:00
Hermès Bélusca-Maïto
a722e660bf ** wip ** investigate some aspects in usetup partition list ui drawing code 2025-01-28 15:33:29 +01:00
Hermès Bélusca-Maïto
ba2e90a8c2 ** wip ** setuplib volume drive letters assignment 2025-01-28 15:33:28 +01:00
Hermès Bélusca-Maïto
41380b3b54 ** wip ** dump MountedDevices key 2025-01-28 15:33:27 +01:00
Hermès Bélusca-Maïto
39fcaba8cb ** WIP ** [SETUPLIB] Make volumes support more robust.
* Enumerate volumes with PnP + extra fixes.

* Tag disks as basic or dynamic during enumeration.

  Setup currently only supports basic disks, so this will help detect
  such disks and take appropriate actions accordingly. For example:
  - warn that ReactOS cannot be installed on them;
  - in the future, support installation only in the case a dynamic
    volume exactly covers one unique partition;
  - etc.

* Check whether the volume, if dynamic, lays exactly on a single
  partition and is suitable for OS installation.
  See e.g. https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/shared/ntddvol.h#L310
2025-01-28 15:33:26 +01:00
Hermès Bélusca-Maïto
63706f04fb moving around some gpt/mbr checks for disks 2025-01-28 15:33:25 +01:00
Hermès Bélusca-Maïto
5d518e17c2 ** wip wip ** Investigate enumeration with setup classes instead (not used yet) 2025-01-28 15:33:25 +01:00
Hermès Bélusca-Maïto
5731c50acf ** WIP ** Implement PnP enumeration of disks
Note to self: check these references:
https://stackoverflow.com/questions/52146560/get-information-for-physical-disks-when-storage-spaces-is-enabled
https://stackoverflow.com/questions/42426931/how-to-get-from-device-manager-device-e-g-from-its-physical-device-object-nam/42439253#42439253
2025-01-28 15:33:24 +01:00
Hermès Bélusca-Maïto
60bea22009 [USETUP] Add PnP CM enumeration API implementation CM_Get_Device_Interface_List[Size]
These two functions will be used later for enumerating disks and volumes
in a PnP-compatible way.

The implementation of these functions is based on the one used in the
Win32 cfgmgr32.dll and the umpnpmgr service. They ultimately call the
NT-exported NtPlugPlayControl() API.
2025-01-28 15:33:23 +01:00
Hermès Bélusca-Maïto
85d317447d [SETUPLIB] Don't immediately unmount volumes when deleting partitions...
...but wait until the partitions are actually updated on disk.

DeletePartition() deletes partitions only in the virtual partitions list
in memory; the partitions still exist on the disk and are written only
later when committing all partition changes.

Thus, we do the same for file system volumes that lay on top of these
partitions being deleted: we move the linked VOLENTRY structures to a
list of "pending volumes to unmount", while they still actually stay
mounted on the system. Only when partition changes are about to be
committed to disk, is the "pending volumes to unmount" list processed
and the volumes actually unmounted first.

[SETUPLIB] Support device naming for volumes

Split InitVolume() and setting a default volume device name.
2025-01-28 15:33:22 +01:00
Hermès Bélusca-Maïto
889cfa828d ** TEMP ** DON'T COMMIT -- FOR TESTING PURPOSES ONLY ** 2025-01-28 15:33:21 +01:00
21 changed files with 2717 additions and 1031 deletions

View File

@@ -1371,7 +1371,8 @@ DoUpdate:
/* Update the mounted devices list */
// FIXME: This should technically be done by mountmgr (if AutoMount is enabled)!
SetMountedDeviceValues(PartitionList);
// SetMountedDeviceValues(PartitionList);
ImportMountedDevices();
}
#ifdef __REACTOS__

View File

@@ -134,4 +134,324 @@ pOpenDevice(
return pOpenDevice_UStr(&Name, DeviceHandle);
}
/* PnP ENUMERATION SUPPORT HELPERS *******************************************/
#define _CFGMGR32_
#include <cfgmgr32.h>
/**
* @brief
* Enumerates devices using PnP support.
* The type of devices to be enumerated is specified by an interface
* class GUID. A user-provided callback is invoked for each device found.
*
* @param[in] InterfaceClassGuid
* The interface class GUID designating the devices to enumerate.
*
* @param[in] Callback
* A user-provided callback function of type PENUM_DEVICES_PROC.
*
* @param[in] Context
* An optional context for the callback function.
*
* @note
* This function uses the lower-level user-mode CM_* PnP API,
* that are more widely available than the more common Win32
* SetupDi* functions.
* See
* https://learn.microsoft.com/en-us/windows-hardware/drivers/install/porting-from-setupapi-to-cfgmgr32#get-a-list-of-interfaces-get-the-device-exposing-each-interface-and-get-a-property-from-the-device
* for more details.
**/
NTSTATUS
// pNtEnumDevicesByInterfaceClass
pNtEnumDevicesPnP(
_In_ const GUID* InterfaceClassGuid,
_In_ PENUM_DEVICES_PROC Callback,
_In_opt_ PVOID Context)
{
NTSTATUS Status;
CONFIGRET cr;
ULONG DevIFaceListLength = 0;
PWSTR DevIFaceList = NULL;
PWSTR CurrentIFace;
/*
* Retrieve a list of device interface instances belonging to the given interface class.
* Equivalent to:
* hDevInfo = SetupDiGetClassDevs(pGuid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
* and SetupDiEnumDeviceInterfaces(hDevInfo, NULL, pGuid, i, &DevIFaceData);
*/
do
{
cr = CM_Get_Device_Interface_List_SizeW(&DevIFaceListLength,
(GUID*)InterfaceClassGuid,
NULL,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cr != CR_SUCCESS)
break;
if (DevIFaceList) RtlFreeHeap(ProcessHeap, 0, DevIFaceList);
DevIFaceList = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY,
DevIFaceListLength * sizeof(WCHAR));
if (!DevIFaceList)
{
cr = CR_OUT_OF_MEMORY;
break;
}
cr = CM_Get_Device_Interface_ListW((GUID*)InterfaceClassGuid,
NULL,
DevIFaceList,
DevIFaceListLength,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
} while (cr == CR_BUFFER_SMALL);
if (cr != CR_SUCCESS)
{
if (DevIFaceList) RtlFreeHeap(ProcessHeap, 0, DevIFaceList);
return STATUS_UNSUCCESSFUL;
}
/* Enumerate each device for the given interface class.
* NOTE: This gives the proper interface names with the correct casing,
* contrary to SetupDiGetDeviceInterfaceDetailW(...) that gives them
* in all lower-case letters. */
for (CurrentIFace = DevIFaceList;
*CurrentIFace;
CurrentIFace += wcslen(CurrentIFace) + 1)
{
UNICODE_STRING Name;
HANDLE DeviceHandle;
// TESTING
#if 0
WCHAR DevInstPath[MAX_DEVICE_ID_LEN];
PWSTR buffer = NULL;
ULONG buffersize = 0;
cr = CM_Locate_DevNodeW(&DevInst,
CurrentDevice, // ????
CM_LOCATE_DEVNODE_NORMAL);
if (cr != CR_SUCCESS)
break;
cr = CM_Get_Device_IDW(DevInst,
DevInstPath,
_countof(DevInstPath),
0);
for (;;)
{
// SetupDiGetDeviceRegistryPropertyW(..., SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, ...);
cr = CM_Get_DevNode_Registry_PropertyW(DevInst,
CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME,
NULL, // PULONG pulRegDataType
(PBYTE)buffer,
&buffersize,
0);
if (cr != CR_BUFFER_SMALL)
break;
if (buffer) RtlFreeHeap(ProcessHeap, 0, buffer);
buffer = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, buffersize);
if (!buffer)
{
cr = CR_OUT_OF_MEMORY;
break;
}
}
if (cr != CR_SUCCESS)
continue;
#endif
RtlInitUnicodeString(&Name, CurrentIFace);
/* Normalize the interface path in case it is of Win32-style */
if (Name.Length > 4 * sizeof(WCHAR) &&
Name.Buffer[0] == '\\' && Name.Buffer[1] == '\\' &&
Name.Buffer[2] == '?' && Name.Buffer[3] == '\\')
{
Name.Buffer[1] = '?';
}
Status = pOpenDevice(/*Name*/CurrentIFace, &DeviceHandle);
if (NT_SUCCESS(Status))
{
/* Do the callback */
if (Callback)
{
(void)Callback(InterfaceClassGuid,
CurrentIFace, DeviceHandle, Context);
}
NtClose(DeviceHandle);
}
#if 0
if (buffer) RtlFreeHeap(ProcessHeap, 0, buffer);
#endif
}
if (DevIFaceList) RtlFreeHeap(ProcessHeap, 0, DevIFaceList);
return STATUS_SUCCESS;
}
#if 0 // FIXME!
// FIXME: This is actually Win7+
#define CM_GETIDLIST_FILTER_PRESENT (0x00000100)
#define CM_GETIDLIST_FILTER_CLASS (0x00000200)
NTSTATUS
// pNtEnumDevicesBySetupClass
pNtEnumDevicesPnP_Alt(
_In_ const GUID* SetupClassGuid,
_In_ PENUM_DEVICES_PROC Callback,
_In_opt_ PVOID Context)
{
NTSTATUS Status;
CONFIGRET cr;
WCHAR guidString[MAX_GUID_STRING_LEN];
ULONG DevIDListLength = 0;
PWSTR DevIDList = NULL;
PWSTR CurrentID;
// GuidToString(), UuidToStringW(), RtlStringFromGUID()
Status = RtlStringCchPrintfW(guidString, _countof(guidString),
// L"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"
L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
SetupClassGuid->Data1, SetupClassGuid->Data2, SetupClassGuid->Data3,
SetupClassGuid->Data4[0], SetupClassGuid->Data4[1],
SetupClassGuid->Data4[2], SetupClassGuid->Data4[3],
SetupClassGuid->Data4[4], SetupClassGuid->Data4[5],
SetupClassGuid->Data4[6], SetupClassGuid->Data4[7]);
ASSERT(NT_SUCCESS(Status));
/*
* Retrieve a list of device interface instances belonging to the given interface class.
* Equivalent to:
* hDevInfo = SetupDiGetClassDevs(pGuid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
* and SetupDiEnumDeviceInterfaces(hDevInfo, NULL, pGuid, i, &DevIFaceData);
*/
do
{
cr = CM_Get_Device_ID_List_SizeW(&DevIDListLength,
guidString,
CM_GETIDLIST_FILTER_CLASS |
CM_GETIDLIST_FILTER_PRESENT);
if (cr != CR_SUCCESS)
break;
if (DevIDList) RtlFreeHeap(ProcessHeap, 0, DevIDList);
DevIDList = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY,
DevIDListLength * sizeof(WCHAR));
if (!DevIDList)
{
cr = CR_OUT_OF_MEMORY;
break;
}
cr = CM_Get_Device_ID_ListW(guidString,
DevIDList,
DevIDListLength,
CM_GETIDLIST_FILTER_CLASS |
CM_GETIDLIST_FILTER_PRESENT);
} while (cr == CR_BUFFER_SMALL);
if (cr != CR_SUCCESS)
{
if (DevIDList) RtlFreeHeap(ProcessHeap, 0, DevIDList);
return STATUS_UNSUCCESSFUL;
}
/* Enumerate each device for the given interface class.
* NOTE: This gives the proper interface names with the correct casing,
* contrary to SetupDiGetDeviceInterfaceDetailW(...) that gives them
* in all lower-case letters. */
for (CurrentID = DevIDList;
*CurrentID;
CurrentID += wcslen(CurrentID) + 1)
{
UNICODE_STRING Name;
HANDLE DeviceHandle;
WCHAR DevInstPath[MAX_DEVICE_ID_LEN];
DEVINST DevInst;
PWSTR buffer = NULL;
ULONG buffersize = 0;
cr = CM_Locate_DevNodeW(&DevInst,
CurrentID, // CurrentDevice,
CM_LOCATE_DEVNODE_NORMAL);
if (cr != CR_SUCCESS)
break;
#if 1 // TEST: DevInstPath should get back CurrentID
cr = CM_Get_Device_IDW(DevInst,
DevInstPath,
_countof(DevInstPath),
0);
#endif
for (;;)
{
// SetupDiGetDeviceRegistryPropertyW(..., SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, ...);
cr = CM_Get_DevNode_Registry_PropertyW(DevInst,
CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME,
NULL, // PULONG pulRegDataType
(PBYTE)buffer,
&buffersize,
0);
if (cr != CR_BUFFER_SMALL)
break;
if (buffer) RtlFreeHeap(ProcessHeap, 0, buffer);
buffer = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, buffersize);
if (!buffer)
{
cr = CR_OUT_OF_MEMORY;
break;
}
}
if (cr != CR_SUCCESS)
continue;
RtlInitUnicodeString(&Name, buffer);
/* Normalize the interface path in case it is of Win32-style */
if (Name.Length > 4 * sizeof(WCHAR) &&
Name.Buffer[0] == '\\' && Name.Buffer[1] == '\\' &&
Name.Buffer[2] == '?' && Name.Buffer[3] == '\\')
{
Name.Buffer[1] = '?';
}
Status = pOpenDevice(/*Name*/buffer, &DeviceHandle);
if (NT_SUCCESS(Status))
{
/* Do the callback */
if (Callback)
{
(void)Callback(SetupClassGuid,
buffer, DeviceHandle, Context);
}
NtClose(DeviceHandle);
}
if (buffer) RtlFreeHeap(ProcessHeap, 0, buffer);
}
if (DevIDList) RtlFreeHeap(ProcessHeap, 0, DevIDList);
return STATUS_SUCCESS;
}
#endif
/* EOF */

View File

@@ -38,4 +38,19 @@ pOpenDevice(
_In_ PCWSTR DevicePath,
_Out_ PHANDLE DeviceHandle);
/* PnP ENUMERATION SUPPORT HELPERS *******************************************/
typedef NTSTATUS
(NTAPI *PENUM_DEVICES_PROC)(
_In_ const GUID* InterfaceClassGuid,
_In_ PCWSTR DevicePath,
_In_ HANDLE DeviceHandle,
_In_opt_ PVOID Context);
NTSTATUS
pNtEnumDevicesPnP(
_In_ const GUID* InterfaceClassGuid,
_In_ PENUM_DEVICES_PROC Callback,
_In_opt_ PVOID Context);
/* EOF */

File diff suppressed because it is too large Load Diff

View File

@@ -26,6 +26,12 @@
((PartitionType) == PARTITION_DELL) || \
((PartitionType) == PARTITION_IBM) )
#define IsLDMPartition(PartitionType) \
((PartitionType) == PARTITION_LDM) /* || \
(PartitionType) == 0x8E || // Linux LVM \
(PartitionType) == PARTITION_SPACES_DATA || \
(PartitionType) == PARTITION_SPACES) */
/* PARTITION UTILITY FUNCTIONS **********************************************/
@@ -42,15 +48,22 @@ typedef enum _FORMATSTATE
typedef struct _PARTENTRY PARTENTRY, *PPARTENTRY;
typedef struct _VOLENTRY
{
LIST_ENTRY ListEntry; ///< Entry in VolumesList
LIST_ENTRY ListEntry; ///< Entry in VolumesList or PendingUnmountVolumesList
VOLINFO Info;
FORMATSTATE FormatState;
/* Volume must be checked */
BOOLEAN NeedsCheck;
/* Volume is new and has not yet been actually formatted and mounted */
BOOLEAN New;
/* Volume state flags */
union
{
UCHAR AsByte;
struct
{
BOOLEAN New : 1; ///< New volume, not yet formatted and mounted.
BOOLEAN NeedsCheck : 1; ///< Volume must be checked.
UCHAR Reserved : 6;
};
};
// union {
// PVOLUME_DISK_EXTENTS pExtents;
@@ -76,13 +89,21 @@ typedef struct _PARTENTRY
ULONG PartitionIndex; /* Index in the LayoutBuffer->PartitionEntry[] cached array of the corresponding DiskEntry */
WCHAR DeviceName[MAX_PATH]; ///< NT device name: "\Device\HarddiskM\PartitionN"
BOOLEAN LogicalPartition;
/* Partition is partitioned disk space */
BOOLEAN IsPartitioned;
/* Partition is new, table does not exist on disk yet */
BOOLEAN New;
/* Partition state flags */
union
{
UCHAR AsByte;
struct
{
BOOLEAN New : 1; ///< New partition, its table entry does not exist on disk yet.
// NOTE: See comment for the PARTLIST::SystemPartition member.
// MBR: BootIndicator == TRUE / GPT: PARTITION_SYSTEM_GUID.
// BOOLEAN IsSystemPartition : 1; // FIXME: Re-enable when BootIndicator gets deprecated.
BOOLEAN LogicalPartition : 1; ///< MBR-specific logical partition.
BOOLEAN IsPartitioned : 1; ///< Partitioned disk space.
UCHAR Reserved : 5;
};
};
/*
* Volume-related properties:
@@ -103,7 +124,8 @@ typedef struct _DISKENTRY
/* The list of disks/partitions this disk belongs to */
struct _PARTLIST *PartList;
MEDIA_TYPE MediaType; /* FixedMedia or RemovableMedia */
MEDIA_TYPE MediaType; ///< FixedMedia or RemovableMedia
BOOLEAN IsDynamic; ///< TRUE for dynamic (LDM/LVM) or FALSE for basic disk
/* Disk geometry */
@@ -185,6 +207,8 @@ typedef struct _PARTLIST
/* (Basic) Volumes management */
LIST_ENTRY VolumesList;
LIST_ENTRY PendingUnmountVolumesList; ///< List of volumes to unmount
ULONG DriveMap; ///< Drive letters map, used by AssignNextDriveLetter()
} PARTLIST, *PPARTLIST;
@@ -385,13 +409,17 @@ BOOLEAN
WritePartitionsToDisk(
IN PPARTLIST List);
BOOLEAN
SetMountedDeviceValues(
_In_ PPARTLIST List);
VOID
SetMBRPartitionType(
IN PPARTENTRY PartEntry,
IN UCHAR PartitionType);
BOOLEAN
SetMountedDeviceValues(
_In_ PPARTLIST List);
NTSTATUS
ImportMountedDevices(VOID);
/* EOF */

View File

@@ -8,6 +8,7 @@
/* INCLUDES ******************************************************************/
#include "precomp.h"
#include <mountdev.h>
#include "volutil.h"
#include "fsrec.h"
@@ -19,12 +20,238 @@
/* FUNCTIONS *****************************************************************/
/**
* @brief
* Requests the MountMgr to retrieve the drive letter,
* if any, associated to the given volume.
*
* @param[in] VolumeName
* Device name of the volume.
*
* @param[out] DriveLetter
* Pointer to a WCHAR buffer receiving the corresponding drive letter,
* or UNICODE_NULL if none has been assigned.
*
* @return A status code.
**/
NTSTATUS
GetVolumeDriveLetter(
_In_ PCUNICODE_STRING VolumeName,
_Out_ PWCHAR DriveLetter)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE Handle;
UNICODE_STRING MountMgrDevice;
ULONG Length;
MOUNTMGR_MOUNT_POINTS MountPoints;
PMOUNTMGR_MOUNT_POINTS MountPointsPtr;
/*
* This variable is used to store the device name
* for the input buffer to IOCTL_MOUNTMGR_QUERY_POINTS.
* It's based on MOUNTMGR_MOUNT_POINT (mountmgr.h).
* Doing it this way prevents memory allocation.
* The device name won't be longer.
*/
struct
{
MOUNTMGR_MOUNT_POINT;
WCHAR DeviceName[256];
} DeviceName;
/* Default to no letter */
*DriveLetter = UNICODE_NULL;
/* First, retrieve the corresponding device name */
DeviceName.SymbolicLinkNameOffset = DeviceName.UniqueIdOffset = 0;
DeviceName.SymbolicLinkNameLength = DeviceName.UniqueIdLength = 0;
DeviceName.DeviceNameOffset = (ULONG_PTR)&DeviceName.DeviceName - (ULONG_PTR)&DeviceName;
DeviceName.DeviceNameLength = VolumeName->Length;
RtlCopyMemory(&DeviceName.DeviceName, VolumeName->Buffer, VolumeName->Length);
/* Now, query the MountMgr for the DOS path */
RtlInitUnicodeString(&MountMgrDevice, MOUNTMGR_DEVICE_NAME);
InitializeObjectAttributes(&ObjectAttributes,
&MountMgrDevice,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(&Handle,
FILE_READ_ATTRIBUTES | SYNCHRONIZE, // FILE_READ_DATA
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
return Status;
}
MountPointsPtr = NULL;
Status = NtDeviceIoControlFile(Handle,
NULL, NULL, NULL,
&IoStatusBlock,
IOCTL_MOUNTMGR_QUERY_POINTS,
&DeviceName, sizeof(DeviceName),
&MountPoints, sizeof(MountPoints));
/* Only tolerated failure here is buffer too small, which is expected */
if (!NT_SUCCESS(Status) && (Status != STATUS_BUFFER_OVERFLOW))
{
goto Quit;
}
/* Compute the needed size to store the mount points list */
Length = MountPoints.Size;
/* Reallocate the memory, even in case of success, because
* that's the buffer that will be returned to the caller */
MountPointsPtr = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, Length);
if (!MountPointsPtr)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quit;
}
/* Re-query the mount points list with proper size */
Status = NtDeviceIoControlFile(Handle,
NULL, NULL, NULL,
&IoStatusBlock,
IOCTL_MOUNTMGR_QUERY_POINTS,
&DeviceName, sizeof(DeviceName),
MountPointsPtr, Length);
if (!NT_SUCCESS(Status))
goto Quit;
/* Find the drive letter amongst the mount points */
for (MountPointsPtr->Size = 0; // Reuse the Size field to store the current index.
MountPointsPtr->Size < MountPointsPtr->NumberOfMountPoints;
MountPointsPtr->Size++)
{
UNICODE_STRING SymLink;
SymLink.Length = SymLink.MaximumLength = MountPointsPtr->MountPoints[MountPointsPtr->Size].SymbolicLinkNameLength;
SymLink.Buffer = (PWCHAR)((ULONG_PTR)MountPointsPtr + MountPointsPtr->MountPoints[MountPointsPtr->Size].SymbolicLinkNameOffset);
if (MOUNTMGR_IS_DRIVE_LETTER(&SymLink))
{
/* Return the drive letter, ensuring it's uppercased */
*DriveLetter = towupper(SymLink.Buffer[12]);
break;
}
}
/* We are done, return success */
Status = STATUS_SUCCESS;
Quit:
if (MountPointsPtr)
RtlFreeHeap(ProcessHeap, 0, MountPointsPtr);
NtClose(Handle);
return Status;
}
/**
* @brief
* Requests the MountMgr to either assign the next available drive letter
* to the given volume, if none already exists, or to retrieve its existing
* associated drive letter.
*
* @param[in] VolumeName
* Device name of the volume.
*
* @param[out] DriveLetter
* Pointer to a WCHAR buffer receiving the corresponding drive letter,
* or UNICODE_NULL if none has been assigned.
*
* @return A status code.
**/
NTSTATUS
GetOrAssignNextVolumeDriveLetter(
_In_ PCUNICODE_STRING VolumeName,
_Out_ PWCHAR DriveLetter)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE Handle;
UNICODE_STRING MountMgrDevice;
MOUNTMGR_DRIVE_LETTER_INFORMATION LetterInfo;
/*
* This variable is used to store the device name
* for the input buffer to IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER.
* It's based on MOUNTMGR_DRIVE_LETTER_TARGET (mountmgr.h).
* Doing it this way prevents memory allocation.
* The device name won't be longer.
*/
struct
{
USHORT DeviceNameLength;
WCHAR DeviceName[256];
} DeviceName;
/* Default to no letter */
*DriveLetter = UNICODE_NULL;
/* First, retrieve the corresponding device name */
DeviceName.DeviceNameLength = VolumeName->Length;
RtlCopyMemory(&DeviceName.DeviceName, VolumeName->Buffer, VolumeName->Length);
/* Now, query the MountMgr for the DOS path */
RtlInitUnicodeString(&MountMgrDevice, MOUNTMGR_DEVICE_NAME);
InitializeObjectAttributes(&ObjectAttributes,
&MountMgrDevice,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(&Handle,
FILE_READ_ATTRIBUTES | SYNCHRONIZE, // FILE_READ_DATA
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
return Status;
}
Status = NtDeviceIoControlFile(Handle,
NULL, NULL, NULL,
&IoStatusBlock,
IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER,
&DeviceName, sizeof(DeviceName),
&LetterInfo, sizeof(LetterInfo));
if (!NT_SUCCESS(Status))
goto Quit;
DPRINT1("DriveLetterWasAssigned = %s, CurrentDriveLetter = %c\n",
LetterInfo.DriveLetterWasAssigned ? "TRUE" : "FALSE",
LetterInfo.CurrentDriveLetter ? LetterInfo.CurrentDriveLetter : '-');
/* Return the drive letter the MountMgr potentially assigned,
* ensuring it's uppercased */
*DriveLetter = towupper(LetterInfo.CurrentDriveLetter);
Quit:
NtClose(Handle);
return Status;
}
/**
* @brief
* Attempts to mount the designated volume, and retrieve and cache
* some of its properties (file system, volume label, ...).
**/
NTSTATUS
MountVolume(
_Inout_ PVOLINFO Volume,
_In_opt_ UCHAR MbrPartitionType)
{
NTSTATUS Status;
UNICODE_STRING Name;
HANDLE VolumeHandle;
/* If the volume is already mounted, just return success */
@@ -128,6 +355,12 @@ MountVolume(
}
}
/* Get the volume drive letter */
__debugbreak();
RtlInitUnicodeString(&Name, Volume->DeviceName);
Status = GetVolumeDriveLetter(&Name, &Volume->DriveLetter);
UNREFERENCED_PARAMETER(Status);
/* Close the volume */
if (VolumeHandle)
NtClose(VolumeHandle);
@@ -215,6 +448,7 @@ DismountVolume(
/* Reset some data only if dismount succeeded */
if (NT_SUCCESS(Status))
{
// TODO: Should we notify MountMgr to delete the drive letter?
Volume->DriveLetter = UNICODE_NULL;
Volume->VolumeLabel[0] = UNICODE_NULL;
Volume->FileSystem[0] = UNICODE_NULL;

View File

@@ -16,6 +16,8 @@ typedef struct _VOLINFO
WCHAR VolumeLabel[20];
WCHAR FileSystem[MAX_PATH+1];
BOOLEAN IsSimpleVolume;
// VOLUME_TYPE VolumeType;
// ULARGE_INTEGER Size;
// PVOLUME_DISK_EXTENTS Extents;
@@ -35,6 +37,12 @@ typedef struct _VOLINFO
(!IsUnknown(VolInfo) && !IsUnformatted(VolInfo))
NTSTATUS
GetOrAssignNextVolumeDriveLetter(
_In_ PCUNICODE_STRING VolumeName,
_Out_ PWCHAR DriveLetter);
// DetectFileSystem()
NTSTATUS
MountVolume(
_Inout_ PVOLINFO Volume,

View File

@@ -15,7 +15,7 @@
#include <guiddef.h>
#include <libs/umpnpmgr/sysguid.h>
/* LOCALS *******************************************************************/
/* LOCALS ********************************************************************/
static HANDLE hEnumKey = NULL;
static HANDLE hServicesKey = NULL;
@@ -36,7 +36,7 @@ typedef struct
WCHAR DeviceIds[ANYSIZE_ARRAY];
} DeviceInstallParams;
/* FUNCTIONS ****************************************************************/
/* FUNCTIONS *****************************************************************/
static BOOLEAN
AreDriversLoaded(
@@ -727,3 +727,145 @@ TerminateUserModePnpManager(VOID)
NtClose(hDeviceInstallListNotEmpty);
hDeviceInstallListNotEmpty = NULL;
}
/* PnP Configuration Manager ENUMERATION API *********************************/
#define _CFGMGR32_
#include <cfgmgr32.h>
static CONFIGRET
NtStatusToCrError(
_In_ NTSTATUS Status)
{
switch (Status)
{
case STATUS_NOT_IMPLEMENTED:
return CR_CALL_NOT_IMPLEMENTED;
case STATUS_INVALID_PARAMETER:
return CR_INVALID_DATA;
case STATUS_NO_SUCH_DEVICE:
return CR_NO_SUCH_DEVINST;
case STATUS_ACCESS_DENIED:
return CR_ACCESS_DENIED;
case STATUS_BUFFER_TOO_SMALL:
return CR_BUFFER_SMALL;
case STATUS_OBJECT_NAME_NOT_FOUND:
return CR_NO_SUCH_VALUE;
default:
return CR_FAILURE;
}
}
// CMAPI
CONFIGRET
WINAPI
CM_Get_Device_Interface_List_SizeW(
_Out_ PULONG pulLen,
_In_ LPGUID InterfaceClassGuid,
_In_opt_ DEVINSTID_W pDeviceID,
_In_ ULONG ulFlags)
{
CONFIGRET ret = CR_SUCCESS;
if (!pulLen)
return CR_INVALID_POINTER;
if (ulFlags & ~CM_GET_DEVICE_INTERFACE_LIST_BITS)
return CR_INVALID_FLAG;
*pulLen = 0;
// PNP_GetInterfaceDeviceListSize()
do
{
NTSTATUS Status;
PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData;
#if 0
if (!IsValidDeviceInstanceID(pDeviceID))
{
ret = CR_INVALID_DEVINST;
break;
}
#endif
RtlInitUnicodeString(&PlugPlayData.DeviceInstance, pDeviceID);
PlugPlayData.FilterGuid = InterfaceClassGuid;
PlugPlayData.Flags = ulFlags;
PlugPlayData.Buffer = NULL;
PlugPlayData.BufferSize = 0;
Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList,
&PlugPlayData,
sizeof(PlugPlayData));
if (NT_SUCCESS(Status))
*pulLen = PlugPlayData.BufferSize;
else
ret = NtStatusToCrError(Status);
} while (0);
return ret;
}
// CMAPI
CONFIGRET
WINAPI
CM_Get_Device_Interface_ListW(
_In_ LPGUID InterfaceClassGuid,
_In_opt_ DEVINSTID_W pDeviceID,
_Out_writes_(BufferLen) PWCHAR Buffer,
_In_ ULONG BufferLen,
_In_ ULONG ulFlags)
{
CONFIGRET ret = CR_SUCCESS;
if (!Buffer || BufferLen == 0)
return CR_INVALID_POINTER;
if (ulFlags & ~CM_GET_DEVICE_INTERFACE_LIST_BITS)
return CR_INVALID_FLAG;
*Buffer = UNICODE_NULL;
// PNP_GetInterfaceDeviceList()
do
{
NTSTATUS Status;
PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData;
#if 0
if (!IsValidDeviceInstanceID(pDeviceID))
{
ret = CR_INVALID_DEVINST;
break;
}
#endif
RtlInitUnicodeString(&PlugPlayData.DeviceInstance, pDeviceID);
PlugPlayData.FilterGuid = InterfaceClassGuid;
PlugPlayData.Flags = ulFlags;
PlugPlayData.Buffer = Buffer;
PlugPlayData.BufferSize = BufferLen;
Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList,
&PlugPlayData,
sizeof(PlugPlayData));
if (NT_SUCCESS(Status))
BufferLen = PlugPlayData.BufferSize;
else
ret = NtStatusToCrError(Status);
} while (0);
return ret;
}
/* EOF */

View File

@@ -92,10 +92,10 @@ GetPartitionTypeString(
}
}
VOID
static VOID
PrettifySize1(
IN OUT PULONGLONG Size,
OUT PCSTR* Unit)
_Inout_ PULONGLONG Size,
_Out_ PCSTR* Unit)
{
ULONGLONG DiskSize = *Size;
@@ -115,10 +115,10 @@ PrettifySize1(
*Size = DiskSize;
}
VOID
static VOID
PrettifySize2(
IN OUT PULONGLONG Size,
OUT PCSTR* Unit)
_Inout_ PULONGLONG Size,
_Out_ PCSTR* Unit)
{
ULONGLONG PartSize = *Size;
@@ -518,6 +518,7 @@ PrintDiskData(
coPos.X = ListUi->Left + 1;
coPos.Y = ListUi->Top + 1 + ListUi->Line;
/* Fill the list background */
if (ListUi->Line >= 0 && ListUi->Line <= Height)
{
FillConsoleOutputAttribute(StdOutput,
@@ -533,6 +534,7 @@ PrintDiskData(
&Written);
}
/* Print the disk description */
coPos.X++;
if (ListUi->Line >= 0 && ListUi->Line <= Height)
{
@@ -611,11 +613,10 @@ DrawPartitionList(
{
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
/* Counts disk description + empty line */
LastLine += 2;
if (CurrentPartLineFound == FALSE)
{
if (!CurrentPartLineFound)
CurrentPartLine += 2;
}
for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
Entry2 != &DiskEntry->PrimaryPartListHead;
@@ -623,19 +624,15 @@ DrawPartitionList(
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
if (PartEntry == ListUi->CurrentPartition)
{
CurrentPartLineFound = TRUE;
}
if (CurrentPartLineFound == FALSE)
{
CurrentPartLine++;
}
/* Counts partition description line */
LastLine++;
if (!CurrentPartLineFound)
CurrentPartLine++;
}
if (CurrentPartLineFound == FALSE)
if (!CurrentPartLineFound)
{
for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
Entry2 != &DiskEntry->LogicalPartListHead;
@@ -643,41 +640,36 @@ DrawPartitionList(
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
if (PartEntry == ListUi->CurrentPartition)
{
CurrentPartLineFound = TRUE;
}
if (CurrentPartLineFound == FALSE)
{
CurrentPartLine++;
}
/* Counts partition description line */
LastLine++;
if (!CurrentPartLineFound)
CurrentPartLine++;
}
}
if (DiskEntry == ListUi->CurrentDisk)
{
CurrentDiskLineFound = TRUE;
}
/* If next disk entry exists, update current lines */
if (Entry->Flink != &List->DiskListHead)
{
if (CurrentDiskLineFound == FALSE)
LastLine++;
if (!CurrentDiskLineFound)
{
CurrentPartLine++;
CurrentDiskLine = CurrentPartLine;
}
LastLine++;
}
/* Otherwise don't */
else
{
LastLine--;
}
}
/* If it possible, make the disk name visible */
/* If possible, make the disk name visible */
if (CurrentPartLine < ListUi->Offset)
{
ListUi->Offset = CurrentPartLine;
@@ -802,12 +794,12 @@ DrawPartitionList(
coPos,
&Written);
}
coPos.X = ListUi->Right - 2;
FillConsoleOutputCharacterA(StdOutput,
CharHorizontalLine, // '-',
2,
coPos,
&Written);
coPos.X = ListUi->Right - 2;
FillConsoleOutputCharacterA(StdOutput,
CharHorizontalLine, // '-',
2,
coPos,
&Written);
}
/* Draw lower right corner */

View File

@@ -1,5 +1,5 @@
[FREELOADER]
DefaultOS=Setup
DefaultOS=Setup_Debug
TimeOut=0
[Display]
@@ -17,7 +17,7 @@ BootType=ReactOSSetup
[Setup_Debug]
BootType=ReactOSSetup
Options=/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /NOGUIBOOT /SIFOPTIONSOVERRIDE
Options=/DEBUG /DEBUGPORT=vbox /NOGUIBOOT /SIFOPTIONSOVERRIDE
[Setup_Aacpi]
BootType=ReactOSSetup

View File

@@ -949,6 +949,7 @@ ClassDispatchPnp(
case IRP_MN_START_DEVICE: {
__debugbreak();
//
// if this is sent to the FDO we should forward it down the
// attachment chain before we start the FDO.

View File

@@ -184,11 +184,13 @@ typedef enum _DISK_USER_WRITE_CACHE_SETTING
typedef struct _DISK_DATA {
#if 0
//
// This field is the ordinal of a partition as it appears on a disk.
//
ULONG PartitionOrdinal;
#endif
//
// How has this disk been partitioned? Either EFI or MBR.
@@ -212,6 +214,7 @@ typedef struct _DISK_DATA {
ULONG MbrCheckSum;
#if 0
//
// Number of hidden sectors for BPB.
//
@@ -243,6 +246,7 @@ typedef struct _DISK_DATA {
//
BOOLEAN BootIndicator;
#endif
} Mbr;
@@ -254,6 +258,7 @@ typedef struct _DISK_DATA {
GUID DiskId;
#if 0
//
// Partition type of this device object.
//
@@ -277,6 +282,7 @@ typedef struct _DISK_DATA {
//
WCHAR PartitionName[36];
#endif
} Efi;

View File

@@ -1649,6 +1649,7 @@ Return Value:
PAGED_CODE();
__debugbreak();
Status = IoReadDiskSignature (Fdo,
fdoExtension->DiskGeometry.BytesPerSector,
&Signature);

View File

@@ -234,6 +234,7 @@ Return Value:
PAGED_CODE();
__debugbreak();
//
// Build the lookaside list for srb's for the physical disk. Should only
// need a couple. If this fails then we don't have an emergency SRB so
@@ -448,6 +449,7 @@ Return Value:
if(!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
__debugbreak();
DiskReadSignature(Fdo);
DiskReadDriveCapacity(Fdo);

View File

@@ -89,8 +89,8 @@ PartitionCreateDevice(
partExt->DeviceName = deviceName;
partExt->StartingOffset = PartitionEntry->StartingOffset.QuadPart;
partExt->PartitionLength = PartitionEntry->PartitionLength.QuadPart;
partExt->OnDiskNumber = PartitionEntry->PartitionNumber; // the "physical" partition number
partExt->DetectedNumber = PdoNumber; // counts only partitions with PDO created
partExt->OnDiskNumber = PartitionEntry->PartitionNumber; // The on-disk partition ordinal // HACK: using PartitionEntry->PartitionNumber is hackish
partExt->DetectedNumber = PdoNumber; // Counts only partitions with PDO created
partExt->VolumeNumber = volumeNum;
// The device is initialized
@@ -114,7 +114,7 @@ PartitionHandleStartDevice(
UNICODE_STRING partitionSymlink, interfaceName;
PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension;
// \\Device\\Harddisk%lu\\Partition%lu
// "\\Device\\Harddisk%lu\\Partition%lu"
swprintf(nameBuf, PartitionSymLinkFormat,
fdoExtension->DiskData.DeviceNumber, PartExt->DetectedNumber);
@@ -296,6 +296,7 @@ PartitionHandleRemove(
UNICODE_STRING partitionSymlink;
PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension;
// "\\Device\\Harddisk%lu\\Partition%lu"
swprintf(nameBuf, PartitionSymLinkFormat,
fdoExtension->DiskData.DeviceNumber, PartExt->DetectedNumber);
@@ -567,6 +568,10 @@ PartitionHandlePnp(
return status;
}
/**
* @brief
* IOCTL dispatcher for partition/volume device objects.
**/
NTSTATUS
PartitionHandleDeviceControl(
_In_ PDEVICE_OBJECT DeviceObject,
@@ -685,12 +690,11 @@ PartitionHandleDeviceControl(
PartMgrAcquireLayoutLock(fdoExtension);
// these functions use on disk numbers, not detected ones
// This function uses on-disk (ordinal) partition numbers, not detected ones
status = IoSetPartitionInformation(fdoExtension->LowerDevice,
fdoExtension->DiskData.BytesPerSector,
partExt->OnDiskNumber,
inputBuffer->PartitionType);
if (NT_SUCCESS(status))
{
partExt->Mbr.PartitionType = inputBuffer->PartitionType;
@@ -712,11 +716,10 @@ PartitionHandleDeviceControl(
PartMgrAcquireLayoutLock(fdoExtension);
// these functions use on disk numbers, not detected ones
// This function uses on-disk (ordinal) partition numbers, not detected ones
status = IoSetPartitionInformationEx(fdoExtension->LowerDevice,
partExt->OnDiskNumber,
inputBuffer);
if (NT_SUCCESS(status))
{
if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR)
@@ -770,9 +773,14 @@ PartitionHandleDeviceControl(
// Partition device should just adjust the starting offset
verifyInfo->StartingOffset.QuadPart += partExt->StartingOffset;
// FIXME:
// - do the addition and check there's no wrapping,
// - check we aren't outside of the partition.
return ForwardIrpAndForget(DeviceObject, Irp);
}
case IOCTL_DISK_UPDATE_PROPERTIES:
case IOCTL_DISK_UPDATE_PROPERTIES: // Here, this is used for volume, but: is this really required?
{
fdoExtension->LayoutValid = FALSE;
IoInvalidateDeviceRelations(fdoExtension->PhysicalDiskDO, BusRelations);
@@ -801,10 +809,16 @@ PartitionHandleDeviceControl(
Irp->IoStatus.Information = sizeof(*deviceNumber);
break;
}
// NOTE: Shouldn't be needed, default: case already does this.
case IOCTL_STORAGE_MEDIA_REMOVAL:
{
return ForwardIrpAndForget(DeviceObject, Irp);
}
// TODO:
// IOCTL_DISK_GET_PARTITION_ATTRIBUTES
// IOCTL_DISK_SET_PARTITION_ATTRIBUTES
// volume stuff (most of that should be in volmgr.sys once it is implemented)
case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
{
@@ -896,6 +910,7 @@ PartitionHandleDeviceControl(
Irp->IoStatus.Information = sizeof(*gptAttrs);
break;
}
// mountmgr notifications (these should be in volmgr.sys once it is implemented)
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
{

View File

@@ -217,7 +217,7 @@ PartMgrUpdatePartitionDevices(
PPARTITION_EXTENSION partExt = CONTAINING_RECORD(curEntry, PARTITION_EXTENSION, ListEntry);
UINT32 partNumber = 0; // count detected partitions for device symlinks
BOOLEAN found = FALSE;
PPARTITION_INFORMATION_EX partEntry;
PPARTITION_INFORMATION_EX partEntry = NULL;
// trying to find this partition in returned layout
for (UINT32 i = 0; i < NewLayout->PartitionCount; i++)
@@ -269,8 +269,8 @@ PartMgrUpdatePartitionDevices(
RtlCopyMemory(partExt->Gpt.Name, partEntry->Gpt.Name, sizeof(partExt->Gpt.Name));
}
partExt->OnDiskNumber = partNumber;
partEntry->PartitionNumber = partNumber; // mark it as a found one
partExt->OnDiskNumber = partNumber; // HACK?? No, here it looks OK; partNumber counted the valid partitions in order of appearance (-> ordinal)
partEntry->PartitionNumber = partNumber; // mark it as a found one // HACK?? Here I think so (should be the PDO number)
totalPartitions++;
}
else
@@ -332,7 +332,7 @@ PartMgrUpdatePartitionDevices(
}
}
partEntry->PartitionNumber = partNumber;
partEntry->PartitionNumber = partNumber; // HACK for the partition ordinal
PDEVICE_OBJECT partitionDevice;
status = PartitionCreateDevice(FdoExtension->DeviceObject,
@@ -352,7 +352,7 @@ PartMgrUpdatePartitionDevices(
totalPartitions++;
// insert the structure to the partition list
// insert the structure in the partition list
curEntry = FdoExtension->PartitionList.Next;
prevEntry = NULL;
while (curEntry != NULL)
@@ -360,7 +360,7 @@ PartMgrUpdatePartitionDevices(
PPARTITION_EXTENSION curPart = CONTAINING_RECORD(curEntry,
PARTITION_EXTENSION,
ListEntry);
if (curPart->OnDiskNumber < partNumber)
if (curPart->OnDiskNumber < partNumber) // HACK: Investigate: should this be OnDiskNumber, or DetectedNumber/PdoNumber?
{
prevEntry = curEntry;
curEntry = curPart->ListEntry.Next;
@@ -373,18 +373,11 @@ PartMgrUpdatePartitionDevices(
PPARTITION_EXTENSION partExt = partitionDevice->DeviceExtension;
if (prevEntry)
{
// insert after prevEntry
partExt->ListEntry.Next = prevEntry->Next;
prevEntry->Next = &partExt->ListEntry;
}
else
{
// insert at the beginning
partExt->ListEntry.Next = FdoExtension->PartitionList.Next;
FdoExtension->PartitionList.Next = &partExt->ListEntry;
}
/* Insert after prevEntry (if != NULL) or at the beginning */
if (!prevEntry)
prevEntry = &FdoExtension->PartitionList;
partExt->ListEntry.Next = prevEntry->Next;
prevEntry->Next = &partExt->ListEntry;
partExt->Attached = TRUE;
}
@@ -422,7 +415,7 @@ PartMgrGetDriveLayout(
return status;
if (FdoExtension->LayoutCache)
ExFreePool(FdoExtension->LayoutCache);
ExFreePoolWithTag(FdoExtension->LayoutCache, TAG_PARTMGR);
FdoExtension->LayoutCache = layoutEx;
FdoExtension->LayoutValid = TRUE;
@@ -444,6 +437,154 @@ PartMgrGetDriveLayout(
return status;
}
/**
* @brief
* Invalidate the partition table cache of the disk (TODO)
* and notify the clients that the disk layout has changed.
**/
static
CODE_SEG("PAGE")
NTSTATUS // VOID
PartMgrInvalidatePartitionTableCache(
_In_ PFDO_EXTENSION FdoExtension) // Or the FDO's DeviceObject?
{
TARGET_DEVICE_CUSTOM_NOTIFICATION notification;
PAGED_CODE();
// NOTE: Win7+ partmgr does here some freeing of layout cache in the FDO...
// ClassInvalidateBusRelations(FdoExtension->DeviceObject);
IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations);
/* Notify everyone that the disk layout has changed */
notification.Event = GUID_IO_DISK_LAYOUT_CHANGE;
notification.Version = 1;
notification.Size = FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer);
notification.FileObject = NULL;
notification.NameBufferOffset = -1;
return IoReportTargetDeviceChangeAsynchronous(FdoExtension->PhysicalDiskDO,
&notification,
NULL,
NULL);
}
/**
* @brief
* Set the given disk drive layout, or reset the disk layout style
* (MBR or GPT) in case the layout's PartitionCount is zero.
*
* @note Requires partitioning lock held.
**/
static
CODE_SEG("PAGE")
NTSTATUS
PartMgrDiskSetDriveLayoutEx(
_In_ PFDO_EXTENSION FdoExtension,
_In_ PDRIVE_LAYOUT_INFORMATION_EX layoutEx) // layoutUser
{
// PDRIVE_LAYOUT_INFORMATION_EX layoutEx;
NTSTATUS status;
PAGED_CODE();
#if 0
SIZE_T layoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]);
layoutSize += layoutUser->PartitionCount * sizeof(PARTITION_INFORMATION_EX);
/* Make a private copy of the structure */
layoutEx = ExAllocatePoolWithTag(PagedPool, layoutSize, TAG_PARTMGR);
if (!layoutEx)
return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyMemory(layoutEx, layoutUser, layoutSize);
#endif
/* If the current disk is super-floppy but the user changes either
* the disk type or the number of partitions to > 1, fail the call */
if (FdoExtension->IsSuperFloppy &&
((layoutEx->PartitionStyle != PARTITION_STYLE_MBR) ||
(layoutEx->PartitionCount > 1)))
{
return STATUS_INVALID_DEVICE_REQUEST;
}
/* If the disk type is MBR, make sure the partitioning does not go beyond
* the 2TB boundary. Since the partition entries must not overlap, it is
* sufficient to check that no partition goes beyond that boundary. */
if (layoutEx->PartitionStyle == PARTITION_STYLE_MBR)
{
for (UINT32 i = 0; i < layoutEx->PartitionCount; i++)
{
PPARTITION_INFORMATION_EX part = &layoutEx->PartitionEntry[i];
ULONGLONG EndOffset = part->StartingOffset.QuadPart + part->PartitionLength.QuadPart;
// In principle, this boundary is: 2^32 * disk_sector_size
// 0x100000000 * FdoExtension->DiskData.BytesPerSector;
if (EndOffset >= 0x20000000000)
{
ERR("Partition crosses 2TB boundary! Failing request.\n");
return STATUS_INVALID_DEVICE_REQUEST;
}
}
}
/* If partition count is 0, it's the same as IOCTL_DISK_CREATE_DISK */
if (layoutEx->PartitionCount == 0)
{
CREATE_DISK createDisk = {0};
createDisk.PartitionStyle = layoutEx->PartitionStyle;
if (createDisk.PartitionStyle == PARTITION_STYLE_MBR)
{
createDisk.Mbr.Signature = layoutEx->Mbr.Signature;
}
else if (createDisk.PartitionStyle == PARTITION_STYLE_GPT)
{
createDisk.Gpt.DiskId = layoutEx->Gpt.DiskId;
}
status = IoCreateDisk(FdoExtension->LowerDevice, &createDisk);
}
else
{
// this in fact updates the bus relations
PartMgrUpdatePartitionDevices(FdoExtension, layoutEx);
/* Write the partition table to the disk */
status = IoWritePartitionTableEx(FdoExtension->LowerDevice, layoutEx);
}
/* Update the layout cache */
if (NT_SUCCESS(status))
{
if (FdoExtension->LayoutCache)
ExFreePoolWithTag(FdoExtension->LayoutCache, TAG_PARTMGR);
FdoExtension->LayoutCache = layoutEx;
FdoExtension->LayoutValid = TRUE;
FdoExtension->IsSuperFloppy = PartMgrIsDiskSuperFloppy(FdoExtension);
}
else
{
FdoExtension->LayoutValid = FALSE;
}
PartMgrInvalidatePartitionTableCache(FdoExtension);
// return the layoutSize value?
return status;
}
//
// This is kind of a HACK: we patch what the disk.sys has read and cached
// as the base partition style with our own information and return it to
// the caller; however, disk.sys still has the old cached information.
// Instead we should always ensure that disk.sys has the correct cached data
// and this means, that this information has to be sent to the disk...
//
static
CODE_SEG("PAGE")
NTSTATUS
@@ -452,30 +593,28 @@ FdoIoctlDiskGetDriveGeometryEx(
_In_ PIRP Irp)
{
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
PDISK_GEOMETRY_EX_INTERNAL geometryEx = Irp->AssociatedIrp.SystemBuffer;
ULONG outBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
NTSTATUS status;
PAGED_CODE();
// We're patching the DISK_PARTITION_INFO part of the returned structure
// as disk.sys doesn't really know about the partition table on a disk
PDISK_GEOMETRY_EX_INTERNAL geometryEx = Irp->AssociatedIrp.SystemBuffer;
ULONG outBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
NTSTATUS status;
status = IssueSyncIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
FdoExtension->LowerDevice,
NULL,
0,
geometryEx,
outBufferLength,
FALSE);
ASSERT(ioStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY_EX);
/* Forward the IOCTL_DISK_GET_DRIVE_GEOMETRY_EX to the disk.sys driver
* before patching the DISK_PARTITION_INFO part of the returned structure.
* Indeed, it doesn't really know about the partition table on a disk. */
status = STATUS_UNSUCCESSFUL;
if (IoForwardIrpSynchronously(FdoExtension->LowerDevice, Irp))
status = Irp->IoStatus.Status;
if (!NT_SUCCESS(status))
{
return status;
}
// if DISK_PARTITION_INFO fits the output size
/* If the DISK_PARTITION_INFO part fits the output size,
* patch it with up-to-date disk partition layout information */
if (outBufferLength >= FIELD_OFFSET(DISK_GEOMETRY_EX_INTERNAL, Detection))
{
PartMgrAcquireLayoutLock(FdoExtension);
@@ -525,6 +664,7 @@ FdoIoctlDiskGetPartitionInfo(
PartMgrAcquireLayoutLock(FdoExtension);
// Alternatively, get the disk size via IOCTL_DISK_GET_LENGTH_INFO
*partInfo = (PARTITION_INFORMATION){
.PartitionType = PARTITION_ENTRY_UNUSED,
.StartingOffset.QuadPart = 0,
@@ -560,6 +700,7 @@ FdoIoctlDiskGetPartitionInfoEx(
PartMgrAcquireLayoutLock(FdoExtension);
// Alternatively, get the disk size via IOCTL_DISK_GET_LENGTH_INFO
// most of the fields a zeroed for Partition0
*partInfoEx = (PARTITION_INFORMATION_EX){
.PartitionLength.QuadPart = FdoExtension->DiskData.DiskSize,
@@ -668,6 +809,7 @@ FdoIoctlDiskSetDriveLayout(
_In_ PIRP Irp)
{
PDRIVE_LAYOUT_INFORMATION layoutInfo = Irp->AssociatedIrp.SystemBuffer;
NTSTATUS status;
PAGED_CODE();
@@ -676,7 +818,7 @@ FdoIoctlDiskSetDriveLayout(
return STATUS_INFO_LENGTH_MISMATCH;
}
size_t layoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[0]);
SIZE_T layoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[0]);
layoutSize += layoutInfo->PartitionCount * sizeof(PARTITION_INFORMATION);
if (!VerifyIrpInBufferSize(Irp, layoutSize))
@@ -685,73 +827,45 @@ FdoIoctlDiskSetDriveLayout(
}
PDRIVE_LAYOUT_INFORMATION_EX layoutEx = PartMgrConvertLayoutToExtended(layoutInfo);
if (layoutEx == NULL)
if (!layoutEx)
{
Irp->IoStatus.Information = 0;
return STATUS_INSUFFICIENT_RESOURCES;
}
PartMgrAcquireLayoutLock(FdoExtension);
// If the current disk is super-floppy but the user changes
// the number of partitions to > 1, fail the call.
if (FdoExtension->IsSuperFloppy && (layoutEx->PartitionCount > 1))
{
PartMgrReleaseLayoutLock(FdoExtension);
return STATUS_INVALID_DEVICE_REQUEST;
}
// this in fact updates the bus relations
PartMgrUpdatePartitionDevices(FdoExtension, layoutEx);
// write the partition table to the disk
NTSTATUS status = IoWritePartitionTableEx(FdoExtension->LowerDevice, layoutEx);
if (NT_SUCCESS(status))
{
// save the layout cache
if (FdoExtension->LayoutCache)
{
ExFreePool(FdoExtension->LayoutCache);
}
FdoExtension->LayoutCache = layoutEx;
FdoExtension->LayoutValid = TRUE;
// set updated partition numbers
for (UINT32 i = 0; i < layoutInfo->PartitionCount; i++)
{
PPARTITION_INFORMATION part = &layoutInfo->PartitionEntry[i];
part->PartitionNumber = layoutEx->PartitionEntry[i].PartitionNumber;
}
FdoExtension->IsSuperFloppy = PartMgrIsDiskSuperFloppy(FdoExtension);
}
else
{
FdoExtension->LayoutValid = FALSE;
}
status = PartMgrDiskSetDriveLayoutEx(FdoExtension, layoutEx);
PartMgrReleaseLayoutLock(FdoExtension);
IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations);
/* Set what we claim to return to the caller */
if (NT_SUCCESS(status))
{
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
SIZE_T OutputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
// notify everyone that the disk layout has changed
TARGET_DEVICE_CUSTOM_NOTIFICATION notification;
if (OutputBufferLength < layoutSize)
{
Irp->IoStatus.Information = OutputBufferLength;
}
else
{
Irp->IoStatus.Information = layoutSize;
notification.Event = GUID_IO_DISK_LAYOUT_CHANGE;
notification.Version = 1;
notification.Size = FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer);
notification.FileObject = NULL;
notification.NameBufferOffset = -1;
/* Return the updated partition numbers */
for (UINT32 i = 0; i < layoutInfo->PartitionCount; i++)
{
PPARTITION_INFORMATION part = &layoutInfo->PartitionEntry[i];
part->PartitionNumber = layoutEx->PartitionEntry[i].PartitionNumber;
}
}
}
IoReportTargetDeviceChangeAsynchronous(FdoExtension->PhysicalDiskDO,
&notification,
NULL,
NULL);
/* In case of failure, free the converted layout; otherwise don't
* do anything because it has been used as the cached layout */
if (!NT_SUCCESS(status))
ExFreePoolWithTag(layoutEx, TAG_PARTMGR);
Irp->IoStatus.Information = layoutSize;
return STATUS_SUCCESS;
return status;
}
static
@@ -761,7 +875,8 @@ FdoIoctlDiskSetDriveLayoutEx(
_In_ PFDO_EXTENSION FdoExtension,
_In_ PIRP Irp)
{
PDRIVE_LAYOUT_INFORMATION_EX layoutEx, layoutUser = Irp->AssociatedIrp.SystemBuffer;
PDRIVE_LAYOUT_INFORMATION_EX layoutUser = Irp->AssociatedIrp.SystemBuffer;
PDRIVE_LAYOUT_INFORMATION_EX layoutEx;
NTSTATUS status;
PAGED_CODE();
@@ -771,7 +886,7 @@ FdoIoctlDiskSetDriveLayoutEx(
return STATUS_INFO_LENGTH_MISMATCH;
}
size_t layoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]);
SIZE_T layoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]);
layoutSize += layoutUser->PartitionCount * sizeof(PARTITION_INFORMATION_EX);
if (!VerifyIrpInBufferSize(Irp, layoutSize))
@@ -790,89 +905,27 @@ FdoIoctlDiskSetDriveLayoutEx(
RtlCopyMemory(layoutEx, layoutUser, layoutSize);
PartMgrAcquireLayoutLock(FdoExtension);
// If the current disk is super-floppy but the user changes either
// the disk type or the number of partitions to > 1, fail the call.
if (FdoExtension->IsSuperFloppy &&
((layoutEx->PartitionStyle != PARTITION_STYLE_MBR) ||
(layoutEx->PartitionCount > 1)))
{
PartMgrReleaseLayoutLock(FdoExtension);
return STATUS_INVALID_DEVICE_REQUEST;
}
// if partition count is 0, it's the same as IOCTL_DISK_CREATE_DISK
if (layoutEx->PartitionCount == 0)
{
CREATE_DISK createDisk = {0};
createDisk.PartitionStyle = layoutEx->PartitionStyle;
if (createDisk.PartitionStyle == PARTITION_STYLE_MBR)
{
createDisk.Mbr.Signature = layoutEx->Mbr.Signature;
}
else if (createDisk.PartitionStyle == PARTITION_STYLE_GPT)
{
createDisk.Gpt.DiskId = layoutEx->Gpt.DiskId;
}
status = IoCreateDisk(FdoExtension->LowerDevice, &createDisk);
}
else
{
// this in fact updates the bus relations
PartMgrUpdatePartitionDevices(FdoExtension, layoutEx);
// write the partition table to the disk
status = IoWritePartitionTableEx(FdoExtension->LowerDevice, layoutEx);
if (NT_SUCCESS(status))
{
// set updated partition numbers
for (UINT32 i = 0; i < layoutEx->PartitionCount; i++)
{
PPARTITION_INFORMATION_EX part = &layoutEx->PartitionEntry[i];
part->PartitionNumber = layoutEx->PartitionEntry[i].PartitionNumber;
}
}
}
// update the layout cache
if (NT_SUCCESS(status))
{
if (FdoExtension->LayoutCache)
{
ExFreePool(FdoExtension->LayoutCache);
}
FdoExtension->LayoutCache = layoutEx;
FdoExtension->LayoutValid = TRUE;
FdoExtension->IsSuperFloppy = PartMgrIsDiskSuperFloppy(FdoExtension);
}
else
{
FdoExtension->LayoutValid = FALSE;
}
status = PartMgrDiskSetDriveLayoutEx(FdoExtension, layoutEx);
PartMgrReleaseLayoutLock(FdoExtension);
IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations);
/* Set what we claim to return to the caller */
if (NT_SUCCESS(status))
{
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
SIZE_T OutputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
// notify everyone that the disk layout has changed
TARGET_DEVICE_CUSTOM_NOTIFICATION notification;
if (OutputBufferLength < layoutSize)
Irp->IoStatus.Information = OutputBufferLength;
else
Irp->IoStatus.Information = layoutSize;
}
notification.Event = GUID_IO_DISK_LAYOUT_CHANGE;
notification.Version = 1;
notification.Size = FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer);
notification.FileObject = NULL;
notification.NameBufferOffset = -1;
/* In case of failure, free the captured layout; otherwise don't
* do anything because it has been used as the cached layout */
if (!NT_SUCCESS(status))
ExFreePoolWithTag(layoutEx, TAG_PARTMGR);
IoReportTargetDeviceChangeAsynchronous(FdoExtension->PhysicalDiskDO,
&notification,
NULL,
NULL);
Irp->IoStatus.Information = layoutSize;
return STATUS_SUCCESS;
return status;
}
static
@@ -888,7 +941,7 @@ FdoIoctlDiskUpdateProperties(
FdoExtension->LayoutValid = FALSE;
PartMgrReleaseLayoutLock(FdoExtension);
IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations);
PartMgrInvalidatePartitionTableCache(FdoExtension);
return STATUS_SUCCESS;
}
@@ -914,7 +967,7 @@ FdoIoctlDiskCreateDisk(
FdoExtension->LayoutValid = FALSE;
PartMgrReleaseLayoutLock(FdoExtension);
IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations);
PartMgrInvalidatePartitionTableCache(FdoExtension);
return status;
}
@@ -936,7 +989,7 @@ FdoIoctlDiskDeleteDriveLayout(
FdoExtension->LayoutValid = FALSE;
PartMgrReleaseLayoutLock(FdoExtension);
IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations);
PartMgrInvalidatePartitionTableCache(FdoExtension);
return status;
}
@@ -1058,10 +1111,10 @@ FdoHandleDeviceRelations(
INFO("Partition style %u\n", FdoExtension->DiskData.PartitionStyle);
// PartMgrRefreshDiskData() calls PartMgrGetDriveLayout() inside
// so we're sure here that it returns only the cached layout.
PDRIVE_LAYOUT_INFORMATION_EX layoutEx;
PartMgrGetDriveLayout(FdoExtension, &layoutEx);
/* PartMgrRefreshDiskData() calls PartMgrGetDriveLayout()
* inside, so we're sure we can use the cached layout */
ASSERT(FdoExtension->LayoutValid);
PDRIVE_LAYOUT_INFORMATION_EX layoutEx = FdoExtension->LayoutCache;
PartMgrUpdatePartitionDevices(FdoExtension, layoutEx);
@@ -1227,6 +1280,10 @@ PartMgrAddDevice(
return STATUS_SUCCESS;
}
/**
* @brief
* IOCTL dispatcher for disk device objects (filter).
**/
static
NTSTATUS
NTAPI
@@ -1238,8 +1295,8 @@ PartMgrDeviceControl(
PFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
NTSTATUS status;
// Note: IRP_MJ_DEVICE_CONTROL handler in the storage stack must be able to pass IOCTLs
// at an IRQL higher than PASSIVE_LEVEL
// Note: IRP_MJ_DEVICE_CONTROL handler in the storage stack
// must be able to pass IOCTLs at an IRQL higher than PASSIVE_LEVEL
INFO("IRP_MJ_DEVICE_CONTROL %p Irp %p IOCTL %x isFdo: %u\n",
DeviceObject, Irp, ioStack->Parameters.DeviceIoControl.IoControlCode, fdoExtension->IsFDO);
@@ -1321,8 +1378,8 @@ PartMgrPnp(
return PartitionHandlePnp(DeviceObject, Irp);
}
switch (ioStack->MinorFunction) {
switch (ioStack->MinorFunction)
{
case IRP_MN_START_DEVICE:
{
NTSTATUS status;
@@ -1362,7 +1419,7 @@ PartMgrPnp(
case IRP_MN_STOP_DEVICE:
{
Irp->IoStatus.Status = STATUS_SUCCESS;
// fallthrough
__fallthrough;
}
default:
{
@@ -1396,6 +1453,7 @@ PartMgrReadWrite(
}
}
// return ForwardIrpAndForget(DeviceObject, Irp);
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(partExt->LowerDevice, Irp);
}
@@ -1434,11 +1492,10 @@ PartMgrPower(
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
else
{
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(partExt->LowerDevice, Irp);
}
// return ForwardIrpAndForget(DeviceObject, Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(partExt->LowerDevice, Irp);
}
DRIVER_DISPATCH PartMgrShutdownFlush;

View File

@@ -97,12 +97,21 @@ typedef struct _PARTITION_EXTENSION
UINT64 PartitionLength;
SINGLE_LIST_ENTRY ListEntry;
UINT32 VolumeNumber; // Volume number in the "\Device\HarddiskVolumeN" device name
/* Volume number in the "\Device\HarddiskVolumeN" name */
UINT32 VolumeNumber;
/* Partition number in the "\Device\HarddiskX\PartitionN" symlink name;
* it is assigned to a partition in order to identify it to the system
* and corresponds to the PDO number given to PartitionCreateDevice() */
UINT32 DetectedNumber;
UINT32 OnDiskNumber; // partition number for issuing Io requests to the kernel
BOOLEAN IsEnumerated; // reported via IRP_MN_QUERY_DEVICE_RELATIONS
/* Partition ordinal (i.e. the order of the partition on a disk),
* used for calling IoSetPartitionInformation(Ex)() API */
UINT32 OnDiskNumber;
BOOLEAN IsEnumerated; //< Reported via IRP_MN_QUERY_DEVICE_RELATIONS
BOOLEAN SymlinkCreated;
BOOLEAN Attached; // attached to PartitionList of the FDO
BOOLEAN Attached; //< Attached to PartitionList of the FDO
union
{
struct
@@ -130,7 +139,7 @@ NTSTATUS
PartitionCreateDevice(
_In_ PDEVICE_OBJECT FDObject,
_In_ PPARTITION_INFORMATION_EX PartitionEntry,
_In_ UINT32 OnDiskNumber,
_In_ UINT32 PdoNumber,
_In_ PARTITION_STYLE PartitionStyle,
_Out_ PDEVICE_OBJECT *PDO);

View File

@@ -12,28 +12,14 @@
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#include <internal/hal.h>
const WCHAR DiskMountString[] = L"\\DosDevices\\%C:";
#define AUTO_DRIVE MAXULONG
#define PARTITION_MAGIC 0xaa55
#define NDEBUG
#include <debug.h>
/* See fstubex.c */
#define EFI_PMBR_OSTYPE_EFI 0xEE
#include <pshpack1.h>
typedef struct _REG_DISK_MOUNT_INFO
{
ULONG Signature;
LARGE_INTEGER StartingOffset;
} REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO;
#include <poppack.h>
typedef enum _DISK_MANAGER
{
NoDiskManager,
@@ -51,10 +37,12 @@ typedef enum _PARTITION_TYPE
DataPartition
} PARTITION_TYPE, *PPARTITION_TYPE;
NTSTATUS
FASTCALL
HalpQueryDriveLayout(IN PUNICODE_STRING DeviceName,
OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
/* PRIVATE FUNCTIONS *********************************************************/
static NTSTATUS
HalpQueryDriveLayout(
_In_ PUNICODE_STRING DeviceName,
_Outptr_ PDRIVE_LAYOUT_INFORMATION* LayoutInfo)
{
IO_STATUS_BLOCK StatusBlock;
PDEVICE_OBJECT DeviceObject = NULL;
@@ -64,6 +52,7 @@ HalpQueryDriveLayout(IN PUNICODE_STRING DeviceName,
NTSTATUS Status;
ULONG BufferSize;
PDRIVE_LAYOUT_INFORMATION Buffer;
PAGED_CODE();
/* Get device pointers */
@@ -93,9 +82,8 @@ HalpQueryDriveLayout(IN PUNICODE_STRING DeviceName,
KeInitializeEvent(&Event, NotificationEvent, FALSE);
do
{
/* If we already had a buffer, it means it's not big
* enough, so free and multiply size by two
*/
/* If we already had a buffer, it means it's not
* big enough, so free and multiply size by two */
if (Buffer != NULL)
{
ExFreePoolWithTag(Buffer, TAG_FSTUB);
@@ -143,7 +131,7 @@ HalpQueryDriveLayout(IN PUNICODE_STRING DeviceName,
/* We're done with the device */
ObDereferenceObject(DeviceObject);
/* If querying worked, then return the buffer to the caller */
/* If querying worked, return the buffer to the caller */
if (NT_SUCCESS(Status))
{
ASSERT(Buffer != NULL);
@@ -161,10 +149,11 @@ HalpQueryDriveLayout(IN PUNICODE_STRING DeviceName,
return Status;
}
NTSTATUS
HalpQueryPartitionType(IN PUNICODE_STRING DeviceName,
IN PDRIVE_LAYOUT_INFORMATION LayoutInfo,
OUT PPARTITION_TYPE PartitionType)
static NTSTATUS
HalpQueryPartitionType(
_In_ PUNICODE_STRING DeviceName,
_In_opt_ PDRIVE_LAYOUT_INFORMATION LayoutInfo,
_Out_ PPARTITION_TYPE PartitionType)
{
USHORT i;
PIRP Irp;
@@ -232,8 +221,7 @@ HalpQueryPartitionType(IN PUNICODE_STRING DeviceName,
/* If we failed querying partition info, try to return something
* if caller didn't provide a precise layout, assume logical
* partition and fake success. Otherwise, just fail.
*/
* partition and fake success. Otherwise, just fail. */
if (!NT_SUCCESS(Status))
{
if (LayoutInfo == NULL)
@@ -245,7 +233,7 @@ HalpQueryPartitionType(IN PUNICODE_STRING DeviceName,
return Status;
}
/* First, handle non MBR style (easy cases) */
/* First, handle non-MBR style (easy case) */
if (PartitionInfo.PartitionStyle != PARTITION_STYLE_MBR)
{
/* If not GPT, we don't know what it is */
@@ -255,10 +243,8 @@ HalpQueryPartitionType(IN PUNICODE_STRING DeviceName,
return STATUS_SUCCESS;
}
/* Check whether that's data partition */
if (RtlCompareMemory(&PartitionInfo.Gpt.PartitionType,
&PARTITION_BASIC_DATA_GUID,
sizeof(GUID)) == sizeof(GUID))
/* Check whether this is a data partition */
if (IsEqualGUID(&PartitionInfo.Gpt.PartitionType, &PARTITION_BASIC_DATA_GUID))
{
*PartitionType = DataPartition;
return STATUS_SUCCESS;
@@ -290,8 +276,8 @@ HalpQueryPartitionType(IN PUNICODE_STRING DeviceName,
return STATUS_SUCCESS;
}
/* Now, evaluate the partition to the 4 in the input layout */
for (i = 0; i < 4; ++i)
/* Now, evaluate the partition to those in the input layout */
for (i = 0; i < NUM_PARTITION_TABLE_ENTRIES; ++i)
{
/* If we find a partition matching */
if (LayoutInfo->PartitionEntry[i].StartingOffset.QuadPart == PartitionInfo.StartingOffset.QuadPart)
@@ -316,8 +302,9 @@ HalpQueryPartitionType(IN PUNICODE_STRING DeviceName,
return STATUS_SUCCESS;
}
PULONG
IopComputeHarddiskDerangements(IN ULONG DiskCount)
static PULONG
IopComputeHarddiskDerangements(
_In_ ULONG DiskCount)
{
PIRP Irp;
KEVENT Event;
@@ -352,8 +339,13 @@ IopComputeHarddiskDerangements(IN ULONG DiskCount)
/* Using their ARC name */
swprintf(Buffer, L"\\ArcName\\multi(0)disk(0)rdisk(%d)", i);
RtlInitUnicodeString(&ArcName, Buffer);
/* Get the attached DeviceObject */
if (NT_SUCCESS(IoGetDeviceObjectPointer(&ArcName, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject)))
Status = IoGetDeviceObjectPointer(&ArcName,
FILE_READ_ATTRIBUTES,
&FileObject,
&DeviceObject);
if (NT_SUCCESS(Status))
{
DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
ObDereferenceObject(FileObject);
@@ -437,9 +429,10 @@ IopComputeHarddiskDerangements(IN ULONG DiskCount)
return Devices;
}
NTSTATUS
HalpNextMountLetter(IN PUNICODE_STRING DeviceName,
OUT PUCHAR DriveLetter)
static NTSTATUS
HalpNextMountLetter(
_In_ PUNICODE_STRING DeviceName,
_Out_ PUCHAR DriveLetter)
{
PIRP Irp;
KEVENT Event;
@@ -476,7 +469,7 @@ HalpNextMountLetter(IN PUNICODE_STRING DeviceName,
Target->DeviceNameLength = DeviceName->Length;
RtlCopyMemory(&Target->DeviceName[0], DeviceName->Buffer, DeviceName->Length);
/* Call the mount manager */
/* Call the MountMgr */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER,
DeviceObject,
@@ -518,9 +511,10 @@ HalpNextMountLetter(IN PUNICODE_STRING DeviceName,
return Status;
}
NTSTATUS
HalpSetMountLetter(IN PUNICODE_STRING DeviceName,
UCHAR DriveLetter)
static NTSTATUS
HalpSetMountLetter(
_In_ PUNICODE_STRING DeviceName,
_In_ UCHAR DriveLetter)
{
PIRP Irp;
KEVENT Event;
@@ -603,29 +597,31 @@ HalpSetMountLetter(IN PUNICODE_STRING DeviceName,
return Status;
}
UCHAR
HalpNextDriveLetter(IN PUNICODE_STRING DeviceName,
IN PSTRING NtDeviceName,
OUT PUCHAR NtSystemPath,
BOOLEAN IsRemovable)
static UCHAR
HalpNextDriveLetter(
_In_ PUNICODE_STRING DeviceName,
_In_ PSTRING NtDeviceName,
_Out_ PUCHAR NtSystemPath,
_In_ BOOLEAN IsRemovable)
{
static const UNICODE_STRING FloppyString = RTL_CONSTANT_STRING(L"\\Device\\Floppy");
static const UNICODE_STRING CdString = RTL_CONSTANT_STRING(L"\\Device\\CdRom");
UCHAR i;
WCHAR Buffer[40];
UCHAR DriveLetter;
UNICODE_STRING FloppyString, CdString, NtDeviceNameU, DosDevice;
UNICODE_STRING NtDeviceNameU, DosDevice;
/* Quick path, ask directly the mount manager to assign the next
* free drive letter
*/
/* Quick path, ask directly the MountMgr
* to assign the next free drive letter */
if (NT_SUCCESS(HalpNextMountLetter(DeviceName, &DriveLetter)))
{
return DriveLetter;
}
/* We'll allow MountMgr to fail only for non vital path */
/* We'll allow the MountMgr to fail only for non vital path */
if (NtDeviceName == NULL || NtSystemPath == NULL)
{
return -1;
return 0xFF;
}
/* And for removable devices */
@@ -635,15 +631,13 @@ HalpNextDriveLetter(IN PUNICODE_STRING DeviceName,
}
/* Removable might be floppy or cdrom */
RtlInitUnicodeString(&FloppyString, L"\\Device\\Floppy");
RtlInitUnicodeString(&CdString, L"\\Device\\CdRom");
/* If floppy, start at A */
if (RtlPrefixUnicodeString(&FloppyString, DeviceName, TRUE))
{
DriveLetter = 'A';
}
/* If CD start C */
/* If CD start at D */
else if (RtlPrefixUnicodeString(&CdString, DeviceName, TRUE))
{
DriveLetter = 'D';
@@ -677,11 +671,11 @@ HalpNextDriveLetter(IN PUNICODE_STRING DeviceName,
/* Last fall back, we're not on a PnP device... */
for (i = DriveLetter; i <= 'Z'; ++i)
{
/* We'll link manually, without MountMgr knowing anything about the device */
/* We'll link manually, without the MountMgr knowing anything about the device */
swprintf(Buffer, L"\\DosDevices\\%c:", i);
RtlInitUnicodeString(&DosDevice, Buffer);
/* If linking worked, then the letter was free ;-) */
/* If linking worked, the letter was free ;-) */
if (NT_SUCCESS(IoCreateSymbolicLink(&DosDevice, DeviceName)))
{
/* If it worked, if we were managing system path, update manually */
@@ -703,8 +697,9 @@ HalpNextDriveLetter(IN PUNICODE_STRING DeviceName,
return 0;
}
BOOLEAN
HalpIsOldStyleFloppy(PUNICODE_STRING DeviceName)
static BOOLEAN
HalpIsOldStyleFloppy(
_In_ PUNICODE_STRING DeviceName)
{
PIRP Irp;
KEVENT Event;
@@ -713,21 +708,21 @@ HalpIsOldStyleFloppy(PUNICODE_STRING DeviceName)
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK IoStatusBlock;
PAGED_CODE();
/* Get the attached device object to our device */
if (!NT_SUCCESS(IoGetDeviceObjectPointer(DeviceName,
FILE_READ_ATTRIBUTES,
&FileObject,
&DeviceObject)))
{
Status = IoGetDeviceObjectPointer(DeviceName,
FILE_READ_ATTRIBUTES,
&FileObject,
&DeviceObject);
if (!NT_SUCCESS(Status))
return FALSE;
}
DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
ObDereferenceObject(FileObject);
/* Query its device name (ie, check floppy.sys implements MountMgr interface) */
/* Query its device name (i.e. check floppy.sys implements MountMgr interface) */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
DeviceObject,
@@ -756,14 +751,14 @@ HalpIsOldStyleFloppy(PUNICODE_STRING DeviceName)
}
/* If status is not STATUS_BUFFER_OVERFLOW, it means
* it's pre-mountmgr driver, aka "Old style".
*/
* it's a pre-MountMgr driver, aka "Old style" */
ObDereferenceObject(DeviceObject);
return (Status != STATUS_BUFFER_OVERFLOW);
}
NTSTATUS
HalpDeleteMountLetter(UCHAR DriveLetter)
static NTSTATUS
HalpDeleteMountLetter(
_In_ UCHAR DriveLetter)
{
PIRP Irp;
KEVENT Event;
@@ -781,7 +776,7 @@ HalpDeleteMountLetter(UCHAR DriveLetter)
swprintf(Buffer, L"\\DosDevices\\%c:", DriveLetter);
RtlInitUnicodeString(&DosDevice, Buffer);
/* Allocate the input buffer for MountMgr */
/* Allocate the input buffer for the MountMgr */
InputBufferLength = DosDevice.Length + sizeof(MOUNTMGR_MOUNT_POINT);
InputBuffer = ExAllocatePoolWithTag(PagedPool, InputBufferLength, TAG_FSTUB);
if (InputBuffer == NULL)
@@ -816,7 +811,7 @@ HalpDeleteMountLetter(UCHAR DriveLetter)
return Status;
}
/* Call the mount manager to delete the drive letter */
/* Call the MountMgr to delete the drive letter */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_DELETE_POINTS,
DeviceObject,
@@ -853,7 +848,7 @@ HalpDeleteMountLetter(UCHAR DriveLetter)
return Status;
}
VOID
static VOID
HalpEnableAutomaticDriveLetterAssignment(VOID)
{
PIRP Irp;
@@ -923,12 +918,12 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
BOOLEAN SystemFound;
IO_STATUS_BLOCK StatusBlock;
PARTITION_TYPE PartitionType;
ANSI_STRING StringA1, StringA2;
PSTR Buffer1, Buffer2, LoadOptions;
PWSTR Buffer1, Buffer2;
PSTR LoadOptions;
OBJECT_ATTRIBUTES ObjectAttributes;
PDRIVE_LAYOUT_INFORMATION LayoutInfo;
PCONFIGURATION_INFORMATION ConfigInfo;
UNICODE_STRING StringU1, StringU2, StringU3;
UNICODE_STRING StringU1, StringU2;
ULONG Increment, DiskCount, RealDiskCount, HarddiskCount, PartitionCount, SystemPartition;
PAGED_CODE();
@@ -938,11 +933,12 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
DiskCount = ConfigInfo->DiskCount;
RealDiskCount = 0;
/* Allocate two generic string buffers we'll use and reuser later on */
Buffer1 = ExAllocatePoolWithTag(NonPagedPool, 128, TAG_FSTUB);
Buffer2 = ExAllocatePoolWithTag(NonPagedPool, 64, TAG_FSTUB);
/* Allocate two generic string buffers we'll use later on */
Buffer1 = ExAllocatePoolWithTag(NonPagedPool, 128 * sizeof(WCHAR), TAG_FSTUB);
Buffer2 = ExAllocatePoolWithTag(NonPagedPool, 64 * sizeof(WCHAR), TAG_FSTUB);
if (Buffer1 == NULL || Buffer2 == NULL)
{
/* We cannot fail */
KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
}
@@ -992,64 +988,52 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
RtlInitString(NtSystemPathString, (PSTR)NtSystemPath);
}
__debugbreak();
/* For each of our disks, create the physical device DOS device */
Increment = 0;
if (DiskCount != 0)
for (i = 0; i < DiskCount; ++i)
{
for (i = 0; i < DiskCount; ++i)
/* Setup the origin name */
swprintf(Buffer1, L"\\Device\\Harddisk%d\\Partition%d", i, 0);
RtlInitUnicodeString(&StringU1, Buffer1);
/* Open the device */
InitializeObjectAttributes(&ObjectAttributes,
&StringU1,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenFile(&FileHandle,
SYNCHRONIZE | FILE_READ_DATA,
&ObjectAttributes,
&StatusBlock,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(Status))
{
/* Setup the origin name */
sprintf(Buffer1, "\\Device\\Harddisk%d\\Partition%d", i, 0);
RtlInitAnsiString(&StringA1, Buffer1);
if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&StringU1, &StringA1, TRUE)))
/* If we succeeded, create the link */
swprintf(Buffer2, L"\\DosDevices\\PhysicalDrive%d", i);
RtlInitUnicodeString(&StringU2, Buffer2);
IoCreateSymbolicLink(&StringU2, &StringU1);
ZwClose(FileHandle);
RealDiskCount = i + 1;
}
if (!NT_SUCCESS(Status))
{
/* Try coping with holes in the \Device\HarddiskX namespace */
if (Increment < 50)
{
/* We cannot fail */
KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
}
/* Open the device */
InitializeObjectAttributes(&ObjectAttributes,
&StringU1,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenFile(&FileHandle,
SYNCHRONIZE | FILE_READ_DATA,
&ObjectAttributes,
&StatusBlock,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(Status))
{
/* If we managed, create the link */
sprintf(Buffer2, "\\DosDevices\\PhysicalDrive%d", i);
RtlInitAnsiString(&StringA2, Buffer2);
Status = RtlAnsiStringToUnicodeString(&StringU2, &StringA2, TRUE);
if (NT_SUCCESS(Status))
{
IoCreateSymbolicLink(&StringU2, &StringU1);
RtlFreeUnicodeString(&StringU2);
}
ZwClose(FileHandle);
RealDiskCount = i + 1;
}
RtlFreeUnicodeString(&StringU1);
if (!NT_SUCCESS(Status))
{
if (Increment < 50)
{
++Increment;
++DiskCount;
}
++Increment;
++DiskCount;
}
}
}
/* We done for our buffers */
/* We are done with our buffers */
ExFreePoolWithTag(Buffer1, TAG_FSTUB);
ExFreePoolWithTag(Buffer2, TAG_FSTUB);
@@ -1078,100 +1062,65 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
/* Compute our disks derangements */
DiskCount -= Increment;
if (RealDiskCount > DiskCount)
{
DiskCount = RealDiskCount;
}
DiskCount = max(DiskCount, RealDiskCount);
Devices = IopComputeHarddiskDerangements(DiskCount);
/* Now, start browsing all our disks for assigning drive letters
* Here, we'll only handle boot partition and primary partitions
*/
HarddiskCount = 0;
/* Now, start browsing all our disks for assigning drive letters.
* Here, we'll only handle boot partition and primary partitions. */
for (i = 0; i < DiskCount; ++i)
{
/* Get device ID according to derangements map */
if (Devices != NULL)
{
HarddiskCount = Devices[i];
}
HarddiskCount = (Devices ? Devices[i] : i);
/* Query disk layout */
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
RtlInitUnicodeString(&StringU1, Buffer);
if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
{
Status = HalpQueryDriveLayout(&StringU1, &LayoutInfo);
if (!NT_SUCCESS(Status))
LayoutInfo = NULL;
}
/* Assume we didn't find system */
SystemFound = FALSE;
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, 1);
RtlInitUnicodeString(&StringU1, Buffer);
/* Query partition info for our disk */
if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
for (PartitionCount = 1; ; ++PartitionCount)
{
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
RtlInitUnicodeString(&StringU1, Buffer);
Status = HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType);
if (!NT_SUCCESS(Status))
{
/* It failed, retry for all the partitions */
break;
}
/* If our partition is bootable (MBR) or data (GPT), that's the system partition */
if (PartitionType == BootablePartition || PartitionType == DataPartition)
{
SystemFound = TRUE;
/* Assign a drive letter and stop here if MBR */
HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, FALSE);
if (PartitionType == BootablePartition)
break;
}
/* Keep looping on all the partitions */
}
/* Mount every primary partition if we didn't find system */
if (!SystemFound)
{
/* It failed, retry for all the partitions */
for (PartitionCount = 1; ; ++PartitionCount)
{
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
RtlInitUnicodeString(&StringU1, Buffer);
if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
{
Status = HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType);
if (!NT_SUCCESS(Status))
break;
}
/* We found a primary partition, assign a drive letter */
if (PartitionType == PrimaryPartition)
{
HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
break;
}
}
}
else
{
/* All right */
for (PartitionCount = 2; ; ++PartitionCount)
{
/* If our partition is bootable (MBR) or data (GPT), that's system partition */
if (PartitionType == BootablePartition || PartitionType == DataPartition)
{
SystemFound = TRUE;
/* Assign a drive letter and stop here if MBR */
HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
if (PartitionType == BootablePartition)
{
break;
}
}
/* Keep looping on all the partitions */
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
RtlInitUnicodeString(&StringU1, Buffer);
if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
{
/* Mount every primary partition if we didn't find system */
if (!SystemFound)
{
for (PartitionCount = 1; ; ++PartitionCount)
{
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
RtlInitUnicodeString(&StringU1, Buffer);
if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
{
break;
}
if (PartitionType == PrimaryPartition)
{
HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
break;
}
}
}
HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, FALSE);
break;
}
}
@@ -1182,51 +1131,40 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
{
ExFreePoolWithTag(LayoutInfo, TAG_FSTUB);
}
HarddiskCount = i + 1;
}
/* Now, assign logical partitions */
for (i = 0; i < DiskCount; ++i)
{
/* Get device ID according to derangements map */
if (Devices != NULL)
{
HarddiskCount = Devices[i];
}
else
{
HarddiskCount = i;
}
HarddiskCount = (Devices ? Devices[i] : i);
/* Query device layout */
/* Query disk layout */
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
RtlInitUnicodeString(&StringU1, Buffer);
if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
{
Status = HalpQueryDriveLayout(&StringU1, &LayoutInfo);
if (!NT_SUCCESS(Status))
LayoutInfo = NULL;
}
/* And assign drive letter to logical partitions */
for (PartitionCount = 1; ; ++PartitionCount)
{
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
RtlInitUnicodeString(&StringU1, Buffer);
if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
{
Status = HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType);
if (!NT_SUCCESS(Status))
break;
}
if (PartitionType == LogicalPartition)
{
HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, FALSE);
}
}
/* Free layout, we'll reallocate it for next device */
if (LayoutInfo != NULL)
{
ExFreePoolWithTag(LayoutInfo, 0);
ExFreePoolWithTag(LayoutInfo, TAG_FSTUB);
}
}
@@ -1234,22 +1172,14 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
for (i = 0; i < DiskCount; ++i)
{
/* Get device ID according to derangements map */
if (Devices != NULL)
{
HarddiskCount = Devices[i];
}
else
{
HarddiskCount = i;
}
HarddiskCount = (Devices ? Devices[i] : i);
/* Query device layout */
/* Query disk layout */
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
RtlInitUnicodeString(&StringU1, Buffer);
if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
{
Status = HalpQueryDriveLayout(&StringU1, &LayoutInfo);
if (!NT_SUCCESS(Status))
LayoutInfo = NULL;
}
/* Save system partition if any */
SystemPartition = 0;
@@ -1257,12 +1187,12 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
{
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
RtlInitUnicodeString(&StringU1, Buffer);
if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
{
Status = HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType);
if (!NT_SUCCESS(Status))
break;
}
if ((PartitionType == BootablePartition || PartitionType == PrimaryPartition) && (SystemPartition == 0))
if ((PartitionType == BootablePartition) ||
((PartitionType == PrimaryPartition) && (SystemPartition == 0)))
{
SystemPartition = PartitionCount;
}
@@ -1271,26 +1201,25 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
/* And assign drive letter to anything but system partition */
for (PartitionCount = 1; ; ++PartitionCount)
{
if (PartitionCount != SystemPartition)
if (PartitionCount == SystemPartition)
continue;
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
RtlInitUnicodeString(&StringU1, Buffer);
Status = HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType);
if (!NT_SUCCESS(Status))
break;
if (PartitionType == PrimaryPartition || PartitionType == FtPartition)
{
swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
RtlInitUnicodeString(&StringU1, Buffer);
if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
{
if (LayoutInfo != NULL)
{
ExFreePoolWithTag(LayoutInfo, 0);
}
break;
}
if (PartitionType == PrimaryPartition || PartitionType == FtPartition)
{
HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
}
HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, FALSE);
}
}
if (LayoutInfo != NULL)
{
ExFreePoolWithTag(LayoutInfo, TAG_FSTUB);
}
}
/* We're done with disks, if we have a device map, free it */
@@ -1330,9 +1259,10 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
*NtSystemPath = DriveLetter;
}
}
/* If it fails through mount manager, retry manually */
/* If it fails through the MountMgr, retry manually */
else
{
UNICODE_STRING StringU3;
RtlInitUnicodeString(&StringU2, L"\\Device\\Floppy");
RtlInitUnicodeString(&StringU3, L"\\Device\\CdRom");
@@ -1353,41 +1283,34 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
while (HalpSetMountLetter(&StringU1, DriveLetter) != STATUS_SUCCESS)
{
++DriveLetter;
if (DriveLetter > 'Z')
{
break;
}
}
/* If we're beyond Z (ie, no slot left) */
/* If we're beyond Z (i.e. no slot left),
* delete Z and reuse it for system */
if (DriveLetter > 'Z')
{
/* Delete Z, and reuse it for system */
HalpDeleteMountLetter('Z');
HalpSetMountLetter(&StringU1, 'Z');
*NtSystemPath = 'Z';
}
else
{
/* Return matching drive letter */
*NtSystemPath = DriveLetter;
DriveLetter = 'Z';
HalpDeleteMountLetter(DriveLetter);
HalpSetMountLetter(&StringU1, DriveLetter);
}
/* Return matching drive letter */
*NtSystemPath = DriveLetter;
}
RtlFreeUnicodeString(&StringU1);
}
/* Enable auto assignement for mountmgr */
/* Enable auto assignment for MountMgr */
HalpEnableAutomaticDriveLetterAssignment();
}
/* PRIVATE FUNCTIONS *********************************************************/
NTSTATUS
NTAPI
HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject,
OUT PDISK_GEOMETRY_EX Geometry)
static NTSTATUS
HalpGetFullGeometry(
_In_ PDEVICE_OBJECT DeviceObject,
_Out_ PDISK_GEOMETRY_EX Geometry)
{
PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
@@ -1436,22 +1359,24 @@ HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject,
return Status;
}
BOOLEAN
NTAPI
HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry,
IN ULONGLONG MaxOffset,
IN ULONGLONG MaxSector)
static BOOLEAN
HalpIsValidPartitionEntry(
_In_ PPARTITION_DESCRIPTOR Entry,
_In_ ULONGLONG MaxOffset,
_In_ ULONGLONG MaxSector)
{
ULONGLONG EndingSector;
PAGED_CODE();
/* Unused partitions are considered valid */
if (Entry->PartitionType == PARTITION_ENTRY_UNUSED) return TRUE;
if (Entry->PartitionType == PARTITION_ENTRY_UNUSED)
return TRUE;
/* Get the last sector of the partition */
EndingSector = GET_STARTING_SECTOR(Entry) + GET_PARTITION_LENGTH(Entry);
/* Check if it's more then the maximum sector */
/* Check if it's more than the maximum sector */
if (EndingSector > MaxSector)
{
/* Invalid partition */
@@ -1477,21 +1402,22 @@ HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry,
return TRUE;
}
VOID
NTAPI
HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset,
IN PLARGE_INTEGER PartitionLength,
IN CCHAR ShiftCount,
IN ULONG SectorsPerTrack,
IN ULONG NumberOfTracks,
IN ULONG ConventionalCylinders,
OUT PPARTITION_DESCRIPTOR PartitionDescriptor)
static VOID
HalpCalculateChsValues(
_In_ PLARGE_INTEGER PartitionOffset,
_In_ PLARGE_INTEGER PartitionLength,
_In_ CCHAR ShiftCount,
_In_ ULONG SectorsPerTrack,
_In_ ULONG NumberOfTracks,
_In_ ULONG ConventionalCylinders,
_Out_ PPARTITION_DESCRIPTOR PartitionDescriptor)
{
LARGE_INTEGER FirstSector, SectorCount;
ULONG LastSector, Remainder, SectorsPerCylinder;
ULONG StartingCylinder, EndingCylinder;
ULONG StartingTrack, EndingTrack;
ULONG StartingSector, EndingSector;
PAGED_CODE();
/* Calculate the number of sectors for each cylinder */
@@ -1616,7 +1542,7 @@ xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject,
/* Return the cylinder count */
*ConventionalCylinders = DiskGeometry->Cylinders.LowPart;
/* Make sure it's not larger then 1024 */
/* Make sure it's not larger than 1024 */
if (DiskGeometry->Cylinders.LowPart >= 1024)
{
/* Otherwise, normalize the value */
@@ -1700,7 +1626,7 @@ xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
Status = IoStatusBlock.Status;
}
/* Check driver Status */
/* Check driver status */
if (NT_SUCCESS(Status))
{
/* Validate the MBR Signature */
@@ -1768,7 +1694,7 @@ FASTCALL
xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize,
IN BOOLEAN ReturnRecognizedPartitions,
IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
{
KEVENT Event;
IO_STATUS_BLOCK IoStatusBlock;
@@ -1947,7 +1873,7 @@ xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
/* Increase the count of containers */
if (++k != 1)
{
/* More then one table is invalid */
/* More than one table is invalid */
DPRINT1("FSTUB: Multiple container partitions found in "
"partition table %d\n - table is invalid\n",
j);
@@ -2019,11 +1945,9 @@ xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
if (PartitionType != PARTITION_ENTRY_UNUSED)
{
/* Check if it's bootable */
PartitionInfo->BootIndicator = PartitionDescriptor->
ActiveFlag & 0x80 ?
TRUE : FALSE;
PartitionInfo->BootIndicator = !!(PartitionDescriptor->ActiveFlag & 0x80);
/* Check if its' a container */
/* Check if it's a container */
if (IsContainerPartition(PartitionType))
{
/* Then don't recognize it and use the volume offset */
@@ -2054,10 +1978,6 @@ xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
PartitionInfo->PartitionLength.QuadPart =
UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor),
SectorSize);
/* Get the partition number */
/* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
PartitionInfo->PartitionNumber = (!IsContainerPartition(PartitionType)) ? i + 1 : 0;
}
else
{
@@ -2067,10 +1987,10 @@ xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
PartitionInfo->StartingOffset.QuadPart = 0;
PartitionInfo->PartitionLength.QuadPart = 0;
PartitionInfo->HiddenSectors = 0;
/* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
PartitionInfo->PartitionNumber = 0;
}
/* Invalidate the partition number (recalculated by the PartMgr) */
PartitionInfo->PartitionNumber = -1;
}
/* Finish debug log, and check for failure */
@@ -2162,8 +2082,8 @@ xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
PartitionInfo->StartingOffset.QuadPart = 0;
PartitionInfo->PartitionLength = DiskGeometryEx.DiskSize;
/* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
PartitionInfo->PartitionNumber = 0;
/* Invalidate the partition number (recalculated by the PartMgr) */
PartitionInfo->PartitionNumber = -1;
/* Set the signature and set the count back to 0 */
(*PartitionBuffer)->Signature = 1;
@@ -2697,7 +2617,7 @@ FASTCALL
IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize,
IN BOOLEAN ReturnRecognizedPartitions,
IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
{
return HALDISPATCH->HalIoReadPartitionTable(DeviceObject,
SectorSize,

View File

@@ -94,17 +94,11 @@ C_ASSERT(sizeof(MASTER_BOOT_RECORD) == 512);
#define EFI_GUID_STRING_SIZE 0x27
#define IS_VALID_DISK_INFO(Disk) \
(Disk) && \
(Disk->DeviceObject) && \
(Disk->SectorSize) && \
(Disk->Buffer) && \
(Disk->SectorCount)
VOID
NTAPI
FstubDbgPrintPartitionEx(IN PPARTITION_INFORMATION_EX PartitionEntry,
IN ULONG PartitionNumber
);
((Disk) && \
((Disk)->DeviceObject) && \
((Disk)->SectorSize) && \
((Disk)->Buffer) && \
((Disk)->SectorCount))
NTSTATUS
NTAPI
@@ -188,9 +182,8 @@ FstubAdjustPartitionCount(IN ULONG SectorSize,
}
/* Then, ensure that we will have a round value,
* ie, all sectors will be full of entries
* There won't be lonely entries
*/
* i.e. all sectors will be full of entries.
* There won't be lonely entries. */
Count = (Count * PARTITION_ENTRY_SIZE) / SectorSize;
Count = (Count * SectorSize) / PARTITION_ENTRY_SIZE;
ASSERT(*PartitionCount <= Count);
@@ -530,34 +523,32 @@ FstubCreateDiskRaw(IN PDEVICE_OBJECT DeviceObject)
return Status;
}
PCHAR
NTAPI
FstubDbgGuidToString(IN PGUID Guid,
OUT PCHAR String)
#ifndef NDEBUG
static __inline
VOID
FstubDbgGuidToString(
_In_ PGUID Guid,
_Out_ PCHAR String)
{
sprintf(String,
"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
Guid->Data1,
Guid->Data2,
Guid->Data3,
Guid->Data4[0],
Guid->Data4[1],
Guid->Data4[2],
Guid->Data4[3],
Guid->Data4[4],
Guid->Data4[5],
Guid->Data4[6],
Guid->Data4[7]);
return String;
Guid->Data1, Guid->Data2, Guid->Data3,
Guid->Data4[0], Guid->Data4[1], Guid->Data4[2], Guid->Data4[3],
Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]);
}
VOID
NTAPI
FstubDbgPrintDriveLayoutEx(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
static VOID
FstubDbgPrintPartitionEx(
_In_ PPARTITION_INFORMATION_EX PartitionEntry,
_In_ ULONG PartitionNumber);
#endif // !NDEBUG
static VOID
FstubDbgPrintDriveLayoutEx(
_In_ PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
{
#ifndef NDEBUG
ULONG i;
CHAR Guid[EFI_GUID_STRING_SIZE];
PAGED_CODE();
@@ -565,104 +556,116 @@ FstubDbgPrintDriveLayoutEx(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
switch (DriveLayout->PartitionStyle)
{
case PARTITION_STYLE_MBR:
if (DriveLayout->PartitionCount % 4 != 0)
{
if (DriveLayout->PartitionCount % NUM_PARTITION_TABLE_ENTRIES != 0)
{
DPRINT("Warning: Partition count isn't a 4-factor: %lu!\n", DriveLayout->PartitionCount);
DbgPrint(" Warning: Partition count isn't a 4-factor: %lu!\n", DriveLayout->PartitionCount);
}
DPRINT("Signature: %8.8x\n", DriveLayout->Mbr.Signature);
DbgPrint(" Signature: %8.8x\n", DriveLayout->Mbr.Signature);
for (i = 0; i < DriveLayout->PartitionCount; i++)
{
FstubDbgPrintPartitionEx(DriveLayout->PartitionEntry, i);
}
break;
}
case PARTITION_STYLE_GPT:
{
CHAR Guid[EFI_GUID_STRING_SIZE];
FstubDbgGuidToString(&(DriveLayout->Gpt.DiskId), Guid);
DPRINT("DiskId: %s\n", Guid);
DPRINT("StartingUsableOffset: %I64x\n", DriveLayout->Gpt.StartingUsableOffset.QuadPart);
DPRINT("UsableLength: %I64x\n", DriveLayout->Gpt.UsableLength.QuadPart);
DPRINT("MaxPartitionCount: %lu\n", DriveLayout->Gpt.MaxPartitionCount);
DbgPrint(" DiskId: %s\n", Guid);
DbgPrint(" StartingUsableOffset: %I64x\n", DriveLayout->Gpt.StartingUsableOffset.QuadPart);
DbgPrint(" UsableLength: %I64x\n", DriveLayout->Gpt.UsableLength.QuadPart);
DbgPrint(" MaxPartitionCount: %lu\n", DriveLayout->Gpt.MaxPartitionCount);
for (i = 0; i < DriveLayout->PartitionCount; i++)
{
FstubDbgPrintPartitionEx(DriveLayout->PartitionEntry, i);
}
break;
}
default:
DPRINT("Unsupported partition style: %lu\n", DriveLayout->PartitionStyle);
DbgPrint(" Unsupported partition style: %lu\n", DriveLayout->PartitionStyle);
}
#endif // !NDEBUG
}
VOID
NTAPI
FstubDbgPrintPartitionEx(IN PPARTITION_INFORMATION_EX PartitionEntry,
IN ULONG PartitionNumber)
#ifndef NDEBUG
static VOID
FstubDbgPrintPartitionEx(
_In_ PPARTITION_INFORMATION_EX PartitionEntry,
_In_ ULONG PartitionNumber)
{
CHAR Guid[EFI_GUID_STRING_SIZE];
PAGED_CODE();
DPRINT("Printing partition %lu\n", PartitionNumber);
switch (PartitionEntry[PartitionNumber].PartitionStyle)
{
case PARTITION_STYLE_MBR:
DPRINT(" StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
DPRINT(" PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
DPRINT(" RewritePartition: %u\n", PartitionEntry[PartitionNumber].RewritePartition);
DPRINT(" PartitionType: %02x\n", PartitionEntry[PartitionNumber].Mbr.PartitionType);
DPRINT(" BootIndicator: %u\n", PartitionEntry[PartitionNumber].Mbr.BootIndicator);
DPRINT(" RecognizedPartition: %u\n", PartitionEntry[PartitionNumber].Mbr.RecognizedPartition);
DPRINT(" HiddenSectors: %lu\n", PartitionEntry[PartitionNumber].Mbr.HiddenSectors);
{
DbgPrint(" StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
DbgPrint(" PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
DbgPrint(" RewritePartition: %u\n", PartitionEntry[PartitionNumber].RewritePartition);
DbgPrint(" PartitionType: %02x\n", PartitionEntry[PartitionNumber].Mbr.PartitionType);
DbgPrint(" BootIndicator: %u\n", PartitionEntry[PartitionNumber].Mbr.BootIndicator);
DbgPrint(" RecognizedPartition: %u\n", PartitionEntry[PartitionNumber].Mbr.RecognizedPartition);
DbgPrint(" HiddenSectors: %lu\n", PartitionEntry[PartitionNumber].Mbr.HiddenSectors);
break;
}
case PARTITION_STYLE_GPT:
DPRINT(" StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
DPRINT(" PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
DPRINT(" RewritePartition: %u\n", PartitionEntry[PartitionNumber].RewritePartition);
{
CHAR Guid[EFI_GUID_STRING_SIZE];
DbgPrint(" StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
DbgPrint(" PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
DbgPrint(" RewritePartition: %u\n", PartitionEntry[PartitionNumber].RewritePartition);
FstubDbgGuidToString(&(PartitionEntry[PartitionNumber].Gpt.PartitionType), Guid);
DPRINT(" PartitionType: %s\n", Guid);
DbgPrint(" PartitionType: %s\n", Guid);
FstubDbgGuidToString(&(PartitionEntry[PartitionNumber].Gpt.PartitionId), Guid);
DPRINT(" PartitionId: %s\n", Guid);
DPRINT(" Attributes: %I64x\n", PartitionEntry[PartitionNumber].Gpt.Attributes);
DPRINT(" Name: %ws\n", PartitionEntry[PartitionNumber].Gpt.Name);
DbgPrint(" PartitionId: %s\n", Guid);
DbgPrint(" Attributes: %I64x\n", PartitionEntry[PartitionNumber].Gpt.Attributes);
DbgPrint(" Name: %ws\n", PartitionEntry[PartitionNumber].Gpt.Name);
break;
}
default:
DPRINT(" Unsupported partition style: %ld\n", PartitionEntry[PartitionNumber].PartitionStyle);
DbgPrint(" Unsupported partition style: %ld\n", PartitionEntry[PartitionNumber].PartitionStyle);
}
}
#endif // !NDEBUG
VOID
NTAPI
FstubDbgPrintSetPartitionEx(IN PSET_PARTITION_INFORMATION_EX PartitionEntry,
IN ULONG PartitionNumber)
static VOID
FstubDbgPrintSetPartitionEx(
_In_ PSET_PARTITION_INFORMATION_EX PartitionEntry,
_In_ ULONG PartitionNumber)
{
CHAR Guid[EFI_GUID_STRING_SIZE];
#ifndef NDEBUG
PAGED_CODE();
DPRINT("FSTUB: SET_PARTITION_INFORMATION_EX: %p\n", PartitionEntry);
DPRINT("Modifying partition %lu\n", PartitionNumber);
DbgPrint("Modifying partition %lu\n", PartitionNumber);
switch (PartitionEntry->PartitionStyle)
{
case PARTITION_STYLE_MBR:
DPRINT(" PartitionType: %02x\n", PartitionEntry->Mbr.PartitionType);
DbgPrint(" PartitionType: %02x\n", PartitionEntry->Mbr.PartitionType);
break;
case PARTITION_STYLE_GPT:
{
CHAR Guid[EFI_GUID_STRING_SIZE];
FstubDbgGuidToString(&(PartitionEntry->Gpt.PartitionType), Guid);
DPRINT(" PartitionType: %s\n", Guid);
DbgPrint(" PartitionType: %s\n", Guid);
FstubDbgGuidToString(&(PartitionEntry->Gpt.PartitionId), Guid);
DPRINT(" PartitionId: %s\n", Guid);
DPRINT(" Attributes: %I64x\n", PartitionEntry->Gpt.Attributes);
DPRINT(" Name: %ws\n", PartitionEntry->Gpt.Name);
DbgPrint(" PartitionId: %s\n", Guid);
DbgPrint(" Attributes: %I64x\n", PartitionEntry->Gpt.Attributes);
DbgPrint(" Name: %ws\n", PartitionEntry->Gpt.Name);
break;
}
default:
DPRINT(" Unsupported partition style: %ld\n", PartitionEntry[PartitionNumber].PartitionStyle);
DbgPrint(" Unsupported partition style: %ld\n", PartitionEntry->PartitionStyle);
}
#endif // !NDEBUG
}
NTSTATUS
@@ -985,6 +988,7 @@ FstubReadPartitionTableEFI(IN PDISK_INFORMATION Disk,
ULONGLONG PartitionEntryLBA;
#endif
PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
PPARTITION_INFORMATION_EX PartitionInfo;
ULONG i, PartitionCount, PartitionIndex, PartitionsPerSector;
PAGED_CODE();
@@ -1076,28 +1080,26 @@ FstubReadPartitionTableEFI(IN PDISK_INFORMATION Disk,
PartitionEntry = ((PEFI_PARTITION_ENTRY)Disk->Buffer)[PartitionIndex];
PartitionIndex++;
/* If partition GUID is 00000000-0000-0000-0000-000000000000, then it's unused, skip it */
if (PartitionEntry.PartitionType.Data1 == 0 &&
PartitionEntry.PartitionType.Data2 == 0 &&
PartitionEntry.PartitionType.Data3 == 0 &&
((PULONGLONG)PartitionEntry.PartitionType.Data4)[0] == 0)
{
/* Skip unused partition */
if (IsEqualGUID(&PartitionEntry.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
continue;
}
/* Write data to structure. Don't forget GPT is using sectors, Windows offsets */
DriveLayoutEx->PartitionEntry[PartitionCount].StartingOffset.QuadPart = PartitionEntry.StartingLBA * Disk->SectorSize;
DriveLayoutEx->PartitionEntry[PartitionCount].PartitionLength.QuadPart = (PartitionEntry.EndingLBA -
PartitionEntry.StartingLBA + 1) *
Disk->SectorSize;
/* This number starts from 1 */
DriveLayoutEx->PartitionEntry[PartitionCount].PartitionNumber = PartitionCount + 1;
DriveLayoutEx->PartitionEntry[PartitionCount].RewritePartition = FALSE;
DriveLayoutEx->PartitionEntry[PartitionCount].PartitionStyle = PARTITION_STYLE_GPT;
DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.PartitionType = PartitionEntry.PartitionType;
DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.PartitionId = PartitionEntry.UniquePartition;
DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.Attributes = PartitionEntry.Attributes;
RtlCopyMemory(DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.Name,
PartitionInfo = &DriveLayoutEx->PartitionEntry[PartitionCount];
PartitionInfo->StartingOffset.QuadPart = PartitionEntry.StartingLBA * Disk->SectorSize;
PartitionInfo->PartitionLength.QuadPart = (PartitionEntry.EndingLBA -
PartitionEntry.StartingLBA + 1) * Disk->SectorSize;
/* Invalidate the partition number (recalculated by the PartMgr) */
PartitionInfo->PartitionNumber = -1;
PartitionInfo->RewritePartition = FALSE;
PartitionInfo->PartitionStyle = PARTITION_STYLE_GPT;
PartitionInfo->Gpt.PartitionType = PartitionEntry.PartitionType;
PartitionInfo->Gpt.PartitionId = PartitionEntry.UniquePartition;
PartitionInfo->Gpt.Attributes = PartitionEntry.Attributes;
RtlCopyMemory(PartitionInfo->Gpt.Name,
PartitionEntry.Name, sizeof(PartitionEntry.Name));
/* Update partition count */
@@ -1656,14 +1658,9 @@ FstubWritePartitionTableEFI(IN PDISK_INFORMATION Disk,
for (i = 0, WrittenPartitions = 0; i < PartitionCount; i++)
{
/* If partition GUID is 00000000-0000-0000-0000-000000000000, then it's unused, skip it */
if (PartitionEntries[i].Gpt.PartitionType.Data1 == 0 &&
PartitionEntries[i].Gpt.PartitionType.Data2 == 0 &&
PartitionEntries[i].Gpt.PartitionType.Data3 == 0 &&
((PULONGLONG)PartitionEntries[i].Gpt.PartitionType.Data4)[0] == 0)
{
/* Skip unused partition */
if (IsEqualGUID(&PartitionEntries[i].Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
continue;
}
/* Copy the entry in the partition entry format */
FstubCopyEntryEFI(&Entry, &PartitionEntries[i], Disk->SectorSize);
@@ -1797,7 +1794,7 @@ FstubWriteSector(IN PDEVICE_OBJECT DeviceObject,
return Status;
}
/* FUNCTIONS *****************************************************************/
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
@@ -2277,7 +2274,7 @@ Cleanup:
NTSTATUS
NTAPI
IoReadPartitionTableEx(IN PDEVICE_OBJECT DeviceObject,
IN PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout)
OUT PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout)
{
NTSTATUS Status;
PDISK_INFORMATION Disk;

View File

@@ -31,7 +31,7 @@ FASTCALL
xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize,
IN BOOLEAN ReturnRecognizedPartitions,
IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer);
OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer);
NTSTATUS
FASTCALL
@@ -240,36 +240,36 @@ xKdUnmapVirtualAddress(
//
// Various offsets in the boot record
//
#define DISK_SIGNATURE_OFFSET 0x1B8
#define PARTITION_TABLE_OFFSET 0x1BE
#define BOOT_SIGNATURE_OFFSET (0x200 - 2)
#define DISK_SIGNATURE_OFFSET 0x1B8
#define PARTITION_TABLE_OFFSET 0x1BE
#define BOOT_SIGNATURE_OFFSET (0x200 - 2)
#define BOOT_RECORD_SIGNATURE 0xAA55
#define NUM_PARTITION_TABLE_ENTRIES 4
#define BOOT_RECORD_SIGNATURE 0xAA55
#define NUM_PARTITION_TABLE_ENTRIES 4
//
// Helper Macros
//
#define GET_STARTING_SECTOR(p) \
((ULONG)(p->StartingSectorLsb0) + \
(ULONG)(p->StartingSectorLsb1 << 8 ) + \
(ULONG)(p->StartingSectorMsb0 << 16) + \
(ULONG)(p->StartingSectorMsb1 << 24))
#define GET_STARTING_SECTOR(p) \
((ULONG)((p)->StartingSectorLsb0) + \
(ULONG)((p)->StartingSectorLsb1 << 8 ) + \
(ULONG)((p)->StartingSectorMsb0 << 16) + \
(ULONG)((p)->StartingSectorMsb1 << 24))
#define GET_ENDING_S_OF_CHS(p) \
((UCHAR)(p->EndingCylinderLsb & 0x3F))
#define GET_ENDING_S_OF_CHS(p) \
((UCHAR)((p)->EndingCylinderLsb & 0x3F))
#define GET_PARTITION_LENGTH(p) \
((ULONG)(p->PartitionLengthLsb0) + \
(ULONG)(p->PartitionLengthLsb1 << 8) + \
(ULONG)(p->PartitionLengthMsb0 << 16) + \
(ULONG)(p->PartitionLengthMsb1 << 24))
((ULONG)((p)->PartitionLengthLsb0) + \
(ULONG)((p)->PartitionLengthLsb1 << 8 ) + \
(ULONG)((p)->PartitionLengthMsb0 << 16) + \
(ULONG)((p)->PartitionLengthMsb1 << 24))
#define SET_PARTITION_LENGTH(p, l) \
p->PartitionLengthLsb0 = l & 0xFF; \
p->PartitionLengthLsb1 = (l >> 8) & 0xFF; \
p->PartitionLengthMsb0 = (l >> 16) & 0xFF; \
p->PartitionLengthMsb1 = (l >> 24) & 0xFF
((p)->PartitionLengthLsb0 = (l) & 0xFF, \
(p)->PartitionLengthLsb1 = ((l) >> 8 ) & 0xFF, \
(p)->PartitionLengthMsb0 = ((l) >> 16) & 0xFF, \
(p)->PartitionLengthMsb1 = ((l) >> 24) & 0xFF)
//
// Structure describing a partition

View File

@@ -631,7 +631,7 @@ IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
/* Check MBR type against EZ Drive type */
StartingOffset.QuadPart = 0;
HalExamineMBR(DeviceObject, DiskGeometry.BytesPerSector, 0x55, &Data);
HalExamineMBR(DeviceObject, DiskGeometry.BytesPerSector, PARTITION_EZDRIVE, &Data);
if (Data)
{
/* If MBR is of the EZ Drive type, we'll read after it */