Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

notify.c File Reference

#include "FsRtlP.h"

Go to the source code of this file.

Classes

struct  _REAL_NOTIFY_SYNC
struct  _NOTIFY_CHANGE

Defines

#define Dbg   (0x04000000)
#define NOTIFY_WATCH_TREE   (0x0001)
#define NOTIFY_IMMEDIATE_NOTIFY   (0x0002)
#define NOTIFY_CLEANUP_CALLED   (0x0004)
#define NOTIFY_DEFER_NOTIFY   (0x0008)
#define NOTIFY_DIR_IS_ROOT   (0x0010)
#define NOTIFY_STREAM_IS_DELETED   (0x0020)
#define Add2Ptr(PTR, INC, CAST)   ((CAST)((PUCHAR)(PTR) + (INC)))
#define PtrOffset(BASE, OFFSET)   ((ULONG)((PCHAR)(OFFSET) - (PCHAR)(BASE)))
#define SetFlag(F, SF)
#define ClearFlag(F, SF)
#define AcquireNotifySync(NS)
#define ReleaseNotifySync(NS)
#define MODULE_POOL_TAG   ('NrSF')

Typedefs

typedef _REAL_NOTIFY_SYNC REAL_NOTIFY_SYNC
typedef _REAL_NOTIFY_SYNCPREAL_NOTIFY_SYNC
typedef _NOTIFY_CHANGE NOTIFY_CHANGE
typedef _NOTIFY_CHANGEPNOTIFY_CHANGE

Functions

PNOTIFY_CHANGE FsRtlIsNotifyOnList (IN PLIST_ENTRY NotifyListHead, IN PVOID FsContext)
VOID FsRtlNotifyCompleteIrp (IN PIRP NotifyIrp, IN PNOTIFY_CHANGE Notify, IN ULONG DataLength, IN NTSTATUS Status, IN ULONG CheckCancel)
BOOLEAN FsRtlNotifySetCancelRoutine (IN PIRP NotifyIrp, IN PNOTIFY_CHANGE Notify OPTIONAL)
BOOLEAN FsRtlNotifyUpdateBuffer (IN PFILE_NOTIFY_INFORMATION NotifyInfo, IN ULONG FileAction, IN PSTRING ParentName, IN PSTRING TargetName, IN PSTRING StreamName OPTIONAL, IN BOOLEAN UnicodeName, IN ULONG SizeOfEntry)
VOID FsRtlNotifyCompleteIrpList (IN PNOTIFY_CHANGE Notify, IN NTSTATUS Status)
VOID FsRtlCancelNotify (IN PDEVICE_OBJECT DeviceObject, IN PIRP ThisIrp)
VOID FsRtlCheckNotifyForDelete (IN PLIST_ENTRY NotifyListHead, IN PVOID FsContext)
NTKERNELAPI VOID FsRtlNotifyInitializeSync (IN PNOTIFY_SYNC *NotifySync)
NTKERNELAPI VOID FsRtlNotifyUninitializeSync (IN PNOTIFY_SYNC *NotifySync)
VOID FsRtlNotifyChangeDirectory (IN PNOTIFY_SYNC NotifySync, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN PLIST_ENTRY NotifyList, IN BOOLEAN WatchTree, IN ULONG CompletionFilter, IN PIRP NotifyIrp)
VOID 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 PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL)
VOID FsRtlNotifyReportChange (IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PSTRING FullTargetName, IN PSTRING TargetName, IN ULONG FilterMatch)
VOID FsRtlNotifyFullReportChange (IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PSTRING FullTargetName, IN USHORT TargetNameOffset, IN PSTRING StreamName OPTIONAL, IN PSTRING NormalizedParentName OPTIONAL, IN ULONG FilterMatch, IN ULONG Action, IN PVOID TargetContext)
VOID FsRtlNotifyCleanup (IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
VOID FsRtlNotifyCompleteIrpList (IN OUT PNOTIFY_CHANGE Notify, IN NTSTATUS Status)


Define Documentation

#define AcquireNotifySync NS   ) 
 

Value:

{ \ ERESOURCE_THREAD _CurrentThread; \ _CurrentThread = (ERESOURCE_THREAD) PsGetCurrentThread(); \ if (_CurrentThread != ((PREAL_NOTIFY_SYNC) (NS))->OwningThread) { \ ExAcquireFastMutexUnsafe( &((PREAL_NOTIFY_SYNC) (NS))->FastMutex ); \ ((PREAL_NOTIFY_SYNC) (NS))->OwningThread = _CurrentThread; \ } \ ((PREAL_NOTIFY_SYNC) (NS))->OwnerCount += 1; \ }

Definition at line 274 of file notify.c.

Referenced by FsRtlCancelNotify(), FsRtlNotifyCleanup(), FsRtlNotifyFullChangeDirectory(), and FsRtlNotifyFullReportChange().

#define Add2Ptr PTR,
INC,
CAST   )     ((CAST)((PUCHAR)(PTR) + (INC)))
 

Definition at line 236 of file notify.c.

Referenced by FsRtlNotifyFullReportChange(), FsRtlNotifyUpdateBuffer(), LfsCloseLogFile(), LfsCopyReadLogRecord(), LfsFindLogRecord(), LfsFlushLfcb(), LfsInitializeLogFile(), LfsIsClientAreaValid(), LfsIsRestartAreaValid(), LfsPinOrMapLogRecordHeader(), LfsReadLogRecord(), LfsReadRestart(), LfsReadRestartArea(), LfsRestartLogFile(), LfsSetBaseLsn(), LfsTransferLogBytes(), LfsUpdateLfcbFromRestart(), LfsUpdateRestartAreaFromLfcb(), LfsVerifyLogFile(), LfsWriteLfsRestart(), LfsWriteLogRecordIntoLogPage(), LfsWriteRestartArea(), UdfCommonRead(), UdfDissectName(), UdfFinishBuffers(), UdfGetNextAllocation(), UdfGetNextAllocationPostProcessing(), UdfInitializeAllocationContext(), UdfInitializePcb(), UdfInsertPrefix(), UdfLoadSparingTables(), UdfLookupActiveIcbInExtent(), UdfLookupDirEntryPostProcessing(), UdfLookupEa(), UdfLookupInitialDirEntry(), UdfLookupNextDirEntry(), UdfNonCachedRead(), UdfNormalizeFileNames(), UdfPrepareBuffers(), UdfQueryDirectory(), and UdfUpdateDirNames().

#define ClearFlag F,
SF   ) 
 

Value:

{ \ (F) &= ~(SF); \ }

Definition at line 258 of file notify.c.

#define Dbg   (0x04000000)
 

Definition at line 67 of file notify.c.

#define MODULE_POOL_TAG   ('NrSF')
 

Definition at line 297 of file notify.c.

#define NOTIFY_CLEANUP_CALLED   (0x0004)
 

Definition at line 216 of file notify.c.

Referenced by FsRtlNotifyCleanup(), and FsRtlNotifyFullChangeDirectory().

#define NOTIFY_DEFER_NOTIFY   (0x0008)
 

Definition at line 217 of file notify.c.

Referenced by FsRtlNotifyFullChangeDirectory(), and FsRtlNotifyFullReportChange().

#define NOTIFY_DIR_IS_ROOT   (0x0010)
 

Definition at line 218 of file notify.c.

Referenced by FsRtlNotifyFullChangeDirectory(), and FsRtlNotifyFullReportChange().

#define NOTIFY_IMMEDIATE_NOTIFY   (0x0002)
 

Definition at line 215 of file notify.c.

Referenced by FsRtlCancelNotify(), FsRtlNotifyCompleteIrpList(), FsRtlNotifyFullChangeDirectory(), and FsRtlNotifyFullReportChange().

#define NOTIFY_STREAM_IS_DELETED   (0x0020)
 

Definition at line 219 of file notify.c.

Referenced by FsRtlCheckNotifyForDelete(), and FsRtlNotifyFullChangeDirectory().

#define NOTIFY_WATCH_TREE   (0x0001)
 

Definition at line 214 of file notify.c.

Referenced by FsRtlNotifyFullChangeDirectory(), and FsRtlNotifyFullReportChange().

#define PtrOffset BASE,
OFFSET   )     ((ULONG)((PCHAR)(OFFSET) - (PCHAR)(BASE)))
 

Definition at line 238 of file notify.c.

Referenced by LfsOpenLogFile().

#define ReleaseNotifySync NS   ) 
 

Value:

{ \ ((PREAL_NOTIFY_SYNC) (NS))->OwnerCount -= 1; \ if (((PREAL_NOTIFY_SYNC) (NS))->OwnerCount == 0) { \ ((PREAL_NOTIFY_SYNC) (NS))->OwningThread = (ERESOURCE_THREAD) 0; \ ExReleaseFastMutexUnsafe(&((PREAL_NOTIFY_SYNC) (NS))->FastMutex); \ } \ }

Definition at line 284 of file notify.c.

Referenced by FsRtlCancelNotify(), FsRtlNotifyCleanup(), FsRtlNotifyFullChangeDirectory(), and FsRtlNotifyFullReportChange().

#define SetFlag F,
SF   ) 
 

Value:

{ \ (F) |= (SF); \ }

Definition at line 254 of file notify.c.


Typedef Documentation

typedef struct _NOTIFY_CHANGE NOTIFY_CHANGE
 

Referenced by FsRtlNotifyFullChangeDirectory().

typedef struct _NOTIFY_CHANGE * PNOTIFY_CHANGE
 

Referenced by FsRtlCancelNotify(), FsRtlCheckNotifyForDelete(), FsRtlIsNotifyOnList(), FsRtlNotifyCleanup(), FsRtlNotifyFullChangeDirectory(), and FsRtlNotifyFullReportChange().

typedef struct _REAL_NOTIFY_SYNC * PREAL_NOTIFY_SYNC
 

Referenced by FsRtlNotifyFullChangeDirectory(), and FsRtlNotifyInitializeSync().

typedef struct _REAL_NOTIFY_SYNC REAL_NOTIFY_SYNC
 


Function Documentation

VOID FsRtlCancelNotify IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  ThisIrp
 

Definition at line 2555 of file notify.c.

References AcquireNotifySync, _NOTIFY_CHANGE::AllocatedBuffer, ASSERT, _IRP::AssociatedIrp, _NOTIFY_CHANGE::Buffer, _NOTIFY_CHANGE::BufferLength, _NOTIFY_CHANGE::DataLength, Dbg, DebugTrace, EXCEPTION_CONTINUE_SEARCH, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FALSE, FlagOn, _NOTIFY_CHANGE::Flags, FsRtlCompleteRequest, FsRtlEnterFileSystem, FsRtlExitFileSystem, FsRtlIsNtstatusExpected(), FsRtlpAllocatePool, _NOTIFY_CHANGE::FullDirectoryName, IoGetCurrentIrpStackLocation, IoMarkIrpPending, IoReleaseCancelSpinLock(), IoSetCancelRoutine, Irp, _NOTIFY_CHANGE::LastEntry, _IRP::MdlAddress, MmGetSystemAddressForMdl, NOTIFY_IMMEDIATE_NOTIFY, _NOTIFY_CHANGE::NotifyIrps, _NOTIFY_CHANGE::NotifySync, NULL, _NOTIFY_CHANGE::OwningProcess, PagedPool, _IO_STACK_LOCATION::Parameters, PNOTIFY_CHANGE, PNOTIFY_SYNC, PsChargePoolQuota(), PsReturnPoolQuota(), _NOTIFY_CHANGE::ReferenceCount, ReleaseNotifySync, SeReleaseSubjectContext(), SetFlag, _NOTIFY_CHANGE::SubjectContext, _NOTIFY_CHANGE::ThisBufferLength, and TRUE.

Referenced by FsRtlNotifySetCancelRoutine().

