Windows: disable short names in redirector option
[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 = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
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 = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1094
1095                             if ( !NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
1096                                                                         AFS_INVALIDATE_DATA_VERSION)))
1097                             {
1098
1099                                 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
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.QuadPart,
1616                           pResultCB->ParentDataVersion.QuadPart);
1617
1618             //
1619             // We raced so go and lookup the directory entry in the parent
1620             //
1621
1622             ulCRC = AFSGenerateCRC( FileName,
1623                                     FALSE);
1624
1625             AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1626                                             ulCRC,
1627                                             &pDirNode);
1628
1629             if( pDirNode != NULL)
1630             {
1631
1632                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1633                               AFS_TRACE_LEVEL_VERBOSE,
1634                               "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1635                               pDirNode,
1636                               FileName);
1637
1638                 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1639                                     &pResultCB->DirEnum.FileId))
1640                 {
1641
1642                     InterlockedIncrement( &pDirNode->OpenReferenceCount);
1643
1644                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1645                                   AFS_TRACE_LEVEL_VERBOSE,
1646                                   "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1647                                   &pDirNode->NameInformation.FileName,
1648                                   pDirNode,
1649                                   pDirNode->OpenReferenceCount);
1650
1651                     *DirNode = pDirNode;
1652
1653                     AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1654
1655                     try_return( ntStatus = STATUS_REPARSE);
1656                 }
1657                 else
1658                 {
1659
1660                     //
1661                     // We found an entry that matches the desired name but it is not the
1662                     // same as the one that was created for us by the file server.
1663                     //
1664
1665                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1666                                   AFS_TRACE_LEVEL_ERROR,
1667                                   "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1668                                   FileName,
1669                                   pDirNode,
1670                                   pDirNode->ObjectInformation->FileId.Cell,
1671                                   pDirNode->ObjectInformation->FileId.Volume,
1672                                   pDirNode->ObjectInformation->FileId.Vnode,
1673                                   pDirNode->ObjectInformation->FileId.Unique,
1674                                   pResultCB->DirEnum.FileId.Cell,
1675                                   pResultCB->DirEnum.FileId.Volume,
1676                                   pResultCB->DirEnum.FileId.Vnode,
1677                                   pResultCB->DirEnum.FileId.Unique);
1678
1679                     if( pDirNode->OpenReferenceCount == 0)
1680                     {
1681
1682                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1683                                       AFS_TRACE_LEVEL_VERBOSE,
1684                                       "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1685                                       pDirNode,
1686                                       &pDirNode->NameInformation.FileName,
1687                                       pDirNode->ObjectInformation->FileId.Cell,
1688                                       pDirNode->ObjectInformation->FileId.Volume,
1689                                       pDirNode->ObjectInformation->FileId.Vnode,
1690                                       pDirNode->ObjectInformation->FileId.Unique,
1691                                       pResultCB->DirEnum.FileId.Cell,
1692                                       pResultCB->DirEnum.FileId.Volume,
1693                                       pResultCB->DirEnum.FileId.Vnode,
1694                                       pResultCB->DirEnum.FileId.Unique);
1695
1696                         AFSDeleteDirEntry( ParentObjectInfo,
1697                                            pDirNode);
1698                     }
1699                     else
1700                     {
1701
1702                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1703
1704                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1705                                       AFS_TRACE_LEVEL_VERBOSE,
1706                                       "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1707                                       pDirNode,
1708                                       &pDirNode->NameInformation.FileName,
1709                                       pDirNode->ObjectInformation->FileId.Cell,
1710                                       pDirNode->ObjectInformation->FileId.Volume,
1711                                       pDirNode->ObjectInformation->FileId.Vnode,
1712                                       pDirNode->ObjectInformation->FileId.Unique,
1713                                       pResultCB->DirEnum.FileId.Cell,
1714                                       pResultCB->DirEnum.FileId.Volume,
1715                                       pResultCB->DirEnum.FileId.Vnode,
1716                                       pResultCB->DirEnum.FileId.Unique);
1717
1718                         AFSRemoveNameEntry( ParentObjectInfo,
1719                                             pDirNode);
1720                     }
1721
1722                     pDirNode = NULL;
1723                 }
1724             }
1725
1726             //
1727             // We are unsure of our current data so set the verify flag. It may already be set
1728             // but no big deal to reset it
1729             //
1730
1731             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1732
1733             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1734         }
1735
1736         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1737                       AFS_TRACE_LEVEL_VERBOSE,
1738                       "AFSNotifyFileCreate Creating new entry %wZ\n",
1739                       FileName);
1740
1741         //
1742         // Initialize the directory entry
1743         //
1744
1745         uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1746
1747         uniTargetName.MaximumLength = uniTargetName.Length;
1748
1749         uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1750
1751         pDirNode = AFSInitDirEntry( ParentObjectInfo,
1752                                     FileName,
1753                                     &uniTargetName,
1754                                     &pResultCB->DirEnum,
1755                                     (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1756
1757         if( pDirNode == NULL)
1758         {
1759
1760             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1761
1762             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1763
1764             AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1765
1766             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1767         }
1768
1769         //
1770         // Init the short name if we have one
1771         //
1772
1773         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1774             pResultCB->DirEnum.ShortNameLength > 0)
1775         {
1776
1777             UNICODE_STRING uniShortName;
1778
1779             pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1780
1781             RtlCopyMemory( pDirNode->NameInformation.ShortName,
1782                            pResultCB->DirEnum.ShortName,
1783                            pDirNode->NameInformation.ShortNameLength);
1784
1785             //
1786             // Generate the short name index
1787             //
1788
1789             uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1790             uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1791
1792             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1793                                                                                TRUE);
1794
1795             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1796                           AFS_TRACE_LEVEL_VERBOSE,
1797                           "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1798                           &uniShortName,
1799                           pDirNode,
1800                           &pDirNode->NameInformation.FileName);
1801         }
1802         else
1803         {
1804             //
1805             // No short name or short names are disabled
1806             //
1807
1808             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1809         }
1810
1811         if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1812         {
1813
1814             //
1815             // Update the parent data version
1816             //
1817
1818             ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1819
1820             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1821                           AFS_TRACE_LEVEL_VERBOSE,
1822                           "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1823                           FileName,
1824                           ParentObjectInfo->FileId.Cell,
1825                           ParentObjectInfo->FileId.Volume,
1826                           ParentObjectInfo->FileId.Vnode,
1827                           ParentObjectInfo->FileId.Unique,
1828                           ParentObjectInfo->DataVersion.QuadPart);
1829         }
1830
1831         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1832
1833         //
1834         // Return the directory node
1835         //
1836
1837         *DirNode = pDirNode;
1838
1839 try_exit:
1840
1841         if( pResultCB != NULL)
1842         {
1843
1844             AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_1_TAG);
1845         }
1846     }
1847
1848     return ntStatus;
1849 }
1850
1851 NTSTATUS
1852 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1853                           IN AFSObjectInfoCB *ObjectInfo,
1854                           IN GUID *AuthGroup)
1855 {
1856
1857     NTSTATUS ntStatus = STATUS_SUCCESS;
1858     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1859     AFSFileUpdateCB stUpdateCB;
1860     ULONG ulResultLen = 0;
1861     AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1862
1863     __Enter
1864     {
1865
1866         //
1867         // Init the control block for the request
1868         //
1869
1870         RtlZeroMemory( &stUpdateCB,
1871                        sizeof( AFSFileUpdateCB));
1872
1873         stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1874
1875         stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1876
1877         stUpdateCB.EaSize = ObjectInfo->EaSize;
1878
1879         stUpdateCB.ParentId = *ParentFid;
1880
1881         stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1882
1883         stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1884
1885         stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1886
1887         stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1888
1889         pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1890                                                                              PAGE_SIZE,
1891                                                                              AFS_UPDATE_RESULT_TAG);
1892
1893         if( pUpdateResultCB == NULL)
1894         {
1895
1896             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1897         }
1898
1899         ulResultLen = PAGE_SIZE;
1900
1901         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1902                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1903                                       AuthGroup,
1904                                       NULL,
1905                                       &ObjectInfo->FileId,
1906                                       &stUpdateCB,
1907                                       sizeof( AFSFileUpdateCB),
1908                                       pUpdateResultCB,
1909                                       &ulResultLen);
1910
1911         if( ntStatus != STATUS_SUCCESS)
1912         {
1913
1914             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1915                           AFS_TRACE_LEVEL_ERROR,
1916                           "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1917                           ObjectInfo->FileId.Cell,
1918                           ObjectInfo->FileId.Volume,
1919                           ObjectInfo->FileId.Vnode,
1920                           ObjectInfo->FileId.Unique,
1921                           ntStatus);
1922
1923             try_return( ntStatus);
1924         }
1925
1926         //
1927         // Update the data version
1928         //
1929
1930         AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1931                         TRUE);
1932
1933         if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1934         {
1935
1936             ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1937         }
1938
1939         AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1940
1941 try_exit:
1942
1943         if( pUpdateResultCB != NULL)
1944         {
1945
1946             AFSExFreePoolWithTag( pUpdateResultCB, AFS_UPDATE_RESULT_TAG);
1947         }
1948     }
1949
1950     return ntStatus;
1951 }
1952
1953 NTSTATUS
1954 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1955                  IN GUID           *AuthGroup,
1956                  IN BOOLEAN         CheckOnly)
1957 {
1958     NTSTATUS ntStatus = STATUS_SUCCESS;
1959     ULONG ulResultLen = 0;
1960     AFSFileDeleteCB stDelete;
1961     AFSFileDeleteResultCB stDeleteResult;
1962     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1963
1964     __Enter
1965     {
1966
1967         stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
1968
1969         stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1970
1971         ulResultLen = sizeof( AFSFileDeleteResultCB);
1972
1973         if( CheckOnly)
1974         {
1975             ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1976         }
1977
1978         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1979                                       ulRequestFlags,
1980                                       AuthGroup,
1981                                       &DirectoryCB->NameInformation.FileName,
1982                                       &DirectoryCB->ObjectInformation->FileId,
1983                                       &stDelete,
1984                                       sizeof( AFSFileDeleteCB),
1985                                       &stDeleteResult,
1986                                       &ulResultLen);
1987
1988         if( ntStatus != STATUS_SUCCESS)
1989         {
1990
1991             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1992                           AFS_TRACE_LEVEL_ERROR,
1993                           "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1994                           stDelete.ParentId.Cell,
1995                           stDelete.ParentId.Volume,
1996                           stDelete.ParentId.Vnode,
1997                           stDelete.ParentId.Unique,
1998                           &DirectoryCB->NameInformation.FileName,
1999                           DirectoryCB->ObjectInformation->FileId.Cell,
2000                           DirectoryCB->ObjectInformation->FileId.Volume,
2001                           DirectoryCB->ObjectInformation->FileId.Vnode,
2002                           DirectoryCB->ObjectInformation->FileId.Unique,
2003                           ntStatus);
2004
2005             try_return( ntStatus);
2006         }
2007
2008         AFSAcquireExcl( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2009                         TRUE);
2010
2011         if( CheckOnly)
2012         {
2013
2014             //
2015             // Validate the parent data version
2016             //
2017
2018             if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2019             {
2020
2021                 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2022
2023                 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2024             }
2025         }
2026         else
2027         {
2028
2029             //
2030             // Update the parent data version
2031             //
2032
2033             if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2034             {
2035
2036                 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2037
2038                 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2039             }
2040             else
2041             {
2042
2043                 //
2044                 // TODO -- The entry must be removed from the directory at which point the
2045                 // Directory data version number can be updated.  Until then we must force
2046                 // a verification.
2047                 //
2048                 // DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2049                 //
2050
2051                 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2052
2053                 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2054             }
2055         }
2056
2057         AFSReleaseResource( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2058
2059 try_exit:
2060
2061         NOTHING;
2062     }
2063
2064     return ntStatus;
2065 }
2066
2067 NTSTATUS
2068 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2069                  IN GUID            *AuthGroup,
2070                  IN AFSObjectInfoCB *ParentObjectInfo,
2071                  IN AFSObjectInfoCB *TargetParentObjectInfo,
2072                  IN AFSDirectoryCB *DirectoryCB,
2073                  IN UNICODE_STRING *TargetName,
2074                  OUT AFSFileID  *UpdatedFID)
2075 {
2076
2077     NTSTATUS ntStatus = STATUS_SUCCESS;
2078     AFSFileRenameCB *pRenameCB = NULL;
2079     AFSFileRenameResultCB *pRenameResultCB = NULL;
2080     ULONG ulResultLen = 0;
2081     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2082
2083     __Enter
2084     {
2085
2086         //
2087         // Init the control block for the request
2088         //
2089
2090         pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2091                                                                  PAGE_SIZE,
2092                                                                  AFS_RENAME_REQUEST_TAG);
2093
2094         if( pRenameCB == NULL)
2095         {
2096
2097             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2098         }
2099
2100         RtlZeroMemory( pRenameCB,
2101                        PAGE_SIZE);
2102
2103         pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2104
2105         pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2106
2107         pRenameCB->TargetNameLength = TargetName->Length;
2108
2109         RtlCopyMemory( pRenameCB->TargetName,
2110                        TargetName->Buffer,
2111                        TargetName->Length);
2112
2113         //
2114         // Use the same buffer for the result control block
2115         //
2116
2117         pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2118
2119         ulResultLen = PAGE_SIZE;
2120
2121         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2122                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2123                                       AuthGroup,
2124                                       &DirectoryCB->NameInformation.FileName,
2125                                       &ObjectInfo->FileId,
2126                                       pRenameCB,
2127                                       sizeof( AFSFileRenameCB) + TargetName->Length,
2128                                       pRenameResultCB,
2129                                       &ulResultLen);
2130
2131         if( ntStatus != STATUS_SUCCESS)
2132         {
2133
2134             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2135                           AFS_TRACE_LEVEL_ERROR,
2136                           "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2137                           ObjectInfo->FileId.Cell,
2138                           ObjectInfo->FileId.Volume,
2139                           ObjectInfo->FileId.Vnode,
2140                           ObjectInfo->FileId.Unique,
2141                           ntStatus);
2142
2143             try_return( ntStatus);
2144         }
2145
2146         //
2147         // Update the information from the returned data
2148         //
2149
2150         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2151                         TRUE);
2152
2153         if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2154         {
2155
2156             ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2157         }
2158         else
2159         {
2160
2161             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2162
2163             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2164         }
2165
2166         if ( ParentObjectInfo != TargetParentObjectInfo)
2167         {
2168
2169             if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2170             {
2171
2172                 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2173             }
2174             else
2175             {
2176
2177                 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2178
2179                 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2180             }
2181         }
2182
2183         //
2184         // Move over the short name
2185         //
2186
2187         DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2188
2189         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2190             DirectoryCB->NameInformation.ShortNameLength > 0)
2191         {
2192
2193             UNICODE_STRING uniShortName;
2194
2195             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2196             uniShortName.MaximumLength = uniShortName.Length;
2197             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2198
2199             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2200                           AFS_TRACE_LEVEL_VERBOSE,
2201                           "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2202                           &uniShortName,
2203                           DirectoryCB,
2204                           &DirectoryCB->NameInformation.FileName);
2205
2206             DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2207
2208             RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2209                            pRenameResultCB->DirEnum.ShortName,
2210                            DirectoryCB->NameInformation.ShortNameLength);
2211
2212             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2213             uniShortName.MaximumLength = uniShortName.Length;
2214             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2215
2216             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2217                           AFS_TRACE_LEVEL_VERBOSE,
2218                           "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2219                           &uniShortName,
2220                           DirectoryCB,
2221                           &DirectoryCB->NameInformation.FileName);
2222         }
2223         else
2224         {
2225
2226             UNICODE_STRING uniShortName;
2227
2228             uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2229             uniShortName.MaximumLength = uniShortName.Length;
2230             uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2231
2232             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2233                           AFS_TRACE_LEVEL_VERBOSE,
2234                           "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2235                           &uniShortName,
2236                           DirectoryCB,
2237                           &DirectoryCB->NameInformation.FileName);
2238
2239             DirectoryCB->NameInformation.ShortNameLength = 0;
2240
2241             DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2242         }
2243
2244         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2245
2246         if( UpdatedFID != NULL)
2247         {
2248             *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2249         }
2250
2251 try_exit:
2252
2253         if( pRenameCB != NULL)
2254         {
2255
2256             AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2257         }
2258     }
2259
2260     return ntStatus;
2261 }
2262
2263 NTSTATUS
2264 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2265                        IN GUID *AuthGroup,
2266                        IN BOOLEAN FastCall,
2267                        OUT AFSDirEnumEntry **DirEnumEntry)
2268 {
2269
2270     NTSTATUS ntStatus = STATUS_SUCCESS;
2271     AFSEvalTargetCB stTargetID;
2272     ULONG ulResultBufferLength;
2273     AFSFileEvalResultCB *pEvalResultCB = NULL;
2274     AFSDirEnumEntry *pDirEnumCB = NULL;
2275     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2276     AFSObjectInfoCB *pParentInfo = NULL;
2277
2278     __Enter
2279     {
2280
2281         RtlZeroMemory( &stTargetID,
2282                        sizeof( AFSEvalTargetCB));
2283
2284         pParentInfo = ObjectInfo->ParentObjectInformation;
2285
2286         if( pParentInfo != NULL)
2287         {
2288
2289             stTargetID.ParentId = pParentInfo->FileId;
2290         }
2291
2292         //
2293         // Allocate our response buffer
2294         //
2295
2296         pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2297                                                                          PAGE_SIZE,
2298                                                                          AFS_GENERIC_MEMORY_30_TAG);
2299
2300         if( pEvalResultCB == NULL)
2301         {
2302
2303             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2304         }
2305
2306         //
2307         // Call to the service to evaluate the fid
2308         //
2309
2310         ulResultBufferLength = PAGE_SIZE;
2311
2312         if( FastCall)
2313         {
2314
2315             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2316         }
2317
2318         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2319                                       ulRequestFlags,
2320                                       AuthGroup,
2321                                       NULL,
2322                                       &ObjectInfo->FileId,
2323                                       &stTargetID,
2324                                       sizeof( AFSEvalTargetCB),
2325                                       pEvalResultCB,
2326                                       &ulResultBufferLength);
2327
2328         if( ntStatus != STATUS_SUCCESS)
2329         {
2330
2331             //
2332             // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2333             // verification
2334             //
2335
2336             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2337             {
2338
2339                 if( pParentInfo != NULL)
2340                 {
2341
2342                     AFSAcquireExcl( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2343                                     TRUE);
2344
2345                     SetFlag( pParentInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2346
2347                     pParentInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2348
2349                     AFSReleaseResource( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2350                 }
2351             }
2352
2353             try_return( ntStatus);
2354         }
2355
2356         //
2357         // Validate the parent data version
2358         //
2359
2360         if ( pParentInfo != NULL)
2361         {
2362
2363             AFSAcquireExcl( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2364                             TRUE);
2365
2366             if ( pParentInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2367             {
2368
2369                 SetFlag( pParentInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2370
2371                 pParentInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2372             }
2373
2374             AFSReleaseResource( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2375         }
2376
2377         //
2378         // Pass back the dir enum entry
2379         //
2380
2381         if( DirEnumEntry != NULL)
2382         {
2383
2384             pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2385                                                                       PAGE_SIZE,
2386                                                                       AFS_GENERIC_MEMORY_2_TAG);
2387
2388             if( pDirEnumCB == NULL)
2389             {
2390
2391                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2392             }
2393
2394             RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2395                            ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2396
2397             *DirEnumEntry = pDirEnumCB;
2398         }
2399
2400 try_exit:
2401
2402         if( pEvalResultCB != NULL)
2403         {
2404
2405             AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2406         }
2407
2408         if( !NT_SUCCESS( ntStatus))
2409         {
2410
2411             if( pDirEnumCB != NULL)
2412             {
2413
2414                 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2415             }
2416
2417             *DirEnumEntry = NULL;
2418         }
2419     }
2420
2421     return ntStatus;
2422 }
2423
2424 NTSTATUS
2425 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2426                          IN AFSObjectInfoCB *ParentObjectInfo,
2427                          IN PUNICODE_STRING SourceName,
2428                          OUT AFSDirEnumEntry **DirEnumEntry)
2429 {
2430
2431     NTSTATUS ntStatus = STATUS_SUCCESS;
2432     AFSEvalTargetCB stTargetID;
2433     ULONG ulResultBufferLength;
2434     AFSFileEvalResultCB *pEvalResultCB = NULL;
2435     AFSDirEnumEntry *pDirEnumCB = NULL;
2436
2437     __Enter
2438     {
2439
2440         stTargetID.ParentId = ParentObjectInfo->FileId;
2441
2442         //
2443         // Allocate our response buffer
2444         //
2445
2446         pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2447                                                                          PAGE_SIZE,
2448                                                                          AFS_GENERIC_MEMORY_31_TAG);
2449
2450         if( pEvalResultCB == NULL)
2451         {
2452
2453             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2454         }
2455
2456         //
2457         // Call to the service to evaluate the fid
2458         //
2459
2460         ulResultBufferLength = PAGE_SIZE;
2461
2462         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2463                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2464                                       AuthGroup,
2465                                       SourceName,
2466                                       NULL,
2467                                       &stTargetID,
2468                                       sizeof( AFSEvalTargetCB),
2469                                       pEvalResultCB,
2470                                       &ulResultBufferLength);
2471
2472         if( ntStatus != STATUS_SUCCESS)
2473         {
2474
2475             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2476             {
2477
2478                 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2479                                 TRUE);
2480
2481                 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2482
2483                 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2484
2485                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2486             }
2487
2488             try_return( ntStatus);
2489         }
2490
2491         //
2492         // Validate the parent data version
2493         //
2494
2495         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2496                         TRUE);
2497
2498         if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2499         {
2500
2501             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2502
2503             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2504         }
2505
2506         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2507
2508         //
2509         // Pass back the dir enum entry
2510         //
2511
2512         if( DirEnumEntry != NULL)
2513         {
2514
2515             pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2516                                                                       PAGE_SIZE,
2517                                                                       AFS_GENERIC_MEMORY_3_TAG);
2518
2519             if( pDirEnumCB == NULL)
2520             {
2521
2522                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2523             }
2524
2525             RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2526                            ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2527
2528             *DirEnumEntry = pDirEnumCB;
2529         }
2530
2531 try_exit:
2532
2533         if( pEvalResultCB != NULL)
2534         {
2535
2536             AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
2537         }
2538
2539         if( !NT_SUCCESS( ntStatus))
2540         {
2541
2542             if( pDirEnumCB != NULL)
2543             {
2544
2545                 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
2546             }
2547
2548             *DirEnumEntry = NULL;
2549         }
2550     }
2551
2552     return ntStatus;
2553 }
2554
2555 NTSTATUS
2556 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
2557                               IN AFSFileID *FileID,
2558                               OUT AFSVolumeInfoCB *VolumeInformation)
2559 {
2560
2561     NTSTATUS ntStatus = STATUS_SUCCESS;
2562     ULONG ulResultLen = 0;
2563
2564     __Enter
2565     {
2566
2567         ulResultLen = sizeof( AFSVolumeInfoCB);
2568
2569         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
2570                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2571                                       AuthGroup,
2572                                       NULL,
2573                                       FileID,
2574                                       NULL,
2575                                       0,
2576                                       VolumeInformation,
2577                                       &ulResultLen);
2578
2579         if( ntStatus != STATUS_SUCCESS)
2580         {
2581
2582             try_return( ntStatus);
2583         }
2584
2585 try_exit:
2586
2587         NOTHING;
2588     }
2589
2590     return ntStatus;
2591 }
2592
2593 NTSTATUS
2594 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
2595                                   IN AFSFileID *FileID,
2596                                   OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
2597 {
2598
2599     NTSTATUS ntStatus = STATUS_SUCCESS;
2600     ULONG ulResultLen = 0;
2601
2602     __Enter
2603     {
2604
2605         ulResultLen = sizeof( AFSVolumeSizeInfoCB);
2606
2607         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
2608                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2609                                       AuthGroup,
2610                                       NULL,
2611                                       FileID,
2612                                       NULL,
2613                                       0,
2614                                       VolumeSizeInformation,
2615                                       &ulResultLen);
2616
2617         if( ntStatus != STATUS_SUCCESS)
2618         {
2619
2620             try_return( ntStatus);
2621         }
2622
2623 try_exit:
2624
2625         NOTHING;
2626     }
2627
2628     return ntStatus;
2629 }
2630
2631 NTSTATUS
2632 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
2633                          IN ULONG InputLength,
2634                          IN ULONG OutputLength,
2635                          IN void *InputDataBuffer,
2636                          OUT void *OutputDataBuffer,
2637                          OUT ULONG *BytesReturned)
2638 {
2639
2640     NTSTATUS ntStatus = STATUS_SUCCESS;
2641     ULONG ulResultLen = 0;
2642     MDL *pInputMdl = NULL, *pOutputMdl = NULL;
2643     void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
2644     ULONG ulBufferLength = OutputLength;
2645     AFSPipeIORequestCB *pIoRequest = NULL;
2646
2647     __Enter
2648     {
2649
2650         //
2651         // Map the user buffer to a system address
2652         //
2653
2654         pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
2655                                                 InputLength,
2656                                                 &pInputMdl);
2657
2658         if( pInputSystemBuffer == NULL)
2659         {
2660
2661             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2662         }
2663
2664         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2665                                                                      sizeof( AFSPipeIORequestCB) +
2666                                                                                 InputLength,
2667                                                                      AFS_GENERIC_MEMORY_4_TAG);
2668
2669         if( pIoRequest == NULL)
2670         {
2671
2672             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2673         }
2674
2675         RtlZeroMemory( pIoRequest,
2676                        sizeof( AFSPipeIORequestCB) + InputLength);
2677
2678         pIoRequest->RequestId = Ccb->RequestID;
2679
2680         pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2681
2682         pIoRequest->BufferLength = InputLength;
2683
2684         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2685                        pInputSystemBuffer,
2686                        InputLength);
2687
2688         pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
2689                                                  OutputLength,
2690                                                  &pOutputMdl);
2691
2692         if( pOutputSystemBuffer == NULL)
2693         {
2694
2695             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2696         }
2697
2698         //
2699         // Send the call to the service
2700         //
2701
2702         ulResultLen = OutputLength;
2703
2704         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
2705                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2706                                       &Ccb->AuthGroup,
2707                                       &Ccb->DirectoryCB->NameInformation.FileName,
2708                                       NULL,
2709                                       pIoRequest,
2710                                       sizeof( AFSPipeIORequestCB) + InputLength,
2711                                       pOutputSystemBuffer,
2712                                       &ulResultLen);
2713
2714         if( ntStatus != STATUS_SUCCESS &&
2715             ntStatus != STATUS_BUFFER_OVERFLOW)
2716         {
2717
2718             if( NT_SUCCESS( ntStatus))
2719             {
2720
2721                 ntStatus = STATUS_DEVICE_NOT_READY;
2722             }
2723
2724             try_return( ntStatus);
2725         }
2726
2727         //
2728         // Return the bytes processed
2729         //
2730
2731         *BytesReturned = ulResultLen;
2732
2733 try_exit:
2734
2735         if( pInputMdl != NULL)
2736         {
2737
2738             MmUnlockPages( pInputMdl);
2739
2740             IoFreeMdl( pInputMdl);
2741         }
2742
2743         if( pOutputMdl != NULL)
2744         {
2745
2746             MmUnlockPages( pOutputMdl);
2747
2748             IoFreeMdl( pOutputMdl);
2749         }
2750
2751         if( pIoRequest != NULL)
2752         {
2753
2754             AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
2755         }
2756     }
2757
2758     return ntStatus;
2759 }
2760
2761 NTSTATUS
2762 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
2763                       IN ULONG InformationClass,
2764                       IN ULONG InputLength,
2765                       IN void *DataBuffer)
2766 {
2767
2768     NTSTATUS ntStatus = STATUS_SUCCESS;
2769     AFSPipeInfoRequestCB *pInfoRequest = NULL;
2770
2771     __Enter
2772     {
2773
2774         pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2775                                                                          sizeof( AFSPipeInfoRequestCB) +
2776                                                                                 InputLength,
2777                                                                          AFS_GENERIC_MEMORY_5_TAG);
2778
2779         if( pInfoRequest == NULL)
2780         {
2781
2782             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2783         }
2784
2785         RtlZeroMemory( pInfoRequest,
2786                        sizeof( AFSPipeInfoRequestCB) + InputLength);
2787
2788         pInfoRequest->RequestId = Ccb->RequestID;
2789
2790         pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2791
2792         pInfoRequest->BufferLength = InputLength;
2793
2794         pInfoRequest->InformationClass = InformationClass;
2795
2796         RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
2797                        DataBuffer,
2798                        InputLength);
2799
2800         //
2801         // Send the call to the service
2802         //
2803
2804         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
2805                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2806                                       &Ccb->AuthGroup,
2807                                       &Ccb->DirectoryCB->NameInformation.FileName,
2808                                       NULL,
2809                                       pInfoRequest,
2810                                       sizeof( AFSPipeInfoRequestCB) + InputLength,
2811                                       NULL,
2812                                       NULL);
2813
2814         if( ntStatus != STATUS_SUCCESS)
2815         {
2816
2817             if( NT_SUCCESS( ntStatus))
2818             {
2819
2820                 ntStatus = STATUS_DEVICE_NOT_READY;
2821             }
2822
2823             try_return( ntStatus);
2824         }
2825
2826 try_exit:
2827
2828         if( pInfoRequest != NULL)
2829         {
2830
2831             AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
2832         }
2833     }
2834
2835     return ntStatus;
2836 }
2837
2838 NTSTATUS
2839 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
2840                         IN ULONG InformationClass,
2841                         IN ULONG OutputLength,
2842                         IN void *DataBuffer,
2843                         OUT ULONG *BytesReturned)
2844 {
2845
2846     NTSTATUS ntStatus = STATUS_SUCCESS;
2847     AFSPipeInfoRequestCB stInfoRequest;
2848     ULONG ulBytesProcessed = 0;
2849
2850     __Enter
2851     {
2852
2853         RtlZeroMemory( &stInfoRequest,
2854                        sizeof( AFSPipeInfoRequestCB));
2855
2856         stInfoRequest.RequestId = Ccb->RequestID;
2857
2858         stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2859
2860         stInfoRequest.BufferLength = OutputLength;
2861
2862         stInfoRequest.InformationClass = InformationClass;
2863
2864         ulBytesProcessed = OutputLength;
2865
2866         //
2867         // Send the call to the service
2868         //
2869
2870         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
2871                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2872                                       &Ccb->AuthGroup,
2873                                       &Ccb->DirectoryCB->NameInformation.FileName,
2874                                       NULL,
2875                                       &stInfoRequest,
2876                                       sizeof( AFSPipeInfoRequestCB),
2877                                       DataBuffer,
2878                                       &ulBytesProcessed);
2879
2880         if( ntStatus != STATUS_SUCCESS)
2881         {
2882
2883             if( NT_SUCCESS( ntStatus))
2884             {
2885
2886                 ntStatus = STATUS_DEVICE_NOT_READY;
2887             }
2888
2889             try_return( ntStatus);
2890         }
2891
2892         *BytesReturned = ulBytesProcessed;
2893
2894 try_exit:
2895
2896         NOTHING;
2897     }
2898
2899     return ntStatus;
2900 }
2901
2902 NTSTATUS
2903 AFSReleaseFid( IN AFSFileID *FileId)
2904 {
2905
2906     NTSTATUS ntStatus = STATUS_SUCCESS;
2907
2908     __Enter
2909     {
2910
2911         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2912                                       0,
2913                                       NULL,
2914                                       NULL,
2915                                       FileId,
2916                                       NULL,
2917                                       0,
2918                                       NULL,
2919                                       NULL);
2920     }
2921
2922     return ntStatus;
2923 }
2924
2925 BOOLEAN
2926 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2927                           IN LARGE_INTEGER *ExtentOffset,
2928                           IN ULONG Length)
2929 {
2930
2931     BOOLEAN bRequestQueued = FALSE;
2932     NTSTATUS ntStatus = STATUS_SUCCESS;
2933     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2934     AFSCommSrvcCB   *pCommSrvc = NULL;
2935     AFSPoolEntry    *pPoolEntry = NULL;
2936     AFSRequestExtentsCB *pRequestExtents = NULL;
2937
2938     __Enter
2939     {
2940
2941
2942         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2943
2944         AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2945                           TRUE);
2946
2947         pPoolEntry = pCommSrvc->RequestPoolHead;
2948
2949         while( pPoolEntry != NULL)
2950         {
2951
2952             if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2953             {
2954
2955                 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2956                 {
2957
2958                     pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2959
2960                     if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2961                         pRequestExtents->Length == Length)
2962                     {
2963
2964                         bRequestQueued = TRUE;
2965                     }