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