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