--- /dev/null
--- /dev/null
--- /dev/null
- #define IOCTL_WMI_51 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x51, METHOD_BUFFERED, FILE_WRITE_ACCESS) // 0x228144
+ ++
+ ++#pragma once
+ ++
+ ++#define IOCTL_WMI_QUERY_ALL_DATA CTL_CODE(FILE_DEVICE_UNKNOWN, 0x00, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224000
+ ++#define IOCTL_WMI_SINGLE_INSTANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x01, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224004
+ ++#define IOCTL_WMI_SET_SINGLE_INSTANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x02, METHOD_BUFFERED, FILE_WRITE_ACCESS) // 0x228008
+ ++#define IOCTL_WMI_SET_SINGLE_ITEM CTL_CODE(FILE_DEVICE_UNKNOWN, 0x03, METHOD_BUFFERED, FILE_WRITE_ACCESS) // 0x22800C
+ ++#define IOCTL_WMI_09 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x09, METHOD_BUFFERED, FILE_WRITE_ACCESS) // 0x228024
+ ++#define IOCTL_WMI_20 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20, METHOD_BUFFERED, FILE_ANY_ACCESS) // 0x220080
+ ++#define IOCTL_WMI_21 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x21, METHOD_BUFFERED, FILE_ANY_ACCESS) // 0x220084
+ ++#define IOCTL_WMI_22 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x22, METHOD_BUFFERED, FILE_ANY_ACCESS) // 0x220088
+ ++#define IOCTL_WMI_TRACE_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x23, METHOD_NEITHER, FILE_WRITE_ACCESS) // 0x22808F
+ ++#define IOCTL_WMI_24 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x24, METHOD_BUFFERED, FILE_ANY_ACCESS) // 0x220090
+ ++#define IOCTL_WMI_25 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x25, METHOD_BUFFERED, FILE_ANY_ACCESS) // 0x220094
+ ++#define IOCTL_WMI_TRACE_USER_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x28, METHOD_NEITHER, FILE_WRITE_ACCESS) // 0x2280A3
+ ++#define IOCTL_WMI_29 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x29, METHOD_BUFFERED, FILE_ANY_ACCESS) // 0x2200A4
+ ++#define IOCTL_WMI_2a CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2a, METHOD_BUFFERED, FILE_ANY_ACCESS) // 0x2200A8
+ ++#define IOCTL_WMI_2b CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2b, METHOD_BUFFERED, FILE_ANY_ACCESS) // 0x2200AC
+ ++#define IOCTL_WMI_42 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x42, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224108
+ ++#define IOCTL_WMI_47 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x47, METHOD_BUFFERED, FILE_WRITE_ACCESS) // 0x22811C
+ ++#define IOCTL_WMI_49 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x49, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224124
+ ++#define IOCTL_WMI_4b CTL_CODE(FILE_DEVICE_UNKNOWN, 0x4b, METHOD_BUFFERED, FILE_WRITE_ACCESS) // 0x22812C
+ ++#define IOCTL_WMI_4c CTL_CODE(FILE_DEVICE_UNKNOWN, 0x4c, METHOD_BUFFERED, FILE_WRITE_ACCESS) // 0x228130
+ ++#define IOCTL_WMI_4d CTL_CODE(FILE_DEVICE_UNKNOWN, 0x4d, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224134
+ ++#define IOCTL_WMI_4e CTL_CODE(FILE_DEVICE_UNKNOWN, 0x4e, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224138
+ ++#define IOCTL_WMI_4f CTL_CODE(FILE_DEVICE_UNKNOWN, 0x4f, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x22413C
+ ++#define IOCTL_WMI_OPEN_GUID_FOR_EVENTS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x50, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224140
- #define IOCTL_WMI_57 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x57, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x22415C
++++#define IOCTL_WMI_RECEIVE_NOTIFICATIONS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x51, METHOD_BUFFERED, FILE_WRITE_ACCESS) // 0x228144
+ ++#define IOCTL_WMI_52 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x52, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224148
+ ++#define IOCTL_WMI_REGISTER_GUIDS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x53, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x22414C, called from ntdll!EtwpRegisterGuids
+ ++#define IOCTL_WMI_54 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x54, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224150
+ ++#define IOCTL_WMI_55 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x55, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224154
+ ++#define IOCTL_WMI_56 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x56, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224158
++++#define IOCTL_WMI_UNREGISTER_GUIDS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x57, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x22415C, called from ntdll!WmiUnregisterGuids
+ ++#define IOCTL_WMI_58 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x58, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224160
+ ++#define IOCTL_WMI_59 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x59, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x224164
+ ++#define IOCTL_WMI_5a CTL_CODE(FILE_DEVICE_UNKNOWN, 0x5a, METHOD_BUFFERED, FILE_WRITE_ACCESS) // 0x228168
--- /dev/null
--- /dev/null
- #include <wmiguid.h>
+ +/*
+ + * PROJECT: ReactOS Kernel
+ + * LICENSE: GPL - See COPYING in the top level directory
+ + * FILE: ntoskrnl/io/wmidrv.c
+ + * PURPOSE: I/O Windows Management Instrumentation (WMI) Support
+ + * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
+ + */
+ +
+ +/* INCLUDES *****************************************************************/
+ +
+ +#include <ntoskrnl.h>
+ +#include <wmistr.h>
- UNIMPLEMENTED_DBGBREAK();
- return STATUS_NOT_IMPLEMENTED;
+ +#include "wmip.h"
+ +
+ +#define NDEBUG
+ +#include <debug.h>
+ +
+ +
+ +/* GLOBALS ******************************************************************/
+ +
+ +POBJECT_TYPE WmipGuidObjectType;
+ +GENERIC_MAPPING WmipGenericMapping;
+ +
+ +
+ +/* FUNCTIONS *****************************************************************/
+ +
+ +NTSTATUS
+ +NTAPI
+ +WmipSecurityMethod(
+ + _In_ PVOID Object,
+ + _In_ SECURITY_OPERATION_CODE OperationType,
+ + _In_ PSECURITY_INFORMATION SecurityInformation,
+ + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ + _Inout_ PULONG CapturedLength,
+ + _Inout_ PSECURITY_DESCRIPTOR *ObjectSecurityDescriptor,
+ + _In_ POOL_TYPE PoolType,
+ + _In_ PGENERIC_MAPPING GenericMapping)
+ +{
-- UNIMPLEMENTED_DBGBREAK();
+ ++ PAGED_CODE();
+ ++
+ ++ ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool));
+ ++ ASSERT((OperationType == QuerySecurityDescriptor) ||
+ ++ (OperationType == SetSecurityDescriptor) ||
+ ++ (OperationType == AssignSecurityDescriptor) ||
+ ++ (OperationType == DeleteSecurityDescriptor));
+ ++
+ ++ if (OperationType == QuerySecurityDescriptor)
+ ++ {
+ ++ return ObQuerySecurityDescriptorInfo(Object,
+ ++ SecurityInformation,
+ ++ SecurityDescriptor,
+ ++ CapturedLength,
+ ++ ObjectSecurityDescriptor);
+ ++ }
+ ++ else if (OperationType == SetSecurityDescriptor)
+ ++ {
+ ++ return ObSetSecurityDescriptorInfo(Object,
+ ++ SecurityInformation,
+ ++ SecurityDescriptor,
+ ++ ObjectSecurityDescriptor,
+ ++ PoolType,
+ ++ GenericMapping);
+ ++ }
+ ++ else if (OperationType == AssignSecurityDescriptor)
+ ++ {
+ ++ ObAssignObjectSecurityDescriptor(Object, SecurityDescriptor, PoolType);
+ ++ return STATUS_SUCCESS;
+ ++ }
+ ++ else if (OperationType == DeleteSecurityDescriptor)
+ ++ {
+ ++ return ObDeassignSecurity(ObjectSecurityDescriptor);
+ ++ }
+ ++
+ ++ ASSERT(FALSE);
+ ++ return STATUS_INVALID_PARAMETER;
+ +}
+ +
+ +VOID
+ +NTAPI
+ +WmipDeleteMethod(
+ + _In_ PVOID Object)
+ +{
-- UNIMPLEMENTED_DBGBREAK();
++++ PWMIP_GUID_OBJECT GuidObject = Object;
++++
++++ /* Check if the object is attached to an IRP */
++++ if (GuidObject->Irp != NULL)
++++ {
++++ /* This is not supported yet */
++++ ASSERT(FALSE);
++++ }
+ +}
+ +
+ +VOID
+ +NTAPI
+ +WmipCloseMethod(
+ + _In_opt_ PEPROCESS Process,
+ + _In_ PVOID Object,
+ + _In_ ACCESS_MASK GrantedAccess,
+ + _In_ ULONG ProcessHandleCount,
+ + _In_ ULONG SystemHandleCount)
+ +{
- Status = RtlGUIDFromString(GuidString, &Guid);
++++ /* For now nothing */
+ +}
+ +
+ +NTSTATUS
+ +NTAPI
+ +WmipInitializeGuidObjectType(
+ + VOID)
+ +{
+ + static UNICODE_STRING GuidObjectName = RTL_CONSTANT_STRING(L"WmiGuid");
+ + OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+ + NTSTATUS Status;
+ +
+ + /* Setup the object type initializer */
+ + RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+ + ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ + ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
+ + ObjectTypeInitializer.GenericMapping = WmipGenericMapping;
+ + ObjectTypeInitializer.PoolType = NonPagedPool;
+ + ObjectTypeInitializer.MaintainHandleCount = FALSE;
+ + ObjectTypeInitializer.ValidAccessMask = STANDARD_RIGHTS_ALL | 0xFFF;
+ + ObjectTypeInitializer.SecurityRequired = TRUE;
+ + ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(WMIP_GUID_OBJECT);;
+ + ObjectTypeInitializer.SecurityProcedure = WmipSecurityMethod;
+ + ObjectTypeInitializer.DeleteProcedure = WmipDeleteMethod;
+ + ObjectTypeInitializer.CloseProcedure = WmipCloseMethod;
+ +
+ + /* Create the object type */
+ + Status = ObCreateObjectType(&GuidObjectName,
+ + &ObjectTypeInitializer,
+ + 0,
+ + &WmipGuidObjectType);
+ + if (!NT_SUCCESS(Status))
+ + {
+ + DPRINT1("ObCreateObjectType failed: 0x%lx\n", Status);
+ + }
+ +
+ + return Status;
+ +}
+ +
+ ++static
+ ++NTSTATUS
+ ++WmipGUIDFromString(
+ ++ _In_ PUNICODE_STRING GuidString,
+ ++ _Out_ PGUID Guid)
+ ++{
+ ++ WCHAR Buffer[GUID_STRING_LENGTH + 2];
+ ++ UNICODE_STRING String;
+ ++
+ ++ /* Validate string length */
+ ++ if (GuidString->Length != GUID_STRING_LENGTH * sizeof(WCHAR))
+ ++ {
+ ++ return STATUS_INVALID_PARAMETER;
+ ++ }
+ ++
+ ++ /* Copy the string and wrap it in {} */
+ ++ RtlCopyMemory(&Buffer[1], GuidString->Buffer, GuidString->Length);
+ ++ Buffer[0] = L'{';
+ ++ Buffer[GUID_STRING_LENGTH + 1] = L'}';
+ ++
+ ++ String.Buffer = Buffer;
+ ++ String.Length = String.MaximumLength = sizeof(Buffer);
+ ++
+ ++ return RtlGUIDFromString(&String, Guid);
+ ++}
+ ++
+ +static
+ +NTSTATUS
+ +WmipCreateGuidObject(
+ + _In_ PUNICODE_STRING GuidString,
+ + _Out_ PWMIP_GUID_OBJECT *OutGuidObject)
+ +{
+ + OBJECT_ATTRIBUTES ObjectAttributes;
+ + GUID Guid;
+ + PWMIP_GUID_OBJECT GuidObject;
+ + NTSTATUS Status;
+ +
+ + /* Convert the string into a GUID structure */
- if (!RtlPrefixUnicodeString(ObjectAttributes->ObjectName, &Prefix, FALSE))
+ ++ Status = WmipGUIDFromString(GuidString, &Guid);
+ + if (!NT_SUCCESS(Status))
+ + {
+ + DPRINT1("WMI: Invalid uuid format for guid '%wZ'\n", GuidString);
+ + return Status;
+ + }
+ +
+ + /* Initialize object attributes for an unnamed object */
+ + InitializeObjectAttributes(&ObjectAttributes,
+ + NULL,
+ + 0,
+ + NULL,
+ + NULL); // FIXME: security descriptor!
+ +
+ + /* Create the GUID object */
+ + Status = ObCreateObject(KernelMode,
+ + WmipGuidObjectType,
+ + &ObjectAttributes,
+ + KernelMode,
+ + NULL,
+ + sizeof(WMIP_GUID_OBJECT),
+ + 0,
+ + 0,
+ + (PVOID*)&GuidObject);
+ + if (!NT_SUCCESS(Status))
+ + {
+ + DPRINT1("WMI: failed to create GUID object: 0x%lx\n", Status);
+ + return Status;
+ + }
+ +
++++ RtlZeroMemory(GuidObject, sizeof(*GuidObject));
+ + GuidObject->Guid = Guid;
+ +
+ + *OutGuidObject = GuidObject;
+ +
+ + return STATUS_SUCCESS;
+ +}
+ +
+ +NTSTATUS
+ +NTAPI
+ +WmipOpenGuidObject(
+ + POBJECT_ATTRIBUTES ObjectAttributes,
+ + ACCESS_MASK DesiredAccess,
+ + KPROCESSOR_MODE AccessMode,
+ + PHANDLE OutGuidObjectHandle,
+ + PVOID *OutGuidObject)
+ +{
+ + static UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\WmiGuid\\");
+ + UNICODE_STRING GuidString;
+ + ULONG HandleAttributes;
+ + PWMIP_GUID_OBJECT GuidObject;
+ + NTSTATUS Status;
+ + PAGED_CODE();
+ +
+ + /* Check if we have the expected prefix */
+ ++ if (!RtlPrefixUnicodeString(&Prefix, ObjectAttributes->ObjectName, FALSE))
+ + {
+ + DPRINT1("WMI: Invalid prefix for guid object '%wZ'\n",
+ + ObjectAttributes->ObjectName);
+ + return STATUS_INVALID_PARAMETER;
+ + }
+ +
+ + /* Extract the GUID string */
+ + GuidString = *ObjectAttributes->ObjectName;
+ + GuidString.Buffer += Prefix.Length / sizeof(WCHAR);
+ + GuidString.Length -= Prefix.Length;
+ +
+ + /* Create the GUID object */
+ + Status = WmipCreateGuidObject(&GuidString, &GuidObject);
+ + if (!NT_SUCCESS(Status))
+ + {
+ + DPRINT1("Failed to create GUID object: 0x%lx\n", Status);
+ + return Status;
+ + }
+ +
+ + /* Set handle attributes */
+ + HandleAttributes = (AccessMode == KernelMode) ? OBJ_KERNEL_HANDLE : 0;
+ +
+ + /* Get a handle for the object */
+ + Status = ObOpenObjectByPointer(GuidObject,
+ + HandleAttributes,
+ + 0,
+ + DesiredAccess,
+ + WmipGuidObjectType,
+ + AccessMode,
+ + OutGuidObjectHandle);
+ + if (!NT_SUCCESS(Status))
+ + {
+ + DPRINT1("ObOpenObjectByPointer failed: 0x%lx\n", Status);
+ + ObfDereferenceObject(GuidObject);
+ + }
+ +
+ + *OutGuidObject = GuidObject;
+ +
+ + return Status;
+ +}
+ +
--- /dev/null
--#include <wmiguid.h>
+ /*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/io/wmidrv.c
+ * PURPOSE: I/O Windows Management Instrumentation (WMI) Support
+ * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+ /* INCLUDES *****************************************************************/
+
+ #include <ntoskrnl.h>
+ #include <wmistr.h>
- ULONG Unknown08;
- ULONG Unknown0C;
+ ++#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;
- (RegisterGuids->RegInfo.BufferSize >
++++ 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;
+ ++
+ 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)
++++{
++++ NT_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))
++++ {
++++ 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");
++++ 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)) ||
- _SEH2_TRY
++++ (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;
+ ++ }
+ ++
- /* Probe and copy the object attributes structure */
- ProbeForRead(RegisterGuids->ObjectAttributes,
- sizeof(OBJECT_ATTRIBUTES),
- sizeof(PVOID));
- LocalObjectAttributes = *RegisterGuids->ObjectAttributes;
++++ /* Capture object attributes */
++++ PreviousMode = ExGetPreviousMode();
++++ Status = WmipCaptureGuidObjectAttributes(RegisterGuids->ObjectAttributes,
++++ &LocalObjectAttributes,
++++ &LocalObjectName,
++++ LocalObjectNameBuffer,
++++ PreviousMode);
++++ if (!NT_SUCCESS(Status))
+ ++ {
- /* Probe and copy the object name UNICODE_STRING */
- ProbeForRead(LocalObjectAttributes.ObjectName,
- sizeof(UNICODE_STRING),
- sizeof(PVOID));
- LocalObjectName = *LocalObjectAttributes.ObjectName;
++++ DPRINT1("WmipCaptureGuidObjectAttributes failed: 0x%lx\n", Status);
++++ return Status;
++++ }
+ ++
- /* Check if the object name has the expected length */
- if (LocalObjectName.Length != 45 * sizeof(WCHAR))
- {
- return STATUS_INVALID_PARAMETER;
- }
++++ /* Open a new GUID object */
++++ Status = WmipOpenGuidObject(&LocalObjectAttributes,
++++ SPECIFIC_RIGHTS_ALL,
++++ PreviousMode,
++++ &GuidObjectHandle,
++++ &GuidObject);
++++ if (!NT_SUCCESS(Status))
++++ {
++++ DPRINT1("WmipOpenGuidObject failed: 0x%lx\n", Status);
++++ return Status;
++++ }
+ ++
- /* Probe and copy the object name buffer */
- ProbeForRead(LocalObjectName.Buffer, LocalObjectName.Length, sizeof(WCHAR));
- RtlCopyMemory(LocalObjectNameBuffer,
- LocalObjectName.Buffer,
- LocalObjectName.Length);
++++ /* Dereference the GUID object */
++++ ObDereferenceObject(GuidObject);
+ ++
- /* Fix pointers */
- LocalObjectName.Buffer = LocalObjectNameBuffer;
- LocalObjectAttributes.ObjectName = &LocalObjectName;
++++ /* Return the handle (user mode will close it) */
++++ Result->Handle = GuidObjectHandle;
++++ Result->TraceHandle = 0;
++++ *OutputLength = 24;
+ ++
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
++++ 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);
+ ++ }
- DPRINT1("Got exception!\n");
- return _SEH2_GetExceptionCode();
++++}
++++
++++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))
+ ++ {
- _SEH2_END;
++++ return STATUS_INVALID_DEVICE_REQUEST;
+ ++ }
- /* Open a new GUID object */
+ ++
- SPECIFIC_RIGHTS_ALL,
++++ /// 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 = WmipOpenGuidObject(&LocalObjectAttributes,
- /* Derefernce the GUID object */
- ObDereferenceObject(GuidObject);
-
- /* Return the handle */
++++ OpenGuidForEvents->DesiredAccess,
+ ++ PreviousMode,
+ ++ &GuidObjectHandle,
+ ++ &GuidObject);
+ ++ if (!NT_SUCCESS(Status))
+ ++ {
++++ DPRINT1("WmipOpenGuidObject failed: 0x%lx\n", Status);
+ ++ return Status;
+ ++ }
+ ++
- *OutputLength = 24;
+ ++ Result->Handle = GuidObjectHandle;
-- _Inout_ PDEVICE_OBJECT DeviceObject,
-- _Inout_ PIRP Irp)
++++
++++ ObDereferenceObject(GuidObject);
+ ++
+ ++ return STATUS_SUCCESS;
+ ++}
+ ++
+ NTSTATUS
+ NTAPI
+ WmipIoControl(
-- UNIMPLEMENTED_DBGBREAK();
-- return STATUS_NOT_IMPLEMENTED;
+ ++ _In_ PDEVICE_OBJECT DeviceObject,
+ ++ _Inout_ PIRP Irp)
+ {
-- UNIMPLEMENTED_DBGBREAK();
+ ++ 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;
++++ }
++++
+ ++ 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)
+ {
+ UNIMPLEMENTED_DBGBREAK();
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ _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;
+ }
+
+