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