Windows: Move Name Array functions to new file
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSNameArray.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011, 2012, 2013 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, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16  *   nor the names of their contributors may be used to endorse or promote
17  *   products derived from this software without specific prior written
18  *   permission from Kernel Drivers, LLC and Your File System, Inc.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 //
34 // File: AFSNameArray.cpp
35 //
36
37 #include "AFSCommon.h"
38
39 AFSNameArrayHdr *
40 AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
41                   IN ULONG InitialElementCount)
42 {
43
44     AFSNameArrayHdr *pNameArray = NULL;
45     AFSNameArrayCB *pCurrentElement = NULL;
46     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
47     LONG lCount;
48
49     __Enter
50     {
51
52         if( InitialElementCount == 0)
53         {
54
55             InitialElementCount = pDevExt->Specific.RDR.NameArrayLength;
56         }
57
58         pNameArray = (AFSNameArrayHdr *)AFSExAllocatePoolWithTag( PagedPool,
59                                                                   sizeof( AFSNameArrayHdr) +
60                                                                     (InitialElementCount * sizeof( AFSNameArrayCB)),
61                                                                   AFS_NAME_ARRAY_TAG);
62
63         if( pNameArray == NULL)
64         {
65
66             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
67                           AFS_TRACE_LEVEL_ERROR,
68                           "AFSInitNameArray Failed to allocate name array\n"));
69
70             try_return( pNameArray);
71         }
72
73         RtlZeroMemory( pNameArray,
74                        sizeof( AFSNameArrayHdr) +
75                           (InitialElementCount * sizeof( AFSNameArrayCB)));
76
77         pNameArray->MaxElementCount = InitialElementCount;
78
79         if( DirectoryCB != NULL)
80         {
81
82             pCurrentElement = &pNameArray->ElementArray[ 0];
83
84             pNameArray->CurrentEntry = pCurrentElement;
85
86             pNameArray->Count = 1;
87
88             pNameArray->LinkCount = 0;
89
90             lCount = InterlockedIncrement( &DirectoryCB->NameArrayReferenceCount);
91
92             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
93                           AFS_TRACE_LEVEL_VERBOSE,
94                           "AFSInitNameArray [NA:%p] Increment count on %wZ DE %p Cnt %d\n",
95                           pNameArray,
96                           &DirectoryCB->NameInformation.FileName,
97                           DirectoryCB,
98                           lCount));
99
100             pCurrentElement->DirectoryCB = DirectoryCB;
101
102             pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
103
104             pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
105
106             if( pCurrentElement->FileId.Vnode == 1)
107             {
108
109                 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
110             }
111
112             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
113                           AFS_TRACE_LEVEL_VERBOSE,
114                           "AFSInitNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
115                           pNameArray,
116                           pCurrentElement->DirectoryCB,
117                           pCurrentElement->FileId.Cell,
118                           pCurrentElement->FileId.Volume,
119                           pCurrentElement->FileId.Vnode,
120                           pCurrentElement->FileId.Unique,
121                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
122                           pCurrentElement->DirectoryCB->ObjectInformation->FileType));
123         }
124
125 try_exit:
126
127         NOTHING;
128     }
129
130     return pNameArray;
131 }
132
133 NTSTATUS
134 AFSPopulateNameArray( IN AFSNameArrayHdr *NameArray,
135                       IN UNICODE_STRING *Path,
136                       IN AFSDirectoryCB *DirectoryCB)
137 {
138
139     NTSTATUS ntStatus = STATUS_SUCCESS;
140     AFSNameArrayCB *pCurrentElement = NULL;
141     LONG lCount;
142
143     __Enter
144     {
145
146         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
147                       AFS_TRACE_LEVEL_VERBOSE,
148                       "AFSPopulateNameArray [NA:%p] passed Path %wZ DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
149                       NameArray,
150                       &Path,
151                       DirectoryCB,
152                       DirectoryCB->ObjectInformation->FileId.Cell,
153                       DirectoryCB->ObjectInformation->FileId.Volume,
154                       DirectoryCB->ObjectInformation->FileId.Vnode,
155                       DirectoryCB->ObjectInformation->FileId.Unique,
156                       &DirectoryCB->NameInformation.FileName,
157                       DirectoryCB->ObjectInformation->FileType));
158
159         //
160         // Init some info in the header
161         //
162
163         pCurrentElement = &NameArray->ElementArray[ 0];
164
165         NameArray->CurrentEntry = pCurrentElement;
166
167         //
168         // The first entry points at the root
169         //
170
171         pCurrentElement->DirectoryCB = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB;
172
173         lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->NameArrayReferenceCount);
174
175         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
176                       AFS_TRACE_LEVEL_VERBOSE,
177                       "AFSPopulateNameArray [NA:%p] Increment count on volume %wZ DE %p Cnt %d\n",
178                       NameArray,
179                       &pCurrentElement->DirectoryCB->NameInformation.FileName,
180                       pCurrentElement->DirectoryCB,
181                       lCount));
182
183         pCurrentElement->Component = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB->NameInformation.FileName;
184
185         pCurrentElement->FileId = DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
186
187         pCurrentElement->Flags = 0;
188
189         if( pCurrentElement->FileId.Vnode == 1)
190         {
191
192             SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
193         }
194
195         NameArray->Count = 1;
196
197         NameArray->LinkCount = 0;
198
199         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
200                       AFS_TRACE_LEVEL_VERBOSE,
201                       "AFSPopulateNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
202                       NameArray,
203                       pCurrentElement->DirectoryCB,
204                       pCurrentElement->FileId.Cell,
205                       pCurrentElement->FileId.Volume,
206                       pCurrentElement->FileId.Vnode,
207                       pCurrentElement->FileId.Unique,
208                       &pCurrentElement->DirectoryCB->NameInformation.FileName,
209                       pCurrentElement->DirectoryCB->ObjectInformation->FileType));
210
211         //
212         // If the root is the parent then we are done ...
213         //
214
215         if( &DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation == DirectoryCB->ObjectInformation)
216         {
217             try_return( ntStatus);
218         }
219
220 try_exit:
221
222         NOTHING;
223     }
224
225     return ntStatus;
226 }
227
228 NTSTATUS
229 AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
230                                       IN AFSNameArrayHdr *RelatedNameArray,
231                                       IN AFSDirectoryCB *DirectoryCB)
232 {
233
234     NTSTATUS ntStatus = STATUS_SUCCESS;
235     AFSNameArrayCB *pCurrentElement = NULL, *pCurrentRelatedElement = NULL;
236     LONG lCount;
237
238     __Enter
239     {
240
241         if ( DirectoryCB)
242         {
243
244             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
245                           AFS_TRACE_LEVEL_VERBOSE,
246                           "AFSPopulateNameArray [NA:%p] passed RelatedNameArray %p DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
247                           NameArray,
248                           RelatedNameArray,
249                           DirectoryCB,
250                           DirectoryCB->ObjectInformation->FileId.Cell,
251                           DirectoryCB->ObjectInformation->FileId.Volume,
252                           DirectoryCB->ObjectInformation->FileId.Vnode,
253                           DirectoryCB->ObjectInformation->FileId.Unique,
254                           &DirectoryCB->NameInformation.FileName,
255                           DirectoryCB->ObjectInformation->FileType));
256         }
257         else
258         {
259
260             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
261                           AFS_TRACE_LEVEL_VERBOSE,
262                           "AFSPopulateNameArray [NA:%p] passed RelatedNameArray %p DE NULL\n",
263                           NameArray,
264                           RelatedNameArray));
265         }
266
267         //
268         // Init some info in the header
269         //
270
271         pCurrentElement = &NameArray->ElementArray[ 0];
272
273         pCurrentRelatedElement = &RelatedNameArray->ElementArray[ 0];
274
275         NameArray->Count = 0;
276
277         NameArray->LinkCount = RelatedNameArray->LinkCount;
278
279         //
280         // Populate the name array with the data from the related array
281         //
282
283         while( TRUE)
284         {
285
286             pCurrentElement->DirectoryCB = pCurrentRelatedElement->DirectoryCB;
287
288             pCurrentElement->Component = pCurrentRelatedElement->DirectoryCB->NameInformation.FileName;
289
290             pCurrentElement->FileId    = pCurrentElement->DirectoryCB->ObjectInformation->FileId;
291
292             pCurrentElement->Flags = 0;
293
294             if( pCurrentElement->FileId.Vnode == 1)
295             {
296
297                 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
298             }
299
300             lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->NameArrayReferenceCount);
301
302             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
303                           AFS_TRACE_LEVEL_VERBOSE,
304                           "AFSPopulateNameArrayFromRelatedArray [NA:%p] Increment count on %wZ DE %p Cnt %d\n",
305                           NameArray,
306                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
307                           pCurrentElement->DirectoryCB,
308                           lCount));
309
310             lCount = InterlockedIncrement( &NameArray->Count);
311
312             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
313                           AFS_TRACE_LEVEL_VERBOSE,
314                           "AFSPopulateNameArrayFromRelatedArray [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
315                           NameArray,
316                           lCount - 1,
317                           pCurrentElement->DirectoryCB,
318                           pCurrentElement->FileId.Cell,
319                           pCurrentElement->FileId.Volume,
320                           pCurrentElement->FileId.Vnode,
321                           pCurrentElement->FileId.Unique,
322                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
323                           pCurrentElement->DirectoryCB->ObjectInformation->FileType));
324
325             if( pCurrentElement->DirectoryCB == DirectoryCB ||
326                 NameArray->Count == RelatedNameArray->Count)
327             {
328
329                 //
330                 // Done ...
331                 //
332
333                 break;
334             }
335
336             pCurrentElement++;
337
338             pCurrentRelatedElement++;
339         }
340
341         NameArray->CurrentEntry = NameArray->Count > 0 ? pCurrentElement : NULL;
342     }
343
344     return ntStatus;
345 }
346
347 NTSTATUS
348 AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
349 {
350
351     NTSTATUS ntStatus = STATUS_SUCCESS;
352     AFSNameArrayCB *pCurrentElement = NULL;
353     LONG lCount, lElement;
354
355     __Enter
356     {
357
358         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
359                       AFS_TRACE_LEVEL_VERBOSE,
360                       "AFSFreeNameArray [NA:%p]\n",
361                       NameArray));
362
363         for ( lElement = 0; lElement < NameArray->Count; lElement++)
364         {
365
366             pCurrentElement = &NameArray->ElementArray[ lElement];
367
368             lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->NameArrayReferenceCount);
369
370             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
371                           AFS_TRACE_LEVEL_VERBOSE,
372                           "AFSFreeNameArray [NA:%p] Decrement count on %wZ DE %p Cnt %d\n",
373                           NameArray,
374                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
375                           pCurrentElement->DirectoryCB,
376                           lCount));
377
378             ASSERT( lCount >= 0);
379         }
380
381         AFSExFreePoolWithTag( NameArray, AFS_NAME_ARRAY_TAG);
382     }
383
384     return ntStatus;
385 }
386
387 NTSTATUS
388 AFSInsertNextElement( IN AFSNameArrayHdr *NameArray,
389                       IN AFSDirectoryCB *DirectoryCB)
390 {
391
392     NTSTATUS ntStatus = STATUS_SUCCESS;
393     AFSNameArrayCB *pCurrentElement = NULL;
394     LONG lCount;
395
396     __Enter
397     {
398
399         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
400                       AFS_TRACE_LEVEL_VERBOSE,
401                       "AFSInsertNextElement [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
402                       NameArray,
403                       DirectoryCB,
404                       DirectoryCB->ObjectInformation->FileId.Cell,
405                       DirectoryCB->ObjectInformation->FileId.Volume,
406                       DirectoryCB->ObjectInformation->FileId.Vnode,
407                       DirectoryCB->ObjectInformation->FileId.Unique,
408                       &DirectoryCB->NameInformation.FileName,
409                       DirectoryCB->ObjectInformation->FileType));
410
411         if( NameArray->Count == (LONG) NameArray->MaxElementCount)
412         {
413
414             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
415                           AFS_TRACE_LEVEL_ERROR,
416                           "AFSInsertNextElement [NA:%p] Name has reached Maximum Size\n",
417                           NameArray));
418
419             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
420         }
421
422         for ( lCount = 0; lCount < NameArray->Count; lCount++)
423         {
424
425             if ( AFSIsEqualFID( &NameArray->ElementArray[ lCount].FileId,
426                                 &DirectoryCB->ObjectInformation->FileId) )
427             {
428
429                 AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
430                               AFS_TRACE_LEVEL_WARNING,
431                               "AFSInsertNextElement [NA:%p] DE %p recursion Status %08X\n",
432                               NameArray,
433                               DirectoryCB,
434                               STATUS_ACCESS_DENIED));
435
436                 try_return( ntStatus = STATUS_ACCESS_DENIED);
437             }
438         }
439
440         if( NameArray->Count > 0)
441         {
442
443             NameArray->CurrentEntry++;
444         }
445         else
446         {
447             NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
448         }
449
450         pCurrentElement = NameArray->CurrentEntry;
451
452         lCount = InterlockedIncrement( &NameArray->Count);
453
454         lCount = InterlockedIncrement( &DirectoryCB->NameArrayReferenceCount);
455
456         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
457                       AFS_TRACE_LEVEL_VERBOSE,
458                       "AFSInsertNextElement [NA:%p] Increment count on %wZ DE %p Cnt %d\n",
459                       NameArray,
460                       &DirectoryCB->NameInformation.FileName,
461                       DirectoryCB,
462                       lCount));
463
464         ASSERT( lCount > 0);
465
466         pCurrentElement->DirectoryCB = DirectoryCB;
467
468         pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
469
470         pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
471
472         pCurrentElement->Flags = 0;
473
474         if( pCurrentElement->FileId.Vnode == 1)
475         {
476
477             SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
478         }
479
480         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
481                       AFS_TRACE_LEVEL_VERBOSE,
482                       "AFSInsertNextElement [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
483                       NameArray,
484                       NameArray->Count - 1,
485                       pCurrentElement->DirectoryCB,
486                       pCurrentElement->FileId.Cell,
487                       pCurrentElement->FileId.Volume,
488                       pCurrentElement->FileId.Vnode,
489                       pCurrentElement->FileId.Unique,
490                       &pCurrentElement->DirectoryCB->NameInformation.FileName,
491                       pCurrentElement->DirectoryCB->ObjectInformation->FileType));
492
493 try_exit:
494
495         NOTHING;
496     }
497
498     return ntStatus;
499 }
500
501 AFSDirectoryCB *
502 AFSBackupEntry( IN AFSNameArrayHdr *NameArray)
503 {
504
505     AFSDirectoryCB *pDirectoryCB = NULL;
506     AFSNameArrayCB *pCurrentElement = NULL;
507     BOOLEAN         bVolumeRoot = FALSE;
508     LONG lCount;
509
510     __Enter
511     {
512
513         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
514                       AFS_TRACE_LEVEL_VERBOSE,
515                       "AFSBackupEntry [NA:%p]\n",
516                       NameArray));
517
518         if( NameArray->Count == 0)
519         {
520
521             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
522                           AFS_TRACE_LEVEL_ERROR,
523                           "AFSBackupEntry [NA:%p] No more entries\n",
524                           NameArray));
525
526             try_return( pCurrentElement);
527         }
528
529         lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->NameArrayReferenceCount);
530
531         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
532                       AFS_TRACE_LEVEL_VERBOSE,
533                       "AFSBackupEntry [NA:%p] Decrement count on %wZ DE %p Cnt %d\n",
534                       NameArray,
535                       &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
536                       NameArray->CurrentEntry->DirectoryCB,
537                       lCount));
538
539         ASSERT( lCount >= 0);
540
541         NameArray->CurrentEntry->DirectoryCB = NULL;
542
543         lCount = InterlockedDecrement( &NameArray->Count);
544
545         if( lCount == 0)
546         {
547             NameArray->CurrentEntry = NULL;
548
549             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
550                           AFS_TRACE_LEVEL_ERROR,
551                           "AFSBackupEntry [NA:%p] No more entries\n",
552                           NameArray));
553         }
554         else
555         {
556
557             bVolumeRoot = BooleanFlagOn( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
558
559             NameArray->CurrentEntry--;
560
561             pCurrentElement = NameArray->CurrentEntry;
562
563             pDirectoryCB = pCurrentElement->DirectoryCB;
564
565             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
566                           AFS_TRACE_LEVEL_VERBOSE,
567                           "AFSBackupEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
568                           NameArray,
569                           NameArray->Count - 1,
570                           pCurrentElement->DirectoryCB,
571                           pCurrentElement->FileId.Cell,
572                           pCurrentElement->FileId.Volume,
573                           pCurrentElement->FileId.Vnode,
574                           pCurrentElement->FileId.Unique,
575                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
576                           pCurrentElement->DirectoryCB->ObjectInformation->FileType));
577
578             //
579             // If the entry we are removing is a volume root,
580             // we must remove the mount point entry as well.
581             // If the NameArray was constructed by checking the
582             // share name via the service, the name array can
583             // contain two volume roots in sequence without a
584             // mount point separating them.
585             //
586
587             if ( bVolumeRoot &&
588                  !BooleanFlagOn( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT))
589             {
590
591                 pDirectoryCB = AFSBackupEntry( NameArray);
592             }
593         }
594
595
596 try_exit:
597
598         NOTHING;
599     }
600
601     return pDirectoryCB;
602 }
603
604 AFSDirectoryCB *
605 AFSGetParentEntry( IN AFSNameArrayHdr *NameArray)
606 {
607
608     AFSDirectoryCB *pDirEntry = NULL;
609     AFSNameArrayCB *pElement = NULL;
610
611     __Enter
612     {
613
614         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
615                       AFS_TRACE_LEVEL_VERBOSE,
616                       "AFSGetParentEntry [NA:%p]\n",
617                       NameArray));
618
619         if( NameArray->Count == 0 ||
620             NameArray->Count == 1)
621         {
622
623             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
624                           AFS_TRACE_LEVEL_ERROR,
625                           "AFSGetParentEntry [NA:%p] No more entries\n",
626                           NameArray));
627
628             try_return( pDirEntry = NULL);
629         }
630
631         pElement = &NameArray->ElementArray[ NameArray->Count - 2];
632
633         pDirEntry = pElement->DirectoryCB;
634
635         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
636                       AFS_TRACE_LEVEL_VERBOSE,
637                       "AFSGetParentEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
638                       NameArray,
639                       NameArray->Count - 2,
640                       pElement->DirectoryCB,
641                       pElement->FileId.Cell,
642                       pElement->FileId.Volume,
643                       pElement->FileId.Vnode,
644                       pElement->FileId.Unique,
645                       &pElement->DirectoryCB->NameInformation.FileName,
646                       pElement->DirectoryCB->ObjectInformation->FileType));
647
648 try_exit:
649
650         NOTHING;
651     }
652
653     return pDirEntry;
654 }
655
656 void
657 AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
658                    IN AFSDirectoryCB *DirectoryCB)
659 {
660
661     AFSNameArrayCB *pCurrentElement = NULL;
662     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
663     LONG lCount, lElement;
664
665     __Enter
666     {
667
668         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
669                       AFS_TRACE_LEVEL_VERBOSE,
670                       "AFSResetNameArray [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
671                       NameArray,
672                       DirectoryCB,
673                       DirectoryCB->ObjectInformation->FileId.Cell,
674                       DirectoryCB->ObjectInformation->FileId.Volume,
675                       DirectoryCB->ObjectInformation->FileId.Vnode,
676                       DirectoryCB->ObjectInformation->FileId.Unique,
677                       &DirectoryCB->NameInformation.FileName,
678                       DirectoryCB->ObjectInformation->FileType));
679
680         //
681         // Dereference previous name array contents
682         //
683
684         for ( lElement = 0; lElement < NameArray->Count; lElement++)
685         {
686
687             pCurrentElement = &NameArray->ElementArray[ lElement];
688
689             lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->NameArrayReferenceCount);
690
691             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
692                           AFS_TRACE_LEVEL_VERBOSE,
693                           "AFSResetNameArray [NA:%p] Decrement count on %wZ DE %p Cnt %d\n",
694                           NameArray,
695                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
696                           pCurrentElement->DirectoryCB,
697                           lCount));
698
699             ASSERT( lCount >= 0);
700         }
701
702         RtlZeroMemory( NameArray,
703                        sizeof( AFSNameArrayHdr) +
704                           ((pDevExt->Specific.RDR.NameArrayLength - 1) * sizeof( AFSNameArrayCB)));
705
706         NameArray->MaxElementCount = pDevExt->Specific.RDR.NameArrayLength;
707
708         if( DirectoryCB != NULL)
709         {
710
711             pCurrentElement = &NameArray->ElementArray[ 0];
712
713             NameArray->CurrentEntry = pCurrentElement;
714
715             NameArray->Count = 1;
716
717             NameArray->LinkCount = 0;
718
719             lCount = InterlockedIncrement( &DirectoryCB->NameArrayReferenceCount);
720
721             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
722                           AFS_TRACE_LEVEL_VERBOSE,
723                           "AFSResetNameArray [NA:%p] Increment count on %wZ DE %p Cnt %d\n",
724                           NameArray,
725                           &DirectoryCB->NameInformation.FileName,
726                           DirectoryCB,
727                           lCount));
728
729             pCurrentElement->DirectoryCB = DirectoryCB;
730
731             pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
732
733             pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
734
735             pCurrentElement->Flags  = 0;
736
737             if( pCurrentElement->FileId.Vnode == 1)
738             {
739
740                 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
741             }
742
743             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
744                           AFS_TRACE_LEVEL_VERBOSE,
745                           "AFSResetNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
746                           NameArray,
747                           pCurrentElement->DirectoryCB,
748                           pCurrentElement->FileId.Cell,
749                           pCurrentElement->FileId.Volume,
750                           pCurrentElement->FileId.Vnode,
751                           pCurrentElement->FileId.Unique,
752                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
753                           pCurrentElement->DirectoryCB->ObjectInformation->FileType));
754         }
755     }
756
757     return;
758 }
759
760 void
761 AFSDumpNameArray( IN AFSNameArrayHdr *NameArray)
762 {
763
764     AFSNameArrayCB *pCurrentElement = NULL;
765
766     pCurrentElement = &NameArray->ElementArray[ 0];
767
768     AFSPrint("AFSDumpNameArray Start (%d)\n", NameArray->Count);
769
770     while( pCurrentElement->DirectoryCB != NULL)
771     {
772
773         AFSPrint("FID %08lX-%08lX-%08lX-%08lX %wZ\n",
774                   pCurrentElement->FileId.Cell,
775                   pCurrentElement->FileId.Volume,
776                   pCurrentElement->FileId.Vnode,
777                   pCurrentElement->FileId.Unique,
778                   &pCurrentElement->DirectoryCB->NameInformation.FileName);
779
780         pCurrentElement++;
781     }
782
783     AFSPrint("AFSDumpNameArray End\n\n");
784
785     return;
786 }