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