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