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