Windows: AFS_INVALIDATE_DATA_VERSION only by service
[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 = AFSExAllocatePoolWithTag( 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 = AFSExAllocatePoolWithTag( 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                         if( pCurrentDirEntry->ShortNameLength > 0 &&
1021                             pDirNode->NameInformation.ShortNameLength > 0)
1022                         {
1023                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1024                                           AFS_TRACE_LEVEL_VERBOSE,
1025                                           "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
1026                                           &uniDirName,
1027                                           &pDirNode->NameInformation.FileName,
1028                                           ObjectInfoCB->FileId.Cell,
1029                                           ObjectInfoCB->FileId.Volume,
1030                                           ObjectInfoCB->FileId.Vnode,
1031                                           ObjectInfoCB->FileId.Unique,
1032                                           pDirNode->NameInformation.ShortName,
1033                                           pCurrentDirEntry->ShortName));
1034                         }
1035                         else if( pCurrentDirEntry->ShortNameLength == 0 &&
1036                                  pDirNode->NameInformation.ShortNameLength > 0)
1037                         {
1038
1039                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1040                                           AFS_TRACE_LEVEL_VERBOSE,
1041                                           "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name NULL\n",
1042                                           &uniDirName,
1043                                           &pDirNode->NameInformation.FileName,
1044                                           ObjectInfoCB->FileId.Cell,
1045                                           ObjectInfoCB->FileId.Volume,
1046                                           ObjectInfoCB->FileId.Vnode,
1047                                           ObjectInfoCB->FileId.Unique,
1048                                           pDirNode->NameInformation.ShortName));
1049                         }
1050                         else if( pCurrentDirEntry->ShortNameLength > 0 &&
1051                                  pDirNode->NameInformation.ShortNameLength == 0)
1052                         {
1053                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1054                                           AFS_TRACE_LEVEL_VERBOSE,
1055                                           "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1056                                           &uniDirName,
1057                                           &pDirNode->NameInformation.FileName,
1058                                           ObjectInfoCB->FileId.Cell,
1059                                           ObjectInfoCB->FileId.Volume,
1060                                           ObjectInfoCB->FileId.Vnode,
1061                                           ObjectInfoCB->FileId.Unique,
1062                                           pCurrentDirEntry->ShortName));
1063                         }
1064                         else
1065                         {
1066                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1067                                           AFS_TRACE_LEVEL_VERBOSE,
1068                                           "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1069                                           &uniDirName,
1070                                           &pDirNode->NameInformation.FileName,
1071                                           ObjectInfoCB->FileId.Cell,
1072                                           ObjectInfoCB->FileId.Volume,
1073                                           ObjectInfoCB->FileId.Vnode,
1074                                           ObjectInfoCB->FileId.Unique));
1075                         }
1076
1077                         //
1078                         // Update the metadata for the entry
1079                         //
1080
1081                         if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1082                         {
1083
1084                             AFSUpdateMetaData( pDirNode,
1085                                                pCurrentDirEntry);
1086                         }
1087
1088                         //
1089                         // Next dir entry
1090                         //
1091
1092                         pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1093
1094                         if( ulResultLen >= ulEntryLength)
1095                         {
1096                             ulResultLen -= ulEntryLength;
1097                         }
1098                         else
1099                         {
1100                             ulResultLen = 0;
1101                         }
1102
1103                         continue;
1104                     }
1105                 }
1106                 else if ( pDirNode)
1107                 {
1108
1109                     //
1110                     // File name matches but FileID does not.
1111                     //
1112
1113                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1114                                   AFS_TRACE_LEVEL_VERBOSE,
1115                                   "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1116                                   pDirNode,
1117                                   &pDirNode->NameInformation.FileName,
1118                                   ObjectInfoCB->FileId.Cell,
1119                                   ObjectInfoCB->FileId.Volume,
1120                                   ObjectInfoCB->FileId.Vnode,
1121                                   ObjectInfoCB->FileId.Unique));
1122
1123                     //
1124                     // Need to tear down this entry and rebuild it below
1125                     //
1126
1127                     if( pDirNode->DirOpenReferenceCount <= 0 &&
1128                         pDirNode->NameArrayReferenceCount <= 0)
1129                     {
1130
1131                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1132                                       AFS_TRACE_LEVEL_VERBOSE,
1133                                       "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1134                                       pDirNode,
1135                                       &pDirNode->NameInformation.FileName,
1136                                       pDirNode->ObjectInformation->FileId.Cell,
1137                                       pDirNode->ObjectInformation->FileId.Volume,
1138                                       pDirNode->ObjectInformation->FileId.Vnode,
1139                                       pDirNode->ObjectInformation->FileId.Unique,
1140                                       pCurrentDirEntry->FileId.Cell,
1141                                       pCurrentDirEntry->FileId.Volume,
1142                                       pCurrentDirEntry->FileId.Vnode,
1143                                       pCurrentDirEntry->FileId.Unique));
1144
1145                         AFSDeleteDirEntry( ObjectInfoCB,
1146                                            &pDirNode);
1147                     }
1148                     else
1149                     {
1150
1151                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1152
1153                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1154                                       AFS_TRACE_LEVEL_WARNING,
1155                                       "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1156                                       pDirNode,
1157                                       &pDirNode->NameInformation.FileName,
1158                                       pDirNode->ObjectInformation->FileId.Cell,
1159                                       pDirNode->ObjectInformation->FileId.Volume,
1160                                       pDirNode->ObjectInformation->FileId.Vnode,
1161                                       pDirNode->ObjectInformation->FileId.Unique,
1162                                       pCurrentDirEntry->FileId.Cell,
1163                                       pCurrentDirEntry->FileId.Volume,
1164                                       pCurrentDirEntry->FileId.Vnode,
1165                                       pCurrentDirEntry->FileId.Unique));
1166
1167                         AFSRemoveNameEntry( ObjectInfoCB,
1168                                             pDirNode);
1169                     }
1170                 }
1171                 else
1172                 {
1173
1174                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1175                                   AFS_TRACE_LEVEL_VERBOSE,
1176                                   "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1177                                   &uniDirName,
1178                                   ObjectInfoCB->FileId.Cell,
1179                                   ObjectInfoCB->FileId.Volume,
1180                                   ObjectInfoCB->FileId.Vnode,
1181                                   ObjectInfoCB->FileId.Unique));
1182                 }
1183
1184                 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1185                                             &uniDirName,
1186                                             &uniTargetName,
1187                                             pCurrentDirEntry,
1188                                             (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1189
1190                 if( pDirNode == NULL)
1191                 {
1192
1193                     ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1194
1195                     break;
1196                 }
1197
1198                 AFSUpdateMetaData( pDirNode,
1199                                    pCurrentDirEntry);
1200
1201                 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1202                 {
1203
1204                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1205                                   AFS_TRACE_LEVEL_VERBOSE,
1206                                   "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1207                                   &uniDirName,
1208                                   pDirNode->ObjectInformation->FileId.Cell,
1209                                   pDirNode->ObjectInformation->FileId.Volume,
1210                                   pDirNode->ObjectInformation->FileId.Vnode,
1211                                   pDirNode->ObjectInformation->FileId.Unique));
1212
1213                     AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1214                                     TRUE);
1215
1216                     SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1217
1218                     pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1219
1220                     AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1221                 }
1222
1223                 //
1224                 // Init the short name if we have one
1225                 //
1226
1227                 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1228                     pCurrentDirEntry->ShortNameLength > 0)
1229                 {
1230
1231                     UNICODE_STRING uniShortName;
1232
1233                     pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1234
1235                     RtlCopyMemory( pDirNode->NameInformation.ShortName,
1236                                    pCurrentDirEntry->ShortName,
1237                                    pDirNode->NameInformation.ShortNameLength);
1238
1239                     //
1240                     // Generate the short name index
1241                     //
1242
1243                     uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1244                     uniShortName.MaximumLength = uniShortName.Length;
1245                     uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1246
1247                     if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1248                                                  NULL,
1249                                                  NULL))
1250                     {
1251
1252                         pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1253                                                                                            TRUE);
1254
1255                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1256                                       AFS_TRACE_LEVEL_VERBOSE,
1257                                       "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1258                                       &uniShortName,
1259                                       pDirNode,
1260                                       &pDirNode->NameInformation.FileName,
1261                                       pCurrentDirEntry->FileId.Cell,
1262                                       pCurrentDirEntry->FileId.Volume,
1263                                       pCurrentDirEntry->FileId.Vnode,
1264                                       pCurrentDirEntry->FileId.Unique));
1265                     }
1266                     else
1267                     {
1268                         pDirNode->NameInformation.ShortNameLength = 0;
1269
1270                         RtlZeroMemory( pDirNode->NameInformation.ShortName,
1271                                        (12 * sizeof( WCHAR)));
1272                     }
1273                 }
1274                 else
1275                 {
1276
1277                     //
1278                     // No short name or short names have been disabled
1279                     //
1280
1281                     pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1282                 }
1283
1284                 //
1285                 // Insert the node into the name tree
1286                 //
1287
1288                 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1289
1290                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1291                 {
1292
1293                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1294
1295                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1296                                   AFS_TRACE_LEVEL_VERBOSE,
1297                                   "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1298                                   pDirNode,
1299                                   &pDirNode->NameInformation.FileName));
1300                 }
1301                 else
1302                 {
1303
1304                     if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1305                                                                      pDirNode)))
1306                     {
1307                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1308                                       AFS_TRACE_LEVEL_VERBOSE,
1309                                       "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1310                                       pDirNode,
1311                                       &pDirNode->NameInformation.FileName));
1312
1313                         //
1314                         // Delete this dir entry and continue on
1315                         //
1316
1317                         AFSDeleteDirEntry( ObjectInfoCB,
1318                                            &pDirNode);
1319
1320                         pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1321
1322                         if( ulResultLen >= ulEntryLength)
1323                         {
1324                             ulResultLen -= ulEntryLength;
1325                         }
1326                         else
1327                         {
1328                             ulResultLen = 0;
1329                         }
1330
1331                         continue;
1332                     }
1333                     else
1334                     {
1335                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1336                                       AFS_TRACE_LEVEL_VERBOSE,
1337                                       "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1338                                       pDirNode,
1339                                       &pDirNode->NameInformation.FileName));
1340                     }
1341                 }
1342
1343                 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1344
1345                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1346                 {
1347
1348                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1349
1350                     SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1351
1352                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1353                                   AFS_TRACE_LEVEL_VERBOSE,
1354                                   "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1355                                   pDirNode,
1356                                   &pDirNode->NameInformation.FileName));
1357                 }
1358                 else
1359                 {
1360
1361                     AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1362                                                       pDirNode);
1363
1364                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1365                                   AFS_TRACE_LEVEL_VERBOSE,
1366                                   "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1367                                   pDirNode,
1368                                   &pDirNode->NameInformation.FileName));
1369                 }
1370
1371                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1372                 {
1373
1374                     ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1375                 }
1376                 else
1377                 {
1378
1379                     (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1380
1381                     pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1382                 }
1383
1384                 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1385
1386                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1387
1388                 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1389
1390                 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1391                               AFS_TRACE_LEVEL_VERBOSE,
1392                               "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1393                               &pDirNode->NameInformation.FileName,
1394                               ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1395                               ObjectInfoCB->FileId.Cell,
1396                               ObjectInfoCB->FileId.Volume,
1397                               ObjectInfoCB->FileId.Vnode,
1398                               ObjectInfoCB->FileId.Unique));
1399
1400                 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1401                 {
1402
1403                     //
1404                     // Insert the short name entry if we have a valid short name
1405                     //
1406
1407                     if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1408                     {
1409
1410                         ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1411
1412                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1413                                       AFS_TRACE_LEVEL_VERBOSE,
1414                                       "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1415                                       pDirNode,
1416                                       &pDirNode->NameInformation.FileName));
1417
1418                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1419                     }
1420                     else
1421                     {
1422
1423                         if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1424                                                                      pDirNode)))
1425                         {
1426                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1427                                           AFS_TRACE_LEVEL_VERBOSE,
1428                                           "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1429                                           pDirNode,
1430                                           pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1431                                           &pDirNode->NameInformation.FileName));
1432                         }
1433                         else
1434                         {
1435                             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1436
1437                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1438                                           AFS_TRACE_LEVEL_VERBOSE,
1439                                           "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1440                                           pDirNode,
1441                                           &pDirNode->NameInformation.FileName));
1442                         }
1443                     }
1444                 }
1445
1446                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1447
1448                 //
1449                 // Next dir entry
1450                 //
1451
1452                 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1453
1454                 if( ulResultLen >= ulEntryLength)
1455                 {
1456                     ulResultLen -= ulEntryLength;
1457                 }
1458                 else
1459                 {
1460                     ulResultLen = 0;
1461                 }
1462             }
1463
1464             ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1465
1466             //
1467             // Reset the information in the request buffer since it got trampled
1468             // above
1469             //
1470
1471             pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1472         }
1473
1474 try_exit:
1475
1476         //
1477         // Cleanup
1478         //
1479
1480         if( pBuffer != NULL)
1481         {
1482
1483             AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
1484         }
1485     }
1486
1487     return ntStatus;
1488 }
1489
1490 NTSTATUS
1491 AFSNotifyFileCreate( IN GUID            *AuthGroup,
1492                      IN AFSObjectInfoCB *ParentObjectInfo,
1493                      IN PLARGE_INTEGER FileSize,
1494                      IN ULONG FileAttributes,
1495                      IN UNICODE_STRING *FileName,
1496                      OUT AFSDirectoryCB **DirNode)
1497 {
1498
1499     NTSTATUS ntStatus = STATUS_SUCCESS;
1500     AFSFileCreateCB stCreateCB;
1501     AFSFileCreateResultCB *pResultCB = NULL;
1502     ULONG ulResultLen = 0;
1503     UNICODE_STRING uniTargetName;
1504     AFSDirectoryCB *pDirNode = NULL;
1505     ULONG     ulCRC = 0;
1506     LONG       lCount;
1507     LARGE_INTEGER liOldDataVersion;
1508     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1509     BOOLEAN bReleaseParentTreeLock = FALSE;
1510
1511     __Enter
1512     {
1513
1514         *DirNode = NULL;
1515
1516         //
1517         // Init the control block for the request
1518         //
1519
1520         RtlZeroMemory( &stCreateCB,
1521                        sizeof( AFSFileCreateCB));
1522
1523         stCreateCB.ParentId = ParentObjectInfo->FileId;
1524
1525         stCreateCB.AllocationSize = *FileSize;
1526
1527         stCreateCB.FileAttributes = FileAttributes;
1528
1529         stCreateCB.EaSize = 0;
1530
1531         liOldDataVersion = ParentObjectInfo->DataVersion;
1532
1533         //
1534         // Allocate our return buffer
1535         //
1536
1537         pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1538                                                                        PAGE_SIZE,
1539                                                                        AFS_GENERIC_MEMORY_1_TAG);
1540
1541         if( pResultCB == NULL)
1542         {
1543
1544             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1545         }
1546
1547         RtlZeroMemory( pResultCB,
1548                        PAGE_SIZE);
1549
1550         ulResultLen = PAGE_SIZE;
1551
1552         //
1553         // Send the call to the service
1554         //
1555
1556         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1557                                       AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1558                                       AuthGroup,
1559                                       FileName,
1560                                       NULL,
1561                                       NULL,
1562                                       0,
1563                                       &stCreateCB,
1564                                       sizeof( AFSFileCreateCB),
1565                                       pResultCB,
1566                                       &ulResultLen);
1567
1568         if( ntStatus != STATUS_SUCCESS)
1569         {
1570
1571             if( NT_SUCCESS( ntStatus))
1572             {
1573
1574                 ntStatus = STATUS_DEVICE_NOT_READY;
1575             }
1576
1577             try_return( ntStatus);
1578         }
1579
1580         //
1581         // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1582         // and though we created the node, it is already in our list. If this is the case then
1583         // look up the entry rather than create a new entry
1584         // The check is to ensure the DV has been modified
1585         //
1586
1587         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1588                         TRUE);
1589
1590         bReleaseParentTreeLock = TRUE;
1591
1592         if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1593         {
1594
1595             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1596                           AFS_TRACE_LEVEL_WARNING,
1597                           "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",
1598                           FileName,
1599                           ParentObjectInfo->FileId.Cell,
1600                           ParentObjectInfo->FileId.Volume,
1601                           ParentObjectInfo->FileId.Vnode,
1602                           ParentObjectInfo->FileId.Unique,
1603                           ParentObjectInfo->DataVersion.HighPart,
1604                           ParentObjectInfo->DataVersion.LowPart,
1605                           pResultCB->ParentDataVersion.HighPart,
1606                           pResultCB->ParentDataVersion.LowPart));
1607
1608             //
1609             // We raced so go and lookup the directory entry in the parent
1610             //
1611
1612             ulCRC = AFSGenerateCRC( FileName,
1613                                     FALSE);
1614
1615             AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1616                                             ulCRC,
1617                                             &pDirNode);
1618
1619             if( pDirNode != NULL)
1620             {
1621
1622                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1623                               AFS_TRACE_LEVEL_VERBOSE,
1624                               "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1625                               pDirNode,
1626                               FileName));
1627
1628                 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1629                                     &pResultCB->DirEnum.FileId))
1630                 {
1631
1632                     *DirNode = pDirNode;
1633
1634                     try_return( ntStatus = STATUS_REPARSE);
1635                 }
1636                 else
1637                 {
1638
1639                     //
1640                     // We found an entry that matches the desired name but it is not the
1641                     // same as the one that was created for us by the file server.
1642                     //
1643
1644                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1645                                   AFS_TRACE_LEVEL_ERROR,
1646                                   "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1647                                   FileName,
1648                                   pDirNode,
1649                                   pDirNode->ObjectInformation->FileId.Cell,
1650                                   pDirNode->ObjectInformation->FileId.Volume,
1651                                   pDirNode->ObjectInformation->FileId.Vnode,
1652                                   pDirNode->ObjectInformation->FileId.Unique,
1653                                   pResultCB->DirEnum.FileId.Cell,
1654                                   pResultCB->DirEnum.FileId.Volume,
1655                                   pResultCB->DirEnum.FileId.Vnode,
1656                                   pResultCB->DirEnum.FileId.Unique));
1657
1658                     if( pDirNode->DirOpenReferenceCount <= 0 &&
1659                         pDirNode->NameArrayReferenceCount <= 0)
1660                     {
1661
1662                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1663                                       AFS_TRACE_LEVEL_VERBOSE,
1664                                       "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1665                                       pDirNode,
1666                                       &pDirNode->NameInformation.FileName,
1667                                       pDirNode->ObjectInformation->FileId.Cell,
1668                                       pDirNode->ObjectInformation->FileId.Volume,
1669                                       pDirNode->ObjectInformation->FileId.Vnode,
1670                                       pDirNode->ObjectInformation->FileId.Unique,
1671                                       pResultCB->DirEnum.FileId.Cell,
1672                                       pResultCB->DirEnum.FileId.Volume,
1673                                       pResultCB->DirEnum.FileId.Vnode,
1674                                       pResultCB->DirEnum.FileId.Unique));
1675
1676                         AFSDeleteDirEntry( ParentObjectInfo,
1677                                            &pDirNode);
1678                     }
1679                     else
1680                     {
1681
1682                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1683
1684                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1685                                       AFS_TRACE_LEVEL_VERBOSE,
1686                                       "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1687                                       pDirNode,
1688                                       &pDirNode->NameInformation.FileName,
1689                                       pDirNode->ObjectInformation->FileId.Cell,
1690                                       pDirNode->ObjectInformation->FileId.Volume,
1691                                       pDirNode->ObjectInformation->FileId.Vnode,
1692                                       pDirNode->ObjectInformation->FileId.Unique,
1693                                       pResultCB->DirEnum.FileId.Cell,
1694                                       pResultCB->DirEnum.FileId.Volume,
1695                                       pResultCB->DirEnum.FileId.Vnode,
1696                                       pResultCB->DirEnum.FileId.Unique));
1697
1698                         AFSRemoveNameEntry( ParentObjectInfo,
1699                                             pDirNode);
1700                     }
1701
1702                     pDirNode = NULL;
1703                 }
1704             }
1705
1706             //
1707             // We are unsure of our current data so set the verify flag. It may already be set
1708             // but no big deal to reset it
1709             //
1710
1711             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1712
1713             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1714         }
1715
1716         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1717                       AFS_TRACE_LEVEL_VERBOSE,
1718                       "AFSNotifyFileCreate Creating new entry %wZ\n",
1719                       FileName));
1720
1721         //
1722         // Initialize the directory entry
1723         //
1724
1725         uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1726
1727         uniTargetName.MaximumLength = uniTargetName.Length;
1728
1729         uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1730
1731         pDirNode = AFSInitDirEntry( ParentObjectInfo,
1732                                     FileName,
1733                                     &uniTargetName,
1734                                     &pResultCB->DirEnum,
1735                                     (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1736
1737         if( pDirNode == NULL)
1738         {
1739
1740             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1741
1742             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1743
1744             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1745         }
1746
1747         //
1748         // Init the short name if we have one
1749         //
1750
1751         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1752             pResultCB->DirEnum.ShortNameLength > 0)
1753         {
1754
1755             UNICODE_STRING uniShortName;
1756
1757             pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1758
1759             RtlCopyMemory( pDirNode->NameInformation.ShortName,
1760                            pResultCB->DirEnum.ShortName,
1761                            pDirNode->NameInformation.ShortNameLength);
1762
1763             //
1764             // Generate the short name index
1765             //
1766
1767             uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1768             uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1769
1770             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1771                                                                                TRUE);
1772
1773             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1774                           AFS_TRACE_LEVEL_VERBOSE,
1775                           "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1776                           &uniShortName,
1777                           pDirNode,
1778                           &pDirNode->NameInformation.FileName));
1779         }
1780         else
1781         {
1782             //
1783             // No short name or short names are disabled
1784             //
1785
1786             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1787         }
1788
1789         if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1790         {
1791
1792             //
1793             // Update the parent data version
1794             //
1795
1796             ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1797
1798             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1799                           AFS_TRACE_LEVEL_VERBOSE,
1800                           "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1801                           FileName,
1802                           ParentObjectInfo->FileId.Cell,
1803                           ParentObjectInfo->FileId.Volume,
1804                           ParentObjectInfo->FileId.Vnode,
1805                           ParentObjectInfo->FileId.Unique,
1806                           ParentObjectInfo->DataVersion.QuadPart));
1807         }
1808
1809         //
1810         // Return the directory node
1811         //
1812
1813         *DirNode = pDirNode;
1814
1815 try_exit:
1816
1817         if ( *DirNode != NULL)
1818         {
1819
1820             lCount = InterlockedIncrement( &(*DirNode)->DirOpenReferenceCount);
1821
1822             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1823                           AFS_TRACE_LEVEL_VERBOSE,
1824                           "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1825                           &(*DirNode)->NameInformation.FileName,
1826                           *DirNode,
1827                           lCount));
1828
1829             ASSERT( lCount >= 0);
1830         }
1831
1832         if ( bReleaseParentTreeLock)
1833         {
1834
1835             AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1836         }
1837
1838         if( pResultCB != NULL)
1839         {
1840
1841             AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_1_TAG);
1842         }
1843     }
1844
1845     return ntStatus;
1846 }
1847
1848 NTSTATUS
1849 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1850                           IN AFSObjectInfoCB *ObjectInfo,
1851                           IN GUID *AuthGroup)
1852 {
1853
1854     NTSTATUS ntStatus = STATUS_SUCCESS;
1855     AFSFileUpdateCB stUpdateCB;
1856     ULONG ulResultLen = 0;
1857     AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1858
1859     __Enter
1860     {
1861
1862         //
1863         // Init the control block for the request
1864         //
1865
1866         RtlZeroMemory( &stUpdateCB,
1867                        sizeof( AFSFileUpdateCB));
1868
1869         stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1870
1871         stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1872
1873         stUpdateCB.EaSize = ObjectInfo->EaSize;
1874
1875         stUpdateCB.ParentId = *ParentFid;
1876
1877         stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1878
1879         stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1880
1881         stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1882
1883         stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1884
1885         pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1886                                                                              PAGE_SIZE,
1887                                                                              AFS_UPDATE_RESULT_TAG);
1888
1889         if( pUpdateResultCB == NULL)
1890         {
1891
1892             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1893         }
1894
1895         ulResultLen = PAGE_SIZE;
1896
1897         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1898                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1899                                       AuthGroup,
1900                                       NULL,
1901                                       &ObjectInfo->FileId,
1902                                       ObjectInfo->VolumeCB->VolumeInformation.Cell,
1903                                       ObjectInfo->VolumeCB->VolumeInformation.CellLength,
1904                                       &stUpdateCB,
1905                                       sizeof( AFSFileUpdateCB),
1906                                       pUpdateResultCB,
1907                                       &ulResultLen);
1908
1909         if( ntStatus != STATUS_SUCCESS)
1910         {
1911
1912             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1913                           AFS_TRACE_LEVEL_ERROR,
1914                           "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1915                           ObjectInfo->FileId.Cell,
1916                           ObjectInfo->FileId.Volume,
1917                           ObjectInfo->FileId.Vnode,
1918                           ObjectInfo->FileId.Unique,
1919                           ntStatus));
1920
1921             try_return( ntStatus);
1922         }
1923
1924         //
1925         // Update the data version
1926         //
1927
1928         AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1929                         TRUE);
1930
1931         if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1932         {
1933
1934             ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1935         }
1936
1937         AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1938
1939 try_exit:
1940
1941         if( pUpdateResultCB != NULL)
1942         {
1943
1944             AFSExFreePoolWithTag( pUpdateResultCB, AFS_UPDATE_RESULT_TAG);
1945         }
1946     }
1947
1948     return ntStatus;
1949 }
1950
1951 NTSTATUS
1952 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1953                  IN GUID           *AuthGroup,
1954                  IN BOOLEAN         CheckOnly)
1955 {
1956     NTSTATUS ntStatus = STATUS_SUCCESS;
1957     ULONG ulResultLen = 0;
1958     AFSFileDeleteCB stDelete;
1959     AFSFileDeleteResultCB stDeleteResult;
1960     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1961     AFSObjectInfoCB *pObjectInfo = NULL;
1962     AFSObjectInfoCB *pParentObjectInfo = NULL;
1963
1964     __Enter
1965     {
1966
1967         pObjectInfo = DirectoryCB->ObjectInformation;
1968
1969         pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
1970                                                &pObjectInfo->ParentFileId);
1971
1972         stDelete.ParentId = pObjectInfo->ParentFileId;
1973
1974         stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1975
1976         ulResultLen = sizeof( AFSFileDeleteResultCB);
1977
1978         if( CheckOnly)
1979         {
1980             ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1981         }
1982
1983         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1984                                       ulRequestFlags,
1985                                       AuthGroup,
1986                                       &DirectoryCB->NameInformation.FileName,
1987                                       &pObjectInfo->FileId,
1988                                       pObjectInfo->VolumeCB->VolumeInformation.Cell,
1989                                       pObjectInfo->VolumeCB->VolumeInformation.CellLength,
1990                                       &stDelete,
1991                                       sizeof( AFSFileDeleteCB),
1992                                       &stDeleteResult,
1993                                       &ulResultLen);
1994
1995         if( ntStatus != STATUS_SUCCESS)
1996         {
1997
1998             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1999                           AFS_TRACE_LEVEL_ERROR,
2000                           "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2001                           stDelete.ParentId.Cell,
2002                           stDelete.ParentId.Volume,
2003                           stDelete.ParentId.Vnode,
2004                           stDelete.ParentId.Unique,
2005                           &DirectoryCB->NameInformation.FileName,
2006                           pObjectInfo->FileId.Cell,
2007                           pObjectInfo->FileId.Volume,
2008                           pObjectInfo->FileId.Vnode,
2009                           pObjectInfo->FileId.Unique,
2010                           ntStatus));
2011
2012             try_return( ntStatus);
2013         }
2014
2015         AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2016                         TRUE);
2017
2018         if( CheckOnly)
2019         {
2020
2021             //
2022             // Validate the parent data version
2023             //
2024
2025             if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2026             {
2027
2028                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2029
2030                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2031             }
2032         }
2033         else
2034         {
2035
2036             //
2037             // Update the parent data version
2038             //
2039
2040             if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2041             {
2042
2043                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2044
2045                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2046             }
2047             else
2048             {
2049
2050                 //
2051                 // TODO -- The entry must be removed from the directory at which point the
2052                 // Directory data version number can be updated.  Until then we must force
2053                 // a verification.
2054                 //
2055                 // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2056                 //
2057
2058                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2059
2060                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2061             }
2062         }
2063
2064         AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2065
2066 try_exit:
2067
2068         if ( pParentObjectInfo)
2069         {
2070
2071             AFSReleaseObjectInfo( &pParentObjectInfo);
2072         }
2073     }
2074
2075     return ntStatus;
2076 }
2077
2078
2079 NTSTATUS
2080 AFSNotifyHardLink( IN AFSObjectInfoCB *ObjectInfo,
2081                    IN GUID            *AuthGroup,
2082                    IN AFSObjectInfoCB *ParentObjectInfo,
2083                    IN AFSObjectInfoCB *TargetParentObjectInfo,
2084                    IN AFSDirectoryCB  *SourceDirectoryCB,
2085                    IN UNICODE_STRING  *TargetName,
2086                    IN BOOLEAN          bReplaceIfExists,
2087                    OUT AFSDirectoryCB **TargetDirectoryCB)
2088 {
2089
2090     NTSTATUS ntStatus = STATUS_SUCCESS;
2091     AFSFileHardLinkCB *pHardLinkCB = NULL;
2092     AFSFileHardLinkResultCB *pResultCB = NULL;
2093     ULONG ulResultLen = 0;
2094     AFSDirectoryCB *pDirNode = NULL;
2095     ULONG     ulCRC = 0;
2096     BOOLEAN bReleaseParentLock = FALSE, bReleaseTargetParentLock = FALSE;
2097     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2098     LONG lCount;
2099
2100     __Enter
2101     {
2102
2103         //
2104         // Init the control block for the request
2105         //
2106
2107         pHardLinkCB = (AFSFileHardLinkCB *)AFSExAllocatePoolWithTag( PagedPool,
2108                                                                      PAGE_SIZE,
2109                                                                      AFS_HARDLINK_REQUEST_TAG);
2110
2111         if( pHardLinkCB == NULL)
2112         {
2113
2114             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2115         }
2116
2117         RtlZeroMemory( pHardLinkCB,
2118                        PAGE_SIZE);
2119
2120         pHardLinkCB->SourceParentId = ParentObjectInfo->FileId;
2121
2122         pHardLinkCB->TargetParentId = TargetParentObjectInfo->FileId;
2123
2124         pHardLinkCB->TargetNameLength = TargetName->Length;
2125
2126         RtlCopyMemory( pHardLinkCB->TargetName,
2127                        TargetName->Buffer,
2128                        TargetName->Length);
2129
2130         pHardLinkCB->bReplaceIfExists = bReplaceIfExists;
2131
2132         //
2133         // Use the same buffer for the result control block
2134         //
2135
2136         pResultCB = (AFSFileHardLinkResultCB *)pHardLinkCB;
2137
2138         ulResultLen = PAGE_SIZE;
2139
2140         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_HARDLINK_FILE,
2141                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2142                                       AuthGroup,
2143                                       &SourceDirectoryCB->NameInformation.FileName,
2144                                       &ObjectInfo->FileId,
2145                                       ObjectInfo->VolumeCB->VolumeInformation.Cell,
2146                                       ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2147                                       pHardLinkCB,
2148                                       sizeof( AFSFileHardLinkCB) + TargetName->Length,
2149                                       pResultCB,
2150                                       &ulResultLen);
2151
2152         if( ntStatus != STATUS_SUCCESS)
2153         {
2154
2155             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2156                           AFS_TRACE_LEVEL_ERROR,
2157                           "AFSNotifyHardLink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2158                           ObjectInfo->FileId.Cell,
2159                           ObjectInfo->FileId.Volume,
2160                           ObjectInfo->FileId.Vnode,
2161                           ObjectInfo->FileId.Unique,
2162                           ntStatus));
2163
2164             try_return( ntStatus);
2165         }
2166
2167         //
2168         // Update the information from the returned data
2169         //
2170
2171         if ( ParentObjectInfo != TargetParentObjectInfo)
2172         {
2173
2174             AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2175                             TRUE);
2176
2177             bReleaseParentLock = TRUE;
2178
2179             if ( ParentObjectInfo->DataVersion.QuadPart == pResultCB->SourceParentDataVersion.QuadPart - 1)
2180             {
2181
2182                 ParentObjectInfo->DataVersion = pResultCB->SourceParentDataVersion;
2183             }
2184             else
2185             {
2186
2187                 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2188
2189                 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2190             }
2191         }
2192
2193         AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2194                         TRUE);
2195
2196         bReleaseTargetParentLock = TRUE;
2197
2198         if ( TargetParentObjectInfo->DataVersion.QuadPart == pResultCB->TargetParentDataVersion.QuadPart - 1)
2199         {
2200
2201             TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2202         }
2203         else
2204         {
2205
2206             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2207                           AFS_TRACE_LEVEL_WARNING,
2208                           "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",
2209                           TargetName,
2210                           TargetParentObjectInfo->FileId.Cell,
2211                           TargetParentObjectInfo->FileId.Volume,
2212                           TargetParentObjectInfo->FileId.Vnode,
2213                           TargetParentObjectInfo->FileId.Unique,
2214                           TargetParentObjectInfo->DataVersion.HighPart,
2215                           TargetParentObjectInfo->DataVersion.LowPart,
2216                           pResultCB->TargetParentDataVersion.HighPart,
2217                           pResultCB->TargetParentDataVersion.LowPart));
2218
2219             //
2220             // We raced so go and lookup the directory entry in the parent
2221             //
2222
2223             ulCRC = AFSGenerateCRC( TargetName,
2224                                     FALSE);
2225
2226             AFSLocateCaseSensitiveDirEntry( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2227                                             ulCRC,
2228                                             &pDirNode);
2229
2230             if( pDirNode != NULL)
2231             {
2232
2233                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2234                               AFS_TRACE_LEVEL_VERBOSE,
2235                               "AFSNotifyHardLink Located dir entry %p for file %wZ\n",
2236                               pDirNode,
2237                               TargetName));
2238
2239                 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2240                                     &pResultCB->DirEnum.FileId))
2241                 {
2242
2243                     try_return( ntStatus = STATUS_REPARSE);
2244                 }
2245                 else
2246                 {
2247
2248                     //
2249                     // We found an entry that matches the desired name but it is not the
2250                     // same as the one that was created for us by the file server.
2251                     //
2252
2253                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2254                                   AFS_TRACE_LEVEL_ERROR,
2255                                   "AFSNotifyHardLink Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
2256                                   TargetName,
2257                                   pDirNode,
2258                                   pDirNode->ObjectInformation->FileId.Cell,
2259                                   pDirNode->ObjectInformation->FileId.Volume,
2260                                   pDirNode->ObjectInformation->FileId.Vnode,
2261                                   pDirNode->ObjectInformation->FileId.Unique,
2262                                   pResultCB->DirEnum.FileId.Cell,
2263                                   pResultCB->DirEnum.FileId.Volume,
2264                                   pResultCB->DirEnum.FileId.Vnode,
2265                                   pResultCB->DirEnum.FileId.Unique));
2266
2267                     if( pDirNode->DirOpenReferenceCount <= 0 &&
2268                         pDirNode->NameArrayReferenceCount <= 0)
2269                     {
2270
2271                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2272                                       AFS_TRACE_LEVEL_VERBOSE,
2273                                       "AFSNotifyHardLink Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2274                                       pDirNode,
2275                                       &pDirNode->NameInformation.FileName,
2276                                       pDirNode->ObjectInformation->FileId.Cell,
2277                                       pDirNode->ObjectInformation->FileId.Volume,
2278                                       pDirNode->ObjectInformation->FileId.Vnode,
2279                                       pDirNode->ObjectInformation->FileId.Unique,
2280                                       pResultCB->DirEnum.FileId.Cell,
2281                                       pResultCB->DirEnum.FileId.Volume,
2282                                       pResultCB->DirEnum.FileId.Vnode,
2283                                       pResultCB->DirEnum.FileId.Unique));
2284
2285                         AFSDeleteDirEntry( TargetParentObjectInfo,
2286                                            &pDirNode);
2287                     }
2288                     else
2289                     {
2290
2291                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2292
2293                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2294                                       AFS_TRACE_LEVEL_VERBOSE,
2295                                       "AFSNotifyHardLink Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2296                                       pDirNode,
2297                                       &pDirNode->NameInformation.FileName,
2298                                       pDirNode->ObjectInformation->FileId.Cell,
2299                                       pDirNode->ObjectInformation->FileId.Volume,
2300                                       pDirNode->ObjectInformation->FileId.Vnode,
2301                                       pDirNode->ObjectInformation->FileId.Unique,
2302                                       pResultCB->DirEnum.FileId.Cell,
2303                                       pResultCB->DirEnum.FileId.Volume,
2304                                       pResultCB->DirEnum.FileId.Vnode,
2305                                       pResultCB->DirEnum.FileId.Unique));
2306
2307                         AFSRemoveNameEntry( TargetParentObjectInfo,
2308                                             pDirNode);
2309                     }
2310
2311                     pDirNode = NULL;
2312                 }
2313             }
2314
2315             //
2316             // We are unsure of our current data so set the verify flag. It may already be set
2317             // but no big deal to reset it
2318             //
2319
2320             SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2321
2322             TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2323         }
2324
2325         //
2326         // Create the hard link entry
2327         //
2328
2329         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2330                       AFS_TRACE_LEVEL_VERBOSE,
2331                       "AFSNotifyHardLink Creating new entry %wZ\n",
2332                       TargetName));
2333
2334         //
2335         // Initialize the directory entry
2336         //
2337
2338         pDirNode = AFSInitDirEntry( TargetParentObjectInfo,
2339                                     TargetName,
2340                                     NULL,
2341                                     &pResultCB->DirEnum,
2342                                     (ULONG)InterlockedIncrement( &TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
2343
2344         if( pDirNode == NULL)
2345         {
2346
2347             SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2348
2349             TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2350
2351             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2352         }
2353
2354         //
2355         // Init the short name if we have one
2356         //
2357
2358         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2359             pResultCB->DirEnum.ShortNameLength > 0)
2360         {
2361
2362             UNICODE_STRING uniShortName;
2363
2364             pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
2365
2366             RtlCopyMemory( pDirNode->NameInformation.ShortName,
2367                            pResultCB->DirEnum.ShortName,
2368                            pDirNode->NameInformation.ShortNameLength);
2369
2370             //
2371             // Generate the short name index
2372             //
2373
2374             uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
2375             uniShortName.Buffer = pDirNode->NameInformation.ShortName;
2376
2377             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2378                                                                                TRUE);
2379
2380             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2381                           AFS_TRACE_LEVEL_VERBOSE,
2382                           "AFSNotifyHardLink Initialized short name %wZ for DE %p for %wZ\n",
2383                           &uniShortName,
2384                           pDirNode,
2385                           &pDirNode->NameInformation.FileName));
2386         }
2387         else
2388         {
2389             //
2390             // No short name or short names are disabled
2391             //
2392
2393             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2394         }
2395
2396         if ( !BooleanFlagOn( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2397         {
2398
2399             //
2400             // Update the target parent data version
2401             //
2402
2403             TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2404
2405             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2406                           AFS_TRACE_LEVEL_VERBOSE,
2407                           "AFSNotifyHardLink entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
2408                           TargetName,
2409                           TargetParentObjectInfo->FileId.Cell,
2410                           TargetParentObjectInfo->FileId.Volume,
2411                           TargetParentObjectInfo->FileId.Vnode,
2412                           TargetParentObjectInfo->FileId.Unique,
2413                           TargetParentObjectInfo->DataVersion.QuadPart));
2414         }
2415
2416 try_exit:
2417
2418         if ( TargetDirectoryCB != NULL)
2419         {
2420
2421             lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2422
2423             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2424                           AFS_TRACE_LEVEL_VERBOSE,
2425                           "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2426                           &pDirNode->NameInformation.FileName,
2427                           pDirNode,
2428                           lCount));
2429
2430             ASSERT( lCount >= 0);
2431
2432             *TargetDirectoryCB = pDirNode;
2433         }
2434
2435         if ( bReleaseTargetParentLock)
2436         {
2437
2438             AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2439         }
2440
2441         if ( bReleaseParentLock)
2442         {
2443
2444             AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2445         }
2446
2447         if( pHardLinkCB != NULL)
2448         {
2449
2450             AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2451         }
2452     }
2453
2454     return ntStatus;
2455 }
2456
2457
2458
2459 NTSTATUS
2460 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2461                  IN GUID            *AuthGroup,
2462                  IN AFSObjectInfoCB *ParentObjectInfo,
2463                  IN AFSObjectInfoCB *TargetParentObjectInfo,
2464                  IN AFSDirectoryCB *DirectoryCB,
2465                  IN UNICODE_STRING *TargetName,
2466                  OUT AFSFileID  *UpdatedFID)
2467 {
2468
2469     NTSTATUS ntStatus = STATUS_SUCCESS;
2470     AFSFileRenameCB *pRenameCB = NULL;
2471     AFSFileRenameResultCB *pRenameResultCB = NULL;
2472     ULONG ulResultLen = 0;
2473     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2474
2475     __Enter
2476     {
2477
2478         //
2479         // Init the control block for the request
2480         //
2481
2482         pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2483                                                                  PAGE_SIZE,
2484                                                                  AFS_RENAME_REQUEST_TAG);
2485
2486         if( pRenameCB == NULL)
2487         {
2488
2489             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2490         }
2491
2492         RtlZeroMemory( pRenameCB,
2493                        PAGE_SIZE);
2494
2495         pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2496
2497         pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2498
2499         pRenameCB->TargetNameLength = TargetName->Length;
2500
2501         RtlCopyMemory( pRenameCB->TargetName,
2502                        TargetName->Buffer,
2503                        TargetName->Length);
2504
2505         //
2506         // Use the same buffer for the result control block
2507         //
2508
2509         pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2510
2511         ulResultLen = PAGE_SIZE;
2512
2513         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2514                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2515                                       AuthGroup,
2516                                       &DirectoryCB->NameInformation.FileName,
2517                                       &ObjectInfo->FileId,
2518                                       ObjectInfo->VolumeCB->VolumeInformation.Cell,
2519                                       ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2520                                       pRenameCB,
2521                                       sizeof( AFSFileRenameCB) + TargetName->Length,
2522                                       pRenameResultCB,
2523                                       &ulResultLen);
2524
2525         if( ntStatus != STATUS_SUCCESS)
2526         {
2527
2528             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2529                           AFS_TRACE_LEVEL_ERROR,
2530                           "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2531                           ObjectInfo->FileId.Cell,
2532                           ObjectInfo->FileId.Volume,
2533                           ObjectInfo->FileId.Vnode,
2534                           ObjectInfo->FileId.Unique,
2535                           ntStatus));
2536
2537             try_return( ntStatus);
2538         }
2539
2540         //
2541         // Update the information from the returned data
2542         //
2543
2544         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2545                         TRUE);
2546
2547         if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2548         {
2549
2550             ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2551         }
2552         else
2553         {
2554
2555             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2556
2557             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2558         }
2559
2560         if ( ParentObjectInfo != TargetParentObjectInfo)
2561         {
2562
2563             AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2564                             TRUE);
2565
2566             if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2567             {
2568
2569                 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2570             }
2571             else
2572             {
2573
2574                 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2575
2576                 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2577             }
2578         }
2579
2580         //
2581         // Move over the short name
2582         //
2583
2584         DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2585
2586         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2587             DirectoryCB->NameInformation.ShortNameLength > 0)
2588         {
2589
2590             UNICODE_STRING uniShortName;
2591
2592             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2593             uniShortName.MaximumLength = uniShortName.Length;
2594             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2595
2596             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2597                           AFS_TRACE_LEVEL_VERBOSE,
2598                           "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2599                           &uniShortName,
2600                           DirectoryCB,
2601                           &DirectoryCB->NameInformation.FileName));
2602
2603             DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2604
2605             RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2606                            pRenameResultCB->DirEnum.ShortName,
2607                            DirectoryCB->NameInformation.ShortNameLength);
2608
2609             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2610             uniShortName.MaximumLength = uniShortName.Length;
2611             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2612
2613             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2614                           AFS_TRACE_LEVEL_VERBOSE,
2615                           "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2616                           &uniShortName,
2617                           DirectoryCB,
2618                           &DirectoryCB->NameInformation.FileName));
2619         }
2620         else
2621         {
2622
2623             UNICODE_STRING uniShortName;
2624
2625             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2626             uniShortName.MaximumLength = uniShortName.Length;
2627             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2628
2629             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2630                           AFS_TRACE_LEVEL_VERBOSE,
2631                           "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2632                           &uniShortName,
2633                           DirectoryCB,
2634                           &DirectoryCB->NameInformation.FileName));
2635
2636             DirectoryCB->NameInformation.ShortNameLength = 0;
2637
2638             DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2639         }
2640
2641         if ( ParentObjectInfo != TargetParentObjectInfo)
2642         {
2643
2644             AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2645         }
2646
2647         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2648
2649         if( UpdatedFID != NULL)
2650         {
2651             *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2652         }
2653
2654 try_exit:
2655
2656         if( pRenameCB != NULL)
2657         {
2658
2659             AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2660         }
2661     }
2662
2663     return ntStatus;
2664 }
2665
2666 NTSTATUS
2667 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2668                        IN GUID *AuthGroup,
2669                        IN BOOLEAN FastCall,
2670                        OUT AFSDirEnumEntry **DirEnumEntry)
2671 {
2672
2673     NTSTATUS ntStatus = STATUS_SUCCESS;
2674     AFSEvalTargetCB stTargetID;
2675     ULONG ulResultBufferLength;
2676     AFSFileEvalResultCB *pEvalResultCB = NULL;
2677     AFSDirEnumEntry *pDirEnumCB = NULL;
2678     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2679     AFSObjectInfoCB *pParentObjectInfo = NULL;
2680
2681     __Enter
2682     {
2683
2684         RtlZeroMemory( &stTargetID,
2685                        sizeof( AFSEvalTargetCB));
2686
2687         if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2688         {
2689
2690             pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
2691                                                    &ObjectInfo->ParentFileId);
2692
2693             stTargetID.ParentId = ObjectInfo->ParentFileId;
2694         }
2695
2696         //
2697         // Allocate our response buffer
2698         //
2699
2700         pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2701                                                                          PAGE_SIZE,
2702                                                                          AFS_GENERIC_MEMORY_30_TAG);
2703
2704         if( pEvalResultCB == NULL)
2705         {
2706
2707             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2708         }
2709
2710         //
2711         // Call to the service to evaluate the fid
2712         //
2713
2714         ulResultBufferLength = PAGE_SIZE;
2715
2716         if( FastCall)
2717         {
2718
2719             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2720         }
2721
2722         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2723                                       ulRequestFlags,
2724                                       AuthGroup,
2725                                       NULL,
2726                                       &ObjectInfo->FileId,
2727                                       ObjectInfo->VolumeCB->VolumeInformation.Cell,
2728                                       ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2729                                       &stTargetID,
2730                                       sizeof( AFSEvalTargetCB),
2731                                       pEvalResultCB,
2732                                       &ulResultBufferLength);
2733
2734         if( ntStatus != STATUS_SUCCESS)
2735         {
2736
2737             //
2738             // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2739             // verification
2740             //
2741
2742             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2743             {
2744
2745                 if( pParentObjectInfo != NULL)
2746                 {
2747
2748                     AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2749                                     TRUE);
2750
2751                     SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2752
2753                     pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2754
2755                     AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2756                 }
2757             }
2758
2759             try_return( ntStatus);
2760         }
2761
2762         //
2763         // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
2764         // ObjectInfo->FileType is something else.  The same is true for
2765         // pDirEnumEntry->FileType is DIRECTORY.  Perform a sanity check
2766         // to ensure consistency.  An inconsistent pDirEnumEntry can be
2767         // produced as a result of invalid status info received from a file
2768         // server.  If the types are inconsistent or if the type does not
2769         // match the implied type derived from the vnode (odd values are
2770         // directories and even values are other types), prevent the request
2771         // from completing successfully.  This may prevent access to the file or
2772         // directory but will prevent a BSOD.
2773         //
2774
2775         if ( !AFSIsEqualFID( &ObjectInfo->FileId,
2776                              &pEvalResultCB->DirEnum.FileId))
2777         {
2778
2779             try_return( ntStatus = STATUS_UNSUCCESSFUL);
2780         }
2781
2782         switch ( pEvalResultCB->DirEnum.FileType)
2783         {
2784
2785         case AFS_FILE_TYPE_DIRECTORY:
2786             if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
2787             {
2788
2789                 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2790             }
2791
2792             if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2793                  ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
2794             {
2795
2796                 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2797             }
2798
2799             break;
2800
2801         case AFS_FILE_TYPE_FILE:
2802             if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
2803             {
2804
2805                 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2806             }
2807
2808             if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2809                  ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
2810             {
2811
2812                 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2813             }
2814
2815             break;
2816         }
2817
2818         //
2819         // Validate the parent data version
2820         //
2821
2822         if ( pParentObjectInfo != NULL)
2823         {
2824
2825             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2826                             TRUE);
2827
2828             if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2829             {
2830
2831                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2832
2833                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2834             }
2835
2836             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2837         }
2838
2839         //
2840         // Pass back the dir enum entry
2841         //
2842
2843         if( DirEnumEntry != NULL)
2844         {
2845
2846             pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2847                                                                       PAGE_SIZE,
2848                                                                       AFS_GENERIC_MEMORY_2_TAG);
2849
2850             if( pDirEnumCB == NULL)
2851             {
2852
2853                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2854             }
2855
2856             RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2857                            ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2858
2859             *DirEnumEntry = pDirEnumCB;
2860         }
2861
2862 try_exit:
2863
2864         if ( pParentObjectInfo != NULL)
2865         {
2866
2867             AFSReleaseObjectInfo( &pParentObjectInfo);
2868         }
2869
2870         if( pEvalResultCB != NULL)
2871         {
2872
2873             AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2874         }
2875
2876         if( !NT_SUCCESS( ntStatus))
2877         {
2878
2879             if( pDirEnumCB != NULL)
2880             {
2881
2882                 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2883             }
2884
2885             *DirEnumEntry = NULL;
2886         }
2887     }
2888
2889     return ntStatus;
2890 }
2891
2892 NTSTATUS
2893 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2894                          IN AFSObjectInfoCB *ParentObjectInfo,
2895                          IN PUNICODE_STRING SourceName,
2896                          IN ULONG Flags,
2897                          OUT AFSDirEnumEntry **DirEnumEntry)
2898 {
2899
2900     NTSTATUS ntStatus = STATUS_SUCCESS;
2901     AFSEvalTargetCB stTargetID;
2902     ULONG ulResultBufferLength;
2903     AFSFileEvalResultCB *pEvalResultCB = NULL;
2904     AFSDirEnumEntry *pDirEnumCB = NULL;
2905
2906     __Enter
2907     {
2908
2909         stTargetID.ParentId = ParentObjectInfo->FileId;
2910
2911         //
2912         // Allocate our response buffer
2913         //
2914
2915         pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2916                                                                          PAGE_SIZE,
2917                                                                          AFS_GENERIC_MEMORY_31_TAG);
2918
2919         if( pEvalResultCB == NULL)
2920         {
2921
2922             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2923         }
2924
2925         //
2926         // Call to the service to evaluate the fid
2927         //
2928
2929         ulResultBufferLength = PAGE_SIZE;
2930
2931         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2932                                       AFS_REQUEST_FLAG_SYNCHRONOUS | Flags,
2933                                       AuthGroup,
2934                                       SourceName,
2935                                       NULL,
2936                                       ParentObjectInfo->VolumeCB->VolumeInformation.Cell,
2937                                       ParentObjectInfo->VolumeCB->VolumeInformation.CellLength,
2938                                       &stTargetID,
2939                                       sizeof( AFSEvalTargetCB),
2940                                       pEvalResultCB,
2941                                       &ulResultBufferLength);
2942
2943         if( ntStatus != STATUS_SUCCESS)
2944         {
2945
2946             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2947             {
2948
2949                 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2950                                 TRUE);
2951
2952                 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2953
2954                 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2955
2956                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2957             }
2958
2959             try_return( ntStatus);
2960         }
2961
2962         //
2963         // Validate the parent data version
2964         //
2965
2966         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2967                         TRUE);
2968
2969         if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2970         {
2971
2972             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2973
2974             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2975         }
2976
2977         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2978
2979         //
2980         // Pass back the dir enum entry
2981         //
2982
2983         if( DirEnumEntry != NULL)
2984         {
2985
2986             pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2987                                                                       PAGE_SIZE,
2988                                                                       AFS_GENERIC_MEMORY_3_TAG);
2989
2990             if( pDirEnumCB == NULL)
2991             {
2992
2993                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2994             }
2995
2996             RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2997                            ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2998
2999             *DirEnumEntry = pDirEnumCB;
3000         }
3001
3002 try_exit:
3003
3004         if( pEvalResultCB != NULL)
3005         {
3006
3007             AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
3008         }
3009
3010         if( !NT_SUCCESS( ntStatus))
3011         {
3012
3013             if( pDirEnumCB != NULL)
3014             {
3015
3016                 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
3017             }
3018
3019             *DirEnumEntry = NULL;
3020         }
3021     }
3022
3023     return ntStatus;
3024 }
3025
3026 NTSTATUS
3027 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
3028                               IN AFSFileID *FileID,
3029                               OUT AFSVolumeInfoCB *VolumeInformation)
3030 {
3031
3032     NTSTATUS ntStatus = STATUS_SUCCESS;
3033     ULONG ulResultLen = 0;
3034
3035     __Enter
3036     {
3037
3038         ulResultLen = sizeof( AFSVolumeInfoCB);
3039
3040         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
3041                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3042                                       AuthGroup,
3043                                       NULL,
3044                                       FileID,
3045                                       NULL,
3046                                       0,
3047                                       NULL,
3048                                       0,
3049                                       VolumeInformation,
3050                                       &ulResultLen);
3051
3052         if( ntStatus != STATUS_SUCCESS)
3053         {
3054
3055             try_return( ntStatus);
3056         }
3057
3058 try_exit:
3059
3060         NOTHING;
3061     }
3062
3063     return ntStatus;
3064 }
3065
3066 NTSTATUS
3067 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
3068                                   IN AFSFileID *FileID,
3069                                   OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
3070 {
3071
3072     NTSTATUS ntStatus = STATUS_SUCCESS;
3073     ULONG ulResultLen = 0;
3074
3075     __Enter
3076     {
3077
3078         ulResultLen = sizeof( AFSVolumeSizeInfoCB);
3079
3080         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
3081                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3082                                       AuthGroup,
3083                                       NULL,
3084                                       FileID,
3085                                       NULL,
3086                                       0,
3087                                       NULL,
3088                                       0,
3089                                       VolumeSizeInformation,
3090                                       &ulResultLen);
3091
3092         if( ntStatus != STATUS_SUCCESS)
3093         {
3094
3095             try_return( ntStatus);
3096         }
3097
3098 try_exit:
3099
3100         NOTHING;
3101     }
3102
3103     return ntStatus;
3104 }
3105
3106 NTSTATUS
3107 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
3108                          IN ULONG InputLength,
3109                          IN ULONG OutputLength,
3110                          IN void *InputDataBuffer,
3111                          OUT void *OutputDataBuffer,
3112                          OUT ULONG *BytesReturned)
3113 {
3114
3115     NTSTATUS ntStatus = STATUS_SUCCESS;
3116     ULONG ulResultLen = 0;
3117     MDL *pInputMdl = NULL, *pOutputMdl = NULL;
3118     void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
3119     AFSPipeIORequestCB *pIoRequest = NULL;
3120
3121     __Enter
3122     {
3123
3124         //
3125         // Map the user buffer to a system address
3126         //
3127
3128         pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
3129                                                 InputLength,
3130                                                 &pInputMdl);
3131
3132         if( pInputSystemBuffer == NULL)
3133         {
3134
3135             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3136         }
3137
3138         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3139                                                                      sizeof( AFSPipeIORequestCB) +
3140                                                                                 InputLength,
3141                                                                      AFS_GENERIC_MEMORY_4_TAG);
3142
3143         if( pIoRequest == NULL)
3144         {
3145
3146             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3147         }
3148
3149         RtlZeroMemory( pIoRequest,
3150                        sizeof( AFSPipeIORequestCB) + InputLength);
3151
3152         pIoRequest->RequestId = Ccb->RequestID;
3153
3154         pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3155
3156         pIoRequest->BufferLength = InputLength;
3157
3158         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
3159                        pInputSystemBuffer,
3160                        InputLength);
3161
3162         pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
3163                                                  OutputLength,
3164                                                  &pOutputMdl);
3165
3166         if( pOutputSystemBuffer == NULL)
3167         {
3168
3169             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3170         }
3171
3172         //
3173         // Send the call to the service
3174         //
3175
3176         ulResultLen = OutputLength;
3177
3178         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
3179                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3180                                       &Ccb->AuthGroup,
3181                                       &Ccb->DirectoryCB->NameInformation.FileName,
3182                                       NULL,
3183                                       NULL,
3184                                       0,
3185                                       pIoRequest,
3186                                       sizeof( AFSPipeIORequestCB) + InputLength,
3187                                       pOutputSystemBuffer,
3188                                       &ulResultLen);
3189
3190         if( ntStatus != STATUS_SUCCESS &&
3191             ntStatus != STATUS_BUFFER_OVERFLOW)
3192         {
3193
3194             if( NT_SUCCESS( ntStatus))
3195             {
3196
3197                 ntStatus = STATUS_DEVICE_NOT_READY;
3198             }
3199
3200             try_return( ntStatus);
3201         }
3202
3203         //
3204         // Return the bytes processed
3205         //
3206
3207         *BytesReturned = ulResultLen;
3208
3209 try_exit:
3210
3211         if( pInputMdl != NULL)
3212         {
3213
3214             MmUnlockPages( pInputMdl);
3215
3216             IoFreeMdl( pInputMdl);
3217         }
3218
3219         if( pOutputMdl != NULL)
3220         {
3221
3222             MmUnlockPages( pOutputMdl);
3223
3224             IoFreeMdl( pOutputMdl);
3225         }
3226
3227         if( pIoRequest != NULL)
3228         {
3229
3230             AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
3231         }
3232     }
3233
3234     return ntStatus;
3235 }
3236
3237 NTSTATUS
3238 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
3239                       IN ULONG InformationClass,
3240                       IN ULONG InputLength,
3241                       IN void *DataBuffer)
3242 {
3243
3244     NTSTATUS ntStatus = STATUS_SUCCESS;
3245     AFSPipeInfoRequestCB *pInfoRequest = NULL;
3246
3247     __Enter
3248     {
3249
3250         pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3251                                                                          sizeof( AFSPipeInfoRequestCB) +
3252                                                                                 InputLength,
3253                                                                          AFS_GENERIC_MEMORY_5_TAG);
3254
3255         if( pInfoRequest == NULL)
3256         {
3257
3258             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3259         }
3260
3261         RtlZeroMemory( pInfoRequest,
3262                        sizeof( AFSPipeInfoRequestCB) + InputLength);
3263
3264         pInfoRequest->RequestId = Ccb->RequestID;
3265
3266         pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3267
3268         pInfoRequest->BufferLength = InputLength;
3269
3270         pInfoRequest->InformationClass = InformationClass;
3271
3272         RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
3273                        DataBuffer,
3274                        InputLength);
3275
3276         //
3277         // Send the call to the service
3278         //
3279
3280         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
3281                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3282                                       &Ccb->AuthGroup,
3283                                       &Ccb->DirectoryCB->NameInformation.FileName,
3284                                       NULL,
3285                                       NULL,
3286                                       0,
3287                                       pInfoRequest,
3288                                       sizeof( AFSPipeInfoRequestCB) + InputLength,
3289                                       NULL,
3290                                       NULL);
3291
3292         if( ntStatus != STATUS_SUCCESS)
3293         {
3294
3295             if( NT_SUCCESS( ntStatus))
3296             {
3297
3298                 ntStatus = STATUS_DEVICE_NOT_READY;
3299             }
3300
3301             try_return( ntStatus);
3302         }
3303
3304 try_exit:
3305
3306         if( pInfoRequest != NULL)
3307         {
3308
3309             AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
3310         }
3311     }
3312
3313     return ntStatus;
3314 }
3315
3316 NTSTATUS
3317 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
3318                         IN ULONG InformationClass,
3319                         IN ULONG OutputLength,
3320                         IN void *DataBuffer,
3321                         OUT ULONG *BytesReturned)
3322 {
3323
3324     NTSTATUS ntStatus = STATUS_SUCCESS;
3325     AFSPipeInfoRequestCB stInfoRequest;
3326     ULONG ulBytesProcessed = 0;
3327
3328     __Enter
3329     {
3330
3331         RtlZeroMemory( &stInfoRequest,
3332                        sizeof( AFSPipeInfoRequestCB));
3333
3334         stInfoRequest.RequestId = Ccb->RequestID;
3335
3336         stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3337
3338         stInfoRequest.BufferLength = OutputLength;
3339
3340         stInfoRequest.InformationClass = InformationClass;
3341
3342         ulBytesProcessed = OutputLength;
3343
3344         //
3345         // Send the call to the service
3346         //
3347
3348         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
3349                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3350                                       &Ccb->AuthGroup,
3351                                       &Ccb->DirectoryCB->NameInformation.FileName,
3352                                       NULL,
3353                                       NULL,
3354                                       0,
3355                                       &stInfoRequest,
3356                                       sizeof( AFSPipeInfoRequestCB),
3357                                       DataBuffer,
3358                                       &ulBytesProcessed);
3359
3360         if( ntStatus != STATUS_SUCCESS)
3361         {
3362
3363             if( NT_SUCCESS( ntStatus))
3364             {
3365
3366                 ntStatus = STATUS_DEVICE_NOT_READY;
3367             }
3368
3369             try_return( ntStatus);
3370         }
3371
3372         *BytesReturned = ulBytesProcessed;
3373
3374 try_exit:
3375
3376         NOTHING;
3377     }
3378
3379     return ntStatus;
3380 }
3381
3382 NTSTATUS
3383 AFSReleaseFid( IN AFSFileID *FileId)
3384 {
3385
3386     NTSTATUS ntStatus = STATUS_SUCCESS;
3387
3388     __Enter
3389     {
3390
3391         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
3392                                       0,
3393                                       NULL,
3394                                       NULL,
3395                                       FileId,
3396                                       NULL,
3397                                       0,
3398                                       NULL,
3399                                       0,
3400                                       NULL,
3401                                       NULL);
3402     }
3403
3404     return ntStatus;
3405 }
3406
3407 BOOLEAN
3408 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
3409                           IN LARGE_INTEGER *ExtentOffset,
3410                           IN ULONG Length)
3411 {
3412
3413     BOOLEAN bRequestQueued = FALSE;
3414     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3415     AFSCommSrvcCB   *pCommSrvc = NULL;
3416     AFSPoolEntry    *pPoolEntry = NULL;
3417     AFSRequestExtentsCB *pRequestExtents = NULL;
3418
3419     __Enter
3420     {
3421
3422
3423         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
3424
3425         AFSAcquireShared( &pCommSrvc->IrpPoolLock,
3426                           TRUE);
3427
3428         pPoolEntry = pCommSrvc->RequestPoolHead;
3429
3430         while( pPoolEntry != NULL)
3431         {
3432
3433             if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
3434             {
3435
3436                 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
3437                 {
3438
3439                     pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
3440
3441                     if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
3442                         pRequestExtents->Length == Length)
3443                     {
3444
3445                         bRequestQueued = TRUE;
3446                     }
3447                 }
3448             }
3449
3450             pPoolEntry = pPoolEntry->fLink;
3451         }
3452
3453         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
3454     }
3455
3456     return bRequestQueued;
3457 }
3458
3459 NTSTATUS
3460 AFSCreateSymlink( IN GUID *AuthGroup,
3461                   IN AFSObjectInfoCB *ParentObjectInfo,
3462                   IN UNICODE_STRING *FileName,
3463                   IN AFSObjectInfoCB *ObjectInfo,
3464                   IN UNICODE_STRING *TargetName)
3465 {
3466
3467     NTSTATUS                  ntStatus = STATUS_SUCCESS;
3468     AFSCreateSymlinkCB       *pSymlinkCreate = NULL;
3469     ULONG                     ulResultLen = 0;
3470     AFSCreateSymlinkResultCB *pSymlinkResult = NULL;
3471
3472     __Enter
3473     {
3474
3475         //
3476         // Allocate our request and result structures
3477         //
3478
3479         pSymlinkCreate = (AFSCreateSymlinkCB *)ExAllocatePoolWithTag( PagedPool,
3480                                                                       sizeof( AFSCreateSymlinkCB) +
3481                                                                           TargetName->Length,
3482                                                                       AFS_SYMLINK_REQUEST_TAG);
3483
3484         if( pSymlinkCreate == NULL)
3485         {
3486
3487             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3488         }
3489
3490         RtlZeroMemory( pSymlinkCreate,
3491                        sizeof( AFSCreateSymlinkCB) +
3492                              TargetName->Length);
3493
3494         pSymlinkResult = (AFSCreateSymlinkResultCB *)ExAllocatePoolWithTag( PagedPool,
3495                                                                             PAGE_SIZE,
3496                                                                             AFS_SYMLINK_REQUEST_TAG);
3497
3498         if( pSymlinkResult == NULL)
3499         {
3500
3501             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3502         }
3503
3504         RtlZeroMemory( pSymlinkResult,
3505                        PAGE_SIZE);
3506
3507         //
3508         // Populate the request buffer
3509         //
3510
3511         RtlCopyMemory( &pSymlinkCreate->ParentId,
3512                        &ObjectInfo->ParentFileId,
3513                        sizeof( AFSFileID));
3514
3515         pSymlinkCreate->TargetNameLength = TargetName->Length;
3516
3517         RtlCopyMemory( pSymlinkCreate->TargetName,
3518                        TargetName->Buffer,
3519                        TargetName->Length);
3520
3521         ulResultLen = PAGE_SIZE;
3522
3523         //
3524         // Call the service to create the symlink entry
3525         //
3526
3527         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_SYMLINK,
3528                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3529                                       AuthGroup,
3530                                       FileName,
3531                                       &ObjectInfo->FileId,
3532                                       ObjectInfo->VolumeCB->VolumeInformation.Cell,
3533                                       ObjectInfo->VolumeCB->VolumeInformation.CellLength,
3534                                       pSymlinkCreate,
3535                                       sizeof( AFSCreateSymlinkCB) +
3536                                                 TargetName->Length,
3537                                       pSymlinkResult,
3538                                       &ulResultLen);
3539
3540         if ( ntStatus == STATUS_FILE_DELETED )
3541         {
3542
3543             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3544                           AFS_TRACE_LEVEL_ERROR,
3545                           "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3546                           ObjectInfo->FileId.Cell,
3547                           ObjectInfo->FileId.Volume,
3548                           ObjectInfo->FileId.Vnode,
3549                           ObjectInfo->FileId.Unique,
3550                           ntStatus));
3551
3552             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3553
3554             ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3555
3556             SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3557
3558             try_return( ntStatus = STATUS_ACCESS_DENIED);
3559         }
3560         else if( ntStatus != STATUS_SUCCESS)
3561         {
3562
3563             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3564                           AFS_TRACE_LEVEL_ERROR,
3565                           "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3566                           ObjectInfo->FileId.Cell,
3567                           ObjectInfo->FileId.Volume,
3568                           ObjectInfo->FileId.Vnode,
3569                           ObjectInfo->FileId.Unique,
3570                           ntStatus));
3571
3572             try_return( ntStatus);
3573         }
3574
3575         //
3576         // After successful creation the open object has been deleted and replaced by
3577         // the actual symlink.
3578         //
3579
3580         SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3581
3582         ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3583
3584         SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3585
3586 try_exit:
3587
3588         if( pSymlinkCreate != NULL)
3589         {
3590
3591             AFSExFreePoolWithTag( pSymlinkCreate, AFS_SYMLINK_REQUEST_TAG);
3592         }
3593
3594         if( pSymlinkResult != NULL)
3595         {
3596
3597             AFSExFreePoolWithTag( pSymlinkResult, AFS_SYMLINK_REQUEST_TAG);
3598         }
3599     }
3600
3601     return ntStatus;
3602 }