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