[prev in list] [next in list] [prev in thread] [next in thread] 

List:       ros-diffs
Subject:    [ros-diffs] [gdalsnes] 13782: init. work on a notify-directory impl.
From:       <gdalsnes () svn ! reactos ! com>
Date:       2005-02-28 21:01:00
Message-ID: 000001c51dd8$9b41cf50$6601a8c0 () penelope
[Download RAW message or body]

init. work on a notify-directory impl.
Modified: trunk/reactos/ntoskrnl/fs/notify.c
  _____  

Modified: trunk/reactos/ntoskrnl/fs/notify.c
--- trunk/reactos/ntoskrnl/fs/notify.c	2005-02-28 20:43:23 UTC (rev
13781)
+++ trunk/reactos/ntoskrnl/fs/notify.c	2005-02-28 21:00:59 UTC (rev
13782)
@@ -5,14 +5,126 @@

  * FILE:            ntoskrnl/fs/notify.c
  * PURPOSE:         No purpose listed.
  *
- * PROGRAMMERS:     No programmer listed.
+ * PROGRAMMERS:     Gunnar Dalsnes
  */
 
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
+
+PAGED_LOOKASIDE_LIST    NotifyEntryLookaside;
+
+typedef struct _NOTIFY_ENTRY
+{
+   LIST_ENTRY ListEntry;
+   PSTRING FullDirectoryName;
+   BOOLEAN WatchTree;
+   BOOLEAN IgnoreBuffer;
+   ULONG CompletionFilter;
+   LIST_ENTRY IrpQueue;
+   PVOID Fcb;
+   PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback;
+   PSECURITY_SUBJECT_CONTEXT SubjectContext;
+   PVOID FsContext;
+   LIST_ENTRY BufferedChangesList;
+} NOTIFY_ENTRY, *PNOTIFY_ENTRY;
+
+typedef struct _BUFFERED_CHANGE
+{
+   LIST_ENTRY ListEntry;
+   ULONG Action;
+   USHORT NameLen;
+   WCHAR RelativeName[1];
+   
+} BUFFERED_CHANGE, *PBUFFERED_CHANGE;
+
+
 /**********************************************************************
+ * NAME                    PRIVATE
+ * FsRtlpInitNotifyImplementation
+ *
+ */
+VOID
+STDCALL INIT_FUNCTION
+FsRtlpInitNotifyImplementation(VOID)
+{
+   ExInitializePagedLookasideList( &NotifyEntryLookaside,
+                                    NULL,
+                                    NULL,
+                                    0,
+                                    sizeof(NOTIFY_ENTRY),
+                                    0 /* FSRTL_NOTIFY_TAG*/,
+                                    0
+                                    );
+
+   
+}
+
+
+
+
+
+/**********************************************************************
+ * NAME                    PRIVATE
+ * FsRtlpNotifyCancelRoutine
+ *
+ */
+static
+VOID
+STDCALL 
+FsRtlpNotifyCancelRoutine(
+   IN PDEVICE_OBJECT DeviceObject, 
+   IN PIRP Irp
+   )
+{
+   PFAST_MUTEX Lock;
+
+   //don't need this since we have our own sync. protecting irp
cancellation
+   IoReleaseCancelSpinLock(Irp->CancelIrql); 
+
+   Lock = (PFAST_MUTEX)Irp->Tail.Overlay.DriverContext[3];
+
+   ExAcquireFastMutex(Lock );
+   
+   RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+   
+   ExReleaseFastMutex(Lock);
+
+   Irp->IoStatus.Status = STATUS_CANCELLED;
+   Irp->IoStatus.Information = 0;
+
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   
+}
+
+
+
+static
+PNOTIFY_ENTRY
+FASTCALL
+FsRtlpFindNotifyEntry(
+   PLIST_ENTRY NotifyList,
+   PVOID FsContext
+   )
+{
+   PLIST_ENTRY EnumEntry;
+   PNOTIFY_ENTRY NotifyEntry;
+   
+   LIST_FOR_EACH(EnumEntry, NotifyList)
+   {
+      NotifyEntry = CONTAINING_RECORD(EnumEntry, NOTIFY_ENTRY,
ListEntry);
+      
+      if (NotifyEntry->FsContext == FsContext)
+      {
+         return NotifyEntry;
+      }
+   }
+
+   return NULL;   
+}
+
+/**********************************************************************
  * NAME							EXPORTED
  *	FsRtlNotifyChangeDirectory@28
  *
@@ -57,7 +169,8 @@
  *	FsRtlNotifyCleanup@12
  *
  * DESCRIPTION
- *	
+ *	 Called by FSD when all handles to FileObject (identified by
FsContext) are closed
+ *
  * ARGUMENTS
  *
  * RETURN VALUE
@@ -72,6 +185,64 @@
 	IN	PVOID		FsContext
 	)
 {
+   PNOTIFY_ENTRY NotifyEntry;
+   LIST_ENTRY CompletedListHead;
+   PLIST_ENTRY TmpEntry;
+   PBUFFERED_CHANGE BufferedChange;
+   PIRP Irp;
+   
+   InitializeListHead(&CompletedListHead);
+   
+   ExAcquireFastMutex((PFAST_MUTEX)NotifySync);   
+   
+   NotifyEntry = FsRtlpFindNotifyEntry(NotifyList, FsContext);
+   
+   if (NotifyEntry)
+   {
+      /* free buffered changes */
+      while (!IsListEmpty(&NotifyEntry->BufferedChangesList))
+      {
+         TmpEntry = RemoveHeadList(&NotifyEntry->BufferedChangesList);
+         BufferedChange = CONTAINING_RECORD(TmpEntry , BUFFERED_CHANGE,
ListEntry);
+         ExFreePool(BufferedChange);
+      }
+
+      /* cancel(?) pending irps */
+      while (!IsListEmpty(&NotifyEntry->IrpQueue))
+      {
+         TmpEntry = RemoveHeadList(&NotifyEntry->IrpQueue);
+         Irp = CONTAINING_RECORD(TmpEntry , IRP,
Tail.Overlay.ListEntry);
+
+         /* irp cancelation bolilerplate */
+         if (!IoSetCancelRoutine(Irp, NULL))
+         {  
+            //The cancel routine will be called. When we release the
lock it will complete the irp.
+            InitializeListHead(&Irp->Tail.Overlay.ListEntry);
+            continue;
+         }
+
+         Irp->IoStatus.Status = STATUS_NOTIFY_CLEANUP; /* FIXME:
correct status? */
+         Irp->IoStatus.Information = 0;
+
+         /* avoid holding lock while completing irp */
+         InsertTailList(&CompletedListHead,
&Irp->Tail.Overlay.ListEntry);
+      }
+         
+      /* Unlink and free the NotifyStruct */
+      RemoveEntryList(&NotifyEntry->ListEntry);
+      ExFreeToPagedLookasideList(&NotifyEntryLookaside, NotifyEntry);
+   }
+   
+   ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+   
+   /* complete defered irps */
+   while (!IsListEmpty(&CompletedListHead)) 
+   {
+      TmpEntry = RemoveHeadList(&CompletedListHead);
+      Irp = CONTAINING_RECORD(TmpEntry , IRP, Tail.Overlay.ListEntry);
+      IoCompleteRequest(Irp, IO_NO_INCREMENT);     
+   }
+   
 }
 
 
@@ -119,6 +290,75 @@
 }
 
 
