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