Windows: AFSCleanup calls AFSDeleteFcbExtents
[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
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 %08lX EXCL %08lX\n",
151                               &pFcb->NPFcb->Resource,
152                               PsGetCurrentThread());
153
154                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
155                                   TRUE);
156
157                 ASSERT( pFcb->OpenHandleCount != 0);
158
159                 AFSReleaseResource( &pFcb->NPFcb->Resource);
160
161                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
162
163                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
164                               AFS_TRACE_LEVEL_VERBOSE,
165                               "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
166                               pFcb,
167                               lCount);
168
169                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
170                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
171                                     pCcb);
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 %08lX 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_FCB_REF_COUNTING,
201                                   AFS_TRACE_LEVEL_VERBOSE,
202                                   "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX 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 %08lX 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 %08lX 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 %08lX FileObject %08lX\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 %08lX 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 %08lX 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 %08lX 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 %08lX 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                     // Attempt to flush any dirty extents to the server. This may be a little
601                     // aggressive, to flush whenever the handle is closed, but it ensures
602                     // coherency.
603                     //
604
605                     if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
606                         pFcb->Specific.File.ExtentsDirtyCount != 0)
607                     {
608
609                         AFSFlushExtents( pFcb,
610                                          &pCcb->AuthGroup);
611
612                         ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
613                     }
614
615                     if( pFcb->OpenHandleCount == 1)
616                     {
617
618                         //
619                         // Wait for any outstanding queued flushes to complete
620                         //
621
622                         AFSWaitOnQueuedFlushes( pFcb);
623
624                         AFSTearDownFcbExtents( pFcb,
625                                                &pCcb->AuthGroup);
626                     }
627
628                     //
629                     // Indicate the file access mode that is being released
630                     //
631
632                     stFileCleanup.FileAccess = pCcb->FileAccess;
633
634                     //
635                     // Remove the share access at this time since we may not get the close for sometime on this FO.
636                     //
637
638                     IoRemoveShareAccess( pFileObject,
639                                          &pFcb->ShareAccess);
640
641
642                     //
643                     // We don't need the name array after the user closes the handle on the file
644                     //
645
646                     if( pCcb->NameArray != NULL)
647                     {
648
649                         AFSFreeNameArray( pCcb->NameArray);
650
651                         pCcb->NameArray = NULL;
652                     }
653
654                     //
655                     // Release the Fcb Resource across the call to the service
656                     // which may block for quite a while if flushing of the
657                     // data is required.
658                     //
659
660                     AFSReleaseResource( &pFcb->NPFcb->Resource);
661
662                     //
663                     // Push the request to the service
664                     //
665
666                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
667                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
668                                                   &pCcb->AuthGroup,
669                                                   &pCcb->DirectoryCB->NameInformation.FileName,
670                                                   &pObjectInfo->FileId,
671                                                   &stFileCleanup,
672                                                   sizeof( AFSFileCleanupCB),
673                                                   pResultCB,
674                                                   &ulResultLen);
675
676                     //
677                     // Regain exclusive access to the Fcb
678                     //
679
680                     AFSAcquireExcl( &pFcb->NPFcb->Resource,
681                                     TRUE);
682
683                     if ( NT_SUCCESS( ntStatus))
684                     {
685
686                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
687
688                         if ( pParentObjectInfo != NULL)
689                         {
690
691                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
692                                             TRUE);
693
694                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
695                             {
696
697                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
698
699                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
700                             }
701
702                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
703                         }
704                     }
705
706                     ntStatus = STATUS_SUCCESS;
707                 }
708
709                 //
710                 // Decrement the open child handle count
711                 //
712
713                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
714
715                 if( pParentObjectInfo != NULL)
716                 {
717
718                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
719
720                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
721
722                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
723                                   AFS_TRACE_LEVEL_VERBOSE,
724                                   "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
725                                   pParentObjectInfo,
726                                   lCount);
727                 }
728
729
730                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
731
732                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
733                               AFS_TRACE_LEVEL_VERBOSE,
734                               "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
735                               pFcb,
736                               lCount);
737
738                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
739                 {
740                     //
741                     // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
742                     //
743
744                     AFSObjectInfoIncrement( pObjectInfo);
745
746                     ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
747
748                     AFSReleaseResource( &pFcb->NPFcb->Resource);
749
750                     AFSPerformObjectInvalidate( pObjectInfo,
751                                                 AFS_INVALIDATE_DATA_VERSION);
752                 }
753                 else
754                 {
755
756                     AFSReleaseResource( &pFcb->NPFcb->Resource);
757                 }
758
759                 break;
760             }
761
762             //
763             // Root or directory node
764             //
765
766             case AFS_ROOT_FCB:
767             {
768
769                 //
770                 // Set the root Fcb to this node
771                 //
772
773                 pRootFcb = pFcb;
774
775                 //
776                 // Fall through to below
777                 //
778             }
779
780             case AFS_DIRECTORY_FCB:
781             {
782
783                 //
784                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
785                 //
786
787                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
788                               AFS_TRACE_LEVEL_VERBOSE,
789                               "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
790                               &pFcb->NPFcb->Resource,
791                               PsGetCurrentThread());
792
793                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
794                                   TRUE);
795
796                 //
797                 // Perform some final common processing
798                 //
799
800                 ASSERT( pFcb->OpenHandleCount != 0);
801
802                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
803                 {
804
805                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
806                 }
807
808                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
809
810                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
811                 {
812
813                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
814
815                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
816                     {
817
818                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
819
820                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
821                     }
822
823                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
824                     {
825
826                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
827
828                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
829                     }
830
831                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
832                     {
833
834                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
835
836                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
837                     }
838                 }
839
840                 //
841                 // If the count has dropped to one and there is a pending delete
842                 // then delete the node.  The final count will be decremented just
843                 // before the Fcb->NPFcb->Resource is released.
844                 //
845
846                 if( pFcb->OpenHandleCount == 1 &&
847                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
848                 {
849
850                     //
851                     // Try to notify the service about the delete
852                     //
853
854                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
855
856                     //
857                     // Indicate the file access mode that is being released
858                     //
859
860                     stFileCleanup.FileAccess = pCcb->FileAccess;
861
862                     //
863                     // Push the request to the service
864                     //
865
866                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
867                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
868                                                   &pCcb->AuthGroup,
869                                                   &pCcb->DirectoryCB->NameInformation.FileName,
870                                                   &pObjectInfo->FileId,
871                                                   &stFileCleanup,
872                                                   sizeof( AFSFileCleanupCB),
873                                                   pResultCB,
874                                                   &ulResultLen);
875
876                     if( !NT_SUCCESS( ntStatus) &&
877                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
878                     {
879
880                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
881                                       AFS_TRACE_LEVEL_ERROR,
882                                       "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
883                                       &pCcb->FullFileName,
884                                       ntStatus);
885
886                         ntStatus = STATUS_SUCCESS;
887
888                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
889                     }
890                     else
891                     {
892
893                         ntStatus = STATUS_SUCCESS;
894
895                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
896                                       AFS_TRACE_LEVEL_VERBOSE,
897                                       "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
898                                       &pCcb->FullFileName,
899                                       pCcb->DirectoryCB);
900
901                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
902
903                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
904
905                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
906
907                         ASSERT( pParentObjectInfo != NULL);
908
909                         AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
910                                         TRUE);
911
912                         if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
913                         {
914
915                             SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
916
917                             pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
918                         }
919                         else
920                         {
921
922                             pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
923                         }
924
925                         //
926                         // Now that the service has the entry has deleted we need to remove it from the parent
927                         // tree so another lookup on the node will fail
928                         //
929
930                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
931                         {
932
933                             AFSRemoveNameEntry( pParentObjectInfo,
934                                                 pCcb->DirectoryCB);
935                         }
936                         else
937                         {
938
939                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
940                                           AFS_TRACE_LEVEL_VERBOSE,
941                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
942                                           pCcb->DirectoryCB,
943                                           &pCcb->DirectoryCB->NameInformation.FileName);
944                         }
945
946                         AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
947
948                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
949                                                         pCcb,
950                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
951                                                         (ULONG)FILE_ACTION_REMOVED);
952
953                     }
954                 }
955
956                 //
957                 // If there have been any updates to the node then push it to
958                 // the service
959                 //
960
961                 else
962                 {
963
964                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
965                     {
966
967                         ULONG ulNotifyFilter = 0;
968
969                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
970
971                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
972
973                         if(  pParentObjectInfo != NULL)
974                         {
975
976                             ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
977
978                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
979                                                             pCcb,
980                                                             (ULONG)ulNotifyFilter,
981                                                             (ULONG)FILE_ACTION_MODIFIED);
982                         }
983                     }
984
985                     //
986                     // Indicate the file access mode that is being released
987                     //
988
989                     stFileCleanup.FileAccess = pCcb->FileAccess;
990
991                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
992                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
993                                                   &pCcb->AuthGroup,
994                                                   &pCcb->DirectoryCB->NameInformation.FileName,
995                                                   &pObjectInfo->FileId,
996                                                   &stFileCleanup,
997                                                   sizeof( AFSFileCleanupCB),
998                                                   pResultCB,
999                                                   &ulResultLen);
1000
1001                     if ( NT_SUCCESS( ntStatus))
1002                     {
1003
1004                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1005
1006                         if ( pParentObjectInfo != NULL)
1007                         {
1008
1009                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1010                                               TRUE);
1011
1012                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1013                             {
1014
1015                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1016
1017                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1018                             }
1019
1020                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1021                         }
1022                     }
1023
1024                     ntStatus = STATUS_SUCCESS;
1025                 }
1026
1027                 //
1028                 // Release the notification for this directory if there is one
1029                 //
1030
1031                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
1032                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
1033                                     pCcb);
1034
1035                 //
1036                 // Remove the share access at this time since we may not get the close for sometime on this FO.
1037                 //
1038
1039                 IoRemoveShareAccess( pFileObject,
1040                                      &pFcb->ShareAccess);
1041
1042                 //
1043                 // We don't need the name array after the user closes the handle on the file
1044                 //
1045
1046                 if( pCcb->NameArray != NULL)
1047                 {
1048
1049                     AFSFreeNameArray( pCcb->NameArray);
1050
1051                     pCcb->NameArray = NULL;
1052                 }
1053
1054                 //
1055                 // Decrement the open child handle count
1056                 //
1057
1058                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1059
1060                 if( pParentObjectInfo != NULL)
1061                 {
1062
1063                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1064
1065                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1066
1067                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1068                                   AFS_TRACE_LEVEL_VERBOSE,
1069                                   "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1070                                   pParentObjectInfo,
1071                                   lCount);
1072                 }
1073
1074                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1075
1076                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1077
1078                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1079                               AFS_TRACE_LEVEL_VERBOSE,
1080                               "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
1081                               pFcb,
1082                               lCount);
1083
1084                 break;
1085             }
1086
1087             case AFS_SYMBOLIC_LINK_FCB:
1088             case AFS_MOUNT_POINT_FCB:
1089             case AFS_DFS_LINK_FCB:
1090             case AFS_INVALID_FCB:
1091             {
1092
1093                 //
1094                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
1095                 //
1096
1097                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1098                               AFS_TRACE_LEVEL_VERBOSE,
1099                               "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
1100                               &pFcb->NPFcb->Resource,
1101                               PsGetCurrentThread());
1102
1103                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1104                                   TRUE);
1105
1106                 //
1107                 // Perform some final common processing
1108                 //
1109
1110                 ASSERT( pFcb->OpenHandleCount != 0);
1111
1112                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
1113                 {
1114
1115                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
1116                 }
1117
1118                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1119
1120                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1121                 {
1122
1123                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
1124
1125                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
1126                     {
1127
1128                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
1129
1130                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1131                     }
1132
1133                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
1134                     {
1135
1136                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
1137
1138                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1139                     }
1140
1141                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
1142                     {
1143
1144                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1145
1146                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1147                     }
1148                 }
1149
1150                 //
1151                 // If the count has dropped to one and there is a pending delete
1152                 // then delete the node.  The final count will be decremented just
1153                 // before the Fcb->NPFcb->Resource is released.
1154                 //
1155
1156                 if( pFcb->OpenHandleCount == 1 &&
1157                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1158                 {
1159
1160                     //
1161                     // Try to notify the service about the delete
1162                     //
1163
1164                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
1165
1166                     //
1167                     // Indicate the file access mode that is being released
1168                     //
1169
1170                     stFileCleanup.FileAccess = pCcb->FileAccess;
1171
1172                     //
1173                     // Push the request to the service
1174                     //
1175
1176                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1177                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1178                                                   &pCcb->AuthGroup,
1179                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1180                                                   &pObjectInfo->FileId,
1181                                                   &stFileCleanup,
1182                                                   sizeof( AFSFileCleanupCB),
1183                                                   pResultCB,
1184                                                   &ulResultLen);
1185
1186                     if( !NT_SUCCESS( ntStatus) &&
1187                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
1188                     {
1189
1190                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1191                                       AFS_TRACE_LEVEL_ERROR,
1192                                       "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
1193                                       &pCcb->FullFileName,
1194                                       ntStatus);
1195
1196                         ntStatus = STATUS_SUCCESS;
1197
1198                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1199                     }
1200                     else
1201                     {
1202
1203                         ntStatus = STATUS_SUCCESS;
1204
1205                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1206                                       AFS_TRACE_LEVEL_VERBOSE,
1207                                       "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1208                                       &pCcb->FullFileName,
1209                                       pCcb->DirectoryCB);
1210
1211                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1212
1213                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1214
1215                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1216
1217                         ASSERT( pParentObjectInfo != NULL);
1218
1219                         AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1220                                         TRUE);
1221
1222                         if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1223                         {
1224
1225                             SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1226
1227                             pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1228                         }
1229                         else
1230                         {
1231                             pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
1232                         }
1233
1234                         //
1235                         // Now that the service has the entry has deleted we need to remove it from the parent
1236                         // tree so another lookup on the node will fail
1237                         //
1238
1239                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1240                         {
1241
1242                             AFSRemoveNameEntry( pParentObjectInfo,
1243                                                 pCcb->DirectoryCB);
1244                         }
1245                         else
1246                         {
1247
1248                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1249                                           AFS_TRACE_LEVEL_VERBOSE,
1250                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1251                                           pCcb->DirectoryCB,
1252                                           &pCcb->DirectoryCB->NameInformation.FileName);
1253                         }
1254
1255                         AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1256
1257                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1258                                                         pCcb,
1259                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1260                                                         (ULONG)FILE_ACTION_REMOVED);
1261
1262                     }
1263                 }
1264
1265                 //
1266                 // If there have been any updates to the node then push it to
1267                 // the service
1268                 //
1269
1270                 else
1271                 {
1272
1273                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1274                     {
1275
1276                         ULONG ulNotifyFilter = 0;
1277
1278                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1279
1280                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1281
1282                         if(  pParentObjectInfo != NULL)
1283                         {
1284
1285                             ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1286
1287                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1288                                                             pCcb,
1289                                                             (ULONG)ulNotifyFilter,
1290                                                             (ULONG)FILE_ACTION_MODIFIED);
1291                         }
1292                     }
1293
1294                     //
1295                     // Indicate the file access mode that is being released
1296                     //
1297
1298                     stFileCleanup.FileAccess = pCcb->FileAccess;
1299
1300                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1301                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1302                                                   &pCcb->AuthGroup,
1303                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1304                                                   &pObjectInfo->FileId,
1305                                                   &stFileCleanup,
1306                                                   sizeof( AFSFileCleanupCB),
1307                                                   pResultCB,
1308                                                   &ulResultLen);
1309
1310                     if ( NT_SUCCESS( ntStatus))
1311                     {
1312
1313                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1314
1315                         if ( pParentObjectInfo != NULL)
1316                         {
1317
1318                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1319                                               TRUE);
1320
1321                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1322                             {
1323
1324                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1325
1326                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1327                             }
1328
1329                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1330                         }
1331                     }
1332
1333                     ntStatus = STATUS_SUCCESS;
1334                 }
1335
1336                 //
1337                 // Remove the share access at this time since we may not get the close for sometime on this FO.
1338                 //
1339
1340                 IoRemoveShareAccess( pFileObject,
1341                                      &pFcb->ShareAccess);
1342
1343                 //
1344                 // We don't need the name array after the user closes the handle on the file
1345                 //
1346
1347                 if( pCcb->NameArray != NULL)
1348                 {
1349
1350                     AFSFreeNameArray( pCcb->NameArray);
1351
1352                     pCcb->NameArray = NULL;
1353                 }
1354
1355                 //
1356                 // Decrement the open child handle count
1357                 //
1358
1359                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1360
1361                 if( pParentObjectInfo != NULL)
1362                 {
1363
1364                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1365
1366                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1367
1368                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1369                                   AFS_TRACE_LEVEL_VERBOSE,
1370                                   "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1371                                   pParentObjectInfo,
1372                                   lCount);
1373                 }
1374
1375                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1376
1377                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1378
1379                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1380                               AFS_TRACE_LEVEL_VERBOSE,
1381                               "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
1382                               pFcb,
1383                               lCount);
1384
1385                 break;
1386             }
1387
1388             case AFS_SPECIAL_SHARE_FCB:
1389             {
1390
1391                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1392                               AFS_TRACE_LEVEL_VERBOSE,
1393                               "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
1394                               &pFcb->NPFcb->Resource,
1395                               PsGetCurrentThread());
1396
1397                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1398                                 TRUE);
1399
1400                 ASSERT( pFcb->OpenHandleCount != 0);
1401
1402                 //
1403                 // Decrement the open child handle count
1404                 //
1405
1406                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1407
1408                 if( pParentObjectInfo != NULL &&
1409                     pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0)
1410                 {
1411
1412                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1413
1414                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1415                                   AFS_TRACE_LEVEL_VERBOSE,
1416                                   "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1417                                   pParentObjectInfo,
1418                                   lCount);
1419                 }
1420
1421                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1422
1423                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1424
1425                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1426                               AFS_TRACE_LEVEL_VERBOSE,
1427                               "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
1428                               pFcb,
1429                               lCount);
1430
1431                 break;
1432             }
1433
1434             default:
1435
1436                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1437                               AFS_TRACE_LEVEL_WARNING,
1438                               "AFSCleanup Processing unknown node type %d\n",
1439                               pFcb->Header.NodeTypeCode);
1440
1441                 break;
1442         }
1443
1444
1445 try_exit:
1446
1447         if( pResultCB != NULL)
1448         {
1449
1450             AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_32_TAG);
1451         }
1452
1453         if( pFileObject != NULL)
1454         {
1455
1456             //
1457             // Setup the fileobject flags to indicate cleanup is complete.
1458             //
1459
1460             SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1461         }
1462
1463         //
1464         // Complete the request
1465         //
1466
1467         AFSCompleteRequest( Irp, ntStatus);
1468     }
1469     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
1470     {
1471
1472         AFSDbgLogMsg( 0,
1473                       0,
1474                       "EXCEPTION - AFSCleanup\n");
1475
1476         AFSDumpTraceFilesFnc();
1477     }
1478
1479     return ntStatus;
1480 }