mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[PARTMGR] Add the Partition Manager driver
This driver works as complement to disk.sys/classpnp.sys from Windows 10 Manages partition PDOs and exposes them as volumes to mountmgr.sys. The driver is almost complete, just some minor IOCTLs missing (will be added on demand)
This commit is contained in:
parent
bbfc515eb3
commit
bd8226afe7
10 changed files with 2511 additions and 0 deletions
|
@ -2,4 +2,5 @@ add_subdirectory(class)
|
|||
add_subdirectory(floppy)
|
||||
add_subdirectory(ide)
|
||||
add_subdirectory(mountmgr)
|
||||
add_subdirectory(partmgr)
|
||||
add_subdirectory(port)
|
||||
|
|
19
drivers/storage/partmgr/CMakeLists.txt
Normal file
19
drivers/storage/partmgr/CMakeLists.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
list(APPEND SOURCE
|
||||
partition.c
|
||||
partmgr.c
|
||||
utils.c)
|
||||
|
||||
list(APPEND PCH_SKIP_SOURCE
|
||||
guid.c)
|
||||
|
||||
add_library(partmgr MODULE
|
||||
${SOURCE}
|
||||
${PCH_SKIP_SOURCE}
|
||||
partmgr.rc)
|
||||
|
||||
add_pch(partmgr partmgr.h "${PCH_SKIP_SOURCE}")
|
||||
set_module_type(partmgr kernelmodedriver)
|
||||
add_importlibs(partmgr ntoskrnl hal)
|
||||
add_registry_inf(partmgr_reg.inf)
|
||||
add_cd_file(TARGET partmgr DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
14
drivers/storage/partmgr/debug.h
Normal file
14
drivers/storage/partmgr/debug.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* PROJECT: Partition manager driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Debug helpers
|
||||
* COPYRIGHT: 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||
*/
|
||||
|
||||
#include <reactos/debug.h>
|
||||
|
||||
#define ERR(fmt, ...) ERR__(DPFLTR_DISK_ID, fmt, ##__VA_ARGS__)
|
||||
#define WARN(fmt, ...) WARN__(DPFLTR_DISK_ID, fmt, ##__VA_ARGS__)
|
||||
#define TRACE(fmt, ...) TRACE__(DPFLTR_DISK_ID, fmt, ##__VA_ARGS__)
|
||||
#define INFO(fmt, ...) INFO__(DPFLTR_DISK_ID, fmt, ##__VA_ARGS__)
|
||||
// #define FDPRINT(lvl, fmt, ...) FDPRINT__(DPFLTR_DISK_ID, lvl, fmt, __VA_ARGS__)
|
11
drivers/storage/partmgr/guid.c
Normal file
11
drivers/storage/partmgr/guid.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
|
||||
|
||||
#include <ntdef.h>
|
||||
#include <initguid.h>
|
||||
#include <wdmguid.h>
|
||||
|
||||
#define DEVICE_TYPE ULONG
|
||||
#include <ntdddisk.h>
|
||||
#include <ioevent.h>
|
||||
|
||||
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
|
816
drivers/storage/partmgr/partition.c
Normal file
816
drivers/storage/partmgr/partition.c
Normal file
|
@ -0,0 +1,816 @@
|
|||
/*
|
||||
* PROJECT: Partition manager driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Partition device code
|
||||
* COPYRIGHT: 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||
*/
|
||||
|
||||
#include "partmgr.h"
|
||||
|
||||
static const WCHAR PartitionSymLinkFormat[] = L"\\Device\\Harddisk%u\\Partition%u";
|
||||
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
PartitionCreateDevice(
|
||||
_In_ PDEVICE_OBJECT FDObject,
|
||||
_In_ PPARTITION_INFORMATION_EX PartitionEntry,
|
||||
_In_ UINT32 PdoNumber,
|
||||
_In_ PARTITION_STYLE PartitionStyle,
|
||||
_Out_ PDEVICE_OBJECT *PDO)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
static UINT32 HarddiskVolumeNextId = 1; // this is 1-based
|
||||
|
||||
WCHAR nameBuf[64];
|
||||
UNICODE_STRING deviceName;
|
||||
|
||||
// create the device object
|
||||
|
||||
swprintf(nameBuf, L"\\Device\\HarddiskVolume%u", HarddiskVolumeNextId++);
|
||||
RtlCreateUnicodeString(&deviceName, nameBuf);
|
||||
|
||||
PDEVICE_OBJECT partitionDevice;
|
||||
NTSTATUS status = IoCreateDevice(FDObject->DriverObject,
|
||||
sizeof(PARTITION_EXTENSION),
|
||||
&deviceName,
|
||||
FILE_DEVICE_DISK,
|
||||
FILE_DEVICE_SECURE_OPEN,
|
||||
FALSE,
|
||||
&partitionDevice);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
ERR("Unable to create device object %wZ\n", &deviceName);
|
||||
return status;
|
||||
}
|
||||
|
||||
INFO("Created device object %p %wZ\n", partitionDevice, &deviceName);
|
||||
|
||||
PPARTITION_EXTENSION partExt = partitionDevice->DeviceExtension;
|
||||
RtlZeroMemory(partExt, sizeof(*partExt));
|
||||
|
||||
partitionDevice->StackSize = FDObject->StackSize;
|
||||
partitionDevice->Flags |= DO_DIRECT_IO;
|
||||
|
||||
if (PartitionStyle == PARTITION_STYLE_MBR)
|
||||
{
|
||||
partExt->Mbr.PartitionType = PartitionEntry->Mbr.PartitionType;
|
||||
partExt->Mbr.BootIndicator = PartitionEntry->Mbr.BootIndicator;
|
||||
partExt->Mbr.HiddenSectors = PartitionEntry->Mbr.HiddenSectors;
|
||||
}
|
||||
else
|
||||
{
|
||||
partExt->Gpt.PartitionType = PartitionEntry->Gpt.PartitionType;
|
||||
partExt->Gpt.PartitionId = PartitionEntry->Gpt.PartitionType;
|
||||
partExt->Gpt.Attributes = PartitionEntry->Gpt.Attributes;
|
||||
|
||||
RtlCopyMemory(partExt->Gpt.Name, PartitionEntry->Gpt.Name, sizeof(partExt->Gpt.Name));
|
||||
}
|
||||
|
||||
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->DeviceObject = partitionDevice;
|
||||
partExt->LowerDevice = FDObject;
|
||||
|
||||
partitionDevice->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
*PDO = partitionDevice;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
PartitionHandleStartDevice(
|
||||
_In_ PPARTITION_EXTENSION PartExt,
|
||||
_In_ PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
// fix the damn kernel!
|
||||
if (PartExt->DeviceRemoved)
|
||||
{
|
||||
DPRINT1("IRP_MN_START_DEVICE after IRP_MN_REMOVE_DEVICE!\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// first, create a symbolic link for our device
|
||||
WCHAR nameBuf[64];
|
||||
UNICODE_STRING partitionSymlink, interfaceName;
|
||||
PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension;
|
||||
|
||||
// \\Device\\Harddisk%u\\Partition%u
|
||||
swprintf(nameBuf, PartitionSymLinkFormat,
|
||||
fdoExtension->DiskData.DeviceNumber, PartExt->DetectedNumber);
|
||||
|
||||
if (!RtlCreateUnicodeString(&partitionSymlink, nameBuf))
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
NTSTATUS status = IoCreateSymbolicLink(&partitionSymlink, &PartExt->DeviceName);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
PartExt->SymlinkCreated = TRUE;
|
||||
|
||||
TRACE("Symlink created %wZ -> %wZ\n", &PartExt->DeviceName, &partitionSymlink);
|
||||
|
||||
// our partition device will have two interfaces:
|
||||
// GUID_DEVINTERFACE_PARTITION and GUID_DEVINTERFACE_VOLUME
|
||||
// the former one is used to notify mountmgr about new device
|
||||
|
||||
status = IoRegisterDeviceInterface(PartExt->DeviceObject,
|
||||
&GUID_DEVINTERFACE_PARTITION,
|
||||
NULL,
|
||||
&interfaceName);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
PartExt->PartitionInterfaceName = interfaceName;
|
||||
status = IoSetDeviceInterfaceState(&interfaceName, TRUE);
|
||||
|
||||
INFO("Partition interface %wZ\n", &interfaceName);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
RtlFreeUnicodeString(&interfaceName);
|
||||
RtlInitUnicodeString(&PartExt->PartitionInterfaceName, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = IoRegisterDeviceInterface(PartExt->DeviceObject,
|
||||
&GUID_DEVINTERFACE_VOLUME,
|
||||
NULL,
|
||||
&interfaceName);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
PartExt->VolumeInterfaceName = interfaceName;
|
||||
status = IoSetDeviceInterfaceState(&interfaceName, TRUE);
|
||||
|
||||
INFO("Volume interface %wZ\n", &interfaceName);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
RtlFreeUnicodeString(&interfaceName);
|
||||
RtlInitUnicodeString(&PartExt->VolumeInterfaceName, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
PartitionHandleRemove(
|
||||
_In_ PPARTITION_EXTENSION PartExt,
|
||||
_In_ BOOLEAN FinalRemove)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
// remove the symbolic link
|
||||
if (PartExt->SymlinkCreated)
|
||||
{
|
||||
WCHAR nameBuf[64];
|
||||
UNICODE_STRING partitionSymlink;
|
||||
PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension;
|
||||
|
||||
swprintf(nameBuf, PartitionSymLinkFormat,
|
||||
fdoExtension->DiskData.DeviceNumber, PartExt->DetectedNumber);
|
||||
|
||||
RtlInitUnicodeString(&partitionSymlink, nameBuf);
|
||||
|
||||
status = IoDeleteSymbolicLink(&partitionSymlink);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
return status;
|
||||
}
|
||||
PartExt->SymlinkCreated = FALSE;
|
||||
|
||||
INFO("Symlink removed %wZ -> %wZ\n", &PartExt->DeviceName, &partitionSymlink);
|
||||
}
|
||||
|
||||
// release device interfaces
|
||||
if (PartExt->PartitionInterfaceName.Buffer)
|
||||
{
|
||||
status = IoSetDeviceInterfaceState(&PartExt->PartitionInterfaceName, FALSE);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
return status;
|
||||
}
|
||||
RtlFreeUnicodeString(&PartExt->PartitionInterfaceName);
|
||||
RtlInitUnicodeString(&PartExt->PartitionInterfaceName, NULL);
|
||||
}
|
||||
|
||||
if (PartExt->VolumeInterfaceName.Buffer)
|
||||
{
|
||||
status = IoSetDeviceInterfaceState(&PartExt->VolumeInterfaceName, FALSE);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
return status;
|
||||
}
|
||||
RtlFreeUnicodeString(&PartExt->VolumeInterfaceName);
|
||||
RtlInitUnicodeString(&PartExt->VolumeInterfaceName, NULL);
|
||||
}
|
||||
|
||||
if (FinalRemove)
|
||||
{
|
||||
// fix the damn kernel!
|
||||
if (PartExt->DeviceRemoved)
|
||||
{
|
||||
DPRINT1("Double IRP_MN_REMOVE_DEVICE!\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PartExt->DeviceRemoved = TRUE;
|
||||
|
||||
ASSERT(PartExt->DeviceName.Buffer);
|
||||
if (PartExt->DeviceName.Buffer)
|
||||
{
|
||||
INFO("Removed device %wZ\n", &PartExt->DeviceName);
|
||||
RtlFreeUnicodeString(&PartExt->DeviceName);
|
||||
}
|
||||
|
||||
IoDeleteDevice(PartExt->DeviceObject);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
PartitionHandleDeviceRelations(
|
||||
_In_ PPARTITION_EXTENSION PartExt,
|
||||
_In_ PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
// fix the damn kernel!
|
||||
if (PartExt->DeviceRemoved)
|
||||
{
|
||||
DPRINT1("QDR after device removal!\n");
|
||||
return STATUS_DEVICE_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
DEVICE_RELATION_TYPE type = ioStack->Parameters.QueryDeviceRelations.Type;
|
||||
|
||||
if (type == TargetDeviceRelation)
|
||||
{
|
||||
// Device relations has one entry built in to it's size.
|
||||
PDEVICE_RELATIONS deviceRelations =
|
||||
ExAllocatePoolZero(PagedPool, sizeof(DEVICE_RELATIONS), TAG_PARTMGR);
|
||||
|
||||
if (deviceRelations != NULL)
|
||||
{
|
||||
deviceRelations->Count = 1;
|
||||
deviceRelations->Objects[0] = PartExt->DeviceObject;
|
||||
ObReferenceObject(deviceRelations->Objects[0]);
|
||||
|
||||
Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
return Irp->IoStatus.Status;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
PartitionHandleQueryId(
|
||||
_In_ PPARTITION_EXTENSION PartExt,
|
||||
_In_ PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
BUS_QUERY_ID_TYPE idType = ioStack->Parameters.QueryId.IdType;
|
||||
UNICODE_STRING idString;
|
||||
NTSTATUS status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
switch (idType)
|
||||
{
|
||||
case BusQueryDeviceID:
|
||||
status = RtlCreateUnicodeString(&idString, L"STORAGE\\Partition")
|
||||
? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
|
||||
break;
|
||||
case BusQueryHardwareIDs:
|
||||
case BusQueryCompatibleIDs:
|
||||
{
|
||||
static WCHAR volumeID[] = L"STORAGE\\Volume\0";
|
||||
|
||||
idString.Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(volumeID), TAG_PARTMGR);
|
||||
RtlCopyMemory(idString.Buffer, volumeID, sizeof(volumeID));
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case BusQueryInstanceID:
|
||||
{
|
||||
WCHAR string[64];
|
||||
PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension;
|
||||
|
||||
PartMgrAcquireLayoutLock(fdoExtension);
|
||||
|
||||
if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR)
|
||||
{
|
||||
swprintf(string, L"S%08lx_O%I64x_L%I64x",
|
||||
fdoExtension->DiskData.Mbr.Signature,
|
||||
PartExt->StartingOffset,
|
||||
PartExt->PartitionLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
swprintf(string,
|
||||
L"S%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02xS_O%I64x_L%I64x",
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data1,
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data2,
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data3,
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data4[0],
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data4[1],
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data4[2],
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data4[3],
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data4[4],
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data4[5],
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data4[6],
|
||||
fdoExtension->DiskData.Gpt.DiskId.Data4[7],
|
||||
PartExt->StartingOffset,
|
||||
PartExt->PartitionLength);
|
||||
}
|
||||
|
||||
PartMgrReleaseLayoutLock(fdoExtension);
|
||||
|
||||
status = RtlCreateUnicodeString(&idString, string)
|
||||
? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Information = NT_SUCCESS(status) ? (ULONG_PTR) idString.Buffer : 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
PartitionHandleQueryCapabilities(
|
||||
_In_ PPARTITION_EXTENSION PartExt,
|
||||
_In_ PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PDEVICE_CAPABILITIES devCaps = ioStack->Parameters.DeviceCapabilities.Capabilities;
|
||||
|
||||
PAGED_CODE();
|
||||
ASSERT(devCaps);
|
||||
|
||||
devCaps->SilentInstall = TRUE;
|
||||
devCaps->RawDeviceOK = TRUE;
|
||||
devCaps->NoDisplayInUI = TRUE;
|
||||
devCaps->Address = PartExt->OnDiskNumber;
|
||||
devCaps->UniqueID = 1;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
PartitionHandlePnp(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp)
|
||||
{
|
||||
PPARTITION_EXTENSION partExt = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
switch (ioStack->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
{
|
||||
status = PartitionHandleStartDevice(partExt, Irp);
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||
{
|
||||
status = PartitionHandleDeviceRelations(partExt, Irp);
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_STOP_DEVICE:
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_STOP_DEVICE:
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
case IRP_MN_STOP_DEVICE:
|
||||
{
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
{
|
||||
status = PartitionHandleRemove(partExt, FALSE);
|
||||
break;
|
||||
}
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
{
|
||||
status = PartitionHandleRemove(partExt, TRUE);
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_ID:
|
||||
{
|
||||
status = PartitionHandleQueryId(partExt, Irp);
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_CAPABILITIES:
|
||||
{
|
||||
status = PartitionHandleQueryCapabilities(partExt, Irp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
PartitionHandleDeviceControl(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PPARTITION_EXTENSION partExt = DeviceObject->DeviceExtension;
|
||||
PFDO_EXTENSION fdoExtension = partExt->LowerDevice->DeviceExtension;
|
||||
NTSTATUS status;
|
||||
|
||||
ASSERT(!partExt->IsFDO);
|
||||
|
||||
if (!partExt->IsEnumerated)
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_DEVICE_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
switch (ioStack->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
// disk stuff
|
||||
case IOCTL_DISK_GET_PARTITION_INFO:
|
||||
{
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(PARTITION_INFORMATION)))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PartMgrAcquireLayoutLock(fdoExtension);
|
||||
|
||||
// not supported on anything other than MBR
|
||||
if (fdoExtension->DiskData.PartitionStyle != PARTITION_STYLE_MBR)
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
PartMgrReleaseLayoutLock(fdoExtension);
|
||||
break;
|
||||
}
|
||||
|
||||
PPARTITION_INFORMATION partInfo = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
*partInfo = (PARTITION_INFORMATION){
|
||||
.PartitionType = partExt->Mbr.PartitionType,
|
||||
.StartingOffset.QuadPart = partExt->StartingOffset,
|
||||
.PartitionLength.QuadPart = partExt->PartitionLength,
|
||||
.HiddenSectors = partExt->Mbr.HiddenSectors,
|
||||
.PartitionNumber = partExt->DetectedNumber,
|
||||
.BootIndicator = partExt->Mbr.BootIndicator,
|
||||
.RecognizedPartition = partExt->Mbr.RecognizedPartition,
|
||||
.RewritePartition = FALSE,
|
||||
};
|
||||
|
||||
PartMgrReleaseLayoutLock(fdoExtension);
|
||||
|
||||
Irp->IoStatus.Information = sizeof(*partInfo);
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case IOCTL_DISK_GET_PARTITION_INFO_EX:
|
||||
{
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(PARTITION_INFORMATION_EX)))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PPARTITION_INFORMATION_EX partInfoEx = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
PartMgrAcquireLayoutLock(fdoExtension);
|
||||
|
||||
*partInfoEx = (PARTITION_INFORMATION_EX){
|
||||
.StartingOffset.QuadPart = partExt->StartingOffset,
|
||||
.PartitionLength.QuadPart = partExt->PartitionLength,
|
||||
.PartitionNumber = partExt->DetectedNumber,
|
||||
.PartitionStyle = fdoExtension->DiskData.PartitionStyle,
|
||||
.RewritePartition = FALSE,
|
||||
};
|
||||
|
||||
if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR)
|
||||
{
|
||||
partInfoEx->Mbr = (PARTITION_INFORMATION_MBR){
|
||||
.PartitionType = partExt->Mbr.PartitionType,
|
||||
.HiddenSectors = partExt->Mbr.HiddenSectors,
|
||||
.BootIndicator = partExt->Mbr.BootIndicator,
|
||||
.RecognizedPartition = partExt->Mbr.RecognizedPartition,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
partInfoEx->Gpt = (PARTITION_INFORMATION_GPT){
|
||||
.PartitionType = partExt->Gpt.PartitionType,
|
||||
.PartitionId = partExt->Gpt.PartitionId,
|
||||
.Attributes = partExt->Gpt.Attributes,
|
||||
};
|
||||
|
||||
RtlCopyMemory(partInfoEx->Gpt.Name,
|
||||
partExt->Gpt.Name,
|
||||
sizeof(partInfoEx->Gpt.Name));
|
||||
}
|
||||
|
||||
PartMgrReleaseLayoutLock(fdoExtension);
|
||||
|
||||
Irp->IoStatus.Information = sizeof(*partInfoEx);
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case IOCTL_DISK_SET_PARTITION_INFO:
|
||||
{
|
||||
PSET_PARTITION_INFORMATION inputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
if (!VerifyIrpInBufferSize(Irp, sizeof(*inputBuffer)))
|
||||
{
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
PartMgrAcquireLayoutLock(fdoExtension);
|
||||
|
||||
// these functions use on disk numbers, not detected ones
|
||||
status = IoSetPartitionInformation(fdoExtension->LowerDevice,
|
||||
fdoExtension->DiskData.BytesPerSector,
|
||||
partExt->OnDiskNumber,
|
||||
inputBuffer->PartitionType);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
partExt->Mbr.PartitionType = inputBuffer->PartitionType;
|
||||
}
|
||||
|
||||
PartMgrReleaseLayoutLock(fdoExtension);
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
break;
|
||||
}
|
||||
case IOCTL_DISK_SET_PARTITION_INFO_EX:
|
||||
{
|
||||
PSET_PARTITION_INFORMATION_EX inputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
if (!VerifyIrpInBufferSize(Irp, sizeof(*inputBuffer)))
|
||||
{
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
PartMgrAcquireLayoutLock(fdoExtension);
|
||||
|
||||
// these functions use on disk numbers, not detected ones
|
||||
status = IoSetPartitionInformationEx(fdoExtension->LowerDevice,
|
||||
partExt->OnDiskNumber,
|
||||
inputBuffer);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR)
|
||||
{
|
||||
partExt->Mbr.PartitionType = inputBuffer->Mbr.PartitionType;
|
||||
}
|
||||
else
|
||||
{
|
||||
partExt->Gpt.PartitionType = inputBuffer->Gpt.PartitionType;
|
||||
partExt->Gpt.PartitionId = inputBuffer->Gpt.PartitionId;
|
||||
partExt->Gpt.Attributes = inputBuffer->Gpt.Attributes;
|
||||
|
||||
RtlMoveMemory(partExt->Gpt.Name,
|
||||
inputBuffer->Gpt.Name,
|
||||
sizeof(partExt->Gpt.Name));
|
||||
}
|
||||
}
|
||||
|
||||
PartMgrReleaseLayoutLock(fdoExtension);
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
break;
|
||||
}
|
||||
case IOCTL_DISK_GET_LENGTH_INFO:
|
||||
{
|
||||
PGET_LENGTH_INFORMATION lengthInfo = Irp->AssociatedIrp.SystemBuffer;
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(*lengthInfo)))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PartMgrAcquireLayoutLock(fdoExtension);
|
||||
|
||||
lengthInfo->Length.QuadPart = partExt->PartitionLength;
|
||||
|
||||
PartMgrReleaseLayoutLock(fdoExtension);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(*lengthInfo);
|
||||
break;
|
||||
}
|
||||
case IOCTL_DISK_VERIFY:
|
||||
{
|
||||
PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer;
|
||||
if (!VerifyIrpInBufferSize(Irp, sizeof(*verifyInfo)))
|
||||
{
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
// Partition device should just adjust the starting offset
|
||||
verifyInfo->StartingOffset.QuadPart += partExt->StartingOffset;
|
||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||
}
|
||||
case IOCTL_DISK_UPDATE_PROPERTIES:
|
||||
{
|
||||
fdoExtension->LayoutValid = FALSE;
|
||||
IoInvalidateDeviceRelations(fdoExtension->PhysicalDiskDO, BusRelations);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case IOCTL_STORAGE_MEDIA_REMOVAL:
|
||||
{
|
||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||
}
|
||||
// volume stuff (most of that should be in volmgr.sys one it is implemented)
|
||||
case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
|
||||
{
|
||||
PVOLUME_DISK_EXTENTS volExts = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
// we fill only one extent entry so sizeof(*volExts) is enough
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(*volExts)))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
PartMgrAcquireLayoutLock(fdoExtension);
|
||||
|
||||
// the only type of volume we support right now is disk partition
|
||||
// so this structure is simple
|
||||
|
||||
*volExts = (VOLUME_DISK_EXTENTS) {
|
||||
.NumberOfDiskExtents = 1,
|
||||
.Extents = {{
|
||||
.DiskNumber = fdoExtension->DiskData.DeviceNumber,
|
||||
.StartingOffset.QuadPart = partExt->StartingOffset,
|
||||
.ExtentLength.QuadPart = partExt->PartitionLength
|
||||
}}
|
||||
};
|
||||
|
||||
PartMgrReleaseLayoutLock(fdoExtension);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(*volExts);
|
||||
break;
|
||||
}
|
||||
case IOCTL_VOLUME_ONLINE:
|
||||
{
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case IOCTL_VOLUME_GET_GPT_ATTRIBUTES:
|
||||
{
|
||||
PVOLUME_GET_GPT_ATTRIBUTES_INFORMATION gptAttrs = Irp->AssociatedIrp.SystemBuffer;
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(*gptAttrs)))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
// not supported on anything other than GPT
|
||||
if (fdoExtension->DiskData.PartitionStyle != PARTITION_STYLE_GPT)
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
gptAttrs->GptAttributes = partExt->Gpt.Attributes;
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(*gptAttrs);
|
||||
break;
|
||||
}
|
||||
// mountmgr stuff
|
||||
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
|
||||
{
|
||||
PMOUNTDEV_NAME name = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(USHORT)))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
name->NameLength = partExt->DeviceName.Length;
|
||||
|
||||
// return NameLength back
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(USHORT) + name->NameLength))
|
||||
{
|
||||
Irp->IoStatus.Information = sizeof(USHORT);
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
break;
|
||||
}
|
||||
|
||||
RtlCopyMemory(name->Name, partExt->DeviceName.Buffer, name->NameLength);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(USHORT) + name->NameLength;
|
||||
break;
|
||||
}
|
||||
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
|
||||
{
|
||||
PMOUNTDEV_UNIQUE_ID uniqueId = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
if (!partExt->VolumeInterfaceName.Buffer)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(USHORT)))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
uniqueId->UniqueIdLength = partExt->VolumeInterfaceName.Length;
|
||||
|
||||
// return UniqueIdLength back
|
||||
if (!VerifyIrpOutBufferSize(Irp, sizeof(USHORT) + uniqueId->UniqueIdLength))
|
||||
{
|
||||
Irp->IoStatus.Information = sizeof(USHORT);
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
break;
|
||||
}
|
||||
|
||||
RtlCopyMemory(uniqueId->UniqueId,
|
||||
partExt->VolumeInterfaceName.Buffer,
|
||||
uniqueId->UniqueIdLength);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(USHORT) + uniqueId->UniqueIdLength;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return status;
|
||||
}
|
1373
drivers/storage/partmgr/partmgr.c
Normal file
1373
drivers/storage/partmgr/partmgr.c
Normal file
File diff suppressed because it is too large
Load diff
192
drivers/storage/partmgr/partmgr.h
Normal file
192
drivers/storage/partmgr/partmgr.h
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* PROJECT: Partition manager driver
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Main header
|
||||
* COPYRIGHT: 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||
*/
|
||||
|
||||
#ifndef _PARTMGR_H_
|
||||
#define _PARTMGR_H_
|
||||
|
||||
#include <ntifs.h>
|
||||
#include <mountdev.h>
|
||||
#include <ntddvol.h>
|
||||
#include <ntdddisk.h>
|
||||
#include <ndk/psfuncs.h>
|
||||
#include <ndk/section_attribs.h>
|
||||
#include <ioevent.h>
|
||||
#include <stdio.h>
|
||||
#include <debug/driverdbg.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define TAG_PARTMGR 'MtrP'
|
||||
|
||||
// from disk.sys
|
||||
typedef struct _DISK_GEOMETRY_EX_INTERNAL
|
||||
{
|
||||
DISK_GEOMETRY Geometry;
|
||||
INT64 DiskSize;
|
||||
DISK_PARTITION_INFO Partition;
|
||||
DISK_DETECTION_INFO Detection;
|
||||
} DISK_GEOMETRY_EX_INTERNAL, *PDISK_GEOMETRY_EX_INTERNAL;
|
||||
|
||||
typedef struct _FDO_EXTENSION
|
||||
{
|
||||
BOOLEAN IsFDO;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PDEVICE_OBJECT LowerDevice;
|
||||
PDEVICE_OBJECT PhysicalDiskDO;
|
||||
KEVENT SyncEvent;
|
||||
|
||||
BOOLEAN LayoutValid;
|
||||
PDRIVE_LAYOUT_INFORMATION_EX LayoutCache;
|
||||
|
||||
SINGLE_LIST_ENTRY PartitionList;
|
||||
UINT32 EnumeratedPartitionsTotal;
|
||||
|
||||
struct {
|
||||
UINT64 DiskSize;
|
||||
UINT32 DeviceNumber;
|
||||
UINT32 BytesPerSector;
|
||||
PARTITION_STYLE PartitionStyle;
|
||||
union {
|
||||
struct {
|
||||
UINT32 Signature;
|
||||
} Mbr;
|
||||
struct {
|
||||
GUID DiskId;
|
||||
} Gpt;
|
||||
};
|
||||
} DiskData;
|
||||
} FDO_EXTENSION, *PFDO_EXTENSION;
|
||||
|
||||
typedef struct _PARTITION_EXTENSION
|
||||
{
|
||||
BOOLEAN IsFDO;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PDEVICE_OBJECT LowerDevice;
|
||||
PDEVICE_OBJECT Part0Device;
|
||||
|
||||
UINT64 StartingOffset;
|
||||
UINT64 PartitionLength;
|
||||
SINGLE_LIST_ENTRY ListEntry;
|
||||
|
||||
UINT32 DetectedNumber;
|
||||
UINT32 OnDiskNumber; // partition number for issuing Io requests to the kernel
|
||||
BOOLEAN IsEnumerated; // reported via IRP_MN_QUERY_DEVICE_RELATIONS
|
||||
BOOLEAN SymlinkCreated;
|
||||
BOOLEAN DeviceRemoved; // !!!
|
||||
BOOLEAN Attached; // attached to PartitionList of the FDO
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
GUID PartitionType;
|
||||
GUID PartitionId;
|
||||
UINT64 Attributes;
|
||||
WCHAR Name[36];
|
||||
} Gpt;
|
||||
struct
|
||||
{
|
||||
UINT8 PartitionType;
|
||||
BOOLEAN BootIndicator;
|
||||
BOOLEAN RecognizedPartition;
|
||||
UINT32 HiddenSectors;
|
||||
} Mbr;
|
||||
};
|
||||
UNICODE_STRING PartitionInterfaceName;
|
||||
UNICODE_STRING VolumeInterfaceName;
|
||||
UNICODE_STRING DeviceName;
|
||||
} PARTITION_EXTENSION, *PPARTITION_EXTENSION;
|
||||
|
||||
NTSTATUS
|
||||
PartitionCreateDevice(
|
||||
_In_ PDEVICE_OBJECT FDObject,
|
||||
_In_ PPARTITION_INFORMATION_EX PartitionEntry,
|
||||
_In_ UINT32 OnDiskNumber,
|
||||
_In_ PARTITION_STYLE PartitionStyle,
|
||||
_Out_ PDEVICE_OBJECT *PDO);
|
||||
|
||||
NTSTATUS
|
||||
PartitionHandleRemove(
|
||||
_In_ PPARTITION_EXTENSION PartExt,
|
||||
_In_ BOOLEAN FinalRemove);
|
||||
|
||||
NTSTATUS
|
||||
PartitionHandlePnp(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
PartitionHandleDeviceControl(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ForwardIrpAndForget(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
IssueSyncIoControlRequest(
|
||||
_In_ UINT32 IoControlCode,
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PVOID InputBuffer,
|
||||
_In_ ULONG InputBufferLength,
|
||||
_In_ PVOID OutputBuffer,
|
||||
_In_ ULONG OutputBufferLength,
|
||||
_In_ BOOLEAN InternalDeviceIoControl);
|
||||
|
||||
inline
|
||||
BOOLEAN
|
||||
VerifyIrpOutBufferSize(
|
||||
_In_ PIRP Irp,
|
||||
_In_ SIZE_T Size)
|
||||
{
|
||||
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
if (ioStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
|
||||
{
|
||||
Irp->IoStatus.Information = Size;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
inline
|
||||
BOOLEAN
|
||||
VerifyIrpInBufferSize(
|
||||
_In_ PIRP Irp,
|
||||
_In_ SIZE_T Size)
|
||||
{
|
||||
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
if (ioStack->Parameters.DeviceIoControl.InputBufferLength < Size)
|
||||
{
|
||||
Irp->IoStatus.Information = Size;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
inline
|
||||
VOID
|
||||
PartMgrAcquireLayoutLock(
|
||||
_In_ PFDO_EXTENSION FDOExtension)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
KeWaitForSingleObject(&FDOExtension->SyncEvent, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
|
||||
inline
|
||||
VOID
|
||||
PartMgrReleaseLayoutLock(
|
||||
_In_ PFDO_EXTENSION FDOExtension)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
KeSetEvent(&FDOExtension->SyncEvent, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
|
||||
#endif // _PARTMGR_H_
|
5
drivers/storage/partmgr/partmgr.rc
Normal file
5
drivers/storage/partmgr/partmgr.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "Partition Manager"
|
||||
#define REACTOS_STR_INTERNAL_NAME "partmgr"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "partmgr.sys"
|
||||
#include <reactos/version.rc>
|
7
drivers/storage/partmgr/partmgr_reg.inf
Normal file
7
drivers/storage/partmgr/partmgr_reg.inf
Normal file
|
@ -0,0 +1,7 @@
|
|||
[AddReg]
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\partmgr","ErrorControl",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\partmgr","DisplayName",0x00000000,"Partition Manager"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\partmgr","Group",0x00000000,"Boot Bus Extender"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\partmgr","ImagePath",0x00020000,"system32\drivers\partmgr.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\partmgr","Start",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\partmgr","Type",0x00010001,0x00000001
|
73
drivers/storage/partmgr/utils.c
Normal file
73
drivers/storage/partmgr/utils.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include "partmgr.h"
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ForwardIrpAndForget(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp)
|
||||
{
|
||||
// this part of a structure is identical in both FDO and PDO
|
||||
PDEVICE_OBJECT LowerDevice = ((PFDO_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
|
||||
|
||||
ASSERT(LowerDevice);
|
||||
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(LowerDevice, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
IssueSyncIoControlRequest(
|
||||
_In_ UINT32 IoControlCode,
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PVOID InputBuffer,
|
||||
_In_ ULONG InputBufferLength,
|
||||
_In_ PVOID OutputBuffer,
|
||||
_In_ ULONG OutputBufferLength,
|
||||
_In_ BOOLEAN InternalDeviceIoControl)
|
||||
{
|
||||
PIRP Irp;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PKEVENT Event;
|
||||
NTSTATUS Status;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Allocate a non-paged event */
|
||||
Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Event), TAG_PARTMGR);
|
||||
if (!Event)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Initialize it */
|
||||
KeInitializeEvent(Event, NotificationEvent, FALSE);
|
||||
|
||||
/* Build the IRP */
|
||||
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
|
||||
DeviceObject,
|
||||
InputBuffer,
|
||||
InputBufferLength,
|
||||
OutputBuffer,
|
||||
OutputBufferLength,
|
||||
InternalDeviceIoControl,
|
||||
Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
{
|
||||
/* Fail, free the event */
|
||||
ExFreePoolWithTag(Event, TAG_PARTMGR);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Call the driver and check if it's pending */
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* Wait on the driver */
|
||||
KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
/* Free the event and return the Status */
|
||||
ExFreePoolWithTag(Event, TAG_PARTMGR);
|
||||
return Status;
|
||||
}
|
Loading…
Reference in a new issue