+
+static
+VOID
+FASTCALL
+FsRtlpWatchedDirectoryWasDeleted(
+   IN PNOTIFY_SYNC         NotifySync,
+   IN PLIST_ENTRY       NotifyList,
+   IN PVOID          Fcb
+   )
+{
+   LIST_ENTRY CompletedListHead;
+   PLIST_ENTRY EnumEntry, TmpEntry;
+   PNOTIFY_ENTRY NotifyEntry;
+   PBUFFERED_CHANGE BufferedChange;
+   PIRP Irp;
+   
+   InitializeListHead(&CompletedListHead);
+   
+   ExAcquireFastMutex((PFAST_MUTEX)NotifySync);
+
+   LIST_FOR_EACH_SAFE(EnumEntry, NotifyList, NotifyEntry, NOTIFY_ENTRY,
ListEntry )
+   {
+      if (NotifyEntry->Fcb == Fcb)
+      {
+         RemoveEntryList(&NotifyEntry->ListEntry);         
+         
+         /* free buffered changes */
+         while (!IsListEmpty(&NotifyEntry->BufferedChangesList))
+         {
+            TmpEntry =
RemoveHeadList(&NotifyEntry->BufferedChangesList);
+            BufferedChange = CONTAINING_RECORD(TmpEntry ,
BUFFERED_CHANGE, ListEntry);
+            ExFreePool(BufferedChange);
+         }
+         
+         /* cancel(?) pending irps */
+         while (!IsListEmpty(&NotifyEntry->IrpQueue))
+         {
+            TmpEntry = RemoveHeadList(&NotifyEntry->IrpQueue);
+            Irp = CONTAINING_RECORD(TmpEntry , IRP,
Tail.Overlay.ListEntry);
+
+            /* irp cancelation bolilerplate */
+            if (!IoSetCancelRoutine(Irp, NULL))
+            {  
+               //The cancel routine will be called. When we release the
lock it will complete the irp.
+               InitializeListHead(&Irp->Tail.Overlay.ListEntry);
+               continue;
+            }
+            
+            Irp->IoStatus.Status = STATUS_NOTIFY_CLEANUP; /* FIXME:
correct status? */
+            Irp->IoStatus.Information = 0;
+         
+            /* avoid holding lock while completing irp */
+            InsertTailList(&CompletedListHead,
&Irp->Tail.Overlay.ListEntry);
+         }
+      }
+   }
+   
+   ExReleaseFastMutex((PFAST_MUTEX)NotifySync);   
+   
+   /* complete defered irps */
+   while (!IsListEmpty(&CompletedListHead)) 
+   {
+      TmpEntry = RemoveHeadList(&CompletedListHead);
+      Irp = CONTAINING_RECORD(TmpEntry , IRP, Tail.Overlay.ListEntry);
+      IoCompleteRequest(Irp, IO_NO_INCREMENT);     
+   }
+   
+}
+
 /**********************************************************************
  * NAME							EXPORTED
  *	FsRtlNotifyFullChangeDirectory@40
@@ -137,23 +377,185 @@
 	IN	PNOTIFY_SYNC			NotifySync,
 	IN	PLIST_ENTRY			NotifyList,
 	IN	PVOID				FsContext,
-	IN	PSTRING				FullDirectoryName,
-	IN	BOOLEAN				WatchTree,
-	IN	BOOLEAN				IgnoreBuffer,
-	IN	ULONG				CompletionFilter,
-	IN	PIRP				NotifyIrp,
-	IN	PCHECK_FOR_TRAVERSE_ACCESS	TraverseCallback
OPTIONAL,
+   IN PSTRING           FullDirectoryName,
+   IN BOOLEAN           WatchTree,
+   IN BOOLEAN           IgnoreBuffer,
+   IN ULONG          CompletionFilter,
+   IN PIRP           NotifyIrp,
+   IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback  OPTIONAL,
 	IN	PSECURITY_SUBJECT_CONTEXT	SubjectContext
OPTIONAL
 	)
 {
-#if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1300)
-	DbgPrint("%s()\n", __FUNCTION__);
-#else
-	DbgPrint("FsRtlNotifyFullChangeDirectory()\n");
-#endif
+   PIO_STACK_LOCATION IrpStack;   
+   PNOTIFY_ENTRY NotifyEntry;
+   PBUFFERED_CHANGE BufferedChange; 
+   PLIST_ENTRY TmpEntry;
+   
+   if (!NotifyIrp)
+   {
+      /* all other params are ignored if NotifyIrp == NULL */
+      FsRtlpWatchedDirectoryWasDeleted(NotifySync, NotifyList,
FsContext);
+      return;
+   }
+   
+   ExAcquireFastMutex((PFAST_MUTEX)NotifySync);
+   
+   IrpStack = IoGetCurrentIrpStackLocation(NotifyIrp);
+   if (IrpStack->FileObject->Flags & FO_CLEANUP_COMPLETE)
+   {
+      ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+      
+      NotifyIrp->IoStatus.Information = 0;
+      NotifyIrp->IoStatus.Status = STATUS_NOTIFY_CLEANUP;
+      IoCompleteRequest(NotifyIrp, IO_NO_INCREMENT);
+      return;       
+   }
+   
+   NotifyEntry = FsRtlpFindNotifyEntry(NotifyList, FsContext);
+
+   if (!NotifyEntry)
+   {
+      /* No NotifyStruct for this FileObject existed */
+      
+      NotifyEntry =
ExAllocateFromPagedLookasideList(&NotifyEntryLookaside);
+      
+      NotifyEntry->FsContext = FsContext;
+      NotifyEntry->FullDirectoryName = FullDirectoryName;
+      NotifyEntry->WatchTree = WatchTree;
+      NotifyEntry->IgnoreBuffer = IgnoreBuffer;
+      NotifyEntry->CompletionFilter = CompletionFilter;
+      NotifyEntry->TraverseCallback = TraverseCallback;
+      NotifyEntry->SubjectContext = SubjectContext;
+      NotifyEntry->Fcb = IrpStack->FileObject->FsContext;
+      InitializeListHead(&NotifyEntry->IrpQueue);
+      InitializeListHead(&NotifyEntry->BufferedChangesList);
+      
+      InsertTailList(NotifyList, &NotifyEntry->ListEntry);
+   }
+   
+   /*
+    * FIXME: this NotifyStruct allready have values for WatchTree,
CompletionFilter etc.
+    * What if the WatchTree, CompletionFilter etc. params are different
from
+    * those in the NotifyStruct? Should the params be ignored or should
the params overwrite
+    * the "old" values in the NotifyStruct??
+    * STATUS: Currently we ignore these params for subsequesnt request.
+    *
+    * -Gunnar
+    */
+
+   if (IsListEmpty(&NotifyEntry->BufferedChangesList))
+   {
+      /* No changes are pending. Queue the irp */
+
+      /* Irp cancelation boilerplate */
+      IoSetCancelRoutine(NotifyIrp, FsRtlpNotifyCancelRoutine);
+      if (NotifyIrp->Cancel && IoSetCancelRoutine(NotifyIrp, NULL))
+      {              
+         //irp was canceled
+         ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+
+         NotifyIrp->IoStatus.Status = STATUS_CANCELLED;
+         NotifyIrp->IoStatus.Information = 0;
+
+         IoCompleteRequest(NotifyIrp, IO_NO_INCREMENT);
+         return;
+      }
+
+      IoMarkIrpPending(NotifyIrp);
+
+      //FIXME: any point in setting irp status/information before
queueing?
+      
+      /* save NotifySych for use in the cancel routine */
+      NotifyIrp->Tail.Overlay.DriverContext[3] = NotifySync;
+      InsertTailList(&NotifyEntry->IrpQueue,
&NotifyIrp->Tail.Overlay.ListEntry);
+
+      ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+      return;
+   }
+    
+
+    
+
+   /*
+   typedef struct _FILE_NOTIFY_INFORMATION {
+   ULONG NextEntryOffset;
+   ULONG Action;
+   ULONG NameLength;
+   WCHAR Name[1];
+   } FILE_NOTIFY_INFORMATION, *PFILE_NOTIFY_INFORMATION;
+   */
+   
+   /* Buffered changes exist */
+   
+   
+   /* Copy as much buffered data as available/the buffer can hold */
+   while (!IsListEmpty(&NotifyEntry->BufferedChangesList))
+   {
+      TmpEntry = RemoveHeadList(&NotifyEntry->BufferedChangesList);
+      BufferedChange = CONTAINING_RECORD(TmpEntry, BUFFERED_CHANGE,
ListEntry);
+
+       /* FIXME:
+       Fill user-buffer with recorded events until full. If user buffer
is too small to hold even
+       a single record or can only hold some of the events, what should
we do????????????
+       */
+       
+       /* FIXME: implement this (copy data to user) */
+
+//             BufferedChange->Action = Action;
+//             RecordedChange->Name
+//             RecordedChange->NameLength
+
+      ExFreePool(BufferedChange);
+
+
+   }
+
+   ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+   
+   NotifyIrp->IoStatus.Information = 0; //<- FIXME
+   NotifyIrp->IoStatus.Status = STATUS_SUCCESS;
+   IoCompleteRequest(NotifyIrp, IO_NO_INCREMENT);
 }
 
 
