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