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