+
+static
+PIRP
+FASTCALL
+FsRtlpGetNextIrp(PNOTIFY_ENTRY NotifyEntry)
+{
+   PIRP Irp;
+   PLIST_ENTRY TmpEntry;   
+   
+   /* Loop to get a non-canceled irp */
+   while (!IsListEmpty(&NotifyEntry->IrpQueue))
+   {
+      /* If we have queued irp(s) we can't possibly have buffered
changes too */
+      ASSERT(IsListEmpty(&NotifyEntry->BufferedChangesList));
+         
+      TmpEntry = RemoveHeadList(&NotifyEntry->IrpQueue);
+      Irp = CONTAINING_RECORD(TmpEntry , IRP, Tail.Overlay.ListEntry);
+
+      /* irp cancelation bolilerplate */
+      if (!IoSetCancelRoutine(Irp, NULL))
+      {  
+         //The cancel routine will be called. When we release the lock
it will complete the irp.
+         InitializeListHead(&Irp->Tail.Overlay.ListEntry);
+         continue;
+      }
+
+      /* Finally we got a non-canceled irp */
+      return Irp;            
+   }
+   
+   return NULL;
+}
+   
+   
+   
+   
+
+
 /**********************************************************************
  * NAME							EXPORTED
  *	FsRtlNotifyFullReportChange@36
@@ -172,7 +574,7 @@
 	IN	PNOTIFY_SYNC	NotifySync,
 	IN	PLIST_ENTRY	NotifyList,
 	IN	PSTRING		FullTargetName,
-	IN	USHORT		TargetNameOffset,
+	IN	USHORT		TargetNameOffset, /* in bytes */
 	IN	PSTRING		StreamName		OPTIONAL,
 	IN	PSTRING		NormalizedParentName	OPTIONAL,
 	IN	ULONG		FilterMatch,
@@ -180,6 +582,80 @@
 	IN	PVOID		TargetContext
 	)
 {
+   UNICODE_STRING FullDirName;
+   UNICODE_STRING TargetName;
+   PLIST_ENTRY EnumEntry;
+   PNOTIFY_ENTRY NotifyEntry;
+   PBUFFERED_CHANGE BufferedChange;
+   PIRP Irp;
+   LIST_ENTRY CompletedListHead;
+   
+   InitializeListHead(&CompletedListHead);
+   
+   FullDirName.Buffer = (WCHAR*)FullTargetName->Buffer;
+   FullDirName.MaximumLength = FullDirName.Length = TargetNameOffset -
sizeof(WCHAR);
+   
+   TargetName.Buffer = (WCHAR*)(FullTargetName->Buffer +
TargetNameOffset);
+   TargetName.MaximumLength = TargetName.Length =
FullTargetName->Length - TargetNameOffset;
+   
+
+   ExAcquireFastMutex((PFAST_MUTEX)NotifySync);   
+
+   LIST_FOR_EACH_SAFE(EnumEntry, NotifyList, NotifyEntry, NOTIFY_ENTRY,
ListEntry )
+   {
+      /* rule out some easy cases */
+      /* FIXME: short vs. long names??? */
+      if (FilterMatch != NotifyEntry->CompletionFilter) continue;
+      
+      if (FullDirName.Length < NotifyEntry->FullDirectoryName->Length)
continue;
+      
+      if (!NotifyEntry->WatchTree && FullDirName.Length !=
NotifyEntry->FullDirectoryName->Length) continue;
+
+      if (wcsncmp((WCHAR*)NotifyEntry->FullDirectoryName->Buffer, 
+            FullDirName.Buffer, 
+            NotifyEntry->FullDirectoryName->Length/sizeof(WCHAR)) != 0)
continue;
+      
+      /* Found a valid change */
+      
+      if ((Irp = FsRtlpGetNextIrp(NotifyEntry)))
+      {
+         //FIXME: copy data to user
+         
+         Irp->IoStatus.Status = STATUS_SUCCESS;
+         Irp->IoStatus.Information = 0;
+         
+         /* avoid holding lock while completing irp */
+         InsertTailList(&CompletedListHead,
&Irp->Tail.Overlay.ListEntry);
+      }
+      else
+      {
+         /* No irp in queue. Buffer changes */
+         /* FIXME: how much stuff should we buffer? 
+            -Should we alloc with quotas? 
+            -Should we use a hardcoded limit?
+            -Should we use a time-out? (drop changes if they are not
retrieved in x seconds?
+         */
+         BufferedChange = ExAllocatePool(PagedPool,
FIELD_OFFSET(BUFFERED_CHANGE, RelativeName) + TargetName.Length);
+         
+         BufferedChange->Action = Action;
+         BufferedChange->NameLen = TargetName.Length;
+         memcpy(BufferedChange->RelativeName, TargetName.Buffer,
TargetName.Length); 
+         
+         InsertTailList(&NotifyEntry->BufferedChangesList,
&BufferedChange->ListEntry);
+      }
+   }
+
+   ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+   
+   /* complete defered irps */
+   while (!IsListEmpty(&CompletedListHead)) 
+   {
+      EnumEntry = RemoveHeadList(&CompletedListHead);
+      Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
+      
+      IoCompleteRequest(Irp, IO_NO_INCREMENT);     
+   }
+   
 }
 
 
@@ -198,25 +674,11 @@
 VOID
 STDCALL
 FsRtlNotifyInitializeSync (
-    IN  PNOTIFY_SYNC NotifySync
+    IN  PNOTIFY_SYNC *NotifySync
 	)
 {
-#if 0
-    *NotifySync = NULL;
-    *NotifySync = ExAllocatePoolWithTag (
-			0x10,			// PoolType???
-			sizeof (NOTIFY_SYNC),	// NumberOfBytes = 0x28
-			FSRTL_TAG
-			);
-
-    *NotifySync->Unknown0 = 1;
-    *NotifySync->Unknown2 = 0;
-    *NotifySync->Unknown3 = 1;
-    *NotifySync->Unknown4 = 4;
-    *NotifySync->Unknown5 = 0;
-    *NotifySync->Unknown9 = 0;
-    *NotifySync->Unknown10 = 0;
-#endif
+   *NotifySync = ExAllocatePoolWithTag(NonPagedPool,
sizeof(FAST_MUTEX), 0/*FSRTL_NOTIFY_TAG*/ );
+   ExInitializeFastMutex((PFAST_MUTEX)*NotifySync);
 }
 
 
@@ -246,11 +708,11 @@
 		NotifySync,
 		NotifyList,
 		FullTargetName,
-		(FullTargetName->Length - *FileNamePartLength), /*?*/
+		(FullTargetName->Length - *FileNamePartLength),
 		NULL,
 		NULL,
 		FilterMatch,
-		0, /* Action ? */
+		0,
 		NULL
 		);
 }