02562 : 02563 02564 This routine is for an Irp which is being cancelled. We Null the cancel 02565 routine and then walk through the Irps for this notify structure and 02566 complete all cancelled Irps. It is possible there is pending notify 02567 stored in the buffer for this Irp. In this case we want to copy the 02568 data to a system buffer if possible. 02569 02570 Arguments: 02571 02572 DeviceObject - Ignored. 02573 02574 ThisIrp - This is the Irp to cancel. 02575 02576 Return Value: 02577 02578 None. 02579 02580 --*/ 02581 02582 { 02583 PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL; 02584 02585 PNOTIFY_CHANGE Notify; 02586 PNOTIFY_SYNC NotifySync; 02587 LONG ExceptionCode; 02588 02589 UNREFERENCED_PARAMETER( DeviceObject ); 02590 02591 DebugTrace( +1, Dbg, "FsRtlCancelNotify: Entered\n", 0 ); 02592 DebugTrace( 0, Dbg, "Irp -> %08lx\n", Irp ); 02593 02594 // 02595 // Capture the notify structure. 02596 // 02597 02598 Notify = (PNOTIFY_CHANGE) ThisIrp->IoStatus.Information; 02599 02600 // 02601 // Void the cancel routine and release the cancel spinlock. 02602 // 02603 02604 IoSetCancelRoutine( ThisIrp, NULL ); 02605 ThisIrp->IoStatus.Information = 0; 02606 IoReleaseCancelSpinLock( ThisIrp->CancelIrql ); 02607 02608 FsRtlEnterFileSystem(); 02609 02610 // 02611 // Grab the mutex for this structure. 02612 // 02613 02614 NotifySync = Notify->NotifySync; 02615 AcquireNotifySync( NotifySync ); 02616 02617 // 02618 // Use a try finally to faciltate cleanup. 02619 // 02620 02621 try { 02622 02623 // 02624 // Remove the Irp from the queue. 02625 // 02626 02627 RemoveEntryList( &ThisIrp->Tail.Overlay.ListEntry ); 02628 02629 IoMarkIrpPending( ThisIrp ); 02630 02631 // 02632 // We now have the Irp. Check to see if there is data stored 02633 // in the buffer for this Irp. 02634 // 02635 02636 if (Notify->Buffer != NULL 02637 && Notify->AllocatedBuffer == NULL 02638 02639 && ((ThisIrp->MdlAddress != NULL 02640 && MmGetSystemAddressForMdl( ThisIrp->MdlAddress ) == Notify->Buffer) 02641 02642 || (Notify->Buffer == ThisIrp->AssociatedIrp.SystemBuffer))) { 02643 02644 PIRP NextIrp; 02645 PVOID NewBuffer; 02646 ULONG NewBufferLength; 02647 PIO_STACK_LOCATION IrpSp; 02648 02649 // 02650 // Initialize the above values. 02651 // 02652 02653 NewBuffer = NULL; 02654 NewBufferLength = 0; 02655 02656 // 02657 // Remember the next Irp on the list. Find the length of any 02658 // buffer it might have. Also keep a pointer to the buffer 02659 // if present. 02660 // 02661 02662 if (!IsListEmpty( &Notify->NotifyIrps )) { 02663 02664 NextIrp = CONTAINING_RECORD( Notify->NotifyIrps.Flink, 02665 IRP, 02666 Tail.Overlay.ListEntry ); 02667 02668 IrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 02669 02670 // 02671 // If the buffer here is large enough to hold the data we 02672 // can use that buffer. 02673 // 02674 02675 if (IrpSp->Parameters.NotifyDirectory.Length >= Notify->DataLength) { 02676 02677 // 02678 // If there is a system buffer or Mdl then get a new 02679 // buffer there. 02680 // 02681 02682 if (NextIrp->AssociatedIrp.SystemBuffer != NULL) { 02683 02684 NewBuffer = NextIrp->AssociatedIrp.SystemBuffer; 02685 02686 } else if (NextIrp->MdlAddress != NULL) { 02687 02688 NewBuffer = MmGetSystemAddressForMdl( NextIrp->MdlAddress ); 02689 } 02690 02691 NewBufferLength = IrpSp->Parameters.NotifyDirectory.Length; 02692 02693 if (NewBufferLength > Notify->BufferLength) { 02694 02695 NewBufferLength = Notify->BufferLength; 02696 } 02697 } 02698 02699 // 02700 // Otherwise check if the user's original buffer is larger than 02701 // the current buffer. 02702 // 02703 02704 } else if (Notify->BufferLength >= Notify->DataLength) { 02705 02706 NewBufferLength = Notify->BufferLength; 02707 } 02708 02709 // 02710 // If we have a new buffer length then we either have a new 02711 // buffer or need to allocate one. We will do this under 02712 // the protection of a try-except in order to continue in the 02713 // event of a failure. 02714 // 02715 02716 if (NewBufferLength != 0) { 02717 02718 BOOLEAN ChargedQuota; 02719 02720 try { 02721 02722 ChargedQuota = FALSE; 02723 02724 if (NewBuffer == NULL) { 02725 02726 PsChargePoolQuota( Notify->OwningProcess, 02727 PagedPool, 02728 NewBufferLength ); 02729 02730 ChargedQuota = TRUE; 02731 02732 // 02733 // If we didn't get an error then attempt to 02734 // allocate the pool. If there is an error 02735 // don't forget to release the quota. 02736 // 02737 02738 NewBuffer = FsRtlpAllocatePool( PagedPool, 02739 NewBufferLength ); 02740 02741 Notify->AllocatedBuffer = NewBuffer; 02742 } 02743 02744 // 02745 // Now copy the data over to the new buffer. 02746 // 02747 02748 RtlCopyMemory( NewBuffer, 02749 Notify->Buffer, 02750 Notify->DataLength ); 02751 02752 // 02753 // It is possible that the buffer size changed. 02754 // 02755 02756 Notify->ThisBufferLength = NewBufferLength; 02757 Notify->Buffer = NewBuffer; 02758 02759 } except( FsRtlIsNtstatusExpected( ExceptionCode = GetExceptionCode()) ? 02760 EXCEPTION_EXECUTE_HANDLER : 02761 EXCEPTION_CONTINUE_SEARCH ) { 02762 02763 ASSERT( (ExceptionCode == STATUS_INSUFFICIENT_RESOURCES) || 02764 (ExceptionCode == STATUS_QUOTA_EXCEEDED) ); 02765 02766 // 02767 // Return quota if we allocated the buffer. 02768 // 02769 02770 if (ChargedQuota) { 02771 02772 PsReturnPoolQuota( Notify->OwningProcess, 02773 PagedPool, 02774 NewBufferLength ); 02775 } 02776 02777 // 02778 // Forget any current buffer and resort to immediate 02779 // notify. 02780 // 02781 02782 SetFlag( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY ); 02783 } 02784 02785 // 02786 // Otherwise set the immediate notify flag. 02787 // 02788 02789 } else { 02790 02791 SetFlag( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY ); 02792 } 02793 02794 // 02795 // If the immediate notify flag is set then clear the other 02796 // values in the notify structures. 02797 // 02798 02799 if (FlagOn( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY )) { 02800 02801 // 02802 // Forget any current buffer and resort to immediate 02803 // notify. 02804 // 02805 02806 Notify->AllocatedBuffer = Notify->Buffer = NULL; 02807 02808 Notify->ThisBufferLength = 02809 Notify->DataLength = Notify->LastEntry = 0; 02810 } 02811 } 02812 02813 // 02814 // Complete the Irp with status cancelled. 02815 // 02816 02817 FsRtlCompleteRequest( ThisIrp, STATUS_CANCELLED ); 02818 02819 // 02820 // Decrement the count of Irps that might go through the cancel path. 02821 // 02822 02823 InterlockedDecrement( &Notify->ReferenceCount ); 02824 02825 if (Notify->ReferenceCount == 0) { 02826 02827 if (Notify->AllocatedBuffer != NULL) { 02828 02829 PsReturnPoolQuota( Notify->OwningProcess, 02830 PagedPool, 02831 Notify->ThisBufferLength ); 02832 02833 ExFreePool( Notify->AllocatedBuffer ); 02834 } 02835 02836 if (Notify->FullDirectoryName != NULL) { 02837 02838 SubjectContext = Notify->SubjectContext; 02839 } 02840 02841 ExFreePool( Notify ); 02842 Notify = NULL; 02843 } 02844 02845 } finally { 02846 02847 // 02848 // No matter how we exit, we release the mutex. 02849 // 02850 02851 ReleaseNotifySync( NotifySync ); 02852 02853 if (SubjectContext != NULL) { 02854 02855 SeReleaseSubjectContext( SubjectContext ); 02856 ExFreePool( SubjectContext ); 02857 } 02858 02859 FsRtlExitFileSystem(); 02860 02861 DebugTrace( -1, Dbg, "FsRtlCancelNotify: Exit\n", 0 ); 02862 } 02863 02864 return; 02865 }

VOID FsRtlCheckNotifyForDelete IN PLIST_ENTRY  NotifyListHead,
IN PVOID  FsContext
 

Definition at line 2873 of file notify.c.

References _NOTIFY_CHANGE::Flags, FsRtlNotifyCompleteIrpList(), NOTIFY_STREAM_IS_DELETED, _NOTIFY_CHANGE::NotifyIrps, PAGED_CODE, PNOTIFY_CHANGE, SetFlag, and _NOTIFY_CHANGE::StreamID.

Referenced by FsRtlNotifyFullChangeDirectory().

02880 : 02881 02882 This routine is called when a stream is being marked for delete. We will 02883 walk through the notify structures looking for an Irp for the same stream. 02884 We will complete these Irps with STATUS_DELETE_PENDING. 02885 02886 Arguments: 02887 02888 NotifyListHead - This is the start of the notify list. 02889 02890 StreamID - This is the Context ID used to identify the stream. 02891 02892 Return Value: 02893 02894 None. 02895 02896 --*/ 02897 02898 { 02899 PLIST_ENTRY Link; 02900 02901 PNOTIFY_CHANGE ThisNotify; 02902 02903 PAGED_CODE(); 02904 02905 // 02906 // Walk through all the entries on the list looking for a match. 02907 // 02908 02909 for (Link = NotifyListHead->Flink; 02910 Link != NotifyListHead; 02911 Link = Link->Flink) { 02912 02913 // 02914 // Obtain the notify structure from the link. 02915 // 02916 02917 ThisNotify = CONTAINING_RECORD( Link, NOTIFY_CHANGE, NotifyList ); 02918 02919 // 02920 // If the context field matches, then complete any waiting Irps. 02921 // 02922 02923 if (ThisNotify->StreamID == StreamID) { 02924 02925 // 02926 // Start by marking the notify structure as file deleted. 02927 // 02928 02929 SetFlag( ThisNotify->Flags, NOTIFY_STREAM_IS_DELETED ); 02930 02931 // 02932 // Now complete all of the Irps on this list. 02933 // 02934 02935 if (!IsListEmpty( &ThisNotify->NotifyIrps )) { 02936 02937 FsRtlNotifyCompleteIrpList( ThisNotify, STATUS_DELETE_PENDING ); 02938 } 02939 } 02940 } 02941 02942 return; 02943 } }

PNOTIFY_CHANGE FsRtlIsNotifyOnList IN PLIST_ENTRY  NotifyListHead,
IN PVOID  FsContext
 

Definition at line 1920 of file notify.c.

References Dbg, DebugTrace, _NOTIFY_CHANGE::FsContext, NULL, PAGED_CODE, and PNOTIFY_CHANGE.

Referenced by FsRtlNotifyCleanup(), and FsRtlNotifyFullChangeDirectory().

01927 : 01928 01929 This routine is called to walk through a notify list searching for 01930 a member associated with the FsContext value. 01931 01932 Arguments: 01933 01934 NotifyListHead - This is the start of the notify list. 01935 01936 FsContext - This is supplied by the file system so that this notify 01937 structure can be uniquely identified. 01938 01939 Return Value: 01940 01941 PNOTIFY_CHANGE - A pointer to the matching structure is returned. NULL 01942 is returned if the structure isn't present. 01943 01944 --*/ 01945 01946 { 01947 PLIST_ENTRY Link; 01948 01949 PNOTIFY_CHANGE ThisNotify; 01950 PNOTIFY_CHANGE Notify; 01951 01952 PAGED_CODE(); 01953 01954 DebugTrace( +1, Dbg, "FsRtlIsNotifyOnList: Entered\n", 0 ); 01955 01956 // 01957 // Assume we won't have a match. 01958 // 01959 01960 Notify = NULL; 01961 01962 // 01963 // Walk through all the entries on the list looking for a match. 01964 // 01965 01966 for (Link = NotifyListHead->Flink; 01967 Link != NotifyListHead; 01968 Link = Link->Flink) { 01969 01970 // 01971 // Obtain the notify structure from the link. 01972 // 01973 01974 ThisNotify = CONTAINING_RECORD( Link, NOTIFY_CHANGE, NotifyList ); 01975 01976 // 01977 // If the context field matches, remember this structure and 01978 // exit. 01979 // 01980 01981 if (ThisNotify->FsContext == FsContext) { 01982 01983 Notify = ThisNotify; 01984 break; 01985 } 01986 } 01987 01988 DebugTrace( 0, Dbg, "Notify Structure -> %08lx\n", Notify ); 01989 DebugTrace( -1, Dbg, "FsRtlIsNotifyOnList: Exit\n", 0 ); 01990 01991 return Notify; 01992 }

VOID FsRtlNotifyChangeDirectory IN PNOTIFY_SYNC  NotifySync,
IN PVOID  FsContext,
IN PSTRING  FullDirectoryName,
IN PLIST_ENTRY  NotifyList,
IN BOOLEAN  WatchTree,
IN ULONG  CompletionFilter,
IN PIRP  NotifyIrp
 

Definition at line 469 of file notify.c.

References Dbg, DebugTrace, FsRtlNotifyFullChangeDirectory(), NULL, PAGED_CODE, TRUE, and WatchTree.

00481 : 00482 00483 This routine is called by a file system which has received a NotifyChange 00484 request. This routine checks if there is already a notify structure and 00485 inserts one if not present. With a notify structure in hand, we check 00486 whether we already have a pending notify and report it if so. If there 00487 is no pending notify, we check if this Irp has already been cancelled and 00488 completes it if so. Otherwise we add this to the list of Irps waiting 00489 for notification. 00490 00491 Arguments: 00492 00493 NotifySync - This is the controlling fast mutex for this notify list. 00494 It is stored here so that it can be found for an Irp which is being 00495 cancelled. 00496 00497 FsContext - This is supplied by the file system so that this notify 00498 structure can be uniquely identified. 00499 00500 FullDirectoryName - Points to the full name for the directory associated 00501 with this notify structure. 00502 00503 NotifyList - This is the start of the notify list to add this 00504 structure to. 00505 00506 WatchTree - This indicates whether all subdirectories for this directory 00507 should be watched, or just the directory itself. 00508 00509 CompletionFilter - This provides the mask to determine which operations 00510 will trigger the notify operations. 00511 00512 NotifyIrp - This is the Irp to complete on notify change. 00513 00514 Return Value: 00515 00516 None. 00517 00518 --*/ 00519 00520 { 00521 PAGED_CODE(); 00522 00523 DebugTrace( +1, Dbg, "FsRtlNotifyChangeDirectory: Entered\n", 0 ); 00524 00525 // 00526 // We will simply call the full notify routine to do the real work. 00527 // 00528 00529 FsRtlNotifyFullChangeDirectory( NotifySync, 00530 NotifyList, 00531 FsContext, 00532 FullDirectoryName, 00533 WatchTree, 00534 TRUE, 00535 CompletionFilter, 00536 NotifyIrp, 00537 NULL, 00538 NULL ); 00539 00540 DebugTrace( -1, Dbg, "FsRtlNotifyChangeDirectory: Exit\n", 0 ); 00541 00542 return; 00543 }

VOID FsRtlNotifyCleanup IN PNOTIFY_SYNC  NotifySync,
IN PLIST_ENTRY  NotifyList,
IN PVOID  FsContext
 

Definition at line 1795 of file notify.c.

References AcquireNotifySync, _NOTIFY_CHANGE::AllocatedBuffer, Dbg, DebugTrace, ExFreePool(), _NOTIFY_CHANGE::Flags, FsRtlIsNotifyOnList(), FsRtlNotifyCompleteIrpList(), _NOTIFY_CHANGE::FullDirectoryName, NOTIFY_CLEANUP_CALLED, _NOTIFY_CHANGE::NotifyIrps, _NOTIFY_CHANGE::NotifyList, NULL, _NOTIFY_CHANGE::OwningProcess, PAGED_CODE, PagedPool, PNOTIFY_CHANGE, PsReturnPoolQuota(), _NOTIFY_CHANGE::ReferenceCount, ReleaseNotifySync, SeReleaseSubjectContext(), SetFlag, _NOTIFY_CHANGE::SubjectContext, and _NOTIFY_CHANGE::ThisBufferLength.

Referenced by UdfCommonCleanup().

01803 : 01804 01805 This routine is called for a cleanup of a user directory handle. We 01806 walk through our notify structures looking for a matching context field. 01807 We complete all the pending notify Irps for this Notify structure, remove 01808 the notify structure and deallocate it. 01809 01810 Arguments: 01811 01812 NotifySync - This is the controlling fast mutex for this notify list. 01813 It is stored here so that it can be found for an Irp which is being 01814 cancelled. 01815 01816 NotifyList - This is the start of the notify list to add this 01817 structure to. 01818 01819 FsContext - This is a unique value assigned by the file system to 01820 identify a particular notify structure. 01821 01822 Return Value: 01823 01824 None. 01825 01826 --*/ 01827 01828 { 01829 PNOTIFY_CHANGE Notify; 01830 PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL; 01831 01832 PAGED_CODE(); 01833 01834 DebugTrace( +1, Dbg, "FsRtlNotifyCleanup: Entered\n", 0 ); 01835 DebugTrace( 0, Dbg, "Mutex -> %08lx\n", Mutex ); 01836 DebugTrace( 0, Dbg, "Notify List -> %08lx\n", NotifyList ); 01837 DebugTrace( 0, Dbg, "FsContext -> %08lx\n", FsContext ); 01838 01839 // 01840 // Acquire exclusive access to the list by acquiring the mutex. 01841 // 01842 01843 AcquireNotifySync( NotifySync ); 01844 01845 // 01846 // Use a try-finally to facilitate cleanup. 01847 // 01848 01849 try { 01850 01851 // 01852 // Search for a match on the list. 01853 // 01854 01855 Notify = FsRtlIsNotifyOnList( NotifyList, FsContext ); 01856 01857 // 01858 // If found, then complete all the Irps with STATUS_NOTIFY_CLEANUP 01859 // 01860 01861 if (Notify != NULL) { 01862 01863 // 01864 // Set the flag to indicate that we have been called with cleanup. 01865 // 01866 01867 SetFlag( Notify->Flags, NOTIFY_CLEANUP_CALLED ); 01868 01869 if (!IsListEmpty( &Notify->NotifyIrps )) { 01870 01871 FsRtlNotifyCompleteIrpList( Notify, STATUS_NOTIFY_CLEANUP ); 01872 } 01873 01874 RemoveEntryList( &Notify->NotifyList ); 01875 01876 InterlockedDecrement( &Notify->ReferenceCount ); 01877 01878 if (Notify->ReferenceCount == 0) { 01879 01880 if (Notify->AllocatedBuffer != NULL) { 01881 01882 PsReturnPoolQuota( Notify->OwningProcess, 01883 PagedPool, 01884 Notify->ThisBufferLength ); 01885 01886 ExFreePool( Notify->AllocatedBuffer ); 01887 } 01888 01889 if (Notify->FullDirectoryName != NULL) { 01890 01891 SubjectContext = Notify->SubjectContext; 01892 } 01893 01894 ExFreePool( Notify ); 01895 } 01896 } 01897 01898 } finally { 01899 01900 ReleaseNotifySync( NotifySync ); 01901 01902 if (SubjectContext != NULL) { 01903 01904 SeReleaseSubjectContext( SubjectContext ); 01905 ExFreePool( SubjectContext ); 01906 } 01907 01908 DebugTrace( -1, Dbg, "FsRtlNotifyCleanup: Exit\n", 0 ); 01909 } 01910 01911 return; 01912 }

VOID FsRtlNotifyCompleteIrp IN PIRP  NotifyIrp,
IN PNOTIFY_CHANGE  Notify,
IN ULONG  DataLength,
IN NTSTATUS  Status,
IN ULONG  CheckCancel
 

Definition at line 2000 of file notify.c.

References _IO_STACK_LOCATION::Control, Dbg, DebugTrace, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FlagOn, FsRtlCompleteRequest, FsRtlNotifySetCancelRoutine(), IoGetCurrentIrpStackLocation, IoMarkIrpPending, IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_INPUT_OPERATION, MmGetSystemAddressForMdl, NULL, PAGED_CODE, PagedPool, _IO_STACK_LOCATION::Parameters, PsReturnPoolQuota(), SL_PENDING_RETURNED, and Status.

Referenced by FsRtlNotifyCompleteIrpList(), and FsRtlNotifyFullChangeDirectory().

02010 : 02011 02012 This routine is called to complete an Irp with the data in the NOTIFY_CHANGE 02013 structure. 02014 02015 Arguments: 02016 02017 NotifyIrp - Irp to complete. 02018 02019 Notify - Notify structure which contains the data. 02020 02021 DataLength - This is the length of the data in the buffer in the notify 02022 structure. A value of zero indicates that we should complete the 02023 request with STATUS_NOTIFY_ENUM_DIR. 02024 02025 Status - Indicates the status to complete the Irp with. 02026 02027 CheckCancel - Indicates if we should only complete the irp if we clear the cancel routine 02028 ourselves. 02029 02030 Return Value: 02031 02032 None. 02033 02034 --*/ 02035 02036 { 02037 PIO_STACK_LOCATION IrpSp; 02038 02039 PAGED_CODE(); 02040 02041 DebugTrace( +1, Dbg, "FsRtlIsNotifyCompleteIrp: Entered\n", 0 ); 02042 02043 // 02044 // Attempt to clear the cancel routine. If this routine owns the cancel 02045 // routine then it can complete the irp. Otherwise there is a cancel underway 02046 // on this. 02047 // 02048 02049 if (FsRtlNotifySetCancelRoutine( NotifyIrp, Notify ) || !CheckCancel) { 02050 02051 // 02052 // We only process the buffer if the status is STATUS_SUCCESS. 02053 // 02054 02055 if (Status == STATUS_SUCCESS) { 02056 02057 // 02058 // Get the current Stack location 02059 // 02060 02061 IrpSp = IoGetCurrentIrpStackLocation( NotifyIrp ); 02062 02063 // 02064 // If the data won't fit in the user's buffer or there was already a 02065 // buffer overflow then return the alternate status code. If the data 02066 // was already stored in the Irp buffer then we know that we won't 02067 // take this path. Otherwise we wouldn't be cleaning up the Irp 02068 // correctly. 02069 // 02070 02071 if (DataLength == 0 02072 || IrpSp->Parameters.NotifyDirectory.Length < DataLength) { 02073 02074 Status = STATUS_NOTIFY_ENUM_DIR; 02075 02076 // 02077 // We have to carefully return the buffer to the user and handle all 02078 // of the different buffer cases. If there is no allocated buffer 02079 // in the notify structure it means that we have already used the 02080 // caller's buffer. 02081 // 02082 // 1 - If the system allocated an associated system buffer we 02083 // can simply fill that in. 02084 // 02085 // 2 - If there is an Mdl then we get a system address for the Mdl 02086 // and copy the data into it. 02087 // 02088 // 3 - If there is only a user's buffer and pending has not been 02089 // returned, we can fill the user's buffer in directly. 02090 // 02091 // 4 - If there is only a user's buffer and pending has been returned 02092 // then we are not in the user's address space. We dress up 02093 // the Irp with our system buffer and let the Io system 02094 // copy the data in. 02095 // 02096 02097 } else { 02098 02099 if (Notify->AllocatedBuffer != NULL) { 02100 02101 // 02102 // Protect the copy with a try-except and ignore the buffer 02103 // if we have some error in copying it to the buffer. 02104 // 02105 02106 try { 02107 02108 if (NotifyIrp->AssociatedIrp.SystemBuffer != NULL) { 02109 02110 RtlCopyMemory( NotifyIrp->AssociatedIrp.SystemBuffer, 02111 Notify->AllocatedBuffer, 02112 DataLength ); 02113 02114 } else if (NotifyIrp->MdlAddress != NULL) { 02115 02116 RtlCopyMemory( MmGetSystemAddressForMdl( NotifyIrp->MdlAddress ), 02117 Notify->AllocatedBuffer, 02118 DataLength ); 02119 02120 } else if (!FlagOn( IrpSp->Control, SL_PENDING_RETURNED )) { 02121 02122 RtlCopyMemory( NotifyIrp->UserBuffer, 02123 Notify->AllocatedBuffer, 02124 DataLength ); 02125 02126 } else { 02127 02128 NotifyIrp->Flags |= (IRP_BUFFERED_IO | IRP_INPUT_OPERATION | IRP_DEALLOCATE_BUFFER); 02129 NotifyIrp->AssociatedIrp.SystemBuffer = Notify->AllocatedBuffer; 02130 02131 } 02132 02133 } except( EXCEPTION_EXECUTE_HANDLER ) { 02134 02135 Status = STATUS_NOTIFY_ENUM_DIR; 02136 DataLength = 0; 02137 } 02138 02139 // 02140 // Return the quota and deallocate the buffer if we didn't pass it 02141 // back via the irp. 02142 // 02143 02144 PsReturnPoolQuota( Notify->OwningProcess, PagedPool, Notify->ThisBufferLength ); 02145 02146 if (Notify->AllocatedBuffer != NotifyIrp->AssociatedIrp.SystemBuffer 02147 && Notify->AllocatedBuffer != NULL) { 02148 02149 ExFreePool( Notify->AllocatedBuffer ); 02150 } 02151 02152 Notify->AllocatedBuffer = NULL; 02153 Notify->ThisBufferLength = 0; 02154 } 02155 02156 // 02157 // Update the data length in the Irp. 02158 // 02159 02160 NotifyIrp->IoStatus.Information = DataLength; 02161 02162 // 02163 // Show that there is no buffer in the notify package 02164 // anymore. 02165 // 02166 02167 Notify->Buffer = NULL; 02168 } 02169 } 02170 02171 // 02172 // Make sure the Irp is marked as pending returned. 02173 // 02174 02175 IoMarkIrpPending( NotifyIrp ); 02176 02177 // 02178 // Now complete the request. 02179 // 02180 02181 FsRtlCompleteRequest( NotifyIrp, Status ); 02182 } 02183 02184 DebugTrace( -1, Dbg, "FsRtlIsNotifyCompleteIrp: Exit\n", 0 ); 02185 02186 return; 02187 }

VOID FsRtlNotifyCompleteIrpList IN OUT PNOTIFY_CHANGE  Notify,
IN NTSTATUS  Status
 

Definition at line 2467 of file notify.c.

References ClearFlag, Dbg, DebugTrace, FsRtlNotifyCompleteIrp(), Irp, NOTIFY_IMMEDIATE_NOTIFY, Status, and TRUE.

Referenced by FsRtlCheckNotifyForDelete(), FsRtlNotifyCleanup(), and FsRtlNotifyFullReportChange().

02474 : 02475 02476 This routine walks through the Irps for a particular notify structure 02477 and completes the Irps with the indicated status. If the status is 02478 STATUS_SUCCESS then we are completing an Irp because of a notification event. 02479 In that case we look at the notify structure to decide if we can return the 02480 data to the user. 02481 02482 Arguments: 02483 02484 Notify - This is the notify change structure. 02485 02486 Status - Indicates the status used to complete the request. If this status 02487 is STATUS_SUCCESS then we only want to complete one Irp. Otherwise we 02488 want complete all the Irps in the list. 02489 02490 Return Value: 02491 02492 None. 02493 02494 --*/ 02495 02496 { 02497 PIRP Irp; 02498 ULONG DataLength; 02499 02500 DebugTrace( +1, Dbg, "FsRtlNotifyCompleteIrpList: Entered\n", 0 ); 02501 02502 DataLength = Notify->DataLength; 02503 02504 // 02505 // Clear the fields to indicate that there is no more data to return. 02506 // 02507 02508 ClearFlag( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY ); 02509 Notify->DataLength = 0; 02510 Notify->LastEntry = 0; 02511 02512 // 02513 // Walk through all the Irps in the list. We are never called unless 02514 // there is at least one irp. 02515 // 02516 02517 do { 02518 02519 Irp = CONTAINING_RECORD( Notify->NotifyIrps.Flink, IRP, Tail.Overlay.ListEntry ); 02520 02521 RemoveHeadList( &Notify->NotifyIrps ); 02522 02523 // 02524 // Call our completion routine to complete the request. 02525 // 02526 02527 FsRtlNotifyCompleteIrp( Irp, 02528 Notify, 02529 DataLength, 02530 Status, 02531 TRUE ); 02532 02533 // 02534 // If we were only to complete one Irp then break now. 02535 // 02536 02537 if (Status == STATUS_SUCCESS) { 02538 02539 break; 02540 } 02541 02542 } while (!IsListEmpty( &Notify->NotifyIrps )); 02543 02544 DebugTrace( -1, Dbg, "FsRtlNotifyCompleteIrpList: Exit\n", 0 ); 02545 02546 return; 02547 }

VOID FsRtlNotifyCompleteIrpList IN PNOTIFY_CHANGE  Notify,
IN NTSTATUS  Status
 

VOID 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 PSECURITY_SUBJECT_CONTEXT SubjectContext  OPTIONAL
 

Definition at line 547 of file notify.c.

References AcquireNotifySync, _NOTIFY_CHANGE::BufferLength, CHAR, _NOTIFY_CHANGE::CharacterSize, ClearFlag, _NOTIFY_CHANGE::CompletionFilter, _NOTIFY_CHANGE::DataLength, Dbg, DebugTrace, ExFreePool(), FALSE, _IO_STACK_LOCATION::FileObject, FlagOn, _FILE_OBJECT::Flags, _NOTIFY_CHANGE::Flags, FO_CLEANUP_COMPLETE, _NOTIFY_CHANGE::FsContext, _FILE_OBJECT::FsContext, FsRtlCheckNotifyForDelete(), FsRtlCompleteRequest, FsRtlIsNotifyOnList(), FsRtlNotifyCompleteIrp(), FsRtlNotifySetCancelRoutine(), FsRtlpAllocatePool, _NOTIFY_CHANGE::FullDirectoryName, IoGetCurrentIrpStackLocation, IoMarkIrpPending, _NOTIFY_CHANGE::LastEntry, NOTIFY_CHANGE, NOTIFY_CLEANUP_CALLED, NOTIFY_DEFER_NOTIFY, NOTIFY_DIR_IS_ROOT, NOTIFY_IMMEDIATE_NOTIFY, NOTIFY_STREAM_IS_DELETED, NOTIFY_WATCH_TREE, _NOTIFY_CHANGE::NotifyIrps, _NOTIFY_CHANGE::NotifyList, _NOTIFY_CHANGE::NotifySync, NULL, _NOTIFY_CHANGE::OwningProcess, PAGED_CODE, PagedPool, _IO_STACK_LOCATION::Parameters, PNOTIFY_CHANGE, PREAL_NOTIFY_SYNC, _NOTIFY_CHANGE::ReferenceCount, ReleaseNotifySync, SeReleaseSubjectContext(), SetFlag, _NOTIFY_CHANGE::StreamID, _NOTIFY_CHANGE::SubjectContext, THREAD_TO_PROCESS, _NOTIFY_CHANGE::TraverseCallback, try_return, and WatchTree.

Referenced by FsRtlNotifyChangeDirectory(), and UdfNotifyChangeDirectory().

00562 : 00563 00564 This routine is called by a file system which has received a NotifyChange 00565 request. This routine checks if there is already a notify structure and 00566 inserts one if not present. With a notify structure in hand, we check 00567 whether we already have a pending notify and report it if so. If there 00568 is no pending notify, we check if this Irp has already been cancelled and 00569 completes it if so. Otherwise we add this to the list of Irps waiting 00570 for notification. 00571 00572 This is the version of this routine which understands about the user's 00573 buffer and will fill it in on a reported change. 00574 00575 Arguments: 00576 00577 NotifySync - This is the controlling fast mutex for this notify list. 00578 It is stored here so that it can be found for an Irp which is being 00579 cancelled. 00580 00581 NotifyList - This is the start of the notify list to add this 00582 structure to. 00583 00584 FsContext - This is supplied by the file system so that this notify 00585 structure can be uniquely identified. If the NotifyIrp is not specified 00586 then this is used to identify the stream and it will match the FsContext 00587 field in the file object of a stream being deleted. 00588 00589 FullDirectoryName - Points to the full name for the directory associated 00590 with this notify structure. Ignored if the NotifyIrp is not specified. 00591 00592 WatchTree - This indicates whether all subdirectories for this directory 00593 should be watched, or just the directory itself. Ignored if the 00594 NotifyIrp is not specified. 00595 00596 IgnoreBuffer - Indicates whether we will always ignore any user buffer 00597 and force the directory to be reenumerated. This will speed up the 00598 operation. Ignored if the NotifyIrp is not specified. 00599 00600 CompletionFilter - This provides the mask to determine which operations 00601 will trigger the notify operations. Ignored if the NotifyIrp is not 00602 specified. 00603 00604 NotifyIrp - This is the Irp to complete on notify change. If this irp is 00605 not specified it means that the stream represented by this file object 00606 is being deleted. 00607 00608 TraverseCallback - If specified we must call this routine when a change 00609 has occurred in a subdirectory being watched in a tree. This will 00610 let the filesystem check if the watcher has traverse access to that 00611 directory. Ignored if the NotifyIrp is not specified. 00612 00613 SubjectContext - If there is a traverse callback routine then we will 00614 pass this subject context as a parameter to the call. We will release 00615 the context and free the structure when done with it. Ignored if the 00616 NotifyIrp is not specified. 00617 00618 Return Value: 00619 00620 None. 00621 00622 --*/ 00623 00624 { 00625 PNOTIFY_CHANGE Notify; 00626 PIO_STACK_LOCATION IrpSp; 00627 00628 PAGED_CODE(); 00629 00630 DebugTrace( +1, Dbg, "FsRtlNotifyFullChangeDirectory: Entered\n", 0 ); 00631 00632 // 00633 // Acquire exclusive access to the list by acquiring the mutex. 00634 // 00635 00636 AcquireNotifySync( NotifySync ); 00637 00638 // 00639 // Use a try-finally to facilitate cleanup. 00640 // 00641 00642 try { 00643 00644 // 00645 // If there is no Irp then find all of the pending Irps whose file objects 00646 // refer to the same stream and complete them with STATUS_DELETE_PENDING. 00647 // 00648 00649 if (NotifyIrp == NULL) { 00650 00651 FsRtlCheckNotifyForDelete( NotifyList, FsContext ); 00652 try_return( NOTHING ); 00653 } 00654 00655 // 00656 // Get the current Stack location 00657 // 00658 00659 IrpSp = IoGetCurrentIrpStackLocation( NotifyIrp ); 00660 00661 // 00662 // Clear the Iosb in the Irp. 00663 // 00664 00665 NotifyIrp->IoStatus.Status = STATUS_SUCCESS; 00666 NotifyIrp->IoStatus.Information = 0; 00667 00668 // 00669 // If the file object has already gone through cleanup, then complete 00670 // the request immediately. 00671 // 00672 00673 if (FlagOn( IrpSp->FileObject->Flags, FO_CLEANUP_COMPLETE )) { 00674 00675 // 00676 // Always mark this Irp as pending returned. 00677 // 00678 00679 IoMarkIrpPending( NotifyIrp ); 00680 00681 FsRtlCompleteRequest( NotifyIrp, STATUS_NOTIFY_CLEANUP ); 00682 try_return( NOTHING ); 00683 } 00684 00685 // 00686 // If the notify structure is not already in the list, add it 00687 // now. 00688 // 00689 00690 Notify = FsRtlIsNotifyOnList( NotifyList, FsContext ); 00691 00692 if (Notify == NULL) { 00693 00694 // 00695 // Allocate and initialize the structure. 00696 // 00697 00698 Notify = FsRtlpAllocatePool( PagedPool, sizeof( NOTIFY_CHANGE )); 00699 RtlZeroMemory( Notify, sizeof( NOTIFY_CHANGE )); 00700 00701 Notify->NotifySync = (PREAL_NOTIFY_SYNC) NotifySync; 00702 Notify->FsContext = FsContext; 00703 Notify->StreamID = IrpSp->FileObject->FsContext; 00704 00705 Notify->TraverseCallback = TraverseCallback; 00706 Notify->SubjectContext = SubjectContext; 00707 SubjectContext = NULL; 00708 00709 Notify->FullDirectoryName = FullDirectoryName; 00710 00711 InitializeListHead( &Notify->NotifyIrps ); 00712 00713 if (WatchTree) { 00714 00715 SetFlag( Notify->Flags, NOTIFY_WATCH_TREE ); 00716 } 00717 00718 if (FullDirectoryName == NULL) { 00719 00720 // 00721 // In the view index we aren't using this buffer to hold a 00722 // unicode string. 00723 // 00724 00725 Notify->CharacterSize = sizeof( CHAR ); 00726 00727 } else { 00728 00729 // 00730 // We look at the directory name to decide if we have a unicode 00731 // name. 00732 // 00733 00734 if (FullDirectoryName->Length >= 2 00735 && FullDirectoryName->Buffer[1] == '\0') { 00736 00737 Notify->CharacterSize = sizeof( WCHAR ); 00738 00739 } else { 00740 00741 Notify->CharacterSize = sizeof( CHAR ); 00742 } 00743 00744 if (FullDirectoryName->Length == Notify->CharacterSize) { 00745 00746 SetFlag( Notify->Flags, NOTIFY_DIR_IS_ROOT ); 00747 } 00748 } 00749 00750 Notify->CompletionFilter = CompletionFilter; 00751 00752 // 00753 // If we are to return data to the user then look for the length 00754 // of the original buffer in the IrpSp. 00755 // 00756 00757 if (!IgnoreBuffer) { 00758 00759 Notify->BufferLength = IrpSp->Parameters.NotifyDirectory.Length; 00760 } 00761 00762 Notify->OwningProcess = THREAD_TO_PROCESS( NotifyIrp->Tail.Overlay.Thread ); 00763 InsertTailList( NotifyList, &Notify->NotifyList ); 00764 00765 Notify->ReferenceCount = 1; 00766 00767 // 00768 // If we have already been called with cleanup then complete 00769 // the request immediately. 00770 // 00771 00772 } else if (FlagOn( Notify->Flags, NOTIFY_CLEANUP_CALLED )) { 00773 00774 // 00775 // Always mark this Irp as pending returned. 00776 // 00777 00778 IoMarkIrpPending( NotifyIrp ); 00779 00780 FsRtlCompleteRequest( NotifyIrp, STATUS_NOTIFY_CLEANUP ); 00781 try_return( NOTHING ); 00782 00783 // 00784 // If this file has been deleted then complete with STATUS_DELETE_PENDING. 00785 // 00786 00787 } else if (FlagOn( Notify->Flags, NOTIFY_STREAM_IS_DELETED )) { 00788 00789 // 00790 // Always mark this Irp as pending returned. 00791 // 00792 00793 IoMarkIrpPending( NotifyIrp ); 00794 00795 FsRtlCompleteRequest( NotifyIrp, STATUS_DELETE_PENDING ); 00796 try_return( NOTHING ); 00797 00798 // 00799 // If the notify pending flag is set or there is data in an internal buffer 00800 // we complete this Irp immediately and exit. 00801 // 00802 00803 } else if (FlagOn( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY ) 00804 && !FlagOn( Notify->Flags, NOTIFY_DEFER_NOTIFY )) { 00805 00806 DebugTrace( 0, Dbg, "Notify has been pending\n", 0 ); 00807 00808 // 00809 // Clear the flag in our notify structure before completing the 00810 // Irp. This will prevent a caller who reposts in his completion 00811 // routine from looping in the completion routine. 00812 // 00813 00814 ClearFlag( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY ); 00815 00816 // 00817 // Always mark this Irp as pending returned. 00818 // 00819 00820 IoMarkIrpPending( NotifyIrp ); 00821 00822 FsRtlCompleteRequest( NotifyIrp, STATUS_NOTIFY_ENUM_DIR ); 00823 try_return( NOTHING ); 00824 00825 } else if (Notify->DataLength != 0 00826 && !FlagOn( Notify->Flags, NOTIFY_DEFER_NOTIFY )) { 00827 00828 ULONG ThisDataLength = Notify->DataLength; 00829 00830 // 00831 // Now set our buffer pointers back to indicate an empty buffer. 00832 // 00833 00834 Notify->DataLength = 0; 00835 Notify->LastEntry = 0; 00836 00837 FsRtlNotifyCompleteIrp( NotifyIrp, 00838 Notify, 00839 ThisDataLength, 00840 STATUS_SUCCESS, 00841 FALSE ); 00842 00843 try_return( NOTHING ); 00844 } 00845 00846 // 00847 // Add the Irp to the tail of the notify queue. 00848 // 00849 00850 NotifyIrp->IoStatus.Information = (ULONG_PTR) Notify; 00851 IoMarkIrpPending( NotifyIrp ); 00852 InsertTailList( &Notify->NotifyIrps, &NotifyIrp->Tail.Overlay.ListEntry ); 00853 00854 // 00855 // Increment the reference count to indicate that Irp might go through cancel. 00856 // 00857 00858 InterlockedIncrement( &Notify->ReferenceCount ); 00859 00860 // 00861 // Call the routine to set the cancel routine. 00862 // 00863 00864 FsRtlNotifySetCancelRoutine( NotifyIrp, NULL ); 00865 00866 try_exit: NOTHING; 00867 } finally { 00868 00869 // 00870 // Release the mutex. 00871 // 00872 00873 ReleaseNotifySync( NotifySync ); 00874 00875 // 00876 // If there is still a subject context then release it and deallocate 00877 // the structure. Remember that if FullDirectoryName is null, it means 00878 // this is a view index, not a directory index, and the SubjectContext 00879 // is really a piece of file system context information. 00880 // 00881 00882 if ((SubjectContext != NULL) && 00883 (Notify->FullDirectoryName != NULL)) { 00884 00885 SeReleaseSubjectContext( SubjectContext ); 00886 ExFreePool( SubjectContext ); 00887 } 00888 00889 DebugTrace( -1, Dbg, "FsRtlNotifyFullChangeDirectory: Exit\n", 0 ); 00890 } 00891 00892 return; 00893 }

VOID FsRtlNotifyFullReportChange IN PNOTIFY_SYNC  NotifySync,
IN PLIST_ENTRY  NotifyList,
IN PSTRING  FullTargetName,
IN USHORT  TargetNameOffset,
IN PSTRING StreamName  OPTIONAL,
IN PSTRING NormalizedParentName  OPTIONAL,
IN ULONG  FilterMatch,
IN ULONG  Action,
IN PVOID  TargetContext
 

Definition at line 973 of file notify.c.

References AcquireNotifySync, Action, Add2Ptr, _NOTIFY_CHANGE::AllocatedBuffer, ASSERT, ASSERTMSG, _IRP::AssociatedIrp, _NOTIFY_CHANGE::Buffer, _NOTIFY_CHANGE::BufferLength, CHAR, _NOTIFY_CHANGE::CharacterSize, ClearFlag, _NOTIFY_CHANGE::CompletionFilter, _NOTIFY_CHANGE::DataLength, Dbg, DebugTrace, EXCEPTION_CONTINUE_SEARCH, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FALSE, FileName, FlagOn, _NOTIFY_CHANGE::Flags, _NOTIFY_CHANGE::FsContext, FsRtlIsNtstatusExpected(), FsRtlNotifyCompleteIrpList(), FsRtlNotifyUpdateBuffer(), FsRtlpAllocatePool, _NOTIFY_CHANGE::FullDirectoryName, IoGetCurrentIrpStackLocation, L, _NOTIFY_CHANGE::LastEntry, LongAlign, _IRP::MdlAddress, MmGetSystemAddressForMdl, NOTIFY_DEFER_NOTIFY, NOTIFY_DIR_IS_ROOT, NOTIFY_IMMEDIATE_NOTIFY, NOTIFY_WATCH_TREE, _NOTIFY_CHANGE::NotifyIrps, NULL, _NOTIFY_CHANGE::OwningProcess, PAGED_CODE, PagedPool, _IO_STACK_LOCATION::Parameters, PNOTIFY_CHANGE, PsChargePoolQuota(), PsReturnPoolQuota(), ReleaseNotifySync, SetFlag, _NOTIFY_CHANGE::SubjectContext, _NOTIFY_CHANGE::ThisBufferLength, _NOTIFY_CHANGE::TraverseCallback, TRUE, and USHORT.

Referenced by FsRtlNotifyReportChange().

00987 : 00988 00989 This routine is called by a file system when a file has been modified in 00990 such a way that it will cause a notify change Irp to complete. We walk 00991 through all the notify structures looking for those structures which 00992 would be associated with an ancestor directory of the target file name. 00993 00994 We look for all the notify structures which have a filter match and 00995 then check that the directory name in the notify structure is a 00996 proper prefix of the full target name. 00997 00998 If we find a notify structure which matches the above conditions, we 00999 complete all the Irps for the notify structure. If the structure has 01000 no Irps, we mark the notify pending field. 01001 01002 Arguments: 01003 01004 NotifySync - This is the controlling fast mutex for this notify list. 01005 It is stored here so that it can be found for an Irp which is being 01006 cancelled. 01007 01008 NotifyList - This is the start of the notify list to add this 01009 structure to. 01010 01011 FullTargetName - This is the full name of the file from the root of the volume. 01012 01013 TargetNameOffset - This is the offset in the full name of the final component 01014 of the name. 01015 01016 StreamName - If present then this is the stream name to store with 01017 the filename. 01018 01019 NormalizedParentName - If present this is the same path as the parent name 01020 but the DOS-ONLY names have been replaced with the associated long name. 01021 01022 FilterMatch - This flag field is compared with the completion filter 01023 in the notify structure. If any of the corresponding bits in the 01024 completion filter are set, then a notify condition exists. 01025 01026 Action - This is the action code to store in the user's buffer if 01027 present. 01028 01029 TargetContext - This is one of the context pointers to pass to the file 01030 system if performing a traverse check in the case of a tree being 01031 watched. 01032 01033 Return Value: 01034 01035 None. 01036 01037 --*/ 01038 01039 { 01040 PLIST_ENTRY NotifyLinks; 01041 01042 STRING NormalizedParent; 01043 STRING ParentName; 01044 STRING TargetName; 01045 01046 PNOTIFY_CHANGE Notify; 01047 STRING TargetParent; 01048 PIRP NotifyIrp; 01049 01050 BOOLEAN NotifyIsParent; 01051 BOOLEAN ViewIndex = FALSE; 01052 UCHAR ComponentCount; 01053 ULONG SizeOfEntry; 01054 ULONG CurrentOffset; 01055 ULONG NextEntryOffset; 01056 ULONG ExceptionCode; 01057 01058 PAGED_CODE(); 01059 01060 DebugTrace( +1, Dbg, "FsRtlNotifyFullReportChange: Entered\n", 0 ); 01061 01062 // 01063 // If this is a change to the root directory then return immediately. 01064 // 01065 01066 if ((TargetNameOffset == 0) && (FullTargetName != NULL)) { 01067 01068 DebugTrace( -1, Dbg, "FsRtlNotifyFullReportChange: Exit\n", 0 ); 01069 return; 01070 } 01071 01072 ParentName.Buffer = NULL; 01073 TargetName.Buffer = NULL; 01074 01075 // 01076 // Acquire exclusive access to the list by acquiring the mutex. 01077 // 01078 01079 AcquireNotifySync( NotifySync ); 01080 01081 // 01082 // Use a try-finally to facilitate cleanup. 01083 // 01084 01085 try { 01086 01087 // 01088 // Walk through all the notify blocks. 01089 // 01090 01091 for (NotifyLinks = NotifyList->Flink; 01092 NotifyLinks != NotifyList; 01093 NotifyLinks = NotifyLinks->Flink) { 01094 01095 // 01096 // Obtain the Notify structure from the list entry. 01097 // 01098 01099 Notify = CONTAINING_RECORD( NotifyLinks, NOTIFY_CHANGE, NotifyList ); 01100 01101 // 01102 // The rules for deciding whether this notification applies are 01103 // different for view indices versus file name indices (directories). 01104 // 01105 01106 if (FullTargetName == NULL) { 01107 01108 ASSERTMSG( "Directory notify handle in view index notify list!", Notify->FullDirectoryName == NULL); 01109 01110 // 01111 // Make sure this is the Fcb being watched. 01112 // 01113 01114 if (TargetContext != Notify->SubjectContext) { 01115 01116 continue; 01117 } 01118 01119 TargetParent.Buffer = NULL; 01120 TargetParent.Length = 0; 01121 01122 ViewIndex = TRUE; 01123 01124 // 01125 // Handle the directory case. 01126 // 01127 01128 } else { 01129 01130 ASSERTMSG( "View index notify handle in directory notify list!", Notify->FullDirectoryName != NULL); 01131 01132 // 01133 // If the length of the name in the notify block is currently zero then 01134 // someone is doing a rename and we can skip this block. 01135 // 01136 01137 if (Notify->FullDirectoryName->Length == 0) { 01138 01139 continue; 01140 } 01141 01142 // 01143 // If this filter match is not part of the completion filter then continue. 01144 // 01145 01146 if (!(FilterMatch & Notify->CompletionFilter)) { 01147 01148 continue; 01149 } 01150 01151 // 01152 // If there is no normalized name then set its value from the full 01153 // file name. 01154 // 01155 01156 if (!ARGUMENT_PRESENT( NormalizedParentName )) { 01157 NormalizedParent.Buffer = FullTargetName->Buffer; 01158 NormalizedParent.Length = TargetNameOffset; 01159 01160 if (NormalizedParent.Length != Notify->CharacterSize) { 01161 01162 NormalizedParent.Length -= Notify->CharacterSize; 01163 } 01164 01165 NormalizedParent.MaximumLength = NormalizedParent.Length; 01166 01167 NormalizedParentName = &NormalizedParent; 01168 } 01169 01170 // 01171 // If the length of the directory being watched is longer than the 01172 // parent of the modified file then it can't be an ancestor of the 01173 // modified file. 01174 // 01175 01176 if (Notify->FullDirectoryName->Length > NormalizedParentName->Length) { 01177 01178 continue; 01179 } 01180 01181 // 01182 // If the lengths match exactly then this can only be the parent of 01183 // the modified file. 01184 // 01185 01186 if (NormalizedParentName->Length == Notify->FullDirectoryName->Length) { 01187 01188 NotifyIsParent = TRUE; 01189 01190 // 01191 // If we are not watching the subtree of this directory then continue. 01192 // 01193 01194 } else if (!FlagOn( Notify->Flags, NOTIFY_WATCH_TREE )) { 01195 01196 continue; 01197 01198 // 01199 // The watched directory can only be an ancestor of the modified 01200 // file. Make sure that there is legal pathname separator immediately 01201 // after the end of the watched directory name within the normalized name. 01202 // If the watched directory is the root then we know this condition is TRUE. 01203 // 01204 01205 } else { 01206 01207 if (!FlagOn( Notify->Flags, NOTIFY_DIR_IS_ROOT )) { 01208 01209 // 01210 // Check for the character size. 01211 // 01212 01213 if (Notify->CharacterSize == sizeof( CHAR )) { 01214 01215 if (*(Add2Ptr( NormalizedParentName->Buffer, 01216 Notify->FullDirectoryName->Length, 01217 PCHAR )) != '\\') { 01218 01219 continue; 01220 } 01221 01222 } else if (*(Add2Ptr( NormalizedParentName->Buffer, 01223 Notify->FullDirectoryName->Length, 01224 PWCHAR )) != L'\\') { 01225 01226 continue; 01227 } 01228 } 01229 01230 NotifyIsParent = FALSE; 01231 } 01232 01233 // 01234 // We now have a correct match of the name lengths. Now verify that the 01235 // characters match exactly. 01236 // 01237 01238 if (!RtlEqualMemory( Notify->FullDirectoryName->Buffer, 01239 NormalizedParentName->Buffer, 01240 Notify->FullDirectoryName->Length )) { 01241 01242 continue; 01243 } 01244 01245 // 01246 // The characters are correct. Now check in the case of a non-parent 01247 // notify that we have traverse callback. 01248 // 01249 01250 if (!NotifyIsParent && 01251 Notify->TraverseCallback != NULL && 01252 !Notify->TraverseCallback( Notify->FsContext, 01253 TargetContext, 01254 Notify->SubjectContext )) { 01255 01256 continue; 01257 } 01258 } 01259 01260 // 01261 // If this entry is going into a buffer then check that 01262 // it will fit. 01263 // 01264 01265 if (!FlagOn( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY ) 01266 && Notify->BufferLength != 0) { 01267 01268 ULONG AllocationLength; 01269 01270 AllocationLength = 0; 01271 NotifyIrp = NULL; 01272 01273 // 01274 // If we don't already have a buffer then check to see 01275 // if we have any Irps in the list and use the buffer 01276 // length in the Irp. 01277 // 01278 01279 if (Notify->ThisBufferLength == 0) { 01280 01281 // 01282 // If there is an entry in the list then get the length. 01283 // 01284 01285 if (!IsListEmpty( &Notify->NotifyIrps )) { 01286 01287 PIO_STACK_LOCATION IrpSp; 01288 01289 NotifyIrp = CONTAINING_RECORD( Notify->NotifyIrps.Flink, 01290 IRP, 01291 Tail.Overlay.ListEntry ); 01292 01293 IrpSp = IoGetCurrentIrpStackLocation( NotifyIrp ); 01294 01295 AllocationLength = IrpSp->Parameters.NotifyDirectory.Length; 01296 01297 // 01298 // Otherwise use the caller's last buffer size. 01299 // 01300 01301 } else { 01302 01303 AllocationLength = Notify->BufferLength; 01304 } 01305 01306 // 01307 // Otherwise use the length of the current buffer. 01308 // 01309 01310 } else { 01311 01312 AllocationLength = Notify->ThisBufferLength; 01313 } 01314 01315 // 01316 // Build the strings for the relative name. This includes 01317 // the strings for the parent name, file name and stream 01318 // name. 01319 // 01320 01321 if (!NotifyIsParent) { 01322 01323 // 01324 // We need to find the string for the ancestor of this 01325 // file from the watched directory. If the normalized parent 01326 // name is the same as the parent name then we can use 01327 // the tail of the parent directly. Otherwise we need to 01328 // count the matching name components and capture the 01329 // final components. 01330 // 01331 01332 if (!ViewIndex) { 01333 01334 // 01335 // If the watched directory is the root then we just use the full 01336 // parent name. 01337 // 01338 01339 if (FlagOn( Notify->Flags, NOTIFY_DIR_IS_ROOT ) || 01340 NormalizedParentName->Buffer != FullTargetName->Buffer) { 01341 01342 // 01343 // If we don't have a string for the parent then construct 01344 // it now. 01345 // 01346 01347 if (ParentName.Buffer == NULL) { 01348 01349 ParentName.Buffer = FullTargetName->Buffer; 01350 ParentName.Length = TargetNameOffset; 01351 01352 if (ParentName.Length != Notify->CharacterSize) { 01353 01354 ParentName.Length -= Notify->CharacterSize; 01355 } 01356 01357 ParentName.MaximumLength = ParentName.Length; 01358 } 01359 01360 // 01361 // Count through the components of the parent until we have 01362 // swallowed the same number of name components as in the 01363 // watched directory name. We have the unicode version and 01364 // the Ansi version to watch for. 01365 // 01366 01367 ComponentCount = 0; 01368 CurrentOffset = 0; 01369 01370 // 01371 // If this is the root then there is no more to do. 01372 // 01373 01374 if (FlagOn( Notify->Flags, NOTIFY_DIR_IS_ROOT )) { 01375 01376 NOTHING; 01377 01378 } else { 01379 01380 ULONG ParentComponentCount; 01381 ULONG ParentOffset; 01382 01383 ParentComponentCount = 1; 01384 ParentOffset = 0; 01385 01386 if (Notify->CharacterSize == sizeof( CHAR )) { 01387 01388 // 01389 // Find the number of components in the parent. We 01390 // have to do this for each one because this name and 01391 // the number of components could have changed. 01392 // 01393 01394 while (ParentOffset < Notify->FullDirectoryName->Length) { 01395 01396 if (*((PCHAR) Notify->FullDirectoryName->Buffer + ParentOffset) == '\\') { 01397 01398 ParentComponentCount += 1; 01399 } 01400 01401 ParentOffset += 1; 01402 } 01403 01404 while (TRUE) { 01405 01406 if (*((PCHAR) ParentName.Buffer + CurrentOffset) == '\\') { 01407 01408 ComponentCount += 1; 01409 01410 if (ComponentCount == ParentComponentCount) { 01411 01412 break; 01413 } 01414 01415 } 01416 01417 CurrentOffset += 1; 01418 } 01419 01420 } else { 01421 01422 // 01423 // Find the number of components in the parent. We 01424 // have to do this for each one because this name and 01425 // the number of components could have changed. 01426 // 01427 01428 while (ParentOffset < Notify->FullDirectoryName->Length / sizeof( WCHAR )) { 01429 01430 if (*((PWCHAR) Notify->FullDirectoryName->Buffer + ParentOffset) == '\\') { 01431 01432 ParentComponentCount += 1; 01433 } 01434 01435 ParentOffset += 1; 01436 } 01437 01438 while (TRUE) { 01439 01440 if (*((PWCHAR) ParentName.Buffer + CurrentOffset) == L'\\') { 01441 01442 ComponentCount += 1; 01443 01444 if (ComponentCount == ParentComponentCount) { 01445 01446 break; 01447 } 01448 } 01449 01450 CurrentOffset += 1; 01451 } 01452 01453 // 01454 // Convert characters to bytes. 01455 // 01456 01457 CurrentOffset *= Notify->CharacterSize; 01458 } 01459 } 01460 01461 // 01462 // We now know the offset into the parent name of the separator 01463 // immediately preceding the relative parent name. Construct the 01464 // target parent name for the buffer. 01465 // 01466 01467 CurrentOffset += Notify->CharacterSize; 01468 01469 TargetParent.Buffer = Add2Ptr( ParentName.Buffer, 01470 CurrentOffset, 01471 PCHAR ); 01472 TargetParent.MaximumLength = 01473 TargetParent.Length = ParentName.Length - (USHORT) CurrentOffset; 01474 01475 // 01476 // If the normalized is the same as the parent name use the portion 01477 // after the match with the watched directory. 01478 // 01479 01480 } else { 01481 01482 TargetParent.Buffer = Add2Ptr( NormalizedParentName->Buffer, 01483 (Notify->FullDirectoryName->Length + 01484 Notify->CharacterSize), 01485 PCHAR ); 01486 01487 TargetParent.MaximumLength = 01488 TargetParent.Length = NormalizedParentName->Length - 01489 Notify->FullDirectoryName->Length - 01490 Notify->CharacterSize; 01491 01492 } 01493 } 01494 01495 } else { 01496 01497 // 01498 // The length of the target parent is zero. 01499 // 01500 01501 TargetParent.Length = 0; 01502 } 01503 01504 // 01505 // Compute how much buffer space this report will take. 01506 // 01507 01508 SizeOfEntry = FIELD_OFFSET( FILE_NOTIFY_INFORMATION, FileName ); 01509 01510 if (ViewIndex) { 01511 01512 // 01513 // In the view index case, the information to copy to the 01514 // buffer comes to us in the stream name, and that is all 01515 // the room we need to worry about having. 01516 // 01517 01518 ASSERT(ARGUMENT_PRESENT( StreamName )); 01519 01520 SizeOfEntry += StreamName->Length; 01521 01522 } else { 01523 01524 // 01525 // If there is a parent to report, find the size and include a separator 01526 // character. 01527 // 01528 01529 if (!NotifyIsParent) { 01530 01531 if (Notify->CharacterSize == sizeof( CHAR )) { 01532 01533 SizeOfEntry += RtlOemStringToCountedUnicodeSize( &TargetParent ); 01534 01535 } else { 01536 01537 SizeOfEntry += TargetParent.Length; 01538 } 01539 01540 // 01541 // Include the separator. This is always a unicode character. 01542 // 01543 01544 SizeOfEntry += sizeof( WCHAR ); 01545 } 01546 01547 // 01548 // If we don't have the string for the target then construct it now. 01549 // 01550 01551 if (TargetName.Buffer == NULL) { 01552 01553 TargetName.Buffer = Add2Ptr( FullTargetName->Buffer, TargetNameOffset, PCHAR ); 01554 TargetName.MaximumLength = 01555 TargetName.Length = FullTargetName->Length - TargetNameOffset; 01556 } 01557 01558 if (Notify->CharacterSize == sizeof( CHAR )) { 01559 01560 SizeOfEntry += RtlOemStringToCountedUnicodeSize( &TargetName ); 01561 01562 } else { 01563 01564 SizeOfEntry += TargetName.Length; 01565 } 01566 01567 // 01568 // If there is a stream name then add the bytes needed 01569 // for that. 01570 // 01571 01572 if (ARGUMENT_PRESENT( StreamName )) { 01573 01574 // 01575 // Add the space needed for the ':' separator. 01576 // 01577 01578 if (Notify->CharacterSize == sizeof( WCHAR )) { 01579 01580 SizeOfEntry += (StreamName->Length + sizeof( WCHAR )); 01581 01582 } else { 01583 01584 SizeOfEntry += (RtlOemStringToCountedUnicodeSize( StreamName ) 01585 + sizeof( CHAR )); 01586 } 01587 } 01588 } 01589 01590 // 01591 // Remember if this report would overflow the buffer. 01592 // 01593 01594 NextEntryOffset = (ULONG)LongAlign( Notify->DataLength ); 01595 01596 if (SizeOfEntry <= AllocationLength 01597 && (NextEntryOffset + SizeOfEntry) <= AllocationLength) { 01598 01599 PFILE_NOTIFY_INFORMATION NotifyInfo = NULL; 01600 01601 // 01602 // If there is already a notify buffer, we append this 01603 // data to it. 01604 // 01605 01606 if (Notify->Buffer != NULL) { 01607 01608 NotifyInfo = Add2Ptr( Notify->Buffer, 01609 Notify->LastEntry, 01610 PFILE_NOTIFY_INFORMATION ); 01611 01612 NotifyInfo->NextEntryOffset = NextEntryOffset - Notify->LastEntry; 01613 01614 Notify->LastEntry = NextEntryOffset; 01615 01616 NotifyInfo = Add2Ptr( Notify->Buffer, 01617 Notify->LastEntry, 01618 PFILE_NOTIFY_INFORMATION ); 01619 01620 // 01621 // If there is an Irp list we check whether we will need 01622 // to allocate a new buffer. 01623 // 01624 01625 } else if (NotifyIrp != NULL) { 01626 01627 if (NotifyIrp->AssociatedIrp.SystemBuffer != NULL) { 01628 01629 Notify->Buffer = 01630 NotifyInfo = NotifyIrp->AssociatedIrp.SystemBuffer; 01631 01632 Notify->ThisBufferLength = AllocationLength; 01633 01634 } else if (NotifyIrp->MdlAddress != NULL) { 01635 01636 Notify->Buffer = 01637 NotifyInfo = MmGetSystemAddressForMdl( NotifyIrp->MdlAddress ); 01638 01639 Notify->ThisBufferLength = AllocationLength; 01640 } 01641 } 01642 01643 // 01644 // If we need to allocate a buffer, we will charge quota 01645 // to the original process and allocate paged pool. 01646 // 01647 01648 if (Notify->Buffer == NULL) { 01649 01650 BOOLEAN ChargedQuota = FALSE; 01651 01652 try { 01653 01654 PsChargePoolQuota( Notify->OwningProcess, 01655 PagedPool, 01656 AllocationLength ); 01657 01658 ChargedQuota = TRUE; 01659 01660 Notify->AllocatedBuffer = 01661 Notify->Buffer = FsRtlpAllocatePool( PagedPool, 01662 AllocationLength ); 01663 01664 Notify->ThisBufferLength = AllocationLength; 01665 01666 NotifyInfo = Notify->Buffer; 01667 01668 } except(( ExceptionCode = GetExceptionCode(), FsRtlIsNtstatusExpected(ExceptionCode)) 01669 ? EXCEPTION_EXECUTE_HANDLER 01670 : EXCEPTION_CONTINUE_SEARCH ) { 01671 01672 01673 ASSERT( (ExceptionCode == STATUS_INSUFFICIENT_RESOURCES) || 01674 (ExceptionCode == STATUS_QUOTA_EXCEEDED) ); 01675 01676 // 01677 // Return quota if we allocated the buffer. 01678 // 01679 01680 if (ChargedQuota) { 01681 01682 PsReturnPoolQuota( Notify->OwningProcess, 01683 PagedPool, 01684 AllocationLength ); 01685 01686 } 01687 01688 // 01689 // Forget any current buffer and resort to immediate 01690 // notify. 01691 // 01692 01693 SetFlag( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY ); 01694 } 01695 } 01696 01697 // 01698 // If we have a buffer then fill in the results 01699 // from this operation. Otherwise we remember 01700 // to simply alert the caller. 01701 // 01702 01703 if (NotifyInfo != NULL) { 01704 01705 // 01706 // Update the buffer with the current data. 01707 // 01708 01709 if (FsRtlNotifyUpdateBuffer( NotifyInfo, 01710 Action, 01711 &TargetParent, 01712 &TargetName, 01713 StreamName, 01714 (BOOLEAN) (Notify->CharacterSize == sizeof( WCHAR )), 01715 SizeOfEntry )) { 01716 01717 // 01718 // Update the buffer data length. 01719 // 01720 01721 Notify->DataLength = NextEntryOffset + SizeOfEntry; 01722 01723 // 01724 // We couldn't copy the data into the buffer. Just 01725 // notify without any additional information. 01726 // 01727 01728 } else { 01729 01730 SetFlag( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY ); 01731 } 01732 } 01733 01734 } else { 01735 01736 SetFlag( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY ); 01737 } 01738 01739 // 01740 // If we have a buffer but can't use it then clear all of the 01741 // buffer related fields. Also deallocate any buffer allocated 01742 // by us. 01743 // 01744 01745 if (FlagOn( Notify->Flags, NOTIFY_IMMEDIATE_NOTIFY ) 01746 && Notify->Buffer != NULL) { 01747 01748 if (Notify->AllocatedBuffer != NULL) { 01749 01750 PsReturnPoolQuota( Notify->OwningProcess, 01751 PagedPool, 01752 Notify->ThisBufferLength ); 01753 01754 ExFreePool( Notify->AllocatedBuffer ); 01755 } 01756 01757 Notify->AllocatedBuffer = Notify->Buffer = NULL; 01758 01759 Notify->ThisBufferLength = Notify->DataLength = Notify->LastEntry = 0; 01760 } 01761 } 01762 01763 // 01764 // Complete the next entry on the list if we aren't holding 01765 // up notification. 01766 // 01767 01768 if (Action == FILE_ACTION_RENAMED_OLD_NAME) { 01769 01770 SetFlag( Notify->Flags, NOTIFY_DEFER_NOTIFY ); 01771 01772 } else { 01773 01774 ClearFlag( Notify->Flags, NOTIFY_DEFER_NOTIFY ); 01775 01776 if (!IsListEmpty( &Notify->NotifyIrps )) { 01777 01778 FsRtlNotifyCompleteIrpList( Notify, STATUS_SUCCESS ); 01779 } 01780 } 01781 } 01782 01783 } finally { 01784 01785 ReleaseNotifySync( NotifySync ); 01786 01787 DebugTrace( -1, Dbg, "FsRtlNotifyFullReportChange: Exit\n", 0 ); 01788 } 01789 01790 return; 01791 }

NTKERNELAPI VOID FsRtlNotifyInitializeSync IN PNOTIFY_SYNC NotifySync  ) 
 

Definition at line 371 of file notify.c.

References Dbg, DebugTrace, ERESOURCE_THREAD, ExInitializeFastMutex, _REAL_NOTIFY_SYNC::FastMutex, FsRtlpAllocatePool, NonPagedPool, NULL, _REAL_NOTIFY_SYNC::OwnerCount, _REAL_NOTIFY_SYNC::OwningThread, PAGED_CODE, PNOTIFY_SYNC, and PREAL_NOTIFY_SYNC.

Referenced by UdfInitializeVcb().

00377 : 00378 00379 This routine is called to allocate and initialize the synchronization object 00380 for this notify list. 00381 00382 Arguments: 00383 00384 NotifySync - This is the address to store the structure we allocate. 00385 00386 Return Value: 00387 00388 None. 00389 00390 --*/ 00391 00392 { 00393 PREAL_NOTIFY_SYNC RealSync; 00394 00395 PAGED_CODE(); 00396 00397 DebugTrace( +1, Dbg, "FsRtlNotifyInitializeSync: Entered\n", 0 ); 00398 00399 // 00400 // Clear the pointer and then attempt to allocate a non-paged 00401 // structure. 00402 // 00403 00404 *NotifySync = NULL; 00405 00406 RealSync = (PREAL_NOTIFY_SYNC) FsRtlpAllocatePool( NonPagedPool, 00407 sizeof( REAL_NOTIFY_SYNC )); 00408 00409 // 00410 // Initialize the structure. 00411 // 00412 00413 ExInitializeFastMutex( &RealSync->FastMutex ); 00414 RealSync->OwningThread = (ERESOURCE_THREAD) 0; 00415 RealSync->OwnerCount = 0; 00416 00417 *NotifySync = (PNOTIFY_SYNC) RealSync; 00418 00419 DebugTrace( -1, Dbg, "FsRtlNotifyInitializeSync: Exit\n", 0 ); 00420 return; 00421 }

VOID FsRtlNotifyReportChange IN PNOTIFY_SYNC  NotifySync,
IN PLIST_ENTRY  NotifyList,
IN PSTRING  FullTargetName,
IN PSTRING  TargetName,
IN ULONG  FilterMatch
 

Definition at line 897 of file notify.c.

References Dbg, DebugTrace, FsRtlNotifyFullReportChange(), NULL, PAGED_CODE, and USHORT.

00907 : 00908 00909 This routine is called by a file system when a file has been modified in 00910 such a way that it will cause a notify change Irp to complete. We walk 00911 through all the notify structures looking for those structures which 00912 would be associated with an ancestor directory of the target file name. 00913 00914 We look for all the notify structures which have a filter match and 00915 then check that the directory name in the notify structure is a 00916 proper prefix of the full target name. 00917 00918 If we find a notify structure which matches the above conditions, we 00919 complete all the Irps for the notify structure. If the structure has 00920 no Irps, we mark the notify pending field. 00921 00922 Arguments: 00923 00924 NotifySync - This is the controlling fast mutex for this notify list. 00925 It is stored here so that it can be found for an Irp which is being 00926 cancelled. 00927 00928 NotifyList - This is the start of the notify list to add this 00929 structure to. 00930 00931 FullTargetName - This is the full name of the file which has been 00932 changed. 00933 00934 TargetName - This is the final component of the modified file. 00935 00936 FilterMatch - This flag field is compared with the completion filter 00937 in the notify structure. If any of the corresponding 00938 bits in the completion filter are set, then a notify 00939 condition exists. 00940 00941 Return Value: 00942 00943 None. 00944 00945 --*/ 00946 00947 { 00948 PAGED_CODE(); 00949 00950 DebugTrace( +1, Dbg, "FsRtlNotifyReportChange: Entered\n", 0 ); 00951 00952 // 00953 // Call the full notify routine to do the actual work. 00954 // 00955 00956 FsRtlNotifyFullReportChange( NotifySync, 00957 NotifyList, 00958 FullTargetName, 00959 (USHORT) (FullTargetName->Length - TargetName->Length), 00960 NULL, 00961 NULL, 00962 FilterMatch, 00963 0, 00964 NULL ); 00965 00966 DebugTrace( -1, Dbg, "FsRtlNotifyReportChange: Exit\n", 0 ); 00967 00968 return; 00969 }

BOOLEAN FsRtlNotifySetCancelRoutine IN PIRP  NotifyIrp,
IN PNOTIFY_CHANGE Notify  OPTIONAL
 

Definition at line 2195 of file notify.c.

References Dbg, DebugTrace, FALSE, FsRtlCancelNotify(), IoAcquireCancelSpinLock(), IoReleaseCancelSpinLock(), IoSetCancelRoutine, NULL, PDRIVER_CANCEL, and TRUE.

Referenced by FsRtlNotifyCompleteIrp(), and FsRtlNotifyFullChangeDirectory().

02202 : 02203 02204 This is a separate routine because it cannot be paged. 02205 02206 Arguments: 02207 02208 NotifyIrp - Set the cancel routine in this Irp. 02209 02210 Notify - If NULL then we are setting the cancel routine. If not-NULL then we 02211 are clearing the cancel routine. If the cancel routine is not-null then 02212 we need to decrement the reference count on this Notify structure 02213 02214 Return Value: 02215 02216 BOOLEAN - Only meaningfull if Notify is specified. It indicates if this 02217 routine cleared the cancel routine. FALSE indicates that the cancel 02218 routine is processing the Irp. 02219 02220 --*/ 02221 02222 { 02223 BOOLEAN ClearedCancel = FALSE; 02224 PDRIVER_CANCEL CurrentCancel; 02225 02226 // 02227 // Grab the cancel spinlock and set our cancel routine in the Irp. 02228 // 02229 02230 IoAcquireCancelSpinLock( &NotifyIrp->CancelIrql ); 02231 02232 // 02233 // If we are completing an Irp then clear the cancel routine and 02234 // the information field. 02235 // 02236 02237 if (ARGUMENT_PRESENT( Notify )) { 02238 02239 CurrentCancel = IoSetCancelRoutine( NotifyIrp, NULL ); 02240 NotifyIrp->IoStatus.Information = 0; 02241 02242 IoReleaseCancelSpinLock( NotifyIrp->CancelIrql ); 02243 02244 // 02245 // If the current cancel routine is non-NULL then decrement the reference count 02246 // in the Notify. 02247 // 02248 02249 if (CurrentCancel != NULL) { 02250 02251 InterlockedDecrement( &Notify->ReferenceCount ); 02252 ClearedCancel = TRUE; 02253 } 02254 02255 // 02256 // If the cancel flag is set, we complete the Irp with cancelled 02257 // status and exit. 02258 // 02259 02260 } else if (NotifyIrp->Cancel) { 02261 02262 DebugTrace( 0, Dbg, "Irp has been cancelled\n", 0 ); 02263 02264 FsRtlCancelNotify( NULL, NotifyIrp ); 02265 02266 } else { 02267 02268 // 02269 // Set our cancel routine in the Irp. 02270 // 02271 02272 IoSetCancelRoutine( NotifyIrp, FsRtlCancelNotify ); 02273 02274 IoReleaseCancelSpinLock( NotifyIrp->CancelIrql ); 02275 } 02276 02277 return ClearedCancel; 02278 }

NTKERNELAPI VOID FsRtlNotifyUninitializeSync IN PNOTIFY_SYNC NotifySync  ) 
 

Definition at line 426 of file notify.c.

References Dbg, DebugTrace, ExFreePool(), NULL, and PAGED_CODE.

Referenced by UdfDeleteVcb().

00432 : 00433 00434 This routine is called to uninitialize the synchronization object 00435 for this notify list. 00436 00437 Arguments: 00438 00439 NotifySync - This is the address containing the pointer to our synchronization 00440 object. 00441 00442 Return Value: 00443 00444 None. 00445 00446 --*/ 00447 00448 { 00449 PAGED_CODE(); 00450 00451 DebugTrace( +1, Dbg, "FsRtlNotifyUninitializeSync: Entered\n", 0 ); 00452 00453 // 00454 // Free the structure if present and clear the pointer. 00455 // 00456 00457 if (*NotifySync != NULL) { 00458 00459 ExFreePool( *NotifySync ); 00460 *NotifySync = NULL; 00461 } 00462 00463 DebugTrace( -1, Dbg, "FsRtlNotifyUninitializeSync: Exit\n", 0 ); 00464 return; 00465 }

BOOLEAN FsRtlNotifyUpdateBuffer IN PFILE_NOTIFY_INFORMATION  NotifyInfo,
IN ULONG  FileAction,
IN PSTRING  ParentName,
IN PSTRING  TargetName,
IN PSTRING StreamName  OPTIONAL,
IN BOOLEAN  UnicodeName,
IN ULONG  SizeOfEntry
 

Definition at line 2286 of file notify.c.

References Add2Ptr, ASSERT, Dbg, DebugTrace, EXCEPTION_EXECUTE_HANDLER, FALSE, FileName, L, PAGED_CODE, RtlOemToUnicodeN(), and TRUE.

Referenced by FsRtlNotifyFullReportChange().

02298 : 02299 02300 This routine is called to fill in a FILE_NOTIFY_INFORMATION structure for a 02301 notify change event. The main work is in converting an OEM string to Unicode. 02302 02303 Arguments: 02304 02305 NotifyInfo - Information structure to complete. 02306 02307 FileAction - Action which triggered the notification event. 02308 02309 ParentName - Relative path to the parent of the changed file from the 02310 directory being watched. The length for this will be zero if the modified 02311 file is in the watched directory. 02312 02313 TargetName - This is the name of the modified file. 02314 02315 StreamName - If present there is a stream name to append to the filename. 02316 02317 UnicodeName - Indicates if the above name is Unicode or Oem. 02318 02319 SizeOfEntry - Indicates the number of bytes to be used in the buffer. 02320 02321 Return Value: 02322 02323 BOOLEAN - TRUE if we were able to update the buffer, FALSE otherwise. 02324 02325 --*/ 02326 02327 { 02328 BOOLEAN CopiedToBuffer; 02329 ULONG BufferOffset = 0; 02330 02331 PAGED_CODE(); 02332 02333 DebugTrace( +1, Dbg, "FsRtlNotifyUpdateBuffer: Entered\n", 0 ); 02334 02335 // 02336 // Protect the entire call with a try-except. If we had an error 02337 // we will assume that we have a bad buffer and we won't return 02338 // the data in the buffer. 02339 // 02340 02341 try { 02342 02343 // 02344 // Update the common fields in the notify information. 02345 // 02346 02347 NotifyInfo->NextEntryOffset = 0; 02348 NotifyInfo->Action = FileAction; 02349 02350 NotifyInfo->FileNameLength = SizeOfEntry - FIELD_OFFSET( FILE_NOTIFY_INFORMATION, FileName ); 02351 02352 // 02353 // If we have a unicode name, then copy the data directly into the output buffer. 02354 // 02355 02356 if (UnicodeName) { 02357 02358 if (ParentName->Length != 0) { 02359 02360 RtlCopyMemory( NotifyInfo->FileName, 02361 ParentName->Buffer, 02362 ParentName->Length ); 02363 02364 *(Add2Ptr( NotifyInfo->FileName, ParentName->Length, PWCHAR )) = L'\\'; 02365 BufferOffset = ParentName->Length + sizeof( WCHAR ); 02366 } 02367 02368 RtlCopyMemory( Add2Ptr( NotifyInfo->FileName, 02369 BufferOffset, 02370 PVOID ), 02371 TargetName->Buffer, 02372 TargetName->Length ); 02373 02374 if (ARGUMENT_PRESENT( StreamName )) { 02375 02376 BufferOffset += TargetName->Length; 02377 02378 *(Add2Ptr( NotifyInfo->FileName, BufferOffset, PWCHAR )) = L':'; 02379 02380 RtlCopyMemory( Add2Ptr( NotifyInfo->FileName, 02381 BufferOffset + sizeof( WCHAR ), 02382 PVOID ), 02383 StreamName->Buffer, 02384 StreamName->Length ); 02385 } 02386 02387 // 02388 // For a non-unicode name, use the conversion routines. 02389 // 02390 02391 } else { 02392 02393 ULONG BufferLength; 02394 02395 if (ParentName->Length != 0) { 02396 02397 RtlOemToUnicodeN( NotifyInfo->FileName, 02398 NotifyInfo->FileNameLength, 02399 &BufferLength, 02400 ParentName->Buffer, 02401 ParentName->Length ); 02402 02403 *(Add2Ptr( NotifyInfo->FileName, BufferLength, PWCHAR )) = L'\\'; 02404 02405 BufferOffset = BufferLength + sizeof( WCHAR ); 02406 } 02407 02408 // 02409 // For view indices, we do not have a parent name. 02410 // 02411 02412 if (ParentName->Length == 0) { 02413 02414 ASSERT(ARGUMENT_PRESENT( StreamName )); 02415 02416 RtlCopyMemory( Add2Ptr( NotifyInfo->FileName, 02417 BufferOffset, 02418 PCHAR ), 02419 StreamName->Buffer, 02420 StreamName->Length ); 02421 02422 } else { 02423 02424 RtlOemToUnicodeN( Add2Ptr( NotifyInfo->FileName, 02425 BufferOffset, 02426 PWCHAR ), 02427 NotifyInfo->FileNameLength, 02428 &BufferLength, 02429 TargetName->Buffer, 02430 TargetName->Length ); 02431 02432 if (ARGUMENT_PRESENT( StreamName )) { 02433 02434 BufferOffset += BufferLength; 02435 02436 *(Add2Ptr( NotifyInfo->FileName, BufferOffset, PWCHAR )) = L':'; 02437 02438 RtlOemToUnicodeN( Add2Ptr( NotifyInfo->FileName, 02439 BufferOffset + sizeof( WCHAR ), 02440 PWCHAR ), 02441 NotifyInfo->FileNameLength, 02442 &BufferLength, 02443 StreamName->Buffer, 02444 StreamName->Length ); 02445 } 02446 } 02447 } 02448 02449 CopiedToBuffer = TRUE; 02450 02451 } except( EXCEPTION_EXECUTE_HANDLER ) { 02452 02453 CopiedToBuffer = FALSE; 02454 } 02455 02456 DebugTrace( -1, Dbg, "FsRtlNotifyUpdateBuffer: Exit\n", 0 ); 02457 02458 return CopiedToBuffer; 02459 }


Generated on Sat May 15 19:44:51 2004 for test by doxygen 1.3.7