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