@@ -276,16 +738,10 @@
 VOID
 STDCALL
 FsRtlNotifyUninitializeSync (
-    IN OUT PNOTIFY_SYNC NotifySync
+    IN PNOTIFY_SYNC NotifySync
 	)
 {
-#if 0
-    if (NULL != *NotifySync) 
-	{
-        ExFreePool (*NotifySync);
-        *NotifySync = NULL;
-	}
-#endif
+   ExFreePool (NotifySync);
 }
 
 /**********************************************************************

[Attachment #3 (text/html)]

<html>
<head>
<style>
<!--
body { background-color:#ffffff }
.file { border:1px solid #eeeeee; margin-top:1em; margin-bottom:1em }
.pathname { font-family:monospace; float:right }
.fileheader { margin-bottom:.5em }
.diff { margin:0 }
.tasklist { padding:4px; border:1px dashed #000000; margin-top:1em }
.tasklist ul { margin-top:0; margin-bottom:0 }
tr.alt { background-color:#eeeeee }
#added { background-color:#ddffdd }
#addedchars { background-color:#99ff99; font-weight:bolder }
tr.alt #added { background-color:#ccf7cc }
#removed { background-color:#ffdddd }
#removedchars { background-color:#ff9999; font-weight:bolder }
tr.alt #removed { background-color:#f7cccc }
#info { color:#888888 }
#context { background-color:#eeeeee }
td {padding-left:.3em; padding-right:.3em }
tr.head { border-bottom-width:1px; border-bottom-style:solid }
tr.head td { padding:0; padding-top:.2em }
.task { background-color:#ffff00 }
.comment { padding:4px; border:1px dashed #000000; background-color:#ffffdd }
.error { color:red }
hr { border-width:0px; height:2px; background:black }
-->
</style>
</head>
<body>
<pre class="comment">init. work on a notify-directory impl.</pre><pre class="diff" \
id="context">Modified: trunk/reactos/ntoskrnl/fs/notify.c </pre><hr /><div \
class="file"> <div class="fileheader"><big><b>Modified: \
trunk/reactos/ntoskrnl/fs/notify.c</b></big></div> <pre class="diff"><small \
                id="info">--- trunk/reactos/ntoskrnl/fs/notify.c	2005-02-28 20:43:23 \
                UTC (rev 13781)
+++ trunk/reactos/ntoskrnl/fs/notify.c	2005-02-28 21:00:59 UTC (rev 13782)
@@ -5,14 +5,126 @@
</small></pre><pre class="diff" id="context"> &nbsp;* FILE: &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp;ntoskrnl/fs/notify.c  &nbsp;* PURPOSE: &nbsp; &nbsp; &nbsp; \
&nbsp; No purpose listed.  &nbsp;*
</pre><pre class="diff" id="removed">- * PROGRAMMERS: &nbsp; &nbsp; <span \
id="removedchars">No programmer listed.</span> </pre><pre class="diff" id="added">+ * \
PROGRAMMERS: &nbsp; &nbsp; <span id="addedchars">Gunnar Dalsnes</span> </pre><pre \
class="diff" id="context"> &nbsp;*/  
 #include &lt;ntoskrnl.h&gt;
 #define NDEBUG
 #include &lt;internal/debug.h&gt;
 
