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