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