Windows: Replace ParentObjectInformation 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     UNREFERENCED_PARAMETER(LibDeviceObject);
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         if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
110         {
111
112             pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
113                                                    &pObjectInfo->ParentFileId);
114         }
115
116         pRootFcb = pObjectInfo->VolumeCB->RootFcb;
117
118         RtlZeroMemory( &stFileCleanup,
119                        sizeof( AFSFileCleanupCB));
120
121         stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
122
123         stFileCleanup.Identifier = (ULONGLONG)pFileObject;
124
125         //
126         // Allocate our return buffer
127         //
128
129         pResultCB = (AFSFileCleanupResultCB *)AFSExAllocatePoolWithTag( PagedPool,
130                                                                         PAGE_SIZE,
131                                                                         AFS_GENERIC_MEMORY_32_TAG);
132
133         if( pResultCB == NULL)
134         {
135
136             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
137         }
138
139         RtlZeroMemory( pResultCB,
140                        PAGE_SIZE);
141
142         ulResultLen = PAGE_SIZE;
143
144
145         //
146         // Perform the cleanup functionality depending on the type of node it is
147         //
148
149         switch( pFcb->Header.NodeTypeCode)
150         {
151
152             case AFS_ROOT_ALL:
153             {
154
155                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
156                               AFS_TRACE_LEVEL_VERBOSE,
157                               "AFSCleanup Acquiring GlobalRoot lock %p EXCL %08lX\n",
158                               &pFcb->NPFcb->Resource,
159                               PsGetCurrentThread());
160
161                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
162                                   TRUE);
163
164                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
165                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
166                                     pCcb);
167
168                 ASSERT( pFcb->OpenHandleCount != 0);
169
170                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
171
172                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
173                               AFS_TRACE_LEVEL_VERBOSE,
174                               "AFSCleanup (RootAll) Decrement handle count on Fcb %p Cnt %d\n",
175                               pFcb,
176                               lCount);
177
178                 AFSReleaseResource( &pFcb->NPFcb->Resource);
179
180                 break;
181             }
182
183             case AFS_IOCTL_FCB:
184             {
185
186                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
187                               AFS_TRACE_LEVEL_VERBOSE,
188                               "AFSCleanup Acquiring PIOCtl lock %p EXCL %08lX\n",
189                               &pFcb->NPFcb->Resource,
190                               PsGetCurrentThread());
191
192                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
193                                   TRUE);
194
195                 ASSERT( pFcb->OpenHandleCount != 0);
196
197                 //
198                 // Decrement the open child handle count
199                 //
200
201                 if( pParentObjectInfo != NULL &&
202                     pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0)
203                 {
204
205                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
206
207                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
208                                   AFS_TRACE_LEVEL_VERBOSE,
209                                   "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %p Cnt %d\n",
210                                   pParentObjectInfo,
211                                   lCount);
212                 }
213
214                 AFSReleaseResource( &pFcb->NPFcb->Resource);
215
216                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
217
218                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
219                               AFS_TRACE_LEVEL_VERBOSE,
220                               "AFSCleanup (IOCtl) Decrement handle count on Fcb %p Cnt %d\n",
221                               pFcb,
222                               lCount);
223
224                 break;
225             }
226
227             //
228             // This Fcb represents a file
229             //
230
231             case AFS_FILE_FCB:
232             {
233
234                 //
235                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
236                 //
237
238                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
239                               AFS_TRACE_LEVEL_VERBOSE,
240                               "AFSCleanup Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
241                               &pFcb->NPFcb->SectionObjectResource,
242                               PsGetCurrentThread());
243
244                 AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
245                                 TRUE);
246
247                 //
248                 // If the handle has write permission ...
249                 //
250
251                 if( ((pCcb->GrantedAccess & FILE_WRITE_DATA) || pFcb->OpenHandleCount == 1) &&
252                     CcIsFileCached( pIrpSp->FileObject))
253                 {
254
255                     __try
256                     {
257
258                         CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
259                                       NULL,
260                                       0,
261                                       &stIoSB);
262
263                         if( !NT_SUCCESS( stIoSB.Status))
264                         {
265
266                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
267                                           AFS_TRACE_LEVEL_ERROR,
268                                           "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
269                                           &pCcb->FullFileName,
270                                           pObjectInfo->FileId.Cell,
271                                           pObjectInfo->FileId.Volume,
272                                           pObjectInfo->FileId.Vnode,
273                                           pObjectInfo->FileId.Unique,
274                                           stIoSB.Status,
275                                           stIoSB.Information);
276
277                             ntStatus = stIoSB.Status;
278                         }
279
280                         if ( ( pFcb->OpenHandleCount == 1 ||
281                                BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE)) &&
282                              pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
283                         {
284
285                             if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
286                                                        NULL,
287                                                        0,
288                                                        FALSE))
289                             {
290
291                                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
292                                               AFS_TRACE_LEVEL_WARNING,
293                                               "AFSCleanup CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
294                                               pObjectInfo->FileId.Cell,
295                                               pObjectInfo->FileId.Volume,
296                                               pObjectInfo->FileId.Vnode,
297                                               pObjectInfo->FileId.Unique);
298
299                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
300                             }
301                             else
302                             {
303                                 ClearFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
304                             }
305                         }
306                     }
307                     __except( EXCEPTION_EXECUTE_HANDLER)
308                     {
309
310                         ntStatus = GetExceptionCode();
311
312                         AFSDbgLogMsg( 0,
313                                       0,
314                                       "EXCEPTION - AFSCleanup Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
315                                       pObjectInfo->FileId.Cell,
316                                       pObjectInfo->FileId.Volume,
317                                       pObjectInfo->FileId.Vnode,
318                                       pObjectInfo->FileId.Unique,
319                                       ntStatus);
320
321                         SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
322                     }
323                 }
324
325                 //
326                 // Uninitialize the cache map. This call is unconditional.
327                 //
328
329                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
330                               AFS_TRACE_LEVEL_VERBOSE,
331                               "AFSCleanup Tearing down cache map for Fcb %p FileObject %p\n",
332                               pFcb,
333                               pFileObject);
334
335                 CcUninitializeCacheMap( pFileObject,
336                                         NULL,
337                                         NULL);
338
339
340                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
341                               AFS_TRACE_LEVEL_VERBOSE,
342                               "AFSCleanup Releasing Fcb SectionObject lock %p EXCL %08lX\n",
343                               &pFcb->NPFcb->SectionObjectResource,
344                               PsGetCurrentThread());
345
346                 AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
347
348                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
349                               AFS_TRACE_LEVEL_VERBOSE,
350                               "AFSCleanup Acquiring Fcb lock %p EXCL %08lX\n",
351                               &pFcb->NPFcb->Resource,
352                               PsGetCurrentThread());
353
354                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
355                                 TRUE);
356
357                 //
358                 // Unlock all outstanding locks on the file, again, unconditionally
359                 //
360
361                 (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
362                                            pFileObject,
363                                            IoGetRequestorProcess( Irp),
364                                            NULL);
365
366                 //
367                 // Tell the service to unlock all on the file
368                 //
369
370                 ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
371
372                 //
373                 // Perform some final common processing
374                 //
375
376                 ASSERT( pFcb->OpenHandleCount != 0);
377
378                 if( pParentObjectInfo != NULL)
379                 {
380
381                     stFileCleanup.ParentId = pParentObjectInfo->FileId;
382                 }
383
384                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
385
386                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
387                 {
388
389                     stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
390
391                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
392
393                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
394                     {
395
396                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
397
398                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
399                     }
400
401                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
402                     {
403
404                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
405
406                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
407                     }
408
409                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
410                     {
411
412                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
413
414                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
415                     }
416
417                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
418                     {
419
420                         stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
421
422                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
423                     }
424                 }
425
426                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
427                 {
428
429                     stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
430                 }
431
432                 //
433                 // If the count has dropped to one and there is a pending delete
434                 // then delete the node.  The final count will be decremented just
435                 // before the Fcb->NPFcb->Resource is released.
436                 //
437
438                 if( pFcb->OpenHandleCount == 1 &&
439                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
440                 {
441
442                     ntStatus = STATUS_SUCCESS;
443
444                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
445
446                     //
447                     // Indicate the file access mode that is being released
448                     //
449
450                     stFileCleanup.FileAccess = pCcb->FileAccess;
451
452                     //
453                     // Push the request to the service
454                     //
455
456                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
457                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
458                                                   &pCcb->AuthGroup,
459                                                   &pCcb->DirectoryCB->NameInformation.FileName,
460                                                   &pObjectInfo->FileId,
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                         AFSDbgLogMsg( 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                             AFSDbgLogMsg( 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                             AFSDbgLogMsg( 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                         AFSDbgLogMsg( 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                                 AFSDbgLogMsg( 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                                 AFSDbgLogMsg( 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                                 AFSDbgLogMsg( 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                                                   &stFileCleanup,
698                                                   sizeof( AFSFileCleanupCB),
699                                                   pResultCB,
700                                                   &ulResultLen);
701
702                     //
703                     // Regain exclusive access to the Fcb
704                     //
705
706                     AFSAcquireExcl( &pFcb->NPFcb->Resource,
707                                     TRUE);
708
709                     if ( NT_SUCCESS( ntStatus))
710                     {
711
712                         if ( pParentObjectInfo != NULL)
713                         {
714
715                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
716                                             TRUE);
717
718                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
719                             {
720
721                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
722
723                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
724                             }
725
726                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
727                         }
728                     }
729
730                     ntStatus = STATUS_SUCCESS;
731                 }
732
733                 //
734                 // Decrement the open child handle count
735                 //
736
737                 if( pParentObjectInfo != NULL)
738                 {
739
740                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
741
742                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
743
744                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
745                                   AFS_TRACE_LEVEL_VERBOSE,
746                                   "AFSCleanup (File) Decrement child open handle count on Parent object %p Cnt %d\n",
747                                   pParentObjectInfo,
748                                   lCount);
749                 }
750
751
752                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
753
754                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
755                               AFS_TRACE_LEVEL_VERBOSE,
756                               "AFSCleanup (File) Decrement handle count on Fcb %p Cnt %d\n",
757                               pFcb,
758                               lCount);
759
760                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE))
761                 {
762                     //
763                     // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
764                     //
765
766                     lCount = AFSObjectInfoIncrement( pObjectInfo,
767                                                      AFS_OBJECT_REFERENCE_INVALIDATION);
768
769                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
770                                   AFS_TRACE_LEVEL_VERBOSE,
771                                   "AFSCleanup Setting Purge on Close Increment count on object %p Cnt %d\n",
772                                   pObjectInfo,
773                                   lCount);
774
775                     ClearFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
776
777                     AFSReleaseResource( &pFcb->NPFcb->Resource);
778
779                     AFSPerformObjectInvalidate( pObjectInfo,
780                                                 AFS_INVALIDATE_DATA_VERSION);
781                 }
782                 else
783                 {
784
785                     AFSReleaseResource( &pFcb->NPFcb->Resource);
786                 }
787
788                 break;
789             }
790
791             //
792             // Root or directory node
793             //
794
795             case AFS_ROOT_FCB:
796             {
797
798                 //
799                 // Set the root Fcb to this node
800                 //
801
802                 pRootFcb = pFcb;
803
804                 //
805                 // Fall through to below
806                 //
807             }
808
809             case AFS_DIRECTORY_FCB:
810             {
811
812                 //
813                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
814                 //
815
816                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
817                               AFS_TRACE_LEVEL_VERBOSE,
818                               "AFSCleanup Acquiring Dcb lock %p EXCL %08lX\n",
819                               &pFcb->NPFcb->Resource,
820                               PsGetCurrentThread());
821
822                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
823                                   TRUE);
824
825                 //
826                 // Perform some final common processing
827                 //
828
829                 ASSERT( pFcb->OpenHandleCount != 0);
830
831                 if( pParentObjectInfo != NULL)
832                 {
833
834                     stFileCleanup.ParentId = pParentObjectInfo->FileId;
835                 }
836
837                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
838
839                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
840                 {
841
842                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
843
844                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
845                     {
846
847                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
848
849                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
850                     }
851
852                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
853                     {
854
855                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
856
857                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
858                     }
859
860                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
861                     {
862
863                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
864
865                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
866                     }
867                 }
868
869                 //
870                 // If the count has dropped to one and there is a pending delete
871                 // then delete the node.  The final count will be decremented just
872                 // before the Fcb->NPFcb->Resource is released.
873                 //
874
875                 if( pFcb->OpenHandleCount == 1 &&
876                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
877                 {
878
879                     //
880                     // Try to notify the service about the delete
881                     //
882
883                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
884
885                     //
886                     // Indicate the file access mode that is being released
887                     //
888
889                     stFileCleanup.FileAccess = pCcb->FileAccess;
890
891                     //
892                     // Push the request to the service
893                     //
894
895                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
896                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
897                                                   &pCcb->AuthGroup,
898                                                   &pCcb->DirectoryCB->NameInformation.FileName,
899                                                   &pObjectInfo->FileId,
900                                                   &stFileCleanup,
901                                                   sizeof( AFSFileCleanupCB),
902                                                   pResultCB,
903                                                   &ulResultLen);
904
905                     if( !NT_SUCCESS( ntStatus) &&
906                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
907                     {
908
909                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
910                                       AFS_TRACE_LEVEL_ERROR,
911                                       "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
912                                       &pCcb->FullFileName,
913                                       ntStatus);
914
915                         ntStatus = STATUS_SUCCESS;
916
917                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
918                     }
919                     else
920                     {
921
922                         ntStatus = STATUS_SUCCESS;
923
924                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
925                                       AFS_TRACE_LEVEL_VERBOSE,
926                                       "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
927                                       &pCcb->FullFileName,
928                                       pCcb->DirectoryCB);
929
930                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
931
932                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
933
934                         ASSERT( pParentObjectInfo != NULL);
935
936                         if ( pParentObjectInfo != NULL)
937                         {
938
939                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
940                                             TRUE);
941
942                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
943                             {
944
945                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
946
947                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
948                             }
949                             else
950                             {
951
952                                 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
953                             }
954
955                             //
956                             // Now that the service has the entry has deleted we need to remove it from the parent
957                             // tree so another lookup on the node will fail
958                             //
959
960                             if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
961                             {
962
963                                 AFSRemoveNameEntry( pParentObjectInfo,
964                                                     pCcb->DirectoryCB);
965                             }
966                             else
967                             {
968
969                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
970                                               AFS_TRACE_LEVEL_VERBOSE,
971                                               "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
972                                               pCcb->DirectoryCB,
973                                               &pCcb->DirectoryCB->NameInformation.FileName);
974                             }
975
976                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
977
978                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
979                                                             pCcb,
980                                                             (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
981                                                             (ULONG)FILE_ACTION_REMOVED);
982                         }
983                         else
984                         {
985                             if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
986                             {
987
988                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
989                                               AFS_TRACE_LEVEL_VERBOSE,
990                                               "AFSCleanup DE %p for %wZ NOT removing entry due to pParentObjectInfo == NULL\n",
991                                               pCcb->DirectoryCB,
992                                               &pCcb->DirectoryCB->NameInformation.FileName);
993                             }
994                         }
995                     }
996                 }
997
998                 //
999                 // If there have been any updates to the node then push it to
1000                 // the service
1001                 //
1002
1003                 else
1004                 {
1005
1006                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED) &&
1007                         pParentObjectInfo != NULL)
1008                     {
1009
1010                         ULONG ulNotifyFilter = 0;
1011
1012                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1013
1014                         ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1015
1016                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1017                                                         pCcb,
1018                                                         (ULONG)ulNotifyFilter,
1019                                                         (ULONG)FILE_ACTION_MODIFIED);
1020                     }
1021
1022                     //
1023                     // Indicate the file access mode that is being released
1024                     //
1025
1026                     stFileCleanup.FileAccess = pCcb->FileAccess;
1027
1028                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1029                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1030                                                   &pCcb->AuthGroup,
1031                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1032                                                   &pObjectInfo->FileId,
1033                                                   &stFileCleanup,
1034                                                   sizeof( AFSFileCleanupCB),
1035                                                   pResultCB,
1036                                                   &ulResultLen);
1037
1038                     if ( NT_SUCCESS( ntStatus))
1039                     {
1040
1041                         if ( pParentObjectInfo != NULL)
1042                         {
1043
1044                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1045                                               TRUE);
1046
1047                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1048                             {
1049
1050                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1051
1052                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1053                             }
1054
1055                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1056                         }
1057                     }
1058
1059                     ntStatus = STATUS_SUCCESS;
1060                 }
1061
1062                 //
1063                 // Release the notification for this directory if there is one
1064                 //
1065
1066                 FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
1067                                     &pControlDeviceExt->Specific.Control.DirNotifyList,
1068                                     pCcb);
1069
1070                 //
1071                 // Remove the share access at this time since we may not get the close for sometime on this FO.
1072                 //
1073
1074                 IoRemoveShareAccess( pFileObject,
1075                                      &pFcb->ShareAccess);
1076
1077                 //
1078                 // We don't need the name array after the user closes the handle on the file
1079                 //
1080
1081                 if( pCcb->NameArray != NULL)
1082                 {
1083
1084                     AFSFreeNameArray( pCcb->NameArray);
1085
1086                     pCcb->NameArray = NULL;
1087                 }
1088
1089                 //
1090                 // Decrement the open child handle count
1091                 //
1092
1093                 if( pParentObjectInfo != NULL)
1094                 {
1095
1096                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1097
1098                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1099
1100                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1101                                   AFS_TRACE_LEVEL_VERBOSE,
1102                                   "AFSCleanup (Dir) Decrement child open handle count on Parent object %p Cnt %d\n",
1103                                   pParentObjectInfo,
1104                                   lCount);
1105                 }
1106
1107                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1108
1109                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1110                               AFS_TRACE_LEVEL_VERBOSE,
1111                               "AFSCleanup (Dir) Decrement handle count on Fcb %p Cnt %d\n",
1112                               pFcb,
1113                               lCount);
1114
1115                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1116
1117                 break;
1118             }
1119
1120             case AFS_SYMBOLIC_LINK_FCB:
1121             case AFS_MOUNT_POINT_FCB:
1122             case AFS_DFS_LINK_FCB:
1123             case AFS_INVALID_FCB:
1124             {
1125
1126                 //
1127                 // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
1128                 //
1129
1130                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1131                               AFS_TRACE_LEVEL_VERBOSE,
1132                               "AFSCleanup (MP/SL) Acquiring Dcb lock %p EXCL %08lX\n",
1133                               &pFcb->NPFcb->Resource,
1134                               PsGetCurrentThread());
1135
1136                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1137                                   TRUE);
1138
1139                 //
1140                 // Perform some final common processing
1141                 //
1142
1143                 ASSERT( pFcb->OpenHandleCount != 0);
1144
1145                 if( pParentObjectInfo != NULL)
1146                 {
1147
1148                     stFileCleanup.ParentId = pParentObjectInfo->FileId;
1149                 }
1150
1151                 stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1152
1153                 if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
1154                 {
1155
1156                     stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
1157
1158                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
1159                     {
1160
1161                         stFileCleanup.CreateTime = pObjectInfo->CreationTime;
1162
1163                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1164                     }
1165
1166                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
1167                     {
1168
1169                         stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
1170
1171                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1172                     }
1173
1174                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
1175                     {
1176
1177                         stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
1178
1179                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1180                     }
1181                 }
1182
1183                 //
1184                 // If the count has dropped to one and there is a pending delete
1185                 // then delete the node.  The final count will be decremented just
1186                 // before the Fcb->NPFcb->Resource is released.
1187                 //
1188
1189                 if( pFcb->OpenHandleCount == 1 &&
1190                     BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1191                 {
1192
1193                     //
1194                     // Try to notify the service about the delete
1195                     //
1196
1197                     ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
1198
1199                     //
1200                     // Indicate the file access mode that is being released
1201                     //
1202
1203                     stFileCleanup.FileAccess = pCcb->FileAccess;
1204
1205                     //
1206                     // Push the request to the service
1207                     //
1208
1209                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1210                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1211                                                   &pCcb->AuthGroup,
1212                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1213                                                   &pObjectInfo->FileId,
1214                                                   &stFileCleanup,
1215                                                   sizeof( AFSFileCleanupCB),
1216                                                   pResultCB,
1217                                                   &ulResultLen);
1218
1219                     if( !NT_SUCCESS( ntStatus) &&
1220                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
1221                     {
1222
1223                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1224                                       AFS_TRACE_LEVEL_ERROR,
1225                                       "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
1226                                       &pCcb->FullFileName,
1227                                       ntStatus);
1228
1229                         ntStatus = STATUS_SUCCESS;
1230
1231                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1232                     }
1233                     else
1234                     {
1235
1236                         ntStatus = STATUS_SUCCESS;
1237
1238                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1239                                       AFS_TRACE_LEVEL_VERBOSE,
1240                                       "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
1241                                       &pCcb->FullFileName,
1242                                       pCcb->DirectoryCB);
1243
1244                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
1245
1246                         ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1247
1248                         ASSERT( pParentObjectInfo != NULL);
1249
1250                         if ( pParentObjectInfo != NULL)
1251                         {
1252
1253                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1254                                             TRUE);
1255
1256                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1257                             {
1258
1259                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1260
1261                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1262                             }
1263                             else
1264                             {
1265                                 pParentObjectInfo->DataVersion.QuadPart = pResultCB->ParentDataVersion.QuadPart;
1266                             }
1267
1268                             //
1269                             // Now that the service has the entry has deleted we need to remove it from the parent
1270                             // tree so another lookup on the node will fail
1271                             //
1272
1273                             if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1274                             {
1275
1276                                 AFSRemoveNameEntry( pParentObjectInfo,
1277                                                     pCcb->DirectoryCB);
1278                             }
1279                             else
1280                             {
1281
1282                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1283                                               AFS_TRACE_LEVEL_VERBOSE,
1284                                               "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
1285                                               pCcb->DirectoryCB,
1286                                               &pCcb->DirectoryCB->NameInformation.FileName);
1287                             }
1288
1289                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1290
1291                             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1292                                                             pCcb,
1293                                                             (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
1294                                                             (ULONG)FILE_ACTION_REMOVED);
1295                         }
1296                         else
1297                         {
1298
1299                             if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
1300                             {
1301
1302                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1303                                               AFS_TRACE_LEVEL_VERBOSE,
1304                                               "AFSCleanup DE %p for %wZ NOT removing entry due to pParentObjectInfo == NULL\n",
1305                                               pCcb->DirectoryCB,
1306                                               &pCcb->DirectoryCB->NameInformation.FileName);
1307                             }
1308                         }
1309                     }
1310                 }
1311
1312                 //
1313                 // If there have been any updates to the node then push it to
1314                 // the service
1315                 //
1316
1317                 else
1318                 {
1319
1320                     if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED) &&
1321                         pParentObjectInfo != NULL)
1322                     {
1323
1324                         ULONG ulNotifyFilter = 0;
1325
1326                         ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1327
1328                         ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
1329
1330                         AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1331                                                         pCcb,
1332                                                         (ULONG)ulNotifyFilter,
1333                                                         (ULONG)FILE_ACTION_MODIFIED);
1334                     }
1335
1336                     //
1337                     // Indicate the file access mode that is being released
1338                     //
1339
1340                     stFileCleanup.FileAccess = pCcb->FileAccess;
1341
1342                     ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
1343                                                   ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
1344                                                   &pCcb->AuthGroup,
1345                                                   &pCcb->DirectoryCB->NameInformation.FileName,
1346                                                   &pObjectInfo->FileId,
1347                                                   &stFileCleanup,
1348                                                   sizeof( AFSFileCleanupCB),
1349                                                   pResultCB,
1350                                                   &ulResultLen);
1351
1352                     if ( NT_SUCCESS( ntStatus))
1353                     {
1354
1355                         if ( pParentObjectInfo != NULL)
1356                         {
1357
1358                             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1359                                               TRUE);
1360
1361                             if ( pParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart)
1362                             {
1363
1364                                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1365
1366                                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1367                             }
1368
1369                             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1370                         }
1371                     }
1372
1373                     ntStatus = STATUS_SUCCESS;
1374                 }
1375
1376                 //
1377                 // Remove the share access at this time since we may not get the close for sometime on this FO.
1378                 //
1379
1380                 IoRemoveShareAccess( pFileObject,
1381                                      &pFcb->ShareAccess);
1382
1383                 //
1384                 // We don't need the name array after the user closes the handle on the file
1385                 //
1386
1387                 if( pCcb->NameArray != NULL)
1388                 {
1389
1390                     AFSFreeNameArray( pCcb->NameArray);
1391
1392                     pCcb->NameArray = NULL;
1393                 }
1394
1395                 //
1396                 // Decrement the open child handle count
1397                 //
1398
1399                 if( pParentObjectInfo != NULL)
1400                 {
1401
1402                     ASSERT( pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0);
1403
1404                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1405
1406                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1407                                   AFS_TRACE_LEVEL_VERBOSE,
1408                                   "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %p Cnt %d\n",
1409                                   pParentObjectInfo,
1410                                   lCount);
1411                 }
1412
1413                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1414
1415                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1416                               AFS_TRACE_LEVEL_VERBOSE,
1417                               "AFSCleanup (MP/SL) Decrement handle count on Fcb %p Cnt %d\n",
1418                               pFcb,
1419                               lCount);
1420
1421                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1422
1423                 break;
1424             }
1425
1426             case AFS_SPECIAL_SHARE_FCB:
1427             {
1428
1429                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1430                               AFS_TRACE_LEVEL_VERBOSE,
1431                               "AFSCleanup Acquiring SPECIAL SHARE lock %p EXCL %08lX\n",
1432                               &pFcb->NPFcb->Resource,
1433                               PsGetCurrentThread());
1434
1435                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1436                                 TRUE);
1437
1438                 ASSERT( pFcb->OpenHandleCount != 0);
1439
1440                 //
1441                 // Decrement the open child handle count
1442                 //
1443
1444                 if( pParentObjectInfo != NULL &&
1445                     pParentObjectInfo->Specific.Directory.ChildOpenHandleCount > 0)
1446                 {
1447
1448                     lCount = InterlockedDecrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
1449
1450                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1451                                   AFS_TRACE_LEVEL_VERBOSE,
1452                                   "AFSCleanup (Share) Decrement child open handle count on Parent object %p Cnt %d\n",
1453                                   pParentObjectInfo,
1454                                   lCount);
1455                 }
1456
1457                 lCount = InterlockedDecrement( &pFcb->OpenHandleCount);
1458
1459                 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1460                               AFS_TRACE_LEVEL_VERBOSE,
1461                               "AFSCleanup (Share) Decrement handle count on Fcb %p Cnt %d\n",
1462                               pFcb,
1463                               lCount);
1464
1465                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1466
1467                 break;
1468             }
1469
1470             default:
1471
1472                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1473                               AFS_TRACE_LEVEL_ERROR,
1474                               "AFSCleanup Processing unknown node type %d\n",
1475                               pFcb->Header.NodeTypeCode);
1476
1477                 break;
1478         }
1479
1480
1481 try_exit:
1482
1483         if ( pParentObjectInfo != NULL)
1484         {
1485
1486             AFSReleaseObjectInfo( &pParentObjectInfo);
1487         }
1488
1489         if( pResultCB != NULL)
1490         {
1491
1492             AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_32_TAG);
1493         }
1494
1495         if( pFileObject != NULL)
1496         {
1497
1498             //
1499             // Setup the fileobject flags to indicate cleanup is complete.
1500             //
1501
1502             SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
1503         }
1504
1505         //
1506         // Complete the request
1507         //
1508
1509         AFSCompleteRequest( Irp, ntStatus);
1510     }
1511     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
1512     {
1513
1514         AFSDbgLogMsg( 0,
1515                       0,
1516                       "EXCEPTION - AFSCleanup\n");
1517
1518         AFSDumpTraceFilesFnc();
1519     }
1520
1521     return ntStatus;
1522 }