[NTOSKRNL]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 23 Feb 2014 14:56:48 +0000 (14:56 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 23 Feb 2014 14:56:48 +0000 (14:56 +0000)
Implement WmipFastIoDeviceControl, start implementing WmipIoControl

svn path=/branches/kernel-fun/; revision=62302

reactos/include/reactos/wmiioctl.h [moved from reactos/include/reactos/wmiguid.h with 100% similarity]
reactos/ntoskrnl/wmi/wmidrv.c

index 5267054..46b2ca3 100644 (file)
 
 #include <ntoskrnl.h>
 #include <wmistr.h>
-#include <wmiguid.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;
+    ULONG Unknown08;
+    ULONG Unknown0C;
+    BOOLEAN Unknown10;
+} WMIP_RESULT, *PWMIP_RESULT;
+
+
 PDEVICE_OBJECT WmipServiceDeviceObject;
 PDEVICE_OBJECT WmipAdminDeviceObject;
 FAST_IO_DISPATCH WmipFastIoDispatch;
@@ -42,14 +66,167 @@ WmipOpenCloseCleanup(
     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
+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;
+    }
+
+    _SEH2_TRY
+    {
+        /* Probe and copy the object attributes structure */
+        ProbeForRead(RegisterGuids->ObjectAttributes,
+                     sizeof(OBJECT_ATTRIBUTES),
+                     sizeof(PVOID));
+        LocalObjectAttributes = *RegisterGuids->ObjectAttributes;
+
+        /* Probe and copy the object name UNICODE_STRING */
+        ProbeForRead(LocalObjectAttributes.ObjectName,
+                     sizeof(UNICODE_STRING),
+                     sizeof(PVOID));
+        LocalObjectName = *LocalObjectAttributes.ObjectName;
+
+        /* Check if the object name has the expected length */
+        if (LocalObjectName.Length != 45 * sizeof(WCHAR))
+        {
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        /* Probe and copy the object name buffer */
+        ProbeForRead(LocalObjectName.Buffer, LocalObjectName.Length, sizeof(WCHAR));
+        RtlCopyMemory(LocalObjectNameBuffer,
+                      LocalObjectName.Buffer,
+                      LocalObjectName.Length);
+
+        /* Fix pointers */
+        LocalObjectName.Buffer = LocalObjectNameBuffer;
+        LocalObjectAttributes.ObjectName = &LocalObjectName;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        DPRINT1("Got exception!\n");
+        return _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+
+    /* Open a new GUID object */
+    PreviousMode = ExGetPreviousMode();
+    Status = WmipOpenGuidObject(&LocalObjectAttributes,
+                                SPECIFIC_RIGHTS_ALL,
+                                PreviousMode,
+                                &GuidObjectHandle,
+                                &GuidObject);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    /* Derefernce the GUID object */
+    ObDereferenceObject(GuidObject);
+
+    /* Return the handle */
+    Result->Handle = GuidObjectHandle;
+    *OutputLength = 24;
+
+    return STATUS_SUCCESS;
+}
+
 NTSTATUS
 NTAPI
 WmipIoControl(
-  _Inout_  PDEVICE_OBJECT DeviceObject,
-  _Inout_  PIRP Irp)
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _Inout_ PIRP Irp)
 {
-    UNIMPLEMENTED_DBGBREAK();
-    return STATUS_NOT_IMPLEMENTED;
+    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;
+        }
+
+        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
@@ -87,7 +264,32 @@ WmipFastIoDeviceControl(
     _Out_ PIO_STATUS_BLOCK IoStatus,
     _In_ PDEVICE_OBJECT DeviceObject)
 {
-    UNIMPLEMENTED_DBGBREAK();
+    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;
 }