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