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/inte... ============================================================================== --- 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/pn... ============================================================================== --- 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@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; +}