74acdaad86ccc9e981612e885ee03f4571368598
[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
60     __Enter
61     {
62
63         uniGUID.Length = 0;
64         uniGUID.MaximumLength = 0;
65         uniGUID.Buffer = NULL;
66
67         if( AuthGroup != NULL)
68         {
69             RtlStringFromGUID( *AuthGroup,
70                                &uniGUID);
71         }
72
73         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
74                       AFS_TRACE_LEVEL_VERBOSE,
75                       "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
76                       ObjectInfoCB->FileId.Cell,
77                       ObjectInfoCB->FileId.Volume,
78                       ObjectInfoCB->FileId.Vnode,
79                       ObjectInfoCB->FileId.Unique,
80                       &uniGUID);
81
82         if( AuthGroup != NULL)
83         {
84             RtlFreeUnicodeString( &uniGUID);
85         }
86
87         //
88         // Initialize the directory enumeration buffer for the directory
89         //
90
91         pBuffer = AFSExAllocatePoolWithTag( PagedPool,
92                                             AFS_DIR_ENUM_BUFFER_LEN,
93                                             AFS_DIR_BUFFER_TAG);
94
95         if( pBuffer == NULL)
96         {
97
98             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
99         }
100
101         RtlZeroMemory( pBuffer,
102                        AFS_DIR_ENUM_BUFFER_LEN);
103
104         ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
105
106         //
107         // Use the payload buffer for information we will pass to the service
108         //
109
110         pDirQueryCB = (AFSDirQueryCB *)pBuffer;
111
112         pDirQueryCB->EnumHandle = 0;
113
114         if( FastQuery)
115         {
116
117             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
118         }
119
120         //
121         // Loop on the information
122         //
123
124         while( TRUE)
125         {
126
127             //
128             // Go and retrieve the directory contents
129             //
130
131             ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
132                                           ulRequestFlags,
133                                           AuthGroup,
134                                           NULL,
135                                           &ObjectInfoCB->FileId,
136                                           (void *)pDirQueryCB,
137                                           sizeof( AFSDirQueryCB),
138                                           pBuffer,
139                                           &ulResultLen);
140
141             if( ntStatus != STATUS_SUCCESS ||
142                 ulResultLen == 0)
143             {
144
145                 if( ntStatus == STATUS_NO_MORE_FILES ||
146                     ntStatus == STATUS_NO_MORE_ENTRIES)
147                 {
148
149                     ntStatus = STATUS_SUCCESS;
150                 }
151                 else
152                 {
153
154                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
155                                   AFS_TRACE_LEVEL_ERROR,
156                                   "AFSEnumerateDirectory Failed to enumerate directory Status %08lX\n",
157                                   ntStatus);
158                 }
159
160                 break;
161             }
162
163             pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
164
165             pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
166
167             //
168             // Remove the leading header from the processed length
169             //
170
171             ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
172
173             while( ulResultLen > 0)
174             {
175
176                 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
177
178                 uniDirName.MaximumLength = uniDirName.Length;
179
180                 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
181
182                 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
183
184                 uniTargetName.MaximumLength = uniTargetName.Length;
185
186                 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
187
188                 //
189                 // Be sure we don't have this entry in the case sensitive tree
190                 //
191
192                 ulCRC = AFSGenerateCRC( &uniDirName,
193                                         FALSE);
194
195                 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
196                                                 ulCRC,
197                                                 &pDirNode);
198
199                 if( pDirNode != NULL)
200                 {
201
202                     //
203                     // Duplicate entry, skip it
204                     //
205
206                     ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
207                                                     uniDirName.Length +
208                                                     uniTargetName.Length);
209
210                     pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
211
212                     if( ulResultLen >= ulEntryLength)
213                     {
214                         ulResultLen -= ulEntryLength;
215                     }
216                     else
217                     {
218                         ulResultLen = 0;
219                     }
220
221                     continue;
222                 }
223
224                 pDirNode = AFSInitDirEntry( ObjectInfoCB,
225                                             &uniDirName,
226                                             &uniTargetName,
227                                             pCurrentDirEntry,
228                                             (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
229
230                 if( pDirNode == NULL)
231                 {
232
233                     ntStatus = STATUS_INSUFFICIENT_RESOURCES;
234
235                     break;
236                 }
237
238                 //
239                 // Set up the entry length
240                 //
241
242                 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
243                                                     pCurrentDirEntry->FileNameLength +
244                                                     pCurrentDirEntry->TargetNameLength);
245
246                 //
247                 // Init the short name if we have one
248                 //
249
250                 if( pCurrentDirEntry->ShortNameLength > 0)
251                 {
252
253                     UNICODE_STRING uniShortName;
254
255                     pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
256
257                     RtlCopyMemory( pDirNode->NameInformation.ShortName,
258                                    pCurrentDirEntry->ShortName,
259                                    pDirNode->NameInformation.ShortNameLength);
260
261                     //
262                     // Generate the short name index
263                     //
264
265                     uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
266                     uniShortName.Buffer = pDirNode->NameInformation.ShortName;
267
268                     pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
269                                                                                        TRUE);
270                 }
271
272                 //
273                 // Insert the node into the name tree
274                 //
275
276                 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
277
278                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
279                 {
280
281                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
282                 }
283                 else
284                 {
285
286                     AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
287                                                     pDirNode);
288                 }
289
290                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
291                 {
292
293                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
294
295                     SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
296                 }
297                 else
298                 {
299
300                     AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
301                                                       pDirNode);
302                 }
303
304                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
305                 {
306
307                     ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
308                 }
309                 else
310                 {
311
312                     ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
313
314                     pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
315                 }
316
317                 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
318
319                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
320
321                 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
322
323                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
324                               AFS_TRACE_LEVEL_VERBOSE,
325                               "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
326                               &pDirNode->NameInformation.FileName,
327                               ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
328                               ObjectInfoCB->FileId.Cell,
329                               ObjectInfoCB->FileId.Volume,
330                               ObjectInfoCB->FileId.Vnode,
331                               ObjectInfoCB->FileId.Unique);
332
333                 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
334                 {
335
336                     //
337                     // Insert the short name entry if we have a valid short name
338                     //
339
340                     if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
341                     {
342
343                         ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
344                     }
345                     else
346                     {
347
348                         AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
349                                                     pDirNode);
350                     }
351                 }
352
353                 //
354                 // Next dir entry
355                 //
356
357                 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
358
359                 if( ulResultLen >= ulEntryLength)
360                 {
361                     ulResultLen -= ulEntryLength;
362                 }
363                 else
364                 {
365                     ulResultLen = 0;
366                 }
367             }
368
369             ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
370
371             //
372             // Reset the information in the request buffer since it got trampled
373             // above
374             //
375
376             pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
377
378             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
379                           AFS_TRACE_LEVEL_VERBOSE,
380                           "AFSEnumerateDirectory EnumHandle %08lX\n",
381                           pDirQueryCB->EnumHandle);
382
383             //
384             // If the enumeration handle is -1 then we are done
385             //
386
387             if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
388             {
389
390                 break;
391             }
392         }
393
394 try_exit:
395
396         //
397         // Cleanup
398         //
399
400         if( pBuffer != NULL)
401         {
402
403             AFSExFreePool( pBuffer);
404         }
405
406         //
407         // If the processing failed then we should reset the directory content in the event
408         // it is re-enumerated
409         //
410
411         if( !NT_SUCCESS( ntStatus))
412         {
413
414             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
415                           AFS_TRACE_LEVEL_ERROR,
416                           "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
417                           ObjectInfoCB->FileId.Cell,
418                           ObjectInfoCB->FileId.Volume,
419                           ObjectInfoCB->FileId.Vnode,
420                           ObjectInfoCB->FileId.Unique,
421                           ntStatus);
422
423             AFSResetDirectoryContent( ObjectInfoCB);
424         }
425     }
426
427     return ntStatus;
428 }
429
430 NTSTATUS
431 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
432                                  IN AFSFileID *FileId)
433 {
434
435     NTSTATUS ntStatus = STATUS_SUCCESS;
436     AFSDirQueryCB stDirQueryCB;
437     ULONG   ulRequestFlags = 0;
438
439     __Enter
440     {
441
442         //
443         // Use the payload buffer for information we will pass to the service
444         //
445
446         stDirQueryCB.EnumHandle = 0;
447
448         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
449                                       ulRequestFlags,
450                                       AuthGroup,
451                                       NULL,
452                                       FileId,
453                                       (void *)&stDirQueryCB,
454                                       sizeof( AFSDirQueryCB),
455                                       NULL,
456                                       NULL);
457
458         if( ntStatus != STATUS_SUCCESS)
459         {
460
461             if( ntStatus == STATUS_NO_MORE_FILES ||
462                 ntStatus == STATUS_NO_MORE_ENTRIES)
463             {
464
465                 ntStatus = STATUS_SUCCESS;
466             }
467             else
468             {
469
470                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
471                               AFS_TRACE_LEVEL_ERROR,
472                               "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
473                               ntStatus);
474             }
475         }
476     }
477
478     return ntStatus;
479 }
480
481 NTSTATUS
482 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
483                            IN GUID *AuthGroup)
484 {
485
486     NTSTATUS ntStatus = STATUS_SUCCESS;
487     void *pBuffer = NULL;
488     ULONG ulResultLen = 0;
489     AFSDirQueryCB *pDirQueryCB;
490     AFSDirEnumEntry *pCurrentDirEntry = NULL;
491     AFSDirectoryCB *pDirNode = NULL;
492     ULONG  ulEntryLength = 0;
493     AFSDirEnumResp *pDirEnumResponse = NULL;
494     UNICODE_STRING uniDirName, uniTargetName;
495     ULONG   ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
496     ULONG ulCRC = 0;
497     AFSObjectInfoCB *pObjectInfo = NULL;
498     ULONGLONG ullIndex = 0;
499     UNICODE_STRING uniGUID;
500
501     __Enter
502     {
503
504         uniGUID.Length = 0;
505         uniGUID.MaximumLength = 0;
506         uniGUID.Buffer = NULL;
507
508         if( AuthGroup != NULL)
509         {
510             RtlStringFromGUID( *AuthGroup,
511                                &uniGUID);
512         }
513
514         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
515                       AFS_TRACE_LEVEL_VERBOSE,
516                       "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
517                       ObjectInfoCB->FileId.Cell,
518                       ObjectInfoCB->FileId.Volume,
519                       ObjectInfoCB->FileId.Vnode,
520                       ObjectInfoCB->FileId.Unique,
521                       &uniGUID);
522
523         if( AuthGroup != NULL)
524         {
525             RtlFreeUnicodeString( &uniGUID);
526         }
527
528         //
529         // Initialize the directory enumeration buffer for the directory
530         //
531
532         pBuffer = AFSExAllocatePoolWithTag( PagedPool,
533                                             AFS_DIR_ENUM_BUFFER_LEN,
534                                             AFS_DIR_BUFFER_TAG);
535
536         if( pBuffer == NULL)
537         {
538
539             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
540         }
541
542         RtlZeroMemory( pBuffer,
543                        AFS_DIR_ENUM_BUFFER_LEN);
544
545         ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
546
547         //
548         // Use the payload buffer for information we will pass to the service
549         //
550
551         pDirQueryCB = (AFSDirQueryCB *)pBuffer;
552
553         pDirQueryCB->EnumHandle = 0;
554
555         //
556         // Loop on the information
557         //
558
559         while( TRUE)
560         {
561
562             //
563             // Go and retrieve the directory contents
564             //
565
566             ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
567                                           ulRequestFlags,
568                                           AuthGroup,
569                                           NULL,
570                                           &ObjectInfoCB->FileId,
571                                           (void *)pDirQueryCB,
572                                           sizeof( AFSDirQueryCB),
573                                           pBuffer,
574                                           &ulResultLen);
575
576             if( ntStatus != STATUS_SUCCESS ||
577                 ulResultLen == 0)
578             {
579
580                 if( ntStatus == STATUS_NO_MORE_FILES ||
581                     ntStatus == STATUS_NO_MORE_ENTRIES)
582                 {
583
584                     ntStatus = STATUS_SUCCESS;
585                 }
586                 else
587                 {
588
589                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
590                                   AFS_TRACE_LEVEL_ERROR,
591                                   "AFSVerifyDirectoryContent Failed to enumerate directory Status %08lX\n",
592                                   ntStatus);
593                 }
594
595                 break;
596             }
597
598             pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
599
600             pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
601
602             //
603             // Remove the leading header from the processed length
604             //
605
606             ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
607
608             while( ulResultLen > 0)
609             {
610
611                 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
612
613                 uniDirName.MaximumLength = uniDirName.Length;
614
615                 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
616
617                 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
618
619                 uniTargetName.MaximumLength = uniTargetName.Length;
620
621                 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
622
623                 //
624                 // Does this entry already exist in the directory?
625                 //
626
627                 ulCRC = AFSGenerateCRC( &uniDirName,
628                                         FALSE);
629
630                 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
631
632                 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
633                                                 ulCRC,
634                                                 &pDirNode);
635
636                 //
637                 //
638                 // Set up the entry length
639                 //
640
641                 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
642                                            pCurrentDirEntry->FileNameLength +
643                                            pCurrentDirEntry->TargetNameLength);
644
645                 if( pDirNode != NULL)
646                 {
647
648                     //
649                     // Check that the FIDs are the same
650                     //
651
652                     if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
653                                        &pDirNode->ObjectInformation->FileId))
654                     {
655
656                         AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
657                                           TRUE);
658
659                         ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
660
661                         ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
662                                                        ullIndex,
663                                                        (AFSBTreeEntry **)&pObjectInfo);
664
665                         AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
666
667                         if( NT_SUCCESS( ntStatus) &&
668                             pObjectInfo != NULL)
669                         {
670
671                             //
672                             // Indicate this is a valid entry
673                             //
674
675                             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
676
677                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
678                                           AFS_TRACE_LEVEL_VERBOSE,
679                                           "AFSVerifyDirectoryContent Verified entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
680                                           &uniDirName,
681                                           ObjectInfoCB->FileId.Cell,
682                                           ObjectInfoCB->FileId.Volume,
683                                           ObjectInfoCB->FileId.Vnode,
684                                           ObjectInfoCB->FileId.Unique);
685
686
687                             //
688                             // Update the metadata for the entry
689                             //
690
691                             if( pObjectInfo->DataVersion.QuadPart == 0 ||
692                                 pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
693                             {
694
695                                 AFSUpdateMetaData( pDirNode,
696                                                    pCurrentDirEntry);
697
698                                 if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
699                                 {
700
701                                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
702                                                   AFS_TRACE_LEVEL_VERBOSE,
703                                                   "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
704                                                   &uniDirName,
705                                                   ObjectInfoCB->FileId.Cell,
706                                                   ObjectInfoCB->FileId.Volume,
707                                                   ObjectInfoCB->FileId.Vnode,
708                                                   ObjectInfoCB->FileId.Unique);
709
710                                     SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
711                                     pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
712                                     pObjectInfo->Expiration.QuadPart = 0;
713                                 }
714                             }
715
716                             //
717                             // Next dir entry
718                             //
719
720                             pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
721
722                             if( ulResultLen >= ulEntryLength)
723                             {
724                                 ulResultLen -= ulEntryLength;
725                             }
726                             else
727                             {
728                                 ulResultLen = 0;
729                             }
730
731                             continue;
732                         }
733                     }
734
735                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
736                                   AFS_TRACE_LEVEL_VERBOSE,
737                                   "AFSVerifyDirectoryContent Processing dir entry %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
738                                   &pDirNode->NameInformation.FileName,
739                                   ObjectInfoCB->FileId.Cell,
740                                   ObjectInfoCB->FileId.Volume,
741                                   ObjectInfoCB->FileId.Vnode,
742                                   ObjectInfoCB->FileId.Unique);
743
744                     //
745                     // Need to tear down this entry and rebuild it below
746                     //
747
748                     if( pDirNode->OpenReferenceCount == 0)
749                     {
750
751                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
752                                       AFS_TRACE_LEVEL_VERBOSE,
753                                       "AFSVerifyDirectoryContent Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
754                                       &pDirNode->NameInformation.FileName,
755                                       ObjectInfoCB->FileId.Cell,
756                                       ObjectInfoCB->FileId.Volume,
757                                       ObjectInfoCB->FileId.Vnode,
758                                       ObjectInfoCB->FileId.Unique);
759
760                         AFSDeleteDirEntry( ObjectInfoCB,
761                                            pDirNode);
762                     }
763                     else
764                     {
765
766                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
767                                       AFS_TRACE_LEVEL_VERBOSE,
768                                       "AFSVerifyDirectoryContent Setting dir entry %p name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
769                                       pDirNode,
770                                       &pDirNode->NameInformation.FileName,
771                                       ObjectInfoCB->FileId.Cell,
772                                       ObjectInfoCB->FileId.Volume,
773                                       ObjectInfoCB->FileId.Vnode,
774                                       ObjectInfoCB->FileId.Unique);
775
776                         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
777
778                         AFSRemoveNameEntry( ObjectInfoCB,
779                                             pDirNode);
780                     }
781                 }
782
783                 pDirNode = AFSInitDirEntry( ObjectInfoCB,
784                                             &uniDirName,
785                                             &uniTargetName,
786                                             pCurrentDirEntry,
787                                             (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
788
789                 if( pDirNode == NULL)
790                 {
791
792                     ntStatus = STATUS_INSUFFICIENT_RESOURCES;
793
794                     break;
795                 }
796
797                 //
798                 // Init the short name if we have one
799                 //
800
801                 if( pCurrentDirEntry->ShortNameLength > 0)
802                 {
803
804                     UNICODE_STRING uniShortName;
805
806                     pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
807
808                     RtlCopyMemory( pDirNode->NameInformation.ShortName,
809                                    pCurrentDirEntry->ShortName,
810                                    pDirNode->NameInformation.ShortNameLength);
811
812                     //
813                     // Generate the short name index
814                     //
815
816                     uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
817                     uniShortName.Buffer = pDirNode->NameInformation.ShortName;
818
819                     pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
820                                                                                        TRUE);
821                 }
822
823                 //
824                 // Insert the node into the name tree
825                 //
826
827                 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
828
829                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
830                 {
831
832                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
833                 }
834                 else
835                 {
836
837                     AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
838                                                     pDirNode);
839                 }
840
841                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
842                 {
843
844                     ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
845
846                     SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
847                 }
848                 else
849                 {
850
851                     AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
852                                                       pDirNode);
853                 }
854
855                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
856                 {
857
858                     ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
859                 }
860                 else
861                 {
862
863                     (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
864
865                     pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
866                 }
867
868                 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
869
870                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
871
872                 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
873
874                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
875                               AFS_TRACE_LEVEL_VERBOSE,
876                               "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
877                               &pDirNode->NameInformation.FileName,
878                               ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
879                               ObjectInfoCB->FileId.Cell,
880                               ObjectInfoCB->FileId.Volume,
881                               ObjectInfoCB->FileId.Vnode,
882                               ObjectInfoCB->FileId.Unique);
883
884                 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
885                 {
886
887                     //
888                     // Insert the short name entry if we have a valid short name
889                     //
890
891                     if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
892                     {
893
894                         ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
895                     }
896                     else
897                     {
898
899                         AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
900                                                     pDirNode);
901                     }
902                 }
903
904                 //
905                 // Next dir entry
906                 //
907
908                 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
909
910                 if( ulResultLen >= ulEntryLength)
911                 {
912                     ulResultLen -= ulEntryLength;
913                 }
914                 else
915                 {
916                     ulResultLen = 0;
917                 }
918             }
919
920             ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
921
922             //
923             // Reset the information in the request buffer since it got trampled
924             // above
925             //
926
927             pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
928
929             //
930             // If the enumeration handle is -1 then we are done
931             //
932
933             if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
934             {
935
936                 break;
937             }
938         }
939
940 try_exit:
941
942         //
943         // Cleanup
944         //
945
946         if( pBuffer != NULL)
947         {
948
949             AFSExFreePool( pBuffer);
950         }
951     }
952
953     return ntStatus;
954 }
955
956 NTSTATUS
957 AFSNotifyFileCreate( IN GUID            *AuthGroup,
958                      IN AFSObjectInfoCB *ParentObjectInfo,
959                      IN PLARGE_INTEGER FileSize,
960                      IN ULONG FileAttributes,
961                      IN UNICODE_STRING *FileName,
962                      OUT AFSDirectoryCB **DirNode)
963 {
964
965     NTSTATUS ntStatus = STATUS_SUCCESS;
966     AFSFileCreateCB stCreateCB;
967     AFSFileCreateResultCB *pResultCB = NULL;
968     ULONG ulResultLen = 0;
969     UNICODE_STRING uniTargetName;
970     AFSDirectoryCB *pDirNode = NULL;
971     ULONG     ulCRC = 0;
972     LARGE_INTEGER liOldDataVersion;
973
974     __Enter
975     {
976
977         //
978         // Init the control block for the request
979         //
980
981         RtlZeroMemory( &stCreateCB,
982                        sizeof( AFSFileCreateCB));
983
984         stCreateCB.ParentId = ParentObjectInfo->FileId;
985
986         stCreateCB.AllocationSize = *FileSize;
987
988         stCreateCB.FileAttributes = FileAttributes;
989
990         stCreateCB.EaSize = 0;
991
992         liOldDataVersion = ParentObjectInfo->DataVersion;
993
994         //
995         // Allocate our return buffer
996         //
997
998         pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
999                                                                        PAGE_SIZE,
1000                                                                        AFS_GENERIC_MEMORY_1_TAG);
1001
1002         if( pResultCB == NULL)
1003         {
1004
1005             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1006         }
1007
1008         RtlZeroMemory( pResultCB,
1009                        PAGE_SIZE);
1010
1011         ulResultLen = PAGE_SIZE;
1012
1013         //
1014         // Send the call to the service
1015         //
1016
1017         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1018                                       AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1019                                       AuthGroup,
1020                                       FileName,
1021                                       NULL,
1022                                       &stCreateCB,
1023                                       sizeof( AFSFileCreateCB),
1024                                       pResultCB,
1025                                       &ulResultLen);
1026
1027         if( ntStatus != STATUS_SUCCESS)
1028         {
1029
1030             if( NT_SUCCESS( ntStatus))
1031             {
1032
1033                 ntStatus = STATUS_DEVICE_NOT_READY;
1034             }
1035
1036             try_return( ntStatus);
1037         }
1038
1039         //
1040         // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1041         // and though we created the node, it is already in our list. If this is the case then
1042         // look up the entry rather than create a new entry
1043         // The check is to ensure the DV has been modified
1044         //
1045
1046         if( liOldDataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1 ||
1047             liOldDataVersion.QuadPart != ParentObjectInfo->DataVersion.QuadPart)
1048         {
1049
1050             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1051                           AFS_TRACE_LEVEL_VERBOSE,
1052                           "AFSNotifyFileCreate Raced with an invalidate call and a re-enumeration for entry %wZ\n",
1053                           FileName);
1054
1055             //
1056             // We raced so go and lookup the directory entry in the parent
1057             //
1058
1059             ulCRC = AFSGenerateCRC( FileName,
1060                                     FALSE);
1061
1062             AFSAcquireShared( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1063                               TRUE);
1064
1065             AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1066                                             ulCRC,
1067                                             &pDirNode);
1068
1069             AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1070
1071             if( pDirNode != NULL)
1072             {
1073
1074                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1075                               AFS_TRACE_LEVEL_VERBOSE,
1076                               "AFSNotifyFileCreate Located dir entry for file %wZ\n",
1077                               FileName);
1078
1079                 *DirNode = pDirNode;
1080
1081                 try_return( ntStatus = STATUS_REPARSE);
1082             }
1083
1084             //
1085             // We are unsure of our current data so set the verify flag. It may already be set
1086             // but no big deal to reset it
1087             //
1088
1089             SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1090
1091             ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1092         }
1093         else
1094         {
1095
1096             //
1097             // Update the parent data version
1098             //
1099
1100             ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1101         }
1102
1103         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1104                       AFS_TRACE_LEVEL_VERBOSE,
1105                       "AFSNotifyFileCreate Creating new entry %wZ\n",
1106                       FileName);
1107
1108         //
1109         // Initialize the directory entry
1110         //
1111
1112         uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1113
1114         uniTargetName.MaximumLength = uniTargetName.Length;
1115
1116         uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1117
1118         pDirNode = AFSInitDirEntry( ParentObjectInfo,
1119                                     FileName,
1120                                     &uniTargetName,
1121                                     &pResultCB->DirEnum,
1122                                     (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1123
1124         if( pDirNode == NULL)
1125         {
1126
1127             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1128         }
1129
1130         //
1131         // Init the short name if we have one
1132         //
1133
1134         if( pResultCB->DirEnum.ShortNameLength > 0)
1135         {
1136
1137             UNICODE_STRING uniShortName;
1138
1139             pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1140
1141             RtlCopyMemory( pDirNode->NameInformation.ShortName,
1142                            pResultCB->DirEnum.ShortName,
1143                            pDirNode->NameInformation.ShortNameLength);
1144
1145             //
1146             // Generate the short name index
1147             //
1148
1149             uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1150             uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1151
1152             pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1153                                                                                TRUE);
1154         }
1155
1156         //
1157         // Return the directory node
1158         //
1159
1160         *DirNode = pDirNode;
1161
1162 try_exit:
1163
1164         if( pResultCB != NULL)
1165         {
1166
1167             AFSExFreePool( pResultCB);
1168         }
1169     }
1170
1171     return ntStatus;
1172 }
1173
1174 NTSTATUS
1175 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1176                           IN AFSObjectInfoCB *ObjectInfo,
1177                           IN GUID *AuthGroup)
1178 {
1179
1180     NTSTATUS ntStatus = STATUS_SUCCESS;
1181     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1182     AFSFileUpdateCB stUpdateCB;
1183     ULONG ulResultLen = 0;
1184     AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1185
1186     __Enter
1187     {
1188
1189         //
1190         // Init the control block for the request
1191         //
1192
1193         RtlZeroMemory( &stUpdateCB,
1194                        sizeof( AFSFileUpdateCB));
1195
1196         stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1197
1198         stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1199
1200         stUpdateCB.EaSize = ObjectInfo->EaSize;
1201
1202         stUpdateCB.ParentId = *ParentFid;
1203
1204         stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1205
1206         stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1207
1208         stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1209
1210         stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1211
1212         pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1213                                                                              PAGE_SIZE,
1214                                                                              AFS_UPDATE_RESULT_TAG);
1215
1216         if( pUpdateResultCB == NULL)
1217         {
1218
1219             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1220         }
1221
1222         ulResultLen = PAGE_SIZE;
1223
1224         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1225                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1226                                       AuthGroup,
1227                                       NULL,
1228                                       &ObjectInfo->FileId,
1229                                       &stUpdateCB,
1230                                       sizeof( AFSFileUpdateCB),
1231                                       pUpdateResultCB,
1232                                       &ulResultLen);
1233
1234         if( ntStatus != STATUS_SUCCESS)
1235         {
1236
1237             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1238                           AFS_TRACE_LEVEL_ERROR,
1239                           "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1240                           ObjectInfo->FileId.Cell,
1241                           ObjectInfo->FileId.Volume,
1242                           ObjectInfo->FileId.Vnode,
1243                           ObjectInfo->FileId.Unique,
1244                           ntStatus);
1245
1246             try_return( ntStatus);
1247         }
1248
1249         //
1250         // Update the data version
1251         //
1252
1253         ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1254
1255 try_exit:
1256
1257         if( pUpdateResultCB != NULL)
1258         {
1259
1260             AFSExFreePool( pUpdateResultCB);
1261         }
1262     }
1263
1264     return ntStatus;
1265 }
1266
1267 NTSTATUS
1268 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1269                  IN BOOLEAN CheckOnly)
1270 {
1271     NTSTATUS ntStatus = STATUS_SUCCESS;
1272     ULONG ulResultLen = 0;
1273     AFSFileDeleteCB stDelete;
1274     AFSFileDeleteResultCB stDeleteResult;
1275     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1276     GUID *pAuthGroup = NULL;
1277
1278     __Enter
1279     {
1280
1281         stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
1282
1283         stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1284
1285         ulResultLen = sizeof( AFSFileDeleteResultCB);
1286
1287         if( CheckOnly)
1288         {
1289             ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1290         }
1291
1292         if( DirectoryCB->ObjectInformation->Fcb != NULL)
1293         {
1294             pAuthGroup = &DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1295         }
1296
1297         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1298                                       ulRequestFlags,
1299                                       pAuthGroup,
1300                                       &DirectoryCB->NameInformation.FileName,
1301                                       &DirectoryCB->ObjectInformation->FileId,
1302                                       &stDelete,
1303                                       sizeof( AFSFileDeleteCB),
1304                                       &stDeleteResult,
1305                                       &ulResultLen);
1306
1307         if( ntStatus != STATUS_SUCCESS)
1308         {
1309
1310             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1311                           AFS_TRACE_LEVEL_ERROR,
1312                           "AFSNotifyDelete failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1313                           &DirectoryCB->ObjectInformation->FileId.Cell,
1314                           &DirectoryCB->ObjectInformation->FileId.Volume,
1315                           &DirectoryCB->ObjectInformation->FileId.Vnode,
1316                           &DirectoryCB->ObjectInformation->FileId.Unique,
1317                           ntStatus);
1318
1319             try_return( ntStatus);
1320         }
1321
1322         if( !CheckOnly)
1323         {
1324
1325             //
1326             // Update the parent data version
1327             //
1328
1329             if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
1330             {
1331
1332                 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1333
1334                 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1335             }
1336         }
1337
1338 try_exit:
1339
1340         NOTHING;
1341     }
1342
1343     return ntStatus;
1344 }
1345
1346 NTSTATUS
1347 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
1348                  IN AFSObjectInfoCB *ParentObjectInfo,
1349                  IN AFSObjectInfoCB *TargetParentObjectInfo,
1350                  IN AFSDirectoryCB *DirectoryCB,
1351                  IN UNICODE_STRING *TargetName,
1352                  OUT AFSFileID  *UpdatedFID)
1353 {
1354
1355     NTSTATUS ntStatus = STATUS_SUCCESS;
1356     AFSFileRenameCB *pRenameCB = NULL;
1357     AFSFileRenameResultCB *pRenameResultCB = NULL;
1358     ULONG ulResultLen = 0;
1359     GUID *pAuthGroup = NULL;
1360
1361     __Enter
1362     {
1363
1364         //
1365         // Init the control block for the request
1366         //
1367
1368         pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
1369                                                                  PAGE_SIZE,
1370                                                                  AFS_RENAME_REQUEST_TAG);
1371
1372         if( pRenameCB == NULL)
1373         {
1374
1375             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1376         }
1377
1378         RtlZeroMemory( pRenameCB,
1379                        PAGE_SIZE);
1380
1381         pRenameCB->SourceParentId = ParentObjectInfo->FileId;
1382
1383         pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
1384
1385         pRenameCB->TargetNameLength = TargetName->Length;
1386
1387         RtlCopyMemory( pRenameCB->TargetName,
1388                        TargetName->Buffer,
1389                        TargetName->Length);
1390
1391         if( ObjectInfo->Fcb != NULL)
1392         {
1393             pAuthGroup = &ObjectInfo->Fcb->AuthGroup;
1394         }
1395
1396         //
1397         // Use the same buffer for the result control block
1398         //
1399
1400         pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
1401
1402         ulResultLen = PAGE_SIZE;
1403
1404         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
1405                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1406                                       pAuthGroup,
1407                                       &DirectoryCB->NameInformation.FileName,
1408                                       &ObjectInfo->FileId,
1409                                       pRenameCB,
1410                                       sizeof( AFSFileRenameCB) + TargetName->Length,
1411                                       pRenameResultCB,
1412                                       &ulResultLen);
1413
1414         if( ntStatus != STATUS_SUCCESS)
1415         {
1416
1417             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1418                           AFS_TRACE_LEVEL_ERROR,
1419                           "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1420                           ObjectInfo->FileId.Cell,
1421                           ObjectInfo->FileId.Volume,
1422                           ObjectInfo->FileId.Vnode,
1423                           ObjectInfo->FileId.Unique,
1424                           ntStatus);
1425
1426             try_return( ntStatus);
1427         }
1428
1429         //
1430         // Update the information from the returned data
1431         //
1432
1433         ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
1434
1435         TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
1436
1437         //
1438         // Move over the short name
1439         //
1440
1441         DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
1442
1443         if( DirectoryCB->NameInformation.ShortNameLength > 0)
1444         {
1445
1446             RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
1447                            pRenameResultCB->DirEnum.ShortName,
1448                            DirectoryCB->NameInformation.ShortNameLength);
1449         }
1450
1451         if( UpdatedFID != NULL)
1452         {
1453
1454             *UpdatedFID = pRenameResultCB->DirEnum.FileId;
1455         }
1456
1457 try_exit:
1458
1459         if( pRenameCB != NULL)
1460         {
1461
1462             AFSExFreePool( pRenameCB);
1463         }
1464     }
1465
1466     return ntStatus;
1467 }
1468
1469 NTSTATUS
1470 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
1471                        IN GUID *AuthGroup,
1472                        IN BOOLEAN FastCall,
1473                        OUT AFSDirEnumEntry **DirEnumEntry)
1474 {
1475
1476     NTSTATUS ntStatus = STATUS_SUCCESS;
1477     AFSEvalTargetCB stTargetID;
1478     ULONG ulResultBufferLength;
1479     AFSDirEnumEntry *pDirEnumCB = NULL;
1480     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1481
1482     __Enter
1483     {
1484
1485         RtlZeroMemory( &stTargetID,
1486                        sizeof( AFSEvalTargetCB));
1487
1488         if( ObjectInfo->ParentObjectInformation != NULL)
1489         {
1490
1491             stTargetID.ParentId = ObjectInfo->ParentObjectInformation->FileId;
1492         }
1493
1494         //
1495         // Allocate our response buffer
1496         //
1497
1498         pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1499                                                                   PAGE_SIZE,
1500                                                                   AFS_GENERIC_MEMORY_2_TAG);
1501
1502         if( pDirEnumCB == NULL)
1503         {
1504
1505             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1506         }
1507
1508         //
1509         // Call to the service to evaluate the fid
1510         //
1511
1512         ulResultBufferLength = PAGE_SIZE;
1513
1514         if( FastCall)
1515         {
1516
1517             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
1518         }
1519
1520         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
1521                                       ulRequestFlags,
1522                                       AuthGroup,
1523                                       NULL,
1524                                       &ObjectInfo->FileId,
1525                                       &stTargetID,
1526                                       sizeof( AFSEvalTargetCB),
1527                                       pDirEnumCB,
1528                                       &ulResultBufferLength);
1529
1530         if( ntStatus != STATUS_SUCCESS)
1531         {
1532
1533             //
1534             // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
1535             // verification
1536             //
1537
1538             if( ntStatus == STATUS_INVALID_HANDLE)
1539             {
1540
1541                 if( ObjectInfo->ParentObjectInformation != NULL)
1542                 {
1543
1544                     SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1545                 }
1546             }
1547
1548             try_return( ntStatus);
1549         }
1550
1551         //
1552         // Pass back the dir enum entry
1553         //
1554
1555         if( DirEnumEntry != NULL)
1556         {
1557
1558             *DirEnumEntry = pDirEnumCB;
1559         }
1560         else
1561         {
1562
1563             AFSExFreePool( pDirEnumCB);
1564         }
1565
1566 try_exit:
1567
1568         if( !NT_SUCCESS( ntStatus))
1569         {
1570
1571             if( pDirEnumCB != NULL)
1572             {
1573
1574                 AFSExFreePool( pDirEnumCB);
1575             }
1576
1577             *DirEnumEntry = NULL;
1578         }
1579     }
1580
1581     return ntStatus;
1582 }
1583
1584 NTSTATUS
1585 AFSEvaluateTargetByName( IN GUID *AuthGroup,
1586                          IN AFSFileID *ParentFileId,
1587                          IN PUNICODE_STRING SourceName,
1588                          OUT AFSDirEnumEntry **DirEnumEntry)
1589 {
1590
1591     NTSTATUS ntStatus = STATUS_SUCCESS;
1592     AFSEvalTargetCB stTargetID;
1593     ULONG ulResultBufferLength;
1594     AFSDirEnumEntry *pDirEnumCB = NULL;
1595
1596     __Enter
1597     {
1598
1599         stTargetID.ParentId = *ParentFileId;
1600
1601         //
1602         // Allocate our response buffer
1603         //
1604
1605         pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1606                                                                   PAGE_SIZE,
1607                                                                   AFS_GENERIC_MEMORY_3_TAG);
1608
1609         if( pDirEnumCB == NULL)
1610         {
1611
1612             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1613         }
1614
1615         //
1616         // Call to the service to evaluate the fid
1617         //
1618
1619         ulResultBufferLength = PAGE_SIZE;
1620
1621         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
1622                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1623                                       AuthGroup,
1624                                       SourceName,
1625                                       NULL,
1626                                       &stTargetID,
1627                                       sizeof( AFSEvalTargetCB),
1628                                       pDirEnumCB,
1629                                       &ulResultBufferLength);
1630
1631         if( ntStatus != STATUS_SUCCESS)
1632         {
1633
1634             try_return( ntStatus);
1635         }
1636
1637         //
1638         // Pass back the dir enum entry
1639         //
1640
1641         if( DirEnumEntry != NULL)
1642         {
1643
1644             *DirEnumEntry = pDirEnumCB;
1645         }
1646         else
1647         {
1648
1649             AFSExFreePool( pDirEnumCB);
1650         }
1651
1652 try_exit:
1653
1654         if( !NT_SUCCESS( ntStatus))
1655         {
1656
1657             if( pDirEnumCB != NULL)
1658             {
1659
1660                 AFSExFreePool( pDirEnumCB);
1661             }
1662
1663             *DirEnumEntry = NULL;
1664         }
1665     }
1666
1667     return ntStatus;
1668 }
1669
1670 NTSTATUS
1671 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
1672                               IN AFSFileID *FileID,
1673                               OUT AFSVolumeInfoCB *VolumeInformation)
1674 {
1675
1676     NTSTATUS ntStatus = STATUS_SUCCESS;
1677     ULONG ulResultLen = 0;
1678
1679     __Enter
1680     {
1681
1682         ulResultLen = sizeof( AFSVolumeInfoCB);
1683
1684         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
1685                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1686                                       AuthGroup,
1687                                       NULL,
1688                                       FileID,
1689                                       NULL,
1690                                       0,
1691                                       VolumeInformation,
1692                                       &ulResultLen);
1693
1694         if( ntStatus != STATUS_SUCCESS)
1695         {
1696
1697             try_return( ntStatus);
1698         }
1699
1700 try_exit:
1701
1702         NOTHING;
1703     }
1704
1705     return ntStatus;
1706 }
1707
1708 NTSTATUS
1709 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
1710                          IN ULONG InputLength,
1711                          IN ULONG OutputLength,
1712                          IN void *InputDataBuffer,
1713                          OUT void *OutputDataBuffer,
1714                          OUT ULONG *BytesReturned)
1715 {
1716
1717     NTSTATUS ntStatus = STATUS_SUCCESS;
1718     ULONG ulResultLen = 0;
1719     MDL *pInputMdl = NULL, *pOutputMdl = NULL;
1720     void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
1721     ULONG ulBufferLength = OutputLength;
1722     AFSPipeIORequestCB *pIoRequest = NULL;
1723     GUID *pAuthGroup = NULL;
1724
1725     __Enter
1726     {
1727
1728         //
1729         // Map the user buffer to a system address
1730         //
1731
1732         pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
1733                                                 InputLength,
1734                                                 &pInputMdl);
1735
1736         if( pInputSystemBuffer == NULL)
1737         {
1738
1739             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1740         }
1741
1742         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
1743                                                                      sizeof( AFSPipeIORequestCB) +
1744                                                                                 InputLength,
1745                                                                      AFS_GENERIC_MEMORY_4_TAG);
1746
1747         if( pIoRequest == NULL)
1748         {
1749
1750             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1751         }
1752
1753         RtlZeroMemory( pIoRequest,
1754                        sizeof( AFSPipeIORequestCB) + InputLength);
1755
1756         pIoRequest->RequestId = Ccb->RequestID;
1757
1758         pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1759
1760         pIoRequest->BufferLength = InputLength;
1761
1762         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
1763                        pInputSystemBuffer,
1764                        InputLength);
1765
1766         pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
1767                                                  OutputLength,
1768                                                  &pOutputMdl);
1769
1770         if( pOutputSystemBuffer == NULL)
1771         {
1772
1773             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1774         }
1775
1776         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
1777         {
1778             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1779         }
1780
1781         //
1782         // Send the call to the service
1783         //
1784
1785         ulResultLen = OutputLength;
1786
1787         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
1788                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1789                                       pAuthGroup,
1790                                       &Ccb->DirectoryCB->NameInformation.FileName,
1791                                       NULL,
1792                                       pIoRequest,
1793                                       sizeof( AFSPipeIORequestCB) + InputLength,
1794                                       pOutputSystemBuffer,
1795                                       &ulResultLen);
1796
1797         if( ntStatus != STATUS_SUCCESS &&
1798             ntStatus != STATUS_BUFFER_OVERFLOW)
1799         {
1800
1801             if( NT_SUCCESS( ntStatus))
1802             {
1803
1804                 ntStatus = STATUS_DEVICE_NOT_READY;
1805             }
1806
1807             try_return( ntStatus);
1808         }
1809
1810         //
1811         // Return the bytes processed
1812         //
1813
1814         *BytesReturned = ulResultLen;
1815
1816 try_exit:
1817
1818         if( pInputMdl != NULL)
1819         {
1820
1821             MmUnlockPages( pInputMdl);
1822
1823             IoFreeMdl( pInputMdl);
1824         }
1825
1826         if( pOutputMdl != NULL)
1827         {
1828
1829             MmUnlockPages( pOutputMdl);
1830
1831             IoFreeMdl( pOutputMdl);
1832         }
1833
1834         if( pIoRequest != NULL)
1835         {
1836
1837             AFSExFreePool( pIoRequest);
1838         }
1839     }
1840
1841     return ntStatus;
1842 }
1843
1844 NTSTATUS
1845 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
1846                       IN ULONG InformationClass,
1847                       IN ULONG InputLength,
1848                       IN void *DataBuffer)
1849 {
1850
1851     NTSTATUS ntStatus = STATUS_SUCCESS;
1852     AFSPipeInfoRequestCB *pInfoRequest = NULL;
1853     GUID *pAuthGroup = NULL;
1854
1855     __Enter
1856     {
1857
1858         pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
1859                                                                          sizeof( AFSPipeInfoRequestCB) +
1860                                                                                 InputLength,
1861                                                                          AFS_GENERIC_MEMORY_5_TAG);
1862
1863         if( pInfoRequest == NULL)
1864         {
1865
1866             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1867         }
1868
1869         RtlZeroMemory( pInfoRequest,
1870                        sizeof( AFSPipeInfoRequestCB) + InputLength);
1871
1872         pInfoRequest->RequestId = Ccb->RequestID;
1873
1874         pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1875
1876         pInfoRequest->BufferLength = InputLength;
1877
1878         pInfoRequest->InformationClass = InformationClass;
1879
1880         RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
1881                        DataBuffer,
1882                        InputLength);
1883
1884         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
1885         {
1886             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1887         }
1888
1889         //
1890         // Send the call to the service
1891         //
1892
1893         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
1894                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1895                                       pAuthGroup,
1896                                       &Ccb->DirectoryCB->NameInformation.FileName,
1897                                       NULL,
1898                                       pInfoRequest,
1899                                       sizeof( AFSPipeInfoRequestCB) + InputLength,
1900                                       NULL,
1901                                       NULL);
1902
1903         if( ntStatus != STATUS_SUCCESS)
1904         {
1905
1906             if( NT_SUCCESS( ntStatus))
1907             {
1908
1909                 ntStatus = STATUS_DEVICE_NOT_READY;
1910             }
1911
1912             try_return( ntStatus);
1913         }
1914
1915 try_exit:
1916
1917         if( pInfoRequest != NULL)
1918         {
1919
1920             AFSExFreePool( pInfoRequest);
1921         }
1922     }
1923
1924     return ntStatus;
1925 }
1926
1927 NTSTATUS
1928 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
1929                         IN ULONG InformationClass,
1930                         IN ULONG OutputLength,
1931                         IN void *DataBuffer,
1932                         OUT ULONG *BytesReturned)
1933 {
1934
1935     NTSTATUS ntStatus = STATUS_SUCCESS;
1936     AFSPipeInfoRequestCB stInfoRequest;
1937     ULONG ulBytesProcessed = 0;
1938     GUID *pAuthGroup = NULL;
1939
1940     __Enter
1941     {
1942
1943         RtlZeroMemory( &stInfoRequest,
1944                        sizeof( AFSPipeInfoRequestCB));
1945
1946         stInfoRequest.RequestId = Ccb->RequestID;
1947
1948         stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1949
1950         stInfoRequest.BufferLength = OutputLength;
1951
1952         stInfoRequest.InformationClass = InformationClass;
1953
1954         ulBytesProcessed = OutputLength;
1955
1956         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
1957         {
1958             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1959         }
1960
1961         //
1962         // Send the call to the service
1963         //
1964
1965         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
1966                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1967                                       pAuthGroup,
1968                                       &Ccb->DirectoryCB->NameInformation.FileName,
1969                                       NULL,
1970                                       &stInfoRequest,
1971                                       sizeof( AFSPipeInfoRequestCB),
1972                                       DataBuffer,
1973                                       &ulBytesProcessed);
1974
1975         if( ntStatus != STATUS_SUCCESS)
1976         {
1977
1978             if( NT_SUCCESS( ntStatus))
1979             {
1980
1981                 ntStatus = STATUS_DEVICE_NOT_READY;
1982             }
1983
1984             try_return( ntStatus);
1985         }
1986
1987         *BytesReturned = ulBytesProcessed;
1988
1989 try_exit:
1990
1991         NOTHING;
1992     }
1993
1994     return ntStatus;
1995 }
1996
1997 NTSTATUS
1998 AFSReleaseFid( IN AFSFileID *FileId)
1999 {
2000
2001     NTSTATUS ntStatus = STATUS_SUCCESS;
2002
2003     __Enter
2004     {
2005
2006         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2007                                       0,
2008                                       NULL,
2009                                       NULL,
2010                                       FileId,
2011                                       NULL,
2012                                       0,
2013                                       NULL,
2014                                       NULL);
2015     }
2016
2017     return ntStatus;
2018 }
2019
2020 BOOLEAN
2021 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2022                           IN LARGE_INTEGER *ExtentOffset,
2023                           IN ULONG Length)
2024 {
2025
2026     BOOLEAN bRequestQueued = FALSE;
2027     NTSTATUS ntStatus = STATUS_SUCCESS;
2028     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2029     AFSCommSrvcCB   *pCommSrvc = NULL;
2030     AFSPoolEntry    *pPoolEntry = NULL;
2031     AFSRequestExtentsCB *pRequestExtents = NULL;
2032
2033     __Enter
2034     {
2035
2036
2037         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2038
2039         AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2040                           TRUE);
2041
2042         pPoolEntry = pCommSrvc->RequestPoolHead;
2043
2044         while( pPoolEntry != NULL)
2045         {
2046
2047             if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2048             {
2049
2050                 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2051                 {
2052
2053                     pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2054
2055                     if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2056                         pRequestExtents->Length == Length)
2057                     {
2058
2059                         bRequestQueued = TRUE;
2060                     }
2061                 }
2062             }
2063
2064             pPoolEntry = pPoolEntry->fLink;
2065         }
2066
2067         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2068     }
2069
2070     return bRequestQueued;
2071 }