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