Windows: Track AuthGroup in Context Control Block
[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             if( pDirNode != NULL)
1329             {
1330
1331                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1332                               AFS_TRACE_LEVEL_VERBOSE,
1333                               "AFSNotifyFileCreate Located dir entry for file %wZ\n",
1334                               FileName);
1335
1336                 InterlockedIncrement( &pDirNode->OpenReferenceCount);
1337
1338                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1339                               AFS_TRACE_LEVEL_VERBOSE,
1340                               "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1341                               &pDirNode->NameInformation.FileName,
1342                               pDirNode,
1343                               pDirNode->OpenReferenceCount);
1344
1345                 *DirNode = pDirNode;
1346
1347                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1348
1349                 try_return( ntStatus = STATUS_REPARSE);
1350             }
1351
1352             AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1353
1354             //
1355             // We are unsure of our current data so set the verify flag. It may already be set
1356             // but no big deal to reset it
1357             //
1358
1359             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1360
1361             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1362         }
1363         else
1364         {
1365
1366             //
1367             // Update the parent data version
1368             //
1369
1370             ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1371         }
1372
1373         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1374                       AFS_TRACE_LEVEL_VERBOSE,
1375                       "AFSNotifyFileCreate Creating new entry %wZ\n",
1376                       FileName);
1377
1378         //
1379         // Initialize the directory entry
1380         //
1381
1382         uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1383
1384         uniTargetName.MaximumLength = uniTargetName.Length;
1385
1386         uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1387
1388         pDirNode = AFSInitDirEntry( ParentObjectInfo,
1389                                     FileName,
1390                                     &uniTargetName,
1391                                     &pResultCB->DirEnum,
1392                                     (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1393
1394         if( pDirNode == NULL)
1395         {
1396
1397             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1398         }
1399
1400         //
1401         // Init the short name if we have one
1402         //
1403
1404         if( pResultCB->DirEnum.ShortNameLength > 0)
1405         {
1406
1407             UNICODE_STRING uniShortName;
1408
1409             pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1410
1411             RtlCopyMemory( pDirNode->NameInformation.ShortName,
1412                            pResultCB->DirEnum.ShortName,
1413                            pDirNode->NameInformation.ShortNameLength);
1414
1415             //
1416             // Generate the short name index
1417             //
1418
1419             uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1420             uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1421
1422             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1423                                                                                TRUE);
1424
1425             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1426                           AFS_TRACE_LEVEL_VERBOSE,
1427                           "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1428                           &uniShortName,
1429                           pDirNode,
1430                           &pDirNode->NameInformation.FileName);
1431         }
1432
1433         //
1434         // Return the directory node
1435         //
1436
1437         *DirNode = pDirNode;
1438
1439 try_exit:
1440
1441         if( pResultCB != NULL)
1442         {
1443
1444             AFSExFreePool( pResultCB);
1445         }
1446     }
1447
1448     return ntStatus;
1449 }
1450
1451 NTSTATUS
1452 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1453                           IN AFSObjectInfoCB *ObjectInfo,
1454                           IN GUID *AuthGroup)
1455 {
1456
1457     NTSTATUS ntStatus = STATUS_SUCCESS;
1458     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1459     AFSFileUpdateCB stUpdateCB;
1460     ULONG ulResultLen = 0;
1461     AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1462
1463     __Enter
1464     {
1465
1466         //
1467         // Init the control block for the request
1468         //
1469
1470         RtlZeroMemory( &stUpdateCB,
1471                        sizeof( AFSFileUpdateCB));
1472
1473         stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1474
1475         stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1476
1477         stUpdateCB.EaSize = ObjectInfo->EaSize;
1478
1479         stUpdateCB.ParentId = *ParentFid;
1480
1481         stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1482
1483         stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1484
1485         stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1486
1487         stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1488
1489         pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1490                                                                              PAGE_SIZE,
1491                                                                              AFS_UPDATE_RESULT_TAG);
1492
1493         if( pUpdateResultCB == NULL)
1494         {
1495
1496             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1497         }
1498
1499         ulResultLen = PAGE_SIZE;
1500
1501         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1502                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1503                                       AuthGroup,
1504                                       NULL,
1505                                       &ObjectInfo->FileId,
1506                                       &stUpdateCB,
1507                                       sizeof( AFSFileUpdateCB),
1508                                       pUpdateResultCB,
1509                                       &ulResultLen);
1510
1511         if( ntStatus != STATUS_SUCCESS)
1512         {
1513
1514             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1515                           AFS_TRACE_LEVEL_ERROR,
1516                           "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1517                           ObjectInfo->FileId.Cell,
1518                           ObjectInfo->FileId.Volume,
1519                           ObjectInfo->FileId.Vnode,
1520                           ObjectInfo->FileId.Unique,
1521                           ntStatus);
1522
1523             try_return( ntStatus);
1524         }
1525
1526         //
1527         // Update the data version
1528         //
1529
1530         ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1531
1532 try_exit:
1533
1534         if( pUpdateResultCB != NULL)
1535         {
1536
1537             AFSExFreePool( pUpdateResultCB);
1538         }
1539     }
1540
1541     return ntStatus;
1542 }
1543
1544 NTSTATUS
1545 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1546                  IN GUID           *AuthGroup,
1547                  IN BOOLEAN         CheckOnly)
1548 {
1549     NTSTATUS ntStatus = STATUS_SUCCESS;
1550     ULONG ulResultLen = 0;
1551     AFSFileDeleteCB stDelete;
1552     AFSFileDeleteResultCB stDeleteResult;
1553     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1554
1555     __Enter
1556     {
1557
1558         stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
1559
1560         stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1561
1562         ulResultLen = sizeof( AFSFileDeleteResultCB);
1563
1564         if( CheckOnly)
1565         {
1566             ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1567         }
1568
1569         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1570                                       ulRequestFlags,
1571                                       AuthGroup,
1572                                       &DirectoryCB->NameInformation.FileName,
1573                                       &DirectoryCB->ObjectInformation->FileId,
1574                                       &stDelete,
1575                                       sizeof( AFSFileDeleteCB),
1576                                       &stDeleteResult,
1577                                       &ulResultLen);
1578
1579         if( ntStatus != STATUS_SUCCESS)
1580         {
1581
1582             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1583                           AFS_TRACE_LEVEL_ERROR,
1584                           "AFSNotifyDelete failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1585                           &DirectoryCB->ObjectInformation->FileId.Cell,
1586                           &DirectoryCB->ObjectInformation->FileId.Volume,
1587                           &DirectoryCB->ObjectInformation->FileId.Vnode,
1588                           &DirectoryCB->ObjectInformation->FileId.Unique,
1589                           ntStatus);
1590
1591             try_return( ntStatus);
1592         }
1593
1594         if( !CheckOnly)
1595         {
1596
1597             //
1598             // Update the parent data version
1599             //
1600
1601             if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
1602             {
1603
1604                 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1605
1606                 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1607             }
1608         }
1609
1610 try_exit:
1611
1612         NOTHING;
1613     }
1614
1615     return ntStatus;
1616 }
1617
1618 NTSTATUS
1619 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
1620                  IN GUID            *AuthGroup,
1621                  IN AFSObjectInfoCB *ParentObjectInfo,
1622                  IN AFSObjectInfoCB *TargetParentObjectInfo,
1623                  IN AFSDirectoryCB *DirectoryCB,
1624                  IN UNICODE_STRING *TargetName,
1625                  OUT AFSFileID  *UpdatedFID)
1626 {
1627
1628     NTSTATUS ntStatus = STATUS_SUCCESS;
1629     AFSFileRenameCB *pRenameCB = NULL;
1630     AFSFileRenameResultCB *pRenameResultCB = NULL;
1631     ULONG ulResultLen = 0;
1632
1633     __Enter
1634     {
1635
1636         //
1637         // Init the control block for the request
1638         //
1639
1640         pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
1641                                                                  PAGE_SIZE,
1642                                                                  AFS_RENAME_REQUEST_TAG);
1643
1644         if( pRenameCB == NULL)
1645         {
1646
1647             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1648         }
1649
1650         RtlZeroMemory( pRenameCB,
1651                        PAGE_SIZE);
1652
1653         pRenameCB->SourceParentId = ParentObjectInfo->FileId;
1654
1655         pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
1656
1657         pRenameCB->TargetNameLength = TargetName->Length;
1658
1659         RtlCopyMemory( pRenameCB->TargetName,
1660                        TargetName->Buffer,
1661                        TargetName->Length);
1662
1663         //
1664         // Use the same buffer for the result control block
1665         //
1666
1667         pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
1668
1669         ulResultLen = PAGE_SIZE;
1670
1671         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
1672                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1673                                       AuthGroup,
1674                                       &DirectoryCB->NameInformation.FileName,
1675                                       &ObjectInfo->FileId,
1676                                       pRenameCB,
1677                                       sizeof( AFSFileRenameCB) + TargetName->Length,
1678                                       pRenameResultCB,
1679                                       &ulResultLen);
1680
1681         if( ntStatus != STATUS_SUCCESS)
1682         {
1683
1684             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1685                           AFS_TRACE_LEVEL_ERROR,
1686                           "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1687                           ObjectInfo->FileId.Cell,
1688                           ObjectInfo->FileId.Volume,
1689                           ObjectInfo->FileId.Vnode,
1690                           ObjectInfo->FileId.Unique,
1691                           ntStatus);
1692
1693             try_return( ntStatus);
1694         }
1695
1696         //
1697         // Update the information from the returned data
1698         //
1699
1700         ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
1701
1702         TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
1703
1704         //
1705         // Move over the short name
1706         //
1707
1708         DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
1709
1710         if( DirectoryCB->NameInformation.ShortNameLength > 0)
1711         {
1712
1713             UNICODE_STRING uniShortName;
1714
1715             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
1716             uniShortName.MaximumLength = uniShortName.Length;
1717             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
1718
1719             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1720                           AFS_TRACE_LEVEL_VERBOSE,
1721                           "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
1722                           &uniShortName,
1723                           DirectoryCB,
1724                           &DirectoryCB->NameInformation.FileName);
1725
1726             DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
1727
1728             RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
1729                            pRenameResultCB->DirEnum.ShortName,
1730                            DirectoryCB->NameInformation.ShortNameLength);
1731
1732             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
1733             uniShortName.MaximumLength = uniShortName.Length;
1734             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
1735
1736             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1737                           AFS_TRACE_LEVEL_VERBOSE,
1738                           "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
1739                           &uniShortName,
1740                           DirectoryCB,
1741                           &DirectoryCB->NameInformation.FileName);
1742         }
1743         else
1744         {
1745
1746             UNICODE_STRING uniShortName;
1747
1748             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
1749             uniShortName.MaximumLength = uniShortName.Length;
1750             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
1751
1752             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1753                           AFS_TRACE_LEVEL_VERBOSE,
1754                           "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
1755                           &uniShortName,
1756                           DirectoryCB,
1757                           &DirectoryCB->NameInformation.FileName);
1758
1759             DirectoryCB->NameInformation.ShortNameLength = 0;
1760
1761             DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1762         }
1763
1764         if( UpdatedFID != NULL)
1765         {
1766             *UpdatedFID = pRenameResultCB->DirEnum.FileId;
1767         }
1768
1769 try_exit:
1770
1771         if( pRenameCB != NULL)
1772         {
1773
1774             AFSExFreePool( pRenameCB);
1775         }
1776     }
1777
1778     return ntStatus;
1779 }
1780
1781 NTSTATUS
1782 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
1783                        IN GUID *AuthGroup,
1784                        IN BOOLEAN FastCall,
1785                        OUT AFSDirEnumEntry **DirEnumEntry)
1786 {
1787
1788     NTSTATUS ntStatus = STATUS_SUCCESS;
1789     AFSEvalTargetCB stTargetID;
1790     ULONG ulResultBufferLength;
1791     AFSDirEnumEntry *pDirEnumCB = NULL;
1792     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1793
1794     __Enter
1795     {
1796
1797         RtlZeroMemory( &stTargetID,
1798                        sizeof( AFSEvalTargetCB));
1799
1800         if( ObjectInfo->ParentObjectInformation != NULL)
1801         {
1802
1803             stTargetID.ParentId = ObjectInfo->ParentObjectInformation->FileId;
1804         }
1805
1806         //
1807         // Allocate our response buffer
1808         //
1809
1810         pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1811                                                                   PAGE_SIZE,
1812                                                                   AFS_GENERIC_MEMORY_2_TAG);
1813
1814         if( pDirEnumCB == NULL)
1815         {
1816
1817             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1818         }
1819
1820         //
1821         // Call to the service to evaluate the fid
1822         //
1823
1824         ulResultBufferLength = PAGE_SIZE;
1825
1826         if( FastCall)
1827         {
1828
1829             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
1830         }
1831
1832         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
1833                                       ulRequestFlags,
1834                                       AuthGroup,
1835                                       NULL,
1836                                       &ObjectInfo->FileId,
1837                                       &stTargetID,
1838                                       sizeof( AFSEvalTargetCB),
1839                                       pDirEnumCB,
1840                                       &ulResultBufferLength);
1841
1842         if( ntStatus != STATUS_SUCCESS)
1843         {
1844
1845             //
1846             // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
1847             // verification
1848             //
1849
1850             if( ntStatus == STATUS_INVALID_HANDLE)
1851             {
1852
1853                 if( ObjectInfo->ParentObjectInformation != NULL)
1854                 {
1855
1856                     SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1857                 }
1858             }
1859
1860             try_return( ntStatus);
1861         }
1862
1863         //
1864         // Pass back the dir enum entry
1865         //
1866
1867         if( DirEnumEntry != NULL)
1868         {
1869
1870             *DirEnumEntry = pDirEnumCB;
1871         }
1872         else
1873         {
1874
1875             AFSExFreePool( pDirEnumCB);
1876         }
1877
1878 try_exit:
1879
1880         if( !NT_SUCCESS( ntStatus))
1881         {
1882
1883             if( pDirEnumCB != NULL)
1884             {
1885
1886                 AFSExFreePool( pDirEnumCB);
1887             }
1888
1889             *DirEnumEntry = NULL;
1890         }
1891     }
1892
1893     return ntStatus;
1894 }
1895
1896 NTSTATUS
1897 AFSEvaluateTargetByName( IN GUID *AuthGroup,
1898                          IN AFSFileID *ParentFileId,
1899                          IN PUNICODE_STRING SourceName,
1900                          OUT AFSDirEnumEntry **DirEnumEntry)
1901 {
1902
1903     NTSTATUS ntStatus = STATUS_SUCCESS;
1904     AFSEvalTargetCB stTargetID;
1905     ULONG ulResultBufferLength;
1906     AFSDirEnumEntry *pDirEnumCB = NULL;
1907
1908     __Enter
1909     {
1910
1911         stTargetID.ParentId = *ParentFileId;
1912
1913         //
1914         // Allocate our response buffer
1915         //
1916
1917         pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1918                                                                   PAGE_SIZE,
1919                                                                   AFS_GENERIC_MEMORY_3_TAG);
1920
1921         if( pDirEnumCB == NULL)
1922         {
1923
1924             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1925         }
1926
1927         //
1928         // Call to the service to evaluate the fid
1929         //
1930
1931         ulResultBufferLength = PAGE_SIZE;
1932
1933         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
1934                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1935                                       AuthGroup,
1936                                       SourceName,
1937                                       NULL,
1938                                       &stTargetID,
1939                                       sizeof( AFSEvalTargetCB),
1940                                       pDirEnumCB,
1941                                       &ulResultBufferLength);
1942
1943         if( ntStatus != STATUS_SUCCESS)
1944         {
1945
1946             try_return( ntStatus);
1947         }
1948
1949         //
1950         // Pass back the dir enum entry
1951         //
1952
1953         if( DirEnumEntry != NULL)
1954         {
1955
1956             *DirEnumEntry = pDirEnumCB;
1957         }
1958         else
1959         {
1960
1961             AFSExFreePool( pDirEnumCB);
1962         }
1963
1964 try_exit:
1965
1966         if( !NT_SUCCESS( ntStatus))
1967         {
1968
1969             if( pDirEnumCB != NULL)
1970             {
1971
1972                 AFSExFreePool( pDirEnumCB);
1973             }
1974
1975             *DirEnumEntry = NULL;
1976         }
1977     }
1978
1979     return ntStatus;
1980 }
1981
1982 NTSTATUS
1983 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
1984                               IN AFSFileID *FileID,
1985                               OUT AFSVolumeInfoCB *VolumeInformation)
1986 {
1987
1988     NTSTATUS ntStatus = STATUS_SUCCESS;
1989     ULONG ulResultLen = 0;
1990
1991     __Enter
1992     {
1993
1994         ulResultLen = sizeof( AFSVolumeInfoCB);
1995
1996         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
1997                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1998                                       AuthGroup,
1999                                       NULL,
2000                                       FileID,
2001                                       NULL,
2002                                       0,
2003                                       VolumeInformation,
2004                                       &ulResultLen);
2005
2006         if( ntStatus != STATUS_SUCCESS)
2007         {
2008
2009             try_return( ntStatus);
2010         }
2011
2012 try_exit:
2013
2014         NOTHING;
2015     }
2016
2017     return ntStatus;
2018 }
2019
2020 NTSTATUS
2021 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
2022                          IN ULONG InputLength,
2023                          IN ULONG OutputLength,
2024                          IN void *InputDataBuffer,
2025                          OUT void *OutputDataBuffer,
2026                          OUT ULONG *BytesReturned)
2027 {
2028
2029     NTSTATUS ntStatus = STATUS_SUCCESS;
2030     ULONG ulResultLen = 0;
2031     MDL *pInputMdl = NULL, *pOutputMdl = NULL;
2032     void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
2033     ULONG ulBufferLength = OutputLength;
2034     AFSPipeIORequestCB *pIoRequest = 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         //
2088         // Send the call to the service
2089         //
2090
2091         ulResultLen = OutputLength;
2092
2093         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
2094                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2095                                       &Ccb->AuthGroup,
2096                                       &Ccb->DirectoryCB->NameInformation.FileName,
2097                                       NULL,
2098                                       pIoRequest,
2099                                       sizeof( AFSPipeIORequestCB) + InputLength,
2100                                       pOutputSystemBuffer,
2101                                       &ulResultLen);
2102
2103         if( ntStatus != STATUS_SUCCESS &&
2104             ntStatus != STATUS_BUFFER_OVERFLOW)
2105         {
2106
2107             if( NT_SUCCESS( ntStatus))
2108             {
2109
2110                 ntStatus = STATUS_DEVICE_NOT_READY;
2111             }
2112
2113             try_return( ntStatus);
2114         }
2115
2116         //
2117         // Return the bytes processed
2118         //
2119
2120         *BytesReturned = ulResultLen;
2121
2122 try_exit:
2123
2124         if( pInputMdl != NULL)
2125         {
2126
2127             MmUnlockPages( pInputMdl);
2128
2129             IoFreeMdl( pInputMdl);
2130         }
2131
2132         if( pOutputMdl != NULL)
2133         {
2134
2135             MmUnlockPages( pOutputMdl);
2136
2137             IoFreeMdl( pOutputMdl);
2138         }
2139
2140         if( pIoRequest != NULL)
2141         {
2142
2143             AFSExFreePool( pIoRequest);
2144         }
2145     }
2146
2147     return ntStatus;
2148 }
2149
2150 NTSTATUS
2151 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
2152                       IN ULONG InformationClass,
2153                       IN ULONG InputLength,
2154                       IN void *DataBuffer)
2155 {
2156
2157     NTSTATUS ntStatus = STATUS_SUCCESS;
2158     AFSPipeInfoRequestCB *pInfoRequest = NULL;
2159
2160     __Enter
2161     {
2162
2163         pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2164                                                                          sizeof( AFSPipeInfoRequestCB) +
2165                                                                                 InputLength,
2166                                                                          AFS_GENERIC_MEMORY_5_TAG);
2167
2168         if( pInfoRequest == NULL)
2169         {
2170
2171             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2172         }
2173
2174         RtlZeroMemory( pInfoRequest,
2175                        sizeof( AFSPipeInfoRequestCB) + InputLength);
2176
2177         pInfoRequest->RequestId = Ccb->RequestID;
2178
2179         pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2180
2181         pInfoRequest->BufferLength = InputLength;
2182
2183         pInfoRequest->InformationClass = InformationClass;
2184
2185         RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
2186                        DataBuffer,
2187                        InputLength);
2188
2189         //
2190         // Send the call to the service
2191         //
2192
2193         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
2194                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2195                                       &Ccb->AuthGroup,
2196                                       &Ccb->DirectoryCB->NameInformation.FileName,
2197                                       NULL,
2198                                       pInfoRequest,
2199                                       sizeof( AFSPipeInfoRequestCB) + InputLength,
2200                                       NULL,
2201                                       NULL);
2202
2203         if( ntStatus != STATUS_SUCCESS)
2204         {
2205
2206             if( NT_SUCCESS( ntStatus))
2207             {
2208
2209                 ntStatus = STATUS_DEVICE_NOT_READY;
2210             }
2211
2212             try_return( ntStatus);
2213         }
2214
2215 try_exit:
2216
2217         if( pInfoRequest != NULL)
2218         {
2219
2220             AFSExFreePool( pInfoRequest);
2221         }
2222     }
2223
2224     return ntStatus;
2225 }
2226
2227 NTSTATUS
2228 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
2229                         IN ULONG InformationClass,
2230                         IN ULONG OutputLength,
2231                         IN void *DataBuffer,
2232                         OUT ULONG *BytesReturned)
2233 {
2234
2235     NTSTATUS ntStatus = STATUS_SUCCESS;
2236     AFSPipeInfoRequestCB stInfoRequest;
2237     ULONG ulBytesProcessed = 0;
2238
2239     __Enter
2240     {
2241
2242         RtlZeroMemory( &stInfoRequest,
2243                        sizeof( AFSPipeInfoRequestCB));
2244
2245         stInfoRequest.RequestId = Ccb->RequestID;
2246
2247         stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2248
2249         stInfoRequest.BufferLength = OutputLength;
2250
2251         stInfoRequest.InformationClass = InformationClass;
2252
2253         ulBytesProcessed = OutputLength;
2254
2255         //
2256         // Send the call to the service
2257         //
2258
2259         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
2260                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2261                                       &Ccb->AuthGroup,
2262                                       &Ccb->DirectoryCB->NameInformation.FileName,
2263                                       NULL,
2264                                       &stInfoRequest,
2265                                       sizeof( AFSPipeInfoRequestCB),
2266                                       DataBuffer,
2267                                       &ulBytesProcessed);
2268
2269         if( ntStatus != STATUS_SUCCESS)
2270         {
2271
2272             if( NT_SUCCESS( ntStatus))
2273             {
2274
2275                 ntStatus = STATUS_DEVICE_NOT_READY;
2276             }
2277
2278             try_return( ntStatus);
2279         }
2280
2281         *BytesReturned = ulBytesProcessed;
2282
2283 try_exit:
2284
2285         NOTHING;
2286     }
2287
2288     return ntStatus;
2289 }
2290
2291 NTSTATUS
2292 AFSReleaseFid( IN AFSFileID *FileId)
2293 {
2294
2295     NTSTATUS ntStatus = STATUS_SUCCESS;
2296
2297     __Enter
2298     {
2299
2300         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2301                                       0,
2302                                       NULL,
2303                                       NULL,
2304                                       FileId,
2305                                       NULL,
2306                                       0,
2307                                       NULL,
2308                                       NULL);
2309     }
2310
2311     return ntStatus;
2312 }
2313
2314 BOOLEAN
2315 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2316                           IN LARGE_INTEGER *ExtentOffset,
2317                           IN ULONG Length)
2318 {
2319
2320     BOOLEAN bRequestQueued = FALSE;
2321     NTSTATUS ntStatus = STATUS_SUCCESS;
2322     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2323     AFSCommSrvcCB   *pCommSrvc = NULL;
2324     AFSPoolEntry    *pPoolEntry = NULL;
2325     AFSRequestExtentsCB *pRequestExtents = NULL;
2326
2327     __Enter
2328     {
2329
2330
2331         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2332
2333         AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2334                           TRUE);
2335
2336         pPoolEntry = pCommSrvc->RequestPoolHead;
2337
2338         while( pPoolEntry != NULL)
2339         {
2340
2341             if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2342             {
2343
2344                 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2345                 {
2346
2347                     pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2348
2349                     if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2350                         pRequestExtents->Length == Length)
2351                     {
2352
2353                         bRequestQueued = TRUE;
2354                     }
2355                 }
2356             }
2357
2358             pPoolEntry = pPoolEntry->fLink;
2359         }
2360
2361         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2362     }
2363
2364     return bRequestQueued;
2365 }