mirror of
https://github.com/reactos/reactos
synced 2025-10-06 16:32:42 +02:00
Compare commits
24 Commits
hpoussin/K
...
hbelusca/s
Author | SHA1 | Date | |
---|---|---|---|
|
bceeb18146 | ||
|
90865ee872 | ||
|
686f3f0523 | ||
|
b063438248 | ||
|
d0af99fcad | ||
|
299c3e8aed | ||
|
5cc0ee942f | ||
|
5004e520a5 | ||
|
1827e4e776 | ||
|
8c04fdd1af | ||
|
53d2bd5f87 | ||
|
2a9984f5d1 | ||
|
5a034f3ede | ||
|
686ef2741d | ||
|
a722e660bf | ||
|
ba2e90a8c2 | ||
|
41380b3b54 | ||
|
39fcaba8cb | ||
|
63706f04fb | ||
|
5d518e17c2 | ||
|
5731c50acf | ||
|
60bea22009 | ||
|
85d317447d | ||
|
889cfa828d |
@@ -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__
|
||||
|
@@ -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 */
|
||||
|
@@ -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
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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 */
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -1649,6 +1649,7 @@ Return Value:
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
__debugbreak();
|
||||
Status = IoReadDiskSignature (Fdo,
|
||||
fdoExtension->DiskGeometry.BytesPerSector,
|
||||
&Signature);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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:
|
||||
{
|
||||
|
@@ -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,
|
||||
¬ification,
|
||||
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,
|
||||
¬ification,
|
||||
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,
|
||||
¬ification,
|
||||
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;
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user