Windows: Directory Entry Processing
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCommSupport.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: AFSCommSupport.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 NTSTATUS
42 AFSEnumerateDirectory( IN GUID *AuthGroup,
43                        IN AFSObjectInfoCB *ObjectInfoCB,
44                        IN BOOLEAN   FastQuery)
45 {
46
47     NTSTATUS ntStatus = STATUS_SUCCESS;
48     void *pBuffer = NULL;
49     ULONG ulResultLen = 0;
50     AFSDirQueryCB *pDirQueryCB;
51     AFSDirEnumEntry *pCurrentDirEntry = NULL;
52     AFSDirectoryCB *pDirNode = NULL;
53     ULONG  ulEntryLength = 0;
54     AFSDirEnumResp *pDirEnumResponse = NULL;
55     UNICODE_STRING uniDirName, uniTargetName;
56     ULONG   ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
57     ULONG ulCRC = 0;
58     UNICODE_STRING uniGUID;
59
60     __Enter
61     {
62
63         uniGUID.Length = 0;
64         uniGUID.MaximumLength = 0;
65         uniGUID.Buffer = NULL;
66
67         if( AuthGroup != NULL)
68         {
69             RtlStringFromGUID( *AuthGroup,
70                                &uniGUID);
71         }
72
73         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
74                       AFS_TRACE_LEVEL_VERBOSE,
75                       "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
76                       ObjectInfoCB->FileId.Cell,
77                       ObjectInfoCB->FileId.Volume,
78                       ObjectInfoCB->FileId.Vnode,
79                       ObjectInfoCB->FileId.Unique,
80                       &uniGUID);
81
82         if( AuthGroup != NULL)
83         {
84             RtlFreeUnicodeString( &uniGUID);
85         }
86
87         //
88         // Initialize the directory enumeration buffer for the directory
89         //
90
91         pBuffer = AFSExAllocatePoolWithTag( PagedPool,
92                                             AFS_DIR_ENUM_BUFFER_LEN,
93                                             AFS_DIR_BUFFER_TAG);
94
95         if( pBuffer == NULL)
96         {
97
98             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
99         }
100
101         RtlZeroMemory( pBuffer,
102                        AFS_DIR_ENUM_BUFFER_LEN);
103
104         ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
105
106         //
107         // Use the payload buffer for information we will pass to the service
108         //
109
110         pDirQueryCB = (AFSDirQueryCB *)pBuffer;
111
112         pDirQueryCB->EnumHandle = 0;
113
114         if( FastQuery)
115         {
116
117             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
118         }
119
120         //
121         // Loop on the information
122         //
123
124         while( TRUE)
125         {
126
127             //
128             // Go and retrieve the directory contents
129             //
130
131             ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
132                                           ulRequestFlags,
133                                           AuthGroup,
134                                           NULL,
135                                           &ObjectInfoCB->FileId,
136                                           (void *)pDirQueryCB,
137                                           sizeof( AFSDirQueryCB),
138                                           pBuffer,
139                                           &ulResultLen);
140
141             if( ntStatus != STATUS_SUCCESS ||
142                 ulResultLen == 0)
143             {
144
145                 if( ntStatus == STATUS_NO_MORE_FILES ||
146                     ntStatus == STATUS_NO_MORE_ENTRIES)
147                 {
148
149                     ntStatus = STATUS_SUCCESS;
150                 }
151                 else
152                 {
153
154                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
155                                   AFS_TRACE_LEVEL_ERROR,
156                                   "AFSEnumerateDirectory Failed to enumerate directory Status %08lX\n",
157                                   ntStatus);
158                 }
159
160                 break;
161             }
162
163             pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
164
165             pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
166
167             //
168             // Remove the leading header from the processed length
169             //
170
171             ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
172
173             while( ulResultLen > 0)
174             {
175
176                 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
177
178                 uniDirName.MaximumLength = uniDirName.Length;
179
180                 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
181
182                 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
183
184                 uniTargetName.MaximumLength = uniTargetName.Length;
185
186                 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
187
188                 //
189                 // Be sure we don't have this entry in the case sensitive tree
190                 //
191
192                 ulCRC = AFSGenerateCRC( &uniDirName,
193                                         FALSE);
194
195                 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
196                                                 ulCRC,
197                                                 &pDirNode);
198
199                 if( pDirNode != NULL)
200                 {
201
202                     //
203                     // Duplicate entry, skip it
204                     //
205
206                     ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
207                                                     uniDirName.Length +
208                                                     uniTargetName.Length);
209
210                     pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
211
212                     if( ulResultLen >= ulEntryLength)
213                     {
214                         ulResultLen -= ulEntryLength;
215                     }
216                     else
217                     {
218                         ulResultLen = 0;
219                     }
220
221                     continue;
222                 }
223
224                 pDirNode = AFSInitDirEntry( ObjectInfoCB,
225                                             &uniDirName,
226                                             &uniTargetName,
227                                             pCurrentDirEntry,
228                                             (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
229
230                 if( pDirNode == NULL)
231                 {
232
233                     ntStatus = STATUS_INSUFFICIENT_RESOURCES;
234
235                     break;
236                 }
237
238                 //
239                 // Set up the entry length
240                 //
241
242                 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
243                                                     pCurrentDirEntry->FileNameLength +
244                                                     pCurrentDirEntry->TargetNameLength);
245
246                 //
247                 // Init the short name if we have one
248                 //
249
250                 if( pCurrentDirEntry->ShortNameLength > 0)
251                 {
252
253                     UNICODE_STRING uniShortName;
254
255                     pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
256
257                     RtlCopyMemory( pDirNode->NameInformation.ShortName,
258                                    pCurrentDirEntry->ShortName,
259                                    pDirNode->NameInformation.ShortNameLength);
260
261                     //
262                     // Generate the short name index
263                     //
264
265                     uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
266                     uniShortName.MaximumLength = uniShortName.Length;
267                     uniShortName.Buffer = pDirNode->NameInformation.ShortName;
268
269                     if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
270                                                  NULL,
271                                                  NULL))
272                     {
273
274                         pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
275                                                                                            TRUE);
276
277                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
278                                       AFS_TRACE_LEVEL_VERBOSE,
279                                       "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
280                                       &uniShortName,
281                                       pDirNode,
282                                       &pDirNode->NameInformation.FileName,
283                                       pCurrentDirEntry->FileId.Cell,
284                                       pCurrentDirEntry->FileId.Volume,
285                                       pCurrentDirEntry->FileId.Vnode,
286                                       pCurrentDirEntry->FileId.Unique);
287                     }
288                     else
289                     {
290                         pDirNode->NameInformation.ShortNameLength = 0;
291
292                         RtlZeroMemory( pDirNode->NameInformation.ShortName,
293                                        (12 * sizeof( WCHAR)));
294                     }
295                 }
296
297                 //
298                 // Insert the node into the name tree
299                 //
300
301                 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
302
303                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
304                 {
305
306                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
307
308                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
309                                   AFS_TRACE_LEVEL_VERBOSE,
310                                   "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
311                                   pDirNode,
312                                   &pDirNode->NameInformation.FileName);
313                 }
314                 else
315                 {
316
317                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
318                                   AFS_TRACE_LEVEL_VERBOSE,
319                                   "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
320                                   pDirNode,
321                                   &pDirNode->NameInformation.FileName);
322
323                     if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
324                                                                      pDirNode)))
325                     {
326
327                         //
328                         // Delete this dir entry and continue on
329                         //
330
331                         AFSDeleteDirEntry( ObjectInfoCB,
332                                            pDirNode);
333
334                         pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
335
336                         if( ulResultLen >= ulEntryLength)
337                         {
338                             ulResultLen -= ulEntryLength;
339                         }
340                         else
341                         {
342                             ulResultLen = 0;
343                         }
344
345                         continue;
346                     }
347                 }
348
349                 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
350
351                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
352                 {
353
354                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
355                                   AFS_TRACE_LEVEL_VERBOSE,
356                                   "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
357                                   pDirNode,
358                                   &pDirNode->NameInformation.FileName);
359
360                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
361
362                     SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
363                 }
364                 else
365                 {
366
367                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
368                                   AFS_TRACE_LEVEL_VERBOSE,
369                                   "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
370                                   pDirNode,
371                                   &pDirNode->NameInformation.FileName);
372
373                     AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
374                                                       pDirNode);
375                 }
376
377                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
378                 {
379
380                     ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
381                 }
382                 else
383                 {
384
385                     ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
386
387                     pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
388                 }
389
390                 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
391
392                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
393
394                 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
395
396                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
397                               AFS_TRACE_LEVEL_VERBOSE,
398                               "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
399                               &pDirNode->NameInformation.FileName,
400                               ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
401                               ObjectInfoCB->FileId.Cell,
402                               ObjectInfoCB->FileId.Volume,
403                               ObjectInfoCB->FileId.Vnode,
404                               ObjectInfoCB->FileId.Unique);
405
406                 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
407                 {
408
409                     //
410                     // Insert the short name entry if we have a valid short name
411                     //
412
413                     if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
414                     {
415
416                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
417                                       AFS_TRACE_LEVEL_VERBOSE,
418                                       "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
419                                       pDirNode,
420                                       &pDirNode->NameInformation.FileName);
421
422                         ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
423
424                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
425                     }
426                     else
427                     {
428
429                         if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
430                                                                     pDirNode)))
431                         {
432                             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
433
434                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
435                                           AFS_TRACE_LEVEL_VERBOSE,
436                                           "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
437                                           pDirNode,
438                                           &pDirNode->NameInformation.FileName);
439                         }
440                     }
441                 }
442
443                 //
444                 // Next dir entry
445                 //
446
447                 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
448
449                 if( ulResultLen >= ulEntryLength)
450                 {
451                     ulResultLen -= ulEntryLength;
452                 }
453                 else
454                 {
455                     ulResultLen = 0;
456                 }
457             }
458
459             ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
460
461             //
462             // Reset the information in the request buffer since it got trampled
463             // above
464             //
465
466             pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
467
468             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
469                           AFS_TRACE_LEVEL_VERBOSE,
470                           "AFSEnumerateDirectory EnumHandle %08lX\n",
471                           pDirQueryCB->EnumHandle);
472
473             //
474             // If the enumeration handle is -1 then we are done
475             //
476
477             if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
478             {
479
480                 break;
481             }
482         }
483
484 try_exit:
485
486         //
487         // Cleanup
488         //
489
490         if( pBuffer != NULL)
491         {
492
493             AFSExFreePool( pBuffer);
494         }
495
496         //
497         // If the processing failed then we should reset the directory content in the event
498         // it is re-enumerated
499         //
500
501         if( !NT_SUCCESS( ntStatus))
502         {
503
504             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
505                           AFS_TRACE_LEVEL_ERROR,
506                           "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
507                           ObjectInfoCB->FileId.Cell,
508                           ObjectInfoCB->FileId.Volume,
509                           ObjectInfoCB->FileId.Vnode,
510                           ObjectInfoCB->FileId.Unique,
511                           ntStatus);
512
513             AFSResetDirectoryContent( ObjectInfoCB);
514         }
515     }
516
517     return ntStatus;
518 }
519
520 NTSTATUS
521 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
522                                  IN AFSFileID *FileId)
523 {
524
525     NTSTATUS ntStatus = STATUS_SUCCESS;
526     AFSDirQueryCB stDirQueryCB;
527     ULONG   ulRequestFlags = 0;
528
529     __Enter
530     {
531
532         //
533         // Use the payload buffer for information we will pass to the service
534         //
535
536         stDirQueryCB.EnumHandle = 0;
537
538         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
539                                       ulRequestFlags,
540                                       AuthGroup,
541                                       NULL,
542                                       FileId,
543                                       (void *)&stDirQueryCB,
544                                       sizeof( AFSDirQueryCB),
545                                       NULL,
546                                       NULL);
547
548         if( ntStatus != STATUS_SUCCESS)
549         {
550
551             if( ntStatus == STATUS_NO_MORE_FILES ||
552                 ntStatus == STATUS_NO_MORE_ENTRIES)
553             {
554
555                 ntStatus = STATUS_SUCCESS;
556             }
557             else
558             {
559
560                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
561                               AFS_TRACE_LEVEL_ERROR,
562                               "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
563                               ntStatus);
564             }
565         }
566     }
567
568     return ntStatus;
569 }
570
571 NTSTATUS
572 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
573                            IN GUID *AuthGroup)
574 {
575
576     NTSTATUS ntStatus = STATUS_SUCCESS;
577     void *pBuffer = NULL;
578     ULONG ulResultLen = 0;
579     AFSDirQueryCB *pDirQueryCB;
580     AFSDirEnumEntry *pCurrentDirEntry = NULL;
581     AFSDirectoryCB *pDirNode = NULL;
582     ULONG  ulEntryLength = 0;
583     AFSDirEnumResp *pDirEnumResponse = NULL;
584     UNICODE_STRING uniDirName, uniTargetName;
585     ULONG   ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
586     ULONG ulCRC = 0;
587     AFSObjectInfoCB *pObjectInfo = NULL;
588     ULONGLONG ullIndex = 0;
589     UNICODE_STRING uniGUID;
590
591     __Enter
592     {
593
594         uniGUID.Length = 0;
595         uniGUID.MaximumLength = 0;
596         uniGUID.Buffer = NULL;
597
598         if( AuthGroup != NULL)
599         {
600             RtlStringFromGUID( *AuthGroup,
601                                &uniGUID);
602         }
603
604         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
605                       AFS_TRACE_LEVEL_VERBOSE,
606                       "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
607                       ObjectInfoCB->FileId.Cell,
608                       ObjectInfoCB->FileId.Volume,
609                       ObjectInfoCB->FileId.Vnode,
610                       ObjectInfoCB->FileId.Unique,
611                       &uniGUID);
612
613         if( AuthGroup != NULL)
614         {
615             RtlFreeUnicodeString( &uniGUID);
616         }
617
618         //
619         // Initialize the directory enumeration buffer for the directory
620         //
621
622         pBuffer = AFSExAllocatePoolWithTag( PagedPool,
623                                             AFS_DIR_ENUM_BUFFER_LEN,
624                                             AFS_DIR_BUFFER_TAG);
625
626         if( pBuffer == NULL)
627         {
628
629             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
630         }
631
632         RtlZeroMemory( pBuffer,
633                        AFS_DIR_ENUM_BUFFER_LEN);
634
635         ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
636
637         //
638         // Use the payload buffer for information we will pass to the service
639         //
640
641         pDirQueryCB = (AFSDirQueryCB *)pBuffer;
642
643         pDirQueryCB->EnumHandle = 0;
644
645         //
646         // Loop on the information
647         //
648
649         while( TRUE)
650         {
651
652             //
653             // Go and retrieve the directory contents
654             //
655
656             ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
657                                           ulRequestFlags,
658                                           AuthGroup,
659                                           NULL,
660                                           &ObjectInfoCB->FileId,
661                                           (void *)pDirQueryCB,
662                                           sizeof( AFSDirQueryCB),
663                                           pBuffer,
664                                           &ulResultLen);
665
666             if( ntStatus != STATUS_SUCCESS ||
667                 ulResultLen == 0)
668             {
669
670                 if( ntStatus == STATUS_NO_MORE_FILES ||
671                     ntStatus == STATUS_NO_MORE_ENTRIES)
672                 {
673
674                     ntStatus = STATUS_SUCCESS;
675                 }
676                 else
677                 {
678
679                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
680                                   AFS_TRACE_LEVEL_ERROR,
681                                   "AFSVerifyDirectoryContent Failed to enumerate directory Status %08lX\n",
682                                   ntStatus);
683                 }
684
685                 break;
686             }
687
688             pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
689
690             pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
691
692             //
693             // Remove the leading header from the processed length
694             //
695
696             ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
697
698             while( ulResultLen > 0)
699             {
700
701                 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
702
703                 uniDirName.MaximumLength = uniDirName.Length;
704
705                 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
706
707                 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
708
709                 uniTargetName.MaximumLength = uniTargetName.Length;
710
711                 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
712
713                 //
714                 // Does this entry already exist in the directory?
715                 //
716
717                 ulCRC = AFSGenerateCRC( &uniDirName,
718                                         FALSE);
719
720                 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
721
722                 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
723                                                 ulCRC,
724                                                 &pDirNode);
725
726                 //
727                 //
728                 // Set up the entry length
729                 //
730
731                 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
732                                            pCurrentDirEntry->FileNameLength +
733                                            pCurrentDirEntry->TargetNameLength);
734
735                 if( pDirNode != NULL)
736                 {
737
738                     //
739                     // Check that the FIDs are the same
740                     //
741
742                     if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
743                                        &pDirNode->ObjectInformation->FileId))
744                     {
745
746                         AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
747                                           TRUE);
748
749                         ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
750
751                         ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
752                                                        ullIndex,
753                                                        (AFSBTreeEntry **)&pObjectInfo);
754
755                         AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
756
757                         if( NT_SUCCESS( ntStatus) &&
758                             pObjectInfo != NULL)
759                         {
760
761                             //
762                             // Indicate this is a valid entry
763                             //
764
765                             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
766
767                             if( pCurrentDirEntry->ShortNameLength > 0 &&
768                                 pDirNode->NameInformation.ShortNameLength > 0)
769                             {
770                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
771                                               AFS_TRACE_LEVEL_VERBOSE,
772                                               "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) old short name %S New short name %S\n",
773                                               &uniDirName,
774                                               &pDirNode->NameInformation.FileName,
775                                               pDirNode->NameInformation.ShortName,
776                                               pCurrentDirEntry->ShortName);
777                             }
778                             else if( pCurrentDirEntry->ShortNameLength == 0 &&
779                                      pDirNode->NameInformation.ShortNameLength > 0)
780                             {
781                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
782                                               AFS_TRACE_LEVEL_VERBOSE,
783                                               "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) old short name %S New short name NULL\n",
784                                               &uniDirName,
785                                               &pDirNode->NameInformation.FileName,
786                                               pDirNode->NameInformation.ShortName);
787                             }
788                             else if( pCurrentDirEntry->ShortNameLength > 0 &&
789                                      pDirNode->NameInformation.ShortNameLength == 0)
790                             {
791                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
792                                               AFS_TRACE_LEVEL_VERBOSE,
793                                               "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) old short name NULL New short name %S\n",
794                                               &uniDirName,
795                                               &pDirNode->NameInformation.FileName,
796                                               pCurrentDirEntry->ShortName);
797                             }
798                             else
799                             {
800                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
801                                               AFS_TRACE_LEVEL_VERBOSE,
802                                               "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) old short name NULL New short name NULL\n",
803                                               &uniDirName,
804                                               &pDirNode->NameInformation.FileName);
805                             }
806
807                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
808                                           AFS_TRACE_LEVEL_VERBOSE,
809                                           "AFSVerifyDirectoryContent Verified entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
810                                           &uniDirName,
811                                           ObjectInfoCB->FileId.Cell,
812                                           ObjectInfoCB->FileId.Volume,
813                                           ObjectInfoCB->FileId.Vnode,
814                                           ObjectInfoCB->FileId.Unique);
815
816
817                             //
818                             // Update the metadata for the entry
819                             //
820
821                             if( pObjectInfo->DataVersion.QuadPart == 0 ||
822                                 pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
823                             {
824
825                                 AFSUpdateMetaData( pDirNode,
826                                                    pCurrentDirEntry);
827
828                                 if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
829                                 {
830
831                                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
832                                                   AFS_TRACE_LEVEL_VERBOSE,
833                                                   "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
834                                                   &uniDirName,
835                                                   ObjectInfoCB->FileId.Cell,
836                                                   ObjectInfoCB->FileId.Volume,
837                                                   ObjectInfoCB->FileId.Vnode,
838                                                   ObjectInfoCB->FileId.Unique);
839
840                                     SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
841                                     pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
842                                     pObjectInfo->Expiration.QuadPart = 0;
843                                 }
844                             }
845
846                             //
847                             // Next dir entry
848                             //
849
850                             pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
851
852                             if( ulResultLen >= ulEntryLength)
853                             {
854                                 ulResultLen -= ulEntryLength;
855                             }
856                             else
857                             {
858                                 ulResultLen = 0;
859                             }
860
861                             continue;
862                         }
863                     }
864
865                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
866                                   AFS_TRACE_LEVEL_VERBOSE,
867                                   "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
868                                   pDirNode,
869                                   &pDirNode->NameInformation.FileName,
870                                   ObjectInfoCB->FileId.Cell,
871                                   ObjectInfoCB->FileId.Volume,
872                                   ObjectInfoCB->FileId.Vnode,
873                                   ObjectInfoCB->FileId.Unique);
874
875                     //
876                     // Need to tear down this entry and rebuild it below
877                     //
878
879                     if( pDirNode->OpenReferenceCount == 0)
880                     {
881
882                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
883                                       AFS_TRACE_LEVEL_VERBOSE,
884                                       "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
885                                       pDirNode,
886                                       &pDirNode->NameInformation.FileName,
887                                       ObjectInfoCB->FileId.Cell,
888                                       ObjectInfoCB->FileId.Volume,
889                                       ObjectInfoCB->FileId.Vnode,
890                                       ObjectInfoCB->FileId.Unique,
891                                       pCurrentDirEntry->FileId.Cell,
892                                       pCurrentDirEntry->FileId.Volume,
893                                       pCurrentDirEntry->FileId.Vnode,
894                                       pCurrentDirEntry->FileId.Unique);
895
896                         AFSDeleteDirEntry( ObjectInfoCB,
897                                            pDirNode);
898                     }
899                     else
900                     {
901
902                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
903
904                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
905                                       AFS_TRACE_LEVEL_VERBOSE,
906                                       "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
907                                       pDirNode,
908                                       &pDirNode->NameInformation.FileName,
909                                       ObjectInfoCB->FileId.Cell,
910                                       ObjectInfoCB->FileId.Volume,
911                                       ObjectInfoCB->FileId.Vnode,
912                                       ObjectInfoCB->FileId.Unique,
913                                       pCurrentDirEntry->FileId.Cell,
914                                       pCurrentDirEntry->FileId.Volume,
915                                       pCurrentDirEntry->FileId.Vnode,
916                                       pCurrentDirEntry->FileId.Unique);
917
918                         AFSRemoveNameEntry( ObjectInfoCB,
919                                             pDirNode);
920                     }
921                 }
922
923                 pDirNode = AFSInitDirEntry( ObjectInfoCB,
924                                             &uniDirName,
925                                             &uniTargetName,
926                                             pCurrentDirEntry,
927                                             (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
928
929                 if( pDirNode == NULL)
930                 {
931
932                     ntStatus = STATUS_INSUFFICIENT_RESOURCES;
933
934                     break;
935                 }
936
937                 //
938                 // Init the short name if we have one
939                 //
940
941                 if( pCurrentDirEntry->ShortNameLength > 0)
942                 {
943
944                     UNICODE_STRING uniShortName;
945
946                     pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
947
948                     RtlCopyMemory( pDirNode->NameInformation.ShortName,
949                                    pCurrentDirEntry->ShortName,
950                                    pDirNode->NameInformation.ShortNameLength);
951
952                     //
953                     // Generate the short name index
954                     //
955
956                     uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
957                     uniShortName.MaximumLength = uniShortName.Length;
958                     uniShortName.Buffer = pDirNode->NameInformation.ShortName;
959
960                     if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
961                                                  NULL,
962                                                  NULL))
963                     {
964
965                         pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
966                                                                                            TRUE);
967
968                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
969                                       AFS_TRACE_LEVEL_VERBOSE,
970                                       "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
971                                       &uniShortName,
972                                       pDirNode,
973                                       &pDirNode->NameInformation.FileName,
974                                       pCurrentDirEntry->FileId.Cell,
975                                       pCurrentDirEntry->FileId.Volume,
976                                       pCurrentDirEntry->FileId.Vnode,
977                                       pCurrentDirEntry->FileId.Unique);
978                     }
979                     else
980                     {
981                         pDirNode->NameInformation.ShortNameLength = 0;
982
983                         RtlZeroMemory( pDirNode->NameInformation.ShortName,
984                                        (12 * sizeof( WCHAR)));
985                     }
986                 }
987                 else
988                 {
989
990                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
991                                   AFS_TRACE_LEVEL_VERBOSE,
992                                   "AFSVerifyDirectoryContent NO short name for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
993                                   pDirNode,
994                                   &pDirNode->NameInformation.FileName,
995                                   pCurrentDirEntry->FileId.Cell,
996                                   pCurrentDirEntry->FileId.Volume,
997                                   pCurrentDirEntry->FileId.Vnode,
998                                   pCurrentDirEntry->FileId.Unique);
999                 }
1000
1001                 //
1002                 // Insert the node into the name tree
1003                 //
1004
1005                 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1006
1007                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1008                 {
1009
1010                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1011
1012                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1013                                   AFS_TRACE_LEVEL_VERBOSE,
1014                                   "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1015                                   pDirNode,
1016                                   &pDirNode->NameInformation.FileName);
1017                 }
1018                 else
1019                 {
1020
1021                     if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1022                                                                      pDirNode)))
1023                     {
1024                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1025                                       AFS_TRACE_LEVEL_VERBOSE,
1026                                       "AFSVerifyDirectoryContent Failed to nsert DE %p to case sensitive tree for %wZ\n",
1027                                       pDirNode,
1028                                       &pDirNode->NameInformation.FileName);
1029
1030                         //
1031                         // Delete this dir entry and continue on
1032                         //
1033
1034                         AFSDeleteDirEntry( ObjectInfoCB,
1035                                            pDirNode);
1036
1037                         pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1038
1039                         if( ulResultLen >= ulEntryLength)
1040                         {
1041                             ulResultLen -= ulEntryLength;
1042                         }
1043                         else
1044                         {
1045                             ulResultLen = 0;
1046                         }
1047
1048                         continue;
1049                     }
1050                     else
1051                     {
1052                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1053                                       AFS_TRACE_LEVEL_VERBOSE,
1054                                       "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1055                                       pDirNode,
1056                                       &pDirNode->NameInformation.FileName);
1057                     }
1058                 }
1059
1060                 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1061
1062                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1063                 {
1064
1065                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1066
1067                     SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1068
1069                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1070                                   AFS_TRACE_LEVEL_VERBOSE,
1071                                   "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1072                                   pDirNode,
1073                                   &pDirNode->NameInformation.FileName);
1074                 }
1075                 else
1076                 {
1077
1078                     AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1079                                                       pDirNode);
1080
1081                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1082                                   AFS_TRACE_LEVEL_VERBOSE,
1083                                   "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1084                                   pDirNode,
1085                                   &pDirNode->NameInformation.FileName);
1086                 }
1087
1088                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1089                 {
1090
1091                     ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1092                 }
1093                 else
1094                 {
1095
1096                     (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1097
1098                     pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1099                 }
1100
1101                 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1102
1103                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1104
1105                 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1106
1107                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1108                               AFS_TRACE_LEVEL_VERBOSE,
1109                               "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1110                               &pDirNode->NameInformation.FileName,
1111                               ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1112                               ObjectInfoCB->FileId.Cell,
1113                               ObjectInfoCB->FileId.Volume,
1114                               ObjectInfoCB->FileId.Vnode,
1115                               ObjectInfoCB->FileId.Unique);
1116
1117                 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1118                 {
1119
1120                     //
1121                     // Insert the short name entry if we have a valid short name
1122                     //
1123
1124                     if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1125                     {
1126
1127                         ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1128
1129                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1130                                       AFS_TRACE_LEVEL_VERBOSE,
1131                                       "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1132                                       pDirNode,
1133                                       &pDirNode->NameInformation.FileName);
1134
1135                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1136                     }
1137                     else
1138                     {
1139
1140                         if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1141                                                                      pDirNode)))
1142                         {
1143                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1144                                           AFS_TRACE_LEVEL_VERBOSE,
1145                                           "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1146                                           pDirNode,
1147                                           pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1148                                           &pDirNode->NameInformation.FileName);
1149                         }
1150                         else
1151                         {
1152                             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1153
1154                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1155                                           AFS_TRACE_LEVEL_VERBOSE,
1156                                           "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1157                                           pDirNode,
1158                                           &pDirNode->NameInformation.FileName);
1159                         }
1160                     }
1161                 }
1162
1163                 //
1164                 // Next dir entry
1165                 //
1166
1167                 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1168
1169                 if( ulResultLen >= ulEntryLength)
1170                 {
1171                     ulResultLen -= ulEntryLength;
1172                 }
1173                 else
1174                 {
1175                     ulResultLen = 0;
1176                 }
1177             }
1178
1179             ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1180
1181             //
1182             // Reset the information in the request buffer since it got trampled
1183             // above
1184             //
1185
1186             pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1187
1188             //
1189             // If the enumeration handle is -1 then we are done
1190             //
1191
1192             if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
1193             {
1194
1195                 break;
1196             }
1197         }
1198
1199 try_exit:
1200
1201         //
1202         // Cleanup
1203         //
1204
1205         if( pBuffer != NULL)
1206         {
1207
1208             AFSExFreePool( pBuffer);
1209         }
1210     }
1211
1212     return ntStatus;
1213 }
1214
1215 NTSTATUS
1216 AFSNotifyFileCreate( IN GUID            *AuthGroup,
1217                      IN AFSObjectInfoCB *ParentObjectInfo,
1218                      IN PLARGE_INTEGER FileSize,
1219                      IN ULONG FileAttributes,
1220                      IN UNICODE_STRING *FileName,
1221                      OUT AFSDirectoryCB **DirNode)
1222 {
1223
1224     NTSTATUS ntStatus = STATUS_SUCCESS;
1225     AFSFileCreateCB stCreateCB;
1226     AFSFileCreateResultCB *pResultCB = NULL;
1227     ULONG ulResultLen = 0;
1228     UNICODE_STRING uniTargetName;
1229     AFSDirectoryCB *pDirNode = NULL;
1230     ULONG     ulCRC = 0;
1231     LARGE_INTEGER liOldDataVersion;
1232
1233     __Enter
1234     {
1235
1236         //
1237         // Init the control block for the request
1238         //
1239
1240         RtlZeroMemory( &stCreateCB,
1241                        sizeof( AFSFileCreateCB));
1242
1243         stCreateCB.ParentId = ParentObjectInfo->FileId;
1244
1245         stCreateCB.AllocationSize = *FileSize;
1246
1247         stCreateCB.FileAttributes = FileAttributes;
1248
1249         stCreateCB.EaSize = 0;
1250
1251         liOldDataVersion = ParentObjectInfo->DataVersion;
1252
1253         //
1254         // Allocate our return buffer
1255         //
1256
1257         pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1258                                                                        PAGE_SIZE,
1259                                                                        AFS_GENERIC_MEMORY_1_TAG);
1260
1261         if( pResultCB == NULL)
1262         {
1263
1264             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1265         }
1266
1267         RtlZeroMemory( pResultCB,
1268                        PAGE_SIZE);
1269
1270         ulResultLen = PAGE_SIZE;
1271
1272         //
1273         // Send the call to the service
1274         //
1275
1276         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1277                                       AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1278                                       AuthGroup,
1279                                       FileName,
1280                                       NULL,
1281                                       &stCreateCB,
1282                                       sizeof( AFSFileCreateCB),
1283                                       pResultCB,
1284                                       &ulResultLen);
1285
1286         if( ntStatus != STATUS_SUCCESS)
1287         {
1288
1289             if( NT_SUCCESS( ntStatus))
1290             {
1291
1292                 ntStatus = STATUS_DEVICE_NOT_READY;
1293             }
1294
1295             try_return( ntStatus);
1296         }
1297
1298         //
1299         // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1300         // and though we created the node, it is already in our list. If this is the case then
1301         // look up the entry rather than create a new entry
1302         // The check is to ensure the DV has been modified
1303         //
1304
1305         if( liOldDataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1 ||
1306             liOldDataVersion.QuadPart != ParentObjectInfo->DataVersion.QuadPart)
1307         {
1308
1309             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1310                           AFS_TRACE_LEVEL_VERBOSE,
1311                           "AFSNotifyFileCreate Raced with an invalidate call and a re-enumeration for entry %wZ\n",
1312                           FileName);
1313
1314             //
1315             // We raced so go and lookup the directory entry in the parent
1316             //
1317
1318             ulCRC = AFSGenerateCRC( FileName,
1319                                     FALSE);
1320
1321             AFSAcquireShared( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1322                               TRUE);
1323
1324             AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1325                                             ulCRC,
1326                                             &pDirNode);
1327
1328             AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1329
1330             if( pDirNode != NULL)
1331             {
1332
1333                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1334                               AFS_TRACE_LEVEL_VERBOSE,
1335                               "AFSNotifyFileCreate Located dir entry for file %wZ\n",
1336                               FileName);
1337
1338                 *DirNode = pDirNode;
1339
1340                 try_return( ntStatus = STATUS_REPARSE);
1341             }
1342
1343             //
1344             // We are unsure of our current data so set the verify flag. It may already be set
1345             // but no big deal to reset it
1346             //
1347
1348             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1349
1350             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1351         }
1352         else
1353         {
1354
1355             //
1356             // Update the parent data version
1357             //
1358
1359             ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1360         }
1361
1362         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1363                       AFS_TRACE_LEVEL_VERBOSE,
1364                       "AFSNotifyFileCreate Creating new entry %wZ\n",
1365                       FileName);
1366
1367         //
1368         // Initialize the directory entry
1369         //
1370
1371         uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1372
1373         uniTargetName.MaximumLength = uniTargetName.Length;
1374
1375         uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1376
1377         pDirNode = AFSInitDirEntry( ParentObjectInfo,
1378                                     FileName,
1379                                     &uniTargetName,
1380                                     &pResultCB->DirEnum,
1381                                     (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1382
1383         if( pDirNode == NULL)
1384         {
1385
1386             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1387         }
1388
1389         //
1390         // Init the short name if we have one
1391         //
1392
1393         if( pResultCB->DirEnum.ShortNameLength > 0)
1394         {
1395
1396             UNICODE_STRING uniShortName;
1397
1398             pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1399
1400             RtlCopyMemory( pDirNode->NameInformation.ShortName,
1401                            pResultCB->DirEnum.ShortName,
1402                            pDirNode->NameInformation.ShortNameLength);
1403
1404             //
1405             // Generate the short name index
1406             //
1407
1408             uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1409             uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1410
1411             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1412                                                                                TRUE);
1413
1414             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1415                           AFS_TRACE_LEVEL_VERBOSE,
1416                           "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1417                           &uniShortName,
1418                           pDirNode,
1419                           &pDirNode->NameInformation.FileName);
1420         }
1421
1422         //
1423         // Return the directory node
1424         //
1425
1426         *DirNode = pDirNode;
1427
1428 try_exit:
1429
1430         if( pResultCB != NULL)
1431         {
1432
1433             AFSExFreePool( pResultCB);
1434         }
1435     }
1436
1437     return ntStatus;
1438 }
1439
1440 NTSTATUS
1441 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1442                           IN AFSObjectInfoCB *ObjectInfo,
1443                           IN GUID *AuthGroup)
1444 {
1445
1446     NTSTATUS ntStatus = STATUS_SUCCESS;
1447     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1448     AFSFileUpdateCB stUpdateCB;
1449     ULONG ulResultLen = 0;
1450     AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1451
1452     __Enter
1453     {
1454
1455         //
1456         // Init the control block for the request
1457         //
1458
1459         RtlZeroMemory( &stUpdateCB,
1460                        sizeof( AFSFileUpdateCB));
1461
1462         stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1463
1464         stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1465
1466         stUpdateCB.EaSize = ObjectInfo->EaSize;
1467
1468         stUpdateCB.ParentId = *ParentFid;
1469
1470         stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1471
1472         stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1473
1474         stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1475
1476         stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1477
1478         pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1479                                                                              PAGE_SIZE,
1480                                                                              AFS_UPDATE_RESULT_TAG);
1481
1482         if( pUpdateResultCB == NULL)
1483         {
1484
1485             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1486         }
1487
1488         ulResultLen = PAGE_SIZE;
1489
1490         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1491                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1492                                       AuthGroup,
1493                                       NULL,
1494                                       &ObjectInfo->FileId,
1495                                       &stUpdateCB,
1496                                       sizeof( AFSFileUpdateCB),
1497                                       pUpdateResultCB,
1498                                       &ulResultLen);
1499
1500         if( ntStatus != STATUS_SUCCESS)
1501         {
1502
1503             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1504                           AFS_TRACE_LEVEL_ERROR,
1505                           "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1506                           ObjectInfo->FileId.Cell,
1507                           ObjectInfo->FileId.Volume,
1508                           ObjectInfo->FileId.Vnode,
1509                           ObjectInfo->FileId.Unique,
1510                           ntStatus);
1511
1512             try_return( ntStatus);
1513         }
1514
1515         //
1516         // Update the data version
1517         //
1518
1519         ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1520
1521 try_exit:
1522
1523         if( pUpdateResultCB != NULL)
1524         {
1525
1526             AFSExFreePool( pUpdateResultCB);
1527         }
1528     }
1529
1530     return ntStatus;
1531 }
1532
1533 NTSTATUS
1534 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1535                  IN BOOLEAN CheckOnly)
1536 {
1537     NTSTATUS ntStatus = STATUS_SUCCESS;
1538     ULONG ulResultLen = 0;
1539     AFSFileDeleteCB stDelete;
1540     AFSFileDeleteResultCB stDeleteResult;
1541     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1542     GUID *pAuthGroup = NULL;
1543
1544     __Enter
1545     {
1546
1547         stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
1548
1549         stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1550
1551         ulResultLen = sizeof( AFSFileDeleteResultCB);
1552
1553         if( CheckOnly)
1554         {
1555             ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1556         }
1557
1558         if( DirectoryCB->ObjectInformation->Fcb != NULL)
1559         {
1560             pAuthGroup = &DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1561         }
1562
1563         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1564                                       ulRequestFlags,
1565                                       pAuthGroup,
1566                                       &DirectoryCB->NameInformation.FileName,
1567                                       &DirectoryCB->ObjectInformation->FileId,
1568                                       &stDelete,
1569                                       sizeof( AFSFileDeleteCB),
1570                                       &stDeleteResult,
1571                                       &ulResultLen);
1572
1573         if( ntStatus != STATUS_SUCCESS)
1574         {
1575
1576             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1577                           AFS_TRACE_LEVEL_ERROR,
1578                           "AFSNotifyDelete failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1579                           &DirectoryCB->ObjectInformation->FileId.Cell,
1580                           &DirectoryCB->ObjectInformation->FileId.Volume,
1581                           &DirectoryCB->ObjectInformation->FileId.Vnode,
1582                           &DirectoryCB->ObjectInformation->FileId.Unique,
1583                           ntStatus);
1584
1585             try_return( ntStatus);
1586         }
1587
1588         if( !CheckOnly)
1589         {
1590
1591             //
1592             // Update the parent data version
1593             //
1594
1595             if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
1596             {
1597
1598                 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1599
1600                 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1601             }
1602         }
1603
1604 try_exit:
1605
1606         NOTHING;
1607     }
1608
1609     return ntStatus;
1610 }
1611
1612 NTSTATUS
1613 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
1614                  IN AFSObjectInfoCB *ParentObjectInfo,
1615                  IN AFSObjectInfoCB *TargetParentObjectInfo,
1616                  IN AFSDirectoryCB *DirectoryCB,
1617                  IN UNICODE_STRING *TargetName,
1618                  OUT AFSFileID  *UpdatedFID)
1619 {
1620
1621     NTSTATUS ntStatus = STATUS_SUCCESS;
1622     AFSFileRenameCB *pRenameCB = NULL;
1623     AFSFileRenameResultCB *pRenameResultCB = NULL;
1624     ULONG ulResultLen = 0;
1625     GUID *pAuthGroup = NULL;
1626
1627     __Enter
1628     {
1629
1630         //
1631         // Init the control block for the request
1632         //
1633
1634         pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
1635                                                                  PAGE_SIZE,
1636                                                                  AFS_RENAME_REQUEST_TAG);
1637
1638         if( pRenameCB == NULL)
1639         {
1640
1641             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1642         }
1643
1644         RtlZeroMemory( pRenameCB,
1645                        PAGE_SIZE);
1646
1647         pRenameCB->SourceParentId = ParentObjectInfo->FileId;
1648
1649         pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
1650
1651         pRenameCB->TargetNameLength = TargetName->Length;
1652
1653         RtlCopyMemory( pRenameCB->TargetName,
1654                        TargetName->Buffer,
1655                        TargetName->Length);
1656
1657         if( ObjectInfo->Fcb != NULL)
1658         {
1659             pAuthGroup = &ObjectInfo->Fcb->AuthGroup;
1660         }
1661
1662         //
1663         // Use the same buffer for the result control block
1664         //
1665
1666         pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
1667
1668         ulResultLen = PAGE_SIZE;
1669
1670         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
1671                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1672                                       pAuthGroup,
1673                                       &DirectoryCB->NameInformation.FileName,
1674                                       &ObjectInfo->FileId,
1675                                       pRenameCB,
1676                                       sizeof( AFSFileRenameCB) + TargetName->Length,
1677                                       pRenameResultCB,
1678                                       &ulResultLen);
1679
1680         if( ntStatus != STATUS_SUCCESS)
1681         {
1682
1683             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1684                           AFS_TRACE_LEVEL_ERROR,
1685                           "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1686                           ObjectInfo->FileId.Cell,
1687                           ObjectInfo->FileId.Volume,
1688                           ObjectInfo->FileId.Vnode,
1689                           ObjectInfo->FileId.Unique,
1690                           ntStatus);
1691
1692             try_return( ntStatus);
1693         }
1694
1695         //
1696         // Update the information from the returned data
1697         //
1698
1699         ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
1700
1701         TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
1702
1703         //
1704         // Move over the short name
1705         //
1706
1707         DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
1708
1709         if( DirectoryCB->NameInformation.ShortNameLength > 0)
1710         {
1711
1712             UNICODE_STRING uniShortName;
1713
1714             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
1715             uniShortName.MaximumLength = uniShortName.Length;
1716             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
1717
1718             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1719                           AFS_TRACE_LEVEL_VERBOSE,
1720                           "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
1721                           &uniShortName,
1722                           DirectoryCB,
1723                           &DirectoryCB->NameInformation.FileName);
1724
1725             DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
1726
1727             RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
1728                            pRenameResultCB->DirEnum.ShortName,
1729                            DirectoryCB->NameInformation.ShortNameLength);
1730
1731             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
1732             uniShortName.MaximumLength = uniShortName.Length;
1733             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
1734
1735             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1736                           AFS_TRACE_LEVEL_VERBOSE,
1737                           "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
1738                           &uniShortName,
1739                           DirectoryCB,
1740                           &DirectoryCB->NameInformation.FileName);
1741         }
1742         else
1743         {
1744
1745             UNICODE_STRING uniShortName;
1746
1747             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
1748             uniShortName.MaximumLength = uniShortName.Length;
1749             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
1750
1751             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1752                           AFS_TRACE_LEVEL_VERBOSE,
1753                           "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
1754                           &uniShortName,
1755                           DirectoryCB,
1756                           &DirectoryCB->NameInformation.FileName);
1757
1758             DirectoryCB->NameInformation.ShortNameLength = 0;
1759
1760             DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1761         }
1762
1763         if( UpdatedFID != NULL)
1764         {
1765             *UpdatedFID = pRenameResultCB->DirEnum.FileId;
1766         }
1767
1768 try_exit:
1769
1770         if( pRenameCB != NULL)
1771         {
1772
1773             AFSExFreePool( pRenameCB);
1774         }
1775     }
1776
1777     return ntStatus;
1778 }
1779
1780 NTSTATUS
1781 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
1782                        IN GUID *AuthGroup,
1783                        IN BOOLEAN FastCall,
1784                        OUT AFSDirEnumEntry **DirEnumEntry)
1785 {
1786
1787     NTSTATUS ntStatus = STATUS_SUCCESS;
1788     AFSEvalTargetCB stTargetID;
1789     ULONG ulResultBufferLength;
1790     AFSDirEnumEntry *pDirEnumCB = NULL;
1791     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1792
1793     __Enter
1794     {
1795
1796         RtlZeroMemory( &stTargetID,
1797                        sizeof( AFSEvalTargetCB));
1798
1799         if( ObjectInfo->ParentObjectInformation != NULL)
1800         {
1801
1802             stTargetID.ParentId = ObjectInfo->ParentObjectInformation->FileId;
1803         }
1804
1805         //
1806         // Allocate our response buffer
1807         //
1808
1809         pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1810                                                                   PAGE_SIZE,
1811                                                                   AFS_GENERIC_MEMORY_2_TAG);
1812
1813         if( pDirEnumCB == NULL)
1814         {
1815
1816             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1817         }
1818
1819         //
1820         // Call to the service to evaluate the fid
1821         //
1822
1823         ulResultBufferLength = PAGE_SIZE;
1824
1825         if( FastCall)
1826         {
1827
1828             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
1829         }
1830
1831         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
1832                                       ulRequestFlags,
1833                                       AuthGroup,
1834                                       NULL,
1835                                       &ObjectInfo->FileId,
1836                                       &stTargetID,
1837                                       sizeof( AFSEvalTargetCB),
1838                                       pDirEnumCB,
1839                                       &ulResultBufferLength);
1840
1841         if( ntStatus != STATUS_SUCCESS)
1842         {
1843
1844             //
1845             // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
1846             // verification
1847             //
1848
1849             if( ntStatus == STATUS_INVALID_HANDLE)
1850             {
1851
1852                 if( ObjectInfo->ParentObjectInformation != NULL)
1853                 {
1854
1855                     SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1856                 }
1857             }
1858
1859             try_return( ntStatus);
1860         }
1861
1862         //
1863         // Pass back the dir enum entry
1864         //
1865
1866         if( DirEnumEntry != NULL)
1867         {
1868
1869             *DirEnumEntry = pDirEnumCB;
1870         }
1871         else
1872         {
1873
1874             AFSExFreePool( pDirEnumCB);
1875         }
1876
1877 try_exit:
1878
1879         if( !NT_SUCCESS( ntStatus))
1880         {
1881
1882             if( pDirEnumCB != NULL)
1883             {
1884
1885                 AFSExFreePool( pDirEnumCB);
1886             }
1887
1888             *DirEnumEntry = NULL;
1889         }
1890     }
1891
1892     return ntStatus;
1893 }
1894
1895 NTSTATUS
1896 AFSEvaluateTargetByName( IN GUID *AuthGroup,
1897                          IN AFSFileID *ParentFileId,
1898                          IN PUNICODE_STRING SourceName,
1899                          OUT AFSDirEnumEntry **DirEnumEntry)
1900 {
1901
1902     NTSTATUS ntStatus = STATUS_SUCCESS;
1903     AFSEvalTargetCB stTargetID;
1904     ULONG ulResultBufferLength;
1905     AFSDirEnumEntry *pDirEnumCB = NULL;
1906
1907     __Enter
1908     {
1909
1910         stTargetID.ParentId = *ParentFileId;
1911
1912         //
1913         // Allocate our response buffer
1914         //
1915
1916         pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1917                                                                   PAGE_SIZE,
1918                                                                   AFS_GENERIC_MEMORY_3_TAG);
1919
1920         if( pDirEnumCB == NULL)
1921         {
1922
1923             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1924         }
1925
1926         //
1927         // Call to the service to evaluate the fid
1928         //
1929
1930         ulResultBufferLength = PAGE_SIZE;
1931
1932         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
1933                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1934                                       AuthGroup,
1935                                       SourceName,
1936                                       NULL,
1937                                       &stTargetID,
1938                                       sizeof( AFSEvalTargetCB),
1939                                       pDirEnumCB,
1940                                       &ulResultBufferLength);
1941
1942         if( ntStatus != STATUS_SUCCESS)
1943         {
1944
1945             try_return( ntStatus);
1946         }
1947
1948         //
1949         // Pass back the dir enum entry
1950         //
1951
1952         if( DirEnumEntry != NULL)
1953         {
1954
1955             *DirEnumEntry = pDirEnumCB;
1956         }
1957         else
1958         {
1959
1960             AFSExFreePool( pDirEnumCB);
1961         }
1962
1963 try_exit:
1964
1965         if( !NT_SUCCESS( ntStatus))
1966         {
1967
1968             if( pDirEnumCB != NULL)
1969             {
1970
1971                 AFSExFreePool( pDirEnumCB);
1972             }
1973
1974             *DirEnumEntry = NULL;
1975         }
1976     }
1977
1978     return ntStatus;
1979 }
1980
1981 NTSTATUS
1982 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
1983                               IN AFSFileID *FileID,
1984                               OUT AFSVolumeInfoCB *VolumeInformation)
1985 {
1986
1987     NTSTATUS ntStatus = STATUS_SUCCESS;
1988     ULONG ulResultLen = 0;
1989
1990     __Enter
1991     {
1992
1993         ulResultLen = sizeof( AFSVolumeInfoCB);
1994
1995         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
1996                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1997                                       AuthGroup,
1998                                       NULL,
1999                                       FileID,
2000                                       NULL,
2001                                       0,
2002                                       VolumeInformation,
2003                                       &ulResultLen);
2004
2005         if( ntStatus != STATUS_SUCCESS)
2006         {
2007
2008             try_return( ntStatus);
2009         }
2010
2011 try_exit:
2012
2013         NOTHING;
2014     }
2015
2016     return ntStatus;
2017 }
2018
2019 NTSTATUS
2020 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
2021                          IN ULONG InputLength,
2022                          IN ULONG OutputLength,
2023                          IN void *InputDataBuffer,
2024                          OUT void *OutputDataBuffer,
2025                          OUT ULONG *BytesReturned)
2026 {
2027
2028     NTSTATUS ntStatus = STATUS_SUCCESS;
2029     ULONG ulResultLen = 0;
2030     MDL *pInputMdl = NULL, *pOutputMdl = NULL;
2031     void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
2032     ULONG ulBufferLength = OutputLength;
2033     AFSPipeIORequestCB *pIoRequest = NULL;
2034     GUID *pAuthGroup = NULL;
2035
2036     __Enter
2037     {
2038
2039         //
2040         // Map the user buffer to a system address
2041         //
2042
2043         pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
2044                                                 InputLength,
2045                                                 &pInputMdl);
2046
2047         if( pInputSystemBuffer == NULL)
2048         {
2049
2050             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2051         }
2052
2053         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2054                                                                      sizeof( AFSPipeIORequestCB) +
2055                                                                                 InputLength,
2056                                                                      AFS_GENERIC_MEMORY_4_TAG);
2057
2058         if( pIoRequest == NULL)
2059         {
2060
2061             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2062         }
2063
2064         RtlZeroMemory( pIoRequest,
2065                        sizeof( AFSPipeIORequestCB) + InputLength);
2066
2067         pIoRequest->RequestId = Ccb->RequestID;
2068
2069         pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2070
2071         pIoRequest->BufferLength = InputLength;
2072
2073         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2074                        pInputSystemBuffer,
2075                        InputLength);
2076
2077         pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
2078                                                  OutputLength,
2079                                                  &pOutputMdl);
2080
2081         if( pOutputSystemBuffer == NULL)
2082         {
2083
2084             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2085         }
2086
2087         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
2088         {
2089             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
2090         }
2091
2092         //
2093         // Send the call to the service
2094         //
2095
2096         ulResultLen = OutputLength;
2097
2098         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
2099                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2100                                       pAuthGroup,
2101                                       &Ccb->DirectoryCB->NameInformation.FileName,
2102                                       NULL,
2103                                       pIoRequest,
2104                                       sizeof( AFSPipeIORequestCB) + InputLength,
2105                                       pOutputSystemBuffer,
2106                                       &ulResultLen);
2107
2108         if( ntStatus != STATUS_SUCCESS &&
2109             ntStatus != STATUS_BUFFER_OVERFLOW)
2110         {
2111
2112             if( NT_SUCCESS( ntStatus))
2113             {
2114
2115                 ntStatus = STATUS_DEVICE_NOT_READY;
2116             }
2117
2118             try_return( ntStatus);
2119         }
2120
2121         //
2122         // Return the bytes processed
2123         //
2124
2125         *BytesReturned = ulResultLen;
2126
2127 try_exit:
2128
2129         if( pInputMdl != NULL)
2130         {
2131
2132             MmUnlockPages( pInputMdl);
2133
2134             IoFreeMdl( pInputMdl);
2135         }
2136
2137         if( pOutputMdl != NULL)
2138         {
2139
2140             MmUnlockPages( pOutputMdl);
2141
2142             IoFreeMdl( pOutputMdl);
2143         }
2144
2145         if( pIoRequest != NULL)
2146         {
2147
2148             AFSExFreePool( pIoRequest);
2149         }
2150     }
2151
2152     return ntStatus;
2153 }
2154
2155 NTSTATUS
2156 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
2157                       IN ULONG InformationClass,
2158                       IN ULONG InputLength,
2159                       IN void *DataBuffer)
2160 {
2161
2162     NTSTATUS ntStatus = STATUS_SUCCESS;
2163     AFSPipeInfoRequestCB *pInfoRequest = NULL;
2164     GUID *pAuthGroup = NULL;
2165
2166     __Enter
2167     {
2168
2169         pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2170                                                                          sizeof( AFSPipeInfoRequestCB) +
2171                                                                                 InputLength,
2172                                                                          AFS_GENERIC_MEMORY_5_TAG);
2173
2174         if( pInfoRequest == NULL)
2175         {
2176
2177             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2178         }
2179
2180         RtlZeroMemory( pInfoRequest,
2181                        sizeof( AFSPipeInfoRequestCB) + InputLength);
2182
2183         pInfoRequest->RequestId = Ccb->RequestID;
2184
2185         pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2186
2187         pInfoRequest->BufferLength = InputLength;
2188
2189         pInfoRequest->InformationClass = InformationClass;
2190
2191         RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
2192                        DataBuffer,
2193                        InputLength);
2194
2195         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
2196         {
2197             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
2198         }
2199
2200         //
2201         // Send the call to the service
2202         //
2203
2204         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
2205                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2206                                       pAuthGroup,
2207                                       &Ccb->DirectoryCB->NameInformation.FileName,
2208                                       NULL,
2209                                       pInfoRequest,
2210                                       sizeof( AFSPipeInfoRequestCB) + InputLength,
2211                                       NULL,
2212                                       NULL);
2213
2214         if( ntStatus != STATUS_SUCCESS)
2215         {
2216
2217             if( NT_SUCCESS( ntStatus))
2218             {
2219
2220                 ntStatus = STATUS_DEVICE_NOT_READY;
2221             }
2222
2223             try_return( ntStatus);
2224         }
2225
2226 try_exit:
2227
2228         if( pInfoRequest != NULL)
2229         {
2230
2231             AFSExFreePool( pInfoRequest);
2232         }
2233     }
2234
2235     return ntStatus;
2236 }
2237
2238 NTSTATUS
2239 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
2240                         IN ULONG InformationClass,
2241                         IN ULONG OutputLength,
2242                         IN void *DataBuffer,
2243                         OUT ULONG *BytesReturned)
2244 {
2245
2246     NTSTATUS ntStatus = STATUS_SUCCESS;
2247     AFSPipeInfoRequestCB stInfoRequest;
2248     ULONG ulBytesProcessed = 0;
2249     GUID *pAuthGroup = NULL;
2250
2251     __Enter
2252     {
2253
2254         RtlZeroMemory( &stInfoRequest,
2255                        sizeof( AFSPipeInfoRequestCB));
2256
2257         stInfoRequest.RequestId = Ccb->RequestID;
2258
2259         stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2260
2261         stInfoRequest.BufferLength = OutputLength;
2262
2263         stInfoRequest.InformationClass = InformationClass;
2264
2265         ulBytesProcessed = OutputLength;
2266
2267         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
2268         {
2269             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
2270         }
2271
2272         //
2273         // Send the call to the service
2274         //
2275
2276         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
2277                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2278                                       pAuthGroup,
2279                                       &Ccb->DirectoryCB->NameInformation.FileName,
2280                                       NULL,
2281                                       &stInfoRequest,
2282                                       sizeof( AFSPipeInfoRequestCB),
2283                                       DataBuffer,
2284                                       &ulBytesProcessed);
2285
2286         if( ntStatus != STATUS_SUCCESS)
2287         {
2288
2289             if( NT_SUCCESS( ntStatus))
2290             {
2291
2292                 ntStatus = STATUS_DEVICE_NOT_READY;
2293             }
2294
2295             try_return( ntStatus);
2296         }
2297
2298         *BytesReturned = ulBytesProcessed;
2299
2300 try_exit:
2301
2302         NOTHING;
2303     }
2304
2305     return ntStatus;
2306 }
2307
2308 NTSTATUS
2309 AFSReleaseFid( IN AFSFileID *FileId)
2310 {
2311
2312     NTSTATUS ntStatus = STATUS_SUCCESS;
2313
2314     __Enter
2315     {
2316
2317         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2318                                       0,
2319                                       NULL,
2320                                       NULL,
2321                                       FileId,
2322                                       NULL,
2323                                       0,
2324                                       NULL,
2325                                       NULL);
2326     }
2327
2328     return ntStatus;
2329 }
2330
2331 BOOLEAN
2332 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2333                           IN LARGE_INTEGER *ExtentOffset,
2334                           IN ULONG Length)
2335 {
2336
2337     BOOLEAN bRequestQueued = FALSE;
2338     NTSTATUS ntStatus = STATUS_SUCCESS;
2339     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2340     AFSCommSrvcCB   *pCommSrvc = NULL;
2341     AFSPoolEntry    *pPoolEntry = NULL;
2342     AFSRequestExtentsCB *pRequestExtents = NULL;
2343
2344     __Enter
2345     {
2346
2347
2348         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2349
2350         AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2351                           TRUE);
2352
2353         pPoolEntry = pCommSrvc->RequestPoolHead;
2354
2355         while( pPoolEntry != NULL)
2356         {
2357
2358             if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2359             {
2360
2361                 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2362                 {
2363
2364                     pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2365
2366                     if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2367                         pRequestExtents->Length == Length)
2368                     {
2369
2370                         bRequestQueued = TRUE;
2371                     }
2372                 }
2373             }
2374
2375             pPoolEntry = pPoolEntry->fLink;
2376         }
2377
2378         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2379     }
2380
2381     return bRequestQueued;
2382 }