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