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