mirror of
https://github.com/reactos/reactos.git
synced 2025-02-25 01:39:30 +00:00
init. work on a notify-directory impl.
svn path=/trunk/; revision=13782
This commit is contained in:
parent
e508120441
commit
799674bef8
1 changed files with 497 additions and 41 deletions
|
@ -5,13 +5,125 @@
|
|||
* 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 @@ FsRtlNotifyChangeDirectory (
|
|||
* FsRtlNotifyCleanup@12
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Called by FSD when all handles to FileObject (identified by FsContext) are closed
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURN VALUE
|
||||
|
@ -72,6 +185,64 @@ FsRtlNotifyCleanup (
|
|||
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 @@ FsRtlNotifyFilterReportChange (
|
|||
}
|
||||
|
||||
|
||||
|
||||
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 @@ FsRtlNotifyFullChangeDirectory (
|
|||
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 @@ FsRtlNotifyFullReportChange (
|
|||
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 @@ FsRtlNotifyFullReportChange (
|
|||
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 @@ FsRtlNotifyFullReportChange (
|
|||
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 @@ FsRtlNotifyReportChange (
|
|||
NotifySync,
|
||||
NotifyList,
|
||||
FullTargetName,
|
||||
(FullTargetName->Length - *FileNamePartLength), /*?*/
|
||||
(FullTargetName->Length - *FileNamePartLength),
|
||||
NULL,
|
||||
NULL,
|
||||
FilterMatch,
|
||||
0, /* Action ? */
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
@ -276,16 +738,10 @@ FsRtlNotifyReportChange (
|
|||
VOID
|
||||
STDCALL
|
||||
FsRtlNotifyUninitializeSync (
|
||||
IN OUT PNOTIFY_SYNC NotifySync
|
||||
IN PNOTIFY_SYNC NotifySync
|
||||
)
|
||||
{
|
||||
#if 0
|
||||
if (NULL != *NotifySync)
|
||||
{
|
||||
ExFreePool (*NotifySync);
|
||||
*NotifySync = NULL;
|
||||
}
|
||||
#endif
|
||||
ExFreePool (NotifySync);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
|
Loading…
Reference in a new issue