</pre><pre class="diff" id="added">+
+PAGED_LOOKASIDE_LIST &nbsp; &nbsp;NotifyEntryLookaside;
+
+typedef struct _NOTIFY_ENTRY
+{
+ &nbsp; LIST_ENTRY ListEntry;
+ &nbsp; PSTRING FullDirectoryName;
+ &nbsp; BOOLEAN WatchTree;
+ &nbsp; BOOLEAN IgnoreBuffer;
+ &nbsp; ULONG CompletionFilter;
+ &nbsp; LIST_ENTRY IrpQueue;
+ &nbsp; PVOID Fcb;
+ &nbsp; PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback;
+ &nbsp; PSECURITY_SUBJECT_CONTEXT SubjectContext;
+ &nbsp; PVOID FsContext;
+ &nbsp; LIST_ENTRY BufferedChangesList;
+} NOTIFY_ENTRY, *PNOTIFY_ENTRY;
+
+typedef struct _BUFFERED_CHANGE
+{
+ &nbsp; LIST_ENTRY ListEntry;
+ &nbsp; ULONG Action;
+ &nbsp; USHORT NameLen;
+ &nbsp; WCHAR RelativeName[1];
+ &nbsp; 
+} BUFFERED_CHANGE, *PBUFFERED_CHANGE;
+
+
</pre><pre class="diff" id="context"> \
/********************************************************************** </pre><pre \
class="diff" id="added">+ * NAME &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp;PRIVATE + * FsRtlpInitNotifyImplementation
+ *
+ */
+VOID
+STDCALL INIT_FUNCTION
+FsRtlpInitNotifyImplementation(VOID)
+{
+ &nbsp; ExInitializePagedLookasideList( &amp;NotifyEntryLookaside,
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NULL, + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp;NULL, + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0, + &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp;sizeof(NOTIFY_ENTRY), + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 \
/* FSRTL_NOTIFY_TAG*/, + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 + &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;); +
+ &nbsp; 
+}
+
+
+
+
+
+/**********************************************************************
+ * NAME &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PRIVATE
+ * FsRtlpNotifyCancelRoutine
+ *
+ */
+static
+VOID
+STDCALL 
+FsRtlpNotifyCancelRoutine(
+ &nbsp; IN PDEVICE_OBJECT DeviceObject, 
+ &nbsp; IN PIRP Irp
+ &nbsp; )
+{
+ &nbsp; PFAST_MUTEX Lock;
+
+ &nbsp; //don't need this since we have our own sync. protecting irp cancellation
+ &nbsp; IoReleaseCancelSpinLock(Irp-&gt;CancelIrql); 
+
+ &nbsp; Lock = (PFAST_MUTEX)Irp-&gt;Tail.Overlay.DriverContext[3];
+
+ &nbsp; ExAcquireFastMutex(Lock );
+ &nbsp; 
+ &nbsp; RemoveEntryList(&amp;Irp-&gt;Tail.Overlay.ListEntry);
+ &nbsp; 
+ &nbsp; ExReleaseFastMutex(Lock);
+
+ &nbsp; Irp-&gt;IoStatus.Status = STATUS_CANCELLED;
+ &nbsp; Irp-&gt;IoStatus.Information = 0;
+
+ &nbsp; IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ &nbsp; 
+}
+
+
+
+static
+PNOTIFY_ENTRY
+FASTCALL
+FsRtlpFindNotifyEntry(
+ &nbsp; PLIST_ENTRY NotifyList,
+ &nbsp; PVOID FsContext
+ &nbsp; )
+{
+ &nbsp; PLIST_ENTRY EnumEntry;
+ &nbsp; PNOTIFY_ENTRY NotifyEntry;
+ &nbsp; 
+ &nbsp; LIST_FOR_EACH(EnumEntry, NotifyList)
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;NotifyEntry = CONTAINING_RECORD(EnumEntry, NOTIFY_ENTRY, \
ListEntry); + &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;if (NotifyEntry-&gt;FsContext == FsContext)
+ &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; return NotifyEntry;
+ &nbsp; &nbsp; &nbsp;}
+ &nbsp; }
+
+ &nbsp; return NULL; &nbsp; 
+}
+
+/**********************************************************************
</pre><pre class="diff" id="context"> &nbsp;* NAME							EXPORTED
 &nbsp;*	FsRtlNotifyChangeDirectory@28
 &nbsp;*
@@ -57,7 +169,8 @@
</pre><pre class="diff" id="context"> &nbsp;*	FsRtlNotifyCleanup@12
 &nbsp;*
 &nbsp;* DESCRIPTION
</pre><pre class="diff" id="removed">- *	
</pre><pre class="diff" id="added">+ *	<span id="addedchars"> Called by FSD when all \
handles to FileObject (identified by FsContext) are closed</span> + *
</pre><pre class="diff" id="context"> &nbsp;* ARGUMENTS
 &nbsp;*
 &nbsp;* RETURN VALUE
@@ -72,6 +185,64 @@
</pre><pre class="diff" id="context"> 	IN	PVOID		FsContext
 	)
 {
</pre><pre class="diff" id="added">+ &nbsp; PNOTIFY_ENTRY NotifyEntry;
+ &nbsp; LIST_ENTRY CompletedListHead;
+ &nbsp; PLIST_ENTRY TmpEntry;
+ &nbsp; PBUFFERED_CHANGE BufferedChange;
+ &nbsp; PIRP Irp;
+ &nbsp; 
+ &nbsp; InitializeListHead(&amp;CompletedListHead);
+ &nbsp; 
+ &nbsp; ExAcquireFastMutex((PFAST_MUTEX)NotifySync); &nbsp; 
+ &nbsp; 
+ &nbsp; NotifyEntry = FsRtlpFindNotifyEntry(NotifyList, FsContext);
+ &nbsp; 
+ &nbsp; if (NotifyEntry)
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;/* free buffered changes */
+ &nbsp; &nbsp; &nbsp;while (!IsListEmpty(&amp;NotifyEntry-&gt;BufferedChangesList))
+ &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; TmpEntry = \
RemoveHeadList(&amp;NotifyEntry-&gt;BufferedChangesList); + &nbsp; &nbsp; &nbsp; \
&nbsp; BufferedChange = CONTAINING_RECORD(TmpEntry , BUFFERED_CHANGE, ListEntry); + \
&nbsp; &nbsp; &nbsp; &nbsp; ExFreePool(BufferedChange); + &nbsp; &nbsp; &nbsp;}
+
+ &nbsp; &nbsp; &nbsp;/* cancel(?) pending irps */
+ &nbsp; &nbsp; &nbsp;while (!IsListEmpty(&amp;NotifyEntry-&gt;IrpQueue))
+ &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; TmpEntry = \
RemoveHeadList(&amp;NotifyEntry-&gt;IrpQueue); + &nbsp; &nbsp; &nbsp; &nbsp; Irp = \
CONTAINING_RECORD(TmpEntry , IRP, Tail.Overlay.ListEntry); +
+ &nbsp; &nbsp; &nbsp; &nbsp; /* irp cancelation bolilerplate */
+ &nbsp; &nbsp; &nbsp; &nbsp; if (!IoSetCancelRoutine(Irp, NULL))
+ &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//The cancel routine will be called. When \
we release the lock it will complete the irp. + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp;InitializeListHead(&amp;Irp-&gt;Tail.Overlay.ListEntry); + &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp;continue; + &nbsp; &nbsp; &nbsp; &nbsp; }
+
+ &nbsp; &nbsp; &nbsp; &nbsp; Irp-&gt;IoStatus.Status = STATUS_NOTIFY_CLEANUP; /* \
FIXME: correct status? */ + &nbsp; &nbsp; &nbsp; &nbsp; Irp-&gt;IoStatus.Information \
= 0; +
+ &nbsp; &nbsp; &nbsp; &nbsp; /* avoid holding lock while completing irp */
+ &nbsp; &nbsp; &nbsp; &nbsp; InsertTailList(&amp;CompletedListHead, \
&amp;Irp-&gt;Tail.Overlay.ListEntry); + &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; 
+ &nbsp; &nbsp; &nbsp;/* Unlink and free the NotifyStruct */
+ &nbsp; &nbsp; &nbsp;RemoveEntryList(&amp;NotifyEntry-&gt;ListEntry);
+ &nbsp; &nbsp; &nbsp;ExFreeToPagedLookasideList(&amp;NotifyEntryLookaside, \
NotifyEntry); + &nbsp; }
+ &nbsp; 
+ &nbsp; ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+ &nbsp; 
+ &nbsp; /* complete defered irps */
+ &nbsp; while (!IsListEmpty(&amp;CompletedListHead)) 
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;TmpEntry = RemoveHeadList(&amp;CompletedListHead);
+ &nbsp; &nbsp; &nbsp;Irp = CONTAINING_RECORD(TmpEntry , IRP, \
Tail.Overlay.ListEntry); + &nbsp; &nbsp; &nbsp;IoCompleteRequest(Irp, \
IO_NO_INCREMENT); &nbsp; &nbsp;  + &nbsp; }
+ &nbsp; 
</pre><pre class="diff" id="context"> }
 
 
@@ -119,6 +290,75 @@
</pre><pre class="diff" id="context"> }
 
 
</pre><pre class="diff" id="added">+
+static
+VOID
+FASTCALL
+FsRtlpWatchedDirectoryWasDeleted(
+ &nbsp; IN PNOTIFY_SYNC &nbsp; &nbsp; &nbsp; &nbsp; NotifySync,
+ &nbsp; IN PLIST_ENTRY &nbsp; &nbsp; &nbsp; NotifyList,
+ &nbsp; IN PVOID &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Fcb
+ &nbsp; )
+{
+ &nbsp; LIST_ENTRY CompletedListHead;
+ &nbsp; PLIST_ENTRY EnumEntry, TmpEntry;
+ &nbsp; PNOTIFY_ENTRY NotifyEntry;
+ &nbsp; PBUFFERED_CHANGE BufferedChange;
+ &nbsp; PIRP Irp;
+ &nbsp; 
+ &nbsp; InitializeListHead(&amp;CompletedListHead);
+ &nbsp; 
+ &nbsp; ExAcquireFastMutex((PFAST_MUTEX)NotifySync);
+
+ &nbsp; LIST_FOR_EACH_SAFE(EnumEntry, NotifyList, NotifyEntry, NOTIFY_ENTRY, \
ListEntry ) + &nbsp; {
+ &nbsp; &nbsp; &nbsp;if (NotifyEntry-&gt;Fcb == Fcb)
+ &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; RemoveEntryList(&amp;NotifyEntry-&gt;ListEntry); &nbsp; \
&nbsp; &nbsp; &nbsp;  + &nbsp; &nbsp; &nbsp; &nbsp; 
+ &nbsp; &nbsp; &nbsp; &nbsp; /* free buffered changes */
+ &nbsp; &nbsp; &nbsp; &nbsp; while \
(!IsListEmpty(&amp;NotifyEntry-&gt;BufferedChangesList)) + &nbsp; &nbsp; &nbsp; \
&nbsp; { + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TmpEntry = \
RemoveHeadList(&amp;NotifyEntry-&gt;BufferedChangesList); + &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp;BufferedChange = CONTAINING_RECORD(TmpEntry , BUFFERED_CHANGE, \
ListEntry); + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ExFreePool(BufferedChange);
+ &nbsp; &nbsp; &nbsp; &nbsp; }
+ &nbsp; &nbsp; &nbsp; &nbsp; 
+ &nbsp; &nbsp; &nbsp; &nbsp; /* cancel(?) pending irps */
+ &nbsp; &nbsp; &nbsp; &nbsp; while (!IsListEmpty(&amp;NotifyEntry-&gt;IrpQueue))
+ &nbsp; &nbsp; &nbsp; &nbsp; {
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TmpEntry = \
RemoveHeadList(&amp;NotifyEntry-&gt;IrpQueue); + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp;Irp = CONTAINING_RECORD(TmpEntry , IRP, Tail.Overlay.ListEntry); +
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/* irp cancelation bolilerplate */
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (!IoSetCancelRoutine(Irp, NULL))
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //The cancel routine will be \
called. When we release the lock it will complete the irp. + &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; InitializeListHead(&amp;Irp-&gt;Tail.Overlay.ListEntry); \
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue; + &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp;} + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Irp-&gt;IoStatus.Status = \
STATUS_NOTIFY_CLEANUP; /* FIXME: correct status? */ + &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp;Irp-&gt;IoStatus.Information = 0; + &nbsp; &nbsp; &nbsp; &nbsp; 
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/* avoid holding lock while completing irp \
*/ + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;InsertTailList(&amp;CompletedListHead, \
&amp;Irp-&gt;Tail.Overlay.ListEntry); + &nbsp; &nbsp; &nbsp; &nbsp; }
+ &nbsp; &nbsp; &nbsp;}
+ &nbsp; }
+ &nbsp; 
+ &nbsp; ExReleaseFastMutex((PFAST_MUTEX)NotifySync); &nbsp; 
+ &nbsp; 
+ &nbsp; /* complete defered irps */
+ &nbsp; while (!IsListEmpty(&amp;CompletedListHead)) 
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;TmpEntry = RemoveHeadList(&amp;CompletedListHead);
+ &nbsp; &nbsp; &nbsp;Irp = CONTAINING_RECORD(TmpEntry , IRP, \
Tail.Overlay.ListEntry); + &nbsp; &nbsp; &nbsp;IoCompleteRequest(Irp, \
IO_NO_INCREMENT); &nbsp; &nbsp;  + &nbsp; }
+ &nbsp; 
+}
+
</pre><pre class="diff" id="context"> \
/**********************************************************************  &nbsp;* \
NAME							EXPORTED  &nbsp;*	FsRtlNotifyFullChangeDirectory@40
@@ -137,23 +377,185 @@
</pre><pre class="diff" id="context"> 	IN	PNOTIFY_SYNC			NotifySync,
 	IN	PLIST_ENTRY			NotifyList,
 	IN	PVOID				FsContext,
</pre><pre class="diff" id="removed">-	IN	PSTRING				FullDirectoryName,
-	IN	BOOLEAN				WatchTree,
-	IN	BOOLEAN				IgnoreBuffer,
-	IN	ULONG				CompletionFilter,
-	IN	PIRP				NotifyIrp,
-<span id="removedchars">	IN	PCHECK_FOR_TRAVERSE_ACCESS	TraverseCallback	OPTIONAL</span>,
 </pre><pre class="diff" id="added">+<span id="addedchars"> &nbsp; IN PSTRING &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; FullDirectoryName</span>, + &nbsp; IN BOOLEAN &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; WatchTree, + &nbsp; IN BOOLEAN &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; IgnoreBuffer, + &nbsp; IN ULONG &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp;CompletionFilter, + &nbsp; IN PIRP &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
NotifyIrp, + &nbsp; IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback &nbsp;OPTIONAL,
</pre><pre class="diff" id="context"> \
IN	PSECURITY_SUBJECT_CONTEXT	SubjectContext		OPTIONAL  )
 {
</pre><pre class="diff" id="removed">-#if defined(__GNUC__) || (defined(_MSC_VER) \
                &amp;&amp; _MSC_VER &gt;= 1300)
-	DbgPrint(&quot;%s()\n&quot;, __FUNCTION__);
-#else
-	DbgPrint(&quot;FsRtlNotifyFullChangeDirectory()\n&quot;);
-#endif
</pre><pre class="diff" id="added">+ &nbsp; PIO_STACK_LOCATION IrpStack; &nbsp; 
+ &nbsp; PNOTIFY_ENTRY NotifyEntry;
+ &nbsp; PBUFFERED_CHANGE BufferedChange; 
+ &nbsp; PLIST_ENTRY TmpEntry;
+ &nbsp; 
+ &nbsp; if (!NotifyIrp)
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;/* all other params are ignored if NotifyIrp == NULL */
+ &nbsp; &nbsp; &nbsp;FsRtlpWatchedDirectoryWasDeleted(NotifySync, NotifyList, \
FsContext); + &nbsp; &nbsp; &nbsp;return;
+ &nbsp; }
+ &nbsp; 
+ &nbsp; ExAcquireFastMutex((PFAST_MUTEX)NotifySync);
+ &nbsp; 
+ &nbsp; IrpStack = IoGetCurrentIrpStackLocation(NotifyIrp);
+ &nbsp; if (IrpStack-&gt;FileObject-&gt;Flags &amp; FO_CLEANUP_COMPLETE)
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+ &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;NotifyIrp-&gt;IoStatus.Information = 0;
+ &nbsp; &nbsp; &nbsp;NotifyIrp-&gt;IoStatus.Status = STATUS_NOTIFY_CLEANUP;
+ &nbsp; &nbsp; &nbsp;IoCompleteRequest(NotifyIrp, IO_NO_INCREMENT);
+ &nbsp; &nbsp; &nbsp;return; &nbsp; &nbsp; &nbsp; 
+ &nbsp; }
+ &nbsp; 
+ &nbsp; NotifyEntry = FsRtlpFindNotifyEntry(NotifyList, FsContext);
+
+ &nbsp; if (!NotifyEntry)
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;/* No NotifyStruct for this FileObject existed */
+ &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;NotifyEntry = \
ExAllocateFromPagedLookasideList(&amp;NotifyEntryLookaside); + &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;NotifyEntry-&gt;FsContext = FsContext;
+ &nbsp; &nbsp; &nbsp;NotifyEntry-&gt;FullDirectoryName = FullDirectoryName;
+ &nbsp; &nbsp; &nbsp;NotifyEntry-&gt;WatchTree = WatchTree;
+ &nbsp; &nbsp; &nbsp;NotifyEntry-&gt;IgnoreBuffer = IgnoreBuffer;
+ &nbsp; &nbsp; &nbsp;NotifyEntry-&gt;CompletionFilter = CompletionFilter;
+ &nbsp; &nbsp; &nbsp;NotifyEntry-&gt;TraverseCallback = TraverseCallback;
+ &nbsp; &nbsp; &nbsp;NotifyEntry-&gt;SubjectContext = SubjectContext;
+ &nbsp; &nbsp; &nbsp;NotifyEntry-&gt;Fcb = IrpStack-&gt;FileObject-&gt;FsContext;
+ &nbsp; &nbsp; &nbsp;InitializeListHead(&amp;NotifyEntry-&gt;IrpQueue);
+ &nbsp; &nbsp; &nbsp;InitializeListHead(&amp;NotifyEntry-&gt;BufferedChangesList);
+ &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;InsertTailList(NotifyList, &amp;NotifyEntry-&gt;ListEntry);
+ &nbsp; }
+ &nbsp; 
+ &nbsp; /*
+ &nbsp; &nbsp;* FIXME: this NotifyStruct allready have values for WatchTree, \
CompletionFilter etc. + &nbsp; &nbsp;* What if the WatchTree, CompletionFilter etc. \
params are different from + &nbsp; &nbsp;* those in the NotifyStruct? Should the \
params be ignored or should the params overwrite + &nbsp; &nbsp;* the &quot;old&quot; \
values in the NotifyStruct?? + &nbsp; &nbsp;* STATUS: Currently we ignore these \
params for subsequesnt request.  + &nbsp; &nbsp;*
+ &nbsp; &nbsp;* -Gunnar
+ &nbsp; &nbsp;*/
+
+ &nbsp; if (IsListEmpty(&amp;NotifyEntry-&gt;BufferedChangesList))
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;/* No changes are pending. Queue the irp */
+
+ &nbsp; &nbsp; &nbsp;/* Irp cancelation boilerplate */
+ &nbsp; &nbsp; &nbsp;IoSetCancelRoutine(NotifyIrp, FsRtlpNotifyCancelRoutine);
+ &nbsp; &nbsp; &nbsp;if (NotifyIrp-&gt;Cancel &amp;&amp; \
IoSetCancelRoutine(NotifyIrp, NULL)) + &nbsp; &nbsp; &nbsp;{ &nbsp; &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp; + &nbsp; &nbsp; &nbsp; &nbsp; //irp was canceled
+ &nbsp; &nbsp; &nbsp; &nbsp; ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+
+ &nbsp; &nbsp; &nbsp; &nbsp; NotifyIrp-&gt;IoStatus.Status = STATUS_CANCELLED;
+ &nbsp; &nbsp; &nbsp; &nbsp; NotifyIrp-&gt;IoStatus.Information = 0;
+
+ &nbsp; &nbsp; &nbsp; &nbsp; IoCompleteRequest(NotifyIrp, IO_NO_INCREMENT);
+ &nbsp; &nbsp; &nbsp; &nbsp; return;
+ &nbsp; &nbsp; &nbsp;}
+
+ &nbsp; &nbsp; &nbsp;IoMarkIrpPending(NotifyIrp);
+
+ &nbsp; &nbsp; &nbsp;//FIXME: any point in setting irp status/information before \
queueing? + &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;/* save NotifySych for use in the cancel routine */
+ &nbsp; &nbsp; &nbsp;NotifyIrp-&gt;Tail.Overlay.DriverContext[3] = NotifySync;
+ &nbsp; &nbsp; &nbsp;InsertTailList(&amp;NotifyEntry-&gt;IrpQueue, \
&amp;NotifyIrp-&gt;Tail.Overlay.ListEntry); +
+ &nbsp; &nbsp; &nbsp;ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+ &nbsp; &nbsp; &nbsp;return;
+ &nbsp; }
+ &nbsp; &nbsp;
+
+ &nbsp; &nbsp;
+
+ &nbsp; /*
+ &nbsp; typedef struct _FILE_NOTIFY_INFORMATION {
+ &nbsp; ULONG NextEntryOffset;
+ &nbsp; ULONG Action;
+ &nbsp; ULONG NameLength;
+ &nbsp; WCHAR Name[1];
+ &nbsp; } FILE_NOTIFY_INFORMATION, *PFILE_NOTIFY_INFORMATION;
+ &nbsp; */
+ &nbsp; 
+ &nbsp; /* Buffered changes exist */
+ &nbsp; 
+ &nbsp; 
+ &nbsp; /* Copy as much buffered data as available/the buffer can hold */
+ &nbsp; while (!IsListEmpty(&amp;NotifyEntry-&gt;BufferedChangesList))
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;TmpEntry = \
RemoveHeadList(&amp;NotifyEntry-&gt;BufferedChangesList); + &nbsp; &nbsp; \
&nbsp;BufferedChange = CONTAINING_RECORD(TmpEntry, BUFFERED_CHANGE, ListEntry); +
+ &nbsp; &nbsp; &nbsp; /* FIXME:
+ &nbsp; &nbsp; &nbsp; Fill user-buffer with recorded events until full. If user \
buffer is too small to hold even + &nbsp; &nbsp; &nbsp; a single record or can only \
hold some of the events, what should we do???????????? + &nbsp; &nbsp; &nbsp; */
+ &nbsp; &nbsp; &nbsp; 
+ &nbsp; &nbsp; &nbsp; /* FIXME: implement this (copy data to user) */
+
+// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BufferedChange-&gt;Action = Action;
+// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RecordedChange-&gt;Name
+// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RecordedChange-&gt;NameLength
+
+ &nbsp; &nbsp; &nbsp;ExFreePool(BufferedChange);
+
+
+ &nbsp; }
+
+ &nbsp; ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+ &nbsp; 
+ &nbsp; NotifyIrp-&gt;IoStatus.Information = 0; //&lt;- FIXME
+ &nbsp; NotifyIrp-&gt;IoStatus.Status = STATUS_SUCCESS;
+ &nbsp; IoCompleteRequest(NotifyIrp, IO_NO_INCREMENT);
</pre><pre class="diff" id="context"> }
 
 
</pre><pre class="diff" id="added">+
+static
+PIRP
+FASTCALL
+FsRtlpGetNextIrp(PNOTIFY_ENTRY NotifyEntry)
+{
+ &nbsp; PIRP Irp;
+ &nbsp; PLIST_ENTRY TmpEntry; &nbsp; 
+ &nbsp; 
+ &nbsp; /* Loop to get a non-canceled irp */
+ &nbsp; while (!IsListEmpty(&amp;NotifyEntry-&gt;IrpQueue))
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;/* If we have queued irp(s) we can't possibly have buffered \
changes too */ + &nbsp; &nbsp; \
&nbsp;ASSERT(IsListEmpty(&amp;NotifyEntry-&gt;BufferedChangesList)); + &nbsp; &nbsp; \
&nbsp; &nbsp;  + &nbsp; &nbsp; &nbsp;TmpEntry = \
RemoveHeadList(&amp;NotifyEntry-&gt;IrpQueue); + &nbsp; &nbsp; &nbsp;Irp = \
CONTAINING_RECORD(TmpEntry , IRP, Tail.Overlay.ListEntry); +
+ &nbsp; &nbsp; &nbsp;/* irp cancelation bolilerplate */
+ &nbsp; &nbsp; &nbsp;if (!IoSetCancelRoutine(Irp, NULL))
+ &nbsp; &nbsp; &nbsp;{ &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; //The cancel routine will be called. When we release \
the lock it will complete the irp. + &nbsp; &nbsp; &nbsp; &nbsp; \
InitializeListHead(&amp;Irp-&gt;Tail.Overlay.ListEntry); + &nbsp; &nbsp; &nbsp; \
&nbsp; continue; + &nbsp; &nbsp; &nbsp;}
+
+ &nbsp; &nbsp; &nbsp;/* Finally we got a non-canceled irp */
+ &nbsp; &nbsp; &nbsp;return Irp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; }
+ &nbsp; 
+ &nbsp; return NULL;
+}
+ &nbsp; 
+ &nbsp; 
+ &nbsp; 
+ &nbsp; 
+
+
</pre><pre class="diff" id="context"> \
/**********************************************************************  &nbsp;* \
NAME							EXPORTED  &nbsp;*	FsRtlNotifyFullReportChange@36
@@ -172,7 +574,7 @@
</pre><pre class="diff" id="context"> 	IN	PNOTIFY_SYNC	NotifySync,
 	IN	PLIST_ENTRY	NotifyList,
 	IN	PSTRING		FullTargetName,
</pre><pre class="diff" id="removed">-	IN	USHORT		TargetNameOffset,
</pre><pre class="diff" id="added">+	IN	USHORT		TargetNameOffset,<span \
id="addedchars"> /* in bytes */</span> </pre><pre class="diff" id="context"> \
IN	PSTRING		StreamName		OPTIONAL,  IN	PSTRING		NormalizedParentName	OPTIONAL,
 	IN	ULONG		FilterMatch,
