ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

notify.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/fsrtl/notify.c
00005  * PURPOSE:         Change Notifications and Sync for File System Drivers
00006  * PROGRAMMERS:     Pierre Schweitzer
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* PRIVATE FUNCTIONS *********************************************************/
00016 
00017 VOID
00018 FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange,
00019                            IN NTSTATUS Status);
00020 
00021 BOOLEAN
00022 FsRtlNotifySetCancelRoutine(IN PIRP Irp,
00023                             IN PNOTIFY_CHANGE NotifyChange OPTIONAL);
00024 
00025 VOID
00026 NTAPI
00027 FsRtlCancelNotify(IN PDEVICE_OBJECT DeviceObject,
00028                   IN PIRP Irp)
00029 {
00030     IoReleaseCancelSpinLock(Irp->CancelIrql);
00031     UNIMPLEMENTED;
00032 }
00033 
00034 /*
00035  * @implemented
00036  */
00037 VOID
00038 FsRtlCheckNotifyForDelete(IN PLIST_ENTRY NotifyList,
00039                           IN PVOID FsContext)
00040 {
00041     PLIST_ENTRY NextEntry;
00042     PNOTIFY_CHANGE NotifyChange;
00043 
00044     if (!IsListEmpty(NotifyList))
00045     {
00046         /* Browse the notifications list to find the matching entry */
00047         for (NextEntry = NotifyList->Flink;
00048              NextEntry != NotifyList;
00049              NextEntry = NextEntry->Flink)
00050         {
00051             NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
00052             /* If the current record matches with the given context, it's the good one */
00053             if (NotifyChange->FsContext == FsContext && !IsListEmpty(&(NotifyChange->NotifyIrps)))
00054             {
00055                 FsRtlNotifyCompleteIrpList(NotifyChange, STATUS_DELETE_PENDING);
00056             }
00057         }
00058     }
00059 }
00060 
00061 PNOTIFY_CHANGE
00062 FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList,
00063                     IN PVOID FsContext)
00064 {
00065     PLIST_ENTRY NextEntry;
00066     PNOTIFY_CHANGE NotifyChange;
00067 
00068     if (!IsListEmpty(NotifyList))
00069     {
00070         /* Browse the notifications list to find the matching entry */
00071         for (NextEntry = NotifyList->Flink;
00072              NextEntry != NotifyList;
00073              NextEntry = NextEntry->Flink)
00074         {
00075             NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
00076             /* If the current record matches with the given context, it's the good one */
00077             if (NotifyChange->FsContext == FsContext)
00078             {
00079                 return NotifyChange;
00080             }
00081         }
00082     }
00083     return NULL;
00084 }
00085 
00086 VOID
00087 FORCEINLINE
00088 FsRtlNotifyAcquireFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
00089 {
00090     ULONG_PTR CurrentThread = (ULONG_PTR)KeGetCurrentThread();
00091 
00092     /* Only acquire fast mutex if it's not already acquired by the current thread */
00093     if (RealNotifySync->OwningThread != CurrentThread)
00094     {
00095         ExAcquireFastMutexUnsafe(&(RealNotifySync->FastMutex));
00096         RealNotifySync->OwningThread = CurrentThread;
00097     }
00098     /* Whatever the case, keep trace of the attempt to acquire fast mutex */
00099     RealNotifySync->OwnerCount++;
00100 }
00101 
00102 /*
00103  * @implemented
00104  */
00105 VOID
00106 FsRtlNotifyCompleteIrp(IN PIRP Irp,
00107                        IN PNOTIFY_CHANGE NotifyChange,
00108                        IN ULONG DataLength,
00109                        IN NTSTATUS Status,
00110                        IN BOOLEAN SkipCompletion)
00111 {
00112     PVOID Buffer;
00113     PIO_STACK_LOCATION Stack;
00114 
00115     PAGED_CODE();
00116 
00117     /* Check if we need to complete */
00118     if (!FsRtlNotifySetCancelRoutine(Irp, NotifyChange) && SkipCompletion)
00119     {
00120         return;
00121     }
00122 
00123     /* No succes => no data to return just complete */
00124     if (Status != STATUS_SUCCESS)
00125     {
00126         goto Completion;
00127     }
00128 
00129     /* Ensure there's something to return */
00130     Stack = IoGetCurrentIrpStackLocation(Irp);
00131     if (!DataLength || Stack->Parameters.NotifyDirectory.Length < DataLength)
00132     {
00133         Status = STATUS_NOTIFY_ENUM_DIR;
00134         goto Completion;
00135     }
00136 
00137     /* Ensture there's a buffer where to find data */
00138     if (!NotifyChange->AllocatedBuffer)
00139     {
00140         Irp->IoStatus.Information = DataLength;
00141         NotifyChange->Buffer = NULL;
00142         goto Completion;
00143     }
00144 
00145     /* Now, browse all the way to return data
00146      * and find the one that will work. We will
00147      * return data whatever happens
00148      */
00149     if (Irp->AssociatedIrp.SystemBuffer)
00150     {
00151         Buffer = Irp->AssociatedIrp.SystemBuffer;
00152         goto CopyAndComplete;
00153     }
00154 
00155     if (Irp->MdlAddress)
00156     {
00157         Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
00158         goto CopyAndComplete;
00159     }
00160 
00161     if (!(Stack->Control & SL_PENDING_RETURNED))
00162     {
00163         Buffer = Irp->UserBuffer;
00164         goto CopyAndComplete;
00165     }
00166 
00167     Irp->Flags |= (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_SYNCHRONOUS_PAGING_IO);
00168     Irp->AssociatedIrp.SystemBuffer = NotifyChange->AllocatedBuffer;
00169     /* Nothing to copy */
00170     goto ReleaseAndComplete;
00171 
00172 CopyAndComplete:
00173     _SEH2_TRY
00174     {
00175         RtlCopyMemory(Buffer, NotifyChange->AllocatedBuffer, DataLength);
00176     }
00177     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00178     {
00179         /* Do nothing */
00180     }
00181     _SEH2_END;
00182 
00183 ReleaseAndComplete:
00184     PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
00185 
00186     /* Release buffer UNLESS it's used */
00187     if (NotifyChange->AllocatedBuffer != Irp->AssociatedIrp.SystemBuffer &&
00188         NotifyChange->AllocatedBuffer)
00189     {
00190         ExFreePoolWithTag(NotifyChange->AllocatedBuffer, 0);
00191     }
00192 
00193     /* Prepare for return */
00194     NotifyChange->AllocatedBuffer = 0;
00195     NotifyChange->ThisBufferLength = 0;
00196     Irp->IoStatus.Information = DataLength;
00197     NotifyChange->Buffer = NULL;
00198 
00199     /* Finally complete */
00200 Completion:
00201     IoMarkIrpPending(Irp);
00202     Irp->IoStatus.Status = Status;
00203     IoCompleteRequest(Irp, EVENT_INCREMENT);
00204 }
00205 
00206 /*
00207  * @implemented
00208  */
00209 VOID
00210 FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange,
00211                            IN NTSTATUS Status)
00212 {
00213     PIRP Irp;
00214     ULONG DataLength;
00215     PLIST_ENTRY NextEntry;
00216 
00217     DataLength = NotifyChange->DataLength;
00218 
00219     NotifyChange->Flags &= (INVALIDATE_BUFFERS | WATCH_TREE);
00220     NotifyChange->DataLength = 0;
00221     NotifyChange->LastEntry = 0;
00222 
00223     while (!IsListEmpty(&(NotifyChange->NotifyIrps)))
00224     {
00225         /* We take the first entry */
00226         NextEntry = RemoveHeadList(&(NotifyChange->NotifyIrps));
00227         Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
00228         /* We complete it */
00229         FsRtlNotifyCompleteIrp(Irp, NotifyChange, DataLength, Status, TRUE);
00230         /* If we're notifying success, just notify first one */
00231         if (Status == STATUS_SUCCESS)
00232             break;
00233     }
00234 }
00235 
00236 VOID
00237 FORCEINLINE
00238 FsRtlNotifyReleaseFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
00239 {
00240     RealNotifySync->OwnerCount--;
00241     /* Release the fast mutex only if no other instance needs it */
00242     if (!RealNotifySync->OwnerCount)
00243     {
00244         ExReleaseFastMutexUnsafe(&(RealNotifySync->FastMutex));
00245         RealNotifySync->OwningThread = (ULONG_PTR)0;
00246     }
00247 }
00248 
00249 /*
00250  * @implemented
00251  */
00252 BOOLEAN
00253 FsRtlNotifySetCancelRoutine(IN PIRP Irp,
00254                             IN PNOTIFY_CHANGE NotifyChange OPTIONAL)
00255 {
00256     PDRIVER_CANCEL CancelRoutine;
00257 
00258     /* Acquire cancel lock */
00259     IoAcquireCancelSpinLock(&Irp->CancelIrql);
00260 
00261     /* If NotifyChange was given */
00262     if (NotifyChange)
00263     {
00264         /* First get cancel routine */
00265         CancelRoutine = IoSetCancelRoutine(Irp, NULL);
00266         Irp->IoStatus.Information = 0;
00267         /* Release cancel lock */
00268         IoReleaseCancelSpinLock(Irp->CancelIrql);
00269         /* If there was a cancel routine */
00270         if (CancelRoutine)
00271         {
00272             /* Decrease reference count */
00273             InterlockedDecrement((PLONG)&NotifyChange->ReferenceCount);
00274             /* Notify that we removed cancel routine */
00275             return TRUE;
00276         }
00277     }
00278     else
00279     {
00280         /* If IRP is cancel, call FsRtl cancel routine */
00281         if (Irp->Cancel)
00282         {
00283              FsRtlCancelNotify(NULL, Irp);
00284         }
00285         else
00286         {
00287             /* Otherwise, define FsRtl cancel routine as IRP cancel routine */
00288             IoSetCancelRoutine(Irp, FsRtlCancelNotify);
00289             /* Release lock */
00290             IoReleaseCancelSpinLock(Irp->CancelIrql);
00291         }
00292     }
00293 
00294     /* Return that we didn't removed cancel routine */
00295     return FALSE;
00296 }
00297 
00298 /* PUBLIC FUNCTIONS **********************************************************/
00299 
00300 /*++
00301  * @name FsRtlNotifyChangeDirectory
00302  * @implemented
00303  *
00304  * Lets FSD know if changes occures in the specified directory.
00305  * Directory will be reenumerated. 
00306  *
00307  * @param NotifySync
00308  *        Synchronization object pointer
00309  *
00310  * @param FsContext
00311  *        Used to identify the notify structure
00312  *
00313  * @param FullDirectoryName
00314  *        String (A or W) containing the full directory name 
00315  *
00316  * @param NotifyList
00317  *        Notify list pointer (to head)
00318  *
00319  * @param WatchTree
00320  *        True to notify changes in subdirectories too
00321  *
00322  * @param CompletionFilter
00323  *        Used to define types of changes to notify
00324  *
00325  * @param NotifyIrp
00326  *        IRP pointer to complete notify operation. It can be null
00327  *
00328  * @return None
00329  *
00330  * @remarks This function only redirects to FsRtlNotifyFilterChangeDirectory.
00331  *
00332  *--*/
00333 VOID
00334 NTAPI
00335 FsRtlNotifyChangeDirectory(IN PNOTIFY_SYNC NotifySync,
00336                            IN PVOID FsContext,
00337                            IN PSTRING FullDirectoryName,
00338                            IN PLIST_ENTRY NotifyList,
00339                            IN BOOLEAN WatchTree,
00340                            IN ULONG CompletionFilter,
00341                            IN PIRP NotifyIrp)
00342 {
00343     FsRtlNotifyFilterChangeDirectory(NotifySync,
00344                                      NotifyList,
00345                                      FsContext,
00346                                      FullDirectoryName,
00347                                      WatchTree,
00348                                      TRUE,
00349                                      CompletionFilter,
00350                                      NotifyIrp,
00351                                      NULL,
00352                                      NULL,
00353                                      NULL);
00354 }
00355 
00356 /*++
00357  * @name FsRtlNotifyCleanup
00358  * @implemented
00359  *
00360  * Called by FSD when all handles to FileObject (identified by FsContext) are closed
00361  *
00362  * @param NotifySync
00363  *        Synchronization object pointer
00364  *
00365  * @param NotifyList
00366  *        Notify list pointer (to head) 
00367  *
00368  * @param FsContext
00369  *        Used to identify the notify structure
00370  *
00371  * @return None
00372  *
00373  * @remarks None
00374  *
00375  *--*/
00376 VOID
00377 NTAPI
00378 FsRtlNotifyCleanup(IN PNOTIFY_SYNC NotifySync,
00379                    IN PLIST_ENTRY NotifyList,
00380                    IN PVOID FsContext)
00381 {
00382     PNOTIFY_CHANGE NotifyChange;
00383     PREAL_NOTIFY_SYNC RealNotifySync;
00384     PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL;
00385 
00386     /* Get real structure hidden behind the opaque pointer */
00387     RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
00388 
00389     /* Acquire the fast mutex */
00390     FsRtlNotifyAcquireFastMutex(RealNotifySync);
00391 
00392     _SEH2_TRY
00393     {
00394         /* Find if there's a matching notification with the FsContext */
00395         NotifyChange = FsRtlIsNotifyOnList(NotifyList, FsContext);
00396         if (NotifyChange)
00397         {
00398             /* Mark it as to know that cleanup is in process */
00399             NotifyChange->Flags |= CLEANUP_IN_PROCESS;
00400 
00401             /* If there are pending IRPs, complete them using the STATUS_NOTIFY_CLEANUP status */
00402             if (!IsListEmpty(&NotifyChange->NotifyIrps))
00403             {
00404                 FsRtlNotifyCompleteIrpList(NotifyChange, STATUS_NOTIFY_CLEANUP);
00405             }
00406 
00407             /* Decrease reference number and if 0 is reached, it's time to do complete cleanup */
00408             if (!InterlockedDecrement((PLONG)&(NotifyChange->ReferenceCount)))
00409             {
00410                 /* Remove it from the notifications list */
00411                 RemoveEntryList(&NotifyChange->NotifyList);
00412 
00413                 /* In case there was an allocated buffer, free it */
00414                 if (NotifyChange->AllocatedBuffer)
00415                 {
00416                     PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
00417                     ExFreePool(NotifyChange->AllocatedBuffer);
00418                 }
00419 
00420                 /* In case there the string was set, get the captured subject security context */
00421                 if (NotifyChange->FullDirectoryName)
00422                 {
00423                     SubjectContext = NotifyChange->SubjectContext;
00424                 }
00425 
00426                 /* Finally, free the notification, as it's not needed anymore */
00427                 ExFreePool(NotifyChange);
00428             }
00429         }
00430     }
00431     _SEH2_FINALLY
00432     {
00433         /* Release fast mutex */
00434         FsRtlNotifyReleaseFastMutex(RealNotifySync);
00435 
00436         /* If the subject security context was captured, release and free it */
00437         if (SubjectContext)
00438         {
00439             SeReleaseSubjectContext(SubjectContext);
00440             ExFreePool(SubjectContext);
00441         }
00442     }
00443     _SEH2_END;
00444 }
00445 
00446 /*++
00447  * @name FsRtlNotifyFilterChangeDirectory
00448  * @unimplemented
00449  *
00450  * FILLME
00451  *
00452  * @param NotifySync
00453  *        FILLME
00454  *
00455  * @param NotifyList
00456  *        FILLME
00457  *
00458  * @param FsContext
00459  *        FILLME
00460  *
00461  * @param FullDirectoryName
00462  *        FILLME
00463  *
00464  * @param WatchTree
00465  *        FILLME
00466  *
00467  * @param IgnoreBuffer
00468  *        FILLME
00469  *
00470  * @param CompletionFilter
00471  *        FILLME
00472  *
00473  * @param NotifyIrp
00474  *        FILLME
00475  *
00476  * @param TraverseCallback
00477  *        FILLME
00478  *
00479  * @param SubjectContext
00480  *        FILLME
00481  *
00482  * @param FilterCallback
00483  *        FILLME
00484  *
00485  * @return None
00486  *
00487  * @remarks None
00488  *
00489  *--*/
00490 VOID
00491 NTAPI
00492 FsRtlNotifyFilterChangeDirectory(IN PNOTIFY_SYNC NotifySync,
00493                                  IN PLIST_ENTRY NotifyList,
00494                                  IN PVOID FsContext,
00495                                  IN PSTRING FullDirectoryName,
00496                                  IN BOOLEAN WatchTree,
00497                                  IN BOOLEAN IgnoreBuffer,
00498                                  IN ULONG CompletionFilter,
00499                                  IN PIRP NotifyIrp,
00500                                  IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL,
00501                                  IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL,
00502                                  IN PFILTER_REPORT_CHANGE FilterCallback OPTIONAL)
00503 {
00504     ULONG SavedLength;
00505     PIO_STACK_LOCATION Stack;
00506     PNOTIFY_CHANGE NotifyChange;
00507     PREAL_NOTIFY_SYNC RealNotifySync;
00508 
00509     PAGED_CODE();
00510 
00511     DPRINT("FsRtlNotifyFilterChangeDirectory(): %p, %p, %p, %wZ, %d, %d, %u, %p, %p, %p, %p\n",
00512     NotifySync, NotifyList, FsContext, FullDirectoryName, WatchTree, IgnoreBuffer, CompletionFilter, NotifyIrp,
00513     TraverseCallback, SubjectContext, FilterCallback);
00514 
00515     /* Get real structure hidden behind the opaque pointer */
00516     RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
00517 
00518     /* Acquire the fast mutex */
00519     FsRtlNotifyAcquireFastMutex(RealNotifySync);
00520 
00521     _SEH2_TRY
00522     {
00523         /* If we have no IRP, FSD is performing a cleanup */
00524         if (!NotifyIrp)
00525         {
00526             /* So, we delete */
00527             FsRtlCheckNotifyForDelete(NotifyList, FsContext);
00528             _SEH2_LEAVE;
00529         }
00530 
00531         NotifyIrp->IoStatus.Status = STATUS_SUCCESS;
00532         NotifyIrp->IoStatus.Information = (ULONG_PTR)NULL;
00533 
00534         Stack = IoGetCurrentIrpStackLocation(NotifyIrp);
00535         /* If FileObject's been cleaned up, just return */
00536         if (Stack->FileObject->Flags & FO_CLEANUP_COMPLETE)
00537         {
00538             IoMarkIrpPending(NotifyIrp);
00539             NotifyIrp->IoStatus.Status = STATUS_NOTIFY_CLEANUP;
00540             IoCompleteRequest(NotifyIrp, EVENT_INCREMENT);
00541             _SEH2_LEAVE;
00542         }
00543 
00544         /* Try to find a matching notification has been already registered */
00545         NotifyChange = FsRtlIsNotifyOnList(NotifyList, FsContext);
00546         if (NotifyChange)
00547         {
00548             /* If it's been found, and is cleaned up, immediatly complete */
00549             if (NotifyChange->Flags & CLEANUP_IN_PROCESS)
00550             {
00551                 IoMarkIrpPending(NotifyIrp);
00552                 NotifyIrp->IoStatus.Status = STATUS_NOTIFY_CLEANUP;
00553                 IoCompleteRequest(NotifyIrp, EVENT_INCREMENT);
00554             }
00555             /* Or if it's about to be deleted, complete */
00556             else if (NotifyChange->Flags & DELETE_IN_PROCESS)
00557             {
00558                 IoMarkIrpPending(NotifyIrp);
00559                 NotifyIrp->IoStatus.Status = STATUS_DELETE_PENDING;
00560                 IoCompleteRequest(NotifyIrp, EVENT_INCREMENT);
00561             }
00562             /* Complete if there is directory enumeration and no buffer available any more */
00563             if ((NotifyChange->Flags & INVALIDATE_BUFFERS) && (NotifyChange->Flags & ENUMERATE_DIR))
00564             {
00565                 NotifyChange->Flags &= ~INVALIDATE_BUFFERS;
00566                 IoMarkIrpPending(NotifyIrp);
00567                 NotifyIrp->IoStatus.Status = STATUS_NOTIFY_ENUM_DIR;
00568                 IoCompleteRequest(NotifyIrp, EVENT_INCREMENT);
00569             }
00570             /* If no data yet, or directory enumeration, handle */
00571             else if (NotifyChange->DataLength == 0 || (NotifyChange->Flags & ENUMERATE_DIR))
00572             {
00573                 goto HandleIRP;
00574             }
00575             /* Else, just complete with we have */
00576             else
00577             {
00578                 SavedLength = NotifyChange->DataLength;
00579                 NotifyChange->DataLength = 0;
00580                 FsRtlNotifyCompleteIrp(NotifyIrp, NotifyChange, SavedLength, STATUS_SUCCESS, FALSE);
00581             }
00582 
00583             _SEH2_LEAVE;
00584         }
00585 
00586         /* Allocate new notification */
00587         NotifyChange = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
00588                                              sizeof(NOTIFY_CHANGE), 'FSrN');
00589         RtlZeroMemory(NotifyChange, sizeof(NOTIFY_CHANGE));
00590 
00591         /* Set basic information */
00592         NotifyChange->NotifySync = NotifySync;
00593         NotifyChange->FsContext = FsContext;
00594         NotifyChange->StreamID = Stack->FileObject->FsContext;
00595         NotifyChange->TraverseCallback = TraverseCallback;
00596         NotifyChange->SubjectContext = SubjectContext;
00597         NotifyChange->FullDirectoryName = FullDirectoryName;
00598         NotifyChange->FilterCallback = FilterCallback;
00599         InitializeListHead(&(NotifyChange->NotifyIrps));
00600 
00601         /* Keep trace of WatchTree */
00602         if (WatchTree)
00603         {
00604             NotifyChange->Flags |= WATCH_TREE;
00605         }
00606 
00607         /* If string is empty, faulty to ANSI */
00608         if (FullDirectoryName->Length == 0)
00609         {
00610             NotifyChange->CharacterSize = sizeof(CHAR);
00611         }
00612         else
00613         {
00614             /* If it can't contain WCHAR, it's ANSI */
00615             if (FullDirectoryName->Length < sizeof(WCHAR))
00616             {
00617                 NotifyChange->CharacterSize = sizeof(CHAR);
00618             }
00619             /* First char is \, so in unicode, right part is 0
00620              * whereas in ANSI it contains next char
00621              */
00622             else if (((CHAR*)FullDirectoryName->Buffer)[1] == 0)
00623             {
00624                 NotifyChange->CharacterSize = sizeof(WCHAR);
00625             }
00626             else
00627             {
00628                 NotifyChange->CharacterSize = sizeof(CHAR);
00629             }
00630 
00631             /* Now, check is user is willing to watch root */
00632             if (FullDirectoryName->Length == NotifyChange->CharacterSize)
00633             {
00634                 NotifyChange->Flags |= WATCH_ROOT;
00635             }
00636         }
00637 
00638         NotifyChange->CompletionFilter = CompletionFilter;
00639 
00640         /* In case we have not to ignore buffer , keep its length */
00641         if (!IgnoreBuffer)
00642         {
00643             NotifyChange->BufferLength = Stack->Parameters.NotifyDirectory.Length;
00644         }
00645 
00646         NotifyChange->OwningProcess = NotifyIrp->Tail.Overlay.Thread->ThreadsProcess;
00647 
00648         /* Insert the notification into the notification list */
00649         InsertTailList(NotifyList, &(NotifyChange->NotifyList));
00650 
00651         NotifyChange->ReferenceCount = 1;
00652 
00653 HandleIRP:
00654         /* Associate the notification to the IRP */
00655         NotifyIrp->IoStatus.Information = (ULONG_PTR)NotifyChange;
00656         /* The IRP is pending */
00657         IoMarkIrpPending(NotifyIrp);
00658         /* Insert the IRP in the IRP list */
00659         InsertTailList(&(NotifyChange->NotifyIrps), &(NotifyIrp->Tail.Overlay.ListEntry));
00660         /* Increment reference count */
00661         InterlockedIncrement((PLONG)&(NotifyChange->ReferenceCount));
00662         /* Set cancel routine to FsRtl one */
00663         FsRtlNotifySetCancelRoutine(NotifyIrp, NULL);
00664     }
00665     _SEH2_FINALLY
00666     {
00667         /* Release fast mutex */
00668         FsRtlNotifyReleaseFastMutex(RealNotifySync);
00669 
00670         /* If the subject security context was captured and there's no notify */
00671         if (SubjectContext && (!NotifyChange || FullDirectoryName))
00672         {
00673             SeReleaseSubjectContext(SubjectContext);
00674             ExFreePool(SubjectContext);
00675         }
00676     }
00677     _SEH2_END;
00678 }
00679 
00680 /*++
00681  * @name FsRtlNotifyFilterReportChange
00682  * @unimplemented
00683  *
00684  * FILLME
00685  *
00686  * @param NotifySync
00687  *        FILLME
00688  *
00689  * @param NotifyList
00690  *        FILLME
00691  *
00692  * @param FullTargetName
00693  *        FILLME
00694  *
00695  * @param TargetNameOffset
00696  *        FILLME
00697  *
00698  * @param StreamName
00699  *        FILLME
00700  *
00701  * @param NormalizedParentName
00702  *        FILLME
00703  *
00704  * @param FilterMatch
00705  *        FILLME
00706  *
00707  * @param Action
00708  *        FILLME
00709  *
00710  * @param TargetContext
00711  *        FILLME
00712  *
00713  * @param FilterContext
00714  *        FILLME
00715  *
00716  * @return None
00717  *
00718  * @remarks None
00719  *
00720  *--*/
00721 VOID
00722 NTAPI
00723 FsRtlNotifyFilterReportChange(IN PNOTIFY_SYNC NotifySync,
00724                               IN PLIST_ENTRY NotifyList,
00725                               IN PSTRING FullTargetName,
00726                               IN USHORT TargetNameOffset,
00727                               IN PSTRING StreamName OPTIONAL,
00728                               IN PSTRING NormalizedParentName OPTIONAL,
00729                               IN ULONG FilterMatch,
00730                               IN ULONG Action,
00731                               IN PVOID TargetContext,
00732                               IN PVOID FilterContext)
00733 {
00734     KeBugCheck(FILE_SYSTEM);
00735 }
00736 
00737 /*++
00738  * @name FsRtlNotifyFullChangeDirectory
00739  * @implemented
00740  *
00741  * Lets FSD know if changes occures in the specified directory. 
00742  *
00743  * @param NotifySync
00744  *        Synchronization object pointer
00745  *
00746  * @param NotifyList
00747  *        Notify list pointer (to head) 
00748  *
00749  * @param FsContext
00750  *        Used to identify the notify structure
00751  *
00752  * @param FullDirectoryName
00753  *        String (A or W) containing the full directory name 
00754  *
00755  * @param WatchTree
00756  *        True to notify changes in subdirectories too
00757  *
00758  * @param IgnoreBuffer
00759  *        True to reenumerate directory. It's ignored it NotifyIrp is null
00760  *
00761  * @param CompletionFilter
00762  *        Used to define types of changes to notify
00763  *
00764  * @param NotifyIrp
00765  *        IRP pointer to complete notify operation. It can be null
00766  *
00767  * @param TraverseCallback
00768  *        Pointer to a callback function. It's called each time a change is
00769  *        done in a subdirectory of the main directory. It's ignored it NotifyIrp
00770  *        is null
00771  *
00772  * @param SubjectContext
00773  *        Pointer to pass to SubjectContext member of TraverseCallback.
00774  *        It's freed after use. It's ignored it NotifyIrp is null
00775  *
00776  * @return None
00777  *
00778  * @remarks This function only redirects to FsRtlNotifyFilterChangeDirectory.
00779  *
00780  *--*/
00781 VOID
00782 NTAPI
00783 FsRtlNotifyFullChangeDirectory(IN PNOTIFY_SYNC NotifySync,
00784                                IN PLIST_ENTRY NotifyList,
00785                                IN PVOID FsContext,
00786                                IN PSTRING FullDirectoryName,
00787                                IN BOOLEAN WatchTree,
00788                                IN BOOLEAN IgnoreBuffer,
00789                                IN ULONG CompletionFilter,
00790                                IN PIRP NotifyIrp,
00791                                IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL,
00792                                IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL)
00793 {
00794     FsRtlNotifyFilterChangeDirectory(NotifySync,
00795                                      NotifyList,
00796                                      FsContext,
00797                                      FullDirectoryName,
00798                                      WatchTree,
00799                                      IgnoreBuffer,
00800                                      CompletionFilter,
00801                                      NotifyIrp,
00802                                      TraverseCallback,
00803                                      SubjectContext,
00804                                      NULL);
00805 }
00806 
00807 /*++
00808  * @name FsRtlNotifyFullReportChange
00809  * @implemented
00810  *
00811  * Complets the pending notify IRPs.
00812  *
00813  * @param NotifySync
00814  *        Synchronization object pointer
00815  *
00816  * @param NotifyList
00817  *        Notify list pointer (to head) 
00818  *
00819  * @param FullTargetName
00820  *        String (A or W) containing the full directory name that changed
00821  *
00822  * @param TargetNameOffset
00823  *        Offset, in FullTargetName, of the final component that is in the changed directory 
00824  *
00825  * @param StreamName
00826  *        String (A or W) containing a stream name
00827  *
00828  * @param NormalizedParentName
00829  *        String (A or W) containing the full directory name that changed with long names
00830  *
00831  * @param FilterMatch
00832  *        Flags that will be compared to the completion filter
00833  *
00834  * @param Action
00835  *        Action code to store in user's buffer
00836  *
00837  * @param TargetContext
00838  *        Pointer to a callback function. It's called each time a change is
00839  *        done in a subdirectory of the main directory.
00840  *
00841  * @return None
00842  *
00843  * @remarks This function only redirects to FsRtlNotifyFilterReportChange.
00844  *
00845  *--*/
00846 VOID
00847 NTAPI
00848 FsRtlNotifyFullReportChange(IN PNOTIFY_SYNC NotifySync,
00849                             IN PLIST_ENTRY NotifyList,
00850                             IN PSTRING FullTargetName,
00851                             IN USHORT TargetNameOffset,
00852                             IN PSTRING StreamName OPTIONAL,
00853                             IN PSTRING NormalizedParentName OPTIONAL,
00854                             IN ULONG FilterMatch,
00855                             IN ULONG Action,
00856                             IN PVOID TargetContext)
00857 {
00858     FsRtlNotifyFilterReportChange(NotifySync,
00859                                   NotifyList,
00860                                   FullTargetName,
00861                                   TargetNameOffset,
00862                                   StreamName,
00863                                   NormalizedParentName,
00864                                   FilterMatch,
00865                                   Action,
00866                                   TargetContext,
00867                                   NULL);
00868 }
00869 
00870 /*++
00871  * @name FsRtlNotifyInitializeSync
00872  * @implemented
00873  *
00874  * Allocates the internal structure associated with notifications.
00875  *
00876  * @param NotifySync
00877  *        Opaque pointer. It will receive the address of the allocated internal structure.
00878  *
00879  * @return None
00880  *
00881  * @remarks This function raise an exception in case of a failure.
00882  *
00883  *--*/
00884 VOID
00885 NTAPI
00886 FsRtlNotifyInitializeSync(IN PNOTIFY_SYNC *NotifySync)
00887 {
00888     PREAL_NOTIFY_SYNC RealNotifySync;
00889 
00890     *NotifySync = NULL;
00891     
00892     RealNotifySync = ExAllocatePoolWithTag(NonPagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
00893                                            sizeof(REAL_NOTIFY_SYNC), 'FSNS');
00894     ExInitializeFastMutex(&(RealNotifySync->FastMutex));
00895     RealNotifySync->OwningThread = 0;
00896     RealNotifySync->OwnerCount = 0;
00897 
00898     *NotifySync = RealNotifySync;
00899 }
00900 
00901 /*++
00902  * @name FsRtlNotifyReportChange
00903  * @implemented
00904  *
00905  * Complets the pending notify IRPs.
00906  *
00907  * @param NotifySync
00908  *        Synchronization object pointer
00909  *
00910  * @param NotifyList
00911  *        Notify list pointer (to head) 
00912  *
00913  * @param FullTargetName
00914  *        String (A or W) containing the full directory name that changed
00915  *
00916  * @param FileNamePartLength
00917  *        Length of the final component that is in the changed directory
00918  *
00919  * @param FilterMatch
00920  *        Flags that will be compared to the completion filter
00921  *
00922  * @return None
00923  *
00924  * @remarks This function only redirects to FsRtlNotifyFilterReportChange.
00925  *
00926  *--*/
00927 VOID
00928 NTAPI
00929 FsRtlNotifyReportChange(IN PNOTIFY_SYNC NotifySync,
00930                         IN PLIST_ENTRY NotifyList,
00931                         IN PSTRING FullTargetName,
00932                         IN PUSHORT FileNamePartLength,
00933                         IN ULONG FilterMatch)
00934 {
00935       FsRtlNotifyFilterReportChange(NotifySync,
00936                                     NotifyList,
00937                                     FullTargetName,
00938                                     FullTargetName->Length - *FileNamePartLength,
00939                                     NULL,
00940                                     NULL,
00941                                     FilterMatch,
00942                                     0,
00943                                     NULL,
00944                                     NULL); 
00945 }
00946 
00947 /*++
00948  * @name FsRtlNotifyUninitializeSync
00949  * @implemented
00950  *
00951  * Uninitialize a NOTIFY_SYNC object
00952  *
00953  * @param NotifySync
00954  *        Address of a pointer to a PNOTIFY_SYNC object previously
00955  *        initialized by FsRtlNotifyInitializeSync()
00956  *
00957  * @return None
00958  *
00959  * @remarks None
00960  *
00961  *--*/
00962 VOID
00963 NTAPI
00964 FsRtlNotifyUninitializeSync(IN PNOTIFY_SYNC *NotifySync)
00965 {
00966     if (*NotifySync)
00967     {
00968         ExFreePoolWithTag(*NotifySync, 'FSNS');
00969         *NotifySync = NULL;
00970     }
00971 }
00972 

Generated on Sat May 26 2012 04:20:16 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.