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