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