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