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