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