5bf60531b2decf30529741523ae01e91e6476848
[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             AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
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                             // if successfully queued.  Cannot call AFSPerformObjectInvalidate directly
1074                             // because ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock is
1075                             // held during the sequence AFSVerifyEntry->AFSValidateDirectoryCache->
1076                             // AFSVerifyDirectoryContent and AFSPerformObjectInvalidate requires the
1077                             // Fcb->NPFcb->Resource which must be held prior to the TreeLock in the
1078                             // lock hierarchy.
1079                             //
1080
1081                             lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1082
1083                             if ( !NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
1084                                                                         AFS_INVALIDATE_DATA_VERSION)))
1085                             {
1086
1087                                 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1088                             }
1089                         }
1090                         else
1091                         {
1092
1093                             AFSUpdateMetaData( pDirNode,
1094                                                pCurrentDirEntry);
1095                         }
1096
1097                         //
1098                         // Next dir entry
1099                         //
1100
1101                         pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1102
1103                         if( ulResultLen >= ulEntryLength)
1104                         {
1105                             ulResultLen -= ulEntryLength;
1106                         }
1107                         else
1108                         {
1109                             ulResultLen = 0;
1110                         }
1111
1112                         continue;
1113                     }
1114                 }
1115                 else if ( pDirNode)
1116                 {
1117
1118                     //
1119                     // File name matches but FileID does not.
1120                     //
1121
1122                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1123                                   AFS_TRACE_LEVEL_VERBOSE,
1124                                   "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1125                                   pDirNode,
1126                                   &pDirNode->NameInformation.FileName,
1127                                   ObjectInfoCB->FileId.Cell,
1128                                   ObjectInfoCB->FileId.Volume,
1129                                   ObjectInfoCB->FileId.Vnode,
1130                                   ObjectInfoCB->FileId.Unique);
1131
1132                     //
1133                     // Need to tear down this entry and rebuild it below
1134                     //
1135
1136                     if( pDirNode->OpenReferenceCount == 0)
1137                     {
1138
1139                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1140                                       AFS_TRACE_LEVEL_VERBOSE,
1141                                       "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1142                                       pDirNode,
1143                                       &pDirNode->NameInformation.FileName,
1144                                       pDirNode->ObjectInformation->FileId.Cell,
1145                                       pDirNode->ObjectInformation->FileId.Volume,
1146                                       pDirNode->ObjectInformation->FileId.Vnode,
1147                                       pDirNode->ObjectInformation->FileId.Unique,
1148                                       pCurrentDirEntry->FileId.Cell,
1149                                       pCurrentDirEntry->FileId.Volume,
1150                                       pCurrentDirEntry->FileId.Vnode,
1151                                       pCurrentDirEntry->FileId.Unique);
1152
1153                         AFSDeleteDirEntry( ObjectInfoCB,
1154                                            pDirNode);
1155                     }
1156                     else
1157                     {
1158
1159                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1160
1161                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1162                                       AFS_TRACE_LEVEL_WARNING,
1163                                       "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1164                                       pDirNode,
1165                                       &pDirNode->NameInformation.FileName,
1166                                       pDirNode->ObjectInformation->FileId.Cell,
1167                                       pDirNode->ObjectInformation->FileId.Volume,
1168                                       pDirNode->ObjectInformation->FileId.Vnode,
1169                                       pDirNode->ObjectInformation->FileId.Unique,
1170                                       pCurrentDirEntry->FileId.Cell,
1171                                       pCurrentDirEntry->FileId.Volume,
1172                                       pCurrentDirEntry->FileId.Vnode,
1173                                       pCurrentDirEntry->FileId.Unique);
1174
1175                         AFSRemoveNameEntry( ObjectInfoCB,
1176                                             pDirNode);
1177                     }
1178                 }
1179                 else
1180                 {
1181
1182                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1183                                   AFS_TRACE_LEVEL_VERBOSE,
1184                                   "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1185                                   &uniDirName,
1186                                   ObjectInfoCB->FileId.Cell,
1187                                   ObjectInfoCB->FileId.Volume,
1188                                   ObjectInfoCB->FileId.Vnode,
1189                                   ObjectInfoCB->FileId.Unique);
1190                 }
1191
1192                 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1193                                             &uniDirName,
1194                                             &uniTargetName,
1195                                             pCurrentDirEntry,
1196                                             (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1197
1198                 if( pDirNode == NULL)
1199                 {
1200
1201                     ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1202
1203                     break;
1204                 }
1205
1206                 AFSUpdateMetaData( pDirNode,
1207                                    pCurrentDirEntry);
1208
1209                 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1210                 {
1211
1212                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1213                                   AFS_TRACE_LEVEL_VERBOSE,
1214                                   "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1215                                   &uniDirName,
1216                                   pDirNode->ObjectInformation->FileId.Cell,
1217                                   pDirNode->ObjectInformation->FileId.Volume,
1218                                   pDirNode->ObjectInformation->FileId.Vnode,
1219                                   pDirNode->ObjectInformation->FileId.Unique);
1220
1221                     AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1222                                     TRUE);
1223
1224                     SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1225
1226                     pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1227
1228                     AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1229                 }
1230
1231                 //
1232                 // Init the short name if we have one
1233                 //
1234
1235                 if( pCurrentDirEntry->ShortNameLength > 0)
1236                 {
1237
1238                     UNICODE_STRING uniShortName;
1239
1240                     pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1241
1242                     RtlCopyMemory( pDirNode->NameInformation.ShortName,
1243                                    pCurrentDirEntry->ShortName,
1244                                    pDirNode->NameInformation.ShortNameLength);
1245
1246                     //
1247                     // Generate the short name index
1248                     //
1249
1250                     uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1251                     uniShortName.MaximumLength = uniShortName.Length;
1252                     uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1253
1254                     if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1255                                                  NULL,
1256                                                  NULL))
1257                     {
1258
1259                         pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1260                                                                                            TRUE);
1261
1262                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1263                                       AFS_TRACE_LEVEL_VERBOSE,
1264                                       "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1265                                       &uniShortName,
1266                                       pDirNode,
1267                                       &pDirNode->NameInformation.FileName,
1268                                       pCurrentDirEntry->FileId.Cell,
1269                                       pCurrentDirEntry->FileId.Volume,
1270                                       pCurrentDirEntry->FileId.Vnode,
1271                                       pCurrentDirEntry->FileId.Unique);
1272                     }
1273                     else
1274                     {
1275                         pDirNode->NameInformation.ShortNameLength = 0;
1276
1277                         RtlZeroMemory( pDirNode->NameInformation.ShortName,
1278                                        (12 * sizeof( WCHAR)));
1279                     }
1280                 }
1281                 else
1282                 {
1283
1284                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1285                                   AFS_TRACE_LEVEL_VERBOSE,
1286                                   "AFSVerifyDirectoryContent NO short name for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1287                                   pDirNode,
1288                                   &pDirNode->NameInformation.FileName,
1289                                   pCurrentDirEntry->FileId.Cell,
1290                                   pCurrentDirEntry->FileId.Volume,
1291                                   pCurrentDirEntry->FileId.Vnode,
1292                                   pCurrentDirEntry->FileId.Unique);
1293                 }
1294
1295                 //
1296                 // Insert the node into the name tree
1297                 //
1298
1299                 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1300
1301                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1302                 {
1303
1304                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1305
1306                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1307                                   AFS_TRACE_LEVEL_VERBOSE,
1308                                   "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1309                                   pDirNode,
1310                                   &pDirNode->NameInformation.FileName);
1311                 }
1312                 else
1313                 {
1314
1315                     if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1316                                                                      pDirNode)))
1317                     {
1318                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1319                                       AFS_TRACE_LEVEL_VERBOSE,
1320                                       "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1321                                       pDirNode,
1322                                       &pDirNode->NameInformation.FileName);
1323
1324                         //
1325                         // Delete this dir entry and continue on
1326                         //
1327
1328                         AFSDeleteDirEntry( ObjectInfoCB,
1329                                            pDirNode);
1330
1331                         pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1332
1333                         if( ulResultLen >= ulEntryLength)
1334                         {
1335                             ulResultLen -= ulEntryLength;
1336                         }
1337                         else
1338                         {
1339                             ulResultLen = 0;
1340                         }
1341
1342                         continue;
1343                     }
1344                     else
1345                     {
1346                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1347                                       AFS_TRACE_LEVEL_VERBOSE,
1348                                       "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1349                                       pDirNode,
1350                                       &pDirNode->NameInformation.FileName);
1351                     }
1352                 }
1353
1354                 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1355
1356                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1357                 {
1358
1359                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1360
1361                     SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1362
1363                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1364                                   AFS_TRACE_LEVEL_VERBOSE,
1365                                   "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1366                                   pDirNode,
1367                                   &pDirNode->NameInformation.FileName);
1368                 }
1369                 else
1370                 {
1371
1372                     AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1373                                                       pDirNode);
1374
1375                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1376                                   AFS_TRACE_LEVEL_VERBOSE,
1377                                   "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1378                                   pDirNode,
1379                                   &pDirNode->NameInformation.FileName);
1380                 }
1381
1382                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1383                 {
1384
1385                     ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1386                 }
1387                 else
1388                 {
1389
1390                     (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1391
1392                     pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1393                 }
1394
1395                 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1396
1397                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1398
1399                 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1400
1401                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1402                               AFS_TRACE_LEVEL_VERBOSE,
1403                               "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1404                               &pDirNode->NameInformation.FileName,
1405                               ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1406                               ObjectInfoCB->FileId.Cell,
1407                               ObjectInfoCB->FileId.Volume,
1408                               ObjectInfoCB->FileId.Vnode,
1409                               ObjectInfoCB->FileId.Unique);
1410
1411                 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1412                 {
1413
1414                     //
1415                     // Insert the short name entry if we have a valid short name
1416                     //
1417
1418                     if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1419                     {
1420
1421                         ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1422
1423                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1424                                       AFS_TRACE_LEVEL_VERBOSE,
1425                                       "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1426                                       pDirNode,
1427                                       &pDirNode->NameInformation.FileName);
1428
1429                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1430                     }
1431                     else
1432                     {
1433
1434                         if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1435                                                                      pDirNode)))
1436                         {
1437                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1438                                           AFS_TRACE_LEVEL_VERBOSE,
1439                                           "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1440                                           pDirNode,
1441                                           pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1442                                           &pDirNode->NameInformation.FileName);
1443                         }
1444                         else
1445                         {
1446                             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1447
1448                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1449                                           AFS_TRACE_LEVEL_VERBOSE,
1450                                           "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1451                                           pDirNode,
1452                                           &pDirNode->NameInformation.FileName);
1453                         }
1454                     }
1455                 }
1456
1457                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1458
1459                 //
1460                 // Next dir entry
1461                 //
1462
1463                 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1464
1465                 if( ulResultLen >= ulEntryLength)
1466                 {
1467                     ulResultLen -= ulEntryLength;
1468                 }
1469                 else
1470                 {
1471                     ulResultLen = 0;
1472                 }
1473             }
1474
1475             ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1476
1477             //
1478             // Reset the information in the request buffer since it got trampled
1479             // above
1480             //
1481
1482             pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1483         }
1484
1485 try_exit:
1486
1487         //
1488         // Cleanup
1489         //
1490
1491         if( pBuffer != NULL)
1492         {
1493
1494             AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
1495         }
1496     }
1497
1498     return ntStatus;
1499 }
1500
1501 NTSTATUS
1502 AFSNotifyFileCreate( IN GUID            *AuthGroup,
1503                      IN AFSObjectInfoCB *ParentObjectInfo,
1504                      IN PLARGE_INTEGER FileSize,
1505                      IN ULONG FileAttributes,
1506                      IN UNICODE_STRING *FileName,
1507                      OUT AFSDirectoryCB **DirNode)
1508 {
1509
1510     NTSTATUS ntStatus = STATUS_SUCCESS;
1511     AFSFileCreateCB stCreateCB;
1512     AFSFileCreateResultCB *pResultCB = NULL;
1513     ULONG ulResultLen = 0;
1514     UNICODE_STRING uniTargetName;
1515     AFSDirectoryCB *pDirNode = NULL;
1516     ULONG     ulCRC = 0;
1517     LARGE_INTEGER liOldDataVersion;
1518
1519     __Enter
1520     {
1521
1522         //
1523         // Init the control block for the request
1524         //
1525
1526         RtlZeroMemory( &stCreateCB,
1527                        sizeof( AFSFileCreateCB));
1528
1529         stCreateCB.ParentId = ParentObjectInfo->FileId;
1530
1531         stCreateCB.AllocationSize = *FileSize;
1532
1533         stCreateCB.FileAttributes = FileAttributes;
1534
1535         stCreateCB.EaSize = 0;
1536
1537         liOldDataVersion = ParentObjectInfo->DataVersion;
1538
1539         //
1540         // Allocate our return buffer
1541         //
1542
1543         pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1544                                                                        PAGE_SIZE,
1545                                                                        AFS_GENERIC_MEMORY_1_TAG);
1546
1547         if( pResultCB == NULL)
1548         {
1549
1550             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1551         }
1552
1553         RtlZeroMemory( pResultCB,
1554                        PAGE_SIZE);
1555
1556         ulResultLen = PAGE_SIZE;
1557
1558         //
1559         // Send the call to the service
1560         //
1561
1562         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1563                                       AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1564                                       AuthGroup,
1565                                       FileName,
1566                                       NULL,
1567                                       &stCreateCB,
1568                                       sizeof( AFSFileCreateCB),
1569                                       pResultCB,
1570                                       &ulResultLen);
1571
1572         if( ntStatus != STATUS_SUCCESS)
1573         {
1574
1575             if( NT_SUCCESS( ntStatus))
1576             {
1577
1578                 ntStatus = STATUS_DEVICE_NOT_READY;
1579             }
1580
1581             try_return( ntStatus);
1582         }
1583
1584         //
1585         // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1586         // and though we created the node, it is already in our list. If this is the case then
1587         // look up the entry rather than create a new entry
1588         // The check is to ensure the DV has been modified
1589         //
1590
1591         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1592                         TRUE);
1593
1594         if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1595         {
1596
1597             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1598                           AFS_TRACE_LEVEL_WARNING,
1599                           "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",
1600                           FileName,
1601                           ParentObjectInfo->FileId.Cell,
1602                           ParentObjectInfo->FileId.Volume,
1603                           ParentObjectInfo->FileId.Vnode,
1604                           ParentObjectInfo->FileId.Unique,
1605                           ParentObjectInfo->DataVersion.QuadPart,
1606                           pResultCB->ParentDataVersion.QuadPart);
1607
1608             //
1609             // We raced so go and lookup the directory entry in the parent
1610             //
1611
1612             ulCRC = AFSGenerateCRC( FileName,
1613                                     FALSE);
1614
1615             AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1616                                             ulCRC,
1617                                             &pDirNode);
1618
1619             if( pDirNode != NULL)
1620             {
1621
1622                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1623                               AFS_TRACE_LEVEL_VERBOSE,
1624                               "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1625                               pDirNode,
1626                               FileName);
1627
1628                 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1629                                     &pResultCB->DirEnum.FileId))
1630                 {
1631
1632                     InterlockedIncrement( &pDirNode->OpenReferenceCount);
1633
1634                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1635                                   AFS_TRACE_LEVEL_VERBOSE,
1636                                   "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1637                                   &pDirNode->NameInformation.FileName,
1638                                   pDirNode,
1639                                   pDirNode->OpenReferenceCount);
1640
1641                     *DirNode = pDirNode;
1642
1643                     AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1644
1645                     try_return( ntStatus = STATUS_REPARSE);
1646                 }
1647                 else
1648                 {
1649
1650                     //
1651                     // We found an entry that matches the desired name but it is not the
1652                     // same as the one that was created for us by the file server.
1653                     //
1654
1655                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1656                                   AFS_TRACE_LEVEL_ERROR,
1657                                   "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1658                                   FileName,
1659                                   pDirNode,
1660                                   pDirNode->ObjectInformation->FileId.Cell,
1661                                   pDirNode->ObjectInformation->FileId.Volume,
1662                                   pDirNode->ObjectInformation->FileId.Vnode,
1663                                   pDirNode->ObjectInformation->FileId.Unique,
1664                                   pResultCB->DirEnum.FileId.Cell,
1665                                   pResultCB->DirEnum.FileId.Volume,
1666                                   pResultCB->DirEnum.FileId.Vnode,
1667                                   pResultCB->DirEnum.FileId.Unique);
1668
1669                     if( pDirNode->OpenReferenceCount == 0)
1670                     {
1671
1672                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1673                                       AFS_TRACE_LEVEL_VERBOSE,
1674                                       "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1675                                       pDirNode,
1676                                       &pDirNode->NameInformation.FileName,
1677                                       pDirNode->ObjectInformation->FileId.Cell,
1678                                       pDirNode->ObjectInformation->FileId.Volume,
1679                                       pDirNode->ObjectInformation->FileId.Vnode,
1680                                       pDirNode->ObjectInformation->FileId.Unique,
1681                                       pResultCB->DirEnum.FileId.Cell,
1682                                       pResultCB->DirEnum.FileId.Volume,
1683                                       pResultCB->DirEnum.FileId.Vnode,
1684                                       pResultCB->DirEnum.FileId.Unique);
1685
1686                         AFSDeleteDirEntry( ParentObjectInfo,
1687                                            pDirNode);
1688                     }
1689                     else
1690                     {
1691
1692                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1693
1694                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1695                                       AFS_TRACE_LEVEL_VERBOSE,
1696                                       "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1697                                       pDirNode,
1698                                       &pDirNode->NameInformation.FileName,
1699                                       pDirNode->ObjectInformation->FileId.Cell,
1700                                       pDirNode->ObjectInformation->FileId.Volume,
1701                                       pDirNode->ObjectInformation->FileId.Vnode,
1702                                       pDirNode->ObjectInformation->FileId.Unique,
1703                                       pResultCB->DirEnum.FileId.Cell,
1704                                       pResultCB->DirEnum.FileId.Volume,
1705                                       pResultCB->DirEnum.FileId.Vnode,
1706                                       pResultCB->DirEnum.FileId.Unique);
1707
1708                         AFSRemoveNameEntry( ParentObjectInfo,
1709                                             pDirNode);
1710                     }
1711
1712                     pDirNode = NULL;
1713                 }
1714             }
1715
1716             //
1717             // We are unsure of our current data so set the verify flag. It may already be set
1718             // but no big deal to reset it
1719             //
1720
1721             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1722
1723             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1724         }
1725
1726         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1727                       AFS_TRACE_LEVEL_VERBOSE,
1728                       "AFSNotifyFileCreate Creating new entry %wZ\n",
1729                       FileName);
1730
1731         //
1732         // Initialize the directory entry
1733         //
1734
1735         uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1736
1737         uniTargetName.MaximumLength = uniTargetName.Length;
1738
1739         uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1740
1741         pDirNode = AFSInitDirEntry( ParentObjectInfo,
1742                                     FileName,
1743                                     &uniTargetName,
1744                                     &pResultCB->DirEnum,
1745                                     (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1746
1747         if( pDirNode == NULL)
1748         {
1749
1750             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1751
1752             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1753
1754             AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1755
1756             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1757         }
1758
1759         //
1760         // Init the short name if we have one
1761         //
1762
1763         if( pResultCB->DirEnum.ShortNameLength > 0)
1764         {
1765
1766             UNICODE_STRING uniShortName;
1767
1768             pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1769
1770             RtlCopyMemory( pDirNode->NameInformation.ShortName,
1771                            pResultCB->DirEnum.ShortName,
1772                            pDirNode->NameInformation.ShortNameLength);
1773
1774             //
1775             // Generate the short name index
1776             //
1777
1778             uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1779             uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1780
1781             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1782                                                                                TRUE);
1783
1784             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1785                           AFS_TRACE_LEVEL_VERBOSE,
1786                           "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1787                           &uniShortName,
1788                           pDirNode,
1789                           &pDirNode->NameInformation.FileName);
1790         }
1791
1792         if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1793         {
1794
1795             //
1796             // Update the parent data version
1797             //
1798
1799             ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1800
1801             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1802                           AFS_TRACE_LEVEL_VERBOSE,
1803                           "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1804                           FileName,
1805                           ParentObjectInfo->FileId.Cell,
1806                           ParentObjectInfo->FileId.Volume,
1807                           ParentObjectInfo->FileId.Vnode,
1808                           ParentObjectInfo->FileId.Unique,
1809                           ParentObjectInfo->DataVersion.QuadPart);
1810         }
1811
1812         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1813
1814         //
1815         // Return the directory node
1816         //
1817
1818         *DirNode = pDirNode;
1819
1820 try_exit:
1821
1822         if( pResultCB != NULL)
1823         {
1824
1825             AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_1_TAG);
1826         }
1827     }
1828
1829     return ntStatus;
1830 }
1831
1832 NTSTATUS
1833 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1834                           IN AFSObjectInfoCB *ObjectInfo,
1835                           IN GUID *AuthGroup)
1836 {
1837
1838     NTSTATUS ntStatus = STATUS_SUCCESS;
1839     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1840     AFSFileUpdateCB stUpdateCB;
1841     ULONG ulResultLen = 0;
1842     AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1843
1844     __Enter
1845     {
1846
1847         //
1848         // Init the control block for the request
1849         //
1850
1851         RtlZeroMemory( &stUpdateCB,
1852                        sizeof( AFSFileUpdateCB));
1853
1854         stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1855
1856         stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1857
1858         stUpdateCB.EaSize = ObjectInfo->EaSize;
1859
1860         stUpdateCB.ParentId = *ParentFid;
1861
1862         stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1863
1864         stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1865
1866         stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1867
1868         stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1869
1870         pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1871                                                                              PAGE_SIZE,
1872                                                                              AFS_UPDATE_RESULT_TAG);
1873
1874         if( pUpdateResultCB == NULL)
1875         {
1876
1877             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1878         }
1879
1880         ulResultLen = PAGE_SIZE;
1881
1882         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1883                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1884                                       AuthGroup,
1885                                       NULL,
1886                                       &ObjectInfo->FileId,
1887                                       &stUpdateCB,
1888                                       sizeof( AFSFileUpdateCB),
1889                                       pUpdateResultCB,
1890                                       &ulResultLen);
1891
1892         if( ntStatus != STATUS_SUCCESS)
1893         {
1894
1895             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1896                           AFS_TRACE_LEVEL_ERROR,
1897                           "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1898                           ObjectInfo->FileId.Cell,
1899                           ObjectInfo->FileId.Volume,
1900                           ObjectInfo->FileId.Vnode,
1901                           ObjectInfo->FileId.Unique,
1902                           ntStatus);
1903
1904             try_return( ntStatus);
1905         }
1906
1907         //
1908         // Update the data version
1909         //
1910
1911         AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1912                         TRUE);
1913
1914         if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1915         {
1916
1917             ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1918         }
1919
1920         AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1921
1922 try_exit:
1923
1924         if( pUpdateResultCB != NULL)
1925         {
1926
1927             AFSExFreePoolWithTag( pUpdateResultCB, AFS_UPDATE_RESULT_TAG);
1928         }
1929     }
1930
1931     return ntStatus;
1932 }
1933
1934 NTSTATUS
1935 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1936                  IN GUID           *AuthGroup,
1937                  IN BOOLEAN         CheckOnly)
1938 {
1939     NTSTATUS ntStatus = STATUS_SUCCESS;
1940     ULONG ulResultLen = 0;
1941     AFSFileDeleteCB stDelete;
1942     AFSFileDeleteResultCB stDeleteResult;
1943     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1944
1945     __Enter
1946     {
1947
1948         stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
1949
1950         stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1951
1952         ulResultLen = sizeof( AFSFileDeleteResultCB);
1953
1954         if( CheckOnly)
1955         {
1956             ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1957         }
1958
1959         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1960                                       ulRequestFlags,
1961                                       AuthGroup,
1962                                       &DirectoryCB->NameInformation.FileName,
1963                                       &DirectoryCB->ObjectInformation->FileId,
1964                                       &stDelete,
1965                                       sizeof( AFSFileDeleteCB),
1966                                       &stDeleteResult,
1967                                       &ulResultLen);
1968
1969         if( ntStatus != STATUS_SUCCESS)
1970         {
1971
1972             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1973                           AFS_TRACE_LEVEL_ERROR,
1974                           "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1975                           stDelete.ParentId.Cell,
1976                           stDelete.ParentId.Volume,
1977                           stDelete.ParentId.Vnode,
1978                           stDelete.ParentId.Unique,
1979                           &DirectoryCB->NameInformation.FileName,
1980                           DirectoryCB->ObjectInformation->FileId.Cell,
1981                           DirectoryCB->ObjectInformation->FileId.Volume,
1982                           DirectoryCB->ObjectInformation->FileId.Vnode,
1983                           DirectoryCB->ObjectInformation->FileId.Unique,
1984                           ntStatus);
1985
1986             try_return( ntStatus);
1987         }
1988
1989         AFSAcquireExcl( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1990                         TRUE);
1991
1992         if( CheckOnly)
1993         {
1994
1995             //
1996             // Validate the parent data version
1997             //
1998
1999             if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2000             {
2001
2002                 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2003
2004                 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2005             }
2006         }
2007         else
2008         {
2009
2010             //
2011             // Update the parent data version
2012             //
2013
2014             if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2015             {
2016
2017                 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2018
2019                 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2020             }
2021             else
2022             {
2023
2024                 //
2025                 // TODO -- The entry must be removed from the directory at which point the
2026                 // Directory data version number can be updated.  Until then we must force
2027                 // a verification.
2028                 //
2029                 // DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2030                 //
2031
2032                 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2033
2034                 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2035             }
2036         }
2037
2038         AFSReleaseResource( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2039
2040 try_exit:
2041
2042         NOTHING;
2043     }
2044
2045     return ntStatus;
2046 }
2047
2048 NTSTATUS
2049 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2050                  IN GUID            *AuthGroup,
2051                  IN AFSObjectInfoCB *ParentObjectInfo,
2052                  IN AFSObjectInfoCB *TargetParentObjectInfo,
2053                  IN AFSDirectoryCB *DirectoryCB,
2054                  IN UNICODE_STRING *TargetName,
2055                  OUT AFSFileID  *UpdatedFID)
2056 {
2057
2058     NTSTATUS ntStatus = STATUS_SUCCESS;
2059     AFSFileRenameCB *pRenameCB = NULL;
2060     AFSFileRenameResultCB *pRenameResultCB = NULL;
2061     ULONG ulResultLen = 0;
2062
2063     __Enter
2064     {
2065
2066         //
2067         // Init the control block for the request
2068         //
2069
2070         pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2071                                                                  PAGE_SIZE,
2072                                                                  AFS_RENAME_REQUEST_TAG);
2073
2074         if( pRenameCB == NULL)
2075         {
2076
2077             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2078         }
2079
2080         RtlZeroMemory( pRenameCB,
2081                        PAGE_SIZE);
2082
2083         pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2084
2085         pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2086
2087         pRenameCB->TargetNameLength = TargetName->Length;
2088
2089         RtlCopyMemory( pRenameCB->TargetName,
2090                        TargetName->Buffer,
2091                        TargetName->Length);
2092
2093         //
2094         // Use the same buffer for the result control block
2095         //
2096
2097         pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2098
2099         ulResultLen = PAGE_SIZE;
2100
2101         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2102                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2103                                       AuthGroup,
2104                                       &DirectoryCB->NameInformation.FileName,
2105                                       &ObjectInfo->FileId,
2106                                       pRenameCB,
2107                                       sizeof( AFSFileRenameCB) + TargetName->Length,
2108                                       pRenameResultCB,
2109                                       &ulResultLen);
2110
2111         if( ntStatus != STATUS_SUCCESS)
2112         {
2113
2114             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2115                           AFS_TRACE_LEVEL_ERROR,
2116                           "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2117                           ObjectInfo->FileId.Cell,
2118                           ObjectInfo->FileId.Volume,
2119                           ObjectInfo->FileId.Vnode,
2120                           ObjectInfo->FileId.Unique,
2121                           ntStatus);
2122
2123             try_return( ntStatus);
2124         }
2125
2126         //
2127         // Update the information from the returned data
2128         //
2129
2130         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2131                         TRUE);
2132
2133         if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2134         {
2135
2136             ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2137         }
2138         else
2139         {
2140
2141             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2142
2143             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2144         }
2145
2146         if ( ParentObjectInfo != TargetParentObjectInfo)
2147         {
2148
2149             if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2150             {
2151
2152                 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2153             }
2154             else
2155             {
2156
2157                 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2158
2159                 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2160             }
2161         }
2162
2163         //
2164         // Move over the short name
2165         //
2166
2167         DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2168
2169         if( DirectoryCB->NameInformation.ShortNameLength > 0)
2170         {
2171
2172             UNICODE_STRING uniShortName;
2173
2174             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2175             uniShortName.MaximumLength = uniShortName.Length;
2176             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2177
2178             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2179                           AFS_TRACE_LEVEL_VERBOSE,
2180                           "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2181                           &uniShortName,
2182                           DirectoryCB,
2183                           &DirectoryCB->NameInformation.FileName);
2184
2185             DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2186
2187             RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2188                            pRenameResultCB->DirEnum.ShortName,
2189                            DirectoryCB->NameInformation.ShortNameLength);
2190
2191             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2192             uniShortName.MaximumLength = uniShortName.Length;
2193             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2194
2195             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2196                           AFS_TRACE_LEVEL_VERBOSE,
2197                           "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2198                           &uniShortName,
2199                           DirectoryCB,
2200                           &DirectoryCB->NameInformation.FileName);
2201         }
2202         else
2203         {
2204
2205             UNICODE_STRING uniShortName;
2206
2207             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2208             uniShortName.MaximumLength = uniShortName.Length;
2209             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2210
2211             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2212                           AFS_TRACE_LEVEL_VERBOSE,
2213                           "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2214                           &uniShortName,
2215                           DirectoryCB,
2216                           &DirectoryCB->NameInformation.FileName);
2217
2218             DirectoryCB->NameInformation.ShortNameLength = 0;
2219
2220             DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2221         }
2222
2223         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2224
2225         if( UpdatedFID != NULL)
2226         {
2227             *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2228         }
2229
2230 try_exit:
2231
2232         if( pRenameCB != NULL)
2233         {
2234
2235             AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2236         }
2237     }
2238
2239     return ntStatus;
2240 }
2241
2242 NTSTATUS
2243 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2244                        IN GUID *AuthGroup,
2245                        IN BOOLEAN FastCall,
2246                        OUT AFSDirEnumEntry **DirEnumEntry)
2247 {
2248
2249     NTSTATUS ntStatus = STATUS_SUCCESS;
2250     AFSEvalTargetCB stTargetID;
2251     ULONG ulResultBufferLength;
2252     AFSFileEvalResultCB *pEvalResultCB = NULL;
2253     AFSDirEnumEntry *pDirEnumCB = NULL;
2254     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2255     AFSObjectInfoCB *pParentInfo = NULL;
2256
2257     __Enter
2258     {
2259
2260         RtlZeroMemory( &stTargetID,
2261                        sizeof( AFSEvalTargetCB));
2262
2263         pParentInfo = ObjectInfo->ParentObjectInformation;
2264
2265         if( pParentInfo != NULL)
2266         {
2267
2268             stTargetID.ParentId = pParentInfo->FileId;
2269         }
2270
2271         //
2272         // Allocate our response buffer
2273         //
2274
2275         pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2276                                                                          PAGE_SIZE,
2277                                                                          AFS_GENERIC_MEMORY_30_TAG);
2278
2279         if( pEvalResultCB == NULL)
2280         {
2281
2282             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2283         }
2284
2285         //
2286         // Call to the service to evaluate the fid
2287         //
2288
2289         ulResultBufferLength = PAGE_SIZE;
2290
2291         if( FastCall)
2292         {
2293
2294             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2295         }
2296
2297         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2298                                       ulRequestFlags,
2299                                       AuthGroup,
2300                                       NULL,
2301                                       &ObjectInfo->FileId,
2302                                       &stTargetID,
2303                                       sizeof( AFSEvalTargetCB),
2304                                       pEvalResultCB,
2305                                       &ulResultBufferLength);
2306
2307         if( ntStatus != STATUS_SUCCESS)
2308         {
2309
2310             //
2311             // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2312             // verification
2313             //
2314
2315             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2316             {
2317
2318                 if( pParentInfo != NULL)
2319                 {
2320
2321                     AFSAcquireExcl( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2322                                     TRUE);
2323
2324                     SetFlag( pParentInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2325
2326                     pParentInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2327
2328                     AFSReleaseResource( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2329                 }
2330             }
2331
2332             try_return( ntStatus);
2333         }
2334
2335         //
2336         // Validate the parent data version
2337         //
2338
2339         if ( pParentInfo != NULL)
2340         {
2341
2342             AFSAcquireExcl( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2343                             TRUE);
2344
2345             if ( pParentInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2346             {
2347
2348                 SetFlag( pParentInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2349
2350                 pParentInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2351             }
2352
2353             AFSReleaseResource( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2354         }
2355
2356         //
2357         // Pass back the dir enum entry
2358         //
2359
2360         if( DirEnumEntry != NULL)
2361         {
2362
2363             pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2364                                                                       PAGE_SIZE,
2365                                                                       AFS_GENERIC_MEMORY_2_TAG);
2366
2367             if( pDirEnumCB == NULL)
2368             {
2369
2370                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2371             }
2372
2373             RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2374                            ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2375
2376             *DirEnumEntry = pDirEnumCB;
2377         }
2378
2379 try_exit:
2380
2381         if( pEvalResultCB != NULL)
2382         {
2383
2384             AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2385         }
2386
2387         if( !NT_SUCCESS( ntStatus))
2388         {
2389
2390             if( pDirEnumCB != NULL)
2391             {
2392
2393                 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2394             }
2395
2396             *DirEnumEntry = NULL;
2397         }
2398     }
2399
2400     return ntStatus;
2401 }
2402
2403 NTSTATUS
2404 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2405                          IN AFSObjectInfoCB *ParentObjectInfo,
2406                          IN PUNICODE_STRING SourceName,
2407                          OUT AFSDirEnumEntry **DirEnumEntry)
2408 {
2409
2410     NTSTATUS ntStatus = STATUS_SUCCESS;
2411     AFSEvalTargetCB stTargetID;
2412     ULONG ulResultBufferLength;
2413     AFSFileEvalResultCB *pEvalResultCB = NULL;
2414     AFSDirEnumEntry *pDirEnumCB = NULL;
2415
2416     __Enter
2417     {
2418
2419         stTargetID.ParentId = ParentObjectInfo->FileId;
2420
2421         //
2422         // Allocate our response buffer
2423         //
2424
2425         pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2426                                                                          PAGE_SIZE,
2427                                                                          AFS_GENERIC_MEMORY_31_TAG);
2428
2429         if( pEvalResultCB == NULL)
2430         {
2431
2432             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2433         }
2434
2435         //
2436         // Call to the service to evaluate the fid
2437         //
2438
2439         ulResultBufferLength = PAGE_SIZE;
2440
2441         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2442                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2443                                       AuthGroup,
2444                                       SourceName,
2445                                       NULL,
2446                                       &stTargetID,
2447                                       sizeof( AFSEvalTargetCB),
2448                                       pEvalResultCB,
2449                                       &ulResultBufferLength);
2450
2451         if( ntStatus != STATUS_SUCCESS)
2452         {
2453
2454             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2455             {
2456
2457                 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2458                                 TRUE);
2459
2460                 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2461
2462                 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2463
2464                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2465             }
2466
2467             try_return( ntStatus);
2468         }
2469
2470         //
2471         // Validate the parent data version
2472         //
2473
2474         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2475                         TRUE);
2476
2477         if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2478         {
2479
2480             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2481
2482             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2483         }
2484
2485         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2486
2487         //
2488         // Pass back the dir enum entry
2489         //
2490
2491         if( DirEnumEntry != NULL)
2492         {
2493
2494             pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2495                                                                       PAGE_SIZE,
2496                                                                       AFS_GENERIC_MEMORY_3_TAG);
2497
2498             if( pDirEnumCB == NULL)
2499             {
2500
2501                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2502             }
2503
2504             RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2505                            ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2506
2507             *DirEnumEntry = pDirEnumCB;
2508         }
2509
2510 try_exit:
2511
2512         if( pEvalResultCB != NULL)
2513         {
2514
2515             AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
2516         }
2517
2518         if( !NT_SUCCESS( ntStatus))
2519         {
2520
2521             if( pDirEnumCB != NULL)
2522             {
2523
2524                 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
2525             }
2526
2527             *DirEnumEntry = NULL;
2528         }
2529     }
2530
2531     return ntStatus;
2532 }
2533
2534 NTSTATUS
2535 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
2536                               IN AFSFileID *FileID,
2537                               OUT AFSVolumeInfoCB *VolumeInformation)
2538 {
2539
2540     NTSTATUS ntStatus = STATUS_SUCCESS;
2541     ULONG ulResultLen = 0;
2542
2543     __Enter
2544     {
2545
2546         ulResultLen = sizeof( AFSVolumeInfoCB);
2547
2548         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
2549                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2550                                       AuthGroup,
2551                                       NULL,
2552                                       FileID,
2553                                       NULL,
2554                                       0,
2555                                       VolumeInformation,
2556                                       &ulResultLen);
2557
2558         if( ntStatus != STATUS_SUCCESS)
2559         {
2560
2561             try_return( ntStatus);
2562         }
2563
2564 try_exit:
2565
2566         NOTHING;
2567     }
2568
2569     return ntStatus;
2570 }
2571
2572 NTSTATUS
2573 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
2574                                   IN AFSFileID *FileID,
2575                                   OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
2576 {
2577
2578     NTSTATUS ntStatus = STATUS_SUCCESS;
2579     ULONG ulResultLen = 0;
2580
2581     __Enter
2582     {
2583
2584         ulResultLen = sizeof( AFSVolumeSizeInfoCB);
2585
2586         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
2587                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2588                                       AuthGroup,
2589                                       NULL,
2590                                       FileID,
2591                                       NULL,
2592                                       0,
2593                                       VolumeSizeInformation,
2594                                       &ulResultLen);
2595
2596         if( ntStatus != STATUS_SUCCESS)
2597         {
2598
2599             try_return( ntStatus);
2600         }
2601
2602 try_exit:
2603
2604         NOTHING;
2605     }
2606
2607     return ntStatus;
2608 }
2609
2610 NTSTATUS
2611 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
2612                          IN ULONG InputLength,
2613                          IN ULONG OutputLength,
2614                          IN void *InputDataBuffer,
2615                          OUT void *OutputDataBuffer,
2616                          OUT ULONG *BytesReturned)
2617 {
2618
2619     NTSTATUS ntStatus = STATUS_SUCCESS;
2620     ULONG ulResultLen = 0;
2621     MDL *pInputMdl = NULL, *pOutputMdl = NULL;
2622     void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
2623     ULONG ulBufferLength = OutputLength;
2624     AFSPipeIORequestCB *pIoRequest = NULL;
2625
2626     __Enter
2627     {
2628
2629         //
2630         // Map the user buffer to a system address
2631         //
2632
2633         pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
2634                                                 InputLength,
2635                                                 &pInputMdl);
2636
2637         if( pInputSystemBuffer == NULL)
2638         {
2639
2640             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2641         }
2642
2643         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2644                                                                      sizeof( AFSPipeIORequestCB) +
2645                                                                                 InputLength,
2646                                                                      AFS_GENERIC_MEMORY_4_TAG);
2647
2648         if( pIoRequest == NULL)
2649         {
2650
2651             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2652         }
2653
2654         RtlZeroMemory( pIoRequest,
2655                        sizeof( AFSPipeIORequestCB) + InputLength);
2656
2657         pIoRequest->RequestId = Ccb->RequestID;
2658
2659         pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2660
2661         pIoRequest->BufferLength = InputLength;
2662
2663         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2664                        pInputSystemBuffer,
2665                        InputLength);
2666
2667         pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
2668                                                  OutputLength,
2669                                                  &pOutputMdl);
2670
2671         if( pOutputSystemBuffer == NULL)
2672         {
2673
2674             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2675         }
2676
2677         //
2678         // Send the call to the service
2679         //
2680
2681         ulResultLen = OutputLength;
2682
2683         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
2684                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2685                                       &Ccb->AuthGroup,
2686                                       &Ccb->DirectoryCB->NameInformation.FileName,
2687                                       NULL,
2688                                       pIoRequest,
2689                                       sizeof( AFSPipeIORequestCB) + InputLength,
2690                                       pOutputSystemBuffer,
2691                                       &ulResultLen);
2692
2693         if( ntStatus != STATUS_SUCCESS &&
2694             ntStatus != STATUS_BUFFER_OVERFLOW)
2695         {
2696
2697             if( NT_SUCCESS( ntStatus))
2698             {
2699
2700                 ntStatus = STATUS_DEVICE_NOT_READY;
2701             }
2702
2703             try_return( ntStatus);
2704         }
2705
2706         //
2707         // Return the bytes processed
2708         //
2709
2710         *BytesReturned = ulResultLen;
2711
2712 try_exit:
2713
2714         if( pInputMdl != NULL)
2715         {
2716
2717             MmUnlockPages( pInputMdl);
2718
2719             IoFreeMdl( pInputMdl);
2720         }
2721
2722         if( pOutputMdl != NULL)
2723         {
2724
2725             MmUnlockPages( pOutputMdl);
2726
2727             IoFreeMdl( pOutputMdl);
2728         }
2729
2730         if( pIoRequest != NULL)
2731         {
2732
2733             AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
2734         }
2735     }
2736
2737     return ntStatus;
2738 }
2739
2740 NTSTATUS
2741 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
2742                       IN ULONG InformationClass,
2743                       IN ULONG InputLength,
2744                       IN void *DataBuffer)
2745 {
2746
2747     NTSTATUS ntStatus = STATUS_SUCCESS;
2748     AFSPipeInfoRequestCB *pInfoRequest = NULL;
2749
2750     __Enter
2751     {
2752
2753         pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2754                                                                          sizeof( AFSPipeInfoRequestCB) +
2755                                                                                 InputLength,
2756                                                                          AFS_GENERIC_MEMORY_5_TAG);
2757
2758         if( pInfoRequest == NULL)
2759         {
2760
2761             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2762         }
2763
2764         RtlZeroMemory( pInfoRequest,
2765                        sizeof( AFSPipeInfoRequestCB) + InputLength);
2766
2767         pInfoRequest->RequestId = Ccb->RequestID;
2768
2769         pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2770
2771         pInfoRequest->BufferLength = InputLength;
2772
2773         pInfoRequest->InformationClass = InformationClass;
2774
2775         RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
2776                        DataBuffer,
2777                        InputLength);
2778
2779         //
2780         // Send the call to the service
2781         //
2782
2783         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
2784                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2785                                       &Ccb->AuthGroup,
2786                                       &Ccb->DirectoryCB->NameInformation.FileName,
2787                                       NULL,
2788                                       pInfoRequest,
2789                                       sizeof( AFSPipeInfoRequestCB) + InputLength,
2790                                       NULL,
2791                                       NULL);
2792
2793         if( ntStatus != STATUS_SUCCESS)
2794         {
2795
2796             if( NT_SUCCESS( ntStatus))
2797             {
2798
2799                 ntStatus = STATUS_DEVICE_NOT_READY;
2800             }
2801
2802             try_return( ntStatus);
2803         }
2804
2805 try_exit:
2806
2807         if( pInfoRequest != NULL)
2808         {
2809
2810             AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
2811         }
2812     }
2813
2814     return ntStatus;
2815 }
2816
2817 NTSTATUS
2818 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
2819                         IN ULONG InformationClass,
2820                         IN ULONG OutputLength,
2821                         IN void *DataBuffer,
2822                         OUT ULONG *BytesReturned)
2823 {
2824
2825     NTSTATUS ntStatus = STATUS_SUCCESS;
2826     AFSPipeInfoRequestCB stInfoRequest;
2827     ULONG ulBytesProcessed = 0;
2828
2829     __Enter
2830     {
2831
2832         RtlZeroMemory( &stInfoRequest,
2833                        sizeof( AFSPipeInfoRequestCB));
2834
2835         stInfoRequest.RequestId = Ccb->RequestID;
2836
2837         stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2838
2839         stInfoRequest.BufferLength = OutputLength;
2840
2841         stInfoRequest.InformationClass = InformationClass;
2842
2843         ulBytesProcessed = OutputLength;
2844
2845         //
2846         // Send the call to the service
2847         //
2848
2849         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
2850                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2851                                       &Ccb->AuthGroup,
2852                                       &Ccb->DirectoryCB->NameInformation.FileName,
2853                                       NULL,
2854                                       &stInfoRequest,
2855                                       sizeof( AFSPipeInfoRequestCB),
2856                                       DataBuffer,
2857                                       &ulBytesProcessed);
2858
2859         if( ntStatus != STATUS_SUCCESS)
2860         {
2861
2862             if( NT_SUCCESS( ntStatus))
2863             {
2864
2865                 ntStatus = STATUS_DEVICE_NOT_READY;
2866             }
2867
2868             try_return( ntStatus);
2869         }
2870
2871         *BytesReturned = ulBytesProcessed;
2872
2873 try_exit:
2874
2875         NOTHING;
2876     }
2877
2878     return ntStatus;
2879 }
2880
2881 NTSTATUS
2882 AFSReleaseFid( IN AFSFileID *FileId)
2883 {
2884
2885     NTSTATUS ntStatus = STATUS_SUCCESS;
2886
2887     __Enter
2888     {
2889
2890         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2891                                       0,
2892                                       NULL,
2893                                       NULL,
2894                                       FileId,
2895                                       NULL,
2896                                       0,
2897                                       NULL,
2898                                       NULL);
2899     }
2900
2901     return ntStatus;
2902 }
2903
2904 BOOLEAN
2905 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2906                           IN LARGE_INTEGER *ExtentOffset,
2907                           IN ULONG Length)
2908 {
2909
2910     BOOLEAN bRequestQueued = FALSE;
2911     NTSTATUS ntStatus = STATUS_SUCCESS;
2912     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2913     AFSCommSrvcCB   *pCommSrvc = NULL;
2914     AFSPoolEntry    *pPoolEntry = NULL;
2915     AFSRequestExtentsCB *pRequestExtents = NULL;
2916
2917     __Enter
2918     {
2919
2920
2921         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2922
2923         AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2924                           TRUE);
2925
2926         pPoolEntry = pCommSrvc->RequestPoolHead;
2927
2928         while( pPoolEntry != NULL)
2929         {
2930
2931             if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2932             {
2933
2934                 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2935                 {
2936
2937                     pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2938
2939                     if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2940                         pRequestExtents->Length == Length)
2941                     {
2942
2943                         bRequestQueued = TRUE;
2944                     }
2945                 }
2946             }
2947
2948             pPoolEntry = pPoolEntry->fLink;
2949         }
2950
2951         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2952     }
2953
2954     return bRequestQueued;
2955 }