📄 plugplay.c
字号:
if (DeviceObject == NULL)
{
return STATUS_NO_SUCH_DEVICE;
}
Buffer = ExAllocatePool(NonPagedPool, BufferSize);
if (Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = IoGetDeviceProperty(DeviceObject,
Property,
BufferSize,
Buffer,
&BufferSize);
ObDereferenceObject(DeviceObject);
if (NT_SUCCESS(Status))
{
_SEH_TRY
{
memcpy(Buffer, PropertyData->Buffer, BufferSize);
PropertyData->BufferSize = BufferSize;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
ExFreePool(Buffer);
return Status;
}
static NTSTATUS
IopGetRelatedDevice(PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA RelatedDeviceData)
{
UNICODE_STRING RootDeviceName;
PDEVICE_OBJECT DeviceObject = NULL;
PDEVICE_NODE DeviceNode = NULL;
PDEVICE_NODE RelatedDeviceNode;
UNICODE_STRING TargetDeviceInstance;
NTSTATUS Status = STATUS_SUCCESS;
ULONG Relation = 0;
ULONG MaximumLength = 0;
DPRINT("IopGetRelatedDevice() called\n");
DPRINT("Device name: %wZ\n", &RelatedDeviceData->TargetDeviceInstance);
Status = IopCaptureUnicodeString(&TargetDeviceInstance, &RelatedDeviceData->TargetDeviceInstance);
if (!NT_SUCCESS(Status))
{
return Status;
}
_SEH_TRY
{
Relation = RelatedDeviceData->Relation;
MaximumLength = RelatedDeviceData->RelatedDeviceInstanceLength;
ProbeForWrite(RelatedDeviceData->RelatedDeviceInstance,
MaximumLength,
sizeof(WCHAR));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status))
{
ExFreePool(TargetDeviceInstance.Buffer);
return Status;
}
RtlInitUnicodeString(&RootDeviceName,
L"HTREE\\ROOT\\0");
if (RtlEqualUnicodeString(&TargetDeviceInstance,
&RootDeviceName,
TRUE))
{
DeviceNode = IopRootDeviceNode;
ExFreePool(TargetDeviceInstance.Buffer);
}
else
{
/* Get the device object */
DeviceObject = IopGetDeviceObjectFromDeviceInstance(&TargetDeviceInstance);
ExFreePool(TargetDeviceInstance.Buffer);
if (DeviceObject == NULL)
return STATUS_NO_SUCH_DEVICE;
DeviceNode = ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode;
}
switch (Relation)
{
case PNP_GET_PARENT_DEVICE:
RelatedDeviceNode = DeviceNode->Parent;
break;
case PNP_GET_CHILD_DEVICE:
RelatedDeviceNode = DeviceNode->Child;
break;
case PNP_GET_SIBLING_DEVICE:
RelatedDeviceNode = DeviceNode->NextSibling;
break;
default:
if (DeviceObject != NULL)
{
ObDereferenceObject(DeviceObject);
}
return STATUS_INVALID_PARAMETER;
}
if (RelatedDeviceNode == NULL)
{
if (DeviceObject)
{
ObDereferenceObject(DeviceObject);
}
return STATUS_NO_SUCH_DEVICE;
}
if (RelatedDeviceNode->InstancePath.Length > MaximumLength)
{
if (DeviceObject)
{
ObDereferenceObject(DeviceObject);
}
return STATUS_BUFFER_TOO_SMALL;
}
/* Copy related device instance name */
_SEH_TRY
{
RtlCopyMemory(RelatedDeviceData->RelatedDeviceInstance,
RelatedDeviceNode->InstancePath.Buffer,
RelatedDeviceNode->InstancePath.Length);
RelatedDeviceData->RelatedDeviceInstanceLength = RelatedDeviceNode->InstancePath.Length;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (DeviceObject != NULL)
{
ObDereferenceObject(DeviceObject);
}
DPRINT("IopGetRelatedDevice() done\n");
return Status;
}
static NTSTATUS
IopDeviceStatus(PPLUGPLAY_CONTROL_STATUS_DATA StatusData)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_NODE DeviceNode;
ULONG Operation = 0;
ULONG DeviceStatus = 0;
ULONG DeviceProblem = 0;
UNICODE_STRING DeviceInstance;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("IopDeviceStatus() called\n");
DPRINT("Device name: %wZ\n", &StatusData->DeviceInstance);
Status = IopCaptureUnicodeString(&DeviceInstance, &StatusData->DeviceInstance);
if (!NT_SUCCESS(Status))
{
return Status;
}
_SEH_TRY
{
Operation = StatusData->Operation;
if (Operation == PNP_SET_DEVICE_STATUS)
{
DeviceStatus = StatusData->DeviceStatus;
DeviceProblem = StatusData->DeviceProblem;
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status))
{
if (DeviceInstance.Buffer)
{
ExFreePool(DeviceInstance.Buffer);
}
return Status;
}
/* Get the device object */
DeviceObject = IopGetDeviceObjectFromDeviceInstance(&StatusData->DeviceInstance);
ExFreePool(DeviceInstance.Buffer);
if (DeviceObject == NULL)
return STATUS_NO_SUCH_DEVICE;
DeviceNode = IopGetDeviceNode(DeviceObject);
switch (Operation)
{
case PNP_GET_DEVICE_STATUS:
DPRINT("Get status data\n");
DeviceStatus = DeviceNode->Flags;
DeviceProblem = DeviceNode->Problem;
break;
case PNP_SET_DEVICE_STATUS:
DPRINT("Set status data\n");
DeviceNode->Flags = DeviceStatus;
DeviceNode->Problem = DeviceProblem;
break;
case PNP_CLEAR_DEVICE_STATUS:
DPRINT1("FIXME: Clear status data!\n");
break;
}
ObDereferenceObject(DeviceObject);
if (Operation == PNP_GET_DEVICE_STATUS)
{
_SEH_TRY
{
StatusData->DeviceStatus = DeviceStatus;
StatusData->DeviceProblem = DeviceProblem;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status;
}
static NTSTATUS
IopGetDeviceDepth(PPLUGPLAY_CONTROL_DEPTH_DATA DepthData)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_NODE DeviceNode;
UNICODE_STRING DeviceInstance;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("IopGetDeviceDepth() called\n");
DPRINT("Device name: %wZ\n", &DepthData->DeviceInstance);
Status = IopCaptureUnicodeString(&DeviceInstance, &DepthData->DeviceInstance);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Get the device object */
DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DepthData->DeviceInstance);
ExFreePool(DeviceInstance.Buffer);
if (DeviceObject == NULL)
return STATUS_NO_SUCH_DEVICE;
DeviceNode = IopGetDeviceNode(DeviceObject);
DepthData->Depth = DeviceNode->Level;
ObDereferenceObject(DeviceObject);
_SEH_TRY
{
DepthData->Depth = DeviceNode->Level;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
return Status;
}
static NTSTATUS
IopResetDevice(PPLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_NODE DeviceNode;
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING DeviceInstance;
Status = IopCaptureUnicodeString(&DeviceInstance, &ResetDeviceData->DeviceInstance);
if (!NT_SUCCESS(Status))
return Status;
DPRINT("IopResetDevice(%wZ)\n", &DeviceInstance);
/* Get the device object */
DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
ExFreePool(DeviceInstance.Buffer);
if (DeviceObject == NULL)
return STATUS_NO_SUCH_DEVICE;
DeviceNode = IopGetDeviceNode(DeviceObject);
/* FIXME: we should stop the device, before starting it again */
/* Start the device */
IopDeviceNodeClearFlag(DeviceNode, DNF_DISABLED);
Status = IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
if (NT_SUCCESS(Status))
Status = IopActionInitChildServices(DeviceNode, DeviceNode->Parent, FALSE);
ObDereferenceObject(DeviceObject);
return Status;
}
/*
* NtPlugPlayControl
*
* A function for doing various Plug & Play operations from user mode.
*
* Parameters
* PlugPlayControlClass
* 0x00 Reenumerate device tree
*
* Buffer points to UNICODE_STRING decribing the instance
* path (like "HTREE\ROOT\0" or "Root\ACPI_HAL\0000"). For
* more information about instance paths see !devnode command
* in kernel debugger or look at "Inside Windows 2000" book,
* chapter "Driver Loading, Initialization, and Installation".
*
* 0x01 Register new device
* 0x02 Deregister device
* 0x03 Initialize device
* 0x04 Start device
* 0x06 Query and remove device
* 0x07 User response
*
* Called after processing the message from NtGetPlugPlayEvent.
*
* 0x08 Generate legacy device
* 0x09 Get interface device list
* 0x0A Get property data
* 0x0B Device class association (Registration)
* 0x0C Get related device
* 0x0D Get device interface alias
* 0x0E Get/set/clear device status
* 0x0F Get device depth
* 0x10 Query device relations
* 0x11 Query target device relation
* 0x12 Query conflict list
* 0x13 Retrieve dock data
* 0x14 Reset device
* 0x15 Halt device
* 0x16 Get blocked driver data
*
* Buffer
* The buffer contains information that is specific to each control
* code. The buffer is read-only.
*
* BufferSize
* Size of the buffer pointed by the Buffer parameter. If the
* buffer size specifies incorrect value for specified control
* code, error ??? is returned.
*
* Return Values
* STATUS_PRIVILEGE_NOT_HELD
* STATUS_SUCCESS
* ...
*
* @unimplemented
*/
NTSTATUS STDCALL
NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass,
IN OUT PVOID Buffer,
IN ULONG BufferLength)
{
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("NtPlugPlayControl(%lu %p %lu) called\n",
PlugPlayControlClass, Buffer, BufferLength);
/* Function can only be called from user-mode */
if (KeGetPreviousMode() == KernelMode)
{
DPRINT1("NtGetPlugPlayEvent cannot be called from kernel mode!\n");
return STATUS_ACCESS_DENIED;
}
/* Check for Tcb privilege */
if (!SeSinglePrivilegeCheck(SeTcbPrivilege,
UserMode))
{
DPRINT1("NtGetPlugPlayEvent: Caller does not hold the SeTcbPrivilege privilege!\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
/* Probe the buffer */
_SEH_TRY
{
ProbeForWrite(Buffer,
BufferLength,
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status))
{
return Status;
}
switch (PlugPlayControlClass)
{
case PlugPlayControlUserResponse:
if (Buffer || BufferLength != 0)
return STATUS_INVALID_PARAMETER;
return IopRemovePlugPlayEvent();
case PlugPlayControlProperty:
if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA))
return STATUS_INVALID_PARAMETER;
return IopGetDeviceProperty((PPLUGPLAY_CONTROL_PROPERTY_DATA)Buffer);
case PlugPlayControlGetRelatedDevice:
if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA))
return STATUS_INVALID_PARAMETER;
return IopGetRelatedDevice((PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA)Buffer);
case PlugPlayControlDeviceStatus:
if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_STATUS_DATA))
return STATUS_INVALID_PARAMETER;
return IopDeviceStatus((PPLUGPLAY_CONTROL_STATUS_DATA)Buffer);
case PlugPlayControlGetDeviceDepth:
if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_DEPTH_DATA))
return STATUS_INVALID_PARAMETER;
return IopGetDeviceDepth((PPLUGPLAY_CONTROL_DEPTH_DATA)Buffer);
case PlugPlayControlResetDevice:
if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA))
return STATUS_INVALID_PARAMETER;
return IopResetDevice((PPLUGPLAY_CONTROL_RESET_DEVICE_DATA)Buffer);
default:
return STATUS_NOT_IMPLEMENTED;
}
return STATUS_NOT_IMPLEMENTED;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -