Windows: Call AFSExeceptionFilter for all exceptions
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCleanup.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011, 2012, 2013 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, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16  *   nor the names of their contributors may be used to endorse or promote
17  *   products derived from this software without specific prior written
18  *   permission from Kernel Drivers, LLC and Your File System, Inc.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 //
34 // File: AFSCleanup.cpp
35 //
36
37 #include "AFSCommon.h"
38
39 //
40 // Function: AFSCleanup
41 //
42 // Description:
43 //
44 //      This function is the IRP_MJ_CLEANUP dispatch handler
45 //
46 // Return:
47 //
48 //       A status is returned for the handling of this request
49 //
50
51 NTSTATUS
52 AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
53             IN PIRP Irp)
54 {
55     UNREFERENCED_PARAMETER(LibDeviceObject);
56     NTSTATUS ntStatus = STATUS_SUCCESS;
57     AFSDeviceExt *pDeviceExt = NULL;
58     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
59     AFSFcb *pFcb = NULL;
60     AFSCcb *pCcb = NULL;
61     PFILE_OBJECT pFileObject = NULL;
62     AFSFcb *pRootFcb = NULL;
63     AFSDeviceExt *pControlDeviceExt = NULL;
64     IO_STATUS_BLOCK stIoSB;
65     AFSObjectInfoCB *pObjectInfo = NULL;
66     AFSObjectInfoCB *pParentObjectInfo = NULL;
67     AFSFileCleanupCB stFileCleanup;
68     AFSFileCleanupResultCB *pResultCB = NULL;
69     ULONG ulResultLen = 0;
70     ULONG   ulNotificationFlags = 0;
71     LONG    lCount;
72
73     __try
74     {
75
76         if( AFSRDRDeviceObject == NULL)
77         {
78
79             //
80             // Let this through, it's a cleanup on the library control device
81             //
82
83             try_return( ntStatus);
84         }
85
86         pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
87
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         if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
108         {
109
110             pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
111                                                    &pObjectInfo->ParentFileId,
112                                                    FALSE);
113         }
114
115         pRootFcb = pObjectInfo->VolumeCB->RootFcb;
116
117         RtlZeroMemory( &stFileCleanup,
118                        sizeof( AFSFileCleanupCB));
119
120         stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
121
122         stFileCleanup.Identifier = (ULONGLONG)pFileObject;
123
124         //
125         // Allocate our return buffer
126         //
127
128         pResultCB = (AFSFileCleanupResultCB *)AFSExAllocatePoolWithTag( PagedPool,
129                                                                         PAGE_SIZE,
130                                                                         AFS_GENERIC_MEMORY_32_TAG);
131
132         if( pResultCB == NULL)
133         {
134
135             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
136         }
137
138         RtlZeroMemory( pResultCB,
139                        PAGE_SIZE);
140
141         ulResultLen = PAGE_SIZE;
142
143
144         //
145         // Perform the cleanup functionality depending on the type of node it is
146         //
147
148         switch( pFcb->Header.NodeTypeCode)
149         {
150
151             case AFS_ROOT_ALL:
152             {
153
154                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
155                               AFS_TRACE_LEVEL_VERBOSE,
156                               "AFSCleanup Acquiring GlobalRoot lock %p EXCL %08lX\n",
157                               &pFcb->NPFcb->Resource,
158                               PsGetCurrentThread()));
159
160                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
161                                   TRUE);
162
163                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
164                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
165                                     pCcb);
166
167                 ASSERT( pFcb->OpenHandleCount != 0);
168
169                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
170
171                 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
172                               AFS_TRACE_LEVEL_VERBOSE,
173                               "AFSCleanup (RootAll) Decrement handle count on Fcb %p Cnt %d\n",
174                               pFcb,
175                               lCount));
176
177                 AFSReleaseResource( &pFcb->NPFcb->Resource);
178
179                 break;
180             }
181
182             case AFS_IOCTL_FCB:
183             {
184
185                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
186                               AFS_TRACE_LEVEL_VERBOSE,
187                               "AFSCleanup Acquiring PIOCtl lock %p EXCL %08lX\n",
188                               &pFcb->NPFcb->Resource,
189                               PsGetCurrentThread()));
190
191                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
192                                   TRUE);
193
194                 ASSERT( pFcb->OpenHandleCount != 0);
195
196                 //
197                 // Decrement the open child handle count
198                 //
199
200                 if( pParentObjectInfo != NULL &&
201                     pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0)
202                 {
203
204                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
205
206                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
207                                   AFS_TRACE_LEVEL_VERBOSE,
208                                   "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %p Cnt %d\n",
209                                   pParentObjectInfo,
210                                   lCount));
211                 }
212
213                 AFSReleaseResource( &pFcb->NPFcb->Resource);
214
215                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
216
217                 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
218                               AFS_TRACE_LEVEL_VERBOSE,
219                               "AFSCleanup (IOCtl) Decrement handle count on Fcb %p Cnt %d\n",
220                               pFcb,
221                               lCount));
222
223                 break;
224             }
225
226             //
227             // This Fcb represents a file
228             //
229
230             case AFS_FILE_FCB:
231             {
232
233                 //
234                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
235                 //
236
237                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
238                               AFS_TRACE_LEVEL_VERBOSE,
239                               "AFSCleanup Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
240                               &pFcb->NPFcb->SectionObjectResource,
241                               PsGetCurrentThread()));
242
243                 AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
244                                 TRUE);
245
246                 __try
247                 {
248
249                     //
250                     // If the handle has write permission ...
251                     //
252
253                     if( ((pCcb->GrantedAccess & FILE_WRITE_DATA) || pFcb->OpenHandleCount == 1) &&
254                         CcIsFileCached( pIrpSp->FileObject))
255                     {
256
257                         CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
258                                       NULL,
259                                       0,
260                                       &stIoSB);
261
262                         if( !NT_SUCCESS( stIoSB.Status))
263                         {
264
265                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
266                                           AFS_TRACE_LEVEL_ERROR,
267                                           "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
268                                           &pCcb->FullFileName,
269                                           pObjectInfo->FileId.Cell,
270                                           pObjectInfo->FileId.Volume,
271                                           pObjectInfo->FileId.Vnode,
272                                           pObjectInfo->FileId.Unique,
273                                           stIoSB.Status,
274                                           stIoSB.Information));
275
276                             ntStatus = stIoSB.Status;
277                         }
278
279                         if ( ( pFcb->OpenHandleCount == 1 ||
280                                BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE)) &&
281                              pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
282                         {
283
284                             if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
285                                                        NULL,
286                                                        0,
287                                                        FALSE))
288                             {
289
290                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
291                                               AFS_TRACE_LEVEL_WARNING,
292                                               "AFSCleanup CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
293                                               pObjectInfo->FileId.Cell,
294                                               pObjectInfo->FileId.Volume,
295                                               pObjectInfo->FileId.Vnode,
296                                               pObjectInfo->FileId.Unique));
297
298                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
299                             }
300                             else
301                             {
302                                 ClearFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
303                             }
304                         }
305                     }
306
307                     //
308                     // Uninitialize the cache map. This call is unconditional.
309                     //
310
311                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
312                                   AFS_TRACE_LEVEL_VERBOSE,
313                                   "AFSCleanup Tearing down cache map for Fcb %p FileObject %p\n",
314                                   pFcb,
315                                   pFileObject));
316
317                     CcUninitializeCacheMap( pFileObject,
318                                             NULL,
319                                             NULL);
320                 }
321                 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
322                 {
323
324                     ntStatus = GetExceptionCode();
325
326                     AFSDbgTrace(( 0,
327                                   0,
328                                   "EXCEPTION - AFSCleanup Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
329                                   pObjectInfo->FileId.Cell,
330                                   pObjectInfo->FileId.Volume,
331                                   pObjectInfo->FileId.Vnode,
332                                   pObjectInfo->FileId.Unique,
333                                   ntStatus));
334
335                     SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
336                 }
337
338                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
339                               AFS_TRACE_LEVEL_VERBOSE,
340                               "AFSCleanup Releasing Fcb SectionObject lock %p EXCL %08lX\n",
341                               &pFcb->NPFcb->SectionObjectResource,
342                               PsGetCurrentThread()));
343
344                 AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
345
346                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
347                               AFS_TRACE_LEVEL_VERBOSE,
348                               "AFSCleanup Acquiring Fcb lock %p EXCL %08lX\n",
349                               &pFcb->NPFcb->Resource,
350                               PsGetCurrentThread()));
351
352                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
353                                 TRUE);
354
355                 //
356                 // Unlock all outstanding locks on the file, again, unconditionally
357                 //
358
359                 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
360                                            pFileObject,
361                                            IoGetRequestorProcess( Irp),
362                                            NULL);
363
364                 //
365                 // Tell the service to unlock all on the file
366                 //
367
368                 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
369
370                 //
371                 // Perform some final common processing
372                 //
373
374                 ASSERT( pFcb->OpenHandleCount != 0);
375
376                 if( pParentObjectInfo != NULL)
377                 {
378
379                     stFileCleanup.ParentId = pParentObjectInfo->FileId;
380                 }
381
382                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
383
384                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
385                 {
386
387                     stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
388
389                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
390
391                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
392                     {
393
394                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
395
396                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
397                     }
398
399                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
400                     {
401
402                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
403
404                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
405                     }
406
407                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
408                     {
409
410                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
411
412                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
413                     }
414
415                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
416                     {
417
418                         stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
419
420                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
421                     }
422                 }
423
424                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
425                 {
426
427                     stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
428                 }
429
430                 //
431                 // If the count has dropped to one and there is a pending delete
432                 // then delete the node.  The final count will be decremented just
433                 // before the Fcb->NPFcb->Resource is released.
434                 //
435
436                 if( pFcb->OpenHandleCount == 1 &&
437                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
438                 {
439
440                     ntStatus = STATUS_SUCCESS;
441
442                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
443
444                     //
445                     // Indicate the file access mode that is being released
446                     //
447
448                     stFileCleanup.FileAccess = pCcb->FileAccess;
449
450                     //
451                     // Push the request to the service
452                     //
453
454                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
455                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
456                                                   &pCcb->AuthGroup,
457                                                   &pCcb->DirectoryCB->NameInformation.FileName,
458                                                   &pObjectInfo->FileId,
459                                                   pObjectInfo->VolumeCB->VolumeInformation.Cell,
460                                                   pObjectInfo->VolumeCB->VolumeInformation.CellLength,
461                                                   &stFileCleanup,
462                                                   sizeof( AFSFileCleanupCB),
463                                                   pResultCB,
464                                                   &ulResultLen);
465
466                     if( !NT_SUCCESS( ntStatus) &&
467                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
468                     {
469
470                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
471                                       AFS_TRACE_LEVEL_ERROR,
472                                       "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
473                                       &pCcb->FullFileName,
474                                       ntStatus));
475
476                         ntStatus = STATUS_SUCCESS;
477
478                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
479                     }
480                     else
481                     {
482
483                         ntStatus = STATUS_SUCCESS;
484
485                         if ( --pObjectInfo->Links < 1)
486                         {
487
488                             //
489                             // Stop anything possibly in process
490                             //
491
492                             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
493                                           AFS_TRACE_LEVEL_VERBOSE,
494                                           "AFSCleanup Acquiring Fcb extents lock %p EXCL %08lX\n",
495                                           &pFcb->NPFcb->Specific.File.ExtentsResource,
496                                           PsGetCurrentThread()));
497
498                             AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
499                                             TRUE);
500
501                             pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
502
503                             KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
504                                         0,
505                                         FALSE);
506
507                             //
508                             // The file has been deleted since the Link count is zero
509                             //
510
511                             AFSDeleteFcbExtents( pFcb);
512
513                             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
514                                           AFS_TRACE_LEVEL_VERBOSE,
515                                           "AFSCleanup Releasing Fcb extents lock %p EXCL %08lX\n",
516                                           &pFcb->NPFcb->Specific.File.ExtentsResource,
517                                           PsGetCurrentThread()));
518
519                             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
520                         }
521
522                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
523                                       AFS_TRACE_LEVEL_VERBOSE,
524                                       "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
525                                       &pCcb->FullFileName,
526                                       pCcb->DirectoryCB));
527
528                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
529
530                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
531
532                         ASSERT( pParentObjectInfo != NULL);
533
534                         if ( pParentObjectInfo != NULL)
535                         {
536
537                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
538                                             TRUE);
539
540                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
541                             {
542
543                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
544
545                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
546                             }
547                             else
548                             {
549
550                                 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
551                             }
552
553                             //
554                             // Now that the service has the entry has deleted we need to remove it from the parent
555                             // tree so another lookup on the node will fail
556                             //
557
558                             if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
559                             {
560
561                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
562                                               AFS_TRACE_LEVEL_VERBOSE,
563                                               "AFSCleanup DE %p for %wZ removing entry\n",
564                                               pCcb->DirectoryCB,
565                                               &pCcb->DirectoryCB->NameInformation.FileName));
566
567                                 AFSRemoveNameEntry( pParentObjectInfo,
568                                                     pCcb->DirectoryCB);
569                             }
570                             else
571                             {
572
573                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
574                                               AFS_TRACE_LEVEL_VERBOSE,
575                                               "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
576                                               pCcb->DirectoryCB,
577                                               &pCcb->DirectoryCB->NameInformation.FileName));
578                             }
579
580                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
581
582                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
583                                                             pCcb,
584                                                             (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
585                                                             (ULONG)FILE_ACTION_REMOVED);
586                         }
587                         else
588                         {
589                             if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
590                             {
591
592                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
593                                               AFS_TRACE_LEVEL_VERBOSE,
594                                               "AFSCleanup DE %p for %wZ NOT removing entry due to pParentObjectInfo == NULL\n",
595                                               pCcb->DirectoryCB,
596                                               &pCcb->DirectoryCB->NameInformation.FileName));
597                             }
598                         }
599                     }
600                 }
601                 else
602                 {
603
604                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED) &&
605                         pParentObjectInfo != NULL)
606                     {
607
608                         ULONG ulNotifyFilter = 0;
609
610                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
611
612                         ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
613
614                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
615                                                         pCcb,
616                                                         (ULONG)ulNotifyFilter,
617                                                         (ULONG)FILE_ACTION_MODIFIED);
618                     }
619
620
621                     //
622                     // Whenever a handle with write access or the last handle is closed
623                     // notify the service to FSync the file.  If the redirector is holding
624                     // dirty extents, flush them to the service.  This is a bit aggressive
625                     // but it ensures cache coherency.
626                     //
627
628                     if( (pCcb->GrantedAccess & FILE_WRITE_DATA) || (pFcb->OpenHandleCount == 1))
629                     {
630
631                         if ( pFcb->Specific.File.ExtentsDirtyCount != 0)
632                         {
633
634                             AFSFlushExtents( pFcb,
635                                              &pCcb->AuthGroup);
636                         }
637
638                         ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
639                     }
640
641                     if( pFcb->OpenHandleCount == 1)
642                     {
643
644                         //
645                         // Wait for any outstanding queued flushes to complete
646                         //
647
648                         AFSWaitOnQueuedFlushes( pFcb);
649
650                         AFSTearDownFcbExtents( pFcb,
651                                                &pCcb->AuthGroup);
652                     }
653
654                     //
655                     // Indicate the file access mode that is being released
656                     //
657
658                     stFileCleanup.FileAccess = pCcb->FileAccess;
659
660                     //
661                     // Remove the share access at this time since we may not get the close for sometime on this FO.
662                     //
663
664                     IoRemoveShareAccess( pFileObject,
665                                          &pFcb->ShareAccess);
666
667
668                     //
669                     // We don't need the name array after the user closes the handle on the file
670                     //
671
672                     if( pCcb->NameArray != NULL)
673                     {
674
675                         AFSFreeNameArray( pCcb->NameArray);
676
677                         pCcb->NameArray = NULL;
678                     }
679
680                     //
681                     // Release the Fcb Resource across the call to the service
682                     // which may block for quite a while if flushing of the
683                     // data is required.
684                     //
685
686                     AFSReleaseResource( &pFcb->NPFcb->Resource);
687
688                     //
689                     // Push the request to the service
690                     //
691
692                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
693                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
694                                                   &pCcb->AuthGroup,
695                                                   &pCcb->DirectoryCB->NameInformation.FileName,
696                                                   &pObjectInfo->FileId,
697                                                   pObjectInfo->VolumeCB->VolumeInformation.Cell,
698                                                   pObjectInfo->VolumeCB->VolumeInformation.CellLength,
699                                                   &stFileCleanup,
700                                                   sizeof( AFSFileCleanupCB),
701                                                   pResultCB,
702                                                   &ulResultLen);
703
704                     //
705                     // Regain exclusive access to the Fcb
706                     //
707
708                     AFSAcquireExcl( &pFcb->NPFcb->Resource,
709                                     TRUE);
710
711                     if ( NT_SUCCESS( ntStatus))
712                     {
713
714                         if ( pParentObjectInfo != NULL)
715                         {
716
717                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
718                                             TRUE);
719
720                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
721                             {
722
723                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
724
725                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
726                             }
727
728                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
729                         }
730                     }
731
732                     ntStatus = STATUS_SUCCESS;
733                 }
734
735                 //
736                 // Decrement the open child handle count
737                 //
738
739                 if( pParentObjectInfo != NULL)
740                 {
741
742                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
743
744                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
745
746                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
747                                   AFS_TRACE_LEVEL_VERBOSE,
748                                   "AFSCleanup (File) Decrement child open handle count on Parent object %p Cnt %d\n",
749                                   pParentObjectInfo,
750                                   lCount));
751                 }
752
753
754                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
755
756                 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
757                               AFS_TRACE_LEVEL_VERBOSE,
758                               "AFSCleanup (File) Decrement handle count on Fcb %p Cnt %d\n",
759                               pFcb,
760                               lCount));
761
762                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
763                 {
764                     //
765                     // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
766                     //
767
768                     lCount = AFSObjectInfoIncrement( pObjectInfo,
769                                                      AFS_OBJECT_REFERENCE_INVALIDATION);
770
771                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
772                                   AFS_TRACE_LEVEL_VERBOSE,
773                                   "AFSCleanup Setting Purge on Close Increment count on object %p Cnt %d\n",
774                                   pObjectInfo,
775                                   lCount));
776
777                     ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
778
779                     AFSReleaseResource( &pFcb->NPFcb->Resource);
780
781                     AFSPerformObjectInvalidate( pObjectInfo,
782                                                 AFS_INVALIDATE_DATA_VERSION);
783                 }
784                 else
785                 {
786
787                     AFSReleaseResource( &pFcb->NPFcb->Resource);
788                 }
789
790                 break;
791             }
792
793             //
794             // Root or directory node
795             //
796
797             case AFS_ROOT_FCB:
798             {
799
800                 //
801                 // Set the root Fcb to this node
802                 //
803
804                 pRootFcb = pFcb;
805
806                 //
807                 // Fall through to below
808                 //
809             }
810
811             case AFS_DIRECTORY_FCB:
812             {
813
814                 //
815                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
816                 //
817
818                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
819                               AFS_TRACE_LEVEL_VERBOSE,
820                               "AFSCleanup Acquiring Dcb lock %p EXCL %08lX\n",
821                               &pFcb->NPFcb->Resource,
822                               PsGetCurrentThread()));
823
824                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
825                                   TRUE);
826
827                 //
828                 // Perform some final common processing
829                 //
830
831                 ASSERT( pFcb->OpenHandleCount != 0);
832
833                 if( pParentObjectInfo != NULL)
834                 {
835
836                     stFileCleanup.ParentId = pParentObjectInfo->FileId;
837                 }
838
839                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
840
841                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
842                 {
843
844                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
845
846                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
847                     {
848
849                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
850
851                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
852                     }
853
854                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
855                     {
856
857                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
858
859                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
860                     }
861
862                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
863                     {
864
865                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
866
867                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
868                     }
869                 }
870
871                 //
872                 // If the count has dropped to one and there is a pending delete
873                 // then delete the node.  The final count will be decremented just
874                 // before the Fcb->NPFcb->Resource is released.
875                 //
876
877                 if( pFcb->OpenHandleCount == 1 &&
878                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
879                 {
880
881                     //
882                     // Try to notify the service about the delete
883                     //
884
885                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
886
887                     //
888                     // Indicate the file access mode that is being released
889                     //
890
891                     stFileCleanup.FileAccess = pCcb->FileAccess;
892
893                     //
894                     // Push the request to the service
895                     //
896
897                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
898                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
899                                                   &pCcb->AuthGroup,
900                                                   &pCcb->DirectoryCB->NameInformation.FileName,
901                                                   &pObjectInfo->FileId,
902                                                   pObjectInfo->VolumeCB->VolumeInformation.Cell,
903                                                   pObjectInfo->VolumeCB->VolumeInformation.CellLength,
904                                                   &stFileCleanup,
905                                                   sizeof( AFSFileCleanupCB),
906                                                   pResultCB,
907                                                   &ulResultLen);
908
909                     if( !NT_SUCCESS( ntStatus) &&
910                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
911                     {
912
913                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
914                                       AFS_TRACE_LEVEL_ERROR,
915                                       "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
916                                       &pCcb->FullFileName,
917                                       ntStatus));
918
919                         ntStatus = STATUS_SUCCESS;
920
921                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
922                     }
923                     else
924                     {
925
926                         ntStatus = STATUS_SUCCESS;
927
928                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
929                                       AFS_TRACE_LEVEL_VERBOSE,
930                                       "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
931                                       &pCcb->FullFileName,
932                                       pCcb->DirectoryCB));
933
934                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
935
936                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
937
938                         ASSERT( pParentObjectInfo != NULL);
939
940                         if ( pParentObjectInfo != NULL)
941                         {
942
943                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
944                                             TRUE);
945
946                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
947                             {
948
949                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
950
951                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
952                             }
953                             else
954                             {
955
956                                 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
957                             }
958
959                             //
960                             // Now that the service has the entry has deleted we need to remove it from the parent
961                             // tree so another lookup on the node will fail
962                             //
963
964                             if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
965                             {
966
967                                 AFSRemoveNameEntry( pParentObjectInfo,
968                                                     pCcb->DirectoryCB);
969                             }
970                             else
971                             {
972
973                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
974                                               AFS_TRACE_LEVEL_VERBOSE,
975                                               "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
976                                               pCcb->DirectoryCB,
977                                               &pCcb->DirectoryCB->NameInformation.FileName));
978                             }
979
980                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
981
982                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
983                                                             pCcb,
984                                                             (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
985                                                             (ULONG)FILE_ACTION_REMOVED);
986                         }
987                         else
988                         {
989                             if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
990                             {
991
992                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
993                                               AFS_TRACE_LEVEL_VERBOSE,
994                                               "AFSCleanup DE %p for %wZ NOT removing entry due to pParentObjectInfo == NULL\n",
995                                               pCcb->DirectoryCB,
996                                               &pCcb->DirectoryCB->NameInformation.FileName));
997                             }
998                         }
999                     }
1000                 }
1001
1002                 //
1003                 // If there have been any updates to the node then push it to
1004                 // the service
1005                 //
1006
1007                 else
1008                 {
1009
1010                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED) &&
1011                         pParentObjectInfo != NULL)
1012                     {
1013
1014                         ULONG ulNotifyFilter = 0;
1015
1016                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1017
1018                         ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1019
1020                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1021                                                         pCcb,
1022                                                         (ULONG)ulNotifyFilter,
1023                                                         (ULONG)FILE_ACTION_MODIFIED);
1024                     }
1025
1026                     //
1027                     // Indicate the file access mode that is being released
1028                     //
1029
1030                     stFileCleanup.FileAccess = pCcb->FileAccess;
1031
1032                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1033                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1034                                                   &pCcb->AuthGroup,
1035                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1036                                                   &pObjectInfo->FileId,
1037                                                   pObjectInfo->VolumeCB->VolumeInformation.Cell,
1038                                                   pObjectInfo->VolumeCB->VolumeInformation.CellLength,
1039                                                   &stFileCleanup,
1040                                                   sizeof( AFSFileCleanupCB),
1041                                                   pResultCB,
1042                                                   &ulResultLen);
1043
1044                     if ( NT_SUCCESS( ntStatus))
1045                     {
1046
1047                         if ( pParentObjectInfo != NULL)
1048                         {
1049
1050                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1051                                               TRUE);
1052
1053                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1054                             {
1055
1056                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1057
1058                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1059                             }
1060
1061                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1062                         }
1063                     }
1064
1065                     ntStatus = STATUS_SUCCESS;
1066                 }
1067
1068                 //
1069                 // Release the notification for this directory if there is one
1070                 //
1071
1072                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
1073                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
1074                                     pCcb);
1075
1076                 //
1077                 // Remove the share access at this time since we may not get the close for sometime on this FO.
1078                 //
1079
1080                 IoRemoveShareAccess( pFileObject,
1081                                      &pFcb->ShareAccess);
1082
1083                 //
1084                 // We don't need the name array after the user closes the handle on the file
1085                 //
1086
1087                 if( pCcb->NameArray != NULL)
1088                 {
1089
1090                     AFSFreeNameArray( pCcb->NameArray);
1091
1092                     pCcb->NameArray = NULL;
1093                 }
1094
1095                 //
1096                 // Decrement the open child handle count
1097                 //
1098
1099                 if( pParentObjectInfo != NULL)
1100                 {
1101
1102                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1103
1104                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1105
1106                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1107                                   AFS_TRACE_LEVEL_VERBOSE,
1108                                   "AFSCleanup (Dir) Decrement child open handle count on Parent object %p Cnt %d\n",
1109                                   pParentObjectInfo,
1110                                   lCount));
1111                 }
1112
1113                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1114
1115                 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1116                               AFS_TRACE_LEVEL_VERBOSE,
1117                               "AFSCleanup (Dir) Decrement handle count on Fcb %p Cnt %d\n",
1118                               pFcb,
1119                               lCount));
1120
1121                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1122
1123                 break;
1124             }
1125
1126             case AFS_SYMBOLIC_LINK_FCB:
1127             case AFS_MOUNT_POINT_FCB:
1128             case AFS_DFS_LINK_FCB:
1129             case AFS_INVALID_FCB:
1130             {
1131
1132                 //
1133                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
1134                 //
1135
1136                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1137                               AFS_TRACE_LEVEL_VERBOSE,
1138                               "AFSCleanup (MP/SL) Acquiring Dcb lock %p EXCL %08lX\n",
1139                               &pFcb->NPFcb->Resource,
1140                               PsGetCurrentThread()));
1141
1142                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1143                                   TRUE);
1144
1145                 //
1146                 // Perform some final common processing
1147                 //
1148
1149                 ASSERT( pFcb->OpenHandleCount != 0);
1150
1151                 if( pParentObjectInfo != NULL)
1152                 {
1153
1154                     stFileCleanup.ParentId = pParentObjectInfo->FileId;
1155                 }
1156
1157                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1158
1159                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1160                 {
1161
1162                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
1163
1164                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
1165                     {
1166
1167                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
1168
1169                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1170                     }
1171
1172                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
1173                     {
1174
1175                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
1176
1177                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1178                     }
1179
1180                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
1181                     {
1182
1183                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1184
1185                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1186                     }
1187                 }
1188
1189                 //
1190                 // If the count has dropped to one and there is a pending delete
1191                 // then delete the node.  The final count will be decremented just
1192                 // before the Fcb->NPFcb->Resource is released.
1193                 //
1194
1195                 if( pFcb->OpenHandleCount == 1 &&
1196                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1197                 {
1198
1199                     //
1200                     // Try to notify the service about the delete
1201                     //
1202
1203                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
1204
1205                     //
1206                     // Indicate the file access mode that is being released
1207                     //
1208
1209                     stFileCleanup.FileAccess = pCcb->FileAccess;
1210
1211                     //
1212                     // Push the request to the service
1213                     //
1214
1215                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1216                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1217                                                   &pCcb->AuthGroup,
1218                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1219                                                   &pObjectInfo->FileId,
1220                                                   pObjectInfo->VolumeCB->VolumeInformation.Cell,
1221                                                   pObjectInfo->VolumeCB->VolumeInformation.CellLength,
1222                                                   &stFileCleanup,
1223                                                   sizeof( AFSFileCleanupCB),
1224                                                   pResultCB,
1225                                                   &ulResultLen);
1226
1227                     if( !NT_SUCCESS( ntStatus) &&
1228                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
1229                     {
1230
1231                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1232                                       AFS_TRACE_LEVEL_ERROR,
1233                                       "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
1234                                       &pCcb->FullFileName,
1235                                       ntStatus));
1236
1237                         ntStatus = STATUS_SUCCESS;
1238
1239                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1240                     }
1241                     else
1242                     {
1243
1244                         ntStatus = STATUS_SUCCESS;
1245
1246                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1247                                       AFS_TRACE_LEVEL_VERBOSE,
1248                                       "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1249                                       &pCcb->FullFileName,
1250                                       pCcb->DirectoryCB));
1251
1252                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1253
1254                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1255
1256                         ASSERT( pParentObjectInfo != NULL);
1257
1258                         if ( pParentObjectInfo != NULL)
1259                         {
1260
1261                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1262                                             TRUE);
1263
1264                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1265                             {
1266
1267                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1268
1269                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1270                             }
1271                             else
1272                             {
1273                                 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
1274                             }
1275
1276                             //
1277                             // Now that the service has the entry has deleted we need to remove it from the parent
1278                             // tree so another lookup on the node will fail
1279                             //
1280
1281                             if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1282                             {
1283
1284                                 AFSRemoveNameEntry( pParentObjectInfo,
1285                                                     pCcb->DirectoryCB);
1286                             }
1287                             else
1288                             {
1289
1290                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1291                                               AFS_TRACE_LEVEL_VERBOSE,
1292                                               "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1293                                               pCcb->DirectoryCB,
1294                                               &pCcb->DirectoryCB->NameInformation.FileName));
1295                             }
1296
1297                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1298
1299                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1300                                                             pCcb,
1301                                                             (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1302                                                             (ULONG)FILE_ACTION_REMOVED);
1303                         }
1304                         else
1305                         {
1306
1307                             if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1308                             {
1309
1310                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1311                                               AFS_TRACE_LEVEL_VERBOSE,
1312                                               "AFSCleanup DE %p for %wZ NOT removing entry due to pParentObjectInfo == NULL\n",
1313                                               pCcb->DirectoryCB,
1314                                               &pCcb->DirectoryCB->NameInformation.FileName));
1315                             }
1316                         }
1317                     }
1318                 }
1319
1320                 //
1321                 // If there have been any updates to the node then push it to
1322                 // the service
1323                 //
1324
1325                 else
1326                 {
1327
1328                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED) &&
1329                         pParentObjectInfo != NULL)
1330                     {
1331
1332                         ULONG ulNotifyFilter = 0;
1333
1334                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1335
1336                         ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1337
1338                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1339                                                         pCcb,
1340                                                         (ULONG)ulNotifyFilter,
1341                                                         (ULONG)FILE_ACTION_MODIFIED);
1342                     }
1343
1344                     //
1345                     // Indicate the file access mode that is being released
1346                     //
1347
1348                     stFileCleanup.FileAccess = pCcb->FileAccess;
1349
1350                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1351                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1352                                                   &pCcb->AuthGroup,
1353                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1354                                                   &pObjectInfo->FileId,
1355                                                   pObjectInfo->VolumeCB->VolumeInformation.Cell,
1356                                                   pObjectInfo->VolumeCB->VolumeInformation.CellLength,
1357                                                   &stFileCleanup,
1358                                                   sizeof( AFSFileCleanupCB),
1359                                                   pResultCB,
1360                                                   &ulResultLen);
1361
1362                     if ( NT_SUCCESS( ntStatus))
1363                     {
1364
1365                         if ( pParentObjectInfo != NULL)
1366                         {
1367
1368                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1369                                               TRUE);
1370
1371                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1372                             {
1373
1374                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1375
1376                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1377                             }
1378
1379                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1380                         }
1381                     }
1382
1383                     ntStatus = STATUS_SUCCESS;
1384                 }
1385
1386                 //
1387                 // Remove the share access at this time since we may not get the close for sometime on this FO.
1388                 //
1389
1390                 IoRemoveShareAccess( pFileObject,
1391                                      &pFcb->ShareAccess);
1392
1393                 //
1394                 // We don't need the name array after the user closes the handle on the file
1395                 //
1396
1397                 if( pCcb->NameArray != NULL)
1398                 {
1399
1400                     AFSFreeNameArray( pCcb->NameArray);
1401
1402                     pCcb->NameArray = NULL;
1403                 }
1404
1405                 //
1406                 // Decrement the open child handle count
1407                 //
1408
1409                 if( pParentObjectInfo != NULL)
1410                 {
1411
1412                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1413
1414                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1415
1416                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1417                                   AFS_TRACE_LEVEL_VERBOSE,
1418                                   "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %p Cnt %d\n",
1419                                   pParentObjectInfo,
1420                                   lCount));
1421                 }
1422
1423                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1424
1425                 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1426                               AFS_TRACE_LEVEL_VERBOSE,
1427                               "AFSCleanup (MP/SL) Decrement handle count on Fcb %p Cnt %d\n",
1428                               pFcb,
1429                               lCount));
1430
1431                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1432
1433                 break;
1434             }
1435
1436             case AFS_SPECIAL_SHARE_FCB:
1437             {
1438
1439                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1440                               AFS_TRACE_LEVEL_VERBOSE,
1441                               "AFSCleanup Acquiring SPECIAL SHARE lock %p EXCL %08lX\n",
1442                               &pFcb->NPFcb->Resource,
1443                               PsGetCurrentThread()));
1444
1445                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1446                                 TRUE);
1447
1448                 ASSERT( pFcb->OpenHandleCount != 0);
1449
1450                 //
1451                 // Decrement the open child handle count
1452                 //
1453
1454                 if( pParentObjectInfo != NULL &&
1455                     pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0)
1456                 {
1457
1458                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1459
1460                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1461                                   AFS_TRACE_LEVEL_VERBOSE,
1462                                   "AFSCleanup (Share) Decrement child open handle count on Parent object %p Cnt %d\n",
1463                                   pParentObjectInfo,
1464                                   lCount));
1465                 }
1466
1467                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1468
1469                 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1470                               AFS_TRACE_LEVEL_VERBOSE,
1471                               "AFSCleanup (Share) Decrement handle count on Fcb %p Cnt %d\n",
1472                               pFcb,
1473                               lCount));
1474
1475                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1476
1477                 break;
1478             }
1479
1480             default:
1481
1482                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1483                               AFS_TRACE_LEVEL_ERROR,
1484                               "AFSCleanup Processing unknown node type %d\n",
1485                               pFcb->Header.NodeTypeCode));
1486
1487                 break;
1488         }
1489
1490
1491 try_exit:
1492
1493         if ( pParentObjectInfo != NULL)
1494         {
1495
1496             AFSReleaseObjectInfo( &pParentObjectInfo);
1497         }
1498
1499         if( pResultCB != NULL)
1500         {
1501
1502             AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_32_TAG);
1503         }
1504
1505         if( pFileObject != NULL)
1506         {
1507
1508             //
1509             // Setup the fileobject flags to indicate cleanup is complete.
1510             //
1511
1512             SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1513         }
1514
1515         //
1516         // Complete the request
1517         //
1518
1519         AFSCompleteRequest( Irp, ntStatus);
1520     }
1521     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
1522     {
1523
1524         AFSDbgTrace(( 0,
1525                       0,
1526                       "EXCEPTION - AFSCleanup\n"));
1527
1528         AFSDumpTraceFilesFnc();
1529     }
1530
1531     return ntStatus;
1532 }