Author: pschweitzer
Date: Thu Jan 15 14:19:00 2009
New Revision: 38777
URL:
http://svn.reactos.org/svn/reactos?rev=38777&view=rev
Log:
Implemented FsRtlIsNotifyOnList, FsRtlNotifyCleanup
Modified:
branches/pierre-fsd/ntoskrnl/fsrtl/notify.c
branches/pierre-fsd/ntoskrnl/include/internal/fsrtl.h
Modified: branches/pierre-fsd/ntoskrnl/fsrtl/notify.c
URL:
http://svn.reactos.org/svn/reactos/branches/pierre-fsd/ntoskrnl/fsrtl/notif…
==============================================================================
--- branches/pierre-fsd/ntoskrnl/fsrtl/notify.c [iso-8859-1] (original)
+++ branches/pierre-fsd/ntoskrnl/fsrtl/notify.c [iso-8859-1] Thu Jan 15 14:19:00 2009
@@ -11,6 +11,95 @@
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+PNOTIFY_CHANGE
+FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList,
+ IN PVOID FsContext)
+{
+ PLIST_ENTRY NextEntry;
+ PNOTIFY_CHANGE NotifyChange;
+
+ if (!IsListEmpty(NotifyList))
+ {
+ /* Browse the notifications list to find the matching entry */
+ for (NextEntry = NotifyList->Flink;
+ NextEntry != NotifyList;
+ NextEntry = NextEntry->Flink)
+ {
+ NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
+ /* If the current record matches with the given context, it's the good
one */
+ if (NotifyChange->FsContext == FsContext)
+ {
+ return NotifyChange;
+ }
+ }
+ }
+ return NULL;
+}
+
+VOID
+FORCEINLINE
+FsRtlNotifyAcquireFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
+{
+ /* Only acquire fast mutex if it's not already acquired by the current thread */
+ if (RealNotifySync->OwningThread != (ULONG_PTR)KeGetCurrentThread())
+ {
+ ExAcquireFastMutexUnsafe(&(RealNotifySync->FastMutex));
+ RealNotifySync->OwningThread = (ULONG_PTR)KeGetCurrentThread();
+ }
+ /* Whatever the case, keep trace of the attempt to acquire fast mutex */
+ RealNotifySync->OwnerCount++;
+}
+
+VOID
+FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange,
+ IN NTSTATUS Status)
+{
+}
+
+VOID
+FORCEINLINE
+FsRtlNotifyReleaseFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
+{
+ RealNotifySync->OwnerCount--;
+ /* Release the fast mutex only if no other instance needs it */
+ if (!RealNotifySync->OwnerCount)
+ {
+ ExReleaseFastMutexUnsafe(&(RealNotifySync->FastMutex));
+ RealNotifySync->OwningThread = (ULONG_PTR)0;
+ }
+}
+
+/* PSEH FUNCTIONS ************************************************************/
+
+VOID
+FsRtlNotifyCleanupFinal(PREAL_NOTIFY_SYNC RealNotifySync,
+ PSECURITY_SUBJECT_CONTEXT SubjectContext)
+{
+ /* Release fast mutex */
+ FsRtlNotifyReleaseFastMutex(RealNotifySync);
+
+ /* If the subject security context was captured, release and free it */
+ if (SubjectContext)
+ {
+ SeReleaseSubjectContext(SubjectContext);
+ ExFreePool(SubjectContext);
+ }
+}
+
+_SEH_DEFINE_LOCALS(FsRtlNotifyCleanupFinal)
+{
+ PREAL_NOTIFY_SYNC RealNotifySync;
+ PSECURITY_SUBJECT_CONTEXT SubjectContext;
+};
+
+_SEH_FINALLYFUNC(FsRtlNotifyCleanupFinal_PSEH)
+{
+ _SEH_ACCESS_LOCALS(FsRtlNotifyCleanupFinal);
+ FsRtlNotifyCleanupFinal(_SEH_VAR(RealNotifySync), _SEH_VAR(SubjectContext));
+}
/* PUBLIC FUNCTIONS **********************************************************/
@@ -72,18 +161,18 @@
/*++
* @name FsRtlNotifyCleanup
- * @unimplemented
+ * @implemented
*
* Called by FSD when all handles to FileObject (identified by FsContext) are closed
*
- * @param NotifySync
- * FILLME
- *
- * @param NotifyList
- * FILLME
+ * @param NotifySync
+ * Synchronization object pointer
+ *
+ * @param NotifyList
+ * Notify list pointer (to head)
*
* @param FsContext
- * FILLME
+ * Used to identify the notify structure
*
* @return None
*
@@ -95,8 +184,60 @@
FsRtlNotifyCleanup(IN PNOTIFY_SYNC NotifySync,
IN PLIST_ENTRY NotifyList,
IN PVOID FsContext)
-{
- KEBUGCHECK(0);
+{
+ PNOTIFY_CHANGE NotifyChange;
+ PREAL_NOTIFY_SYNC RealNotifySync;
+
+ /* Get real structure hidden behind the opaque pointer */
+ RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
+
+ /* Acquire the fast mutex */
+ FsRtlNotifyAcquireFastMutex(RealNotifySync);
+
+ _SEH_TRY
+ {
+ _SEH_DECLARE_LOCALS(FsRtlNotifyCleanupFinal);
+ _SEH_VAR(RealNotifySync) = RealNotifySync;
+ _SEH_VAR(SubjectContext) = NULL;
+
+ /* Find if there's a matching notification with the FsContext */
+ NotifyChange = FsRtlIsNotifyOnList(NotifyList, FsContext);
+ if (NotifyChange)
+ {
+ /* Mark it as to know that cleanup is in process */
+ NotifyChange->Flags |= CLEANUP_IN_PROCESS;
+
+ /* If there are pending IRPs, complete them using the STATUS_NOTIFY_CLEANUP
status */
+ if (!IsListEmpty(NotifyChange->NotifyIrps))
+ {
+ FsRtlNotifyCompleteIrpList(NotifyChange, STATUS_NOTIFY_CLEANUP);
+ }
+ /* Remove from the list */
+ RemoveEntryList(NotifyChange->NotifyList);
+
+ /* Downcrease reference number and if 0 is reached, it's time to do total
cleanup */
+ if (!InterlockedDecrement((PLONG)&(NotifyChange->ReferenceCount)))
+ {
+ /* In case there was an allocated buffer, free it */
+ if (NotifyChange->AllocatedBuffer)
+ {
+ PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess,
NotifyChange->ThisBufferLength);
+ ExFreePool(NotifyChange->AllocatedBuffer);
+ }
+
+ /* In case there the string was set, get the captured subject security
context */
+ if (NotifyChange->FullDirectoryName)
+ {
+ _SEH_VAR(SubjectContext) = NotifyChange->SubjectContext;
+ }
+
+ /* Finally, free the notification, as it's not needed anymore */
+ ExFreePool(NotifyChange);
+ }
+ }
+ }
+ _SEH_FINALLY(FsRtlNotifyCleanupFinal_PSEH)
+ _SEH_END;
}
/*++
Modified: branches/pierre-fsd/ntoskrnl/include/internal/fsrtl.h
URL:
http://svn.reactos.org/svn/reactos/branches/pierre-fsd/ntoskrnl/include/int…
==============================================================================
--- branches/pierre-fsd/ntoskrnl/include/internal/fsrtl.h [iso-8859-1] (original)
+++ branches/pierre-fsd/ntoskrnl/include/internal/fsrtl.h [iso-8859-1] Thu Jan 15 14:19:00
2009
@@ -48,6 +48,11 @@
// Number of maximum pair count per MCB
//
#define MAXIMUM_PAIR_COUNT 15
+
+//
+// Notifications flags
+//
+#define CLEANUP_IN_PROCESS 4
//
// Internal structure for NOTIFY_SYNC