55224aaaccba188c9d4ee744f2d916ffb05119e6
[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                                                   pObjectInfo->FileId.Cell,
836                                                   pObjectInfo->FileId.Volume,
837                                                   pObjectInfo->FileId.Vnode,
838                                                   pObjectInfo->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                                       pDirNode->ObjectInformation->FileId.Cell,
888                                       pDirNode->ObjectInformation->FileId.Volume,
889                                       pDirNode->ObjectInformation->FileId.Vnode,
890                                       pDirNode->ObjectInformation->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                                       pDirNode->ObjectInformation->FileId.Cell,
910                                       pDirNode->ObjectInformation->FileId.Volume,
911                                       pDirNode->ObjectInformation->FileId.Vnode,
912                                       pDirNode->ObjectInformation->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 insert 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     AFSFileEvalResultCB *pEvalResultCB = NULL;
1792     AFSDirEnumEntry *pDirEnumCB = NULL;
1793     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1794
1795     __Enter
1796     {
1797
1798         RtlZeroMemory( &stTargetID,
1799                        sizeof( AFSEvalTargetCB));
1800
1801         if( ObjectInfo->ParentObjectInformation != NULL)
1802         {
1803
1804             stTargetID.ParentId = ObjectInfo->ParentObjectInformation->FileId;
1805         }
1806
1807         //
1808         // Allocate our response buffer
1809         //
1810
1811         pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1812                                                                          PAGE_SIZE,
1813                                                                          AFS_GENERIC_MEMORY_30_TAG);
1814
1815         if( pEvalResultCB == NULL)
1816         {
1817
1818             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1819         }
1820
1821         //
1822         // Call to the service to evaluate the fid
1823         //
1824
1825         ulResultBufferLength = PAGE_SIZE;
1826
1827         if( FastCall)
1828         {
1829
1830             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
1831         }
1832
1833         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
1834                                       ulRequestFlags,
1835                                       AuthGroup,
1836                                       NULL,
1837                                       &ObjectInfo->FileId,
1838                                       &stTargetID,
1839                                       sizeof( AFSEvalTargetCB),
1840                                       pEvalResultCB,
1841                                       &ulResultBufferLength);
1842
1843         if( ntStatus != STATUS_SUCCESS)
1844         {
1845
1846             //
1847             // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
1848             // verification
1849             //
1850
1851             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
1852             {
1853
1854                 if( ObjectInfo->ParentObjectInformation != NULL)
1855                 {
1856
1857                     SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1858                 }
1859             }
1860
1861             try_return( ntStatus);
1862         }
1863
1864         //
1865         // Pass back the dir enum entry
1866         //
1867
1868         if( DirEnumEntry != NULL)
1869         {
1870
1871             pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1872                                                                       PAGE_SIZE,
1873                                                                       AFS_GENERIC_MEMORY_2_TAG);
1874
1875             if( pDirEnumCB == NULL)
1876             {
1877
1878                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1879             }
1880
1881             RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
1882                            ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
1883
1884             *DirEnumEntry = pDirEnumCB;
1885         }
1886
1887 try_exit:
1888
1889         if( pEvalResultCB != NULL)
1890         {
1891
1892             AFSExFreePool( pEvalResultCB);
1893         }
1894
1895         if( !NT_SUCCESS( ntStatus))
1896         {
1897
1898             if( pDirEnumCB != NULL)
1899             {
1900
1901                 AFSExFreePool( pDirEnumCB);
1902             }
1903
1904             *DirEnumEntry = NULL;
1905         }
1906     }
1907
1908     return ntStatus;
1909 }
1910
1911 NTSTATUS
1912 AFSEvaluateTargetByName( IN GUID *AuthGroup,
1913                          IN AFSObjectInfoCB *ParentObjectInfo,
1914                          IN PUNICODE_STRING SourceName,
1915                          OUT AFSDirEnumEntry **DirEnumEntry)
1916 {
1917
1918     NTSTATUS ntStatus = STATUS_SUCCESS;
1919     AFSEvalTargetCB stTargetID;
1920     ULONG ulResultBufferLength;
1921     AFSFileEvalResultCB *pEvalResultCB = NULL;
1922     AFSDirEnumEntry *pDirEnumCB = NULL;
1923
1924     __Enter
1925     {
1926
1927         stTargetID.ParentId = ParentObjectInfo->FileId;
1928
1929         //
1930         // Allocate our response buffer
1931         //
1932
1933         pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1934                                                                          PAGE_SIZE,
1935                                                                          AFS_GENERIC_MEMORY_31_TAG);
1936
1937         if( pEvalResultCB == NULL)
1938         {
1939
1940             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1941         }
1942
1943         //
1944         // Call to the service to evaluate the fid
1945         //
1946
1947         ulResultBufferLength = PAGE_SIZE;
1948
1949         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
1950                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1951                                       AuthGroup,
1952                                       SourceName,
1953                                       NULL,
1954                                       &stTargetID,
1955                                       sizeof( AFSEvalTargetCB),
1956                                       pEvalResultCB,
1957                                       &ulResultBufferLength);
1958
1959         if( ntStatus != STATUS_SUCCESS)
1960         {
1961
1962             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
1963             {
1964                 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1965             }
1966
1967             try_return( ntStatus);
1968         }
1969
1970         //
1971         // Pass back the dir enum entry
1972         //
1973
1974         if( DirEnumEntry != NULL)
1975         {
1976
1977             pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1978                                                                       PAGE_SIZE,
1979                                                                       AFS_GENERIC_MEMORY_3_TAG);
1980
1981             if( pDirEnumCB == NULL)
1982             {
1983
1984                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1985             }
1986
1987             RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
1988                            ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
1989
1990             *DirEnumEntry = pDirEnumCB;
1991         }
1992
1993 try_exit:
1994
1995         if( pEvalResultCB != NULL)
1996         {
1997
1998             AFSExFreePool( pEvalResultCB);
1999         }
2000
2001         if( !NT_SUCCESS( ntStatus))
2002         {
2003
2004             if( pDirEnumCB != NULL)
2005             {
2006
2007                 AFSExFreePool( pDirEnumCB);
2008             }
2009
2010             *DirEnumEntry = NULL;
2011         }
2012     }
2013
2014     return ntStatus;
2015 }
2016
2017 NTSTATUS
2018 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
2019                               IN AFSFileID *FileID,
2020                               OUT AFSVolumeInfoCB *VolumeInformation)
2021 {
2022
2023     NTSTATUS ntStatus = STATUS_SUCCESS;
2024     ULONG ulResultLen = 0;
2025
2026     __Enter
2027     {
2028
2029         ulResultLen = sizeof( AFSVolumeInfoCB);
2030
2031         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
2032                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2033                                       AuthGroup,
2034                                       NULL,
2035                                       FileID,
2036                                       NULL,
2037                                       0,
2038                                       VolumeInformation,
2039                                       &ulResultLen);
2040
2041         if( ntStatus != STATUS_SUCCESS)
2042         {
2043
2044             try_return( ntStatus);
2045         }
2046
2047 try_exit:
2048
2049         NOTHING;
2050     }
2051
2052     return ntStatus;
2053 }
2054
2055 NTSTATUS
2056 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
2057                          IN ULONG InputLength,
2058                          IN ULONG OutputLength,
2059                          IN void *InputDataBuffer,
2060                          OUT void *OutputDataBuffer,
2061                          OUT ULONG *BytesReturned)
2062 {
2063
2064     NTSTATUS ntStatus = STATUS_SUCCESS;
2065     ULONG ulResultLen = 0;
2066     MDL *pInputMdl = NULL, *pOutputMdl = NULL;
2067     void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
2068     ULONG ulBufferLength = OutputLength;
2069     AFSPipeIORequestCB *pIoRequest = NULL;
2070
2071     __Enter
2072     {
2073
2074         //
2075         // Map the user buffer to a system address
2076         //
2077
2078         pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
2079                                                 InputLength,
2080                                                 &pInputMdl);
2081
2082         if( pInputSystemBuffer == NULL)
2083         {
2084
2085             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2086         }
2087
2088         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2089                                                                      sizeof( AFSPipeIORequestCB) +
2090                                                                                 InputLength,
2091                                                                      AFS_GENERIC_MEMORY_4_TAG);
2092
2093         if( pIoRequest == NULL)
2094         {
2095
2096             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2097         }
2098
2099         RtlZeroMemory( pIoRequest,
2100                        sizeof( AFSPipeIORequestCB) + InputLength);
2101
2102         pIoRequest->RequestId = Ccb->RequestID;
2103
2104         pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2105
2106         pIoRequest->BufferLength = InputLength;
2107
2108         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2109                        pInputSystemBuffer,
2110                        InputLength);
2111
2112         pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
2113                                                  OutputLength,
2114                                                  &pOutputMdl);
2115
2116         if( pOutputSystemBuffer == NULL)
2117         {
2118
2119             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2120         }
2121
2122         //
2123         // Send the call to the service
2124         //
2125
2126         ulResultLen = OutputLength;
2127
2128         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
2129                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2130                                       &Ccb->AuthGroup,
2131                                       &Ccb->DirectoryCB->NameInformation.FileName,
2132                                       NULL,
2133                                       pIoRequest,
2134                                       sizeof( AFSPipeIORequestCB) + InputLength,
2135                                       pOutputSystemBuffer,
2136                                       &ulResultLen);
2137
2138         if( ntStatus != STATUS_SUCCESS &&
2139             ntStatus != STATUS_BUFFER_OVERFLOW)
2140         {
2141
2142             if( NT_SUCCESS( ntStatus))
2143             {
2144
2145                 ntStatus = STATUS_DEVICE_NOT_READY;
2146             }
2147
2148             try_return( ntStatus);
2149         }
2150
2151         //
2152         // Return the bytes processed
2153         //
2154
2155         *BytesReturned = ulResultLen;
2156
2157 try_exit:
2158
2159         if( pInputMdl != NULL)
2160         {
2161
2162             MmUnlockPages( pInputMdl);
2163
2164             IoFreeMdl( pInputMdl);
2165         }
2166
2167         if( pOutputMdl != NULL)
2168         {
2169
2170             MmUnlockPages( pOutputMdl);
2171
2172             IoFreeMdl( pOutputMdl);
2173         }
2174
2175         if( pIoRequest != NULL)
2176         {
2177
2178             AFSExFreePool( pIoRequest);
2179         }
2180     }
2181
2182     return ntStatus;
2183 }
2184
2185 NTSTATUS
2186 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
2187                       IN ULONG InformationClass,
2188                       IN ULONG InputLength,
2189                       IN void *DataBuffer)
2190 {
2191
2192     NTSTATUS ntStatus = STATUS_SUCCESS;
2193     AFSPipeInfoRequestCB *pInfoRequest = NULL;
2194
2195     __Enter
2196     {
2197
2198         pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2199                                                                          sizeof( AFSPipeInfoRequestCB) +
2200                                                                                 InputLength,
2201                                                                          AFS_GENERIC_MEMORY_5_TAG);
2202
2203         if( pInfoRequest == NULL)
2204         {
2205
2206             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2207         }
2208
2209         RtlZeroMemory( pInfoRequest,
2210                        sizeof( AFSPipeInfoRequestCB) + InputLength);
2211
2212         pInfoRequest->RequestId = Ccb->RequestID;
2213
2214         pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2215
2216         pInfoRequest->BufferLength = InputLength;
2217
2218         pInfoRequest->InformationClass = InformationClass;
2219
2220         RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
2221                        DataBuffer,
2222                        InputLength);
2223
2224         //
2225         // Send the call to the service
2226         //
2227
2228         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
2229                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2230                                       &Ccb->AuthGroup,
2231                                       &Ccb->DirectoryCB->NameInformation.FileName,
2232                                       NULL,
2233                                       pInfoRequest,
2234                                       sizeof( AFSPipeInfoRequestCB) + InputLength,
2235                                       NULL,
2236                                       NULL);
2237
2238         if( ntStatus != STATUS_SUCCESS)
2239         {
2240
2241             if( NT_SUCCESS( ntStatus))
2242             {
2243
2244                 ntStatus = STATUS_DEVICE_NOT_READY;
2245             }
2246
2247             try_return( ntStatus);
2248         }
2249
2250 try_exit:
2251
2252         if( pInfoRequest != NULL)
2253         {
2254
2255             AFSExFreePool( pInfoRequest);
2256         }
2257     }
2258
2259     return ntStatus;
2260 }
2261
2262 NTSTATUS
2263 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
2264                         IN ULONG InformationClass,
2265                         IN ULONG OutputLength,
2266                         IN void *DataBuffer,
2267                         OUT ULONG *BytesReturned)
2268 {
2269
2270     NTSTATUS ntStatus = STATUS_SUCCESS;
2271     AFSPipeInfoRequestCB stInfoRequest;
2272     ULONG ulBytesProcessed = 0;
2273
2274     __Enter
2275     {
2276
2277         RtlZeroMemory( &stInfoRequest,
2278                        sizeof( AFSPipeInfoRequestCB));
2279
2280         stInfoRequest.RequestId = Ccb->RequestID;
2281
2282         stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2283
2284         stInfoRequest.BufferLength = OutputLength;
2285
2286         stInfoRequest.InformationClass = InformationClass;
2287
2288         ulBytesProcessed = OutputLength;
2289
2290         //
2291         // Send the call to the service
2292         //
2293
2294         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
2295                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2296                                       &Ccb->AuthGroup,
2297                                       &Ccb->DirectoryCB->NameInformation.FileName,
2298                                       NULL,
2299                                       &stInfoRequest,
2300                                       sizeof( AFSPipeInfoRequestCB),
2301                                       DataBuffer,
2302                                       &ulBytesProcessed);
2303
2304         if( ntStatus != STATUS_SUCCESS)
2305         {
2306
2307             if( NT_SUCCESS( ntStatus))
2308             {
2309
2310                 ntStatus = STATUS_DEVICE_NOT_READY;
2311             }
2312
2313             try_return( ntStatus);
2314         }
2315
2316         *BytesReturned = ulBytesProcessed;
2317
2318 try_exit:
2319
2320         NOTHING;
2321     }
2322
2323     return ntStatus;
2324 }
2325
2326 NTSTATUS
2327 AFSReleaseFid( IN AFSFileID *FileId)
2328 {
2329
2330     NTSTATUS ntStatus = STATUS_SUCCESS;
2331
2332     __Enter
2333     {
2334
2335         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2336                                       0,
2337                                       NULL,
2338                                       NULL,
2339                                       FileId,
2340                                       NULL,
2341                                       0,
2342                                       NULL,
2343                                       NULL);
2344     }
2345
2346     return ntStatus;
2347 }
2348
2349 BOOLEAN
2350 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2351                           IN LARGE_INTEGER *ExtentOffset,
2352                           IN ULONG Length)
2353 {
2354
2355     BOOLEAN bRequestQueued = FALSE;
2356     NTSTATUS ntStatus = STATUS_SUCCESS;
2357     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2358     AFSCommSrvcCB   *pCommSrvc = NULL;
2359     AFSPoolEntry    *pPoolEntry = NULL;
2360     AFSRequestExtentsCB *pRequestExtents = NULL;
2361
2362     __Enter
2363     {
2364
2365
2366         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2367
2368         AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2369                           TRUE);
2370
2371         pPoolEntry = pCommSrvc->RequestPoolHead;
2372
2373         while( pPoolEntry != NULL)
2374         {
2375
2376             if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2377             {
2378
2379                 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2380                 {
2381
2382                     pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2383
2384                     if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2385                         pRequestExtents->Length == Length)
2386                     {
2387
2388                         bRequestQueued = TRUE;
2389                     }
2390                 }
2391             }
2392
2393             pPoolEntry = pPoolEntry->fLink;
2394         }
2395
2396         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2397     }
2398
2399     return bRequestQueued;
2400 }