Author: ekohl
Date: Mon Feb 13 22:38:11 2017
New Revision: 73795
URL:
http://svn.reactos.org/svn/reactos?rev=73795&view=rev
Log:
[NTOSKRNL]
Implement IopGetDeviceRelations().
Modified:
trunk/reactos/ntoskrnl/io/pnpmgr/plugplay.c
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/plugplay.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/plugpla…
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/plugplay.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/plugplay.c [iso-8859-1] Mon Feb 13 22:38:11 2017
@@ -163,7 +163,6 @@
}
return IopTraverseDeviceNode(IopRootDeviceNode, DeviceInstance);
-
}
static NTSTATUS
@@ -357,7 +356,7 @@
{
_SEH2_TRY
{
- memcpy(PropertyData->Buffer, Buffer, BufferSize);
+ RtlCopyMemory(PropertyData->Buffer, Buffer, BufferSize);
PropertyData->BufferSize = BufferSize;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -645,11 +644,160 @@
NTSTATUS
IopGetDeviceRelations(PPLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA RelationsData)
{
+ UNICODE_STRING DeviceInstance;
+ PDEVICE_OBJECT DeviceObject = NULL;
+ IO_STACK_LOCATION Stack;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PDEVICE_RELATIONS DeviceRelations = NULL;
+ PDEVICE_OBJECT ChildDeviceObject;
+ PDEVICE_NODE ChildDeviceNode;
+ ULONG i;
+ ULONG Relations;
+ ULONG BufferSize, RequiredSize;
+ ULONG BufferLeft;
+ PWCHAR Buffer, Ptr;
+ NTSTATUS Status = STATUS_SUCCESS;
+
DPRINT("IopGetDeviceRelations() called\n");
DPRINT("Device name: %wZ\n", &RelationsData->DeviceInstance);
- DPRINT("Relations: %lu\n", &RelationsData->Relations);
-
- return STATUS_NOT_IMPLEMENTED;
+ DPRINT("Relations: %lu\n", RelationsData->Relations);
+ DPRINT("BufferSize: %lu\n", RelationsData->BufferSize);
+ DPRINT("Buffer: %p\n", RelationsData->Buffer);
+
+ _SEH2_TRY
+ {
+ Relations = RelationsData->Relations;
+ BufferSize = RelationsData->BufferSize;
+ Buffer = RelationsData->Buffer;
+
+ ProbeForWrite(RelationsData->Buffer,
+ RelationsData->BufferSize,
+ sizeof(CHAR));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ Status = IopCaptureUnicodeString(&DeviceInstance,
&RelationsData->DeviceInstance);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IopCaptureUnicodeString() failed (Status 0x%08lx)\n",
Status);
+ return Status;
+ }
+
+ /* Get the device object */
+ DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
+ if (DeviceObject == NULL)
+ {
+ DPRINT1("IopGetDeviceObjectFromDeviceInstance() returned NULL\n");
+ Status = STATUS_NO_SUCH_DEVICE;
+ goto done;
+ }
+
+ switch (Relations)
+ {
+ case 0: /* EjectRelations */
+ Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations;
+ break;
+
+ case 1: /* RemovalRelations */
+ Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
+ break;
+
+ case 2: /* PowerRelations */
+ Stack.Parameters.QueryDeviceRelations.Type = PowerRelations;
+ break;
+
+ case 3: /* BusRelations */
+ Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
+ break;
+
+ default:
+ Status = STATUS_INVALID_PARAMETER;
+ goto done;
+ }
+
+ Status = IopInitiatePnpIrp(DeviceObject,
+ &IoStatusBlock,
+ IRP_MN_QUERY_DEVICE_RELATIONS,
+ &Stack);
+ if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
+ {
+ DPRINT1("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
+
+ DPRINT("Found %d device relations\n", DeviceRelations->Count);
+
+ _SEH2_TRY
+ {
+ RequiredSize = 0;
+ BufferLeft = BufferSize;
+ Ptr = Buffer;
+
+ for (i = 0; i < DeviceRelations->Count; i++)
+ {
+ ChildDeviceObject = DeviceRelations->Objects[i];
+
+ ChildDeviceNode = IopGetDeviceNode(ChildDeviceObject);
+ if (ChildDeviceNode)
+ {
+ DPRINT("Device instance: %wZ\n",
&ChildDeviceNode->InstancePath);
+ DPRINT("RequiredSize: %hu\n",
ChildDeviceNode->InstancePath.Length + sizeof(WCHAR));
+
+ if (Ptr != NULL)
+ {
+ if (BufferLeft < ChildDeviceNode->InstancePath.Length + 2 *
sizeof(WCHAR))
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ RtlCopyMemory(Ptr,
+ ChildDeviceNode->InstancePath.Buffer,
+ ChildDeviceNode->InstancePath.Length);
+ Ptr = (PWCHAR)((ULONG_PTR)Ptr +
ChildDeviceNode->InstancePath.Length);
+ *Ptr = UNICODE_NULL;
+ Ptr = (PWCHAR)((ULONG_PTR)Ptr + sizeof(WCHAR));
+
+ BufferLeft -= (ChildDeviceNode->InstancePath.Length +
sizeof(WCHAR));
+ }
+
+ RequiredSize += (ChildDeviceNode->InstancePath.Length +
sizeof(WCHAR));
+ }
+ }
+
+ if (Ptr != NULL && BufferLeft >= sizeof(WCHAR))
+ *Ptr = UNICODE_NULL;
+
+ if (RequiredSize > 0)
+ RequiredSize += sizeof(WCHAR);
+
+ DPRINT("BufferSize: %lu RequiredSize: %lu\n",
RelationsData->BufferSize, RequiredSize);
+
+ RelationsData->BufferSize = RequiredSize;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+done:
+ if (DeviceRelations != NULL)
+ ExFreePool(DeviceRelations);
+
+ if (DeviceObject != NULL)
+ ObDereferenceObject(DeviceObject);
+
+ if (DeviceInstance.Buffer != NULL)
+ ExFreePool(DeviceInstance.Buffer);
+
+ return Status;
}
static NTSTATUS