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