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