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