{
HANDLE Handle;
ULONG Unknown04;
- ULONG Unknown08;
- ULONG Unknown0C;
+ 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;
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(
/* Make sure the input buffer is large enough */
if ((InputLength < sizeof(WMIP_REGISTER_GUIDS)) ||
- (RegisterGuids->RegInfo.BufferSize >
+ (RegisterGuids->RegInfo.BufferSize >
(InputLength - FIELD_OFFSET(WMIP_REGISTER_GUIDS, RegInfo))))
{
return STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
- _SEH2_TRY
+ /* Capture object attributes */
+ PreviousMode = ExGetPreviousMode();
+ Status = WmipCaptureGuidObjectAttributes(RegisterGuids->ObjectAttributes,
+ &LocalObjectAttributes,
+ &LocalObjectName,
+ LocalObjectNameBuffer,
+ PreviousMode);
+ if (!NT_SUCCESS(Status))
{
- /* Probe and copy the object attributes structure */
- ProbeForRead(RegisterGuids->ObjectAttributes,
- sizeof(OBJECT_ATTRIBUTES),
- sizeof(PVOID));
- LocalObjectAttributes = *RegisterGuids->ObjectAttributes;
+ DPRINT1("WmipCaptureGuidObjectAttributes failed: 0x%lx\n", Status);
+ return Status;
+ }
- /* Probe and copy the object name UNICODE_STRING */
- ProbeForRead(LocalObjectAttributes.ObjectName,
- sizeof(UNICODE_STRING),
- sizeof(PVOID));
- LocalObjectName = *LocalObjectAttributes.ObjectName;
+ /* 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;
+ }
- /* Check if the object name has the expected length */
- if (LocalObjectName.Length != 45 * sizeof(WCHAR))
- {
- return STATUS_INVALID_PARAMETER;
- }
+ /* Dereference the GUID object */
+ ObDereferenceObject(GuidObject);
- /* Probe and copy the object name buffer */
- ProbeForRead(LocalObjectName.Buffer, LocalObjectName.Length, sizeof(WCHAR));
- RtlCopyMemory(LocalObjectNameBuffer,
- LocalObjectName.Buffer,
- LocalObjectName.Length);
+ /* Return the handle (user mode will close it) */
+ Result->Handle = GuidObjectHandle;
+ Result->TraceHandle = 0;
+ *OutputLength = 24;
- /* Fix pointers */
- LocalObjectName.Buffer = LocalObjectNameBuffer;
- LocalObjectAttributes.ObjectName = &LocalObjectName;
+ 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);
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+}
+
+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))
{
- DPRINT1("Got exception!\n");
- return _SEH2_GetExceptionCode();
+ return STATUS_INVALID_DEVICE_REQUEST;
}
- _SEH2_END;
- /* Open a new GUID object */
+ /// 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,
- SPECIFIC_RIGHTS_ALL,
+ OpenGuidForEvents->DesiredAccess,
PreviousMode,
&GuidObjectHandle,
&GuidObject);
if (!NT_SUCCESS(Status))
{
+ DPRINT1("WmipOpenGuidObject failed: 0x%lx\n", Status);
return Status;
}
- /* Derefernce the GUID object */
- ObDereferenceObject(GuidObject);
-
- /* Return the handle */
Result->Handle = GuidObjectHandle;
- *OutputLength = 24;
+
+ ObDereferenceObject(GuidObject);
return STATUS_SUCCESS;
}
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;