c7ba719b15f7e51685bf5e94da5076c7bca9de36
[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                                                FALSE);
1972
1973         stDelete.ParentId = pObjectInfo->ParentFileId;
1974
1975         stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1976
1977         ulResultLen = sizeof( AFSFileDeleteResultCB);
1978
1979         if( CheckOnly)
1980         {
1981             ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1982         }
1983
1984         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1985                                       ulRequestFlags,
1986                                       AuthGroup,
1987                                       &DirectoryCB->NameInformation.FileName,
1988                                       &pObjectInfo->FileId,
1989                                       pObjectInfo->VolumeCB->VolumeInformation.Cell,
1990                                       pObjectInfo->VolumeCB->VolumeInformation.CellLength,
1991                                       &stDelete,
1992                                       sizeof( AFSFileDeleteCB),
1993                                       &stDeleteResult,
1994                                       &ulResultLen);
1995
1996         if( ntStatus != STATUS_SUCCESS)
1997         {
1998
1999             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2000                           AFS_TRACE_LEVEL_ERROR,
2001                           "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2002                           stDelete.ParentId.Cell,
2003                           stDelete.ParentId.Volume,
2004                           stDelete.ParentId.Vnode,
2005                           stDelete.ParentId.Unique,
2006                           &DirectoryCB->NameInformation.FileName,
2007                           pObjectInfo->FileId.Cell,
2008                           pObjectInfo->FileId.Volume,
2009                           pObjectInfo->FileId.Vnode,
2010                           pObjectInfo->FileId.Unique,
2011                           ntStatus));
2012
2013             try_return( ntStatus);
2014         }
2015
2016         AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2017                         TRUE);
2018
2019         if( CheckOnly)
2020         {
2021
2022             //
2023             // Validate the parent data version
2024             //
2025
2026             if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2027             {
2028
2029                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2030
2031                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2032             }
2033         }
2034         else
2035         {
2036
2037             //
2038             // Update the parent data version
2039             //
2040
2041             if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2042             {
2043
2044                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2045
2046                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2047             }
2048             else
2049             {
2050
2051                 //
2052                 // TODO -- The entry must be removed from the directory at which point the
2053                 // Directory data version number can be updated.  Until then we must force
2054                 // a verification.
2055                 //
2056                 // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2057                 //
2058
2059                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2060
2061                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2062             }
2063         }
2064
2065         AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2066
2067 try_exit:
2068
2069         if ( pParentObjectInfo)
2070         {
2071
2072             AFSReleaseObjectInfo( &pParentObjectInfo);
2073         }
2074     }
2075
2076     return ntStatus;
2077 }
2078
2079
2080 NTSTATUS
2081 AFSNotifyHardLink( IN AFSObjectInfoCB *ObjectInfo,
2082                    IN GUID            *AuthGroup,
2083                    IN AFSObjectInfoCB *ParentObjectInfo,
2084                    IN AFSObjectInfoCB *TargetParentObjectInfo,
2085                    IN AFSDirectoryCB  *SourceDirectoryCB,
2086                    IN UNICODE_STRING  *TargetName,
2087                    IN BOOLEAN          bReplaceIfExists,
2088                    OUT AFSDirectoryCB **TargetDirectoryCB)
2089 {
2090
2091     NTSTATUS ntStatus = STATUS_SUCCESS;
2092     AFSFileHardLinkCB *pHardLinkCB = NULL;
2093     AFSFileHardLinkResultCB *pResultCB = NULL;
2094     ULONG ulResultLen = 0;
2095     AFSDirectoryCB *pDirNode = NULL;
2096     ULONG     ulCRC = 0;
2097     BOOLEAN bReleaseParentLock = FALSE, bReleaseTargetParentLock = FALSE;
2098     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2099     LONG lCount;
2100
2101     __Enter
2102     {
2103
2104         //
2105         // Init the control block for the request
2106         //
2107
2108         pHardLinkCB = (AFSFileHardLinkCB *)AFSExAllocatePoolWithTag( PagedPool,
2109                                                                      PAGE_SIZE,
2110                                                                      AFS_HARDLINK_REQUEST_TAG);
2111
2112         if( pHardLinkCB == NULL)
2113         {
2114
2115             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2116         }
2117
2118         RtlZeroMemory( pHardLinkCB,
2119                        PAGE_SIZE);
2120
2121         pHardLinkCB->SourceParentId = ParentObjectInfo->FileId;
2122
2123         pHardLinkCB->TargetParentId = TargetParentObjectInfo->FileId;
2124
2125         pHardLinkCB->TargetNameLength = TargetName->Length;
2126
2127         RtlCopyMemory( pHardLinkCB->TargetName,
2128                        TargetName->Buffer,
2129                        TargetName->Length);
2130
2131         pHardLinkCB->bReplaceIfExists = bReplaceIfExists;
2132
2133         //
2134         // Use the same buffer for the result control block
2135         //
2136
2137         pResultCB = (AFSFileHardLinkResultCB *)pHardLinkCB;
2138
2139         ulResultLen = PAGE_SIZE;
2140
2141         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_HARDLINK_FILE,
2142                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2143                                       AuthGroup,
2144                                       &SourceDirectoryCB->NameInformation.FileName,
2145                                       &ObjectInfo->FileId,
2146                                       ObjectInfo->VolumeCB->VolumeInformation.Cell,
2147                                       ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2148                                       pHardLinkCB,
2149                                       sizeof( AFSFileHardLinkCB) + TargetName->Length,
2150                                       pResultCB,
2151                                       &ulResultLen);
2152
2153         if( ntStatus != STATUS_SUCCESS)
2154         {
2155
2156             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2157                           AFS_TRACE_LEVEL_ERROR,
2158                           "AFSNotifyHardLink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2159                           ObjectInfo->FileId.Cell,
2160                           ObjectInfo->FileId.Volume,
2161                           ObjectInfo->FileId.Vnode,
2162                           ObjectInfo->FileId.Unique,
2163                           ntStatus));
2164
2165             try_return( ntStatus);
2166         }
2167
2168         //
2169         // Update the information from the returned data
2170         //
2171
2172         if ( ParentObjectInfo != TargetParentObjectInfo)
2173         {
2174
2175             AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2176                             TRUE);
2177
2178             bReleaseParentLock = TRUE;
2179
2180             if ( ParentObjectInfo->DataVersion.QuadPart == pResultCB->SourceParentDataVersion.QuadPart - 1)
2181             {
2182
2183                 ParentObjectInfo->DataVersion = pResultCB->SourceParentDataVersion;
2184             }
2185             else
2186             {
2187
2188                 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2189
2190                 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2191             }
2192         }
2193
2194         AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2195                         TRUE);
2196
2197         bReleaseTargetParentLock = TRUE;
2198
2199         if ( TargetParentObjectInfo->DataVersion.QuadPart == pResultCB->TargetParentDataVersion.QuadPart - 1)
2200         {
2201
2202             TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2203         }
2204         else
2205         {
2206
2207             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2208                           AFS_TRACE_LEVEL_WARNING,
2209                           "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",
2210                           TargetName,
2211                           TargetParentObjectInfo->FileId.Cell,
2212                           TargetParentObjectInfo->FileId.Volume,
2213                           TargetParentObjectInfo->FileId.Vnode,
2214                           TargetParentObjectInfo->FileId.Unique,
2215                           TargetParentObjectInfo->DataVersion.HighPart,
2216                           TargetParentObjectInfo->DataVersion.LowPart,
2217                           pResultCB->TargetParentDataVersion.HighPart,
2218                           pResultCB->TargetParentDataVersion.LowPart));
2219
2220             //
2221             // We raced so go and lookup the directory entry in the parent
2222             //
2223
2224             ulCRC = AFSGenerateCRC( TargetName,
2225                                     FALSE);
2226
2227             AFSLocateCaseSensitiveDirEntry( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2228                                             ulCRC,
2229                                             &pDirNode);
2230
2231             if( pDirNode != NULL)
2232             {
2233
2234                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2235                               AFS_TRACE_LEVEL_VERBOSE,
2236                               "AFSNotifyHardLink Located dir entry %p for file %wZ\n",
2237                               pDirNode,
2238                               TargetName));
2239
2240                 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2241                                     &pResultCB->DirEnum.FileId))
2242                 {
2243
2244                     try_return( ntStatus = STATUS_REPARSE);
2245                 }
2246                 else
2247                 {
2248
2249                     //
2250                     // We found an entry that matches the desired name but it is not the
2251                     // same as the one that was created for us by the file server.
2252                     //
2253
2254                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2255                                   AFS_TRACE_LEVEL_ERROR,
2256                                   "AFSNotifyHardLink Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
2257                                   TargetName,
2258                                   pDirNode,
2259                                   pDirNode->ObjectInformation->FileId.Cell,
2260                                   pDirNode->ObjectInformation->FileId.Volume,
2261                                   pDirNode->ObjectInformation->FileId.Vnode,
2262                                   pDirNode->ObjectInformation->FileId.Unique,
2263                                   pResultCB->DirEnum.FileId.Cell,
2264                                   pResultCB->DirEnum.FileId.Volume,
2265                                   pResultCB->DirEnum.FileId.Vnode,
2266                                   pResultCB->DirEnum.FileId.Unique));
2267
2268                     if( pDirNode->DirOpenReferenceCount <= 0 &&
2269                         pDirNode->NameArrayReferenceCount <= 0)
2270                     {
2271
2272                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2273                                       AFS_TRACE_LEVEL_VERBOSE,
2274                                       "AFSNotifyHardLink Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2275                                       pDirNode,
2276                                       &pDirNode->NameInformation.FileName,
2277                                       pDirNode->ObjectInformation->FileId.Cell,
2278                                       pDirNode->ObjectInformation->FileId.Volume,
2279                                       pDirNode->ObjectInformation->FileId.Vnode,
2280                                       pDirNode->ObjectInformation->FileId.Unique,
2281                                       pResultCB->DirEnum.FileId.Cell,
2282                                       pResultCB->DirEnum.FileId.Volume,
2283                                       pResultCB->DirEnum.FileId.Vnode,
2284                                       pResultCB->DirEnum.FileId.Unique));
2285
2286                         AFSDeleteDirEntry( TargetParentObjectInfo,
2287                                            &pDirNode);
2288                     }
2289                     else
2290                     {
2291
2292                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2293
2294                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2295                                       AFS_TRACE_LEVEL_VERBOSE,
2296                                       "AFSNotifyHardLink Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2297                                       pDirNode,
2298                                       &pDirNode->NameInformation.FileName,
2299                                       pDirNode->ObjectInformation->FileId.Cell,
2300                                       pDirNode->ObjectInformation->FileId.Volume,
2301                                       pDirNode->ObjectInformation->FileId.Vnode,
2302                                       pDirNode->ObjectInformation->FileId.Unique,
2303                                       pResultCB->DirEnum.FileId.Cell,
2304                                       pResultCB->DirEnum.FileId.Volume,
2305                                       pResultCB->DirEnum.FileId.Vnode,
2306                                       pResultCB->DirEnum.FileId.Unique));
2307
2308                         AFSRemoveNameEntry( TargetParentObjectInfo,
2309                                             pDirNode);
2310                     }
2311
2312                     pDirNode = NULL;
2313                 }
2314             }
2315
2316             //
2317             // We are unsure of our current data so set the verify flag. It may already be set
2318             // but no big deal to reset it
2319             //
2320
2321             SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2322
2323             TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2324         }
2325
2326         //
2327         // Create the hard link entry
2328         //
2329
2330         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2331                       AFS_TRACE_LEVEL_VERBOSE,
2332                       "AFSNotifyHardLink Creating new entry %wZ\n",
2333                       TargetName));
2334
2335         //
2336         // Initialize the directory entry
2337         //
2338
2339         pDirNode = AFSInitDirEntry( TargetParentObjectInfo,
2340                                     TargetName,
2341                                     NULL,
2342                                     &pResultCB->DirEnum,
2343                                     (ULONG)InterlockedIncrement( &TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
2344
2345         if( pDirNode == NULL)
2346         {
2347
2348             SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2349
2350             TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2351
2352             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2353         }
2354
2355         //
2356         // Init the short name if we have one
2357         //
2358
2359         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2360             pResultCB->DirEnum.ShortNameLength > 0)
2361         {
2362
2363             UNICODE_STRING uniShortName;
2364
2365             pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
2366
2367             RtlCopyMemory( pDirNode->NameInformation.ShortName,
2368                            pResultCB->DirEnum.ShortName,
2369                            pDirNode->NameInformation.ShortNameLength);
2370
2371             //
2372             // Generate the short name index
2373             //
2374
2375             uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
2376             uniShortName.Buffer = pDirNode->NameInformation.ShortName;
2377
2378             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2379                                                                                TRUE);
2380
2381             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2382                           AFS_TRACE_LEVEL_VERBOSE,
2383                           "AFSNotifyHardLink Initialized short name %wZ for DE %p for %wZ\n",
2384                           &uniShortName,
2385                           pDirNode,
2386                           &pDirNode->NameInformation.FileName));
2387         }
2388         else
2389         {
2390             //
2391             // No short name or short names are disabled
2392             //
2393
2394             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2395         }
2396
2397         if ( !BooleanFlagOn( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2398         {
2399
2400             //
2401             // Update the target parent data version
2402             //
2403
2404             TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2405
2406             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2407                           AFS_TRACE_LEVEL_VERBOSE,
2408                           "AFSNotifyHardLink entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
2409                           TargetName,
2410                           TargetParentObjectInfo->FileId.Cell,
2411                           TargetParentObjectInfo->FileId.Volume,
2412                           TargetParentObjectInfo->FileId.Vnode,
2413                           TargetParentObjectInfo->FileId.Unique,
2414                           TargetParentObjectInfo->DataVersion.QuadPart));
2415         }
2416
2417 try_exit:
2418
2419         if ( TargetDirectoryCB != NULL)
2420         {
2421
2422             lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2423
2424             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2425                           AFS_TRACE_LEVEL_VERBOSE,
2426                           "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2427                           &pDirNode->NameInformation.FileName,
2428                           pDirNode,
2429                           lCount));
2430
2431             ASSERT( lCount >= 0);
2432
2433             *TargetDirectoryCB = pDirNode;
2434         }
2435
2436         if ( bReleaseTargetParentLock)
2437         {
2438
2439             AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2440         }
2441
2442         if ( bReleaseParentLock)
2443         {
2444
2445             AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2446         }
2447
2448         if( pHardLinkCB != NULL)
2449         {
2450
2451             AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2452         }
2453     }
2454
2455     return ntStatus;
2456 }
2457
2458
2459
2460 NTSTATUS
2461 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2462                  IN GUID            *AuthGroup,
2463                  IN AFSObjectInfoCB *ParentObjectInfo,
2464                  IN AFSObjectInfoCB *TargetParentObjectInfo,
2465                  IN AFSDirectoryCB *DirectoryCB,
2466                  IN UNICODE_STRING *TargetName,
2467                  OUT AFSFileID  *UpdatedFID)
2468 {
2469
2470     NTSTATUS ntStatus = STATUS_SUCCESS;
2471     AFSFileRenameCB *pRenameCB = NULL;
2472     AFSFileRenameResultCB *pRenameResultCB = NULL;
2473     ULONG ulResultLen = 0;
2474     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2475
2476     __Enter
2477     {
2478
2479         //
2480         // Init the control block for the request
2481         //
2482
2483         pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2484                                                                  PAGE_SIZE,
2485                                                                  AFS_RENAME_REQUEST_TAG);
2486
2487         if( pRenameCB == NULL)
2488         {
2489
2490             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2491         }
2492
2493         RtlZeroMemory( pRenameCB,
2494                        PAGE_SIZE);
2495
2496         pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2497
2498         pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2499
2500         pRenameCB->TargetNameLength = TargetName->Length;
2501
2502         RtlCopyMemory( pRenameCB->TargetName,
2503                        TargetName->Buffer,
2504                        TargetName->Length);
2505
2506         //
2507         // Use the same buffer for the result control block
2508         //
2509
2510         pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2511
2512         ulResultLen = PAGE_SIZE;
2513
2514         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2515                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2516                                       AuthGroup,
2517                                       &DirectoryCB->NameInformation.FileName,
2518                                       &ObjectInfo->FileId,
2519                                       ObjectInfo->VolumeCB->VolumeInformation.Cell,
2520                                       ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2521                                       pRenameCB,
2522                                       sizeof( AFSFileRenameCB) + TargetName->Length,
2523                                       pRenameResultCB,
2524                                       &ulResultLen);
2525
2526         if( ntStatus != STATUS_SUCCESS)
2527         {
2528
2529             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2530                           AFS_TRACE_LEVEL_ERROR,
2531                           "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2532                           ObjectInfo->FileId.Cell,
2533                           ObjectInfo->FileId.Volume,
2534                           ObjectInfo->FileId.Vnode,
2535                           ObjectInfo->FileId.Unique,
2536                           ntStatus));
2537
2538             try_return( ntStatus);
2539         }
2540
2541         //
2542         // Update the information from the returned data
2543         //
2544
2545         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2546                         TRUE);
2547
2548         if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2549         {
2550
2551             ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2552         }
2553         else
2554         {
2555
2556             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2557
2558             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2559         }
2560
2561         if ( ParentObjectInfo != TargetParentObjectInfo)
2562         {
2563
2564             AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2565                             TRUE);
2566
2567             if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2568             {
2569
2570                 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2571             }
2572             else
2573             {
2574
2575                 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2576
2577                 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2578             }
2579         }
2580
2581         //
2582         // Move over the short name
2583         //
2584
2585         DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2586
2587         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2588             DirectoryCB->NameInformation.ShortNameLength > 0)
2589         {
2590
2591             UNICODE_STRING uniShortName;
2592
2593             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2594             uniShortName.MaximumLength = uniShortName.Length;
2595             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2596
2597             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2598                           AFS_TRACE_LEVEL_VERBOSE,
2599                           "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2600                           &uniShortName,
2601                           DirectoryCB,
2602                           &DirectoryCB->NameInformation.FileName));
2603
2604             DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2605
2606             RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2607                            pRenameResultCB->DirEnum.ShortName,
2608                            DirectoryCB->NameInformation.ShortNameLength);
2609
2610             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2611             uniShortName.MaximumLength = uniShortName.Length;
2612             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2613
2614             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2615                           AFS_TRACE_LEVEL_VERBOSE,
2616                           "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2617                           &uniShortName,
2618                           DirectoryCB,
2619                           &DirectoryCB->NameInformation.FileName));
2620         }
2621         else
2622         {
2623
2624             UNICODE_STRING uniShortName;
2625
2626             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2627             uniShortName.MaximumLength = uniShortName.Length;
2628             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2629
2630             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2631                           AFS_TRACE_LEVEL_VERBOSE,
2632                           "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2633                           &uniShortName,
2634                           DirectoryCB,
2635                           &DirectoryCB->NameInformation.FileName));
2636
2637             DirectoryCB->NameInformation.ShortNameLength = 0;
2638
2639             DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2640         }
2641
2642         if ( ParentObjectInfo != TargetParentObjectInfo)
2643         {
2644
2645             AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2646         }
2647
2648         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2649
2650         if( UpdatedFID != NULL)
2651         {
2652             *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2653         }
2654
2655 try_exit:
2656
2657         if( pRenameCB != NULL)
2658         {
2659
2660             AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2661         }
2662     }
2663
2664     return ntStatus;
2665 }
2666
2667 NTSTATUS
2668 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2669                        IN GUID *AuthGroup,
2670                        IN BOOLEAN FastCall,
2671                        OUT AFSDirEnumEntry **DirEnumEntry)
2672 {
2673
2674     NTSTATUS ntStatus = STATUS_SUCCESS;
2675     AFSEvalTargetCB stTargetID;
2676     ULONG ulResultBufferLength;
2677     AFSFileEvalResultCB *pEvalResultCB = NULL;
2678     AFSDirEnumEntry *pDirEnumCB = NULL;
2679     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2680     AFSObjectInfoCB *pParentObjectInfo = NULL;
2681
2682     __Enter
2683     {
2684
2685         RtlZeroMemory( &stTargetID,
2686                        sizeof( AFSEvalTargetCB));
2687
2688         if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2689         {
2690
2691             pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
2692                                                    &ObjectInfo->ParentFileId,
2693                                                    TRUE);
2694
2695             stTargetID.ParentId = ObjectInfo->ParentFileId;
2696         }
2697
2698         //
2699         // Allocate our response buffer
2700         //
2701
2702         pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2703                                                                          PAGE_SIZE,
2704                                                                          AFS_GENERIC_MEMORY_30_TAG);
2705
2706         if( pEvalResultCB == NULL)
2707         {
2708
2709             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2710         }
2711
2712         //
2713         // Call to the service to evaluate the fid
2714         //
2715
2716         ulResultBufferLength = PAGE_SIZE;
2717
2718         if( FastCall)
2719         {
2720
2721             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2722         }
2723
2724         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2725                                       ulRequestFlags,
2726                                       AuthGroup,
2727                                       NULL,
2728                                       &ObjectInfo->FileId,
2729                                       ObjectInfo->VolumeCB->VolumeInformation.Cell,
2730                                       ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2731                                       &stTargetID,
2732                                       sizeof( AFSEvalTargetCB),
2733                                       pEvalResultCB,
2734                                       &ulResultBufferLength);
2735
2736         if( ntStatus != STATUS_SUCCESS)
2737         {
2738
2739             //
2740             // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2741             // verification
2742             //
2743
2744             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2745             {
2746
2747                 if( pParentObjectInfo != NULL)
2748                 {
2749
2750                     AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2751                                     TRUE);
2752
2753                     SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2754
2755                     pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2756
2757                     AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2758                 }
2759             }
2760
2761             try_return( ntStatus);
2762         }
2763
2764         //
2765         // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
2766         // ObjectInfo->FileType is something else.  The same is true for
2767         // pDirEnumEntry->FileType is DIRECTORY.  Perform a sanity check
2768         // to ensure consistency.  An inconsistent pDirEnumEntry can be
2769         // produced as a result of invalid status info received from a file
2770         // server.  If the types are inconsistent or if the type does not
2771         // match the implied type derived from the vnode (odd values are
2772         // directories and even values are other types), prevent the request
2773         // from completing successfully.  This may prevent access to the file or
2774         // directory but will prevent a BSOD.
2775         //
2776
2777         if ( !AFSIsEqualFID( &ObjectInfo->FileId,
2778                              &pEvalResultCB->DirEnum.FileId))
2779         {
2780
2781             try_return( ntStatus = STATUS_UNSUCCESSFUL);
2782         }
2783
2784         switch ( pEvalResultCB->DirEnum.FileType)
2785         {
2786
2787         case AFS_FILE_TYPE_DIRECTORY:
2788             if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
2789             {
2790
2791                 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2792             }
2793
2794             if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2795                  ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
2796             {
2797
2798                 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2799             }
2800
2801             break;
2802
2803         case AFS_FILE_TYPE_FILE:
2804             if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
2805             {
2806
2807                 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2808             }
2809
2810             if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2811                  ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
2812             {
2813
2814                 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2815             }
2816
2817             break;
2818         }
2819
2820         //
2821         // Validate the parent data version
2822         //
2823
2824         if ( pParentObjectInfo != NULL)
2825         {
2826
2827             AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2828                             TRUE);
2829
2830             if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2831             {
2832
2833                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2834
2835                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2836             }
2837
2838             AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2839         }
2840
2841         //
2842         // Pass back the dir enum entry
2843         //
2844
2845         if( DirEnumEntry != NULL)
2846         {
2847
2848             pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2849                                                                       PAGE_SIZE,
2850                                                                       AFS_GENERIC_MEMORY_2_TAG);
2851
2852             if( pDirEnumCB == NULL)
2853             {
2854
2855                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2856             }
2857
2858             RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2859                            ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2860
2861             *DirEnumEntry = pDirEnumCB;
2862         }
2863
2864 try_exit:
2865
2866         if ( pParentObjectInfo != NULL)
2867         {
2868
2869             AFSReleaseObjectInfo( &pParentObjectInfo);
2870         }
2871
2872         if( pEvalResultCB != NULL)
2873         {
2874
2875             AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2876         }
2877
2878         if( !NT_SUCCESS( ntStatus))
2879         {
2880
2881             if( pDirEnumCB != NULL)
2882             {
2883
2884                 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2885             }
2886
2887             *DirEnumEntry = NULL;
2888         }
2889     }
2890
2891     return ntStatus;
2892 }
2893
2894 NTSTATUS
2895 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2896                          IN AFSObjectInfoCB *ParentObjectInfo,
2897                          IN PUNICODE_STRING SourceName,
2898                          IN ULONG Flags,
2899                          OUT AFSDirEnumEntry **DirEnumEntry)
2900 {
2901
2902     NTSTATUS ntStatus = STATUS_SUCCESS;
2903     AFSEvalTargetCB stTargetID;
2904     ULONG ulResultBufferLength;
2905     AFSFileEvalResultCB *pEvalResultCB = NULL;
2906     AFSDirEnumEntry *pDirEnumCB = NULL;
2907
2908     __Enter
2909     {
2910
2911         stTargetID.ParentId = ParentObjectInfo->FileId;
2912
2913         //
2914         // Allocate our response buffer
2915         //
2916
2917         pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2918                                                                          PAGE_SIZE,
2919                                                                          AFS_GENERIC_MEMORY_31_TAG);
2920
2921         if( pEvalResultCB == NULL)
2922         {
2923
2924             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2925         }
2926
2927         //
2928         // Call to the service to evaluate the fid
2929         //
2930
2931         ulResultBufferLength = PAGE_SIZE;
2932
2933         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2934                                       AFS_REQUEST_FLAG_SYNCHRONOUS | Flags,
2935                                       AuthGroup,
2936                                       SourceName,
2937                                       NULL,
2938                                       ParentObjectInfo->VolumeCB->VolumeInformation.Cell,
2939                                       ParentObjectInfo->VolumeCB->VolumeInformation.CellLength,
2940                                       &stTargetID,
2941                                       sizeof( AFSEvalTargetCB),
2942                                       pEvalResultCB,
2943                                       &ulResultBufferLength);
2944
2945         if( ntStatus != STATUS_SUCCESS)
2946         {
2947
2948             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2949             {
2950
2951                 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2952                                 TRUE);
2953
2954                 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2955
2956                 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2957
2958                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2959             }
2960
2961             try_return( ntStatus);
2962         }
2963
2964         //
2965         // Validate the parent data version
2966         //
2967
2968         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2969                         TRUE);
2970
2971         if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2972         {
2973
2974             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2975
2976             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2977         }
2978
2979         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2980
2981         //
2982         // Pass back the dir enum entry
2983         //
2984
2985         if( DirEnumEntry != NULL)
2986         {
2987
2988             pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2989                                                                       PAGE_SIZE,
2990                                                                       AFS_GENERIC_MEMORY_3_TAG);
2991
2992             if( pDirEnumCB == NULL)
2993             {
2994
2995                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2996             }
2997
2998             RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2999                            ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
3000
3001             *DirEnumEntry = pDirEnumCB;
3002         }
3003
3004 try_exit:
3005
3006         if( pEvalResultCB != NULL)
3007         {
3008
3009             AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
3010         }
3011
3012         if( !NT_SUCCESS( ntStatus))
3013         {
3014
3015             if( pDirEnumCB != NULL)
3016             {
3017
3018                 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
3019             }
3020
3021             *DirEnumEntry = NULL;
3022         }
3023     }
3024
3025     return ntStatus;
3026 }
3027
3028 NTSTATUS
3029 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
3030                               IN AFSFileID *FileID,
3031                               OUT AFSVolumeInfoCB *VolumeInformation)
3032 {
3033
3034     NTSTATUS ntStatus = STATUS_SUCCESS;
3035     ULONG ulResultLen = 0;
3036
3037     __Enter
3038     {
3039
3040         ulResultLen = sizeof( AFSVolumeInfoCB);
3041
3042         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
3043                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3044                                       AuthGroup,
3045                                       NULL,
3046                                       FileID,
3047                                       NULL,
3048                                       0,
3049                                       NULL,
3050                                       0,
3051                                       VolumeInformation,
3052                                       &ulResultLen);
3053
3054         if( ntStatus != STATUS_SUCCESS)
3055         {
3056
3057             try_return( ntStatus);
3058         }
3059
3060 try_exit:
3061
3062         NOTHING;
3063     }
3064
3065     return ntStatus;
3066 }
3067
3068 NTSTATUS
3069 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
3070                                   IN AFSFileID *FileID,
3071                                   OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
3072 {
3073
3074     NTSTATUS ntStatus = STATUS_SUCCESS;
3075     ULONG ulResultLen = 0;
3076
3077     __Enter
3078     {
3079
3080         ulResultLen = sizeof( AFSVolumeSizeInfoCB);
3081
3082         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
3083                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3084                                       AuthGroup,
3085                                       NULL,
3086                                       FileID,
3087                                       NULL,
3088                                       0,
3089                                       NULL,
3090                                       0,
3091                                       VolumeSizeInformation,
3092                                       &ulResultLen);
3093
3094         if( ntStatus != STATUS_SUCCESS)
3095         {
3096
3097             try_return( ntStatus);
3098         }
3099
3100 try_exit:
3101
3102         NOTHING;
3103     }
3104
3105     return ntStatus;
3106 }
3107
3108 NTSTATUS
3109 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
3110                          IN ULONG InputLength,
3111                          IN ULONG OutputLength,
3112                          IN void *InputDataBuffer,
3113                          OUT void *OutputDataBuffer,
3114                          OUT ULONG *BytesReturned)
3115 {
3116
3117     NTSTATUS ntStatus = STATUS_SUCCESS;
3118     ULONG ulResultLen = 0;
3119     MDL *pInputMdl = NULL, *pOutputMdl = NULL;
3120     void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
3121     AFSPipeIORequestCB *pIoRequest = NULL;
3122
3123     __Enter
3124     {
3125
3126         //
3127         // Map the user buffer to a system address
3128         //
3129
3130         pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
3131                                                 InputLength,
3132                                                 &pInputMdl);
3133
3134         if( pInputSystemBuffer == NULL)
3135         {
3136
3137             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3138         }
3139
3140         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3141                                                                      sizeof( AFSPipeIORequestCB) +
3142                                                                                 InputLength,
3143                                                                      AFS_GENERIC_MEMORY_4_TAG);
3144
3145         if( pIoRequest == NULL)
3146         {
3147
3148             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3149         }
3150
3151         RtlZeroMemory( pIoRequest,
3152                        sizeof( AFSPipeIORequestCB) + InputLength);
3153
3154         pIoRequest->RequestId = Ccb->RequestID;
3155
3156         pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3157
3158         pIoRequest->BufferLength = InputLength;
3159
3160         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
3161                        pInputSystemBuffer,
3162                        InputLength);
3163
3164         pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
3165                                                  OutputLength,
3166                                                  &pOutputMdl);
3167
3168         if( pOutputSystemBuffer == NULL)
3169         {
3170
3171             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3172         }
3173
3174         //
3175         // Send the call to the service
3176         //
3177
3178         ulResultLen = OutputLength;
3179
3180         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
3181                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3182                                       &Ccb->AuthGroup,
3183                                       &Ccb->DirectoryCB->NameInformation.FileName,
3184                                       NULL,
3185                                       NULL,
3186                                       0,
3187                                       pIoRequest,
3188                                       sizeof( AFSPipeIORequestCB) + InputLength,
3189                                       pOutputSystemBuffer,
3190                                       &ulResultLen);
3191
3192         if( ntStatus != STATUS_SUCCESS &&
3193             ntStatus != STATUS_BUFFER_OVERFLOW)
3194         {
3195
3196             if( NT_SUCCESS( ntStatus))
3197             {
3198
3199                 ntStatus = STATUS_DEVICE_NOT_READY;
3200             }
3201
3202             try_return( ntStatus);
3203         }
3204
3205         //
3206         // Return the bytes processed
3207         //
3208
3209         *BytesReturned = ulResultLen;
3210
3211 try_exit:
3212
3213         if( pInputMdl != NULL)
3214         {
3215
3216             MmUnlockPages( pInputMdl);
3217
3218             IoFreeMdl( pInputMdl);
3219         }
3220
3221         if( pOutputMdl != NULL)
3222         {
3223
3224             MmUnlockPages( pOutputMdl);
3225
3226             IoFreeMdl( pOutputMdl);
3227         }
3228
3229         if( pIoRequest != NULL)
3230         {
3231
3232             AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
3233         }
3234     }
3235
3236     return ntStatus;
3237 }
3238
3239 NTSTATUS
3240 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
3241                       IN ULONG InformationClass,
3242                       IN ULONG InputLength,
3243                       IN void *DataBuffer)
3244 {
3245
3246     NTSTATUS ntStatus = STATUS_SUCCESS;
3247     AFSPipeInfoRequestCB *pInfoRequest = NULL;
3248
3249     __Enter
3250     {
3251
3252         pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3253                                                                          sizeof( AFSPipeInfoRequestCB) +
3254                                                                                 InputLength,
3255                                                                          AFS_GENERIC_MEMORY_5_TAG);
3256
3257         if( pInfoRequest == NULL)
3258         {
3259
3260             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3261         }
3262
3263         RtlZeroMemory( pInfoRequest,
3264                        sizeof( AFSPipeInfoRequestCB) + InputLength);
3265
3266         pInfoRequest->RequestId = Ccb->RequestID;
3267
3268         pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3269
3270         pInfoRequest->BufferLength = InputLength;
3271
3272         pInfoRequest->InformationClass = InformationClass;
3273
3274         RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
3275                        DataBuffer,
3276                        InputLength);
3277
3278         //
3279         // Send the call to the service
3280         //
3281
3282         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
3283                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3284                                       &Ccb->AuthGroup,
3285                                       &Ccb->DirectoryCB->NameInformation.FileName,
3286                                       NULL,
3287                                       NULL,
3288                                       0,
3289                                       pInfoRequest,
3290                                       sizeof( AFSPipeInfoRequestCB) + InputLength,
3291                                       NULL,
3292                                       NULL);
3293
3294         if( ntStatus != STATUS_SUCCESS)
3295         {
3296
3297             if( NT_SUCCESS( ntStatus))
3298             {
3299
3300                 ntStatus = STATUS_DEVICE_NOT_READY;
3301             }
3302
3303             try_return( ntStatus);
3304         }
3305
3306 try_exit:
3307
3308         if( pInfoRequest != NULL)
3309         {
3310
3311             AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
3312         }
3313     }
3314
3315     return ntStatus;
3316 }
3317
3318 NTSTATUS
3319 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
3320                         IN ULONG InformationClass,
3321                         IN ULONG OutputLength,
3322                         IN void *DataBuffer,
3323                         OUT ULONG *BytesReturned)
3324 {
3325
3326     NTSTATUS ntStatus = STATUS_SUCCESS;
3327     AFSPipeInfoRequestCB stInfoRequest;
3328     ULONG ulBytesProcessed = 0;
3329
3330     __Enter
3331     {
3332
3333         RtlZeroMemory( &stInfoRequest,
3334                        sizeof( AFSPipeInfoRequestCB));
3335
3336         stInfoRequest.RequestId = Ccb->RequestID;
3337
3338         stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3339
3340         stInfoRequest.BufferLength = OutputLength;
3341
3342         stInfoRequest.InformationClass = InformationClass;
3343
3344         ulBytesProcessed = OutputLength;
3345
3346         //
3347         // Send the call to the service
3348         //
3349
3350         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
3351                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3352                                       &Ccb->AuthGroup,
3353                                       &Ccb->DirectoryCB->NameInformation.FileName,
3354                                       NULL,
3355                                       NULL,
3356                                       0,
3357                                       &stInfoRequest,
3358                                       sizeof( AFSPipeInfoRequestCB),
3359                                       DataBuffer,
3360                                       &ulBytesProcessed);
3361
3362         if( ntStatus != STATUS_SUCCESS)
3363         {
3364
3365             if( NT_SUCCESS( ntStatus))
3366             {
3367
3368                 ntStatus = STATUS_DEVICE_NOT_READY;
3369             }
3370
3371             try_return( ntStatus);
3372         }
3373
3374         *BytesReturned = ulBytesProcessed;
3375
3376 try_exit:
3377
3378         NOTHING;
3379     }
3380
3381     return ntStatus;
3382 }
3383
3384 NTSTATUS
3385 AFSReleaseFid( IN AFSFileID *FileId)
3386 {
3387
3388     NTSTATUS ntStatus = STATUS_SUCCESS;
3389
3390     __Enter
3391     {
3392
3393         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
3394                                       0,
3395                                       NULL,
3396                                       NULL,
3397                                       FileId,
3398                                       NULL,
3399                                       0,
3400                                       NULL,
3401                                       0,
3402                                       NULL,
3403                                       NULL);
3404     }
3405
3406     return ntStatus;
3407 }
3408
3409 BOOLEAN
3410 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
3411                           IN LARGE_INTEGER *ExtentOffset,
3412                           IN ULONG Length)
3413 {
3414
3415     BOOLEAN bRequestQueued = FALSE;
3416     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3417     AFSCommSrvcCB   *pCommSrvc = NULL;
3418     AFSPoolEntry    *pPoolEntry = NULL;
3419     AFSRequestExtentsCB *pRequestExtents = NULL;
3420
3421     __Enter
3422     {
3423
3424
3425         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
3426
3427         AFSAcquireShared( &pCommSrvc->IrpPoolLock,
3428                           TRUE);
3429
3430         pPoolEntry = pCommSrvc->RequestPoolHead;
3431
3432         while( pPoolEntry != NULL)
3433         {
3434
3435             if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
3436             {
3437
3438                 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
3439                 {
3440
3441                     pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
3442
3443                     if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
3444                         pRequestExtents->Length == Length)
3445                     {
3446
3447                         bRequestQueued = TRUE;
3448                     }
3449                 }
3450             }
3451
3452             pPoolEntry = pPoolEntry->fLink;
3453         }
3454
3455         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
3456     }
3457
3458     return bRequestQueued;
3459 }
3460
3461 NTSTATUS
3462 AFSCreateSymlink( IN GUID *AuthGroup,
3463                   IN AFSObjectInfoCB *ParentObjectInfo,
3464                   IN UNICODE_STRING *FileName,
3465                   IN AFSObjectInfoCB *ObjectInfo,
3466                   IN UNICODE_STRING *TargetName)
3467 {
3468
3469     NTSTATUS                  ntStatus = STATUS_SUCCESS;
3470     AFSCreateSymlinkCB       *pSymlinkCreate = NULL;
3471     ULONG                     ulResultLen = 0;
3472     AFSCreateSymlinkResultCB *pSymlinkResult = NULL;
3473
3474     __Enter
3475     {
3476
3477         //
3478         // Allocate our request and result structures
3479         //
3480
3481         pSymlinkCreate = (AFSCreateSymlinkCB *)ExAllocatePoolWithTag( PagedPool,
3482                                                                       sizeof( AFSCreateSymlinkCB) +
3483                                                                           TargetName->Length,
3484                                                                       AFS_SYMLINK_REQUEST_TAG);
3485
3486         if( pSymlinkCreate == NULL)
3487         {
3488
3489             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3490         }
3491
3492         RtlZeroMemory( pSymlinkCreate,
3493                        sizeof( AFSCreateSymlinkCB) +
3494                              TargetName->Length);
3495
3496         pSymlinkResult = (AFSCreateSymlinkResultCB *)ExAllocatePoolWithTag( PagedPool,
3497                                                                             PAGE_SIZE,
3498                                                                             AFS_SYMLINK_REQUEST_TAG);
3499
3500         if( pSymlinkResult == NULL)
3501         {
3502
3503             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3504         }
3505
3506         RtlZeroMemory( pSymlinkResult,
3507                        PAGE_SIZE);
3508
3509         //
3510         // Populate the request buffer
3511         //
3512
3513         RtlCopyMemory( &pSymlinkCreate->ParentId,
3514                        &ObjectInfo->ParentFileId,
3515                        sizeof( AFSFileID));
3516
3517         pSymlinkCreate->TargetNameLength = TargetName->Length;
3518
3519         RtlCopyMemory( pSymlinkCreate->TargetName,
3520                        TargetName->Buffer,
3521                        TargetName->Length);
3522
3523         ulResultLen = PAGE_SIZE;
3524
3525         //
3526         // Call the service to create the symlink entry
3527         //
3528
3529         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_SYMLINK,
3530                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
3531                                       AuthGroup,
3532                                       FileName,
3533                                       &ObjectInfo->FileId,
3534                                       ObjectInfo->VolumeCB->VolumeInformation.Cell,
3535                                       ObjectInfo->VolumeCB->VolumeInformation.CellLength,
3536                                       pSymlinkCreate,
3537                                       sizeof( AFSCreateSymlinkCB) +
3538                                                 TargetName->Length,
3539                                       pSymlinkResult,
3540                                       &ulResultLen);
3541
3542         if ( ntStatus == STATUS_FILE_DELETED )
3543         {
3544
3545             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3546                           AFS_TRACE_LEVEL_ERROR,
3547                           "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3548                           ObjectInfo->FileId.Cell,
3549                           ObjectInfo->FileId.Volume,
3550                           ObjectInfo->FileId.Vnode,
3551                           ObjectInfo->FileId.Unique,
3552                           ntStatus));
3553
3554             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3555
3556             ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3557
3558             SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3559
3560             try_return( ntStatus = STATUS_ACCESS_DENIED);
3561         }
3562         else if( ntStatus != STATUS_SUCCESS)
3563         {
3564
3565             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3566                           AFS_TRACE_LEVEL_ERROR,
3567                           "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3568                           ObjectInfo->FileId.Cell,
3569                           ObjectInfo->FileId.Volume,
3570                           ObjectInfo->FileId.Vnode,
3571                           ObjectInfo->FileId.Unique,
3572                           ntStatus));
3573
3574             try_return( ntStatus);
3575         }
3576
3577         //
3578         // After successful creation the open object has been deleted and replaced by
3579         // the actual symlink.
3580         //
3581
3582         SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3583
3584         ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3585
3586         SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3587
3588 try_exit:
3589
3590         if( pSymlinkCreate != NULL)
3591         {
3592
3593             AFSExFreePoolWithTag( pSymlinkCreate, AFS_SYMLINK_REQUEST_TAG);
3594         }
3595
3596         if( pSymlinkResult != NULL)
3597         {
3598
3599             AFSExFreePoolWithTag( pSymlinkResult, AFS_SYMLINK_REQUEST_TAG);
3600         }
3601     }
3602
3603     return ntStatus;
3604 }