mirror of
https://github.com/reactos/reactos.git
synced 2024-11-18 13:01:40 +00:00
706 lines
19 KiB
C
706 lines
19 KiB
C
/*
|
|
* PROJECT: ReactOS Kernel
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: ntoskrnl/wmi/wmidrv.c
|
|
* PURPOSE: I/O Windows Management Instrumentation (WMI) Support
|
|
* PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
#include <wmistr.h>
|
|
#include <wmiioctl.h>
|
|
#include "wmip.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
// FIXME: these should go to a shared header
|
|
typedef struct _WMIP_REGISTER_GUIDS
|
|
{
|
|
POBJECT_ATTRIBUTES ObjectAttributes;
|
|
ULONG Unknown04;
|
|
ULONG Unknown08;
|
|
ULONG Unknown0C;
|
|
ULONG Unknown10;
|
|
ULONG Unknown14;
|
|
|
|
WMIREGINFOW RegInfo;
|
|
} WMIP_REGISTER_GUIDS, *PWMIP_REGISTER_GUIDS;
|
|
|
|
typedef struct _WMIP_RESULT
|
|
{
|
|
HANDLE Handle;
|
|
ULONG Unknown04;
|
|
TRACEHANDLE TraceHandle;
|
|
BOOLEAN Unknown10;
|
|
} WMIP_RESULT, *PWMIP_RESULT;
|
|
|
|
typedef struct _WMI_UNREGISTER_GUID
|
|
{
|
|
GUID Guid;
|
|
ULONG Unknown10;
|
|
ULONG Unknown14;
|
|
ULONG Unknown18;
|
|
ULONG Unknown1C;
|
|
} WMI_UNREGISTER_GUID, *PWMI_UNREGISTER_GUID;
|
|
|
|
typedef struct _WMI_GUID_OBJECT_ENTRY
|
|
{
|
|
HANDLE Handle;
|
|
ULONG Unknown04;
|
|
} WMI_GUID_OBJECT_ENTRY, *PWMI_GUID_OBJECT_ENTRY;
|
|
|
|
typedef struct _WMI_NOTIFICATION
|
|
{
|
|
ULONG NumberOfGuidObjects;
|
|
ULONG Unknown04;
|
|
ULONG Unknown08;
|
|
ULONG Unknown0C;
|
|
ULONG Unknown10;
|
|
ULONG Unknown14;
|
|
WMI_GUID_OBJECT_ENTRY GuidObjects[0];
|
|
} WMI_NOTIFICATION, *PWMI_NOTIFICATION;
|
|
|
|
typedef struct _WMI_SET_MARK
|
|
{
|
|
ULONG Flags;
|
|
WCHAR Mark[1];
|
|
} WMI_SET_MARK, *PWMI_SET_MARK;
|
|
|
|
PDEVICE_OBJECT WmipServiceDeviceObject;
|
|
PDEVICE_OBJECT WmipAdminDeviceObject;
|
|
FAST_IO_DISPATCH WmipFastIoDispatch;
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
DRIVER_DISPATCH WmipOpenCloseCleanup;
|
|
DRIVER_DISPATCH WmipIoControl;
|
|
DRIVER_DISPATCH WmipSystemControl;
|
|
DRIVER_DISPATCH WmipShutdown;
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WmipOpenCloseCleanup(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
/* No work to do, just return success */
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
WmiTraceEvent(
|
|
PVOID InputBuffer,
|
|
KPROCESSOR_MODE PreviousMode)
|
|
{
|
|
UNIMPLEMENTED_DBGBREAK();
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
WmiTraceUserMessage(
|
|
PVOID InputBuffer,
|
|
ULONG InputBufferLength)
|
|
{
|
|
UNIMPLEMENTED_DBGBREAK();
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
WmipCaptureGuidObjectAttributes(
|
|
_In_ POBJECT_ATTRIBUTES GuidObjectAttributes,
|
|
_Out_ POBJECT_ATTRIBUTES CapuredObjectAttributes,
|
|
_Out_ PUNICODE_STRING CapturedObjectName,
|
|
_Out_ PWSTR ObjectNameBuffer,
|
|
_In_ KPROCESSOR_MODE AccessMode)
|
|
{
|
|
ASSERT(AccessMode != KernelMode);
|
|
|
|
_SEH2_TRY
|
|
{
|
|
/* Probe and copy the object attributes structure */
|
|
ProbeForRead(GuidObjectAttributes,
|
|
sizeof(OBJECT_ATTRIBUTES),
|
|
sizeof(PVOID));
|
|
*CapuredObjectAttributes = *GuidObjectAttributes;
|
|
|
|
/* Probe and copy the object name UNICODE_STRING */
|
|
ProbeForRead(CapuredObjectAttributes->ObjectName,
|
|
sizeof(UNICODE_STRING),
|
|
sizeof(PVOID));
|
|
*CapturedObjectName = *CapuredObjectAttributes->ObjectName;
|
|
|
|
/* Check if the object name has the expected length */
|
|
if (CapturedObjectName->Length != 45 * sizeof(WCHAR))
|
|
{
|
|
_SEH2_YIELD(return STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
/* Probe and copy the object name buffer */
|
|
ProbeForRead(CapturedObjectName->Buffer,
|
|
CapturedObjectName->Length,
|
|
sizeof(WCHAR));
|
|
RtlCopyMemory(ObjectNameBuffer,
|
|
CapturedObjectName->Buffer,
|
|
CapturedObjectName->Length);
|
|
|
|
/* Fix pointers */
|
|
CapturedObjectName->Buffer = ObjectNameBuffer;
|
|
GuidObjectAttributes->ObjectName = CapturedObjectName;
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DPRINT1("Got exception!\n");
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
|
}
|
|
_SEH2_END;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
WmipRegisterGuids(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_In_ PVOID Buffer,
|
|
_In_ ULONG InputLength,
|
|
_Inout_ PULONG OutputLength)
|
|
{
|
|
PWMIP_REGISTER_GUIDS RegisterGuids = (PWMIP_REGISTER_GUIDS)Buffer;
|
|
PWMIP_RESULT Result = (PWMIP_RESULT)Buffer;
|
|
OBJECT_ATTRIBUTES LocalObjectAttributes;
|
|
UNICODE_STRING LocalObjectName;
|
|
WCHAR LocalObjectNameBuffer[45 + 1];
|
|
KPROCESSOR_MODE PreviousMode;
|
|
HANDLE GuidObjectHandle;
|
|
PVOID GuidObject;
|
|
NTSTATUS Status;
|
|
|
|
/* Make sure the input buffer is large enough */
|
|
if ((InputLength < sizeof(WMIP_REGISTER_GUIDS)) ||
|
|
(RegisterGuids->RegInfo.BufferSize >
|
|
(InputLength - FIELD_OFFSET(WMIP_REGISTER_GUIDS, RegInfo))))
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
/* Make sure we have a resonable GUID count */
|
|
if ((RegisterGuids->RegInfo.GuidCount == 0) ||
|
|
(RegisterGuids->RegInfo.GuidCount > 0x10000))
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
/* Capture object attributes */
|
|
PreviousMode = ExGetPreviousMode();
|
|
Status = WmipCaptureGuidObjectAttributes(RegisterGuids->ObjectAttributes,
|
|
&LocalObjectAttributes,
|
|
&LocalObjectName,
|
|
LocalObjectNameBuffer,
|
|
PreviousMode);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("WmipCaptureGuidObjectAttributes failed: 0x%lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/* Open a new GUID object */
|
|
Status = WmipOpenGuidObjectByName(&LocalObjectAttributes,
|
|
SPECIFIC_RIGHTS_ALL,
|
|
PreviousMode,
|
|
&GuidObjectHandle,
|
|
&GuidObject);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("WmipOpenGuidObjectByName failed: 0x%lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/* Dereference the GUID object */
|
|
ObDereferenceObject(GuidObject);
|
|
|
|
/* Return the handle (user mode will close it) */
|
|
Result->Handle = GuidObjectHandle;
|
|
Result->TraceHandle = 0;
|
|
*OutputLength = 24;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
WmipUnregisterGuids(
|
|
_In_ PVOID Buffer,
|
|
_In_ ULONG InputLength,
|
|
_Inout_ PULONG OutputLength)
|
|
{
|
|
/* For now we have nothing to do */
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
WmipClearIrpObjectList(
|
|
_In_ PIRP Irp)
|
|
{
|
|
PWMIP_IRP_CONTEXT IrpContext;
|
|
PLIST_ENTRY ListEntry;
|
|
PWMIP_GUID_OBJECT GuidObject;
|
|
|
|
/* Get the IRP context */
|
|
IrpContext = (PWMIP_IRP_CONTEXT)Irp->Tail.Overlay.DriverContext;
|
|
|
|
/* Loop all GUID objects attached to this IRP */
|
|
for (ListEntry = IrpContext->GuidObjectListHead.Flink;
|
|
ListEntry != &IrpContext->GuidObjectListHead;
|
|
ListEntry = ListEntry->Flink)
|
|
{
|
|
/* Get the GUID object */
|
|
GuidObject = CONTAINING_RECORD(ListEntry, WMIP_GUID_OBJECT, IrpLink);
|
|
|
|
/* Make sure the IRP matches and clear it */
|
|
ASSERT(GuidObject->Irp == Irp);
|
|
GuidObject->Irp = NULL;
|
|
|
|
/* Remove the entry */
|
|
RemoveEntryList(ListEntry);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
WmipNotificationIrpCancel(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
/* Clear the list */
|
|
WmipClearIrpObjectList(Irp);
|
|
|
|
/* Release the cancel spin lock */
|
|
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
|
|
|
/* Set the status to cancelled and complete the IRP */
|
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
static
|
|
VOID
|
|
WmipInitializeIrpContext(
|
|
PWMIP_IRP_CONTEXT IrpContext)
|
|
{
|
|
/* Initialize the list head for GUID objects */
|
|
InitializeListHead(&IrpContext->GuidObjectListHead);
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
WmipReceiveNotifications(
|
|
_Inout_ PIRP Irp,
|
|
_In_ PVOID Buffer,
|
|
_In_ ULONG InputLength,
|
|
_Inout_ PULONG OutputLength)
|
|
{
|
|
PWMI_NOTIFICATION Notification;
|
|
PWMIP_IRP_CONTEXT IrpContext;
|
|
NTSTATUS Status;
|
|
|
|
//__debugbreak();
|
|
if ((InputLength < sizeof(WMI_NOTIFICATION)) || (*OutputLength < 0x38))
|
|
{
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
/// FIXME: For now we don't do any actual work, but simply pretend we are
|
|
/// waiting for notifications. We won't ever deliver any though.
|
|
Notification = (PWMI_NOTIFICATION)Buffer;
|
|
DBG_UNREFERENCED_LOCAL_VARIABLE(Notification);
|
|
|
|
// loop all objects
|
|
// reference the object
|
|
// on failure, fail the whole request
|
|
|
|
// loop all objects
|
|
// update the irp (synchronization!)
|
|
// if we had one before complete the old irp with an error
|
|
|
|
/* Get the IRP context and initialize it */
|
|
IrpContext = (PWMIP_IRP_CONTEXT)Irp->Tail.Overlay.DriverContext;
|
|
WmipInitializeIrpContext(IrpContext);
|
|
|
|
// loop all objects
|
|
// insert the objects into the IRP list
|
|
|
|
/* Set our cancel routine for cleanup */
|
|
IoSetCancelRoutine(Irp, WmipNotificationIrpCancel);
|
|
|
|
/* Check if the IRP is already being cancelled */
|
|
if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
|
|
{
|
|
Status = STATUS_CANCELLED;
|
|
}
|
|
else
|
|
{
|
|
/* Mark the IRP as pending */
|
|
IoMarkIrpPending(Irp);
|
|
Status = STATUS_PENDING;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
typedef struct _WMI_OPEN_GUID_FOR_EVENTS
|
|
{
|
|
POBJECT_ATTRIBUTES ObjectAttributes;
|
|
ACCESS_MASK DesiredAccess;
|
|
ULONG Unknown08;
|
|
ULONG Unknown0C;
|
|
} WMI_OPEN_GUID_FOR_EVENTS, *PWMI_OPEN_GUID_FOR_EVENTS;
|
|
|
|
typedef struct _WMIP_RESULT2
|
|
{
|
|
ULONG Unknown00;
|
|
ULONG Unknown04;
|
|
HANDLE Handle;
|
|
ULONG Unknown0C;
|
|
} WMIP_RESULT2, *PWMIP_RESULT2;
|
|
|
|
static
|
|
NTSTATUS
|
|
WmipOpenGuidForEvents(
|
|
PVOID Buffer,
|
|
ULONG InputLength,
|
|
PULONG OutputLength)
|
|
{
|
|
PWMI_OPEN_GUID_FOR_EVENTS OpenGuidForEvents = Buffer;
|
|
PWMIP_RESULT2 Result = (PWMIP_RESULT2)Buffer;
|
|
OBJECT_ATTRIBUTES LocalObjectAttributes;
|
|
UNICODE_STRING LocalObjectName;
|
|
WCHAR LocalObjectNameBuffer[45 + 1];
|
|
KPROCESSOR_MODE PreviousMode;
|
|
HANDLE GuidObjectHandle;
|
|
PVOID GuidObject;
|
|
NTSTATUS Status;
|
|
|
|
if ((InputLength != sizeof(WMI_OPEN_GUID_FOR_EVENTS)) ||
|
|
(*OutputLength != sizeof(WMIP_RESULT2)))
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
/* Capture object attributes */
|
|
PreviousMode = ExGetPreviousMode();
|
|
Status = WmipCaptureGuidObjectAttributes(OpenGuidForEvents->ObjectAttributes,
|
|
&LocalObjectAttributes,
|
|
&LocalObjectName,
|
|
LocalObjectNameBuffer,
|
|
PreviousMode);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("ProbeAndCaptureGuidObjectAttributes failed: 0x%lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/* Open a new GUID object */
|
|
Status = WmipOpenGuidObjectByName(&LocalObjectAttributes,
|
|
OpenGuidForEvents->DesiredAccess,
|
|
PreviousMode,
|
|
&GuidObjectHandle,
|
|
&GuidObject);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("WmipOpenGuidObjectByName failed: 0x%lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
Result->Handle = GuidObjectHandle;
|
|
|
|
ObDereferenceObject(GuidObject);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
WmiSetMark(
|
|
PWMI_SET_MARK Buffer,
|
|
ULONG Length)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WmipIoControl(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStackLocation;
|
|
ULONG IoControlCode;
|
|
PVOID Buffer;
|
|
ULONG InputLength, OutputLength;
|
|
NTSTATUS Status;
|
|
PAGED_CODE();
|
|
|
|
/* Get the current stack location */
|
|
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
/* Get the io control parameters */
|
|
IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
|
|
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
|
InputLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
|
|
OutputLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
|
|
|
|
switch (IoControlCode)
|
|
{
|
|
|
|
case IOCTL_WMI_REGISTER_GUIDS:
|
|
{
|
|
Status = WmipRegisterGuids(DeviceObject,
|
|
Buffer,
|
|
InputLength,
|
|
&OutputLength);
|
|
break;
|
|
}
|
|
|
|
case IOCTL_WMI_UNREGISTER_GUIDS:
|
|
{
|
|
Status = WmipUnregisterGuids(Buffer,
|
|
InputLength,
|
|
&OutputLength);
|
|
break;
|
|
}
|
|
|
|
case IOCTL_WMI_RECEIVE_NOTIFICATIONS:
|
|
{
|
|
Status = WmipReceiveNotifications(Irp,
|
|
Buffer,
|
|
InputLength,
|
|
&OutputLength);
|
|
break;
|
|
}
|
|
|
|
case 0x228168:
|
|
{
|
|
DPRINT1("IOCTL 0x228168 is unimplemented, ignoring\n");
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
case IOCTL_WMI_OPEN_GUID_FOR_EVENTS:
|
|
{
|
|
Status = WmipOpenGuidForEvents(Buffer, InputLength, &OutputLength);
|
|
break;
|
|
}
|
|
|
|
case IOCTL_WMI_SET_MARK:
|
|
{
|
|
if (InputLength < FIELD_OFFSET(WMI_SET_MARK, Mark))
|
|
{
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
Status = WmiSetMark(Buffer, InputLength);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
DPRINT1("Unsupported yet IOCTL: 0x%lx\n", IoControlCode);
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
__debugbreak();
|
|
break;
|
|
}
|
|
|
|
if (Status == STATUS_PENDING)
|
|
return Status;
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
Irp->IoStatus.Information = NT_SUCCESS(Status) ? OutputLength : 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WmipSystemControl(
|
|
_Inout_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
UNIMPLEMENTED_DBGBREAK();
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WmipShutdown(
|
|
_Inout_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
_Function_class_(FAST_IO_DEVICE_CONTROL)
|
|
_IRQL_requires_same_
|
|
BOOLEAN
|
|
NTAPI
|
|
WmipFastIoDeviceControl(
|
|
_In_ PFILE_OBJECT FileObject,
|
|
_In_ BOOLEAN Wait,
|
|
_In_opt_ PVOID InputBuffer,
|
|
_In_ ULONG InputBufferLength,
|
|
_Out_opt_ PVOID OutputBuffer,
|
|
_In_ ULONG OutputBufferLength,
|
|
_In_ ULONG IoControlCode,
|
|
_Out_ PIO_STATUS_BLOCK IoStatus,
|
|
_In_ PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
if (IoControlCode == IOCTL_WMI_TRACE_EVENT)
|
|
{
|
|
if (InputBufferLength < 0x30)
|
|
{
|
|
DPRINT1("Buffer too small\n");
|
|
return FALSE;
|
|
}
|
|
|
|
IoStatus->Status = WmiTraceEvent(InputBuffer, ExGetPreviousMode());
|
|
return TRUE;
|
|
}
|
|
else if (IoControlCode == IOCTL_WMI_TRACE_USER_MESSAGE)
|
|
{
|
|
if (InputBufferLength < 0x30)
|
|
{
|
|
DPRINT1("Buffer too small\n");
|
|
return FALSE;
|
|
}
|
|
|
|
IoStatus->Status = WmiTraceUserMessage(InputBuffer, InputBufferLength);
|
|
return TRUE;
|
|
}
|
|
|
|
DPRINT1("Invalid io control code for fast dispatch: 0x%lx\n", IoControlCode);
|
|
return FALSE;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WmipDockUndockEventCallback(
|
|
_In_ PVOID NotificationStructure,
|
|
_Inout_opt_ PVOID Context)
|
|
{
|
|
UNIMPLEMENTED_DBGBREAK();
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
_Function_class_(DRIVER_INITIALIZE)
|
|
_IRQL_requires_same_
|
|
NTSTATUS
|
|
NTAPI
|
|
WmipDriverEntry(
|
|
_In_ PDRIVER_OBJECT DriverObject,
|
|
_In_ PUNICODE_STRING RegistryPath)
|
|
{
|
|
static UNICODE_STRING ServiceDeviceName = RTL_CONSTANT_STRING(L"\\Device\\WMIDataDevice");
|
|
static UNICODE_STRING ServiceDosDeviceName = RTL_CONSTANT_STRING(L"\\DosDevices\\WMIDataDevice");
|
|
static UNICODE_STRING AdminDeviceName = RTL_CONSTANT_STRING(L"\\Device\\WMIAdminDevice");
|
|
static UNICODE_STRING AdminDosDeviceName = RTL_CONSTANT_STRING(L"\\DosDevices\\WMIAdminDevice");
|
|
NTSTATUS Status;
|
|
PAGED_CODE();
|
|
|
|
/* Create the service device object */
|
|
Status = IoCreateDevice(DriverObject,
|
|
0,
|
|
&ServiceDeviceName,
|
|
FILE_DEVICE_UNKNOWN,
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
0,
|
|
&WmipServiceDeviceObject);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to create service device: 0x%lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/* Create a symbolic link for the service device */
|
|
Status = IoCreateSymbolicLink(&ServiceDosDeviceName, &ServiceDeviceName);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("IoCreateSymbolicLink() failed: 0x%lx\n", Status);
|
|
IoDeleteDevice(WmipServiceDeviceObject);
|
|
return Status;
|
|
}
|
|
|
|
/* Create the admin device object */
|
|
Status = IoCreateDevice(DriverObject,
|
|
0,
|
|
&AdminDeviceName,
|
|
FILE_DEVICE_UNKNOWN,
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
0,
|
|
&WmipAdminDeviceObject);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to create admin device: 0x%lx\n", Status);
|
|
IoDeleteDevice(WmipServiceDeviceObject);
|
|
IoDeleteSymbolicLink(&ServiceDosDeviceName);
|
|
return Status;
|
|
}
|
|
|
|
/* Create a symbolic link for the admin device */
|
|
Status = IoCreateSymbolicLink(&AdminDosDeviceName, &AdminDeviceName);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("IoCreateSymbolicLink() failed: 0x%lx\n", Status);
|
|
IoDeleteSymbolicLink(&ServiceDosDeviceName);
|
|
IoDeleteDevice(WmipServiceDeviceObject);
|
|
IoDeleteDevice(WmipAdminDeviceObject);
|
|
return Status;
|
|
}
|
|
|
|
/* Initialize dispatch routines */
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = WmipOpenCloseCleanup;
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = WmipOpenCloseCleanup;
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WmipIoControl;
|
|
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = WmipOpenCloseCleanup;
|
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = WmipSystemControl;
|
|
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = WmipShutdown;
|
|
|
|
/* Initialize fast dispatch */
|
|
RtlZeroMemory(&WmipFastIoDispatch, sizeof(WmipFastIoDispatch));
|
|
WmipFastIoDispatch.SizeOfFastIoDispatch = sizeof(WmipFastIoDispatch);
|
|
WmipFastIoDispatch.FastIoDeviceControl = WmipFastIoDeviceControl;
|
|
DriverObject->FastIoDispatch = &WmipFastIoDispatch;
|
|
|
|
/* Register the WMI service device */
|
|
IoWMIRegistrationControl(WmipServiceDeviceObject, WMIREG_ACTION_REGISTER);
|
|
|
|
/* Register a shutdown notification */
|
|
IoRegisterShutdownNotification(WmipServiceDeviceObject);
|
|
|
|
/* Initialization is done */
|
|
WmipServiceDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
WmipAdminDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|