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