Author: pschweitzer
Date: Thu Nov 26 11:31:19 2009
New Revision: 44288
URL:
http://svn.reactos.org/svn/reactos?rev=44288&view=rev
Log:
Implemented IoReportTargetDeviceChangeAsynchronous and IoReportTargetDeviceChange
Modified:
branches/arty-newcc/ntoskrnl/include/internal/io.h
branches/arty-newcc/ntoskrnl/io/pnpmgr/pnpreport.c
Modified: branches/arty-newcc/ntoskrnl/include/internal/io.h
URL:
http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/include/int…
==============================================================================
--- branches/arty-newcc/ntoskrnl/include/internal/io.h [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/include/internal/io.h [iso-8859-1] Thu Nov 26 11:31:19
2009
@@ -490,6 +490,18 @@
} DEVICETREE_TRAVERSE_CONTEXT, *PDEVICETREE_TRAVERSE_CONTEXT;
//
+// Internal structure for notifications
+//
+typedef struct _INTERNAL_WORK_QUEUE_ITEM
+{
+ WORK_QUEUE_ITEM WorkItem;
+ PDEVICE_OBJECT PhysicalDeviceObject;
+ PDEVICE_CHANGE_COMPLETE_CALLBACK Callback;
+ PVOID Context;
+ PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure;
+} INTERNAL_WORK_QUEUE_ITEM, *PINTERNAL_WORK_QUEUE_ITEM;
+
+//
// PNP Routines
//
VOID
@@ -506,6 +518,16 @@
VOID
PnpInit2(
VOID
+);
+
+NTSTATUS
+PpSetCustomTargetEvent(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PKEVENT NotifyEvent,
+ IN OUT PNTSTATUS NotifyStatus,
+ IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback,
+ IN PVOID Context,
+ IN PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
);
VOID
@@ -613,6 +635,9 @@
IopGetRegistryValue(IN HANDLE Handle,
IN PWSTR ValueName,
OUT PKEY_VALUE_FULL_INFORMATION *Information);
+
+VOID
+IopReportTargetDeviceChangeAsyncWorker(PVOID Context);
//
Modified: branches/arty-newcc/ntoskrnl/io/pnpmgr/pnpreport.c
URL:
http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/io/pnpmgr/p…
==============================================================================
--- branches/arty-newcc/ntoskrnl/io/pnpmgr/pnpreport.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/io/pnpmgr/pnpreport.c [iso-8859-1] Thu Nov 26 11:31:19
2009
@@ -4,6 +4,7 @@
* FILE: ntoskrnl/io/pnpmgr/pnpreport.c
* PURPOSE: Device Changes Reporting Functions
* PROGRAMMERS: Filip Navara (xnavara(a)volny.cz)
+ * Pierre Schweitzer
*/
/* INCLUDES ******************************************************************/
@@ -11,6 +12,34 @@
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+NTSTATUS
+PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PKEVENT NotifyEvent,
+ IN OUT PNTSTATUS NotifyStatus,
+ IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback,
+ IN PVOID Context,
+ IN PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure)
+{
+ ASSERT(NotificationStructure);
+ ASSERT(DeviceObject);
+
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+VOID
+IopReportTargetDeviceChangeAsyncWorker(PVOID Context)
+{
+ PINTERNAL_WORK_QUEUE_ITEM Item;
+
+ Item = (PINTERNAL_WORK_QUEUE_ITEM)Context;
+ PpSetCustomTargetEvent(Item->PhysicalDeviceObject, NULL, NULL, Item->Callback,
Item->Context, Item->NotificationStructure);
+ ObDereferenceObject(Item->PhysicalDeviceObject);
+ ExFreePoolWithTag(Context, ' pP');
+}
/* PUBLIC FUNCTIONS **********************************************************/
@@ -112,35 +141,54 @@
}
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
NTAPI
IoReportTargetDeviceChange(IN PDEVICE_OBJECT PhysicalDeviceObject,
IN PVOID NotificationStructure)
{
- PTARGET_DEVICE_CUSTOM_NOTIFICATION IntNotificationStructure;
-
- ASSERT(NotificationStructure);
-
- if (!IopIsValidPhysicalDeviceObject(PhysicalDeviceObject))
- {
- KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG)PhysicalDeviceObject, 0, 0);
- }
-
- IntNotificationStructure = (PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure;
- if ((RtlCompareMemory(&(IntNotificationStructure->Event),
&(GUID_TARGET_DEVICE_QUERY_REMOVE), sizeof(GUID))) ||
- (RtlCompareMemory(&(IntNotificationStructure->Event),
&(GUID_TARGET_DEVICE_REMOVE_CANCELLED), sizeof(GUID))) ||
- (RtlCompareMemory(&(IntNotificationStructure->Event),
&(GUID_TARGET_DEVICE_REMOVE_COMPLETE), sizeof(GUID))))
- {
- return STATUS_INVALID_DEVICE_REQUEST;
- }
-
- return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * @unimplemented
+ KEVENT NotifyEvent;
+ NTSTATUS Status, NotifyStatus;
+ PTARGET_DEVICE_CUSTOM_NOTIFICATION notifyStruct =
(PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure;
+
+ ASSERT(notifyStruct);
+
+ /* Check for valid PDO */
+ if (!IopIsValidPhysicalDeviceObject(PhysicalDeviceObject))
+ {
+ KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG)PhysicalDeviceObject, 0, 0);
+ }
+
+ /* FileObject must be null. PnP will fill in it */
+ ASSERT(notifyStruct->FileObject == NULL);
+
+ /* Do not handle system PnP events */
+ if ((RtlCompareMemory(&(notifyStruct->Event),
&(GUID_TARGET_DEVICE_QUERY_REMOVE), sizeof(GUID)) != sizeof(GUID)) ||
+ (RtlCompareMemory(&(notifyStruct->Event),
&(GUID_TARGET_DEVICE_REMOVE_CANCELLED), sizeof(GUID)) != sizeof(GUID)) ||
+ (RtlCompareMemory(&(notifyStruct->Event),
&(GUID_TARGET_DEVICE_REMOVE_COMPLETE), sizeof(GUID)) != sizeof(GUID)))
+ {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ /* FIXME: Other checks to do on notify struct */
+
+ /* Initialize even that will let us know when PnP will have finished notify */
+ KeInitializeEvent(&NotifyEvent, NotificationEvent, FALSE);
+
+ Status = PpSetCustomTargetEvent(PhysicalDeviceObject, &NotifyEvent,
&NotifyStatus, NULL, NULL, notifyStruct);
+ /* If no error, wait for the notify to end and return the status of the notify and not
of the event */
+ if (NT_SUCCESS(Status))
+ {
+ KeWaitForSingleObject(&NotifyEvent, Executive, KernelMode, FALSE, NULL);
+ Status = NotifyStatus;
+ }
+
+ return Status;
+}
+
+/*
+ * @implemented
*/
NTSTATUS
NTAPI
@@ -149,6 +197,47 @@
IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback
OPTIONAL,
IN PVOID Context OPTIONAL)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
+ PINTERNAL_WORK_QUEUE_ITEM Item = NULL;
+ PTARGET_DEVICE_CUSTOM_NOTIFICATION notifyStruct =
(PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure;
+
+ ASSERT(notifyStruct);
+
+ /* Check for valid PDO */
+ if (!IopIsValidPhysicalDeviceObject(PhysicalDeviceObject))
+ {
+ KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG)PhysicalDeviceObject, 0, 0);
+ }
+
+ /* FileObject must be null. PnP will fill in it */
+ ASSERT(notifyStruct->FileObject == NULL);
+
+ /* Do not handle system PnP events */
+ if ((RtlCompareMemory(&(notifyStruct->Event),
&(GUID_TARGET_DEVICE_QUERY_REMOVE), sizeof(GUID)) != sizeof(GUID)) ||
+ (RtlCompareMemory(&(notifyStruct->Event),
&(GUID_TARGET_DEVICE_REMOVE_CANCELLED), sizeof(GUID)) != sizeof(GUID)) ||
+ (RtlCompareMemory(&(notifyStruct->Event),
&(GUID_TARGET_DEVICE_REMOVE_COMPLETE), sizeof(GUID)) != sizeof(GUID)))
+ {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ /* FIXME: Other checks to do on notify struct */
+
+ /* We need to store all the data given by the caller with the WorkItem, so use our own
struct */
+ Item = ExAllocatePoolWithTag(NonPagedPool, sizeof(INTERNAL_WORK_QUEUE_ITEM), '
pP');
+ if (!Item)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Initialize all stuff */
+ ObReferenceObject(PhysicalDeviceObject);
+ Item->NotificationStructure = notifyStruct;
+ Item->PhysicalDeviceObject = PhysicalDeviceObject;
+ Item->Callback = Callback;
+ Item->Context = Context;
+ ExInitializeWorkItem(&(Item->WorkItem),
(PWORKER_THREAD_ROUTINE)IopReportTargetDeviceChangeAsyncWorker, Item);
+
+ /* Finally, queue the item, our work here is done */
+ ExQueueWorkItem(&(Item->WorkItem), DelayedWorkQueue);
+
+ return STATUS_PENDING;
+}