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