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