@@ -358,6 +358,28 @@ private NtResult<FileBasicInformation> QueryBasicInformation(bool throw_on_error
358358 return Query ( FileInformationClass . FileBasicInformation , new FileBasicInformation ( ) , throw_on_error ) ;
359359 }
360360
361+ private static IEnumerable < DirectoryChangeNotification > ReadNotifications ( SafeHGlobalBuffer buffer , IoStatus status )
362+ {
363+ List < DirectoryChangeNotification > ns = new List < DirectoryChangeNotification > ( ) ;
364+
365+ // Change buffer size to reflect what's in the buffer.
366+ buffer . Initialize ( ( uint ) status . Information32 ) ;
367+
368+ int offset = 0 ;
369+ while ( offset < buffer . Length )
370+ {
371+ var info = buffer . GetStructAtOffset < FileNotifyInformation > ( offset ) ;
372+ var result = info . Result ;
373+ ns . Add ( new DirectoryChangeNotification ( result . Action , info . Data . ReadUnicodeString ( result . FileNameLength / 2 ) ) ) ;
374+ if ( result . NextEntryOffset == 0 )
375+ {
376+ break ;
377+ }
378+ offset += result . NextEntryOffset ;
379+ }
380+ return ns . AsReadOnly ( ) ;
381+ }
382+
361383 #endregion
362384
363385 #region Static Methods
@@ -3249,6 +3271,99 @@ public IEnumerable<string> FindFilesBySid(Sid sid)
32493271 }
32503272 }
32513273
3274+ /// <summary>
3275+ /// Get change notifications.
3276+ /// </summary>
3277+ /// <param name="completion_filter">The filter of events to watch for.</param>
3278+ /// <param name="watch_subtree">True to watch all sub directories.</param>
3279+ /// <param name="throw_on_error">True to throw on error.</param>
3280+ /// <returns>The list of changes.</returns>
3281+ public NtResult < IEnumerable < DirectoryChangeNotification > > GetChangeNotification (
3282+ DirectoryChangeNotifyFilter completion_filter , bool watch_subtree , bool throw_on_error )
3283+ {
3284+ using ( NtAsyncResult result = new NtAsyncResult ( this ) )
3285+ {
3286+ using ( var buffer = new SafeHGlobalBuffer ( 4096 ) )
3287+ {
3288+ return result . CompleteCall ( NtSystemCalls . NtNotifyChangeDirectoryFile (
3289+ Handle , result . EventHandle , IntPtr . Zero , IntPtr . Zero , result . IoStatusBuffer ,
3290+ buffer , buffer . Length , completion_filter , watch_subtree ) )
3291+ . CreateResult ( throw_on_error , ( ) => ReadNotifications ( buffer , result . IoStatusBuffer . Result ) ) ;
3292+ }
3293+ }
3294+ }
3295+
3296+ /// <summary>
3297+ /// Get change notifications.
3298+ /// </summary>
3299+ /// <param name="completion_filter">The filter of events to watch for.</param>
3300+ /// <param name="watch_subtree">True to watch all sub directories.</param>
3301+ /// <returns>The list of changes.</returns>
3302+ public IEnumerable < DirectoryChangeNotification > GetChangeNotification ( DirectoryChangeNotifyFilter completion_filter , bool watch_subtree )
3303+ {
3304+ return GetChangeNotification ( completion_filter , watch_subtree , true ) . Result ;
3305+ }
3306+
3307+ /// <summary>
3308+ /// Get change notifications.
3309+ /// </summary>
3310+ /// <param name="completion_filter">The filter of events to watch for.</param>
3311+ /// <param name="watch_subtree">True to watch all sub directories.</param>
3312+ /// <param name="throw_on_error">True to throw on error.</param>
3313+ /// <param name="token">Cancellation token.</param>
3314+ /// <returns>The list of changes.</returns>
3315+ public async Task < NtResult < IEnumerable < DirectoryChangeNotification > > > GetChangeNotificationAsync (
3316+ DirectoryChangeNotifyFilter completion_filter , bool watch_subtree , CancellationToken token , bool throw_on_error )
3317+ {
3318+ using ( var buffer = new SafeHGlobalBuffer ( 4096 ) )
3319+ {
3320+ var status = await RunFileCallAsync ( result => NtSystemCalls . NtNotifyChangeDirectoryFile (
3321+ Handle , result . EventHandle , IntPtr . Zero , IntPtr . Zero , result . IoStatusBuffer ,
3322+ buffer , buffer . Length , completion_filter , watch_subtree ) , token , throw_on_error ) ;
3323+ return status . Map ( r => ReadNotifications ( buffer , r ) ) ;
3324+ }
3325+ }
3326+
3327+ /// <summary>
3328+ /// Get change notifications.
3329+ /// </summary>
3330+ /// <param name="completion_filter">The filter of events to watch for.</param>
3331+ /// <param name="watch_subtree">True to watch all sub directories.</param>
3332+ /// <param name="throw_on_error">True to throw on error.</param>
3333+ /// <returns>The list of changes.</returns>
3334+ public Task < NtResult < IEnumerable < DirectoryChangeNotification > > > GetChangeNotificationAsync (
3335+ DirectoryChangeNotifyFilter completion_filter , bool watch_subtree , bool throw_on_error )
3336+ {
3337+ return GetChangeNotificationAsync ( completion_filter , watch_subtree , CancellationToken . None , throw_on_error ) ;
3338+ }
3339+
3340+ /// <summary>
3341+ /// Get change notifications.
3342+ /// </summary>
3343+ /// <param name="completion_filter">The filter of events to watch for.</param>
3344+ /// <param name="watch_subtree">True to watch all sub directories.</param>
3345+ /// <param name="token">Cancellation token.</param>
3346+ /// <returns>The list of changes.</returns>
3347+ public async Task < IEnumerable < DirectoryChangeNotification > > GetChangeNotificationAsync (
3348+ DirectoryChangeNotifyFilter completion_filter , bool watch_subtree , CancellationToken token )
3349+ {
3350+ var result = await GetChangeNotificationAsync ( completion_filter , watch_subtree , token , true ) ;
3351+ return result . Result ;
3352+ }
3353+
3354+ /// <summary>
3355+ /// Get change notifications.
3356+ /// </summary>
3357+ /// <param name="completion_filter">The filter of events to watch for.</param>
3358+ /// <param name="watch_subtree">True to watch all sub directories.</param>
3359+ /// <param name="token">Cancellation token.</param>
3360+ /// <returns>The list of changes.</returns>
3361+ public Task < IEnumerable < DirectoryChangeNotification > > GetChangeNotificationAsync (
3362+ DirectoryChangeNotifyFilter completion_filter , bool watch_subtree )
3363+ {
3364+ return GetChangeNotificationAsync ( completion_filter , watch_subtree , CancellationToken . None ) ;
3365+ }
3366+
32523367 /// <summary>
32533368 /// Method to query information for this object type.
32543369 /// </summary>
0 commit comments