Windows: More RDR Garbage Collection
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSFcbSupport.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: AFSFcbSupport.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSInitFcb
43 //
44 // Description:
45 //
46 //      This function performs Fcb initialization
47 //
48 // Return:
49 //
50 //      Return Fcb->NPFcb->Resource held exclusive
51 //
52
53 NTSTATUS
54 AFSInitFcb( IN AFSDirectoryCB  *DirEntry)
55 {
56
57     NTSTATUS ntStatus = STATUS_SUCCESS;
58     AFSFcb *pFcb = NULL;
59     AFSNonPagedFcb *pNPFcb = NULL;
60     USHORT  usFcbLength = 0;
61     AFSObjectInfoCB *pObjectInfo = NULL;
62     AFSVolumeCB *pVolumeCB = NULL;
63
64     __Enter
65     {
66
67         pObjectInfo = DirEntry->ObjectInformation;
68
69         if ( pObjectInfo->Fcb != NULL)
70         {
71
72             AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
73                             TRUE);
74
75             try_return( ntStatus = STATUS_SUCCESS);
76         }
77
78         pVolumeCB = pObjectInfo->VolumeCB;
79
80         //
81         // Allocate the Fcb and the nonpaged portion of the Fcb.
82         //
83
84         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
85                       AFS_TRACE_LEVEL_VERBOSE_2,
86                       "AFSInitFcb Initializing fcb for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
87                       &DirEntry->NameInformation.FileName,
88                       pObjectInfo->FileId.Cell,
89                       pObjectInfo->FileId.Volume,
90                       pObjectInfo->FileId.Vnode,
91                       pObjectInfo->FileId.Unique);
92
93         usFcbLength = sizeof( AFSFcb);
94
95         pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
96                                                    usFcbLength,
97                                                    AFS_FCB_ALLOCATION_TAG);
98
99         if( pFcb == NULL)
100         {
101
102             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
103                           AFS_TRACE_LEVEL_ERROR,
104                           "AFSInitFcb Failed to allocate fcb\n");
105
106             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
107         }
108
109         RtlZeroMemory( pFcb,
110                        usFcbLength);
111
112         pFcb->Header.NodeByteSize = usFcbLength;
113
114         pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
115                                                              sizeof( AFSNonPagedFcb),
116                                                              AFS_FCB_NP_ALLOCATION_TAG);
117
118         if( pNPFcb == NULL)
119         {
120
121             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
122                           AFS_TRACE_LEVEL_ERROR,
123                           "AFSInitFcb Failed to allocate non-paged fcb\n");
124
125             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
126         }
127
128         RtlZeroMemory( pNPFcb,
129                        sizeof( AFSNonPagedFcb));
130
131         pNPFcb->Size = sizeof( AFSNonPagedFcb);
132
133         pNPFcb->Type = AFS_NON_PAGED_FCB;
134
135         //
136         // Initialize the advanced header
137         //
138
139         ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);
140
141         FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);
142
143         //
144         // OK, initialize the entry
145         //
146
147         ExInitializeResourceLite( &pNPFcb->Resource);
148
149         ExInitializeResourceLite( &pNPFcb->PagingResource);
150
151         ExInitializeResourceLite( &pNPFcb->SectionObjectResource);
152
153         ExInitializeResourceLite( &pNPFcb->CcbListLock);
154
155         //
156         // Grab the Fcb for processing
157         //
158
159         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
160                       AFS_TRACE_LEVEL_VERBOSE,
161                       "AFSInitFcb Acquiring Fcb lock %p EXCL %08lX\n",
162                       &pNPFcb->Resource,
163                       PsGetCurrentThread());
164
165         AFSAcquireExcl( &pNPFcb->Resource,
166                         TRUE);
167
168         pFcb->Header.Resource = &pNPFcb->Resource;
169
170         pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;
171
172         pFcb->NPFcb = pNPFcb;
173
174         //
175         // Set type specific information
176         //
177
178         if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
179         {
180
181             //
182             // Reset the type to a directory type
183             //
184
185             pFcb->Header.NodeTypeCode = AFS_DIRECTORY_FCB;
186         }
187         else if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
188         {
189
190             pFcb->Header.NodeTypeCode = AFS_FILE_FCB;
191
192             //
193             // Initialize the file specific information
194             //
195
196             FsRtlInitializeFileLock( &pFcb->Specific.File.FileLock,
197                                      NULL,
198                                      NULL);
199
200             //
201             // Initialize the header file sizes to our dir entry information
202             //
203
204             pFcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
205             pFcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
206             pFcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
207
208             //
209             // Initialize the Extents resources and so forth.  The
210             // quiescent state is that no one has the extents for
211             // IO (do the extents are not busy) and there is no
212             // extents request outstanding (and hence the "last
213             // one" is complete).
214             //
215             ExInitializeResourceLite( &pNPFcb->Specific.File.ExtentsResource );
216
217             KeInitializeEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
218                                NotificationEvent,
219                                TRUE );
220
221             for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
222             {
223                 InitializeListHead(&pFcb->Specific.File.ExtentsLists[i]);
224             }
225
226             pNPFcb->Specific.File.DirtyListHead = NULL;
227             pNPFcb->Specific.File.DirtyListTail = NULL;
228
229             ExInitializeResourceLite( &pNPFcb->Specific.File.DirtyExtentsListLock);
230
231             KeInitializeEvent( &pNPFcb->Specific.File.FlushEvent,
232                                SynchronizationEvent,
233                                TRUE);
234
235             KeInitializeEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
236                                NotificationEvent,
237                                TRUE);
238         }
239         else if( pObjectInfo->FileType == AFS_FILE_TYPE_SPECIAL_SHARE_NAME)
240         {
241
242             pFcb->Header.NodeTypeCode = AFS_SPECIAL_SHARE_FCB;
243         }
244         else if( pObjectInfo->FileType == AFS_FILE_TYPE_PIOCTL)
245         {
246
247             pFcb->Header.NodeTypeCode = AFS_IOCTL_FCB;
248         }
249         else if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
250         {
251
252             pFcb->Header.NodeTypeCode = AFS_SYMBOLIC_LINK_FCB;
253         }
254         else if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
255         {
256
257             pFcb->Header.NodeTypeCode = AFS_MOUNT_POINT_FCB;
258         }
259         else if( pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
260         {
261             pFcb->Header.NodeTypeCode = AFS_DFS_LINK_FCB;
262         }
263         else
264         {
265             pFcb->Header.NodeTypeCode = AFS_INVALID_FCB;
266         }
267
268         pFcb->ObjectInformation = pObjectInfo;
269
270         AFSAcquireShared( &pObjectInfo->NonPagedInfo->ObjectInfoLock,
271                           TRUE);
272         //
273         // Swap the allocated FCB into the ObjectInformation structure if it
274         // does not already have one.
275         //
276
277         if ( InterlockedCompareExchangePointer( (PVOID *)&pObjectInfo->Fcb, pFcb, NULL) != NULL)
278         {
279
280             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
281                           AFS_TRACE_LEVEL_WARNING,
282                           "AFSInitFcb Raced Fcb %p pFcb %p Name %wZ\n",
283                           pObjectInfo->Fcb,
284                           pFcb,
285                           &DirEntry->NameInformation.FileName);
286
287             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
288                           AFS_TRACE_LEVEL_VERBOSE,
289                           "AFSInitFcb Acquiring Fcb lock %p EXCL %08lX\n",
290                           &pObjectInfo->Fcb->NPFcb->Resource,
291                           PsGetCurrentThread());
292
293             AFSReleaseResource( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
294
295             AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
296                             TRUE);
297
298             try_return( ntStatus = STATUS_REPARSE);
299         }
300
301         AFSReleaseResource( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
302
303         AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
304                       AFS_TRACE_LEVEL_VERBOSE,
305                       "AFSInitFcb Initialized Fcb %p Name %wZ\n",
306                       &pObjectInfo->Fcb,
307                       &DirEntry->NameInformation.FileName);
308
309 try_exit:
310
311         if( ntStatus != STATUS_SUCCESS)
312         {
313
314             if ( !NT_SUCCESS( ntStatus))
315             {
316
317                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
318                               AFS_TRACE_LEVEL_ERROR,
319                               "AFSInitFcb Failed to initialize fcb Status %08lX\n",
320                               ntStatus);
321             }
322
323             if( pFcb != NULL)
324             {
325
326                 if( pNPFcb != NULL)
327                 {
328
329                     AFSReleaseResource( &pNPFcb->Resource);
330
331                     FsRtlTeardownPerStreamContexts( &pFcb->Header);
332
333                     if ( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
334                     {
335
336                         FsRtlUninitializeFileLock( &pFcb->Specific.File.FileLock);
337
338                         ExDeleteResourceLite( &pNPFcb->Specific.File.ExtentsResource);
339
340                         ExDeleteResourceLite( &pNPFcb->Specific.File.DirtyExtentsListLock);
341                     }
342
343                     ExDeleteResourceLite( &pNPFcb->SectionObjectResource);
344
345                     ExDeleteResourceLite( &pNPFcb->PagingResource);
346
347                     ExDeleteResourceLite( &pNPFcb->CcbListLock);
348
349                     ExDeleteResourceLite( &pNPFcb->Resource);
350
351                     AFSExFreePoolWithTag( pNPFcb, AFS_FCB_NP_ALLOCATION_TAG);
352                 }
353
354                 AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);
355             }
356         }
357     }
358
359     return ntStatus;
360 }
361
362 NTSTATUS
363 AFSInitVolume( IN GUID *AuthGroup,
364                IN AFSFileID *RootFid,
365                OUT AFSVolumeCB **VolumeCB)
366 {
367
368     NTSTATUS ntStatus = STATUS_SUCCESS;
369     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
370     AFSNonPagedVolumeCB *pNonPagedVcb = NULL;
371     AFSVolumeCB *pVolumeCB = NULL;
372     AFSNonPagedObjectInfoCB *pNonPagedObject = NULL;
373     ULONGLONG ullIndex = 0;
374     BOOLEAN bReleaseLocks = FALSE;
375     AFSVolumeInfoCB stVolumeInformation = {0};
376     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
377     LONG lCount;
378
379     __Enter
380     {
381
382         //
383         // Before grabbing any locks ask the service for the volume information
384         // This may be a waste but we need to get this information prior to
385         // taking any volume tree locks. Don't do this for any 'reserved' cell entries
386         //
387
388         if( RootFid->Cell != 0)
389         {
390
391             RtlZeroMemory( &stVolumeInformation,
392                            sizeof( AFSVolumeInfoCB));
393
394             ntStatus = AFSRetrieveVolumeInformation( AuthGroup,
395                                                      RootFid,
396                                                      &stVolumeInformation);
397
398             if( !NT_SUCCESS( ntStatus))
399             {
400
401                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
402                               AFS_TRACE_LEVEL_ERROR,
403                               "AFSInitVolume AFSRetrieveVolumeInformation(RootFid) failure %08lX\n",
404                               ntStatus);
405
406                 try_return( ntStatus);
407             }
408
409             //
410             // Grab our tree locks and see if we raced with someone else
411             //
412
413             AFSAcquireExcl( pDeviceExt->Specific.RDR.VolumeTree.TreeLock,
414                             TRUE);
415
416             AFSAcquireExcl( &pDeviceExt->Specific.RDR.VolumeListLock,
417                             TRUE);
418
419             bReleaseLocks = TRUE;
420
421             ullIndex = AFSCreateHighIndex( RootFid);
422
423             ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
424                                            ullIndex,
425                                            (AFSBTreeEntry **)&pVolumeCB);
426
427             if( NT_SUCCESS( ntStatus) &&
428                 pVolumeCB != NULL)
429             {
430
431                 //
432                 // So we don't lock with an invalidation call ...
433                 //
434
435                 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
436
437                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
438                               AFS_TRACE_LEVEL_VERBOSE,
439                               "AFSInitVolume Increment count on volume %p Cnt %d\n",
440                               pVolumeCB,
441                               lCount);
442
443                 AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
444
445                 AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
446
447                 bReleaseLocks = FALSE;
448
449                 AFSAcquireExcl( pVolumeCB->VolumeLock,
450                                 TRUE);
451
452                 *VolumeCB = pVolumeCB;
453
454                 try_return( ntStatus);
455             }
456
457             //
458             // Revert our status from the above call back to success.
459             //
460
461             ntStatus = STATUS_SUCCESS;
462         }
463
464         //
465         // For the global root we allocate out volume node and insert it
466         // into the volume tree ...
467         //
468
469         pVolumeCB = (AFSVolumeCB *)AFSExAllocatePoolWithTag( PagedPool,
470                                                              sizeof( AFSVolumeCB),
471                                                              AFS_VCB_ALLOCATION_TAG);
472
473         if( pVolumeCB == NULL)
474         {
475
476             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
477                           AFS_TRACE_LEVEL_ERROR,
478                           "AFSInitVolume Failed to allocate the root volume cb\n");
479
480             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
481         }
482
483         RtlZeroMemory( pVolumeCB,
484                        sizeof( AFSVolumeCB));
485
486         //
487         // The non paged portion
488         //
489
490         pNonPagedVcb = (AFSNonPagedVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool,
491                                                                         sizeof( AFSNonPagedVolumeCB),
492                                                                         AFS_VCB_NP_ALLOCATION_TAG);
493
494         if( pNonPagedVcb == NULL)
495         {
496
497             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
498                           AFS_TRACE_LEVEL_ERROR,
499                           "AFSInitVolume Failed to allocate the root non paged volume cb\n");
500
501             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
502         }
503
504         RtlZeroMemory( pNonPagedVcb,
505                        sizeof( AFSNonPagedVolumeCB));
506
507         ExInitializeResourceLite( &pNonPagedVcb->VolumeLock);
508
509         ExInitializeResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);
510
511         pNonPagedObject = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
512                                                                                sizeof( AFSNonPagedObjectInfoCB),
513                                                                                AFS_NP_OBJECT_INFO_TAG);
514
515         if( pNonPagedObject == NULL)
516         {
517
518             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
519                           AFS_TRACE_LEVEL_ERROR,
520                           "AFSInitVolume Failed to allocate the root non paged object cb\n");
521
522             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
523         }
524
525         RtlZeroMemory( pNonPagedObject,
526                        sizeof( AFSNonPagedObjectInfoCB));
527
528         ExInitializeResourceLite( &pNonPagedObject->ObjectInfoLock);
529
530         ExInitializeResourceLite( &pNonPagedObject->DirectoryNodeHdrLock);
531
532         pVolumeCB->NonPagedVcb = pNonPagedVcb;
533
534         pVolumeCB->ObjectInformation.NonPagedInfo = pNonPagedObject;
535
536         pVolumeCB->VolumeLock = &pNonPagedVcb->VolumeLock;
537
538         pVolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock = &pNonPagedObject->DirectoryNodeHdrLock;
539
540         pVolumeCB->ObjectInfoTree.TreeLock = &pNonPagedVcb->ObjectInfoTreeLock;
541
542         //
543         // Bias our reference by 1
544         //
545
546         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
547                       AFS_TRACE_LEVEL_VERBOSE,
548                       "AFSInitVolume Initializing count (2) on volume %p\n",
549                       pVolumeCB);
550
551         pVolumeCB->VolumeReferenceCount = 2;
552
553         AFSAcquireExcl( pVolumeCB->VolumeLock,
554                         TRUE);
555
556         pVolumeCB->DirectoryCB = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
557                                                                              sizeof( AFSDirectoryCB) + sizeof( WCHAR),
558                                                                              AFS_DIR_ENTRY_TAG);
559
560         if( pVolumeCB->DirectoryCB == NULL)
561         {
562
563             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
564         }
565
566         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
567                       AFS_TRACE_LEVEL_VERBOSE,
568                       "AFSInitVolume AFS_DIR_ENTRY_TAG allocated %p\n",
569                       pVolumeCB->DirectoryCB);
570
571         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
572                                                                                 sizeof( AFSNonPagedDirectoryCB),
573                                                                                 AFS_DIR_ENTRY_NP_TAG);
574
575         if( pNonPagedDirEntry == NULL)
576         {
577
578             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
579         }
580
581         RtlZeroMemory( pVolumeCB->DirectoryCB,
582                        sizeof( AFSDirectoryCB) + sizeof( WCHAR));
583
584         RtlZeroMemory( pNonPagedDirEntry,
585                        sizeof( AFSNonPagedDirectoryCB));
586
587         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
588
589         pVolumeCB->DirectoryCB->NonPaged = pNonPagedDirEntry;
590
591         //
592         // Initialize the non-paged portion of the directory entry
593         //
594
595         KeQuerySystemTime( &pVolumeCB->ObjectInformation.CreationTime);
596         KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastWriteTime);
597         KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastAccessTime);
598
599         pVolumeCB->ObjectInformation.FileType = AFS_FILE_TYPE_DIRECTORY;
600
601         SetFlag( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_ROOT_VOLUME);
602
603         pVolumeCB->ObjectInformation.FileId.Cell = RootFid->Cell;
604         pVolumeCB->ObjectInformation.FileId.Volume = RootFid->Volume;
605         pVolumeCB->ObjectInformation.FileId.Vnode = RootFid->Vnode;
606         pVolumeCB->ObjectInformation.FileId.Unique = RootFid->Unique;
607         pVolumeCB->ObjectInformation.FileId.Hash = RootFid->Hash;
608
609         pVolumeCB->ObjectInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
610
611         pVolumeCB->DirectoryCB->NameInformation.FileName.Length = sizeof( WCHAR);
612
613         pVolumeCB->DirectoryCB->NameInformation.FileName.MaximumLength = pVolumeCB->DirectoryCB->NameInformation.FileName.Length;
614
615         pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer = (WCHAR *)((char *)pVolumeCB->DirectoryCB + sizeof( AFSDirectoryCB));
616
617         RtlCopyMemory( pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer,
618                        L"\\",
619                        sizeof( WCHAR));
620
621         //
622         // Copy in the volume information retrieved above
623         //
624
625         RtlCopyMemory( &pVolumeCB->VolumeInformation,
626                        &stVolumeInformation,
627                        sizeof( AFSVolumeInfoCB));
628
629         //
630         // Setup pointers
631         //
632
633         pVolumeCB->DirectoryCB->ObjectInformation = &pVolumeCB->ObjectInformation;
634
635         pVolumeCB->DirectoryCB->ObjectInformation->VolumeCB = pVolumeCB;
636
637         //
638         // Insert the volume into our volume tree. Don't insert any reserved entries
639         //
640
641         if( RootFid->Cell != 0)
642         {
643
644             pVolumeCB->TreeEntry.HashIndex = ullIndex;
645
646             if( pDeviceExt->Specific.RDR.VolumeTree.TreeHead == NULL)
647             {
648
649                 pDeviceExt->Specific.RDR.VolumeTree.TreeHead = &pVolumeCB->TreeEntry;
650
651                 SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
652             }
653             else
654             {
655
656                 if ( NT_SUCCESS( AFSInsertHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
657                                                      &pVolumeCB->TreeEntry)))
658                 {
659
660                     SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
661                 }
662             }
663
664             if( pDeviceExt->Specific.RDR.VolumeListHead == NULL)
665             {
666
667                 pDeviceExt->Specific.RDR.VolumeListHead = pVolumeCB;
668             }
669             else
670             {
671
672                 pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = (void *)pVolumeCB;
673
674                 pVolumeCB->ListEntry.bLink = pDeviceExt->Specific.RDR.VolumeListTail;
675             }
676
677             pDeviceExt->Specific.RDR.VolumeListTail = pVolumeCB;
678         }
679
680         *VolumeCB = pVolumeCB;
681
682 try_exit:
683
684         if( !NT_SUCCESS( ntStatus))
685         {
686
687             if( pNonPagedVcb != NULL)
688             {
689
690                 AFSReleaseResource( pVolumeCB->VolumeLock);
691
692                 ExDeleteResourceLite( &pNonPagedVcb->VolumeLock);
693
694                 ExDeleteResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);
695
696                 AFSExFreePoolWithTag( pNonPagedVcb, AFS_VCB_NP_ALLOCATION_TAG);
697             }
698
699             if( pNonPagedObject != NULL)
700             {
701
702                 ExDeleteResourceLite( &pNonPagedObject->ObjectInfoLock);
703
704                 AFSExFreePoolWithTag( pNonPagedObject, AFS_NP_OBJECT_INFO_TAG);
705             }
706
707             if( pVolumeCB != NULL)
708             {
709
710                 if( pVolumeCB->DirectoryCB != NULL)
711                 {
712
713                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
714                                   AFS_TRACE_LEVEL_VERBOSE,
715                                   "AFSInitVolume AFS_DIR_ENTRY_TAG deallocating %p\n",
716                                   pVolumeCB->DirectoryCB);
717
718                     AFSExFreePoolWithTag( pVolumeCB->DirectoryCB, AFS_DIR_ENTRY_TAG);
719                 }
720
721                 AFSExFreePoolWithTag( pVolumeCB, AFS_VCB_ALLOCATION_TAG);
722             }
723
724             if( pNonPagedDirEntry != NULL)
725             {
726
727                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
728
729                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
730             }
731         }
732
733         if( bReleaseLocks)
734         {
735
736             AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
737
738             AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
739         }
740     }
741
742     return ntStatus;
743 }
744
745 NTSTATUS
746 AFSRemoveVolume( IN AFSVolumeCB *VolumeCB)
747 {
748
749     NTSTATUS ntStatus = STATUS_SUCCESS;
750     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
751
752     __Enter
753     {
754
755         //
756         // Remove the volume from the tree and list
757         // Don't process the list information for reserved entries
758         //
759
760         if( VolumeCB->ObjectInformation.FileId.Cell != 0)
761         {
762
763             if( BooleanFlagOn( VolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE))
764             {
765
766                 AFSRemoveHashEntry( &pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
767                                     &VolumeCB->TreeEntry);
768             }
769
770             if( VolumeCB->ListEntry.fLink == NULL)
771             {
772
773                 pDeviceExt->Specific.RDR.VolumeListTail = (AFSVolumeCB *)VolumeCB->ListEntry.bLink;
774
775                 if( pDeviceExt->Specific.RDR.VolumeListTail != NULL)
776                 {
777
778                     pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = NULL;
779                 }
780             }
781             else
782             {
783
784                 ((AFSVolumeCB *)(VolumeCB->ListEntry.fLink))->ListEntry.bLink = VolumeCB->ListEntry.bLink;
785             }
786
787             if( VolumeCB->ListEntry.bLink == NULL)
788             {
789
790                 pDeviceExt->Specific.RDR.VolumeListHead = (AFSVolumeCB *)VolumeCB->ListEntry.fLink;
791
792                 if( pDeviceExt->Specific.RDR.VolumeListHead != NULL)
793                 {
794
795                     pDeviceExt->Specific.RDR.VolumeListHead->ListEntry.bLink = NULL;
796                 }
797             }
798             else
799             {
800
801                 ((AFSVolumeCB *)(VolumeCB->ListEntry.bLink))->ListEntry.fLink = VolumeCB->ListEntry.fLink;
802             }
803         }
804
805         //
806         // Remove any PIOctl objects we have
807         //
808
809         if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB != NULL)
810         {
811
812             if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
813             {
814
815                 AFSAcquireExcl( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
816                                 TRUE);
817
818                 AFSRemoveFcb( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
819
820                 AFSReleaseResource( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
821             }
822
823             AFSDeleteObjectInfo( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
824
825             ExDeleteResourceLite( &VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
826
827             AFSExFreePoolWithTag( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
828
829             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
830                           AFS_TRACE_LEVEL_VERBOSE,
831                           "AFSRemoveVolume (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
832                           VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB);
833
834             AFSExFreePoolWithTag( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
835         }
836
837         if( BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_HELD_IN_SERVICE))
838         {
839
840             //
841             // Release the fid in the service
842             //
843
844             AFSReleaseFid( &VolumeCB->ObjectInformation.FileId);
845         }
846
847         //
848         // Free up the memory
849         //
850
851         if( VolumeCB->NonPagedVcb != NULL)
852         {
853
854             if( ExIsResourceAcquiredLite( VolumeCB->VolumeLock))
855             {
856                 AFSReleaseResource( VolumeCB->VolumeLock);
857             }
858
859             ExDeleteResourceLite( &VolumeCB->NonPagedVcb->VolumeLock);
860
861             ExDeleteResourceLite( &VolumeCB->NonPagedVcb->ObjectInfoTreeLock);
862
863             AFSExFreePoolWithTag( VolumeCB->NonPagedVcb, AFS_VCB_NP_ALLOCATION_TAG);
864         }
865
866         if( VolumeCB->ObjectInformation.NonPagedInfo != NULL)
867         {
868
869             ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
870
871             ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->DirectoryNodeHdrLock);
872
873             AFSExFreePoolWithTag( VolumeCB->ObjectInformation.NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
874         }
875
876         if( VolumeCB->DirectoryCB != NULL)
877         {
878
879             if( VolumeCB->DirectoryCB->NonPaged != NULL)
880             {
881
882                 ExDeleteResourceLite( &VolumeCB->DirectoryCB->NonPaged->Lock);
883
884                 AFSExFreePoolWithTag( VolumeCB->DirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
885             }
886
887             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
888                           AFS_TRACE_LEVEL_VERBOSE,
889                           "AFSRemoveVolume AFS_DIR_ENTRY_TAG deallocating %p\n",
890                           VolumeCB->DirectoryCB);
891
892             AFSExFreePoolWithTag( VolumeCB->DirectoryCB, AFS_DIR_ENTRY_TAG);
893         }
894
895         AFSExFreePoolWithTag( VolumeCB, AFS_VCB_ALLOCATION_TAG);
896     }
897
898     return ntStatus;
899 }
900
901
902 //
903 // Function: AFSInitRootFcb
904 //
905 // Description:
906 //
907 //      This function performs Root node Fcb initialization
908 //
909 // Return:
910 //
911 //      A status is returned for the function
912 //
913
914 NTSTATUS
915 AFSInitRootFcb( IN ULONGLONG ProcessID,
916                 IN AFSVolumeCB *VolumeCB)
917 {
918
919     UNREFERENCED_PARAMETER(ProcessID);
920     NTSTATUS ntStatus = STATUS_SUCCESS;
921     AFSFcb *pFcb = NULL;
922     AFSNonPagedFcb *pNPFcb = NULL;
923
924     __Enter
925     {
926
927         //
928         // Initialize the root fcb
929         //
930
931         pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
932                                                    sizeof( AFSFcb),
933                                                    AFS_FCB_ALLOCATION_TAG);
934
935         if( pFcb == NULL)
936         {
937
938             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
939                           AFS_TRACE_LEVEL_ERROR,
940                           "AFSInitRootFcb Failed to allocate the root fcb\n");
941
942             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
943         }
944
945         RtlZeroMemory( pFcb,
946                        sizeof( AFSFcb));
947
948         pFcb->Header.NodeByteSize = sizeof( AFSFcb);
949
950         pFcb->Header.NodeTypeCode = AFS_ROOT_FCB;
951
952         pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
953                                                              sizeof( AFSNonPagedFcb),
954                                                              AFS_FCB_NP_ALLOCATION_TAG);
955
956         if( pNPFcb == NULL)
957         {
958
959             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
960                           AFS_TRACE_LEVEL_ERROR,
961                           "AFSInitRootFcb Failed to allocate the non-paged fcb\n");
962
963             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
964         }
965
966         RtlZeroMemory( pNPFcb,
967                        sizeof( AFSNonPagedFcb));
968
969         pNPFcb->Size = sizeof( AFSNonPagedFcb);
970
971         pNPFcb->Type = AFS_NON_PAGED_FCB;
972
973         //
974         // OK, initialize the entry
975         //
976
977         ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);
978
979         FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);
980
981         ExInitializeResourceLite( &pNPFcb->Resource);
982
983         ExInitializeResourceLite( &pNPFcb->PagingResource);
984
985         ExInitializeResourceLite( &pNPFcb->SectionObjectResource);
986
987         ExInitializeResourceLite( &pNPFcb->CcbListLock);
988
989         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
990                       AFS_TRACE_LEVEL_VERBOSE,
991                       "AFSInitRootFcb Acquiring Fcb lock %p EXCL %08lX\n",
992                       &pNPFcb->Resource,
993                       PsGetCurrentThread());
994
995         AFSAcquireExcl( &pNPFcb->Resource,
996                         TRUE);
997
998         pFcb->Header.Resource = &pNPFcb->Resource;
999
1000         pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;
1001
1002         pFcb->NPFcb = pNPFcb;
1003
1004         //
1005         // Save the root Fcb in the VolumeCB
1006         //
1007
1008         pFcb->ObjectInformation = &VolumeCB->ObjectInformation;
1009
1010         VolumeCB->ObjectInformation.VolumeCB = VolumeCB;
1011
1012         AFSAcquireShared( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1013                           TRUE);
1014         //
1015         // Swap the allocated FCB into the ObjectInformation structure if it
1016         // does not already have one.
1017         //
1018
1019         if ( InterlockedCompareExchangePointer( (PVOID *)&VolumeCB->ObjectInformation.Fcb, pFcb, NULL) != NULL)
1020         {
1021
1022             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1023                           AFS_TRACE_LEVEL_WARNING,
1024                           "AFSInitRootFcb Raced Fcb %p pFcb %p\n",
1025                           VolumeCB->ObjectInformation.Fcb,
1026                           pFcb);
1027
1028             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1029                           AFS_TRACE_LEVEL_VERBOSE,
1030                           "AFSInitRootFcb Acquiring Fcb lock %p EXCL %08lX\n",
1031                           &VolumeCB->ObjectInformation.Fcb->NPFcb->Resource,
1032                           PsGetCurrentThread());
1033
1034             AFSReleaseResource( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1035
1036             AFSAcquireExcl( &VolumeCB->ObjectInformation.Fcb->NPFcb->Resource,
1037                             TRUE);
1038
1039             try_return( ntStatus = STATUS_REPARSE);
1040         }
1041
1042         VolumeCB->RootFcb = VolumeCB->ObjectInformation.Fcb;
1043
1044         AFSReleaseResource( &VolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1045
1046         AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1047                       AFS_TRACE_LEVEL_VERBOSE,
1048                       "AFSInitRootFcb Initialized Fcb %p\n",
1049                       &VolumeCB->ObjectInformation.Fcb);
1050
1051 try_exit:
1052
1053         if( !NT_SUCCESS( ntStatus) ||
1054             ntStatus == STATUS_REPARSE)
1055         {
1056
1057             if( pFcb != NULL)
1058             {
1059
1060                 if( pNPFcb != NULL)
1061                 {
1062
1063                     AFSReleaseResource( &pNPFcb->Resource);
1064
1065                     FsRtlTeardownPerStreamContexts( &pFcb->Header);
1066
1067                     ExDeleteResourceLite( &pNPFcb->SectionObjectResource);
1068
1069                     ExDeleteResourceLite( &pNPFcb->PagingResource);
1070
1071                     ExDeleteResourceLite( &pNPFcb->CcbListLock);
1072
1073                     ExDeleteResourceLite( &pNPFcb->Resource);
1074
1075                     AFSExFreePoolWithTag( pNPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1076                 }
1077
1078                 AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);
1079             }
1080         }
1081     }
1082
1083     return ntStatus;
1084 }
1085
1086 //
1087 // Function: AFSRemoveRootFcb
1088 //
1089 // Description:
1090 //
1091 //      This function performs root Fcb removal/deallocation from
1092 //      the provided VolumeCB object.
1093 //
1094 // Return:
1095 //
1096 //      None
1097 //
1098
1099 void
1100 AFSRemoveRootFcb( IN AFSVolumeCB *VolumeCB)
1101 {
1102     AFSFcb * pRootFcb;
1103
1104     pRootFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)&VolumeCB->ObjectInformation.Fcb,
1105                                                              NULL,
1106                                                              (PVOID *)&VolumeCB->ObjectInformation.Fcb);
1107
1108     if ( pRootFcb == NULL)
1109     {
1110
1111         return;
1112     }
1113
1114     //
1115     // The Fcb has been disconnected from the ObjectInformation block.
1116     // Clear it from the RootFcb convenience pointer.
1117     //
1118
1119     VolumeCB->RootFcb = NULL;
1120
1121     if( pRootFcb->NPFcb != NULL)
1122     {
1123
1124         //
1125         // Now the resource
1126         //
1127
1128         ExDeleteResourceLite( &pRootFcb->NPFcb->Resource);
1129
1130         ExDeleteResourceLite( &pRootFcb->NPFcb->PagingResource);
1131
1132         ExDeleteResourceLite( &pRootFcb->NPFcb->SectionObjectResource);
1133
1134         ExDeleteResourceLite( &pRootFcb->NPFcb->CcbListLock);
1135
1136         FsRtlTeardownPerStreamContexts( &pRootFcb->Header);
1137
1138         //
1139         // The non paged region
1140         //
1141
1142         AFSExFreePoolWithTag( pRootFcb->NPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1143
1144         pRootFcb->NPFcb = NULL;
1145     }
1146
1147     //
1148     // And the Fcb itself
1149     //
1150
1151     AFSExFreePoolWithTag( pRootFcb, AFS_FCB_ALLOCATION_TAG);
1152
1153     return;
1154 }
1155
1156 //
1157 // Function: AFSRemoveFcb
1158 //
1159 // Description:
1160 //
1161 //      This function performs Fcb removal/deallocation
1162 //
1163 // Return:
1164 //
1165 //      A status is returned for the function
1166 //
1167
1168 void
1169 AFSRemoveFcb( IN AFSFcb **ppFcb)
1170 {
1171
1172     AFSFcb * pFcb;
1173
1174     pFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)ppFcb, NULL, (PVOID)(*ppFcb));
1175
1176     if ( pFcb == NULL)
1177     {
1178
1179         return;
1180     }
1181
1182     ASSERT( pFcb->Header.NodeTypeCode != AFS_ROOT_FCB);
1183
1184     //
1185     // Uninitialize the file lock if it is a file
1186     //
1187
1188     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1189                   AFS_TRACE_LEVEL_VERBOSE,
1190                   "AFSRemoveFcb Removing Fcb %p\n",
1191                   pFcb);
1192
1193     if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1194     {
1195
1196         FsRtlUninitializeFileLock( &pFcb->Specific.File.FileLock);
1197
1198         //
1199         // The resource we allocated
1200         //
1201
1202         ExDeleteResourceLite( &pFcb->NPFcb->Specific.File.ExtentsResource );
1203
1204         ExDeleteResourceLite( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
1205
1206     }
1207     else if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1208     {
1209
1210
1211     }
1212
1213     //
1214     // Tear down the FM specific contexts
1215     //
1216
1217     FsRtlTeardownPerStreamContexts( &pFcb->Header);
1218
1219     //
1220     // Delete the resources
1221     //
1222
1223     ExDeleteResourceLite( &pFcb->NPFcb->Resource);
1224
1225     ExDeleteResourceLite( &pFcb->NPFcb->PagingResource);
1226
1227     ExDeleteResourceLite( &pFcb->NPFcb->SectionObjectResource);
1228
1229     ExDeleteResourceLite( &pFcb->NPFcb->CcbListLock);
1230
1231     //
1232     // The non paged region
1233     //
1234
1235     AFSExFreePoolWithTag( pFcb->NPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1236
1237     //
1238     // And the Fcb itself, which includes the name
1239     //
1240
1241     AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);
1242
1243     return;
1244 }
1245
1246 NTSTATUS
1247 AFSInitCcb( IN OUT AFSCcb **Ccb,
1248             IN     AFSDirectoryCB *DirectoryCB,
1249             IN     ACCESS_MASK     GrantedAccess,
1250             IN     ULONG           FileAccess)
1251 {
1252
1253     NTSTATUS Status = STATUS_SUCCESS;
1254     AFSCcb *pCcb = NULL;
1255     LONG lCount;
1256
1257     __Enter
1258     {
1259
1260         //
1261         // Allocate our context control block
1262         //
1263
1264         pCcb = (AFSCcb *)AFSExAllocatePoolWithTag( PagedPool,
1265                                                    sizeof( AFSCcb),
1266                                                    AFS_CCB_ALLOCATION_TAG);
1267
1268         if( pCcb == NULL)
1269         {
1270
1271             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1272                           AFS_TRACE_LEVEL_ERROR,
1273                           "AFSInitCcb Failed to allocate Ccb\n");
1274
1275             try_return( Status = STATUS_INSUFFICIENT_RESOURCES);
1276         }
1277
1278         RtlZeroMemory( pCcb,
1279                        sizeof( AFSCcb));
1280
1281         pCcb->Size = sizeof( AFSCcb);
1282
1283         pCcb->Type = AFS_CCB;
1284
1285         pCcb->NPCcb = (AFSNonPagedCcb *)AFSExAllocatePoolWithTag( NonPagedPool,
1286                                                      sizeof( AFSNonPagedCcb),
1287                                                      AFS_CCB_NP_ALLOCATION_TAG);
1288
1289         if( pCcb->NPCcb == NULL)
1290         {
1291
1292             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1293                           AFS_TRACE_LEVEL_ERROR,
1294                           "AFSInitCcb Failed to allocate NPCcb\n");
1295
1296             try_return( Status = STATUS_INSUFFICIENT_RESOURCES);
1297         }
1298
1299         ExInitializeResourceLite( &pCcb->NPCcb->CcbLock);
1300
1301         pCcb->DirectoryCB = DirectoryCB;
1302
1303         lCount = InterlockedIncrement( &pCcb->DirectoryCB->DirOpenReferenceCount);
1304
1305         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1306                       AFS_TRACE_LEVEL_VERBOSE,
1307                       "AFSInitCcb Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1308                       &pCcb->DirectoryCB->NameInformation.FileName,
1309                       pCcb->DirectoryCB,
1310                       pCcb,
1311                       lCount);
1312
1313         pCcb->GrantedAccess = GrantedAccess;
1314
1315         pCcb->FileAccess = FileAccess;
1316
1317         //
1318         // Return the Ccb
1319         //
1320
1321         *Ccb = pCcb;
1322
1323 try_exit:
1324
1325         if( !NT_SUCCESS( Status))
1326         {
1327
1328             if( pCcb != NULL)
1329             {
1330
1331                 if ( pCcb->NPCcb != NULL)
1332                 {
1333
1334                     AFSExFreePoolWithTag( pCcb->NPCcb, AFS_CCB_NP_ALLOCATION_TAG);
1335                 }
1336
1337                 AFSExFreePoolWithTag( pCcb, AFS_CCB_ALLOCATION_TAG);
1338             }
1339
1340             *Ccb = NULL;
1341         }
1342     }
1343
1344     return Status;
1345 }
1346
1347 //
1348 // Function: AFSRemoveCcb
1349 //
1350 // Description:
1351 //
1352 //      This function performs Ccb removal/deallocation
1353 //
1354 // Return:
1355 //
1356 //      None
1357 //
1358
1359 void
1360 AFSRemoveCcb( IN AFSFcb *Fcb,
1361               IN AFSCcb *Ccb)
1362 {
1363
1364     LONG lCount;
1365
1366     AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1367                     TRUE);
1368
1369     if( Fcb != NULL &&
1370         BooleanFlagOn( Ccb->Flags, CCB_FLAG_INSERTED_CCB_LIST))
1371     {
1372
1373         AFSAcquireExcl( &Fcb->NPFcb->CcbListLock,
1374                         TRUE);
1375
1376         if( Ccb->ListEntry.fLink == NULL)
1377         {
1378
1379             Fcb->CcbListTail = (AFSCcb *)Ccb->ListEntry.bLink;
1380
1381             if( Fcb->CcbListTail != NULL)
1382             {
1383                 Fcb->CcbListTail->ListEntry.fLink = NULL;
1384             }
1385         }
1386         else
1387         {
1388             ((AFSCcb *)(Ccb->ListEntry.fLink))->ListEntry.bLink = Ccb->ListEntry.bLink;
1389         }
1390
1391         if( Ccb->ListEntry.bLink == NULL)
1392         {
1393
1394             Fcb->CcbListHead = (AFSCcb *)Ccb->ListEntry.fLink;
1395
1396             if( Fcb->CcbListHead != NULL)
1397             {
1398                 Fcb->CcbListHead->ListEntry.bLink = NULL;
1399             }
1400         }
1401         else
1402         {
1403             ((AFSCcb *)(Ccb->ListEntry.bLink))->ListEntry.fLink = Ccb->ListEntry.fLink;
1404         }
1405
1406         AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
1407     }
1408
1409     if( Ccb->MaskName.Buffer != NULL)
1410     {
1411
1412         AFSExFreePoolWithTag( Ccb->MaskName.Buffer, AFS_GENERIC_MEMORY_6_TAG);
1413     }
1414
1415     if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_FREE_FULL_PATHNAME))
1416     {
1417
1418         AFSExFreePoolWithTag( Ccb->FullFileName.Buffer, 0);
1419     }
1420
1421     //
1422     // If we have a name array then delete it
1423     //
1424
1425     if( Ccb->NameArray != NULL)
1426     {
1427
1428         AFSFreeNameArray( Ccb->NameArray);
1429
1430         Ccb->NameArray = NULL;
1431     }
1432
1433     if( Ccb->DirectorySnapshot != NULL)
1434     {
1435
1436         AFSExFreePoolWithTag( Ccb->DirectorySnapshot, AFS_DIR_SNAPSHOT_TAG);
1437
1438         Ccb->DirectorySnapshot = NULL;
1439     }
1440
1441     if( Ccb->NotifyMask.Buffer != NULL)
1442     {
1443
1444         AFSExFreePoolWithTag( Ccb->NotifyMask.Buffer, AFS_GENERIC_MEMORY_7_TAG);
1445     }
1446
1447     if ( Ccb->DirectoryCB != NULL)
1448     {
1449
1450         lCount = InterlockedDecrement( &Ccb->DirectoryCB->DirOpenReferenceCount);
1451
1452         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1453                       AFS_TRACE_LEVEL_VERBOSE,
1454                       "AFSRemoveCcb Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1455                       &Ccb->DirectoryCB->NameInformation.FileName,
1456                       Ccb->DirectoryCB,
1457                       Ccb,
1458                       lCount);
1459
1460         ASSERT( lCount >= 0);
1461     }
1462
1463     AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1464
1465     //
1466     // Free up the Ccb
1467     //
1468
1469     ExDeleteResourceLite( &Ccb->NPCcb->CcbLock);
1470
1471     AFSExFreePoolWithTag( Ccb->NPCcb, AFS_CCB_NP_ALLOCATION_TAG);
1472
1473     AFSExFreePoolWithTag( Ccb, AFS_CCB_ALLOCATION_TAG);
1474 }
1475
1476 NTSTATUS
1477 AFSInsertCcb( IN AFSFcb *Fcb,
1478               IN AFSCcb *Ccb)
1479 {
1480
1481     NTSTATUS ntStatus = STATUS_SUCCESS;
1482
1483     AFSAcquireExcl( &Fcb->NPFcb->CcbListLock,
1484                     TRUE);
1485
1486     AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1487                     TRUE);
1488
1489     if( Fcb->CcbListHead == NULL)
1490     {
1491         Fcb->CcbListHead = Ccb;
1492     }
1493     else
1494     {
1495         Fcb->CcbListTail->ListEntry.fLink = (void *)Ccb;
1496
1497         Ccb->ListEntry.bLink = (void *)Fcb->CcbListTail;
1498     }
1499
1500     Fcb->CcbListTail = Ccb;
1501
1502     SetFlag( Ccb->Flags, CCB_FLAG_INSERTED_CCB_LIST);
1503
1504     AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1505
1506     AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
1507
1508     return ntStatus;
1509 }