@@ -180,6 +582,80 @@
</pre><pre class="diff" id="context"> 	IN	PVOID		TargetContext
 	)
 {
</pre><pre class="diff" id="added">+ &nbsp; UNICODE_STRING FullDirName;
+ &nbsp; UNICODE_STRING TargetName;
+ &nbsp; PLIST_ENTRY EnumEntry;
+ &nbsp; PNOTIFY_ENTRY NotifyEntry;
+ &nbsp; PBUFFERED_CHANGE BufferedChange;
+ &nbsp; PIRP Irp;
+ &nbsp; LIST_ENTRY CompletedListHead;
+ &nbsp; 
+ &nbsp; InitializeListHead(&amp;CompletedListHead);
+ &nbsp; 
+ &nbsp; FullDirName.Buffer = (WCHAR*)FullTargetName-&gt;Buffer;
+ &nbsp; FullDirName.MaximumLength = FullDirName.Length = TargetNameOffset - \
sizeof(WCHAR); + &nbsp; 
+ &nbsp; TargetName.Buffer = (WCHAR*)(FullTargetName-&gt;Buffer + TargetNameOffset);
+ &nbsp; TargetName.MaximumLength = TargetName.Length = FullTargetName-&gt;Length - \
TargetNameOffset; + &nbsp; 
+
+ &nbsp; ExAcquireFastMutex((PFAST_MUTEX)NotifySync); &nbsp; 
+
+ &nbsp; LIST_FOR_EACH_SAFE(EnumEntry, NotifyList, NotifyEntry, NOTIFY_ENTRY, \
ListEntry ) + &nbsp; {
+ &nbsp; &nbsp; &nbsp;/* rule out some easy cases */
+ &nbsp; &nbsp; &nbsp;/* FIXME: short vs. long names??? */
+ &nbsp; &nbsp; &nbsp;if (FilterMatch != NotifyEntry-&gt;CompletionFilter) continue;
+ &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;if (FullDirName.Length &lt; \
NotifyEntry-&gt;FullDirectoryName-&gt;Length) continue; + &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;if (!NotifyEntry-&gt;WatchTree &amp;&amp; FullDirName.Length != \
NotifyEntry-&gt;FullDirectoryName-&gt;Length) continue; +
+ &nbsp; &nbsp; &nbsp;if \
(wcsncmp((WCHAR*)NotifyEntry-&gt;FullDirectoryName-&gt;Buffer,  + &nbsp; &nbsp; \
&nbsp; &nbsp; &nbsp; &nbsp;FullDirName.Buffer,  + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp;NotifyEntry-&gt;FullDirectoryName-&gt;Length/sizeof(WCHAR)) != 0) continue; + \
&nbsp; &nbsp; &nbsp; + &nbsp; &nbsp; &nbsp;/* Found a valid change */
+ &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;if ((Irp = FsRtlpGetNextIrp(NotifyEntry)))
+ &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; //FIXME: copy data to user
+ &nbsp; &nbsp; &nbsp; &nbsp; 
+ &nbsp; &nbsp; &nbsp; &nbsp; Irp-&gt;IoStatus.Status = STATUS_SUCCESS;
+ &nbsp; &nbsp; &nbsp; &nbsp; Irp-&gt;IoStatus.Information = 0;
+ &nbsp; &nbsp; &nbsp; &nbsp; 
+ &nbsp; &nbsp; &nbsp; &nbsp; /* avoid holding lock while completing irp */
+ &nbsp; &nbsp; &nbsp; &nbsp; InsertTailList(&amp;CompletedListHead, \
&amp;Irp-&gt;Tail.Overlay.ListEntry); + &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp;else
+ &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; /* No irp in queue. Buffer changes */
+ &nbsp; &nbsp; &nbsp; &nbsp; /* FIXME: how much stuff should we buffer? 
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-Should we alloc with quotas? 
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-Should we use a hardcoded limit?
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-Should we use a time-out? (drop changes \
if they are not retrieved in x seconds? + &nbsp; &nbsp; &nbsp; &nbsp; */
+ &nbsp; &nbsp; &nbsp; &nbsp; BufferedChange = ExAllocatePool(PagedPool, \
FIELD_OFFSET(BUFFERED_CHANGE, RelativeName) + TargetName.Length); + &nbsp; &nbsp; \
&nbsp; &nbsp;  + &nbsp; &nbsp; &nbsp; &nbsp; BufferedChange-&gt;Action = Action;
+ &nbsp; &nbsp; &nbsp; &nbsp; BufferedChange-&gt;NameLen = TargetName.Length;
+ &nbsp; &nbsp; &nbsp; &nbsp; memcpy(BufferedChange-&gt;RelativeName, \
TargetName.Buffer, TargetName.Length);  + &nbsp; &nbsp; &nbsp; &nbsp; 
+ &nbsp; &nbsp; &nbsp; &nbsp; \
InsertTailList(&amp;NotifyEntry-&gt;BufferedChangesList, \
&amp;BufferedChange-&gt;ListEntry); + &nbsp; &nbsp; &nbsp;}
+ &nbsp; }
+
+ &nbsp; ExReleaseFastMutex((PFAST_MUTEX)NotifySync);
+ &nbsp; 
+ &nbsp; /* complete defered irps */
+ &nbsp; while (!IsListEmpty(&amp;CompletedListHead)) 
+ &nbsp; {
+ &nbsp; &nbsp; &nbsp;EnumEntry = RemoveHeadList(&amp;CompletedListHead);
+ &nbsp; &nbsp; &nbsp;Irp = CONTAINING_RECORD(EnumEntry, IRP, \
Tail.Overlay.ListEntry); + &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;IoCompleteRequest(Irp, IO_NO_INCREMENT); &nbsp; &nbsp; 
+ &nbsp; }
+ &nbsp; 
</pre><pre class="diff" id="context"> }
 
 
@@ -198,25 +674,11 @@
</pre><pre class="diff" id="context"> VOID
 STDCALL
 FsRtlNotifyInitializeSync (
</pre><pre class="diff" id="removed">- &nbsp; &nbsp;IN &nbsp;PNOTIFY_SYNC NotifySync
</pre><pre class="diff" id="added">+ &nbsp; &nbsp;IN &nbsp;PNOTIFY_SYNC <span \
id="addedchars">*</span>NotifySync </pre><pre class="diff" id="context"> 	)
 {
</pre><pre class="diff" id="removed">-#if 0
- &nbsp; &nbsp;*NotifySync = NULL;
- &nbsp; &nbsp;*NotifySync = ExAllocatePoolWithTag (
-			0x10,			// PoolType???
-			sizeof (NOTIFY_SYNC),	// NumberOfBytes = 0x28
-			FSRTL_TAG
-			);
-
- &nbsp; &nbsp;*NotifySync-&gt;Unknown0 = 1;
- &nbsp; &nbsp;*NotifySync-&gt;Unknown2 = 0;
- &nbsp; &nbsp;*NotifySync-&gt;Unknown3 = 1;
- &nbsp; &nbsp;*NotifySync-&gt;Unknown4 = 4;
- &nbsp; &nbsp;*NotifySync-&gt;Unknown5 = 0;
- &nbsp; &nbsp;*NotifySync-&gt;Unknown9 = 0;
- &nbsp; &nbsp;*NotifySync-&gt;Unknown10 = 0;
-#endif
</pre><pre class="diff" id="added">+ &nbsp; *NotifySync = \
ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), 0/*FSRTL_NOTIFY_TAG*/ ); + \
&nbsp; ExInitializeFastMutex((PFAST_MUTEX)*NotifySync); </pre><pre class="diff" \
id="context"> }  
 
