a6c1ec50ac26549df89d163db143fd04c71f95bf
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCleanup.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSCleanup.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSCleanup
43 //
44 // Description:
45 //
46 //      This function is the IRP_MJ_CLEANUP dispatch handler
47 //
48 // Return:
49 //
50 //       A status is returned for the handling of this request
51 //
52
53 NTSTATUS
54 AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
55             IN PIRP Irp)
56 {
57     UNREFERENCED_PARAMETER(LibDeviceObject);
58     NTSTATUS ntStatus = STATUS_SUCCESS;
59     AFSDeviceExt *pDeviceExt = NULL;
60     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
61     AFSFcb *pFcb = NULL;
62     AFSCcb *pCcb = NULL;
63     PFILE_OBJECT pFileObject = NULL;
64     AFSFcb *pRootFcb = NULL;
65     AFSDeviceExt *pControlDeviceExt = NULL;
66     IO_STATUS_BLOCK stIoSB;
67     AFSObjectInfoCB *pObjectInfo = NULL;
68     AFSObjectInfoCB *pParentObjectInfo = NULL;
69     AFSFileCleanupCB stFileCleanup;
70     AFSFileCleanupResultCB *pResultCB = NULL;
71     ULONG ulResultLen = 0;
72     ULONG   ulNotificationFlags = 0;
73     LONG    lCount;
74
75     __try
76     {
77
78         if( AFSRDRDeviceObject == NULL)
79         {
80
81             //
82             // Let this through, it's a cleanup on the library control device
83             //
84
85             try_return( ntStatus);
86         }
87
88         pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
89
90         pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
91
92         //
93         // Set some initial variables to make processing easier
94         //
95
96         pFileObject = pIrpSp->FileObject;
97
98         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
99
100         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
101
102         if( pFcb == NULL)
103         {
104             try_return( ntStatus);
105         }
106
107         pObjectInfo = pFcb->ObjectInformation;
108
109         pRootFcb = pObjectInfo->VolumeCB->RootFcb;
110
111         RtlZeroMemory( &stFileCleanup,
112                        sizeof( AFSFileCleanupCB));
113
114         stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
115
116         stFileCleanup.Identifier = (ULONGLONG)pFileObject;
117
118         //
119         // Allocate our return buffer
120         //
121
122         pResultCB = (AFSFileCleanupResultCB *)AFSExAllocatePoolWithTag( PagedPool,
123                                                                         PAGE_SIZE,
124                                                                         AFS_GENERIC_MEMORY_32_TAG);
125
126         if( pResultCB == NULL)
127         {
128
129             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
130         }
131
132         RtlZeroMemory( pResultCB,
133                        PAGE_SIZE);
134
135         ulResultLen = PAGE_SIZE;
136
137
138         //
139         // Perform the cleanup functionality depending on the type of node it is
140         //
141
142         switch( pFcb->Header.NodeTypeCode)
143         {
144
145             case AFS_ROOT_ALL:
146             {
147
148                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
149                               AFS_TRACE_LEVEL_VERBOSE,
150                               "AFSCleanup Acquiring GlobalRoot lock %p EXCL %08lX\n",
151                               &pFcb->NPFcb->Resource,
152                               PsGetCurrentThread());
153
154                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
155                                   TRUE);
156
157                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
158                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
159                                     pCcb);
160
161                 ASSERT( pFcb->OpenHandleCount != 0);
162
163                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
164
165                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
166                               AFS_TRACE_LEVEL_VERBOSE,
167                               "AFSCleanup (RootAll) Decrement handle count on Fcb %p Cnt %d\n",
168                               pFcb,
169                               lCount);
170
171                 AFSReleaseResource( &pFcb->NPFcb->Resource);
172
173                 break;
174             }
175
176             case AFS_IOCTL_FCB:
177             {
178
179                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
180                               AFS_TRACE_LEVEL_VERBOSE,
181                               "AFSCleanup Acquiring PIOCtl lock %p EXCL %08lX\n",
182                               &pFcb->NPFcb->Resource,
183                               PsGetCurrentThread());
184
185                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
186                                   TRUE);
187
188                 ASSERT( pFcb->OpenHandleCount != 0);
189
190                 //
191                 // Decrement the open child handle count
192                 //
193
194                 if( pObjectInfo->ParentObjectInformation != NULL &&
195                     pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
196                 {
197
198                     lCount = InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
199
200                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
201                                   AFS_TRACE_LEVEL_VERBOSE,
202                                   "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %p Cnt %d\n",
203                                   pObjectInfo->ParentObjectInformation,
204                                   lCount);
205                 }
206
207                 AFSReleaseResource( &pFcb->NPFcb->Resource);
208
209                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
210
211                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
212                               AFS_TRACE_LEVEL_VERBOSE,
213                               "AFSCleanup (IOCtl) Decrement handle count on Fcb %p Cnt %d\n",
214                               pFcb,
215                               lCount);
216
217                 break;
218             }
219
220             //
221             // This Fcb represents a file
222             //
223
224             case AFS_FILE_FCB:
225             {
226
227                 //
228                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
229                 //
230
231                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
232                               AFS_TRACE_LEVEL_VERBOSE,
233                               "AFSCleanup Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
234                               &pFcb->NPFcb->SectionObjectResource,
235                               PsGetCurrentThread());
236
237                 AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
238                                 TRUE);
239
240                 //
241                 // If the handle has write permission ...
242                 //
243
244                 if( ((pCcb->GrantedAccess & FILE_WRITE_DATA) || pFcb->OpenHandleCount == 1) &&
245                     CcIsFileCached( pIrpSp->FileObject))
246                 {
247
248                     __try
249                     {
250
251                         CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
252                                       NULL,
253                                       0,
254                                       &stIoSB);
255
256                         if( !NT_SUCCESS( stIoSB.Status))
257                         {
258
259                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
260                                           AFS_TRACE_LEVEL_ERROR,
261                                           "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
262                                           &pCcb->FullFileName,
263                                           pObjectInfo->FileId.Cell,
264                                           pObjectInfo->FileId.Volume,
265                                           pObjectInfo->FileId.Vnode,
266                                           pObjectInfo->FileId.Unique,
267                                           stIoSB.Status,
268                                           stIoSB.Information);
269
270                             ntStatus = stIoSB.Status;
271                         }
272
273                         if ( ( pFcb->OpenHandleCount == 1 ||
274                                BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE)) &&
275                              pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
276                         {
277
278                             if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
279                                                        NULL,
280                                                        0,
281                                                        FALSE))
282                             {
283
284                                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
285                                               AFS_TRACE_LEVEL_WARNING,
286                                               "AFSCleanup CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
287                                               pObjectInfo->FileId.Cell,
288                                               pObjectInfo->FileId.Volume,
289                                               pObjectInfo->FileId.Vnode,
290                                               pObjectInfo->FileId.Unique);
291
292                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
293                             }
294                             else
295                             {
296                                 ClearFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
297                             }
298                         }
299                     }
300                     __except( EXCEPTION_EXECUTE_HANDLER)
301                     {
302
303                         ntStatus = GetExceptionCode();
304
305                         AFSDbgLogMsg( 0,
306                                       0,
307                                       "EXCEPTION - AFSCleanup Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
308                                       pObjectInfo->FileId.Cell,
309                                       pObjectInfo->FileId.Volume,
310                                       pObjectInfo->FileId.Vnode,
311                                       pObjectInfo->FileId.Unique,
312                                       ntStatus);
313
314                         SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
315                     }
316                 }
317
318                 //
319                 // Uninitialize the cache map. This call is unconditional.
320                 //
321
322                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
323                               AFS_TRACE_LEVEL_VERBOSE,
324                               "AFSCleanup Tearing down cache map for Fcb %p FileObject %p\n",
325                               pFcb,
326                               pFileObject);
327
328                 CcUninitializeCacheMap( pFileObject,
329                                         NULL,
330                                         NULL);
331
332
333                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
334                               AFS_TRACE_LEVEL_VERBOSE,
335                               "AFSCleanup Releasing Fcb SectionObject lock %p EXCL %08lX\n",
336                               &pFcb->NPFcb->SectionObjectResource,
337                               PsGetCurrentThread());
338
339                 AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
340
341                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
342                               AFS_TRACE_LEVEL_VERBOSE,
343                               "AFSCleanup Acquiring Fcb lock %p EXCL %08lX\n",
344                               &pFcb->NPFcb->Resource,
345                               PsGetCurrentThread());
346
347                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
348                                 TRUE);
349
350                 //
351                 // Unlock all outstanding locks on the file, again, unconditionally
352                 //
353
354                 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
355                                            pFileObject,
356                                            IoGetRequestorProcess( Irp),
357                                            NULL);
358
359                 //
360                 // Tell the service to unlock all on the file
361                 //
362
363                 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
364
365                 //
366                 // Perform some final common processing
367                 //
368
369                 ASSERT( pFcb->OpenHandleCount != 0);
370
371                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
372                 {
373
374                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
375                 }
376
377                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
378
379                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
380                 {
381
382                     stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
383
384                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
385
386                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
387                     {
388
389                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
390
391                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
392                     }
393
394                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
395                     {
396
397                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
398
399                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
400                     }
401
402                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
403                     {
404
405                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
406
407                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
408                     }
409
410                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
411                     {
412
413                         stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
414
415                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
416                     }
417                 }
418
419                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
420                 {
421
422                     stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
423                 }
424
425                 //
426                 // If the count has dropped to one and there is a pending delete
427                 // then delete the node.  The final count will be decremented just
428                 // before the Fcb->NPFcb->Resource is released.
429                 //
430
431                 if( pFcb->OpenHandleCount == 1 &&
432                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
433                 {
434
435                     ntStatus = STATUS_SUCCESS;
436
437                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
438
439                     //
440                     // Indicate the file access mode that is being released
441                     //
442
443                     stFileCleanup.FileAccess = pCcb->FileAccess;
444
445                     //
446                     // Push the request to the service
447                     //
448
449                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
450                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
451                                                   &pCcb->AuthGroup,
452                                                   &pCcb->DirectoryCB->NameInformation.FileName,
453                                                   &pObjectInfo->FileId,
454                                                   &stFileCleanup,
455                                                   sizeof( AFSFileCleanupCB),
456                                                   pResultCB,
457                                                   &ulResultLen);
458
459                     if( !NT_SUCCESS( ntStatus) &&
460                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
461                     {
462
463                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
464                                       AFS_TRACE_LEVEL_ERROR,
465                                       "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
466                                       &pCcb->FullFileName,
467                                       ntStatus);
468
469                         ntStatus = STATUS_SUCCESS;
470
471                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
472                     }
473                     else
474                     {
475
476                         ntStatus = STATUS_SUCCESS;
477
478                         if ( --pObjectInfo->Links < 1)
479                         {
480
481                             //
482                             // Stop anything possibly in process
483                             //
484
485                             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
486                                           AFS_TRACE_LEVEL_VERBOSE,
487                                           "AFSCleanup Acquiring Fcb extents lock %p EXCL %08lX\n",
488                                           &pFcb->NPFcb->Specific.File.ExtentsResource,
489                                           PsGetCurrentThread());
490
491                             AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
492                                             TRUE);
493
494                             pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
495
496                             KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
497                                         0,
498                                         FALSE);
499
500                             //
501                             // The file has been deleted since the Link count is zero
502                             //
503
504                             AFSDeleteFcbExtents( pFcb);
505
506                             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
507                                           AFS_TRACE_LEVEL_VERBOSE,
508                                           "AFSCleanup Releasing Fcb extents lock %p EXCL %08lX\n",
509                                           &pFcb->NPFcb->Specific.File.ExtentsResource,
510                                           PsGetCurrentThread());
511
512                             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
513                         }
514
515                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
516                                       AFS_TRACE_LEVEL_VERBOSE,
517                                       "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
518                                       &pCcb->FullFileName,
519                                       pCcb->DirectoryCB);
520
521                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
522
523                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
524
525                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
526
527                         ASSERT( pParentObjectInfo != NULL);
528
529                         AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
530                                         TRUE);
531
532                         if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
533                         {
534
535                             SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
536
537                             pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
538                         }
539                         else
540                         {
541
542                             pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
543                         }
544
545                         //
546                         // Now that the service has the entry has deleted we need to remove it from the parent
547                         // tree so another lookup on the node will fail
548                         //
549
550                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
551                         {
552
553                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
554                                           AFS_TRACE_LEVEL_VERBOSE,
555                                           "AFSCleanup DE %p for %wZ removing entry\n",
556                                           pCcb->DirectoryCB,
557                                           &pCcb->DirectoryCB->NameInformation.FileName);
558
559                             AFSRemoveNameEntry( pParentObjectInfo,
560                                                 pCcb->DirectoryCB);
561                         }
562                         else
563                         {
564
565                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
566                                           AFS_TRACE_LEVEL_VERBOSE,
567                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
568                                           pCcb->DirectoryCB,
569                                           &pCcb->DirectoryCB->NameInformation.FileName);
570                         }
571
572                         AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
573
574                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
575                                                         pCcb,
576                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
577                                                         (ULONG)FILE_ACTION_REMOVED);
578
579                     }
580                 }
581                 else
582                 {
583
584                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
585                     {
586
587                         ULONG ulNotifyFilter = 0;
588
589                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
590
591                         ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
592
593                         AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
594                                                         pCcb,
595                                                         (ULONG)ulNotifyFilter,
596                                                         (ULONG)FILE_ACTION_MODIFIED);
597                     }
598
599
600                     //
601                     // Whenever a handle with write access or the last handle is closed
602                     // notify the service to FSync the file.  If the redirector is holding
603                     // dirty extents, flush them to the service.  This is a bit aggressive
604                     // but it ensures cache coherency.
605                     //
606
607                     if( (pCcb->GrantedAccess & FILE_WRITE_DATA) || (pFcb->OpenHandleCount == 1))
608                     {
609
610                         if ( pFcb->Specific.File.ExtentsDirtyCount != 0)
611                         {
612
613                             AFSFlushExtents( pFcb,
614                                              &pCcb->AuthGroup);
615                         }
616
617                         ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
618                     }
619
620                     if( pFcb->OpenHandleCount == 1)
621                     {
622
623                         //
624                         // Wait for any outstanding queued flushes to complete
625                         //
626
627                         AFSWaitOnQueuedFlushes( pFcb);
628
629                         AFSTearDownFcbExtents( pFcb,
630                                                &pCcb->AuthGroup);
631                     }
632
633                     //
634                     // Indicate the file access mode that is being released
635                     //
636
637                     stFileCleanup.FileAccess = pCcb->FileAccess;
638
639                     //
640                     // Remove the share access at this time since we may not get the close for sometime on this FO.
641                     //
642
643                     IoRemoveShareAccess( pFileObject,
644                                          &pFcb->ShareAccess);
645
646
647                     //
648                     // We don't need the name array after the user closes the handle on the file
649                     //
650
651                     if( pCcb->NameArray != NULL)
652                     {
653
654                         AFSFreeNameArray( pCcb->NameArray);
655
656                         pCcb->NameArray = NULL;
657                     }
658
659                     //
660                     // Release the Fcb Resource across the call to the service
661                     // which may block for quite a while if flushing of the
662                     // data is required.
663                     //
664
665                     AFSReleaseResource( &pFcb->NPFcb->Resource);
666
667                     //
668                     // Push the request to the service
669                     //
670
671                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
672                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
673                                                   &pCcb->AuthGroup,
674                                                   &pCcb->DirectoryCB->NameInformation.FileName,
675                                                   &pObjectInfo->FileId,
676                                                   &stFileCleanup,
677                                                   sizeof( AFSFileCleanupCB),
678                                                   pResultCB,
679                                                   &ulResultLen);
680
681                     //
682                     // Regain exclusive access to the Fcb
683                     //
684
685                     AFSAcquireExcl( &pFcb->NPFcb->Resource,
686                                     TRUE);
687
688                     if ( NT_SUCCESS( ntStatus))
689                     {
690
691                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
692
693                         if ( pParentObjectInfo != NULL)
694                         {
695
696                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
697                                             TRUE);
698
699                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
700                             {
701
702                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
703
704                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
705                             }
706
707                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
708                         }
709                     }
710
711                     ntStatus = STATUS_SUCCESS;
712                 }
713
714                 //
715                 // Decrement the open child handle count
716                 //
717
718                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
719
720                 if( pParentObjectInfo != NULL)
721                 {
722
723                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
724
725                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
726
727                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
728                                   AFS_TRACE_LEVEL_VERBOSE,
729                                   "AFSCleanup (File) Decrement child open handle count on Parent object %p Cnt %d\n",
730                                   pParentObjectInfo,
731                                   lCount);
732                 }
733
734
735                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
736
737                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
738                               AFS_TRACE_LEVEL_VERBOSE,
739                               "AFSCleanup (File) Decrement handle count on Fcb %p Cnt %d\n",
740                               pFcb,
741                               lCount);
742
743                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
744                 {
745                     //
746                     // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
747                     //
748
749                     lCount = AFSObjectInfoIncrement( pObjectInfo,
750                                                      AFS_OBJECT_REFERENCE_INVALIDATION);
751
752                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
753                                   AFS_TRACE_LEVEL_VERBOSE,
754                                   "AFSCleanup Setting Purge on Close Increment count on object %p Cnt %d\n",
755                                   pObjectInfo,
756                                   lCount);
757
758                     ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
759
760                     AFSReleaseResource( &pFcb->NPFcb->Resource);
761
762                     AFSPerformObjectInvalidate( pObjectInfo,
763                                                 AFS_INVALIDATE_DATA_VERSION);
764                 }
765                 else
766                 {
767
768                     AFSReleaseResource( &pFcb->NPFcb->Resource);
769                 }
770
771                 break;
772             }
773
774             //
775             // Root or directory node
776             //
777
778             case AFS_ROOT_FCB:
779             {
780
781                 //
782                 // Set the root Fcb to this node
783                 //
784
785                 pRootFcb = pFcb;
786
787                 //
788                 // Fall through to below
789                 //
790             }
791
792             case AFS_DIRECTORY_FCB:
793             {
794
795                 //
796                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
797                 //
798
799                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
800                               AFS_TRACE_LEVEL_VERBOSE,
801                               "AFSCleanup Acquiring Dcb lock %p EXCL %08lX\n",
802                               &pFcb->NPFcb->Resource,
803                               PsGetCurrentThread());
804
805                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
806                                   TRUE);
807
808                 //
809                 // Perform some final common processing
810                 //
811
812                 ASSERT( pFcb->OpenHandleCount != 0);
813
814                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
815                 {
816
817                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
818                 }
819
820                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
821
822                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
823                 {
824
825                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
826
827                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
828                     {
829
830                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
831
832                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
833                     }
834
835                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
836                     {
837
838                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
839
840                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
841                     }
842
843                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
844                     {
845
846                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
847
848                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
849                     }
850                 }
851
852                 //
853                 // If the count has dropped to one and there is a pending delete
854                 // then delete the node.  The final count will be decremented just
855                 // before the Fcb->NPFcb->Resource is released.
856                 //
857
858                 if( pFcb->OpenHandleCount == 1 &&
859                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
860                 {
861
862                     //
863                     // Try to notify the service about the delete
864                     //
865
866                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
867
868                     //
869                     // Indicate the file access mode that is being released
870                     //
871
872                     stFileCleanup.FileAccess = pCcb->FileAccess;
873
874                     //
875                     // Push the request to the service
876                     //
877
878                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
879                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
880                                                   &pCcb->AuthGroup,
881                                                   &pCcb->DirectoryCB->NameInformation.FileName,
882                                                   &pObjectInfo->FileId,
883                                                   &stFileCleanup,
884                                                   sizeof( AFSFileCleanupCB),
885                                                   pResultCB,
886                                                   &ulResultLen);
887
888                     if( !NT_SUCCESS( ntStatus) &&
889                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
890                     {
891
892                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
893                                       AFS_TRACE_LEVEL_ERROR,
894                                       "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
895                                       &pCcb->FullFileName,
896                                       ntStatus);
897
898                         ntStatus = STATUS_SUCCESS;
899
900                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
901                     }
902                     else
903                     {
904
905                         ntStatus = STATUS_SUCCESS;
906
907                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
908                                       AFS_TRACE_LEVEL_VERBOSE,
909                                       "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
910                                       &pCcb->FullFileName,
911                                       pCcb->DirectoryCB);
912
913                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
914
915                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
916
917                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
918
919                         ASSERT( pParentObjectInfo != NULL);
920
921                         AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
922                                         TRUE);
923
924                         if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
925                         {
926
927                             SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
928
929                             pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
930                         }
931                         else
932                         {
933
934                             pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
935                         }
936
937                         //
938                         // Now that the service has the entry has deleted we need to remove it from the parent
939                         // tree so another lookup on the node will fail
940                         //
941
942                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
943                         {
944
945                             AFSRemoveNameEntry( pParentObjectInfo,
946                                                 pCcb->DirectoryCB);
947                         }
948                         else
949                         {
950
951                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
952                                           AFS_TRACE_LEVEL_VERBOSE,
953                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
954                                           pCcb->DirectoryCB,
955                                           &pCcb->DirectoryCB->NameInformation.FileName);
956                         }
957
958                         AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
959
960                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
961                                                         pCcb,
962                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
963                                                         (ULONG)FILE_ACTION_REMOVED);
964
965                     }
966                 }
967
968                 //
969                 // If there have been any updates to the node then push it to
970                 // the service
971                 //
972
973                 else
974                 {
975
976                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
977                     {
978
979                         ULONG ulNotifyFilter = 0;
980
981                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
982
983                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
984
985                         if(  pParentObjectInfo != NULL)
986                         {
987
988                             ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
989
990                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
991                                                             pCcb,
992                                                             (ULONG)ulNotifyFilter,
993                                                             (ULONG)FILE_ACTION_MODIFIED);
994                         }
995                     }
996
997                     //
998                     // Indicate the file access mode that is being released
999                     //
1000
1001                     stFileCleanup.FileAccess = pCcb->FileAccess;
1002
1003                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1004                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1005                                                   &pCcb->AuthGroup,
1006                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1007                                                   &pObjectInfo->FileId,
1008                                                   &stFileCleanup,
1009                                                   sizeof( AFSFileCleanupCB),
1010                                                   pResultCB,
1011                                                   &ulResultLen);
1012
1013                     if ( NT_SUCCESS( ntStatus))
1014                     {
1015
1016                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1017
1018                         if ( pParentObjectInfo != NULL)
1019                         {
1020
1021                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1022                                               TRUE);
1023
1024                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1025                             {
1026
1027                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1028
1029                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1030                             }
1031
1032                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1033                         }
1034                     }
1035
1036                     ntStatus = STATUS_SUCCESS;
1037                 }
1038
1039                 //
1040                 // Release the notification for this directory if there is one
1041                 //
1042
1043                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
1044                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
1045                                     pCcb);
1046
1047                 //
1048                 // Remove the share access at this time since we may not get the close for sometime on this FO.
1049                 //
1050
1051                 IoRemoveShareAccess( pFileObject,
1052                                      &pFcb->ShareAccess);
1053
1054                 //
1055                 // We don't need the name array after the user closes the handle on the file
1056                 //
1057
1058                 if( pCcb->NameArray != NULL)
1059                 {
1060
1061                     AFSFreeNameArray( pCcb->NameArray);
1062
1063                     pCcb->NameArray = NULL;
1064                 }
1065
1066                 //
1067                 // Decrement the open child handle count
1068                 //
1069
1070                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1071
1072                 if( pParentObjectInfo != NULL)
1073                 {
1074
1075                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1076
1077                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1078
1079                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1080                                   AFS_TRACE_LEVEL_VERBOSE,
1081                                   "AFSCleanup (Dir) Decrement child open handle count on Parent object %p Cnt %d\n",
1082                                   pParentObjectInfo,
1083                                   lCount);
1084                 }
1085
1086                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1087
1088                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1089                               AFS_TRACE_LEVEL_VERBOSE,
1090                               "AFSCleanup (Dir) Decrement handle count on Fcb %p Cnt %d\n",
1091                               pFcb,
1092                               lCount);
1093
1094                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1095
1096                 break;
1097             }
1098
1099             case AFS_SYMBOLIC_LINK_FCB:
1100             case AFS_MOUNT_POINT_FCB:
1101             case AFS_DFS_LINK_FCB:
1102             case AFS_INVALID_FCB:
1103             {
1104
1105                 //
1106                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
1107                 //
1108
1109                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1110                               AFS_TRACE_LEVEL_VERBOSE,
1111                               "AFSCleanup (MP/SL) Acquiring Dcb lock %p EXCL %08lX\n",
1112                               &pFcb->NPFcb->Resource,
1113                               PsGetCurrentThread());
1114
1115                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1116                                   TRUE);
1117
1118                 //
1119                 // Perform some final common processing
1120                 //
1121
1122                 ASSERT( pFcb->OpenHandleCount != 0);
1123
1124                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
1125                 {
1126
1127                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
1128                 }
1129
1130                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1131
1132                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1133                 {
1134
1135                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
1136
1137                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
1138                     {
1139
1140                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
1141
1142                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1143                     }
1144
1145                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
1146                     {
1147
1148                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
1149
1150                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1151                     }
1152
1153                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
1154                     {
1155
1156                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1157
1158                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1159                     }
1160                 }
1161
1162                 //
1163                 // If the count has dropped to one and there is a pending delete
1164                 // then delete the node.  The final count will be decremented just
1165                 // before the Fcb->NPFcb->Resource is released.
1166                 //
1167
1168                 if( pFcb->OpenHandleCount == 1 &&
1169                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1170                 {
1171
1172                     //
1173                     // Try to notify the service about the delete
1174                     //
1175
1176                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
1177
1178                     //
1179                     // Indicate the file access mode that is being released
1180                     //
1181
1182                     stFileCleanup.FileAccess = pCcb->FileAccess;
1183
1184                     //
1185                     // Push the request to the service
1186                     //
1187
1188                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1189                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1190                                                   &pCcb->AuthGroup,
1191                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1192                                                   &pObjectInfo->FileId,
1193                                                   &stFileCleanup,
1194                                                   sizeof( AFSFileCleanupCB),
1195                                                   pResultCB,
1196                                                   &ulResultLen);
1197
1198                     if( !NT_SUCCESS( ntStatus) &&
1199                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
1200                     {
1201
1202                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1203                                       AFS_TRACE_LEVEL_ERROR,
1204                                       "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
1205                                       &pCcb->FullFileName,
1206                                       ntStatus);
1207
1208                         ntStatus = STATUS_SUCCESS;
1209
1210                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1211                     }
1212                     else
1213                     {
1214
1215                         ntStatus = STATUS_SUCCESS;
1216
1217                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1218                                       AFS_TRACE_LEVEL_VERBOSE,
1219                                       "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1220                                       &pCcb->FullFileName,
1221                                       pCcb->DirectoryCB);
1222
1223                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1224
1225                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1226
1227                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1228
1229                         ASSERT( pParentObjectInfo != NULL);
1230
1231                         AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1232                                         TRUE);
1233
1234                         if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1235                         {
1236
1237                             SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1238
1239                             pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1240                         }
1241                         else
1242                         {
1243                             pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
1244                         }
1245
1246                         //
1247                         // Now that the service has the entry has deleted we need to remove it from the parent
1248                         // tree so another lookup on the node will fail
1249                         //
1250
1251                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1252                         {
1253
1254                             AFSRemoveNameEntry( pParentObjectInfo,
1255                                                 pCcb->DirectoryCB);
1256                         }
1257                         else
1258                         {
1259
1260                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1261                                           AFS_TRACE_LEVEL_VERBOSE,
1262                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1263                                           pCcb->DirectoryCB,
1264                                           &pCcb->DirectoryCB->NameInformation.FileName);
1265                         }
1266
1267                         AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1268
1269                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1270                                                         pCcb,
1271                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1272                                                         (ULONG)FILE_ACTION_REMOVED);
1273
1274                     }
1275                 }
1276
1277                 //
1278                 // If there have been any updates to the node then push it to
1279                 // the service
1280                 //
1281
1282                 else
1283                 {
1284
1285                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1286                     {
1287
1288                         ULONG ulNotifyFilter = 0;
1289
1290                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1291
1292                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1293
1294                         if(  pParentObjectInfo != NULL)
1295                         {
1296
1297                             ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1298
1299                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1300                                                             pCcb,
1301                                                             (ULONG)ulNotifyFilter,
1302                                                             (ULONG)FILE_ACTION_MODIFIED);
1303                         }
1304                     }
1305
1306                     //
1307                     // Indicate the file access mode that is being released
1308                     //
1309
1310                     stFileCleanup.FileAccess = pCcb->FileAccess;
1311
1312                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1313                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1314                                                   &pCcb->AuthGroup,
1315                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1316                                                   &pObjectInfo->FileId,
1317                                                   &stFileCleanup,
1318                                                   sizeof( AFSFileCleanupCB),
1319                                                   pResultCB,
1320                                                   &ulResultLen);
1321
1322                     if ( NT_SUCCESS( ntStatus))
1323                     {
1324
1325                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1326
1327                         if ( pParentObjectInfo != NULL)
1328                         {
1329
1330                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1331                                               TRUE);
1332
1333                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1334                             {
1335
1336                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1337
1338                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1339                             }
1340
1341                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1342                         }
1343                     }
1344
1345                     ntStatus = STATUS_SUCCESS;
1346                 }
1347
1348                 //
1349                 // Remove the share access at this time since we may not get the close for sometime on this FO.
1350                 //
1351
1352                 IoRemoveShareAccess( pFileObject,
1353                                      &pFcb->ShareAccess);
1354
1355                 //
1356                 // We don't need the name array after the user closes the handle on the file
1357                 //
1358
1359                 if( pCcb->NameArray != NULL)
1360                 {
1361
1362                     AFSFreeNameArray( pCcb->NameArray);
1363
1364                     pCcb->NameArray = NULL;
1365                 }
1366
1367                 //
1368                 // Decrement the open child handle count
1369                 //
1370
1371                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1372
1373                 if( pParentObjectInfo != NULL)
1374                 {
1375
1376                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1377
1378                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1379
1380                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1381                                   AFS_TRACE_LEVEL_VERBOSE,
1382                                   "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %p Cnt %d\n",
1383                                   pParentObjectInfo,
1384                                   lCount);
1385                 }
1386
1387                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1388
1389                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1390                               AFS_TRACE_LEVEL_VERBOSE,
1391                               "AFSCleanup (MP/SL) Decrement handle count on Fcb %p Cnt %d\n",
1392                               pFcb,
1393                               lCount);
1394
1395                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1396
1397                 break;
1398             }
1399
1400             case AFS_SPECIAL_SHARE_FCB:
1401             {
1402
1403                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1404                               AFS_TRACE_LEVEL_VERBOSE,
1405                               "AFSCleanup Acquiring SPECIAL SHARE lock %p EXCL %08lX\n",
1406                               &pFcb->NPFcb->Resource,
1407                               PsGetCurrentThread());
1408
1409                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1410                                 TRUE);
1411
1412                 ASSERT( pFcb->OpenHandleCount != 0);
1413
1414                 //
1415                 // Decrement the open child handle count
1416                 //
1417
1418                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1419
1420                 if( pParentObjectInfo != NULL &&
1421                     pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0)
1422                 {
1423
1424                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1425
1426                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1427                                   AFS_TRACE_LEVEL_VERBOSE,
1428                                   "AFSCleanup (Share) Decrement child open handle count on Parent object %p Cnt %d\n",
1429                                   pParentObjectInfo,
1430                                   lCount);
1431                 }
1432
1433                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1434
1435                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1436                               AFS_TRACE_LEVEL_VERBOSE,
1437                               "AFSCleanup (Share) Decrement handle count on Fcb %p Cnt %d\n",
1438                               pFcb,
1439                               lCount);
1440
1441                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1442
1443                 break;
1444             }
1445
1446             default:
1447
1448                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1449                               AFS_TRACE_LEVEL_ERROR,
1450                               "AFSCleanup Processing unknown node type %d\n",
1451                               pFcb->Header.NodeTypeCode);
1452
1453                 break;
1454         }
1455
1456
1457 try_exit:
1458
1459         if( pResultCB != NULL)
1460         {
1461
1462             AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_32_TAG);
1463         }
1464
1465         if( pFileObject != NULL)
1466         {
1467
1468             //
1469             // Setup the fileobject flags to indicate cleanup is complete.
1470             //
1471
1472             SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1473         }
1474
1475         //
1476         // Complete the request
1477         //
1478
1479         AFSCompleteRequest( Irp, ntStatus);
1480     }
1481     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
1482     {
1483
1484         AFSDbgLogMsg( 0,
1485                       0,
1486                       "EXCEPTION - AFSCleanup\n");
1487
1488         AFSDumpTraceFilesFnc();
1489     }
1490
1491     return ntStatus;
1492 }