Merge the following revisions from kernel-fun branch:
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Thu, 19 Mar 2015 10:47:36 +0000 (10:47 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Thu, 19 Mar 2015 10:47:36 +0000 (10:47 +0000)
r62291
[NTOSKRNL]
Start implementing the built-in WMI driver

r62294
[NTOSKRNL]
Add basic code for the WMI GUID object

r62301
[NTOSKRNK]
Halfplement WmipSecurityMethod, implement WmipGUIDFromString as a wrapper around RtlGUIDFromString due to different format requirements, fix usage of RtlPrefixUnicodeString.

r62302
[NTOSKRNL]
Implement WmipFastIoDeviceControl, start implementing WmipIoControl

r62321
[NTOSKRNL]
Stubplement IOCTL_WMI_UNREGISTER_GUIDS and IOCTL_WMI_RECEIVE_NOTIFICATIONS, just enough that the callers don't error out.

r62322
[NTOSKRNL]
Zero out the guid object, remove debug breakpoints in WmipDeleteMethod and WmipCloseMethod (for now there's nothing to do), factor out the code to capture the guid object attributes into WmipCaptureGuidObjectAttributes, ignore ioctl 0x228168 for now and stubplement IOCTL_WMI_OPEN_GUID_FOR_EVENTS

svn path=/trunk/; revision=66797

1  2  3  4 
reactos/include/reactos/wmiioctl.h
reactos/ntoskrnl/io/iomgr/iomgr.c
reactos/ntoskrnl/ntos.cmake
reactos/ntoskrnl/wmi/guidobj.c
reactos/ntoskrnl/wmi/wmidrv.c
reactos/ntoskrnl/wmi/wmip.h

index 0000000,28639b6,0000000,0000000..97d4708
mode 000000,100644,000000,000000..100644
--- /dev/null
--- /dev/null
--- /dev/null
@@@@@ -1,0 -1,37 -1,0 -1,0 +1,37 @@@@@
 -  #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
Simple merge
@@@@@ -267,9 -267,12 -267,12 -267,10 +267,11 @@@@@ list(APPEND SOURC
        ${REACTOS_SOURCE_DIR}/ntoskrnl/se/sd.c
        ${REACTOS_SOURCE_DIR}/ntoskrnl/se/semgr.c
        ${REACTOS_SOURCE_DIR}/ntoskrnl/se/sid.c
 --     ${REACTOS_SOURCE_DIR}/ntoskrnl/se/srm.c
        ${REACTOS_SOURCE_DIR}/ntoskrnl/se/token.c
        ${REACTOS_SOURCE_DIR}/ntoskrnl/vf/driver.c
-       ${REACTOS_SOURCE_DIR}/ntoskrnl/wmi/wmi.c)
+  +    ${REACTOS_SOURCE_DIR}/ntoskrnl/wmi/guidobj.c
+       ${REACTOS_SOURCE_DIR}/ntoskrnl/wmi/wmi.c
+       ${REACTOS_SOURCE_DIR}/ntoskrnl/wmi/wmidrv.c)
    
    list(APPEND ASM_SOURCE ${REACTOS_SOURCE_DIR}/ntoskrnl/ex/zw.S)
    
index 0000000,da824c4,e53935d,0000000..301b457
mode 000000,100644,100644,000000..100644
--- /dev/null
--- /dev/null
@@@@@ -1,0 -1,267 -1,207 -1,0 +1,275 @@@@@
  - #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;
+  +}
+  +
index 0000000,46b2ca3,5267054,5267054..5fef374
mode 000000,100644,100644,100644..100644
--- /dev/null
@@@@@ -1,0 -1,398 -1,196 -1,196 +1,677 @@@@@
  --#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;
+   }
+   
+   
index 0000000,709505f,8c0caa4,2dffb3e..30cd72c
mode 000000,100644,100644,100644..100644
--- /dev/null
@@@@@ -1,0 -1,32 -1,30 -1,12 +1,39 @@@@@
+   
+   #pragma once
+   
+ ++#define GUID_STRING_LENGTH 36
+ ++
++++typedef struct _WMIP_IRP_CONTEXT
++++{
++++    LIST_ENTRY GuidObjectListHead;
++++} WMIP_IRP_CONTEXT, *PWMIP_IRP_CONTEXT;
++++
+  +typedef struct _WMIP_GUID_OBJECT
+  +{
+  +    GUID Guid;
++++    PIRP Irp;
++++    LIST_ENTRY IrpLink;
+  +} WMIP_GUID_OBJECT, *PWMIP_GUID_OBJECT;
+  +
+   
+   _Function_class_(DRIVER_INITIALIZE)
+   _IRQL_requires_same_
+   NTSTATUS
+   NTAPI
+   WmipDriverEntry(
+       _In_ PDRIVER_OBJECT DriverObject,
+       _In_ PUNICODE_STRING RegistryPath);
+   
+  +NTSTATUS
+  +NTAPI
+  +WmipInitializeGuidObjectType(
+  +    VOID);
+  +
+  +NTSTATUS
+  +NTAPI
+  +WmipOpenGuidObject(
+  +    POBJECT_ATTRIBUTES ObjectAttributes,
+  +    ACCESS_MASK DesiredAccess,
+  +    KPROCESSOR_MODE AccessMode,
+  +    PHANDLE OutGuidObjectHandle,
+  +    PVOID *OutGuidObject);