@@ -246,11 +708,11 @@
</pre><pre class="diff" id="context"> 		NotifySync,
 		NotifyList,
 		FullTargetName,
</pre><pre class="diff" id="removed">-		(FullTargetName-&gt;Length - \
*FileNamePartLength),<span id="removedchars"> /*?*/</span> </pre><pre class="diff" \
id="added">+		(FullTargetName-&gt;Length - *FileNamePartLength), </pre><pre \
class="diff" id="context"> 		NULL,  NULL,
 		FilterMatch,
</pre><pre class="diff" id="removed">-		0,<span id="removedchars"> /* Action ? \
*/</span> </pre><pre class="diff" id="added">+		0,
</pre><pre class="diff" id="context"> 		NULL
 		);
 }
@@ -276,16 +738,10 @@
</pre><pre class="diff" id="context"> VOID
 STDCALL
 FsRtlNotifyUninitializeSync (
</pre><pre class="diff" id="removed">- &nbsp; &nbsp;IN <span id="removedchars">OUT \
</span>PNOTIFY_SYNC NotifySync </pre><pre class="diff" id="added">+ &nbsp; &nbsp;IN \
PNOTIFY_SYNC NotifySync </pre><pre class="diff" id="context"> 	)
 {
</pre><pre class="diff" id="removed">-#if 0
- &nbsp; &nbsp;if (NULL != *NotifySync) 
-	{
- &nbsp; &nbsp; &nbsp; &nbsp;ExFreePool (*NotifySync);
- &nbsp; &nbsp; &nbsp; &nbsp;*NotifySync = NULL;
-	}
-#endif
</pre><pre class="diff" id="added">+ &nbsp; ExFreePool (NotifySync);
</pre><pre class="diff" id="context"> }
 
 /**********************************************************************
</pre>
</div>

</body>
</html>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic