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