Windows: remove unused code block
[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                 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         *DirEnumEntry = pDirEnumCB;
1642
1643 try_exit:
1644
1645         if( !NT_SUCCESS( ntStatus))
1646         {
1647
1648             if( pDirEnumCB != NULL)
1649             {
1650
1651                 AFSExFreePool( pDirEnumCB);
1652             }
1653
1654             *DirEnumEntry = NULL;
1655         }
1656     }
1657
1658     return ntStatus;
1659 }
1660
1661 NTSTATUS
1662 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
1663                               IN AFSFileID *FileID,
1664                               OUT AFSVolumeInfoCB *VolumeInformation)
1665 {
1666
1667     NTSTATUS ntStatus = STATUS_SUCCESS;
1668     ULONG ulResultLen = 0;
1669
1670     __Enter
1671     {
1672
1673         ulResultLen = sizeof( AFSVolumeInfoCB);
1674
1675         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
1676                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1677                                       AuthGroup,
1678                                       NULL,
1679                                       FileID,
1680                                       NULL,
1681                                       0,
1682                                       VolumeInformation,
1683                                       &ulResultLen);
1684
1685         if( ntStatus != STATUS_SUCCESS)
1686         {
1687
1688             try_return( ntStatus);
1689         }
1690
1691 try_exit:
1692
1693         NOTHING;
1694     }
1695
1696     return ntStatus;
1697 }
1698
1699 NTSTATUS
1700 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
1701                          IN ULONG InputLength,
1702                          IN ULONG OutputLength,
1703                          IN void *InputDataBuffer,
1704                          OUT void *OutputDataBuffer,
1705                          OUT ULONG *BytesReturned)
1706 {
1707
1708     NTSTATUS ntStatus = STATUS_SUCCESS;
1709     ULONG ulResultLen = 0;
1710     MDL *pInputMdl = NULL, *pOutputMdl = NULL;
1711     void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
1712     ULONG ulBufferLength = OutputLength;
1713     AFSPipeIORequestCB *pIoRequest = NULL;
1714     GUID *pAuthGroup = NULL;
1715
1716     __Enter
1717     {
1718
1719         //
1720         // Map the user buffer to a system address
1721         //
1722
1723         pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
1724                                                 InputLength,
1725                                                 &pInputMdl);
1726
1727         if( pInputSystemBuffer == NULL)
1728         {
1729
1730             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1731         }
1732
1733         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
1734                                                                      sizeof( AFSPipeIORequestCB) +
1735                                                                                 InputLength,
1736                                                                      AFS_GENERIC_MEMORY_4_TAG);
1737
1738         if( pIoRequest == NULL)
1739         {
1740
1741             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1742         }
1743
1744         RtlZeroMemory( pIoRequest,
1745                        sizeof( AFSPipeIORequestCB) + InputLength);
1746
1747         pIoRequest->RequestId = Ccb->RequestID;
1748
1749         pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1750
1751         pIoRequest->BufferLength = InputLength;
1752
1753         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
1754                        pInputSystemBuffer,
1755                        InputLength);
1756
1757         pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
1758                                                  OutputLength,
1759                                                  &pOutputMdl);
1760
1761         if( pOutputSystemBuffer == NULL)
1762         {
1763
1764             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1765         }
1766
1767         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
1768         {
1769             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1770         }
1771
1772         //
1773         // Send the call to the service
1774         //
1775
1776         ulResultLen = OutputLength;
1777
1778         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
1779                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1780                                       pAuthGroup,
1781                                       &Ccb->DirectoryCB->NameInformation.FileName,
1782                                       NULL,
1783                                       pIoRequest,
1784                                       sizeof( AFSPipeIORequestCB) + InputLength,
1785                                       pOutputSystemBuffer,
1786                                       &ulResultLen);
1787
1788         if( ntStatus != STATUS_SUCCESS &&
1789             ntStatus != STATUS_BUFFER_OVERFLOW)
1790         {
1791
1792             if( NT_SUCCESS( ntStatus))
1793             {
1794
1795                 ntStatus = STATUS_DEVICE_NOT_READY;
1796             }
1797
1798             try_return( ntStatus);
1799         }
1800
1801         //
1802         // Return the bytes processed
1803         //
1804
1805         *BytesReturned = ulResultLen;
1806
1807 try_exit:
1808
1809         if( pInputMdl != NULL)
1810         {
1811
1812             MmUnlockPages( pInputMdl);
1813
1814             IoFreeMdl( pInputMdl);
1815         }
1816
1817         if( pOutputMdl != NULL)
1818         {
1819
1820             MmUnlockPages( pOutputMdl);
1821
1822             IoFreeMdl( pOutputMdl);
1823         }
1824
1825         if( pIoRequest != NULL)
1826         {
1827
1828             AFSExFreePool( pIoRequest);
1829         }
1830     }
1831
1832     return ntStatus;
1833 }
1834
1835 NTSTATUS
1836 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
1837                       IN ULONG InformationClass,
1838                       IN ULONG InputLength,
1839                       IN void *DataBuffer)
1840 {
1841
1842     NTSTATUS ntStatus = STATUS_SUCCESS;
1843     AFSPipeInfoRequestCB *pInfoRequest = NULL;
1844     GUID *pAuthGroup = NULL;
1845
1846     __Enter
1847     {
1848
1849         pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
1850                                                                          sizeof( AFSPipeInfoRequestCB) +
1851                                                                                 InputLength,
1852                                                                          AFS_GENERIC_MEMORY_5_TAG);
1853
1854         if( pInfoRequest == NULL)
1855         {
1856
1857             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1858         }
1859
1860         RtlZeroMemory( pInfoRequest,
1861                        sizeof( AFSPipeInfoRequestCB) + InputLength);
1862
1863         pInfoRequest->RequestId = Ccb->RequestID;
1864
1865         pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1866
1867         pInfoRequest->BufferLength = InputLength;
1868
1869         pInfoRequest->InformationClass = InformationClass;
1870
1871         RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
1872                        DataBuffer,
1873                        InputLength);
1874
1875         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
1876         {
1877             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1878         }
1879
1880         //
1881         // Send the call to the service
1882         //
1883
1884         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
1885                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1886                                       pAuthGroup,
1887                                       &Ccb->DirectoryCB->NameInformation.FileName,
1888                                       NULL,
1889                                       pInfoRequest,
1890                                       sizeof( AFSPipeInfoRequestCB) + InputLength,
1891                                       NULL,
1892                                       NULL);
1893
1894         if( ntStatus != STATUS_SUCCESS)
1895         {
1896
1897             if( NT_SUCCESS( ntStatus))
1898             {
1899
1900                 ntStatus = STATUS_DEVICE_NOT_READY;
1901             }
1902
1903             try_return( ntStatus);
1904         }
1905
1906 try_exit:
1907
1908         if( pInfoRequest != NULL)
1909         {
1910
1911             AFSExFreePool( pInfoRequest);
1912         }
1913     }
1914
1915     return ntStatus;
1916 }
1917
1918 NTSTATUS
1919 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
1920                         IN ULONG InformationClass,
1921                         IN ULONG OutputLength,
1922                         IN void *DataBuffer,
1923                         OUT ULONG *BytesReturned)
1924 {
1925
1926     NTSTATUS ntStatus = STATUS_SUCCESS;
1927     AFSPipeInfoRequestCB stInfoRequest;
1928     ULONG ulBytesProcessed = 0;
1929     GUID *pAuthGroup = NULL;
1930
1931     __Enter
1932     {
1933
1934         RtlZeroMemory( &stInfoRequest,
1935                        sizeof( AFSPipeInfoRequestCB));
1936
1937         stInfoRequest.RequestId = Ccb->RequestID;
1938
1939         stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1940
1941         stInfoRequest.BufferLength = OutputLength;
1942
1943         stInfoRequest.InformationClass = InformationClass;
1944
1945         ulBytesProcessed = OutputLength;
1946
1947         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
1948         {
1949             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1950         }
1951
1952         //
1953         // Send the call to the service
1954         //
1955
1956         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
1957                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1958                                       pAuthGroup,
1959                                       &Ccb->DirectoryCB->NameInformation.FileName,
1960                                       NULL,
1961                                       &stInfoRequest,
1962                                       sizeof( AFSPipeInfoRequestCB),
1963                                       DataBuffer,
1964                                       &ulBytesProcessed);
1965
1966         if( ntStatus != STATUS_SUCCESS)
1967         {
1968
1969             if( NT_SUCCESS( ntStatus))
1970             {
1971
1972                 ntStatus = STATUS_DEVICE_NOT_READY;
1973             }
1974
1975             try_return( ntStatus);
1976         }
1977
1978         *BytesReturned = ulBytesProcessed;
1979
1980 try_exit:
1981
1982         NOTHING;
1983     }
1984
1985     return ntStatus;
1986 }
1987
1988 NTSTATUS
1989 AFSReleaseFid( IN AFSFileID *FileId)
1990 {
1991
1992     NTSTATUS ntStatus = STATUS_SUCCESS;
1993
1994     __Enter
1995     {
1996
1997         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
1998                                       0,
1999                                       NULL,
2000                                       NULL,
2001                                       FileId,
2002                                       NULL,
2003                                       0,
2004                                       NULL,
2005                                       NULL);
2006     }
2007
2008     return ntStatus;
2009 }
2010
2011 BOOLEAN
2012 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2013                           IN LARGE_INTEGER *ExtentOffset,
2014                           IN ULONG Length)
2015 {
2016
2017     BOOLEAN bRequestQueued = FALSE;
2018     NTSTATUS ntStatus = STATUS_SUCCESS;
2019     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2020     AFSCommSrvcCB   *pCommSrvc = NULL;
2021     AFSPoolEntry    *pPoolEntry = NULL;
2022     AFSRequestExtentsCB *pRequestExtents = NULL;
2023
2024     __Enter
2025     {
2026
2027
2028         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2029
2030         AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2031                           TRUE);
2032
2033         pPoolEntry = pCommSrvc->RequestPoolHead;
2034
2035         while( pPoolEntry != NULL)
2036         {
2037
2038             if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2039             {
2040
2041                 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2042                 {
2043
2044                     pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2045
2046                     if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2047                         pRequestExtents->Length == Length)
2048                     {
2049
2050                         bRequestQueued = TRUE;
2051                     }
2052                 }
2053             }
2054
2055             pPoolEntry = pPoolEntry->fLink;
2056         }
2057
2058         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2059     }
2060
2061     return bRequestQueued;
2062 }