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