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