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