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