f8945ec293bc1dc5b6fdd6063ef2a3a0063dfb6b
[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 lock %08lX EXCL %08lX\n",
234                               &pFcb->NPFcb->Resource,
235                               PsGetCurrentThread());
236
237                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
238                                 TRUE);
239
240                 //
241                 // If the handle has write permission ...
242                 //
243
244                 if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
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                     __except( EXCEPTION_EXECUTE_HANDLER)
274                     {
275
276                         ntStatus = GetExceptionCode();
277                     }
278                 }
279
280                 //
281                 // Uninitialize the cache map. This call is unconditional.
282                 //
283
284                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
285                               AFS_TRACE_LEVEL_VERBOSE,
286                               "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
287                               pFcb,
288                               pFileObject);
289
290                 CcUninitializeCacheMap( pFileObject,
291                                         NULL,
292                                         NULL);
293
294                 //
295                 // Unlock all outstanding locks on the file, again, unconditionally
296                 //
297
298                 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
299                                            pFileObject,
300                                            IoGetRequestorProcess( Irp),
301                                            NULL);
302
303                 //
304                 // Tell the service to unlock all on the file
305                 //
306
307                 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
308
309                 //
310                 // Perform some final common processing
311                 //
312
313                 ASSERT( pFcb->OpenHandleCount != 0);
314
315                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
316                 {
317
318                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
319                 }
320
321                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
322
323                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
324                 {
325
326                     stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
327
328                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
329
330                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
331                     {
332
333                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
334
335                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
336                     }
337
338                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
339                     {
340
341                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
342
343                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
344                     }
345
346                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
347                     {
348
349                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
350
351                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
352                     }
353
354                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
355                     {
356
357                         stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
358
359                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
360                     }
361                 }
362
363                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
364                 {
365
366                     stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
367                 }
368
369                 //
370                 // If the count has dropped to one and there is a pending delete
371                 // then delete the node.  The final count will be decremented just
372                 // before the Fcb->NPFcb->Resource is released.
373                 //
374
375                 if( pFcb->OpenHandleCount == 1 &&
376                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
377                 {
378
379                     ntStatus = STATUS_SUCCESS;
380
381                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
382
383                     //
384                     // Indicate the file access mode that is being released
385                     //
386
387                     stFileCleanup.FileAccess = pCcb->FileAccess;
388
389                     //
390                     // Push the request to the service
391                     //
392
393                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
394                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
395                                                   &pCcb->AuthGroup,
396                                                   &pCcb->DirectoryCB->NameInformation.FileName,
397                                                   &pObjectInfo->FileId,
398                                                   &stFileCleanup,
399                                                   sizeof( AFSFileCleanupCB),
400                                                   pResultCB,
401                                                   &ulResultLen);
402
403                     if( !NT_SUCCESS( ntStatus) &&
404                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
405                     {
406
407                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
408                                       AFS_TRACE_LEVEL_ERROR,
409                                       "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
410                                       &pCcb->FullFileName,
411                                       ntStatus);
412
413                         ntStatus = STATUS_SUCCESS;
414
415                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
416                     }
417                     else
418                     {
419
420                         ntStatus = STATUS_SUCCESS;
421
422                         if ( --pObjectInfo->Links < 1)
423                         {
424
425                             //
426                             // Stop anything possibly in process
427                             //
428
429                             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
430                                           AFS_TRACE_LEVEL_VERBOSE,
431                                           "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
432                                           &pFcb->NPFcb->Specific.File.ExtentsResource,
433                                           PsGetCurrentThread());
434
435                             AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
436                                             TRUE);
437
438                             pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
439
440                             KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
441                                         0,
442                                         FALSE);
443
444                             //
445                             // Before telling the server about the deleted file, tear down all extents for
446                             // the file
447                             //
448
449                             AFSTearDownFcbExtents( pFcb,
450                                                    &pCcb->AuthGroup);
451
452                             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
453                                           AFS_TRACE_LEVEL_VERBOSE,
454                                           "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
455                                           &pFcb->NPFcb->Specific.File.ExtentsResource,
456                                           PsGetCurrentThread());
457
458                             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
459                         }
460
461                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
462                                       AFS_TRACE_LEVEL_VERBOSE,
463                                       "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
464                                       &pCcb->FullFileName,
465                                       pCcb->DirectoryCB);
466
467                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
468
469                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
470
471                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
472
473                         ASSERT( pParentObjectInfo != NULL);
474
475                         AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
476                                         TRUE);
477
478                         if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
479                         {
480
481                             SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
482
483                             pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
484                         }
485                         else
486                         {
487
488                             pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
489                         }
490
491                         //
492                         // Now that the service has the entry has deleted we need to remove it from the parent
493                         // tree so another lookup on the node will fail
494                         //
495
496                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
497                         {
498
499                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
500                                           AFS_TRACE_LEVEL_VERBOSE,
501                                           "AFSCleanup DE %p for %wZ removing entry\n",
502                                           pCcb->DirectoryCB,
503                                           &pCcb->DirectoryCB->NameInformation.FileName);
504
505                             AFSRemoveNameEntry( pParentObjectInfo,
506                                                 pCcb->DirectoryCB);
507                         }
508                         else
509                         {
510
511                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
512                                           AFS_TRACE_LEVEL_VERBOSE,
513                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
514                                           pCcb->DirectoryCB,
515                                           &pCcb->DirectoryCB->NameInformation.FileName);
516                         }
517
518                         AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
519
520                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
521                                                         pCcb,
522                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
523                                                         (ULONG)FILE_ACTION_REMOVED);
524
525                     }
526                 }
527                 else
528                 {
529
530                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
531                     {
532
533                         ULONG ulNotifyFilter = 0;
534
535                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
536
537                         ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
538
539                         AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
540                                                         pCcb,
541                                                         (ULONG)ulNotifyFilter,
542                                                         (ULONG)FILE_ACTION_MODIFIED);
543                     }
544
545                     //
546                     // Attempt to flush any dirty extents to the server. This may be a little
547                     // aggressive, to flush whenever the handle is closed, but it ensures
548                     // coherency.
549                     //
550
551                     if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
552                         pFcb->Specific.File.ExtentsDirtyCount != 0)
553                     {
554
555                         AFSFlushExtents( pFcb,
556                                          &pCcb->AuthGroup);
557
558                         ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
559                     }
560
561                     if( pFcb->OpenHandleCount == 1)
562                     {
563
564                         //
565                         // Wait for any outstanding queued flushes to complete
566                         //
567
568                         AFSWaitOnQueuedFlushes( pFcb);
569
570                         AFSTearDownFcbExtents( pFcb,
571                                                &pCcb->AuthGroup);
572                     }
573
574                     //
575                     // Indicate the file access mode that is being released
576                     //
577
578                     stFileCleanup.FileAccess = pCcb->FileAccess;
579
580                     //
581                     // Remove the share access at this time since we may not get the close for sometime on this FO.
582                     //
583
584                     IoRemoveShareAccess( pFileObject,
585                                          &pFcb->ShareAccess);
586
587
588                     //
589                     // We don't need the name array after the user closes the handle on the file
590                     //
591
592                     if( pCcb->NameArray != NULL)
593                     {
594
595                         AFSFreeNameArray( pCcb->NameArray);
596
597                         pCcb->NameArray = NULL;
598                     }
599
600                     //
601                     // Release the Fcb Resource across the call to the service
602                     // which may block for quite a while if flushing of the
603                     // data is required.
604                     //
605
606                     AFSReleaseResource( &pFcb->NPFcb->Resource);
607
608                     //
609                     // Push the request to the service
610                     //
611
612                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
613                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
614                                                   &pCcb->AuthGroup,
615                                                   &pCcb->DirectoryCB->NameInformation.FileName,
616                                                   &pObjectInfo->FileId,
617                                                   &stFileCleanup,
618                                                   sizeof( AFSFileCleanupCB),
619                                                   pResultCB,
620                                                   &ulResultLen);
621
622                     //
623                     // Regain exclusive access to the Fcb
624                     //
625
626                     AFSAcquireExcl( &pFcb->NPFcb->Resource,
627                                     TRUE);
628
629                     if ( NT_SUCCESS( ntStatus))
630                     {
631
632                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
633
634                         if ( pParentObjectInfo != NULL)
635                         {
636
637                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
638                                             TRUE);
639
640                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
641                             {
642
643                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
644
645                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
646                             }
647
648                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
649                         }
650                     }
651
652                     ntStatus = STATUS_SUCCESS;
653                 }
654
655                 //
656                 // Decrement the open child handle count
657                 //
658
659                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
660
661                 if( pParentObjectInfo != NULL)
662                 {
663
664                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
665
666                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
667
668                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
669                                   AFS_TRACE_LEVEL_VERBOSE,
670                                   "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
671                                   pParentObjectInfo,
672                                   lCount);
673                 }
674
675
676                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
677
678                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
679                               AFS_TRACE_LEVEL_VERBOSE,
680                               "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
681                               pFcb,
682                               lCount);
683
684                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
685                 {
686                     //
687                     // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
688                     //
689
690                     AFSObjectInfoIncrement( pObjectInfo);
691
692                     ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
693
694                     AFSReleaseResource( &pFcb->NPFcb->Resource);
695
696                     AFSPerformObjectInvalidate( pObjectInfo,
697                                                 AFS_INVALIDATE_DATA_VERSION);
698                 }
699                 else
700                 {
701
702                     AFSReleaseResource( &pFcb->NPFcb->Resource);
703                 }
704
705                 break;
706             }
707
708             //
709             // Root or directory node
710             //
711
712             case AFS_ROOT_FCB:
713             {
714
715                 //
716                 // Set the root Fcb to this node
717                 //
718
719                 pRootFcb = pFcb;
720
721                 //
722                 // Fall through to below
723                 //
724             }
725
726             case AFS_DIRECTORY_FCB:
727             {
728
729                 //
730                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
731                 //
732
733                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
734                               AFS_TRACE_LEVEL_VERBOSE,
735                               "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
736                               &pFcb->NPFcb->Resource,
737                               PsGetCurrentThread());
738
739                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
740                                   TRUE);
741
742                 //
743                 // Perform some final common processing
744                 //
745
746                 ASSERT( pFcb->OpenHandleCount != 0);
747
748                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
749                 {
750
751                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
752                 }
753
754                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
755
756                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
757                 {
758
759                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
760
761                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
762                     {
763
764                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
765
766                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
767                     }
768
769                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
770                     {
771
772                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
773
774                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
775                     }
776
777                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
778                     {
779
780                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
781
782                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
783                     }
784                 }
785
786                 //
787                 // If the count has dropped to one and there is a pending delete
788                 // then delete the node.  The final count will be decremented just
789                 // before the Fcb->NPFcb->Resource is released.
790                 //
791
792                 if( pFcb->OpenHandleCount == 1 &&
793                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
794                 {
795
796                     //
797                     // Try to notify the service about the delete
798                     //
799
800                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
801
802                     //
803                     // Indicate the file access mode that is being released
804                     //
805
806                     stFileCleanup.FileAccess = pCcb->FileAccess;
807
808                     //
809                     // Push the request to the service
810                     //
811
812                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
813                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
814                                                   &pCcb->AuthGroup,
815                                                   &pCcb->DirectoryCB->NameInformation.FileName,
816                                                   &pObjectInfo->FileId,
817                                                   &stFileCleanup,
818                                                   sizeof( AFSFileCleanupCB),
819                                                   pResultCB,
820                                                   &ulResultLen);
821
822                     if( !NT_SUCCESS( ntStatus) &&
823                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
824                     {
825
826                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
827                                       AFS_TRACE_LEVEL_ERROR,
828                                       "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
829                                       &pCcb->FullFileName,
830                                       ntStatus);
831
832                         ntStatus = STATUS_SUCCESS;
833
834                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
835                     }
836                     else
837                     {
838
839                         ntStatus = STATUS_SUCCESS;
840
841                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
842                                       AFS_TRACE_LEVEL_VERBOSE,
843                                       "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
844                                       &pCcb->FullFileName,
845                                       pCcb->DirectoryCB);
846
847                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
848
849                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
850
851                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
852
853                         ASSERT( pParentObjectInfo != NULL);
854
855                         AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
856                                         TRUE);
857
858                         if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
859                         {
860
861                             SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
862
863                             pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
864                         }
865                         else
866                         {
867
868                             pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
869                         }
870
871                         //
872                         // Now that the service has the entry has deleted we need to remove it from the parent
873                         // tree so another lookup on the node will fail
874                         //
875
876                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
877                         {
878
879                             AFSRemoveNameEntry( pParentObjectInfo,
880                                                 pCcb->DirectoryCB);
881                         }
882                         else
883                         {
884
885                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
886                                           AFS_TRACE_LEVEL_VERBOSE,
887                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
888                                           pCcb->DirectoryCB,
889                                           &pCcb->DirectoryCB->NameInformation.FileName);
890                         }
891
892                         AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
893
894                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
895                                                         pCcb,
896                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
897                                                         (ULONG)FILE_ACTION_REMOVED);
898
899                     }
900                 }
901
902                 //
903                 // If there have been any updates to the node then push it to
904                 // the service
905                 //
906
907                 else
908                 {
909
910                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
911                     {
912
913                         ULONG ulNotifyFilter = 0;
914
915                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
916
917                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
918
919                         if(  pParentObjectInfo != NULL)
920                         {
921
922                             ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
923
924                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
925                                                             pCcb,
926                                                             (ULONG)ulNotifyFilter,
927                                                             (ULONG)FILE_ACTION_MODIFIED);
928                         }
929                     }
930
931                     //
932                     // Indicate the file access mode that is being released
933                     //
934
935                     stFileCleanup.FileAccess = pCcb->FileAccess;
936
937                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
938                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
939                                                   &pCcb->AuthGroup,
940                                                   &pCcb->DirectoryCB->NameInformation.FileName,
941                                                   &pObjectInfo->FileId,
942                                                   &stFileCleanup,
943                                                   sizeof( AFSFileCleanupCB),
944                                                   pResultCB,
945                                                   &ulResultLen);
946
947                     if ( NT_SUCCESS( ntStatus))
948                     {
949
950                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
951
952                         if ( pParentObjectInfo != NULL)
953                         {
954
955                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
956                                               TRUE);
957
958                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
959                             {
960
961                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
962
963                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
964                             }
965
966                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
967                         }
968                     }
969
970                     ntStatus = STATUS_SUCCESS;
971                 }
972
973                 //
974                 // Release the notification for this directory if there is one
975                 //
976
977                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
978                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
979                                     pCcb);
980
981                 //
982                 // Remove the share access at this time since we may not get the close for sometime on this FO.
983                 //
984
985                 IoRemoveShareAccess( pFileObject,
986                                      &pFcb->ShareAccess);
987
988                 //
989                 // We don't need the name array after the user closes the handle on the file
990                 //
991
992                 if( pCcb->NameArray != NULL)
993                 {
994
995                     AFSFreeNameArray( pCcb->NameArray);
996
997                     pCcb->NameArray = NULL;
998                 }
999
1000                 //
1001                 // Decrement the open child handle count
1002                 //
1003
1004                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1005
1006                 if( pParentObjectInfo != NULL)
1007                 {
1008
1009                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1010
1011                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1012
1013                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1014                                   AFS_TRACE_LEVEL_VERBOSE,
1015                                   "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1016                                   pParentObjectInfo,
1017                                   lCount);
1018                 }
1019
1020                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1021
1022                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1023
1024                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1025                               AFS_TRACE_LEVEL_VERBOSE,
1026                               "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
1027                               pFcb,
1028                               lCount);
1029
1030                 break;
1031             }
1032
1033             case AFS_SYMBOLIC_LINK_FCB:
1034             case AFS_MOUNT_POINT_FCB:
1035             case AFS_DFS_LINK_FCB:
1036             case AFS_INVALID_FCB:
1037             {
1038
1039                 //
1040                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
1041                 //
1042
1043                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1044                               AFS_TRACE_LEVEL_VERBOSE,
1045                               "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
1046                               &pFcb->NPFcb->Resource,
1047                               PsGetCurrentThread());
1048
1049                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1050                                   TRUE);
1051
1052                 //
1053                 // Perform some final common processing
1054                 //
1055
1056                 ASSERT( pFcb->OpenHandleCount != 0);
1057
1058                 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
1059                 {
1060
1061                     stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
1062                 }
1063
1064                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1065
1066                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1067                 {
1068
1069                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
1070
1071                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
1072                     {
1073
1074                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
1075
1076                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1077                     }
1078
1079                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
1080                     {
1081
1082                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
1083
1084                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1085                     }
1086
1087                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
1088                     {
1089
1090                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1091
1092                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1093                     }
1094                 }
1095
1096                 //
1097                 // If the count has dropped to one and there is a pending delete
1098                 // then delete the node.  The final count will be decremented just
1099                 // before the Fcb->NPFcb->Resource is released.
1100                 //
1101
1102                 if( pFcb->OpenHandleCount == 1 &&
1103                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1104                 {
1105
1106                     //
1107                     // Try to notify the service about the delete
1108                     //
1109
1110                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
1111
1112                     //
1113                     // Indicate the file access mode that is being released
1114                     //
1115
1116                     stFileCleanup.FileAccess = pCcb->FileAccess;
1117
1118                     //
1119                     // Push the request to the service
1120                     //
1121
1122                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1123                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1124                                                   &pCcb->AuthGroup,
1125                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1126                                                   &pObjectInfo->FileId,
1127                                                   &stFileCleanup,
1128                                                   sizeof( AFSFileCleanupCB),
1129                                                   pResultCB,
1130                                                   &ulResultLen);
1131
1132                     if( !NT_SUCCESS( ntStatus) &&
1133                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
1134                     {
1135
1136                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1137                                       AFS_TRACE_LEVEL_ERROR,
1138                                       "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
1139                                       &pCcb->FullFileName,
1140                                       ntStatus);
1141
1142                         ntStatus = STATUS_SUCCESS;
1143
1144                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1145                     }
1146                     else
1147                     {
1148
1149                         ntStatus = STATUS_SUCCESS;
1150
1151                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1152                                       AFS_TRACE_LEVEL_VERBOSE,
1153                                       "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1154                                       &pCcb->FullFileName,
1155                                       pCcb->DirectoryCB);
1156
1157                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1158
1159                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1160
1161                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1162
1163                         ASSERT( pParentObjectInfo != NULL);
1164
1165                         AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1166                                         TRUE);
1167
1168                         if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1169                         {
1170
1171                             SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1172
1173                             pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1174                         }
1175                         else
1176                         {
1177                             pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
1178                         }
1179
1180                         //
1181                         // Now that the service has the entry has deleted we need to remove it from the parent
1182                         // tree so another lookup on the node will fail
1183                         //
1184
1185                         if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1186                         {
1187
1188                             AFSRemoveNameEntry( pParentObjectInfo,
1189                                                 pCcb->DirectoryCB);
1190                         }
1191                         else
1192                         {
1193
1194                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1195                                           AFS_TRACE_LEVEL_VERBOSE,
1196                                           "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1197                                           pCcb->DirectoryCB,
1198                                           &pCcb->DirectoryCB->NameInformation.FileName);
1199                         }
1200
1201                         AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1202
1203                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1204                                                         pCcb,
1205                                                         (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1206                                                         (ULONG)FILE_ACTION_REMOVED);
1207
1208                     }
1209                 }
1210
1211                 //
1212                 // If there have been any updates to the node then push it to
1213                 // the service
1214                 //
1215
1216                 else
1217                 {
1218
1219                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1220                     {
1221
1222                         ULONG ulNotifyFilter = 0;
1223
1224                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1225
1226                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1227
1228                         if(  pParentObjectInfo != NULL)
1229                         {
1230
1231                             ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1232
1233                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1234                                                             pCcb,
1235                                                             (ULONG)ulNotifyFilter,
1236                                                             (ULONG)FILE_ACTION_MODIFIED);
1237                         }
1238                     }
1239
1240                     //
1241                     // Indicate the file access mode that is being released
1242                     //
1243
1244                     stFileCleanup.FileAccess = pCcb->FileAccess;
1245
1246                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1247                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1248                                                   &pCcb->AuthGroup,
1249                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1250                                                   &pObjectInfo->FileId,
1251                                                   &stFileCleanup,
1252                                                   sizeof( AFSFileCleanupCB),
1253                                                   pResultCB,
1254                                                   &ulResultLen);
1255
1256                     if ( NT_SUCCESS( ntStatus))
1257                     {
1258
1259                         pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1260
1261                         if ( pParentObjectInfo != NULL)
1262                         {
1263
1264                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1265                                               TRUE);
1266
1267                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1268                             {
1269
1270                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1271
1272                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1273                             }
1274
1275                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1276                         }
1277                     }
1278
1279                     ntStatus = STATUS_SUCCESS;
1280                 }
1281
1282                 //
1283                 // Remove the share access at this time since we may not get the close for sometime on this FO.
1284                 //
1285
1286                 IoRemoveShareAccess( pFileObject,
1287                                      &pFcb->ShareAccess);
1288
1289                 //
1290                 // We don't need the name array after the user closes the handle on the file
1291                 //
1292
1293                 if( pCcb->NameArray != NULL)
1294                 {
1295
1296                     AFSFreeNameArray( pCcb->NameArray);
1297
1298                     pCcb->NameArray = NULL;
1299                 }
1300
1301                 //
1302                 // Decrement the open child handle count
1303                 //
1304
1305                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1306
1307                 if( pParentObjectInfo != NULL)
1308                 {
1309
1310                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1311
1312                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1313
1314                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1315                                   AFS_TRACE_LEVEL_VERBOSE,
1316                                   "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1317                                   pParentObjectInfo,
1318                                   lCount);
1319                 }
1320
1321                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1322
1323                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1324
1325                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1326                               AFS_TRACE_LEVEL_VERBOSE,
1327                               "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
1328                               pFcb,
1329                               lCount);
1330
1331                 break;
1332             }
1333
1334             case AFS_SPECIAL_SHARE_FCB:
1335             {
1336
1337                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1338                               AFS_TRACE_LEVEL_VERBOSE,
1339                               "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
1340                               &pFcb->NPFcb->Resource,
1341                               PsGetCurrentThread());
1342
1343                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1344                                 TRUE);
1345
1346                 ASSERT( pFcb->OpenHandleCount != 0);
1347
1348                 //
1349                 // Decrement the open child handle count
1350                 //
1351
1352                 pParentObjectInfo = pObjectInfo->ParentObjectInformation;
1353
1354                 if( pParentObjectInfo != NULL &&
1355                     pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0)
1356                 {
1357
1358                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1359
1360                     AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1361                                   AFS_TRACE_LEVEL_VERBOSE,
1362                                   "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
1363                                   pParentObjectInfo,
1364                                   lCount);
1365                 }
1366
1367                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1368
1369                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1370
1371                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1372                               AFS_TRACE_LEVEL_VERBOSE,
1373                               "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
1374                               pFcb,
1375                               lCount);
1376
1377                 break;
1378             }
1379
1380             default:
1381
1382                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1383                               AFS_TRACE_LEVEL_WARNING,
1384                               "AFSCleanup Processing unknown node type %d\n",
1385                               pFcb->Header.NodeTypeCode);
1386
1387                 break;
1388         }
1389
1390
1391 try_exit:
1392
1393         if( pResultCB != NULL)
1394         {
1395
1396             AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_32_TAG);
1397         }
1398
1399         if( pFileObject != NULL)
1400         {
1401
1402             //
1403             // Setup the fileobject flags to indicate cleanup is complete.
1404             //
1405
1406             SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1407         }
1408
1409         //
1410         // Complete the request
1411         //
1412
1413         AFSCompleteRequest( Irp, ntStatus);
1414     }
1415     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
1416     {
1417
1418         AFSDbgLogMsg( 0,
1419                       0,
1420                       "EXCEPTION - AFSCleanup\n");
1421
1422         AFSDumpTraceFilesFnc();
1423     }
1424
1425     return ntStatus;
1426 }